From 324a68949ae480296638afc8a13c0cc631e42918 Mon Sep 17 00:00:00 2001 From: NuclearW Date: Sat, 4 May 2013 03:36:35 -0400 Subject: [PATCH] Rolling xp diminishing returns This adds on top of the diminishing returns system a mechanic such that gains will expire the configured number of minutes after they occured, rather than all being reset at once. This prevents someone from not getting diminishing returns on the xp gain they recieved just before the reset would have occured. Obligatory explanatory graphs: http://i.imgur.com/uSzicIR.png --- .../datatypes/player/PlayerProfile.java | 58 ++++++++++++++----- .../nossr50/datatypes/skills/SkillXpGain.java | 19 ++++++ .../gmail/nossr50/listeners/SelfListener.java | 2 +- src/main/java/com/gmail/nossr50/mcMMO.java | 6 +- .../player/ClearRegisteredXPGainTask.java | 9 +-- 5 files changed, 67 insertions(+), 27 deletions(-) create mode 100644 src/main/java/com/gmail/nossr50/datatypes/skills/SkillXpGain.java 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); } } }