project: upstream to d314c0ecee
This commit is contained in:
@@ -24,6 +24,7 @@
|
|||||||
*/
|
*/
|
||||||
package net.runelite.http.api.ge;
|
package net.runelite.http.api.ge;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import net.runelite.http.api.worlds.WorldType;
|
import net.runelite.http.api.worlds.WorldType;
|
||||||
|
|
||||||
@@ -42,4 +43,6 @@ public class GrandExchangeTrade
|
|||||||
private int offer;
|
private int offer;
|
||||||
private int slot;
|
private int slot;
|
||||||
private WorldType worldType;
|
private WorldType worldType;
|
||||||
}
|
private int seq;
|
||||||
|
private Instant resetTime;
|
||||||
|
}
|
||||||
@@ -12,4 +12,9 @@ public interface WidgetNode extends Node
|
|||||||
* @see net.runelite.api.widgets.Widget
|
* @see net.runelite.api.widgets.Widget
|
||||||
*/
|
*/
|
||||||
int getId();
|
int getId();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see net.runelite.api.widgets.WidgetModalMode
|
||||||
|
*/
|
||||||
|
int getModalMode();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Abex
|
||||||
|
* 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.api.events;
|
||||||
|
|
||||||
|
import lombok.Value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Posted when an interface is about to be closed
|
||||||
|
*/
|
||||||
|
@Value
|
||||||
|
public class WidgetClosed
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The ID of the interface that is closed
|
||||||
|
*/
|
||||||
|
private final int groupId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see net.runelite.api.widgets.WidgetModalMode
|
||||||
|
*/
|
||||||
|
private final int modalMode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the interface will be unloaded or if it will be immediately reloaded
|
||||||
|
*/
|
||||||
|
private final boolean unload;
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Abex
|
||||||
|
* 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.api.widgets;
|
||||||
|
|
||||||
|
public class WidgetModalMode
|
||||||
|
{
|
||||||
|
public static final int MODAL_NOCLICKTHROUGH = 0;
|
||||||
|
public static final int NON_MODAL = 1;
|
||||||
|
public static final int MODAL_CLICKTHROUGH = 3;
|
||||||
|
}
|
||||||
@@ -32,6 +32,8 @@ import java.util.Map;
|
|||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.table.AbstractTableModel;
|
import javax.swing.table.AbstractTableModel;
|
||||||
|
import net.runelite.api.Client;
|
||||||
|
import net.runelite.api.WidgetNode;
|
||||||
import net.runelite.api.widgets.Widget;
|
import net.runelite.api.widgets.Widget;
|
||||||
import net.runelite.client.callback.ClientThread;
|
import net.runelite.client.callback.ClientThread;
|
||||||
|
|
||||||
@@ -40,10 +42,13 @@ public class WidgetInfoTableModel extends AbstractTableModel
|
|||||||
@Inject
|
@Inject
|
||||||
private ClientThread clientThread;
|
private ClientThread clientThread;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private Client client;
|
||||||
|
|
||||||
private static final int COL_FIELD = 0;
|
private static final int COL_FIELD = 0;
|
||||||
private static final int COL_VALUE = 1;
|
private static final int COL_VALUE = 1;
|
||||||
|
|
||||||
private static final List<WidgetField> fields = populateWidgetFields();
|
private final List<WidgetField> fields = populateWidgetFields();
|
||||||
|
|
||||||
private Widget widget = null;
|
private Widget widget = null;
|
||||||
private Map<WidgetField, Object> values = null;
|
private Map<WidgetField, Object> values = null;
|
||||||
@@ -132,7 +137,7 @@ public class WidgetInfoTableModel extends AbstractTableModel
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<WidgetField> populateWidgetFields()
|
private List<WidgetField> populateWidgetFields()
|
||||||
{
|
{
|
||||||
List<WidgetField> out = new ArrayList<>();
|
List<WidgetField> out = new ArrayList<>();
|
||||||
|
|
||||||
@@ -194,6 +199,15 @@ public class WidgetInfoTableModel extends AbstractTableModel
|
|||||||
out.add(new WidgetField<>("NoScrollThrough", Widget::getNoScrollThrough, Widget::setNoScrollThrough, Boolean.class));
|
out.add(new WidgetField<>("NoScrollThrough", Widget::getNoScrollThrough, Widget::setNoScrollThrough, Boolean.class));
|
||||||
out.add(new WidgetField<>("TargetVerb", Widget::getTargetVerb, Widget::setTargetVerb, String.class));
|
out.add(new WidgetField<>("TargetVerb", Widget::getTargetVerb, Widget::setTargetVerb, String.class));
|
||||||
out.add(new WidgetField<>("DragParent", Widget::getDragParent));
|
out.add(new WidgetField<>("DragParent", Widget::getDragParent));
|
||||||
|
out.add(new WidgetField<>("ModalMode", w ->
|
||||||
|
{
|
||||||
|
WidgetNode attachment = client.getComponentTable().get(w.getParentId());
|
||||||
|
if (attachment != null)
|
||||||
|
{
|
||||||
|
return attachment.getModalMode();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}));
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,7 +119,9 @@ import org.apache.commons.text.similarity.FuzzyScore;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class GrandExchangePlugin extends Plugin
|
public class GrandExchangePlugin extends Plugin
|
||||||
{
|
{
|
||||||
private static final int GE_SLOTS = 8;
|
@VisibleForTesting
|
||||||
|
static final int GE_SLOTS = 8;
|
||||||
|
private static final int GE_LOGIN_BURST_WINDOW = 2; // ticks
|
||||||
private static final int OFFER_CONTAINER_ITEM = 21;
|
private static final int OFFER_CONTAINER_ITEM = 21;
|
||||||
private static final int OFFER_DEFAULT_ITEM_ID = 6512;
|
private static final int OFFER_DEFAULT_ITEM_ID = 6512;
|
||||||
private static final String OSB_GE_TEXT = "<br>OSBuddy Actively traded price: ";
|
private static final String OSB_GE_TEXT = "<br>OSBuddy Actively traded price: ";
|
||||||
@@ -141,6 +143,7 @@ public class GrandExchangePlugin extends Plugin
|
|||||||
private NavigationButton button;
|
private NavigationButton button;
|
||||||
|
|
||||||
@Getter(AccessLevel.PACKAGE)
|
@Getter(AccessLevel.PACKAGE)
|
||||||
|
@Setter(AccessLevel.PACKAGE)
|
||||||
private GrandExchangePanel panel;
|
private GrandExchangePanel panel;
|
||||||
|
|
||||||
@Getter(AccessLevel.PACKAGE)
|
@Getter(AccessLevel.PACKAGE)
|
||||||
@@ -189,7 +192,7 @@ public class GrandExchangePlugin extends Plugin
|
|||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private GrandExchangeClient grandExchangeClient;
|
private GrandExchangeClient grandExchangeClient;
|
||||||
private boolean loginBurstGeUpdates;
|
private int lastLoginTick;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private OSBGrandExchangeClient osbGrandExchangeClient;
|
private OSBGrandExchangeClient osbGrandExchangeClient;
|
||||||
@@ -198,6 +201,7 @@ public class GrandExchangePlugin extends Plugin
|
|||||||
|
|
||||||
private String machineUuid;
|
private String machineUuid;
|
||||||
private String lastUsername;
|
private String lastUsername;
|
||||||
|
private int tradeSeq;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logic from {@link org.apache.commons.text.similarity.FuzzyScore}
|
* Logic from {@link org.apache.commons.text.similarity.FuzzyScore}
|
||||||
@@ -314,6 +318,8 @@ public class GrandExchangePlugin extends Plugin
|
|||||||
|
|
||||||
osbItem = -1;
|
osbItem = -1;
|
||||||
osbGrandExchangeResult = null;
|
osbGrandExchangeResult = null;
|
||||||
|
|
||||||
|
lastLoginTick = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -325,6 +331,7 @@ public class GrandExchangePlugin extends Plugin
|
|||||||
grandExchangeText = null;
|
grandExchangeText = null;
|
||||||
grandExchangeItem = null;
|
grandExchangeItem = null;
|
||||||
lastUsername = machineUuid = null;
|
lastUsername = machineUuid = null;
|
||||||
|
tradeSeq = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
@@ -370,26 +377,23 @@ public class GrandExchangePlugin extends Plugin
|
|||||||
if (offer.getState() == GrandExchangeOfferState.EMPTY && client.getGameState() != GameState.LOGGED_IN)
|
if (offer.getState() == GrandExchangeOfferState.EMPTY && client.getGameState() != GameState.LOGGED_IN)
|
||||||
{
|
{
|
||||||
// Trades are cleared by the client during LOGIN_SCREEN/HOPPING/LOGGING_IN, ignore those so we don't
|
// Trades are cleared by the client during LOGIN_SCREEN/HOPPING/LOGGING_IN, ignore those so we don't
|
||||||
// zero and re-submit the trade on login as an update
|
// clear the offer config.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
log.debug("GE offer updated: state: {}, slot: {}, item: {}, qty: {}, login: {}",
|
log.debug("GE offer updated: state: {}, slot: {}, item: {}, qty: {}, lastLoginTick: {}",
|
||||||
offer.getState(), slot, offer.getItemId(), offer.getQuantitySold(), loginBurstGeUpdates);
|
offer.getState(), slot, offer.getItemId(), offer.getQuantitySold(), lastLoginTick);
|
||||||
|
|
||||||
ItemComposition offerItem = itemManager.getItemComposition(offer.getItemId());
|
ItemComposition offerItem = itemManager.getItemComposition(offer.getItemId());
|
||||||
boolean shouldStack = offerItem.isStackable() || offer.getTotalQuantity() > 1;
|
boolean shouldStack = offerItem.isStackable() || offer.getTotalQuantity() > 1;
|
||||||
BufferedImage itemImage = itemManager.getImage(offer.getItemId(), offer.getTotalQuantity(), shouldStack);
|
BufferedImage itemImage = itemManager.getImage(offer.getItemId(), offer.getTotalQuantity(), shouldStack);
|
||||||
SwingUtilities.invokeLater(() -> panel.getOffersPanel().updateOffer(offerItem, itemImage, offer, slot));
|
SwingUtilities.invokeLater(() -> panel.getOffersPanel().updateOffer(offerItem, itemImage, offer, slot));
|
||||||
|
|
||||||
|
updateLimitTimer(offer);
|
||||||
|
|
||||||
submitTrade(slot, offer);
|
submitTrade(slot, offer);
|
||||||
|
|
||||||
updateConfig(slot, offer);
|
updateConfig(slot, offer);
|
||||||
|
|
||||||
if (loginBurstGeUpdates && slot == GE_SLOTS - 1) // slots are sent sequentially on login; this is the last one
|
|
||||||
{
|
|
||||||
loginBurstGeUpdates = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@@ -403,6 +407,7 @@ public class GrandExchangePlugin extends Plugin
|
|||||||
}
|
}
|
||||||
|
|
||||||
SavedOffer savedOffer = getOffer(slot);
|
SavedOffer savedOffer = getOffer(slot);
|
||||||
|
boolean login = client.getTickCount() <= lastLoginTick + GE_LOGIN_BURST_WINDOW;
|
||||||
if (savedOffer == null && (state == GrandExchangeOfferState.BUYING || state == GrandExchangeOfferState.SELLING) && offer.getQuantitySold() == 0)
|
if (savedOffer == null && (state == GrandExchangeOfferState.BUYING || state == GrandExchangeOfferState.SELLING) && offer.getQuantitySold() == 0)
|
||||||
{
|
{
|
||||||
// new offer
|
// new offer
|
||||||
@@ -413,7 +418,9 @@ public class GrandExchangePlugin extends Plugin
|
|||||||
grandExchangeTrade.setOffer(offer.getPrice());
|
grandExchangeTrade.setOffer(offer.getPrice());
|
||||||
grandExchangeTrade.setSlot(slot);
|
grandExchangeTrade.setSlot(slot);
|
||||||
grandExchangeTrade.setWorldType(getGeWorldType());
|
grandExchangeTrade.setWorldType(getGeWorldType());
|
||||||
grandExchangeTrade.setLogin(loginBurstGeUpdates);
|
grandExchangeTrade.setLogin(login);
|
||||||
|
grandExchangeTrade.setSeq(tradeSeq++);
|
||||||
|
grandExchangeTrade.setResetTime(getLimitResetTime(offer.getItemId()));
|
||||||
|
|
||||||
log.debug("Submitting new trade: {}", grandExchangeTrade);
|
log.debug("Submitting new trade: {}", grandExchangeTrade);
|
||||||
grandExchangeClient.submit(grandExchangeTrade);
|
grandExchangeClient.submit(grandExchangeTrade);
|
||||||
@@ -444,7 +451,9 @@ public class GrandExchangePlugin extends Plugin
|
|||||||
grandExchangeTrade.setOffer(offer.getPrice());
|
grandExchangeTrade.setOffer(offer.getPrice());
|
||||||
grandExchangeTrade.setSlot(slot);
|
grandExchangeTrade.setSlot(slot);
|
||||||
grandExchangeTrade.setWorldType(getGeWorldType());
|
grandExchangeTrade.setWorldType(getGeWorldType());
|
||||||
grandExchangeTrade.setLogin(loginBurstGeUpdates);
|
grandExchangeTrade.setLogin(login);
|
||||||
|
grandExchangeTrade.setSeq(tradeSeq++);
|
||||||
|
grandExchangeTrade.setResetTime(getLimitResetTime(offer.getItemId()));
|
||||||
|
|
||||||
log.debug("Submitting cancelled: {}", grandExchangeTrade);
|
log.debug("Submitting cancelled: {}", grandExchangeTrade);
|
||||||
grandExchangeClient.submit(grandExchangeTrade);
|
grandExchangeClient.submit(grandExchangeTrade);
|
||||||
@@ -469,7 +478,9 @@ public class GrandExchangePlugin extends Plugin
|
|||||||
grandExchangeTrade.setOffer(offer.getPrice());
|
grandExchangeTrade.setOffer(offer.getPrice());
|
||||||
grandExchangeTrade.setSlot(slot);
|
grandExchangeTrade.setSlot(slot);
|
||||||
grandExchangeTrade.setWorldType(getGeWorldType());
|
grandExchangeTrade.setWorldType(getGeWorldType());
|
||||||
grandExchangeTrade.setLogin(loginBurstGeUpdates);
|
grandExchangeTrade.setLogin(login);
|
||||||
|
grandExchangeTrade.setSeq(tradeSeq++);
|
||||||
|
grandExchangeTrade.setResetTime(getLimitResetTime(offer.getItemId()));
|
||||||
|
|
||||||
log.debug("Submitting trade: {}", grandExchangeTrade);
|
log.debug("Submitting trade: {}", grandExchangeTrade);
|
||||||
grandExchangeClient.submit(grandExchangeTrade);
|
grandExchangeClient.submit(grandExchangeTrade);
|
||||||
@@ -508,8 +519,6 @@ public class GrandExchangePlugin extends Plugin
|
|||||||
savedOffer.setSpent(offer.getSpent());
|
savedOffer.setSpent(offer.getSpent());
|
||||||
savedOffer.setState(offer.getState());
|
savedOffer.setState(offer.getState());
|
||||||
setOffer(slot, savedOffer);
|
setOffer(slot, savedOffer);
|
||||||
|
|
||||||
updateLimitTimer(offer);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -532,14 +541,19 @@ public class GrandExchangePlugin extends Plugin
|
|||||||
@Subscribe
|
@Subscribe
|
||||||
public void onGameStateChanged(GameStateChanged gameStateChanged)
|
public void onGameStateChanged(GameStateChanged gameStateChanged)
|
||||||
{
|
{
|
||||||
if (gameStateChanged.getGameState() == GameState.LOGIN_SCREEN)
|
switch (gameStateChanged.getGameState())
|
||||||
{
|
{
|
||||||
panel.getOffersPanel().resetOffers();
|
case LOGIN_SCREEN:
|
||||||
loginBurstGeUpdates = true;
|
panel.getOffersPanel().resetOffers();
|
||||||
}
|
break;
|
||||||
else if (gameStateChanged.getGameState() == GameState.LOGGED_IN)
|
case LOGGING_IN:
|
||||||
{
|
case HOPPING:
|
||||||
grandExchangeClient.setMachineId(getMachineUuid());
|
case CONNECTION_LOST:
|
||||||
|
lastLoginTick = client.getTickCount();
|
||||||
|
break;
|
||||||
|
case LOGGED_IN:
|
||||||
|
grandExchangeClient.setMachineId(getMachineUuid());
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -952,12 +966,14 @@ public class GrandExchangePlugin extends Plugin
|
|||||||
}
|
}
|
||||||
hasher.putUnencodedChars(username);
|
hasher.putUnencodedChars(username);
|
||||||
machineUuid = hasher.hash().toString();
|
machineUuid = hasher.hash().toString();
|
||||||
|
tradeSeq = 0;
|
||||||
return machineUuid;
|
return machineUuid;
|
||||||
}
|
}
|
||||||
catch (SocketException ex)
|
catch (SocketException ex)
|
||||||
{
|
{
|
||||||
log.debug("unable to generate machine id", ex);
|
log.debug("unable to generate machine id", ex);
|
||||||
machineUuid = null;
|
machineUuid = null;
|
||||||
|
tradeSeq = 0;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,8 @@ public enum Tab
|
|||||||
HOPS("Hops Patches", ItemID.BARLEY),
|
HOPS("Hops Patches", ItemID.BARLEY),
|
||||||
BUSH("Bush Patches", ItemID.POISON_IVY_BERRIES),
|
BUSH("Bush Patches", ItemID.POISON_IVY_BERRIES),
|
||||||
GRAPE("Grape Patches", ItemID.GRAPES),
|
GRAPE("Grape Patches", ItemID.GRAPES),
|
||||||
SPECIAL("Special Patches", ItemID.MUSHROOM);
|
SPECIAL("Special Patches", ItemID.MUSHROOM),
|
||||||
|
TIME_OFFSET("Farming Tick Offset", ItemID.WATERING_CAN);
|
||||||
|
|
||||||
public static final Tab[] FARMING_TABS = {HERB, TREE, FRUIT_TREE, SPECIAL, FLOWER, ALLOTMENT, BUSH, GRAPE, HOPS};
|
public static final Tab[] FARMING_TABS = {HERB, TREE, FRUIT_TREE, SPECIAL, FLOWER, ALLOTMENT, BUSH, GRAPE, HOPS};
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ import net.runelite.client.config.Units;
|
|||||||
public interface TimeTrackingConfig extends Config
|
public interface TimeTrackingConfig extends Config
|
||||||
{
|
{
|
||||||
String CONFIG_GROUP = "timetracking";
|
String CONFIG_GROUP = "timetracking";
|
||||||
|
String FARM_TICK_OFFSET = "farmTickOffset";
|
||||||
|
String FARM_TICK_OFFSET_PRECISION = "farmTickOffsetPrecision";
|
||||||
String AUTOWEED = "autoweed";
|
String AUTOWEED = "autoweed";
|
||||||
String BIRD_HOUSE = "birdhouse";
|
String BIRD_HOUSE = "birdhouse";
|
||||||
String BOTANIST = "botanist";
|
String BOTANIST = "botanist";
|
||||||
|
|||||||
@@ -25,6 +25,8 @@
|
|||||||
*/
|
*/
|
||||||
package net.runelite.client.plugins.timetracking;
|
package net.runelite.client.plugins.timetracking;
|
||||||
|
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.name.Named;
|
||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.GridLayout;
|
import java.awt.GridLayout;
|
||||||
@@ -38,16 +40,18 @@ import javax.swing.JPanel;
|
|||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.border.EmptyBorder;
|
import javax.swing.border.EmptyBorder;
|
||||||
import net.runelite.client.util.AsyncBufferedImage;
|
import net.runelite.client.config.ConfigManager;
|
||||||
import net.runelite.client.game.ItemManager;
|
import net.runelite.client.game.ItemManager;
|
||||||
import net.runelite.client.plugins.timetracking.clocks.ClockManager;
|
import net.runelite.client.plugins.timetracking.clocks.ClockManager;
|
||||||
import net.runelite.client.plugins.timetracking.farming.FarmingContractManager;
|
import net.runelite.client.plugins.timetracking.farming.FarmingContractManager;
|
||||||
|
import net.runelite.client.plugins.timetracking.farming.FarmingNextTickPanel;
|
||||||
import net.runelite.client.plugins.timetracking.farming.FarmingTracker;
|
import net.runelite.client.plugins.timetracking.farming.FarmingTracker;
|
||||||
import net.runelite.client.plugins.timetracking.hunter.BirdHouseTracker;
|
import net.runelite.client.plugins.timetracking.hunter.BirdHouseTracker;
|
||||||
import net.runelite.client.ui.ColorScheme;
|
import net.runelite.client.ui.ColorScheme;
|
||||||
import net.runelite.client.ui.PluginPanel;
|
import net.runelite.client.ui.PluginPanel;
|
||||||
import net.runelite.client.ui.components.materialtabs.MaterialTab;
|
import net.runelite.client.ui.components.materialtabs.MaterialTab;
|
||||||
import net.runelite.client.ui.components.materialtabs.MaterialTabGroup;
|
import net.runelite.client.ui.components.materialtabs.MaterialTabGroup;
|
||||||
|
import net.runelite.client.util.AsyncBufferedImage;
|
||||||
|
|
||||||
class TimeTrackingPanel extends PluginPanel
|
class TimeTrackingPanel extends PluginPanel
|
||||||
{
|
{
|
||||||
@@ -64,9 +68,11 @@ class TimeTrackingPanel extends PluginPanel
|
|||||||
@Nullable
|
@Nullable
|
||||||
private TabContentPanel activeTabPanel = null;
|
private TabContentPanel activeTabPanel = null;
|
||||||
|
|
||||||
TimeTrackingPanel(ItemManager itemManager, TimeTrackingConfig config,
|
@Inject
|
||||||
FarmingTracker farmingTracker, BirdHouseTracker birdHouseTracker, ClockManager clockManager,
|
TimeTrackingPanel(ItemManager itemManager, TimeTrackingConfig config, FarmingTracker farmingTracker,
|
||||||
FarmingContractManager farmingContractManager)
|
BirdHouseTracker birdHouseTracker, ClockManager clockManager,
|
||||||
|
FarmingContractManager farmingContractManager, ConfigManager configManager,
|
||||||
|
@Named("developerMode") boolean developerMode)
|
||||||
{
|
{
|
||||||
super(false);
|
super(false);
|
||||||
|
|
||||||
@@ -93,6 +99,11 @@ class TimeTrackingPanel extends PluginPanel
|
|||||||
{
|
{
|
||||||
addTab(tab, farmingTracker.createTabPanel(tab, farmingContractManager));
|
addTab(tab, farmingTracker.createTabPanel(tab, farmingContractManager));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (developerMode)
|
||||||
|
{
|
||||||
|
addTab(Tab.TIME_OFFSET, new FarmingNextTickPanel(farmingTracker, config, configManager));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addTab(Tab tab, TabContentPanel tabContentPanel)
|
private void addTab(Tab tab, TabContentPanel tabContentPanel)
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
*/
|
*/
|
||||||
package net.runelite.client.plugins.timetracking;
|
package net.runelite.client.plugins.timetracking;
|
||||||
|
|
||||||
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
@@ -32,20 +33,21 @@ import java.time.temporal.ChronoUnit;
|
|||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.ScheduledFuture;
|
import java.util.concurrent.ScheduledFuture;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import javax.inject.Inject;
|
|
||||||
import net.runelite.api.ChatMessageType;
|
import net.runelite.api.ChatMessageType;
|
||||||
import net.runelite.api.Client;
|
import net.runelite.api.Client;
|
||||||
import net.runelite.api.GameState;
|
import net.runelite.api.GameState;
|
||||||
import net.runelite.api.coords.WorldPoint;
|
import net.runelite.api.coords.WorldPoint;
|
||||||
import net.runelite.client.events.ConfigChanged;
|
|
||||||
import net.runelite.api.events.ChatMessage;
|
import net.runelite.api.events.ChatMessage;
|
||||||
|
import net.runelite.api.events.CommandExecuted;
|
||||||
import net.runelite.api.events.GameTick;
|
import net.runelite.api.events.GameTick;
|
||||||
|
import net.runelite.api.events.WidgetClosed;
|
||||||
import net.runelite.api.widgets.Widget;
|
import net.runelite.api.widgets.Widget;
|
||||||
import net.runelite.api.widgets.WidgetInfo;
|
import net.runelite.api.widgets.WidgetInfo;
|
||||||
|
import net.runelite.api.widgets.WidgetModalMode;
|
||||||
import net.runelite.client.config.ConfigManager;
|
import net.runelite.client.config.ConfigManager;
|
||||||
import net.runelite.client.eventbus.Subscribe;
|
import net.runelite.client.eventbus.Subscribe;
|
||||||
|
import net.runelite.client.events.ConfigChanged;
|
||||||
import net.runelite.client.events.RuneScapeProfileChanged;
|
import net.runelite.client.events.RuneScapeProfileChanged;
|
||||||
import net.runelite.client.game.ItemManager;
|
|
||||||
import net.runelite.client.plugins.Plugin;
|
import net.runelite.client.plugins.Plugin;
|
||||||
import net.runelite.client.plugins.PluginDescriptor;
|
import net.runelite.client.plugins.PluginDescriptor;
|
||||||
import static net.runelite.client.plugins.timetracking.TimeTrackingConfig.CONFIG_GROUP;
|
import static net.runelite.client.plugins.timetracking.TimeTrackingConfig.CONFIG_GROUP;
|
||||||
@@ -88,18 +90,15 @@ public class TimeTrackingPlugin extends Plugin
|
|||||||
@Inject
|
@Inject
|
||||||
private ClockManager clockManager;
|
private ClockManager clockManager;
|
||||||
|
|
||||||
@Inject
|
|
||||||
private ItemManager itemManager;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private TimeTrackingConfig config;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private InfoBoxManager infoBoxManager;
|
private InfoBoxManager infoBoxManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private ScheduledExecutorService executorService;
|
private ScheduledExecutorService executorService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private ConfigManager configManager;
|
||||||
|
|
||||||
private ScheduledFuture panelUpdateFuture;
|
private ScheduledFuture panelUpdateFuture;
|
||||||
|
|
||||||
private TimeTrackingPanel panel;
|
private TimeTrackingPanel panel;
|
||||||
@@ -109,6 +108,8 @@ public class TimeTrackingPlugin extends Plugin
|
|||||||
private WorldPoint lastTickLocation;
|
private WorldPoint lastTickLocation;
|
||||||
private boolean lastTickPostLogin;
|
private boolean lastTickPostLogin;
|
||||||
|
|
||||||
|
private int lastModalCloseTick = 0;
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
TimeTrackingConfig provideConfig(ConfigManager configManager)
|
TimeTrackingConfig provideConfig(ConfigManager configManager)
|
||||||
{
|
{
|
||||||
@@ -125,7 +126,7 @@ public class TimeTrackingPlugin extends Plugin
|
|||||||
|
|
||||||
final BufferedImage icon = ImageUtil.getResourceStreamFromClass(getClass(), "watch.png");
|
final BufferedImage icon = ImageUtil.getResourceStreamFromClass(getClass(), "watch.png");
|
||||||
|
|
||||||
panel = new TimeTrackingPanel(itemManager, config, farmingTracker, birdHouseTracker, clockManager, farmingContractManager);
|
panel = injector.getInstance(TimeTrackingPanel.class);
|
||||||
|
|
||||||
navButton = NavigationButton.builder()
|
navButton = NavigationButton.builder()
|
||||||
.tooltip("Time Tracking")
|
.tooltip("Time Tracking")
|
||||||
@@ -174,6 +175,16 @@ public class TimeTrackingPlugin extends Plugin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onCommandExecuted(CommandExecuted commandExecuted)
|
||||||
|
{
|
||||||
|
if (commandExecuted.getCommand().equals("resetfarmtick"))
|
||||||
|
{
|
||||||
|
configManager.unsetRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, TimeTrackingConfig.FARM_TICK_OFFSET_PRECISION);
|
||||||
|
configManager.unsetRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, TimeTrackingConfig.FARM_TICK_OFFSET);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onGameTick(GameTick t)
|
public void onGameTick(GameTick t)
|
||||||
{
|
{
|
||||||
@@ -206,7 +217,7 @@ public class TimeTrackingPlugin extends Plugin
|
|||||||
}
|
}
|
||||||
|
|
||||||
boolean birdHouseDataChanged = birdHouseTracker.updateData(loc);
|
boolean birdHouseDataChanged = birdHouseTracker.updateData(loc);
|
||||||
boolean farmingDataChanged = farmingTracker.updateData(loc);
|
boolean farmingDataChanged = farmingTracker.updateData(loc, client.getTickCount() - lastModalCloseTick);
|
||||||
boolean farmingContractDataChanged = farmingContractManager.updateData(loc);
|
boolean farmingContractDataChanged = farmingContractManager.updateData(loc);
|
||||||
|
|
||||||
if (birdHouseDataChanged || farmingDataChanged || farmingContractDataChanged)
|
if (birdHouseDataChanged || farmingDataChanged || farmingContractDataChanged)
|
||||||
@@ -235,6 +246,15 @@ public class TimeTrackingPlugin extends Plugin
|
|||||||
farmingContractManager.setContract(null);
|
farmingContractManager.setContract(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
private void onWidgetClosed(WidgetClosed ev)
|
||||||
|
{
|
||||||
|
if (ev.getModalMode() != WidgetModalMode.NON_MODAL)
|
||||||
|
{
|
||||||
|
lastModalCloseTick = client.getTickCount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Schedule(period = 10, unit = ChronoUnit.SECONDS)
|
@Schedule(period = 10, unit = ChronoUnit.SECONDS)
|
||||||
public void checkCompletion()
|
public void checkCompletion()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
*/
|
*/
|
||||||
package net.runelite.client.plugins.timetracking.farming;
|
package net.runelite.client.plugins.timetracking.farming;
|
||||||
|
|
||||||
|
import com.google.inject.Singleton;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
@@ -47,6 +48,7 @@ import net.runelite.client.plugins.timetracking.TimeTrackingPlugin;
|
|||||||
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
|
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
|
||||||
import net.runelite.client.util.Text;
|
import net.runelite.client.util.Text;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
public class FarmingContractManager
|
public class FarmingContractManager
|
||||||
{
|
{
|
||||||
private static final int GUILDMASTER_JANE_NPC_ID = NullNpcID.NULL_8628;
|
private static final int GUILDMASTER_JANE_NPC_ID = NullNpcID.NULL_8628;
|
||||||
@@ -264,7 +266,7 @@ public class FarmingContractManager
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((contract.requiresHealthCheck() && state == CropState.HARVESTABLE)
|
if ((contract.getPatchImplementation().isHealthCheckRequired() && state == CropState.HARVESTABLE)
|
||||||
&& !(hasEmptyPatch || hasDiseasedPatch || hasDeadPatch))
|
&& !(hasEmptyPatch || hasDiseasedPatch || hasDeadPatch))
|
||||||
{
|
{
|
||||||
summary = SummaryState.OCCUPIED;
|
summary = SummaryState.OCCUPIED;
|
||||||
|
|||||||
@@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Morgan Lewis
|
||||||
|
* 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.Inject;
|
||||||
|
import java.awt.GridBagConstraints;
|
||||||
|
import java.awt.GridBagLayout;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.swing.JTextArea;
|
||||||
|
import net.runelite.client.config.ConfigManager;
|
||||||
|
import net.runelite.client.plugins.timetracking.TabContentPanel;
|
||||||
|
import net.runelite.client.plugins.timetracking.TimeTrackingConfig;
|
||||||
|
import net.runelite.client.plugins.timetracking.TimeablePanel;
|
||||||
|
import net.runelite.client.ui.ColorScheme;
|
||||||
|
|
||||||
|
public class FarmingNextTickPanel extends TabContentPanel
|
||||||
|
{
|
||||||
|
private final FarmingTracker farmingTracker;
|
||||||
|
private final TimeTrackingConfig config;
|
||||||
|
private final ConfigManager configManager;
|
||||||
|
private final List<TimeablePanel<Void>> patchPanels;
|
||||||
|
private final JTextArea infoTextArea;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public FarmingNextTickPanel(
|
||||||
|
FarmingTracker farmingTracker,
|
||||||
|
TimeTrackingConfig config,
|
||||||
|
ConfigManager configManager
|
||||||
|
)
|
||||||
|
{
|
||||||
|
this.farmingTracker = farmingTracker;
|
||||||
|
this.config = config;
|
||||||
|
this.configManager = configManager;
|
||||||
|
this.patchPanels = new ArrayList<>();
|
||||||
|
|
||||||
|
setLayout(new GridBagLayout());
|
||||||
|
setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
|
|
||||||
|
GridBagConstraints c = new GridBagConstraints();
|
||||||
|
c.fill = GridBagConstraints.HORIZONTAL;
|
||||||
|
c.weightx = 1;
|
||||||
|
c.gridx = 0;
|
||||||
|
c.gridy = 0;
|
||||||
|
|
||||||
|
int[] times = {5, 10, 20, 40, 80, 160, 320, 640};
|
||||||
|
|
||||||
|
for (int time : times)
|
||||||
|
{
|
||||||
|
TimeablePanel<Void> panel = new TimeablePanel<>(null, time + " minute tick", time);
|
||||||
|
patchPanels.add(panel);
|
||||||
|
add(panel, c);
|
||||||
|
c.gridy++;
|
||||||
|
}
|
||||||
|
|
||||||
|
infoTextArea = new JTextArea();
|
||||||
|
add(infoTextArea, c);
|
||||||
|
c.gridy++;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getUpdateInterval()
|
||||||
|
{
|
||||||
|
return 50;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update()
|
||||||
|
{
|
||||||
|
long unixNow = Instant.now().getEpochSecond();
|
||||||
|
|
||||||
|
for (TimeablePanel<Void> panel : patchPanels)
|
||||||
|
{
|
||||||
|
int tickLength = panel.getProgress().getMaximumValue();
|
||||||
|
long nextTick = farmingTracker.getTickTime(tickLength, 1);
|
||||||
|
panel.getEstimate().setText(getFormattedEstimate(nextTick - unixNow, config.timeFormatMode()));
|
||||||
|
}
|
||||||
|
|
||||||
|
String offsetPrecisionMins = configManager.getRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, TimeTrackingConfig.FARM_TICK_OFFSET_PRECISION);
|
||||||
|
String offsetTimeMins = configManager.getRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, TimeTrackingConfig.FARM_TICK_OFFSET);
|
||||||
|
|
||||||
|
infoTextArea.setText("Offset precision:" + offsetPrecisionMins + "\nFarming tick offset: -" + offsetTimeMins);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -54,4 +54,10 @@ public class FarmingRegion
|
|||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,20 +27,24 @@ package net.runelite.client.plugins.timetracking.farming;
|
|||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.EnumMap;
|
import java.util.EnumMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.runelite.api.Client;
|
import net.runelite.api.Client;
|
||||||
import net.runelite.api.Varbits;
|
import net.runelite.api.Varbits;
|
||||||
import net.runelite.api.coords.WorldPoint;
|
import net.runelite.api.coords.WorldPoint;
|
||||||
import net.runelite.api.vars.Autoweed;
|
import net.runelite.api.vars.Autoweed;
|
||||||
|
import net.runelite.api.widgets.WidgetModalMode;
|
||||||
import net.runelite.client.config.ConfigManager;
|
import net.runelite.client.config.ConfigManager;
|
||||||
import net.runelite.client.game.ItemManager;
|
import net.runelite.client.game.ItemManager;
|
||||||
import net.runelite.client.plugins.timetracking.SummaryState;
|
import net.runelite.client.plugins.timetracking.SummaryState;
|
||||||
import net.runelite.client.plugins.timetracking.Tab;
|
import net.runelite.client.plugins.timetracking.Tab;
|
||||||
import net.runelite.client.plugins.timetracking.TimeTrackingConfig;
|
import net.runelite.client.plugins.timetracking.TimeTrackingConfig;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
@Singleton
|
@Singleton
|
||||||
public class FarmingTracker
|
public class FarmingTracker
|
||||||
{
|
{
|
||||||
@@ -58,9 +62,11 @@ public class FarmingTracker
|
|||||||
*/
|
*/
|
||||||
private final Map<Tab, Long> completionTimes = new EnumMap<>(Tab.class);
|
private final Map<Tab, Long> completionTimes = new EnumMap<>(Tab.class);
|
||||||
|
|
||||||
|
private boolean newRegionLoaded;
|
||||||
|
private Collection<FarmingRegion> lastRegions;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private FarmingTracker(Client client, ItemManager itemManager, ConfigManager configManager,
|
private FarmingTracker(Client client, ItemManager itemManager, ConfigManager configManager, TimeTrackingConfig config, FarmingWorld farmingWorld)
|
||||||
TimeTrackingConfig config, FarmingWorld farmingWorld)
|
|
||||||
{
|
{
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.itemManager = itemManager;
|
this.itemManager = itemManager;
|
||||||
@@ -69,7 +75,6 @@ public class FarmingTracker
|
|||||||
this.farmingWorld = farmingWorld;
|
this.farmingWorld = farmingWorld;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public FarmingTabPanel createTabPanel(Tab tab, FarmingContractManager farmingContractManager)
|
public FarmingTabPanel createTabPanel(Tab tab, FarmingContractManager farmingContractManager)
|
||||||
{
|
{
|
||||||
return new FarmingTabPanel(this, itemManager, config, farmingWorld.getTabs().get(tab), farmingContractManager);
|
return new FarmingTabPanel(this, itemManager, config, farmingWorld.getTabs().get(tab), farmingContractManager);
|
||||||
@@ -78,10 +83,18 @@ public class FarmingTracker
|
|||||||
/**
|
/**
|
||||||
* Updates tracker data for the current region. Returns true if any data was changed.
|
* Updates tracker data for the current region. Returns true if any data was changed.
|
||||||
*/
|
*/
|
||||||
public boolean updateData(WorldPoint location)
|
public boolean updateData(WorldPoint location, int timeSinceModalClose)
|
||||||
{
|
{
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
|
|
||||||
|
//Varbits don't get sent when a modal widget is open so just return
|
||||||
|
if (client.getComponentTable().getNodes()
|
||||||
|
.stream()
|
||||||
|
.anyMatch(widgetNode -> widgetNode.getModalMode() != WidgetModalMode.NON_MODAL))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
String autoweed = Integer.toString(client.getVar(Varbits.AUTOWEED));
|
String autoweed = Integer.toString(client.getVar(Varbits.AUTOWEED));
|
||||||
if (!autoweed.equals(configManager.getRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, TimeTrackingConfig.AUTOWEED)))
|
if (!autoweed.equals(configManager.getRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, TimeTrackingConfig.AUTOWEED)))
|
||||||
@@ -100,13 +113,16 @@ public class FarmingTracker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (FarmingRegion region : farmingWorld.getRegions().get(location.getRegionID()))
|
Collection<FarmingRegion> newRegions = farmingWorld.getRegionsForLocation(location);
|
||||||
{
|
|
||||||
if (!region.isInBounds(location))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (!newRegions.equals(lastRegions))
|
||||||
|
{
|
||||||
|
newRegionLoaded = true;
|
||||||
|
log.debug("New region loaded. {} at {} ticks", newRegions.toString(), client.getTickCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (FarmingRegion region : newRegions)
|
||||||
|
{
|
||||||
// Write config with new varbits
|
// Write config with new varbits
|
||||||
// timetracking.<rsprofile>.<regionID>.<VarbitID>=<varbitValue>:<unix time>
|
// timetracking.<rsprofile>.<regionID>.<VarbitID>=<varbitValue>:<unix time>
|
||||||
long unixNow = Instant.now().getEpochSecond();
|
long unixNow = Instant.now().getEpochSecond();
|
||||||
@@ -121,20 +137,62 @@ public class FarmingTracker
|
|||||||
if (storedValue != null)
|
if (storedValue != null)
|
||||||
{
|
{
|
||||||
String[] parts = storedValue.split(":");
|
String[] parts = storedValue.split(":");
|
||||||
if (parts.length == 2 && parts[0].equals(strVarbit))
|
if (parts.length == 2)
|
||||||
{
|
{
|
||||||
long unixTime = 0;
|
if (parts[0].equals(strVarbit))
|
||||||
try
|
|
||||||
{
|
{
|
||||||
unixTime = Long.parseLong(parts[1]);
|
long unixTime = 0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
unixTime = Long.parseLong(parts[1]);
|
||||||
|
}
|
||||||
|
catch (NumberFormatException e)
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
if (unixTime + (5 * 60) > unixNow && unixNow + 30 > unixTime)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (NumberFormatException e)
|
else if (!newRegionLoaded && timeSinceModalClose > 1)
|
||||||
{
|
{
|
||||||
// ignored
|
PatchState previousPatchState = patch.getImplementation().forVarbitValue(Integer.parseInt(parts[0]));
|
||||||
|
PatchState currentPatchState = patch.getImplementation().forVarbitValue(client.getVar(varbit));
|
||||||
|
|
||||||
|
if (previousPatchState == null || currentPatchState == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int patchTickRate = previousPatchState.getTickRate();
|
||||||
|
|
||||||
|
if (isObservedGrowthTick(previousPatchState, currentPatchState))
|
||||||
|
{
|
||||||
|
Integer storedOffsetPrecision = configManager.getRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, TimeTrackingConfig.FARM_TICK_OFFSET_PRECISION, int.class);
|
||||||
|
Integer storedOffsetMins = configManager.getRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, TimeTrackingConfig.FARM_TICK_OFFSET, int.class);
|
||||||
|
|
||||||
|
int offsetMins = (int) Math.abs(((Instant.now().getEpochSecond() / 60) % patchTickRate) - patchTickRate);
|
||||||
|
log.debug("Observed an exact growth tick. Offset is: {} from a {} minute tick", offsetMins, patchTickRate);
|
||||||
|
|
||||||
|
if (storedOffsetMins != null && storedOffsetMins != 0 && offsetMins != storedOffsetMins % patchTickRate)
|
||||||
|
{
|
||||||
|
WorldPoint playerLocation = client.getLocalPlayer().getWorldLocation();
|
||||||
|
log.error("Offset error! Observed new offset of {}, previous observed offset was {} ({}) Player Loc:{}", offsetMins, storedOffsetMins, storedOffsetMins % patchTickRate, playerLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (storedOffsetPrecision == null || patchTickRate >= storedOffsetPrecision)
|
||||||
|
{
|
||||||
|
log.debug("Found a longer growth tick {}, saving new offset", patchTickRate);
|
||||||
|
|
||||||
|
configManager.setRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, TimeTrackingConfig.FARM_TICK_OFFSET_PRECISION, patchTickRate);
|
||||||
|
configManager.setRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, TimeTrackingConfig.FARM_TICK_OFFSET, offsetMins);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (unixTime + (5 * 60) > unixNow && unixNow + 30 > unixTime)
|
else
|
||||||
{
|
{
|
||||||
continue;
|
log.debug("ignoring growth tick for offset calculation; newRegionLoaded={} timeSinceModalClose={}", newRegionLoaded, timeSinceModalClose);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -145,6 +203,10 @@ public class FarmingTracker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Do one scan after loading a new region before possibly updating tick offsets
|
||||||
|
newRegionLoaded = false;
|
||||||
|
lastRegions = newRegions;
|
||||||
|
|
||||||
if (changed)
|
if (changed)
|
||||||
{
|
{
|
||||||
updateCompletionTime();
|
updateCompletionTime();
|
||||||
@@ -153,6 +215,47 @@ public class FarmingTracker
|
|||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isObservedGrowthTick(PatchState previous, PatchState current)
|
||||||
|
{
|
||||||
|
//Check the previous state so it will still calculate during the final growth tick
|
||||||
|
int patchTickRate = previous.getTickRate();
|
||||||
|
CropState previousCropState = previous.getCropState();
|
||||||
|
CropState currentCropState = current.getCropState();
|
||||||
|
Produce previousProduce = previous.getProduce();
|
||||||
|
|
||||||
|
//Ignore weeds growing or being cleared.
|
||||||
|
if (previousProduce == Produce.WEEDS || current.getProduce() == Produce.WEEDS
|
||||||
|
|| current.getProduce() != previousProduce
|
||||||
|
|| patchTickRate <= 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (previousCropState == CropState.GROWING)
|
||||||
|
{
|
||||||
|
if ((currentCropState == CropState.GROWING && current.getStage() - previous.getStage() == 1)
|
||||||
|
|| currentCropState == CropState.DISEASED)
|
||||||
|
{
|
||||||
|
log.debug("Found GROWING -> GROWING or GROWING -> DISEASED");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentCropState == CropState.HARVESTABLE && !previousProduce.getPatchImplementation().isHealthCheckRequired())
|
||||||
|
{
|
||||||
|
log.debug("Found GROWING -> HARVESTABLE");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (previousCropState == CropState.DISEASED && currentCropState == CropState.DEAD)
|
||||||
|
{
|
||||||
|
log.debug("Found DISEASED -> DEAD");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public PatchPrediction predictPatch(FarmingPatch patch)
|
public PatchPrediction predictPatch(FarmingPatch patch)
|
||||||
{
|
{
|
||||||
@@ -203,8 +306,7 @@ public class FarmingTracker
|
|||||||
|
|
||||||
int stage = state.getStage();
|
int stage = state.getStage();
|
||||||
int stages = state.getStages();
|
int stages = state.getStages();
|
||||||
int tickrate = state.getTickRate() * 60;
|
int tickrate = state.getTickRate();
|
||||||
int farmingTickLength = 5 * 60;
|
|
||||||
|
|
||||||
if (autoweed && state.getProduce() == Produce.WEEDS)
|
if (autoweed && state.getProduce() == Produce.WEEDS)
|
||||||
{
|
{
|
||||||
@@ -216,17 +318,16 @@ public class FarmingTracker
|
|||||||
if (botanist)
|
if (botanist)
|
||||||
{
|
{
|
||||||
tickrate /= 5;
|
tickrate /= 5;
|
||||||
farmingTickLength /= 5;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
long doneEstimate = 0;
|
long doneEstimate = 0;
|
||||||
if (tickrate > 0)
|
if (tickrate > 0)
|
||||||
{
|
{
|
||||||
long tickNow = (unixNow + farmingTickLength) / tickrate;
|
long tickNow = getTickTime(tickrate, 0, unixNow);
|
||||||
long tickTime = (unixTime + farmingTickLength) / tickrate;
|
long tickTime = getTickTime(tickrate, 0, unixTime);
|
||||||
int delta = (int) (tickNow - tickTime);
|
int delta = (int) (tickNow - tickTime) / (tickrate * 60);
|
||||||
|
|
||||||
doneEstimate = ((stages - 1 - stage) + tickTime) * tickrate + farmingTickLength;
|
doneEstimate = getTickTime(tickrate, stages - 1 - stage, tickTime);
|
||||||
|
|
||||||
stage += delta;
|
stage += delta;
|
||||||
if (stage >= stages)
|
if (stage >= stages)
|
||||||
@@ -244,10 +345,39 @@ public class FarmingTracker
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getTickTime(int tickRate, int ticks)
|
||||||
|
{
|
||||||
|
return getTickTime(tickRate, ticks, Instant.now().getEpochSecond());
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTickTime(int tickRate, int ticks, long requestedTime)
|
||||||
|
{
|
||||||
|
Integer offsetPrecisionMins = configManager.getRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, TimeTrackingConfig.FARM_TICK_OFFSET_PRECISION, int.class);
|
||||||
|
Integer offsetTimeMins = configManager.getRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, TimeTrackingConfig.FARM_TICK_OFFSET, int.class);
|
||||||
|
|
||||||
|
//All offsets are negative but are stored as positive
|
||||||
|
long calculatedOffsetTime = 0L;
|
||||||
|
if (offsetPrecisionMins != null && offsetTimeMins != null && (offsetPrecisionMins >= tickRate || offsetPrecisionMins >= 40))
|
||||||
|
{
|
||||||
|
calculatedOffsetTime = (offsetTimeMins % tickRate) * 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Calculate "now" as +offset seconds in the future so we calculate the correct ticks
|
||||||
|
long unixNow = requestedTime + calculatedOffsetTime;
|
||||||
|
|
||||||
|
//The time that the tick requested will happen
|
||||||
|
long timeOfCurrentTick = (unixNow - (unixNow % (tickRate * 60)));
|
||||||
|
long timeOfGoalTick = timeOfCurrentTick + (ticks * tickRate * 60);
|
||||||
|
|
||||||
|
//Move ourselves back to real time
|
||||||
|
return timeOfGoalTick - calculatedOffsetTime;
|
||||||
|
}
|
||||||
|
|
||||||
public void loadCompletionTimes()
|
public void loadCompletionTimes()
|
||||||
{
|
{
|
||||||
summaries.clear();
|
summaries.clear();
|
||||||
completionTimes.clear();
|
completionTimes.clear();
|
||||||
|
lastRegions = null;
|
||||||
updateCompletionTime();
|
updateCompletionTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import com.google.common.collect.HashMultimap;
|
|||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
import com.google.common.collect.Multimaps;
|
import com.google.common.collect.Multimaps;
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -36,6 +37,7 @@ import java.util.Map;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import net.runelite.api.Varbits;
|
import net.runelite.api.Varbits;
|
||||||
import net.runelite.api.coords.WorldPoint;
|
import net.runelite.api.coords.WorldPoint;
|
||||||
@@ -44,7 +46,7 @@ import net.runelite.client.plugins.timetracking.Tab;
|
|||||||
@Singleton
|
@Singleton
|
||||||
class FarmingWorld
|
class FarmingWorld
|
||||||
{
|
{
|
||||||
@Getter
|
@SuppressWarnings("PMD.ImmutableField")
|
||||||
private Multimap<Integer, FarmingRegion> regions = HashMultimap.create();
|
private Multimap<Integer, FarmingRegion> regions = HashMultimap.create();
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@@ -64,11 +66,11 @@ class FarmingWorld
|
|||||||
// It may be worth it to add a specialization for these patches
|
// It may be worth it to add a specialization for these patches
|
||||||
add(new FarmingRegion("Al Kharid", 13106,
|
add(new FarmingRegion("Al Kharid", 13106,
|
||||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.CACTUS)
|
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.CACTUS)
|
||||||
));
|
), 13362, 13105);
|
||||||
|
|
||||||
add(new FarmingRegion("Ardougne", 10290,
|
add(new FarmingRegion("Ardougne", 10290,
|
||||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.BUSH)
|
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.BUSH)
|
||||||
));
|
), 10546);
|
||||||
add(new FarmingRegion("Ardougne", 10548,
|
add(new FarmingRegion("Ardougne", 10548,
|
||||||
new FarmingPatch("North", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT),
|
new FarmingPatch("North", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT),
|
||||||
new FarmingPatch("South", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT),
|
new FarmingPatch("South", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT),
|
||||||
@@ -80,7 +82,7 @@ class FarmingWorld
|
|||||||
add(new FarmingRegion("Brimhaven", 11058,
|
add(new FarmingRegion("Brimhaven", 11058,
|
||||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.FRUIT_TREE),
|
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.FRUIT_TREE),
|
||||||
new FarmingPatch("", Varbits.FARMING_4772, PatchImplementation.SPIRIT_TREE)
|
new FarmingPatch("", Varbits.FARMING_4772, PatchImplementation.SPIRIT_TREE)
|
||||||
));
|
), 11057);
|
||||||
|
|
||||||
add(new FarmingRegion("Catherby", 11062,
|
add(new FarmingRegion("Catherby", 11062,
|
||||||
new FarmingPatch("North", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT),
|
new FarmingPatch("North", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT),
|
||||||
@@ -93,9 +95,10 @@ class FarmingWorld
|
|||||||
@Override
|
@Override
|
||||||
public boolean isInBounds(WorldPoint loc)
|
public boolean isInBounds(WorldPoint loc)
|
||||||
{
|
{
|
||||||
if (loc.getY() < 3456)
|
if (loc.getX() >= 2816 && loc.getY() < 3456)
|
||||||
{
|
{
|
||||||
return loc.getX() <= 2840 && loc.getY() > 3440;
|
//Upstairs sends different varbits
|
||||||
|
return loc.getX() < 2840 && loc.getY() >= 3440 && loc.getPlane() == 0;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -104,10 +107,11 @@ class FarmingWorld
|
|||||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.FRUIT_TREE)
|
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.FRUIT_TREE)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
//The fruit tree patch is always sent when upstairs in 11317
|
||||||
@Override
|
@Override
|
||||||
public boolean isInBounds(WorldPoint loc)
|
public boolean isInBounds(WorldPoint loc)
|
||||||
{
|
{
|
||||||
return loc.getX() > 2840 || loc.getY() < 3440;
|
return loc.getX() >= 2840 || loc.getY() < 3440 || loc.getPlane() == 1;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -121,7 +125,7 @@ class FarmingWorld
|
|||||||
|
|
||||||
add(new FarmingRegion("Entrana", 11060,
|
add(new FarmingRegion("Entrana", 11060,
|
||||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.HOPS)
|
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.HOPS)
|
||||||
));
|
), 11316);
|
||||||
|
|
||||||
add(new FarmingRegion("Etceteria", 10300,
|
add(new FarmingRegion("Etceteria", 10300,
|
||||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.BUSH),
|
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.BUSH),
|
||||||
@@ -130,7 +134,7 @@ class FarmingWorld
|
|||||||
|
|
||||||
add(new FarmingRegion("Falador", 11828,
|
add(new FarmingRegion("Falador", 11828,
|
||||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.TREE)
|
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.TREE)
|
||||||
));
|
), 12084);
|
||||||
add(new FarmingRegion("Falador", 12083,
|
add(new FarmingRegion("Falador", 12083,
|
||||||
new FarmingPatch("North West", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT),
|
new FarmingPatch("North West", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT),
|
||||||
new FarmingPatch("South East", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT),
|
new FarmingPatch("South East", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT),
|
||||||
@@ -142,7 +146,8 @@ class FarmingWorld
|
|||||||
@Override
|
@Override
|
||||||
public boolean isInBounds(WorldPoint loc)
|
public boolean isInBounds(WorldPoint loc)
|
||||||
{
|
{
|
||||||
return loc.getY() > 3280;
|
//Not on region boundary due to Port Sarim Spirit Tree patch
|
||||||
|
return loc.getY() >= 3272;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -150,7 +155,30 @@ class FarmingWorld
|
|||||||
new FarmingPatch("East", Varbits.FARMING_4771, PatchImplementation.HARDWOOD_TREE),
|
new FarmingPatch("East", Varbits.FARMING_4771, PatchImplementation.HARDWOOD_TREE),
|
||||||
new FarmingPatch("Middle", Varbits.FARMING_4772, PatchImplementation.HARDWOOD_TREE),
|
new FarmingPatch("Middle", Varbits.FARMING_4772, PatchImplementation.HARDWOOD_TREE),
|
||||||
new FarmingPatch("West", Varbits.FARMING_4773, PatchImplementation.HARDWOOD_TREE)
|
new FarmingPatch("West", Varbits.FARMING_4773, PatchImplementation.HARDWOOD_TREE)
|
||||||
), 14907);
|
)
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public boolean isInBounds(WorldPoint loc)
|
||||||
|
{
|
||||||
|
//Hardwood tree varbits are sent anywhere on plane 0 of fossil island.
|
||||||
|
//Varbits get sent 1 tick earlier than expected when climbing certain ladders and stairs
|
||||||
|
|
||||||
|
//Stairs to house on the hill
|
||||||
|
if (loc.getX() == 3753 && loc.getY() >= 3868 && loc.getY() <= 3870)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//East and west ladders to rope bridge
|
||||||
|
if ((loc.getX() == 3729 || loc.getX() == 3728 || loc.getX() == 3747 || loc.getX() == 3746)
|
||||||
|
&& loc.getY() <= 3832 && loc.getY() >= 3830)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return loc.getPlane() == 0;
|
||||||
|
}
|
||||||
|
}, 14907, 14908, 15164, 14652, 14906, 14650, 15162, 15163);
|
||||||
add(new FarmingRegion("Seaweed", 15008,
|
add(new FarmingRegion("Seaweed", 15008,
|
||||||
new FarmingPatch("North", Varbits.FARMING_4771, PatchImplementation.SEAWEED),
|
new FarmingPatch("North", Varbits.FARMING_4771, PatchImplementation.SEAWEED),
|
||||||
new FarmingPatch("South", Varbits.FARMING_4772, PatchImplementation.SEAWEED)
|
new FarmingPatch("South", Varbits.FARMING_4772, PatchImplementation.SEAWEED)
|
||||||
@@ -159,7 +187,7 @@ class FarmingWorld
|
|||||||
add(new FarmingRegion("Gnome Stronghold", 9781,
|
add(new FarmingRegion("Gnome Stronghold", 9781,
|
||||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.TREE),
|
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.TREE),
|
||||||
new FarmingPatch("", Varbits.FARMING_4772, PatchImplementation.FRUIT_TREE)
|
new FarmingPatch("", Varbits.FARMING_4772, PatchImplementation.FRUIT_TREE)
|
||||||
));
|
), 9782, 9526, 9525);
|
||||||
|
|
||||||
add(new FarmingRegion("Harmony", 15148,
|
add(new FarmingRegion("Harmony", 15148,
|
||||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT),
|
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT),
|
||||||
@@ -171,11 +199,9 @@ class FarmingWorld
|
|||||||
new FarmingPatch("South West", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT),
|
new FarmingPatch("South West", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT),
|
||||||
new FarmingPatch("", Varbits.FARMING_4773, PatchImplementation.FLOWER),
|
new FarmingPatch("", Varbits.FARMING_4773, PatchImplementation.FLOWER),
|
||||||
new FarmingPatch("", Varbits.FARMING_4774, PatchImplementation.HERB),
|
new FarmingPatch("", Varbits.FARMING_4774, PatchImplementation.HERB),
|
||||||
new FarmingPatch("", Varbits.FARMING_4775, PatchImplementation.COMPOST)
|
new FarmingPatch("", Varbits.FARMING_4775, PatchImplementation.COMPOST),
|
||||||
));
|
|
||||||
add(new FarmingRegion("Kourend", 6711,
|
|
||||||
new FarmingPatch("", Varbits.FARMING_7904, PatchImplementation.SPIRIT_TREE)
|
new FarmingPatch("", Varbits.FARMING_7904, PatchImplementation.SPIRIT_TREE)
|
||||||
));
|
), 6711);
|
||||||
add(new FarmingRegion("Kourend", 7223,
|
add(new FarmingRegion("Kourend", 7223,
|
||||||
new FarmingPatch("East 1", Varbits.GRAPES_4953, PatchImplementation.GRAPES),
|
new FarmingPatch("East 1", Varbits.GRAPES_4953, PatchImplementation.GRAPES),
|
||||||
new FarmingPatch("East 2", Varbits.GRAPES_4954, PatchImplementation.GRAPES),
|
new FarmingPatch("East 2", Varbits.GRAPES_4954, PatchImplementation.GRAPES),
|
||||||
@@ -200,23 +226,29 @@ class FarmingWorld
|
|||||||
));
|
));
|
||||||
add(new FarmingRegion("Lumbridge", 12594,
|
add(new FarmingRegion("Lumbridge", 12594,
|
||||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.TREE)
|
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.TREE)
|
||||||
));
|
), 12850);
|
||||||
|
|
||||||
add(new FarmingRegion("Morytania", 13622,
|
add(new FarmingRegion("Morytania", 13622,
|
||||||
new FarmingPatch("Mushroom", Varbits.FARMING_4771, PatchImplementation.MUSHROOM)
|
new FarmingPatch("Mushroom", Varbits.FARMING_4771, PatchImplementation.MUSHROOM)
|
||||||
));
|
), 13878);
|
||||||
add(new FarmingRegion("Morytania", 14391,
|
add(new FarmingRegion("Morytania", 14391,
|
||||||
new FarmingPatch("North West", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT),
|
new FarmingPatch("North West", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT),
|
||||||
new FarmingPatch("South East", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT),
|
new FarmingPatch("South East", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT),
|
||||||
new FarmingPatch("", Varbits.FARMING_4773, PatchImplementation.FLOWER),
|
new FarmingPatch("", Varbits.FARMING_4773, PatchImplementation.FLOWER),
|
||||||
new FarmingPatch("", Varbits.FARMING_4774, PatchImplementation.HERB),
|
new FarmingPatch("", Varbits.FARMING_4774, PatchImplementation.HERB),
|
||||||
new FarmingPatch("", Varbits.FARMING_4775, PatchImplementation.COMPOST)
|
new FarmingPatch("", Varbits.FARMING_4775, PatchImplementation.COMPOST)
|
||||||
));
|
), 14390);
|
||||||
|
|
||||||
|
|
||||||
add(new FarmingRegion("Port Sarim", 12082,
|
add(new FarmingRegion("Port Sarim", 12082,
|
||||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.SPIRIT_TREE)
|
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.SPIRIT_TREE)
|
||||||
));
|
)
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public boolean isInBounds(WorldPoint loc)
|
||||||
|
{
|
||||||
|
return loc.getY() < 3272;
|
||||||
|
}
|
||||||
|
}, 12083);
|
||||||
|
|
||||||
add(new FarmingRegion("Rimmington", 11570,
|
add(new FarmingRegion("Rimmington", 11570,
|
||||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.BUSH)
|
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.BUSH)
|
||||||
@@ -224,7 +256,7 @@ class FarmingWorld
|
|||||||
|
|
||||||
add(new FarmingRegion("Seers' Village", 10551,
|
add(new FarmingRegion("Seers' Village", 10551,
|
||||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.HOPS)
|
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.HOPS)
|
||||||
));
|
), 10550);
|
||||||
|
|
||||||
add(new FarmingRegion("Tai Bwo Wannai", 11056,
|
add(new FarmingRegion("Tai Bwo Wannai", 11056,
|
||||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.CALQUAT)
|
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.CALQUAT)
|
||||||
@@ -232,11 +264,11 @@ class FarmingWorld
|
|||||||
|
|
||||||
add(new FarmingRegion("Taverley", 11573,
|
add(new FarmingRegion("Taverley", 11573,
|
||||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.TREE)
|
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.TREE)
|
||||||
));
|
), 11829);
|
||||||
|
|
||||||
add(new FarmingRegion("Tree Gnome Village", 9777,
|
add(new FarmingRegion("Tree Gnome Village", 9777,
|
||||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.FRUIT_TREE)
|
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.FRUIT_TREE)
|
||||||
));
|
), 10033);
|
||||||
|
|
||||||
add(new FarmingRegion("Troll Stronghold", 11321,
|
add(new FarmingRegion("Troll Stronghold", 11321,
|
||||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.HERB)
|
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.HERB)
|
||||||
@@ -258,6 +290,7 @@ class FarmingWorld
|
|||||||
new FarmingPatch("Hespori", Varbits.FARMING_7908, PatchImplementation.HESPORI)
|
new FarmingPatch("Hespori", Varbits.FARMING_7908, PatchImplementation.HESPORI)
|
||||||
));
|
));
|
||||||
|
|
||||||
|
//Full 3x3 region area centered on farming guild
|
||||||
add(farmingGuildRegion = new FarmingRegion("Farming Guild", 4922,
|
add(farmingGuildRegion = new FarmingRegion("Farming Guild", 4922,
|
||||||
new FarmingPatch("", Varbits.FARMING_7905, PatchImplementation.TREE),
|
new FarmingPatch("", Varbits.FARMING_7905, PatchImplementation.TREE),
|
||||||
new FarmingPatch("", Varbits.FARMING_4775, PatchImplementation.HERB),
|
new FarmingPatch("", Varbits.FARMING_4775, PatchImplementation.HERB),
|
||||||
@@ -272,18 +305,20 @@ class FarmingWorld
|
|||||||
new FarmingPatch("Anima", Varbits.FARMING_7911, PatchImplementation.ANIMA),
|
new FarmingPatch("Anima", Varbits.FARMING_7911, PatchImplementation.ANIMA),
|
||||||
new FarmingPatch("", Varbits.FARMING_7910, PatchImplementation.CELASTRUS),
|
new FarmingPatch("", Varbits.FARMING_7910, PatchImplementation.CELASTRUS),
|
||||||
new FarmingPatch("", Varbits.FARMING_7907, PatchImplementation.REDWOOD)
|
new FarmingPatch("", Varbits.FARMING_7907, PatchImplementation.REDWOOD)
|
||||||
));
|
), 5177, 5178, 5179, 4921, 4923, 4665, 4666, 4667);
|
||||||
|
|
||||||
|
//All of Prifddinas, and all of Prifddinas Underground
|
||||||
add(new FarmingRegion("Prifddinas", 13151,
|
add(new FarmingRegion("Prifddinas", 13151,
|
||||||
new FarmingPatch("North", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT),
|
new FarmingPatch("North", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT),
|
||||||
new FarmingPatch("South", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT),
|
new FarmingPatch("South", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT),
|
||||||
new FarmingPatch("", Varbits.FARMING_4773, PatchImplementation.FLOWER),
|
new FarmingPatch("", Varbits.FARMING_4773, PatchImplementation.FLOWER),
|
||||||
new FarmingPatch("", Varbits.FARMING_4775, PatchImplementation.CRYSTAL_TREE),
|
new FarmingPatch("", Varbits.FARMING_4775, PatchImplementation.CRYSTAL_TREE),
|
||||||
new FarmingPatch("", Varbits.FARMING_4774, PatchImplementation.COMPOST) // TODO: Find correct varbit
|
new FarmingPatch("", Varbits.FARMING_4774, PatchImplementation.COMPOST) // TODO: Find correct varbit
|
||||||
));
|
), 12895, 12894, 13150,
|
||||||
|
/* Underground */ 12994, 12993, 12737, 12738, 12126, 12127, 13250);
|
||||||
|
|
||||||
// Finalize
|
// Finalize
|
||||||
this.regions = Multimaps.unmodifiableMultimap(regions);
|
this.regions = Multimaps.unmodifiableMultimap(this.regions);
|
||||||
Map<Tab, Set<FarmingPatch>> umtabs = new TreeMap<>();
|
Map<Tab, Set<FarmingPatch>> umtabs = new TreeMap<>();
|
||||||
for (Map.Entry<Tab, Set<FarmingPatch>> e : tabs.entrySet())
|
for (Map.Entry<Tab, Set<FarmingPatch>> e : tabs.entrySet())
|
||||||
{
|
{
|
||||||
@@ -306,4 +341,11 @@ class FarmingWorld
|
|||||||
.add(p);
|
.add(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Collection<FarmingRegion> getRegionsForLocation(WorldPoint location)
|
||||||
|
{
|
||||||
|
return this.regions.get(location.getRegionID()).stream()
|
||||||
|
.filter(region -> region.isInBounds(location))
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ import net.runelite.client.plugins.timetracking.Tab;
|
|||||||
@Getter
|
@Getter
|
||||||
public enum PatchImplementation
|
public enum PatchImplementation
|
||||||
{
|
{
|
||||||
BELLADONNA(Tab.SPECIAL, "")
|
BELLADONNA(Tab.SPECIAL, "", false)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -71,7 +71,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
MUSHROOM(Tab.SPECIAL, "")
|
MUSHROOM(Tab.SPECIAL, "", false)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -109,7 +109,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
HESPORI(Tab.SPECIAL, "")
|
HESPORI(Tab.SPECIAL, "", true)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -137,7 +137,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ALLOTMENT(Tab.ALLOTMENT, "")
|
ALLOTMENT(Tab.ALLOTMENT, "", false)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -470,7 +470,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
HERB(Tab.HERB, "")
|
HERB(Tab.HERB, "", false)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -738,7 +738,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
FLOWER(Tab.FLOWER, "")
|
FLOWER(Tab.FLOWER, "", false)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -1011,7 +1011,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
BUSH(Tab.BUSH, "")
|
BUSH(Tab.BUSH, "", true)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -1244,7 +1244,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
FRUIT_TREE(Tab.FRUIT_TREE, "")
|
FRUIT_TREE(Tab.FRUIT_TREE, "", true)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -1527,7 +1527,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
HOPS(Tab.HOPS, "")
|
HOPS(Tab.HOPS, "", false)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -1830,7 +1830,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
TREE(Tab.TREE, "")
|
TREE(Tab.TREE, "", true)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -2113,7 +2113,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
HARDWOOD_TREE(Tab.TREE, "Hardwood Trees")
|
HARDWOOD_TREE(Tab.TREE, "Hardwood Trees", true)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -2196,7 +2196,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
REDWOOD(Tab.TREE, "Redwood Trees")
|
REDWOOD(Tab.TREE, "Redwood Trees", true)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -2244,7 +2244,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
SPIRIT_TREE(Tab.TREE, "Spirit Trees")
|
SPIRIT_TREE(Tab.TREE, "Spirit Trees", true)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -2292,7 +2292,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ANIMA(Tab.SPECIAL, "")
|
ANIMA(Tab.SPECIAL, "", false)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -2339,7 +2339,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
CACTUS(Tab.SPECIAL, "Cactus")
|
CACTUS(Tab.SPECIAL, "Cactus", true)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -2412,7 +2412,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
SEAWEED(Tab.SPECIAL, "Seaweed")
|
SEAWEED(Tab.SPECIAL, "Seaweed", false)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -2450,7 +2450,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
CALQUAT(Tab.FRUIT_TREE, "Calquat")
|
CALQUAT(Tab.FRUIT_TREE, "Calquat", true)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -2493,7 +2493,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
CELASTRUS(Tab.FRUIT_TREE, "Celastrus")
|
CELASTRUS(Tab.FRUIT_TREE, "Celastrus", true)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -2551,7 +2551,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
GRAPES(Tab.GRAPE, "")
|
GRAPES(Tab.GRAPE, "", true)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -2576,7 +2576,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
CRYSTAL_TREE(Tab.FRUIT_TREE, "Crystal Tree")
|
CRYSTAL_TREE(Tab.FRUIT_TREE, "Crystal Tree", true)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -2604,7 +2604,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
COMPOST(Tab.SPECIAL, "Compost Bin")
|
COMPOST(Tab.SPECIAL, "Compost Bin", true)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -2677,7 +2677,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
GIANT_COMPOST(Tab.SPECIAL, "Giant Compost Bin")
|
GIANT_COMPOST(Tab.SPECIAL, "Giant Compost Bin", true)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -2787,4 +2787,6 @@ public enum PatchImplementation
|
|||||||
private final Tab tab;
|
private final Tab tab;
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
|
private final boolean healthCheckRequired;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,13 +65,13 @@ public enum Produce
|
|||||||
POISON_IVY("Poison ivy", "Poison ivy berries", PatchImplementation.BUSH, ItemID.POISON_IVY_BERRIES, 20, 9, 20, 5),
|
POISON_IVY("Poison ivy", "Poison ivy berries", PatchImplementation.BUSH, ItemID.POISON_IVY_BERRIES, 20, 9, 20, 5),
|
||||||
|
|
||||||
// Hop crops
|
// Hop crops
|
||||||
BARLEY("Barley", ItemID.BARLEY, 10, 5, 0, 3),
|
BARLEY("Barley", PatchImplementation.HOPS, ItemID.BARLEY, 10, 5, 0, 3),
|
||||||
HAMMERSTONE("Hammerstone", ItemID.HAMMERSTONE_HOPS, 10, 5, 0, 3),
|
HAMMERSTONE("Hammerstone", PatchImplementation.HOPS, ItemID.HAMMERSTONE_HOPS, 10, 5, 0, 3),
|
||||||
ASGARNIAN("Asgarnian", ItemID.ASGARNIAN_HOPS, 10, 6, 0, 3),
|
ASGARNIAN("Asgarnian", PatchImplementation.HOPS, ItemID.ASGARNIAN_HOPS, 10, 6, 0, 3),
|
||||||
JUTE("Jute", ItemID.JUTE_FIBRE, 10, 6, 0, 3),
|
JUTE("Jute", PatchImplementation.HOPS, ItemID.JUTE_FIBRE, 10, 6, 0, 3),
|
||||||
YANILLIAN("Yanillian", ItemID.YANILLIAN_HOPS, 10, 7, 0, 3),
|
YANILLIAN("Yanillian", PatchImplementation.HOPS, ItemID.YANILLIAN_HOPS, 10, 7, 0, 3),
|
||||||
KRANDORIAN("Krandorian", ItemID.KRANDORIAN_HOPS, 10, 8, 0, 3),
|
KRANDORIAN("Krandorian", PatchImplementation.HOPS, ItemID.KRANDORIAN_HOPS, 10, 8, 0, 3),
|
||||||
WILDBLOOD("Wildblood", ItemID.WILDBLOOD_HOPS, 10, 9, 0, 3),
|
WILDBLOOD("Wildblood", PatchImplementation.HOPS, ItemID.WILDBLOOD_HOPS, 10, 9, 0, 3),
|
||||||
|
|
||||||
// Herb crops
|
// Herb crops
|
||||||
GUAM("Guam", PatchImplementation.HERB, ItemID.GUAM_LEAF, 20, 5, 0, 3),
|
GUAM("Guam", PatchImplementation.HERB, ItemID.GUAM_LEAF, 20, 5, 0, 3),
|
||||||
@@ -113,25 +113,25 @@ public enum Produce
|
|||||||
POTATO_CACTUS("Potato cactus", "Potato cacti", PatchImplementation.CACTUS, ItemID.POTATO_CACTUS, 10, 8, 5, 7),
|
POTATO_CACTUS("Potato cactus", "Potato cacti", PatchImplementation.CACTUS, ItemID.POTATO_CACTUS, 10, 8, 5, 7),
|
||||||
|
|
||||||
// Hardwood
|
// Hardwood
|
||||||
TEAK("Teak", ItemID.TEAK_LOGS, 560, 8),
|
TEAK("Teak", PatchImplementation.HARDWOOD_TREE, ItemID.TEAK_LOGS, 560, 8),
|
||||||
MAHOGANY("Mahogany", ItemID.MAHOGANY_LOGS, 640, 9),
|
MAHOGANY("Mahogany", PatchImplementation.HARDWOOD_TREE, ItemID.MAHOGANY_LOGS, 640, 9),
|
||||||
|
|
||||||
// Anima
|
// Anima
|
||||||
ATTAS("Attas", NullItemID.NULL_22940, 640, 9),
|
ATTAS("Attas", PatchImplementation.ANIMA, NullItemID.NULL_22940, 640, 9),
|
||||||
IASOR("Iasor", NullItemID.NULL_22939, 640, 9),
|
IASOR("Iasor", PatchImplementation.ANIMA, NullItemID.NULL_22939, 640, 9),
|
||||||
KRONOS("Kronos", NullItemID.NULL_22938, 640, 9),
|
KRONOS("Kronos", PatchImplementation.ANIMA, NullItemID.NULL_22938, 640, 9),
|
||||||
|
|
||||||
// Special crops
|
// Special crops
|
||||||
SEAWEED("Seaweed", ItemID.GIANT_SEAWEED, 10, 5, 0, 4),
|
SEAWEED("Seaweed", PatchImplementation.SEAWEED, ItemID.GIANT_SEAWEED, 10, 5, 0, 4),
|
||||||
GRAPE("Grape", ItemID.GRAPES, 5, 8, 0, 5),
|
GRAPE("Grape", PatchImplementation.GRAPES, ItemID.GRAPES, 5, 8, 0, 5),
|
||||||
MUSHROOM("Mushroom", ItemID.MUSHROOM, 40, 7, 0, 7),
|
MUSHROOM("Mushroom", PatchImplementation.MUSHROOM, ItemID.MUSHROOM, 40, 7, 0, 7),
|
||||||
BELLADONNA("Belladonna", ItemID.CAVE_NIGHTSHADE, 80, 5),
|
BELLADONNA("Belladonna", PatchImplementation.BELLADONNA, ItemID.CAVE_NIGHTSHADE, 80, 5),
|
||||||
CALQUAT("Calquat", ItemID.CALQUAT_FRUIT, 160, 9, 0, 7),
|
CALQUAT("Calquat", PatchImplementation.CALQUAT, ItemID.CALQUAT_FRUIT, 160, 9, 0, 7),
|
||||||
SPIRIT_TREE("Spirit tree", ItemID.SPIRIT_TREE, 320, 13),
|
SPIRIT_TREE("Spirit tree", PatchImplementation.SPIRIT_TREE, ItemID.SPIRIT_TREE, 320, 13),
|
||||||
CELASTRUS("Celastrus", "Celastrus tree", PatchImplementation.CELASTRUS, ItemID.BATTLESTAFF, 160, 6, 0, 4),
|
CELASTRUS("Celastrus", "Celastrus tree", PatchImplementation.CELASTRUS, ItemID.BATTLESTAFF, 160, 6, 0, 4),
|
||||||
REDWOOD("Redwood", "Redwood tree", PatchImplementation.REDWOOD, ItemID.REDWOOD_LOGS, 640, 11),
|
REDWOOD("Redwood", "Redwood tree", PatchImplementation.REDWOOD, ItemID.REDWOOD_LOGS, 640, 11),
|
||||||
HESPORI("Hespori", NullItemID.NULL_23044, 640, 4, 0, 2),
|
HESPORI("Hespori", PatchImplementation.HESPORI, NullItemID.NULL_23044, 640, 4, 0, 2),
|
||||||
CRYSTAL_TREE("Crystal tree", ItemID.CRYSTAL_SHARDS, 80, 7),
|
CRYSTAL_TREE("Crystal tree", PatchImplementation.CRYSTAL_TREE, ItemID.CRYSTAL_SHARDS, 80, 7),
|
||||||
|
|
||||||
// Compost bins
|
// Compost bins
|
||||||
EMPTY_COMPOST_BIN("Compost Bin", PatchImplementation.COMPOST, ItemID.COMPOST_BIN, 0, 1, 0, 0), // Dummy produce for the empty state
|
EMPTY_COMPOST_BIN("Compost Bin", PatchImplementation.COMPOST, ItemID.COMPOST_BIN, 0, 1, 0, 0), // Dummy produce for the empty state
|
||||||
@@ -204,20 +204,6 @@ public enum Produce
|
|||||||
this(name, name, null, itemID, tickrate, stages, 0, 1);
|
this(name, name, null, itemID, tickrate, stages, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean requiresHealthCheck()
|
|
||||||
{
|
|
||||||
switch (this.patchImplementation)
|
|
||||||
{
|
|
||||||
case BUSH:
|
|
||||||
case TREE:
|
|
||||||
case CACTUS:
|
|
||||||
case REDWOOD:
|
|
||||||
case CELASTRUS:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
static Produce getByItemID(int itemId)
|
static Produce getByItemID(int itemId)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user