diff --git a/runelite-api/src/main/java/net/runelite/api/Client.java b/runelite-api/src/main/java/net/runelite/api/Client.java index a27caba9b1..621b6b3ca1 100644 --- a/runelite-api/src/main/java/net/runelite/api/Client.java +++ b/runelite-api/src/main/java/net/runelite/api/Client.java @@ -131,11 +131,11 @@ public interface Client extends GameShell GameState getGameState(); /** - * Sets the current game state. + * Sets the current game state * - * @param gameState new game state + * @param gameState */ - void setGameState(int gameState); + void setGameState(GameState gameState); /** * Gets the current logged in username. diff --git a/runelite-api/src/main/java/net/runelite/api/GameState.java b/runelite-api/src/main/java/net/runelite/api/GameState.java index 6a61fcfe59..7b1ee7a893 100644 --- a/runelite-api/src/main/java/net/runelite/api/GameState.java +++ b/runelite-api/src/main/java/net/runelite/api/GameState.java @@ -28,10 +28,12 @@ import java.util.Arrays; import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; +import lombok.Getter; /** * An enumeration of game states the client is in. */ +@Getter public enum GameState { /** diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java index cc5df5a7ee..db46a9f020 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java @@ -77,7 +77,7 @@ public class EmoteClue extends ClueScroll implements TextClueScroll, LocationClu new EmoteClue("Panic in the heart of the Haunted Woods. Beware of double agents! Have no items equipped when you do.", "Haunted Woods", null, new WorldPoint(3611, 3492, 0), PANIC, emptySlot("Nothing at all", HEAD, CAPE, AMULET, WEAPON, BODY, SHIELD, LEGS, GLOVES, BOOTS, RING, AMMO)), new EmoteClue("Show your anger towards the Statue of Saradomin in Ellamaria's garden. Beware of double agents! Equip a zamorak godsword.", "Varrock Castle", BY_THE_BEAR_CAGE_IN_VARROCK_PALACE_GARDENS, new WorldPoint(3230, 3478, 0), ANGRY, item(ZAMORAK_GODSWORD)), new EmoteClue("Show your anger at the Wise old man. Beware of double agents! Equip an abyssal whip, a legend's cape and some spined chaps.", "Draynor Village", BEHIND_MISS_SCHISM_IN_DRAYNOR_VILLAGE, new WorldPoint(3088, 3254, 0), ANGRY, any("Abyssal whip", item(ABYSSAL_WHIP), item(VOLCANIC_ABYSSAL_WHIP), item(FROZEN_ABYSSAL_WHIP)), item(CAPE_OF_LEGENDS), item(SPINED_CHAPS)), - new EmoteClue("Beckon by a collection of crystalline maple trees. Beware of double agents! Equip Bryophyta's staff and a nature tiara.", "North of Prifddinas", CRYSTALLINE_MAPLE_TREES, new WorldPoint(2211, 3427, 0), BECKON, range(BRYOPHYTAS_STAFF_UNCHARGED, BRYOPHYTAS_STAFF), item(NATURE_TIARA)), + new EmoteClue("Beckon by a collection of crystalline maple trees. Beware of double agents! Equip Bryophyta's staff and a nature tiara.", "North of Prifddinas", CRYSTALLINE_MAPLE_TREES, new WorldPoint(2211, 3427, 0), BECKON, range("Bryophyta's staff", BRYOPHYTAS_STAFF_UNCHARGED, BRYOPHYTAS_STAFF), item(NATURE_TIARA)), new EmoteClue("Beckon in the Digsite, near the eastern winch. Bow before you talk to me. Equip a green gnome hat, snakeskin boots and an iron pickaxe.", "Digsite", DIGSITE, new WorldPoint(3370, 3425, 0), BECKON, BOW, item(GREEN_HAT), item(SNAKESKIN_BOOTS), item(IRON_PICKAXE)), new EmoteClue("Beckon in Tai Bwo Wannai. Clap before you talk to me. Equip green dragonhide chaps, a ring of dueling and a mithril medium helmet.", "Tai Bwo Wannai", SOUTH_OF_THE_SHRINE_IN_TAI_BWO_WANNAI_VILLAGE, new WorldPoint(2803, 3073, 0), BECKON, CLAP, item(GREEN_DHIDE_CHAPS), any("Ring of dueling", item(RING_OF_DUELING1), item(RING_OF_DUELING2), item(RING_OF_DUELING3), item(RING_OF_DUELING4), item(RING_OF_DUELING5), item(RING_OF_DUELING6), item(RING_OF_DUELING7), item(RING_OF_DUELING8)), item(MITHRIL_MED_HELM)), new EmoteClue("Beckon in the combat ring of Shayzien. Show your anger before you talk to me. Equip an adamant platebody, adamant full helm and adamant platelegs.", "Shayzien combat ring", WEST_OF_THE_SHAYZIEN_COMBAT_RING, new WorldPoint(1545, 3594, 0), BECKON, ANGRY, item(ADAMANT_PLATELEGS), item(ADAMANT_PLATEBODY), item(ADAMANT_FULL_HELM)), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/lowmemory/LowMemoryPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/lowmemory/LowMemoryPlugin.java index 14047a43b3..039a69cac3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/lowmemory/LowMemoryPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/lowmemory/LowMemoryPlugin.java @@ -25,11 +25,8 @@ package net.runelite.client.plugins.lowmemory; import javax.inject.Inject; -import javax.inject.Singleton; import net.runelite.api.Client; -import net.runelite.api.GameState; -import net.runelite.api.events.GameStateChanged; -import net.runelite.client.eventbus.EventBus; +import net.runelite.client.callback.ClientThread; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; @@ -39,39 +36,23 @@ import net.runelite.client.plugins.PluginDescriptor; tags = {"memory", "usage", "ground", "decorations"}, enabledByDefault = false ) -@Singleton public class LowMemoryPlugin extends Plugin { @Inject private Client client; @Inject - private EventBus eventBus; + private ClientThread clientThread; @Override - protected void startUp() throws Exception + protected void startUp() { - eventBus.subscribe(GameStateChanged.class, this, this::onGameStateChanged); - - if (client.getGameState() == GameState.LOGGED_IN) - { - client.changeMemoryMode(true); - } + clientThread.invoke(() -> client.changeMemoryMode(true)); } @Override - protected void shutDown() throws Exception + protected void shutDown() { - eventBus.unregister(this); - - client.changeMemoryMode(false); + clientThread.invoke(() -> client.changeMemoryMode(false)); } - - private void onGameStateChanged(GameStateChanged event) - { - if (event.getGameState() == GameState.LOGIN_SCREEN) - { - client.changeMemoryMode(true); - } - } -} +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPanel.java index 70cd5798d9..463236423f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPanel.java @@ -79,7 +79,7 @@ class RaidsPanel extends PluginPanel { if ((client.getGameState() == GameState.LOGGED_IN)) { - client.setGameState(40); + client.setGameState(GameState.CONNECTION_LOST); } }); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java index b05f80fc0d..ae3324a75c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java @@ -25,6 +25,7 @@ */ package net.runelite.client.plugins.xptracker; +import com.google.common.annotations.VisibleForTesting; import static com.google.common.base.MoreObjects.firstNonNull; import com.google.common.collect.ImmutableList; import com.google.inject.Binder; @@ -38,6 +39,7 @@ import java.util.Objects; import javax.inject.Inject; import lombok.AccessLevel; import lombok.Getter; +import lombok.Setter; import lombok.extern.slf4j.Slf4j; import net.runelite.api.Actor; import net.runelite.api.Client; @@ -120,6 +122,8 @@ public class XpTrackerPlugin extends Plugin private EventBus eventBus; private NavigationButton navButton; + @Setter(AccessLevel.PACKAGE) + @VisibleForTesting private XpPanel xpPanel; private XpWorldType lastWorldType; private String lastUsername; @@ -198,7 +202,7 @@ public class XpTrackerPlugin extends Plugin eventBus.subscribe(MenuOptionClicked.class, this, this::onMenuOptionClicked); } - private void onGameStateChanged(GameStateChanged event) + void onGameStateChanged(GameStateChanged event) { GameState state = event.getGameState(); if (state == GameState.LOGGED_IN) @@ -356,7 +360,7 @@ public class XpTrackerPlugin extends Plugin } } - private void onExperienceChanged(ExperienceChanged event) + void onExperienceChanged(ExperienceChanged event) { final Skill skill = event.getSkill(); final int currentXp = client.getSkillExperience(skill); @@ -414,7 +418,7 @@ public class XpTrackerPlugin extends Plugin xpPanel.updateTotal(xpState.getTotalSnapshot()); } - private void onGameTick(GameTick event) + void onGameTick(GameTick event) { if (initializeTracker) { @@ -441,7 +445,7 @@ public class XpTrackerPlugin extends Plugin log.debug("Skill xp for {} changed when offline: {} -> {}", skill, skillState.getCurrentXp(), currentXp); // Offset start xp for offline gains - long diff = skillState.getCurrentXp() - currentXp; + long diff = currentXp - skillState.getCurrentXp(); skillState.setStartXp(skillState.getStartXp() + diff); } } @@ -539,6 +543,11 @@ public class XpTrackerPlugin extends Plugin } } + XpStateSingle getSkillState(Skill skill) + { + return xpState.getSkill(skill); + } + XpSnapshotSingle getSkillSnapshot(Skill skill) { return xpState.getSkillSnapshot(skill); diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/xptracker/XpTrackerPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/xptracker/XpTrackerPluginTest.java new file mode 100644 index 0000000000..8f65e81cbf --- /dev/null +++ b/runelite-client/src/test/java/net/runelite/client/plugins/xptracker/XpTrackerPluginTest.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2019, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.plugins.xptracker; + +import com.google.inject.Guice; +import com.google.inject.testing.fieldbinder.Bind; +import com.google.inject.testing.fieldbinder.BoundFieldModule; +import java.util.EnumSet; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.Player; +import net.runelite.api.Skill; +import net.runelite.api.WorldType; +import net.runelite.api.events.ExperienceChanged; +import net.runelite.api.events.GameStateChanged; +import net.runelite.api.events.GameTick; +import net.runelite.client.game.NPCManager; +import net.runelite.client.game.SkillIconManager; +import net.runelite.client.ui.ClientToolbar; +import net.runelite.client.ui.overlay.OverlayManager; +import static org.junit.Assert.assertEquals; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class XpTrackerPluginTest +{ + @Inject + private XpTrackerPlugin xpTrackerPlugin; + + @Mock + @Bind + private ClientToolbar clientToolbar; + + @Mock + @Bind + private Client client; + + @Mock + @Bind + private SkillIconManager skillIconManager; + + @Mock + @Bind + private XpTrackerConfig xpTrackerConfig; + + @Mock + @Bind + private NPCManager npcManager; + + @Mock + @Bind + private OverlayManager overlayManager; + + @Before + public void before() + { + Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); + + when(client.getLocalPlayer()).thenReturn(mock(Player.class)); + + xpTrackerPlugin.setXpPanel(mock(XpPanel.class)); + } + + @Test + public void testOfflineXp() + { + GameStateChanged gameStateChanged = new GameStateChanged(); + gameStateChanged.setGameState(GameState.LOGGING_IN); + + // Flag initialization of tracker + xpTrackerPlugin.onGameStateChanged(gameStateChanged); + when(client.getSkillExperience(Skill.ATTACK)).thenReturn(42); + // Initialize tracker + xpTrackerPlugin.onGameTick(GameTick.INSTANCE); + + // Gain attack xp + when(client.getSkillExperience(Skill.ATTACK)).thenReturn(100); + ExperienceChanged experienceChanged = new ExperienceChanged(); + experienceChanged.setSkill(Skill.ATTACK); + xpTrackerPlugin.onExperienceChanged(experienceChanged); + + // Offline gain + when(client.getSkillExperience(Skill.ATTACK)).thenReturn(42000); + // Flag initialization of tracker + xpTrackerPlugin.onGameStateChanged(gameStateChanged); + // Initialize tracker + xpTrackerPlugin.onGameTick(GameTick.INSTANCE); + + // Start at 42 xp, gain of 58 xp, offline gain of 41900 xp - offset start XP: 42 + 41900 + XpStateSingle skillState = xpTrackerPlugin.getSkillState(Skill.ATTACK); + assertEquals(41942, skillState.getStartXp()); + } +} \ No newline at end of file