diff --git a/src/intents/object/ObjectIdRequestIntent.java b/src/intents/object/ObjectIdRequestIntent.java deleted file mode 100644 index 784b64c4..00000000 --- a/src/intents/object/ObjectIdRequestIntent.java +++ /dev/null @@ -1,54 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 /// Project SWG /// www.projectswg.com - * - * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on - * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. - * Our goal is to create an emulator which will provide a server for players to - * continue playing a game similar to the one they used to play. We are basing - * it on the final publish of the game prior to end-game events. - * - * This file is part of Holocore. - * - * -------------------------------------------------------------------------------- - * - * Holocore is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * Holocore is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Holocore. If not, see - ******************************************************************************/ - -package intents.object; - -import resources.control.Intent; - -/** - * Created by Waverunner on 8/19/2015 - */ -public class ObjectIdRequestIntent extends Intent { - public static final String TYPE = "ObjectIdRequestIntent"; - - private String identifier; - private int amount; - - public ObjectIdRequestIntent(String identifier, int amount) { - super(TYPE); - this.identifier = identifier; - this.amount = amount; - } - - public String getIdentifier() { - return identifier; - } - - public int getAmount() { - return amount; - } -} \ No newline at end of file diff --git a/src/intents/object/ObjectIdResponseIntent.java b/src/intents/object/ObjectIdResponseIntent.java deleted file mode 100644 index 6799adec..00000000 --- a/src/intents/object/ObjectIdResponseIntent.java +++ /dev/null @@ -1,56 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 /// Project SWG /// www.projectswg.com - * - * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on - * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. - * Our goal is to create an emulator which will provide a server for players to - * continue playing a game similar to the one they used to play. We are basing - * it on the final publish of the game prior to end-game events. - * - * This file is part of Holocore. - * - * -------------------------------------------------------------------------------- - * - * Holocore is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * Holocore is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Holocore. If not, see - ******************************************************************************/ - -package intents.object; - -import resources.control.Intent; - -import java.util.List; - -/** - * Created by Waverunner on 8/19/2015 - */ -public class ObjectIdResponseIntent extends Intent { - public static final String TYPE = "ObjectIdResponseIntent"; - - private String identifier; - private List reservedIds; - - public ObjectIdResponseIntent(String identifier, List reservedIds) { - super(TYPE); - this.identifier = identifier; - this.reservedIds = reservedIds; - } - - public String getIdentifier() { - return identifier; - } - - public List getReservedIds() { - return reservedIds; - } -} \ No newline at end of file diff --git a/src/services/group/GroupService.java b/src/services/group/GroupService.java index e8a76a4c..bbd45131 100644 --- a/src/services/group/GroupService.java +++ b/src/services/group/GroupService.java @@ -32,8 +32,6 @@ import intents.NotifyPlayersPacketIntent; import intents.PlayerEventIntent; import intents.chat.ChatRoomUpdateIntent; import intents.object.ObjectCreatedIntent; -import intents.object.ObjectIdRequestIntent; -import intents.object.ObjectIdResponseIntent; import network.packets.swg.zone.chat.ChatSystemMessage; import resources.chat.ChatAvatar; import resources.control.Intent; @@ -58,19 +56,16 @@ import java.util.Map; * Created by Waverunner on 10/4/2015 */ public class GroupService extends Service { - - private final List reservedIds = new ArrayList<>(); + private final Map groups = new HashMap<>(); public GroupService() { registerForIntent(GroupEventIntent.TYPE); registerForIntent(PlayerEventIntent.TYPE); - registerForIntent(ObjectIdResponseIntent.TYPE); } @Override public boolean start() { - new ObjectIdRequestIntent("GroupService", 50).broadcast(); return super.start(); } @@ -82,11 +77,6 @@ public class GroupService extends Service { if (i instanceof GroupEventIntent) handleGroupEventIntent((GroupEventIntent) i); break; - case ObjectIdResponseIntent.TYPE: - if (!(i instanceof ObjectIdResponseIntent) || !((ObjectIdResponseIntent) i).getIdentifier().equals("GroupService")) - break; - reservedIds.addAll(((ObjectIdResponseIntent)i).getReservedIds()); - break; case PlayerEventIntent.TYPE: if (i instanceof PlayerEventIntent) handlePlayerEventIntent((PlayerEventIntent) i); @@ -289,7 +279,7 @@ public class GroupService extends Service { } private GroupObject createGroup(Player player) { - GroupObject group = (GroupObject) ObjectCreator.createObjectFromTemplate(getNextObjectId(), "object/group/shared_group_object.iff"); + GroupObject group = (GroupObject) ObjectCreator.createObjectFromTemplate("object/group/shared_group_object.iff"); if (group == null) return null; @@ -306,15 +296,6 @@ public class GroupService extends Service { return group; } - private long getNextObjectId() { - synchronized (reservedIds) { - if (reservedIds.size() <= 5) - new ObjectIdRequestIntent("GroupService", 50).broadcast(); - - return reservedIds.remove(0); - } - } - private void sendGroupSystemMessage(GroupObject group, String id) { Map members = group.getGroupMembers(); diff --git a/src/services/objects/ObjectCreator.java b/src/services/objects/ObjectCreator.java index acaae9e7..c1d6c708 100644 --- a/src/services/objects/ObjectCreator.java +++ b/src/services/objects/ObjectCreator.java @@ -52,21 +52,40 @@ import resources.objects.waypoint.WaypointObject; import resources.objects.weapon.WeaponObject; public final class ObjectCreator { - + + private static final Object OBJECT_ID_MUTEX = new Object(); + private static long maxObjectId = 1; + + public static void updateMaxObjectId(long objectId) { + synchronized (OBJECT_ID_MUTEX) { + if (objectId > maxObjectId) + maxObjectId = objectId; + } + } + public static SWGObject createObjectFromTemplate(long objectId, String template) { if (!template.startsWith("object/")) return null; if (!template.endsWith(".iff")) return null; - SWGObject obj = createObjectFromType(objectId, getFirstTemplatePart(template.substring(7, template.length()))); + SWGObject obj = createObjectFromType(objectId, getTemplatePart(template, 1)); if (obj == null) return null; obj.setTemplate(template); handlePostCreation(obj); + updateMaxObjectId(objectId); return obj; } + public static SWGObject createObjectFromTemplate(String template) { + long id = 0; + synchronized (OBJECT_ID_MUTEX) { + id = maxObjectId++; + } + return createObjectFromTemplate(id, template); + } + private static SWGObject createObjectFromType(long objectId, String type) { switch (type) { case "building": return new BuildingObject(objectId); @@ -146,11 +165,21 @@ public final class ObjectCreator { /* Misc helper methods */ - private static String getFirstTemplatePart(String template) { - int ind = template.indexOf('/'); - if (ind == -1) - return ""; - return template.substring(0, ind); + private static String getTemplatePart(String template, int index) { + int start = 0; + int end = 0; + for (int i = 0; i < template.length(); i++) { + if (template.charAt(i) != '/') + continue; + index--; + if (index == 0) + start = i+1; + else if (index == -1) { + end = i; + break; + } + } + return template.substring(start, end); } } diff --git a/src/services/objects/ObjectManager.java b/src/services/objects/ObjectManager.java index af812307..5c38ddc1 100644 --- a/src/services/objects/ObjectManager.java +++ b/src/services/objects/ObjectManager.java @@ -37,8 +37,6 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import intents.object.ObjectCreatedIntent; -import intents.object.ObjectIdRequestIntent; -import intents.object.ObjectIdResponseIntent; import intents.object.ObjectTeleportIntent; import intents.player.DeleteCharacterIntent; import intents.RequestZoneInIntent; @@ -48,7 +46,6 @@ import network.packets.swg.ErrorMessage; import network.packets.swg.zone.SceneDestroyObject; import network.packets.swg.zone.insertion.SelectCharacter; import resources.Location; -import resources.containers.ContainerPermissions; import resources.control.Intent; import resources.control.Manager; import resources.objects.SWGObject; @@ -74,7 +71,6 @@ public class ObjectManager extends Manager { private final ObjectDatabase database; private final Map objectMap; - private long maxObjectId; public ObjectManager() { objectAwareness = new ObjectAwareness(); @@ -86,7 +82,6 @@ public class ObjectManager extends Manager { database = new CachedObjectDatabase("odb/objects.db"); objectMap = new Hashtable<>(16*1024); - maxObjectId = 1; addChildService(objectAwareness); addChildService(mapManager); @@ -97,7 +92,6 @@ public class ObjectManager extends Manager { registerForIntent(GalacticPacketIntent.TYPE); registerForIntent(ObjectTeleportIntent.TYPE); - registerForIntent(ObjectIdRequestIntent.TYPE); registerForIntent(ObjectCreatedIntent.TYPE); registerForIntent(DeleteCharacterIntent.TYPE); } @@ -113,16 +107,15 @@ public class ObjectManager extends Manager { long startLoad = System.nanoTime(); Log.i("ObjectManager", "Loading objects from ObjectDatabase..."); System.out.println("ObjectManager: Loading objects from ObjectDatabase..."); - database.load(); - database.traverse(new Traverser() { - @Override - public void process(SWGObject obj) { - loadObject(obj); - if (obj.getObjectId() >= maxObjectId) { - maxObjectId = obj.getObjectId() + 1; + synchronized (database) { + database.load(); + database.traverse(new Traverser() { + @Override + public void process(SWGObject obj) { + loadObject(obj); } - } - }); + }); + } double loadTime = (System.nanoTime() - startLoad) / 1E6; Log.i("ObjectManager", "Finished loading %d objects. Time: %fms", database.size(), loadTime); System.out.printf("ObjectManager: Finished loading %d objects. Time: %fms%n", database.size(), loadTime); @@ -137,23 +130,7 @@ public class ObjectManager extends Manager { // if creature is not a player if (!(obj instanceof CreatureObject && ((CreatureObject) obj).isLoggedOutPlayer())) objectAwareness.add(obj); - if (obj instanceof CreatureObject && ((CreatureObject) obj).getPlayerObject() != null) { - if (!obj.hasSlot("bank")) { - SWGObject missing = createObject(obj, "object/tangible/bank/shared_character_bank.iff", false); - missing.setContainerPermissions(ContainerPermissions.INVENTORY); - } - - if (!obj.hasSlot("mission_bag")) { - SWGObject missing = createObject(obj, "object/tangible/mission_bag/shared_mission_bag.iff", false); - missing.setContainerPermissions(ContainerPermissions.INVENTORY); - } - - if (!obj.hasSlot("appearance_inventory")) { - SWGObject missing = createObject(obj, "object/tangible/inventory/shared_appearance_inventory.iff", false); - missing.setContainerPermissions(ContainerPermissions.INVENTORY); - } - } - objectMap.put(obj.getObjectId(), obj); + putObject(obj); updateBuildoutParent(obj); addChildrenObjects(obj); } @@ -163,7 +140,7 @@ public class ObjectManager extends Manager { if (obj.getParent().isBuildout()) { long id = obj.getParent().getObjectId(); obj.getParent().removeObject(obj); - SWGObject parent = objectMap.get(id); + SWGObject parent = getObjectById(id); if (parent != null) parent.addObject(obj); else { @@ -178,15 +155,17 @@ public class ObjectManager extends Manager { private void addChildrenObjects(SWGObject obj) { for (SWGObject child : obj.getContainedObjects()) { - objectMap.put(child.getObjectId(), child); + putObject(child); addChildrenObjects(child); } } @Override public boolean terminate() { - database.traverse((obj) -> obj.setOwner(null)); - database.close(); + synchronized (database) { + database.traverse((obj) -> obj.setOwner(null)); + database.close(); + } return super.terminate(); } @@ -194,8 +173,6 @@ public class ObjectManager extends Manager { public void onIntentReceived(Intent i) { if (i instanceof GalacticPacketIntent) { processGalacticPacketIntent((GalacticPacketIntent) i); - } else if (i instanceof ObjectIdRequestIntent) { - processObjectIdRequestIntent((ObjectIdRequestIntent) i); } else if (i instanceof ObjectCreatedIntent) { processObjectCreatedIntent((ObjectCreatedIntent) i); } else if (i instanceof DeleteCharacterIntent) { @@ -204,24 +181,9 @@ public class ObjectManager extends Manager { } private void processObjectCreatedIntent(ObjectCreatedIntent intent) { - SWGObject object = intent.getObject(); - synchronized (objectMap) { - if (object.getObjectId() >= maxObjectId) { - maxObjectId = object.getObjectId() + 1; - } - objectMap.put(object.getObjectId(), object); - } + putObject(intent.getObject()); } - - private void processObjectIdRequestIntent(ObjectIdRequestIntent intent) { - List reservedIds = new ArrayList<>(); - for (int i = 0; i < intent.getAmount(); i++) { - reservedIds.add(getNextObjectId()); - } - - new ObjectIdResponseIntent(intent.getIdentifier(), reservedIds).broadcast(); - } - + private void processGalacticPacketIntent(GalacticPacketIntent gpi) { Packet packet = gpi.getPacket(); if (packet instanceof SelectCharacter) { @@ -238,9 +200,11 @@ public class ObjectManager extends Manager { } public SWGObject deleteObject(long objId) { + synchronized (database) { + database.remove(objId); + } synchronized (objectMap) { SWGObject obj = objectMap.remove(objId); - database.remove(objId); if (obj == null) return null; obj.clearAware(); @@ -249,9 +213,16 @@ public class ObjectManager extends Manager { return obj; } } - + + private void putObject(SWGObject object) { + ObjectCreator.updateMaxObjectId(object.getObjectId()); + synchronized (objectMap) { + objectMap.put(object.getObjectId(), object); + } + } + public SWGObject destroyObject(long objectId) { - SWGObject object = objectMap.get(objectId); + SWGObject object = getObjectById(objectId); return (object != null ? destroyObject(object) : null); } @@ -316,25 +287,22 @@ public class ObjectManager extends Manager { } public SWGObject createObject(SWGObject parent, String template, Location l, boolean addToDatabase) { - synchronized (objectMap) { - long objectId = getNextObjectId(); - SWGObject obj = ObjectCreator.createObjectFromTemplate(objectId, template); - if (obj == null) { - System.err.println("ObjectManager: Unable to create object with template " + template); - return null; - } - obj.setLocation(l); - objectMap.put(objectId, obj); - if (parent != null) { - parent.addObject(obj); - } - if (addToDatabase) { - database.put(objectId, obj); - } - Log.v("ObjectManager", "Created object %d [%s]", obj.getObjectId(), obj.getTemplate()); - new ObjectCreatedIntent(obj).broadcast(); - return obj; + SWGObject obj = ObjectCreator.createObjectFromTemplate(template); + if (obj == null) { + System.err.println("ObjectManager: Unable to create object with template " + template); + return null; } + obj.setLocation(l); + if (parent != null) { + parent.addObject(obj); + } + synchronized (database) { + if (addToDatabase) + database.put(obj.getObjectId(), obj); + } + Log.v("ObjectManager", "Created object %d [%s]", obj.getObjectId(), obj.getTemplate()); + new ObjectCreatedIntent(obj).broadcast(); + return obj; } private void zoneInCharacter(PlayerManager playerManager, long netId, long characterId) { @@ -343,7 +311,7 @@ public class ObjectManager extends Manager { Log.e("ObjectManager", "Unable to zone in null player '%d'", netId); return; } - SWGObject creatureObj = objectMap.get(characterId); + SWGObject creatureObj = getObjectById(characterId); if (creatureObj == null) { System.err.println("ObjectManager: Failed to start zone - CreatureObject could not be fetched from database [Character: " + characterId + " User: " + player.getUsername() + "]"); Log.e("ObjectManager", "Failed to start zone - CreatureObject could not be fetched from database [Character: %d User: %s]", characterId, player.getUsername()); @@ -377,10 +345,4 @@ public class ObjectManager extends Manager { }, timeToRead, time); } - private long getNextObjectId() { - synchronized (objectMap) { - return maxObjectId++; - } - } - }