From 70ea9b3bc93b4bcedc701e0a93d0416efaec220e Mon Sep 17 00:00:00 2001 From: MagicBot Date: Tue, 20 Oct 2026 07:37:54 -0400 Subject: [PATCH] Move the vendor mod table off the legacy item template LOAD_TEMPLATE_MODTABLES now returns a templateID -> modTable map that ForgeManager owns (vendorModTables). ForgeManager.forgeItem, WorkOrder validation and the ManageNPCMsg forge item list read it through ForgeManager.getVendorModTable(), and ItemTemplate.modTable is removed. Values are unchanged: static_vendor_items has 5089 rows, one per templateID, all present in static_item_templates, modTable 0-30. Templates not in the table still read 0. The old loader stopped at the first templateID missing from ItemTemplate.templates; there are none. No comparator added or removed. Co-Authored-By: Claude Opus 5.5 --- src/engine/db/handlers/dbItemHandler.java | 14 +++++++------- src/engine/gameManager/ForgeManager.java | 17 ++++++++++++----- src/engine/loot/WorkOrder.java | 2 +- src/engine/net/client/msg/ManageNPCMsg.java | 9 +++++---- src/engine/objects/ItemTemplate.java | 1 - src/engine/server/world/WorldServer.java | 4 ++-- 6 files changed, 27 insertions(+), 20 deletions(-) diff --git a/src/engine/db/handlers/dbItemHandler.java b/src/engine/db/handlers/dbItemHandler.java index 4708e655..ffd16640 100644 --- a/src/engine/db/handlers/dbItemHandler.java +++ b/src/engine/db/handlers/dbItemHandler.java @@ -201,23 +201,23 @@ public class dbItemHandler extends dbHandlerBase { } } - public void LOAD_TEMPLATE_MODTABLES() { + public HashMap LOAD_TEMPLATE_MODTABLES() { + + HashMap modTables = new HashMap<>(); try (Connection connection = DbManager.getConnection(); PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM `static_vendor_items`;"); ResultSet rs = preparedStatement.executeQuery()) { - while (rs.next()) { - int templateID = rs.getInt("templateID"); - int modTable = rs.getInt("modTable"); - ItemTemplate template = ItemTemplate.templates.get(templateID); - template.modTable = modTable; - } + while (rs.next()) + modTables.put(rs.getInt("templateID"), rs.getInt("modTable")); } catch (Exception e) { Logger.error(e); } + Logger.info("read: " + modTables.size()); + return modTables; } public Item GET_ITEM(final int itemUUID) { diff --git a/src/engine/gameManager/ForgeManager.java b/src/engine/gameManager/ForgeManager.java index 08e19fcb..39f7a250 100644 --- a/src/engine/gameManager/ForgeManager.java +++ b/src/engine/gameManager/ForgeManager.java @@ -49,6 +49,9 @@ public enum ForgeManager implements Runnable { public static final ConcurrentHashMap> vendorWorkOrderLookup = new ConcurrentHashMap<>(); public static final ConcurrentHashMap itemWorkOrderLookup = new ConcurrentHashMap<>(); + // Server-only data from static_vendor_items; the client templates have no mod table. + public static HashMap vendorModTables = new HashMap<>(); + public static void start() { Thread forgeManager; @@ -248,8 +251,8 @@ public enum ForgeManager implements Runnable { // Create new virtual item from specified template - ItemTemplate template = ItemTemplate.templates.get(workOrder.templateID); Item forgedItem = new Item(workOrder.templateID); + int modTable = getVendorModTable(workOrder.templateID); // forgedItem gets a negative id; a virtual item which is not persisted @@ -264,13 +267,13 @@ public enum ForgeManager implements Runnable { // Assign a prefix and suffix to this item if random rolled - if (workOrder.prefixToken == 0 && workOrder.vendor.getItemModTable().contains((template.modTable))) - forgedItem.prefixToken = calcRandomMod(workOrder.vendor, mbEnums.ItemModType.PREFIX, template.modTable); + if (workOrder.prefixToken == 0 && workOrder.vendor.getItemModTable().contains(modTable)) + forgedItem.prefixToken = calcRandomMod(workOrder.vendor, mbEnums.ItemModType.PREFIX, modTable); else forgedItem.prefixToken = workOrder.prefixToken; - if (workOrder.suffixToken == 0 && workOrder.vendor.getItemModTable().contains((template.modTable))) - forgedItem.suffixToken = calcRandomMod(workOrder.vendor, mbEnums.ItemModType.SUFFIX, template.modTable); + if (workOrder.suffixToken == 0 && workOrder.vendor.getItemModTable().contains(modTable)) + forgedItem.suffixToken = calcRandomMod(workOrder.vendor, mbEnums.ItemModType.SUFFIX, modTable); else forgedItem.suffixToken = workOrder.suffixToken; @@ -364,6 +367,10 @@ public enum ForgeManager implements Runnable { DbManager.WarehouseQueries.WRITE_WORKORDER(workOrder); } + public static int getVendorModTable(int templateID) { + return vendorModTables.getOrDefault(templateID, 0); + } + public static int calcRandomMod(NPC vendor, mbEnums.ItemModType itemModType, int modTable) { // Random prefix or suffix token based on item.template.modtable diff --git a/src/engine/loot/WorkOrder.java b/src/engine/loot/WorkOrder.java index 798e05b8..6deaedc7 100644 --- a/src/engine/loot/WorkOrder.java +++ b/src/engine/loot/WorkOrder.java @@ -136,7 +136,7 @@ public class WorkOrder implements Delayed { return 30; //30: That person cannot carry that item if ((workOrder.prefixToken != 0 || workOrder.suffixToken != 0) && - !workOrder.vendor.getItemModTable().contains((template.modTable))) + !workOrder.vendor.getItemModTable().contains(ForgeManager.getVendorModTable(workOrder.templateID))) return 59; //59: This hireling does not have this formula if (!Warehouse.calcCostOverrun(workOrder).isEmpty()) diff --git a/src/engine/net/client/msg/ManageNPCMsg.java b/src/engine/net/client/msg/ManageNPCMsg.java index b6bb09a4..30827499 100644 --- a/src/engine/net/client/msg/ManageNPCMsg.java +++ b/src/engine/net/client/msg/ManageNPCMsg.java @@ -421,16 +421,17 @@ public class ManageNPCMsg extends ClientNetMsg { for (int templateID : rollableSet) { ItemTemplate template = ItemTemplate.templates.get(templateID); + int modTable = ForgeManager.getVendorModTable(templateID); writer.put((byte) 1); writer.putInt(0); writer.putInt(templateID); //itemID writer.putInt(template.cacheTemplate.getItemValue()); writer.putInt(600); writer.put((byte) 1); - writer.put((byte) template.modTable); - writer.put((byte) template.modTable); - writer.put((byte) template.modTable); - writer.put((byte) template.modTable);//EffectItemType + writer.put((byte) modTable); + writer.put((byte) modTable); + writer.put((byte) modTable); + writer.put((byte) modTable);//EffectItemType } ArrayList cooking = NPCManager.getAllCookingForVendor(npc); diff --git a/src/engine/objects/ItemTemplate.java b/src/engine/objects/ItemTemplate.java index d1f22766..a78d7eb1 100644 --- a/src/engine/objects/ItemTemplate.java +++ b/src/engine/objects/ItemTemplate.java @@ -101,7 +101,6 @@ public class ItemTemplate { // engine.parsers.objects.RuneTemplate keeps the full list. public final HashMap item_power_action = new HashMap<>(); public final HashMap item_resource_cost = new HashMap<>(); - public int modTable; public int deed_type; public int deed_furniture_id; public int deed_target_id; diff --git a/src/engine/server/world/WorldServer.java b/src/engine/server/world/WorldServer.java index 955973c1..be954b42 100644 --- a/src/engine/server/world/WorldServer.java +++ b/src/engine/server/world/WorldServer.java @@ -307,8 +307,8 @@ public class WorldServer { Logger.info("Loading Item Templates"); DbManager.ItemQueries.LOAD_ITEM_TEMPLATES(); - Logger.info("Back fill template modTables"); - DbManager.ItemQueries.LOAD_TEMPLATE_MODTABLES(); + Logger.info("Loading vendor modTables"); + ForgeManager.vendorModTables = DbManager.ItemQueries.LOAD_TEMPLATE_MODTABLES(); Logger.info("Loading Deed Templates"); DeedTemplate._deeds = DeedParser.parseDeedFolder();