timetracking: add compost tracking

This commit is contained in:
LlemonDuck
2022-05-07 14:19:13 -07:00
committed by GitHub
parent bb1f49b0b4
commit 0500f94830
11 changed files with 758 additions and 9 deletions

View File

@@ -0,0 +1,323 @@
/*
* Copyright (c) 2022 LlemonDuck
* 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.timetracking.farming;
import com.google.inject.Guice;
import com.google.inject.testing.fieldbinder.Bind;
import com.google.inject.testing.fieldbinder.BoundFieldModule;
import java.time.Instant;
import java.util.Collections;
import javax.inject.Inject;
import net.runelite.api.ChatMessageType;
import net.runelite.api.Client;
import net.runelite.api.GameObject;
import net.runelite.api.ItemID;
import net.runelite.api.MenuAction;
import net.runelite.api.ObjectComposition;
import net.runelite.api.Player;
import net.runelite.api.Scene;
import net.runelite.api.Tile;
import net.runelite.api.coords.WorldPoint;
import net.runelite.api.events.ChatMessage;
import net.runelite.api.events.MenuOptionClicked;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.client.config.ConfigManager;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ErrorCollector;
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.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class CompostTrackerTest
{
@Inject
private CompostTracker compostTracker;
@Mock
@Bind
private Client client;
@Mock
@Bind
private FarmingWorld farmingWorld;
@Mock
@Bind
private ConfigManager configManager;
@Mock
@Bind
private FarmingRegion farmingRegion;
@Mock
@Bind
private FarmingPatch farmingPatch;
@Mock
@Bind
private GameObject patchObject;
@Mock
@Bind
private Player player;
@Mock
@Bind
private Scene scene;
@Mock
@Bind
private Tile tile;
@Mock
@Bind
private ObjectComposition patchDef;
@Rule
public ErrorCollector collector = new ErrorCollector();
private static final int PATCH_ID = 12345;
private static final int PATCH_VARBIT = 54321;
private static final WorldPoint worldPoint = new WorldPoint(1, 2, 0);
@Before
public void before()
{
Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this);
compostTracker.pendingCompostActions.clear();
when(client.getBaseX()).thenReturn(0);
when(client.getBaseY()).thenReturn(0);
when(client.getPlane()).thenReturn(0);
when(client.getLocalPlayer()).thenReturn(player);
when(player.getWorldLocation()).thenReturn(worldPoint);
when(client.getScene()).thenReturn(scene);
when(client.getObjectDefinition(PATCH_ID)).thenReturn(patchDef);
when(scene.getTiles()).thenReturn(new Tile[][][]{{null, {null, null, tile}}}); // indices match worldPoint
when(tile.getGameObjects()).thenReturn(new GameObject[]{patchObject});
when(farmingWorld.getRegionsForLocation(any())).thenReturn(Collections.singleton(farmingRegion));
when(farmingRegion.getPatches()).thenReturn(new FarmingPatch[]{farmingPatch});
when(farmingPatch.getVarbit()).thenReturn(PATCH_VARBIT);
when(farmingPatch.configKey()).thenReturn("MOCK");
when(patchObject.getId()).thenReturn(PATCH_ID);
when(patchObject.sizeX()).thenReturn(1);
when(patchObject.sizeY()).thenReturn(1);
when(patchDef.getVarbitId()).thenReturn(PATCH_VARBIT);
}
@Test
public void setCompostState_storesNonNullChangesToConfig()
{
compostTracker.setCompostState(farmingPatch, CompostState.COMPOST);
verify(configManager).setRSProfileConfiguration("timetracking", "MOCK.compost", CompostState.COMPOST);
}
@Test
public void setCompostState_storesNullChangesByClearingConfig()
{
compostTracker.setCompostState(farmingPatch, null);
verify(configManager).unsetRSProfileConfiguration("timetracking", "MOCK.compost");
}
@Test
public void getCompostState_directlyReturnsFromConfig()
{
when(configManager.getRSProfileConfiguration("timetracking", "MOCK.compost", CompostState.class)).thenReturn(
CompostState.SUPERCOMPOST);
assertThat(compostTracker.getCompostState(farmingPatch), is(CompostState.SUPERCOMPOST));
}
@Test
public void determineCompostUsed_returnsAppropriateCompostValues()
{
// invalid
collector.checkThat(
CompostTracker.determineCompostUsed("This is not a farming chat message."),
is((CompostState) null)
);
collector.checkThat(
CompostTracker.determineCompostUsed("Contains word compost but is not examine message."),
is((CompostState) null)
);
// inspect
collector.checkThat(
CompostTracker.determineCompostUsed("This is an allotment. The soil has been treated with supercompost. The patch is empty and weeded."),
is(CompostState.SUPERCOMPOST)
);
// fertile soil on existing patch
collector.checkThat(
CompostTracker.determineCompostUsed("This patch has already been fertilised with ultracompost - the spell can't make it any more fertile."),
is(CompostState.ULTRACOMPOST)
);
// fertile soil on cleared patch
collector.checkThat(
CompostTracker.determineCompostUsed("The herb patch has been treated with supercompost."),
is(CompostState.SUPERCOMPOST)
);
// bucket on cleared patch
collector.checkThat(
CompostTracker.determineCompostUsed("You treat the herb patch with ultracompost."),
is(CompostState.ULTRACOMPOST)
);
collector.checkThat(
CompostTracker.determineCompostUsed("You treat the tree patch with compost."),
is(CompostState.COMPOST)
);
collector.checkThat(
CompostTracker.determineCompostUsed("You treat the fruit tree patch with supercompost."),
is(CompostState.SUPERCOMPOST)
);
}
@Test
public void onMenuOptionClicked_queuesPendingCompostForInspectActions()
{
MenuOptionClicked inspectPatchAction = mock(MenuOptionClicked.class);
when(inspectPatchAction.getMenuAction()).thenReturn(MenuAction.GAME_OBJECT_SECOND_OPTION);
when(inspectPatchAction.getMenuOption()).thenReturn("Inspect");
when(inspectPatchAction.getId()).thenReturn(PATCH_ID);
when(inspectPatchAction.getParam0()).thenReturn(1);
when(inspectPatchAction.getParam1()).thenReturn(2);
compostTracker.onMenuOptionClicked(inspectPatchAction);
CompostTracker.PendingCompost actual = compostTracker.pendingCompostActions.get(farmingPatch);
assertThat(actual.getFarmingPatch(), is(farmingPatch));
assertThat(actual.getPatchLocation(), is(new WorldPoint(1, 2, 0)));
}
@Test
public void onMenuOptionClicked_queuesPendingCompostForCompostActions()
{
Widget widget = mock(Widget.class);
when(client.getSelectedWidget()).thenReturn(widget);
when(widget.getItemId()).thenReturn(ItemID.ULTRACOMPOST);
MenuOptionClicked inspectPatchAction = mock(MenuOptionClicked.class);
when(inspectPatchAction.getMenuAction()).thenReturn(MenuAction.WIDGET_TARGET_ON_GAME_OBJECT);
when(inspectPatchAction.getId()).thenReturn(PATCH_ID);
when(inspectPatchAction.getParam0()).thenReturn(1);
when(inspectPatchAction.getParam1()).thenReturn(2);
compostTracker.onMenuOptionClicked(inspectPatchAction);
CompostTracker.PendingCompost actual = compostTracker.pendingCompostActions.get(farmingPatch);
assertThat(actual.getFarmingPatch(), is(farmingPatch));
assertThat(actual.getPatchLocation(), is(new WorldPoint(1, 2, 0)));
}
@Test
public void onMenuOptionClicked_queuesPendingCompostForFertileSoilSpellActions()
{
Widget widget = mock(Widget.class);
when(client.getSelectedWidget()).thenReturn(widget);
when(widget.getId()).thenReturn(WidgetInfo.SPELL_LUNAR_FERTILE_SOIL.getPackedId());
MenuOptionClicked inspectPatchAction = mock(MenuOptionClicked.class);
when(inspectPatchAction.getMenuAction()).thenReturn(MenuAction.WIDGET_TARGET_ON_GAME_OBJECT);
when(inspectPatchAction.getId()).thenReturn(PATCH_ID);
when(inspectPatchAction.getParam0()).thenReturn(1);
when(inspectPatchAction.getParam1()).thenReturn(2);
compostTracker.onMenuOptionClicked(inspectPatchAction);
CompostTracker.PendingCompost actual = compostTracker.pendingCompostActions.get(farmingPatch);
assertThat(actual.getFarmingPatch(), is(farmingPatch));
assertThat(actual.getPatchLocation(), is(new WorldPoint(1, 2, 0)));
}
@Test
public void onChatMessage_ignoresInvalidTypes()
{
ChatMessage chatEvent = mock(ChatMessage.class);
when(chatEvent.getType()).thenReturn(ChatMessageType.PUBLICCHAT);
compostTracker.onChatMessage(chatEvent);
verifyNoInteractions(client);
verifyNoInteractions(farmingWorld);
}
@Test
public void onChatMessage_handlesInspectMessages()
{
ChatMessage chatEvent = mock(ChatMessage.class);
when(chatEvent.getType()).thenReturn(ChatMessageType.SPAM);
when(chatEvent.getMessage()).thenReturn("This is a tree patch. The soil has been treated with ultracompost. The patch is empty and weeded.");
compostTracker.pendingCompostActions.put(farmingPatch, new CompostTracker.PendingCompost(Instant.MAX, worldPoint, farmingPatch));
compostTracker.onChatMessage(chatEvent);
verify(configManager).setRSProfileConfiguration("timetracking", "MOCK.compost", CompostState.ULTRACOMPOST);
}
@Test
public void onChatMessage_handlesBucketUseMessages()
{
ChatMessage chatEvent = mock(ChatMessage.class);
when(chatEvent.getType()).thenReturn(ChatMessageType.SPAM);
when(chatEvent.getMessage()).thenReturn("You treat the herb patch with compost.");
compostTracker.pendingCompostActions.put(farmingPatch, new CompostTracker.PendingCompost(Instant.MAX, worldPoint, farmingPatch));
compostTracker.onChatMessage(chatEvent);
verify(configManager).setRSProfileConfiguration("timetracking", "MOCK.compost", CompostState.COMPOST);
}
@Test
public void onChatMessage_handlesFertileSoilMessages()
{
ChatMessage chatEvent = mock(ChatMessage.class);
when(chatEvent.getType()).thenReturn(ChatMessageType.SPAM);
when(chatEvent.getMessage()).thenReturn("The allotment has been treated with supercompost.");
compostTracker.pendingCompostActions.put(farmingPatch, new CompostTracker.PendingCompost(Instant.MAX, worldPoint, farmingPatch));
compostTracker.onChatMessage(chatEvent);
verify(configManager).setRSProfileConfiguration("timetracking", "MOCK.compost", CompostState.SUPERCOMPOST);
}
}