2
0
Эх сурвалжийг харах

Use a DelayQueue to manage rolling diminished returns

riking 11 жил өмнө
parent
commit
332860b9ce

+ 9 - 36
src/main/java/com/gmail/nossr50/datatypes/player/PlayerProfile.java

@@ -1,12 +1,10 @@
 package com.gmail.nossr50.datatypes.player;
 
 import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
 import java.util.Map;
-import java.util.Map.Entry;
 import java.util.Set;
 import java.util.UUID;
+import java.util.concurrent.DelayQueue;
 
 import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.config.Config;
@@ -36,8 +34,8 @@ public class PlayerProfile {
     private final Map<SkillType, Float>     skillsXp   = new HashMap<SkillType, Float>();     // Skill & XP
     private final Map<AbilityType, Integer> abilityDATS = new HashMap<AbilityType, Integer>(); // Ability & Cooldown
 
-    // Store previous XP gains for diminished returns
-    private HashMap<SkillType, LinkedList<SkillXpGain>> gainedSkillsXp = new HashMap<SkillType, LinkedList<SkillXpGain>>();
+    // Store previous XP gains for deminished returns
+    private DelayQueue<SkillXpGain> gainedSkillsXp = new DelayQueue<SkillXpGain>();
     private HashMap<SkillType, Float> rollingSkillsXp = new HashMap<SkillType, Float>();
 
     @Deprecated
@@ -304,15 +302,8 @@ public class PlayerProfile {
      * @param skillType Skill being used
      * @param xp Experience amount to add
      */
-    public void registeredXpGain(SkillType skillType, float xp) {
-        LinkedList<SkillXpGain> gains = gainedSkillsXp.get(skillType);
-
-        if (gains == null) {
-            gains = new LinkedList<SkillXpGain>(); // Maybe add an initial capacity?
-        }
-        gains.addLast(new SkillXpGain(System.currentTimeMillis(), xp));
-
-        gainedSkillsXp.put(skillType, gains);
+    public void registerXpGain(SkillType skillType, float xp) {
+        gainedSkillsXp.add(new SkillXpGain(skillType, xp));
         rollingSkillsXp.put(skillType, getRegisteredXpGain(skillType) + xp);
     }
 
@@ -322,28 +313,10 @@ public class PlayerProfile {
      *
      * @param age Age in milliseconds that gains older than should be removed
      */
-    public void removeXpGainsOlderThan(long age) {
-        long now = System.currentTimeMillis();
-
-        Iterator<Entry<SkillType, LinkedList<SkillXpGain>>> iterator = gainedSkillsXp.entrySet().iterator();
-        while (iterator.hasNext()) {
-            Entry<SkillType, LinkedList<SkillXpGain>> skillGains = iterator.next();
-
-            float xp = 0;
-            // 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<SkillXpGain> gainsIterator = skillGains.getValue().iterator();
-            while (gainsIterator.hasNext()) {
-                SkillXpGain gain = gainsIterator.next();
-
-                if (now - gain.getTime() >= age) {
-                    gainsIterator.remove();
-                    xp += gain.getXp();
-                }
-                else {
-                    break;
-                }
-            }
-            rollingSkillsXp.put(skillGains.getKey(), rollingSkillsXp.get(skillGains.getKey()) - xp);
+    public void purgeExpiredXpGains() {
+        SkillXpGain gain = null;
+        while ((gain = gainedSkillsXp.poll()) != null) {
+            rollingSkillsXp.put(gain.getSkill(), getRegisteredXpGain(gain.getSkill()) - gain.getXp());
         }
     }
 

+ 41 - 6
src/main/java/com/gmail/nossr50/datatypes/skills/SkillXpGain.java

@@ -1,19 +1,54 @@
 package com.gmail.nossr50.datatypes.skills;
 
-public class SkillXpGain {
-    private final long time;
+import java.util.concurrent.Delayed;
+import java.util.concurrent.TimeUnit;
+
+import com.gmail.nossr50.config.experience.ExperienceConfig;
+
+public class SkillXpGain implements Delayed {
+    private final long expiryTime;
     private final float xp;
+    private final SkillType type;
 
-    public SkillXpGain(long time, float xp) {
-        this.time = time;
+    public SkillXpGain(SkillType type, float xp) {
+        this.expiryTime = System.currentTimeMillis() + getDuration();
         this.xp = xp;
+        this.type = type;
     }
 
-    public long getTime() {
-        return time;
+    public SkillType getSkill() {
+        return type;
     }
 
     public float getXp() {
         return xp;
     }
+
+    private static long getDuration() {
+        return TimeUnit.MINUTES.toMillis(ExperienceConfig.getInstance().getDiminishedReturnsTimeInterval());
+    }
+
+    public int compareTo(SkillXpGain other) {
+        if (this.expiryTime < other.expiryTime) {
+            return -1;
+        }
+        else if (this.expiryTime > other.expiryTime) {
+            return 1;
+        }
+        return 0;
+    }
+
+    @Override
+    public int compareTo(Delayed other) {
+        if (other instanceof SkillXpGain) {
+            // Use more efficient method if possible (private fields)
+            return this.compareTo((SkillXpGain) other);
+        }
+        return (int) (getDelay(TimeUnit.MILLISECONDS) - other.getDelay(TimeUnit.MILLISECONDS));
+    }
+
+    @Override
+    public long getDelay(TimeUnit arg0) {
+        return arg0.convert(expiryTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
+    }
 }

+ 1 - 1
src/main/java/com/gmail/nossr50/mcMMO.java

@@ -497,7 +497,7 @@ public class mcMMO extends JavaPlugin {
 
         // Clear the registered XP data so players can earn XP again
         if (ExperienceConfig.getInstance().getDiminishedReturnsThreshold() > 0) {
-            new ClearRegisteredXPGainTask().runTaskTimer(this, 60 * 20, 60 * 20);
+            new ClearRegisteredXPGainTask().runTaskTimer(this, 60, 60);
         }
     }
 

+ 1 - 2
src/main/java/com/gmail/nossr50/runnables/player/ClearRegisteredXPGainTask.java

@@ -2,7 +2,6 @@ package com.gmail.nossr50.runnables.player;
 
 import org.bukkit.scheduler.BukkitRunnable;
 
-import com.gmail.nossr50.config.experience.ExperienceConfig;
 import com.gmail.nossr50.datatypes.player.McMMOPlayer;
 import com.gmail.nossr50.util.player.UserManager;
 
@@ -10,7 +9,7 @@ public class ClearRegisteredXPGainTask extends BukkitRunnable {
     @Override
     public void run() {
         for (McMMOPlayer mcMMOPlayer : UserManager.getPlayers()) {
-            mcMMOPlayer.getProfile().removeXpGainsOlderThan(ExperienceConfig.getInstance().getDiminishedReturnsTimeInterval() * 60 * 1000);
+            mcMMOPlayer.getProfile().purgeExpiredXpGains();
         }
     }
 }

+ 1 - 1
src/main/java/com/gmail/nossr50/util/EventUtils.java

@@ -161,7 +161,7 @@ public class EventUtils {
 
         if (!isCancelled) {
             UserManager.getPlayer(player).addXp(skill, event.getRawXpGained());
-            UserManager.getPlayer(player).getProfile().registeredXpGain(skill, event.getRawXpGained());
+            UserManager.getPlayer(player).getProfile().registerXpGain(skill, event.getRawXpGained());
         }
 
         return !isCancelled;