diff --git a/src/resources/callback/CallbackManager.java b/src/resources/callback/CallbackManager.java index b8fc99266..cb2960cec 100644 --- a/src/resources/callback/CallbackManager.java +++ b/src/resources/callback/CallbackManager.java @@ -29,10 +29,12 @@ package resources.callback; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; public class CallbackManager extends BaseCallbackManager { private final List callbacks; + private final AtomicInteger running; public CallbackManager(String name) { this(name, 1); @@ -41,6 +43,7 @@ public class CallbackManager extends BaseCallbackManager { public CallbackManager(String name, int threadCount) { super(name, threadCount); this.callbacks = new ArrayList<>(); + this.running = new AtomicInteger(0); } public void addCallback(T callback) { @@ -68,8 +71,13 @@ public class CallbackManager extends BaseCallbackManager { } } + public boolean isQueueEmpty() { + return running.get() == 0; + } + public boolean callOnEach(CallCallback call) { synchronized (callbacks) { + running.incrementAndGet(); return call(() -> { for (T callback : callbacks) { try { @@ -78,6 +86,7 @@ public class CallbackManager extends BaseCallbackManager { e.printStackTrace(); } } + running.decrementAndGet(); }); } } diff --git a/src/resources/objects/awareness/AwarenessHandler.java b/src/resources/objects/awareness/AwarenessHandler.java index f7a15305b..7a51926c2 100644 --- a/src/resources/objects/awareness/AwarenessHandler.java +++ b/src/resources/objects/awareness/AwarenessHandler.java @@ -57,6 +57,14 @@ public class AwarenessHandler { } } + public boolean isCallbacksDone() { + for (TerrainMap map : terrains.values()) { + if (!map.isCallbacksDone()) + return false; + } + return true; + } + private void loadTerrainMaps(TerrainMapCallback callback) { for (Terrain t : Terrain.values()) { TerrainMap map = new TerrainMap(t); @@ -113,9 +121,13 @@ public class AwarenessHandler { } public void disappearObject(SWGObject obj, boolean disappearObjects, boolean disappearCustom) { - moveObject(obj, GONE_LOCATION); - if (disappearObjects) - obj.clearObjectsAware(); + TerrainMap map = getTerrainMap(obj); + if (map != null) { + if (disappearObjects) + map.removeFromMap(obj); + else + map.removeWithoutUpdate(obj); + } if (disappearCustom) obj.clearCustomAware(true); } diff --git a/src/resources/objects/awareness/TerrainMap.java b/src/resources/objects/awareness/TerrainMap.java index ebccbdb3a..31f09f903 100644 --- a/src/resources/objects/awareness/TerrainMap.java +++ b/src/resources/objects/awareness/TerrainMap.java @@ -78,6 +78,10 @@ public class TerrainMap { callbackManager.setCallback(callback); } + public boolean isCallbacksDone() { + return callbackManager.isQueueEmpty(); + } + public void moveWithinMap(SWGObject obj, Location loc) { obj.setLocation(loc); if (isInAwareness(obj)) { diff --git a/test/resources/objects/awareness/MapCallback.java b/test/resources/objects/awareness/MapCallback.java index 623ac9e2b..4e21e1378 100644 --- a/test/resources/objects/awareness/MapCallback.java +++ b/test/resources/objects/awareness/MapCallback.java @@ -33,32 +33,34 @@ import org.junit.Assert; import resources.objects.SWGObject; import resources.objects.awareness.TerrainMap.TerrainMapCallback; +import resources.server_info.Log; class MapCallback implements TerrainMapCallback { - private final BlockingCounter withinRange = new BlockingCounter(); - private final BlockingCounter outOfRange = new BlockingCounter(); - private final BlockingCounter successfulMove = new BlockingCounter(); - private final BlockingCounter failedMove = new BlockingCounter(); + private final AtomicInteger withinRange = new AtomicInteger(0); + private final AtomicInteger outOfRange = new AtomicInteger(0); + private final AtomicInteger successfulMove = new AtomicInteger(0); + private final AtomicInteger failedMove = new AtomicInteger(0); @Override public void onWithinRange(SWGObject obj, SWGObject inRange) { - withinRange.increment(); + withinRange.incrementAndGet(); } @Override public void onOutOfRange(SWGObject obj, SWGObject outRange) { - outOfRange.increment(); + outOfRange.incrementAndGet(); } @Override public void onMoveSuccess(SWGObject obj) { - successfulMove.increment(); + successfulMove.incrementAndGet(); } @Override public void onMoveFailure(SWGObject obj) { - failedMove.increment(); + failedMove.incrementAndGet(); + Log.e(this, "Move failed!"); } public void set(int withinRange, int outOfRange, int successful, int failed) { @@ -84,18 +86,18 @@ class MapCallback implements TerrainMapCallback { return failedMove.get(); } - public void waitAndTest(int withinRange, int outOfRange, int successful, int failed, long timeout) { - waitFor(withinRange, outOfRange, successful, failed, timeout); - testAssert(withinRange, outOfRange, successful, failed); - } +// public void waitAndTest(int withinRange, int outOfRange, int successful, int failed, long timeout) { +// waitFor(withinRange, outOfRange, successful, failed, timeout); +// testAssert(withinRange, outOfRange, successful, failed); +// } - public void waitFor(int withinRange, int outOfRange, int successful, int failed, long timeout) { - long start = System.nanoTime(); - this.withinRange.waitUntil(withinRange, timeout); - this.outOfRange.waitUntil(outOfRange, timeout-(long)((System.nanoTime()-start)/1E6)); - this.successfulMove.waitUntil(successful, timeout-(long)((System.nanoTime()-start)/1E6)); - this.failedMove.waitUntil(failed, timeout-(long)((System.nanoTime()-start)/1E6)); - } +// public void waitFor(int withinRange, int outOfRange, int successful, int failed, long timeout) { +// long start = System.nanoTime(); +// this.withinRange.waitUntil(withinRange, timeout); +// this.outOfRange.waitUntil(outOfRange, timeout-(long)((System.nanoTime()-start)/1E6)); +// this.successfulMove.waitUntil(successful, timeout-(long)((System.nanoTime()-start)/1E6)); +// this.failedMove.waitUntil(failed, timeout-(long)((System.nanoTime()-start)/1E6)); +// } public void testAssert(int withinRange, int outOfRange, int successful, int failed) { Assert.assertEquals("TEST-WITHIN-RANGE", withinRange, this.withinRange.get()); @@ -104,57 +106,4 @@ class MapCallback implements TerrainMapCallback { Assert.assertEquals("TEST-FAILED-MOVE", failed, this.failedMove.get()); } - private static class BlockingCounter { - - private final Object mutex; - private final AtomicInteger integer; - - public BlockingCounter() { - mutex = new Object(); - integer = new AtomicInteger(0); - } - - public boolean waitUntil(int value, long timeout) { - long start = System.nanoTime(); - while (timeout > 0 && integer.get() < value && waitForChange(timeout)) { - timeout -= (long) ((System.nanoTime()-start)/1E6); - start = System.nanoTime(); - if (integer.get() >= value) - return true; - } - return false; - } - - public boolean waitForChange(long timeout) { - synchronized (mutex) { - int initial = integer.get(); - try { - mutex.wait(timeout); - } catch (InterruptedException e) { - return false; - } - return initial != integer.get(); - } - } - - public void increment() { - integer.incrementAndGet(); - synchronized (mutex) { - mutex.notifyAll(); - } - } - - public int get() { - return integer.get(); - } - - public void set(int i) { - integer.set(i); - synchronized (mutex) { - mutex.notifyAll(); - } - } - - } - } diff --git a/test/resources/objects/awareness/TestAwarenessHandler.java b/test/resources/objects/awareness/TestAwarenessHandler.java index 88afa6a61..59a3decdf 100644 --- a/test/resources/objects/awareness/TestAwarenessHandler.java +++ b/test/resources/objects/awareness/TestAwarenessHandler.java @@ -95,10 +95,12 @@ public class TestAwarenessHandler { GenericCreatureObject creature = new GenericCreatureObject(1); initAwareness(awareness, callback); awareness.moveObject(creature, CREATURE_LOCATION); - callback.waitAndTest(WITHIN_RANGE.size(), 0, 1, 0, 1000); + awaitCallbacks(awareness, 1000); + callback.testAssert(WITHIN_RANGE.size(), 0, 1, 0); callback.set(0, 0, 0, 0); awareness.moveObject(creature, CREATURE_LOCATION); - callback.waitAndTest(0, 0, 1, 0, 1000); + awaitCallbacks(awareness, 1000); + callback.testAssert(0, 0, 1, 0); } @Test @@ -108,13 +110,16 @@ public class TestAwarenessHandler { initAwareness(awareness, callback); GenericCreatureObject creature = new GenericCreatureObject(1); awareness.moveObject(creature, CREATURE_LOCATION); - callback.waitAndTest(WITHIN_RANGE.size(), 0, 1, 0, 1000); + awaitCallbacks(awareness, 1000); + callback.testAssert(WITHIN_RANGE.size(), 0, 1, 0); callback.set(0, 0, 0, 0); awareness.moveObject(creature, new Location(0, 0, 0, Terrain.TATOOINE)); - callback.waitAndTest(0, WITHIN_RANGE.size(), 1, 0, 1000); + awaitCallbacks(awareness, 1000); + callback.testAssert(0, WITHIN_RANGE.size(), 1, 0); callback.set(0, 0, 0, 0); awareness.moveObject(creature, CREATURE_LOCATION); - callback.waitAndTest(WITHIN_RANGE.size(), 0, 1, 0, 1000); + awaitCallbacks(awareness, 1000); + callback.testAssert(WITHIN_RANGE.size(), 0, 1, 0); } @Test @@ -130,7 +135,8 @@ public class TestAwarenessHandler { Assert.assertNotNull("Starport is null!", starport); initAwareness(awareness, callback); awareness.moveObject(creature, CREATURE_LOCATION); - callback.waitAndTest(WITHIN_RANGE.size(), 0, 1, 0, 1000); + awaitCallbacks(awareness, 1000); + callback.testAssert(WITHIN_RANGE.size(), 0, 1, 0); callback.set(0, 0, 0, 0); awareness.moveObject(creature, starport.getCellByNumber(1), new Location(0, 0, 0, Terrain.TATOOINE)); awareness.moveObject(CREATURE2, CREATURE2_LOCATION); @@ -142,10 +148,21 @@ public class TestAwarenessHandler { for (SWGObject obj : EISLEY_OBJECTS) { awareness.moveObject(obj, obj.getLocation()); } - callback.waitFor(0, 0, EISLEY_OBJECTS.size(), 0, 2000); + awaitCallbacks(awareness, 1000); callback.set(0, 0, 0, 0); } + private void awaitCallbacks(AwarenessHandler awareness, long timeout) { + try { + while (!awareness.isCallbacksDone() && timeout > 0) { + Thread.sleep(1); + timeout--; + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + private static class MapCallbackRealistic extends MapCallback { @Override diff --git a/test/resources/objects/awareness/TestTerrainMap.java b/test/resources/objects/awareness/TestTerrainMap.java index 02821cc8e..b50670824 100644 --- a/test/resources/objects/awareness/TestTerrainMap.java +++ b/test/resources/objects/awareness/TestTerrainMap.java @@ -60,7 +60,8 @@ public class TestTerrainMap { GenericCreatureObject objB = new GenericCreatureObject(2); map.moveWithinMap(objA, new Location(0, 0, 0, Terrain.TATOOINE)); // 0 - Within Range, 1 - Successful Move map.moveWithinMap(objB, new Location(5, 0, 5, Terrain.TATOOINE)); // 1 - Within Range, 1 - Successful Move - callback.waitAndTest(1, 0, 2, 0, 1000); + awaitCallbacks(map, 1000); + callback.testAssert(1, 0, 2, 0); } finally { map.stop(); } @@ -81,7 +82,8 @@ public class TestTerrainMap { objB.setLocation(new Location(5, 0, 5, Terrain.TATOOINE)); objB.moveToContainer(cell); map.moveToParent(objB, cell); // 0 - Within Range, 0 - Successful Move - callback.waitAndTest(1, 0, 2, 0, 1000); + awaitCallbacks(map, 1000); + callback.testAssert(1, 0, 2, 0); } finally { map.stop(); } @@ -96,9 +98,12 @@ public class TestTerrainMap { map.start(); GenericCreatureObject objA = new GenericCreatureObject(1); GenericCreatureObject objB = new GenericCreatureObject(2); + objA.setPrefLoadRange(200); + objB.setPrefLoadRange(200); map.moveWithinMap(objA, new Location(5, 0, 5, Terrain.TATOOINE)); // 0 - Within Range, 1 - Successful Move map.moveWithinMap(objB, new Location(-5, 0, -5, Terrain.TATOOINE)); // 1 - Within Range, 1 - Successful Move - callback.waitAndTest(1, 0, 2, 0, 1000); + awaitCallbacks(map, 1000); + callback.testAssert(1, 0, 2, 0); } finally { map.stop(); } @@ -135,7 +140,7 @@ public class TestTerrainMap { map.moveWithinMap(obj, obj.getLocation()); } map.moveWithinMap(creature, creatureLocation); - callback.waitFor(0, 0, tatObjects.size()+1, 0, 1000); + awaitCallbacks(map, 1000); Assert.assertEquals(0, withinRange.size()); Assert.assertTrue("TEST-ONLY-WITHIN-RANGE", onlyWithinRange.get()); } finally { @@ -153,4 +158,15 @@ public class TestTerrainMap { return true; } + private void awaitCallbacks(TerrainMap map, long timeout) { + try { + while (!map.isCallbacksDone() && timeout > 0) { + Thread.sleep(1); + timeout--; + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + }