From b4bb5572af4fe6c80c37e0c217e847ef07a431f2 Mon Sep 17 00:00:00 2001 From: Infinitay Date: Sat, 20 Dec 2025 07:47:28 -0500 Subject: [PATCH 01/29] feat(module): Created PluginModule class for modular plugin lifecycle - Created an abstract class PluginModule to better handle multiple modules within the plugin and to appropriately handle the lifecycle - Construct injected common fields such as OverlayManager, Client, and the config - Field injected on-demand fields such as EventBus and GameEventManager - Automatically (un)registers the module from the EventBus - Re-fire various events by utilizing GameEventManager#simulateGameEvents within #startUp - Abstracted #onStartUp to handle module starts, #onShutdown to handle module stops, and #isEnabled to determine the status of the module --- .../pluginmodulesystem/PluginModule.java | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/main/java/randomeventhelper/pluginmodulesystem/PluginModule.java diff --git a/src/main/java/randomeventhelper/pluginmodulesystem/PluginModule.java b/src/main/java/randomeventhelper/pluginmodulesystem/PluginModule.java new file mode 100644 index 0000000..bb49a8c --- /dev/null +++ b/src/main/java/randomeventhelper/pluginmodulesystem/PluginModule.java @@ -0,0 +1,55 @@ +package randomeventhelper.pluginmodulesystem; + +import javax.inject.Inject; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.client.callback.ClientThread; +import net.runelite.client.config.Config; +import net.runelite.client.eventbus.EventBus; +import net.runelite.client.ui.overlay.OverlayManager; +import net.runelite.client.util.GameEventManager; +import randomeventhelper.RandomEventHelperConfig; + +@Slf4j +// Thanks to Llemon for this - Since we are now relying on constructor injection, we will need a constructor followed by injecting it +// To keep it a little cleaner, you can still use lombok RAC and also pass in @Inject into it so that the constructor will be injected properly +// Also, keep in mind that we don't need to define final variables within the module classes themselves since they will be passed in via the constructor injection super call +@RequiredArgsConstructor(onConstructor = @__(@Inject)) +public abstract class PluginModule +{ + // It's fine to field inject these since we only need access to them here and not in the module classes themselves + @Inject + protected EventBus eventBus; + @Inject + protected GameEventManager gameEventManager; + protected final OverlayManager overlayManager; + protected final RandomEventHelperConfig config; + protected final Client client; + + public abstract void onStartUp(); + + public abstract void onShutdown(); + + public abstract boolean isEnabled(); + + public void startUp() + { + this.eventBus.register(this); + this.onStartUp(); + if (client.getGameState().getState() >= GameState.LOGGED_IN.getState()) + { + // Remember to pass in the instance (this) and not the class (#getClass) + this.gameEventManager.simulateGameEvents(this); + } + log.debug("Started the {} module", this.getClass().getSimpleName()); + } + + public void shutdown() + { + this.eventBus.unregister(this); + this.onShutdown(); + log.debug("Shutdown the {} module", this.getClass().getSimpleName()); + } +} From c471c4b831047a1f6ce642e59f137ab98c67a5eb Mon Sep 17 00:00:00 2001 From: Infinitay Date: Sun, 21 Dec 2025 18:59:05 -0500 Subject: [PATCH 02/29] refactor: Start refactoring RandomEventHelper to modular plugin lifecycle - Removed prior injections that have yet to be refactored - Refactored #startUp, #shutDown, and #onConfigChanged to utilize the new modular system to handle state changes --- .../RandomEventHelperPlugin.java | 227 ++---------------- .../pluginmodulesystem/PluginModule.java | 3 +- 2 files changed, 26 insertions(+), 204 deletions(-) diff --git a/src/main/java/randomeventhelper/RandomEventHelperPlugin.java b/src/main/java/randomeventhelper/RandomEventHelperPlugin.java index f9e56e5..535e018 100644 --- a/src/main/java/randomeventhelper/RandomEventHelperPlugin.java +++ b/src/main/java/randomeventhelper/RandomEventHelperPlugin.java @@ -1,6 +1,8 @@ package randomeventhelper; +import com.google.common.collect.ImmutableMap; import com.google.inject.Provides; +import java.util.Map; import javax.inject.Inject; import lombok.extern.slf4j.Slf4j; import net.runelite.api.Actor; @@ -30,6 +32,7 @@ import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.ui.overlay.OverlayManager; +import randomeventhelper.pluginmodulesystem.PluginModule; import randomeventhelper.randomevents.beekeeper.BeekeeperHelper; import randomeventhelper.randomevents.drilldemon.DrillDemonHelper; import randomeventhelper.randomevents.freakyforester.FreakyForesterHelper; @@ -70,90 +73,24 @@ public class RandomEventHelperPlugin extends Plugin @Inject private RandomEventHelperItemOverlay itemOverlay; - @Inject - private SurpriseExamHelper surpriseExamHelper; - - @Inject - private BeekeeperHelper beekeeperHelper; - - @Inject - private FreakyForesterHelper freakyForesterHelper; - - @Inject - private PinballHelper pinballHelper; - - @Inject - private DrillDemonHelper drillDemonHelper; - - @Inject - private GravediggerHelper gravediggerHelper; - - @Inject - private GravediggerOverlay gravediggerOverlay; - - @Inject - private MimeHelper mimeHelper; - - @Inject - private MazeHelper mazeHelper; - - @Inject - private SandwichLadyHelper sandwichLadyHelper; - - @Inject - private QuizMasterHelper quizMasterHelper; - - @Inject - private PirateHelper pirateHelper; + // -> + private Map pluginModulesMap; @Override protected void startUp() throws Exception { this.overlayManager.add(overlay); this.overlayManager.add(itemOverlay); - if (config.isSurpriseExamEnabled()) - { - surpriseExamHelper.startUp(); - } - if (config.isBeekeeperEnabled()) - { - beekeeperHelper.startUp(); - } - if (config.isFreakyForesterEnabled()) - { - freakyForesterHelper.startUp(); - } - if (config.isPinballEnabled()) - { - pinballHelper.startUp(); - } - if (config.isDrillDemonEnabled()) - { - drillDemonHelper.startUp(); - } - if (config.isGravediggerEnabled()) - { - gravediggerHelper.startUp(gravediggerOverlay); - } - if (config.isMimeEnabled()) - { - mimeHelper.startUp(); - } - if (config.isMazeEnabled()) - { - mazeHelper.startUp(); - } - if (config.isSandwichLadyEnabled()) - { - sandwichLadyHelper.startUp(); - } - if (config.isQuizMasterEnabled()) - { - quizMasterHelper.startUp(); - } - if (config.isCaptArnavChestEnabled()) + + pluginModulesMap = ImmutableMap.builder() + .build(); + // Start only the enabled modules + for (PluginModule module : pluginModulesMap.values()) { - pirateHelper.startUp(); + if (module.isEnabled()) + { + module.startUp(); + } } } @@ -162,17 +99,11 @@ protected void shutDown() throws Exception { this.overlayManager.remove(overlay); this.overlayManager.remove(itemOverlay); - surpriseExamHelper.shutDown(); - beekeeperHelper.shutDown(); - freakyForesterHelper.shutDown(); - pinballHelper.shutDown(); - drillDemonHelper.shutDown(); - gravediggerHelper.shutDown(); - mimeHelper.shutDown(); - mazeHelper.shutDown(); - sandwichLadyHelper.shutDown(); - quizMasterHelper.shutDown(); - pirateHelper.shutDown(); + // Shutdown all modules regardless of their enabled state + for (PluginModule module : pluginModulesMap.values()) + { + module.shutdown(); + } } @Subscribe @@ -181,125 +112,17 @@ public void onConfigChanged(ConfigChanged configChanged) if (configChanged.getGroup().equals("randomeventhelper")) { log.debug("Config changed: {} | New value: {}", configChanged.getKey(), configChanged.getNewValue()); - if (configChanged.getKey().equals("isSurpriseExamEnabled")) - { - if (config.isSurpriseExamEnabled()) - { - surpriseExamHelper.startUp(); - } - else - { - surpriseExamHelper.shutDown(); - } - } - else if (configChanged.getKey().equals("isBeekeeperEnabled")) - { - if (config.isBeekeeperEnabled()) - { - beekeeperHelper.startUp(); - } - else - { - beekeeperHelper.shutDown(); - } - } - else if (configChanged.getKey().equals("isFreakyForesterEnabled")) - { - if (config.isFreakyForesterEnabled()) - { - freakyForesterHelper.startUp(); - } - else - { - freakyForesterHelper.shutDown(); - } - } - else if (configChanged.getKey().equals("isPinballEnabled")) - { - if (config.isPinballEnabled()) - { - pinballHelper.startUp(); - } - else - { - pinballHelper.shutDown(); - } - } - else if (configChanged.getKey().equals("isDrillDemonEnabled")) - { - if (config.isDrillDemonEnabled()) - { - drillDemonHelper.startUp(); - } - else - { - drillDemonHelper.shutDown(); - } - } - else if (configChanged.getKey().equals("isGravediggerEnabled")) - { - if (config.isGravediggerEnabled()) - { - gravediggerHelper.startUp(gravediggerOverlay); - } - else - { - gravediggerHelper.shutDown(); - } - } - else if (configChanged.getKey().equals("isMimeEnabled")) - { - if (config.isMimeEnabled()) - { - mimeHelper.startUp(); - } - else - { - mimeHelper.shutDown(); - } - } - else if (configChanged.getKey().equals("isMazeEnabled")) - { - if (config.isMazeEnabled()) - { - mazeHelper.startUp(); - } - else - { - mazeHelper.shutDown(); - } - } - else if (configChanged.getKey().equals("isSandwichLadyEnabled")) - { - if (config.isSandwichLadyEnabled()) - { - sandwichLadyHelper.startUp(); - } - else - { - sandwichLadyHelper.shutDown(); - } - } - else if (configChanged.getKey().equals("isQuizMasterEnabled")) - { - if (config.isQuizMasterEnabled()) - { - quizMasterHelper.startUp(); - } - else - { - quizMasterHelper.shutDown(); - } - } - else if (configChanged.getKey().equals("isCaptArnavChestEnabled")) + // Let's first handle plugin module updates - so lets first check to see if the changed config key is a mapped module + PluginModule module = pluginModulesMap.get(configChanged.getKey()); + if (module != null) { - if (config.isCaptArnavChestEnabled()) + if (module.isEnabled()) { - pirateHelper.startUp(); + module.startUp(); } else { - pirateHelper.shutDown(); + module.shutdown(); } } } diff --git a/src/main/java/randomeventhelper/pluginmodulesystem/PluginModule.java b/src/main/java/randomeventhelper/pluginmodulesystem/PluginModule.java index bb49a8c..3b52d11 100644 --- a/src/main/java/randomeventhelper/pluginmodulesystem/PluginModule.java +++ b/src/main/java/randomeventhelper/pluginmodulesystem/PluginModule.java @@ -5,8 +5,6 @@ import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; import net.runelite.api.GameState; -import net.runelite.client.callback.ClientThread; -import net.runelite.client.config.Config; import net.runelite.client.eventbus.EventBus; import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.util.GameEventManager; @@ -41,6 +39,7 @@ public void startUp() if (client.getGameState().getState() >= GameState.LOGGED_IN.getState()) { // Remember to pass in the instance (this) and not the class (#getClass) + // Re-posts NpcSpawned, PlayerSpawned, WallObjectSpawned, DecorativeObjectSpawned, GroundObjectSpawned, GameObjectSpawned, ItemSpawned, WorldEntitySpawned this.gameEventManager.simulateGameEvents(this); } log.debug("Started the {} module", this.getClass().getSimpleName()); From 191c2b6326f3b784bb79707032015d2b2e22d36e Mon Sep 17 00:00:00 2001 From: Infinitay Date: Sun, 21 Dec 2025 19:11:59 -0500 Subject: [PATCH 03/29] refactor(surpriseexam): Migrate SurpriseExamHelper to PluginModule lifecycle - Refactored SurpriseExamHelper to the modular plugin lifecycle - Now extends PluginModule and implements respective methods, moving the existing start/stop login there - Use constructor injection and removed duplicate field injections - Injected SurpriseExamHelper and added it to the pluginModulesMap --- .../RandomEventHelperPlugin.java | 4 +++ .../surpriseexam/SurpriseExamHelper.java | 31 ++++++++++++------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/main/java/randomeventhelper/RandomEventHelperPlugin.java b/src/main/java/randomeventhelper/RandomEventHelperPlugin.java index 535e018..0e748f7 100644 --- a/src/main/java/randomeventhelper/RandomEventHelperPlugin.java +++ b/src/main/java/randomeventhelper/RandomEventHelperPlugin.java @@ -73,6 +73,9 @@ public class RandomEventHelperPlugin extends Plugin @Inject private RandomEventHelperItemOverlay itemOverlay; + @Inject + private SurpriseExamHelper surpriseExamHelper; + // -> private Map pluginModulesMap; @@ -83,6 +86,7 @@ protected void startUp() throws Exception this.overlayManager.add(itemOverlay); pluginModulesMap = ImmutableMap.builder() + .put("isSurpriseExamEnabled", surpriseExamHelper) .build(); // Start only the enabled modules for (PluginModule module : pluginModulesMap.values()) diff --git a/src/main/java/randomeventhelper/randomevents/surpriseexam/SurpriseExamHelper.java b/src/main/java/randomeventhelper/randomevents/surpriseexam/SurpriseExamHelper.java index dab2c2e..0195368 100644 --- a/src/main/java/randomeventhelper/randomevents/surpriseexam/SurpriseExamHelper.java +++ b/src/main/java/randomeventhelper/randomevents/surpriseexam/SurpriseExamHelper.java @@ -23,20 +23,15 @@ import net.runelite.api.gameval.NpcID; import net.runelite.api.widgets.Widget; import net.runelite.client.callback.ClientThread; -import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.ui.overlay.OverlayManager; +import randomeventhelper.RandomEventHelperConfig; +import randomeventhelper.pluginmodulesystem.PluginModule; @Slf4j @Singleton -public class SurpriseExamHelper +public class SurpriseExamHelper extends PluginModule { - @Inject - private EventBus eventBus; - - @Inject - private Client client; - @Inject private ClientThread clientThread; @@ -111,9 +106,15 @@ public class SurpriseExamHelper InterfaceID.PatternNext.SELECT_3 }; - public void startUp() + @Inject + public SurpriseExamHelper(OverlayManager overlayManager, RandomEventHelperConfig config, Client client) + { + super(overlayManager, config, client); + } + + @Override + public void onStartUp() { - this.eventBus.register(this); this.overlayManager.add(overlay); this.patternCardHint = null; this.patternCardAnswers = null; @@ -123,9 +124,9 @@ public void startUp() this.relationshipSystem = new OSRSItemRelationshipSystem(); } - public void shutDown() + @Override + public void onShutdown() { - this.eventBus.unregister(this); this.overlayManager.remove(overlay); this.patternCardHint = null; this.patternCardAnswers = null; @@ -135,6 +136,12 @@ public void shutDown() this.relationshipSystem = null; } + @Override + public boolean isEnabled() + { + return this.config.isSurpriseExamEnabled(); + } + @Subscribe public void onWidgetLoaded(WidgetLoaded widgetLoaded) { From 172025135bd553ac1ade4104d08e7ffbe16fa254 Mon Sep 17 00:00:00 2001 From: Infinitay Date: Sun, 21 Dec 2025 20:08:48 -0500 Subject: [PATCH 04/29] feat(PluginModule): Add #isLoggedIn to check if the player is logged in --- .../randomeventhelper/pluginmodulesystem/PluginModule.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/randomeventhelper/pluginmodulesystem/PluginModule.java b/src/main/java/randomeventhelper/pluginmodulesystem/PluginModule.java index 3b52d11..49c9cd0 100644 --- a/src/main/java/randomeventhelper/pluginmodulesystem/PluginModule.java +++ b/src/main/java/randomeventhelper/pluginmodulesystem/PluginModule.java @@ -36,7 +36,7 @@ public void startUp() { this.eventBus.register(this); this.onStartUp(); - if (client.getGameState().getState() >= GameState.LOGGED_IN.getState()) + if (this.client.getGameState().getState() >= GameState.LOGGED_IN.getState()) { // Remember to pass in the instance (this) and not the class (#getClass) // Re-posts NpcSpawned, PlayerSpawned, WallObjectSpawned, DecorativeObjectSpawned, GroundObjectSpawned, GameObjectSpawned, ItemSpawned, WorldEntitySpawned @@ -51,4 +51,9 @@ public void shutdown() this.onShutdown(); log.debug("Shutdown the {} module", this.getClass().getSimpleName()); } + + public boolean isLoggedIn() + { + return this.client.getGameState().getState() >= GameState.LOGGED_IN.getState(); + } } From 751e08058f9095914b9dfeffd883c6320ddf3d1b Mon Sep 17 00:00:00 2001 From: Infinitay Date: Sun, 21 Dec 2025 20:09:32 -0500 Subject: [PATCH 05/29] feat(surpriseexam): Improve support for starting during active event - Improved handling initial runs when (re)starting the plugin when already inside the Surprise Exam random event - Primarily for when the puzzle interface is already on screen --- .../surpriseexam/SurpriseExamHelper.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/main/java/randomeventhelper/randomevents/surpriseexam/SurpriseExamHelper.java b/src/main/java/randomeventhelper/randomevents/surpriseexam/SurpriseExamHelper.java index 0195368..573f71c 100644 --- a/src/main/java/randomeventhelper/randomevents/surpriseexam/SurpriseExamHelper.java +++ b/src/main/java/randomeventhelper/randomevents/surpriseexam/SurpriseExamHelper.java @@ -122,6 +122,24 @@ public void onStartUp() this.patternNextAnswer = null; this.patternNextAnswerWidget = null; this.relationshipSystem = new OSRSItemRelationshipSystem(); + + if (this.isLoggedIn()) + { + this.clientThread.invokeLater(() -> { + if (this.client.getWidget(InterfaceID.PatternCards.HINT) != null) + { + WidgetLoaded matchingCardsWidgetLoaded = new WidgetLoaded(); + matchingCardsWidgetLoaded.setGroupId(InterfaceID.PATTERN_CARDS); + this.eventBus.post(matchingCardsWidgetLoaded); + } + if (this.client.getWidget(InterfaceID.PatternNext.UNIVERSE_TEXT12) != null) + { + WidgetLoaded whatsNextWidgetLoaded = new WidgetLoaded(); + whatsNextWidgetLoaded.setGroupId(InterfaceID.PATTERN_NEXT); + this.eventBus.post(whatsNextWidgetLoaded); + } + }); + } } @Override From 78101cec6ac49b5ae485de7f3f41235c0fe09dc5 Mon Sep 17 00:00:00 2001 From: Infinitay Date: Mon, 22 Dec 2025 15:38:28 -0500 Subject: [PATCH 06/29] refactor(captarnav): Migrate PirateHelper to PluginModule lifecycle - Refactored PirateHelper to the modular plugin lifecycle - Now extends PluginModule and implements respective methods, moving the existing start/stop login there - Use constructor injection and removed duplicate field injections - Injected PirateHelper and added it to the pluginModulesMap --- .../RandomEventHelperPlugin.java | 4 +++ .../randomevents/pirate/PirateHelper.java | 31 ++++++++++++------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/main/java/randomeventhelper/RandomEventHelperPlugin.java b/src/main/java/randomeventhelper/RandomEventHelperPlugin.java index 0e748f7..c4f644d 100644 --- a/src/main/java/randomeventhelper/RandomEventHelperPlugin.java +++ b/src/main/java/randomeventhelper/RandomEventHelperPlugin.java @@ -73,6 +73,9 @@ public class RandomEventHelperPlugin extends Plugin @Inject private RandomEventHelperItemOverlay itemOverlay; + @Inject + private PirateHelper pirateHelper; + @Inject private SurpriseExamHelper surpriseExamHelper; @@ -86,6 +89,7 @@ protected void startUp() throws Exception this.overlayManager.add(itemOverlay); pluginModulesMap = ImmutableMap.builder() + .put("isCaptArnavChestEnabled", pirateHelper) .put("isSurpriseExamEnabled", surpriseExamHelper) .build(); // Start only the enabled modules diff --git a/src/main/java/randomeventhelper/randomevents/pirate/PirateHelper.java b/src/main/java/randomeventhelper/randomevents/pirate/PirateHelper.java index dbffc01..4603631 100644 --- a/src/main/java/randomeventhelper/randomevents/pirate/PirateHelper.java +++ b/src/main/java/randomeventhelper/randomevents/pirate/PirateHelper.java @@ -14,22 +14,17 @@ import net.runelite.api.gameval.VarbitID; import net.runelite.api.widgets.Widget; import net.runelite.client.callback.ClientThread; -import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.util.Text; +import randomeventhelper.RandomEventHelperConfig; import randomeventhelper.RandomEventHelperPlugin; +import randomeventhelper.pluginmodulesystem.PluginModule; @Slf4j @Singleton -public class PirateHelper +public class PirateHelper extends PluginModule { - @Inject - private EventBus eventBus; - - @Inject - private Client client; - @Inject private ClientThread clientThread; @@ -49,24 +44,36 @@ public class PirateHelper @Getter private Map widgetMap; - public void startUp() + @Inject + public PirateHelper(OverlayManager overlayManager, RandomEventHelperConfig config, Client client) + { + super(overlayManager, config, client); + } + + @Override + public void onStartUp() { - this.eventBus.register(this); this.overlayManager.add(pirateOverlay); this.pirateChestSolver = new PirateChestSolver(); this.initiallyLoaded = false; this.widgetMap = Maps.newHashMap(); } - public void shutDown() + @Override + public void onShutdown() { - this.eventBus.unregister(this); this.overlayManager.remove(pirateOverlay); this.pirateChestSolver = null; this.initiallyLoaded = false; this.widgetMap = null; } + @Override + public boolean isEnabled() + { + return this.config.isCaptArnavChestEnabled(); + } + @Subscribe public void onVarbitChanged(VarbitChanged varbitChanged) { From b0d167be71b4efd93d31d0bd9e083b2cffb501fc Mon Sep 17 00:00:00 2001 From: Infinitay Date: Tue, 23 Dec 2025 21:49:33 -0500 Subject: [PATCH 07/29] refactor(mime): Migrate MimeHelper to PluginModule lifecycle - Refactored MimeHelper to the modular plugin lifecycle - Now extends PluginModule and implements respective methods, moving the existing start/stop login there - Use constructor injection and removed duplicate field injections - Injected MimeHelper and added it to the pluginModulesMap --- .../RandomEventHelperPlugin.java | 4 +++ .../randomevents/mime/MimeHelper.java | 31 ++++++++++++------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/main/java/randomeventhelper/RandomEventHelperPlugin.java b/src/main/java/randomeventhelper/RandomEventHelperPlugin.java index c4f644d..f8986a9 100644 --- a/src/main/java/randomeventhelper/RandomEventHelperPlugin.java +++ b/src/main/java/randomeventhelper/RandomEventHelperPlugin.java @@ -76,6 +76,9 @@ public class RandomEventHelperPlugin extends Plugin @Inject private PirateHelper pirateHelper; + @Inject + private MimeHelper mimeHelper; + @Inject private SurpriseExamHelper surpriseExamHelper; @@ -90,6 +93,7 @@ protected void startUp() throws Exception pluginModulesMap = ImmutableMap.builder() .put("isCaptArnavChestEnabled", pirateHelper) + .put("isMimeEnabled", mimeHelper) .put("isSurpriseExamEnabled", surpriseExamHelper) .build(); // Start only the enabled modules diff --git a/src/main/java/randomeventhelper/randomevents/mime/MimeHelper.java b/src/main/java/randomeventhelper/randomevents/mime/MimeHelper.java index e87425c..1233da8 100644 --- a/src/main/java/randomeventhelper/randomevents/mime/MimeHelper.java +++ b/src/main/java/randomeventhelper/randomevents/mime/MimeHelper.java @@ -14,21 +14,16 @@ import net.runelite.api.gameval.NpcID; import net.runelite.api.widgets.Widget; import net.runelite.client.callback.ClientThread; -import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.ui.overlay.OverlayManager; +import randomeventhelper.RandomEventHelperConfig; import randomeventhelper.RandomEventHelperPlugin; +import randomeventhelper.pluginmodulesystem.PluginModule; @Slf4j @Singleton -public class MimeHelper +public class MimeHelper extends PluginModule { - @Inject - private EventBus eventBus; - - @Inject - private Client client; - @Inject private ClientThread clientThread; @@ -49,24 +44,36 @@ public class MimeHelper private static final int MIME_RANDOM_EVENT_REGION_ID = 8010; - public void startUp() + @Inject + public MimeHelper(OverlayManager overlayManager, RandomEventHelperConfig config, Client client) + { + super(overlayManager, config, client); + } + + @Override + public void onStartUp() { - this.eventBus.register(this); this.overlayManager.add(mimeOverlay); this.mimeNPC = null; this.currentMimeEmote = null; this.mimeEmoteAnswerWidget = null; } - public void shutDown() + @Override + public void onShutdown() { - this.eventBus.unregister(this); this.overlayManager.remove(mimeOverlay); this.mimeNPC = null; this.currentMimeEmote = null; this.mimeEmoteAnswerWidget = null; } + @Override + public boolean isEnabled() + { + return this.config.isMimeEnabled(); + } + @Subscribe public void onAnimationChanged(AnimationChanged animationChanged) { From 36f21ee696a106e5c13128168e37cae967e89167 Mon Sep 17 00:00:00 2001 From: Infinitay Date: Wed, 24 Dec 2025 00:51:44 -0500 Subject: [PATCH 08/29] feat(mime): Improve support for starting during active event, overlay, refactor - Improved handling initial runs when (re)starting the plugin when already inside the Mime random event - Primarily for when the emote button interface is already on screen - Change Mime text when undetermined emote answer - Use default font size for overlay - Refactored Mime animation checks and answer updating into #updateMimeAnimation --- .../randomevents/mime/MimeHelper.java | 54 ++++++++++++++----- .../randomevents/mime/MimeOverlay.java | 5 +- 2 files changed, 43 insertions(+), 16 deletions(-) diff --git a/src/main/java/randomeventhelper/randomevents/mime/MimeHelper.java b/src/main/java/randomeventhelper/randomevents/mime/MimeHelper.java index 1233da8..05fe7be 100644 --- a/src/main/java/randomeventhelper/randomevents/mime/MimeHelper.java +++ b/src/main/java/randomeventhelper/randomevents/mime/MimeHelper.java @@ -57,6 +57,20 @@ public void onStartUp() this.mimeNPC = null; this.currentMimeEmote = null; this.mimeEmoteAnswerWidget = null; + + // Not really needed since we depend on AnimationChanged, so if the plugin is off, then we won't ever catch it + // And if we do catch the animation, then the widget always loads anyway afterward + if (this.isLoggedIn()) + { + this.clientThread.invokeLater(() -> { + if (this.client.getWidget(InterfaceID.MacroMimeEmotes.BUTTON_0) != null) + { + WidgetLoaded mimeEmoteButtonWidgetLoaded = new WidgetLoaded(); + mimeEmoteButtonWidgetLoaded.setGroupId(InterfaceID.MACRO_MIME_EMOTES); + this.eventBus.post(mimeEmoteButtonWidgetLoaded); + } + }); + } } @Override @@ -90,19 +104,8 @@ public void onAnimationChanged(AnimationChanged animationChanged) { return; } - if (mime.getAnimation() != -1 && mime.getAnimation() != 858) - { - MimeEmote mimeEmote = MimeEmote.getMimeEmoteFromAnimationID(mime.getAnimation()); - this.currentMimeEmote = mimeEmote; - if (mimeEmote != null) - { - log.debug("Mime Animation Detected: {}", mimeEmote); - } - else - { - log.debug("Unknown Mime Animation Detected: Animation ID = {}", mime.getAnimation()); - } - } + + this.updateMimeAnimation(mime); } @Subscribe @@ -141,6 +144,9 @@ public void onNpcSpawned(NpcSpawned npcSpawned) { this.mimeNPC = npcSpawned.getNpc(); log.debug("Mime NPC Spawned, setting mimeNPC: {}", this.mimeNPC); + + // In case the Mime is already doing an emote (starting mid-event, etc.) + this.updateMimeAnimation(this.mimeNPC); } } @@ -155,4 +161,26 @@ public void onNpcDespawned(NpcDespawned npcDespawned) log.debug("Mime NPC Despawned, clearing Mime Random Event data"); } } + + private void updateMimeAnimation(NPC mimeNPC) + { + if (mimeNPC.getAnimation() != -1 && mimeNPC.getAnimation() != 858) + { + MimeEmote mimeEmote = MimeEmote.getMimeEmoteFromAnimationID(mimeNPC.getAnimation()); + if (mimeEmote == this.currentMimeEmote) + { + log.debug("Mime Animation unchanged: {}", mimeEmote); + return; + } + this.currentMimeEmote = mimeEmote; + if (mimeEmote != null) + { + log.debug("Mime Animation Detected: {}", mimeEmote); + } + else + { + log.debug("Unknown Mime Animation Detected: Animation ID = {}", mimeNPC.getAnimation()); + } + } + } } diff --git a/src/main/java/randomeventhelper/randomevents/mime/MimeOverlay.java b/src/main/java/randomeventhelper/randomevents/mime/MimeOverlay.java index faa85a5..4f3b297 100644 --- a/src/main/java/randomeventhelper/randomevents/mime/MimeOverlay.java +++ b/src/main/java/randomeventhelper/randomevents/mime/MimeOverlay.java @@ -42,10 +42,9 @@ public Dimension render(Graphics2D graphics2D) { OverlayUtil.renderPolygon(graphics2D, plugin.getMimeEmoteAnswerWidget().getBounds(), Color.GREEN); } - if (plugin.getMimeNPC() != null && plugin.getCurrentMimeEmote() != null) + if (plugin.getMimeNPC() != null) { - String mimeEmoteText = plugin.getCurrentMimeEmote().name(); - graphics2D.setFont(graphics2D.getFont().deriveFont(18f)); + String mimeEmoteText = plugin.getCurrentMimeEmote() != null ? plugin.getCurrentMimeEmote().name() : "Waiting for emote"; int mimeHeight = plugin.getMimeNPC().getLogicalHeight(); int mimeTextOffset = plugin.getMimeNPC().getAnimationHeightOffset(); Point textPoint = plugin.getMimeNPC().getCanvasTextLocation(graphics2D, mimeEmoteText, mimeHeight + mimeTextOffset); From efc92e9dba9a53ef235442bfdc31af845a067275 Mon Sep 17 00:00:00 2001 From: Infinitay Date: Fri, 26 Dec 2025 03:02:09 -0500 Subject: [PATCH 09/29] refactor(drilldemon): Migrate DrillDemonHelper to PluginModule lifecycle - Refactored DrillDemonHelper to the modular plugin lifecycle - Now extends PluginModule and implements respective methods, moving the existing start/stop login there - Use constructor injection and removed duplicate field injections - Injected DrillDemonHelper and added it to the pluginModulesMap --- .../RandomEventHelperPlugin.java | 4 +++ .../drilldemon/DrillDemonHelper.java | 31 ++++++++++++------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/main/java/randomeventhelper/RandomEventHelperPlugin.java b/src/main/java/randomeventhelper/RandomEventHelperPlugin.java index f8986a9..b04fa55 100644 --- a/src/main/java/randomeventhelper/RandomEventHelperPlugin.java +++ b/src/main/java/randomeventhelper/RandomEventHelperPlugin.java @@ -76,6 +76,9 @@ public class RandomEventHelperPlugin extends Plugin @Inject private PirateHelper pirateHelper; + @Inject + private DrillDemonHelper drillDemonHelper; + @Inject private MimeHelper mimeHelper; @@ -93,6 +96,7 @@ protected void startUp() throws Exception pluginModulesMap = ImmutableMap.builder() .put("isCaptArnavChestEnabled", pirateHelper) + .put("isDrillDemonEnabled", drillDemonHelper) .put("isMimeEnabled", mimeHelper) .put("isSurpriseExamEnabled", surpriseExamHelper) .build(); diff --git a/src/main/java/randomeventhelper/randomevents/drilldemon/DrillDemonHelper.java b/src/main/java/randomeventhelper/randomevents/drilldemon/DrillDemonHelper.java index 6735f44..7d961a3 100644 --- a/src/main/java/randomeventhelper/randomevents/drilldemon/DrillDemonHelper.java +++ b/src/main/java/randomeventhelper/randomevents/drilldemon/DrillDemonHelper.java @@ -21,22 +21,17 @@ import net.runelite.api.gameval.NpcID; import net.runelite.api.gameval.ObjectID; import net.runelite.api.gameval.VarbitID; -import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.util.Text; +import randomeventhelper.RandomEventHelperConfig; import randomeventhelper.RandomEventHelperPlugin; +import randomeventhelper.pluginmodulesystem.PluginModule; @Slf4j @Singleton -public class DrillDemonHelper +public class DrillDemonHelper extends PluginModule { - @Inject - private EventBus eventBus; - - @Inject - private Client client; - @Inject private OverlayManager overlayManager; @@ -60,9 +55,15 @@ public class DrillDemonHelper @Getter private DrillExercise requestedExercise; - public void startUp() + @Inject + public DrillDemonHelper(OverlayManager overlayManager, RandomEventHelperConfig config, Client client) + { + super(overlayManager, config, client); + } + + @Override + public void onStartUp() { - this.eventBus.register(this); this.overlayManager.add(drillDemonOverlay); this.exerciseMatsAnswerList = Lists.newArrayListWithExpectedSize(4); this.exerciseMatsMultimap = HashMultimap.create(4, 2); @@ -72,9 +73,9 @@ public void startUp() this.requestedExercise = null; } - public void shutDown() + @Override + public void onShutdown() { - this.eventBus.unregister(this); this.overlayManager.remove(drillDemonOverlay); this.exerciseMatsAnswerList = null; this.exerciseMatsMultimap = null; @@ -84,6 +85,12 @@ public void shutDown() this.requestedExercise = null; } + @Override + public boolean isEnabled() + { + return this.config.isDrillDemonEnabled(); + } + @Subscribe public void onNpcSpawned(NpcSpawned npcSpawned) { From 773da8d43420c4cce13d21370792134729f73bf9 Mon Sep 17 00:00:00 2001 From: Infinitay Date: Fri, 26 Dec 2025 05:12:07 -0500 Subject: [PATCH 10/29] feat(drilldemon): Improve support for starting during active event - Improved handling initial runs when (re)starting the plugin when already inside the Drill Demon random event - Fix race condition issue with events - primarily regarding #onGroundObjectSpawned and exerciseMatsMultimap --- .../drilldemon/DrillDemonHelper.java | 49 ++++++++++++------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/src/main/java/randomeventhelper/randomevents/drilldemon/DrillDemonHelper.java b/src/main/java/randomeventhelper/randomevents/drilldemon/DrillDemonHelper.java index 7d961a3..32d57ec 100644 --- a/src/main/java/randomeventhelper/randomevents/drilldemon/DrillDemonHelper.java +++ b/src/main/java/randomeventhelper/randomevents/drilldemon/DrillDemonHelper.java @@ -21,6 +21,7 @@ import net.runelite.api.gameval.NpcID; import net.runelite.api.gameval.ObjectID; import net.runelite.api.gameval.VarbitID; +import net.runelite.client.callback.ClientThread; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.util.Text; @@ -32,6 +33,9 @@ @Singleton public class DrillDemonHelper extends PluginModule { + @Inject + private ClientThread clientThread; + @Inject private OverlayManager overlayManager; @@ -47,8 +51,6 @@ public class DrillDemonHelper extends PluginModule // private Multimap exerciseVarbitMatMultimap; - private boolean initialRun; - @Getter private NPC drillDemonNPC; @@ -68,9 +70,23 @@ public void onStartUp() this.exerciseMatsAnswerList = Lists.newArrayListWithExpectedSize(4); this.exerciseMatsMultimap = HashMultimap.create(4, 2); this.exerciseVarbitMatMultimap = HashMultimap.create(4, 2); - this.initialRun = true; this.drillDemonNPC = null; this.requestedExercise = null; + + if (this.isLoggedIn()) { + this.clientThread.invoke(() -> + { + log.debug("Initializing varbits for Drill Demon exercise mappings in case plugin was enabled mid-event."); + for (int postVarbitID = VarbitID.MACRO_DRILLDEMON_POST_1; postVarbitID <= VarbitID.MACRO_DRILLDEMON_POST_4; postVarbitID++) + { + int postVarbitValue = client.getVarbitValue(postVarbitID); + VarbitChanged varbitChangedEvent = new VarbitChanged(); + varbitChangedEvent.setVarbitId(postVarbitID); + varbitChangedEvent.setValue(postVarbitValue); + this.onVarbitChanged(varbitChangedEvent); + } + }); + } } @Override @@ -80,7 +96,6 @@ public void onShutdown() this.exerciseMatsAnswerList = null; this.exerciseMatsMultimap = null; this.exerciseVarbitMatMultimap = null; - this.initialRun = true; this.drillDemonNPC = null; this.requestedExercise = null; } @@ -99,19 +114,6 @@ public void onNpcSpawned(NpcSpawned npcSpawned) if (npcSpawned.getNpc().getId() == NpcID.MACRO_DRILLDEMON && this.isInDrillDemonLocalInstance() && (this.drillDemonNPC == null || isNPCInteractingWithPlayer)) { this.drillDemonNPC = npcSpawned.getNpc(); - if (this.initialRun) - { - log.debug("Initializing varbits for Drill Demon exercise mappings in case plugin was enabled mid-event."); - int post1Varbit = client.getVarbitValue(VarbitID.MACRO_DRILLDEMON_POST_1); - int post2Varbit = client.getVarbitValue(VarbitID.MACRO_DRILLDEMON_POST_2); - int post3Varbit = client.getVarbitValue(VarbitID.MACRO_DRILLDEMON_POST_3); - int post4Varbit = client.getVarbitValue(VarbitID.MACRO_DRILLDEMON_POST_4); - this.updateExerciseMappings(post1Varbit, 1); - this.updateExerciseMappings(post2Varbit, 2); - this.updateExerciseMappings(post3Varbit, 3); - this.updateExerciseMappings(post4Varbit, 4); - this.initialRun = false; - } } } @@ -124,7 +126,6 @@ public void onNpcDespawned(NpcDespawned npcDespawned) this.exerciseMatsAnswerList.clear(); this.exerciseMatsMultimap.clear(); this.exerciseVarbitMatMultimap.clear(); - this.initialRun = true; this.drillDemonNPC = null; this.requestedExercise = null; } @@ -195,27 +196,39 @@ public void onGroundObjectSpawned(GroundObjectSpawned groundObjectSpawned) { if (this.isInDrillDemonLocalInstance()) { + int addedPost = -1; switch (groundObjectSpawned.getGroundObject().getId()) { case ObjectID.BARRACK_MAT_1: exerciseMatsMultimap.put(1, groundObjectSpawned.getGroundObject()); log.debug("Added exercise mat with ID {} to post 1", groundObjectSpawned.getGroundObject().getId()); + addedPost = 1; break; case ObjectID.BARRACK_MAT_2: exerciseMatsMultimap.put(2, groundObjectSpawned.getGroundObject()); log.debug("Added exercise mat with ID {} to post 2", groundObjectSpawned.getGroundObject().getId()); + addedPost = 2; break; case ObjectID.BARRACK_MAT_3: exerciseMatsMultimap.put(3, groundObjectSpawned.getGroundObject()); log.debug("Added exercise mat with ID {} to post 3", groundObjectSpawned.getGroundObject().getId()); + addedPost = 3; break; case ObjectID.BARRACK_MAT_4: exerciseMatsMultimap.put(4, groundObjectSpawned.getGroundObject()); log.debug("Added exercise mat with ID {} to post 4", groundObjectSpawned.getGroundObject().getId()); + addedPost = 4; break; default: break; } + + if (addedPost != -1) + { + // Update the mappings in case the mats spawned after the varbits were set + int postVarbit = client.getVarbitValue(VarbitID.MACRO_DRILLDEMON_POST_1 + (addedPost - 1)); + this.updateExerciseMappings(postVarbit, addedPost); + } } } From 3bfbc057872b28af9506d8e796e81c961891a82e Mon Sep 17 00:00:00 2001 From: Infinitay Date: Fri, 26 Dec 2025 19:19:14 -0500 Subject: [PATCH 11/29] refactor(beekeeper): Migrate BeekeeperHelper to PluginModule lifecycle - Refactored BeekeeperHelper to the modular plugin lifecycle - Now extends PluginModule and implements respective methods, moving the existing start/stop login there - Use constructor injection and removed duplicate field injections - Injected BeekeeperHelper and added it to the pluginModulesMap --- .../RandomEventHelperPlugin.java | 4 +++ .../beekeeper/BeekeeperHelper.java | 32 +++++++++++-------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/main/java/randomeventhelper/RandomEventHelperPlugin.java b/src/main/java/randomeventhelper/RandomEventHelperPlugin.java index b04fa55..44e915f 100644 --- a/src/main/java/randomeventhelper/RandomEventHelperPlugin.java +++ b/src/main/java/randomeventhelper/RandomEventHelperPlugin.java @@ -73,6 +73,9 @@ public class RandomEventHelperPlugin extends Plugin @Inject private RandomEventHelperItemOverlay itemOverlay; + @Inject + private BeekeeperHelper beekeeperHelper; + @Inject private PirateHelper pirateHelper; @@ -95,6 +98,7 @@ protected void startUp() throws Exception this.overlayManager.add(itemOverlay); pluginModulesMap = ImmutableMap.builder() + .put("isBeekeeperEnabled", beekeeperHelper) .put("isCaptArnavChestEnabled", pirateHelper) .put("isDrillDemonEnabled", drillDemonHelper) .put("isMimeEnabled", mimeHelper) diff --git a/src/main/java/randomeventhelper/randomevents/beekeeper/BeekeeperHelper.java b/src/main/java/randomeventhelper/randomevents/beekeeper/BeekeeperHelper.java index 0275a72..be97713 100644 --- a/src/main/java/randomeventhelper/randomevents/beekeeper/BeekeeperHelper.java +++ b/src/main/java/randomeventhelper/randomevents/beekeeper/BeekeeperHelper.java @@ -15,21 +15,15 @@ import net.runelite.api.gameval.NpcID; import net.runelite.api.widgets.Widget; import net.runelite.client.callback.ClientThread; -import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.plugins.Plugin; import net.runelite.client.ui.overlay.OverlayManager; +import randomeventhelper.RandomEventHelperConfig; +import randomeventhelper.pluginmodulesystem.PluginModule; @Slf4j @Singleton -public class BeekeeperHelper extends Plugin +public class BeekeeperHelper extends PluginModule { - @Inject - private EventBus eventBus; - - @Inject - private Client client; - @Inject private ClientThread clientThread; @@ -42,20 +36,32 @@ public class BeekeeperHelper extends Plugin @Getter private ImmutableList beehiveAnswerWidgets; - public void startUp() + @Inject + public BeekeeperHelper(OverlayManager overlayManager, RandomEventHelperConfig config, Client client) + { + super(overlayManager, config, client); + } + + @Override + public void onStartUp() { - this.eventBus.register(this); this.overlayManager.add(beekeeperOverlay); this.beehiveAnswerWidgets = null; } - public void shutDown() + @Override + public void onShutdown() { - this.eventBus.unregister(this); this.overlayManager.remove(beekeeperOverlay); this.beehiveAnswerWidgets = null; } + @Override + public boolean isEnabled() + { + return this.config.isBeekeeperEnabled(); + } + @Subscribe public void onWidgetLoaded(WidgetLoaded widgetLoaded) { From 84470ec80587c38b7f856120e6c8646d59a7d0e7 Mon Sep 17 00:00:00 2001 From: Infinitay Date: Fri, 26 Dec 2025 21:16:43 -0500 Subject: [PATCH 12/29] feat(beekeeper): Improve support for starting during active event - Improved handling initial runs when (re)starting the plugin when already inside the Beekeeper random event - Avoid constantly appending corresponding number to destination widget label --- .../beekeeper/BeekeeperHelper.java | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/main/java/randomeventhelper/randomevents/beekeeper/BeekeeperHelper.java b/src/main/java/randomeventhelper/randomevents/beekeeper/BeekeeperHelper.java index be97713..7dadcf2 100644 --- a/src/main/java/randomeventhelper/randomevents/beekeeper/BeekeeperHelper.java +++ b/src/main/java/randomeventhelper/randomevents/beekeeper/BeekeeperHelper.java @@ -47,6 +47,18 @@ public void onStartUp() { this.overlayManager.add(beekeeperOverlay); this.beehiveAnswerWidgets = null; + + if (this.isLoggedIn()) + { + this.clientThread.invokeLater(() -> { + if (this.client.getWidget(InterfaceID.Beehive.EXAMPLE) != null) + { + WidgetLoaded beehiveExampleWidgetLoaded = new WidgetLoaded(); + beehiveExampleWidgetLoaded.setGroupId(InterfaceID.BEEHIVE); + this.eventBus.post(beehiveExampleWidgetLoaded); + } + }); + } } @Override @@ -78,10 +90,10 @@ public void onWidgetLoaded(WidgetLoaded widgetLoaded) Widget destination4LayerWidget = this.client.getWidget(InterfaceID.Beehive.UNIVERSE_TEXT14); if (destination1LayerWidget != null && destination2LayerWidget != null && destination3LayerWidget != null && destination4LayerWidget != null) { - destination1LayerWidget.setText("1. " + destination1LayerWidget.getText()); - destination2LayerWidget.setText("2. " + destination2LayerWidget.getText()); - destination3LayerWidget.setText("3. " + destination3LayerWidget.getText()); - destination4LayerWidget.setText("4. " + destination4LayerWidget.getText()); + destination1LayerWidget.setText(destination1LayerWidget.getText().contains(".") ? destination1LayerWidget.getText() : "1. " + destination1LayerWidget.getText()); + destination2LayerWidget.setText(destination2LayerWidget.getText().contains(".") ? destination2LayerWidget.getText() : "2. " + destination2LayerWidget.getText()); + destination3LayerWidget.setText(destination3LayerWidget.getText().contains(".") ? destination3LayerWidget.getText() : "3. " + destination3LayerWidget.getText()); + destination4LayerWidget.setText(destination4LayerWidget.getText().contains(".") ? destination4LayerWidget.getText() : "4. " + destination4LayerWidget.getText()); } else { From 40374435e5111cba29b90f94c9556ec055e8e4eb Mon Sep 17 00:00:00 2001 From: Infinitay Date: Sat, 27 Dec 2025 02:56:19 -0500 Subject: [PATCH 13/29] feat(captarnav): Improve support for starting during active event - Improved handling initial runs when (re)starting the plugin when doing Capt' Arnav's Chest random event - Add missing isSolved = false assignment within PirateChestSolver#isChestCorrectlySet --- .../randomevents/pirate/PirateChestSolver.java | 1 + .../randomevents/pirate/PirateHelper.java | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/src/main/java/randomeventhelper/randomevents/pirate/PirateChestSolver.java b/src/main/java/randomeventhelper/randomevents/pirate/PirateChestSolver.java index 9a0e3d8..b889aba 100644 --- a/src/main/java/randomeventhelper/randomevents/pirate/PirateChestSolver.java +++ b/src/main/java/randomeventhelper/randomevents/pirate/PirateChestSolver.java @@ -101,6 +101,7 @@ public boolean isChestCorrectlySet() log.debug("Pirate chest locks are correctly set."); return true; } + this.isSolved = false; log.debug("Pirate chest locks are not correctly set."); return false; } diff --git a/src/main/java/randomeventhelper/randomevents/pirate/PirateHelper.java b/src/main/java/randomeventhelper/randomevents/pirate/PirateHelper.java index 4603631..3c168f3 100644 --- a/src/main/java/randomeventhelper/randomevents/pirate/PirateHelper.java +++ b/src/main/java/randomeventhelper/randomevents/pirate/PirateHelper.java @@ -57,6 +57,18 @@ public void onStartUp() this.pirateChestSolver = new PirateChestSolver(); this.initiallyLoaded = false; this.widgetMap = Maps.newHashMap(); + + if (this.isLoggedIn()) + { + this.clientThread.invokeLater(() -> { + if (this.client.getWidget(this.CONFIRM_BUTTON_WIDGET_ID) != null) + { + WidgetLoaded chestConfirmButtonWidgetLoaded = new WidgetLoaded(); + chestConfirmButtonWidgetLoaded.setGroupId(InterfaceID.PIRATE_COMBILOCK); + this.eventBus.post(chestConfirmButtonWidgetLoaded); + } + }); + } } @Override From 289a0eac7ffad9165939b5086a800bbb3c5a470a Mon Sep 17 00:00:00 2001 From: Infinitay Date: Sat, 27 Dec 2025 15:08:12 -0500 Subject: [PATCH 14/29] refactor(quizmaster): Migrate QuizMasterHelper to PluginModule lifecycle - Refactored QuizMasterHelper to the modular plugin lifecycle - Now extends PluginModule and implements respective methods, moving the existing start/stop login there - Use constructor injection and removed duplicate field injections - Injected QuizMasterHelper and added it to the pluginModulesMap --- .../RandomEventHelperPlugin.java | 4 +++ .../quizmaster/QuizMasterHelper.java | 31 ++++++++++++------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/main/java/randomeventhelper/RandomEventHelperPlugin.java b/src/main/java/randomeventhelper/RandomEventHelperPlugin.java index 44e915f..62edf6b 100644 --- a/src/main/java/randomeventhelper/RandomEventHelperPlugin.java +++ b/src/main/java/randomeventhelper/RandomEventHelperPlugin.java @@ -88,6 +88,9 @@ public class RandomEventHelperPlugin extends Plugin @Inject private SurpriseExamHelper surpriseExamHelper; + @Inject + private QuizMasterHelper quizMasterHelper; + // -> private Map pluginModulesMap; @@ -103,6 +106,7 @@ protected void startUp() throws Exception .put("isDrillDemonEnabled", drillDemonHelper) .put("isMimeEnabled", mimeHelper) .put("isSurpriseExamEnabled", surpriseExamHelper) + .put("isQuizMasterEnabled", quizMasterHelper) .build(); // Start only the enabled modules for (PluginModule module : pluginModulesMap.values()) diff --git a/src/main/java/randomeventhelper/randomevents/quizmaster/QuizMasterHelper.java b/src/main/java/randomeventhelper/randomevents/quizmaster/QuizMasterHelper.java index 61c2fbc..cf749be 100644 --- a/src/main/java/randomeventhelper/randomevents/quizmaster/QuizMasterHelper.java +++ b/src/main/java/randomeventhelper/randomevents/quizmaster/QuizMasterHelper.java @@ -17,20 +17,15 @@ import net.runelite.api.gameval.NpcID; import net.runelite.api.widgets.Widget; import net.runelite.client.callback.ClientThread; -import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.ui.overlay.OverlayManager; +import randomeventhelper.RandomEventHelperConfig; +import randomeventhelper.pluginmodulesystem.PluginModule; @Slf4j @Singleton -public class QuizMasterHelper +public class QuizMasterHelper extends PluginModule { - @Inject - private EventBus eventBus; - - @Inject - private Client client; - @Inject private ClientThread clientThread; @@ -43,20 +38,32 @@ public class QuizMasterHelper @Getter private Widget quizAnswerWidget; - public void startUp() + @Inject + public QuizMasterHelper(OverlayManager overlayManager, RandomEventHelperConfig config, Client client) + { + super(overlayManager, config, client); + } + + @Override + public void onStartUp() { - this.eventBus.register(this); this.overlayManager.add(quizMasterOverlay); this.quizAnswerWidget = null; } - public void shutDown() + @Override + public void onShutdown() { - this.eventBus.unregister(this); this.overlayManager.remove(quizMasterOverlay); this.quizAnswerWidget = null; } + @Override + public boolean isEnabled() + { + return this.config.isQuizMasterEnabled(); + } + @Subscribe public void onWidgetLoaded(WidgetLoaded widgetLoaded) { From ae37e9e65c7260b437f0a942f6cd3513323bf0d9 Mon Sep 17 00:00:00 2001 From: Infinitay Date: Sat, 27 Dec 2025 17:27:24 -0500 Subject: [PATCH 15/29] feat(quizmaster): Improve support for starting during active event - Improved handling initial runs when (re)starting the plugin when doing Quiz Master random event --- .../randomevents/quizmaster/QuizMasterHelper.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/randomeventhelper/randomevents/quizmaster/QuizMasterHelper.java b/src/main/java/randomeventhelper/randomevents/quizmaster/QuizMasterHelper.java index cf749be..dab726e 100644 --- a/src/main/java/randomeventhelper/randomevents/quizmaster/QuizMasterHelper.java +++ b/src/main/java/randomeventhelper/randomevents/quizmaster/QuizMasterHelper.java @@ -49,6 +49,18 @@ public void onStartUp() { this.overlayManager.add(quizMasterOverlay); this.quizAnswerWidget = null; + + if (this.isLoggedIn()) + { + this.clientThread.invokeLater(() -> { + if (this.client.getWidget(InterfaceID.MacroQuizshow.BUTTONS) != null) + { + WidgetLoaded quizMasterButtonsWidgetLoaded = new WidgetLoaded(); + quizMasterButtonsWidgetLoaded.setGroupId(InterfaceID.MACRO_QUIZSHOW); + this.eventBus.post(quizMasterButtonsWidgetLoaded); + } + }); + } } @Override From 40a2f7145cfdf4212d84e7c73da80c77ad84514f Mon Sep 17 00:00:00 2001 From: Infinitay Date: Sun, 28 Dec 2025 02:16:52 -0500 Subject: [PATCH 16/29] refactor(sandwich): Migrate SandwichLadyHelper to PluginModule lifecycle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Refactored SandwichLadyHelper to the modular plugin lifecycle     - Now extends PluginModule and implements respective methods, moving the existing start/stop login there     - Use constructor injection and removed duplicate field injections - Injected SandwichLadyHelper and added it to the pluginModulesMap --- .../RandomEventHelperPlugin.java | 4 +++ .../sandwichlady/SandwichLadyHelper.java | 30 ++++++++++++------- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/main/java/randomeventhelper/RandomEventHelperPlugin.java b/src/main/java/randomeventhelper/RandomEventHelperPlugin.java index 62edf6b..cacd413 100644 --- a/src/main/java/randomeventhelper/RandomEventHelperPlugin.java +++ b/src/main/java/randomeventhelper/RandomEventHelperPlugin.java @@ -85,6 +85,9 @@ public class RandomEventHelperPlugin extends Plugin @Inject private MimeHelper mimeHelper; + @Inject + private SandwichLadyHelper sandwichLadyHelper; + @Inject private SurpriseExamHelper surpriseExamHelper; @@ -105,6 +108,7 @@ protected void startUp() throws Exception .put("isCaptArnavChestEnabled", pirateHelper) .put("isDrillDemonEnabled", drillDemonHelper) .put("isMimeEnabled", mimeHelper) + .put("isSandwichLadyEnabled", sandwichLadyHelper) .put("isSurpriseExamEnabled", surpriseExamHelper) .put("isQuizMasterEnabled", quizMasterHelper) .build(); diff --git a/src/main/java/randomeventhelper/randomevents/sandwichlady/SandwichLadyHelper.java b/src/main/java/randomeventhelper/randomevents/sandwichlady/SandwichLadyHelper.java index 4543a33..85ed327 100644 --- a/src/main/java/randomeventhelper/randomevents/sandwichlady/SandwichLadyHelper.java +++ b/src/main/java/randomeventhelper/randomevents/sandwichlady/SandwichLadyHelper.java @@ -12,21 +12,16 @@ import net.runelite.api.gameval.InterfaceID; import net.runelite.api.widgets.Widget; import net.runelite.client.callback.ClientThread; -import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.util.Text; +import randomeventhelper.RandomEventHelperConfig; +import randomeventhelper.pluginmodulesystem.PluginModule; @Slf4j @Singleton -public class SandwichLadyHelper +public class SandwichLadyHelper extends PluginModule { - @Inject - private EventBus eventBus; - - @Inject - private Client client; - @Inject private ClientThread clientThread; @@ -42,9 +37,15 @@ public class SandwichLadyHelper private final String SANDWICH_LADY_TRAY_REGEX = "Have a (?[\\w\\s]+) for free!"; private final Pattern SANDWICH_LADY_PATTERN = Pattern.compile(SANDWICH_LADY_TRAY_REGEX, Pattern.CASE_INSENSITIVE); - public void startUp() + @Inject + public SandwichLadyHelper(OverlayManager overlayManager, RandomEventHelperConfig config, Client client) + { + super(overlayManager, config, client); + } + + @Override + public void onStartUp() { - this.eventBus.register(this); this.overlayManager.add(sandwichLadyOverlay); this.trayFoodAnswerWidget = null; WidgetLoaded temp = new WidgetLoaded(); @@ -52,13 +53,20 @@ public void startUp() onWidgetLoaded(temp); } - public void shutDown() + @Override + public void onShutdown() { this.eventBus.unregister(this); this.overlayManager.remove(sandwichLadyOverlay); this.trayFoodAnswerWidget = null; } + @Override + public boolean isEnabled() + { + return this.config.isSandwichLadyEnabled(); + } + @Subscribe public void onWidgetLoaded(WidgetLoaded widgetLoaded) { From f1f43779bb08e858036ed3caf3503a460c7bf0ff Mon Sep 17 00:00:00 2001 From: Infinitay Date: Sun, 28 Dec 2025 02:42:56 -0500 Subject: [PATCH 17/29] feat(sandwich): Improve support for starting during active event - Improved handling initial runs when (re)starting the plugin when doing Sandwich Lady random event --- .../sandwichlady/SandwichLadyHelper.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/main/java/randomeventhelper/randomevents/sandwichlady/SandwichLadyHelper.java b/src/main/java/randomeventhelper/randomevents/sandwichlady/SandwichLadyHelper.java index 85ed327..280c1df 100644 --- a/src/main/java/randomeventhelper/randomevents/sandwichlady/SandwichLadyHelper.java +++ b/src/main/java/randomeventhelper/randomevents/sandwichlady/SandwichLadyHelper.java @@ -48,9 +48,18 @@ public void onStartUp() { this.overlayManager.add(sandwichLadyOverlay); this.trayFoodAnswerWidget = null; - WidgetLoaded temp = new WidgetLoaded(); - temp.setGroupId(InterfaceID.SANDWICH_TRAY); - onWidgetLoaded(temp); + + if (this.isLoggedIn()) + { + this.clientThread.invokeLater(() -> { + if (this.client.getWidget(InterfaceID.SandwichTray.SANDWHICH_REFRESHMENT_LAYER) != null) + { + WidgetLoaded sandwichLadyTrayRefreshmentWidgetLoaded = new WidgetLoaded(); + sandwichLadyTrayRefreshmentWidgetLoaded.setGroupId(InterfaceID.SANDWICH_TRAY); + this.eventBus.post(sandwichLadyTrayRefreshmentWidgetLoaded); + } + }); + } } @Override From c3d688367b23a25a863b48e9db5d11419f3edea6 Mon Sep 17 00:00:00 2001 From: Infinitay Date: Sun, 28 Dec 2025 05:00:30 -0500 Subject: [PATCH 18/29] refactor(gravedigger): Migrate GravediggerHelper to PluginModule lifecycle - Refactored GravediggerHelper to the modular plugin lifecycle - Now extends PluginModule and implements respective methods, moving the existing start/stop login there - Use constructor injection and removed duplicate field injections - Re-inject GravediggerOverlay - Injected GravediggerHelper and added it to the pluginModulesMap --- .../RandomEventHelperPlugin.java | 5 ++- .../gravedigger/GravediggerHelper.java | 34 +++++++++++-------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/main/java/randomeventhelper/RandomEventHelperPlugin.java b/src/main/java/randomeventhelper/RandomEventHelperPlugin.java index cacd413..dcf8a0f 100644 --- a/src/main/java/randomeventhelper/RandomEventHelperPlugin.java +++ b/src/main/java/randomeventhelper/RandomEventHelperPlugin.java @@ -37,7 +37,6 @@ import randomeventhelper.randomevents.drilldemon.DrillDemonHelper; import randomeventhelper.randomevents.freakyforester.FreakyForesterHelper; import randomeventhelper.randomevents.gravedigger.GravediggerHelper; -import randomeventhelper.randomevents.gravedigger.GravediggerOverlay; import randomeventhelper.randomevents.maze.MazeHelper; import randomeventhelper.randomevents.mime.MimeHelper; import randomeventhelper.randomevents.pinball.PinballHelper; @@ -82,6 +81,9 @@ public class RandomEventHelperPlugin extends Plugin @Inject private DrillDemonHelper drillDemonHelper; + @Inject + private GravediggerHelper gravediggerHelper; + @Inject private MimeHelper mimeHelper; @@ -107,6 +109,7 @@ protected void startUp() throws Exception .put("isBeekeeperEnabled", beekeeperHelper) .put("isCaptArnavChestEnabled", pirateHelper) .put("isDrillDemonEnabled", drillDemonHelper) + .put("isGravediggerEnabled", gravediggerHelper) .put("isMimeEnabled", mimeHelper) .put("isSandwichLadyEnabled", sandwichLadyHelper) .put("isSurpriseExamEnabled", surpriseExamHelper) diff --git a/src/main/java/randomeventhelper/randomevents/gravedigger/GravediggerHelper.java b/src/main/java/randomeventhelper/randomevents/gravedigger/GravediggerHelper.java index 2aa2d4a..75df5a8 100644 --- a/src/main/java/randomeventhelper/randomevents/gravedigger/GravediggerHelper.java +++ b/src/main/java/randomeventhelper/randomevents/gravedigger/GravediggerHelper.java @@ -30,23 +30,18 @@ import net.runelite.api.gameval.InventoryID; import net.runelite.api.gameval.NpcID; import net.runelite.api.gameval.VarbitID; -import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.game.ItemManager; import net.runelite.client.game.SpriteManager; import net.runelite.client.ui.overlay.OverlayManager; +import randomeventhelper.RandomEventHelperConfig; import randomeventhelper.RandomEventHelperPlugin; +import randomeventhelper.pluginmodulesystem.PluginModule; @Slf4j @Singleton -public class GravediggerHelper +public class GravediggerHelper extends PluginModule { - @Inject - private EventBus eventBus; - - @Inject - private Client client; - @Inject private ItemManager itemManager; @@ -56,6 +51,7 @@ public class GravediggerHelper @Inject private OverlayManager overlayManager; + @Inject private GravediggerOverlay gravediggerOverlay; @Inject @@ -79,10 +75,15 @@ public class GravediggerHelper @Getter private Set coffinsInInventory; - public void startUp(GravediggerOverlay gravediggerOverlay) + @Inject + public GravediggerHelper(OverlayManager overlayManager, RandomEventHelperConfig config, Client client) + { + super(overlayManager, config, client); + } + + @Override + public void onStartUp() { - this.gravediggerOverlay = gravediggerOverlay; - this.eventBus.register(this); this.overlayManager.add(this.gravediggerOverlay); this.overlayManager.add(gravediggerItemOverlay); this.initiallyEnteredGraveDiggerArea = true; @@ -94,13 +95,12 @@ public void startUp(GravediggerOverlay gravediggerOverlay) this.coffinsInInventory = Sets.newHashSetWithExpectedSize(5); } - public void shutDown() + @Override + public void onShutdown() { - this.eventBus.unregister(this); if (this.gravediggerOverlay != null) { this.overlayManager.remove(gravediggerOverlay); - this.gravediggerOverlay = null; } this.overlayManager.remove(gravediggerItemOverlay); this.initiallyEnteredGraveDiggerArea = true; @@ -112,6 +112,12 @@ public void shutDown() this.coffinsInInventory = null; } + @Override + public boolean isEnabled() + { + return this.config.isGravediggerEnabled(); + } + @Subscribe public void onGameTick(GameTick gameTick) { From 8b65c1f9af75c3945c257b214d8b1b1efa54a068 Mon Sep 17 00:00:00 2001 From: Infinitay Date: Sun, 28 Dec 2025 06:13:57 -0500 Subject: [PATCH 19/29] feat(gravedigger): Improve support for starting during active event - Improved handling initial runs when (re)starting the plugin when doing Gravedigger random event - Removed reliance on #onGameTick and `initiallyEnteredGraveDiggerArea` - Allow the plugin lifecycle's #startUp and specifically GameEventManager#simulateGameEvents to handle re-posting events - Migrate over ItemContainerChanged and VarbitChanged re-posts and fetching of sprites/images to #onStartUp - Removed unnecessary event listeners for GameTick and NpcSpawned --- .../gravedigger/GravediggerHelper.java | 146 ++++++------------ 1 file changed, 43 insertions(+), 103 deletions(-) diff --git a/src/main/java/randomeventhelper/randomevents/gravedigger/GravediggerHelper.java b/src/main/java/randomeventhelper/randomevents/gravedigger/GravediggerHelper.java index 75df5a8..fc5d047 100644 --- a/src/main/java/randomeventhelper/randomevents/gravedigger/GravediggerHelper.java +++ b/src/main/java/randomeventhelper/randomevents/gravedigger/GravediggerHelper.java @@ -18,18 +18,15 @@ import net.runelite.api.Client; import net.runelite.api.GameObject; import net.runelite.api.Item; -import net.runelite.api.NPC; -import net.runelite.api.Tile; import net.runelite.api.events.GameObjectSpawned; -import net.runelite.api.events.GameTick; import net.runelite.api.events.ItemContainerChanged; import net.runelite.api.events.MenuEntryAdded; import net.runelite.api.events.NpcDespawned; -import net.runelite.api.events.NpcSpawned; import net.runelite.api.events.VarbitChanged; import net.runelite.api.gameval.InventoryID; import net.runelite.api.gameval.NpcID; import net.runelite.api.gameval.VarbitID; +import net.runelite.client.callback.ClientThread; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.game.ItemManager; import net.runelite.client.game.SpriteManager; @@ -43,13 +40,13 @@ public class GravediggerHelper extends PluginModule { @Inject - private ItemManager itemManager; + private ClientThread clientThread; @Inject - private SpriteManager spriteManager; + private ItemManager itemManager; @Inject - private OverlayManager overlayManager; + private SpriteManager spriteManager; @Inject private GravediggerOverlay gravediggerOverlay; @@ -57,8 +54,6 @@ public class GravediggerHelper extends PluginModule @Inject private GravediggerItemOverlay gravediggerItemOverlay; - private boolean initiallyEnteredGraveDiggerArea; - // @Getter private Map graveMap; @@ -86,24 +81,57 @@ public void onStartUp() { this.overlayManager.add(this.gravediggerOverlay); this.overlayManager.add(gravediggerItemOverlay); - this.initiallyEnteredGraveDiggerArea = true; this.graveMap = Maps.newHashMapWithExpectedSize(5); this.coffinItemImageMap = Maps.newHashMapWithExpectedSize(5); this.coffinSkillImageMap = Maps.newHashMapWithExpectedSize(5); this.previousInventory = HashMultiset.create(); this.currentInventoryItems = HashMultiset.create(); this.coffinsInInventory = Sets.newHashSetWithExpectedSize(5); + + if (this.isLoggedIn()) + { + this.clientThread.invokeLater(() -> { + ItemContainerChanged itemContainerChangedEvent = new ItemContainerChanged(InventoryID.INV, this.client.getItemContainer(InventoryID.INV)); + this.onItemContainerChanged(itemContainerChangedEvent); + + for (GraveNumber graveNumber : GraveNumber.values()) + { + VarbitChanged graveTypeVarbitChangedEvent = new VarbitChanged(); + graveTypeVarbitChangedEvent.setVarbitId(graveNumber.getGraveTypeVarbitID()); + graveTypeVarbitChangedEvent.setValue(this.client.getVarbitValue(graveNumber.getGraveTypeVarbitID())); + VarbitChanged placedCoffinVarbitChangedEvent = new VarbitChanged(); + placedCoffinVarbitChangedEvent.setVarbitId(graveNumber.getPlacedCoffinVarbitID()); + placedCoffinVarbitChangedEvent.setValue(this.client.getVarbitValue(graveNumber.getPlacedCoffinVarbitID())); + // Use this#onVarbitChanged instead of EventBus#post because there is some CrowdsourcingVarbits exception due to us not having a proper VarpID (-1) + this.onVarbitChanged(graveTypeVarbitChangedEvent); + this.onVarbitChanged(placedCoffinVarbitChangedEvent); + } + + // Make sure we're fetching the sprites and item images on the client thread + if (this.coffinItemImageMap.isEmpty()) + { + for (Coffin coffin : Coffin.values()) + { + this.coffinItemImageMap.put(coffin, coffin.getItemImage(this.itemManager)); + } + } + + if (this.coffinSkillImageMap.isEmpty()) + { + for (Coffin coffin : Coffin.values()) + { + this.coffinSkillImageMap.put(coffin, coffin.getSkillIconImage(this.spriteManager)); + } + } + }); + } } @Override public void onShutdown() { - if (this.gravediggerOverlay != null) - { - this.overlayManager.remove(gravediggerOverlay); - } + this.overlayManager.remove(gravediggerOverlay); this.overlayManager.remove(gravediggerItemOverlay); - this.initiallyEnteredGraveDiggerArea = true; this.graveMap = null; this.coffinItemImageMap = null; this.coffinSkillImageMap = null; @@ -118,79 +146,6 @@ public boolean isEnabled() return this.config.isGravediggerEnabled(); } - @Subscribe - public void onGameTick(GameTick gameTick) - { - // There is an edgecase where when you're at the grave digger random event if a varb is still 0 then it won't fire. - // So lets handle this by checking to see if a player is in the grave digger random event area via NPC Leo spawn - // And by using a separate variable to make sure not to run this constantly every game tick - if (this.initiallyEnteredGraveDiggerArea) - { - if (this.currentInventoryItems.isEmpty()) - { - ItemContainerChanged itemContainerChangedEvent = new ItemContainerChanged(InventoryID.INV, this.client.getItemContainer(InventoryID.INV)); - this.onItemContainerChanged(itemContainerChangedEvent); - } - - if (this.graveMap.isEmpty()) - { - Tile[][][] sceneTiles = this.client.getTopLevelWorldView().getScene().getTiles(); // [Plane][x][y] - Tile[][] tilesInZ = sceneTiles[this.client.getTopLevelWorldView().getPlane()]; // Tiles at [z] - - for (Tile[] tilesInZX : tilesInZ) // Tiles at [z][x] - { - for (Tile tile : tilesInZX) // Tiles at [z][x][y] - { - if (tile != null && tile.getGameObjects() != null) - { - for (GameObject gameObject : tile.getGameObjects()) - { - // There seemed to be some case where the game object was null - if (gameObject == null) - { - continue; - } - GameObjectSpawned gameObjectSpawnedEvent = new GameObjectSpawned(); - gameObjectSpawnedEvent.setGameObject(gameObject); - this.onGameObjectSpawned(gameObjectSpawnedEvent); - } - } - } - } - } - - for (GraveNumber graveNumber : GraveNumber.values()) - { - VarbitChanged graveTypeVarbitChangedEvent = new VarbitChanged(); - graveTypeVarbitChangedEvent.setVarbitId(graveNumber.getGraveTypeVarbitID()); - graveTypeVarbitChangedEvent.setValue(this.client.getVarbitValue(graveNumber.getGraveTypeVarbitID())); - VarbitChanged placedCoffinVarbitChangedEvent = new VarbitChanged(); - placedCoffinVarbitChangedEvent.setVarbitId(graveNumber.getPlacedCoffinVarbitID()); - placedCoffinVarbitChangedEvent.setValue(this.client.getVarbitValue(graveNumber.getPlacedCoffinVarbitID())); - this.onVarbitChanged(graveTypeVarbitChangedEvent); - this.onVarbitChanged(placedCoffinVarbitChangedEvent); - } - - if (this.coffinItemImageMap.isEmpty()) - { - for (Coffin coffin : Coffin.values()) - { - this.coffinItemImageMap.put(coffin, coffin.getItemImage(this.itemManager)); - } - } - - if (this.coffinSkillImageMap.isEmpty()) - { - for (Coffin coffin : Coffin.values()) - { - this.coffinSkillImageMap.put(coffin, coffin.getSkillIconImage(this.spriteManager)); - } - } - - this.initiallyEnteredGraveDiggerArea = false; - } - } - @Subscribe public void onVarbitChanged(VarbitChanged varbitChanged) { @@ -302,27 +257,12 @@ else if (GraveNumber.isFilledGraveObjectID(gameObject.getId())) } } - @Subscribe - public void onNpcSpawned(NpcSpawned npcSpawned) - { - NPC npc = npcSpawned.getNpc(); - if (RandomEventHelperPlugin.isInRandomEventLocalInstance(this.client)) - { - if (npc.getId() == NpcID.MACRO_GRAVEDIGGER) - { - log.debug("Grave Digger Leo NPC spawned in grave digger random event area."); - this.initiallyEnteredGraveDiggerArea = true; - } - } - } - @Subscribe public void onNpcDespawned(NpcDespawned npcDespawned) { if (npcDespawned.getNpc().getId() == NpcID.MACRO_GRAVEDIGGER) { log.debug("Grave Digger Leo NPC despawned, resetting grave digger area state."); - this.initiallyEnteredGraveDiggerArea = false; this.graveMap.clear(); this.coffinItemImageMap.clear(); this.previousInventory.clear(); From a9fbc97536cb5c2e836f249cca094a24916257f1 Mon Sep 17 00:00:00 2001 From: Infinitay Date: Sun, 28 Dec 2025 06:16:00 -0500 Subject: [PATCH 20/29] fix(gravedigger): Fix NPE when starting plugin with an empty grave - Fix NPE that was thrown as a result of grave#getFilledGrave being null such as when starting the plugin with an empty grave - Now fetching either a filled or empty grave depending on which is available -> skipping if both null --- .../randomevents/gravedigger/GravediggerOverlay.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/randomeventhelper/randomevents/gravedigger/GravediggerOverlay.java b/src/main/java/randomeventhelper/randomevents/gravedigger/GravediggerOverlay.java index f976231..0f2b0d6 100644 --- a/src/main/java/randomeventhelper/randomevents/gravedigger/GravediggerOverlay.java +++ b/src/main/java/randomeventhelper/randomevents/gravedigger/GravediggerOverlay.java @@ -78,7 +78,13 @@ public Dimension render(Graphics2D graphics2D) Color placedCoffinTransparentColor = this.getTransparentColor(placedCoffin.getColor(), 50); // Renders the check or cross above the grave depending on if the correct coffin is placed - Point centeredSpritePoint = Perspective.getCanvasImageLocation(client, grave.getFilledGrave().getLocalLocation(), checkBufferedImage, 0); + GameObject graveObject = grave.getFilledGrave() != null ? grave.getFilledGrave() : grave.getEmptyGrave(); + if (graveObject == null) + { + continue; + } + + Point centeredSpritePoint = Perspective.getCanvasImageLocation(client, graveObject.getLocalLocation(), checkBufferedImage, 0); if (centeredSpritePoint != null) { if (placedCoffin != requiredCoffin) From 6d782250ee92f8aa4a733ed8795bf84a55190c2b Mon Sep 17 00:00:00 2001 From: Infinitay Date: Mon, 29 Dec 2025 00:32:08 -0500 Subject: [PATCH 21/29] refactor(maze): Migrate MazeHelper to PluginModule lifecycle - Refactored MazeHelper to the modular plugin lifecycle - Now extends PluginModule and implements respective methods, moving the existing start/stop login there - Use constructor injection and removed duplicate field injections - Injected MazeHelper and added it to the pluginModulesMap --- .../RandomEventHelperPlugin.java | 4 +++ .../randomevents/maze/MazeHelper.java | 32 ++++++++++++------- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/main/java/randomeventhelper/RandomEventHelperPlugin.java b/src/main/java/randomeventhelper/RandomEventHelperPlugin.java index dcf8a0f..ba72549 100644 --- a/src/main/java/randomeventhelper/RandomEventHelperPlugin.java +++ b/src/main/java/randomeventhelper/RandomEventHelperPlugin.java @@ -84,6 +84,9 @@ public class RandomEventHelperPlugin extends Plugin @Inject private GravediggerHelper gravediggerHelper; + @Inject + private MazeHelper mazeHelper; + @Inject private MimeHelper mimeHelper; @@ -110,6 +113,7 @@ protected void startUp() throws Exception .put("isCaptArnavChestEnabled", pirateHelper) .put("isDrillDemonEnabled", drillDemonHelper) .put("isGravediggerEnabled", gravediggerHelper) + .put("isMazeEnabled", mazeHelper) .put("isMimeEnabled", mimeHelper) .put("isSandwichLadyEnabled", sandwichLadyHelper) .put("isSurpriseExamEnabled", surpriseExamHelper) diff --git a/src/main/java/randomeventhelper/randomevents/maze/MazeHelper.java b/src/main/java/randomeventhelper/randomevents/maze/MazeHelper.java index eafb533..ad15fad 100644 --- a/src/main/java/randomeventhelper/randomevents/maze/MazeHelper.java +++ b/src/main/java/randomeventhelper/randomevents/maze/MazeHelper.java @@ -18,23 +18,19 @@ import net.runelite.api.events.GameTick; import net.runelite.api.gameval.ObjectID; import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.events.PluginMessage; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginManager; +import net.runelite.client.ui.overlay.OverlayManager; +import randomeventhelper.RandomEventHelperConfig; import randomeventhelper.RandomEventHelperPlugin; +import randomeventhelper.pluginmodulesystem.PluginModule; @Slf4j @Singleton -public class MazeHelper +public class MazeHelper extends PluginModule { - @Inject - private EventBus eventBus; - - @Inject - private Client client; - @Inject private PluginManager pluginManager; @@ -48,7 +44,14 @@ public class MazeHelper private boolean isFirstRun; private GameObject mazeExitObject; // Only purpose this serves is to avoid unnecessary onGameTick - public void startUp() + @Inject + public MazeHelper(OverlayManager overlayManager, RandomEventHelperConfig config, Client client) + { + super(overlayManager, config, client); + } + + @Override + public void onStartUp() { Optional shortestPathPlugin = pluginManager.getPlugins().stream().filter(plugin -> plugin.getName().equals("Shortest Path")).findAny(); @@ -76,14 +79,13 @@ public void startUp() this.configManager.setConfiguration("randomeventhelper", "isMazeEnabled", false); return; } - this.eventBus.register(this); this.isFirstRun = true; this.mazeExitObject = null; } - public void shutDown() + @Override + public void onShutdown() { - this.eventBus.unregister(this); Optional shortestPathPlugin = pluginManager.getPlugins().stream().filter(plugin -> plugin.getName().equals("Shortest Path")).findAny(); if (shortestPathPlugin.isPresent()) { @@ -99,6 +101,12 @@ public void shutDown() this.mazeExitObject = null; } + @Override + public boolean isEnabled() + { + return this.config.isMazeEnabled(); + } + @Subscribe public void onGameObjectSpawned(GameObjectSpawned gameObjectSpawned) { From 725260453f1d107d27db2ee9dc1e56f14f934e13 Mon Sep 17 00:00:00 2001 From: Infinitay Date: Mon, 29 Dec 2025 04:43:17 -0500 Subject: [PATCH 22/29] refactor(maze): Remove now redundant cold start handling - Removed no longer needed event listener for GameTick - Removed no longer needed variables that help track first start or required for cold start support --- .../randomevents/maze/MazeHelper.java | 57 +------------------ 1 file changed, 1 insertion(+), 56 deletions(-) diff --git a/src/main/java/randomeventhelper/randomevents/maze/MazeHelper.java b/src/main/java/randomeventhelper/randomevents/maze/MazeHelper.java index ad15fad..f9c7813 100644 --- a/src/main/java/randomeventhelper/randomevents/maze/MazeHelper.java +++ b/src/main/java/randomeventhelper/randomevents/maze/MazeHelper.java @@ -9,13 +9,10 @@ import lombok.extern.slf4j.Slf4j; import net.runelite.api.ChatMessageType; import net.runelite.api.Client; -import net.runelite.api.GameObject; -import net.runelite.api.Tile; import net.runelite.api.coords.LocalPoint; import net.runelite.api.coords.WorldPoint; import net.runelite.api.events.GameObjectDespawned; import net.runelite.api.events.GameObjectSpawned; -import net.runelite.api.events.GameTick; import net.runelite.api.gameval.ObjectID; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; @@ -41,9 +38,6 @@ public class MazeHelper extends PluginModule private static final String PLUGIN_MESSAGE_SHORTEST_PATH_PATH_KEY = "path"; private static final String PLUGIN_MESSAGE_SHORTEST_PATH_CLEAR_KEY = "clear"; - private boolean isFirstRun; - private GameObject mazeExitObject; // Only purpose this serves is to avoid unnecessary onGameTick - @Inject public MazeHelper(OverlayManager overlayManager, RandomEventHelperConfig config, Client client) { @@ -77,10 +71,7 @@ public void onStartUp() }); // Remember to disable Maze config option as well this.configManager.setConfiguration("randomeventhelper", "isMazeEnabled", false); - return; } - this.isFirstRun = true; - this.mazeExitObject = null; } @Override @@ -91,14 +82,9 @@ public void onShutdown() { if (!pluginManager.isPluginEnabled(shortestPathPlugin.get())) { - if (this.isFirstRun) - { - this.sendShortestPathClear(); - } + this.sendShortestPathClear(); } } - this.isFirstRun = true; - this.mazeExitObject = null; } @Override @@ -117,8 +103,6 @@ public void onGameObjectSpawned(GameObjectSpawned gameObjectSpawned) LocalPoint shrineLocalPoint = gameObjectSpawned.getGameObject().getLocalLocation(); WorldPoint instancedShrineWorldPoint = WorldPoint.fromLocalInstance(this.client, shrineLocalPoint); log.debug("Detected maze exit object spawn, setting shortest path to it"); - this.isFirstRun = false; - this.mazeExitObject = gameObjectSpawned.getGameObject(); this.sendShortestPathDestination(instancedShrineWorldPoint); } } @@ -130,49 +114,10 @@ public void onGameObjectDespawned(GameObjectDespawned gameObjectDespawned) if (gameObjectDespawned.getGameObject().getId() == ObjectID.MACRO_MAZE_COMPLETE) { log.debug("Detected maze exit object despawn, clearing shortest path"); - this.isFirstRun = false; - this.mazeExitObject = null; this.sendShortestPathClear(); } } - @Subscribe - public void onGameTick(GameTick gameTick) - { - if (this.isFirstRun && this.isInMazeLocalInstance() && this.mazeExitObject == null) - { - log.debug("Cold start detected in maze instance, searching for maze exit object"); - this.isFirstRun = false; - - Tile[][][] sceneTiles = this.client.getTopLevelWorldView().getScene().getTiles(); // [Plane][x][y] - Tile[][] tilesInZ = sceneTiles[this.client.getTopLevelWorldView().getPlane()]; // Tiles at [z] - for (Tile[] tilesInZX : tilesInZ) // Tiles at [z][x] - { - for (Tile tile : tilesInZX) // Tiles at [z][x][y] - { - if (tile != null && tile.getGameObjects() != null) - { - for (GameObject gameObject : tile.getGameObjects()) - { - // There seemed to be some case where the game object was null - if (gameObject == null) - { - continue; - } - GameObjectSpawned gameObjectSpawnedEvent = new GameObjectSpawned(); - gameObjectSpawnedEvent.setGameObject(gameObject); - this.onGameObjectSpawned(gameObjectSpawnedEvent); - if (this.mazeExitObject != null) - { - return; - } - } - } - } - } - } - } - private boolean sendShortestPathDestination(WorldPoint destinationWorldPoint) { if (destinationWorldPoint == null) From 330b56916cfdc3e273c7055c80c8b0c39cb7ccba Mon Sep 17 00:00:00 2001 From: Infinitay Date: Mon, 29 Dec 2025 04:43:49 -0500 Subject: [PATCH 23/29] fix(maze): Fix not clearing the current path when plugin is shutdown --- .../java/randomeventhelper/randomevents/maze/MazeHelper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/randomeventhelper/randomevents/maze/MazeHelper.java b/src/main/java/randomeventhelper/randomevents/maze/MazeHelper.java index f9c7813..befe011 100644 --- a/src/main/java/randomeventhelper/randomevents/maze/MazeHelper.java +++ b/src/main/java/randomeventhelper/randomevents/maze/MazeHelper.java @@ -80,7 +80,7 @@ public void onShutdown() Optional shortestPathPlugin = pluginManager.getPlugins().stream().filter(plugin -> plugin.getName().equals("Shortest Path")).findAny(); if (shortestPathPlugin.isPresent()) { - if (!pluginManager.isPluginEnabled(shortestPathPlugin.get())) + if (pluginManager.isPluginEnabled(shortestPathPlugin.get())) { this.sendShortestPathClear(); } From 027fe3c0150c7cfcebcaa44edc1c5d8a365d5fb5 Mon Sep 17 00:00:00 2001 From: Infinitay Date: Wed, 31 Dec 2025 01:12:52 -0500 Subject: [PATCH 24/29] refactor(freakyforester): Migrate FreakyForesterHelper to PluginModule lifecycle - Refactored FreakyForesterHelper to the modular plugin lifecycle - Now extends PluginModule and implements respective methods, moving the existing start/stop login there - Use constructor injection and removed duplicate field injections - Injected FreakyForesterHelper and added it to the pluginModulesMap --- .../RandomEventHelperPlugin.java | 4 +++ .../freakyforester/FreakyForesterHelper.java | 32 +++++++++---------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/main/java/randomeventhelper/RandomEventHelperPlugin.java b/src/main/java/randomeventhelper/RandomEventHelperPlugin.java index ba72549..425cea8 100644 --- a/src/main/java/randomeventhelper/RandomEventHelperPlugin.java +++ b/src/main/java/randomeventhelper/RandomEventHelperPlugin.java @@ -81,6 +81,9 @@ public class RandomEventHelperPlugin extends Plugin @Inject private DrillDemonHelper drillDemonHelper; + @Inject + private FreakyForesterHelper freakyForesterHelper; + @Inject private GravediggerHelper gravediggerHelper; @@ -112,6 +115,7 @@ protected void startUp() throws Exception .put("isBeekeeperEnabled", beekeeperHelper) .put("isCaptArnavChestEnabled", pirateHelper) .put("isDrillDemonEnabled", drillDemonHelper) + .put("isFreakyForesterEnabled", freakyForesterHelper) .put("isGravediggerEnabled", gravediggerHelper) .put("isMazeEnabled", mazeHelper) .put("isMimeEnabled", mimeHelper) diff --git a/src/main/java/randomeventhelper/randomevents/freakyforester/FreakyForesterHelper.java b/src/main/java/randomeventhelper/randomevents/freakyforester/FreakyForesterHelper.java index 49b8554..4db99bd 100644 --- a/src/main/java/randomeventhelper/randomevents/freakyforester/FreakyForesterHelper.java +++ b/src/main/java/randomeventhelper/randomevents/freakyforester/FreakyForesterHelper.java @@ -2,7 +2,6 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.Sets; -import com.google.inject.Provides; import java.util.Map; import java.util.Set; import java.util.regex.Matcher; @@ -20,25 +19,18 @@ import net.runelite.api.events.NpcDespawned; import net.runelite.api.events.NpcSpawned; import net.runelite.api.gameval.NpcID; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.events.ConfigChanged; import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.util.Text; import randomeventhelper.RandomEventHelperConfig; import randomeventhelper.RandomEventHelperPlugin; +import randomeventhelper.pluginmodulesystem.PluginModule; @Slf4j @Singleton -public class FreakyForesterHelper +public class FreakyForesterHelper extends PluginModule { - @Inject - private EventBus eventBus; - - @Inject - private Client client; - @Inject private OverlayManager overlayManager; @@ -78,15 +70,15 @@ public class FreakyForesterHelper .put(4, NpcID.MACRO_PHEASANT_MODEL_4) .build(); - @Provides - RandomEventHelperConfig provideConfig(ConfigManager configManager) + @Inject + public FreakyForesterHelper(OverlayManager overlayManager, RandomEventHelperConfig config, Client client) { - return configManager.getConfig(RandomEventHelperConfig.class); + super(overlayManager, config, client); } - public void startUp() + @Override + public void onStartUp() { - this.eventBus.register(this); this.overlayManager.add(freakyForesterOverlay); this.pheasantHighlightMode = config.pheasantHighlightMode(); this.pheasantTailFeathers = 0; @@ -95,9 +87,9 @@ public void startUp() this.freakyForesterNPC = null; } - public void shutDown() + @Override + public void onShutdown() { - this.eventBus.unregister(this); this.overlayManager.remove(freakyForesterOverlay); this.pheasantTailFeathers = 0; this.pheasantNPCSet = null; @@ -107,6 +99,12 @@ public void shutDown() this.freakyForesterNPC = null; } + @Override + public boolean isEnabled() + { + return this.config.isFreakyForesterEnabled(); + } + @Subscribe public void onConfigChanged(ConfigChanged configChanged) { From c98b52ff76d3484fe33bbb63981ccb2068617e8b Mon Sep 17 00:00:00 2001 From: Infinitay Date: Wed, 31 Dec 2025 01:28:02 -0500 Subject: [PATCH 25/29] feat(freakyforester): Improve support for starting during active event - Improved handling initial runs when (re)starting the plugin when doing Freaky Forester random event --- .../freakyforester/FreakyForesterHelper.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/main/java/randomeventhelper/randomevents/freakyforester/FreakyForesterHelper.java b/src/main/java/randomeventhelper/randomevents/freakyforester/FreakyForesterHelper.java index 4db99bd..6b5b75e 100644 --- a/src/main/java/randomeventhelper/randomevents/freakyforester/FreakyForesterHelper.java +++ b/src/main/java/randomeventhelper/randomevents/freakyforester/FreakyForesterHelper.java @@ -61,8 +61,6 @@ public class FreakyForesterHelper extends PluginModule @Getter private NPC freakyForesterNPC; - private boolean initialRun; - private final Map PHEASANT_TAIL_NPCID_MAP = ImmutableMap.builder() .put(1, NpcID.MACRO_PHEASANT_MODEL_1) .put(2, NpcID.MACRO_PHEASANT_MODEL_2) @@ -83,7 +81,6 @@ public void onStartUp() this.pheasantHighlightMode = config.pheasantHighlightMode(); this.pheasantTailFeathers = 0; this.pheasantNPCSet = Sets.newHashSet(); - this.initialRun = true; this.freakyForesterNPC = null; } @@ -95,7 +92,6 @@ public void onShutdown() this.pheasantNPCSet = null; this.nearestPheasantNPC = null; this.specificPheasantNPC = null; - this.initialRun = true; this.freakyForesterNPC = null; } @@ -213,12 +209,6 @@ else if (this.PHEASANT_TAIL_NPCID_MAP.containsValue(npcDespawned.getNpc().getId( @Subscribe public void onGameTick(GameTick gameTick) { - // In case the player is already in the Freaky Forester instance when the plugin is started - if (this.initialRun && this.isInFreakyForesterInstance() && this.pheasantNPCSet.isEmpty()) - { - this.initialRun = false; - this.client.getTopLevelWorldView().npcs().stream().filter(npc -> !npc.isDead()).forEach(npc -> this.onNpcSpawned(new NpcSpawned(npc))); - } if (this.pheasantHighlightMode == PheasantMode.NEAREST && !this.pheasantNPCSet.isEmpty()) { this.updateNearestPheasant(); From 7b9d492011d2ebe5bbab8fc0c13063cfcc28e2ab Mon Sep 17 00:00:00 2001 From: Infinitay Date: Mon, 5 Jan 2026 02:01:34 -0500 Subject: [PATCH 26/29] fix(maze): Fix not showing path on restart, use instanced WorldPoint instead - Fixed an issue where the Shortest Path wasn't properly calculated/rendered upon restarts/cold-starts - Now uses the player's LocalPoint and converts it to an instanced WorldPoint (WorldPoint#fromLocalInstance) as the starting WorldPoint for the path generation - Modified logging to reflect usage of point types --- .../randomevents/maze/MazeHelper.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/main/java/randomeventhelper/randomevents/maze/MazeHelper.java b/src/main/java/randomeventhelper/randomevents/maze/MazeHelper.java index befe011..b9179f6 100644 --- a/src/main/java/randomeventhelper/randomevents/maze/MazeHelper.java +++ b/src/main/java/randomeventhelper/randomevents/maze/MazeHelper.java @@ -140,17 +140,22 @@ private boolean sendShortestPathDestination(WorldPoint destinationWorldPoint) private Map generatePathPayload(WorldPoint destinationWorldPoint) { - WorldPoint startingWorldPoint = client.getLocalPlayer().getWorldLocation(); - if (startingWorldPoint == null) + LocalPoint startingLocalPoint = client.getLocalPlayer().getLocalLocation(); + + if (startingLocalPoint == null) { - log.warn("[#generatePathPayload-WorldPoint] Player's starting world point is null, cannot generate payload starting point"); + log.warn("[#generatePathPayload(WorldPoint)] Player's starting local point is null, cannot generate payload starting point"); return Map.of(); } - return this.generatePathPayload(startingWorldPoint, destinationWorldPoint); + + WorldPoint localInstanceStartingWorldPoint = WorldPoint.fromLocalInstance(this.client, startingLocalPoint); + log.debug("[#generatePathPayload(WorldPoint)] Converted player's local point {} to local instance world point {}", startingLocalPoint, localInstanceStartingWorldPoint); + return this.generatePathPayload(localInstanceStartingWorldPoint, destinationWorldPoint); } private Map generatePathPayload(WorldPoint startingWorldPoint, WorldPoint destinationWorldPoint) { + log.debug("[#generatePathPayload(WorldPoint, WorldPoint)] Generated path payload with starting point: {} and destination point: {}", startingWorldPoint, destinationWorldPoint); return Map.of( "start", startingWorldPoint, "target", destinationWorldPoint From 40ebf1c442550c55689058adf2d28ad081550599 Mon Sep 17 00:00:00 2001 From: Infinitay Date: Wed, 7 Jan 2026 00:28:28 -0500 Subject: [PATCH 27/29] refactor(pinball): Migrate PinballHelper to PluginModule lifecycle - Refactored PinballHelper to the modular plugin lifecycle - Now extends PluginModule and implements respective methods, moving the existing start/stop login there - Use constructor injection and removed duplicate field injections - Injected PinballHelper and added it to the pluginModulesMap --- .../RandomEventHelperPlugin.java | 4 +++ .../randomevents/pinball/PinballHelper.java | 31 ++++++++++++------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/main/java/randomeventhelper/RandomEventHelperPlugin.java b/src/main/java/randomeventhelper/RandomEventHelperPlugin.java index 425cea8..85f963f 100644 --- a/src/main/java/randomeventhelper/RandomEventHelperPlugin.java +++ b/src/main/java/randomeventhelper/RandomEventHelperPlugin.java @@ -93,6 +93,9 @@ public class RandomEventHelperPlugin extends Plugin @Inject private MimeHelper mimeHelper; + @Inject + private PinballHelper pinballHelper; + @Inject private SandwichLadyHelper sandwichLadyHelper; @@ -119,6 +122,7 @@ protected void startUp() throws Exception .put("isGravediggerEnabled", gravediggerHelper) .put("isMazeEnabled", mazeHelper) .put("isMimeEnabled", mimeHelper) + .put("isPinballEnabled", pinballHelper) .put("isSandwichLadyEnabled", sandwichLadyHelper) .put("isSurpriseExamEnabled", surpriseExamHelper) .put("isQuizMasterEnabled", quizMasterHelper) diff --git a/src/main/java/randomeventhelper/randomevents/pinball/PinballHelper.java b/src/main/java/randomeventhelper/randomevents/pinball/PinballHelper.java index 9871d08..babf497 100644 --- a/src/main/java/randomeventhelper/randomevents/pinball/PinballHelper.java +++ b/src/main/java/randomeventhelper/randomevents/pinball/PinballHelper.java @@ -15,22 +15,17 @@ import net.runelite.api.events.VarbitChanged; import net.runelite.api.gameval.NpcID; import net.runelite.api.gameval.VarbitID; -import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.util.Text; +import randomeventhelper.RandomEventHelperConfig; import randomeventhelper.RandomEventHelperPlugin; +import randomeventhelper.pluginmodulesystem.PluginModule; @Slf4j @Singleton -public class PinballHelper +public class PinballHelper extends PluginModule { - @Inject - private EventBus eventBus; - - @Inject - private Client client; - @Inject private OverlayManager overlayManager; @@ -45,24 +40,36 @@ public class PinballHelper private boolean initial = false; - public void startUp() + @Inject + public PinballHelper(OverlayManager overlayManager, RandomEventHelperConfig config, Client client) + { + super(overlayManager, config, client); + } + + @Override + public void onStartUp() { - this.eventBus.register(this); this.overlayManager.add(pinballOverlay); this.activePinballPost = null; this.pinballPostsMap = Maps.newHashMap(); this.initial = false; } - public void shutDown() + @Override + public void onShutdown() { - this.eventBus.unregister(this); this.overlayManager.remove(pinballOverlay); this.activePinballPost = null; this.pinballPostsMap = null; this.initial = false; } + @Override + public boolean isEnabled() + { + return this.config.isPinballEnabled(); + } + @Subscribe public void onNpcDespawned(NpcDespawned npcDespawned) { From 5f3efba7b4b9bc70ebed03c9c79fbc9292cba118 Mon Sep 17 00:00:00 2001 From: Infinitay Date: Wed, 7 Jan 2026 02:01:53 -0500 Subject: [PATCH 28/29] feat(pinball): Improve support for starting during active event - Improved handling initial runs when (re)starting the plugin when doing Pinball random event --- .../randomevents/pinball/PinballHelper.java | 43 ++++++++++++------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/src/main/java/randomeventhelper/randomevents/pinball/PinballHelper.java b/src/main/java/randomeventhelper/randomevents/pinball/PinballHelper.java index babf497..fc09aa8 100644 --- a/src/main/java/randomeventhelper/randomevents/pinball/PinballHelper.java +++ b/src/main/java/randomeventhelper/randomevents/pinball/PinballHelper.java @@ -15,6 +15,7 @@ import net.runelite.api.events.VarbitChanged; import net.runelite.api.gameval.NpcID; import net.runelite.api.gameval.VarbitID; +import net.runelite.client.callback.ClientThread; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.util.Text; @@ -26,6 +27,9 @@ @Singleton public class PinballHelper extends PluginModule { + @Inject + private ClientThread clientThread; + @Inject private OverlayManager overlayManager; @@ -38,8 +42,6 @@ public class PinballHelper extends PluginModule // private Map pinballPostsMap; - private boolean initial = false; - @Inject public PinballHelper(OverlayManager overlayManager, RandomEventHelperConfig config, Client client) { @@ -52,7 +54,11 @@ public void onStartUp() this.overlayManager.add(pinballOverlay); this.activePinballPost = null; this.pinballPostsMap = Maps.newHashMap(); - this.initial = false; + + if (this.isLoggedIn()) + { + this.initiateActivePost(); + } } @Override @@ -61,7 +67,6 @@ public void onShutdown() this.overlayManager.remove(pinballOverlay); this.activePinballPost = null; this.pinballPostsMap = null; - this.initial = false; } @Override @@ -93,18 +98,9 @@ public void onGameObjectSpawned(GameObjectSpawned gameObjectSpawned) { log.debug("A pinball post has spawned: {}", pinballPost); this.pinballPostsMap.put(pinballPost.getVarbitValue(), gameObject); - - if (!this.initial) + if (this.activePinballPost == null) { - int currentPostVarbitValue = this.client.getVarbitValue(VarbitID.MACRO_PINBALL_CURRENT); - if (currentPostVarbitValue != 0) - { - VarbitChanged temp = new VarbitChanged(); - temp.setVarbitId(VarbitID.MACRO_PINBALL_CURRENT); - temp.setValue(currentPostVarbitValue); - this.onVarbitChanged(temp); - this.initial = true; - } + this.initiateActivePost(); } } } @@ -121,6 +117,10 @@ public void onVarbitChanged(VarbitChanged varbitChanged) { log.debug("The active pinball post has changed to: {}", pinballPost); this.activePinballPost = this.pinballPostsMap.get(value); + if (this.activePinballPost == null) + { + log.warn("The active pinball post game object is null for pinball post: {}", pinballPost); + } } else { @@ -141,8 +141,19 @@ public void onChatMessage(ChatMessage chatMessage) log.debug("Pinball game has ended so resetting active pinball post and pinball posts set."); this.activePinballPost = null; this.pinballPostsMap = Maps.newHashMap(); - this.initial = false; } } } + + private void initiateActivePost() + { + this.clientThread.invokeLater(() -> + { + int postVarbitValue = this.client.getVarbitValue(VarbitID.MACRO_PINBALL_CURRENT); + VarbitChanged varbitChangedEvent = new VarbitChanged(); + varbitChangedEvent.setVarbitId(VarbitID.MACRO_PINBALL_CURRENT); + varbitChangedEvent.setValue(postVarbitValue); + this.onVarbitChanged(varbitChangedEvent); + }); + } } From e63d8e707f3a81945d3b709fbf39bec988d6c4e7 Mon Sep 17 00:00:00 2001 From: Infinitay Date: Wed, 7 Jan 2026 02:38:42 -0500 Subject: [PATCH 29/29] fix(drilldemon): Use #invokeLater to fix possible race conditions - Other modules rely on #invokeLater, so this also maintains consistency --- .../randomevents/drilldemon/DrillDemonHelper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/randomeventhelper/randomevents/drilldemon/DrillDemonHelper.java b/src/main/java/randomeventhelper/randomevents/drilldemon/DrillDemonHelper.java index 32d57ec..ac8b44b 100644 --- a/src/main/java/randomeventhelper/randomevents/drilldemon/DrillDemonHelper.java +++ b/src/main/java/randomeventhelper/randomevents/drilldemon/DrillDemonHelper.java @@ -74,7 +74,7 @@ public void onStartUp() this.requestedExercise = null; if (this.isLoggedIn()) { - this.clientThread.invoke(() -> + this.clientThread.invokeLater(() -> { log.debug("Initializing varbits for Drill Demon exercise mappings in case plugin was enabled mid-event."); for (int postVarbitID = VarbitID.MACRO_DRILLDEMON_POST_1; postVarbitID <= VarbitID.MACRO_DRILLDEMON_POST_4; postVarbitID++)