From c7bfc890bd007f1fa4a5cbfb0b1448ffa4b0934d Mon Sep 17 00:00:00 2001 From: Light2 Date: Sat, 21 Sep 2013 19:02:35 +0200 Subject: [PATCH] Cloning works now, changed object list to hash map (significant performance increase) --- src/main/NGECore.java | 7 +++ .../objectControllerObjects/StartTask.java | 10 ++-- src/resources/objects/Buff.java | 49 ++++++++++++++++++- .../objects/creature/CreatureObject.java | 16 ++++++ src/services/BuffService.java | 9 +++- src/services/CharacterService.java | 4 +- src/services/PlayerService.java | 36 ++++++++++++-- src/services/SimulationService.java | 17 +++---- src/services/combat/CombatService.java | 2 +- src/services/guild/GuildService.java | 2 +- src/services/map/MapService.java | 1 + src/services/object/ObjectService.java | 48 ++++++------------ .../object/ObjectTransactionManager.java | 3 +- 13 files changed, 145 insertions(+), 59 deletions(-) diff --git a/src/main/NGECore.java b/src/main/NGECore.java index 2a7fc4e0..0ebb0880 100644 --- a/src/main/NGECore.java +++ b/src/main/NGECore.java @@ -84,6 +84,8 @@ import engine.servers.PingServer; public class NGECore { public static boolean didServerCrash = false; + + private static NGECore instance; private Config config = null; @@ -135,6 +137,8 @@ public class NGECore { } public void start() { + + instance = this; config = new Config(); config.setFilePath("nge.cfg"); if (!(config.loadConfigFile())) { @@ -375,5 +379,8 @@ public class NGECore { return Thread.currentThread(); } + public static NGECore getInstance() { + return instance; + } } diff --git a/src/protocol/swg/objectControllerObjects/StartTask.java b/src/protocol/swg/objectControllerObjects/StartTask.java index c8cdd408..da3e74b7 100644 --- a/src/protocol/swg/objectControllerObjects/StartTask.java +++ b/src/protocol/swg/objectControllerObjects/StartTask.java @@ -48,16 +48,20 @@ public class StartTask extends ObjControllerObject { @Override public IoBuffer serialize() { - IoBuffer result = IoBuffer.allocate(33).order(ByteOrder.LITTLE_ENDIAN); + IoBuffer result = IoBuffer.allocate(37).order(ByteOrder.LITTLE_ENDIAN); result.putInt(ObjControllerMessage.START_TASK); result.putLong(objectId); result.putInt(0); - result.put((byte) 0); + result.put((byte) 4); // 0 for no cooldown, 0x26 adds execute time (usually 0.25) result.putInt(actionCounter); - result.putLong(0); + result.putInt(0); + result.putInt(0); result.putInt(commandCRC); + result.putInt(0); // second unknown crc + result.putInt(0); // unk + result.putFloat(0); // cooldown return result.flip(); diff --git a/src/resources/objects/Buff.java b/src/resources/objects/Buff.java index 20a2dc73..b064f061 100644 --- a/src/resources/objects/Buff.java +++ b/src/resources/objects/Buff.java @@ -22,10 +22,17 @@ package resources.objects; import java.nio.ByteOrder; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import main.NGECore; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.buffer.SimpleBufferAllocator; +import resources.objects.creature.CreatureObject; + import com.sleepycat.persist.model.NotPersistent; import com.sleepycat.persist.model.Persistent; @@ -56,7 +63,9 @@ public class Buff implements IListObject { private boolean decayOnPvPDeath; private long startTime; private int totalPlayTime; - private byte decayCounter; + private byte decayCounter = 0; + @NotPersistent + private ScheduledFuture removalTask; public Buff(String buffName, long ownerId) { @@ -355,8 +364,44 @@ public class Buff implements IListObject { return decayCounter; } - public void incDecayCounter(byte decayCounter) { + public void incDecayCounter() { this.decayCounter++; } + public ScheduledFuture getRemovalTask() { + return removalTask; + } + + public void setRemovalTask(ScheduledFuture removalTask) { + this.removalTask = removalTask; + } + + public void updateRemovalTask() { + + if(removalTask == null) + return; + + removalTask.cancel(true); + + final NGECore core = NGECore.getInstance(); + final CreatureObject owner = (CreatureObject) core.objectService.getObject(getOwnerId()); + + if(owner == null) + return; + + ScheduledFuture task = Executors.newScheduledThreadPool(1).schedule(new Runnable() { + + @Override + public void run() { + + core.buffService.removeBuffFromCreature(owner, Buff.this); + + } + + }, (long) getRemainingDuration(), TimeUnit.SECONDS); + + setRemovalTask(task); + + } + } diff --git a/src/resources/objects/creature/CreatureObject.java b/src/resources/objects/creature/CreatureObject.java index 31608c77..13695e7f 100644 --- a/src/resources/objects/creature/CreatureObject.java +++ b/src/resources/objects/creature/CreatureObject.java @@ -1042,7 +1042,23 @@ public class CreatureObject extends TangibleObject implements IPersistent { } notifyObservers(messageBuilder.buildRemoveBuffDelta(buff), true); } + + public void updateBuff(Buff buff) { + buff.updateRemovalTask(); + synchronized(objectMutex) { + setBuffListCounter(getBuffListCounter() + 1); + notifyObservers(messageBuilder.buildUpdateBuffDelta(buff), true); + } + } + public void updateAllBuffs() { + synchronized(objectMutex) { + for(Buff buff : buffList.get()) { + updateBuff(buff); + } + } + } + public int getBuffListCounter() { synchronized(objectMutex) { return buffListUpdateCounter; diff --git a/src/services/BuffService.java b/src/services/BuffService.java index 5673e37a..1a0ab123 100644 --- a/src/services/BuffService.java +++ b/src/services/BuffService.java @@ -24,6 +24,7 @@ package services; import java.util.Map; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; @@ -92,7 +93,7 @@ public class BuffService implements INetworkDispatch { if(buff.getDuration() > 0) { - scheduler.schedule(new Runnable() { + ScheduledFuture task = scheduler.schedule(new Runnable() { @Override public void run() { @@ -103,6 +104,9 @@ public class BuffService implements INetworkDispatch { } }, (long) buff.getDuration(), TimeUnit.SECONDS); + + buff.setRemovalTask(task); + } } @@ -124,7 +128,7 @@ public class BuffService implements INetworkDispatch { for(final Buff buff : creature.getBuffList().get().toArray(new Buff[] { })) { if(buff.getRemainingDuration() > 0 && buff.getDuration() > 0) { - scheduler.schedule(new Runnable() { + ScheduledFuture task = scheduler.schedule(new Runnable() { @Override public void run() { @@ -134,6 +138,7 @@ public class BuffService implements INetworkDispatch { } }, (long) buff.getRemainingDuration(), TimeUnit.SECONDS); + buff.setRemovalTask(task); continue; } else { removeBuffFromCreature(creature, buff); diff --git a/src/services/CharacterService.java b/src/services/CharacterService.java index de94db65..8e5c6d8f 100644 --- a/src/services/CharacterService.java +++ b/src/services/CharacterService.java @@ -264,10 +264,8 @@ public class CharacterService implements INetworkDispatch { object._add(weapon); object.setWeaponId(weapon.getObjectID()); - core.scriptService.callScript("scripts/", "demo", "CreateStartingCharacter", core, object); + core.scriptService.callScript("scripts/", "CreateStartingCharacter", "demo", core, object); - - core.getCreatureODB().put(object, Long.class, CreatureObject.class, object.getTransaction()); // might not need to commit transaction but better safe than sorry object.getTransaction().commitSync(); diff --git a/src/services/PlayerService.java b/src/services/PlayerService.java index c592b091..c3cb95fa 100644 --- a/src/services/PlayerService.java +++ b/src/services/PlayerService.java @@ -22,6 +22,7 @@ package services; import java.nio.ByteOrder; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -40,7 +41,9 @@ import protocol.swg.ServerTimeMessage; import resources.common.FileUtilities; import resources.common.Opcodes; import resources.common.SpawnPoint; +import resources.objects.Buff; import resources.objects.building.BuildingObject; +import resources.objects.cell.CellObject; import resources.objects.creature.CreatureObject; import resources.objects.player.PlayerObject; import services.sui.SUIService.ListBoxType; @@ -193,7 +196,7 @@ public class PlayerService implements INetworkDispatch { } - public void sendCloningWindow(CreatureObject creature) { + public void sendCloningWindow(CreatureObject creature, final boolean pvpDeath) { //if(creature.getPosture() != 14) // return; @@ -236,7 +239,7 @@ public class PlayerService implements INetworkDispatch { SpawnPoint spawnPoint = spawnPoints.get(new Random().nextInt(spawnPoints.size())); - handleCloneRequest((CreatureObject) owner, (BuildingObject) cloner, spawnPoint); + handleCloneRequest((CreatureObject) owner, (BuildingObject) cloner, spawnPoint, pvpDeath); } @@ -246,8 +249,35 @@ public class PlayerService implements INetworkDispatch { } - public void handleCloneRequest(CreatureObject creature, BuildingObject cloner, SpawnPoint spawnPoint) { + public void handleCloneRequest(CreatureObject creature, BuildingObject cloner, SpawnPoint spawnPoint, boolean pvpDeath) { + CellObject cell = cloner.getCellByCellNumber(spawnPoint.getCellNumber()); + + if(cell == null) + return; + + core.simulationService.transferToPlanet(creature, cloner.getPlanet(), spawnPoint.getPosition(), spawnPoint.getOrientation(), cell); + + creature.setHealth(creature.getMaxHealth()); + creature.setAction(creature.getMaxAction()); + + creature.setPosture((byte) 0); + creature.setSpeedMultiplierBase(1); + creature.setTurnRadius(1); + + if(pvpDeath) { + List buffs = new ArrayList(creature.getBuffList().get()); + + for(Buff buff : buffs) { + if(buff.isDecayOnPvPDeath()) + buff.incDecayCounter(); + } + + creature.updateAllBuffs(); + } + + creature.setFactionStatus(0); + core.buffService.addBuffToCreature(creature, "cloning_sickness"); } diff --git a/src/services/SimulationService.java b/src/services/SimulationService.java index c6c6bd2e..008c140c 100644 --- a/src/services/SimulationService.java +++ b/src/services/SimulationService.java @@ -103,7 +103,7 @@ public class SimulationService implements INetworkDispatch { quadTrees.put(terrainService.getPlanetList().get(i).getName(), new QuadTree(-8192, -8192, 8192, 8192)); } - List objectList = new ArrayList(core.objectService.getObjectList()); + List objectList = new ArrayList(core.objectService.getObjectList().values()); for(SWGObject obj : objectList) { if(obj.getParentId() == 0 && obj.isInSnapshot()) { core.objectService.loadServerTemplate(obj); @@ -550,8 +550,8 @@ public class SimulationService implements INetworkDispatch { } } - - public void transferToPlanet(SWGObject object, Planet planet, Point3D newPos, Quaternion newOrientation) { + + public void transferToPlanet(SWGObject object, Planet planet, Point3D newPos, Quaternion newOrientation, SWGObject newParent) { Client client = object.getClient(); @@ -582,12 +582,8 @@ public class SimulationService implements INetworkDispatch { synchronized(object.getMutex()) { - Iterator it = object.getAwareObjects().iterator(); + object.getAwareObjects().removeAll(object.getAwareObjects()); - while(it.hasNext()) { - it.remove(); - } - } object.setPlanet(planet); @@ -595,6 +591,9 @@ public class SimulationService implements INetworkDispatch { object.setPosition(newPos); object.setOrientation(newOrientation); + if(newParent != null && newParent instanceof CellObject) + newParent._add(object); + HeartBeatMessage heartBeat = new HeartBeatMessage(); session.write(heartBeat.serialize()); @@ -604,8 +603,8 @@ public class SimulationService implements INetworkDispatch { handleZoneIn(client); object.makeAware(object); - } + public void openContainer(SWGObject requester, SWGObject container) { diff --git a/src/services/combat/CombatService.java b/src/services/combat/CombatService.java index 79adfc10..c6075034 100644 --- a/src/services/combat/CombatService.java +++ b/src/services/combat/CombatService.java @@ -795,7 +795,7 @@ public class CombatService implements INetworkDispatch { attacker.removeDefender(target); target.removeDefender(attacker); - // TODO: Create Clone SUI Window + core.playerService.sendCloningWindow(target, attacker.getSlottedObject("ghost") != null); } diff --git a/src/services/guild/GuildService.java b/src/services/guild/GuildService.java index 1a309fc0..1e0857c4 100644 --- a/src/services/guild/GuildService.java +++ b/src/services/guild/GuildService.java @@ -41,7 +41,7 @@ public class GuildService implements INetworkDispatch { public GuildService(NGECore core) { this.core = core; - for (SWGObject swgObject : core.objectService.getObjectList()) { + for (SWGObject swgObject : core.objectService.getObjectList().values()) { if (swgObject.getTemplate().equals("object/guild/shared_guild_object.iff") && swgObject instanceof GuildObject) { object = (GuildObject) swgObject; } diff --git a/src/services/map/MapService.java b/src/services/map/MapService.java index d6a0f821..e1d81d93 100644 --- a/src/services/map/MapService.java +++ b/src/services/map/MapService.java @@ -112,6 +112,7 @@ public class MapService implements INetworkDispatch { MapLocation location = new MapLocation(planet, nextId.incrementAndGet(), name, x, y, category, subcategory, active); locationMap.get(planet).add(location); + } public String getClosestCityName(SWGObject object) { diff --git a/src/services/object/ObjectService.java b/src/services/object/ObjectService.java index ee2afd70..ff26417b 100644 --- a/src/services/object/ObjectService.java +++ b/src/services/object/ObjectService.java @@ -82,7 +82,7 @@ import resources.objects.weapon.WeaponObject; public class ObjectService implements INetworkDispatch { - private List objectList = Collections.synchronizedList(new ArrayList()); + private Map objectList = new ConcurrentHashMap(); private NGECore core; @@ -101,7 +101,7 @@ public class ObjectService implements INetworkDispatch { @Override public void run() { synchronized(objectList) { - for(SWGObject obj : objectList) { + for(SWGObject obj : objectList.values()) { if(obj.getSlottedObject("ghost") != null) { ((CreatureObject) obj).createTransaction(core.getCreatureODB().getEnvironment()); @@ -192,7 +192,7 @@ public class ObjectService implements INetworkDispatch { loadServerTemplate(object); - objectList.add(object); + objectList.put(objectID, object); return object; } @@ -238,38 +238,20 @@ public class ObjectService implements INetworkDispatch { } public SWGObject getObject(long objectID) { - - SWGObject object = null; - - synchronized(objectList) { - - Iterator it = objectList.iterator(); - - while(it.hasNext()) { - - SWGObject swgObject = it.next(); - if(swgObject.getObjectID() == objectID) { - object = swgObject; - break; - } - } - } - - return object; - + return objectList.get(objectID); } - public List getObjectList() { return objectList; } + public Map getObjectList() { return objectList; } public void destroyObject(SWGObject object) { object.viewChildren(object, true, true, new Traverser() { @Override public void process(SWGObject obj) { - objectList.remove(obj); + objectList.remove(obj.getObjectID()); } }); - objectList.remove(object); + objectList.remove(object.getObjectID()); //core.simulationService.remove(object, object.getPosition().x, object.getPosition().y); } @@ -280,20 +262,18 @@ public class ObjectService implements INetworkDispatch { if(object != null) { destroyObject(object); } + } public SWGObject getObjectByCustomName(String customName) { synchronized(objectList) { - Iterator it = objectList.iterator(); - - while(it.hasNext()) { - SWGObject obj = it.next(); + for(SWGObject obj : objectList.values()) { if(obj.getCustomName() == null) continue; if(obj.getCustomName().equals(customName)) - return it.next(); + return obj; } } @@ -387,13 +367,13 @@ public class ObjectService implements INetworkDispatch { creature.setPlanet(planet); client.setParent(creature); - objectList.add(creature); + objectList.put(creature.getObjectID(), creature); creature.viewChildren(creature, true, true, new Traverser() { @Override public void process(SWGObject object) { - objectList.add(object); + objectList.put(object.getObjectID(), object); } }); @@ -406,7 +386,7 @@ public class ObjectService implements INetworkDispatch { object.setParent(getObject(object.getParentId())); object.getContainerInfo(object.getTemplate()); if(getObject(object.getObjectID()) == null) - objectList.add(object); + objectList.put(object.getObjectID(), object); } }); @@ -479,7 +459,7 @@ public class ObjectService implements INetworkDispatch { } visitor.dispose(); synchronized(objectList) { - for(SWGObject obj : objectList) { + for(SWGObject obj : objectList.values()) { if(obj.getParentId() != 0 && getObject(obj.getParentId()) != null) { SWGObject parent = getObject(obj.getParentId()); parent.add(obj); diff --git a/src/services/object/ObjectTransactionManager.java b/src/services/object/ObjectTransactionManager.java index ac53bf56..caba44ec 100644 --- a/src/services/object/ObjectTransactionManager.java +++ b/src/services/object/ObjectTransactionManager.java @@ -21,6 +21,7 @@ ******************************************************************************/ package services.object; +import java.util.Collection; import java.util.Iterator; import java.util.List; @@ -60,7 +61,7 @@ public class ObjectTransactionManager implements Runnable { Thread.sleep(cycleTime); - List swgObjects = objService.getObjectList(); + Collection swgObjects = objService.getObjectList().values(); synchronized(swgObjects) {