Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/main/java/com/attacktimer/AttackTimerMetronomePlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -398,14 +398,15 @@ public boolean isAttackCooldownPending()

// Match only the start of the line with `^` and the Pattern.MULTILINE
private static final Pattern EAT_MESSAGE = Pattern
.compile("^(" + GENERIC_EAT + "|" + BARBARIAN_POTIONS + "|" + JUG_OF_WINE + ")", Pattern.MULTILINE);
.compile("^(" + GENERIC_EAT + "|" + BARBARIAN_POTIONS + "|" + JUG_OF_WINE + ")", Pattern.MULTILINE & Pattern.CASE_INSENSITIVE);

// gnome foods are also fast eats (Note these are not the food names as the wiki lists them, but the name
// as written in chat), also pre-made and handmade have the same chat message.
private static final String FAST_GNOME_FOOD = "worm hole|tangled toads legs|veg ball|chocolate bomb|worm crunchies|toad crunchies|"
+ "choc chip crunchies|spicy crunchies|fruit batta|cheese and tomato batta|toad batta|vegetable batta|worm batta";
private static final String FAST_FOOD = "karambwan|halibut";
private static final Pattern FAST_EAT = Pattern.compile("(" + FAST_FOOD + "|" + FAST_GNOME_FOOD + ")");
// TODO ^ find out the food messages for https://oldschool.runescape.wiki/w/Crystal_paddlefish and https://oldschool.runescape.wiki/w/Corrupted_paddlefish
private static final Pattern FAST_EAT = Pattern.compile("(" + FAST_FOOD + "|" + FAST_GNOME_FOOD + ")", Pattern.CASE_INSENSITIVE);

@Subscribe
public void onChatMessage(ChatMessage event)
Expand Down
78 changes: 78 additions & 0 deletions src/test/java/com/attacktimer/EatTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package com.attacktimer;

/*
* Copyright (c) 2026, Lexer747 <https://github.com/Lexer747>
* 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.
*/

import static org.mockito.Mockito.when;
import static org.junit.Assert.assertSame;
import org.junit.Test;

import com.attacktimer.AttackTimerMetronomePlugin.AttackState;

import net.runelite.api.ChatMessageType;
import net.runelite.api.Player;
import net.runelite.api.events.ChatMessage;
import net.runelite.api.events.GameTick;

public class EatTest extends IntegrationTests
{
@Test
public void ExhaustiveEatTest() throws Exception
{
Player mockedPlayer = pluginMockSetup();
when(mockedClient.getTickCount()).thenReturn(0);
when(mockedPlayer.getAnimation()).thenReturn(AnimationData.MELEE_GENERIC_SLASH.animationId);
underTest.onGameTick(new GameTick());
assertSame(AttackState.DELAYED_FIRST_TICK, underTest.attackState);
assertSame(3, underTest.attackDelayHoldoffTicks);
String[] fastFoodsToTest = {
// NOTE case sensitivity here is import this should reflect in-game so that the plugin is resilient
// to mixed casing
"Karambwan", "halibut", "choc chip crunchies",
};
String[] foodsToTest = {
"shark", "meat pizza", "A brand new food message", "sunlight antelope", "moonlight antelope",
"purple sweets"
};
var curEatDelayTicks = underTest.pendingEatDelayTicks;
for (String food : foodsToTest)
{
ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", "You eat the " + food + ".", "",
0);
underTest.onChatMessage(chatMessage);
curEatDelayTicks += 3;
assertSame(curEatDelayTicks, underTest.pendingEatDelayTicks);
}

for (String food : fastFoodsToTest)
{
ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", "You eat the " + food + ".", "",
0);
underTest.onChatMessage(chatMessage);
curEatDelayTicks += 2;
assertSame(curEatDelayTicks, underTest.pendingEatDelayTicks);
}
}
}
24 changes: 12 additions & 12 deletions src/test/java/com/attacktimer/IntegrationTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -81,38 +81,38 @@ public class IntegrationTests
{
@Mock
@Bind
private OverlayManager mockedOverlayManager;
protected OverlayManager mockedOverlayManager;

@Mock
@Bind
private ConfigManager mockedConfigManager;
protected ConfigManager mockedConfigManager;

@Mock
@Bind
private AttackTimerMetronomeTileOverlay mockedOverlay;
protected AttackTimerMetronomeTileOverlay mockedOverlay;

@Mock
@Bind
private AttackTimerBarOverlay mockedBarOverlay;
protected AttackTimerBarOverlay mockedBarOverlay;

@Mock
@Bind
private AttackTimerMetronomeConfig mockedConfig;
protected AttackTimerMetronomeConfig mockedConfig;

@Mock
@Bind
private ItemManager mockedItemManager;
protected ItemManager mockedItemManager;

@Mock
@Bind
private Client mockedClient;
protected Client mockedClient;

@Mock
@Bind
private NPCManager mockedNpcManager;
protected NPCManager mockedNpcManager;

@Inject
private AttackTimerMetronomePlugin underTest;
protected AttackTimerMetronomePlugin underTest;

@Before
public void setup()
Expand Down Expand Up @@ -307,7 +307,7 @@ public void eatingFoodTest() throws Exception
performStateVerificationOrUpdate(channel, Paths.get(testdata + "eatingFoodTest.txt"));
}

private void performStateVerificationOrUpdate(ByteArrayDataOutput channel, Path path) throws IOException
protected void performStateVerificationOrUpdate(ByteArrayDataOutput channel, Path path) throws IOException
{
var actualBytes = channel.toByteArray();
switch (Update.system())
Expand All @@ -330,13 +330,13 @@ private void performStateVerificationOrUpdate(ByteArrayDataOutput channel, Path
}
}

private void onGameTick(ByteArrayDataOutput file)
protected void onGameTick(ByteArrayDataOutput file)
{
underTest.onGameTick(new GameTick());
underTest.writeState(file);
}

private void writeTestMessage(String message, ByteArrayDataOutput file)
protected void writeTestMessage(String message, ByteArrayDataOutput file)
{
file.write(testMessagePrefix);
file.write(message.getBytes(StandardCharsets.UTF_8));
Expand Down
Loading