From 35f1738ee426dd67a83430cc939625733692a835 Mon Sep 17 00:00:00 2001 From: MagicBot Date: Mon, 26 Oct 2026 19:16:53 -0400 Subject: [PATCH] Read NPC building owners once instead of per building at boot Building.runAfterLoad ran GET_UID_ENUM for every building (~47k queries). One query now reads the NPC owner IDs before the building load; runtime loads also check the NPC cache. City load reads ownerIsNPC before NPCs are cached, so a pass after the NPC load would not work. Value changes: none. ownerIsNPC is still true exactly when the owner's object.type is 'npc' (dev DB: 388 buildings, 24 owners). Co-Authored-By: Claude Opus 5.5 --- src/engine/db/handlers/dbBuildingHandler.java | 21 +++++++++++++++++++ src/engine/gameManager/BuildingManager.java | 2 ++ src/engine/objects/Building.java | 11 +++------- src/engine/server/world/WorldServer.java | 1 + 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/src/engine/db/handlers/dbBuildingHandler.java b/src/engine/db/handlers/dbBuildingHandler.java index b50b13bb..4f68e9e2 100644 --- a/src/engine/db/handlers/dbBuildingHandler.java +++ b/src/engine/db/handlers/dbBuildingHandler.java @@ -28,6 +28,7 @@ import java.time.LocalDateTime; import java.time.ZoneId; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.concurrent.ConcurrentHashMap; public class dbBuildingHandler extends dbHandlerBase { @@ -100,6 +101,26 @@ public class dbBuildingHandler extends dbHandlerBase { return buildings; } + public HashSet GET_NPC_BUILDING_OWNERS() { + + HashSet npcOwners = new HashSet<>(); + + try (Connection connection = DbManager.getConnection(); + PreparedStatement preparedStatement = connection.prepareStatement("SELECT DISTINCT `obj_building`.`ownerUUID` FROM `obj_building` INNER JOIN `object` ON `object`.`UID` = `obj_building`.`ownerUUID` WHERE `object`.`type` = 'npc';")) { + + ResultSet rs = preparedStatement.executeQuery(); + + while (rs.next()) + npcOwners.add(rs.getInt("ownerUUID")); + + } catch (SQLException e) { + Logger.error(e); + } + + Logger.info("read: " + npcOwners.size() + " NPC building owners"); + return npcOwners; + } + public Building GET_BUILDINGBYUUID(int uuid) { if (uuid == 0) diff --git a/src/engine/gameManager/BuildingManager.java b/src/engine/gameManager/BuildingManager.java index ca12d42f..0ffc3a13 100644 --- a/src/engine/gameManager/BuildingManager.java +++ b/src/engine/gameManager/BuildingManager.java @@ -31,6 +31,7 @@ import java.time.ZoneId; import java.util.ArrayList; import java.util.EnumSet; import java.util.HashMap; +import java.util.HashSet; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ThreadLocalRandom; @@ -44,6 +45,7 @@ public enum BuildingManager { public static HashMap> _buildingFriends = new HashMap<>(); public static HashMap> _buildingCondemned = new HashMap<>(); public static HashMap> _buildingPatrolPoints = new HashMap<>(); + public static HashSet _npcBuildingOwners = new HashSet<>(); public static int getAvailableSlot(Building building) { diff --git a/src/engine/objects/Building.java b/src/engine/objects/Building.java index 385e3470..15a06fe9 100644 --- a/src/engine/objects/Building.java +++ b/src/engine/objects/Building.java @@ -1027,15 +1027,10 @@ public class Building extends AbstractWorldObject { } } - // Submit upgrade job if building is currently set to rank. + // City load reads ownerIsNPC before NPCs are cached, so boot uses the owner set read ahead of buildings. - try { - DbObjectType objectType = DbManager.BuildingQueries.GET_UID_ENUM(this.ownerUUID); - this.ownerIsNPC = (objectType == DbObjectType.NPC); - } catch (Exception e) { - this.ownerIsNPC = false; - Logger.error("Failed to find Object Type for owner " + this.ownerUUID + " Location " + this.getLoc().toString()); - } + this.ownerIsNPC = BuildingManager._npcBuildingOwners.contains(this.ownerUUID) + || DbManager.inCache(GameObjectType.NPC, this.ownerUUID); // Reference friend and condemn lists from BuildingManager diff --git a/src/engine/server/world/WorldServer.java b/src/engine/server/world/WorldServer.java index d1cb41f4..2ba56676 100644 --- a/src/engine/server/world/WorldServer.java +++ b/src/engine/server/world/WorldServer.java @@ -529,6 +529,7 @@ public class WorldServer { Logger.info("Loading all Zones"); DbManager.ZoneQueries.GET_ALL_ZONES(); Logger.info("Loading all Buildings"); + BuildingManager._npcBuildingOwners = DbManager.BuildingQueries.GET_NPC_BUILDING_OWNERS(); DbManager.BuildingQueries.GET_ALL_BUILDINGS(); Logger.info("Loading all Cities"); DbManager.CityQueries.GET_ALL_CITIES();