From 195bdd5971f75c44f11febee51de0ffcf6b7fa8d Mon Sep 17 00:00:00 2001 From: Alexsuperfly Date: Sun, 18 Apr 2021 16:59:49 -0400 Subject: [PATCH] cannon: check invent cballs to initialize count when placing --- .../client/plugins/cannon/CannonPlugin.java | 18 ++ .../plugins/cannon/CannonPluginTest.java | 174 ++++++++++++++++++ 2 files changed, 192 insertions(+) create mode 100644 runelite-client/src/test/java/net/runelite/client/plugins/cannon/CannonPluginTest.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonPlugin.java index 1f9aeeaa25..83844a2c34 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonPlugin.java @@ -39,6 +39,7 @@ import net.runelite.api.GameObject; import net.runelite.api.GameState; import net.runelite.api.InventoryID; import net.runelite.api.Item; +import net.runelite.api.ItemContainer; import net.runelite.api.ItemID; import static net.runelite.api.ObjectID.CANNON_BASE; import net.runelite.api.Player; @@ -301,6 +302,23 @@ public class CannonPlugin extends Plugin cannonPlaced = true; addCounter(); cballsLeft = 0; + + final ItemContainer inventory = client.getItemContainer(InventoryID.INVENTORY); + if (inventory != null) + { + int invCballs = inventory.count(ItemID.GRANITE_CANNONBALL) > 0 + ? inventory.count(ItemID.GRANITE_CANNONBALL) + : inventory.count(ItemID.CANNONBALL); + // Cannonballs are always forcibly loaded after the furnace is added. If the player has more than + // the max number of cannon balls in their inventory, the cannon will always be fully filled. + // This is preferable to using the proceeding "You load the cannon with x cannon balls" message + // since it will show a lower number of cannon balls if the cannon is already partially-filled + // prior to being placed. + if (invCballs >= MAX_CBALLS) + { + cballsLeft = MAX_CBALLS; + } + } } if (event.getMessage().contains("You pick up the cannon") diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/cannon/CannonPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/cannon/CannonPluginTest.java new file mode 100644 index 0000000000..103366fc5c --- /dev/null +++ b/runelite-client/src/test/java/net/runelite/client/plugins/cannon/CannonPluginTest.java @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2021, Alexsuperfly + * Copyright (c) 2021, Jordan Atwood + * 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.cannon; + +import com.google.inject.Guice; +import com.google.inject.testing.fieldbinder.Bind; +import com.google.inject.testing.fieldbinder.BoundFieldModule; +import javax.inject.Inject; +import net.runelite.api.ChatMessageType; +import net.runelite.api.Client; +import net.runelite.api.InventoryID; +import net.runelite.api.ItemContainer; +import net.runelite.api.ItemID; +import net.runelite.api.events.ChatMessage; +import net.runelite.client.Notifier; +import net.runelite.client.game.ItemManager; +import net.runelite.client.ui.overlay.OverlayManager; +import net.runelite.client.ui.overlay.infobox.InfoBoxManager; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import org.junit.Before; +import org.junit.BeforeClass; +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 CannonPluginTest +{ + + @Inject + private CannonPlugin plugin; + + @Mock + @Bind + private CannonConfig config; + + @Mock + @Bind + private CannonOverlay cannonOverlay; + + @Mock + @Bind + private CannonSpotOverlay cannonSpotOverlay; + + @Mock + @Bind + private InfoBoxManager infoBoxManager; + + @Mock + @Bind + private Notifier notifier; + + @Mock + @Bind + private ItemManager itemManager; + + @Mock + @Bind + private Client client; + + @Mock + @Bind + private OverlayManager overlayManager; + + private static final ChatMessage ADD_FURNACE = new ChatMessage(); + + @BeforeClass + public static void chatMessageSetup() + { + ADD_FURNACE.setType(ChatMessageType.SPAM); + ADD_FURNACE.setMessage("You add the furnace."); + } + + @Before + public void before() + { + Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); + } + + @Test + public void addMaxCannonballs() + { + final ItemContainer inventory = mock(ItemContainer.class); + when(client.getItemContainer(InventoryID.INVENTORY)).thenReturn(inventory); + when(inventory.count(ItemID.CANNONBALL)).thenReturn(100); + when(inventory.count(ItemID.GRANITE_CANNONBALL)).thenReturn(0); + + plugin.onChatMessage(ADD_FURNACE); + assertTrue(plugin.isCannonPlaced()); + + assertEquals(30, plugin.getCballsLeft()); + + plugin.onChatMessage(loadCannonballs(30)); + assertEquals(30, plugin.getCballsLeft()); + } + + @Test + public void addNotMaxCannonballs() + { + final ItemContainer inventory = mock(ItemContainer.class); + when(client.getItemContainer(InventoryID.INVENTORY)).thenReturn(inventory); + when(inventory.count(ItemID.GRANITE_CANNONBALL)).thenReturn(12); + + plugin.onChatMessage(ADD_FURNACE); + assertTrue(plugin.isCannonPlaced()); + + assertEquals(0, plugin.getCballsLeft()); + + plugin.onChatMessage(loadCannonballs(12)); + assertEquals(12, plugin.getCballsLeft()); + } + + @Test + public void addReclaimedCannonballs() + { + final ItemContainer inventory = mock(ItemContainer.class); + when(client.getItemContainer(InventoryID.INVENTORY)).thenReturn(inventory); + when(inventory.count(ItemID.CANNONBALL)).thenReturn(1250); + + plugin.onChatMessage(ADD_FURNACE); + assertTrue(plugin.isCannonPlaced()); + + assertEquals(30, plugin.getCballsLeft()); + + plugin.onChatMessage(loadCannonballs(18)); + assertEquals(30, plugin.getCballsLeft()); + } + + private static ChatMessage loadCannonballs(final int numCannonballs) + { + final ChatMessage message = new ChatMessage(); + message.setType(ChatMessageType.GAMEMESSAGE); + + // Cannons use the same chat message for loading cannonballs regardless of whether they're normal or granite. + if (numCannonballs == 1) + { + message.setMessage("You load the cannon with one cannonball."); + } + else + { + message.setMessage(String.format("You load the cannon with %s cannonballs.", numCannonballs)); + } + + return message; + } + +}