Convert farming tracker to time tracking plugin
This commit is contained in:
@@ -22,7 +22,7 @@
|
|||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
package net.runelite.client.plugins.farmingtracker;
|
package net.runelite.client.plugins.timetracking;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@@ -32,12 +32,17 @@ import net.runelite.api.ItemID;
|
|||||||
@Getter
|
@Getter
|
||||||
public enum Tab
|
public enum Tab
|
||||||
{
|
{
|
||||||
ALLOTMENT("Allotments", ItemID.CABBAGE),
|
ALLOTMENT("Allotment Patches", ItemID.CABBAGE),
|
||||||
HERB("Herbs", ItemID.GRIMY_RANARR_WEED),
|
FLOWER("Flower Patches", ItemID.RED_FLOWERS),
|
||||||
TREE("Trees", ItemID.MAHOGANY_LOGS),
|
HERB("Herb Patches", ItemID.GRIMY_RANARR_WEED),
|
||||||
FRUIT_TREE("Fruit Trees", ItemID.PINEAPPLE),
|
TREE("Tree Patches", ItemID.YEW_LOGS),
|
||||||
BUSH("Bushes", ItemID.REDBERRIES),
|
FRUIT_TREE("Fruit Tree Patches", ItemID.PINEAPPLE),
|
||||||
SPECIAL("Special", ItemID.MUSHROOM);
|
HOPS("Hops Patches", ItemID.BARLEY),
|
||||||
|
BUSH("Bush Patches", ItemID.POISON_IVY_BERRIES),
|
||||||
|
GRAPE("Grape Patches", ItemID.GRAPES),
|
||||||
|
SPECIAL("Special Patches", ItemID.MUSHROOM);
|
||||||
|
|
||||||
|
public static final Tab[] FARMING_TABS = {ALLOTMENT, FLOWER, HERB, TREE, FRUIT_TREE, HOPS, BUSH, GRAPE, SPECIAL};
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
private final int itemID;
|
private final int itemID;
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Daniel Teo <https://github.com/takuyakanbr>
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import net.runelite.client.ui.PluginPanel;
|
||||||
|
|
||||||
|
public abstract class TabContentPanel extends JPanel
|
||||||
|
{
|
||||||
|
public abstract void update();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Dimension getPreferredSize()
|
||||||
|
{
|
||||||
|
return new Dimension(PluginPanel.PANEL_WIDTH, super.getPreferredSize().height);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,22 +22,22 @@
|
|||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
package net.runelite.client.plugins.farmingtracker;
|
package net.runelite.client.plugins.timetracking;
|
||||||
|
|
||||||
import net.runelite.client.config.Config;
|
import net.runelite.client.config.Config;
|
||||||
import net.runelite.client.config.ConfigGroup;
|
import net.runelite.client.config.ConfigGroup;
|
||||||
import net.runelite.client.config.ConfigItem;
|
import net.runelite.client.config.ConfigItem;
|
||||||
|
|
||||||
@ConfigGroup("farmingTracker")
|
@ConfigGroup("timetracking")
|
||||||
public interface FarmingTrackerConfig extends Config
|
public interface TimeTrackingConfig extends Config
|
||||||
{
|
{
|
||||||
String KEY_NAME = "farmingTracker";
|
String KEY_NAME = "timetracking";
|
||||||
String AUTOWEED = "autoweed";
|
String AUTOWEED = "autoweed";
|
||||||
|
|
||||||
@ConfigItem(
|
@ConfigItem(
|
||||||
keyName = "estimateRelative",
|
keyName = "estimateRelative",
|
||||||
name = "Show relative time",
|
name = "Show relative time",
|
||||||
description = "Show amount of time remaining for a patch, opposed to when the patch is finished"
|
description = "Show amount of time remaining instead of completion time"
|
||||||
)
|
)
|
||||||
default boolean estimateRelative()
|
default boolean estimateRelative()
|
||||||
{
|
{
|
||||||
@@ -45,21 +45,21 @@ public interface FarmingTrackerConfig extends Config
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ConfigItem(
|
@ConfigItem(
|
||||||
keyName = "patch",
|
keyName = "activeTab",
|
||||||
name = "Default patch",
|
name = "Active Tab",
|
||||||
description = "Default patch on opening the panel",
|
description = "The currently selected tab",
|
||||||
hidden = true
|
hidden = true
|
||||||
)
|
)
|
||||||
default Tab patch()
|
default Tab activeTab()
|
||||||
{
|
{
|
||||||
return Tab.ALLOTMENT;
|
return Tab.ALLOTMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ConfigItem(
|
@ConfigItem(
|
||||||
keyName = "patch",
|
keyName = "activeTab",
|
||||||
name = "",
|
name = "",
|
||||||
description = "",
|
description = "",
|
||||||
hidden = true
|
hidden = true
|
||||||
)
|
)
|
||||||
void setPatch(Tab t);
|
void setActiveTab(Tab t);
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Abex
|
||||||
|
* Copyright (c) 2018, Psikoi <https://github.com/psikoi>
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.GridLayout;
|
||||||
|
import java.awt.Image;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import javax.swing.ImageIcon;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JScrollPane;
|
||||||
|
import javax.swing.border.EmptyBorder;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import net.runelite.client.game.AsyncBufferedImage;
|
||||||
|
import net.runelite.client.game.ItemManager;
|
||||||
|
import net.runelite.client.plugins.timetracking.farming.FarmingTracker;
|
||||||
|
import net.runelite.client.ui.ColorScheme;
|
||||||
|
import net.runelite.client.ui.PluginPanel;
|
||||||
|
import net.runelite.client.ui.components.materialtabs.MaterialTab;
|
||||||
|
import net.runelite.client.ui.components.materialtabs.MaterialTabGroup;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
class TimeTrackingPanel extends PluginPanel
|
||||||
|
{
|
||||||
|
private final ItemManager itemManager;
|
||||||
|
private final TimeTrackingConfig config;
|
||||||
|
|
||||||
|
/* This is the panel the tabs' respective panels will be displayed on. */
|
||||||
|
private final JPanel display = new JPanel();
|
||||||
|
private final MaterialTabGroup tabGroup = new MaterialTabGroup(display);
|
||||||
|
|
||||||
|
private boolean active;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private TabContentPanel activeTabPanel = null;
|
||||||
|
|
||||||
|
TimeTrackingPanel(ItemManager itemManager, TimeTrackingConfig config, FarmingTracker farmingTracker)
|
||||||
|
{
|
||||||
|
super(false);
|
||||||
|
|
||||||
|
this.itemManager = itemManager;
|
||||||
|
this.config = config;
|
||||||
|
|
||||||
|
setLayout(new BorderLayout());
|
||||||
|
setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
|
|
||||||
|
display.setBorder(new EmptyBorder(10, 10, 8, 10));
|
||||||
|
|
||||||
|
tabGroup.setLayout(new GridLayout(0, 6, 7, 7));
|
||||||
|
tabGroup.setBorder(new EmptyBorder(10, 10, 0, 10));
|
||||||
|
|
||||||
|
add(tabGroup, BorderLayout.NORTH);
|
||||||
|
add(display, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
for (Tab tab : Tab.FARMING_TABS)
|
||||||
|
{
|
||||||
|
addTab(tab, farmingTracker.createTabPanel(tab));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addTab(Tab tab, TabContentPanel tabContentPanel)
|
||||||
|
{
|
||||||
|
JPanel wrapped = new JPanel(new BorderLayout());
|
||||||
|
wrapped.add(tabContentPanel, BorderLayout.NORTH);
|
||||||
|
wrapped.setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
|
|
||||||
|
JScrollPane scroller = new JScrollPane(wrapped);
|
||||||
|
scroller.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
|
||||||
|
scroller.getVerticalScrollBar().setPreferredSize(new Dimension(16, 0));
|
||||||
|
scroller.getVerticalScrollBar().setBorder(new EmptyBorder(0, 9, 0, 0));
|
||||||
|
scroller.setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
|
|
||||||
|
// Use a placeholder icon until the async image gets loaded
|
||||||
|
MaterialTab materialTab = new MaterialTab(new ImageIcon(), tabGroup, scroller);
|
||||||
|
materialTab.setPreferredSize(new Dimension(30, 27));
|
||||||
|
materialTab.setName(tab.getName());
|
||||||
|
materialTab.setToolTipText(tab.getName());
|
||||||
|
|
||||||
|
AsyncBufferedImage icon = itemManager.getImage(tab.getItemID());
|
||||||
|
Runnable resize = () ->
|
||||||
|
{
|
||||||
|
BufferedImage subIcon = icon.getSubimage(0, 0, 32, 32);
|
||||||
|
materialTab.setIcon(new ImageIcon(subIcon.getScaledInstance(24, 24, Image.SCALE_SMOOTH)));
|
||||||
|
};
|
||||||
|
icon.onChanged(resize);
|
||||||
|
resize.run();
|
||||||
|
|
||||||
|
materialTab.setOnSelectEvent(() ->
|
||||||
|
{
|
||||||
|
config.setActiveTab(tab);
|
||||||
|
activeTabPanel = tabContentPanel;
|
||||||
|
|
||||||
|
tabContentPanel.update();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
tabGroup.addTab(materialTab);
|
||||||
|
if (config.activeTab() == tab)
|
||||||
|
{
|
||||||
|
tabGroup.select(materialTab);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void update()
|
||||||
|
{
|
||||||
|
if (!active || activeTabPanel == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
activeTabPanel.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivate()
|
||||||
|
{
|
||||||
|
active = true;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDeactivate()
|
||||||
|
{
|
||||||
|
active = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 Abex
|
* Copyright (c) 2018 Abex
|
||||||
|
* Copyright (c) 2018, Daniel Teo <https://github.com/takuyakanbr>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -22,19 +23,17 @@
|
|||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
package net.runelite.client.plugins.farmingtracker;
|
package net.runelite.client.plugins.timetracking;
|
||||||
|
|
||||||
import com.google.common.eventbus.Subscribe;
|
import com.google.common.eventbus.Subscribe;
|
||||||
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.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.runelite.api.Client;
|
import net.runelite.api.Client;
|
||||||
import net.runelite.api.GameState;
|
import net.runelite.api.GameState;
|
||||||
import net.runelite.api.Varbits;
|
|
||||||
import net.runelite.api.coords.WorldPoint;
|
import net.runelite.api.coords.WorldPoint;
|
||||||
import net.runelite.api.events.GameTick;
|
import net.runelite.api.events.GameTick;
|
||||||
import net.runelite.api.events.UsernameChanged;
|
import net.runelite.api.events.UsernameChanged;
|
||||||
@@ -42,58 +41,56 @@ import net.runelite.client.config.ConfigManager;
|
|||||||
import net.runelite.client.game.ItemManager;
|
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 net.runelite.client.plugins.timetracking.farming.FarmingTracker;
|
||||||
import net.runelite.client.task.Schedule;
|
import net.runelite.client.task.Schedule;
|
||||||
import net.runelite.client.ui.NavigationButton;
|
import net.runelite.client.ui.NavigationButton;
|
||||||
import net.runelite.client.ui.ClientToolbar;
|
import net.runelite.client.ui.ClientToolbar;
|
||||||
import net.runelite.client.util.ImageUtil;
|
import net.runelite.client.util.ImageUtil;
|
||||||
|
|
||||||
@PluginDescriptor(
|
@PluginDescriptor(
|
||||||
name = "Farming Tracker",
|
name = "Time Tracking",
|
||||||
description = "Show when your farming plots would be fully grown",
|
description = "Enable the Time Tracking panel, which contains farming trackers",
|
||||||
tags = {"skilling", "panel", "timers"}
|
tags = {"farming", "skilling", "panel"}
|
||||||
)
|
)
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class FarmingTrackerPlugin extends Plugin
|
public class TimeTrackingPlugin extends Plugin
|
||||||
{
|
{
|
||||||
@Inject
|
@Inject
|
||||||
private ClientToolbar clientToolbar;
|
private ClientToolbar clientToolbar;
|
||||||
|
|
||||||
@Inject
|
|
||||||
private ConfigManager configManager;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private Client client;
|
private Client client;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private FarmingWorld farmingWorld;
|
private FarmingTracker farmingTracker;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private ItemManager itemManager;
|
private ItemManager itemManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private FarmingTrackerConfig config;
|
private TimeTrackingConfig config;
|
||||||
|
|
||||||
private FarmingTrackerPanel panel;
|
private TimeTrackingPanel panel;
|
||||||
|
|
||||||
private NavigationButton navButton;
|
private NavigationButton navButton;
|
||||||
|
|
||||||
private WorldPoint lastTickLoc;
|
private WorldPoint lastTickLocation;
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
FarmingTrackerConfig provideConfig(ConfigManager configManager)
|
TimeTrackingConfig provideConfig(ConfigManager configManager)
|
||||||
{
|
{
|
||||||
return configManager.getConfig(FarmingTrackerConfig.class);
|
return configManager.getConfig(TimeTrackingConfig.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void startUp() throws Exception
|
protected void startUp() throws Exception
|
||||||
{
|
{
|
||||||
final BufferedImage icon = ImageUtil.getResourceStreamFromClass(getClass(), "farming.png");
|
final BufferedImage icon = ImageUtil.getResourceStreamFromClass(getClass(), "watch.png");
|
||||||
|
|
||||||
panel = new FarmingTrackerPanel(client, itemManager, configManager, config, farmingWorld);
|
panel = new TimeTrackingPanel(itemManager, config, farmingTracker);
|
||||||
|
|
||||||
navButton = NavigationButton.builder()
|
navButton = NavigationButton.builder()
|
||||||
.tooltip("Farming Tracker")
|
.tooltip("Time Tracking")
|
||||||
.icon(icon)
|
.icon(icon)
|
||||||
.panel(panel)
|
.panel(panel)
|
||||||
.priority(4)
|
.priority(4)
|
||||||
@@ -104,15 +101,10 @@ public class FarmingTrackerPlugin extends Plugin
|
|||||||
updatePanel();
|
updatePanel();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
|
||||||
public void onUsernameChanged(UsernameChanged e)
|
|
||||||
{
|
|
||||||
updatePanel();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void shutDown() throws Exception
|
protected void shutDown() throws Exception
|
||||||
{
|
{
|
||||||
|
lastTickLocation = null;
|
||||||
clientToolbar.removeNavigation(navButton);
|
clientToolbar.removeNavigation(navButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,73 +113,33 @@ public class FarmingTrackerPlugin extends Plugin
|
|||||||
{
|
{
|
||||||
if (client.getGameState() != GameState.LOGGED_IN)
|
if (client.getGameState() != GameState.LOGGED_IN)
|
||||||
{
|
{
|
||||||
lastTickLoc = null;
|
lastTickLocation = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldPoint loc = lastTickLoc;
|
WorldPoint loc = lastTickLocation;
|
||||||
lastTickLoc = client.getLocalPlayer().getWorldLocation();
|
lastTickLocation = client.getLocalPlayer().getWorldLocation();
|
||||||
if (loc == null || loc.getRegionID() != lastTickLoc.getRegionID())
|
|
||||||
|
if (loc == null || loc.getRegionID() != lastTickLocation.getRegionID())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean changed = false;
|
boolean farmingDataChanged = farmingTracker.updateData(loc);
|
||||||
|
|
||||||
{
|
if (farmingDataChanged)
|
||||||
String group = FarmingTrackerConfig.KEY_NAME + "." + client.getUsername();
|
|
||||||
String autoweed = Integer.toString(client.getVar(Varbits.AUTOWEED));
|
|
||||||
if (!autoweed.equals(configManager.getConfiguration(group, FarmingTrackerConfig.AUTOWEED)))
|
|
||||||
{
|
|
||||||
configManager.setConfiguration(group, FarmingTrackerConfig.AUTOWEED, autoweed);
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FarmingRegion region = farmingWorld.getRegions().get(loc.getRegionID());
|
|
||||||
if (region != null && region.isInBounds(loc))
|
|
||||||
{
|
|
||||||
// Write config with new varbits
|
|
||||||
// farmingTracker.<login-username>.<regionID>.<VarbitID>=<varbitValue>:<unix time>
|
|
||||||
String group = FarmingTrackerConfig.KEY_NAME + "." + client.getUsername() + "." + region.getRegionID();
|
|
||||||
long unixNow = Instant.now().getEpochSecond();
|
|
||||||
for (Varbits varbit : region.getVarbits())
|
|
||||||
{
|
|
||||||
// Write the config value if it doesn't match what is current, or it is more than 5 minutes old
|
|
||||||
String key = Integer.toString(varbit.getId());
|
|
||||||
String strVarbit = Integer.toString(client.getVar(varbit));
|
|
||||||
String storedValue = configManager.getConfiguration(group, key);
|
|
||||||
if (storedValue != null)
|
|
||||||
{
|
|
||||||
String[] parts = storedValue.split(":");
|
|
||||||
if (parts.length == 2 && parts[0].equals(strVarbit))
|
|
||||||
{
|
|
||||||
long unixTime = 0;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
unixTime = Long.parseLong(parts[1]);
|
|
||||||
}
|
|
||||||
catch (NumberFormatException e)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
if (unixTime + (5 * 60) > unixNow && unixNow + 30 > unixTime)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
String value = strVarbit + ":" + unixNow;
|
|
||||||
configManager.setConfiguration(group, key, value);
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changed)
|
|
||||||
{
|
{
|
||||||
updatePanel();
|
updatePanel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onUsernameChanged(UsernameChanged e)
|
||||||
|
{
|
||||||
|
farmingTracker.migrateConfiguration();
|
||||||
|
updatePanel();
|
||||||
|
}
|
||||||
|
|
||||||
@Schedule(period = 10, unit = ChronoUnit.SECONDS)
|
@Schedule(period = 10, unit = ChronoUnit.SECONDS)
|
||||||
public void updatePanel()
|
public void updatePanel()
|
||||||
{
|
{
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
package net.runelite.client.plugins.farmingtracker;
|
package net.runelite.client.plugins.timetracking.farming;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
package net.runelite.client.plugins.farmingtracker;
|
package net.runelite.client.plugins.timetracking.farming;
|
||||||
|
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
@@ -34,7 +34,7 @@ import net.runelite.api.Varbits;
|
|||||||
access = AccessLevel.PACKAGE
|
access = AccessLevel.PACKAGE
|
||||||
)
|
)
|
||||||
@Getter
|
@Getter
|
||||||
public class FarmingPatch
|
class FarmingPatch
|
||||||
{
|
{
|
||||||
@Setter(AccessLevel.PACKAGE)
|
@Setter(AccessLevel.PACKAGE)
|
||||||
private FarmingRegion region;
|
private FarmingRegion region;
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
package net.runelite.client.plugins.farmingtracker;
|
package net.runelite.client.plugins.timetracking.farming;
|
||||||
|
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
package net.runelite.client.plugins.farmingtracker;
|
package net.runelite.client.plugins.timetracking.farming;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import net.runelite.api.Varbits;
|
import net.runelite.api.Varbits;
|
||||||
@@ -23,15 +23,11 @@
|
|||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
package net.runelite.client.plugins.farmingtracker;
|
package net.runelite.client.plugins.timetracking.farming;
|
||||||
|
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
import java.awt.BorderLayout;
|
|
||||||
import java.awt.Dimension;
|
|
||||||
import java.awt.GridBagConstraints;
|
import java.awt.GridBagConstraints;
|
||||||
import java.awt.GridBagLayout;
|
import java.awt.GridBagLayout;
|
||||||
import java.awt.Image;
|
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
@@ -39,180 +35,106 @@ import java.time.format.TextStyle;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import javax.swing.ImageIcon;
|
import java.util.Set;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JPanel;
|
|
||||||
import javax.swing.JScrollPane;
|
|
||||||
import javax.swing.border.EmptyBorder;
|
import javax.swing.border.EmptyBorder;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.runelite.api.Client;
|
import net.runelite.api.Client;
|
||||||
import net.runelite.api.vars.Autoweed;
|
import net.runelite.api.vars.Autoweed;
|
||||||
import net.runelite.client.config.ConfigManager;
|
import net.runelite.client.config.ConfigManager;
|
||||||
import net.runelite.client.game.AsyncBufferedImage;
|
|
||||||
import net.runelite.client.game.ItemManager;
|
import net.runelite.client.game.ItemManager;
|
||||||
|
import net.runelite.client.plugins.timetracking.TabContentPanel;
|
||||||
|
import net.runelite.client.plugins.timetracking.TimeTrackingConfig;
|
||||||
import net.runelite.client.ui.ColorScheme;
|
import net.runelite.client.ui.ColorScheme;
|
||||||
import net.runelite.client.ui.FontManager;
|
import net.runelite.client.ui.FontManager;
|
||||||
import net.runelite.client.ui.PluginPanel;
|
|
||||||
import net.runelite.client.ui.components.materialtabs.MaterialTab;
|
|
||||||
import net.runelite.client.ui.components.materialtabs.MaterialTabGroup;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
class FarmingTrackerPanel extends PluginPanel
|
public class FarmingTabPanel extends TabContentPanel
|
||||||
{
|
{
|
||||||
private final Client client;
|
private final Client client;
|
||||||
private final ItemManager itemManager;
|
private final ItemManager itemManager;
|
||||||
private final ConfigManager configManager;
|
private final ConfigManager configManager;
|
||||||
private final FarmingTrackerConfig config;
|
private final TimeTrackingConfig config;
|
||||||
|
private final List<FarmingPatchPanel> patchPanels;
|
||||||
|
|
||||||
private boolean active;
|
FarmingTabPanel(Client client, ItemManager itemManager, ConfigManager configManager,
|
||||||
|
TimeTrackingConfig config, Set<FarmingPatch> patches)
|
||||||
private List<FarmingPatchPanel> patchPanels = new ArrayList<>();
|
|
||||||
|
|
||||||
/* This is the panel the tabs' respective panels will be displayed on. */
|
|
||||||
private final JPanel display = new JPanel();
|
|
||||||
private final MaterialTabGroup tabGroup = new MaterialTabGroup(display);
|
|
||||||
|
|
||||||
FarmingTrackerPanel(
|
|
||||||
Client client,
|
|
||||||
ItemManager itemManager,
|
|
||||||
ConfigManager configManager,
|
|
||||||
FarmingTrackerConfig config,
|
|
||||||
FarmingWorld farmingWorld
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
super(false);
|
|
||||||
|
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.itemManager = itemManager;
|
this.itemManager = itemManager;
|
||||||
this.configManager = configManager;
|
this.configManager = configManager;
|
||||||
this.config = config;
|
this.config = config;
|
||||||
|
this.patchPanels = new ArrayList<>();
|
||||||
|
|
||||||
setLayout(new BorderLayout());
|
setLayout(new GridBagLayout());
|
||||||
setBackground(ColorScheme.DARK_GRAY_COLOR);
|
setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
|
|
||||||
display.setBorder(new EmptyBorder(10, 10, 8, 10));
|
GridBagConstraints c = new GridBagConstraints();
|
||||||
|
c.fill = GridBagConstraints.HORIZONTAL;
|
||||||
|
c.weightx = 1;
|
||||||
|
c.gridx = 0;
|
||||||
|
c.gridy = 0;
|
||||||
|
|
||||||
tabGroup.setBorder(new EmptyBorder(10, 1, 0, 0));
|
PatchImplementation lastImpl = null;
|
||||||
|
|
||||||
add(tabGroup, BorderLayout.NORTH);
|
boolean first = true;
|
||||||
add(display, BorderLayout.CENTER);
|
for (FarmingPatch patch : patches)
|
||||||
|
|
||||||
farmingWorld.getTabs().forEach((tab, patches) ->
|
|
||||||
{
|
{
|
||||||
JPanel container = new JPanel(new GridBagLayout())
|
FarmingPatchPanel p = new FarmingPatchPanel(patch);
|
||||||
|
|
||||||
|
/* Show labels to subdivide tabs into sections */
|
||||||
|
if (patch.getImplementation() != lastImpl && !Strings.isNullOrEmpty(patch.getImplementation().getName()))
|
||||||
{
|
{
|
||||||
@Override
|
JLabel groupLabel = new JLabel(patch.getImplementation().getName());
|
||||||
public Dimension getPreferredSize()
|
|
||||||
{
|
|
||||||
return new Dimension(PluginPanel.PANEL_WIDTH, super.getPreferredSize().height);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
container.setBackground(ColorScheme.DARK_GRAY_COLOR);
|
|
||||||
|
|
||||||
GridBagConstraints c = new GridBagConstraints();
|
|
||||||
c.fill = GridBagConstraints.HORIZONTAL;
|
|
||||||
c.weightx = 1;
|
|
||||||
c.gridx = 0;
|
|
||||||
c.gridy = 0;
|
|
||||||
|
|
||||||
PatchImplementation lastImpl = null;
|
|
||||||
|
|
||||||
boolean first = true;
|
|
||||||
for (FarmingPatch patch : patches)
|
|
||||||
{
|
|
||||||
FarmingPatchPanel p = new FarmingPatchPanel(patch);
|
|
||||||
|
|
||||||
/* Show labels to subdivide tabs into sections */
|
|
||||||
if (patch.getImplementation() != lastImpl && !Strings.isNullOrEmpty(patch.getImplementation().getName()))
|
|
||||||
{
|
|
||||||
JLabel groupLabel = new JLabel(patch.getImplementation().getName());
|
|
||||||
|
|
||||||
if (first)
|
|
||||||
{
|
|
||||||
first = false;
|
|
||||||
groupLabel.setBorder(new EmptyBorder(4, 0, 0, 0));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
groupLabel.setBorder(new EmptyBorder(15, 0, 0, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
groupLabel.setFont(FontManager.getRunescapeSmallFont());
|
|
||||||
|
|
||||||
container.add(groupLabel, c);
|
|
||||||
c.gridy++;
|
|
||||||
lastImpl = patch.getImplementation();
|
|
||||||
}
|
|
||||||
|
|
||||||
patchPanels.add(p);
|
|
||||||
container.add(p, c);
|
|
||||||
c.gridy++;
|
|
||||||
|
|
||||||
/* This is a weird hack to remove the top border on the first tracker of every tab */
|
|
||||||
if (first)
|
if (first)
|
||||||
{
|
{
|
||||||
first = false;
|
first = false;
|
||||||
p.setBorder(null);
|
groupLabel.setBorder(new EmptyBorder(4, 0, 0, 0));
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
groupLabel.setBorder(new EmptyBorder(15, 0, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
groupLabel.setFont(FontManager.getRunescapeSmallFont());
|
||||||
|
|
||||||
|
add(groupLabel, c);
|
||||||
|
c.gridy++;
|
||||||
|
lastImpl = patch.getImplementation();
|
||||||
}
|
}
|
||||||
|
|
||||||
JPanel wrapped = new JPanel(new BorderLayout());
|
patchPanels.add(p);
|
||||||
wrapped.add(container, BorderLayout.NORTH);
|
add(p, c);
|
||||||
wrapped.setBackground(ColorScheme.DARK_GRAY_COLOR);
|
c.gridy++;
|
||||||
|
|
||||||
JScrollPane scroller = new JScrollPane(wrapped);
|
/* This is a weird hack to remove the top border on the first tracker of every tab */
|
||||||
scroller.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
|
if (first)
|
||||||
scroller.getVerticalScrollBar().setPreferredSize(new Dimension(16, 0));
|
|
||||||
scroller.getVerticalScrollBar().setBorder(new EmptyBorder(0, 9, 0, 0));
|
|
||||||
scroller.setBackground(ColorScheme.DARK_GRAY_COLOR);
|
|
||||||
|
|
||||||
//Use a placeholder icon until the async image gets loaded
|
|
||||||
MaterialTab materialTab = new MaterialTab(new ImageIcon(), tabGroup, scroller);
|
|
||||||
materialTab.setPreferredSize(new Dimension(30, 27));
|
|
||||||
materialTab.setName(tab.getName());
|
|
||||||
|
|
||||||
AsyncBufferedImage icon = itemManager.getImage(tab.getItemID());
|
|
||||||
Runnable resize = () ->
|
|
||||||
{
|
{
|
||||||
BufferedImage subIcon = icon.getSubimage(0, 0, 32, 32);
|
first = false;
|
||||||
materialTab.setIcon(new ImageIcon(subIcon.getScaledInstance(24, 24, Image.SCALE_SMOOTH)));
|
p.setBorder(null);
|
||||||
};
|
|
||||||
icon.onChanged(resize);
|
|
||||||
resize.run();
|
|
||||||
|
|
||||||
materialTab.setOnSelectEvent(() ->
|
|
||||||
{
|
|
||||||
config.setPatch(tab);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
tabGroup.addTab(materialTab);
|
|
||||||
if (config.patch() == tab)
|
|
||||||
{
|
|
||||||
tabGroup.select(materialTab);
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void update()
|
@Override
|
||||||
|
public void update()
|
||||||
{
|
{
|
||||||
if (!active)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
long unixNow = Instant.now().getEpochSecond();
|
long unixNow = Instant.now().getEpochSecond();
|
||||||
log.debug("Updating panel with username {}", client.getUsername());
|
log.debug("Updating panel with username {}", client.getUsername());
|
||||||
boolean autoweed = false;
|
|
||||||
|
boolean autoweed;
|
||||||
{
|
{
|
||||||
String group = FarmingTrackerConfig.KEY_NAME + "." + client.getUsername();
|
String group = TimeTrackingConfig.KEY_NAME + "." + client.getUsername();
|
||||||
autoweed = Integer.toString(Autoweed.ON.ordinal())
|
autoweed = Integer.toString(Autoweed.ON.ordinal())
|
||||||
.equals(configManager.getConfiguration(group, FarmingTrackerConfig.AUTOWEED));
|
.equals(configManager.getConfiguration(group, TimeTrackingConfig.AUTOWEED));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (FarmingPatchPanel panel : patchPanels)
|
for (FarmingPatchPanel panel : patchPanels)
|
||||||
{
|
{
|
||||||
FarmingPatch patch = panel.getPatch();
|
FarmingPatch patch = panel.getPatch();
|
||||||
String group = FarmingTrackerConfig.KEY_NAME + "." + client.getUsername() + "." + patch.getRegion().getRegionID();
|
String group = TimeTrackingConfig.KEY_NAME + "." + client.getUsername() + "." + patch.getRegion().getRegionID();
|
||||||
String key = Integer.toString(patch.getVarbit().getId());
|
String key = Integer.toString(patch.getVarbit().getId());
|
||||||
String storedValue = configManager.getConfiguration(group, key);
|
String storedValue = configManager.getConfiguration(group, key);
|
||||||
long unixTime = 0;
|
long unixTime = 0;
|
||||||
@@ -258,19 +180,9 @@ class FarmingTrackerPanel extends PluginPanel
|
|||||||
}
|
}
|
||||||
|
|
||||||
int stage = state.getStage();
|
int stage = state.getStage();
|
||||||
int stages = state.getCropState() == CropState.HARVESTABLE ?
|
int stages = state.getStages();
|
||||||
state.getProduce().getHarvestStages() :
|
int tickrate = state.getTickRate() * 60;
|
||||||
state.getProduce().getStages();
|
|
||||||
int tickrate = 0;
|
|
||||||
switch (state.getCropState())
|
|
||||||
{
|
|
||||||
case HARVESTABLE:
|
|
||||||
tickrate = state.getProduce().getRegrowTickrate() * 60;
|
|
||||||
break;
|
|
||||||
case GROWING:
|
|
||||||
tickrate = state.getProduce().getTickrate() * 60;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (autoweed && state.getProduce() == Produce.WEEDS)
|
if (autoweed && state.getProduce() == Produce.WEEDS)
|
||||||
{
|
{
|
||||||
stage = 0;
|
stage = 0;
|
||||||
@@ -374,17 +286,4 @@ class FarmingTrackerPanel extends PluginPanel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onActivate()
|
|
||||||
{
|
|
||||||
active = true;
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDeactivate()
|
|
||||||
{
|
|
||||||
active = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,169 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 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.client.plugins.timetracking.farming;
|
||||||
|
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.Singleton;
|
||||||
|
import java.time.Instant;
|
||||||
|
import net.runelite.api.Client;
|
||||||
|
import net.runelite.api.Varbits;
|
||||||
|
import net.runelite.api.coords.WorldPoint;
|
||||||
|
import net.runelite.client.config.ConfigManager;
|
||||||
|
import net.runelite.client.game.ItemManager;
|
||||||
|
import net.runelite.client.plugins.timetracking.Tab;
|
||||||
|
import net.runelite.client.plugins.timetracking.TimeTrackingConfig;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class FarmingTracker
|
||||||
|
{
|
||||||
|
@Deprecated
|
||||||
|
private static final String OLD_KEY_NAME = "farmingTracker";
|
||||||
|
|
||||||
|
private final Client client;
|
||||||
|
private final ItemManager itemManager;
|
||||||
|
private final ConfigManager configManager;
|
||||||
|
private final TimeTrackingConfig config;
|
||||||
|
private final FarmingWorld farmingWorld;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private FarmingTracker(Client client, ItemManager itemManager, ConfigManager configManager,
|
||||||
|
TimeTrackingConfig config, FarmingWorld farmingWorld)
|
||||||
|
{
|
||||||
|
this.client = client;
|
||||||
|
this.itemManager = itemManager;
|
||||||
|
this.configManager = configManager;
|
||||||
|
this.config = config;
|
||||||
|
this.farmingWorld = farmingWorld;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public FarmingTabPanel createTabPanel(Tab tab)
|
||||||
|
{
|
||||||
|
return new FarmingTabPanel(client, itemManager, configManager, config, farmingWorld.getTabs().get(tab));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates tracker data for the current region. Returns true if any data was changed.
|
||||||
|
*/
|
||||||
|
public boolean updateData(WorldPoint location)
|
||||||
|
{
|
||||||
|
boolean changed = false;
|
||||||
|
|
||||||
|
{
|
||||||
|
String group = TimeTrackingConfig.KEY_NAME + "." + client.getUsername();
|
||||||
|
String autoweed = Integer.toString(client.getVar(Varbits.AUTOWEED));
|
||||||
|
if (!autoweed.equals(configManager.getConfiguration(group, TimeTrackingConfig.AUTOWEED)))
|
||||||
|
{
|
||||||
|
configManager.setConfiguration(group, TimeTrackingConfig.AUTOWEED, autoweed);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FarmingRegion region = farmingWorld.getRegions().get(location.getRegionID());
|
||||||
|
if (region != null && region.isInBounds(location))
|
||||||
|
{
|
||||||
|
// Write config with new varbits
|
||||||
|
// timetracking.<login-username>.<regionID>.<VarbitID>=<varbitValue>:<unix time>
|
||||||
|
String group = TimeTrackingConfig.KEY_NAME + "." + client.getUsername() + "." + region.getRegionID();
|
||||||
|
long unixNow = Instant.now().getEpochSecond();
|
||||||
|
for (Varbits varbit : region.getVarbits())
|
||||||
|
{
|
||||||
|
// Write the config value if it doesn't match what is current, or it is more than 5 minutes old
|
||||||
|
String key = Integer.toString(varbit.getId());
|
||||||
|
String strVarbit = Integer.toString(client.getVar(varbit));
|
||||||
|
String storedValue = configManager.getConfiguration(group, key);
|
||||||
|
|
||||||
|
if (storedValue != null)
|
||||||
|
{
|
||||||
|
String[] parts = storedValue.split(":");
|
||||||
|
if (parts.length == 2 && parts[0].equals(strVarbit))
|
||||||
|
{
|
||||||
|
long unixTime = 0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
unixTime = Long.parseLong(parts[1]);
|
||||||
|
}
|
||||||
|
catch (NumberFormatException e)
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
if (unixTime + (5 * 60) > unixNow && unixNow + 30 > unixTime)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String value = strVarbit + ":" + unixNow;
|
||||||
|
configManager.setConfiguration(group, key, value);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Migrates configuration data from {@code "farmingTracker"} key to {@code "timetracking"} key.
|
||||||
|
* This method should be removed after a reasonable amount of time.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public void migrateConfiguration()
|
||||||
|
{
|
||||||
|
String username = client.getUsername();
|
||||||
|
|
||||||
|
// migrate autoweed config
|
||||||
|
{
|
||||||
|
String oldGroup = OLD_KEY_NAME + "." + username;
|
||||||
|
String newGroup = TimeTrackingConfig.KEY_NAME + "." + username;
|
||||||
|
String storedValue = configManager.getConfiguration(oldGroup, TimeTrackingConfig.AUTOWEED);
|
||||||
|
|
||||||
|
if (storedValue != null)
|
||||||
|
{
|
||||||
|
configManager.setConfiguration(newGroup, TimeTrackingConfig.AUTOWEED, storedValue);
|
||||||
|
configManager.unsetConfiguration(oldGroup, TimeTrackingConfig.AUTOWEED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// migrate all saved data in all regions
|
||||||
|
for (FarmingRegion region : farmingWorld.getRegions().values())
|
||||||
|
{
|
||||||
|
String oldGroup = OLD_KEY_NAME + "." + username + "." + region.getRegionID();
|
||||||
|
String newGroup = TimeTrackingConfig.KEY_NAME + "." + username + "." + region.getRegionID();
|
||||||
|
|
||||||
|
for (Varbits varbit : region.getVarbits())
|
||||||
|
{
|
||||||
|
String key = Integer.toString(varbit.getId());
|
||||||
|
String storedValue = configManager.getConfiguration(oldGroup, key);
|
||||||
|
|
||||||
|
if (storedValue != null)
|
||||||
|
{
|
||||||
|
configManager.setConfiguration(newGroup, key, storedValue);
|
||||||
|
configManager.unsetConfiguration(oldGroup, key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
package net.runelite.client.plugins.farmingtracker;
|
package net.runelite.client.plugins.timetracking.farming;
|
||||||
|
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -36,9 +36,10 @@ import java.util.TreeSet;
|
|||||||
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;
|
||||||
|
import net.runelite.client.plugins.timetracking.Tab;
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public class FarmingWorld
|
class FarmingWorld
|
||||||
{
|
{
|
||||||
@Getter
|
@Getter
|
||||||
private Map<Integer, FarmingRegion> regions = new HashMap<>();
|
private Map<Integer, FarmingRegion> regions = new HashMap<>();
|
||||||
@@ -51,7 +52,7 @@ public class FarmingWorld
|
|||||||
.thenComparing((FarmingPatch p) -> p.getRegion().getName())
|
.thenComparing((FarmingPatch p) -> p.getRegion().getName())
|
||||||
.thenComparing(FarmingPatch::getName);
|
.thenComparing(FarmingPatch::getName);
|
||||||
|
|
||||||
public FarmingWorld()
|
FarmingWorld()
|
||||||
{
|
{
|
||||||
// Some of these patches get updated in multiple regions.
|
// Some of these patches get updated in multiple regions.
|
||||||
// It may be worth it to add a specialization for these patches
|
// It may be worth it to add a specialization for these patches
|
||||||
@@ -22,10 +22,11 @@
|
|||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
package net.runelite.client.plugins.farmingtracker;
|
package net.runelite.client.plugins.timetracking.farming;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import net.runelite.client.plugins.timetracking.Tab;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@Getter
|
@Getter
|
||||||
@@ -733,7 +734,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
FLOWER(Tab.HERB, "Flowers")
|
FLOWER(Tab.FLOWER, "")
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -1205,7 +1206,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
FRUIT_TREE(Tab.FRUIT_TREE, "Fruit trees")
|
FRUIT_TREE(Tab.FRUIT_TREE, "")
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -1454,7 +1455,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
HOPS(Tab.SPECIAL, "Hops")
|
HOPS(Tab.HOPS, "")
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -2267,7 +2268,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
GRAPES(Tab.BUSH, "Grapes")
|
GRAPES(Tab.GRAPE, "")
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -22,14 +22,32 @@
|
|||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
package net.runelite.client.plugins.farmingtracker;
|
package net.runelite.client.plugins.timetracking.farming;
|
||||||
|
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
|
|
||||||
@Value
|
@Value
|
||||||
public class PatchState
|
class PatchState
|
||||||
{
|
{
|
||||||
private final Produce produce;
|
private final Produce produce;
|
||||||
private final CropState cropState;
|
private final CropState cropState;
|
||||||
private final int stage;
|
private final int stage;
|
||||||
|
|
||||||
|
int getStages()
|
||||||
|
{
|
||||||
|
return cropState == CropState.HARVESTABLE ? produce.getHarvestStages() : produce.getStages();
|
||||||
|
}
|
||||||
|
|
||||||
|
int getTickRate()
|
||||||
|
{
|
||||||
|
switch (cropState)
|
||||||
|
{
|
||||||
|
case HARVESTABLE:
|
||||||
|
return produce.getRegrowTickrate();
|
||||||
|
case GROWING:
|
||||||
|
return produce.getTickrate();
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
package net.runelite.client.plugins.farmingtracker;
|
package net.runelite.client.plugins.timetracking.farming;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@@ -127,7 +127,7 @@ public enum Produce
|
|||||||
*/
|
*/
|
||||||
private final int tickrate;
|
private final int tickrate;
|
||||||
/**
|
/**
|
||||||
* How many states this crop has during groth. Typically tickcount+1
|
* How many states this crop has during growth. Typically tickcount+1
|
||||||
*/
|
*/
|
||||||
private final int stages;
|
private final int stages;
|
||||||
/**
|
/**
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.6 KiB |
@@ -21,7 +21,7 @@
|
|||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
* 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
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/package net.runelite.client.plugins.farmingtracker;
|
*/package net.runelite.client.plugins.timetracking.farming;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
package net.runelite.client.plugins.farmingtracker;
|
package net.runelite.client.plugins.timetracking.farming;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
Reference in New Issue
Block a user