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 <noreply@anthropic.com>
This commit is contained in:
MagicBotandClaude Opus 5.5 committed 2026-10-26 19:16:53 -04:00
1 parent 015d536337
commit 35f1738ee4
4 files changed
+27 -8

No files matched your search

@@ -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<Integer> GET_NPC_BUILDING_OWNERS() {
HashSet<Integer> 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)
@@ -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<Integer, ConcurrentHashMap<Integer, BuildingFriends>> _buildingFriends = new HashMap<>();
public static HashMap<Integer, ConcurrentHashMap<Integer, Condemned>> _buildingCondemned = new HashMap<>();
public static HashMap<Integer, ArrayList<Vector3fImmutable>> _buildingPatrolPoints = new HashMap<>();
public static HashSet<Integer> _npcBuildingOwners = new HashSet<>();
public static int getAvailableSlot(Building building) {
+3 -8
View File
@@ -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
+1
View File
@@ -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();