Ver Fonte

Attempt clean recovery from an unloaded PlayerProfile

This change should cause McMMOPlayer to create a graceful recovery when the database is temporarily unavailable.
When a McMMOPlayer is constructed and recieves an unloaded PlayerProfile, it schedules a task to re-attempt profile retrieval. This task can run for a maximum of 5 seconds, after which a second warning is printed indicating that it has given up (and a message given to the user).
riking há 11 anos atrás
pai
commit
14ae1a69c4

+ 65 - 0
src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java

@@ -4,10 +4,13 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
 
+import org.bukkit.Bukkit;
 import org.bukkit.GameMode;
 import org.bukkit.Location;
 import org.bukkit.Material;
+import org.bukkit.Server;
 import org.bukkit.entity.Player;
+import org.bukkit.scheduler.BukkitRunnable;
 
 import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.config.Config;
@@ -123,6 +126,68 @@ public class McMMOPlayer {
             toolMode.put(toolType, false);
             toolATS.put(toolType, 0);
         }
+
+        if (!profile.isLoaded()) {
+            mcMMO.p.getLogger().warning("Unable to load the PlayerProfile for " + playerName + ". Will retry over the next several seconds.");
+            new RetryProfileLoadingTask().runTaskTimerAsynchronously(mcMMO.p, 11L, 31L);
+        }
+    }
+
+    private class RetryProfileLoadingTask extends BukkitRunnable {
+        private static final int MAX_TRIES = 5;
+        private final String playerName = McMMOPlayer.this.player.getName();
+        private int attempt = 0;
+
+        // WARNING: ASYNC TASK
+        // DO NOT MODIFY THE McMMOPLAYER FROM THIS CODE
+        @Override
+        public void run() {
+            // Quit if they logged out
+            if (!player.isOnline()) {
+                mcMMO.p.getLogger().info("Aborting profile loading recovery for " + playerName + " - player logged out");
+                this.cancel();
+                return;
+            }
+
+            // Send the message that we're doing the recovery
+            if (attempt == 0) {
+                player.sendMessage(LocaleLoader.getString("Recovery.Notice"));
+            }
+
+            // Increment attempt counter and try
+            attempt++;
+            PlayerProfile profile = mcMMO.getDatabaseManager().loadPlayerProfile(playerName, true);
+            // If successful, schedule the apply
+            if (profile.isLoaded()) {
+                new ApplySuccessfulProfile(profile).runTask(mcMMO.p);
+                player.sendMessage(LocaleLoader.getString("Recovery.Success"));
+                this.cancel();
+                return;
+            }
+
+            // If we've failed five times, give up
+            if (attempt >= MAX_TRIES) {
+                mcMMO.p.getLogger().severe("Giving up on attempting to load the PlayerProfile for " + playerName);
+                Bukkit.broadcast(LocaleLoader.getString("Recovery.AdminFailureNotice", playerName), Server.BROADCAST_CHANNEL_ADMINISTRATIVE);
+                player.sendMessage(LocaleLoader.getString("Recovery.Failure").split("\n"));
+                this.cancel();
+                return;
+            }
+        }
+    }
+
+    private class ApplySuccessfulProfile extends BukkitRunnable {
+        private final PlayerProfile profile;
+        private ApplySuccessfulProfile(PlayerProfile profile) {
+            this.profile = profile;
+        }
+
+        // Synchronized task
+        // No database access permitted
+        @Override
+        public void run() {
+            McMMOPlayer.this.profile = profile;
+        }
     }
 
     public AcrobaticsManager getAcrobaticsManager() {

+ 6 - 0
src/main/resources/locale/locale_en_US.properties

@@ -772,3 +772,9 @@ Scoreboard.Misc.Level=Level
 Scoreboard.Misc.CurrentXP=Current XP
 Scoreboard.Misc.RemainingXP=Remaining XP
 Scoreboard.Misc.Overall=Overall
+
+#DATABASE RECOVERY
+Recovery.Notice=[[RED]]Notice: mcMMO was [[DARK_RED]]unable to load your data.[[RED]] Retrying 5 times...
+Recovery.Success=[[GREEN]]Success! Your mcMMO data was loaded.
+Recovery.Failure=[[RED]]mcMMO still cannot load your data. You may want to [[AQUA]]contact the server owner.\n[[YELLOW]]You can still play on the server, but you will have [[BOLD]]no mcMMO levels[[YELLOW]] and any XP you get [[BOLD]]will not be saved[[YELLOW]].
+Recovery.AdminFailureNotice=[[DARK_RED]][A][[RED]] mcMMO was unable to load the player data for [[YELLOW]]{0}[[RED]]. [[LIGHT_PURPLE]]Please inspect your database setup.