From b571da79e3c8f33221641ee5b0b8304416babeed Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 15 Apr 2018 12:19:17 -0400 Subject: [PATCH 1/3] Add deferred eventbus for posting events on the next tick --- .../net/runelite/client/callback/Hooks.java | 8 ++- .../client/util/DeferredEventBus.java | 72 +++++++++++++++++++ .../net/runelite/client/callback/Hooks.java | 1 + 3 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/util/DeferredEventBus.java diff --git a/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java b/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java index 9242384bf8..714064a6b3 100644 --- a/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java +++ b/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java @@ -68,6 +68,7 @@ import net.runelite.client.task.Scheduler; import net.runelite.client.ui.overlay.OverlayLayer; import net.runelite.client.ui.overlay.OverlayRenderer; import net.runelite.client.ui.overlay.infobox.InfoBoxManager; +import net.runelite.client.util.DeferredEventBus; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -80,7 +81,9 @@ public class Hooks private static final Injector injector = RuneLite.getInjector(); private static final Client client = injector.getInstance(Client.class); - public static final EventBus eventBus = injector.getInstance(EventBus.class); + public static final EventBus eventBus = injector.getInstance(EventBus.class); // symbol must match mixin Hook + private static final DeferredEventBus _deferredEventBus = injector.getInstance(DeferredEventBus.class); + public static final EventBus deferredEventBus = _deferredEventBus; // symbol must match mixin Hook private static final Scheduler scheduler = injector.getInstance(Scheduler.class); private static final InfoBoxManager infoBoxManager = injector.getInstance(InfoBoxManager.class); private static final ChatMessageManager chatMessageManager = injector.getInstance(ChatMessageManager.class); @@ -102,6 +105,9 @@ public class Hooks if (shouldProcessGameTick) { shouldProcessGameTick = false; + + _deferredEventBus.replay(); + eventBus.post(tick); } diff --git a/runelite-client/src/main/java/net/runelite/client/util/DeferredEventBus.java b/runelite-client/src/main/java/net/runelite/client/util/DeferredEventBus.java new file mode 100644 index 0000000000..8890c65871 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/util/DeferredEventBus.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.util; + +import com.google.common.eventbus.EventBus; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; +import javax.inject.Inject; +import javax.inject.Singleton; + +@Singleton +public class DeferredEventBus extends EventBus +{ + private final EventBus eventBus; + private final Queue pendingEvents = new ConcurrentLinkedQueue<>(); + + @Inject + private DeferredEventBus(EventBus eventBus) + { + this.eventBus = eventBus; + } + + @Override + public void register(Object object) + { + eventBus.register(object); + } + + @Override + public void unregister(Object object) + { + eventBus.unregister(object); + } + + @Override + public void post(Object object) + { + pendingEvents.add(object); + } + + public void replay() + { + int size = pendingEvents.size(); + while (size-- > 0) + { + Object object = pendingEvents.poll(); + eventBus.post(object); + } + } +} diff --git a/runelite-mixins/src/main/java/net/runelite/client/callback/Hooks.java b/runelite-mixins/src/main/java/net/runelite/client/callback/Hooks.java index 0e5978b363..cf90c14151 100644 --- a/runelite-mixins/src/main/java/net/runelite/client/callback/Hooks.java +++ b/runelite-mixins/src/main/java/net/runelite/client/callback/Hooks.java @@ -42,6 +42,7 @@ public class Hooks public static Logger log; public static EventBus eventBus; + public static EventBus deferredEventBus; public static void draw(MainBufferProvider mainBufferProvider, Graphics graphics, int x, int y) { From c95163dd9a611b12b3eca3a24350921e8dbd29ea Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 15 Apr 2018 12:19:44 -0400 Subject: [PATCH 2/3] Add item container changed event --- .../java/net/runelite/api/ItemContainer.java | 4 +-- .../api/events/ItemContainerChanged.java | 34 +++++++++++++++++++ .../runelite/mixins/RSItemContainerMixin.java | 24 +++++++++++++ 3 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 runelite-api/src/main/java/net/runelite/api/events/ItemContainerChanged.java diff --git a/runelite-api/src/main/java/net/runelite/api/ItemContainer.java b/runelite-api/src/main/java/net/runelite/api/ItemContainer.java index 7b11726384..281553786f 100644 --- a/runelite-api/src/main/java/net/runelite/api/ItemContainer.java +++ b/runelite-api/src/main/java/net/runelite/api/ItemContainer.java @@ -24,11 +24,11 @@ */ package net.runelite.api; -public interface ItemContainer +public interface ItemContainer extends Node { /** * Get the items from the container - * @return + * @return items */ Item[] getItems(); } diff --git a/runelite-api/src/main/java/net/runelite/api/events/ItemContainerChanged.java b/runelite-api/src/main/java/net/runelite/api/events/ItemContainerChanged.java new file mode 100644 index 0000000000..8792c89b20 --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/events/ItemContainerChanged.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.api.events; + +import lombok.Value; +import net.runelite.api.ItemContainer; + +@Value +public class ItemContainerChanged +{ + private final ItemContainer itemContainer; +} diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSItemContainerMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSItemContainerMixin.java index 21658aec88..2de915565b 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSItemContainerMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSItemContainerMixin.java @@ -25,9 +25,12 @@ package net.runelite.mixins; import net.runelite.api.Item; +import net.runelite.api.events.ItemContainerChanged; +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 static net.runelite.client.callback.Hooks.deferredEventBus; import net.runelite.rs.api.RSClient; import net.runelite.rs.api.RSItem; import net.runelite.rs.api.RSItemContainer; @@ -38,6 +41,9 @@ public abstract class RSItemContainerMixin implements RSItemContainer @Shadow("clientInstance") private static RSClient client; + @Inject + private int rl$lastCycle; + @Inject @Override public Item[] getItems() @@ -57,4 +63,22 @@ public abstract class RSItemContainerMixin implements RSItemContainer return items; } + @FieldHook("stackSizes") + @Inject + public void stackSizesChanged(int idx) + { + int cycle = client.getGameCycle(); + if (rl$lastCycle == cycle) + { + // Limit item container updates to one per cycle + return; + } + + rl$lastCycle = cycle; + + ItemContainerChanged event = new ItemContainerChanged(); + event.setItemContainer(this); + deferredEventBus.post(event); + } + } From 317409a3929bd5aea518e4f2c5546b9cb9c0a288 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 15 Apr 2018 12:41:11 -0400 Subject: [PATCH 3/3] runelite-api: add events for actor spawning and despawning --- .../runelite/api/events/ActorDespawned.java | 32 +++++++++++++ .../net/runelite/api/events/ActorSpawned.java | 32 +++++++++++++ .../net/runelite/api/events/NpcDespawned.java | 41 ++++++++++++++++ .../net/runelite/api/events/NpcSpawned.java | 41 ++++++++++++++++ .../runelite/api/events/PlayerDespawned.java | 41 ++++++++++++++++ .../runelite/api/events/PlayerSpawned.java | 41 ++++++++++++++++ .../net/runelite/mixins/RSClientMixin.java | 47 +++++++++++++++++++ .../runelite/mixins/RSItemContainerMixin.java | 3 +- 8 files changed, 276 insertions(+), 2 deletions(-) create mode 100644 runelite-api/src/main/java/net/runelite/api/events/ActorDespawned.java create mode 100644 runelite-api/src/main/java/net/runelite/api/events/ActorSpawned.java create mode 100644 runelite-api/src/main/java/net/runelite/api/events/NpcDespawned.java create mode 100644 runelite-api/src/main/java/net/runelite/api/events/NpcSpawned.java create mode 100644 runelite-api/src/main/java/net/runelite/api/events/PlayerDespawned.java create mode 100644 runelite-api/src/main/java/net/runelite/api/events/PlayerSpawned.java diff --git a/runelite-api/src/main/java/net/runelite/api/events/ActorDespawned.java b/runelite-api/src/main/java/net/runelite/api/events/ActorDespawned.java new file mode 100644 index 0000000000..59297b923f --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/events/ActorDespawned.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.api.events; + +import net.runelite.api.Actor; + +public interface ActorDespawned +{ + Actor getActor(); +} diff --git a/runelite-api/src/main/java/net/runelite/api/events/ActorSpawned.java b/runelite-api/src/main/java/net/runelite/api/events/ActorSpawned.java new file mode 100644 index 0000000000..c4a7590235 --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/events/ActorSpawned.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.api.events; + +import net.runelite.api.Actor; + +public interface ActorSpawned +{ + Actor getActor(); +} diff --git a/runelite-api/src/main/java/net/runelite/api/events/NpcDespawned.java b/runelite-api/src/main/java/net/runelite/api/events/NpcDespawned.java new file mode 100644 index 0000000000..95abbd17a0 --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/events/NpcDespawned.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2018, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.api.events; + +import lombok.Value; +import net.runelite.api.Actor; +import net.runelite.api.NPC; + +@Value +public class NpcDespawned implements ActorDespawned +{ + private final NPC npc; + + @Override + public Actor getActor() + { + return npc; + } +} diff --git a/runelite-api/src/main/java/net/runelite/api/events/NpcSpawned.java b/runelite-api/src/main/java/net/runelite/api/events/NpcSpawned.java new file mode 100644 index 0000000000..56ee7faa15 --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/events/NpcSpawned.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2018, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.api.events; + +import lombok.Value; +import net.runelite.api.Actor; +import net.runelite.api.NPC; + +@Value +public class NpcSpawned implements ActorSpawned +{ + private final NPC npc; + + @Override + public Actor getActor() + { + return npc; + } +} diff --git a/runelite-api/src/main/java/net/runelite/api/events/PlayerDespawned.java b/runelite-api/src/main/java/net/runelite/api/events/PlayerDespawned.java new file mode 100644 index 0000000000..691e19bda8 --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/events/PlayerDespawned.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2018, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.api.events; + +import lombok.Value; +import net.runelite.api.Actor; +import net.runelite.api.Player; + +@Value +public class PlayerDespawned implements ActorDespawned +{ + private final Player player; + + @Override + public Actor getActor() + { + return player; + } +} diff --git a/runelite-api/src/main/java/net/runelite/api/events/PlayerSpawned.java b/runelite-api/src/main/java/net/runelite/api/events/PlayerSpawned.java new file mode 100644 index 0000000000..f8ddae3c82 --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/events/PlayerSpawned.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2018, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.api.events; + +import lombok.Value; +import net.runelite.api.Actor; +import net.runelite.api.Player; + +@Value +public class PlayerSpawned implements ActorSpawned +{ + private final Player player; + + @Override + public Actor getActor() + { + return player; + } +} diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java index b10268ebf9..10abc0e614 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java @@ -66,7 +66,11 @@ import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GrandExchangeOfferChanged; import net.runelite.api.events.MapRegionChanged; import net.runelite.api.events.MenuOpened; +import net.runelite.api.events.NpcDespawned; +import net.runelite.api.events.NpcSpawned; +import net.runelite.api.events.PlayerDespawned; import net.runelite.api.events.PlayerMenuOptionsChanged; +import net.runelite.api.events.PlayerSpawned; import net.runelite.api.events.ResizeableChanged; import net.runelite.api.events.VarbitChanged; import net.runelite.api.events.WidgetLoaded; @@ -79,6 +83,7 @@ import net.runelite.api.mixins.Shadow; import net.runelite.api.widgets.Widget; import net.runelite.api.widgets.WidgetInfo; import net.runelite.client.callback.Hooks; +import static net.runelite.client.callback.Hooks.deferredEventBus; import static net.runelite.client.callback.Hooks.eventBus; import net.runelite.rs.api.RSClanMemberManager; import net.runelite.rs.api.RSClient; @@ -106,6 +111,12 @@ public abstract class RSClientMixin implements RSClient @Inject private static boolean interpolateObjectAnimations; + @Inject + private static RSPlayer[] oldPlayers = new RSPlayer[2048]; + + @Inject + private static RSNPC[] oldNpcs = new RSNPC[32768]; + @Inject @Override public boolean isInterpolatePlayerAnimations() @@ -670,6 +681,42 @@ public abstract class RSClientMixin implements RSClient { npc.setIndex(idx); } + + RSNPC oldNpc = oldNpcs[idx]; + oldNpcs[idx] = npc; + + if (oldNpc != null) + { + eventBus.post(new NpcDespawned(oldNpc)); + } + if (npc != null) + { + deferredEventBus.post(new NpcSpawned(npc)); + } + } + + @FieldHook("cachedPlayers") + @Inject + public static void cachedPlayersChanged(int idx) + { + RSPlayer[] cachedPlayers = client.getCachedPlayers(); + if (idx < 0 || idx >= cachedPlayers.length) + { + return; + } + + RSPlayer player = cachedPlayers[idx]; + RSPlayer oldPlayer = oldPlayers[idx]; + oldPlayers[idx] = player; + + if (oldPlayer != null) + { + eventBus.post(new PlayerDespawned(oldPlayer)); + } + if (player != null) + { + deferredEventBus.post(new PlayerSpawned(player)); + } } @Inject diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSItemContainerMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSItemContainerMixin.java index 2de915565b..4fbc679e5c 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSItemContainerMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSItemContainerMixin.java @@ -76,8 +76,7 @@ public abstract class RSItemContainerMixin implements RSItemContainer rl$lastCycle = cycle; - ItemContainerChanged event = new ItemContainerChanged(); - event.setItemContainer(this); + ItemContainerChanged event = new ItemContainerChanged(this); deferredEventBus.post(event); }