Build static zones from the zone tree at world server boot
ZoneManager.loadZones builds the 1,062 static zones from maps/<MB_WORLD_MAPID>.tree through Zone.createStaticZone, flagged static and keeping their positive tree UIDs (negative IDs come with W10 in 2.4). Player-city zones still load from obj_zone (template 0). Boot aborts on a missing tree file, a missing CZONE template or a missing parent. GET_ALL_ZONES is kept until the removal task. Value changes vs obj_zone (parity: scripts/task14_zone_parity.py): - 44 zones: x/z offsets take the live values; obj_zone had them rounded to whole units (e.g. 279: 192.0 -> 192.48, 274: -238.0 -> -237.653). - Static zones no longer write their hash to obj_zone at boot; the hash is computed in memory (same value). - min/max level 30/60 for the 50 icon zones now comes from constants (no client data carries zone levels); same values as obj_zone. Everything else identical: parent (except the unused root parent), template, name, peace flag, y offset, icons. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
f7b81f46a5
commit
c66ce6e777
4 files changed
+126
-11
No files matched your search
@@ -44,6 +44,23 @@ public class dbZoneHandler extends dbHandlerBase {
|
||||
return zoneList;
|
||||
}
|
||||
|
||||
public ArrayList<Zone> GET_PLAYER_CITY_ZONES() {
|
||||
|
||||
ArrayList<Zone> 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);
|
||||
|
||||
@@ -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<ZoneTreeEntry> zoneTree;
|
||||
ArrayList<Zone> 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<Zone> getAllZonesIn(final Vector3fImmutable loc) {
|
||||
|
||||
@@ -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<NPC> zoneNPCSet = Collections.newSetFromMap(new ConcurrentHashMap<>());
|
||||
public final Set<Mob> 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)
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in new issue
Block a user