diff --git a/src/main/NGECore.java b/src/main/NGECore.java index d68e1493..b80f8e4a 100644 --- a/src/main/NGECore.java +++ b/src/main/NGECore.java @@ -226,6 +226,7 @@ public class NGECore { private ObjectDatabase guildODB; private ObjectDatabase objectIdODB; private ObjectDatabase duplicateIdODB; + private ObjectDatabase reusableIdODB; private ObjectDatabase chatRoomODB; private BusConfiguration eventBusConfig = BusConfiguration.Default(1, new ThreadPoolExecutor(1, 4, 1, TimeUnit.MINUTES, new LinkedBlockingQueue())); @@ -321,6 +322,7 @@ public class NGECore { guildODB = new ObjectDatabase("guild", true, true, true, GuildObject.class); objectIdODB = new ObjectDatabase("oids", true, true, true, ObjectId.class); duplicateIdODB = new ObjectDatabase("doids", true, true, true, DuplicateId.class); + reusableIdODB = new ObjectDatabase("reusableIds", true, true, true, ObjectId.class); chatRoomODB = new ObjectDatabase("chatRooms", true, true, true, ChatRoom.class); resourceHistoryODB = new ObjectDatabase("resourcehistory", true, true, true, GalacticResource.class); auctionODB = new ObjectDatabase("auction", true, true, true, AuctionItem.class); @@ -716,6 +718,10 @@ public class NGECore { return duplicateIdODB; } + public ObjectDatabase getReusableIdODB() { + return reusableIdODB; + } + public ObjectDatabase getChatRoomODB() { return chatRoomODB; } @@ -858,6 +864,7 @@ public class NGECore { resourceHistoryODB.close(); objectIdODB.close(); duplicateIdODB.close(); + reusableIdODB.close(); auctionODB.close(); cityODB.close(); } diff --git a/src/services/StaticService.java b/src/services/StaticService.java index 62b0ad61..e49c3904 100644 --- a/src/services/StaticService.java +++ b/src/services/StaticService.java @@ -140,7 +140,8 @@ public class StaticService implements INetworkDispatch { } //long objectId = core.objectService.getDOId(planetName, template, 0, buildingId, cellNumber, x, y, z); - long objectId = 0; + long objectId = core.objectService.getReusableId(); + //long objectId = 0; SWGObject object = null; MobileTemplate mobileTemplate = core.spawnService.getMobileTemplate(template); diff --git a/src/services/object/ObjectService.java b/src/services/object/ObjectService.java index 4f1e214e..785e0e63 100644 --- a/src/services/object/ObjectService.java +++ b/src/services/object/ObjectService.java @@ -36,6 +36,7 @@ import java.util.List; import java.util.Map; import java.util.Random; import java.util.Set; +import java.util.TreeSet; import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; @@ -152,6 +153,8 @@ public class ObjectService implements INetworkDispatch { private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); protected final Object objectMutex = new Object(); private List loadServerTemplateTasks = Collections.synchronizedList(new ArrayList()); + private int iteratedReusedIds = 0; + private List reusableIds = Collections.synchronizedList(new ArrayList()); public ObjectService(final NGECore core) { this.core = core; @@ -202,6 +205,12 @@ public class ObjectService implements INetworkDispatch { objectList.put(object.getObjectID(), object); } + cursor = core.getReusableIdODB().getCursor(); + + while (cursor.hasNext()) { + reusableIds.add(((ObjectId) cursor.next()).objectId); + } + loadBuildings(); System.out.println("Finished loading objects."); } @@ -788,16 +797,98 @@ public class ObjectService implements INetworkDispatch { long objectId = 0; - if (core.getDuplicateIdODB().contains(key)) { - objectId = ((DuplicateId) core.getDuplicateIdODB().get(key)).getObjectId(); + boolean containsKey; + + synchronized(objectMutex) { + containsKey = core.getDuplicateIdODB().contains(key); + } + + if (containsKey) { + synchronized(objectMutex) { + objectId = ((DuplicateId) core.getDuplicateIdODB().get(key)).getObjectId(); + } + + if (objectList.containsKey(objectId)) { + System.err.println("Warning: DOId already in use. Using one from reusableId pool instead."); + return getReusableId(); + } } else { - objectId = generateObjectID(); - core.getDuplicateIdODB().put(key, new DuplicateId(key, objectId)); + while (true) { + objectId = generateObjectID(); + + synchronized(objectMutex) { + if (!core.getObjectIdODB().contains(objectId)) { + core.getObjectIdODB().put(objectId, new ObjectId(objectId)); + } else { + System.err.println("Error: Generated objectId is already in objectIdODB?"); + System.err.println("Trying again..."); + continue; + } + + if (objectList.containsKey(objectId)) { + System.err.println("Error: Generated objectId is already in objectList?"); + System.err.println("Trying again..."); + continue; + } + } + + break; + } + + synchronized(objectMutex) { + core.getDuplicateIdODB().put(key, new DuplicateId(key, objectId)); + } } return objectId; } - + + public long getReusableId() { + long objectId = 0; + + synchronized(objectMutex) { + objectId = reusableIds.iterator().next(); + + while (objectList.containsKey(objectId) && iteratedReusedIds++ < reusableIds.size()) { + objectId = reusableIds.get(iteratedReusedIds); + } + + if (objectList.containsKey(objectId)) { + objectId = 0; + } + } + + if (objectId == 0) { + while (true) { + objectId = generateObjectID(); + + synchronized(objectMutex) { + if (!core.getObjectIdODB().contains(objectId)) { + core.getObjectIdODB().put(objectId, new ObjectId(objectId)); + } else { + System.err.println("Error: Generated objectId is already in objectIdODB?"); + System.err.println("Trying again..."); + continue; + } + + if (objectList.containsKey(objectId)) { + System.err.println("Error: Generated objectId is already in objectList?"); + System.err.println("Trying again..."); + continue; + } + + core.getReusableIdODB().put(objectId, new ObjectId(objectId)); + reusableIds.add(objectId); + iteratedReusedIds++; + + break; + } + } + } + + return objectId; + } + public Vector getItemsInContainerByStfName(CreatureObject creature, long containerId, String stfName) { Vector itemList = new Vector(); SWGObject container = getObject(containerId); @@ -1080,6 +1171,10 @@ public class ObjectService implements INetworkDispatch { } } + creature.setIntendedTarget(0); + + creature.setLookAtTarget(0); + PlayerObject ghost = (PlayerObject) creature.getSlottedObject("ghost"); if (ghost == null) {