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

Merge branch 'master' of github.com:mcMMO-Dev/mcMMO into configurable

nossr50 6 жил өмнө
parent
commit
fc2077ffdb

+ 5 - 0
Changelog.txt

@@ -161,6 +161,11 @@ Version 2.2.0
     Added API method to grab the level cap of a skill by its PrimarySkillType ENUM definition
     Added API method to check if a skill was being level capped
     Added 'UndefinedSkillBehaviour' for trying to use a method that has no behaviour defined for the provided skill
+Version 2.1.69
+    Fixed a few places where mcMMO would not save player data immediately which may cause players to lose a few minutes of progress
+
+    A big thanks to Sleepyflea for helping test this patch and report this bug.
+
 Version 2.1.68
     Updated Japanese locale (thanks Snake)
     Fixed a bug where consuming food in the off hand did not trigger the Diet abilities

+ 1 - 1
src/main/java/com/gmail/nossr50/api/ExperienceAPI.java

@@ -1073,7 +1073,7 @@ public final class ExperienceAPI {
         PlayerProfile profile = getOfflineProfile(playerUniqueId);
 
         profile.addXp(skill, XP);
-        profile.save();
+        profile.save(true);
     }
 
     @Deprecated

+ 7 - 2
src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java

@@ -90,9 +90,10 @@ public class McMMOPlayer {
     private Location teleportCommence;
     private boolean isUsingUnarmed;
     private HashMap<PrimarySkillType, Double> personalXPModifiers;
+    private String playerName;
 
     public McMMOPlayer(Player player, PlayerProfile profile) {
-        String playerName = player.getName();
+        this.playerName = player.getName();
         UUID uuid = player.getUniqueId();
 
         this.player = player;
@@ -159,6 +160,10 @@ public class McMMOPlayer {
         return personalXPModifiers.get(primarySkillType);
     }
 
+    public String getPlayerName() {
+        return playerName;
+    }
+
     /*public void hideXpBar(PrimarySkillType primarySkillType)
     {
         experienceBarManager.hideExperienceBar(primarySkillType);
@@ -1005,7 +1010,7 @@ public class McMMOPlayer {
         BleedTimerTask.bleedOut(thisPlayer);
 
         if (syncSave) {
-            getProfile().save();
+            getProfile().save(true);
         } else {
             getProfile().scheduleAsyncSave();
         }

+ 40 - 19
src/main/java/com/gmail/nossr50/datatypes/player/PlayerProfile.java

@@ -85,14 +85,23 @@ public class PlayerProfile {
     }
 
     public void scheduleAsyncSave() {
-        new PlayerProfileSaveTask(this).runTaskAsynchronously(mcMMO.p);
+        new PlayerProfileSaveTask(this, false).runTaskAsynchronously(mcMMO.p);
+    }
+
+    public void scheduleSyncSave() {
+        new PlayerProfileSaveTask(this, true).runTask(mcMMO.p);
     }
 
     public void scheduleAsyncSaveDelay() {
-        new PlayerProfileSaveTask(this).runTaskLaterAsynchronously(mcMMO.p, 20);
+        new PlayerProfileSaveTask(this, false).runTaskLaterAsynchronously(mcMMO.p, 20);
     }
 
-    public void save() {
+    @Deprecated
+    public void scheduleSyncSaveDelay() {
+        new PlayerProfileSaveTask(this, true).runTaskLater(mcMMO.p, 20);
+    }
+
+    public void save(boolean useSync) {
         if (!changed || !loaded) {
             saveAttempts = 0;
             return;
@@ -112,7 +121,12 @@ public class PlayerProfile {
 
             if (saveAttempts < 10) {
                 saveAttempts++;
-                scheduleAsyncSaveDelay();
+
+                if(useSync)
+                    scheduleSyncSave(); //Execute sync saves immediately
+                else
+                    scheduleAsyncSaveDelay();
+
                 return;
             } else {
                 mcMMO.p.getLogger().severe("mcMMO has failed to save the profile for "
@@ -121,9 +135,9 @@ public class PlayerProfile {
                         " Check your console for errors and inspect your DB for issues.");
             }
 
+        } else {
+            saveAttempts = 0;
         }
-
-        saveAttempts = 0;
     }
 
     public String getPlayerName() {
@@ -135,7 +149,7 @@ public class PlayerProfile {
     }
 
     public void setUniqueId(UUID uuid) {
-        changed = true;
+        markProfileDirty();
 
         this.uuid = uuid;
     }
@@ -153,17 +167,24 @@ public class PlayerProfile {
     }
 
     public void setMobHealthbarType(MobHealthbarType mobHealthbarType) {
-        changed = true;
+        markProfileDirty();
 
         this.mobHealthbarType = mobHealthbarType;
     }
 
+    /**
+     * Marks the profile as "dirty" which flags a profile to be saved in the next save operation
+     */
+    public void markProfileDirty() {
+        changed = true;
+    }
+
     public int getScoreboardTipsShown() {
         return scoreboardTipsShown;
     }
 
     public void setScoreboardTipsShown(int scoreboardTipsShown) {
-        changed = true;
+        markProfileDirty();
 
         this.scoreboardTipsShown = scoreboardTipsShown;
     }
@@ -181,12 +202,12 @@ public class PlayerProfile {
     }
 
     protected void setChimaeraWingDATS(int DATS) {
-        changed = true;
+        markProfileDirty();
         uniquePlayerData.put(UniqueDataType.CHIMAERA_WING_DATS, DATS);
     }
 
     public void setUniqueData(UniqueDataType uniqueDataType, int newData) {
-        changed = true;
+        markProfileDirty();
         uniquePlayerData.put(uniqueDataType, newData);
     }
 
@@ -211,7 +232,7 @@ public class PlayerProfile {
      * @param DATS    the DATS of the ability
      */
     protected void setAbilityDATS(SuperAbilityType ability, long DATS) {
-        changed = true;
+        markProfileDirty();
 
         abilityDATS.put(ability, (int) (DATS * .001D));
     }
@@ -220,7 +241,7 @@ public class PlayerProfile {
      * Reset all ability cooldowns.
      */
     protected void resetCooldowns() {
-        changed = true;
+        markProfileDirty();
 
         for (SuperAbilityType ability : abilityDATS.keySet()) {
             abilityDATS.put(ability, 0);
@@ -248,7 +269,7 @@ public class PlayerProfile {
             return;
         }
 
-        changed = true;
+        markProfileDirty();
 
         skillsXp.put(skill, xpLevel);
     }
@@ -256,7 +277,7 @@ public class PlayerProfile {
     protected double levelUp(PrimarySkillType skill) {
         double xpRemoved = getXpToLevel(skill);
 
-        changed = true;
+        markProfileDirty();
 
         skills.put(skill, skills.get(skill) + 1);
         skillsXp.put(skill, skillsXp.get(skill) - xpRemoved);
@@ -275,7 +296,7 @@ public class PlayerProfile {
             return;
         }
 
-        changed = true;
+        markProfileDirty();
 
         skillsXp.put(skill, skillsXp.get(skill) - xp);
     }
@@ -285,7 +306,7 @@ public class PlayerProfile {
             return;
         }
 
-        changed = true;
+        markProfileDirty();
 
         skillsXp.put(skill, skillsXp.get(skill) - xp);
     }
@@ -301,7 +322,7 @@ public class PlayerProfile {
             return;
         }
 
-        changed = true;
+        markProfileDirty();
 
         //Don't allow levels to be negative
         if (level < 0)
@@ -328,7 +349,7 @@ public class PlayerProfile {
      * @param xp    Number of experience to add
      */
     public void addXp(PrimarySkillType skill, double xp) {
-        changed = true;
+        markProfileDirty();
 
         if (skill.isChildSkill()) {
             Set<PrimarySkillType> parentSkills = FamilyTree.getParents(skill);

+ 3 - 1
src/main/java/com/gmail/nossr50/listeners/PlayerListener.java

@@ -492,7 +492,9 @@ public class PlayerListener implements Listener {
         }
 
         McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
-        mcMMOPlayer.logout(false);
+        //There's an issue with using Async saves on player quit
+        //Basically there are conditions in which an async task does not execute fast enough to save the data if the server shutdown shortly after this task was scheduled
+        mcMMOPlayer.logout(true);
     }
 
     /**

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

@@ -196,7 +196,6 @@ public class mcMMO extends JavaPlugin {
     @Override
     public void onDisable() {
         try {
-//            Alchemy.finishAllBrews();   // Finish all partially complete AlchemyBrewTasks to prevent vanilla brewing continuation on restart
             UserManager.saveAll();      // Make sure to save player information if the server shuts down
             UserManager.clearAll();
             PartyManager.saveParties(); // Save our parties

+ 1 - 1
src/main/java/com/gmail/nossr50/runnables/SaveTimerTask.java

@@ -14,7 +14,7 @@ public class SaveTimerTask extends BukkitRunnable {
         int count = 1;
 
         for (McMMOPlayer mcMMOPlayer : UserManager.getPlayers()) {
-            new PlayerProfileSaveTask(mcMMOPlayer.getProfile()).runTaskLaterAsynchronously(mcMMO.p, count);
+            new PlayerProfileSaveTask(mcMMOPlayer.getProfile(), false).runTaskLaterAsynchronously(mcMMO.p, count);
             count++;
         }
 

+ 4 - 2
src/main/java/com/gmail/nossr50/runnables/player/PlayerProfileSaveTask.java

@@ -5,13 +5,15 @@ import org.bukkit.scheduler.BukkitRunnable;
 
 public class PlayerProfileSaveTask extends BukkitRunnable {
     private PlayerProfile playerProfile;
+    private boolean isSync;
 
-    public PlayerProfileSaveTask(PlayerProfile playerProfile) {
+    public PlayerProfileSaveTask(PlayerProfile playerProfile, boolean isSync) {
         this.playerProfile = playerProfile;
+        this.isSync = isSync;
     }
 
     @Override
     public void run() {
-        playerProfile.save();
+        playerProfile.save(isSync);
     }
 }

+ 35 - 8
src/main/java/com/gmail/nossr50/util/player/UserManager.java

@@ -11,11 +11,14 @@ import org.bukkit.metadata.FixedMetadataValue;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashSet;
 
 public final class UserManager {
 
     private UserManager() {
     }
+    private static HashSet<McMMOPlayer> playerDataSet; //Used to track players for sync saves on shutdown
+
 
     /**
      * Track a new user.
@@ -24,6 +27,16 @@ public final class UserManager {
      */
     public static void track(McMMOPlayer mcMMOPlayer) {
         mcMMOPlayer.getPlayer().setMetadata(MetadataConstants.PLAYER_DATA_METAKEY, new FixedMetadataValue(mcMMO.p, mcMMOPlayer));
+
+        if(playerDataSet == null)
+            playerDataSet = new HashSet<>();
+
+        playerDataSet.add(mcMMOPlayer); //for sync saves on shutdown
+    }
+
+    public static void cleanupPlayer(McMMOPlayer mcMMOPlayer) {
+        if(playerDataSet != null && playerDataSet.contains(mcMMOPlayer))
+            playerDataSet.remove(mcMMOPlayer);
     }
 
     /**
@@ -32,7 +45,11 @@ public final class UserManager {
      * @param player The Player object
      */
     public static void remove(Player player) {
+        McMMOPlayer mcMMOPlayer = getPlayer(player);
         player.removeMetadata(MetadataConstants.PLAYER_DATA_METAKEY, mcMMO.p);
+
+        if(playerDataSet != null && playerDataSet.contains(mcMMOPlayer))
+            playerDataSet.remove(mcMMOPlayer); //Clear sync save tracking
     }
 
     /**
@@ -42,22 +59,32 @@ public final class UserManager {
         for (Player player : mcMMO.p.getServer().getOnlinePlayers()) {
             remove(player);
         }
+
+        if(playerDataSet != null)
+            playerDataSet.clear(); //Clear sync save tracking
     }
 
     /**
      * Save all users ON THIS THREAD.
      */
     public static void saveAll() {
-        ImmutableList<Player> onlinePlayers = ImmutableList.copyOf(mcMMO.p.getServer().getOnlinePlayers());
-        mcMMO.p.debug("Saving mcMMOPlayers... (" + onlinePlayers.size() + ")");
-
-        for (Player player : onlinePlayers) {
-            try {
-                getPlayer(player).getProfile().save();
-            } catch (Exception e) {
-                mcMMO.p.getLogger().warning("Could not save mcMMO player data for player: " + player.getName());
+        ImmutableList<McMMOPlayer> trackedSyncData = ImmutableList.copyOf(playerDataSet);
+
+        mcMMO.p.getLogger().info("Saving mcMMOPlayers... (" + trackedSyncData.size() + ")");
+
+        for (McMMOPlayer playerData : trackedSyncData) {
+            try
+            {
+                mcMMO.p.getLogger().info("Saving data for player: "+playerData.getPlayerName());
+                playerData.getProfile().save(true);
+            }
+            catch (Exception e)
+            {
+                mcMMO.p.getLogger().warning("Could not save mcMMO player data for player: " + playerData.getPlayerName());
             }
         }
+
+        mcMMO.p.getLogger().info("Finished save operation for "+trackedSyncData.size()+" players!");
     }
 
     public static Collection<McMMOPlayer> getPlayers() {