Async user loading/saving :D

This commit is contained in:
Harry5573OP 2014-05-18 19:22:12 +01:00
parent ead716ef0d
commit 2f74d53dbe
7 changed files with 269 additions and 229 deletions

View File

@ -37,9 +37,8 @@ public interface DatabaseManager {
* Save a user to the database.
*
* @param profile The profile of the player to save
* @return true if successful, false on failure
*/
public boolean saveUser(PlayerProfile profile);
public void saveUser(PlayerProfile profile);
/**
* Retrieve leaderboard info.

View File

@ -206,7 +206,10 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
return worked;
}
public boolean saveUser(PlayerProfile profile) {
public void saveUser(final PlayerProfile profile) {
mcMMO.p.getServer().getScheduler().runTaskAsynchronously(mcMMO.p, new Runnable() {
@Override
public void run() {
String playerName = profile.getPlayerName();
BufferedReader in = null;
@ -225,8 +228,7 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
// Read the line in and copy it to the output it's not the player we want to edit
if (!line.split(":")[0].equalsIgnoreCase(playerName)) {
writer.append(line).append("\r\n");
}
else {
} else {
// Otherwise write the new player information
writer.append(playerName).append(":");
writer.append(profile.getSkillLevel(SkillType.MINING)).append(":");
@ -277,18 +279,18 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
// Write the new file
out = new FileWriter(usersFilePath);
out.write(writer.toString());
return true;
}
catch (Exception e) {
return;
} catch (Exception e) {
e.printStackTrace();
return false;
}
finally {
return;
} finally {
tryClose(in);
tryClose(out);
}
}
}
});
}
public List<PlayerStat> readLeaderboard(SkillType skill, int pageNumber, int statsPerPage) {
updateLeaderboards();

View File

@ -115,25 +115,27 @@ public final class SQLDatabaseManager implements DatabaseManager {
return success;
}
public boolean saveUser(PlayerProfile profile) {
public void saveUser(final PlayerProfile profile) {
if (!checkConnected()) {
return false;
return;
}
mcMMO.p.getServer().getScheduler().runTaskAsynchronously(mcMMO.p, new Runnable() {
@Override
public void run() {
int userId = readId(profile.getPlayerName());
if (userId == -1) {
newUser(profile.getPlayerName());
userId = readId(profile.getPlayerName());
if (userId == -1) {
return false;
return;
}
}
boolean success = true;
MobHealthbarType mobHealthbarType = profile.getMobHealthbarType();
success &= saveLogin(userId, ((int) (System.currentTimeMillis() / Misc.TIME_CONVERSION_FACTOR)));
success &= saveHuds(userId, (mobHealthbarType == null ? Config.getInstance().getMobHealthbarDefault().toString() : mobHealthbarType.toString()));
success &= saveLongs(
saveLogin(userId, ((int) (System.currentTimeMillis() / Misc.TIME_CONVERSION_FACTOR)));
saveHuds(userId, (mobHealthbarType == null ? Config.getInstance().getMobHealthbarDefault().toString() : mobHealthbarType.toString()));
saveLongs(
"UPDATE " + tablePrefix + "cooldowns SET "
+ " mining = ?, woodcutting = ?, unarmed = ?"
+ ", herbalism = ?, excavation = ?, swords = ?"
@ -147,7 +149,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
profile.getAbilityDATS(AbilityType.SERRATED_STRIKES),
profile.getAbilityDATS(AbilityType.SKULL_SPLITTER),
profile.getAbilityDATS(AbilityType.BLAST_MINING));
success &= saveIntegers(
saveIntegers(
"UPDATE " + tablePrefix + "skills SET "
+ " taming = ?, mining = ?, repair = ?, woodcutting = ?"
+ ", unarmed = ?, herbalism = ?, excavation = ?"
@ -167,7 +169,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
profile.getSkillLevel(SkillType.FISHING),
profile.getSkillLevel(SkillType.ALCHEMY),
userId);
success &= saveIntegers(
saveIntegers(
"UPDATE " + tablePrefix + "experience SET "
+ " taming = ?, mining = ?, repair = ?, woodcutting = ?"
+ ", unarmed = ?, herbalism = ?, excavation = ?"
@ -187,7 +189,9 @@ public final class SQLDatabaseManager implements DatabaseManager {
profile.getSkillXpLevel(SkillType.FISHING),
profile.getSkillXpLevel(SkillType.ALCHEMY),
userId);
return success;
return;
}
});
}
public List<PlayerStat> readLeaderboard(SkillType skill, int pageNumber, int statsPerPage) {
@ -351,7 +355,9 @@ public final class SQLDatabaseManager implements DatabaseManager {
return loadPlayerProfile(playerName, create, true);
}
private PlayerProfile loadPlayerProfile(String playerName, boolean create, boolean retry) {
if (!checkConnected()) {
return new PlayerProfile(playerName, false); // return fake profile if not connected
}
@ -458,15 +464,13 @@ public final class SQLDatabaseManager implements DatabaseManager {
resultSet.next();
destination.saveUser(loadFromResult(playerName, resultSet));
resultSet.close();
}
catch (SQLException e) {
} catch (SQLException e) {
// Ignore
}
convertedUsers++;
Misc.printProgress(convertedUsers, progressInterval, startMillis);
}
}
catch (SQLException e) {
} catch (SQLException e) {
printErrors(e);
}
finally {

View File

@ -1,19 +1,5 @@
package com.gmail.nossr50.datatypes.player;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.scheduler.BukkitRunnable;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.config.AdvancedConfig;
import com.gmail.nossr50.config.Config;
import com.gmail.nossr50.config.experience.ExperienceConfig;
@ -26,6 +12,7 @@ import com.gmail.nossr50.datatypes.skills.SkillType;
import com.gmail.nossr50.datatypes.skills.ToolType;
import com.gmail.nossr50.datatypes.skills.XPGainReason;
import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.party.PartyManager;
import com.gmail.nossr50.party.ShareHandler;
import com.gmail.nossr50.runnables.skills.AbilityDisableTask;
@ -53,14 +40,27 @@ import com.gmail.nossr50.util.StringUtils;
import com.gmail.nossr50.util.skills.ParticleEffectUtils;
import com.gmail.nossr50.util.skills.PerksUtils;
import com.gmail.nossr50.util.skills.SkillUtils;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import org.apache.commons.lang.Validate;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.scheduler.BukkitRunnable;
public class McMMOPlayer {
private Player player;
private PlayerProfile profile;
private PlayerProfile playerProfile;
private final Map<SkillType, SkillManager> skillManagers = new HashMap<SkillType, SkillManager>();
private final ConcurrentHashMap<SkillType, SkillManager> skillManagers = new ConcurrentHashMap<SkillType, SkillManager>();
private Party party;
private Party invite;
@ -91,12 +91,26 @@ public class McMMOPlayer {
private boolean isUsingUnarmed;
private final FixedMetadataValue playerMetadata;
public interface Callback {
public void done(String playerName, PlayerProfile profile);
}
public Callback pendingCallback;
public McMMOPlayer(Player player) {
String playerName = player.getName();
final String playerName = player.getName();
this.player = player;
playerMetadata = new FixedMetadataValue(mcMMO.p, playerName);
profile = mcMMO.getDatabaseManager().loadPlayerProfile(playerName, true);
//Fake the profile
playerProfile = new PlayerProfile(playerName, false);
pendingCallback = new Callback() {
public void done(String playerName, PlayerProfile p) {
playerProfile = p;
party = PartyManager.getPlayerParty(playerName);
ptpRecord = new PartyTeleportRecord();
@ -107,12 +121,26 @@ public class McMMOPlayer {
*/
try {
for (SkillType skillType : SkillType.values()) {
skillManagers.put(skillType, skillType.getManagerClass().getConstructor(McMMOPlayer.class).newInstance(this));
skillManagers.put(skillType, skillType.getManagerClass().getConstructor(McMMOPlayer.class).newInstance(McMMOPlayer.this));
}
}
catch (Exception e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
mcMMO.p.getPluginLoader().disablePlugin(mcMMO.p);
e.printStackTrace();
} catch (IllegalArgumentException e) {
mcMMO.p.getPluginLoader().disablePlugin(mcMMO.p);
e.printStackTrace();
} catch (InstantiationException e) {
mcMMO.p.getPluginLoader().disablePlugin(mcMMO.p);
e.printStackTrace();
} catch (NoSuchMethodException e) {
mcMMO.p.getPluginLoader().disablePlugin(mcMMO.p);
e.printStackTrace();
} catch (SecurityException e) {
mcMMO.p.getPluginLoader().disablePlugin(mcMMO.p);
e.printStackTrace();
} catch (InvocationTargetException e) {
mcMMO.p.getPluginLoader().disablePlugin(mcMMO.p);
e.printStackTrace();
}
for (AbilityType abilityType : AbilityType.values()) {
@ -124,11 +152,20 @@ public class McMMOPlayer {
toolMode.put(toolType, false);
}
if (!profile.isLoaded()) {
mcMMO.p.getLogger().warning("Unable to load the PlayerProfile for " + playerName + ". Will retry over the next several seconds.");
if (!playerProfile.isLoaded()) {
mcMMO.p.getLogger().log(Level.WARNING, "Unable to load the PlayerProfile for {0}. Will retry over the next several seconds.", playerName);
new RetryProfileLoadingTask().runTaskTimerAsynchronously(mcMMO.p, 11L, 31L);
}
}
};
mcMMO.p.getServer().getScheduler().runTaskAsynchronously(mcMMO.p, new Runnable() {
@Override
public void run() {
pendingCallback.done(playerName, mcMMO.getDatabaseManager().loadPlayerProfile(playerName, true));
}
});
}
private class RetryProfileLoadingTask extends BukkitRunnable {
private static final int MAX_TRIES = 5;
@ -184,7 +221,7 @@ public class McMMOPlayer {
// No database access permitted
@Override
public void run() {
McMMOPlayer.this.profile = profile;
McMMOPlayer.this.playerProfile = profile;
}
}
@ -548,7 +585,7 @@ public class McMMOPlayer {
break;
}
xpRemoved += profile.levelUp(skillType);
xpRemoved += playerProfile.levelUp(skillType);
levelsGained++;
}
@ -572,7 +609,7 @@ public class McMMOPlayer {
}
public PlayerProfile getProfile() {
return profile;
return playerProfile;
}
/*
@ -798,7 +835,7 @@ public class McMMOPlayer {
SkillUtils.sendSkillMessage(player, ability.getAbilityPlayer(player));
// Enable the ability
profile.setAbilityDATS(ability, System.currentTimeMillis() + (ticks * Misc.TIME_CONVERSION_FACTOR));
playerProfile.setAbilityDATS(ability, System.currentTimeMillis() + (ticks * Misc.TIME_CONVERSION_FACTOR));
setAbilityMode(ability, true);
if (ability == AbilityType.SUPER_BREAKER || ability == AbilityType.GIGA_DRILL_BREAKER) {
@ -863,7 +900,7 @@ public class McMMOPlayer {
* @return the number of seconds remaining before the cooldown expires
*/
public int calculateTimeRemaining(AbilityType ability) {
long deactivatedTimestamp = profile.getAbilityDATS(ability) * Misc.TIME_CONVERSION_FACTOR;
long deactivatedTimestamp = playerProfile.getAbilityDATS(ability) * Misc.TIME_CONVERSION_FACTOR;
return (int) (((deactivatedTimestamp + (PerksUtils.handleCooldownPerks(player, ability.getCooldown()) * Misc.TIME_CONVERSION_FACTOR)) - System.currentTimeMillis()) / Misc.TIME_CONVERSION_FACTOR);
}
@ -875,47 +912,47 @@ public class McMMOPlayer {
* These functions are wrapped from PlayerProfile so that we don't always have to store it alongside the McMMOPlayer object.
*/
public int getSkillLevel(SkillType skill) {
return profile.getSkillLevel(skill);
return playerProfile.getSkillLevel(skill);
}
public float getSkillXpLevelRaw(SkillType skill) {
return profile.getSkillXpLevelRaw(skill);
return playerProfile.getSkillXpLevelRaw(skill);
}
public int getSkillXpLevel(SkillType skill) {
return profile.getSkillXpLevel(skill);
return playerProfile.getSkillXpLevel(skill);
}
public void setSkillXpLevel(SkillType skill, float xpLevel) {
profile.setSkillXpLevel(skill, xpLevel);
playerProfile.setSkillXpLevel(skill, xpLevel);
}
public int getXpToLevel(SkillType skill) {
return profile.getXpToLevel(skill);
return playerProfile.getXpToLevel(skill);
}
public void removeXp(SkillType skill, int xp) {
profile.removeXp(skill, xp);
playerProfile.removeXp(skill, xp);
}
public void modifySkill(SkillType skill, int level) {
profile.modifySkill(skill, level);
playerProfile.modifySkill(skill, level);
}
public void addLevels(SkillType skill, int levels) {
profile.addLevels(skill, levels);
playerProfile.addLevels(skill, levels);
}
public void addXp(SkillType skill, float xp) {
profile.addXp(skill, xp);
playerProfile.addXp(skill, xp);
}
public void setAbilityDATS(AbilityType ability, long DATS) {
profile.setAbilityDATS(ability, DATS);
playerProfile.setAbilityDATS(ability, DATS);
}
public void resetCooldowns() {
profile.resetCooldowns();
playerProfile.resetCooldowns();
}
public FixedMetadataValue getPlayerMetadata() {

View File

@ -65,11 +65,8 @@ public class PlayerProfile {
return;
}
changed = !mcMMO.getDatabaseManager().saveUser(new PlayerProfile(playerName, ImmutableMap.copyOf(skills), ImmutableMap.copyOf(skillsXp), ImmutableMap.copyOf(abilityDATS), mobHealthbarType));
if (changed) {
mcMMO.p.getLogger().warning("PlayerProfile for " + playerName + " failed to save");
}
mcMMO.getDatabaseManager().saveUser(new PlayerProfile(playerName, ImmutableMap.copyOf(skills), ImmutableMap.copyOf(skillsXp), ImmutableMap.copyOf(abilityDATS), mobHealthbarType));
changed = false;
}
public String getPlayerName() {

View File

@ -344,9 +344,9 @@ public class PlayerListener implements Listener {
/**
* Monitor PlayerQuitEvents.
* <p>
* These events are monitored for the purpose of resetting player
* variables and other garbage collection tasks that must take place when
* a player exits the server.
* These events are monitored for the purpose of resetting player variables
* and other garbage collection tasks that must take place when a player
* exits the server.
*
* @param event The event to monitor
*/
@ -407,7 +407,7 @@ public class PlayerListener implements Listener {
}
}
/**
/**e
* Monitor PlayerRespawnEvents.
* <p>
* These events are monitored for the purpose of setting the

View File

@ -1,16 +1,17 @@
package com.gmail.nossr50.skills.alchemy;
import com.gmail.nossr50.config.AdvancedConfig;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.runnables.skills.AlchemyBrewTask;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.bukkit.Location;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.config.AdvancedConfig;
import com.gmail.nossr50.runnables.skills.AlchemyBrewTask;
public final class Alchemy {
public enum Tier {
EIGHT(8),
@ -53,7 +54,7 @@ public final class Alchemy {
public static double catalysisMinSpeed = AdvancedConfig.getInstance().getCatalysisMinSpeed();
public static double catalysisMaxSpeed = AdvancedConfig.getInstance().getCatalysisMaxSpeed();
public static Map<Location, AlchemyBrewTask> brewingStandMap = new HashMap<Location, AlchemyBrewTask>();
public static ConcurrentMap<Location, AlchemyBrewTask> brewingStandMap = new ConcurrentHashMap<Location, AlchemyBrewTask>();
private Alchemy() {}