diff --git a/src/main/java/com/gmail/nossr50/database/FlatFileDatabaseManager.java b/src/main/java/com/gmail/nossr50/database/FlatFileDatabaseManager.java index f0d08f3f8..b60108495 100644 --- a/src/main/java/com/gmail/nossr50/database/FlatFileDatabaseManager.java +++ b/src/main/java/com/gmail/nossr50/database/FlatFileDatabaseManager.java @@ -1338,7 +1338,7 @@ public final class FlatFileDatabaseManager implements DatabaseManager { //Build Data return playerDataBuilder.build(); - } catch (NullArgumentException e) { + } catch (Exception e) { mcMMO.p.getLogger().severe("Critical failure when trying to construct persistent player data!"); e.printStackTrace(); return null; diff --git a/src/main/java/com/gmail/nossr50/datatypes/experience/OnlineExperienceProcessor.java b/src/main/java/com/gmail/nossr50/datatypes/experience/OnlineExperienceProcessor.java index b5dc30adf..48ca776d2 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/experience/OnlineExperienceProcessor.java +++ b/src/main/java/com/gmail/nossr50/datatypes/experience/OnlineExperienceProcessor.java @@ -20,7 +20,6 @@ import com.neetgames.mcmmo.experience.ExperienceProcessor; import com.neetgames.mcmmo.experience.XPGainReason; import com.neetgames.mcmmo.experience.XPGainSource; import com.neetgames.mcmmo.party.Party; -import com.neetgames.mcmmo.player.MMOPlayer; import org.bukkit.GameMode; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; @@ -43,7 +42,7 @@ public class OnlineExperienceProcessor implements ExperienceProcessor { public int getPowerLevel() { int powerLevel = 0; - Map primarySkillTypeLevelMap = mmoPlayerData.getDirtySkillLevelMap().unwrapMap(); + Map primarySkillTypeLevelMap = mmoPlayerData.getSkillLevelMap(); for (PrimarySkillType primarySkillType : primarySkillTypeLevelMap.keySet()) { powerLevel += primarySkillTypeLevelMap.get(primarySkillType); diff --git a/src/main/java/com/gmail/nossr50/datatypes/player/MMODataBuilder.java b/src/main/java/com/gmail/nossr50/datatypes/player/MMODataBuilder.java index ad64ea1d7..7b03d5bc5 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/player/MMODataBuilder.java +++ b/src/main/java/com/gmail/nossr50/datatypes/player/MMODataBuilder.java @@ -5,6 +5,7 @@ import com.gmail.nossr50.datatypes.skills.SuperAbilityType; import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.util.experience.MMOExperienceBarManager; import com.neetgames.mcmmo.UniqueDataType; +import com.neetgames.mcmmo.exceptions.UnexpectedValueException; import com.neetgames.mcmmo.skill.SkillBossBarState; import org.apache.commons.lang.NullArgumentException; import org.bukkit.OfflinePlayer; @@ -59,7 +60,7 @@ public class MMODataBuilder { return new PlayerData(playerUUID, playerName); } - public PlayerData build() throws NullArgumentException { + public PlayerData build() throws UnexpectedValueException, NullPointerException, NullArgumentException { if(playerUUID == null) throw new NullArgumentException("playerUUID"); diff --git a/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java b/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java index 8f0331d7b..c16c4cbce 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java +++ b/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java @@ -47,6 +47,7 @@ import java.util.Map; import java.util.UUID; //TODO: Update javadocs +//TODO: T&C Look over IDE inspection warnings, things have changed public class McMMOPlayer extends PlayerProfile implements OnlineMMOPlayer, Identified { private final @NotNull Player player; private final @NotNull Identity identity; @@ -140,8 +141,8 @@ public class McMMOPlayer extends PlayerProfile implements OnlineMMOPlayer, Ident * If in the future someone wants to remove this, don't forget to also remove what is in the PrimarySkillType enum. - bm01 */ try { - for (CoreRootSkill coreRootSkill : PrimarySkillType.getCoreRootSkills()) { - skillManagers.put(coreRootSkill, coreRootSkill.getSkillManagerClass().getConstructor(McMMOPlayer.class).newInstance(this)); + for (PrimarySkillType primarySkillType : PrimarySkillType.getCoreRootSkills()) { + skillManagers.put(primarySkillType, coreRootSkill.getSkillManagerClass().getConstructor(McMMOPlayer.class).newInstance(this)); } } catch (Exception e) { diff --git a/src/main/java/com/gmail/nossr50/datatypes/player/PlayerData.java b/src/main/java/com/gmail/nossr50/datatypes/player/PlayerData.java index 8399f1e63..65b26d4bb 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/player/PlayerData.java +++ b/src/main/java/com/gmail/nossr50/datatypes/player/PlayerData.java @@ -7,16 +7,11 @@ import com.gmail.nossr50.datatypes.validation.NonNullRule; import com.gmail.nossr50.datatypes.validation.PositiveIntegerRule; import com.gmail.nossr50.datatypes.validation.Validator; import com.gmail.nossr50.util.experience.MMOExperienceBarManager; +import com.google.common.base.Objects; import com.google.common.collect.ImmutableMap; import com.neetgames.mcmmo.UniqueDataType; import com.neetgames.mcmmo.exceptions.UnexpectedValueException; import com.neetgames.mcmmo.skill.SkillBossBarState; -import com.neetgames.neetlib.dirtydata.DirtyData; -import com.neetgames.neetlib.dirtydata.DirtyMap; -import com.neetgames.neetlib.mutableprimitives.MutableBoolean; -import com.neetgames.neetlib.mutableprimitives.MutableInteger; -import com.neetgames.neetlib.mutableprimitives.MutableLong; -import com.neetgames.neetlib.mutableprimitives.MutableString; import org.apache.commons.lang.NullArgumentException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -28,28 +23,28 @@ import java.util.UUID; public class PlayerData { - private final @NotNull MutableBoolean dirtyFlag; //Dirty values in this class will change this flag as needed - /* Player Stuff */ - private final @NotNull DirtyData playerName; - private final @Nullable UUID playerUUID; + private @NotNull String playerName; + private final @Nullable UUID playerUUID; //TODO: T&C See if this is ever actually null, and if it is maybe we shouldn't allow it to be /* Records */ - private final DirtyData lastLogin; + private long lastLogin; /* Skill Data */ - private final @NotNull DirtyMap skillLevelValues; - private final @NotNull DirtyMap skillExperienceValues; - private final @NotNull DirtyMap abilityDeactivationTimestamps; // Ability & Cooldown - private final @NotNull DirtyMap uniquePlayerData; //Misc data that doesn't fit into other categories (chimaera wing, etc..) - private final @NotNull DirtyMap barStateMap; + private final @NotNull Map skillLevelValues; + private final @NotNull Map skillExperienceValues; + private final @NotNull Map abilityDeactivationTimestamps; // Ability & Cooldown + private final @NotNull Map uniquePlayerData; //Misc data that doesn't fit into other categories (chimaera wing, etc..) + private final @NotNull Map barStateMap; /* Special Flags */ - private final @NotNull DirtyData partyChatSpying; - private final @NotNull DirtyData leaderBoardExclusion; + private boolean partyChatSpying; + private boolean leaderBoardExclusion; /* Scoreboards */ - private final @NotNull DirtyData scoreboardTipsShown; + private int scoreboardTipsShown; + + private int lastUpdateHash; /** * Create new persistent player data for a player @@ -57,22 +52,20 @@ public class PlayerData { * * @param playerUUID target player's UUID * @param playerName target player's name - * @throws NullArgumentException thrown when never null arguments are null */ - public PlayerData(@Nullable UUID playerUUID, @NotNull String playerName) throws NullArgumentException { + public PlayerData(@Nullable UUID playerUUID, @NotNull String playerName) { /* * New Data */ - this.dirtyFlag = new MutableBoolean(false); //Set this one first this.playerUUID = playerUUID; - this.playerName = new DirtyData<>(new MutableString(playerName), dirtyFlag); + this.playerName = playerName; - this.skillLevelValues = new DirtyMap<>(new HashMap<>(), dirtyFlag); - this.skillExperienceValues = new DirtyMap<>(new HashMap<>(), dirtyFlag); - this.abilityDeactivationTimestamps = new DirtyMap<>(new HashMap<>(), dirtyFlag); - this.uniquePlayerData = new DirtyMap<>(new EnumMap<>(UniqueDataType.class), dirtyFlag); + this.skillLevelValues = new HashMap<>(); + this.skillExperienceValues = new HashMap<>(); + this.abilityDeactivationTimestamps = new HashMap<>(); + this.uniquePlayerData = new EnumMap<>(UniqueDataType.class); - this.scoreboardTipsShown = new DirtyData<>(new MutableInteger(0), dirtyFlag); + this.scoreboardTipsShown = 0; for(SuperAbilityType superSkill : SuperAbilityType.values()) { abilityDeactivationTimestamps.put(superSkill, 0); @@ -92,11 +85,13 @@ public class PlayerData { //Unique Player Data this.uniquePlayerData.put(UniqueDataType.CHIMAERA_WING_DATS, 0); - this.partyChatSpying = new DirtyData<>(new MutableBoolean(false), dirtyFlag); + this.partyChatSpying = false; - this.barStateMap = new DirtyMap<>(MMOExperienceBarManager.generateDefaultBarStateMap(), dirtyFlag); - this.lastLogin = new DirtyData<>(new MutableLong(0), dirtyFlag); //Value of 0 will represent that the user hasn't been seen online - this.leaderBoardExclusion = new DirtyData<>(new MutableBoolean(false), dirtyFlag); + this.barStateMap = MMOExperienceBarManager.generateDefaultBarStateMap(); + this.lastLogin = 0L; //Value of 0 will represent that the user hasn't been seen online + this.leaderBoardExclusion = false; + + this.lastUpdateHash = hashCode(); } /** @@ -124,34 +119,32 @@ public class PlayerData { @NotNull Map barStateMap, int scoreboardTipsShown, long lastLogin, - boolean leaderBoardExclusion) throws Exception { + boolean leaderBoardExclusion) throws UnexpectedValueException, NullPointerException { /* * Skills Data */ - this.dirtyFlag = new MutableBoolean(false); //Set this one first - validateRootSkillMap(skillLevelValues); - this.skillLevelValues = new DirtyMap<>(skillLevelValues, dirtyFlag); + this.skillLevelValues = skillLevelValues; validateRootSkillMap(skillExperienceValues); - this.skillExperienceValues = new DirtyMap<>(skillExperienceValues, dirtyFlag); + this.skillExperienceValues = skillExperienceValues; validateSuperSkillMap(abilityDeactivationTimestamps); - this.abilityDeactivationTimestamps = new DirtyMap<>(abilityDeactivationTimestamps, dirtyFlag); + this.abilityDeactivationTimestamps = abilityDeactivationTimestamps; - this.uniquePlayerData = new DirtyMap<>(uniquePlayerData, dirtyFlag); + this.uniquePlayerData = uniquePlayerData; - this.scoreboardTipsShown = new DirtyData<>(new MutableInteger(scoreboardTipsShown), dirtyFlag); + this.scoreboardTipsShown = scoreboardTipsShown; this.playerUUID = playerUUID; - this.playerName = new DirtyData<>(new MutableString(playerName), dirtyFlag); - this.barStateMap = new DirtyMap<>(barStateMap, dirtyFlag); + this.playerName = playerName; + this.barStateMap = barStateMap; - this.partyChatSpying = new DirtyData<>(new MutableBoolean(partyChatSpying), dirtyFlag); - this.lastLogin = new DirtyData<>(new MutableLong(lastLogin), dirtyFlag); + this.partyChatSpying = partyChatSpying; + this.lastLogin = lastLogin; - this.leaderBoardExclusion = new DirtyData<>(new MutableBoolean(leaderBoardExclusion), dirtyFlag); + this.leaderBoardExclusion = leaderBoardExclusion; } /** @@ -159,20 +152,30 @@ public class PlayerData { * * @param map target map * @throws UnexpectedValueException when values are outside of expected norms - * @throws Exception when values are outside of expected norms */ - private void validateRootSkillMap(Map map) throws UnexpectedValueException, Exception { + private void validateRootSkillMap(Map map) throws UnexpectedValueException, NullPointerException { //TODO: Check for missing/unregistered - Validator validator = new Validator<>(); + Validator positiveValidator = new Validator<>(); + Validator nullValidator = new Validator<>(); - validator.addRule(new PositiveIntegerRule<>()); - validator.addRule(new NonNullRule<>()); + positiveValidator.addRule(new PositiveIntegerRule<>()); + nullValidator.addRule(new NonNullRule<>()); for(PrimarySkillType primarySkillType : PrimarySkillType.values()) { if(primarySkillType.isChildSkill()) continue; - - validator.validate(map.get(primarySkillType)); + + try { + positiveValidator.validate(map.get(primarySkillType)); + } catch (Exception e) { + throw new UnexpectedValueException(); + } + + try { + nullValidator.validate(map.get(primarySkillType)); + } catch (Exception e) { + throw new NullPointerException(); + } } } @@ -183,7 +186,7 @@ public class PlayerData { * @throws UnexpectedValueException when values are outside of expected norms * @throws Exception when values are outside of expected norms */ - private void validateSuperSkillMap(Map map) throws UnexpectedValueException, Exception { + private void validateSuperSkillMap(Map map) throws UnexpectedValueException, NullPointerException { //TODO: Check for missing/unregistered Validator validator = new Validator<>(); @@ -191,7 +194,11 @@ public class PlayerData { validator.addRule(new NonNullRule<>()); for(SuperAbilityType superSkill : SuperAbilityType.values()) { - validator.validate(map.get(superSkill)); + try { + validator.validate(map.get(superSkill)); + } catch (Exception e) { + throw new UnexpectedValueException(); + } } } @@ -204,30 +211,31 @@ public class PlayerData { return 0; } - public boolean isDirtyProfile() { - return dirtyFlag.getImmutableCopy(); + public boolean isProfileDirty() { + return lastUpdateHash != hashCode(); } + //TODO: T&C this needs to be called or pointless save operations won't be avoided public void resetDirtyFlag() { - dirtyFlag.setBoolean(false); + lastUpdateHash = hashCode(); } public @NotNull String getPlayerName() { - return playerName.getData().getImmutableCopy(); + return playerName; } - public @NotNull UUID getPlayerUUID() { + public @Nullable UUID getPlayerUUID() { return playerUUID; } - public boolean isPartyChatSpying() { return partyChatSpying.getData().getImmutableCopy(); } + public boolean isPartyChatSpying() { return partyChatSpying; } public void togglePartyChatSpying() { - partyChatSpying.getData().setBoolean(!partyChatSpying.getData().getImmutableCopy()); + partyChatSpying = !partyChatSpying; } public void setPartyChatSpying(boolean bool) { - this.partyChatSpying.getData().setBoolean(bool); + this.partyChatSpying = bool; } /* @@ -235,11 +243,11 @@ public class PlayerData { */ public int getScoreboardTipsShown() { - return scoreboardTipsShown.getData(false).getImmutableCopy(); + return scoreboardTipsShown; } public void setScoreboardTipsShown(int newValue) { - scoreboardTipsShown.getData(true).setInt(newValue); + this.scoreboardTipsShown = newValue; } public int getChimaeraWingDATS() { @@ -273,22 +281,6 @@ public class PlayerData { return barStateMap; } - public @NotNull DirtyMap getDirtyBarStateMap() { - return barStateMap; - } - - public @NotNull DirtyMap getDirtySkillLevelMap() { - return skillLevelValues; - } - - public @NotNull DirtyMap getDirtyExperienceValueMap() { - return skillExperienceValues; - } - - public @NotNull DirtyData getDirtyPartyChatSpying() { - return partyChatSpying; - } - public @NotNull Map getSkillLevelsMap() { return skillLevelValues; } @@ -305,24 +297,20 @@ public class PlayerData { return uniquePlayerData; } - public void setDirtyProfile() { - this.dirtyFlag.setBoolean(true); - } - public long getLastLogin() { - return lastLogin.getData().getImmutableCopy(); + return lastLogin; } public void setLastLogin(long newValue) { - lastLogin.getData().setLong(newValue); + this.lastLogin = newValue; } public boolean isLeaderBoardExcluded() { - return leaderBoardExclusion.getData().getImmutableCopy(); + return leaderBoardExclusion; } public void setLeaderBoardExclusion(boolean bool) { - leaderBoardExclusion.getData(true).setBoolean(bool); + this.leaderBoardExclusion = bool; } public @NotNull ImmutableMap copyPrimarySkillLevelsMap() { @@ -332,4 +320,26 @@ public class PlayerData { public @NotNull ImmutableMap copyPrimarySkillExperienceValuesMap() { return ImmutableMap.copyOf(getSkillsExperienceMap()); } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + PlayerData that = (PlayerData) o; + return lastLogin == that.lastLogin + && partyChatSpying == that.partyChatSpying + && leaderBoardExclusion == that.leaderBoardExclusion + && scoreboardTipsShown == that.scoreboardTipsShown + && Objects.equal(playerName, that.playerName) + && Objects.equal(playerUUID, that.playerUUID) + && Objects.equal(skillLevelValues, that.skillLevelValues) + && Objects.equal(skillExperienceValues, that.skillExperienceValues) + && Objects.equal(abilityDeactivationTimestamps, that.abilityDeactivationTimestamps) + && Objects.equal(uniquePlayerData, that.uniquePlayerData) && Objects.equal(barStateMap, that.barStateMap); + } + + @Override + public int hashCode() { + return Objects.hashCode(playerName, playerUUID, lastLogin, skillLevelValues, skillExperienceValues, abilityDeactivationTimestamps, uniquePlayerData, barStateMap, partyChatSpying, leaderBoardExclusion, scoreboardTipsShown); + } } diff --git a/src/main/java/com/gmail/nossr50/datatypes/player/PlayerProfile.java b/src/main/java/com/gmail/nossr50/datatypes/player/PlayerProfile.java index f3f6627ca..a4c6deb5a 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/player/PlayerProfile.java +++ b/src/main/java/com/gmail/nossr50/datatypes/player/PlayerProfile.java @@ -7,6 +7,7 @@ import org.jetbrains.annotations.NotNull; import java.util.UUID; +//TODO: T&C update javadocs? public class PlayerProfile extends AbstractMMOPlayer { /** diff --git a/src/main/java/com/gmail/nossr50/datatypes/validation/NonNullRule.java b/src/main/java/com/gmail/nossr50/datatypes/validation/NonNullRule.java index 5495763b8..0e0ef230a 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/validation/NonNullRule.java +++ b/src/main/java/com/gmail/nossr50/datatypes/validation/NonNullRule.java @@ -2,7 +2,7 @@ package com.gmail.nossr50.datatypes.validation; public class NonNullRule extends Rule { @Override - public void applyRule(T object) throws Exception { + public void applyRule(T object) throws NullPointerException { if(object == null) throw new NullPointerException(); } diff --git a/src/main/java/com/gmail/nossr50/datatypes/validation/PositiveIntegerRule.java b/src/main/java/com/gmail/nossr50/datatypes/validation/PositiveIntegerRule.java index c4348943c..86fd089b4 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/validation/PositiveIntegerRule.java +++ b/src/main/java/com/gmail/nossr50/datatypes/validation/PositiveIntegerRule.java @@ -1,10 +1,10 @@ package com.gmail.nossr50.datatypes.validation; -import com.gmail.nossr50.api.exceptions.UnexpectedValueException; +import com.neetgames.mcmmo.exceptions.UnexpectedValueException; public class PositiveIntegerRule extends Rule { @Override - public void applyRule(T number) throws Exception { + public void applyRule(T number) throws UnexpectedValueException { if(number.intValue() < 0) throw new UnexpectedValueException(); } diff --git a/src/main/java/com/gmail/nossr50/party/PersistentPartyData.java b/src/main/java/com/gmail/nossr50/party/PersistentPartyData.java index 943348697..8946dca90 100644 --- a/src/main/java/com/gmail/nossr50/party/PersistentPartyData.java +++ b/src/main/java/com/gmail/nossr50/party/PersistentPartyData.java @@ -1,58 +1,7 @@ package com.gmail.nossr50.party; -import com.google.common.base.Objects; -import com.neetgames.mcmmo.party.PartyMember; -import com.neetgames.neetlib.dirtydata.DirtyData; -import com.neetgames.neetlib.dirtydata.DirtySet; -import com.neetgames.neetlib.mutableprimitives.MutableBoolean; -import com.neetgames.neetlib.mutableprimitives.MutableString; -import org.jetbrains.annotations.NotNull; - -import java.util.HashSet; -import java.util.Set; public class PersistentPartyData { + private int hashCodeCache; //TODO: T&C wire this up later, see PlayerData for example - private final @NotNull MutableBoolean dirtyFlag; //Dirty values in this class will change this flag as needed - private final @NotNull DirtyData partyName; - private final @NotNull DirtySet partyMembers; //TODO: Add cache for subsets - - public PersistentPartyData(@NotNull String partyName, @NotNull Set partyMembers) throws RuntimeException { - dirtyFlag = new MutableBoolean(false); - this.partyName = new DirtyData<>(new MutableString(partyName), dirtyFlag); - this.partyMembers = new DirtySet<>(new HashSet<>(partyMembers), dirtyFlag); - } - - public @NotNull String getPartyName() { - return partyName.getData().getImmutableCopy(); - } - - public @NotNull Set getPartyMembers() { - return partyMembers; - } - - public boolean isDataDirty() { - return dirtyFlag.getImmutableCopy(); - } - - @Override - public String toString() { - return "PersistentPartyData{" + - "partyName=" + partyName + - ", partyMembers=" + partyMembers + - '}'; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - PersistentPartyData that = (PersistentPartyData) o; - return Objects.equal(partyName, that.partyName) && Objects.equal(partyMembers, that.partyMembers); - } - - @Override - public int hashCode() { - return Objects.hashCode(partyName, partyMembers); - } } diff --git a/src/main/java/com/gmail/nossr50/util/player/PlayerSaveHandler.java b/src/main/java/com/gmail/nossr50/util/player/PlayerSaveHandler.java index ed307bec0..9af2d8ee6 100644 --- a/src/main/java/com/gmail/nossr50/util/player/PlayerSaveHandler.java +++ b/src/main/java/com/gmail/nossr50/util/player/PlayerSaveHandler.java @@ -44,7 +44,7 @@ public class PlayerSaveHandler { 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()) { + if(!playerData.isProfileDirty()) { return; //Don't save data that hasn't changed }