diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/crystalmathlabs/CrystalMathLabs.java b/runelite-client/src/main/java/net/runelite/client/plugins/crystalmathlabs/CrystalMathLabs.java index 8831a7df84..d4d8da33f4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/crystalmathlabs/CrystalMathLabs.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/crystalmathlabs/CrystalMathLabs.java @@ -32,7 +32,6 @@ import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; import net.runelite.api.GameState; import net.runelite.api.Player; -import net.runelite.api.Skill; import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GameTick; import net.runelite.client.eventbus.EventBus; @@ -59,7 +58,7 @@ public class CrystalMathLabs extends Plugin /** * Amount of EXP that must be gained for an update to be submitted. */ - private static final int XP_THRESHOLD = 1000; + private static final int XP_THRESHOLD = 10000; @Inject private Client client; @@ -74,6 +73,8 @@ public class CrystalMathLabs extends Plugin @Override protected void startUp() throws Exception { + fetchXp = true; + eventBus.subscribe(GameStateChanged.class, this, this::onGameStateChanged); eventBus.subscribe(GameTick.class, this, this::onGameTick); } @@ -92,7 +93,7 @@ public class CrystalMathLabs extends Plugin if (!Objects.equals(client.getUsername(), lastUsername)) { lastUsername = client.getUsername(); - lastXp = getTotalXp(); + fetchXp = true; } } else if (state == GameState.LOGIN_SCREEN) @@ -103,12 +104,13 @@ public class CrystalMathLabs extends Plugin return; } - long totalXp = getTotalXp(); + long totalXp = client.getOverallExperience(); // Don't submit update unless xp threshold is reached if (Math.abs(totalXp - lastXp) > XP_THRESHOLD) { log.debug("Submitting update for {}", local.getName()); sendUpdateRequest(local.getName()); + lastXp = totalXp; } } } @@ -117,21 +119,11 @@ public class CrystalMathLabs extends Plugin { if (fetchXp) { - lastXp = getTotalXp(); + lastXp = client.getOverallExperience(); fetchXp = false; } } - private long getTotalXp() - { - long total = 0; - for (Skill skill : Skill.values()) - { - total += client.getSkillExperience(skill); - } - return total; - } - private void sendUpdateRequest(String username) { String reformedUsername = username.replace(" ", "_"); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpStateSingle.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpStateSingle.java index 2b6c694ba1..af37a7ec3c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpStateSingle.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpStateSingle.java @@ -28,21 +28,20 @@ package net.runelite.client.plugins.xptracker; import java.util.HashMap; import java.util.Map; import lombok.Getter; -import lombok.RequiredArgsConstructor; import lombok.Setter; import lombok.extern.slf4j.Slf4j; import net.runelite.api.Experience; import net.runelite.api.Skill; @Slf4j -@RequiredArgsConstructor class XpStateSingle { private final Skill skill; private final Map actions = new HashMap<>(); @Getter - private final long startXp; + @Setter + private long startXp; @Getter private int xpGained = 0; @@ -54,13 +53,19 @@ class XpStateSingle private int startLevelExp = 0; private int endLevelExp = 0; + XpStateSingle(Skill skill, long startXp) + { + this.skill = skill; + this.startXp = startXp; + } + XpAction getXpAction(final XpActionType type) { actions.putIfAbsent(type, new XpAction()); return actions.get(type); } - private long getCurrentXp() + long getCurrentXp() { return startXp + xpGained; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java index e504738eab..9f33e7a888 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java @@ -124,8 +124,9 @@ public class XpTrackerPlugin extends Plugin private XpWorldType lastWorldType; private String lastUsername; private long lastTickMillis = 0; - private boolean fetchXp; + private boolean fetchXp; // fetch lastXp for the online xp tracker private long lastXp = 0; + private boolean initializeTracker; private final XpClient xpClient = new XpClient(); private final XpState xpState = new XpState(); @@ -171,6 +172,10 @@ public class XpTrackerPlugin extends Plugin .build(); clientToolbar.addNavigation(navButton); + + // Initialize the tracker & last xp if already logged in + fetchXp = true; + initializeTracker = true; } @Override @@ -215,8 +220,14 @@ public class XpTrackerPlugin extends Plugin fetchXp = true; lastWorldType = type; resetState(); + // Must be set from hitting the LOGGING_IN case below + assert initializeTracker; } } + else if (state == GameState.LOGGING_IN) + { + initializeTracker = true; + } else if (state == GameState.LOGIN_SCREEN) { Player local = client.getLocalPlayer(); @@ -236,6 +247,7 @@ public class XpTrackerPlugin extends Plugin if (Math.abs(totalXp - lastXp) > XP_THRESHOLD) { xpClient.update(username); + lastXp = totalXp; } } } @@ -354,6 +366,12 @@ public class XpTrackerPlugin extends Plugin final int startGoalXp = startGoal != null ? client.getVar(startGoal) : -1; final int endGoalXp = endGoal != null ? client.getVar(endGoal) : -1; + if (initializeTracker) + { + // This is the XP sync on login, wait until after login to begin counting + return; + } + if (this.hideMaxed && currentLevel >= Experience.MAX_REAL_LEVEL) { return; @@ -372,18 +390,9 @@ public class XpTrackerPlugin extends Plugin final XpUpdateResult updateResult = xpState.updateSkill(skill, currentXp, startGoalXp, endGoalXp); xpPanel.updateSkillExperience(updateResult == XpUpdateResult.UPDATED, xpPauseState.isPaused(skill), skill, xpState.getSkillSnapshot(skill)); - if (skill == Skill.CONSTRUCTION && updateResult == XpUpdateResult.INITIALIZED) - { - // Construction is the last skill initialized on login, now initialize the total experience - long overallXp = client.getOverallExperience(); - log.debug("Initializing XP tracker with {} overall exp", overallXp); - xpState.initializeSkill(Skill.OVERALL, overallXp); - } - else if (xpState.isInitialized(Skill.OVERALL)) - { - xpState.updateSkill(Skill.OVERALL, client.getOverallExperience(), -1, -1); - xpPanel.updateTotal(xpState.getTotalSnapshot()); - } + // Also update the total experience + xpState.updateSkill(Skill.OVERALL, client.getOverallExperience(), -1, -1); + xpPanel.updateTotal(xpState.getTotalSnapshot()); } private void onNpcDespawned(NpcDespawned event) @@ -407,12 +416,69 @@ public class XpTrackerPlugin extends Plugin private void onGameTick(GameTick event) { - rebuildSkills(); + if (initializeTracker) + { + initializeTracker = false; + + // Check for xp gained while logged out + for (Skill skill : Skill.values()) + { + if (skill == Skill.OVERALL || !xpState.isInitialized(skill)) + { + continue; + } + + XpStateSingle skillState = xpState.getSkill(skill); + final int currentXp = client.getSkillExperience(skill); + if (skillState.getCurrentXp() != currentXp) + { + if (currentXp < skillState.getCurrentXp()) + { + log.debug("Xp is going backwards! {} {} -> {}", skill, skillState.getCurrentXp(), currentXp); + resetState(); + break; + } + + log.debug("Skill xp for {} changed when offline: {} -> {}", skill, skillState.getCurrentXp(), currentXp); + // Offset start xp for offline gains + long diff = skillState.getCurrentXp() - currentXp; + skillState.setStartXp(skillState.getStartXp() + diff); + } + } + + // Initialize the tracker with the initial xp if not already initialized + for (Skill skill : Skill.values()) + { + if (skill == Skill.OVERALL) + { + continue; + } + + if (!xpState.isInitialized(skill)) + { + final int currentXp = client.getSkillExperience(skill); + // goal exps are not necessary for skill initialization + XpUpdateResult xpUpdateResult = xpState.updateSkill(skill, currentXp, -1, -1); + assert xpUpdateResult == XpUpdateResult.INITIALIZED; + } + } + + // Initialize the overall xp + if (!xpState.isInitialized(Skill.OVERALL)) + { + long overallXp = client.getOverallExperience(); + log.debug("Initializing XP tracker with {} overall exp", overallXp); + xpState.initializeSkill(Skill.OVERALL, overallXp); + } + } + if (fetchXp) { lastXp = client.getOverallExperience(); fetchXp = false; } + + rebuildSkills(); } private void onMenuEntryAdded(final MenuEntryAdded event)