cannon: use varp for cannonball count
Co-authored-by: Bonfire <5704760+Bonfire@users.noreply.github.com>
This commit is contained in:
@@ -39,6 +39,7 @@ import lombok.Getter;
|
||||
@Getter
|
||||
public enum VarPlayer
|
||||
{
|
||||
CANNON_AMMO(3),
|
||||
ATTACK_STYLE(43),
|
||||
QUEST_POINTS(101),
|
||||
IS_POISONED(102),
|
||||
|
||||
@@ -24,14 +24,10 @@
|
||||
*/
|
||||
package net.runelite.client.plugins.cannon;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.inject.Provides;
|
||||
import java.awt.Color;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.inject.Inject;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -40,25 +36,22 @@ import net.runelite.api.ChatMessageType;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameObject;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.GraphicID;
|
||||
import net.runelite.api.InventoryID;
|
||||
import net.runelite.api.Item;
|
||||
import net.runelite.api.ItemContainer;
|
||||
import net.runelite.api.ItemID;
|
||||
import net.runelite.api.MenuAction;
|
||||
import net.runelite.api.ObjectID;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.Projectile;
|
||||
import net.runelite.api.VarPlayer;
|
||||
import net.runelite.api.coords.LocalPoint;
|
||||
import net.runelite.api.coords.WorldArea;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.GameObjectSpawned;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.ItemContainerChanged;
|
||||
import net.runelite.api.events.MenuOptionClicked;
|
||||
import net.runelite.api.events.ProjectileMoved;
|
||||
import net.runelite.api.events.VarbitChanged;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.Notifier;
|
||||
@@ -80,17 +73,10 @@ import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
|
||||
@Slf4j
|
||||
public class CannonPlugin extends Plugin
|
||||
{
|
||||
private static final Pattern NUMBER_PATTERN = Pattern.compile("([0-9]+)");
|
||||
static final int MAX_OVERLAY_DISTANCE = 4100;
|
||||
static final int MAX_CBALLS = 30;
|
||||
|
||||
private static final Set<Integer> CANNONBALL_PROJECTILE_IDS = ImmutableSet.of(
|
||||
GraphicID.CANNONBALL, GraphicID.GRANITE_CANNONBALL,
|
||||
GraphicID.CANNONBALL_OR, GraphicID.GRANITE_CANNONBALL_OR
|
||||
);
|
||||
|
||||
private CannonCounter counter;
|
||||
private boolean skipProjectileCheckThisTick;
|
||||
private boolean cannonBallNotificationSent;
|
||||
private WorldPoint clickedCannonLocation;
|
||||
private boolean firstCannonLoad;
|
||||
@@ -151,6 +137,7 @@ public class CannonPlugin extends Plugin
|
||||
{
|
||||
overlayManager.add(cannonOverlay);
|
||||
overlayManager.add(cannonSpotOverlay);
|
||||
clientThread.invoke(() -> cballsLeft = client.getVar(VarPlayer.CANNON_AMMO));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -165,7 +152,6 @@ public class CannonPlugin extends Plugin
|
||||
cannonBallNotificationSent = false;
|
||||
cballsLeft = 0;
|
||||
removeCounter();
|
||||
skipProjectileCheckThisTick = false;
|
||||
spotPoints.clear();
|
||||
}
|
||||
|
||||
@@ -278,7 +264,7 @@ public class CannonPlugin extends Plugin
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Subscribe
|
||||
public void onMenuOptionClicked(MenuOptionClicked event)
|
||||
{
|
||||
@@ -309,32 +295,16 @@ public class CannonPlugin extends Plugin
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onProjectileMoved(ProjectileMoved event)
|
||||
public void onVarbitChanged(VarbitChanged varbitChanged)
|
||||
{
|
||||
Projectile projectile = event.getProjectile();
|
||||
|
||||
if (CANNONBALL_PROJECTILE_IDS.contains(projectile.getId()) && cannonPosition != null && cannonWorld == client.getWorld())
|
||||
if (varbitChanged.getIndex() == VarPlayer.CANNON_AMMO.getId())
|
||||
{
|
||||
WorldPoint projectileLoc = WorldPoint.fromLocal(client, projectile.getX1(), projectile.getY1(), client.getPlane());
|
||||
cballsLeft = client.getVar(VarPlayer.CANNON_AMMO);
|
||||
|
||||
//Check to see if projectile x,y is 0 else it will continuously decrease while ball is flying.
|
||||
if (cannonPosition.contains(projectileLoc) && projectile.getX() == 0 && projectile.getY() == 0)
|
||||
if (config.showCannonNotifications() && !cannonBallNotificationSent && cballsLeft > 0 && config.lowWarningThreshold() >= cballsLeft)
|
||||
{
|
||||
// When there's a chat message about cannon reloaded/unloaded/out of ammo,
|
||||
// the message event runs before the projectile event. However they run
|
||||
// in the opposite order on the server. So if both fires in the same tick,
|
||||
// we don't want to update the cannonball counter if it was set to a specific
|
||||
// amount.
|
||||
if (!skipProjectileCheckThisTick)
|
||||
{
|
||||
cballsLeft--;
|
||||
|
||||
if (config.showCannonNotifications() && !cannonBallNotificationSent && cballsLeft > 0 && config.lowWarningThreshold() >= cballsLeft)
|
||||
{
|
||||
notifier.notify(String.format("Your cannon has %d cannon balls remaining!", cballsLeft));
|
||||
cannonBallNotificationSent = true;
|
||||
}
|
||||
}
|
||||
notifier.notify(String.format("Your cannon has %d cannon balls remaining!", cballsLeft));
|
||||
cannonBallNotificationSent = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -351,32 +321,13 @@ public class CannonPlugin extends Plugin
|
||||
{
|
||||
cannonPlaced = true;
|
||||
addCounter();
|
||||
cballsLeft = 0;
|
||||
firstCannonLoad = true;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (event.getMessage().contains("You pick up the cannon")
|
||||
|| event.getMessage().contains("Your cannon has decayed. Speak to Nulodion to get a new one!")
|
||||
|| event.getMessage().contains("Your cannon has been destroyed!"))
|
||||
{
|
||||
cannonPlaced = false;
|
||||
cballsLeft = 0;
|
||||
removeCounter();
|
||||
cannonPosition = null;
|
||||
}
|
||||
@@ -410,83 +361,21 @@ public class CannonPlugin extends Plugin
|
||||
clickedCannonLocation = null;
|
||||
}
|
||||
|
||||
Matcher m = NUMBER_PATTERN.matcher(event.getMessage());
|
||||
if (m.find())
|
||||
{
|
||||
// The cannon will usually refill to MAX_CBALLS, but if the
|
||||
// player didn't have enough cannonballs in their inventory,
|
||||
// it could fill up less than that. Filling the cannon to
|
||||
// cballsLeft + amt is not always accurate though because our
|
||||
// counter doesn't decrease if the player has been too far away
|
||||
// from the cannon due to the projectiels not being in memory,
|
||||
// so our counter can be higher than it is supposed to be.
|
||||
int amt = Integer.valueOf(m.group());
|
||||
if (cballsLeft + amt >= MAX_CBALLS)
|
||||
{
|
||||
skipProjectileCheckThisTick = true;
|
||||
cballsLeft = MAX_CBALLS;
|
||||
}
|
||||
else
|
||||
{
|
||||
cballsLeft += amt;
|
||||
}
|
||||
}
|
||||
else if (event.getMessage().equals("You load the cannon with one cannonball."))
|
||||
{
|
||||
if (cballsLeft + 1 >= MAX_CBALLS)
|
||||
{
|
||||
skipProjectileCheckThisTick = true;
|
||||
cballsLeft = MAX_CBALLS;
|
||||
}
|
||||
else
|
||||
{
|
||||
cballsLeft++;
|
||||
}
|
||||
}
|
||||
|
||||
cannonBallNotificationSent = false;
|
||||
}
|
||||
else if (event.getMessage().contains("Your cannon is out of ammo!"))
|
||||
{
|
||||
skipProjectileCheckThisTick = true;
|
||||
|
||||
// If the player was out of range of the cannon, some cannonballs
|
||||
// may have been used without the client knowing, so having this
|
||||
// extra check is a good idea.
|
||||
cballsLeft = 0;
|
||||
|
||||
if (config.showCannonNotifications())
|
||||
{
|
||||
notifier.notify("Your cannon is out of ammo!");
|
||||
}
|
||||
}
|
||||
else if (event.getMessage().startsWith("Your cannon contains"))
|
||||
{
|
||||
Matcher m = NUMBER_PATTERN.matcher(event.getMessage());
|
||||
if (m.find())
|
||||
{
|
||||
cballsLeft = Integer.parseInt(m.group());
|
||||
}
|
||||
}
|
||||
else if (event.getMessage().startsWith("You unload your cannon and receive Cannonball")
|
||||
|| event.getMessage().startsWith("You unload your cannon and receive Granite cannonball"))
|
||||
{
|
||||
skipProjectileCheckThisTick = true;
|
||||
|
||||
cballsLeft = 0;
|
||||
}
|
||||
else if (event.getMessage().equals("This isn't your cannon!") || event.getMessage().equals("This is not your cannon."))
|
||||
{
|
||||
clickedCannonLocation = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameTick(GameTick event)
|
||||
{
|
||||
skipProjectileCheckThisTick = false;
|
||||
}
|
||||
|
||||
Color getStateColor()
|
||||
{
|
||||
if (cballsLeft > 15)
|
||||
|
||||
@@ -31,10 +31,9 @@ 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.VarPlayer;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.VarbitChanged;
|
||||
import net.runelite.client.Notifier;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
@@ -45,8 +44,11 @@ import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import org.mockito.Mock;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@@ -89,13 +91,12 @@ public class CannonPluginTest
|
||||
@Bind
|
||||
private OverlayManager overlayManager;
|
||||
|
||||
private static final ChatMessage ADD_FURNACE = new ChatMessage();
|
||||
private static final VarbitChanged cannonAmmoChanged = new VarbitChanged();
|
||||
|
||||
@BeforeClass
|
||||
public static void chatMessageSetup()
|
||||
public static void cannonVarpSetup()
|
||||
{
|
||||
ADD_FURNACE.setType(ChatMessageType.SPAM);
|
||||
ADD_FURNACE.setMessage("You add the furnace.");
|
||||
cannonAmmoChanged.setIndex(VarPlayer.CANNON_AMMO.getId());
|
||||
}
|
||||
|
||||
@Before
|
||||
@@ -105,82 +106,92 @@ public class CannonPluginTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addWrongTypeOfCannonballs()
|
||||
public void testAmmoCountOnPlace()
|
||||
{
|
||||
final ChatMessage message = new ChatMessage();
|
||||
message.setType(ChatMessageType.GAMEMESSAGE);
|
||||
message.setMessage("Your cannon contains 20 x Cannonball.<br>You can only add cannonballs of the same kind.");
|
||||
ChatMessage chatMessage = new ChatMessage();
|
||||
chatMessage.setType(ChatMessageType.SPAM);
|
||||
chatMessage.setMessage("You add the furnace.");
|
||||
|
||||
plugin.onChatMessage(message);
|
||||
|
||||
assertEquals(20, plugin.getCballsLeft());
|
||||
}
|
||||
|
||||
@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);
|
||||
plugin.onChatMessage(chatMessage);
|
||||
assertTrue(plugin.isCannonPlaced());
|
||||
|
||||
assertEquals(30, plugin.getCballsLeft());
|
||||
plugin.onVarbitChanged(cannonAmmoChanged);
|
||||
assertEquals(0, plugin.getCballsLeft());
|
||||
|
||||
plugin.onChatMessage(loadCannonballs(30));
|
||||
// Some time passes...
|
||||
|
||||
when(client.getVar(VarPlayer.CANNON_AMMO)).thenReturn(30);
|
||||
plugin.onVarbitChanged(cannonAmmoChanged);
|
||||
assertEquals(30, plugin.getCballsLeft());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addNotMaxCannonballs()
|
||||
public void testCannonInfoBox()
|
||||
{
|
||||
final ItemContainer inventory = mock(ItemContainer.class);
|
||||
when(client.getItemContainer(InventoryID.INVENTORY)).thenReturn(inventory);
|
||||
when(inventory.count(ItemID.GRANITE_CANNONBALL)).thenReturn(12);
|
||||
when(config.showInfobox()).thenReturn(true);
|
||||
|
||||
plugin.onChatMessage(ADD_FURNACE);
|
||||
ChatMessage chatMessage = new ChatMessage();
|
||||
chatMessage.setType(ChatMessageType.SPAM);
|
||||
chatMessage.setMessage("You add the furnace.");
|
||||
|
||||
plugin.onChatMessage(chatMessage);
|
||||
assertTrue(plugin.isCannonPlaced());
|
||||
|
||||
assertEquals(0, plugin.getCballsLeft());
|
||||
|
||||
plugin.onChatMessage(loadCannonballs(12));
|
||||
assertEquals(12, plugin.getCballsLeft());
|
||||
verify(infoBoxManager).addInfoBox(any(CannonCounter.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addReclaimedCannonballs()
|
||||
public void testThresholdNotificationShouldNotify()
|
||||
{
|
||||
final ItemContainer inventory = mock(ItemContainer.class);
|
||||
when(client.getItemContainer(InventoryID.INVENTORY)).thenReturn(inventory);
|
||||
when(inventory.count(ItemID.CANNONBALL)).thenReturn(1250);
|
||||
when(config.showCannonNotifications()).thenReturn(true);
|
||||
when(config.lowWarningThreshold()).thenReturn(10);
|
||||
|
||||
plugin.onChatMessage(ADD_FURNACE);
|
||||
assertTrue(plugin.isCannonPlaced());
|
||||
when(client.getVar(VarPlayer.CANNON_AMMO)).thenReturn(30);
|
||||
plugin.onVarbitChanged(cannonAmmoChanged);
|
||||
when(client.getVar(VarPlayer.CANNON_AMMO)).thenReturn(10);
|
||||
plugin.onVarbitChanged(cannonAmmoChanged);
|
||||
|
||||
assertEquals(30, plugin.getCballsLeft());
|
||||
|
||||
plugin.onChatMessage(loadCannonballs(18));
|
||||
assertEquals(30, plugin.getCballsLeft());
|
||||
verify(notifier, times(1)).notify("Your cannon has 10 cannon balls remaining!");
|
||||
}
|
||||
|
||||
private static ChatMessage loadCannonballs(final int numCannonballs)
|
||||
@Test
|
||||
public void testThresholdNotificationShouldNotifyOnce()
|
||||
{
|
||||
final ChatMessage message = new ChatMessage();
|
||||
message.setType(ChatMessageType.GAMEMESSAGE);
|
||||
when(config.showCannonNotifications()).thenReturn(true);
|
||||
when(config.lowWarningThreshold()).thenReturn(10);
|
||||
|
||||
// Cannons use the same chat message for loading cannonballs regardless of whether they're normal or granite.
|
||||
if (numCannonballs == 1)
|
||||
for (int cballs = 15; cballs >= 8; --cballs)
|
||||
{
|
||||
message.setMessage("You load the cannon with one cannonball.");
|
||||
}
|
||||
else
|
||||
{
|
||||
message.setMessage(String.format("You load the cannon with %s cannonballs.", numCannonballs));
|
||||
when(client.getVar(VarPlayer.CANNON_AMMO)).thenReturn(cballs);
|
||||
plugin.onVarbitChanged(cannonAmmoChanged);
|
||||
}
|
||||
|
||||
return message;
|
||||
verify(notifier, times(1)).notify("Your cannon has 10 cannon balls remaining!");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThresholdNotificationsShouldNotNotify()
|
||||
{
|
||||
when(config.showCannonNotifications()).thenReturn(true);
|
||||
when(config.lowWarningThreshold()).thenReturn(0);
|
||||
|
||||
when(client.getVar(VarPlayer.CANNON_AMMO)).thenReturn(30);
|
||||
plugin.onVarbitChanged(cannonAmmoChanged);
|
||||
when(client.getVar(VarPlayer.CANNON_AMMO)).thenReturn(10);
|
||||
plugin.onVarbitChanged(cannonAmmoChanged);
|
||||
|
||||
verify(notifier, never()).notify("Your cannon has 10 cannon balls remaining!");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCannonOutOfAmmo()
|
||||
{
|
||||
when(config.showCannonNotifications()).thenReturn(true);
|
||||
ChatMessage cannonOutOfAmmo = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", "Your cannon is out of ammo!", "", 0);
|
||||
|
||||
plugin.onChatMessage(cannonOutOfAmmo);
|
||||
|
||||
verify(notifier, times(1)).notify("Your cannon is out of ammo!");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user