From eefbd64089335fe47bc93ced6d3ffe3996594753 Mon Sep 17 00:00:00 2001 From: Bishop Date: Sat, 25 Jul 2026 17:46:25 -0500 Subject: [PATCH 01/11] Custom server name for bank deposit box and Falador bank wall notice --- .../iface/bank/BankDepositBoxInterface.kt | 17 ++++++++++++----- .../asgarnia/falador/handlers/BankNotices.kt | 3 ++- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/Server/src/main/content/global/handlers/iface/bank/BankDepositBoxInterface.kt b/Server/src/main/content/global/handlers/iface/bank/BankDepositBoxInterface.kt index e190a8dde..81880a993 100644 --- a/Server/src/main/content/global/handlers/iface/bank/BankDepositBoxInterface.kt +++ b/Server/src/main/content/global/handlers/iface/bank/BankDepositBoxInterface.kt @@ -1,5 +1,6 @@ package content.global.handlers.iface.bank +import core.ServerConstants import core.api.animate import core.api.dumpBeastOfBurden import core.api.runWorldTask @@ -65,12 +66,18 @@ class BankDepositBoxInterface : InterfaceListener { } override fun defineInterfaceListeners() { + onOpen(Components.BANK_DEPOSIT_BOX_11) { player, _ -> + player.packetDispatch.sendString( + "The Bank of ${ServerConstants.SERVER_NAME} - Deposit Box", + Components.BANK_DEPOSIT_BOX_11, + 12 + ) + return@onOpen true + } on(Components.BANK_DEPOSIT_BOX_11, ::handleDepositBoxMenu) - on( - Components.BANK_DEPOSIT_BOX_11, - BUTTON_DEPOSIT_BOB - ) { player, _, _, _, _, _ -> - dumpBeastOfBurden(player); true + on(Components.BANK_DEPOSIT_BOX_11, BUTTON_DEPOSIT_BOB) { player, _, _, _, _, _ -> + dumpBeastOfBurden(player) + return@on true } } } \ No newline at end of file diff --git a/Server/src/main/content/region/asgarnia/falador/handlers/BankNotices.kt b/Server/src/main/content/region/asgarnia/falador/handlers/BankNotices.kt index 11a124e8b..0e1f4a309 100644 --- a/Server/src/main/content/region/asgarnia/falador/handlers/BankNotices.kt +++ b/Server/src/main/content/region/asgarnia/falador/handlers/BankNotices.kt @@ -2,6 +2,7 @@ package content.region.asgarnia.falador.handlers import content.global.handlers.iface.ScrollInterface import content.global.handlers.iface.ScrollLine +import core.ServerConstants import core.game.interaction.InteractionListener import org.rs09.consts.Components import org.rs09.consts.Scenery @@ -23,7 +24,7 @@ class BankNotices : InteractionListener { ) val CONTENTS_PASSWORD = arrayOf( - ScrollLine("The Bank of RuneScape would like to remind customers that",4), + ScrollLine("The Bank of ${ServerConstants.SERVER_NAME} would like to remind customers that",4), ScrollLine("they should NEVER tell ANYONE their password.",5), ScrollLine("If someone asks you to say your password, please report",7), From 9c227f3ced96bad6763ac69ff842942328f2ec71 Mon Sep 17 00:00:00 2001 From: Bishop Date: Sat, 25 Jul 2026 21:40:59 -0500 Subject: [PATCH 02/11] Custom server name for friends list iface --- .../handlers/iface/FriendsListInterface.kt | 19 +++++ .../entity/player/link/InterfaceManager.java | 74 +++++++++---------- 2 files changed, 53 insertions(+), 40 deletions(-) create mode 100644 Server/src/main/content/global/handlers/iface/FriendsListInterface.kt diff --git a/Server/src/main/content/global/handlers/iface/FriendsListInterface.kt b/Server/src/main/content/global/handlers/iface/FriendsListInterface.kt new file mode 100644 index 000000000..a7044613e --- /dev/null +++ b/Server/src/main/content/global/handlers/iface/FriendsListInterface.kt @@ -0,0 +1,19 @@ +package content.global.handlers.iface + +import core.ServerConstants +import core.api.setInterfaceText +import core.game.component.Component +import core.game.node.entity.player.Player +import core.game.world.GameWorld +import org.rs09.consts.Components + +/** + * Makes sure the server name is always applied to the Friends List interface. + */ + +class FriendsListInterface : Component(Components.FRIENDS2_550) { + override fun open(player: Player) { + super.open(player) + setInterfaceText(player, "Friends List - ${ServerConstants.SERVER_NAME} ${GameWorld.settings!!.worldId}", Components.FRIENDS2_550, 3) + } +} \ No newline at end of file diff --git a/Server/src/main/core/game/node/entity/player/link/InterfaceManager.java b/Server/src/main/core/game/node/entity/player/link/InterfaceManager.java index 4a0fb00ae..859b0aed6 100644 --- a/Server/src/main/core/game/node/entity/player/link/InterfaceManager.java +++ b/Server/src/main/core/game/node/entity/player/link/InterfaceManager.java @@ -14,6 +14,7 @@ import core.net.packet.out.Interface; import core.net.packet.out.WindowsPane; import core.tools.Log; import org.rs09.consts.Components; +import content.global.handlers.iface.FriendsListInterface; import content.region.misc.tutisland.handlers.TutorialStage; import static core.api.ContentAPIKt.log; @@ -352,23 +353,25 @@ public final class InterfaceManager { if (inter == null) { player.addExtension(WeaponInterface.class, inter = new WeaponInterface(player)); } - openTab(0, inter); + openTab(i, inter); break; case 6: - openTab(6, new Component(player.getSpellBookManager().getSpellBook())); // Magic + openTab(i, new Component(player.getSpellBookManager().getSpellBook())); // Magic break; case 7: if (player.getFamiliarManager().hasFamiliar()) { - openTab(7, new Component(662)); + openTab(i, new Component(Components.LORE_STATS_SIDE_662)); // Summoning } break; + case 8: + openTab(i, new FriendsListInterface()); // Friends + break; default: openTab(i, new Component(DEFAULT_TABS[i])); } } else if (tab.isHidden()) { int child = (i < 7 ? 38 : 13) + i; -// boolean resize = isResizable(); //TODO: player.getPacketDispatch().sendInterfaceConfig(getWindowPaneId(), child, false); player.getPacketDispatch().sendInterfaceConfig(getWindowPaneId(), child + 7, false); tabs[i].setHidden(false); @@ -380,29 +383,32 @@ public final class InterfaceManager { * Opens the default tabs. */ public void openDefaultTabs() { - // player.getPacketDispatch().sendInterfaceConfig(548, 51, false); WeaponInterface inter = player.getExtension(WeaponInterface.class); if (inter == null) { player.addExtension(WeaponInterface.class, inter = new WeaponInterface(player)); } - //sendTab(16, 747); // Summoning bar - openTab(0, inter); // Attack - openTab(1, new Component(Components.STATS_320)); // Skills - openTab(2, new Component(Components.QUESTJOURNAL_V2_274)); // Quest - openTab(3, new Component(Components.INVENTORY_149)); // inventory - openTab(4, new Component(Components.WORNITEMS_387)); // Equipment - openTab(5, new Component(Components.PRAYER_271)); // Prayer - openTab(6, new Component(player.getSpellBookManager().getSpellBook())); // Magic - if (player.getFamiliarManager().hasFamiliar()) { - openTab(7, new Component(Components.LORE_STATS_SIDE_662)); // summoning. + for (int i = 0; i < tabs.length; i++) { + switch (i) { + case 0: + openTab(i, inter); + break; + case 6: + openTab(i, new Component(player.getSpellBookManager().getSpellBook())); // Magic + break; + case 7: + if (player.getFamiliarManager().hasFamiliar()) { + openTab(i, new Component(Components.LORE_STATS_SIDE_662)); // Summoning + } + break; + case 8: + if (tabs[i] == null) { + openTab(i, new FriendsListInterface()); // Friends + } + break; + default: + openTab(i, new Component(DEFAULT_TABS[i])); + } } - openTab(8, new Component(Components.FRIENDS2_550)); // Friends - openTab(9, new Component(Components.IGNORE2_551)); // Ignores - openTab(10, new Component(Components.CLANJOIN_589)); // Clan chat - openTab(11, new Component(Components.OPTIONS_261)); // Settings - openTab(12, new Component(Components.EMOTES_464)); // Emotes - openTab(13, new Component(Components.MUSIC_V3_187)); // Music - openTab(14, new Component(Components.LOGOUT_182)); // Logout if (player.getProperties().getAutocastSpell() != null) { inter.selectAutoSpell(inter.getAutospellId(player.getProperties().getAutocastSpell().getSpellId()), true); } @@ -428,25 +434,13 @@ public final class InterfaceManager { * Closes the default tabs. */ public void closeDefaultTabs() { - WeaponInterface inter = player.getExtension(WeaponInterface.class); - if (inter != null) { - close(inter); // Attack + for (int i = 0; i < tabs.length; i++) { + Component tab = tabs[i]; + if (tab != null) { + close(tab); + tabs[i] = null; + } } - close(new Component(Components.STATS_320)); // Skills - close(new Component(Components.QUESTJOURNAL_V2_274)); // Quest - close(new Component(Components.AREA_TASK_259)); // Diary - close(new Component(Components.INVENTORY_149)); // inventory - close(new Component(Components.WORNITEMS_387)); // Equipment - close(new Component(Components.PRAYER_271)); // Prayer - close(new Component(player.getSpellBookManager().getSpellBook())); - close(new Component(Components.LORE_STATS_SIDE_662)); // summoning. - close(new Component(Components.FRIENDS2_550)); // Friends - close(new Component(Components.IGNORE2_551)); // Ignores - close(new Component(Components.CLANJOIN_589)); // Clan chat - close(new Component(Components.OPTIONS_261)); // Settings - close(new Component(Components.EMOTES_464)); // Emotes - close(new Component(Components.MUSIC_V3_187)); // Music - //close(new Component(Components.LOGOUT_182)); // Logout } /** From 4d675294df7e6bdea442db2db042c08aca5899ad Mon Sep 17 00:00:00 2001 From: Bishop Date: Sun, 26 Jul 2026 00:12:59 -0500 Subject: [PATCH 03/11] Stopped lying about credits --- .../game/node/entity/player/info/login/LoginConfiguration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/core/game/node/entity/player/info/login/LoginConfiguration.java b/Server/src/main/core/game/node/entity/player/info/login/LoginConfiguration.java index fb50ee051..b7af34638 100644 --- a/Server/src/main/core/game/node/entity/player/info/login/LoginConfiguration.java +++ b/Server/src/main/core/game/node/entity/player/info/login/LoginConfiguration.java @@ -103,7 +103,7 @@ public final class LoginConfiguration { setInterfaceText(player, "", 378, 39); setInterfaceText(player, "Discord Invite", 378, 14); setInterfaceText(player, "Discord Invite", 378, 129); - setInterfaceText(player, "You can gain more credits by reporting bugs and various other methods of contribution.", 378, 93); + setInterfaceText(player, "You can gain more credits by testing new features and other methods of contribution.", 378, 93); setInterfaceText(player, player.getDetails().getCredits() + "", 378, 96); setInterfaceText(player, "Credits", 378, 94); setInterfaceText(player, "", 378, 229); From 9ab4edc276087d73d92c31aa25a18c46e2602695 Mon Sep 17 00:00:00 2001 From: Bishop Date: Sun, 26 Jul 2026 08:56:19 -0500 Subject: [PATCH 04/11] Fixed #2221 --- .../handlers/iface/AutocastSelectPlugin.java | 2 +- .../iface/tabs/CombatTabInterface.java | 2 +- .../global/skill/magic/MagicAltarListener.kt | 2 +- .../skill/skillcapeperks/SkillcapePerks.kt | 2 +- .../core/game/global/action/EquipHandler.kt | 2 +- .../node/entity/combat/MagicSwingHandler.kt | 2 +- .../combat/equipment/WeaponInterface.java | 56 +++++++++++++++++-- .../player/info/login/LoginConfiguration.java | 18 ++++-- .../entity/player/link/InterfaceManager.java | 2 +- .../game/system/timer/impl/SpellbookSwap.kt | 2 +- 10 files changed, 74 insertions(+), 16 deletions(-) diff --git a/Server/src/main/content/global/handlers/iface/AutocastSelectPlugin.java b/Server/src/main/content/global/handlers/iface/AutocastSelectPlugin.java index 9213cf0f6..9254f2597 100644 --- a/Server/src/main/content/global/handlers/iface/AutocastSelectPlugin.java +++ b/Server/src/main/content/global/handlers/iface/AutocastSelectPlugin.java @@ -44,7 +44,7 @@ public final class AutocastSelectPlugin extends ComponentPlugin { player.removeAttribute("autocast_select"); final WeaponInterface w = player.getExtension(WeaponInterface.class); if (w != null) { - w.selectAutoSpell(button, true); + w.selectAutoSpell(button, true, false); player.getInterfaceManager().openTab(w); } return true; diff --git a/Server/src/main/content/global/handlers/iface/tabs/CombatTabInterface.java b/Server/src/main/content/global/handlers/iface/tabs/CombatTabInterface.java index 0ca513102..9d4c330fe 100644 --- a/Server/src/main/content/global/handlers/iface/tabs/CombatTabInterface.java +++ b/Server/src/main/content/global/handlers/iface/tabs/CombatTabInterface.java @@ -82,7 +82,7 @@ public class CombatTabInterface extends ComponentPlugin { if (button == 4 || button == 5) { inter.openAutocastSelect(); } else if (p.getProperties().getAutocastSpell() != null) { - inter.selectAutoSpell(-1, false); + inter.selectAutoSpell(-1, false, true); } return true; } diff --git a/Server/src/main/content/global/skill/magic/MagicAltarListener.kt b/Server/src/main/content/global/skill/magic/MagicAltarListener.kt index 70ec07e25..704190b33 100644 --- a/Server/src/main/content/global/skill/magic/MagicAltarListener.kt +++ b/Server/src/main/content/global/skill/magic/MagicAltarListener.kt @@ -54,7 +54,7 @@ class MagicAltarListener : InteractionListener { } val weaponInterface = player.getExtension(WeaponInterface::class.java) if (weaponInterface != null && player.properties.autocastSpell != null) { - weaponInterface.selectAutoSpell(-1, true) + weaponInterface.selectAutoSpell(-1, true, true) } if (SpellBook.forInterface(player.spellBookManager.spellBook) == if (altar.id == ANCIENT_ALTAR) SpellBook.ANCIENT else SpellBook.LUNAR) { player.dispatch(SpellbookChangeEvent( diff --git a/Server/src/main/content/global/skill/skillcapeperks/SkillcapePerks.kt b/Server/src/main/content/global/skill/skillcapeperks/SkillcapePerks.kt index 148696543..e10a8d372 100644 --- a/Server/src/main/content/global/skill/skillcapeperks/SkillcapePerks.kt +++ b/Server/src/main/content/global/skill/skillcapeperks/SkillcapePerks.kt @@ -215,7 +215,7 @@ enum class SkillcapePerks(val attribute: String, val effect: ((Player) -> Unit)? } val weaponInterface = player.getExtension(WeaponInterface::class.java) if (weaponInterface != null && player.properties.autocastSpell != null) { - weaponInterface.selectAutoSpell(-1, true) + weaponInterface.selectAutoSpell(-1, true, true) } player.dispatch(SpellbookChangeEvent( SpellBookManager.SpellBook.forInterface(player.spellBookManager.spellBook), diff --git a/Server/src/main/core/game/global/action/EquipHandler.kt b/Server/src/main/core/game/global/action/EquipHandler.kt index 29299e238..48cc0be93 100644 --- a/Server/src/main/core/game/global/action/EquipHandler.kt +++ b/Server/src/main/core/game/global/action/EquipHandler.kt @@ -82,7 +82,7 @@ class EquipHandler : InteractionListener { if (itemEquipmentSlot == EquipmentContainer.SLOT_WEAPON) { player.properties.autocastSpell = null val wif = player.getExtension(WeaponInterface::class.java) - wif.selectAutoSpell(-1, true) + wif.selectAutoSpell(-1, true, true) wif.openAutocastSelect() } } diff --git a/Server/src/main/core/game/node/entity/combat/MagicSwingHandler.kt b/Server/src/main/core/game/node/entity/combat/MagicSwingHandler.kt index 0062c20d9..dbcc956f0 100644 --- a/Server/src/main/core/game/node/entity/combat/MagicSwingHandler.kt +++ b/Server/src/main/core/game/node/entity/combat/MagicSwingHandler.kt @@ -52,7 +52,7 @@ open class MagicSwingHandler (vararg flags: SwingHandlerFlag) entity.properties.spell = null val inter = entity.getExtension(WeaponInterface::class.java) if (inter != null) { - inter.selectAutoSpell(-1, true) + inter.selectAutoSpell(-1, true, true) entity.properties.combatPulse.updateStyle() } return -1 diff --git a/Server/src/main/core/game/node/entity/combat/equipment/WeaponInterface.java b/Server/src/main/core/game/node/entity/combat/equipment/WeaponInterface.java index cb74f3fa6..7c00c5145 100644 --- a/Server/src/main/core/game/node/entity/combat/equipment/WeaponInterface.java +++ b/Server/src/main/core/game/node/entity/combat/equipment/WeaponInterface.java @@ -125,6 +125,16 @@ public final class WeaponInterface extends Component { */ public static final int STYLE_CAST = 8; + /** + * Attribute storing the player's autocast spell for reload upon relog. + */ + public static final String attributeAutocastButtonId = "/save:autocast:buttonid"; + + /** + * Attribute storing the player's autocast combat style for reload upon relog. + */ + public static final String attributeAutocastStyle = "/save:autocast:style"; + /** * The player. */ @@ -259,7 +269,7 @@ public final class WeaponInterface extends Component { player.getProperties().setAttackAnimation(attackAnimations[player.getSettings().getAttackStyleIndex()]); } if (current != WeaponInterfaces.STAFF) { - selectAutoSpell(-1, false); + selectAutoSpell(-1, false, false); PacketRepository.send(InterfaceConfig.class, new InterfaceConfigContext(player, id, getConfig(current.getAttackStyles().length, current.getInterfaceId()), !specialBar)); } else { //if staff PacketRepository.send(InterfaceConfig.class, new InterfaceConfigContext(player, id, 87, !specialBar)); @@ -268,7 +278,7 @@ public final class WeaponInterface extends Component { if (current == WeaponInterfaces.STAFF && player.getAttribute("autocast_select", false)) { open(); } - selectAutoSpell(-1, true); + selectAutoSpell(-1, true, false); } PacketRepository.send(StringPacket.class, new StringContext(player, name, id, 0)); if (player.getSettings().isSpecialToggled()) { @@ -317,7 +327,7 @@ public final class WeaponInterface extends Component { */ private void checkStaffConfigs(int slot) { if (current != WeaponInterfaces.STAFF) { - selectAutoSpell(-1, false); + selectAutoSpell(-1, false, false); return; } boolean defensive = slot == 3; @@ -354,7 +364,7 @@ public final class WeaponInterface extends Component { * @param buttonId The button id. * @param adjustAttackStyle If the attack style should be adjusted. */ - public void selectAutoSpell(int buttonId, boolean adjustAttackStyle) { + public void selectAutoSpell(int buttonId, boolean adjustAttackStyle, boolean forgetAutocast) { boolean modern = player.getSpellBookManager().getSpellBook() == Components.MAGIC_192; int[] data = modern ? MODERN_SPELL_IDS : ANCIENT_SPELL_IDS; if (modern && player.getEquipment().getNew(3).getName().equalsIgnoreCase("Slayer's staff")) { @@ -376,8 +386,13 @@ public final class WeaponInterface extends Component { } } } + if (forgetAutocast) { + removeAttributes(player, attributeAutocastButtonId, attributeAutocastStyle); + } if (buttonId < 0) { player.getProperties().setAutocastSpell(null); + setComponentVisibility(player, Components.WEAPON_STAFF_SEL_90, 83, false); + setComponentVisibility(player, Components.WEAPON_STAFF_SEL_90, 183, false); if (adjustAttackStyle && current != null) { setAttackStyle(3); player.getProperties().getCombatPulse().updateStyle(); @@ -389,6 +404,8 @@ public final class WeaponInterface extends Component { player.getPacketDispatch().sendInterfaceConfig(Components.WEAPON_STAFF_SEL_90, 83, !defensive); current = (CombatSpell) (modern ? SpellBookManager.SpellBook.MODERN.getSpell(data[buttonId]) : SpellBookManager.SpellBook.ANCIENT.getSpell(data[buttonId])); player.getProperties().setAutocastSpell(current); + setAttribute(player, attributeAutocastButtonId, buttonId); + setAttribute(player, attributeAutocastStyle, player.getSettings().getAttackStyleIndex()); int configId = configStart + (2 * buttonId); if (modern && player.getEquipment().getNew(3).getName().equalsIgnoreCase("Slayer's staff") || modern && player.getEquipment().getNew(3).getName().equalsIgnoreCase("Void knight mace")) { boolean slayer = player.getEquipment().getNew(3).getName().equalsIgnoreCase("Slayer's staff"); @@ -508,6 +525,37 @@ public final class WeaponInterface extends Component { return WeaponInterfaces.values()[slot]; } + /** + * Restores the player's autocast settings to what they were in the prior login session. + * Returns false if the player has no autocast to restore, true otherwise. + */ + public boolean restoreAutocast() { + int buttonID = getAttribute(player, attributeAutocastButtonId, -1); + int style = getAttribute(player, attributeAutocastStyle, -1); + if (buttonID < 0 || style < 0 || current != WeaponInterfaces.STAFF || !canAutocast(false)) { + removeAttributes(player, attributeAutocastButtonId, attributeAutocastStyle); + return false; + } + restoreAttackStyle(style); + checkStaffConfigs(style); + selectAutoSpell(buttonID, false, false); + player.getProperties().getCombatPulse().updateStyle(); + return true; + } + + /** + * Restores the player's attack style settings to what they were in the prior login session. + */ + public void restoreAttackStyle(int index) { + if (index < 0 || index >= current.getAttackStyles().length) return; + player.getSettings().toggleAttackStyleIndex(index); + player.getProperties().setAttackStyle(current.getAttackStyles()[index]); + if (index < attackAnimations.length && !player.getAppearance().isNpc()) { + player.getProperties().setAttackAnimation(attackAnimations[index]); + } + player.getProperties().getCombatPulse().updateStyle(); + } + /** * Represents an attack style. * @author Emperor diff --git a/Server/src/main/core/game/node/entity/player/info/login/LoginConfiguration.java b/Server/src/main/core/game/node/entity/player/info/login/LoginConfiguration.java index b7af34638..a4a0ebb66 100644 --- a/Server/src/main/core/game/node/entity/player/info/login/LoginConfiguration.java +++ b/Server/src/main/core/game/node/entity/player/info/login/LoginConfiguration.java @@ -1,5 +1,6 @@ package core.game.node.entity.player.info.login; +import core.api.EquipmentSlot; import core.game.component.Component; import core.game.node.entity.player.Player; import core.game.node.entity.player.link.emote.Emotes; @@ -11,6 +12,7 @@ import core.net.packet.out.Interface; import core.plugin.Plugin; import core.ServerConstants; import core.game.interaction.InteractionListeners; +import core.game.node.entity.combat.equipment.WeaponInterface; import content.global.handlers.iface.RulesAndInfo; import core.tools.Log; import core.game.world.GameWorld; @@ -138,15 +140,23 @@ public final class LoginConfiguration { player.getEmoteManager().unlock(Emotes.SAFETY_FIRST); } + int savedAttackStyle = player.getSettings().getAttackStyleIndex(); for (Item item : player.getEquipment().toArray()) { //Run equip hooks for all items equipped on login. //We should have already been doing this. //Frankly, I don't even want to imagine the number of bugs us *not* doing this has caused. if (item == null) continue; - player.getEquipment().remove(item); - if (!InteractionListeners.run(item.getId(), player, item, true) || !player.getEquipment().add(item, true, false)) { - player.sendMessage(colorize("%RAs you can no longer wear " + item.getName() + ", it has been unequipped.")); - addItemOrBank(player, item.getId(), item.getAmount()); + if (player.getEquipment().remove(item)) { + if (!InteractionListeners.run(item.getId(), player, item, true) || !player.getEquipment().add(item, true, false)) { + player.sendMessage(colorize("%RAs you can no longer wear " + item.getName() + ", it has been unequipped.")); + addItemOrBank(player, item.getId(), item.getAmount()); + } else if (equipSlot(item.getId()) == EquipmentSlot.WEAPON) { + // Put player's weapon style back to how it was before it was re-equipped. + WeaponInterface inter = player.getExtension(WeaponInterface.class); + if (!inter.restoreAutocast()) { + inter.restoreAttackStyle(savedAttackStyle); + } + } } } diff --git a/Server/src/main/core/game/node/entity/player/link/InterfaceManager.java b/Server/src/main/core/game/node/entity/player/link/InterfaceManager.java index 859b0aed6..dde450c7a 100644 --- a/Server/src/main/core/game/node/entity/player/link/InterfaceManager.java +++ b/Server/src/main/core/game/node/entity/player/link/InterfaceManager.java @@ -410,7 +410,7 @@ public final class InterfaceManager { } } if (player.getProperties().getAutocastSpell() != null) { - inter.selectAutoSpell(inter.getAutospellId(player.getProperties().getAutocastSpell().getSpellId()), true); + inter.selectAutoSpell(inter.getAutospellId(player.getProperties().getAutocastSpell().getSpellId()), true, false); } } diff --git a/Server/src/main/core/game/system/timer/impl/SpellbookSwap.kt b/Server/src/main/core/game/system/timer/impl/SpellbookSwap.kt index b689e3a0a..3fe48b5f5 100644 --- a/Server/src/main/core/game/system/timer/impl/SpellbookSwap.kt +++ b/Server/src/main/core/game/system/timer/impl/SpellbookSwap.kt @@ -79,7 +79,7 @@ class SpellbookSwap : PersistTimer(runInterval = minutesToTicks(2), identifier = // Clear autocast val weaponInterface = entity.getExtension(WeaponInterface::class.java) if (weaponInterface != null && entity.properties.autocastSpell != null) { - weaponInterface.selectAutoSpell(-1, true) + weaponInterface.selectAutoSpell(-1, true, true) } // Close autocast selection interface if it's still open if (entity.getAttribute("autocast_select", false)) { From 83c6a961ecf5c252155ac0a3c050e698ca0355c6 Mon Sep 17 00:00:00 2001 From: Bishop Date: Sun, 26 Jul 2026 10:56:52 -0500 Subject: [PATCH 05/11] ContentAPI --- .../game/node/entity/player/info/login/LoginConfiguration.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Server/src/main/core/game/node/entity/player/info/login/LoginConfiguration.java b/Server/src/main/core/game/node/entity/player/info/login/LoginConfiguration.java index a4a0ebb66..e1c4bdbf0 100644 --- a/Server/src/main/core/game/node/entity/player/info/login/LoginConfiguration.java +++ b/Server/src/main/core/game/node/entity/player/info/login/LoginConfiguration.java @@ -1,5 +1,6 @@ package core.game.node.entity.player.info.login; +import core.api.Container; import core.api.EquipmentSlot; import core.game.component.Component; import core.game.node.entity.player.Player; @@ -146,7 +147,7 @@ public final class LoginConfiguration { //We should have already been doing this. //Frankly, I don't even want to imagine the number of bugs us *not* doing this has caused. if (item == null) continue; - if (player.getEquipment().remove(item)) { + if (removeItem(player, item, Container.EQUIPMENT)) { if (!InteractionListeners.run(item.getId(), player, item, true) || !player.getEquipment().add(item, true, false)) { player.sendMessage(colorize("%RAs you can no longer wear " + item.getName() + ", it has been unequipped.")); addItemOrBank(player, item.getId(), item.getAmount()); From c31b643c0b97e517136507608b3c08d4d9b72de1 Mon Sep 17 00:00:00 2001 From: Bishop Date: Sun, 26 Jul 2026 11:17:14 -0500 Subject: [PATCH 06/11] Another ContentAPI --- .../global/handlers/iface/bank/BankDepositBoxInterface.kt | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Server/src/main/content/global/handlers/iface/bank/BankDepositBoxInterface.kt b/Server/src/main/content/global/handlers/iface/bank/BankDepositBoxInterface.kt index 81880a993..29ed3b7e2 100644 --- a/Server/src/main/content/global/handlers/iface/bank/BankDepositBoxInterface.kt +++ b/Server/src/main/content/global/handlers/iface/bank/BankDepositBoxInterface.kt @@ -5,6 +5,7 @@ import core.api.animate import core.api.dumpBeastOfBurden import core.api.runWorldTask import core.api.sendMessage +import core.api.setInterfaceText import core.game.component.Component import core.game.node.entity.player.Player import org.rs09.consts.Animations @@ -67,11 +68,7 @@ class BankDepositBoxInterface : InterfaceListener { override fun defineInterfaceListeners() { onOpen(Components.BANK_DEPOSIT_BOX_11) { player, _ -> - player.packetDispatch.sendString( - "The Bank of ${ServerConstants.SERVER_NAME} - Deposit Box", - Components.BANK_DEPOSIT_BOX_11, - 12 - ) + setInterfaceText(player, "The Bank of ${ServerConstants.SERVER_NAME} - Deposit Box", Components.BANK_DEPOSIT_BOX_11, 12) return@onOpen true } on(Components.BANK_DEPOSIT_BOX_11, ::handleDepositBoxMenu) From 43e53f7658b47cdf31bdca6debbfcef3627a9c14 Mon Sep 17 00:00:00 2001 From: Bishop Date: Sun, 26 Jul 2026 11:56:56 -0500 Subject: [PATCH 07/11] Removed magic numbers --- .../node/entity/combat/equipment/WeaponInterface.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Server/src/main/core/game/node/entity/combat/equipment/WeaponInterface.java b/Server/src/main/core/game/node/entity/combat/equipment/WeaponInterface.java index 7c00c5145..934b1f88f 100644 --- a/Server/src/main/core/game/node/entity/combat/equipment/WeaponInterface.java +++ b/Server/src/main/core/game/node/entity/combat/equipment/WeaponInterface.java @@ -365,6 +365,8 @@ public final class WeaponInterface extends Component { * @param adjustAttackStyle If the attack style should be adjusted. */ public void selectAutoSpell(int buttonId, boolean adjustAttackStyle, boolean forgetAutocast) { + int stdAutocastBookChild = 83; + int defAutocastBookChild = 183; boolean modern = player.getSpellBookManager().getSpellBook() == Components.MAGIC_192; int[] data = modern ? MODERN_SPELL_IDS : ANCIENT_SPELL_IDS; if (modern && player.getEquipment().getNew(3).getName().equalsIgnoreCase("Slayer's staff")) { @@ -391,8 +393,8 @@ public final class WeaponInterface extends Component { } if (buttonId < 0) { player.getProperties().setAutocastSpell(null); - setComponentVisibility(player, Components.WEAPON_STAFF_SEL_90, 83, false); - setComponentVisibility(player, Components.WEAPON_STAFF_SEL_90, 183, false); + setComponentVisibility(player, Components.WEAPON_STAFF_SEL_90, defAutocastBookChild, false); + setComponentVisibility(player, Components.WEAPON_STAFF_SEL_90, stdAutocastBookChild, false); if (adjustAttackStyle && current != null) { setAttackStyle(3); player.getProperties().getCombatPulse().updateStyle(); @@ -400,8 +402,8 @@ public final class WeaponInterface extends Component { return; } boolean defensive = player.getSettings().getAttackStyleIndex() == 3; - player.getPacketDispatch().sendInterfaceConfig(Components.WEAPON_STAFF_SEL_90, 183, defensive); - player.getPacketDispatch().sendInterfaceConfig(Components.WEAPON_STAFF_SEL_90, 83, !defensive); + player.getPacketDispatch().sendInterfaceConfig(Components.WEAPON_STAFF_SEL_90, defAutocastBookChild, defensive); + player.getPacketDispatch().sendInterfaceConfig(Components.WEAPON_STAFF_SEL_90, stdAutocastBookChild, !defensive); current = (CombatSpell) (modern ? SpellBookManager.SpellBook.MODERN.getSpell(data[buttonId]) : SpellBookManager.SpellBook.ANCIENT.getSpell(data[buttonId])); player.getProperties().setAutocastSpell(current); setAttribute(player, attributeAutocastButtonId, buttonId); From 04bc65c83a8515aef31f1f5fbb2012768a33eccf Mon Sep 17 00:00:00 2001 From: Bishop Date: Sun, 26 Jul 2026 12:00:01 -0500 Subject: [PATCH 08/11] ContentAPI on the thing I removed magic numbers from --- .../game/node/entity/combat/equipment/WeaponInterface.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Server/src/main/core/game/node/entity/combat/equipment/WeaponInterface.java b/Server/src/main/core/game/node/entity/combat/equipment/WeaponInterface.java index 934b1f88f..4716e7939 100644 --- a/Server/src/main/core/game/node/entity/combat/equipment/WeaponInterface.java +++ b/Server/src/main/core/game/node/entity/combat/equipment/WeaponInterface.java @@ -402,8 +402,8 @@ public final class WeaponInterface extends Component { return; } boolean defensive = player.getSettings().getAttackStyleIndex() == 3; - player.getPacketDispatch().sendInterfaceConfig(Components.WEAPON_STAFF_SEL_90, defAutocastBookChild, defensive); - player.getPacketDispatch().sendInterfaceConfig(Components.WEAPON_STAFF_SEL_90, stdAutocastBookChild, !defensive); + setComponentVisibility(player, Components.WEAPON_STAFF_SEL_90, defAutocastBookChild, defensive); + setComponentVisibility(player, Components.WEAPON_STAFF_SEL_90, stdAutocastBookChild, !defensive); current = (CombatSpell) (modern ? SpellBookManager.SpellBook.MODERN.getSpell(data[buttonId]) : SpellBookManager.SpellBook.ANCIENT.getSpell(data[buttonId])); player.getProperties().setAutocastSpell(current); setAttribute(player, attributeAutocastButtonId, buttonId); From 3294db8b32160113d1b3c87c805b1af5417913b9 Mon Sep 17 00:00:00 2001 From: Bishop Date: Sun, 26 Jul 2026 13:35:53 -0500 Subject: [PATCH 09/11] Is that really all the magic numbers? --- .../content/global/handlers/iface/FriendsListInterface.kt | 6 +++++- .../global/handlers/iface/bank/BankDepositBoxInterface.kt | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Server/src/main/content/global/handlers/iface/FriendsListInterface.kt b/Server/src/main/content/global/handlers/iface/FriendsListInterface.kt index a7044613e..6617812a0 100644 --- a/Server/src/main/content/global/handlers/iface/FriendsListInterface.kt +++ b/Server/src/main/content/global/handlers/iface/FriendsListInterface.kt @@ -12,8 +12,12 @@ import org.rs09.consts.Components */ class FriendsListInterface : Component(Components.FRIENDS2_550) { + companion object { + private const val TITLE_ELEMENT = 3 + } + override fun open(player: Player) { super.open(player) - setInterfaceText(player, "Friends List - ${ServerConstants.SERVER_NAME} ${GameWorld.settings!!.worldId}", Components.FRIENDS2_550, 3) + setInterfaceText(player, "Friends List - ${ServerConstants.SERVER_NAME} ${GameWorld.settings!!.worldId}", Components.FRIENDS2_550, TITLE_ELEMENT) } } \ No newline at end of file diff --git a/Server/src/main/content/global/handlers/iface/bank/BankDepositBoxInterface.kt b/Server/src/main/content/global/handlers/iface/bank/BankDepositBoxInterface.kt index 29ed3b7e2..1d2692aa3 100644 --- a/Server/src/main/content/global/handlers/iface/bank/BankDepositBoxInterface.kt +++ b/Server/src/main/content/global/handlers/iface/bank/BankDepositBoxInterface.kt @@ -23,6 +23,7 @@ class BankDepositBoxInterface : InterfaceListener { private const val BUTTON_DEPOSIT_BOB = 13 private const val MENU_ELEMENT = 11 + private const val TITLE_ELEMENT = 12 private const val OP_AMOUNT_ONE = 155 private const val OP_AMOUNT_FIVE = 196 private const val OP_AMOUNT_TEN = 124 @@ -68,7 +69,7 @@ class BankDepositBoxInterface : InterfaceListener { override fun defineInterfaceListeners() { onOpen(Components.BANK_DEPOSIT_BOX_11) { player, _ -> - setInterfaceText(player, "The Bank of ${ServerConstants.SERVER_NAME} - Deposit Box", Components.BANK_DEPOSIT_BOX_11, 12) + setInterfaceText(player, "The Bank of ${ServerConstants.SERVER_NAME} - Deposit Box", Components.BANK_DEPOSIT_BOX_11, TITLE_ELEMENT) return@onOpen true } on(Components.BANK_DEPOSIT_BOX_11, ::handleDepositBoxMenu) From 938f068211db720c4e47d9e98f495d7c9db6d2d0 Mon Sep 17 00:00:00 2001 From: Bishop Date: Sat, 1 Aug 2026 10:20:55 -0500 Subject: [PATCH 10/11] Fixed issues Player Name found in testing --- .../game/node/entity/combat/equipment/WeaponInterface.java | 5 ++++- .../node/entity/player/info/login/LoginConfiguration.java | 7 ++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Server/src/main/core/game/node/entity/combat/equipment/WeaponInterface.java b/Server/src/main/core/game/node/entity/combat/equipment/WeaponInterface.java index 4716e7939..e69802089 100644 --- a/Server/src/main/core/game/node/entity/combat/equipment/WeaponInterface.java +++ b/Server/src/main/core/game/node/entity/combat/equipment/WeaponInterface.java @@ -308,6 +308,9 @@ public final class WeaponInterface extends Component { slot = 3; } } + if (current == WeaponInterfaces.STAFF && slot <= 2) { + removeAttributes(player, attributeAutocastButtonId, attributeAutocastStyle); + } if (slot < 0 || slot >= current.getAttackStyles().length) { return false; } @@ -534,7 +537,7 @@ public final class WeaponInterface extends Component { public boolean restoreAutocast() { int buttonID = getAttribute(player, attributeAutocastButtonId, -1); int style = getAttribute(player, attributeAutocastStyle, -1); - if (buttonID < 0 || style < 0 || current != WeaponInterfaces.STAFF || !canAutocast(false)) { + if (buttonID < 0 || style < 0 || !canAutocast(false)) { removeAttributes(player, attributeAutocastButtonId, attributeAutocastStyle); return false; } diff --git a/Server/src/main/core/game/node/entity/player/info/login/LoginConfiguration.java b/Server/src/main/core/game/node/entity/player/info/login/LoginConfiguration.java index e1c4bdbf0..9fdf421cb 100644 --- a/Server/src/main/core/game/node/entity/player/info/login/LoginConfiguration.java +++ b/Server/src/main/core/game/node/entity/player/info/login/LoginConfiguration.java @@ -151,9 +151,14 @@ public final class LoginConfiguration { if (!InteractionListeners.run(item.getId(), player, item, true) || !player.getEquipment().add(item, true, false)) { player.sendMessage(colorize("%RAs you can no longer wear " + item.getName() + ", it has been unequipped.")); addItemOrBank(player, item.getId(), item.getAmount()); + if (equipSlot(item.getId()) == EquipmentSlot.WEAPON) { + // Default to accurate style if weapon frisk failed + WeaponInterface inter = player.getExtension(WeaponInterface.class); + inter.restoreAttackStyle(0); + } } else if (equipSlot(item.getId()) == EquipmentSlot.WEAPON) { - // Put player's weapon style back to how it was before it was re-equipped. WeaponInterface inter = player.getExtension(WeaponInterface.class); + // Put player's weapon style back to how it was before it was re-equipped if (!inter.restoreAutocast()) { inter.restoreAttackStyle(savedAttackStyle); } From feda8c6988a7925bbe5b3f6f675ee5e630580c13 Mon Sep 17 00:00:00 2001 From: Bishop Date: Sat, 1 Aug 2026 10:22:11 -0500 Subject: [PATCH 11/11] Capitalized consts --- .../combat/equipment/WeaponInterface.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Server/src/main/core/game/node/entity/combat/equipment/WeaponInterface.java b/Server/src/main/core/game/node/entity/combat/equipment/WeaponInterface.java index e69802089..87832e062 100644 --- a/Server/src/main/core/game/node/entity/combat/equipment/WeaponInterface.java +++ b/Server/src/main/core/game/node/entity/combat/equipment/WeaponInterface.java @@ -128,12 +128,12 @@ public final class WeaponInterface extends Component { /** * Attribute storing the player's autocast spell for reload upon relog. */ - public static final String attributeAutocastButtonId = "/save:autocast:buttonid"; + public static final String ATTRIBUTE_AUTOCAST_BUTTON_ID = "/save:autocast:buttonid"; /** * Attribute storing the player's autocast combat style for reload upon relog. */ - public static final String attributeAutocastStyle = "/save:autocast:style"; + public static final String ATTRIBUTE_AUTOCAST_STYLE = "/save:autocast:style"; /** * The player. @@ -309,7 +309,7 @@ public final class WeaponInterface extends Component { } } if (current == WeaponInterfaces.STAFF && slot <= 2) { - removeAttributes(player, attributeAutocastButtonId, attributeAutocastStyle); + removeAttributes(player, ATTRIBUTE_AUTOCAST_BUTTON_ID, ATTRIBUTE_AUTOCAST_STYLE); } if (slot < 0 || slot >= current.getAttackStyles().length) { return false; @@ -392,7 +392,7 @@ public final class WeaponInterface extends Component { } } if (forgetAutocast) { - removeAttributes(player, attributeAutocastButtonId, attributeAutocastStyle); + removeAttributes(player, ATTRIBUTE_AUTOCAST_BUTTON_ID, ATTRIBUTE_AUTOCAST_STYLE); } if (buttonId < 0) { player.getProperties().setAutocastSpell(null); @@ -409,8 +409,8 @@ public final class WeaponInterface extends Component { setComponentVisibility(player, Components.WEAPON_STAFF_SEL_90, stdAutocastBookChild, !defensive); current = (CombatSpell) (modern ? SpellBookManager.SpellBook.MODERN.getSpell(data[buttonId]) : SpellBookManager.SpellBook.ANCIENT.getSpell(data[buttonId])); player.getProperties().setAutocastSpell(current); - setAttribute(player, attributeAutocastButtonId, buttonId); - setAttribute(player, attributeAutocastStyle, player.getSettings().getAttackStyleIndex()); + setAttribute(player, ATTRIBUTE_AUTOCAST_BUTTON_ID, buttonId); + setAttribute(player, ATTRIBUTE_AUTOCAST_STYLE, player.getSettings().getAttackStyleIndex()); int configId = configStart + (2 * buttonId); if (modern && player.getEquipment().getNew(3).getName().equalsIgnoreCase("Slayer's staff") || modern && player.getEquipment().getNew(3).getName().equalsIgnoreCase("Void knight mace")) { boolean slayer = player.getEquipment().getNew(3).getName().equalsIgnoreCase("Slayer's staff"); @@ -535,10 +535,10 @@ public final class WeaponInterface extends Component { * Returns false if the player has no autocast to restore, true otherwise. */ public boolean restoreAutocast() { - int buttonID = getAttribute(player, attributeAutocastButtonId, -1); - int style = getAttribute(player, attributeAutocastStyle, -1); + int buttonID = getAttribute(player, ATTRIBUTE_AUTOCAST_BUTTON_ID, -1); + int style = getAttribute(player, ATTRIBUTE_AUTOCAST_STYLE, -1); if (buttonID < 0 || style < 0 || !canAutocast(false)) { - removeAttributes(player, attributeAutocastButtonId, attributeAutocastStyle); + removeAttributes(player, ATTRIBUTE_AUTOCAST_BUTTON_ID, ATTRIBUTE_AUTOCAST_STYLE); return false; } restoreAttackStyle(style);