diff --git a/src/main/java/com/gmail/nossr50/datatypes/player/PlayerProfile.java b/src/main/java/com/gmail/nossr50/datatypes/player/PlayerProfile.java index 2835b341c..8ab1f1a49 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/player/PlayerProfile.java +++ b/src/main/java/com/gmail/nossr50/datatypes/player/PlayerProfile.java @@ -6,6 +6,8 @@ import java.io.FileReader; import java.io.FileWriter; import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; import java.util.Map; import java.util.Set; @@ -18,6 +20,7 @@ import com.gmail.nossr50.database.SQLDatabaseManager; import com.gmail.nossr50.datatypes.MobHealthbarType; import com.gmail.nossr50.datatypes.skills.AbilityType; import com.gmail.nossr50.datatypes.skills.SkillType; +import com.gmail.nossr50.datatypes.skills.SkillXpGain; import com.gmail.nossr50.datatypes.spout.huds.HudType; import com.gmail.nossr50.datatypes.spout.huds.McMMOHud; import com.gmail.nossr50.skills.child.FamilyTree; @@ -40,7 +43,8 @@ public class PlayerProfile { private final Map skillsDATS = new HashMap(); // Ability & Cooldown // Store previous XP gains for deminished returns - private Map gainedSkillsXp = new HashMap(); + private HashMap> gainedSkillsXp = new HashMap>(); + private HashMap rollingSkillsXp = new HashMap(); public PlayerProfile(String playerName, boolean addNew) { this.playerName = playerName; @@ -258,27 +262,16 @@ public class PlayerProfile { public float getRegisteredXpGain(SkillType skillType) { float xp; - if (gainedSkillsXp.get(skillType) == null) { + if (rollingSkillsXp.get(skillType) == null) { xp = 0F; } else { - xp = gainedSkillsXp.get(skillType); + xp = rollingSkillsXp.get(skillType); } return xp; } - /** - * Set registered experience gains - * This is used for diminished XP returns - * - * @param skillType Skill being used - * @param xp Experience amount to set - */ - public void setRegisteredXpGain(SkillType skillType, float xp) { - gainedSkillsXp.put(skillType, xp); - } - /** * Register an experience gain * This is used for diminished XP returns @@ -287,7 +280,42 @@ public class PlayerProfile { * @param xp Experience amount to add */ public void registeredXpGain(SkillType skillType, float xp) { - gainedSkillsXp.put(skillType, getRegisteredXpGain(skillType) + xp); + LinkedList gains = gainedSkillsXp.get(skillType); + + if(gains == null) { + gains = new LinkedList(); // Maybe add an initial capacity? + } + gains.addLast(new SkillXpGain(System.currentTimeMillis(), xp)); + + gainedSkillsXp.put(skillType, gains); + rollingSkillsXp.put(skillType, getRegisteredXpGain(skillType) + xp); + } + + /** + * Remove experience gains older than a given time + * This is used for diminished XP returns + * + * @param age Age in milliseconds that gains older than should be removed + */ + public void removeXpGainsOlderThan(long age) { + long now = System.currentTimeMillis(); + + Iterator> iterator = gainedSkillsXp.values().iterator(); + while(iterator.hasNext()) { + LinkedList skillGains = iterator.next(); + + // Because we are using a LinkedList and addLast ordering is guaranteed, so we loop through and remove things that are too old, and stop immediately once we find a young'n + Iterator gainsIterator = skillGains.iterator(); + while(gainsIterator.hasNext()) { + SkillXpGain gain = gainsIterator.next(); + + if(now - gain.getTime() >= age) { + gainsIterator.remove(); + } else { + break; + } + } + } } /** diff --git a/src/main/java/com/gmail/nossr50/datatypes/skills/SkillXpGain.java b/src/main/java/com/gmail/nossr50/datatypes/skills/SkillXpGain.java new file mode 100644 index 000000000..37bd51739 --- /dev/null +++ b/src/main/java/com/gmail/nossr50/datatypes/skills/SkillXpGain.java @@ -0,0 +1,19 @@ +package com.gmail.nossr50.datatypes.skills; + +public class SkillXpGain { + private final long time; + private final float xp; + + public SkillXpGain(long time, float xp) { + this.time = time; + this.xp = xp; + } + + public long getTime() { + return time; + } + + public float getXp() { + return xp; + } +} diff --git a/src/main/java/com/gmail/nossr50/listeners/SelfListener.java b/src/main/java/com/gmail/nossr50/listeners/SelfListener.java index 2b9bdfd14..c99ba7e8a 100644 --- a/src/main/java/com/gmail/nossr50/listeners/SelfListener.java +++ b/src/main/java/com/gmail/nossr50/listeners/SelfListener.java @@ -64,4 +64,4 @@ public class SelfListener implements Listener { mcMMOPlayer.getProfile().registeredXpGain(skillType, event.getRawXpGained()); } -} \ No newline at end of file +} diff --git a/src/main/java/com/gmail/nossr50/mcMMO.java b/src/main/java/com/gmail/nossr50/mcMMO.java index 002d7dd13..f90db6374 100644 --- a/src/main/java/com/gmail/nossr50/mcMMO.java +++ b/src/main/java/com/gmail/nossr50/mcMMO.java @@ -368,10 +368,8 @@ public class mcMMO extends JavaPlugin { } // Clear the registered XP data so players can earn XP again - long clearRegisteredXPGainInterval = Config.getInstance().getExperienceDeminishedReturnsTimeInterval() * 60 * 20; - - if (kickIntervalTicks > 0 && Config.getInstance().getExperienceDeminishedReturnsThreshold() > 0) { - new ClearRegisteredXPGainTask().runTaskTimer(this, clearRegisteredXPGainInterval, clearRegisteredXPGainInterval); + if (Config.getInstance().getExperienceDeminishedReturnsThreshold() > 0) { + new ClearRegisteredXPGainTask().runTaskTimer(this, 60 * 20, 60 * 20); } } } diff --git a/src/main/java/com/gmail/nossr50/runnables/player/ClearRegisteredXPGainTask.java b/src/main/java/com/gmail/nossr50/runnables/player/ClearRegisteredXPGainTask.java index 5c3c433c2..d93a8b48a 100644 --- a/src/main/java/com/gmail/nossr50/runnables/player/ClearRegisteredXPGainTask.java +++ b/src/main/java/com/gmail/nossr50/runnables/player/ClearRegisteredXPGainTask.java @@ -2,20 +2,15 @@ package com.gmail.nossr50.runnables.player; import org.bukkit.scheduler.BukkitRunnable; +import com.gmail.nossr50.config.Config; import com.gmail.nossr50.datatypes.player.McMMOPlayer; -import com.gmail.nossr50.datatypes.skills.SkillType; import com.gmail.nossr50.util.player.UserManager; public class ClearRegisteredXPGainTask extends BukkitRunnable { @Override public void run() { for (McMMOPlayer mcMMOPlayer : UserManager.getPlayers().values()) { - for (SkillType skillType : SkillType.values()) { - if (skillType.isChildSkill()) { - continue; - } - mcMMOPlayer.getProfile().setRegisteredXpGain(skillType, 0F); - } + mcMMOPlayer.getProfile().removeXpGainsOlderThan(Config.getInstance().getExperienceDeminishedReturnsTimeInterval() * 60 * 1000); } } }