diff --git a/src/services/objects/ObjectAwareness.java b/src/services/objects/ObjectAwareness.java index 810fea83c..061c6ddb9 100644 --- a/src/services/objects/ObjectAwareness.java +++ b/src/services/objects/ObjectAwareness.java @@ -52,6 +52,7 @@ import resources.buildout.BuildoutArea; import resources.control.Intent; import resources.control.Service; import resources.objects.SWGObject; +import resources.objects.SWGObject.ObjectClassification; import resources.objects.creature.CreatureObject; import resources.objects.quadtree.QuadTree; import resources.objects.tangible.TangibleObject; @@ -64,9 +65,11 @@ public class ObjectAwareness extends Service { private static final int DEFAULT_LOAD_RANGE = (int) square(200); // Squared for speed private final Map > quadTree; + private final Map locations; public ObjectAwareness() { - quadTree = new HashMap>(); + quadTree = new HashMap<>(); + locations = new HashMap<>(); registerForIntent(PlayerEventIntent.TYPE); registerForIntent(ObjectCreatedIntent.TYPE); registerForIntent(ObjectTeleportIntent.TYPE); @@ -136,12 +139,11 @@ public class ObjectAwareness extends Service { private void processObjectTeleportIntent(ObjectTeleportIntent oti) { SWGObject object = oti.getObject(); Player owner = object.getOwner(); - Location old = object.getLocation(); object.setLocation(oti.getNewLocation()); if (oti.getParent() != null) { move(object, oti.getParent(), oti.getNewLocation()); } else { - moveFromOld(object, old, false); + move(object, oti.getNewLocation(), false); } object.clearAware(); if (object instanceof CreatureObject && ((CreatureObject) object).isLoggedInPlayer()) @@ -175,9 +177,7 @@ public class ObjectAwareness extends Service { SWGObject obj = i.getObject(); Location newLocation = i.getNewLocation(); BuildoutArea area = obj.getBuildoutArea(); - if (area == null) - Log.e(this, "Unknown buildout area at: " + obj.getWorldLocation()); - else + if (area != null) newLocation = area.adjustLocation(newLocation); move(obj, newLocation, true); if (area != null) @@ -210,20 +210,10 @@ public class ObjectAwareness extends Service { transform = new DataTransform(transform); Location newLocation = transform.getLocation(); newLocation.setTerrain(obj.getTerrain()); - double time = ((CreatureObject) obj).getTimeSinceLastTransform() / 1000; - obj.updateLastTransformTime(); - Location l = obj.getWorldLocation(); - double speed = Math.sqrt(square(l.getX()-newLocation.getX()) + square(l.getZ()-newLocation.getZ())) / time; - if (speed > obj.getMovementScale()*7.3) { - double angle = (newLocation.getX() == l.getX() ? 0 : Math.atan2(newLocation.getZ()-l.getZ(), newLocation.getX()-l.getX())); - newLocation.setX(l.getX()+obj.getMovementScale()*7.3*time*Math.cos(angle)); - newLocation.setZ(l.getZ()+obj.getMovementScale()*7.3*time*Math.sin(angle)); - transform.setSpeed((float) (obj.getMovementScale()*7.3)); - } + moveObjectSpeedChecks(obj, newLocation); + transform.setSpeed((float) (obj.getMovementScale()*7.3)); BuildoutArea area = obj.getBuildoutArea(); - if (area == null) - Log.e(this, "Unknown buildout area at: " + obj.getWorldLocation()); - else + if (area != null) newLocation = area.adjustLocation(newLocation); new PlayerTransformedIntent(obj, obj.getParent(), null, obj.getLocation(), newLocation).broadcast(); move(obj, newLocation, true); @@ -239,6 +229,26 @@ public class ObjectAwareness extends Service { Log.e("ObjectManager", "Could not find parent for transform! Cell: %d Object: %s", transformWithParent.getCellId(), obj); return; } + moveObjectSpeedChecks(obj, parent, newLocation); + transformWithParent.setSpeed((float) (obj.getMovementScale()*7.3)); + new PlayerTransformedIntent((CreatureObject) obj, obj.getParent(), parent, obj.getLocation(), newLocation).broadcast(); + move(obj, parent, newLocation); + obj.sendParentDataTransforms(transformWithParent); + } + + private void moveObjectSpeedChecks(CreatureObject obj, Location newLocation) { + double time = ((CreatureObject) obj).getTimeSinceLastTransform() / 1000; + obj.updateLastTransformTime(); + Location l = obj.getWorldLocation(); + double speed = Math.sqrt(square(l.getX()-newLocation.getX()) + square(l.getZ()-newLocation.getZ())) / time; + if (speed > obj.getMovementScale()*7.3) { + double angle = (newLocation.getX() == l.getX() ? 0 : Math.atan2(newLocation.getZ()-l.getZ(), newLocation.getX()-l.getX())); + newLocation.setX(l.getX()+obj.getMovementScale()*7.3*time*Math.cos(angle)); + newLocation.setZ(l.getZ()+obj.getMovementScale()*7.3*time*Math.sin(angle)); + } + } + + private void moveObjectSpeedChecks(CreatureObject obj, SWGObject parent, Location newLocation) { double time = ((CreatureObject) obj).getTimeSinceLastTransform() / 1000; obj.updateLastTransformTime(); Location l = obj.getWorldLocation(); @@ -249,11 +259,7 @@ public class ObjectAwareness extends Service { double angle = (nWorld.getX() == l.getX() ? 0 : Math.atan2(nWorld.getZ()-l.getZ(), nWorld.getX()-l.getX())) + Math.PI; newLocation.setX(newLocation.getX()+obj.getMovementScale()*7.3*time*invertNormalizedValue(Math.cos(angle))); newLocation.setZ(newLocation.getZ()+obj.getMovementScale()*7.3*time*invertNormalizedValue(Math.sin(angle))); - transformWithParent.setSpeed((float) (obj.getMovementScale()*7.3)); } - new PlayerTransformedIntent((CreatureObject) obj, obj.getParent(), parent, obj.getLocation(), newLocation).broadcast(); - move(obj, parent, newLocation); - obj.sendParentDataTransforms(transformWithParent); } private void loadQuadTree() { @@ -265,9 +271,15 @@ public class ObjectAwareness extends Service { private boolean isInAwareness(SWGObject object) { if (object instanceof CreatureObject && ((CreatureObject) object).isLoggedOutPlayer()) return false; + if (object.getTerrain() == null) + return false; return object.getParent() == null && object instanceof TangibleObject; } + private boolean isInMap(SWGObject object) { + return object.getClassification() == ObjectClassification.GENERATED; + } + private double invertNormalizedValue(double x) { if (x < 0) return -1 - x; @@ -281,13 +293,16 @@ public class ObjectAwareness extends Service { public void add(SWGObject object) { if (!isInAwareness(object)) return; + remove(object); Location l = object.getLocation(); - if (invalidLocation(l)) - return; + if (isInMap(object)) { + synchronized (locations) { + locations.put(object.getObjectId(), l); + } + } QuadTree tree = getTree(l); synchronized (tree) { - if (!tree.contains(l.getX(), l.getZ(), object)) - tree.put(l.getX(), l.getZ(), object); + tree.put(l.getX(), l.getZ(), object); } } @@ -296,7 +311,20 @@ public class ObjectAwareness extends Service { * @param object the object to remove */ public void remove(SWGObject object) { - removeFromLocation(object, object.getLocation()); + Location l; + if (isInMap(object)) { + synchronized (locations) { + l = locations.remove(object.getObjectId()); + } + } else { + l = object.getLocation(); + } + if (l == null) + return; + QuadTree tree = getTree(l); + synchronized (tree) { + tree.remove(l.getX(), l.getZ(), object); + } } /** @@ -329,12 +357,10 @@ public class ObjectAwareness extends Service { */ private void move(SWGObject object, SWGObject nParent, Location nLocation) { SWGObject parent = object.getParent(); - if (parent != null && nParent != parent) { - object.moveToContainer(null); - } else if (parent == null) { + if (parent == null) { remove(object); // Moving from world to cell } - if (object.getParent() == null) { // Should have been updated in removeObject() + if (nParent != parent) { // Intentional. Just in case the ID matches or one is null object.moveToContainer(nParent); } object.setLocation(nLocation); @@ -349,8 +375,6 @@ public class ObjectAwareness extends Service { if (!obj.isGenerated() || !isInAwareness(obj)) return; Location l = obj.getWorldLocation(); - if (invalidLocation(l)) - return; Set objectAware = new HashSet(); QuadTree tree = getTree(l); List range; @@ -364,34 +388,10 @@ public class ObjectAwareness extends Service { obj.updateObjectAwareness(objectAware); } - private void moveFromOld(SWGObject object, Location oldLocation, boolean update) { - if (object.getParent() != null) { - object.moveToContainer(null); - } else { - removeFromLocation(object, oldLocation); // World to World - } - add(object); - if (update) - update(object); - } - - private void removeFromLocation(SWGObject object, Location l) { - if (invalidLocation(l)) - return; - QuadTree tree = getTree(l); - synchronized (tree) { - tree.remove(l.getX(), l.getZ(), object); - } - } - private QuadTree getTree(Location l) { return quadTree.get(l.getTerrain()); } - private boolean invalidLocation(Location l) { - return l == null || l.getTerrain() == null; - } - private boolean isValidInRange(SWGObject obj, SWGObject inRange, Location objLoc) { if (inRange.getObjectId() == obj.getObjectId()) return false;