diff --git a/src/engine/db/handlers/dbZoneHandler.java b/src/engine/db/handlers/dbZoneHandler.java index af0db2ad..7723514c 100644 --- a/src/engine/db/handlers/dbZoneHandler.java +++ b/src/engine/db/handlers/dbZoneHandler.java @@ -44,6 +44,23 @@ public class dbZoneHandler extends dbHandlerBase { return zoneList; } + public ArrayList GET_PLAYER_CITY_ZONES() { + + ArrayList zoneList = new ArrayList<>(); + + try (Connection connection = DbManager.getConnection(); + PreparedStatement preparedStatement = connection.prepareStatement("SELECT `obj_zone`.*, `object`.`parent` FROM `object` INNER JOIN `obj_zone` ON `obj_zone`.`UID` = `object`.`UID` WHERE `obj_zone`.`template` = 0 ORDER BY `object`.`UID` ASC;")) { + + ResultSet rs = preparedStatement.executeQuery(); + zoneList = getObjectsFromRs(rs, 200); + + } catch (SQLException e) { + Logger.error(e); + } + + return zoneList; + } + public Zone GET_BY_UID(long ID) { Zone zone = (Zone) DbManager.getFromCache(mbEnums.GameObjectType.Zone, (int) ID); diff --git a/src/engine/gameManager/ZoneManager.java b/src/engine/gameManager/ZoneManager.java index 5653c0c1..9f112a81 100644 --- a/src/engine/gameManager/ZoneManager.java +++ b/src/engine/gameManager/ZoneManager.java @@ -17,7 +17,9 @@ import engine.mbEnums; import engine.objects.Building; import engine.objects.City; import engine.objects.Zone; +import engine.parsers.map.ZoneTreeParser; import engine.parsers.objects.CZoneTemplate; +import engine.parsers.objects.ZoneTreeEntry; import engine.server.MBServerStatics; import org.pmw.tinylog.Logger; @@ -74,6 +76,55 @@ public enum ZoneManager { Logger.info("Zone templates: " + _zone_templates.size()); } + // Static zones from the map's zone tree, then player-city zones from the DB. False aborts boot. + + public static boolean loadZones(int mapID) { + + ArrayList zoneTree; + ArrayList cityZones; + Zone zone; + int staticCount = 0; + boolean templatesMissing = false; + + zoneTree = ZoneTreeParser.parseZoneTree(mapID); + + if (zoneTree == null) + return false; + + for (ZoneTreeEntry treeEntry : zoneTree) + if (!treeEntry.isPlayerCity && !_zone_templates.containsKey(treeEntry.template)) { + Logger.error("Zone " + treeEntry.uid + " (" + treeEntry.name + ") has no CZONE template " + treeEntry.template); + templatesMissing = true; + } + + if (templatesMissing) + return false; + + // Player-city zones in the tree are a recording's cities; the live ones come from the DB + + for (ZoneTreeEntry treeEntry : zoneTree) { + + if (treeEntry.isPlayerCity) + continue; + + if (treeEntry.parent != 0 && getZoneByUUID(treeEntry.parent) == null) { + Logger.error("Zone " + treeEntry.uid + " (" + treeEntry.name + ") has no parent zone " + treeEntry.parent); + return false; + } + + zone = Zone.createStaticZone(treeEntry); + DbManager.addToCache(zone); + zone.runAfterLoad(); + staticCount++; + } + + cityZones = DbManager.ZoneQueries.GET_PLAYER_CITY_ZONES(); + + Logger.info("Zones: " + staticCount + " static, " + cityZones.size() + " player city"); + + return true; + } + // Find all zones coordinates fit into, starting with Sea Floor public static ArrayList getAllZonesIn(final Vector3fImmutable loc) { diff --git a/src/engine/objects/Zone.java b/src/engine/objects/Zone.java index 725bb00a..e199ffe1 100644 --- a/src/engine/objects/Zone.java +++ b/src/engine/objects/Zone.java @@ -18,6 +18,7 @@ import engine.math.Vector3fImmutable; import engine.mbEnums; import engine.net.ByteBufferWriter; import engine.parsers.objects.CZoneTemplate; +import engine.parsers.objects.ZoneTreeEntry; import engine.server.MBServerStatics; import org.pmw.tinylog.Logger; @@ -34,20 +35,24 @@ public class Zone extends AbstractWorldObject { public final Set zoneNPCSet = Collections.newSetFromMap(new ConcurrentHashMap<>()); public final Set zoneMobSet = Collections.newSetFromMap(new ConcurrentHashMap<>()); + // Server-only hotzone range for zones with icons; no client data carries zone levels + public static final int MACRO_ZONE_MIN_LEVEL = 30; + public static final int MACRO_ZONE_MAX_LEVEL = 60; + public CZoneTemplate template; - public final int playerCityUUID; - public final String zoneName; + public int playerCityUUID; + public String zoneName; public float major_radius; public float minor_radius; - public final float xOffset; - public final float zOffset; - public final float yOffset; - public final int templateID; - public final byte peace_zone; - public final String icon1; - public final String icon2; - public final String icon3; + public float xOffset; + public float zOffset; + public float yOffset; + public int templateID; + public byte peace_zone; + public String icon1; + public String icon2; + public String icon3; public float absX = 0.0f; public float absY = 0.0f; public float absZ = 0.0f; @@ -66,6 +71,13 @@ public class Zone extends AbstractWorldObject { public Terrain terrain = null; + /** + * No Id Constructor + */ + public Zone() { + super(); + } + /** * ResultSet Constructor */ @@ -98,6 +110,36 @@ public class Zone extends AbstractWorldObject { } + // Static zones keep their positive tree UIDs until the W10 switch to negative IDs + public static Zone createStaticZone(ZoneTreeEntry treeEntry) { + + Zone zone = new Zone(); + + zone.setObjectUUID(treeEntry.uid); + zone.setStaticWorldObject(true); + zone.parentZoneID = treeEntry.parent; + zone.templateID = treeEntry.template; + zone.zoneName = treeEntry.name; + zone.peace_zone = treeEntry.peaceZone ? (byte) 1 : (byte) 0; + zone.xOffset = treeEntry.offset.x; + zone.yOffset = treeEntry.offset.y; + zone.zOffset = treeEntry.offset.z; + zone.playerCityUUID = 0; + zone.guild_zone = false; + zone.icon1 = treeEntry.terrain; + zone.icon2 = treeEntry.biome; + zone.icon3 = treeEntry.height; + + if (!zone.icon1.isEmpty()) { + zone.min_level = MACRO_ZONE_MIN_LEVEL; + zone.max_level = MACRO_ZONE_MAX_LEVEL; + } + + zone.hash = DataWarehouse.hasher.encrypt(zone.getObjectUUID()); + + return zone; + } + public static void serializeForClientMsg(Zone zone, ByteBufferWriter writer) { if (zone.templateID == 0 && zone.playerCityUUID == 0) diff --git a/src/engine/server/world/WorldServer.java b/src/engine/server/world/WorldServer.java index 18d7a29f..4482d7a7 100644 --- a/src/engine/server/world/WorldServer.java +++ b/src/engine/server/world/WorldServer.java @@ -536,7 +536,12 @@ public class WorldServer { long start = System.currentTimeMillis(); Logger.info("Loading all Zones"); - DbManager.ZoneQueries.GET_ALL_ZONES(); + + if (!ZoneManager.loadZones(worldMapID)) { + Logger.error("ABORT! Zone tree failed to load!"); + exit(1); + } + Logger.info("Loading all Buildings"); BuildingManager._npcBuildingOwners = DbManager.BuildingQueries.GET_NPC_BUILDING_OWNERS(); DbManager.BuildingQueries.GET_ALL_BUILDINGS();