diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSTileMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSTileMixin.java index b88684fc6b..093fa17d88 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSTileMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSTileMixin.java @@ -24,12 +24,12 @@ */ package net.runelite.mixins; -import net.runelite.api.Actor; +import java.util.ArrayList; +import java.util.List; import net.runelite.api.CollisionData; import net.runelite.api.CollisionDataFlag; import net.runelite.api.Constants; import net.runelite.api.DecorativeObject; -import net.runelite.api.GameObject; import net.runelite.api.GroundObject; import net.runelite.api.Item; import net.runelite.api.ItemLayer; @@ -53,31 +53,31 @@ import net.runelite.api.events.ItemSpawned; import net.runelite.api.events.WallObjectChanged; import net.runelite.api.events.WallObjectDespawned; import net.runelite.api.events.WallObjectSpawned; -import java.util.ArrayList; -import java.util.List; import net.runelite.api.mixins.FieldHook; import net.runelite.api.mixins.Inject; import net.runelite.api.mixins.Mixin; import net.runelite.api.mixins.Shadow; +import net.runelite.rs.api.RSActor; import net.runelite.rs.api.RSClient; +import net.runelite.rs.api.RSDeque; import net.runelite.rs.api.RSGameObject; -import net.runelite.rs.api.RSGroundItem; -import net.runelite.rs.api.RSGroundItemPile; +import net.runelite.rs.api.RSGraphicsObject; +import net.runelite.rs.api.RSItem; +import net.runelite.rs.api.RSItemLayer; import net.runelite.rs.api.RSNode; -import net.runelite.rs.api.RSNodeDeque; +import net.runelite.rs.api.RSProjectile; +import net.runelite.rs.api.RSRenderable; import net.runelite.rs.api.RSTile; +import org.slf4j.Logger; @Mixin(RSTile.class) public abstract class RSTileMixin implements RSTile { - @Shadow("client") + @Shadow("clientInstance") private static RSClient client; @Inject - private static GameObject lastGameObject; - - @Inject - private static RSNodeDeque[][][] lastGroundItems = new RSNodeDeque[Constants.MAX_Z][Constants.SCENE_SIZE][Constants.SCENE_SIZE]; + private static RSDeque[][][] lastGroundItems = new RSDeque[Constants.MAX_Z][Constants.SCENE_SIZE][Constants.SCENE_SIZE]; @Inject private WallObject previousWallObject; @@ -89,7 +89,7 @@ public abstract class RSTileMixin implements RSTile private GroundObject previousGroundObject; @Inject - private GameObject[] previousGameObjects; + private RSGameObject[] previousGameObjects; @Inject @Override @@ -112,7 +112,7 @@ public abstract class RSTileMixin implements RSTile return LocalPoint.fromScene(getX(), getY()); } - @FieldHook("boundaryObject") + @FieldHook("wallObject") @Inject public void wallObjectChanged(int idx) { @@ -135,7 +135,7 @@ public abstract class RSTileMixin implements RSTile wallObjectSpawned.setWallObject(current); client.getCallbacks().post(wallObjectSpawned); } - else if (current != null) + else if (current != null && previous != null) { WallObjectChanged wallObjectChanged = new WallObjectChanged(); wallObjectChanged.setTile(this); @@ -145,7 +145,7 @@ public abstract class RSTileMixin implements RSTile } } - @FieldHook("wallDecoration") + @FieldHook("decorativeObject") @Inject public void decorativeObjectChanged(int idx) { @@ -168,7 +168,7 @@ public abstract class RSTileMixin implements RSTile decorativeObjectSpawned.setDecorativeObject(current); client.getCallbacks().post(decorativeObjectSpawned); } - else if (current != null) + else if (current != null && previous != null) { DecorativeObjectChanged decorativeObjectChanged = new DecorativeObjectChanged(); decorativeObjectChanged.setTile(this); @@ -178,7 +178,7 @@ public abstract class RSTileMixin implements RSTile } } - @FieldHook("floorDecoration") + @FieldHook("groundObject") @Inject public void groundObjectChanged(int idx) { @@ -201,7 +201,7 @@ public abstract class RSTileMixin implements RSTile groundObjectSpawned.setGroundObject(current); client.getCallbacks().post(groundObjectSpawned); } - else if (current != null) + else if (current != null && previous != null) { GroundObjectChanged groundObjectChanged = new GroundObjectChanged(); groundObjectChanged.setTile(this); @@ -211,7 +211,7 @@ public abstract class RSTileMixin implements RSTile } } - @FieldHook("gameObjects") + @FieldHook("objects") @Inject public void gameObjectsChanged(int idx) { @@ -222,69 +222,96 @@ public abstract class RSTileMixin implements RSTile if (previousGameObjects == null) { - previousGameObjects = new GameObject[5]; + previousGameObjects = new RSGameObject[5]; } // Previous game object - GameObject previous = previousGameObjects[idx]; + RSGameObject previous = previousGameObjects[idx]; // GameObject that was changed. RSGameObject current = (RSGameObject) getGameObjects()[idx]; - // Last game object - GameObject last = lastGameObject; - - // Update last game object - lastGameObject = current; - // Update previous object to current previousGameObjects[idx] = current; // Duplicate event, return - if (current != null && current.equals(last)) + if (current == previous) { return; } - // Characters seem to generate a constant stream of new GameObjects - if (current == null || !(current.getRenderable() instanceof Actor)) + // actors, projectiles, and graphics objects are added and removed from the scene each frame as GameObjects, + // so ignore them. + boolean currentInvalid = false, prevInvalid = false; + if (current != null) { - if (current == null && previous != null) + RSRenderable renderable = current.getRenderable(); + currentInvalid = renderable instanceof RSActor || renderable instanceof RSProjectile || renderable instanceof RSGraphicsObject; + } + + if (previous != null) + { + RSRenderable renderable = previous.getRenderable(); + prevInvalid = renderable instanceof RSActor || renderable instanceof RSProjectile || renderable instanceof RSGraphicsObject; + } + + Logger logger = client.getLogger(); + if (current == null) + { + if (prevInvalid) { - GameObjectDespawned gameObjectDespawned = new GameObjectDespawned(); - gameObjectDespawned.setTile(this); - gameObjectDespawned.setGameObject(previous); - client.getCallbacks().post(gameObjectDespawned); + return; } - else if (current != null && previous == null) + + logger.trace("Game object despawn: {}", previous.getId()); + + GameObjectDespawned gameObjectDespawned = new GameObjectDespawned(); + gameObjectDespawned.setTile(this); + gameObjectDespawned.setGameObject(previous); + client.getCallbacks().post(gameObjectDespawned); + } + else if (previous == null) + { + if (currentInvalid) { - GameObjectSpawned gameObjectSpawned = new GameObjectSpawned(); - gameObjectSpawned.setTile(this); - gameObjectSpawned.setGameObject(current); - client.getCallbacks().post(gameObjectSpawned); + return; } - else if (current != null) + + logger.trace("Game object spawn: {}", current.getId()); + + GameObjectSpawned gameObjectSpawned = new GameObjectSpawned(); + gameObjectSpawned.setTile(this); + gameObjectSpawned.setGameObject(current); + client.getCallbacks().post(gameObjectSpawned); + } + else + { + if (currentInvalid && prevInvalid) { - GameObjectChanged gameObjectsChanged = new GameObjectChanged(); - gameObjectsChanged.setTile(this); - gameObjectsChanged.setPrevious(previous); - gameObjectsChanged.setGameObject(current); - client.getCallbacks().post(gameObjectsChanged); + return; } + + logger.trace("Game object change: {} -> {}", previous.getId(), current.getId()); + + GameObjectChanged gameObjectsChanged = new GameObjectChanged(); + gameObjectsChanged.setTile(this); + gameObjectsChanged.setPrevious(previous); + gameObjectsChanged.setGameObject(current); + client.getCallbacks().post(gameObjectsChanged); } } - @FieldHook("groundItemPile") + @FieldHook("itemLayer") @Inject public void itemLayerChanged(int idx) { int x = getX(); int y = getY(); int z = client.getPlane(); - RSNodeDeque[][][] groundItemDeque = client.getGroundItemDeque(); + RSDeque[][][] groundItemDeque = client.getGroundItemDeque(); - RSNodeDeque oldQueue = lastGroundItems[z][x][y]; - RSNodeDeque newQueue = groundItemDeque[z][x][y]; + RSDeque oldQueue = lastGroundItems[z][x][y]; + RSDeque newQueue = groundItemDeque[z][x][y]; if (oldQueue != newQueue) { @@ -294,7 +321,7 @@ public abstract class RSTileMixin implements RSTile RSNode head = oldQueue.getHead(); for (RSNode cur = head.getNext(); cur != head; cur = cur.getNext()) { - RSGroundItem item = (RSGroundItem) cur; + RSItem item = (RSItem) cur; ItemDespawned itemDespawned = new ItemDespawned(this, item); client.getCallbacks().post(itemDespawned); } @@ -302,13 +329,13 @@ public abstract class RSTileMixin implements RSTile lastGroundItems[z][x][y] = newQueue; } - RSGroundItem lastUnlink = client.getLastItemDespawn(); + RSItem lastUnlink = client.getLastItemDespawn(); if (lastUnlink != null) { client.setLastItemDespawn(null); } - RSGroundItemPile itemLayer = (RSGroundItemPile) getItemLayer(); + RSItemLayer itemLayer = (RSItemLayer) getItemLayer(); if (itemLayer == null) { if (lastUnlink != null) @@ -319,7 +346,7 @@ public abstract class RSTileMixin implements RSTile return; } - RSNodeDeque itemDeque = newQueue; + RSDeque itemDeque = newQueue; if (itemDeque == null) { @@ -338,7 +365,7 @@ public abstract class RSTileMixin implements RSTile boolean forward = false; if (head != previous) { - RSGroundItem prev = (RSGroundItem) previous; + RSItem prev = (RSItem) previous; if (x != prev.getX() || y != prev.getY()) { current = prev; @@ -348,7 +375,7 @@ public abstract class RSTileMixin implements RSTile RSNode next = head.getNext(); if (current == null && head != next) { - RSGroundItem n = (RSGroundItem) next; + RSItem n = (RSItem) next; if (x != n.getX() || y != n.getY()) { current = n; @@ -369,7 +396,7 @@ public abstract class RSTileMixin implements RSTile do { - RSGroundItem item = (RSGroundItem) current; + RSItem item = (RSItem) current; item.setX(x); item.setY(y); @@ -380,7 +407,7 @@ public abstract class RSTileMixin implements RSTile // Send spawn events for anything on this tile which is at the wrong location, which happens // when the scene base changes - } while (current != head && (((RSGroundItem) current).getX() != x || ((RSGroundItem) current).getY() != y)); + } while (current != head && (((RSItem) current).getX() != x || ((RSItem) current).getY() != y)); } @Inject