diff --git a/src/resources/objects/SWGObject.java b/src/resources/objects/SWGObject.java index 12a3dc93b..923b92396 100644 --- a/src/resources/objects/SWGObject.java +++ b/src/resources/objects/SWGObject.java @@ -40,6 +40,7 @@ import resources.client_info.visitors.ObjectData.ObjectDataAttribute; import resources.common.CRC; import resources.containers.ContainerPermissionsType; import resources.containers.ContainerResult; +import resources.control.Assert; import resources.encodables.StringId; import resources.network.BaselineBuilder; import resources.network.BaselineObject; @@ -192,7 +193,7 @@ public abstract class SWGObject extends BaselineObject implements Comparable observer.sendPacket(update)); - AwarenessUtilities.callForNewObserver(oldObservers, newObservers, (observer) -> createObject(observer, false)); + AwarenessUtilities.callForNewObserver(oldObservers, newObservers, (observer) -> createObject(observer)); AwarenessUtilities.callForOldObserver(oldObservers, newObservers, (observer) -> destroyObject(observer)); new ContainerTransferIntent(this, container).broadcast(); return ContainerResult.SUCCESS; @@ -636,45 +637,38 @@ public abstract class SWGObject extends BaselineObject implements Comparable observers = target.getAwareness().getChildObservers(); + Assert.notNull(target); if (target.getOwnerShallow() != null) - observers.add(target.getOwnerShallow()); - for (Player observer : observers) { - createObject(observer, ignoreSnapshotChecks); + createObject(target.getOwnerShallow()); + for (Player observer : target.getAwareness().getChildObservers()) { + createObject(observer); } } - public void createObject(Player target, boolean ignoreSnapshotChecks) { + public void createObject(Player target) { + Assert.notNull(target); if (!isVisible(target.getCreatureObject())) { return; } - sendSceneCreateObject(target); - sendBaselines(target); - createChildrenObjects(target, ignoreSnapshotChecks); - sendFinalBaselinePackets(target); - target.sendPacket(new SceneEndBaselines(getObjectId())); + synchronized (target.getSendingLock()) { + sendSceneCreateObject(target); + sendBaselines(target); + createChildrenObjects(target); + sendFinalBaselinePackets(target); + target.sendPacket(new SceneEndBaselines(getObjectId())); + } } public void destroyObject(SWGObject target) { - if (isSnapshot() || target == null) - return; - Set observers = target.getAwareness().getChildObservers(); + Assert.notNull(target); if (target.getOwnerShallow() != null) - observers.add(target.getOwnerShallow()); - for (Player observer : observers) { + destroyObject(target.getOwnerShallow()); + for (Player observer : target.getAwareness().getChildObservers()) { destroyObject(observer); } } @@ -812,33 +806,21 @@ public abstract class SWGObject extends BaselineObject implements Comparable prevAware = obj.getObjectsAware(); Set aware = getNearbyAware(obj); - AwarenessUtilities.callForNewAware(prevAware, aware, (inRange) -> callbackManager.callOnEach((call) -> call.onWithinRange(obj, inRange))); - AwarenessUtilities.callForOldAware(prevAware, aware, (outRange) -> callbackManager.callOnEach((call) -> call.onOutOfRange(obj, outRange))); + callbackManager.callOnEach(call -> { + for (SWGObject n : aware) { + if (!prevAware.contains(n)) + call.onWithinRange(obj, n); + } + for (SWGObject p : prevAware) { + if (!aware.contains(p)) + call.onOutOfRange(obj, p); + } + }); } private Set getNearbyAware(SWGObject obj) { diff --git a/src/resources/objects/player/PlayerObject.java b/src/resources/objects/player/PlayerObject.java index ab0a5d7e7..96ebfe6f7 100644 --- a/src/resources/objects/player/PlayerObject.java +++ b/src/resources/objects/player/PlayerObject.java @@ -387,11 +387,12 @@ public class PlayerObject extends IntangibleObject { this.startPlayTime = startPlayTime; } - public void createChildrenObjects(Player target) { + @Override + public void sendFinalBaselinePackets(Player target) { + super.sendFinalBaselinePackets(target); SWGObject parent = getParent(); if (parent != null && parent instanceof CreatureObject) target.sendPacket(new UpdatePostureMessage(((CreatureObject)parent).getPosture().getId(), getObjectId())); - super.createChildrenObjects(target); } public void createBaseline3(Player target, BaselineBuilder bb) { diff --git a/src/resources/player/Player.java b/src/resources/player/Player.java index 9c61ee98c..4a7f8d1ab 100644 --- a/src/resources/player/Player.java +++ b/src/resources/player/Player.java @@ -40,6 +40,7 @@ public class Player implements Comparable { private final IntentChain packetChain; private final Service playerManager; + private final Object sendingLock; private final long networkId; private String username = ""; @@ -58,6 +59,7 @@ public class Player implements Comparable { public Player(Service playerManager, long networkId) { this.packetChain = new IntentChain(); this.playerManager = playerManager; + this.sendingLock = new Object(); this.networkId = networkId; } @@ -152,9 +154,15 @@ public class Player implements Comparable { return (System.nanoTime()-lastInboundMessage)/1E6; } + public Object getSendingLock() { + return sendingLock; + } + public void sendPacket(Packet ... packets) { - for (Packet p : packets) { - packetChain.broadcastAfter(new OutboundPacketIntent(p, networkId)); + synchronized (getSendingLock()) { + for (Packet p : packets) { + packetChain.broadcastAfter(new OutboundPacketIntent(p, networkId)); + } } } diff --git a/src/services/objects/ObjectAwareness.java b/src/services/objects/ObjectAwareness.java index 3051c12f2..01cb14a6a 100644 --- a/src/services/objects/ObjectAwareness.java +++ b/src/services/objects/ObjectAwareness.java @@ -171,6 +171,11 @@ public class ObjectAwareness extends Service implements TerrainMapCallback { Player p = pei.getPlayer(); CreatureObject creature = p.getCreatureObject(); switch (pei.getEvent()) { + case PE_ZONE_IN_CLIENT: + Assert.notNull(creature); + if (creature.getParent() == null) + moveObject(creature, creature.getLocation()); + break; case PE_DISAPPEAR: Assert.notNull(creature); disappearObject(creature, true, true); @@ -320,7 +325,7 @@ public class ObjectAwareness extends Service implements TerrainMapCallback { if (parent != null) recursiveCreateObject(parent, owner); else - obj.createObject(owner, true); + obj.createObject(owner); } private void moveObject(SWGObject obj, Location requestedLocation) {