diff --git a/src/main/NGECore.java b/src/main/NGECore.java index b58a3922..678fee1b 100644 --- a/src/main/NGECore.java +++ b/src/main/NGECore.java @@ -377,8 +377,9 @@ public class NGECore { objectService.loadBuildings(); terrainService.loadSnapShotObjects(); + objectService.loadServerTemplates(); simulationService.insertSnapShotObjects(); - + simulationService.insertPersistentBuildings(); // Zone services that need to be loaded after the above zoneDispatch.addService(simulationService); diff --git a/src/services/PlayerService.java b/src/services/PlayerService.java index 1e0874cb..764e4c7e 100644 --- a/src/services/PlayerService.java +++ b/src/services/PlayerService.java @@ -566,7 +566,7 @@ public class PlayerService implements INetworkDispatch { try { - for (SWGObject equipment : creature.getEquipmentList()) { + for (SWGObject equipment : new ArrayList(creature.getEquipmentList())) { if (equipment == null) { continue; } diff --git a/src/services/SimulationService.java b/src/services/SimulationService.java index 37b706aa..5acb77dd 100644 --- a/src/services/SimulationService.java +++ b/src/services/SimulationService.java @@ -42,6 +42,8 @@ import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; +import com.sleepycat.persist.EntityCursor; + import engine.clientdata.ClientFileManager; import engine.clientdata.visitors.MeshVisitor; import engine.clientdata.visitors.PortalVisitor; @@ -58,7 +60,6 @@ import engine.resources.scene.Quaternion; import engine.resources.scene.quadtree.QuadTree; import engine.resources.service.INetworkDispatch; import engine.resources.service.INetworkRemoteEvent; - import protocol.swg.ChatFriendsListUpdate; import protocol.swg.ChatOnChangeFriendStatus; import protocol.swg.ChatOnGetFriendsList; @@ -71,7 +72,6 @@ import protocol.swg.UpdateTransformWithParentMessage; import protocol.swg.objectControllerObjects.DataTransform; import protocol.swg.objectControllerObjects.DataTransformWithParent; import protocol.swg.objectControllerObjects.TargetUpdate; - import resources.objects.building.BuildingObject; import resources.objects.cell.CellObject; import resources.objects.creature.CreatureObject; @@ -170,11 +170,27 @@ public class SimulationService implements INetworkDispatch { public void insertSnapShotObjects() { List objectList = new ArrayList(core.objectService.getObjectList().values()); for(SWGObject obj : objectList) { - if(obj.getParentId() == 0 && obj.isInSnapshot()) + if(obj.getParentId() == 0 && (obj.isInSnapshot() || obj.getAttachment("isBuildout") != null)) add(obj, obj.getPosition().x, obj.getPosition().z); } } + public void insertPersistentBuildings() { + EntityCursor cursor = core.getBuildingODB().getCursor(Long.class, BuildingObject.class); + + Iterator it = cursor.iterator(); + + while(it.hasNext()) { + final BuildingObject building = (BuildingObject) core.objectService.getObject(it.next().getObjectID()); + if(building == null) + continue; + if(building.getAttachment("hasLoadedServerTemplate") == null) + core.objectService.loadServerTemplate(building); + add(building, building.getPosition().x, building.getPosition().z); + } + } + + public void addCollidable(AbstractCollidable collidable, float x, float y) { collidableQuadTrees.get(collidable.getPlanet().getName()).put(x, y, collidable); } @@ -198,7 +214,7 @@ public class SimulationService implements INetworkDispatch { Vector childObjects = (Vector) object.getAttachment("childObjects"); if(childObjects != null) { addChildObjects(object, childObjects); - //object.setAttachment("childObjects", null); + object.setAttachment("childObjects", null); } if(notifyObservers) { Point3D pos = new Point3D(x, 0, y); diff --git a/src/services/combat/CombatService.java b/src/services/combat/CombatService.java index c2498f8b..076f8fd1 100644 --- a/src/services/combat/CombatService.java +++ b/src/services/combat/CombatService.java @@ -21,6 +21,7 @@ ******************************************************************************/ package services.combat; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Random; @@ -186,7 +187,7 @@ public class CombatService implements INetworkDispatch { CreatureObject creature = (CreatureObject)target; if(creature.getPosture() == Posture.Incapacitated || creature.getPosture() == Posture.Dead) { - for (TangibleObject defender : creature.getDefendersList()) + for (TangibleObject defender : new ArrayList(creature.getDefendersList())) { defender.removeDefender(creature); creature.removeDefender(defender); diff --git a/src/services/object/ObjectService.java b/src/services/object/ObjectService.java index 94fcc924..49eaf863 100644 --- a/src/services/object/ObjectService.java +++ b/src/services/object/ObjectService.java @@ -113,6 +113,7 @@ public class ObjectService implements INetworkDispatch { private Map serverTemplates = new ConcurrentHashMap(); private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); protected final Object objectMutex = new Object(); + private List loadServerTemplateTasks = Collections.synchronizedList(new ArrayList()); public ObjectService(final NGECore core) { this.core = core; @@ -168,17 +169,24 @@ public class ObjectService implements INetworkDispatch { } }); - loadServerTemplate(building); - core.simulationService.add(building, building.getPosition().x, building.getPosition().z); } } - - public SWGObject createObject(String Template, long objectID, Planet planet, Point3D position, Quaternion orientation, String customServerTemplate) { - return createObject(Template, objectID, planet, position, orientation, customServerTemplate, false); + + public void loadServerTemplates() { + System.out.println("Loading server templates..."); + for(Runnable r : loadServerTemplateTasks) { + r.run(); + } + loadServerTemplateTasks.clear(); + System.out.println("Finished loading server templates..."); } - public SWGObject createObject(String Template, long objectID, Planet planet, Point3D position, Quaternion orientation, String customServerTemplate, boolean overrideSnapshot) { + public SWGObject createObject(String Template, long objectID, Planet planet, Point3D position, Quaternion orientation, String customServerTemplate) { + return createObject(Template, objectID, planet, position, orientation, customServerTemplate, false, true); + } + + public SWGObject createObject(String Template, long objectID, Planet planet, Point3D position, Quaternion orientation, String customServerTemplate, boolean overrideSnapshot, boolean loadServerTemplate) { SWGObject object = null; CrcStringTableVisitor crcTable; try { @@ -266,7 +274,12 @@ public class ObjectService implements INetworkDispatch { if(!core.getObjectIdODB().contains(objectID, Long.class, ObjectId.class)) { core.getObjectIdODB().put(new ObjectId(objectID), Long.class, ObjectId.class); } - loadServerTemplate(object); + if(loadServerTemplate) + loadServerTemplate(object); + else { + final SWGObject pointer = object; + loadServerTemplateTasks.add(() -> loadServerTemplate(pointer)); + } objectList.put(objectID, object); @@ -331,6 +344,7 @@ public class ObjectService implements INetworkDispatch { } catch (IOException e) { System.out.println("!IO error " + template.toString()); } + object.setAttachment("hasLoadedServerTemplate", new Boolean(true)); } public SWGObject createObject(String Template, Planet planet) { @@ -705,7 +719,7 @@ public class ObjectService implements INetworkDispatch { // This is done for buildouts; uncertain about snapshot objects so it's commented for now //long objectId = Delta.createBuffer(8).putInt(chunk.id).putInt(0xF986FFFF).flip().getLong(); // Not sure what extension they add to 4-byte-only snapshot objectIds. With buildouts they add 0xFFFF86F9. This is demonstated in the packet sent to the server when you /target client-spawned objects int objectId = chunk.id; - SWGObject obj = createObject(visitor.getName(chunk.nameId), objectId, planet, new Point3D(chunk.xPosition, chunk.yPosition, chunk.zPosition), new Quaternion(chunk.orientationW, chunk.orientationX, chunk.orientationY, chunk.orientationZ)); + SWGObject obj = createObject(visitor.getName(chunk.nameId), objectId, planet, new Point3D(chunk.xPosition, chunk.yPosition, chunk.zPosition), new Quaternion(chunk.orientationW, chunk.orientationX, chunk.orientationY, chunk.orientationZ), null, false, false); if(obj != null) { obj.setContainerPermissions(WorldPermissions.WORLD_PERMISSIONS); obj.setisInSnapshot(true); @@ -891,7 +905,7 @@ public class ObjectService implements INetworkDispatch { if(objectId != 0 && containerId == 0) { if(portalCRC != 0) { containers.add(objectId); - object = createObject(template, objectId, planet, new Point3D(px + x1, py, pz + z1), new Quaternion(qw, qx, qy, qz), null, true); + object = createObject(template, objectId, planet, new Point3D(px + x1, py, pz + z1), new Quaternion(qw, qx, qy, qz), null, true, false); object.setAttachment("childObjects", null); if (!duplicate.containsValue(objectId)) { ((BuildingObject) object).createTransaction(core.getBuildingODB().getEnvironment()); @@ -899,7 +913,7 @@ public class ObjectService implements INetworkDispatch { ((BuildingObject) object).getTransaction().commitSync(); } } else { - object = createObject(template, objectId, planet, new Point3D(px + x1, py, pz + z1), new Quaternion(qw, qx, qy, qz)); + object = createObject(template, objectId, planet, new Point3D(px + x1, py, pz + z1), new Quaternion(qw, qx, qy, qz), null, false, false); } if(object == null) continue; @@ -908,7 +922,7 @@ public class ObjectService implements INetworkDispatch { object.setAttachment("bigSpawnRange", new Boolean(true)); quadtreeObjects.add(object); } else if(containerId != 0) { - object = createObject(template, 0, planet, new Point3D(px, py, pz), new Quaternion(qw, qx, qy, qz)); + object = createObject(template, 0, planet, new Point3D(px, py, pz), new Quaternion(qw, qx, qy, qz), null, false, false); if(containers.contains(containerId)) { object.setContainerPermissions(WorldPermissions.WORLD_PERMISSIONS); object.setisInSnapshot(false); @@ -926,20 +940,22 @@ public class ObjectService implements INetworkDispatch { parent.add(object); } } else { - object = createObject(template, 0, planet, new Point3D(px + x1, py, pz + z1), new Quaternion(qw, qx, qy, qz)); + object = createObject(template, 0, planet, new Point3D(px + x1, py, pz + z1), new Quaternion(qw, qx, qy, qz), null, false, false); object.setContainerPermissions(WorldPermissions.WORLD_PERMISSIONS); quadtreeObjects.add(object); } //System.out.println("Spawning: " + template + " at: X:" + object.getPosition().x + " Y: " + object.getPosition().y + " Z: " + object.getPosition().z); - + if(object != null) + object.setAttachment("isBuildout", new Boolean(true)); } } - for(SWGObject obj : quadtreeObjects) { + // this might load stuff before snapshots of other planets are finished + /*for(SWGObject obj : quadtreeObjects) { core.simulationService.add(obj, obj.getPosition().x, obj.getPosition().z); - } + }*/ }