Added xp/hr tracker
This commit is contained in:
@@ -51,6 +51,7 @@ import net.runelite.client.plugins.opponentinfo.OpponentInfo;
|
||||
import net.runelite.client.plugins.pestcontrol.PestControl;
|
||||
import net.runelite.client.plugins.runecraft.Runecraft;
|
||||
import net.runelite.client.plugins.xpglobes.XpGlobes;
|
||||
import net.runelite.client.plugins.xptracker.XPTracker;
|
||||
import net.runelite.client.plugins.xtea.Xtea;
|
||||
import net.runelite.client.plugins.zulrah.Zulrah;
|
||||
import org.slf4j.Logger;
|
||||
@@ -90,6 +91,7 @@ public class PluginManager
|
||||
plugins.add(new XpGlobes());
|
||||
plugins.add(new CombatNotifier());
|
||||
plugins.add(new JewelryCount());
|
||||
plugins.add(new XPTracker());
|
||||
plugins.add(new ExaminePlugin());
|
||||
|
||||
if (RuneLite.getOptions().has("developer-mode"))
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Cameron <moberg@tuta.io>
|
||||
* 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.xptracker;
|
||||
|
||||
import net.runelite.api.Skill;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
|
||||
public class SkillXPInfo
|
||||
{
|
||||
private Skill skill;
|
||||
private Instant skillTimeStart = null;
|
||||
private int xpGained = 0;
|
||||
private int loginXp = 0;
|
||||
|
||||
public SkillXPInfo(int loginXp, Skill skill)
|
||||
{
|
||||
this.skill = skill;
|
||||
this.loginXp = loginXp;
|
||||
}
|
||||
|
||||
public int getXpHr()
|
||||
{
|
||||
long timeElapsedInSeconds = Duration.between(
|
||||
skillTimeStart, Instant.now()).getSeconds();
|
||||
return (int) ((1.0 / (timeElapsedInSeconds / 3600.0)) * xpGained);
|
||||
|
||||
}
|
||||
|
||||
public void reset(int loginXp)
|
||||
{
|
||||
xpGained = 0;
|
||||
this.loginXp = loginXp;
|
||||
skillTimeStart = null;
|
||||
}
|
||||
|
||||
public void update(int currentXp)
|
||||
{
|
||||
xpGained = currentXp - loginXp;
|
||||
if (skillTimeStart == null)
|
||||
skillTimeStart = Instant.now();
|
||||
}
|
||||
|
||||
public Instant getSkillTimeStart()
|
||||
{
|
||||
return skillTimeStart;
|
||||
}
|
||||
|
||||
public int getXpGained()
|
||||
{
|
||||
return xpGained;
|
||||
}
|
||||
|
||||
public int getLoginXp()
|
||||
{
|
||||
return loginXp;
|
||||
}
|
||||
|
||||
public Skill getSkill()
|
||||
{
|
||||
return this.skill;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Cameron <moberg@tuta.io>
|
||||
* 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.xptracker;
|
||||
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Skill;
|
||||
import net.runelite.client.RuneLite;
|
||||
import net.runelite.client.ui.PluginPanel;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.*;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GridLayout;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.io.IOException;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class XPPanel extends PluginPanel
|
||||
{
|
||||
private static final Client client = RuneLite.getClient();
|
||||
private static final Logger logger = LoggerFactory.getLogger(XPPanel.class);
|
||||
private Map<Skill, JPanel> labelMap = new HashMap<>();
|
||||
private final XPTracker xpTracker;
|
||||
private JPanel statsPanel;
|
||||
|
||||
public XPPanel(RuneLite runelite, XPTracker xpTracker)
|
||||
{
|
||||
this.xpTracker = xpTracker;
|
||||
|
||||
setMinimumSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT));
|
||||
setPreferredSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT));
|
||||
setSize(PANEL_WIDTH, PANEL_HEIGHT);
|
||||
setVisible(true);
|
||||
statsPanel = new JPanel();
|
||||
statsPanel.setLayout(new GridLayout(24, 1));
|
||||
|
||||
try
|
||||
{
|
||||
for (Skill skill : Skill.values())
|
||||
{
|
||||
if (skill == Skill.OVERALL)
|
||||
break;
|
||||
|
||||
JLabel skillLabel = new JLabel();
|
||||
labelMap.put(skill, makeSkillPanel(skill, skillLabel));
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
logger.warn(null, e);
|
||||
}
|
||||
|
||||
JButton resetButton = new JButton("Reset All");
|
||||
resetButton.setPreferredSize(new Dimension(PANEL_WIDTH, 32));
|
||||
resetButton.addActionListener((ActionEvent e) ->
|
||||
runelite.getExecutor().execute(this::resetAllSkillXpHr));
|
||||
|
||||
statsPanel.add(resetButton);
|
||||
JScrollPane scroll = new JScrollPane(statsPanel);
|
||||
scroll.add(statsPanel);
|
||||
|
||||
add(statsPanel);
|
||||
}
|
||||
|
||||
private JButton makeSkillResetButton(Skill skill) throws IOException
|
||||
{
|
||||
ImageIcon resetIcon = new ImageIcon(ImageIO.read(getClass().getResourceAsStream("reset.png")));
|
||||
JButton resetButton = new JButton(resetIcon);
|
||||
resetButton.setPreferredSize(new Dimension(32, 32));
|
||||
resetButton.addActionListener(actionEvent -> resetSkillXpHr(skill));
|
||||
return resetButton;
|
||||
}
|
||||
|
||||
private JPanel makeSkillPanel(Skill skill, JLabel levelLabel) throws IOException
|
||||
{
|
||||
BorderLayout borderLayout = new BorderLayout();
|
||||
borderLayout.setHgap(12);
|
||||
JPanel iconLevel = new JPanel(borderLayout);
|
||||
iconLevel.setPreferredSize(new Dimension(PANEL_WIDTH, 32));
|
||||
|
||||
String skillIcon = "/skill_icons/" + skill.getName().toLowerCase() + ".png";
|
||||
logger.debug("Loading skill icon from {}", skillIcon);
|
||||
JLabel icon = new JLabel(new ImageIcon(ImageIO.read(XPPanel.class.getResourceAsStream(skillIcon))));
|
||||
iconLevel.add(icon, BorderLayout.LINE_START);
|
||||
|
||||
iconLevel.add(levelLabel, BorderLayout.CENTER);
|
||||
iconLevel.add(makeSkillResetButton(skill), BorderLayout.LINE_END);
|
||||
|
||||
return iconLevel;
|
||||
}
|
||||
|
||||
public void resetSkillXpHr(Skill skill)
|
||||
{
|
||||
int skillIdx = skill.ordinal();
|
||||
xpTracker.getXpInfos()[skillIdx].reset(client.getSkillExperience(skill));
|
||||
statsPanel.remove(labelMap.get(skill));
|
||||
statsPanel.revalidate();
|
||||
statsPanel.repaint();
|
||||
}
|
||||
|
||||
public void resetAllSkillXpHr()
|
||||
{
|
||||
for (SkillXPInfo skillInfo : xpTracker.getXpInfos())
|
||||
{
|
||||
if (skillInfo != null && skillInfo.getSkillTimeStart() != null)
|
||||
resetSkillXpHr(skillInfo.getSkill());
|
||||
}
|
||||
}
|
||||
|
||||
public void updateAllSkillXpHr()
|
||||
{
|
||||
for (SkillXPInfo skillInfo : xpTracker.getXpInfos())
|
||||
{
|
||||
if (skillInfo != null && skillInfo.getSkillTimeStart() != null &&
|
||||
skillInfo.getXpGained() != 0)
|
||||
updateSkillXpHr(skillInfo);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateSkillXpHr(SkillXPInfo skillXPInfo)
|
||||
{
|
||||
JPanel skillPanel = labelMap.get(skillXPInfo.getSkill());
|
||||
JLabel xpHr = (JLabel) skillPanel.getComponent(1);
|
||||
xpHr.setText(NumberFormat.getInstance().format(skillXPInfo.getXpHr()) + " xp/hr");
|
||||
|
||||
if (skillPanel.getParent() != statsPanel)
|
||||
{
|
||||
statsPanel.add(skillPanel);
|
||||
statsPanel.revalidate();
|
||||
statsPanel.repaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Cameron <moberg@tuta.io>
|
||||
* 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.xptracker;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.Skill;
|
||||
import net.runelite.client.RuneLite;
|
||||
import net.runelite.client.events.ExperienceChanged;
|
||||
import net.runelite.client.events.GameStateChanged;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.ui.ClientUI;
|
||||
import net.runelite.client.ui.NavigationButton;
|
||||
import net.runelite.client.util.RunnableExceptionLogger;
|
||||
import java.awt.Font;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class XPTracker extends Plugin
|
||||
{
|
||||
private static final int NUMBER_OF_SKILLS = Skill.values().length - 1; //ignore overall
|
||||
|
||||
private final RuneLite runeLite = RuneLite.getRunelite();
|
||||
private final ClientUI ui = runeLite.getGui();
|
||||
private final Client client = RuneLite.getClient();
|
||||
private ScheduledFuture<?> future;
|
||||
|
||||
private final NavigationButton navButton = new NavigationButton("XP Tracker");
|
||||
private final XPPanel xpPanel = new XPPanel(runeLite, this);
|
||||
private SkillXPInfo[] xpInfos = new SkillXPInfo[NUMBER_OF_SKILLS];
|
||||
|
||||
@Subscribe
|
||||
public void onGameStateChanged(GameStateChanged event)
|
||||
{
|
||||
if (event.getGameState() != GameState.LOGGED_IN)
|
||||
xpPanel.resetAllSkillXpHr();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onXpChanged(ExperienceChanged event)
|
||||
{
|
||||
Skill skill = event.getSkill();
|
||||
String currentUser = client.getLocalPlayer().getName();
|
||||
int skillIdx = skill.ordinal();
|
||||
|
||||
//To catch login ExperienceChanged event.
|
||||
if (xpInfos[skillIdx] != null)
|
||||
{
|
||||
xpInfos[skillIdx].update(client.getSkillExperience(skill));
|
||||
}
|
||||
else
|
||||
{
|
||||
xpInfos[skillIdx] = new SkillXPInfo(client.getSkillExperience(skill),
|
||||
skill);
|
||||
}
|
||||
}
|
||||
|
||||
private void setPluginPanel(ActionEvent e)
|
||||
{
|
||||
ui.expand(xpPanel);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
navButton.getButton().addActionListener(this::setPluginPanel);
|
||||
|
||||
navButton.getButton().setText("XP");
|
||||
ui.getNavigationPanel().addNavigation(navButton);
|
||||
|
||||
ScheduledExecutorService executor = RuneLite.getRunelite().getExecutor();
|
||||
future = executor.scheduleAtFixedRate(RunnableExceptionLogger.wrap(
|
||||
xpPanel::updateAllSkillXpHr), 0, 600, TimeUnit.MILLISECONDS);
|
||||
|
||||
Font font = Font.createFont(Font.TRUETYPE_FONT, getClass().getResourceAsStream("/runescape.ttf"));
|
||||
font = font.deriveFont(Font.BOLD, 16);
|
||||
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||
ge.registerFont(font);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
future.cancel(true);
|
||||
}
|
||||
|
||||
public SkillXPInfo[] getXpInfos()
|
||||
{
|
||||
return xpInfos;
|
||||
}
|
||||
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.1 KiB |
Reference in New Issue
Block a user