mirror of
https://github.com/mcMMO-Dev/mcMMO.git
synced 2024-11-24 14:16:45 +01:00
Move save operation handling to its own class
This commit is contained in:
parent
d33c214266
commit
9b856f456c
@ -1,6 +1,5 @@
|
||||
package com.gmail.nossr50.commands.experience;
|
||||
|
||||
import com.gmail.nossr50.datatypes.experience.XPGainReason;
|
||||
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
|
||||
import com.gmail.nossr50.datatypes.player.PlayerProfile;
|
||||
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
|
||||
@ -28,7 +27,7 @@ public class AddlevelsCommand extends ExperienceCommand {
|
||||
profile.addLevels(skill, value);
|
||||
|
||||
if (player == null) {
|
||||
profile.scheduleAsyncSave();
|
||||
UserManager.getPlayerSaveHandler().scheduleAsyncSave(profile.getPlayerData());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@ public class AddxpCommand extends ExperienceCommand {
|
||||
}
|
||||
else {
|
||||
profile.addXp(skill, value);
|
||||
profile.scheduleAsyncSave();
|
||||
UserManager.getPlayerSaveHandler().scheduleAsyncSave(profile.getPlayerData());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ public class MmoeditCommand extends ExperienceCommand {
|
||||
profile.modifySkill(skill, value);
|
||||
|
||||
if (player == null) {
|
||||
profile.scheduleAsyncSave();
|
||||
UserManager.getPlayerSaveHandler().scheduleAsyncSave(profile.getPlayerData());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -129,7 +129,7 @@ public class SkillresetCommand implements TabExecutor {
|
||||
profile.modifySkill(skill, 0);
|
||||
|
||||
if (player == null) {
|
||||
profile.scheduleAsyncSave();
|
||||
UserManager.getPlayerSaveHandler().scheduleAsyncSave(profile.getPlayerData());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ import com.gmail.nossr50.api.exceptions.InvalidSkillException;
|
||||
import com.gmail.nossr50.config.Config;
|
||||
import com.gmail.nossr50.datatypes.database.DatabaseType;
|
||||
import com.gmail.nossr50.datatypes.database.PlayerStat;
|
||||
import com.gmail.nossr50.datatypes.player.MMODataSnapshot;
|
||||
import com.gmail.nossr50.datatypes.player.PlayerData;
|
||||
import com.gmail.nossr50.datatypes.player.PlayerProfile;
|
||||
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
|
||||
@ -55,6 +56,13 @@ public interface DatabaseManager {
|
||||
*/
|
||||
boolean saveUser(@NotNull PlayerData playerData);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param dataSnapshot target data snapshot
|
||||
* @return true if successful, false on failure
|
||||
*/
|
||||
boolean saveUser(@NotNull MMODataSnapshot dataSnapshot);
|
||||
|
||||
/**
|
||||
* Retrieve leaderboard info.
|
||||
* Will never be null but it may be empty
|
||||
|
@ -258,9 +258,12 @@ public final class FlatFileDatabaseManager implements DatabaseManager {
|
||||
//Not used in FlatFile
|
||||
}
|
||||
|
||||
|
||||
public boolean saveUser(@NotNull PlayerData playerData) {
|
||||
MMODataSnapshot mmoDataSnapshot = new MMODataSnapshot(playerData); //Clone data into Immutable data
|
||||
MMODataSnapshot mmoDataSnapshot = new MMODataSnapshot(playerData);
|
||||
return saveUser(mmoDataSnapshot); //Clone data into Immutable data
|
||||
}
|
||||
|
||||
public boolean saveUser(@NotNull MMODataSnapshot mmoDataSnapshot) {
|
||||
String playerName = mmoDataSnapshot.getPlayerName();
|
||||
UUID uuid = mmoDataSnapshot.getPlayerUUID();
|
||||
|
||||
|
@ -10,6 +10,9 @@ import org.jetbrains.annotations.NotNull;
|
||||
import java.util.UUID;
|
||||
|
||||
public class MMODataSnapshot {
|
||||
/* Save Attempts */
|
||||
private int saveAttempts = 0;
|
||||
|
||||
/* Player Stuff */
|
||||
private final @NotNull String playerName;
|
||||
private final @NotNull UUID playerUUID;
|
||||
@ -109,4 +112,17 @@ public class MMODataSnapshot {
|
||||
public boolean isLeaderBoardExcluded() {
|
||||
return leaderBoardExclusion;
|
||||
}
|
||||
|
||||
public int getSaveAttempts() {
|
||||
return saveAttempts;
|
||||
}
|
||||
|
||||
public void setSaveAttempts(int saveAttempts) {
|
||||
this.saveAttempts = saveAttempts;
|
||||
}
|
||||
|
||||
public void incrementSaveAttempts() {
|
||||
this.saveAttempts += 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
package com.gmail.nossr50.runnables;
|
||||
|
||||
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
|
||||
import com.gmail.nossr50.mcMMO;
|
||||
import com.gmail.nossr50.util.player.UserManager;
|
||||
import com.neetgames.mcmmo.player.OnlineMMOPlayer;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
@ -12,8 +14,8 @@ public class SaveTimerTask extends BukkitRunnable {
|
||||
int count = 1;
|
||||
|
||||
//TODO: write a more efficient bulk save
|
||||
for (OnlineMMOPlayer mmoPlayer : UserManager.getPlayers()) {
|
||||
UserManager.saveUserWithDelay(mmoPlayer.getPersistentPlayerData(), false, count);
|
||||
for (McMMOPlayer mmoPlayer : UserManager.getPlayers()) {
|
||||
UserManager.getPlayerSaveHandler().scheduleAsyncSaveDelay(mmoPlayer.getPlayerData());
|
||||
count++;
|
||||
}
|
||||
|
||||
|
@ -41,9 +41,8 @@ public class FormulaConversionTask extends BukkitRunnable {
|
||||
|
||||
editValues(profile);
|
||||
// Since this is a temporary profile, we save it here.
|
||||
profile.scheduleAsyncSave();
|
||||
}
|
||||
else {
|
||||
UserManager.getPlayerSaveHandler().scheduleAsyncSave(profile.getPlayerData());
|
||||
} else {
|
||||
profile = mcMMOPlayer.getProfile();
|
||||
editValues(profile);
|
||||
}
|
||||
|
@ -0,0 +1,81 @@
|
||||
package com.gmail.nossr50.util.player;
|
||||
|
||||
import com.gmail.nossr50.datatypes.player.MMODataSnapshot;
|
||||
import com.gmail.nossr50.datatypes.player.PlayerData;
|
||||
import com.gmail.nossr50.mcMMO;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
//TODO: Low priority - Track pending Async saves to avoid data loss during server shutdown
|
||||
//TODO: T&C Javadocs
|
||||
public class PlayerSaveHandler {
|
||||
|
||||
private void save(@NotNull MMODataSnapshot mmoDataSnapshot, boolean useSync) {
|
||||
boolean saveSuccessful = mcMMO.getDatabaseManager().saveUser(mmoDataSnapshot);
|
||||
|
||||
//Check for failure to save
|
||||
if (!saveSuccessful) {
|
||||
String playerName = mmoDataSnapshot.getPlayerName();
|
||||
String uuidStr = mmoDataSnapshot.getPlayerUUID().toString();
|
||||
mcMMO.p.getLogger().severe("PlayerProfile saving failed for player name: " + playerName + " UUID: " + uuidStr);
|
||||
|
||||
if(mmoDataSnapshot.getSaveAttempts() > 0) {
|
||||
mcMMO.p.getLogger().severe("Attempted to save profile for player "+playerName
|
||||
+ " resulted in failure. " + mmoDataSnapshot.getSaveAttempts() + " have been made so far.");
|
||||
}
|
||||
|
||||
if(mmoDataSnapshot.getSaveAttempts() < 10) {
|
||||
mmoDataSnapshot.incrementSaveAttempts();
|
||||
|
||||
//Back out of async saving if we detect a server shutdown, this is not always going to be caught
|
||||
if(mcMMO.isServerShutdownExecuted() || useSync)
|
||||
scheduleSyncSave(mmoDataSnapshot); //Execute sync saves immediately
|
||||
else
|
||||
scheduleAsyncSave(mmoDataSnapshot);
|
||||
|
||||
} else {
|
||||
mcMMO.p.getLogger().severe("mcMMO has failed to save the profile for "
|
||||
+ playerName + " numerous times." +
|
||||
" mcMMO will now stop attempting to save this profile." +
|
||||
" Check your console for errors and inspect your DB for issues.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void save(@NotNull PlayerData playerData, boolean useSync) {
|
||||
//TODO: We no longer check if a profile is loaded or not as it should never be unloaded if a save operation is being called, need to double check this to be true
|
||||
if(!playerData.isDirtyProfile()) {
|
||||
return; //Don't save data that hasn't changed
|
||||
}
|
||||
|
||||
MMODataSnapshot mmoDataSnapshot = new MMODataSnapshot(playerData);
|
||||
save(mmoDataSnapshot, useSync);
|
||||
}
|
||||
|
||||
public void scheduleAsyncSave(@NotNull PlayerData playerData) {
|
||||
MMODataSnapshot mmoDataSnapshot = new MMODataSnapshot(playerData);
|
||||
scheduleAsyncSave(mmoDataSnapshot);
|
||||
}
|
||||
|
||||
public void scheduleAsyncSaveDelay(@NotNull PlayerData playerData) {
|
||||
MMODataSnapshot mmoDataSnapshot = new MMODataSnapshot(playerData);
|
||||
scheduleAsyncSaveDelay(mmoDataSnapshot);
|
||||
}
|
||||
|
||||
public void scheduleSyncSave(@NotNull PlayerData playerData) {
|
||||
MMODataSnapshot mmoDataSnapshot = new MMODataSnapshot(playerData);
|
||||
scheduleSyncSave(mmoDataSnapshot);
|
||||
}
|
||||
|
||||
private void scheduleAsyncSave(@NotNull MMODataSnapshot mmoDataSnapshot) {
|
||||
Bukkit.getScheduler().runTaskAsynchronously(mcMMO.p, () -> save(mmoDataSnapshot, false));
|
||||
}
|
||||
|
||||
private void scheduleAsyncSaveDelay(@NotNull MMODataSnapshot mmoDataSnapshot) {
|
||||
Bukkit.getScheduler().runTaskLaterAsynchronously(mcMMO.p, () -> save(mmoDataSnapshot, false), 20L);
|
||||
}
|
||||
|
||||
private void scheduleSyncSave(@NotNull MMODataSnapshot mmoDataSnapshot) {
|
||||
Bukkit.getScheduler().runTask(mcMMO.p, () -> save(mmoDataSnapshot, true));
|
||||
}
|
||||
}
|
@ -19,6 +19,7 @@ import java.util.HashSet;
|
||||
public final class UserManager {
|
||||
|
||||
private static HashSet<McMMOPlayer> playerDataSet; //Used to track players for sync saves on shutdown
|
||||
private @NotNull static final PlayerSaveHandler playerSaveHandler = new PlayerSaveHandler();
|
||||
|
||||
private UserManager() {}
|
||||
|
||||
@ -69,7 +70,7 @@ public final class UserManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Save all users ON THIS THREAD.
|
||||
* Save all users on main thread
|
||||
*/
|
||||
public static void saveAll() {
|
||||
if(playerDataSet == null)
|
||||
@ -79,15 +80,12 @@ public final class UserManager {
|
||||
|
||||
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());
|
||||
for (McMMOPlayer mmoPlayer : trackedSyncData) {
|
||||
try {
|
||||
mcMMO.p.getLogger().info("Saving data for player: "+mmoPlayer.getPlayerName());
|
||||
getPlayerSaveHandler().save(mmoPlayer.getPlayerData(), true);
|
||||
} catch (Exception e) {
|
||||
mcMMO.p.getLogger().severe("Could not save mcMMO player data for player: " + mmoPlayer.getPlayerName());
|
||||
}
|
||||
}
|
||||
|
||||
@ -120,9 +118,9 @@ public final class UserManager {
|
||||
mmoPlayer.getTamingManager().cleanupAllSummons();
|
||||
|
||||
if (syncSave) {
|
||||
getProfile().save(true); //TODO: T&C Wire this up, see master branch com.gmail.nossr50.datatypes.player.PlayerProfile#save
|
||||
getPlayerSaveHandler().save(mmoPlayer.getPlayerData(), true); //TODO: T&C Wire this up, see master branch com.gmail.nossr50.datatypes.player.PlayerProfile#save
|
||||
} else {
|
||||
getProfile().scheduleAsyncSave(); //TODO: T&C Wire this up, see master branch com.gmail.nossr50.datatypes.player.PlayerProfile#scheduleAsyncSave
|
||||
getPlayerSaveHandler().scheduleAsyncSave(mmoPlayer.getPlayerData()); //TODO: T&C Wire this up, see master branch com.gmail.nossr50.datatypes.player.PlayerProfile#scheduleAsyncSave
|
||||
}
|
||||
|
||||
UserManager.remove(targetPlayer);
|
||||
@ -190,4 +188,9 @@ public final class UserManager {
|
||||
public static boolean hasPlayerDataKey(Entity entity) {
|
||||
return entity != null && entity.hasMetadata(mcMMO.playerDataKey);
|
||||
}
|
||||
|
||||
public static @NotNull PlayerSaveHandler getPlayerSaveHandler() {
|
||||
return playerSaveHandler;
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user