From 664f1be79b633432907789284f087b067bb2c71c Mon Sep 17 00:00:00 2001 From: Bishop Date: Mon, 20 Jul 2026 22:44:07 -0500 Subject: [PATCH 01/13] Rename .java to .kt --- .../{ConstructionInterface.java => ConstructionInterface.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Server/src/main/content/global/skill/construction/{ConstructionInterface.java => ConstructionInterface.kt} (100%) diff --git a/Server/src/main/content/global/skill/construction/ConstructionInterface.java b/Server/src/main/content/global/skill/construction/ConstructionInterface.kt similarity index 100% rename from Server/src/main/content/global/skill/construction/ConstructionInterface.java rename to Server/src/main/content/global/skill/construction/ConstructionInterface.kt From 14bb43b56514e8200376344ba1dbf12682eb5e7e Mon Sep 17 00:00:00 2001 From: Bishop Date: Mon, 20 Jul 2026 22:44:08 -0500 Subject: [PATCH 02/13] Flatpack production mechanics --- .../construction/ConstructionInterface.kt | 225 +++++++++--------- .../decoration/workshop/WorkbenchListeners.kt | 111 +++++++++ 2 files changed, 226 insertions(+), 110 deletions(-) create mode 100644 Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt diff --git a/Server/src/main/content/global/skill/construction/ConstructionInterface.kt b/Server/src/main/content/global/skill/construction/ConstructionInterface.kt index a36b0329b..32c244112 100644 --- a/Server/src/main/content/global/skill/construction/ConstructionInterface.kt +++ b/Server/src/main/content/global/skill/construction/ConstructionInterface.kt @@ -1,120 +1,125 @@ -package content.global.skill.construction; +package content.global.skill.construction - -import core.cache.def.impl.ItemDefinition; -import core.game.component.Component; -import core.game.component.ComponentDefinition; -import core.game.component.ComponentPlugin; -import core.game.node.entity.player.Player; -import core.game.node.entity.skill.Skills; -import core.game.node.scenery.Scenery; -import core.plugin.Initializable; -import core.plugin.Plugin; -import core.tools.Log; -import core.tools.SystemLogger; - -import static core.api.ContentAPIKt.log; +import content.global.skill.construction.decoration.workshop.WorkbenchListeners +import core.api.* +import core.cache.def.impl.ItemDefinition +import core.game.interaction.InterfaceListener +import core.game.node.entity.skill.Skills +import core.game.node.scenery.Scenery +import core.tools.Log /** * Handles the creating of a decoration object. * @author Emperor - * + * @author Bishop */ -@Initializable -public final class ConstructionInterface extends ComponentPlugin { - @Override - public Plugin newInstance(Object arg) { - ComponentDefinition.put(396, this); - ComponentDefinition.put(398, this); - ComponentDefinition.put(402, this); - return this; - } +class ConstructionInterface : InterfaceListener { - @Override - public boolean handle(Player player, Component component, int opcode, int button, int slot, int itemId) { - switch (component.getId()) { - case 396: - switch (button) { - case 132: - player.getInterfaceManager().close(); - Hotspot hotspot = player.getAttribute("con:hotspot"); - Scenery object = player.getAttribute("con:hsobject"); - if (hotspot == null || object == null) { - log(this.getClass(), Log.ERR, "Failed building decoration " + hotspot + " : " + object); - break; - } - slot = ((slot % 2 != 0) ? 4 : 0) + (slot >> 1); - if (slot >= hotspot.getHotspot().getDecorations().length) { - log(this.getClass(), Log.ERR, "Failed building decoration " + slot + "/" + hotspot.getHotspot().getDecorations().length); - break; - } - boolean debug = player.isStaff(); - Decoration deco = hotspot.getHotspot().getDecorations()[slot]; - if (!debug) { - if (player.getSkills().getLevel(Skills.CONSTRUCTION) < deco.getLevel()) { - player.sendMessage("You need to have a Construction level of " + deco.getLevel() + " to build that."); - return true; - } - if (!player.getInventory().containsItems(deco.getItems())) { - player.sendMessage("You don't have the right materials."); - return true; - } - for (int tool : deco.getTools()) { - if (tool == BuildingUtils.WATERING_CAN) { - boolean hasWateringCan = false; - for (int i = 0; i < 8; i++) { - if (player.getInventory().contains(tool - i, 1)) { - hasWateringCan = true; - break; - } - } - if (!hasWateringCan) { - player.sendMessage("You need a watering can to plant this."); - return true; - } - continue; - } - if (!player.getInventory().contains(tool, 1)) { - player.sendMessage("You need a " + ItemDefinition.forId(tool).getName() + " to build this."); - return true; - } - } - } - BuildingUtils.buildDecoration(player, hotspot, deco, object); - return true; - } - break; - case 398: - switch (button) { - case 14: - player.getHouseManager().toggleBuildingMode(player, true); - return true; - case 1: - player.getHouseManager().toggleBuildingMode(player, false); - return true; - case 15: - player.getHouseManager().expelGuests(player); - return true; - case 13: - if (!player.getHouseManager().isInHouse(player)) { - player.sendMessage("You can't do this outside of your house."); - return true; - } - HouseManager.leave(player); - return true; - } - break; - case 402: - int index = button - 160; - log(this.getClass(), Log.FINE, "BuildRoom Interface Index: " + index); - if (index > -1 && index < RoomProperties.values().length) { - player.getDialogueInterpreter().open("con:room", RoomProperties.values()[index]); - return true; - } - break; - } - return false; - } + companion object { + const val DECO_INTERFACE = 396 + const val POH_MENU = 398 + const val ROOM_INTERFACE = 402 + } + override fun defineInterfaceListeners() { + on(DECO_INTERFACE) { player, _, _, buttonID, slot, _ -> + when (buttonID) { + 132 -> { + closeInterface(player) + val hotspot = getAttribute(player, "con:hotspot", null) + val `object` = getAttribute(player, "con:hsobject", null) + if (hotspot == null || `object` == null) { + log(this.javaClass, Log.ERR, "Failed building decoration $hotspot : $`object`") + return@on false + } + val slot = (if (slot % 2 != 0) 4 else 0) + (slot shr 1) + if (slot >= hotspot.hotspot.decorations.size) { + log(this.javaClass, Log.ERR, "Failed building decoration " + slot + "/" + hotspot.hotspot.decorations.size) + return@on false + } + val deco = hotspot.hotspot.decorations[slot] + if (!player.isAdmin) { + if (getDynLevel(player, Skills.CONSTRUCTION) < deco.level) { + sendMessage(player, "You need to have a Construction level of " + deco.level + " to build that.") + return@on true + } + if (!player.inventory.containsItems(*deco.items)) { // search for contentAPI way to do this + sendMessage(player, "You don't have the right materials.") + return@on true + } + for (tool in deco.tools) { + if (tool == BuildingUtils.WATERING_CAN) { + var hasWateringCan = false + var i = 0 + while (i < 8) { + if (inInventory(player, tool - i)) { + hasWateringCan = true + break + } + i++ + } + if (!hasWateringCan) { + sendMessage(player, "You need a watering can to plant this.") + return@on true + } + continue + } + if (!player.inventory.contains(tool, 1)) { + sendMessage(player, "You need a ${ItemDefinition.forId(tool).name} to build this.") + return@on true + } + } + if (getAttribute(player, WorkbenchListeners.attributeFlatpackMode, false) && + WorkbenchListeners.getMaxLevel(getAttribute(player, WorkbenchListeners.attributeWorkbenchId, 0)) < deco.level) { + sendMessage(player, "You need a better workbench to make this flatpack.") // placeholder + return@on true + } + } + if (getAttribute(player, WorkbenchListeners.attributeFlatpackMode, false)) { + WorkbenchListeners.produceFlatpack(player, deco) + } else { + BuildingUtils.buildDecoration(player, hotspot, deco, `object`) + } + return@on true + } + else -> return@on false + } + } + + on(POH_MENU) { player, _, _, buttonID, _, _ -> + when (buttonID) { + 14 -> { + player.houseManager.toggleBuildingMode(player, true) + return@on true + } + 1 -> { + player.houseManager.toggleBuildingMode(player, false) + return@on true + } + 15 -> { + player.houseManager.expelGuests(player) + return@on true + } + 13 -> { + if (!player.houseManager.isInHouse(player)) { + player.sendMessage("You can't do this outside of your house.") + return@on true + } + HouseManager.leave(player) + return@on true + } + else -> return@on false + } + } + + on(ROOM_INTERFACE) { player, _, _, buttonID, _, _ -> + val index = buttonID - 160 + log(this.javaClass, Log.FINE, "BuildRoom Interface Index: $index") + if (index > -1 && index < RoomProperties.values().size) { + player.dialogueInterpreter.open("con:room", RoomProperties.values()[index]) + } + return@on true + } + } } \ No newline at end of file diff --git a/Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt b/Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt new file mode 100644 index 000000000..621478745 --- /dev/null +++ b/Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt @@ -0,0 +1,111 @@ +package content.global.skill.construction.decoration.workshop + +import content.global.skill.construction.BuildHotspot +import content.global.skill.construction.BuildingUtils +import content.global.skill.construction.ConstructionInterface +import content.global.skill.construction.Decoration +import core.api.* +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.interaction.InterfaceListener +import core.game.node.entity.player.Player +import core.game.node.entity.skill.Skills +import core.game.node.item.Item +import org.rs09.consts.Items +import org.rs09.consts.Scenery + +/** + * Handles usage of the workbench, which allows construction of flatpacks. + * @author Bishop + */ + +class WorkbenchListeners : InteractionListener, InterfaceListener { + + companion object { + const val WORKBENCH_INTERFACE = 397 + const val attributeWorkbenchId = "con:workbench" + const val attributeFlatpackMode = "con:flatpack" + const val attributeSelection = "con:flatpack-hotspot" + + val WORKBENCHES = intArrayOf( + Scenery.WORKBENCH_13704, // wooden + Scenery.WORKBENCH_13705, // oak + Scenery.WORKBENCH_13706, // steel framed + Scenery.WORKBENCH_13707, // with vice + Scenery.WORKBENCH_13708, // with lathe + ) + + val FLATPACK_CATEGORIES = arrayOf( + BuildHotspot.CHAIRS_1, // 111 + BuildHotspot.BOOKCASE, // 112 + BuildHotspot.BARRELS, // 113 + BuildHotspot.KITCHEN_TABLE, // 114 + BuildHotspot.DINING_TABLE, // 115 + BuildHotspot.DINING_BENCH_1, // 116 + BuildHotspot.BED, // 117 + BuildHotspot.DRESSER, // 118 + BuildHotspot.DRAWERS, // 119 + BuildHotspot.CLOCK, // 120 + BuildHotspot.CAPE_RACK, // 121 + BuildHotspot.MAGIC_WARDROBE, // 122 + BuildHotspot.ARMOUR_CASE, // 123 + BuildHotspot.TREASURE_CHEST, // 124 + BuildHotspot.COSTUME_BOX, // 125 + BuildHotspot.TOY_BOX, // 126 + ) + + val FLATPACKS = mapOf( + Decoration.CRUDE_CHAIR to Items.CRUDE_WOODEN_CHAIR_8496, + Decoration.OAK_CHAIR to Items.OAK_CHAIR_8502 + ) + + fun getMaxLevel(workbenchId: Int): Int { + return (WORKBENCHES.indexOf(workbenchId) + 1) * 20 + } + + // TODO: replace with real flatpack item ID lookup + fun produceFlatpack(player: Player, deco: Decoration) { + val reward = FLATPACKS[deco]?: return + if (removeItem(player, deco.items) || player.isAdmin) { + rewardXP(player, Skills.CONSTRUCTION, deco.experience.toDouble()) + addItemOrDrop(player, reward) + } + } + } + + override fun defineListeners() { + on(WORKBENCHES, IntType.SCENERY, "work-at") { player, node -> + setAttribute(player, attributeWorkbenchId, node.id) + openInterface(player, WORKBENCH_INTERFACE) + return@on true + } + on(WORKBENCHES, IntType.SCENERY, "upgrade") { player, node -> + if (!inInventory(player, Items.OAK_PLANK_8778, 2) || !inInventory(player, Items.STEEL_BAR_2353)) { + return@on false + } + if (removeItem(player, Item(Items.OAK_PLANK_8778, 2)) && removeItem(player, Items.STEEL_BAR_2353)) { + + } + return@on true + } + } + + override fun defineInterfaceListeners() { + on(WORKBENCH_INTERFACE) { player, _, _, buttonID, _, _ -> + val index = buttonID - 111 + if (index < 0 || index >= FLATPACK_CATEGORIES.size) return@on false + val hotspot = FLATPACK_CATEGORIES[index] + setAttribute(player, attributeSelection, hotspot) + setAttribute(player, attributeFlatpackMode, true) + BuildingUtils.openBuildInterface(player, hotspot) + return@on true + } + + onClose(ConstructionInterface.DECO_INTERFACE) { player, _ -> + removeAttribute(player, attributeSelection) + removeAttribute(player, attributeFlatpackMode) + return@onClose true + } + } + +} \ No newline at end of file From 236a143f0cdb54cfd80de897d95a68e889d85a7b Mon Sep 17 00:00:00 2001 From: Bishop Date: Mon, 20 Jul 2026 23:44:26 -0500 Subject: [PATCH 03/13] Flatpack production functionality --- .../construction/ConstructionInterface.kt | 19 ++-- .../decoration/workshop/WorkbenchListeners.kt | 102 +++++++++++++++++- 2 files changed, 111 insertions(+), 10 deletions(-) diff --git a/Server/src/main/content/global/skill/construction/ConstructionInterface.kt b/Server/src/main/content/global/skill/construction/ConstructionInterface.kt index 32c244112..2106c04a1 100644 --- a/Server/src/main/content/global/skill/construction/ConstructionInterface.kt +++ b/Server/src/main/content/global/skill/construction/ConstructionInterface.kt @@ -29,16 +29,22 @@ class ConstructionInterface : InterfaceListener { closeInterface(player) val hotspot = getAttribute(player, "con:hotspot", null) val `object` = getAttribute(player, "con:hsobject", null) - if (hotspot == null || `object` == null) { + val flatpackMode = getAttribute(player, WorkbenchListeners.attributeFlatpackMode, false) + if (hotspot == null || `object` == null && !flatpackMode) { log(this.javaClass, Log.ERR, "Failed building decoration $hotspot : $`object`") return@on false } val slot = (if (slot % 2 != 0) 4 else 0) + (slot shr 1) - if (slot >= hotspot.hotspot.decorations.size) { - log(this.javaClass, Log.ERR, "Failed building decoration " + slot + "/" + hotspot.hotspot.decorations.size) + val buildHotspot = if (flatpackMode) { + getAttribute(player, WorkbenchListeners.attributeSelection, null)?: return@on false + } else { + hotspot.hotspot + } + if (slot >= buildHotspot.decorations.size) { + log(this.javaClass, Log.ERR, "Failed building decoration " + slot + "/" + buildHotspot.decorations.size) return@on false } - val deco = hotspot.hotspot.decorations[slot] + val deco = buildHotspot.decorations[slot] if (!player.isAdmin) { if (getDynLevel(player, Skills.CONSTRUCTION) < deco.level) { sendMessage(player, "You need to have a Construction level of " + deco.level + " to build that.") @@ -70,13 +76,12 @@ class ConstructionInterface : InterfaceListener { return@on true } } - if (getAttribute(player, WorkbenchListeners.attributeFlatpackMode, false) && - WorkbenchListeners.getMaxLevel(getAttribute(player, WorkbenchListeners.attributeWorkbenchId, 0)) < deco.level) { + if (flatpackMode && WorkbenchListeners.getMaxLevel(getAttribute(player, WorkbenchListeners.attributeWorkbenchId, 0)) < deco.level) { sendMessage(player, "You need a better workbench to make this flatpack.") // placeholder return@on true } } - if (getAttribute(player, WorkbenchListeners.attributeFlatpackMode, false)) { + if (flatpackMode) { WorkbenchListeners.produceFlatpack(player, deco) } else { BuildingUtils.buildDecoration(player, hotspot, deco, `object`) diff --git a/Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt b/Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt index 621478745..48944b562 100644 --- a/Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt +++ b/Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt @@ -54,9 +54,105 @@ class WorkbenchListeners : InteractionListener, InterfaceListener { BuildHotspot.TOY_BOX, // 126 ) - val FLATPACKS = mapOf( - Decoration.CRUDE_CHAIR to Items.CRUDE_WOODEN_CHAIR_8496, - Decoration.OAK_CHAIR to Items.OAK_CHAIR_8502 + val FLATPACKS = mapOf( + // Chairs (armchairs) + Decoration.CRUDE_CHAIR to Items.CRUDE_WOODEN_CHAIR_8496, + Decoration.WOODEN_CHAIR to Items.WOODEN_CHAIR_8498, + Decoration.ROCKING_CHAIR to Items.ROCKING_CHAIR_8500, + Decoration.OAK_CHAIR to Items.OAK_CHAIR_8502, + Decoration.OAK_ARMCHAIR to Items.OAK_ARMCHAIR_8504, + Decoration.TEAK_ARMCHAIR to Items.TEAK_ARMCHAIR_8506, + Decoration.MAHOGANY_ARMCHAIR to Items.MAHOGANY_ARMCHAIR_8508, + // Bookcases + Decoration.WOODEN_BOOKCASE to Items.WOODEN_BOOKCASE_8510, + Decoration.OAK_BOOKCASE to Items.OAK_BOOKCASE_8512, + Decoration.MAHOGANY_BOOKCASE to Items.MAHOGANY_BKCASE_8514, + // Beer barrels + Decoration.BASIC_BEER_BARREL to Items.BEER_BARREL_8516, + Decoration.CIDER_BARREL to Items.CIDER_BARREL_8518, + Decoration.ASGARNIAN_ALE_BARREL to Items.ASGARNIAN_ALE_8520, + Decoration.GREENMANS_ALE_BARREL to Items.GREENMANS_ALE_8522, + Decoration.DRAGON_BITTER_BARREL to Items.DRAGON_BITTER_8524, + Decoration.CHEFS_DELIGHT_BARREL to Items.CHEFS_DELIGHT_8526, + // Kitchen tables + Decoration.KITCHEN_WOODEN_TABLE to Items.WOOD_KITCHEN_TABLE_8528, + Decoration.KITCHEN_OAK_TABLE to Items.OAK_KITCHEN_TABLE_8530, + Decoration.KITCHEN_TEAK_TABLE to Items.TEAK_KITCHEN_TABLE_8532, + // Dining tables + Decoration.DINING_TABLE_WOOD to Items.WOOD_DINING_TABLE_8548, + Decoration.DINING_TABLE_OAK to Items.OAK_DINING_TABLE_8550, + Decoration.DINING_TABLE_CARVED_OAK to Items.CARVED_OAK_TABLE_8552, + Decoration.DINING_TABLE_TEAK to Items.TEAK_TABLE_8554, + Decoration.DINING_TABLE_CARVED_TEAK to Items.CARVED_TEAK_TABLE_8556, + Decoration.DINING_TABLE_MAHOGANY to Items.MAHOGANY_TABLE_8558, + Decoration.DINING_TABLE_OPULENT to Items.OPULENT_TABLE_8560, + // Dining benches + Decoration.BENCH_WOODEN to Items.WOODEN_BENCH_8562, + Decoration.BENCH_OAK to Items.OAK_BENCH_8564, + Decoration.BENCH_CARVED_OAK to Items.CARVED_OAK_BENCH_8566, + Decoration.BENCH_TEAK to Items.TEAK_DINING_BENCH_8568, + Decoration.BENCH_CARVED_TEAK to Items.CARVED_TEAK_BENCH_8570, + Decoration.BENCH_MAHOGANY to Items.MAHOGANY_BENCH_8572, + Decoration.BENCH_GILDED to Items.GILDED_BENCH_8574, + // Beds + Decoration.WOODEN_BED to Items.WOODEN_BED_8576, + Decoration.OAK_BED to Items.OAK_BED_8578, + Decoration.LARGE_OAK_BED to Items.LARGE_OAK_BED_8580, + Decoration.TEAK_BED to Items.TEAK_BED_8582, + Decoration.LARGE_TEAK_BED to Items.LARGE_TEAK_BED_8584, + Decoration.FOUR_POSTER to Items.FOUR_POSTER_8586, + Decoration.GILDED_FOUR_POSTER to Items.GILDED_4_POSTER_8588, + // Clocks + Decoration.OAK_CLOCK to Items.OAK_CLOCK_8590, + Decoration.TEAK_CLOCK to Items.TEAK_CLOCK_8592, + Decoration.GILDED_CLOCK to Items.GILDED_CLOCK_8594, + // Dressers + Decoration.SHAVING_STAND to Items.SHAVING_STAND_8596, + Decoration.OAK_SHAVING_STAND to Items.OAK_SHAVING_STAND_8598, + Decoration.OAK_DRESSER to Items.OAK_DRESSER_8600, + Decoration.TEAK_DRESSER to Items.TEAK_DRESSER_8602, + Decoration.FANCY_TEAK_DRESSER to Items.FANCY_TEAK_DRESSER_8604, + Decoration.MAHOGANY_DRESSER to Items.MAHOGANY_DRESSER_8606, + Decoration.GILDED_DRESSER to Items.GILDED_DRESSER_8608, + // Wardrobes + Decoration.SHOE_BOX to Items.SHOE_BOX_8610, + Decoration.OAK_DRAWERS to Items.OAK_DRAWERS_8612, + Decoration.OAK_WARDROBE to Items.OAK_WARDROBE_8614, + Decoration.TEAK_DRAWERS to Items.TEAK_DRAWERS_8616, + Decoration.TEAK_WARDROBE to Items.TEAK_WARDROBE_8618, + Decoration.MAHOGANY_WARDROBE to Items.MAHOGANY_DROBE_8620, + Decoration.GILDED_WARDROBE to Items.GILDED_WARDROBE_8622, + // Cape racks + Decoration.OAK_CAPE_RACK to Items.OAK_CAPE_RACK_9843, + Decoration.TEAK_CAPE_RACK to Items.TEAK_CAPE_RACK_9844, + Decoration.MGANY_CAPE_RACK to Items.MGANY_CAPE_RACK_9845, + Decoration.GILDED_CAPE_RACK to Items.GILDED_CAPE_RACK_9846, + Decoration.MARBLE_CAPE_RACK to Items.MARBLE_CAPE_RACK_9847, + Decoration.MAGIC_CAPE_RACK to Items.MAGICAL_CAPE_RACK_9848, + // Magic wardrobes + Decoration.OAK_MAGIC_WARDROBE to Items.OAK_MAGIC_WARDROBE_9852, + Decoration.C_OAK_MAGIC_WARDROBE to Items.CARVED_OAK_MAGIC_WARDROBE_9853, + Decoration.TEAK_MAGIC_WARDROBE to Items.TEAK_MAGIC_WARDROBE_9854, + Decoration.C_TEAK_MAGIC_WARDROBE to Items.CARVED_TEAK_MAGIC_WARDROBE_9855, + Decoration.MGANY_MAGIC_WARDROBE to Items.MAHOGANY_MAGIC_WARDROBE_9856, + Decoration.GILDED_MAGIC_WARDROBE to Items.GILDED_MAGIC_WARDROBE_9857, + Decoration.MARBLE_MAGIC_WARDROBE to Items.MARBLE_MAGIC_WARDROBE_9858, + // Armour cases + Decoration.OAK_ARMOUR_CASE to Items.OAK_ARMOUR_CASE_9859, + Decoration.TEAK_ARMOUR_CASE to Items.TEAK_ARMOUR_CASE_9860, + Decoration.MGANY_ARMOUR_CASE to Items.MGANY_ARMR_CASE_9861, + // Treasure trail chests + Decoration.OAK_TREASURE_CHEST to Items.OAK_TREASURE_CHEST_9862, + Decoration.TEAK_TREASURE_CHEST to Items.TEAK_TREAS_CHEST_9863, + Decoration.MAHOGANY_TREASURE_CHEST to Items.MGANY_TREAS_CHEST_9864, + // Fancy dress boxes (costume boxes) + Decoration.OAK_COSTUME_BOX to Items.OAK_COSTUME_BOX_9865, + Decoration.TEAK_COSTUME_BOX to Items.TEAK_COSTUME_BOX_9866, + Decoration.MAHOGANY_COSTUME_BOX to Items.MAHOGANY_COS_BOX_9867, + // Toy boxes + Decoration.OAK_TOY_BOX to Items.OAK_TOY_BOX_9849, + Decoration.TEAK_TOY_BOX to Items.TEAK_TOY_BOX_9850, + Decoration.MAHOGANY_TOY_BOX to Items.MAHOGANY_TOY_BOX_9851, ) fun getMaxLevel(workbenchId: Int): Int { From fe4b97907cb89f0d6f95362af50e8b4220cf4f99 Mon Sep 17 00:00:00 2001 From: Bishop Date: Tue, 21 Jul 2026 00:03:12 -0500 Subject: [PATCH 04/13] Application of flatpacks, data moved to decoration --- .../global/skill/construction/Decoration.java | 210 +++++++++++------- .../skill/construction/FlatpackListener.kt | 46 ++++ .../decoration/workshop/WorkbenchListeners.kt | 106 +-------- 3 files changed, 176 insertions(+), 186 deletions(-) create mode 100644 Server/src/main/content/global/skill/construction/FlatpackListener.kt diff --git a/Server/src/main/content/global/skill/construction/Decoration.java b/Server/src/main/content/global/skill/construction/Decoration.java index 4191cb1a9..6b48243ea 100644 --- a/Server/src/main/content/global/skill/construction/Decoration.java +++ b/Server/src/main/content/global/skill/construction/Decoration.java @@ -74,13 +74,13 @@ public enum Decoration { /** * Parlour chair spot */ - CRUDE_CHAIR (13581, 8309, 1, 58, new Item[] { new Item(Items.PLANK_960, 2) }), - WOODEN_CHAIR (13582, 8310, 8, 87, new Item[] { new Item(Items.PLANK_960, 3) }), - ROCKING_CHAIR (13583, 8311, 14, 87, new Item[] { new Item(Items.PLANK_960, 3) }), - OAK_CHAIR (13584, 8312, 19, 120, new Item[] { new Item(Items.OAK_PLANK_8778, 2) }), - OAK_ARMCHAIR (13585, 8313, 26, 180, new Item[] { new Item(Items.OAK_PLANK_8778, 3) }), - TEAK_ARMCHAIR (13586, 8314, 35, 180, new Item[] { new Item(Items.TEAK_PLANK_8780, 2) }), - MAHOGANY_ARMCHAIR(13587, 8315, 50, 280, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2) }), + CRUDE_CHAIR (13581, 8309, 1, 58, new Item[] { new Item(Items.PLANK_960, 2) }, Items.CRUDE_WOODEN_CHAIR_8496), + WOODEN_CHAIR (13582, 8310, 8, 87, new Item[] { new Item(Items.PLANK_960, 3) }, Items.WOODEN_CHAIR_8498), + ROCKING_CHAIR (13583, 8311, 14, 87, new Item[] { new Item(Items.PLANK_960, 3) }, Items.ROCKING_CHAIR_8500), + OAK_CHAIR (13584, 8312, 19, 120, new Item[] { new Item(Items.OAK_PLANK_8778, 2) }, Items.OAK_CHAIR_8502), + OAK_ARMCHAIR (13585, 8313, 26, 180, new Item[] { new Item(Items.OAK_PLANK_8778, 3) }, Items.OAK_ARMCHAIR_8504), + TEAK_ARMCHAIR (13586, 8314, 35, 180, new Item[] { new Item(Items.TEAK_PLANK_8780, 2) }, Items.TEAK_ARMCHAIR_8506), + MAHOGANY_ARMCHAIR(13587, 8315, 50, 280, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2) }, Items.MAHOGANY_ARMCHAIR_8508), /** * Rugs rugs rugs @@ -112,9 +112,9 @@ public enum Decoration { /** * Bookcases */ - WOODEN_BOOKCASE (13597, 8319, 4, 115, new Item[] { new Item(Items.PLANK_960, 4) }), - OAK_BOOKCASE (13598, 8320, 29, 180, new Item[] { new Item(Items.OAK_PLANK_8778, 3) }), - MAHOGANY_BOOKCASE(13599, 8321, 40, 420, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 3) }), + WOODEN_BOOKCASE (13597, 8319, 4, 115, new Item[] { new Item(Items.PLANK_960, 4) }, Items.WOODEN_BOOKCASE_8510), + OAK_BOOKCASE (13598, 8320, 29, 180, new Item[] { new Item(Items.OAK_PLANK_8778, 3) }, Items.OAK_BOOKCASE_8512), + MAHOGANY_BOOKCASE(13599, 8321, 40, 420, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 3) }, Items.MAHOGANY_BKCASE_8514), /** * Kitchen Beer Barrels @@ -122,19 +122,19 @@ public enum Decoration { * Basic: 1, Cider: 14, Asgarnian: 24, Greenman's: 29, D.Bitter: 39, Chef's: 54 * */ - BASIC_BEER_BARREL (13568, 8239, 7, 87, new Item[] { new Item(Items.PLANK_960, 3) }), - CIDER_BARREL (13569, 8240, 12, 91, new Item[] { new Item(Items.PLANK_960, 3), new Item(Items.CIDER_5763, 8) }), - ASGARNIAN_ALE_BARREL(13570, 8241, 18, 184, new Item[] { new Item(Items.OAK_PLANK_8778, 3), new Item(Items.ASGARNIAN_ALE_1905, 8) }), - GREENMANS_ALE_BARREL(13571, 8242, 26, 184, new Item[] { new Item(Items.OAK_PLANK_8778, 3), new Item(Items.GREENMANS_ALE_1909, 8) }), - DRAGON_BITTER_BARREL(13572, 8243, 36, 224, new Item[] { new Item(Items.OAK_PLANK_8778, 3), new Item(Items.DRAGON_BITTER_1911, 8), new Item(Items.STEEL_BAR_2353, 2) }), - CHEFS_DELIGHT_BARREL(13573, 8244, 48, 224, new Item[] { new Item(Items.OAK_PLANK_8778, 3), new Item(Items.CHEFS_DELIGHT_5755, 8), new Item(Items.STEEL_BAR_2353, 2) }), + BASIC_BEER_BARREL (13568, 8239, 7, 87, new Item[] { new Item(Items.PLANK_960, 3) }, Items.BEER_BARREL_8516), + CIDER_BARREL (13569, 8240, 12, 91, new Item[] { new Item(Items.PLANK_960, 3), new Item(Items.CIDER_5763, 8) }, Items.CIDER_BARREL_8518), + ASGARNIAN_ALE_BARREL(13570, 8241, 18, 184, new Item[] { new Item(Items.OAK_PLANK_8778, 3), new Item(Items.ASGARNIAN_ALE_1905, 8) }, Items.ASGARNIAN_ALE_8520), + GREENMANS_ALE_BARREL(13571, 8242, 26, 184, new Item[] { new Item(Items.OAK_PLANK_8778, 3), new Item(Items.GREENMANS_ALE_1909, 8) }, Items.GREENMANS_ALE_8522), + DRAGON_BITTER_BARREL(13572, 8243, 36, 224, new Item[] { new Item(Items.OAK_PLANK_8778, 3), new Item(Items.DRAGON_BITTER_1911, 8), new Item(Items.STEEL_BAR_2353, 2) }, Items.DRAGON_BITTER_8524), + CHEFS_DELIGHT_BARREL(13573, 8244, 48, 224, new Item[] { new Item(Items.OAK_PLANK_8778, 3), new Item(Items.CHEFS_DELIGHT_5755, 8), new Item(Items.STEEL_BAR_2353, 2) }, Items.CHEFS_DELIGHT_8526), /** * Kitchen Tables! */ - KITCHEN_WOODEN_TABLE(13577, 8246, 12, 87, new Item[] { new Item(Items.PLANK_960, 3) }), - KITCHEN_OAK_TABLE (13578, 8247, 32, 180, new Item[] { new Item(Items.OAK_PLANK_8778, 3) }), - KITCHEN_TEAK_TABLE (13579, 8248, 52, 270, new Item[] { new Item(Items.TEAK_PLANK_8780, 3) }), + KITCHEN_WOODEN_TABLE(13577, 8246, 12, 87, new Item[] { new Item(Items.PLANK_960, 3) }, Items.WOOD_KITCHEN_TABLE_8528), + KITCHEN_OAK_TABLE (13578, 8247, 32, 180, new Item[] { new Item(Items.OAK_PLANK_8778, 3) }, Items.OAK_KITCHEN_TABLE_8530), + KITCHEN_TEAK_TABLE (13579, 8248, 52, 270, new Item[] { new Item(Items.TEAK_PLANK_8780, 3) }, Items.TEAK_KITCHEN_TABLE_8532), /** * Kitchen Stoves @@ -182,24 +182,24 @@ public enum Decoration { /** * Dining room tables */ - DINING_TABLE_WOOD (13293, 8246, 10, 115, new Item[] { new Item(Items.PLANK_960, 4) }), - DINING_TABLE_OAK (13294, 8247, 22, 240, new Item[] { new Item(Items.OAK_PLANK_8778, 4) }), - DINING_TABLE_CARVED_OAK (13295, 8247, 31, 360, new Item[] { new Item(Items.OAK_PLANK_8778, 6) }), - DINING_TABLE_TEAK (13296, 8248, 38, 360, new Item[] { new Item(Items.TEAK_PLANK_8780, 4) }), - DINING_TABLE_CARVED_TEAK(13297, 8248, 45, 600, new Item[] { new Item(Items.TEAK_PLANK_8780, 6), new Item(Items.BOLT_OF_CLOTH_8790, 4) }), - DINING_TABLE_MAHOGANY (13298, 8120, 52, 840, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 6) }), - DINING_TABLE_OPULENT (13299, 8121, 72, 3100, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 6), new Item(Items.BOLT_OF_CLOTH_8790, 4), new Item(Items.GOLD_LEAF_8784, 4), new Item(Items.MARBLE_BLOCK_8786, 2) }), + DINING_TABLE_WOOD (13293, 8246, 10, 115, new Item[] { new Item(Items.PLANK_960, 4) }, Items.WOOD_DINING_TABLE_8548), + DINING_TABLE_OAK (13294, 8247, 22, 240, new Item[] { new Item(Items.OAK_PLANK_8778, 4) }, Items.OAK_DINING_TABLE_8550), + DINING_TABLE_CARVED_OAK (13295, 8247, 31, 360, new Item[] { new Item(Items.OAK_PLANK_8778, 6) }, Items.CARVED_OAK_TABLE_8552), + DINING_TABLE_TEAK (13296, 8248, 38, 360, new Item[] { new Item(Items.TEAK_PLANK_8780, 4) }, Items.TEAK_TABLE_8554), + DINING_TABLE_CARVED_TEAK(13297, 8248, 45, 600, new Item[] { new Item(Items.TEAK_PLANK_8780, 6), new Item(Items.BOLT_OF_CLOTH_8790, 4) }, Items.CARVED_TEAK_TABLE_8556), + DINING_TABLE_MAHOGANY (13298, 8120, 52, 840, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 6) }, Items.MAHOGANY_TABLE_8558), + DINING_TABLE_OPULENT (13299, 8121, 72, 3100, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 6), new Item(Items.BOLT_OF_CLOTH_8790, 4), new Item(Items.GOLD_LEAF_8784, 4), new Item(Items.MARBLE_BLOCK_8786, 2) }, Items.OPULENT_TABLE_8560), /** * Dining room benches */ - BENCH_WOODEN (13300, 8108, 10, 115, new Item[] { new Item(Items.PLANK_960, 4) }), - BENCH_OAK (13301, 8109, 22, 240, new Item[] { new Item(Items.OAK_PLANK_8778, 4) }), - BENCH_CARVED_OAK (13302, 8110, 31, 240, new Item[] { new Item(Items.OAK_PLANK_8778, 4) }), - BENCH_TEAK (13303, 8111, 38, 360, new Item[] { new Item(Items.TEAK_PLANK_8780, 4) }), - BENCH_CARVED_TEAK(13304, 8112, 44, 360, new Item[] { new Item(Items.TEAK_PLANK_8780, 4) }), - BENCH_MAHOGANY (13305, 8113, 52, 560, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 6) }), - BENCH_GILDED (13306, 8114, 61, 1760, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 4), new Item(Items.GOLD_LEAF_8784, 4) }), + BENCH_WOODEN (13300, 8108, 10, 115, new Item[] { new Item(Items.PLANK_960, 4) }, Items.WOODEN_BENCH_8562), + BENCH_OAK (13301, 8109, 22, 240, new Item[] { new Item(Items.OAK_PLANK_8778, 4) }, Items.OAK_BENCH_8564), + BENCH_CARVED_OAK (13302, 8110, 31, 240, new Item[] { new Item(Items.OAK_PLANK_8778, 4) }, Items.CARVED_OAK_BENCH_8566), + BENCH_TEAK (13303, 8111, 38, 360, new Item[] { new Item(Items.TEAK_PLANK_8780, 4) }, Items.TEAK_DINING_BENCH_8568), + BENCH_CARVED_TEAK(13304, 8112, 44, 360, new Item[] { new Item(Items.TEAK_PLANK_8780, 4) }, Items.CARVED_TEAK_BENCH_8570), + BENCH_MAHOGANY (13305, 8113, 52, 560, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 6) }, Items.MAHOGANY_BENCH_8572), + BENCH_GILDED (13306, 8114, 61, 1760, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 4), new Item(Items.GOLD_LEAF_8784, 4) }, Items.GILDED_BENCH_8574), /** * Dining room bell-pulls @@ -209,7 +209,7 @@ public enum Decoration { FANCY_BELL_PULL(13309, 8101, 33, 58, new Item[] { new Item(Items.TEAK_PLANK_8780), new Item(Items.BOLT_OF_CLOTH_8790, 2), new Item(Items.GOLD_LEAF_8784) }), /** - * Workshop workbench + * Workshop workbenches */ WORKBENCH_WOODEN (13704, 8375, 17, 143, new Item[] { new Item(Items.PLANK_960, 5) }), WORKBENCH_OAK (13705, 8376, 32, 300, new Item[] { new Item(Items.OAK_PLANK_8778, 5) }), @@ -217,6 +217,12 @@ public enum Decoration { WORKBENCH_WITH_VICE (13707, 8378, 62, 750, new Item[] { new Item(Items.STEEL_FRAMED_BENCH_8377), new Item(Items.OAK_PLANK_8778, 2), new Item(Items.STEEL_BAR_2353) }), WORKBENCH_WITH_LATHE (13708, 8379, 77, 1000, new Item[] { new Item(Items.OAK_WORKBENCH_8376), new Item(Items.OAK_PLANK_8778, 2), new Item(Items.STEEL_BAR_2353) }), + /** + * Workshop stools (linked to workbench/crafting table hotspots) + */ + WORKSHOP_STOOL (13719, -1, 1, 0), + WORKSHOP_STOOL_OAK(13720, -1, 1, 0), + /** * Workshop repair benches/stands */ @@ -425,30 +431,30 @@ public enum Decoration { /** * Bedroom decorations. */ - WOODEN_BED (13148, 8031, 20, 117, new Item[] { new Item(Items.PLANK_960, 3), new Item(Items.BOLT_OF_CLOTH_8790, 2) }), - OAK_BED (13149, 8032, 30, 210, new Item[] { new Item(Items.OAK_PLANK_8778, 3), new Item(Items.BOLT_OF_CLOTH_8790, 2) }), - LARGE_OAK_BED (13150, 8033, 34, 330, new Item[] { new Item(Items.OAK_PLANK_8778, 5), new Item(Items.BOLT_OF_CLOTH_8790, 2) }), - TEAK_BED (13151, 8034, 40, 300, new Item[] { new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.BOLT_OF_CLOTH_8790, 2) }), - LARGE_TEAK_BED (13152, 8035, 45, 480, new Item[] { new Item(Items.TEAK_PLANK_8780, 5), new Item(Items.BOLT_OF_CLOTH_8790, 2) }), - FOUR_POSTER (13153, 8036, 53, 450, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 3), new Item(Items.BOLT_OF_CLOTH_8790, 2) }), - GILDED_FOUR_POSTER(13154, 8037, 60, 1330, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 5), new Item(Items.BOLT_OF_CLOTH_8790, 2), new Item(Items.GOLD_LEAF_8784, 2) }), - OAK_CLOCK (13169, 8052, 25, 142, new Item[] { new Item(Items.OAK_PLANK_8778, 2), new Item(Items.CLOCKWORK_8792) }), - TEAK_CLOCK (13170, 8053, 55, 202, new Item[] { new Item(Items.TEAK_PLANK_8780, 2), new Item(Items.CLOCKWORK_8792) }), - GILDED_CLOCK (13171, 8054, 85, 602, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.CLOCKWORK_8792), new Item(Items.GOLD_LEAF_8784) }), - SHAVING_STAND (13162, 8045, 21, 30, new Item[] { new Item(Items.PLANK_960), new Item(Items.MOLTEN_GLASS_1775) }), - OAK_SHAVING_STAND (13163, 8046, 29, 61, new Item[] { new Item(Items.OAK_PLANK_8778), new Item(Items.MOLTEN_GLASS_1775) }), - OAK_DRESSER (13164, 8047, 37, 121, new Item[] { new Item(Items.OAK_PLANK_8778, 2), new Item(Items.MOLTEN_GLASS_1775) }), - TEAK_DRESSER (13165, 8048, 46, 181, new Item[] { new Item(Items.TEAK_PLANK_8780, 2), new Item(Items.MOLTEN_GLASS_1775) }), - FANCY_TEAK_DRESSER(13166, 8049, 56, 182, new Item[] { new Item(Items.TEAK_PLANK_8780, 2), new Item(Items.MOLTEN_GLASS_1775, 2) }), - MAHOGANY_DRESSER (13167, 8050, 64, 281, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.MOLTEN_GLASS_1775) }), - GILDED_DRESSER (13168, 8051, 74, 582, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.MOLTEN_GLASS_1775, 2), new Item(Items.GOLD_LEAF_8784) }), - SHOE_BOX (13155, 8038, 20, 58, new Item[] { new Item(Items.PLANK_960, 2) }), - OAK_DRAWERS (13156, 8039, 27, 120, new Item[] { new Item(Items.OAK_PLANK_8778, 2) }), - OAK_WARDROBE (13157, 8040, 39, 180, new Item[] { new Item(Items.OAK_PLANK_8778, 3) }), - TEAK_DRAWERS (13158, 8041, 51, 180, new Item[] { new Item(Items.TEAK_PLANK_8780, 2) }), - TEAK_WARDROBE (13159, 8042, 63, 270, new Item[] { new Item(Items.TEAK_PLANK_8780, 3) }), - MAHOGANY_WARDROBE (13160, 8043, 75, 420, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2) }), - GILDED_WARDROBE (13161, 8044, 87, 720, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.GOLD_LEAF_8784) }), + WOODEN_BED (13148, 8031, 20, 117, new Item[] { new Item(Items.PLANK_960, 3), new Item(Items.BOLT_OF_CLOTH_8790, 2) }, Items.WOODEN_BED_8576), + OAK_BED (13149, 8032, 30, 210, new Item[] { new Item(Items.OAK_PLANK_8778, 3), new Item(Items.BOLT_OF_CLOTH_8790, 2) }, Items.OAK_BED_8578), + LARGE_OAK_BED (13150, 8033, 34, 330, new Item[] { new Item(Items.OAK_PLANK_8778, 5), new Item(Items.BOLT_OF_CLOTH_8790, 2) }, Items.LARGE_OAK_BED_8580), + TEAK_BED (13151, 8034, 40, 300, new Item[] { new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.BOLT_OF_CLOTH_8790, 2) }, Items.TEAK_BED_8582), + LARGE_TEAK_BED (13152, 8035, 45, 480, new Item[] { new Item(Items.TEAK_PLANK_8780, 5), new Item(Items.BOLT_OF_CLOTH_8790, 2) }, Items.LARGE_TEAK_BED_8584), + FOUR_POSTER (13153, 8036, 53, 450, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 3), new Item(Items.BOLT_OF_CLOTH_8790, 2) }, Items.FOUR_POSTER_8586), + GILDED_FOUR_POSTER(13154, 8037, 60, 1330, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 5), new Item(Items.BOLT_OF_CLOTH_8790, 2), new Item(Items.GOLD_LEAF_8784, 2) }, Items.GILDED_4_POSTER_8588), + OAK_CLOCK (13169, 8052, 25, 142, new Item[] { new Item(Items.OAK_PLANK_8778, 2), new Item(Items.CLOCKWORK_8792) }, Items.OAK_CLOCK_8590), + TEAK_CLOCK (13170, 8053, 55, 202, new Item[] { new Item(Items.TEAK_PLANK_8780, 2), new Item(Items.CLOCKWORK_8792) }, Items.TEAK_CLOCK_8592), + GILDED_CLOCK (13171, 8054, 85, 602, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.CLOCKWORK_8792), new Item(Items.GOLD_LEAF_8784) }, Items.GILDED_CLOCK_8594), + SHAVING_STAND (13162, 8045, 21, 30, new Item[] { new Item(Items.PLANK_960), new Item(Items.MOLTEN_GLASS_1775) }, Items.SHAVING_STAND_8596), + OAK_SHAVING_STAND (13163, 8046, 29, 61, new Item[] { new Item(Items.OAK_PLANK_8778), new Item(Items.MOLTEN_GLASS_1775) }, Items.OAK_SHAVING_STAND_8598), + OAK_DRESSER (13164, 8047, 37, 121, new Item[] { new Item(Items.OAK_PLANK_8778, 2), new Item(Items.MOLTEN_GLASS_1775) }, Items.OAK_DRESSER_8600), + TEAK_DRESSER (13165, 8048, 46, 181, new Item[] { new Item(Items.TEAK_PLANK_8780, 2), new Item(Items.MOLTEN_GLASS_1775) }, Items.TEAK_DRESSER_8602), + FANCY_TEAK_DRESSER(13166, 8049, 56, 182, new Item[] { new Item(Items.TEAK_PLANK_8780, 2), new Item(Items.MOLTEN_GLASS_1775, 2) }, Items.FANCY_TEAK_DRESSER_8604), + MAHOGANY_DRESSER (13167, 8050, 64, 281, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.MOLTEN_GLASS_1775) }, Items.MAHOGANY_DRESSER_8606), + GILDED_DRESSER (13168, 8051, 74, 582, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.MOLTEN_GLASS_1775, 2), new Item(Items.GOLD_LEAF_8784) }, Items.GILDED_DRESSER_8608), + SHOE_BOX (13155, 8038, 20, 58, new Item[] { new Item(Items.PLANK_960, 2) }, Items.SHOE_BOX_8610), + OAK_DRAWERS (13156, 8039, 27, 120, new Item[] { new Item(Items.OAK_PLANK_8778, 2) }, Items.OAK_DRAWERS_8612), + OAK_WARDROBE (13157, 8040, 39, 180, new Item[] { new Item(Items.OAK_PLANK_8778, 3) }, Items.OAK_WARDROBE_8614), + TEAK_DRAWERS (13158, 8041, 51, 180, new Item[] { new Item(Items.TEAK_PLANK_8780, 2) }, Items.TEAK_DRAWERS_8616), + TEAK_WARDROBE (13159, 8042, 63, 270, new Item[] { new Item(Items.TEAK_PLANK_8780, 3) }, Items.TEAK_WARDROBE_8618), + MAHOGANY_WARDROBE (13160, 8043, 75, 420, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2) }, Items.MAHOGANY_DROBE_8620), + GILDED_WARDROBE (13161, 8044, 87, 720, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.GOLD_LEAF_8784) }, Items.GILDED_WARDROBE_8622), /** * Quest hall decorations. @@ -502,31 +508,31 @@ public enum Decoration { /** * Costume room decorations. */ - OAK_TREASURE_CHEST (18804, 9839, 48, 120, new Item[] { new Item(Items.OAK_PLANK_8778, 2) }), - TEAK_TREASURE_CHEST (18806, 9840, 66, 180, new Item[] { new Item(Items.TEAK_PLANK_8780, 2) }), - MAHOGANY_TREASURE_CHEST(18808, 9841, 84, 280, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2) }), - OAK_ARMOUR_CASE (18778, 9826, 46, 180, new Item[] { new Item(Items.OAK_PLANK_8778, 3) }), - TEAK_ARMOUR_CASE (18780, 9827, 64, 270, new Item[] { new Item(Items.TEAK_PLANK_8780, 3) }), - MGANY_ARMOUR_CASE (18782, 9828, 82, 420, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 3) }), - OAK_MAGIC_WARDROBE (18784, 9829, 42, 240, new Item[] { new Item(Items.OAK_PLANK_8778, 4) }), - C_OAK_MAGIC_WARDROBE (18786, 9830, 51, 360, new Item[] { new Item(Items.OAK_PLANK_8778, 6) }), - TEAK_MAGIC_WARDROBE (18788, 9831, 60, 360, new Item[] { new Item(Items.TEAK_PLANK_8780, 4) }), - C_TEAK_MAGIC_WARDROBE (18790, 9832, 69, 540, new Item[] { new Item(Items.TEAK_PLANK_8780, 6) }), - MGANY_MAGIC_WARDROBE (18792, 9833, 78, 560, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 4) }), - GILDED_MAGIC_WARDROBE (18794, 9834, 87, 860, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 4), new Item(Items.GOLD_LEAF_8784) }), - MARBLE_MAGIC_WARDROBE (18796, 9835, 96, 500, new Item[] { new Item(Items.MARBLE_BLOCK_8786) }), - OAK_CAPE_RACK (18766, 9817, 54, 240, new Item[] { new Item(Items.OAK_PLANK_8778, 4) }), - TEAK_CAPE_RACK (18767, 9818, 63, 360, new Item[] { new Item(Items.TEAK_PLANK_8780, 4) }), - MGANY_CAPE_RACK (18768, 9819, 72, 560, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 4) }), - GILDED_CAPE_RACK (18769, 9820, 81, 860, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 4), new Item(Items.GOLD_LEAF_8784) }), - MARBLE_CAPE_RACK (18770, 9821, 90, 500, new Item[] { new Item(Items.MARBLE_BLOCK_8786) }), - MAGIC_CAPE_RACK (18771, 9822, 99, 1000, new Item[] { new Item(Items.MAGIC_STONE_8788) }), - OAK_TOY_BOX (18798, 9836, 50, 120, new Item[] { new Item(Items.OAK_PLANK_8778, 2) }), - TEAK_TOY_BOX (18800, 9837, 68, 180, new Item[] { new Item(Items.TEAK_PLANK_8780, 2) }), - MAHOGANY_TOY_BOX (18802, 9838, 86, 280, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2) }), - OAK_COSTUME_BOX (18772, 9823, 44, 120, new Item[] { new Item(Items.OAK_PLANK_8778, 2) }), - TEAK_COSTUME_BOX (18774, 9824, 62, 180, new Item[] { new Item(Items.TEAK_PLANK_8780, 2) }), - MAHOGANY_COSTUME_BOX (18776, 9825, 80, 280, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2) }), + OAK_TREASURE_CHEST (18804, 9839, 48, 120, new Item[] { new Item(Items.OAK_PLANK_8778, 2) }, Items.OAK_TREASURE_CHEST_9862), + TEAK_TREASURE_CHEST (18806, 9840, 66, 180, new Item[] { new Item(Items.TEAK_PLANK_8780, 2) }, Items.TEAK_TREAS_CHEST_9863), + MAHOGANY_TREASURE_CHEST(18808, 9841, 84, 280, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2) }, Items.MGANY_TREAS_CHEST_9864), + OAK_ARMOUR_CASE (18778, 9826, 46, 180, new Item[] { new Item(Items.OAK_PLANK_8778, 3) }, Items.OAK_ARMOUR_CASE_9859), + TEAK_ARMOUR_CASE (18780, 9827, 64, 270, new Item[] { new Item(Items.TEAK_PLANK_8780, 3) }, Items.TEAK_ARMOUR_CASE_9860), + MGANY_ARMOUR_CASE (18782, 9828, 82, 420, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 3) }, Items.MGANY_ARMR_CASE_9861), + OAK_MAGIC_WARDROBE (18784, 9829, 42, 240, new Item[] { new Item(Items.OAK_PLANK_8778, 4) }, Items.OAK_MAGIC_WARDROBE_9852), + C_OAK_MAGIC_WARDROBE (18786, 9830, 51, 360, new Item[] { new Item(Items.OAK_PLANK_8778, 6) }, Items.CARVED_OAK_MAGIC_WARDROBE_9853), + TEAK_MAGIC_WARDROBE (18788, 9831, 60, 360, new Item[] { new Item(Items.TEAK_PLANK_8780, 4) }, Items.TEAK_MAGIC_WARDROBE_9854), + C_TEAK_MAGIC_WARDROBE (18790, 9832, 69, 540, new Item[] { new Item(Items.TEAK_PLANK_8780, 6) }, Items.CARVED_TEAK_MAGIC_WARDROBE_9855), + MGANY_MAGIC_WARDROBE (18792, 9833, 78, 560, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 4) }, Items.MAHOGANY_MAGIC_WARDROBE_9856), + GILDED_MAGIC_WARDROBE (18794, 9834, 87, 860, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 4), new Item(Items.GOLD_LEAF_8784) }, Items.GILDED_MAGIC_WARDROBE_9857), + MARBLE_MAGIC_WARDROBE (18796, 9835, 96, 500, new Item[] { new Item(Items.MARBLE_BLOCK_8786) }, Items.MARBLE_MAGIC_WARDROBE_9858), + OAK_CAPE_RACK (18766, 9817, 54, 240, new Item[] { new Item(Items.OAK_PLANK_8778, 4) }, Items.OAK_CAPE_RACK_9843), + TEAK_CAPE_RACK (18767, 9818, 63, 360, new Item[] { new Item(Items.TEAK_PLANK_8780, 4) }, Items.TEAK_CAPE_RACK_9844), + MGANY_CAPE_RACK (18768, 9819, 72, 560, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 4) }, Items.MGANY_CAPE_RACK_9845), + GILDED_CAPE_RACK (18769, 9820, 81, 860, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 4), new Item(Items.GOLD_LEAF_8784) }, Items.GILDED_CAPE_RACK_9846), + MARBLE_CAPE_RACK (18770, 9821, 90, 500, new Item[] { new Item(Items.MARBLE_BLOCK_8786) }, Items.MARBLE_CAPE_RACK_9847), + MAGIC_CAPE_RACK (18771, 9822, 99, 1000, new Item[] { new Item(Items.MAGIC_STONE_8788) }, Items.MAGICAL_CAPE_RACK_9848), + OAK_TOY_BOX (18798, 9836, 50, 120, new Item[] { new Item(Items.OAK_PLANK_8778, 2) }, Items.OAK_TOY_BOX_9849), + TEAK_TOY_BOX (18800, 9837, 68, 180, new Item[] { new Item(Items.TEAK_PLANK_8780, 2) }, Items.TEAK_TOY_BOX_9850), + MAHOGANY_TOY_BOX (18802, 9838, 86, 280, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2) }, Items.MAHOGANY_TOY_BOX_9851), + OAK_COSTUME_BOX (18772, 9823, 44, 120, new Item[] { new Item(Items.OAK_PLANK_8778, 2) }, Items.OAK_COSTUME_BOX_9865), + TEAK_COSTUME_BOX (18774, 9824, 62, 180, new Item[] { new Item(Items.TEAK_PLANK_8780, 2) }, Items.TEAK_COSTUME_BOX_9866), + MAHOGANY_COSTUME_BOX (18776, 9825, 80, 280, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2) }, Items.MAHOGANY_COS_BOX_9867), /** * Chapel decorations. @@ -684,6 +690,11 @@ public enum Decoration { FREMENNIK_WINDOW (13112, -1, 1, 0), TROPICAL_WOOD_WINDOW (10816, -1, 1, 0), FANCY_STONE_WINDOW (13117, -1, 1, 0), + + /** + * Flatpack deco for filling the flatpack hotspot. + */ + FLATPACK(-1, -1, 1, 0), ; /** @@ -716,6 +727,11 @@ public enum Decoration { */ private final Item[] refundItems; + /** + * The item id of the flatpack. + */ + private final int flatpackItemId; + /** * The tools required. */ @@ -774,6 +790,11 @@ public enum Decoration { this.reqsText = generateDefaultReqsText(items, getNailAmount()); } + Decoration(int objectId, int interfaceItem, int level, int experience, Item[] items, int flatpackItemId) { + this(objectId, interfaceItem, level, experience, new int[] { Items.HAMMER_2347, Items.SAW_8794 }, items, new Item[] {}, new String[] {}, flatpackItemId); + this.reqsText = generateDefaultReqsText(items, getNailAmount()); + } + /** * Constructs a new object, default refund items, default requirements text. * @param objectId The object id. @@ -827,6 +848,10 @@ public enum Decoration { * @param reqsText The requirements text to be shown in the interface. */ Decoration(int objectId, int interfaceItem, int level, int experience, int[] tools, Item[] items, Item[] refundItems, String[] reqsText) { + this(objectId, interfaceItem, level, experience, tools, items, refundItems, reqsText, -1); + } + + Decoration(int objectId, int interfaceItem, int level, int experience, int[] tools, Item[] items, Item[] refundItems, String[] reqsText, int flatpackItemId) { this.objectId = objectId; this.objectIds = null; this.interfaceItem = interfaceItem; @@ -835,6 +860,7 @@ public enum Decoration { this.tools = tools; this.items = items; this.refundItems = refundItems; + this.flatpackItemId = flatpackItemId; if (reqsText.length > 0) { System.arraycopy(reqsText, 0, this.reqsText, 0, reqsText.length); } @@ -881,6 +907,7 @@ public enum Decoration { this.tools = tools; this.items = items; this.refundItems = refundItems; + this.flatpackItemId = -1; } /** @@ -931,6 +958,15 @@ public enum Decoration { return null; } + public static Decoration forFlatpackItemId(int flatpackId) { + for (Decoration d : Decoration.values()) { + if (d.getFlatpackItemID() == flatpackId) { + return d; + } + } + return null; + } + /** * Gets the amount of nails required for this hotspot. * @return The amount of nails. @@ -1020,6 +1056,14 @@ public enum Decoration { return objectIds; } + /** + * Gets the flatpack item ID if it exists. + * @return the int ID. + */ + public int getFlatpackItemID() { + return flatpackItemId; + } + /** * If this node should be invisible to user build options * @return true if so. diff --git a/Server/src/main/content/global/skill/construction/FlatpackListener.kt b/Server/src/main/content/global/skill/construction/FlatpackListener.kt new file mode 100644 index 000000000..7e71991ac --- /dev/null +++ b/Server/src/main/content/global/skill/construction/FlatpackListener.kt @@ -0,0 +1,46 @@ +package content.global.skill.construction + +import content.global.skill.construction.BuildingUtils.buildDecoration +import core.api.* +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.node.entity.player.Player +import core.game.node.item.Item +import core.game.node.scenery.Scenery +import org.rs09.consts.Items + +/** + * Handles building furniture using flatpacks + * @author Roderik + * @author Bishop + */ + +class FlatpackListener : InteractionListener { + val flatpacks = Decoration.values().map { it.flatpackItemID }.toIntArray() + val hotspots = BuildHotspot.values().map { it.objectId }.toIntArray() + + override fun defineListeners() { + for (hotspot in hotspots) { + onUseWith(IntType.SCENERY, flatpacks, hotspot) { player, used, with -> + return@onUseWith buildFlatpackOnHotspot(player, used.asItem(), with as Scenery) + } + } + } + + private fun buildFlatpackOnHotspot(player: Player, used: Item, with: Scenery):Boolean { + val hotspotUsed = player.houseManager.getHotspot(with) + val decorationUsed = Decoration.forFlatpackItemId(used.id) + + if(!hotspotUsed.hotspot.decorations.contains(decorationUsed)) { + sendMessage(player, "You can't build that here.") + return false + } + if (!player.inventory.containsItems(Item(Items.HAMMER_2347),Item(Items.SAW_8794))) { + sendMessage(player, "You need a hammer and a saw to build this.") + return false + } + buildDecoration(player, hotspotUsed, decorationUsed, with.asScenery()) + return true + + } +} \ No newline at end of file diff --git a/Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt b/Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt index 48944b562..2bfb15772 100644 --- a/Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt +++ b/Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt @@ -54,115 +54,15 @@ class WorkbenchListeners : InteractionListener, InterfaceListener { BuildHotspot.TOY_BOX, // 126 ) - val FLATPACKS = mapOf( - // Chairs (armchairs) - Decoration.CRUDE_CHAIR to Items.CRUDE_WOODEN_CHAIR_8496, - Decoration.WOODEN_CHAIR to Items.WOODEN_CHAIR_8498, - Decoration.ROCKING_CHAIR to Items.ROCKING_CHAIR_8500, - Decoration.OAK_CHAIR to Items.OAK_CHAIR_8502, - Decoration.OAK_ARMCHAIR to Items.OAK_ARMCHAIR_8504, - Decoration.TEAK_ARMCHAIR to Items.TEAK_ARMCHAIR_8506, - Decoration.MAHOGANY_ARMCHAIR to Items.MAHOGANY_ARMCHAIR_8508, - // Bookcases - Decoration.WOODEN_BOOKCASE to Items.WOODEN_BOOKCASE_8510, - Decoration.OAK_BOOKCASE to Items.OAK_BOOKCASE_8512, - Decoration.MAHOGANY_BOOKCASE to Items.MAHOGANY_BKCASE_8514, - // Beer barrels - Decoration.BASIC_BEER_BARREL to Items.BEER_BARREL_8516, - Decoration.CIDER_BARREL to Items.CIDER_BARREL_8518, - Decoration.ASGARNIAN_ALE_BARREL to Items.ASGARNIAN_ALE_8520, - Decoration.GREENMANS_ALE_BARREL to Items.GREENMANS_ALE_8522, - Decoration.DRAGON_BITTER_BARREL to Items.DRAGON_BITTER_8524, - Decoration.CHEFS_DELIGHT_BARREL to Items.CHEFS_DELIGHT_8526, - // Kitchen tables - Decoration.KITCHEN_WOODEN_TABLE to Items.WOOD_KITCHEN_TABLE_8528, - Decoration.KITCHEN_OAK_TABLE to Items.OAK_KITCHEN_TABLE_8530, - Decoration.KITCHEN_TEAK_TABLE to Items.TEAK_KITCHEN_TABLE_8532, - // Dining tables - Decoration.DINING_TABLE_WOOD to Items.WOOD_DINING_TABLE_8548, - Decoration.DINING_TABLE_OAK to Items.OAK_DINING_TABLE_8550, - Decoration.DINING_TABLE_CARVED_OAK to Items.CARVED_OAK_TABLE_8552, - Decoration.DINING_TABLE_TEAK to Items.TEAK_TABLE_8554, - Decoration.DINING_TABLE_CARVED_TEAK to Items.CARVED_TEAK_TABLE_8556, - Decoration.DINING_TABLE_MAHOGANY to Items.MAHOGANY_TABLE_8558, - Decoration.DINING_TABLE_OPULENT to Items.OPULENT_TABLE_8560, - // Dining benches - Decoration.BENCH_WOODEN to Items.WOODEN_BENCH_8562, - Decoration.BENCH_OAK to Items.OAK_BENCH_8564, - Decoration.BENCH_CARVED_OAK to Items.CARVED_OAK_BENCH_8566, - Decoration.BENCH_TEAK to Items.TEAK_DINING_BENCH_8568, - Decoration.BENCH_CARVED_TEAK to Items.CARVED_TEAK_BENCH_8570, - Decoration.BENCH_MAHOGANY to Items.MAHOGANY_BENCH_8572, - Decoration.BENCH_GILDED to Items.GILDED_BENCH_8574, - // Beds - Decoration.WOODEN_BED to Items.WOODEN_BED_8576, - Decoration.OAK_BED to Items.OAK_BED_8578, - Decoration.LARGE_OAK_BED to Items.LARGE_OAK_BED_8580, - Decoration.TEAK_BED to Items.TEAK_BED_8582, - Decoration.LARGE_TEAK_BED to Items.LARGE_TEAK_BED_8584, - Decoration.FOUR_POSTER to Items.FOUR_POSTER_8586, - Decoration.GILDED_FOUR_POSTER to Items.GILDED_4_POSTER_8588, - // Clocks - Decoration.OAK_CLOCK to Items.OAK_CLOCK_8590, - Decoration.TEAK_CLOCK to Items.TEAK_CLOCK_8592, - Decoration.GILDED_CLOCK to Items.GILDED_CLOCK_8594, - // Dressers - Decoration.SHAVING_STAND to Items.SHAVING_STAND_8596, - Decoration.OAK_SHAVING_STAND to Items.OAK_SHAVING_STAND_8598, - Decoration.OAK_DRESSER to Items.OAK_DRESSER_8600, - Decoration.TEAK_DRESSER to Items.TEAK_DRESSER_8602, - Decoration.FANCY_TEAK_DRESSER to Items.FANCY_TEAK_DRESSER_8604, - Decoration.MAHOGANY_DRESSER to Items.MAHOGANY_DRESSER_8606, - Decoration.GILDED_DRESSER to Items.GILDED_DRESSER_8608, - // Wardrobes - Decoration.SHOE_BOX to Items.SHOE_BOX_8610, - Decoration.OAK_DRAWERS to Items.OAK_DRAWERS_8612, - Decoration.OAK_WARDROBE to Items.OAK_WARDROBE_8614, - Decoration.TEAK_DRAWERS to Items.TEAK_DRAWERS_8616, - Decoration.TEAK_WARDROBE to Items.TEAK_WARDROBE_8618, - Decoration.MAHOGANY_WARDROBE to Items.MAHOGANY_DROBE_8620, - Decoration.GILDED_WARDROBE to Items.GILDED_WARDROBE_8622, - // Cape racks - Decoration.OAK_CAPE_RACK to Items.OAK_CAPE_RACK_9843, - Decoration.TEAK_CAPE_RACK to Items.TEAK_CAPE_RACK_9844, - Decoration.MGANY_CAPE_RACK to Items.MGANY_CAPE_RACK_9845, - Decoration.GILDED_CAPE_RACK to Items.GILDED_CAPE_RACK_9846, - Decoration.MARBLE_CAPE_RACK to Items.MARBLE_CAPE_RACK_9847, - Decoration.MAGIC_CAPE_RACK to Items.MAGICAL_CAPE_RACK_9848, - // Magic wardrobes - Decoration.OAK_MAGIC_WARDROBE to Items.OAK_MAGIC_WARDROBE_9852, - Decoration.C_OAK_MAGIC_WARDROBE to Items.CARVED_OAK_MAGIC_WARDROBE_9853, - Decoration.TEAK_MAGIC_WARDROBE to Items.TEAK_MAGIC_WARDROBE_9854, - Decoration.C_TEAK_MAGIC_WARDROBE to Items.CARVED_TEAK_MAGIC_WARDROBE_9855, - Decoration.MGANY_MAGIC_WARDROBE to Items.MAHOGANY_MAGIC_WARDROBE_9856, - Decoration.GILDED_MAGIC_WARDROBE to Items.GILDED_MAGIC_WARDROBE_9857, - Decoration.MARBLE_MAGIC_WARDROBE to Items.MARBLE_MAGIC_WARDROBE_9858, - // Armour cases - Decoration.OAK_ARMOUR_CASE to Items.OAK_ARMOUR_CASE_9859, - Decoration.TEAK_ARMOUR_CASE to Items.TEAK_ARMOUR_CASE_9860, - Decoration.MGANY_ARMOUR_CASE to Items.MGANY_ARMR_CASE_9861, - // Treasure trail chests - Decoration.OAK_TREASURE_CHEST to Items.OAK_TREASURE_CHEST_9862, - Decoration.TEAK_TREASURE_CHEST to Items.TEAK_TREAS_CHEST_9863, - Decoration.MAHOGANY_TREASURE_CHEST to Items.MGANY_TREAS_CHEST_9864, - // Fancy dress boxes (costume boxes) - Decoration.OAK_COSTUME_BOX to Items.OAK_COSTUME_BOX_9865, - Decoration.TEAK_COSTUME_BOX to Items.TEAK_COSTUME_BOX_9866, - Decoration.MAHOGANY_COSTUME_BOX to Items.MAHOGANY_COS_BOX_9867, - // Toy boxes - Decoration.OAK_TOY_BOX to Items.OAK_TOY_BOX_9849, - Decoration.TEAK_TOY_BOX to Items.TEAK_TOY_BOX_9850, - Decoration.MAHOGANY_TOY_BOX to Items.MAHOGANY_TOY_BOX_9851, - ) - fun getMaxLevel(workbenchId: Int): Int { return (WORKBENCHES.indexOf(workbenchId) + 1) * 20 } - // TODO: replace with real flatpack item ID lookup fun produceFlatpack(player: Player, deco: Decoration) { - val reward = FLATPACKS[deco]?: return + val reward = deco.flatpackItemID + if (reward == -1) return if (removeItem(player, deco.items) || player.isAdmin) { + animate(player, 1) // find fiddling animation rewardXP(player, Skills.CONSTRUCTION, deco.experience.toDouble()) addItemOrDrop(player, reward) } From 528a0da11d6b9eeae20e6572d144164887f2eab8 Mon Sep 17 00:00:00 2001 From: Bishop Date: Tue, 21 Jul 2026 18:26:50 -0500 Subject: [PATCH 05/13] Rough-in of sitting --- .../skill/construction/BuildHotspot.java | 8 +- .../construction/ConstructionInterface.kt | 22 ++-- .../skill/construction/RoomProperties.java | 2 + .../decoration/workshop/WorkbenchListeners.kt | 118 +++++++++++++++--- 4 files changed, 118 insertions(+), 32 deletions(-) diff --git a/Server/src/main/content/global/skill/construction/BuildHotspot.java b/Server/src/main/content/global/skill/construction/BuildHotspot.java index c5ca6c8e7..365d6331a 100644 --- a/Server/src/main/content/global/skill/construction/BuildHotspot.java +++ b/Server/src/main/content/global/skill/construction/BuildHotspot.java @@ -65,8 +65,10 @@ public enum BuildHotspot { * Low-level Work shop hotspots. */ REPAIR(15448, BuildHotspotType.INDIVIDUAL, BuildingUtils.BUILD_MID_ANIM, Decoration.REPAIR_BENCH, Decoration.WHETSTONE, Decoration.ARMOUR_STAND), - WORKBENCH(15439, BuildHotspotType.INDIVIDUAL, BuildingUtils.BUILD_MID_ANIM, Decoration.WORKBENCH_WOODEN, Decoration.WORKBENCH_OAK,Decoration.WORKBENCH_STEEL_FRAME, Decoration.WORKBENCH_WITH_VICE,Decoration.WORKBENCH_WITH_LATHE), - CRAFTING(15441, BuildHotspotType.INDIVIDUAL, BuildingUtils.BUILD_MID_ANIM, Decoration.CRAFTING_TABLE_1, Decoration.CRAFTING_TABLE_2,Decoration.CRAFTING_TABLE_3, Decoration.CRAFTING_TABLE_4), + WORKBENCH(15439, BuildHotspotType.LINKED, BuildingUtils.BUILD_MID_ANIM, Decoration.WORKBENCH_WOODEN, Decoration.WORKBENCH_OAK,Decoration.WORKBENCH_STEEL_FRAME, Decoration.WORKBENCH_WITH_VICE,Decoration.WORKBENCH_WITH_LATHE), + WORKBENCH_STOOL(15540, BuildHotspotType.LINKED, BuildingUtils.BUILD_MID_ANIM, Decoration.WORKSHOP_STOOL, Decoration.WORKSHOP_STOOL,Decoration.WORKSHOP_STOOL_OAK, Decoration.WORKSHOP_STOOL_OAK,Decoration.WORKSHOP_STOOL_OAK), + CRAFTING(15441, BuildHotspotType.LINKED, BuildingUtils.BUILD_MID_ANIM, Decoration.CRAFTING_TABLE_1, Decoration.CRAFTING_TABLE_2,Decoration.CRAFTING_TABLE_3, Decoration.CRAFTING_TABLE_4), + CRAFTING_STOOL(15542, BuildHotspotType.LINKED, BuildingUtils.BUILD_MID_ANIM, Decoration.WORKSHOP_STOOL, Decoration.WORKSHOP_STOOL,Decoration.WORKSHOP_STOOL, Decoration.WORKSHOP_STOOL), TOOL1(15443, BuildHotspotType.RECURSIVE, BuildingUtils.BUILD_HIGH_ANIM, Decoration.TOOL_STORE_1, Decoration.TOOL_STORE_2, Decoration.TOOL_STORE_3, Decoration.TOOL_STORE_4, Decoration.TOOL_STORE_5), TOOL2(15444, BuildHotspotType.RECURSIVE, BuildingUtils.BUILD_HIGH_ANIM, Decoration.TOOL_STORE_1, Decoration.TOOL_STORE_2,Decoration.TOOL_STORE_3, Decoration.TOOL_STORE_4,Decoration.TOOL_STORE_5), TOOL3(15445, BuildHotspotType.RECURSIVE, BuildingUtils.BUILD_HIGH_ANIM, Decoration.TOOL_STORE_1, Decoration.TOOL_STORE_2,Decoration.TOOL_STORE_3, Decoration.TOOL_STORE_4,Decoration.TOOL_STORE_5), @@ -386,6 +388,8 @@ public enum BuildHotspot { linkedHotspots.add(new BuildHotspot[] { DUNGEON_DOOR_LEFT2, DUNGEON_DOOR_RIGHT2 }); linkedHotspots.add(new BuildHotspot[] { SMALL_PLANT_1, SMALL_PLANT1 }); linkedHotspots.add(new BuildHotspot[] { SHELVES, SHELVES_2 }); + linkedHotspots.add(new BuildHotspot[] { WORKBENCH, WORKBENCH_STOOL }); + linkedHotspots.add(new BuildHotspot[] { CRAFTING, CRAFTING_STOOL }); } /** diff --git a/Server/src/main/content/global/skill/construction/ConstructionInterface.kt b/Server/src/main/content/global/skill/construction/ConstructionInterface.kt index 2106c04a1..5745e09d4 100644 --- a/Server/src/main/content/global/skill/construction/ConstructionInterface.kt +++ b/Server/src/main/content/global/skill/construction/ConstructionInterface.kt @@ -9,7 +9,7 @@ import core.game.node.scenery.Scenery import core.tools.Log /** - * Handles the creating of a decoration object. + * Handles the creation of a decoration object. * @author Emperor * @author Bishop */ @@ -17,13 +17,13 @@ import core.tools.Log class ConstructionInterface : InterfaceListener { companion object { - const val DECO_INTERFACE = 396 - const val POH_MENU = 398 - const val ROOM_INTERFACE = 402 + const val decorationInterface = 396 + const val pohMenuInterface = 398 + const val roomInterface = 402 } override fun defineInterfaceListeners() { - on(DECO_INTERFACE) { player, _, _, buttonID, slot, _ -> + on(decorationInterface) { player, _, _, buttonID, slot, _ -> when (buttonID) { 132 -> { closeInterface(player) @@ -76,8 +76,8 @@ class ConstructionInterface : InterfaceListener { return@on true } } - if (flatpackMode && WorkbenchListeners.getMaxLevel(getAttribute(player, WorkbenchListeners.attributeWorkbenchId, 0)) < deco.level) { - sendMessage(player, "You need a better workbench to make this flatpack.") // placeholder + if (flatpackMode && WorkbenchListeners.getBenchLevel(getAttribute(player, WorkbenchListeners.attributeWorkbenchId, 0)) < deco.level) { + sendDialogue(player, "You need a better workbench to make this flatpack.") // TODO: find authentic dialogue return@on true } } @@ -92,7 +92,7 @@ class ConstructionInterface : InterfaceListener { } } - on(POH_MENU) { player, _, _, buttonID, _, _ -> + on(pohMenuInterface) { player, _, _, buttonID, _, _ -> when (buttonID) { 14 -> { player.houseManager.toggleBuildingMode(player, true) @@ -108,7 +108,7 @@ class ConstructionInterface : InterfaceListener { } 13 -> { if (!player.houseManager.isInHouse(player)) { - player.sendMessage("You can't do this outside of your house.") + sendMessage(player, "You can't do this outside of your house.") return@on true } HouseManager.leave(player) @@ -118,11 +118,11 @@ class ConstructionInterface : InterfaceListener { } } - on(ROOM_INTERFACE) { player, _, _, buttonID, _, _ -> + on(roomInterface) { player, _, _, buttonID, _, _ -> val index = buttonID - 160 log(this.javaClass, Log.FINE, "BuildRoom Interface Index: $index") if (index > -1 && index < RoomProperties.values().size) { - player.dialogueInterpreter.open("con:room", RoomProperties.values()[index]) + openDialogue(player, "con:room", RoomProperties.values()[index]) } return@on true } diff --git a/Server/src/main/content/global/skill/construction/RoomProperties.java b/Server/src/main/content/global/skill/construction/RoomProperties.java index 80bc6e6ed..0f4cb7791 100644 --- a/Server/src/main/content/global/skill/construction/RoomProperties.java +++ b/Server/src/main/content/global/skill/construction/RoomProperties.java @@ -130,7 +130,9 @@ public enum RoomProperties { new Hotspot(BuildHotspot.REPAIR, 7, 3, 7, 4), new Hotspot(BuildHotspot.HERALDRY, 7, 6, 7, 7), new Hotspot(BuildHotspot.CRAFTING, 0, 3, 0, 4), + new Hotspot(BuildHotspot.CRAFTING_STOOL, 1, 3), new Hotspot(BuildHotspot.WORKBENCH, 3, 4), + new Hotspot(BuildHotspot.WORKBENCH_STOOL, 3, 3), new Hotspot(BuildHotspot.TOOL4, 7, 1), new Hotspot(BuildHotspot.TOOL2, 6, 0), new Hotspot(BuildHotspot.TOOL1, 1, 0), diff --git a/Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt b/Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt index 2bfb15772..0173a7239 100644 --- a/Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt +++ b/Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt @@ -8,9 +8,13 @@ import core.api.* import core.game.interaction.IntType import core.game.interaction.InteractionListener import core.game.interaction.InterfaceListener +import core.game.interaction.QueueStrength import core.game.node.entity.player.Player import core.game.node.entity.skill.Skills import core.game.node.item.Item +import core.game.node.scenery.SceneryBuilder +import core.game.world.map.Direction +import core.game.world.map.RegionManager import org.rs09.consts.Items import org.rs09.consts.Scenery @@ -22,20 +26,32 @@ import org.rs09.consts.Scenery class WorkbenchListeners : InteractionListener, InterfaceListener { companion object { - const val WORKBENCH_INTERFACE = 397 + const val workbenchInterface = 397 + const val attributeWorkbenchId = "con:workbench" const val attributeFlatpackMode = "con:flatpack" const val attributeSelection = "con:flatpack-hotspot" + const val attributeCrafting = "con:crafting" + const val attributeStandUp = "con:stand-up" - val WORKBENCHES = intArrayOf( - Scenery.WORKBENCH_13704, // wooden - Scenery.WORKBENCH_13705, // oak - Scenery.WORKBENCH_13706, // steel framed - Scenery.WORKBENCH_13707, // with vice - Scenery.WORKBENCH_13708, // with lathe + const val animationSitDown = 4103 + const val animationStandUp = 4105 + const val animationSit = 4107 + const val animationSitOak = 4108 + const val animationCraft = 4109 + const val animationCraftOak = 4110 + + const val `nothing` = 15440 + + private val workbenches = intArrayOf( + Scenery.WORKBENCH_13704, // lv20, wooden + Scenery.WORKBENCH_13705, // lv40, oak + Scenery.WORKBENCH_13706, // lv60, steel framed + Scenery.WORKBENCH_13707, // lv80, with vice + Scenery.WORKBENCH_13708, // lv99, with lathe ) - val FLATPACK_CATEGORIES = arrayOf( + private val decoCategories = arrayOf( BuildHotspot.CHAIRS_1, // 111 BuildHotspot.BOOKCASE, // 112 BuildHotspot.BARRELS, // 113 @@ -54,50 +70,114 @@ class WorkbenchListeners : InteractionListener, InterfaceListener { BuildHotspot.TOY_BOX, // 126 ) - fun getMaxLevel(workbenchId: Int): Int { - return (WORKBENCHES.indexOf(workbenchId) + 1) * 20 + fun getBenchLevel(workbenchId: Int): Int { + return (workbenches.indexOf(workbenchId) + 1) * 20 } fun produceFlatpack(player: Player, deco: Decoration) { val reward = deco.flatpackItemID if (reward == -1) return if (removeItem(player, deco.items) || player.isAdmin) { - animate(player, 1) // find fiddling animation + setAttribute(player, attributeCrafting, true) rewardXP(player, Skills.CONSTRUCTION, deco.experience.toDouble()) addItemOrDrop(player, reward) } } + + private fun sitDown(player: Player) { + val chunk = RegionManager.getRegionChunk(player.location) + for (x in 3..4) { + for (y in 3..4) { + val obj = chunk.objects[x][y] + if (obj != null && obj.id == BuildHotspot.WORKBENCH_STOOL.objectId) { + val finalDir = when ((x * 10) + y) { // I just think this is fun, okay? Don't laugh! + 33 -> Direction.EAST + 34 -> Direction.SOUTH + 43 -> Direction.NORTH + else -> Direction.WEST + } + val sittingAnim = if (obj.id == Scenery.STOOL_13719) animationSit else animationSitOak + val craftingAnim = if (obj.id == Scenery.STOOL_13719) animationCraft else animationCraftOak + animate(player, animationSitDown) + queueScript(player, 1, QueueStrength.NORMAL) { stage -> + when (stage) { + 0 -> { + SceneryBuilder.replace(obj, obj.transform(`nothing`)) + animate(player, sittingAnim) + forceMove(player, player.location, player.location.transform(finalDir, -1), 0, 1000) + return@queueScript delayScript(player, 1) + } + else -> { + if (!getAttribute(player, attributeStandUp, false)) { + if (getAttribute(player, attributeCrafting, false)) { + removeAttribute(player, attributeCrafting) + animate(player, craftingAnim) + } else { + animate(player, sittingAnim) + } + return@queueScript delayScript(player, 2) + } else { + removeAttribute(player, attributeStandUp) + SceneryBuilder.replace(chunk.objects[x][y], obj.transform(BuildHotspot.WORKBENCH_STOOL.objectId)) + animate(player, animationStandUp) + forceMove(player, player.location, player.location.transform(finalDir, 1), 0, 1000) + return@queueScript stopExecuting(player) + } + } + } + } + return + } + } + } + } + + private fun standUp(player: Player) { + setAttribute(player, attributeStandUp, true) + } } override fun defineListeners() { - on(WORKBENCHES, IntType.SCENERY, "work-at") { player, node -> + on(workbenches, IntType.SCENERY, "work-at") { player, node -> + sitDown(player) setAttribute(player, attributeWorkbenchId, node.id) - openInterface(player, WORKBENCH_INTERFACE) + openInterface(player, workbenchInterface) return@on true } - on(WORKBENCHES, IntType.SCENERY, "upgrade") { player, node -> + on(workbenches, IntType.SCENERY, "upgrade") { player, node -> if (!inInventory(player, Items.OAK_PLANK_8778, 2) || !inInventory(player, Items.STEEL_BAR_2353)) { + sendDialogue(player, "You need two oak planks and a steel bar to upgrade this workbench.") // TODO: find authentic dialogue return@on false } if (removeItem(player, Item(Items.OAK_PLANK_8778, 2)) && removeItem(player, Items.STEEL_BAR_2353)) { - + // TODO: upgrading } return@on true } } override fun defineInterfaceListeners() { - on(WORKBENCH_INTERFACE) { player, _, _, buttonID, _, _ -> + on(workbenchInterface) { player, _, _, buttonID, _, _ -> val index = buttonID - 111 - if (index < 0 || index >= FLATPACK_CATEGORIES.size) return@on false - val hotspot = FLATPACK_CATEGORIES[index] + if (index < 0 || index >= decoCategories.size) return@on false + val hotspot = decoCategories[index] setAttribute(player, attributeSelection, hotspot) setAttribute(player, attributeFlatpackMode, true) BuildingUtils.openBuildInterface(player, hotspot) return@on true } - onClose(ConstructionInterface.DECO_INTERFACE) { player, _ -> + onClose(workbenchInterface) { player, _ -> + if (!getAttribute(player, attributeFlatpackMode, false)) { + standUp(player) + removeAttribute(player, attributeSelection) + removeAttribute(player, attributeFlatpackMode) + } + return@onClose true + } + + onClose(ConstructionInterface.decorationInterface) { player, _ -> + standUp(player) removeAttribute(player, attributeSelection) removeAttribute(player, attributeFlatpackMode) return@onClose true From 3722762b70608d0b01b4ec74808cda77d7ccc7c7 Mon Sep 17 00:00:00 2001 From: Bishop Date: Tue, 21 Jul 2026 20:34:18 -0500 Subject: [PATCH 06/13] Debug 1 --- .../skill/construction/BuildHotspot.java | 4 +-- .../skill/construction/BuildingUtils.java | 2 +- .../construction/ConstructionInterface.kt | 10 ++++--- .../skill/construction/RoomProperties.java | 6 ++-- .../decoration/workshop/WorkbenchListeners.kt | 29 ++++++++++++------- 5 files changed, 31 insertions(+), 20 deletions(-) diff --git a/Server/src/main/content/global/skill/construction/BuildHotspot.java b/Server/src/main/content/global/skill/construction/BuildHotspot.java index 365d6331a..3ed0edd20 100644 --- a/Server/src/main/content/global/skill/construction/BuildHotspot.java +++ b/Server/src/main/content/global/skill/construction/BuildHotspot.java @@ -66,15 +66,15 @@ public enum BuildHotspot { */ REPAIR(15448, BuildHotspotType.INDIVIDUAL, BuildingUtils.BUILD_MID_ANIM, Decoration.REPAIR_BENCH, Decoration.WHETSTONE, Decoration.ARMOUR_STAND), WORKBENCH(15439, BuildHotspotType.LINKED, BuildingUtils.BUILD_MID_ANIM, Decoration.WORKBENCH_WOODEN, Decoration.WORKBENCH_OAK,Decoration.WORKBENCH_STEEL_FRAME, Decoration.WORKBENCH_WITH_VICE,Decoration.WORKBENCH_WITH_LATHE), - WORKBENCH_STOOL(15540, BuildHotspotType.LINKED, BuildingUtils.BUILD_MID_ANIM, Decoration.WORKSHOP_STOOL, Decoration.WORKSHOP_STOOL,Decoration.WORKSHOP_STOOL_OAK, Decoration.WORKSHOP_STOOL_OAK,Decoration.WORKSHOP_STOOL_OAK), CRAFTING(15441, BuildHotspotType.LINKED, BuildingUtils.BUILD_MID_ANIM, Decoration.CRAFTING_TABLE_1, Decoration.CRAFTING_TABLE_2,Decoration.CRAFTING_TABLE_3, Decoration.CRAFTING_TABLE_4), - CRAFTING_STOOL(15542, BuildHotspotType.LINKED, BuildingUtils.BUILD_MID_ANIM, Decoration.WORKSHOP_STOOL, Decoration.WORKSHOP_STOOL,Decoration.WORKSHOP_STOOL, Decoration.WORKSHOP_STOOL), TOOL1(15443, BuildHotspotType.RECURSIVE, BuildingUtils.BUILD_HIGH_ANIM, Decoration.TOOL_STORE_1, Decoration.TOOL_STORE_2, Decoration.TOOL_STORE_3, Decoration.TOOL_STORE_4, Decoration.TOOL_STORE_5), TOOL2(15444, BuildHotspotType.RECURSIVE, BuildingUtils.BUILD_HIGH_ANIM, Decoration.TOOL_STORE_1, Decoration.TOOL_STORE_2,Decoration.TOOL_STORE_3, Decoration.TOOL_STORE_4,Decoration.TOOL_STORE_5), TOOL3(15445, BuildHotspotType.RECURSIVE, BuildingUtils.BUILD_HIGH_ANIM, Decoration.TOOL_STORE_1, Decoration.TOOL_STORE_2,Decoration.TOOL_STORE_3, Decoration.TOOL_STORE_4,Decoration.TOOL_STORE_5), TOOL4(15446, BuildHotspotType.RECURSIVE, BuildingUtils.BUILD_HIGH_ANIM, Decoration.TOOL_STORE_1, Decoration.TOOL_STORE_2,Decoration.TOOL_STORE_3, Decoration.TOOL_STORE_4,Decoration.TOOL_STORE_5), TOOL5(15447, BuildHotspotType.RECURSIVE, BuildingUtils.BUILD_HIGH_ANIM, Decoration.TOOL_STORE_1, Decoration.TOOL_STORE_2,Decoration.TOOL_STORE_3, Decoration.TOOL_STORE_4,Decoration.TOOL_STORE_5), HERALDRY(15450, BuildHotspotType.INDIVIDUAL, BuildingUtils.BUILD_MID_ANIM, Decoration.PLUMING_STAND, Decoration.SHIELD_EASEL,Decoration.BANNER_EASEL), + WORKBENCH_STOOL(15440, BuildHotspotType.LINKED, BuildingUtils.BUILD_MID_ANIM, Decoration.WORKSHOP_STOOL, Decoration.WORKSHOP_STOOL,Decoration.WORKSHOP_STOOL_OAK, Decoration.WORKSHOP_STOOL_OAK,Decoration.WORKSHOP_STOOL_OAK), + CRAFTING_STOOL(15442, BuildHotspotType.LINKED, BuildingUtils.BUILD_MID_ANIM, Decoration.WORKSHOP_STOOL, Decoration.WORKSHOP_STOOL,Decoration.WORKSHOP_STOOL, Decoration.WORKSHOP_STOOL), /** * Bedroom hotspots. diff --git a/Server/src/main/content/global/skill/construction/BuildingUtils.java b/Server/src/main/content/global/skill/construction/BuildingUtils.java index 2ee636337..116f2b107 100644 --- a/Server/src/main/content/global/skill/construction/BuildingUtils.java +++ b/Server/src/main/content/global/skill/construction/BuildingUtils.java @@ -439,7 +439,7 @@ public final class BuildingUtils { for (int y = 0; y < 8; y++) { for (BuildHotspot bh : linkedHotspots) { Hotspot h = room.getHotspot(bh, x, y); - if (h != null) { + if (h != null && h.getDecorationIndex() >= 0) { int objectId = bh.getDecorations()[h.getDecorationIndex()].getObjectId(style); Scenery o = chunk.get(x, y, chunk.getIndex(x, y, objectId)); h.setDecorationIndex(-1); diff --git a/Server/src/main/content/global/skill/construction/ConstructionInterface.kt b/Server/src/main/content/global/skill/construction/ConstructionInterface.kt index 5745e09d4..3e8e15ca9 100644 --- a/Server/src/main/content/global/skill/construction/ConstructionInterface.kt +++ b/Server/src/main/content/global/skill/construction/ConstructionInterface.kt @@ -26,11 +26,11 @@ class ConstructionInterface : InterfaceListener { on(decorationInterface) { player, _, _, buttonID, slot, _ -> when (buttonID) { 132 -> { - closeInterface(player) val hotspot = getAttribute(player, "con:hotspot", null) val `object` = getAttribute(player, "con:hsobject", null) val flatpackMode = getAttribute(player, WorkbenchListeners.attributeFlatpackMode, false) - if (hotspot == null || `object` == null && !flatpackMode) { + if ((hotspot == null || `object` == null) && !flatpackMode) { + closeInterface(player) log(this.javaClass, Log.ERR, "Failed building decoration $hotspot : $`object`") return@on false } @@ -38,8 +38,9 @@ class ConstructionInterface : InterfaceListener { val buildHotspot = if (flatpackMode) { getAttribute(player, WorkbenchListeners.attributeSelection, null)?: return@on false } else { - hotspot.hotspot + hotspot!!.hotspot } + closeInterface(player) if (slot >= buildHotspot.decorations.size) { log(this.javaClass, Log.ERR, "Failed building decoration " + slot + "/" + buildHotspot.decorations.size) return@on false @@ -122,7 +123,8 @@ class ConstructionInterface : InterfaceListener { val index = buttonID - 160 log(this.javaClass, Log.FINE, "BuildRoom Interface Index: $index") if (index > -1 && index < RoomProperties.values().size) { - openDialogue(player, "con:room", RoomProperties.values()[index]) + // ContentAPI impl won't work for this + player.dialogueInterpreter.open("con:room", RoomProperties.values()[index]) } return@on true } diff --git a/Server/src/main/content/global/skill/construction/RoomProperties.java b/Server/src/main/content/global/skill/construction/RoomProperties.java index 0f4cb7791..70236bdd4 100644 --- a/Server/src/main/content/global/skill/construction/RoomProperties.java +++ b/Server/src/main/content/global/skill/construction/RoomProperties.java @@ -130,14 +130,14 @@ public enum RoomProperties { new Hotspot(BuildHotspot.REPAIR, 7, 3, 7, 4), new Hotspot(BuildHotspot.HERALDRY, 7, 6, 7, 7), new Hotspot(BuildHotspot.CRAFTING, 0, 3, 0, 4), - new Hotspot(BuildHotspot.CRAFTING_STOOL, 1, 3), new Hotspot(BuildHotspot.WORKBENCH, 3, 4), - new Hotspot(BuildHotspot.WORKBENCH_STOOL, 3, 3), new Hotspot(BuildHotspot.TOOL4, 7, 1), new Hotspot(BuildHotspot.TOOL2, 6, 0), new Hotspot(BuildHotspot.TOOL1, 1, 0), new Hotspot(BuildHotspot.TOOL3, 0, 1), - new Hotspot(BuildHotspot.TOOL5, 0, 6)), + new Hotspot(BuildHotspot.TOOL5, 0, 6), + new Hotspot(BuildHotspot.CRAFTING_STOOL, 1, 3), + new Hotspot(BuildHotspot.WORKBENCH_STOOL, 3, 3)), /** * Bedroom. diff --git a/Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt b/Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt index 0173a7239..570245e26 100644 --- a/Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt +++ b/Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt @@ -51,6 +51,11 @@ class WorkbenchListeners : InteractionListener, InterfaceListener { Scenery.WORKBENCH_13708, // lv99, with lathe ) + private val stools = intArrayOf( + Scenery.STOOL_13719, // wooden + Scenery.STOOL_13720, // oak + ) + private val decoCategories = arrayOf( BuildHotspot.CHAIRS_1, // 111 BuildHotspot.BOOKCASE, // 112 @@ -77,7 +82,7 @@ class WorkbenchListeners : InteractionListener, InterfaceListener { fun produceFlatpack(player: Player, deco: Decoration) { val reward = deco.flatpackItemID if (reward == -1) return - if (removeItem(player, deco.items) || player.isAdmin) { + if (removeItemsIfPlayerHasEnough(player, *deco.items) || player.isAdmin) { setAttribute(player, attributeCrafting, true) rewardXP(player, Skills.CONSTRUCTION, deco.experience.toDouble()) addItemOrDrop(player, reward) @@ -89,15 +94,17 @@ class WorkbenchListeners : InteractionListener, InterfaceListener { for (x in 3..4) { for (y in 3..4) { val obj = chunk.objects[x][y] - if (obj != null && obj.id == BuildHotspot.WORKBENCH_STOOL.objectId) { - val finalDir = when ((x * 10) + y) { // I just think this is fun, okay? Don't laugh! - 33 -> Direction.EAST - 34 -> Direction.SOUTH - 43 -> Direction.NORTH - else -> Direction.WEST + if (obj != null && obj.id in stools) { + val oakStool = obj.id == Scenery.STOOL_13720 + val stoolId = obj.id + val finalDir = when (Pair(x,y)) { + Pair(3,3) -> Direction.EAST + Pair(3,4) -> Direction.SOUTH + Pair(4,3) -> Direction.NORTH + else -> Direction.WEST } - val sittingAnim = if (obj.id == Scenery.STOOL_13719) animationSit else animationSitOak - val craftingAnim = if (obj.id == Scenery.STOOL_13719) animationCraft else animationCraftOak + val sittingAnim = if (oakStool) animationSitOak else animationSit + val craftingAnim = if (oakStool) animationCraftOak else animationCraft animate(player, animationSitDown) queueScript(player, 1, QueueStrength.NORMAL) { stage -> when (stage) { @@ -117,8 +124,9 @@ class WorkbenchListeners : InteractionListener, InterfaceListener { } return@queueScript delayScript(player, 2) } else { + // Clean up and put the player back to normal removeAttribute(player, attributeStandUp) - SceneryBuilder.replace(chunk.objects[x][y], obj.transform(BuildHotspot.WORKBENCH_STOOL.objectId)) + SceneryBuilder.replace(chunk.objects[x][y], obj.transform(stoolId)) animate(player, animationStandUp) forceMove(player, player.location, player.location.transform(finalDir, 1), 0, 1000) return@queueScript stopExecuting(player) @@ -139,6 +147,7 @@ class WorkbenchListeners : InteractionListener, InterfaceListener { override fun defineListeners() { on(workbenches, IntType.SCENERY, "work-at") { player, node -> + face(player, node) sitDown(player) setAttribute(player, attributeWorkbenchId, node.id) openInterface(player, workbenchInterface) From af167f1431bec014b682067fc1989a40183dd0e0 Mon Sep 17 00:00:00 2001 From: Bishop Date: Tue, 21 Jul 2026 23:10:44 -0500 Subject: [PATCH 07/13] Debug 2 --- .../skill/construction/BuildHotspot.java | 2 +- .../skill/construction/BuildOptionPlugin.java | 22 ++++ .../construction/ConstructionInterface.kt | 7 +- .../decoration/workshop/WorkbenchListeners.kt | 120 ++++++++---------- 4 files changed, 78 insertions(+), 73 deletions(-) diff --git a/Server/src/main/content/global/skill/construction/BuildHotspot.java b/Server/src/main/content/global/skill/construction/BuildHotspot.java index 3ed0edd20..2ec669970 100644 --- a/Server/src/main/content/global/skill/construction/BuildHotspot.java +++ b/Server/src/main/content/global/skill/construction/BuildHotspot.java @@ -65,7 +65,7 @@ public enum BuildHotspot { * Low-level Work shop hotspots. */ REPAIR(15448, BuildHotspotType.INDIVIDUAL, BuildingUtils.BUILD_MID_ANIM, Decoration.REPAIR_BENCH, Decoration.WHETSTONE, Decoration.ARMOUR_STAND), - WORKBENCH(15439, BuildHotspotType.LINKED, BuildingUtils.BUILD_MID_ANIM, Decoration.WORKBENCH_WOODEN, Decoration.WORKBENCH_OAK,Decoration.WORKBENCH_STEEL_FRAME, Decoration.WORKBENCH_WITH_VICE,Decoration.WORKBENCH_WITH_LATHE), + WORKBENCH(15439, BuildHotspotType.LINKED, BuildingUtils.BUILD_MID_ANIM, Decoration.WORKBENCH_WOODEN, Decoration.WORKBENCH_OAK,Decoration.WORKBENCH_STEEL_FRAME, Decoration.WORKBENCH_WITH_VICE, Decoration.WORKBENCH_WITH_LATHE), CRAFTING(15441, BuildHotspotType.LINKED, BuildingUtils.BUILD_MID_ANIM, Decoration.CRAFTING_TABLE_1, Decoration.CRAFTING_TABLE_2,Decoration.CRAFTING_TABLE_3, Decoration.CRAFTING_TABLE_4), TOOL1(15443, BuildHotspotType.RECURSIVE, BuildingUtils.BUILD_HIGH_ANIM, Decoration.TOOL_STORE_1, Decoration.TOOL_STORE_2, Decoration.TOOL_STORE_3, Decoration.TOOL_STORE_4, Decoration.TOOL_STORE_5), TOOL2(15444, BuildHotspotType.RECURSIVE, BuildingUtils.BUILD_HIGH_ANIM, Decoration.TOOL_STORE_1, Decoration.TOOL_STORE_2,Decoration.TOOL_STORE_3, Decoration.TOOL_STORE_4,Decoration.TOOL_STORE_5), diff --git a/Server/src/main/content/global/skill/construction/BuildOptionPlugin.java b/Server/src/main/content/global/skill/construction/BuildOptionPlugin.java index 69b0b1483..4e836a663 100644 --- a/Server/src/main/content/global/skill/construction/BuildOptionPlugin.java +++ b/Server/src/main/content/global/skill/construction/BuildOptionPlugin.java @@ -9,6 +9,7 @@ import core.game.interaction.OptionHandler; import core.game.node.Node; import core.game.node.entity.player.Player; import core.game.node.scenery.Scenery; +import core.game.world.map.RegionManager; import core.plugin.Initializable; import core.plugin.Plugin; import core.tools.Log; @@ -16,6 +17,7 @@ import core.tools.SystemLogger; import core.plugin.ClassScanner; import static core.api.ContentAPIKt.log; +import static core.api.ContentAPIKt.setAttribute; /** * The build option handling plugin. @@ -71,6 +73,26 @@ public final class BuildOptionPlugin extends OptionHandler { return true; } + BuildHotspot[] linked = BuildHotspot.getLinkedHotspots(hotspot.getHotspot()); + if (linked != null && linked[0] != hotspot.getHotspot()) { + Room room = player.getHouseManager().getRoom(object.getLocation()); + if (room == null) return true; + for (Hotspot h : room.getHotspots()) { + if (h.getHotspot() == linked[0]) { + int dx = h.getCurrentX() - object.getLocation().getChunkOffsetX(); + int dy = h.getCurrentY() - object.getLocation().getChunkOffsetY(); + Scenery primaryObj = RegionManager.getObject(object.getLocation().transform(dx, dy, 0)); + if (primaryObj != null) { + setAttribute(player, "con:hsobject", primaryObj); + setAttribute(player, "con:hotspot", h); + BuildingUtils.openBuildInterface(player, linked[0]); + } + return true; + } + } + return true; + } + player.setAttribute("con:hotspot", hotspot); BuildingUtils.openBuildInterface(player, hotspot.getHotspot()); return true; diff --git a/Server/src/main/content/global/skill/construction/ConstructionInterface.kt b/Server/src/main/content/global/skill/construction/ConstructionInterface.kt index 3e8e15ca9..d5ce7ff7e 100644 --- a/Server/src/main/content/global/skill/construction/ConstructionInterface.kt +++ b/Server/src/main/content/global/skill/construction/ConstructionInterface.kt @@ -29,8 +29,10 @@ class ConstructionInterface : InterfaceListener { val hotspot = getAttribute(player, "con:hotspot", null) val `object` = getAttribute(player, "con:hsobject", null) val flatpackMode = getAttribute(player, WorkbenchListeners.attributeFlatpackMode, false) - if ((hotspot == null || `object` == null) && !flatpackMode) { + if (!flatpackMode) { closeInterface(player) + } + if ((hotspot == null || `object` == null) && !flatpackMode) { log(this.javaClass, Log.ERR, "Failed building decoration $hotspot : $`object`") return@on false } @@ -40,7 +42,6 @@ class ConstructionInterface : InterfaceListener { } else { hotspot!!.hotspot } - closeInterface(player) if (slot >= buildHotspot.decorations.size) { log(this.javaClass, Log.ERR, "Failed building decoration " + slot + "/" + buildHotspot.decorations.size) return@on false @@ -78,7 +79,7 @@ class ConstructionInterface : InterfaceListener { } } if (flatpackMode && WorkbenchListeners.getBenchLevel(getAttribute(player, WorkbenchListeners.attributeWorkbenchId, 0)) < deco.level) { - sendDialogue(player, "You need a better workbench to make this flatpack.") // TODO: find authentic dialogue + sendMessage(player, "You need a better workbench to make this flatpack.") // TODO: find authentic dialogue return@on true } } diff --git a/Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt b/Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt index 570245e26..15b364da5 100644 --- a/Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt +++ b/Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt @@ -12,9 +12,9 @@ import core.game.interaction.QueueStrength import core.game.node.entity.player.Player import core.game.node.entity.skill.Skills import core.game.node.item.Item -import core.game.node.scenery.SceneryBuilder import core.game.world.map.Direction -import core.game.world.map.RegionManager +import core.game.world.update.flag.context.Animation +import core.tools.ticksToCycles import org.rs09.consts.Items import org.rs09.consts.Scenery @@ -29,10 +29,10 @@ class WorkbenchListeners : InteractionListener, InterfaceListener { const val workbenchInterface = 397 const val attributeWorkbenchId = "con:workbench" - const val attributeFlatpackMode = "con:flatpack" - const val attributeSelection = "con:flatpack-hotspot" - const val attributeCrafting = "con:crafting" - const val attributeStandUp = "con:stand-up" + const val attributeFlatpackMode = "con:flatpack:active" + const val attributeSelection = "con:flatpack:hotspot" + const val attributeReturnDir = "con:flatpack:direction" + const val attributeSuccess = "con:flatpack:success" const val animationSitDown = 4103 const val animationStandUp = 4105 @@ -41,8 +41,6 @@ class WorkbenchListeners : InteractionListener, InterfaceListener { const val animationCraft = 4109 const val animationCraftOak = 4110 - const val `nothing` = 15440 - private val workbenches = intArrayOf( Scenery.WORKBENCH_13704, // lv20, wooden Scenery.WORKBENCH_13705, // lv40, oak @@ -81,76 +79,60 @@ class WorkbenchListeners : InteractionListener, InterfaceListener { fun produceFlatpack(player: Player, deco: Decoration) { val reward = deco.flatpackItemID + val directions = getAttribute(player, attributeReturnDir, arrayOf(Direction.WEST, Direction.NORTH, Direction.EAST)) + val animation = if (getScenery(player.location)?.id == Scenery.STOOL_13720) { animationCraftOak } else { animationCraft } if (reward == -1) return if (removeItemsIfPlayerHasEnough(player, *deco.items) || player.isAdmin) { - setAttribute(player, attributeCrafting, true) + setAttribute(player, attributeSuccess, true) + closeInterface(player) rewardXP(player, Skills.CONSTRUCTION, deco.experience.toDouble()) addItemOrDrop(player, reward) - } - } - - private fun sitDown(player: Player) { - val chunk = RegionManager.getRegionChunk(player.location) - for (x in 3..4) { - for (y in 3..4) { - val obj = chunk.objects[x][y] - if (obj != null && obj.id in stools) { - val oakStool = obj.id == Scenery.STOOL_13720 - val stoolId = obj.id - val finalDir = when (Pair(x,y)) { - Pair(3,3) -> Direction.EAST - Pair(3,4) -> Direction.SOUTH - Pair(4,3) -> Direction.NORTH - else -> Direction.WEST - } - val sittingAnim = if (oakStool) animationSitOak else animationSit - val craftingAnim = if (oakStool) animationCraftOak else animationCraft - animate(player, animationSitDown) - queueScript(player, 1, QueueStrength.NORMAL) { stage -> - when (stage) { - 0 -> { - SceneryBuilder.replace(obj, obj.transform(`nothing`)) - animate(player, sittingAnim) - forceMove(player, player.location, player.location.transform(finalDir, -1), 0, 1000) - return@queueScript delayScript(player, 1) - } - else -> { - if (!getAttribute(player, attributeStandUp, false)) { - if (getAttribute(player, attributeCrafting, false)) { - removeAttribute(player, attributeCrafting) - animate(player, craftingAnim) - } else { - animate(player, sittingAnim) - } - return@queueScript delayScript(player, 2) - } else { - // Clean up and put the player back to normal - removeAttribute(player, attributeStandUp) - SceneryBuilder.replace(chunk.objects[x][y], obj.transform(stoolId)) - animate(player, animationStandUp) - forceMove(player, player.location, player.location.transform(finalDir, 1), 0, 1000) - return@queueScript stopExecuting(player) - } - } - } - } - return - } + animate(player, animation) + lock(player, Animation(animation).duration + 1) + queueScript(player, Animation(animation).duration, QueueStrength.SOFT) { + forceMove(player, player.location, player.location.transform(directions[2], 1), + 0, ticksToCycles(1), directions[1], animationStandUp) + return@queueScript stopExecuting(player) } } } private fun standUp(player: Player) { - setAttribute(player, attributeStandUp, true) + val directions = getAttribute(player, attributeReturnDir, arrayOf(Direction.WEST, Direction.NORTH, Direction.EAST)) + lock(player, 2) + queueScript(player, 1, QueueStrength.SOFT) { + forceMove(player, player.location, player.location.transform(directions[2], 1), + 0, ticksToCycles(1), directions[1], animationStandUp) + return@queueScript stopExecuting(player) + } } } override fun defineListeners() { on(workbenches, IntType.SCENERY, "work-at") { player, node -> - face(player, node) - sitDown(player) - setAttribute(player, attributeWorkbenchId, node.id) - openInterface(player, workbenchInterface) + val baseX = node.location.x - node.location.chunkOffsetX + val baseY = node.location.y - node.location.chunkOffsetY + for (x in 3..4) { + for (y in 3..4) { + val obj = getScenery(baseX + x, baseY + y, node.location.z) ?: continue + if (obj.id in stools) { + val directions = when (Pair(x,y)) { + Pair(3,3) -> arrayOf(Direction.WEST, Direction.NORTH, Direction.EAST) + Pair(3,4) -> arrayOf(Direction.NORTH, Direction.EAST, Direction.SOUTH) + Pair(4,3) -> arrayOf(Direction.SOUTH, Direction.WEST, Direction.NORTH) + else -> arrayOf(Direction.EAST, Direction.SOUTH, Direction.WEST) + } + setAttribute(player, attributeWorkbenchId, node.id) + setAttribute(player, attributeReturnDir, directions) + forceMove(player, player.location, player.location.transform(directions[0], 1), + 0, ticksToCycles(1), directions[1], animationSitDown) { + animate(player, if (obj.id == Scenery.STOOL_13720) animationSitOak else animationSit) + openInterface(player, workbenchInterface) + } + return@on true + } + } + } return@on true } on(workbenches, IntType.SCENERY, "upgrade") { player, node -> @@ -179,16 +161,16 @@ class WorkbenchListeners : InteractionListener, InterfaceListener { onClose(workbenchInterface) { player, _ -> if (!getAttribute(player, attributeFlatpackMode, false)) { standUp(player) - removeAttribute(player, attributeSelection) - removeAttribute(player, attributeFlatpackMode) + removeAttributes(player, attributeFlatpackMode, attributeReturnDir, attributeSelection, attributeSuccess, attributeWorkbenchId) } return@onClose true } onClose(ConstructionInterface.decorationInterface) { player, _ -> - standUp(player) - removeAttribute(player, attributeSelection) - removeAttribute(player, attributeFlatpackMode) + if (getAttribute(player, attributeFlatpackMode, false) && !getAttribute(player, attributeSuccess, false)) { + standUp(player) + } + removeAttributes(player, attributeFlatpackMode, attributeReturnDir, attributeSelection, attributeSuccess, attributeWorkbenchId) return@onClose true } } From 688442e7f0f9caf766d1ab08c9f610e682664182 Mon Sep 17 00:00:00 2001 From: Bishop Date: Wed, 22 Jul 2026 23:37:03 -0500 Subject: [PATCH 08/13] Upgrading and also oops I did getting up wrong --- .../skill/construction/BuildOptionPlugin.java | 8 +- .../skill/construction/BuildRoomDialogue.java | 4 +- .../skill/construction/BuildingUtils.java | 2 +- .../construction/ConstructionInterface.kt | 11 ++- .../decoration/workshop/WorkbenchListeners.kt | 84 ++++++++++++------- 5 files changed, 67 insertions(+), 42 deletions(-) diff --git a/Server/src/main/content/global/skill/construction/BuildOptionPlugin.java b/Server/src/main/content/global/skill/construction/BuildOptionPlugin.java index 4e836a663..fc75c068a 100644 --- a/Server/src/main/content/global/skill/construction/BuildOptionPlugin.java +++ b/Server/src/main/content/global/skill/construction/BuildOptionPlugin.java @@ -50,7 +50,7 @@ public final class BuildOptionPlugin extends OptionHandler { player.getDialogueInterpreter().open("con:removedec", object); return true; } - player.setAttribute("con:hsobject", node); + setAttribute(player, ConstructionInterface.attributeHsObject, node); if (BuildingUtils.isDoorHotspot(object)) { int[] pos = BuildingUtils.roomExists(player, object); if (pos != null) { @@ -83,8 +83,8 @@ public final class BuildOptionPlugin extends OptionHandler { int dy = h.getCurrentY() - object.getLocation().getChunkOffsetY(); Scenery primaryObj = RegionManager.getObject(object.getLocation().transform(dx, dy, 0)); if (primaryObj != null) { - setAttribute(player, "con:hsobject", primaryObj); - setAttribute(player, "con:hotspot", h); + setAttribute(player, ConstructionInterface.attributeHsObject, primaryObj); + setAttribute(player, ConstructionInterface.attributeHotspot, h); BuildingUtils.openBuildInterface(player, linked[0]); } return true; @@ -93,7 +93,7 @@ public final class BuildOptionPlugin extends OptionHandler { return true; } - player.setAttribute("con:hotspot", hotspot); + setAttribute(player, ConstructionInterface.attributeHotspot, hotspot); BuildingUtils.openBuildInterface(player, hotspot.getHotspot()); return true; } diff --git a/Server/src/main/content/global/skill/construction/BuildRoomDialogue.java b/Server/src/main/content/global/skill/construction/BuildRoomDialogue.java index b74e99cb3..08d75d933 100644 --- a/Server/src/main/content/global/skill/construction/BuildRoomDialogue.java +++ b/Server/src/main/content/global/skill/construction/BuildRoomDialogue.java @@ -18,6 +18,8 @@ import java.awt.*; import java.util.ArrayList; import java.util.List; +import static core.api.ContentAPIKt.getAttribute; + /** * Handles the building a room dialogue. * @author Emperor @@ -105,7 +107,7 @@ public final class BuildRoomDialogue extends DialoguePlugin { stage = 2; return true; } - this.door = (Scenery) player.getAttribute("con:hsobject"); + this.door = (Scenery) getAttribute(player, ConstructionInterface.attributeHsObject, null); int[] pos = BuildingUtils.getRoomPosition(player, door); roomX = pos[0]; roomY = pos[1]; diff --git a/Server/src/main/content/global/skill/construction/BuildingUtils.java b/Server/src/main/content/global/skill/construction/BuildingUtils.java index 116f2b107..c98f18d64 100644 --- a/Server/src/main/content/global/skill/construction/BuildingUtils.java +++ b/Server/src/main/content/global/skill/construction/BuildingUtils.java @@ -63,7 +63,7 @@ public final class BuildingUtils { /** * The removing a decoration animation. */ - private static final Animation REMOVE_ANIMATION = Animation.create(3685); + public static final Animation REMOVE_ANIMATION = Animation.create(3685); /** * The plank item. diff --git a/Server/src/main/content/global/skill/construction/ConstructionInterface.kt b/Server/src/main/content/global/skill/construction/ConstructionInterface.kt index d5ce7ff7e..110a09a4f 100644 --- a/Server/src/main/content/global/skill/construction/ConstructionInterface.kt +++ b/Server/src/main/content/global/skill/construction/ConstructionInterface.kt @@ -18,16 +18,19 @@ class ConstructionInterface : InterfaceListener { companion object { const val decorationInterface = 396 - const val pohMenuInterface = 398 - const val roomInterface = 402 + const val pohMenuInterface = 398 + const val roomInterface = 402 + + const val attributeHotspot = "con:hotspot" + const val attributeHsObject = "con:hsobject" } override fun defineInterfaceListeners() { on(decorationInterface) { player, _, _, buttonID, slot, _ -> when (buttonID) { 132 -> { - val hotspot = getAttribute(player, "con:hotspot", null) - val `object` = getAttribute(player, "con:hsobject", null) + val hotspot = getAttribute(player, attributeHotspot, null) + val `object` = getAttribute(player, attributeHsObject, null) val flatpackMode = getAttribute(player, WorkbenchListeners.attributeFlatpackMode, false) if (!flatpackMode) { closeInterface(player) diff --git a/Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt b/Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt index 15b364da5..ddb42b10f 100644 --- a/Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt +++ b/Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt @@ -1,9 +1,6 @@ package content.global.skill.construction.decoration.workshop -import content.global.skill.construction.BuildHotspot -import content.global.skill.construction.BuildingUtils -import content.global.skill.construction.ConstructionInterface -import content.global.skill.construction.Decoration +import content.global.skill.construction.* import core.api.* import core.game.interaction.IntType import core.game.interaction.InteractionListener @@ -28,11 +25,11 @@ class WorkbenchListeners : InteractionListener, InterfaceListener { companion object { const val workbenchInterface = 397 - const val attributeWorkbenchId = "con:workbench" - const val attributeFlatpackMode = "con:flatpack:active" - const val attributeSelection = "con:flatpack:hotspot" - const val attributeReturnDir = "con:flatpack:direction" - const val attributeSuccess = "con:flatpack:success" + const val attributeWorkbenchId = "con:workbench:id" + const val attributeFlatpackMode = "con:workbench:active" + const val attributeDirections = "con:workbench:directions" + const val attributeSelection = "con:workbench:hotspot" + const val attributeSitting = "con:workbench:sitting" const val animationSitDown = 4103 const val animationStandUp = 4105 @@ -73,36 +70,33 @@ class WorkbenchListeners : InteractionListener, InterfaceListener { BuildHotspot.TOY_BOX, // 126 ) + /** + * Returns the maximum construction level of decoration that can be built at a given workbench by id + */ fun getBenchLevel(workbenchId: Int): Int { return (workbenches.indexOf(workbenchId) + 1) * 20 } fun produceFlatpack(player: Player, deco: Decoration) { val reward = deco.flatpackItemID - val directions = getAttribute(player, attributeReturnDir, arrayOf(Direction.WEST, Direction.NORTH, Direction.EAST)) val animation = if (getScenery(player.location)?.id == Scenery.STOOL_13720) { animationCraftOak } else { animationCraft } if (reward == -1) return if (removeItemsIfPlayerHasEnough(player, *deco.items) || player.isAdmin) { - setAttribute(player, attributeSuccess, true) closeInterface(player) + lock(player, Animation(animation).duration) + animate(player, animation) rewardXP(player, Skills.CONSTRUCTION, deco.experience.toDouble()) addItemOrDrop(player, reward) - animate(player, animation) - lock(player, Animation(animation).duration + 1) - queueScript(player, Animation(animation).duration, QueueStrength.SOFT) { - forceMove(player, player.location, player.location.transform(directions[2], 1), - 0, ticksToCycles(1), directions[1], animationStandUp) - return@queueScript stopExecuting(player) - } } } private fun standUp(player: Player) { - val directions = getAttribute(player, attributeReturnDir, arrayOf(Direction.WEST, Direction.NORTH, Direction.EAST)) - lock(player, 2) - queueScript(player, 1, QueueStrength.SOFT) { + val directions = getAttribute(player, attributeDirections, arrayOf(Direction.WEST, Direction.NORTH, Direction.EAST)) + lock(player, animationStandUp) + queueScript(player, 0, QueueStrength.SOFT) { forceMove(player, player.location, player.location.transform(directions[2], 1), - 0, ticksToCycles(1), directions[1], animationStandUp) + 0, ticksToCycles(1), directions[2], animationStandUp) + removeAttributes(player, attributeSitting, attributeDirections) return@queueScript stopExecuting(player) } } @@ -110,6 +104,13 @@ class WorkbenchListeners : InteractionListener, InterfaceListener { override fun defineListeners() { on(workbenches, IntType.SCENERY, "work-at") { player, node -> + setAttribute(player, attributeWorkbenchId, node.id) + if (getAttribute(player, attributeSitting, false)) { + val animation = if (getScenery(player.location)?.id == Scenery.STOOL_13720) { animationSitOak } else { animationSit } + animate(player, animation) + openInterface(player, workbenchInterface) + return@on true + } val baseX = node.location.x - node.location.chunkOffsetX val baseY = node.location.y - node.location.chunkOffsetY for (x in 3..4) { @@ -122,11 +123,11 @@ class WorkbenchListeners : InteractionListener, InterfaceListener { Pair(4,3) -> arrayOf(Direction.SOUTH, Direction.WEST, Direction.NORTH) else -> arrayOf(Direction.EAST, Direction.SOUTH, Direction.WEST) } - setAttribute(player, attributeWorkbenchId, node.id) - setAttribute(player, attributeReturnDir, directions) + setAttribute(player, attributeDirections, directions) forceMove(player, player.location, player.location.transform(directions[0], 1), 0, ticksToCycles(1), directions[1], animationSitDown) { animate(player, if (obj.id == Scenery.STOOL_13720) animationSitOak else animationSit) + setAttribute(player, attributeSitting, true) openInterface(player, workbenchInterface) } return@on true @@ -135,13 +136,36 @@ class WorkbenchListeners : InteractionListener, InterfaceListener { } return@on true } + on(workbenches, IntType.SCENERY, "upgrade") { player, node -> if (!inInventory(player, Items.OAK_PLANK_8778, 2) || !inInventory(player, Items.STEEL_BAR_2353)) { sendDialogue(player, "You need two oak planks and a steel bar to upgrade this workbench.") // TODO: find authentic dialogue - return@on false + return@on true } if (removeItem(player, Item(Items.OAK_PLANK_8778, 2)) && removeItem(player, Items.STEEL_BAR_2353)) { - // TODO: upgrading + val hotspotSearchTile = node.location + // only the 2nd and 3rd best workbenches have upgrade options + val resultDeco = if (node.id == Scenery.WORKBENCH_13706) { // steel framed + Decoration.forObjectId(Scenery.WORKBENCH_13707) // with vice + } else { + Decoration.forObjectId(Scenery.WORKBENCH_13708) // with lathe + } + queueScript(player, 0, QueueStrength.SOFT) { stage -> + when (stage) { + 0 -> { + lock(player, BuildingUtils.REMOVE_ANIMATION.duration + BuildingUtils.BUILD_MID_ANIM.duration) + BuildingUtils.removeDecoration(player, node as core.game.node.scenery.Scenery) + return@queueScript delayScript(player, BuildingUtils.REMOVE_ANIMATION.duration) + } + 1 -> { + val hotspot = Hotspot(BuildHotspot.WORKBENCH, 3, 4, 4, 4) + val hotspotObj = getScenery(hotspotSearchTile) + BuildingUtils.buildDecoration(player, hotspot, resultDeco, hotspotObj) + return@queueScript delayScript(player, BuildingUtils.BUILD_MID_ANIM.duration) + } + else -> return@queueScript stopExecuting(player) + } + } } return@on true } @@ -160,17 +184,13 @@ class WorkbenchListeners : InteractionListener, InterfaceListener { onClose(workbenchInterface) { player, _ -> if (!getAttribute(player, attributeFlatpackMode, false)) { - standUp(player) - removeAttributes(player, attributeFlatpackMode, attributeReturnDir, attributeSelection, attributeSuccess, attributeWorkbenchId) + removeAttributes(player, attributeFlatpackMode, attributeSelection, attributeWorkbenchId) } return@onClose true } onClose(ConstructionInterface.decorationInterface) { player, _ -> - if (getAttribute(player, attributeFlatpackMode, false) && !getAttribute(player, attributeSuccess, false)) { - standUp(player) - } - removeAttributes(player, attributeFlatpackMode, attributeReturnDir, attributeSelection, attributeSuccess, attributeWorkbenchId) + removeAttributes(player, attributeFlatpackMode, attributeSelection, attributeWorkbenchId) return@onClose true } } From 301d589eefbb287e0128f0b69c30953a67c61ced Mon Sep 17 00:00:00 2001 From: Bishop Date: Thu, 23 Jul 2026 19:11:53 -0500 Subject: [PATCH 09/13] Ready for primetime --- .../skill/construction/BuildOptionPlugin.java | 5 +- .../skill/construction/BuildRoomDialogue.java | 2 +- .../skill/construction/BuildingUtils.java | 20 ++- .../construction/ConstructionInterface.kt | 61 ++++++--- .../skill/construction/FlatpackListener.kt | 18 +-- .../global/skill/construction/HouseZone.java | 21 +++ .../construction/decoration/StaySeated.kt | 51 +++++++ .../decoration/workshop/WorkbenchListeners.kt | 127 +++++++++++------- 8 files changed, 222 insertions(+), 83 deletions(-) create mode 100644 Server/src/main/content/global/skill/construction/decoration/StaySeated.kt diff --git a/Server/src/main/content/global/skill/construction/BuildOptionPlugin.java b/Server/src/main/content/global/skill/construction/BuildOptionPlugin.java index fc75c068a..ee74e1f0d 100644 --- a/Server/src/main/content/global/skill/construction/BuildOptionPlugin.java +++ b/Server/src/main/content/global/skill/construction/BuildOptionPlugin.java @@ -13,7 +13,6 @@ import core.game.world.map.RegionManager; import core.plugin.Initializable; import core.plugin.Plugin; import core.tools.Log; -import core.tools.SystemLogger; import core.plugin.ClassScanner; import static core.api.ContentAPIKt.log; @@ -50,7 +49,7 @@ public final class BuildOptionPlugin extends OptionHandler { player.getDialogueInterpreter().open("con:removedec", object); return true; } - setAttribute(player, ConstructionInterface.attributeHsObject, node); + setAttribute(player, ConstructionInterface.attributeHotspotObj, node); if (BuildingUtils.isDoorHotspot(object)) { int[] pos = BuildingUtils.roomExists(player, object); if (pos != null) { @@ -83,7 +82,7 @@ public final class BuildOptionPlugin extends OptionHandler { int dy = h.getCurrentY() - object.getLocation().getChunkOffsetY(); Scenery primaryObj = RegionManager.getObject(object.getLocation().transform(dx, dy, 0)); if (primaryObj != null) { - setAttribute(player, ConstructionInterface.attributeHsObject, primaryObj); + setAttribute(player, ConstructionInterface.attributeHotspotObj, primaryObj); setAttribute(player, ConstructionInterface.attributeHotspot, h); BuildingUtils.openBuildInterface(player, linked[0]); } diff --git a/Server/src/main/content/global/skill/construction/BuildRoomDialogue.java b/Server/src/main/content/global/skill/construction/BuildRoomDialogue.java index 08d75d933..397342e25 100644 --- a/Server/src/main/content/global/skill/construction/BuildRoomDialogue.java +++ b/Server/src/main/content/global/skill/construction/BuildRoomDialogue.java @@ -107,7 +107,7 @@ public final class BuildRoomDialogue extends DialoguePlugin { stage = 2; return true; } - this.door = (Scenery) getAttribute(player, ConstructionInterface.attributeHsObject, null); + this.door = (Scenery) getAttribute(player, ConstructionInterface.attributeHotspotObj, null); int[] pos = BuildingUtils.getRoomPosition(player, door); roomX = pos[0]; roomY = pos[1]; diff --git a/Server/src/main/content/global/skill/construction/BuildingUtils.java b/Server/src/main/content/global/skill/construction/BuildingUtils.java index c98f18d64..e85eec085 100644 --- a/Server/src/main/content/global/skill/construction/BuildingUtils.java +++ b/Server/src/main/content/global/skill/construction/BuildingUtils.java @@ -63,7 +63,7 @@ public final class BuildingUtils { /** * The removing a decoration animation. */ - public static final Animation REMOVE_ANIMATION = Animation.create(3685); + private static final Animation REMOVE_ANIMATION = Animation.create(3685); /** * The plank item. @@ -139,9 +139,13 @@ public final class BuildingUtils { * @param object The object. */ public static void buildDecoration(final Player player, final Hotspot hotspot, final Decoration deco, final Scenery object) { + buildDecoration(player, hotspot, deco, object, false, false); + } + + public static void buildDecoration(final Player player, final Hotspot hotspot, final Decoration deco, final Scenery object, final boolean bypassCost, final boolean bypassXp) { final int nailAmount = deco.getNailAmount(); final NailType type = nailAmount > 0 ? NailType.get(player, nailAmount) : null; - if (nailAmount > 0 && type == null) { + if (nailAmount > 0 && type == null && !bypassCost) { player.getPacketDispatch().sendMessage("You don't have the right materials."); return; } @@ -165,7 +169,7 @@ public final class BuildingUtils { NailType nail = type; @Override public boolean pulse() { - if (nails > 0) { + if (nails > 0 && !bypassCost) { if (!type.isBend()) { player.getPacketDispatch().sendMessage("You use a nail."); nails--; @@ -189,12 +193,14 @@ public final class BuildingUtils { } } } - if (player.getInventory().remove(deco.getItems()) || player.isAdmin()) { + if (player.getInventory().remove(deco.getItems()) || bypassCost || player.isAdmin()) { setDecoration(player, r, room, hotspot, object, deco); - player.getSkills().addExperience(Skills.CONSTRUCTION, deco.getExperience(), true); + if (!bypassXp) { + player.getSkills().addExperience(Skills.CONSTRUCTION, deco.getExperience(), true); - if (getObjectIdsThatGiveFarmingExperience().contains(deco.getObjectId())) { - player.getSkills().addExperience(Skills.FARMING, deco.getExperience(), true); + if (getObjectIdsThatGiveFarmingExperience().contains(deco.getObjectId())) { + player.getSkills().addExperience(Skills.FARMING, deco.getExperience(), true); + } } player.unlock(); } diff --git a/Server/src/main/content/global/skill/construction/ConstructionInterface.kt b/Server/src/main/content/global/skill/construction/ConstructionInterface.kt index 110a09a4f..23a26e878 100644 --- a/Server/src/main/content/global/skill/construction/ConstructionInterface.kt +++ b/Server/src/main/content/global/skill/construction/ConstructionInterface.kt @@ -9,8 +9,8 @@ import core.game.node.scenery.Scenery import core.tools.Log /** - * Handles the creation of a decoration object. - * @author Emperor + * Handles three interfaces related to the Construction skill, namely those which allow a player to build decorations, + * toggle building mode/expel guests, and select a room to add to the POH. * @author Bishop */ @@ -21,41 +21,57 @@ class ConstructionInterface : InterfaceListener { const val pohMenuInterface = 398 const val roomInterface = 402 - const val attributeHotspot = "con:hotspot" - const val attributeHsObject = "con:hsobject" + const val attributeHotspot = "con:hotspot" + const val attributeHotspotObj = "con:hsobject" + + // Register furniture here when it is only obtainable by upgrading, to send the correct rejection message. + val upgradeOnly = arrayOf( + Decoration.WORKBENCH_WITH_VICE, + Decoration.WORKBENCH_WITH_LATHE, + ) } override fun defineInterfaceListeners() { + /** + * Handles the interface for selecting a decoration to build. + */ on(decorationInterface) { player, _, _, buttonID, slot, _ -> when (buttonID) { 132 -> { val hotspot = getAttribute(player, attributeHotspot, null) - val `object` = getAttribute(player, attributeHsObject, null) + val hotspotObj = getAttribute(player, attributeHotspotObj, null) val flatpackMode = getAttribute(player, WorkbenchListeners.attributeFlatpackMode, false) if (!flatpackMode) { closeInterface(player) } - if ((hotspot == null || `object` == null) && !flatpackMode) { - log(this.javaClass, Log.ERR, "Failed building decoration $hotspot : $`object`") + if ((hotspot == null || hotspotObj == null) && !flatpackMode) { + log(this.javaClass, Log.ERR, "Failed building decoration $hotspot : $hotspotObj") return@on false } - val slot = (if (slot % 2 != 0) 4 else 0) + (slot shr 1) + val decoIndex = (if (slot % 2 != 0) 4 else 0) + (slot shr 1) val buildHotspot = if (flatpackMode) { getAttribute(player, WorkbenchListeners.attributeSelection, null)?: return@on false } else { hotspot!!.hotspot } - if (slot >= buildHotspot.decorations.size) { - log(this.javaClass, Log.ERR, "Failed building decoration " + slot + "/" + buildHotspot.decorations.size) + if (decoIndex >= buildHotspot.decorations.size) { + log(this.javaClass, Log.ERR, "Failed building decoration $decoIndex/${buildHotspot.decorations.size}") return@on false } - val deco = buildHotspot.decorations[slot] + val deco = buildHotspot.decorations[decoIndex] if (!player.isAdmin) { if (getDynLevel(player, Skills.CONSTRUCTION) < deco.level) { - sendMessage(player, "You need to have a Construction level of " + deco.level + " to build that.") + closeInterface(player) + sendMessage(player, "You need to have a Construction level of ${deco.level} to build that.") return@on true } - if (!player.inventory.containsItems(*deco.items)) { // search for contentAPI way to do this + if (deco in upgradeOnly) { + closeInterface(player) + sendMessage(player, "That can only be built by upgrading the previous piece of furniture.") + return@on true + } + if (!player.inventory.containsItems(*deco.items)) { // No clean ContentAPI substitute for this + closeInterface(player) sendMessage(player, "You don't have the right materials.") return@on true } @@ -76,20 +92,22 @@ class ConstructionInterface : InterfaceListener { } continue } - if (!player.inventory.contains(tool, 1)) { + if (!inInventory(player, tool)) { + closeInterface(player) sendMessage(player, "You need a ${ItemDefinition.forId(tool).name} to build this.") return@on true } } - if (flatpackMode && WorkbenchListeners.getBenchLevel(getAttribute(player, WorkbenchListeners.attributeWorkbenchId, 0)) < deco.level) { - sendMessage(player, "You need a better workbench to make this flatpack.") // TODO: find authentic dialogue + if (flatpackMode && WorkbenchListeners.getBenchLevel(getAttribute(player, WorkbenchListeners.attributeWorkbenchId, 20)) < deco.level) { + closeInterface(player) + sendMessage(player, "You cannot make this with this workbench.") // Placeholder return@on true } } if (flatpackMode) { WorkbenchListeners.produceFlatpack(player, deco) } else { - BuildingUtils.buildDecoration(player, hotspot, deco, `object`) + BuildingUtils.buildDecoration(player, hotspot, deco, hotspotObj) } return@on true } @@ -97,6 +115,9 @@ class ConstructionInterface : InterfaceListener { } } + /** + * Handles the interface for managing building mode and POH guests. + */ on(pohMenuInterface) { player, _, _, buttonID, _, _ -> when (buttonID) { 14 -> { @@ -123,12 +144,14 @@ class ConstructionInterface : InterfaceListener { } } + /** + * Handles the interface for selecting a new room to add to a POH. + */ on(roomInterface) { player, _, _, buttonID, _, _ -> val index = buttonID - 160 log(this.javaClass, Log.FINE, "BuildRoom Interface Index: $index") if (index > -1 && index < RoomProperties.values().size) { - // ContentAPI impl won't work for this - player.dialogueInterpreter.open("con:room", RoomProperties.values()[index]) + player.dialogueInterpreter.open("con:room", RoomProperties.values()[index]) // ContentAPI impl won't work for this } return@on true } diff --git a/Server/src/main/content/global/skill/construction/FlatpackListener.kt b/Server/src/main/content/global/skill/construction/FlatpackListener.kt index 7e71991ac..d502415d7 100644 --- a/Server/src/main/content/global/skill/construction/FlatpackListener.kt +++ b/Server/src/main/content/global/skill/construction/FlatpackListener.kt @@ -1,6 +1,5 @@ package content.global.skill.construction -import content.global.skill.construction.BuildingUtils.buildDecoration import core.api.* import core.game.interaction.IntType import core.game.interaction.InteractionListener @@ -16,7 +15,7 @@ import org.rs09.consts.Items */ class FlatpackListener : InteractionListener { - val flatpacks = Decoration.values().map { it.flatpackItemID }.toIntArray() + val flatpacks = Decoration.values().map { it.flatpackItemID }.filter { it != -1 }.toIntArray() val hotspots = BuildHotspot.values().map { it.objectId }.toIntArray() override fun defineListeners() { @@ -27,20 +26,23 @@ class FlatpackListener : InteractionListener { } } - private fun buildFlatpackOnHotspot(player: Player, used: Item, with: Scenery):Boolean { + private fun buildFlatpackOnHotspot(player: Player, used: Item, with: Scenery): Boolean { val hotspotUsed = player.houseManager.getHotspot(with) val decorationUsed = Decoration.forFlatpackItemId(used.id) - if(!hotspotUsed.hotspot.decorations.contains(decorationUsed)) { + if (!hotspotUsed.hotspot.decorations.contains(decorationUsed)) { sendMessage(player, "You can't build that here.") return false } - if (!player.inventory.containsItems(Item(Items.HAMMER_2347),Item(Items.SAW_8794))) { + if (!inInventory(player, Items.HAMMER_2347) || !inInventory(player, Items.SAW_8794)) { sendMessage(player, "You need a hammer and a saw to build this.") return false } - buildDecoration(player, hotspotUsed, decorationUsed, with.asScenery()) - return true - + if (removeItem(player, used)) { + BuildingUtils.buildDecoration(player, hotspotUsed, decorationUsed, with.asScenery(), true, true) + return true + } else { + return false + } } } \ No newline at end of file diff --git a/Server/src/main/content/global/skill/construction/HouseZone.java b/Server/src/main/content/global/skill/construction/HouseZone.java index 31a57f6f8..1923e4f66 100644 --- a/Server/src/main/content/global/skill/construction/HouseZone.java +++ b/Server/src/main/content/global/skill/construction/HouseZone.java @@ -3,6 +3,9 @@ package content.global.skill.construction; import core.api.Container; import core.game.world.map.Location; +import core.net.packet.PacketRepository; +import core.net.packet.context.PlayerContext; +import core.net.packet.out.ClearMinimapFlag; import org.rs09.consts.Items; import core.game.node.entity.Entity; import core.game.node.entity.player.Player; @@ -12,6 +15,7 @@ import core.game.world.map.Region; import core.game.system.task.Pulse; import core.game.world.map.zone.ZoneType; +import content.global.skill.construction.decoration.workshop.WorkbenchListeners; import static core.api.ContentAPIKt.*; /** @@ -80,6 +84,23 @@ public final class HouseZone extends MapZone { return super.enter(e); } + @Override + public boolean move(Entity e, Location from, Location to) { + if (e instanceof Player) { + Player p = (Player) e; + if (getAttribute(p, WorkbenchListeners.attributeSitting, false)) { + p.getPulseManager().clear(); + p.getWalkingQueue().reset(); + PacketRepository.send(ClearMinimapFlag.class, new PlayerContext(p)); + if (!getAttribute(p, WorkbenchListeners.attributeStandingUp, false)) { + WorkbenchListeners.standUpFromWorkbench(p); + } + return false; + } + } + return super.move(e, from, to); + } + @Override public boolean death(Entity e, Entity killer) { if (e instanceof Player) { diff --git a/Server/src/main/content/global/skill/construction/decoration/StaySeated.kt b/Server/src/main/content/global/skill/construction/decoration/StaySeated.kt new file mode 100644 index 000000000..65f8b7000 --- /dev/null +++ b/Server/src/main/content/global/skill/construction/decoration/StaySeated.kt @@ -0,0 +1,51 @@ +package content.global.skill.construction.decoration + +import content.global.skill.construction.decoration.workshop.WorkbenchListeners +import core.api.animate +import core.api.getScenery +import core.game.node.entity.Entity +import core.game.node.entity.player.Player +import core.game.system.timer.PersistTimer +import core.game.system.timer.RSTimer +import org.rs09.consts.Scenery +import kotlin.collections.get + +/** + * Makes a player stay seated by reapplying the current animation occasionally. + * An alternative to some features of ChairBenchPlugin. + * Written with workbench stools in mind. + * @author Bishop + */ + +class StaySeated : PersistTimer(10 /*ticks*/, "con:sitting", isSoft = true) { + lateinit var player: Player + + private val standAnim = 808 // Same as AppearanceCache.STAND_ANIM + + // Register new chairs and animations here + private val sittables = mapOf( + Scenery.STOOL_13719 to WorkbenchListeners.animationSit, // wooden workbench stool + Scenery.STOOL_13720 to WorkbenchListeners.animationSitOak, // oak workbench stool + ) + + override fun run(entity: Entity): Boolean { + player = entity as Player + val localObj = getScenery(player.location)?.id + // Don't interrupt a player doing a different animation unless it's the idle animation + val currentAnimId = player.animator.animation?.id ?: -1 + if (localObj in sittables) { + if (currentAnimId != sittables[localObj] && + currentAnimId != standAnim && + currentAnimId != -1) { + return true + } + animate(player, sittables[localObj]) + return true + } + return false + } + + override fun getTimer(vararg args: Any): RSTimer { + return StaySeated() + } +} \ No newline at end of file diff --git a/Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt b/Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt index ddb42b10f..478152370 100644 --- a/Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt +++ b/Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt @@ -1,6 +1,7 @@ package content.global.skill.construction.decoration.workshop import content.global.skill.construction.* +import content.global.skill.construction.decoration.StaySeated import core.api.* import core.game.interaction.IntType import core.game.interaction.InteractionListener @@ -10,7 +11,6 @@ import core.game.node.entity.player.Player import core.game.node.entity.skill.Skills import core.game.node.item.Item import core.game.world.map.Direction -import core.game.world.update.flag.context.Animation import core.tools.ticksToCycles import org.rs09.consts.Items import org.rs09.consts.Scenery @@ -27,9 +27,10 @@ class WorkbenchListeners : InteractionListener, InterfaceListener { const val attributeWorkbenchId = "con:workbench:id" const val attributeFlatpackMode = "con:workbench:active" - const val attributeDirections = "con:workbench:directions" + const val attributeDirections = "con:workbench:directions" const val attributeSelection = "con:workbench:hotspot" const val attributeSitting = "con:workbench:sitting" + const val attributeStandingUp = "con:workbench:standing" const val animationSitDown = 4103 const val animationStandUp = 4105 @@ -47,70 +48,89 @@ class WorkbenchListeners : InteractionListener, InterfaceListener { ) private val stools = intArrayOf( - Scenery.STOOL_13719, // wooden - Scenery.STOOL_13720, // oak + Scenery.STOOL_13719, // wooden stool, bottom 2 tiers + Scenery.STOOL_13720, // oak stool, top 3 tiers ) private val decoCategories = arrayOf( - BuildHotspot.CHAIRS_1, // 111 - BuildHotspot.BOOKCASE, // 112 - BuildHotspot.BARRELS, // 113 - BuildHotspot.KITCHEN_TABLE, // 114 - BuildHotspot.DINING_TABLE, // 115 - BuildHotspot.DINING_BENCH_1, // 116 - BuildHotspot.BED, // 117 - BuildHotspot.DRESSER, // 118 - BuildHotspot.DRAWERS, // 119 - BuildHotspot.CLOCK, // 120 - BuildHotspot.CAPE_RACK, // 121 - BuildHotspot.MAGIC_WARDROBE, // 122 - BuildHotspot.ARMOUR_CASE, // 123 - BuildHotspot.TREASURE_CHEST, // 124 - BuildHotspot.COSTUME_BOX, // 125 - BuildHotspot.TOY_BOX, // 126 + BuildHotspot.CHAIRS_1, // ButtonID 111 + BuildHotspot.BOOKCASE, // ButtonID 112 + BuildHotspot.BARRELS, // ButtonID 113 + BuildHotspot.KITCHEN_TABLE, // ButtonID 114 + BuildHotspot.DINING_TABLE, // ButtonID 115 + BuildHotspot.DINING_BENCH_1, // ButtonID 116 + BuildHotspot.BED, // ButtonID 117 + BuildHotspot.DRESSER, // ButtonID 118 + BuildHotspot.DRAWERS, // ButtonID 119 + BuildHotspot.CLOCK, // ButtonID 120 + BuildHotspot.CAPE_RACK, // ButtonID 121 + BuildHotspot.MAGIC_WARDROBE, // ButtonID 122 + BuildHotspot.ARMOUR_CASE, // ButtonID 123 + BuildHotspot.TREASURE_CHEST, // ButtonID 124 + BuildHotspot.COSTUME_BOX, // ButtonID 125 + BuildHotspot.TOY_BOX, // ButtonID 126 ) /** - * Returns the maximum construction level of decoration that can be built at a given workbench by id + * Returns the maximum construction level of decoration that can be built at a given workbench by id. */ fun getBenchLevel(workbenchId: Int): Int { - return (workbenches.indexOf(workbenchId) + 1) * 20 + return ((workbenches.indexOf(workbenchId) + 1) * 20) } + /** + * Animates the player crafting a flatpack, and exchanges its materials for the flatpack item. + * Flatpacks are free to produce for players with admin rights. + */ fun produceFlatpack(player: Player, deco: Decoration) { val reward = deco.flatpackItemID val animation = if (getScenery(player.location)?.id == Scenery.STOOL_13720) { animationCraftOak } else { animationCraft } if (reward == -1) return if (removeItemsIfPlayerHasEnough(player, *deco.items) || player.isAdmin) { closeInterface(player) - lock(player, Animation(animation).duration) + lock(player, getAnimation(animation).duration) animate(player, animation) rewardXP(player, Skills.CONSTRUCTION, deco.experience.toDouble()) addItemOrDrop(player, reward) } } - private fun standUp(player: Player) { + /** + * Animates the player getting up from the workbench's stool. + * This occurs on the player's first attempt at movement off of the workbench. + */ + @JvmStatic + fun standUpFromWorkbench(player: Player) { val directions = getAttribute(player, attributeDirections, arrayOf(Direction.WEST, Direction.NORTH, Direction.EAST)) - lock(player, animationStandUp) + val animation = if (getScenery(player.location)?.id == Scenery.STOOL_13720) { animationSitOak } else { animationSit } + setAttribute(player, attributeStandingUp, true) + lock(player, 1) + animate(player, animation) queueScript(player, 0, QueueStrength.SOFT) { forceMove(player, player.location, player.location.transform(directions[2], 1), - 0, ticksToCycles(1), directions[2], animationStandUp) - removeAttributes(player, attributeSitting, attributeDirections) + 0, ticksToCycles(1), directions[2], animationStandUp) { + removeAttributes(player, attributeDirections, attributeSitting, attributeStandingUp) + removeTimer(player) + } return@queueScript stopExecuting(player) } } } override fun defineListeners() { + /** + * Animates the player sitting down at the workbench, and opens the workbench interface. + */ on(workbenches, IntType.SCENERY, "work-at") { player, node -> setAttribute(player, attributeWorkbenchId, node.id) + // Skips the animation if the player is already sitting down. if (getAttribute(player, attributeSitting, false)) { val animation = if (getScenery(player.location)?.id == Scenery.STOOL_13720) { animationSitOak } else { animationSit } animate(player, animation) openInterface(player, workbenchInterface) return@on true } + // Ascertains the room rotation from where the stool is, to coordinate animations val baseX = node.location.x - node.location.chunkOffsetX val baseY = node.location.y - node.location.chunkOffsetY for (x in 3..4) { @@ -126,8 +146,10 @@ class WorkbenchListeners : InteractionListener, InterfaceListener { setAttribute(player, attributeDirections, directions) forceMove(player, player.location, player.location.transform(directions[0], 1), 0, ticksToCycles(1), directions[1], animationSitDown) { - animate(player, if (obj.id == Scenery.STOOL_13720) animationSitOak else animationSit) + val animation = if (obj.id == Scenery.STOOL_13720) { animationSitOak } else { animationSit } + animate(player, animation) setAttribute(player, attributeSitting, true) + registerTimer(player, StaySeated()) openInterface(player, workbenchInterface) } return@on true @@ -137,31 +159,43 @@ class WorkbenchListeners : InteractionListener, InterfaceListener { return@on true } + /** + * Handles upgrading a workbench with the minimenu option. + */ on(workbenches, IntType.SCENERY, "upgrade") { player, node -> - if (!inInventory(player, Items.OAK_PLANK_8778, 2) || !inInventory(player, Items.STEEL_BAR_2353)) { - sendDialogue(player, "You need two oak planks and a steel bar to upgrade this workbench.") // TODO: find authentic dialogue + // I could not find any video of how this looks or what the messages are, so all messages in this listener are placeholders. + val hotspot = Hotspot(BuildHotspot.WORKBENCH, 3, 4, 4, 4) + val nodeObj = node as core.game.node.scenery.Scenery + val resultDeco = Decoration.forObjectId(node.id + 1) + if (!player.houseManager.isBuildingMode) { + sendMessage(player, "You have to be in building mode to do this.") // I don't actually know if this is true but better safe than sorry. return@on true } - if (removeItem(player, Item(Items.OAK_PLANK_8778, 2)) && removeItem(player, Items.STEEL_BAR_2353)) { - val hotspotSearchTile = node.location - // only the 2nd and 3rd best workbenches have upgrade options - val resultDeco = if (node.id == Scenery.WORKBENCH_13706) { // steel framed - Decoration.forObjectId(Scenery.WORKBENCH_13707) // with vice - } else { - Decoration.forObjectId(Scenery.WORKBENCH_13708) // with lathe - } + if (getDynLevel(player, Skills.CONSTRUCTION) < resultDeco.level) { + sendMessage(player, "You need a Construction level of ${resultDeco.level} to upgrade this.") + return@on true + } + if (!inInventory(player, Items.OAK_PLANK_8778, 2) || !inInventory(player, Items.STEEL_BAR_2353)) { + sendMessage(player, "You need two oak planks and a steel bar to upgrade this.") + return@on true + } + if (!inInventory(player, Items.HAMMER_2347) || !inInventory(player, Items.SAW_8794)) { + sendMessage(player, "You need a hammer and a saw to upgrade this.") + return@on true + } + if (removeItemsIfPlayerHasEnough(player, Item(Items.OAK_PLANK_8778, 2), Item(Items.STEEL_BAR_2353))) { queueScript(player, 0, QueueStrength.SOFT) { stage -> when (stage) { 0 -> { - lock(player, BuildingUtils.REMOVE_ANIMATION.duration + BuildingUtils.BUILD_MID_ANIM.duration) - BuildingUtils.removeDecoration(player, node as core.game.node.scenery.Scenery) - return@queueScript delayScript(player, BuildingUtils.REMOVE_ANIMATION.duration) + lock(player, BuildingUtils.BUILD_MID_ANIM.duration) + // Replaces the workbench with the upgraded form in HouseManager but not immediately in the instance + BuildingUtils.buildDecoration(player, hotspot, resultDeco, nodeObj, true, false) + return@queueScript delayScript(player, BuildingUtils.BUILD_MID_ANIM.duration) } 1 -> { - val hotspot = Hotspot(BuildHotspot.WORKBENCH, 3, 4, 4, 4) - val hotspotObj = getScenery(hotspotSearchTile) - BuildingUtils.buildDecoration(player, hotspot, resultDeco, hotspotObj) - return@queueScript delayScript(player, BuildingUtils.BUILD_MID_ANIM.duration) + // Temporary replacement until POH can rebuild on next entrance with the correct workbench + replaceScenery(nodeObj, resultDeco.objectId, -1) + return@queueScript stopExecuting(player) } else -> return@queueScript stopExecuting(player) } @@ -172,6 +206,9 @@ class WorkbenchListeners : InteractionListener, InterfaceListener { } override fun defineInterfaceListeners() { + /** + * Directs the player to the appropriate decoration building interface. + */ on(workbenchInterface) { player, _, _, buttonID, _, _ -> val index = buttonID - 111 if (index < 0 || index >= decoCategories.size) return@on false From e542861ca6914121f7cafb4ff810816ab40bbf8d Mon Sep 17 00:00:00 2001 From: Bishop Date: Fri, 24 Jul 2026 11:15:40 -0500 Subject: [PATCH 10/13] Merge conflict resolution attempt --- .../src/main/content/global/skill/construction/HouseZone.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/content/global/skill/construction/HouseZone.java b/Server/src/main/content/global/skill/construction/HouseZone.java index 1923e4f66..c256d1068 100644 --- a/Server/src/main/content/global/skill/construction/HouseZone.java +++ b/Server/src/main/content/global/skill/construction/HouseZone.java @@ -1,6 +1,7 @@ package content.global.skill.construction; +import content.global.skill.construction.decoration.workshop.WorkbenchListeners; import core.api.Container; import core.game.world.map.Location; import core.net.packet.PacketRepository; @@ -15,7 +16,6 @@ import core.game.world.map.Region; import core.game.system.task.Pulse; import core.game.world.map.zone.ZoneType; -import content.global.skill.construction.decoration.workshop.WorkbenchListeners; import static core.api.ContentAPIKt.*; /** From b54c8c7bb6a6bdb0276c9a7afc58d636c9668b74 Mon Sep 17 00:00:00 2001 From: Bishop Date: Thu, 30 Jul 2026 20:58:24 -0500 Subject: [PATCH 11/13] Constlib --- .../skill/construction/BuildOptionPlugin.java | 8 +-- .../skill/construction/BuildRoomDialogue.java | 2 +- .../construction/ConstructionInterface.kt | 25 +++---- .../global/skill/construction/HouseZone.java | 4 +- .../construction/decoration/StaySeated.kt | 6 +- .../decoration/workshop/WorkbenchListeners.kt | 69 +++++++++---------- 6 files changed, 52 insertions(+), 62 deletions(-) diff --git a/Server/src/main/content/global/skill/construction/BuildOptionPlugin.java b/Server/src/main/content/global/skill/construction/BuildOptionPlugin.java index ee74e1f0d..7c26c967c 100644 --- a/Server/src/main/content/global/skill/construction/BuildOptionPlugin.java +++ b/Server/src/main/content/global/skill/construction/BuildOptionPlugin.java @@ -49,7 +49,7 @@ public final class BuildOptionPlugin extends OptionHandler { player.getDialogueInterpreter().open("con:removedec", object); return true; } - setAttribute(player, ConstructionInterface.attributeHotspotObj, node); + setAttribute(player, ConstructionInterface.ATTRIBUTE_HOTSPOT_OBJ, node); if (BuildingUtils.isDoorHotspot(object)) { int[] pos = BuildingUtils.roomExists(player, object); if (pos != null) { @@ -82,8 +82,8 @@ public final class BuildOptionPlugin extends OptionHandler { int dy = h.getCurrentY() - object.getLocation().getChunkOffsetY(); Scenery primaryObj = RegionManager.getObject(object.getLocation().transform(dx, dy, 0)); if (primaryObj != null) { - setAttribute(player, ConstructionInterface.attributeHotspotObj, primaryObj); - setAttribute(player, ConstructionInterface.attributeHotspot, h); + setAttribute(player, ConstructionInterface.ATTRIBUTE_HOTSPOT_OBJ, primaryObj); + setAttribute(player, ConstructionInterface.ATTRIBUTE_HOTSPOT, h); BuildingUtils.openBuildInterface(player, linked[0]); } return true; @@ -92,7 +92,7 @@ public final class BuildOptionPlugin extends OptionHandler { return true; } - setAttribute(player, ConstructionInterface.attributeHotspot, hotspot); + setAttribute(player, ConstructionInterface.ATTRIBUTE_HOTSPOT, hotspot); BuildingUtils.openBuildInterface(player, hotspot.getHotspot()); return true; } diff --git a/Server/src/main/content/global/skill/construction/BuildRoomDialogue.java b/Server/src/main/content/global/skill/construction/BuildRoomDialogue.java index 397342e25..d3d10b797 100644 --- a/Server/src/main/content/global/skill/construction/BuildRoomDialogue.java +++ b/Server/src/main/content/global/skill/construction/BuildRoomDialogue.java @@ -107,7 +107,7 @@ public final class BuildRoomDialogue extends DialoguePlugin { stage = 2; return true; } - this.door = (Scenery) getAttribute(player, ConstructionInterface.attributeHotspotObj, null); + this.door = (Scenery) getAttribute(player, ConstructionInterface.ATTRIBUTE_HOTSPOT_OBJ, null); int[] pos = BuildingUtils.getRoomPosition(player, door); roomX = pos[0]; roomY = pos[1]; diff --git a/Server/src/main/content/global/skill/construction/ConstructionInterface.kt b/Server/src/main/content/global/skill/construction/ConstructionInterface.kt index 23a26e878..2451bf06b 100644 --- a/Server/src/main/content/global/skill/construction/ConstructionInterface.kt +++ b/Server/src/main/content/global/skill/construction/ConstructionInterface.kt @@ -7,6 +7,7 @@ import core.game.interaction.InterfaceListener import core.game.node.entity.skill.Skills import core.game.node.scenery.Scenery import core.tools.Log +import org.rs09.consts.Components /** * Handles three interfaces related to the Construction skill, namely those which allow a player to build decorations, @@ -17,12 +18,8 @@ import core.tools.Log class ConstructionInterface : InterfaceListener { companion object { - const val decorationInterface = 396 - const val pohMenuInterface = 398 - const val roomInterface = 402 - - const val attributeHotspot = "con:hotspot" - const val attributeHotspotObj = "con:hsobject" + const val ATTRIBUTE_HOTSPOT = "con:hotspot" + const val ATTRIBUTE_HOTSPOT_OBJ = "con:hsobject" // Register furniture here when it is only obtainable by upgrading, to send the correct rejection message. val upgradeOnly = arrayOf( @@ -35,12 +32,12 @@ class ConstructionInterface : InterfaceListener { /** * Handles the interface for selecting a decoration to build. */ - on(decorationInterface) { player, _, _, buttonID, slot, _ -> + on(Components.POH_DECORATION_396) { player, _, _, buttonID, slot, _ -> when (buttonID) { 132 -> { - val hotspot = getAttribute(player, attributeHotspot, null) - val hotspotObj = getAttribute(player, attributeHotspotObj, null) - val flatpackMode = getAttribute(player, WorkbenchListeners.attributeFlatpackMode, false) + val hotspot = getAttribute(player, ATTRIBUTE_HOTSPOT, null) + val hotspotObj = getAttribute(player, ATTRIBUTE_HOTSPOT_OBJ, null) + val flatpackMode = getAttribute(player, WorkbenchListeners.ATTRIBUTE_FLATPACK_MODE, false) if (!flatpackMode) { closeInterface(player) } @@ -50,7 +47,7 @@ class ConstructionInterface : InterfaceListener { } val decoIndex = (if (slot % 2 != 0) 4 else 0) + (slot shr 1) val buildHotspot = if (flatpackMode) { - getAttribute(player, WorkbenchListeners.attributeSelection, null)?: return@on false + getAttribute(player, WorkbenchListeners.ATTRIBUTE_WORKBENCH_SELECTION, null)?: return@on false } else { hotspot!!.hotspot } @@ -98,7 +95,7 @@ class ConstructionInterface : InterfaceListener { return@on true } } - if (flatpackMode && WorkbenchListeners.getBenchLevel(getAttribute(player, WorkbenchListeners.attributeWorkbenchId, 20)) < deco.level) { + if (flatpackMode && WorkbenchListeners.getBenchLevel(getAttribute(player, WorkbenchListeners.ATTRIBUTE_WORKBENCH_ID, 20)) < deco.level) { closeInterface(player) sendMessage(player, "You cannot make this with this workbench.") // Placeholder return@on true @@ -118,7 +115,7 @@ class ConstructionInterface : InterfaceListener { /** * Handles the interface for managing building mode and POH guests. */ - on(pohMenuInterface) { player, _, _, buttonID, _, _ -> + on(Components.POH_HOUSE_OPTIONS_398) { player, _, _, buttonID, _, _ -> when (buttonID) { 14 -> { player.houseManager.toggleBuildingMode(player, true) @@ -147,7 +144,7 @@ class ConstructionInterface : InterfaceListener { /** * Handles the interface for selecting a new room to add to a POH. */ - on(roomInterface) { player, _, _, buttonID, _, _ -> + on(Components.POH_ROOMS_402) { player, _, _, buttonID, _, _ -> val index = buttonID - 160 log(this.javaClass, Log.FINE, "BuildRoom Interface Index: $index") if (index > -1 && index < RoomProperties.values().size) { diff --git a/Server/src/main/content/global/skill/construction/HouseZone.java b/Server/src/main/content/global/skill/construction/HouseZone.java index c256d1068..6b2ce9656 100644 --- a/Server/src/main/content/global/skill/construction/HouseZone.java +++ b/Server/src/main/content/global/skill/construction/HouseZone.java @@ -88,11 +88,11 @@ public final class HouseZone extends MapZone { public boolean move(Entity e, Location from, Location to) { if (e instanceof Player) { Player p = (Player) e; - if (getAttribute(p, WorkbenchListeners.attributeSitting, false)) { + if (getAttribute(p, WorkbenchListeners.ATTRIBUTE_WORKBENCH_SEATED, false)) { p.getPulseManager().clear(); p.getWalkingQueue().reset(); PacketRepository.send(ClearMinimapFlag.class, new PlayerContext(p)); - if (!getAttribute(p, WorkbenchListeners.attributeStandingUp, false)) { + if (!getAttribute(p, WorkbenchListeners.ATTRIBUTE_WORKBENCH_STANDING_UP, false)) { WorkbenchListeners.standUpFromWorkbench(p); } return false; diff --git a/Server/src/main/content/global/skill/construction/decoration/StaySeated.kt b/Server/src/main/content/global/skill/construction/decoration/StaySeated.kt index 65f8b7000..bbc4cbea3 100644 --- a/Server/src/main/content/global/skill/construction/decoration/StaySeated.kt +++ b/Server/src/main/content/global/skill/construction/decoration/StaySeated.kt @@ -1,12 +1,12 @@ package content.global.skill.construction.decoration -import content.global.skill.construction.decoration.workshop.WorkbenchListeners import core.api.animate import core.api.getScenery import core.game.node.entity.Entity import core.game.node.entity.player.Player import core.game.system.timer.PersistTimer import core.game.system.timer.RSTimer +import org.rs09.consts.Animations import org.rs09.consts.Scenery import kotlin.collections.get @@ -24,8 +24,8 @@ class StaySeated : PersistTimer(10 /*ticks*/, "con:sitting", isSoft = true) { // Register new chairs and animations here private val sittables = mapOf( - Scenery.STOOL_13719 to WorkbenchListeners.animationSit, // wooden workbench stool - Scenery.STOOL_13720 to WorkbenchListeners.animationSitOak, // oak workbench stool + Scenery.STOOL_13719 to Animations.HUMAN_SEATED_POH_STOOL_4107, + Scenery.STOOL_13720 to Animations.HUMAN_SEATED_POH_OAK_STOOL_4108, ) override fun run(entity: Entity): Boolean { diff --git a/Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt b/Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt index 478152370..08d386f91 100644 --- a/Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt +++ b/Server/src/main/content/global/skill/construction/decoration/workshop/WorkbenchListeners.kt @@ -12,6 +12,8 @@ import core.game.node.entity.skill.Skills import core.game.node.item.Item import core.game.world.map.Direction import core.tools.ticksToCycles +import org.rs09.consts.Animations +import org.rs09.consts.Components import org.rs09.consts.Items import org.rs09.consts.Scenery @@ -23,21 +25,12 @@ import org.rs09.consts.Scenery class WorkbenchListeners : InteractionListener, InterfaceListener { companion object { - const val workbenchInterface = 397 - - const val attributeWorkbenchId = "con:workbench:id" - const val attributeFlatpackMode = "con:workbench:active" - const val attributeDirections = "con:workbench:directions" - const val attributeSelection = "con:workbench:hotspot" - const val attributeSitting = "con:workbench:sitting" - const val attributeStandingUp = "con:workbench:standing" - - const val animationSitDown = 4103 - const val animationStandUp = 4105 - const val animationSit = 4107 - const val animationSitOak = 4108 - const val animationCraft = 4109 - const val animationCraftOak = 4110 + const val ATTRIBUTE_FLATPACK_MODE = "con:workbench:active" + const val ATTRIBUTE_WORKBENCH_ID = "con:workbench:id" + const val ATTRIBUTE_WORKBENCH_SELECTION = "con:workbench:hotspot" + const val ATTRIBUTE_WORKBENCH_SEATED = "con:workbench:sitting" + const val ATTRIBUTE_WORKBENCH_STANDING_UP = "con:workbench:standing" + private const val ATTRIBUTE_DIRECTIONS = "con:workbench:directions" private val workbenches = intArrayOf( Scenery.WORKBENCH_13704, // lv20, wooden @@ -84,7 +77,7 @@ class WorkbenchListeners : InteractionListener, InterfaceListener { */ fun produceFlatpack(player: Player, deco: Decoration) { val reward = deco.flatpackItemID - val animation = if (getScenery(player.location)?.id == Scenery.STOOL_13720) { animationCraftOak } else { animationCraft } + val animation = if (getScenery(player.location)?.id == Scenery.STOOL_13720) { Animations.HUMAN_CRAFT_POH_OAK_STOOL_4110 } else { Animations.HUMAN_CRAFT_POH_STOOL_4109 } if (reward == -1) return if (removeItemsIfPlayerHasEnough(player, *deco.items) || player.isAdmin) { closeInterface(player) @@ -101,15 +94,15 @@ class WorkbenchListeners : InteractionListener, InterfaceListener { */ @JvmStatic fun standUpFromWorkbench(player: Player) { - val directions = getAttribute(player, attributeDirections, arrayOf(Direction.WEST, Direction.NORTH, Direction.EAST)) - val animation = if (getScenery(player.location)?.id == Scenery.STOOL_13720) { animationSitOak } else { animationSit } - setAttribute(player, attributeStandingUp, true) + val directions = getAttribute(player, ATTRIBUTE_DIRECTIONS, arrayOf(Direction.WEST, Direction.NORTH, Direction.EAST)) + val animation = if (getScenery(player.location)?.id == Scenery.STOOL_13720) { Animations.HUMAN_SEATED_POH_OAK_STOOL_4108 } else { Animations.HUMAN_SEATED_POH_STOOL_4107 } + setAttribute(player, ATTRIBUTE_WORKBENCH_STANDING_UP, true) lock(player, 1) animate(player, animation) queueScript(player, 0, QueueStrength.SOFT) { forceMove(player, player.location, player.location.transform(directions[2], 1), - 0, ticksToCycles(1), directions[2], animationStandUp) { - removeAttributes(player, attributeDirections, attributeSitting, attributeStandingUp) + 0, ticksToCycles(1), directions[2], Animations.HUMAN_STAND_POH_STOOL_4105) { + removeAttributes(player, ATTRIBUTE_DIRECTIONS, ATTRIBUTE_WORKBENCH_SEATED, ATTRIBUTE_WORKBENCH_STANDING_UP) removeTimer(player) } return@queueScript stopExecuting(player) @@ -122,12 +115,12 @@ class WorkbenchListeners : InteractionListener, InterfaceListener { * Animates the player sitting down at the workbench, and opens the workbench interface. */ on(workbenches, IntType.SCENERY, "work-at") { player, node -> - setAttribute(player, attributeWorkbenchId, node.id) + setAttribute(player, ATTRIBUTE_WORKBENCH_ID, node.id) // Skips the animation if the player is already sitting down. - if (getAttribute(player, attributeSitting, false)) { - val animation = if (getScenery(player.location)?.id == Scenery.STOOL_13720) { animationSitOak } else { animationSit } + if (getAttribute(player, ATTRIBUTE_WORKBENCH_SEATED, false)) { + val animation = if (getScenery(player.location)?.id == Scenery.STOOL_13720) { Animations.HUMAN_SEATED_POH_OAK_STOOL_4108 } else { Animations.HUMAN_SEATED_POH_STOOL_4107 } animate(player, animation) - openInterface(player, workbenchInterface) + openInterface(player, Components.POH_WORKBENCH_397) return@on true } // Ascertains the room rotation from where the stool is, to coordinate animations @@ -143,14 +136,14 @@ class WorkbenchListeners : InteractionListener, InterfaceListener { Pair(4,3) -> arrayOf(Direction.SOUTH, Direction.WEST, Direction.NORTH) else -> arrayOf(Direction.EAST, Direction.SOUTH, Direction.WEST) } - setAttribute(player, attributeDirections, directions) + setAttribute(player, ATTRIBUTE_DIRECTIONS, directions) forceMove(player, player.location, player.location.transform(directions[0], 1), - 0, ticksToCycles(1), directions[1], animationSitDown) { - val animation = if (obj.id == Scenery.STOOL_13720) { animationSitOak } else { animationSit } + 0, ticksToCycles(1), directions[1], Animations.HUMAN_SIT_POH_STOOL_4103) { + val animation = if (obj.id == Scenery.STOOL_13720) { Animations.HUMAN_SEATED_POH_OAK_STOOL_4108 } else { Animations.HUMAN_SEATED_POH_STOOL_4107 } animate(player, animation) - setAttribute(player, attributeSitting, true) + setAttribute(player, ATTRIBUTE_WORKBENCH_SEATED, true) registerTimer(player, StaySeated()) - openInterface(player, workbenchInterface) + openInterface(player, Components.POH_WORKBENCH_397) } return@on true } @@ -209,25 +202,25 @@ class WorkbenchListeners : InteractionListener, InterfaceListener { /** * Directs the player to the appropriate decoration building interface. */ - on(workbenchInterface) { player, _, _, buttonID, _, _ -> + on(Components.POH_WORKBENCH_397) { player, _, _, buttonID, _, _ -> val index = buttonID - 111 if (index < 0 || index >= decoCategories.size) return@on false val hotspot = decoCategories[index] - setAttribute(player, attributeSelection, hotspot) - setAttribute(player, attributeFlatpackMode, true) + setAttribute(player, ATTRIBUTE_WORKBENCH_SELECTION, hotspot) + setAttribute(player, ATTRIBUTE_FLATPACK_MODE, true) BuildingUtils.openBuildInterface(player, hotspot) return@on true } - onClose(workbenchInterface) { player, _ -> - if (!getAttribute(player, attributeFlatpackMode, false)) { - removeAttributes(player, attributeFlatpackMode, attributeSelection, attributeWorkbenchId) + onClose(Components.POH_WORKBENCH_397) { player, _ -> + if (!getAttribute(player, ATTRIBUTE_FLATPACK_MODE, false)) { + removeAttributes(player, ATTRIBUTE_FLATPACK_MODE, ATTRIBUTE_WORKBENCH_SELECTION, ATTRIBUTE_WORKBENCH_ID) } return@onClose true } - onClose(ConstructionInterface.decorationInterface) { player, _ -> - removeAttributes(player, attributeFlatpackMode, attributeSelection, attributeWorkbenchId) + onClose(Components.POH_DECORATION_396) { player, _ -> + removeAttributes(player, ATTRIBUTE_FLATPACK_MODE, ATTRIBUTE_WORKBENCH_SELECTION, ATTRIBUTE_WORKBENCH_ID) return@onClose true } } From e5a2a576fdb6d0cfd9ca5b33cffaf531394a1a68 Mon Sep 17 00:00:00 2001 From: Bishop Date: Sat, 1 Aug 2026 12:23:41 -0500 Subject: [PATCH 12/13] More consts --- .../construction/ConstructionInterface.kt | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/Server/src/main/content/global/skill/construction/ConstructionInterface.kt b/Server/src/main/content/global/skill/construction/ConstructionInterface.kt index 2451bf06b..21d4d0e07 100644 --- a/Server/src/main/content/global/skill/construction/ConstructionInterface.kt +++ b/Server/src/main/content/global/skill/construction/ConstructionInterface.kt @@ -18,8 +18,13 @@ import org.rs09.consts.Components class ConstructionInterface : InterfaceListener { companion object { - const val ATTRIBUTE_HOTSPOT = "con:hotspot" - const val ATTRIBUTE_HOTSPOT_OBJ = "con:hsobject" + const val ATTRIBUTE_HOTSPOT = "con:hotspot" + const val ATTRIBUTE_HOTSPOT_OBJ = "con:hsobject" + private const val DECO_BUTTON_BUILD = 132 + private const val HOUSE_BUTTON_BUILDMODE_ON = 14 + private const val HOUSE_BUTTON_BUILDMODE_OFF = 1 + private const val HOUSE_BUTTON_EXPEL_GUESTS = 15 + private const val HOUSE_BUTTON_LEAVE_HOUSE = 13 // Register furniture here when it is only obtainable by upgrading, to send the correct rejection message. val upgradeOnly = arrayOf( @@ -34,7 +39,7 @@ class ConstructionInterface : InterfaceListener { */ on(Components.POH_DECORATION_396) { player, _, _, buttonID, slot, _ -> when (buttonID) { - 132 -> { + DECO_BUTTON_BUILD -> { val hotspot = getAttribute(player, ATTRIBUTE_HOTSPOT, null) val hotspotObj = getAttribute(player, ATTRIBUTE_HOTSPOT_OBJ, null) val flatpackMode = getAttribute(player, WorkbenchListeners.ATTRIBUTE_FLATPACK_MODE, false) @@ -117,19 +122,19 @@ class ConstructionInterface : InterfaceListener { */ on(Components.POH_HOUSE_OPTIONS_398) { player, _, _, buttonID, _, _ -> when (buttonID) { - 14 -> { + HOUSE_BUTTON_BUILDMODE_ON -> { player.houseManager.toggleBuildingMode(player, true) return@on true } - 1 -> { + HOUSE_BUTTON_BUILDMODE_OFF -> { player.houseManager.toggleBuildingMode(player, false) return@on true } - 15 -> { + HOUSE_BUTTON_EXPEL_GUESTS -> { player.houseManager.expelGuests(player) return@on true } - 13 -> { + HOUSE_BUTTON_LEAVE_HOUSE -> { if (!player.houseManager.isInHouse(player)) { sendMessage(player, "You can't do this outside of your house.") return@on true From b46a57ab7862abb5cbe52ebf64ba227142614286 Mon Sep 17 00:00:00 2001 From: Bishop Date: Sat, 1 Aug 2026 12:24:22 -0500 Subject: [PATCH 13/13] More private --- .../content/global/skill/construction/ConstructionInterface.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/content/global/skill/construction/ConstructionInterface.kt b/Server/src/main/content/global/skill/construction/ConstructionInterface.kt index 21d4d0e07..3f897cfcb 100644 --- a/Server/src/main/content/global/skill/construction/ConstructionInterface.kt +++ b/Server/src/main/content/global/skill/construction/ConstructionInterface.kt @@ -27,7 +27,7 @@ class ConstructionInterface : InterfaceListener { private const val HOUSE_BUTTON_LEAVE_HOUSE = 13 // Register furniture here when it is only obtainable by upgrading, to send the correct rejection message. - val upgradeOnly = arrayOf( + private val upgradeOnly = arrayOf( Decoration.WORKBENCH_WITH_VICE, Decoration.WORKBENCH_WITH_LATHE, )