diff --git a/src/main/java/net/Indyuce/mmocore/MMOCore.java b/src/main/java/net/Indyuce/mmocore/MMOCore.java index f4c57556..417f21c3 100644 --- a/src/main/java/net/Indyuce/mmocore/MMOCore.java +++ b/src/main/java/net/Indyuce/mmocore/MMOCore.java @@ -78,6 +78,8 @@ import net.Indyuce.mmocore.manager.QuestManager; import net.Indyuce.mmocore.manager.RestrictionManager; import net.Indyuce.mmocore.manager.SkillManager; import net.Indyuce.mmocore.manager.WaypointManager; +import net.Indyuce.mmocore.manager.data.PlayerDataManager; +import net.Indyuce.mmocore.manager.data.YAMLPlayerDataManager; import net.Indyuce.mmocore.manager.profession.AlchemyManager; import net.Indyuce.mmocore.manager.profession.EnchantManager; import net.Indyuce.mmocore.manager.profession.FishingManager; @@ -96,30 +98,30 @@ import net.mmogroup.mmolib.version.SpigotPlugin; public class MMOCore extends JavaPlugin { public static MMOCore plugin; - public final ClassManager classManager = new ClassManager(); public ConfigManager configManager; public WaypointManager waypointManager; public RestrictionManager restrictionManager; + public LootableChestManager chestManager; + public RequestManager requestManager; + public GuildManager guildManager = new GuildManager(); + public ConfigItemManager configItems; + public SkillManager skillManager; + public final ClassManager classManager = new ClassManager(); public final DropTableManager dropTableManager = new DropTableManager(); public final CustomBlockManager mineManager = new CustomBlockManager(); public final BoosterManager boosterManager = new BoosterManager(); - public LootableChestManager chestManager; - public RequestManager requestManager; public final AttributeManager attributeManager = new AttributeManager(); public final PartyManager partyManager = new PartyManager(); - public GuildManager guildManager = new GuildManager(); public final QuestManager questManager = new QuestManager(); - public ConfigItemManager configItems; - public SkillManager skillManager; public final ProfessionManager professionManager = new ProfessionManager(); - // public final SQLManager sqlManager = new SQLManager(); + public final EntityManager entities = new EntityManager(); public VaultEconomy economy; public HologramSupport hologramSupport; public PlaceholderParser placeholderParser = new DefaultParser(); - public final EntityManager entities = new EntityManager(); public InventoryManager inventoryManager; public RegionHandler regionHandler; public PlayerActionBar actionBarManager; + public final PlayerDataManager playerDataManager = new YAMLPlayerDataManager(); /* * professions @@ -160,7 +162,7 @@ public class MMOCore extends JavaPlugin { /* * mmocore stats are functions of the stat base value. the function - * applies all the different stat modifiers saved in the stat map using + * applies all the different stat modifiers saved in the stat map. using * specific stat instances let MMOLib calculate stats with set base * value */ @@ -290,7 +292,7 @@ public class MMOCore extends JavaPlugin { * the player datas can't recognize what profess the player has and * professes will be lost */ - Bukkit.getOnlinePlayers().forEach(player -> PlayerData.setup(player)); + Bukkit.getOnlinePlayers().forEach(player -> playerDataManager.setup(player)); // commands try { @@ -338,11 +340,8 @@ public class MMOCore extends JavaPlugin { int autosave = getConfig().getInt("auto-save.interval") * 20; new BukkitRunnable() { public void run() { - for (PlayerData playerData : PlayerData.getAll()) { - ConfigFile config = new ConfigFile(playerData.getUniqueId()); - playerData.saveInConfig(config.getConfig()); - config.save(); - } + for (PlayerData loaded : PlayerData.getAll()) + playerDataManager.saveData(loaded); guildManager.save(); } @@ -351,11 +350,9 @@ public class MMOCore extends JavaPlugin { } public void onDisable() { - for (PlayerData playerData : PlayerData.getAll()) { - ConfigFile config = new ConfigFile(playerData.getUniqueId()); - playerData.getQuestData().resetBossBar(); - playerData.saveInConfig(config.getConfig()); - config.save(); + for (PlayerData data : PlayerData.getAll()) { + data.getQuestData().resetBossBar(); + playerDataManager.saveData(data); } guildManager.save(); diff --git a/src/main/java/net/Indyuce/mmocore/api/ConfigFile.java b/src/main/java/net/Indyuce/mmocore/api/ConfigFile.java index 4c7a3d98..36ebbfdb 100644 --- a/src/main/java/net/Indyuce/mmocore/api/ConfigFile.java +++ b/src/main/java/net/Indyuce/mmocore/api/ConfigFile.java @@ -49,14 +49,14 @@ public class ConfigFile { public void save() { try { config.save(file); - } catch (IOException e2) { - MMOCore.plugin.getLogger().log(Level.SEVERE, "Could not save " + name + ".yml!"); + } catch (IOException exception) { + MMOCore.plugin.getLogger().log(Level.SEVERE, "Could not save " + name + ".yml: " + exception.getMessage()); } } - + public void delete() { - if(file.exists()) - if(!file.delete()) - MMOCore.plugin.getLogger().log(Level.SEVERE, "Could not delete " + name + ".yml!"); + if (file.exists()) + if (!file.delete()) + MMOCore.plugin.getLogger().log(Level.SEVERE, "Could not delete " + name + ".yml."); } } \ No newline at end of file diff --git a/src/main/java/net/Indyuce/mmocore/api/data/DataProvider.java b/src/main/java/net/Indyuce/mmocore/api/data/DataProvider.java new file mode 100644 index 00000000..be425306 --- /dev/null +++ b/src/main/java/net/Indyuce/mmocore/api/data/DataProvider.java @@ -0,0 +1,18 @@ +package net.Indyuce.mmocore.api.data; + +import net.Indyuce.mmocore.manager.data.PlayerDataManager; +import net.Indyuce.mmocore.manager.social.GuildManager; + +public interface DataProvider { + + /* + * used to separate MySQL data storage from YAML data storage. there is one + * dataProvider per storage mecanism (one for YAML, one for MySQL). a + * dataProvider provides corresponding mmoManagers to correctly save and load + * data + */ + + PlayerDataManager provideDataManager(); + + GuildManager provideGuildManager(); +} diff --git a/src/main/java/net/Indyuce/mmocore/api/data/YAMLDataProvider.java b/src/main/java/net/Indyuce/mmocore/api/data/YAMLDataProvider.java new file mode 100644 index 00000000..db7106e0 --- /dev/null +++ b/src/main/java/net/Indyuce/mmocore/api/data/YAMLDataProvider.java @@ -0,0 +1,18 @@ +package net.Indyuce.mmocore.api.data; + +import net.Indyuce.mmocore.manager.data.PlayerDataManager; +import net.Indyuce.mmocore.manager.data.YAMLPlayerDataManager; +import net.Indyuce.mmocore.manager.social.GuildManager; + +public class YAMLDataProvider implements DataProvider { + + @Override + public PlayerDataManager provideDataManager() { + return new YAMLPlayerDataManager(); + } + + @Override + public GuildManager provideGuildManager() { + return new GuildManager(); + } +} diff --git a/src/main/java/net/Indyuce/mmocore/api/player/OfflinePlayerData.java b/src/main/java/net/Indyuce/mmocore/api/player/OfflinePlayerData.java index 117fd1ca..283f9be8 100644 --- a/src/main/java/net/Indyuce/mmocore/api/player/OfflinePlayerData.java +++ b/src/main/java/net/Indyuce/mmocore/api/player/OfflinePlayerData.java @@ -2,6 +2,7 @@ package net.Indyuce.mmocore.api.player; import java.util.UUID; +import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.profess.PlayerClass; public abstract class OfflinePlayerData { @@ -26,6 +27,6 @@ public abstract class OfflinePlayerData { public abstract long getLastLogin(); public static OfflinePlayerData get(UUID uuid) { - return PlayerData.isLoaded(uuid) ? PlayerData.get(uuid) : new SimpleOfflinePlayerData(uuid); + return MMOCore.plugin.playerDataManager.getOffline(uuid); } } diff --git a/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java b/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java index 02dcb92c..53aeec1a 100644 --- a/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java +++ b/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java @@ -9,9 +9,7 @@ import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.logging.Level; -import java.util.stream.Collectors; -import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; import org.bukkit.Color; import org.bukkit.Location; @@ -19,14 +17,12 @@ import org.bukkit.OfflinePlayer; import org.bukkit.Particle; import org.bukkit.Sound; import org.bukkit.attribute.Attribute; -import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Player; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; import org.bukkit.scheduler.BukkitRunnable; import net.Indyuce.mmocore.MMOCore; -import net.Indyuce.mmocore.api.ConfigFile; import net.Indyuce.mmocore.api.ConfigMessage; import net.Indyuce.mmocore.api.Waypoint; import net.Indyuce.mmocore.api.event.PlayerCastSkillEvent; @@ -67,18 +63,19 @@ public class PlayerData extends OfflinePlayerData { private PlayerClass profess; private int level, experience, classPoints, skillPoints, attributePoints, attributeReallocationPoints;// skillReallocationPoints, private double mana, stamina, stellium; - private List friends; private Party party; private Guild guild; - private final Map classSlots = new HashMap<>(); - private final List boundSkills = new ArrayList<>(); - private final PlayerAttributes attributes = new PlayerAttributes(this); - private final Professions collectSkills = new Professions(this); + private final PlayerQuests questData; - private final Set waypoints = new HashSet<>(); private final PlayerStats playerStats; + private final List friends = new ArrayList<>(); + private final Set waypoints = new HashSet<>(); private final Map skills = new HashMap<>(); + private final List boundSkills = new ArrayList<>(); + private final Professions collectSkills = new Professions(this); private final PlayerSkillData skillData = new PlayerSkillData(this); + private final PlayerAttributes attributes = new PlayerAttributes(this); + private final Map classSlots = new HashMap<>(); private long lastWaypoint, lastLogin, lastFriendRequest, actionBarTimeOut; @@ -90,111 +87,14 @@ public class PlayerData extends OfflinePlayerData { public boolean nocd; public CombatRunnable combat; - private static Map playerData = new HashMap<>(); - - private PlayerData(Player player) { + public PlayerData(Player player) { super(player.getUniqueId()); setPlayer(player); playerStats = new PlayerStats(this); - questData = new PlayerQuests(this); } - public PlayerData load(FileConfiguration config) { - this.classPoints = config.getInt("class-points"); - this.skillPoints = config.getInt("skill-points"); - this.attributePoints = config.getInt("attribute-points"); - // this.skillReallocationPoints = config.getInt("skill-realloc-points"); - this.attributeReallocationPoints = config.getInt("attribute-realloc-points"); - this.level = config.getInt("level"); - this.experience = config.getInt("experience"); - this.profess = config.contains("class") ? MMOCore.plugin.classManager.get(config.getString("class")) : MMOCore.plugin.classManager.getDefaultClass(); - this.mana = getStats().getStat(StatType.MAX_MANA); - this.stamina = getStats().getStat(StatType.MAX_STAMINA); - this.stellium = getStats().getStat(StatType.MAX_STELLIUM); - if (config.contains("guild")) - this.guild = MMOCore.plugin.guildManager.stillInGuild(getUniqueId(), config.getString("guild")); - if (config.contains("attribute")) - attributes.load(config.getConfigurationSection("attribute")); - if (config.contains("profession")) - collectSkills.load(config.getConfigurationSection("profession")); - if (config.contains("quest")) - questData.load(config.getConfigurationSection("quest")); - questData.updateBossBar(); - if (config.contains("waypoints")) - waypoints.addAll(config.getStringList("waypoints")); - MMOCore.plugin.waypointManager.getDefault().forEach(waypoint -> waypoints.add(waypoint.getId())); - this.friends = config.contains("friends") ? config.getStringList("friends").stream().map((str) -> UUID.fromString(str)).collect(Collectors.toList()) : new ArrayList<>(); - if (config.contains("skill")) - config.getConfigurationSection("skill").getKeys(false).forEach(id -> skills.put(id, config.getInt("skill." + id))); - if (config.contains("bound-skills")) - for (String id : config.getStringList("bound-skills")) - if (MMOCore.plugin.skillManager.has(id)) - boundSkills.add(getProfess().getSkill(id)); - - /* - * load class slots, use try so the player can log in. - */ - if (config.contains("class-info")) - for (String key : config.getConfigurationSection("class-info").getKeys(false)) - try { - PlayerClass profess = MMOCore.plugin.classManager.get(key); - Validate.notNull(profess, "Could not find class '" + key + "'"); - applyClassInfo(profess, new SavedClassInformation(config.getConfigurationSection("class-info." + key))); - } catch (IllegalArgumentException exception) { - log(Level.SEVERE, "Could not load class info " + key + ": " + exception.getMessage()); - } - - return this; - } - - public void saveInConfig(FileConfiguration config) { - config.set("class-points", classPoints); - config.set("skill-points", skillPoints); - config.set("attribute-points", attributePoints); - // config.set("skill-realloc-points", skillReallocationPoints); - config.set("attribute-realloc-points", attributeReallocationPoints); - config.set("level", getLevel()); - config.set("experience", experience); - config.set("class", profess == null ? null : profess.getId()); - config.set("waypoints", new ArrayList<>(waypoints)); - config.set("friends", toStringList(friends)); - config.set("last-login", lastLogin); - config.set("guild", guild != null ? guild.getId() : null); - - config.set("skill", null); - skills.entrySet().forEach(entry -> config.set("skill." + entry.getKey(), entry.getValue())); - - List boundSkills = new ArrayList<>(); - this.boundSkills.forEach(skill -> boundSkills.add(skill.getSkill().getId())); - config.set("bound-skills", boundSkills); - - config.set("attribute", null); - config.createSection("attribute"); - attributes.save(config.getConfigurationSection("attribute")); - - config.set("profession", null); - config.createSection("profession"); - collectSkills.save(config.getConfigurationSection("profession")); - - config.set("quest", null); - config.createSection("quest"); - questData.save(config.getConfigurationSection("quest")); - - config.set("class-info", null); - for (String key : classSlots.keySet()) { - SavedClassInformation info = classSlots.get(key); - config.set("class-info." + key + ".level", info.getLevel()); - config.set("class-info." + key + ".experience", info.getExperience()); - config.set("class-info." + key + ".skill-points", info.getSkillPoints()); - config.set("class-info." + key + ".attribute-points", info.getAttributePoints()); - config.set("class-info." + key + ".attribute-realloc-points", info.getAttributeReallocationPoints()); - info.getSkillKeys().forEach(skill -> config.set("class-info." + key + ".skill." + skill, info.getSkillLevel(skill))); - info.getAttributeKeys().forEach(attribute -> config.set("class-info." + key + ".attribute." + attribute, info.getAttributeLevel(attribute))); - } - } - /* * update all references after /mmocore reload so there can be garbage * collection with old plugin objects like class or skill instances. @@ -223,28 +123,14 @@ public class PlayerData extends OfflinePlayerData { } public static PlayerData get(UUID uuid) { - return playerData.get(uuid); - } - - public static void remove(Player player) { - playerData.remove(player.getUniqueId()); - } - - public static PlayerData setup(Player player) { - if (!playerData.containsKey(player.getUniqueId())) - playerData.put(player.getUniqueId(), new PlayerData(player).load(new ConfigFile(player).getConfig())); - return get(player).setPlayer(player); - } - - public static boolean isLoaded(UUID uuid) { - return playerData.containsKey(uuid); + return MMOCore.plugin.playerDataManager.get(uuid); } public static Collection getAll() { - return playerData.values(); + return MMOCore.plugin.playerDataManager.getLoaded(); } - private PlayerData setPlayer(Player player) { + public PlayerData setPlayer(Player player) { this.player = player; this.lastLogin = System.currentTimeMillis(); return this; @@ -284,6 +170,10 @@ public class PlayerData extends OfflinePlayerData { return party; } + public boolean hasGuild() { + return guild != null; + } + public Guild getGuild() { return guild; } @@ -368,8 +258,16 @@ public class PlayerData extends OfflinePlayerData { return classSlots.containsKey(profess.getId()); } + public Set getSavedClasses() { + return classSlots.keySet(); + } + public SavedClassInformation getClassInfo(PlayerClass profess) { - return classSlots.get(profess.getId()); + return getClassInfo(profess.getId()); + } + + public SavedClassInformation getClassInfo(String profess) { + return classSlots.get(profess); } public void applyClassInfo(PlayerClass profess, SavedClassInformation info) { @@ -397,8 +295,8 @@ public class PlayerData extends OfflinePlayerData { } public void heal(double heal) { - double current = player.getHealth(), newest = Math.max(0, Math.min(player.getHealth() + heal, player.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue())); - if (current == newest) + double newest = Math.max(0, Math.min(player.getHealth() + heal, player.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue())); + if (player.getHealth() == newest) return; PlayerRegenResourceEvent event = new PlayerRegenResourceEvent(this, PlayerResource.HEALTH, heal); @@ -761,15 +659,6 @@ public class PlayerData extends OfflinePlayerData { combat = new CombatRunnable(this); } - private List toStringList(List list) { - if (list.isEmpty()) - return null; - - List stringList = new ArrayList<>(); - list.forEach(uuid -> stringList.add(uuid.toString())); - return stringList; - } - public SkillResult cast(Skill skill) { return cast(getProfess().getSkill(skill)); } diff --git a/src/main/java/net/Indyuce/mmocore/listener/PlayerListener.java b/src/main/java/net/Indyuce/mmocore/listener/PlayerListener.java index 7983906d..2b05f1a3 100644 --- a/src/main/java/net/Indyuce/mmocore/listener/PlayerListener.java +++ b/src/main/java/net/Indyuce/mmocore/listener/PlayerListener.java @@ -15,6 +15,7 @@ import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; +import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.event.PlayerCombatEvent; import net.Indyuce.mmocore.api.event.PlayerRegenResourceEvent; import net.Indyuce.mmocore.api.player.PlayerData; @@ -29,7 +30,7 @@ public class PlayerListener implements Listener { @EventHandler(priority = EventPriority.LOW) public void a(PlayerJoinEvent event) { Player player = event.getPlayer(); - PlayerData.setup(player).getStats().getMap().updateAll(); + MMOCore.plugin.playerDataManager.setup(player).getStats().getMap().updateAll(); } /* @@ -50,10 +51,10 @@ public class PlayerListener implements Listener { /* * updates the player's combat log data every time he hits an entity, or * gets hit by an entity or a projectile sent by another entity. updates - * this stuff on HIGH level so other plugins can check if the player just + * this stuff on LOW level so other plugins can check if the player just * entered combat */ - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) public void d(EntityDamageByEntityEvent event) { if (event.getEntity() instanceof Player && !event.getEntity().hasMetadata("NPC")) PlayerData.get((Player) event.getEntity()).updateCombat(); @@ -61,11 +62,9 @@ public class PlayerListener implements Listener { if (event.getDamager() instanceof Player && !event.getDamager().hasMetadata("NPC")) PlayerData.get((Player) event.getDamager()).updateCombat(); - if (event.getDamager() instanceof Projectile && ((Projectile) event.getDamager()).getShooter() instanceof Player) { - if (((Player) ((Projectile) event.getDamager()).getShooter()).hasMetadata("NPC")) - return; - PlayerData.get((Player) ((Projectile) event.getDamager()).getShooter()).updateCombat(); - } + if (event.getDamager() instanceof Projectile && ((Projectile) event.getDamager()).getShooter() instanceof Player) + if (!((Player) ((Projectile) event.getDamager()).getShooter()).hasMetadata("NPC")) + PlayerData.get((Player) ((Projectile) event.getDamager()).getShooter()).updateCombat(); } @EventHandler diff --git a/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java b/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java new file mode 100644 index 00000000..fd290888 --- /dev/null +++ b/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java @@ -0,0 +1,56 @@ +package net.Indyuce.mmocore.manager.data; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +import net.Indyuce.mmocore.api.player.OfflinePlayerData; +import net.Indyuce.mmocore.api.player.PlayerData; +import net.Indyuce.mmocore.api.player.SimpleOfflinePlayerData; + +public abstract class PlayerDataManager { + private final Map map = new HashMap<>(); + + public PlayerData get(OfflinePlayer player) { + return get(player.getUniqueId()); + } + + public PlayerData get(UUID uuid) { + return map.get(uuid); + } + + public OfflinePlayerData getOffline(UUID uuid) { + return isLoaded(uuid) ? get(uuid) : new SimpleOfflinePlayerData(uuid); + } + + public PlayerData setup(Player player) { + + /* + * setup playerData based on loadData method to support both MySQL and + * YAML data storage + */ + if (!map.containsKey(player.getUniqueId())) { + PlayerData generated = new PlayerData(player); + loadData(generated); + map.put(player.getUniqueId(), generated); + } + + return get(player).setPlayer(player); + } + + public boolean isLoaded(UUID uuid) { + return map.containsKey(uuid); + } + + public Collection getLoaded() { + return map.values(); + } + + public abstract void loadData(PlayerData data); + + public abstract void saveData(PlayerData data); +} diff --git a/src/main/java/net/Indyuce/mmocore/manager/data/YAMLPlayerDataManager.java b/src/main/java/net/Indyuce/mmocore/manager/data/YAMLPlayerDataManager.java new file mode 100644 index 00000000..2aea9eec --- /dev/null +++ b/src/main/java/net/Indyuce/mmocore/manager/data/YAMLPlayerDataManager.java @@ -0,0 +1,122 @@ +package net.Indyuce.mmocore.manager.data; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.logging.Level; +import java.util.stream.Collectors; + +import org.apache.commons.lang.Validate; +import org.bukkit.configuration.file.FileConfiguration; + +import net.Indyuce.mmocore.MMOCore; +import net.Indyuce.mmocore.api.ConfigFile; +import net.Indyuce.mmocore.api.player.PlayerData; +import net.Indyuce.mmocore.api.player.profess.PlayerClass; +import net.Indyuce.mmocore.api.player.profess.SavedClassInformation; +import net.Indyuce.mmocore.api.player.stats.StatType; + +public class YAMLPlayerDataManager extends PlayerDataManager { + + @Override + public void loadData(PlayerData data) { + FileConfiguration config = new ConfigFile(data.getPlayer()).getConfig(); + + data.setClassPoints(config.getInt("class-points")); + data.setSkillPoints(config.getInt("skill-points")); + data.setAttributePoints(config.getInt("attribute-points")); + data.setAttributeReallocationPoints(config.getInt("attribute-realloc-points")); + data.setLevel(config.getInt("level")); + data.setExperience(config.getInt("experience")); + if (config.contains("class")) + data.setProfess(MMOCore.plugin.classManager.get(config.getString("class"))); + data.setMana(data.getStats().getStat(StatType.MAX_MANA)); + data.setStamina(data.getStats().getStat(StatType.MAX_STAMINA)); + data.setStellium(data.getStats().getStat(StatType.MAX_STELLIUM)); + if (config.contains("guild")) + data.setGuild(MMOCore.plugin.guildManager.stillInGuild(data.getUniqueId(), config.getString("guild"))); + if (config.contains("attribute")) + data.getAttributes().load(config.getConfigurationSection("attribute")); + if (config.contains("profession")) + data.getCollectionSkills().load(config.getConfigurationSection("profession")); + if (config.contains("quest")) + data.getQuestData().load(config.getConfigurationSection("quest")); + data.getQuestData().updateBossBar(); + if (config.contains("waypoints")) + data.getWaypoints().addAll(config.getStringList("waypoints")); + MMOCore.plugin.waypointManager.getDefault().forEach(waypoint -> data.getWaypoints().add(waypoint.getId())); + if (config.contains("friends")) + config.getStringList("friends").forEach(str -> data.getFriends().add(UUID.fromString(str))); + if (config.contains("skill")) + config.getConfigurationSection("skill").getKeys(false).forEach(id -> data.setSkillLevel(id, config.getInt("skill." + id))); + if (config.contains("bound-skills")) + for (String id : config.getStringList("bound-skills")) + if (MMOCore.plugin.skillManager.has(id)) + data.getBoundSkills().add(data.getProfess().getSkill(id)); + + /* + * load class slots, use try so the player can log in. + */ + if (config.contains("class-info")) + for (String key : config.getConfigurationSection("class-info").getKeys(false)) + try { + PlayerClass profess = MMOCore.plugin.classManager.get(key); + Validate.notNull(profess, "Could not find class '" + key + "'"); + data.applyClassInfo(profess, new SavedClassInformation(config.getConfigurationSection("class-info." + key))); + } catch (IllegalArgumentException exception) { + MMOCore.log(Level.WARNING, "Could not load class info '" + key + "': " + exception.getMessage()); + } + } + + @Override + public void saveData(PlayerData data) { + ConfigFile file = new ConfigFile(data.getPlayer()); + FileConfiguration config = file.getConfig(); + + config.set("class-points", data.getClassPoints()); + config.set("skill-points", data.getSkillPoints()); + config.set("attribute-points", data.getAttributePoints()); + // config.set("skill-realloc-points", skillReallocationPoints); + config.set("attribute-realloc-points", data.getAttributeReallocationPoints()); + config.set("level", data.getLevel()); + config.set("experience", data.getExperience()); + config.set("class", data.getProfess().getId()); + config.set("waypoints", new ArrayList<>(data.getWaypoints())); + config.set("friends", data.getFriends().stream().map(uuid -> uuid.toString()).collect(Collectors.toList())); + config.set("last-login", data.getLastLogin()); + config.set("guild", data.hasGuild() ? data.getGuild().getId() : null); + + config.set("skill", null); + data.mapSkillLevels().entrySet().forEach(entry -> config.set("skill." + entry.getKey(), entry.getValue())); + + List boundSkills = new ArrayList<>(); + data.getBoundSkills().forEach(skill -> boundSkills.add(skill.getSkill().getId())); + config.set("bound-skills", boundSkills); + + config.set("attribute", null); + config.createSection("attribute"); + data.getAttributes().save(config.getConfigurationSection("attribute")); + + config.set("profession", null); + config.createSection("profession"); + data.getCollectionSkills().save(config.getConfigurationSection("profession")); + + config.set("quest", null); + config.createSection("quest"); + data.getQuestData().save(config.getConfigurationSection("quest")); + + config.set("class-info", null); + for (String key : data.getSavedClasses()) { + SavedClassInformation info = data.getClassInfo(key); + config.set("class-info." + key + ".level", info.getLevel()); + config.set("class-info." + key + ".experience", info.getExperience()); + config.set("class-info." + key + ".skill-points", info.getSkillPoints()); + config.set("class-info." + key + ".attribute-points", info.getAttributePoints()); + config.set("class-info." + key + ".attribute-realloc-points", info.getAttributeReallocationPoints()); + info.getSkillKeys().forEach(skill -> config.set("class-info." + key + ".skill." + skill, info.getSkillLevel(skill))); + info.getAttributeKeys().forEach(attribute -> config.set("class-info." + key + ".attribute." + attribute, info.getAttributeLevel(attribute))); + } + + file.save(); + } +}