Create player buildings in memory with a single DB write

Building gets a no-arg constructor, a createBuilding factory (in the style
of Mob.createMob) and persistBuilding, which inserts the row through
building_CREATE, sets the returned UID, caches the object and runs
runAfterLoad. The GET_BUILDINGBYUUID re-select after the insert is gone.

PlaceAssetMsgHandler (createStructure, createBarracks, createWarehouse),
Bane and AddBuildingCmd move onto it.

Value changes:
- floor/level start at -1 and the other unset fields at the obj_building
  column defaults, same as the reloaded row.
- upgradeDateTime keeps milliseconds instead of the DATETIME-rounded value
  (sub-second difference in the upgrade job time).
- Warehouse placement no longer runs runAfterLoad twice, which submitted
  the warehouse upgrade job twice.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
MagicBotandClaude Opus 5.5 committed 2026-10-26 16:02:10 -04:00
1 parent 15437246ce
commit d586536c74
5 files changed
+120 -18

No files matched your search

+63
View File
@@ -32,10 +32,12 @@ import engine.net.ByteBufferWriter;
import engine.net.client.msg.ApplyBuildingEffectMsg;
import engine.net.client.msg.UpdateObjectMsg;
import engine.server.MBServerStatics;
import org.joda.time.DateTime;
import org.pmw.tinylog.Logger;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
@@ -99,6 +101,14 @@ public class Building extends AbstractWorldObject {
private ConcurrentHashMap<Integer, Condemned> condemned;
private ArrayList<Building> children = null;
/**
* No Id Constructor
*/
public Building() {
super();
}
/**
* ResultSet Constructor
*/
@@ -173,6 +183,59 @@ public class Building extends AbstractWorldObject {
}
}
// Defaults mirror the obj_building column defaults so a new building matches a reloaded one.
public static Building createBuilding(Zone parentZone, int ownerUUID, String name, int meshUUID,
Vector3fImmutable localLoc, float scale, int currentHP,
ProtectionState protectionState, int currentGold, int rank,
DateTime upgradeDate, int blueprintUUID, float w, float rotY) {
Building building = new Building();
building.setObjectTypeMask(MBServerStatics.MASK_BUILDING);
building.gridObjectType = GridObjectType.STATIC;
building.parentZoneUUID = parentZone.getObjectUUID();
building.ownerUUID = ownerUUID;
building.name = name;
building.meshUUID = meshUUID;
building.blueprintUUID = blueprintUUID;
building.statLat = localLoc.x;
building.statAlt = localLoc.y;
building.statLon = localLoc.z;
building.meshScale = new Vector3f(scale, scale, scale);
building.setHealth(currentHP);
building.protectionState = protectionState;
building._strongboxValue = currentGold;
building.maxGold = 15000000;
building.rank = rank;
building.w = w;
building.setRot(new Vector3f(0f, rotY, 0f));
building.parentBuildingID = 0;
building.floor = -1;
building.level = -1;
if (upgradeDate != null)
building.upgradeDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(upgradeDate.getMillis()), ZoneId.systemDefault());
return building;
}
// Writes a new player building once and loads it into the simulation; returns null if the insert failed.
public static Building persistBuilding(Building building) {
int objectUUID;
objectUUID = DbManager.BuildingQueries.PERSIST(building);
if (objectUUID <= 0)
return null;
building.setObjectUUID(objectUUID);
DbManager.addToCache(building);
building.runAfterLoad();
return building;
}
/*
* Getters
*/