diff --git a/src/main/java/net/Indyuce/mmocore/MMOCore.java b/src/main/java/net/Indyuce/mmocore/MMOCore.java index 6e084b52..f541cf19 100644 --- a/src/main/java/net/Indyuce/mmocore/MMOCore.java +++ b/src/main/java/net/Indyuce/mmocore/MMOCore.java @@ -9,7 +9,7 @@ import net.Indyuce.mmocore.api.ConfigFile; import net.Indyuce.mmocore.api.PlayerActionBar; import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.api.player.profess.resource.PlayerResource; -import net.Indyuce.mmocore.api.player.social.guilds.Guild; +import net.Indyuce.mmocore.guild.provided.Guild; import net.Indyuce.mmocore.api.player.stats.StatType; import net.Indyuce.mmocore.api.util.debug.DebugMode; import net.Indyuce.mmocore.command.*; diff --git a/src/main/java/net/Indyuce/mmocore/api/ConfigFile.java b/src/main/java/net/Indyuce/mmocore/api/ConfigFile.java index 178191d6..5c611746 100644 --- a/src/main/java/net/Indyuce/mmocore/api/ConfigFile.java +++ b/src/main/java/net/Indyuce/mmocore/api/ConfigFile.java @@ -11,7 +11,7 @@ import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; import net.Indyuce.mmocore.MMOCore; -import net.Indyuce.mmocore.api.player.social.guilds.Guild; +import net.Indyuce.mmocore.guild.provided.Guild; public class ConfigFile { private final File file; diff --git a/src/main/java/net/Indyuce/mmocore/api/event/social/GuildChatEvent.java b/src/main/java/net/Indyuce/mmocore/api/event/social/GuildChatEvent.java index 00f767b2..6d0ab404 100644 --- a/src/main/java/net/Indyuce/mmocore/api/event/social/GuildChatEvent.java +++ b/src/main/java/net/Indyuce/mmocore/api/event/social/GuildChatEvent.java @@ -5,7 +5,7 @@ import org.bukkit.event.HandlerList; import net.Indyuce.mmocore.api.event.PlayerDataEvent; import net.Indyuce.mmocore.api.player.PlayerData; -import net.Indyuce.mmocore.api.player.social.guilds.Guild; +import net.Indyuce.mmocore.guild.provided.Guild; public class GuildChatEvent extends PlayerDataEvent implements Cancellable { private static final HandlerList handlers = new HandlerList(); diff --git a/src/main/java/net/Indyuce/mmocore/api/player/CombatRunnable.java b/src/main/java/net/Indyuce/mmocore/api/player/CombatRunnable.java index a777cb0f..0b30c404 100644 --- a/src/main/java/net/Indyuce/mmocore/api/player/CombatRunnable.java +++ b/src/main/java/net/Indyuce/mmocore/api/player/CombatRunnable.java @@ -1,45 +1,49 @@ package net.Indyuce.mmocore.api.player; -import org.bukkit.Bukkit; -import org.bukkit.scheduler.BukkitRunnable; - import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.event.PlayerCombatEvent; +import org.apache.commons.lang.Validate; +import org.bukkit.Bukkit; +import org.bukkit.scheduler.BukkitRunnable; public class CombatRunnable extends BukkitRunnable { - private final PlayerData player; + private final PlayerData player; - private long lastHit = System.currentTimeMillis(); + private long lastHit = System.currentTimeMillis(); - public CombatRunnable(PlayerData player) { - this.player = player; + private boolean open = true; - if (player.isOnline()) { - MMOCore.plugin.configManager.getSimpleMessage("now-in-combat").send(player.getPlayer()); - Bukkit.getPluginManager().callEvent(new PlayerCombatEvent(player, true)); - runTaskTimer(MMOCore.plugin, 20, 20); - } - } + public CombatRunnable(PlayerData player) { + this.player = player; - public void update() { - lastHit = System.currentTimeMillis(); - } + if (player.isOnline()) { + MMOCore.plugin.configManager.getSimpleMessage("now-in-combat").send(player.getPlayer()); + Bukkit.getPluginManager().callEvent(new PlayerCombatEvent(player, true)); + runTaskTimer(MMOCore.plugin, 20, 20); + } + } - @Override - public void run() { - if (!player.isOnline()) { - close(); - return; - } - if (lastHit + MMOCore.plugin.configManager.combatLogTimer < System.currentTimeMillis()) { - Bukkit.getPluginManager().callEvent(new PlayerCombatEvent(player, false)); - MMOCore.plugin.configManager.getSimpleMessage("leave-combat").send(player.getPlayer()); - close(); - } - } + public void update() { + lastHit = System.currentTimeMillis(); + } - private void close() { - player.combat = null; - cancel(); - } + @Override + public void run() { + if (!player.isOnline()) { + close(); + return; + } + if (lastHit + MMOCore.plugin.configManager.combatLogTimer < System.currentTimeMillis()) { + Bukkit.getPluginManager().callEvent(new PlayerCombatEvent(player, false)); + MMOCore.plugin.configManager.getSimpleMessage("leave-combat").send(player.getPlayer()); + close(); + } + } + + private void close() { + Validate.isTrue(open, "Combat runnable has already been closed"); + player.combat = null; + cancel(); + open = false; + } } 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 366d3857..51db96c9 100644 --- a/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java +++ b/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java @@ -17,7 +17,6 @@ import net.Indyuce.mmocore.api.player.profess.SavedClassInformation; import net.Indyuce.mmocore.api.player.profess.Subclass; import net.Indyuce.mmocore.api.player.profess.resource.PlayerResource; import net.Indyuce.mmocore.api.player.social.FriendRequest; -import net.Indyuce.mmocore.api.player.social.guilds.Guild; import net.Indyuce.mmocore.api.player.stats.PlayerStats; import net.Indyuce.mmocore.api.player.stats.StatType; import net.Indyuce.mmocore.api.quest.PlayerQuests; @@ -25,7 +24,12 @@ import net.Indyuce.mmocore.api.util.Closable; import net.Indyuce.mmocore.api.util.MMOCoreUtils; import net.Indyuce.mmocore.api.util.math.particle.SmallParticleEffect; import net.Indyuce.mmocore.experience.EXPSource; +import net.Indyuce.mmocore.experience.ExperienceObject; +import net.Indyuce.mmocore.experience.ExperienceTableClaimer; import net.Indyuce.mmocore.experience.PlayerProfessions; +import net.Indyuce.mmocore.experience.droptable.ExperienceItem; +import net.Indyuce.mmocore.experience.droptable.ExperienceTable; +import net.Indyuce.mmocore.guild.provided.Guild; import net.Indyuce.mmocore.party.AbstractParty; import net.Indyuce.mmocore.party.provided.Party; import net.Indyuce.mmocore.skill.ClassSkill; @@ -47,7 +51,7 @@ import java.util.*; import java.util.logging.Level; -public class PlayerData extends OfflinePlayerData implements Closable { +public class PlayerData extends OfflinePlayerData implements Closable, ExperienceTableClaimer { /** * Corresponds to the MythicLib player data. It is used to keep @@ -78,6 +82,21 @@ public class PlayerData extends OfflinePlayerData implements Closable { private final Map classSlots = new HashMap<>(); private final Map lastActivity = new HashMap<>(); + /** + * Saves all the items that have been unlocked so far by + * the player. This can be used by other plugins by + * implementing the {@link Unlockable} interface + * + * @see {@link Unlockable} + */ + private final Set unlockedItems = new HashSet<>(); + + /** + * Saves the amount of times the player has claimed some + * exp item in exp tables, for both exp tables used + */ + private final Map tableItemClaims = new HashMap<>(); + // NON-FINAL player data stuff made public to facilitate field change public int skillGuiDisplayOffset; public boolean noCooldown; @@ -225,6 +244,24 @@ public class PlayerData extends OfflinePlayerData implements Closable { return skillPoints; } + @Override + public int getClaims(ExperienceObject object, ExperienceTable table, ExperienceItem item) { + String key = object.geyKey() + "." + table.getId() + "." + item.getId(); + return tableItemClaims.get(key); + } + + @Override + public void setClaims(ExperienceObject object, ExperienceTable table, ExperienceItem item, int times) { + String key = object.geyKey() + "." + table.getId() + "." + item.getId(); + tableItemClaims.put(key, times); + } + + @Deprecated(since = "1.9") + public void setProfessionExpItemClaims(String professionTableItemKey, int times) { + Validate.isTrue(!professionTableItemKey.startsWith("class.") && !professionTableItemKey.startsWith("profession."), "Invalid exp item key"); + tableItemClaims.put("profession." + professionTableItemKey, times); + } + /** * @return Experience needed in order to reach next level */ @@ -252,6 +289,19 @@ public class PlayerData extends OfflinePlayerData implements Closable { return guild != null; } + public boolean hasUnlocked(Unlockable unlockable) { + throw new RuntimeException("Not implemented yet"); + } + + /** + * Unlocks an item for the player + * + * @return If the item was already unlocked when calling this method + */ + public boolean unlock(Unlockable unlockable) { + throw new RuntimeException("Not implemented yet"); + } + public void setLevel(int level) { this.level = Math.max(1, level); @@ -820,7 +870,7 @@ public class PlayerData extends OfflinePlayerData implements Closable { * checks if they could potentially upgrade to one of these * * @return If the player can change its current class to - * a subclass + * a subclass */ public boolean canChooseSubclass() { for (Subclass subclass : getProfess().getSubclasses()) diff --git a/src/main/java/net/Indyuce/mmocore/api/player/Unlockable.java b/src/main/java/net/Indyuce/mmocore/api/player/Unlockable.java new file mode 100644 index 00000000..3ec06f74 --- /dev/null +++ b/src/main/java/net/Indyuce/mmocore/api/player/Unlockable.java @@ -0,0 +1,15 @@ +package net.Indyuce.mmocore.api.player; + +/** + * Some item that can be unlocked + * + * @see {@link PlayerData#unlock(Unlockable)} and {@link PlayerData#hasUnlocked(Unlockable)} + */ +public interface Unlockable { + + /** + * Format being used is the minecraft's default + * namespaced key format, e.g skill_tree:strength_1_5 + */ + String getUnlockNamespacedKey(); +} diff --git a/src/main/java/net/Indyuce/mmocore/api/player/profess/PlayerClass.java b/src/main/java/net/Indyuce/mmocore/api/player/profess/PlayerClass.java index 253ce169..76762b1a 100644 --- a/src/main/java/net/Indyuce/mmocore/api/player/profess/PlayerClass.java +++ b/src/main/java/net/Indyuce/mmocore/api/player/profess/PlayerClass.java @@ -15,6 +15,8 @@ import net.Indyuce.mmocore.api.util.MMOCoreUtils; import net.Indyuce.mmocore.api.util.math.formula.LinearValue; import net.Indyuce.mmocore.api.util.math.particle.CastingParticle; import net.Indyuce.mmocore.experience.ExpCurve; +import net.Indyuce.mmocore.experience.ExperienceObject; +import net.Indyuce.mmocore.experience.droptable.ExperienceTable; import net.Indyuce.mmocore.experience.provider.ExperienceDispenser; import net.Indyuce.mmocore.experience.provider.MainExperienceDispenser; import net.Indyuce.mmocore.experience.source.type.ExperienceSource; @@ -28,12 +30,14 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.NotNull; +import javax.annotation.Nullable; import java.lang.reflect.Field; import java.util.*; import java.util.logging.Level; -public class PlayerClass extends PostLoadObject { +public class PlayerClass extends PostLoadObject implements ExperienceObject { private final String name, id, actionBarFormat; private final List description = new ArrayList<>(), attrDescription = new ArrayList<>(); private final ItemStack icon; @@ -41,6 +45,7 @@ public class PlayerClass extends PostLoadObject { private final ManaDisplayOptions manaDisplay; private final int maxLevel, displayOrder; private final ExpCurve expCurve; + private final ExperienceTable expTable; private final Map stats = new HashMap<>(); private final Map skills = new LinkedHashMap<>(); @@ -87,6 +92,15 @@ public class PlayerClass extends PostLoadObject { config.get("exp-curve").toString().toLowerCase().replace("_", "-").replace(" ", "-")) : ExpCurve.DEFAULT; + ExperienceTable expTable = null; + if (config.contains("exp-table")) + try { + expTable = MMOCore.plugin.experience.loadExperienceTable(config.get("exp-table")); + } catch (RuntimeException exception) { + MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load exp table from class '" + id + "': " + exception.getMessage()); + } + this.expTable = expTable; + if (config.contains("attributes")) for (String key : config.getConfigurationSection("attributes").getKeys(false)) try { @@ -168,6 +182,7 @@ public class PlayerClass extends PostLoadObject { maxLevel = 0; displayOrder = 0; expCurve = ExpCurve.DEFAULT; + expTable = null; castParticle = new CastingParticle(Particle.SPELL_INSTANT); actionBarFormat = ""; @@ -202,10 +217,17 @@ public class PlayerClass extends PostLoadObject { return name; } + @Override + public String geyKey() { + return "class." + getId(); + } + + @NotNull public ManaDisplayOptions getManaDisplay() { return manaDisplay; } + @NotNull public ResourceRegeneration getHandler(PlayerResource resource) { return resourceHandlers.get(resource); } @@ -218,10 +240,16 @@ public class PlayerClass extends PostLoadObject { return displayOrder; } + @Override public ExpCurve getExpCurve() { return expCurve; } + @Override + public ExperienceTable getExperienceTable() { + return expTable; + } + public ItemStack getIcon() { return icon.clone(); } @@ -246,8 +274,13 @@ public class PlayerClass extends PostLoadObject { return options.containsKey(option) ? options.get(option) : option.getDefault(); } + @Deprecated public void setStat(StatType type, double base, double perLevel) { - stats.put(type, new LinearValue(base, perLevel)); + setStat(type, new LinearValue(base, perLevel)); + } + + public void setStat(StatType type, LinearValue value) { + stats.put(type, value); } public double calculateStat(StatType stat, int level) { diff --git a/src/main/java/net/Indyuce/mmocore/command/GuildCommand.java b/src/main/java/net/Indyuce/mmocore/command/GuildCommand.java index 696d3f51..30f6efc9 100644 --- a/src/main/java/net/Indyuce/mmocore/command/GuildCommand.java +++ b/src/main/java/net/Indyuce/mmocore/command/GuildCommand.java @@ -14,7 +14,7 @@ import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.event.MMOCommandEvent; import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.api.player.social.Request; -import net.Indyuce.mmocore.api.player.social.guilds.GuildInvite; +import net.Indyuce.mmocore.guild.provided.GuildInvite; import net.Indyuce.mmocore.manager.InventoryManager; public class GuildCommand extends BukkitCommand { diff --git a/src/main/java/net/Indyuce/mmocore/experience/ExperienceObject.java b/src/main/java/net/Indyuce/mmocore/experience/ExperienceObject.java new file mode 100644 index 00000000..c0e82e7e --- /dev/null +++ b/src/main/java/net/Indyuce/mmocore/experience/ExperienceObject.java @@ -0,0 +1,29 @@ +package net.Indyuce.mmocore.experience; + +import net.Indyuce.mmocore.experience.droptable.ExperienceTable; + +import javax.annotation.Nullable; + +/** + * Either a profession or a class + * + * @author jules + */ +public interface ExperienceObject { + + String geyKey(); + + /** + * Indicates the amount of exp required to level up + * + * @return Exp curve of that object + */ + @Nullable + ExpCurve getExpCurve(); + + /** + * @return Table read when leveling up + */ + @Nullable + ExperienceTable getExperienceTable(); +} diff --git a/src/main/java/net/Indyuce/mmocore/experience/ExperienceTableClaimer.java b/src/main/java/net/Indyuce/mmocore/experience/ExperienceTableClaimer.java new file mode 100644 index 00000000..dcc2b03e --- /dev/null +++ b/src/main/java/net/Indyuce/mmocore/experience/ExperienceTableClaimer.java @@ -0,0 +1,21 @@ +package net.Indyuce.mmocore.experience; + +import net.Indyuce.mmocore.experience.droptable.ExperienceItem; +import net.Indyuce.mmocore.experience.droptable.ExperienceTable; + +/** + * Professions and classes share the same properties because + * they have both exp curves and tables. + *

+ * A 'claimer' is an object that can claim exp tables and therefore + * needs to save how many times it has already claimed some item + * before. + *

+ * Since MMOCore 1.9 it's all centralized in the player class data + */ +public interface ExperienceTableClaimer { + + int getClaims(ExperienceObject object, ExperienceTable table, ExperienceItem item); + + void setClaims(ExperienceObject object, ExperienceTable table, ExperienceItem item, int claims); +} diff --git a/src/main/java/net/Indyuce/mmocore/experience/PlayerProfessions.java b/src/main/java/net/Indyuce/mmocore/experience/PlayerProfessions.java index aeab17be..36614288 100644 --- a/src/main/java/net/Indyuce/mmocore/experience/PlayerProfessions.java +++ b/src/main/java/net/Indyuce/mmocore/experience/PlayerProfessions.java @@ -12,9 +12,6 @@ import net.Indyuce.mmocore.api.event.PlayerLevelUpEvent; import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.api.util.MMOCoreUtils; import net.Indyuce.mmocore.api.util.math.particle.SmallParticleEffect; -import net.Indyuce.mmocore.experience.droptable.ExperienceItem; -import net.Indyuce.mmocore.experience.droptable.ExperienceTable; -import net.Indyuce.mmocore.manager.SoundManager; import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; import org.bukkit.ChatColor; @@ -28,204 +25,194 @@ import java.util.Map; import java.util.Map.Entry; public class PlayerProfessions { - private final Map exp = new HashMap<>(); - private final Map level = new HashMap<>(); - private final Map timesClaimed = new HashMap<>(); - private final PlayerData playerData; + private final Map exp = new HashMap<>(); + private final Map level = new HashMap<>(); - public PlayerProfessions(PlayerData playerData) { - this.playerData = playerData; - } + private final PlayerData playerData; - public PlayerProfessions load(ConfigurationSection config) { - for (String key : config.getKeys(false)) - if (MMOCore.plugin.professionManager.has(key)) { - exp.put(key, config.getInt(key + ".exp")); - level.put(key, config.getInt(key + ".level")); - } + public PlayerProfessions(PlayerData playerData) { + this.playerData = playerData; + } - if (config.contains("times-claimed")) - // Watch out for the deep section lookup - for (String key : config.getConfigurationSection("times-claimed").getKeys(true)) - this.timesClaimed.put(key, config.getInt("times-claimed." + key)); + /** + * When loading data through YAML + */ + public PlayerProfessions load(ConfigurationSection config) { + for (String key : config.getKeys(false)) + if (MMOCore.plugin.professionManager.has(key)) { + exp.put(key, config.getInt(key + ".exp")); + level.put(key, config.getInt(key + ".level")); + } - return this; - } + if (config.contains("times-claimed")) + // Watch out for the deep section lookup + for (String key : config.getConfigurationSection("times-claimed").getKeys(true)) + playerData.setProfessionExpItemClaims(key, config.getInt("times-claimed." + key)); - public void save(ConfigurationSection config) { - for (String id : exp.keySet()) - config.set(id + ".exp", exp.get(id)); - for (String id : level.keySet()) - config.set(id + ".level", level.get(id)); + return this; + } - timesClaimed.forEach((key, value) -> config.set("times-claimed." + key, value)); - } + /** + * When saving data through YAML + */ + public void save(ConfigurationSection config) { + for (String id : exp.keySet()) + config.set(id + ".exp", exp.get(id)); + for (String id : level.keySet()) + config.set(id + ".level", level.get(id)); + } - public String toJsonString() { - JsonObject json = new JsonObject(); - for (Profession profession : MMOCore.plugin.professionManager.getAll()) { - JsonObject object = new JsonObject(); - object.addProperty("exp", getExperience(profession)); - object.addProperty("level", getLevel(profession)); + /** + * When saving data through SQL + */ + public String toJsonString() { + JsonObject json = new JsonObject(); + for (Profession profession : MMOCore.plugin.professionManager.getAll()) { + JsonObject object = new JsonObject(); + object.addProperty("exp", getExperience(profession)); + object.addProperty("level", getLevel(profession)); - json.add(profession.getId(), object); - } + json.add(profession.getId(), object); + } - JsonObject timesClaimed = new JsonObject(); - this.timesClaimed.forEach((key, value) -> timesClaimed.addProperty(key, value)); - json.add("timesClaimed", timesClaimed); + return json.toString(); + } - return json.toString(); - } + /** + * When loading data through SQL + */ + public void load(String json) { + JsonObject obj = new Gson().fromJson(json, JsonObject.class); - public void load(String json) { - JsonObject obj = new Gson().fromJson(json, JsonObject.class); + // Load profession exp and levels + for (Entry entry : obj.entrySet()) + if (MMOCore.plugin.professionManager.has(entry.getKey())) { + JsonObject value = entry.getValue().getAsJsonObject(); + exp.put(entry.getKey(), value.get("exp").getAsInt()); + level.put(entry.getKey(), value.get("level").getAsInt()); + } - // Load profession exp and levels - for (Entry entry : obj.entrySet()) - if (MMOCore.plugin.professionManager.has(entry.getKey())) { - JsonObject value = entry.getValue().getAsJsonObject(); - exp.put(entry.getKey(), value.get("exp").getAsInt()); - level.put(entry.getKey(), value.get("level").getAsInt()); - } + // Load times claimed + if (obj.has("timesClaimed")) + for (Entry entry : obj.getAsJsonObject("timesClaimed").entrySet()) + playerData.setProfessionExpItemClaims(entry.getKey(), entry.getValue().getAsInt()); + } - // Load times claimed - if (obj.has("timesClaimed")) - for (Entry entry : obj.getAsJsonObject("timesClaimed").entrySet()) - timesClaimed.put(entry.getKey(), entry.getValue().getAsInt()); - } + public PlayerData getPlayerData() { + return playerData; + } - public PlayerData getPlayerData() { - return playerData; - } + public int getLevel(String profession) { + return Math.max(1, level.getOrDefault(profession, 1)); + } - public int getLevel(String profession) { - return Math.max(1, level.getOrDefault(profession, 1)); - } + public int getLevel(Profession profession) { + return getLevel(profession.getId()); + } - public int getLevel(Profession profession) { - return getLevel(profession.getId()); - } + public int getExperience(String id) { + return exp.getOrDefault(id, 0); + } - public int getExperience(String id) { - return exp.getOrDefault(id, 0); - } + public int getExperience(Profession profession) { + return getExperience(profession.getId()); + } - public int getExperience(Profession profession) { - return getExperience(profession.getId()); - } + public int getLevelUpExperience(Profession profession) { + return profession.getExpCurve().getExperience(getLevel(profession) + 1); + } - public int getLevelUpExperience(Profession profession) { - return profession.getExpCurve().getExperience(getLevel(profession) + 1); - } + public int getLevelUpExperience(String id) { + return MMOCore.plugin.professionManager.has(id) ? MMOCore.plugin.professionManager.get(id).getExpCurve().getExperience(getLevel(id) + 1) : 0; + } - public int getLevelUpExperience(String id) { - return MMOCore.plugin.professionManager.has(id) ? MMOCore.plugin.professionManager.get(id).getExpCurve().getExperience(getLevel(id) + 1) : 0; - } + public void setLevel(Profession profession, int value) { + level.put(profession.getId(), value); + } - public void setLevel(Profession profession, int value) { - level.put(profession.getId(), value); - } + public void takeLevels(Profession profession, int value) { + int current = level.getOrDefault(profession.getId(), 1); + level.put(profession.getId(), Math.max(1, current - value)); + } - public void takeLevels(Profession profession, int value) { - int current = level.getOrDefault(profession.getId(), 1); - level.put(profession.getId(), Math.max(1, current - value)); - } + public void setExperience(Profession profession, int value) { + exp.put(profession.getId(), value); + } - public void setExperience(Profession profession, int value) { - exp.put(profession.getId(), value); - } + public void giveLevels(Profession profession, int value, EXPSource source) { + int total = 0, level = getLevel(profession); + while (value-- > 0) + total += profession.getExpCurve().getExperience(level + value + 1); + giveExperience(profession, total, source); + } - public void giveLevels(Profession profession, int value, EXPSource source) { - int total = 0, level = getLevel(profession); - while (value-- > 0) - total += profession.getExpCurve().getExperience(level + value + 1); - giveExperience(profession, total, source); - } + public void giveExperience(Profession profession, int value, EXPSource source) { + giveExperience(profession, value, source, null); + } - public void giveExperience(Profession profession, int value, EXPSource source) { - giveExperience(profession, value, source, null); - } + public boolean hasReachedMaxLevel(Profession profession) { + return profession.hasMaxLevel() && getLevel(profession) >= profession.getMaxLevel(); + } - public boolean hasReachedMaxLevel(Profession profession) { - return profession.hasMaxLevel() && getLevel(profession) >= profession.getMaxLevel(); - } - - public void giveExperience(Profession profession, double value, EXPSource source, @Nullable Location hologramLocation) { + public void giveExperience(Profession profession, double value, EXPSource source, @Nullable Location hologramLocation) { Validate.isTrue(playerData.isOnline(), "Cannot give experience to offline player"); if (hasReachedMaxLevel(profession)) { - setExperience(profession, 0); - return; - } + setExperience(profession, 0); + return; + } - value = MMOCore.plugin.boosterManager.calculateExp(profession, value); + value = MMOCore.plugin.boosterManager.calculateExp(profession, value); - // display hologram - if (hologramLocation != null ) - MMOCoreUtils.displayIndicator(hologramLocation.add(.5, 1.5, .5), MMOCore.plugin.configManager.getSimpleMessage("exp-hologram", "exp", "" + value).message()); + // Display hologram + if (hologramLocation != null) + MMOCoreUtils.displayIndicator(hologramLocation.add(.5, 1.5, .5), MMOCore.plugin.configManager.getSimpleMessage("exp-hologram", "exp", "" + value).message()); - PlayerExperienceGainEvent event = new PlayerExperienceGainEvent(playerData, profession, (int) value, source); - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) - return; + PlayerExperienceGainEvent event = new PlayerExperienceGainEvent(playerData, profession, (int) value, source); + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) + return; - exp.put(profession.getId(), exp.containsKey(profession.getId()) ? exp.get(profession.getId()) + event.getExperience() : event.getExperience()); - int needed, exp, level, oldLevel = getLevel(profession); + exp.put(profession.getId(), exp.containsKey(profession.getId()) ? exp.get(profession.getId()) + event.getExperience() : event.getExperience()); + int needed, exp, level, oldLevel = getLevel(profession); - /* - * loop for exp overload when leveling up, will continue looping until - * exp is 0 or max level has been reached - */ - boolean check = false; - while ((exp = this.exp.get(profession.getId())) >= (needed = profession.getExpCurve().getExperience((level = getLevel(profession)) + 1))) { - if (hasReachedMaxLevel(profession)) { - setExperience(profession, 0); - check = true; - break; - } + /* + * Loop for exp overload when leveling up, will continue + * looping until exp is 0 or max level has been reached + */ + boolean check = false; + while ((exp = this.exp.get(profession.getId())) >= (needed = profession.getExpCurve().getExperience((level = getLevel(profession)) + 1))) { + if (hasReachedMaxLevel(profession)) { + setExperience(profession, 0); + check = true; + break; + } - this.exp.put(profession.getId(), exp - needed); - this.level.put(profession.getId(), level + 1); - check = true; - playerData.giveExperience((int) profession.getExperience().calculate(level), null); - } + this.exp.put(profession.getId(), exp - needed); + this.level.put(profession.getId(), level + 1); + check = true; + playerData.giveExperience((int) profession.getExperience().calculate(level), null); + } - if (check) { - Bukkit.getPluginManager().callEvent(new PlayerLevelUpEvent(playerData, profession, oldLevel, level)); - new SmallParticleEffect(playerData.getPlayer(), Particle.SPELL_INSTANT); - new ConfigMessage("profession-level-up").addPlaceholders("level", "" + level, "profession", profession.getName()) - .send(playerData.getPlayer()); - MMOCore.plugin.soundManager.getSound(SoundEvent.LEVEL_UP).playTo(playerData.getPlayer()); - playerData.getStats().updateStats(); + if (check) { + Bukkit.getPluginManager().callEvent(new PlayerLevelUpEvent(playerData, profession, oldLevel, level)); + new SmallParticleEffect(playerData.getPlayer(), Particle.SPELL_INSTANT); + new ConfigMessage("profession-level-up").addPlaceholders("level", "" + level, "profession", profession.getName()) + .send(playerData.getPlayer()); + MMOCore.plugin.soundManager.getSound(SoundEvent.LEVEL_UP).playTo(playerData.getPlayer()); + playerData.getStats().updateStats(); - // Apply profession experience table - if (profession.hasExperienceTable()) - profession.getExperienceTable().claim(playerData, level, this); - } + // Apply profession experience table + if (profession.hasExperienceTable()) + profession.getExperienceTable().claim(playerData, level, profession); + } - StringBuilder bar = new StringBuilder("" + ChatColor.BOLD); - int chars = (int) ((double) exp / needed * 20); - for (int j = 0; j < 20; j++) - bar.append(j == chars ? "" + ChatColor.WHITE + ChatColor.BOLD : "").append("|"); - if (playerData.isOnline()) - MMOCore.plugin.configManager.getSimpleMessage("exp-notification", "profession", profession.getName(), "progress", bar.toString(), "ratio", - MythicLib.plugin.getMMOConfig().decimal.format((double) exp / needed * 100)).send(playerData.getPlayer()); - } - - /** - * @return The amount of times that specific experience item was claimed by the player - */ - public int getTimesClaimed(ExperienceTable table, ExperienceItem item) { - String path = table.getId() + "." + item.getId(); - return timesClaimed.getOrDefault(path, 0); - } - - /** - * See {@link #getTimesClaimed(ExperienceTable, ExperienceItem)} - */ - public void setTimesClaimed(ExperienceTable table, ExperienceItem item, int timesClaimed) { - String path = table.getId() + "." + item.getId(); - this.timesClaimed.put(path, timesClaimed); + StringBuilder bar = new StringBuilder("" + ChatColor.BOLD); + int chars = (int) ((double) exp / needed * 20); + for (int j = 0; j < 20; j++) + bar.append(j == chars ? "" + ChatColor.WHITE + ChatColor.BOLD : "").append("|"); + if (playerData.isOnline()) + MMOCore.plugin.configManager.getSimpleMessage("exp-notification", "profession", profession.getName(), "progress", bar.toString(), "ratio", + MythicLib.plugin.getMMOConfig().decimal.format((double) exp / needed * 100)).send(playerData.getPlayer()); } } diff --git a/src/main/java/net/Indyuce/mmocore/experience/Profession.java b/src/main/java/net/Indyuce/mmocore/experience/Profession.java index 5e21b814..12e10f5d 100644 --- a/src/main/java/net/Indyuce/mmocore/experience/Profession.java +++ b/src/main/java/net/Indyuce/mmocore/experience/Profession.java @@ -16,15 +16,16 @@ import java.util.Map; import java.util.Objects; import java.util.logging.Level; -public class Profession { +public class Profession implements ExperienceObject { private final String id, name; - private final ExpCurve expCurve; private final int maxLevel; private final Map options = new HashMap<>(); + private final ExpCurve expCurve; private final ExperienceTable expTable; /** - * Experience given to the main player level whenever he levels up this profession + * Experience given to the main player level + * whenever he levels up this profession */ private final LinearValue experience; @@ -41,7 +42,7 @@ public class Profession { ExperienceTable expTable = null; if (config.contains("exp-table")) try { - expTable = loadExperienceTable(config.get("exp-table")); + expTable = MMOCore.plugin.experience.loadExperienceTable(config.get("exp-table")); } catch (RuntimeException exception) { MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load exp table from profession '" + id + "': " + exception.getMessage()); } @@ -73,16 +74,7 @@ public class Profession { MMOCore.plugin.professionManager.loadProfessionConfigurations(this, config); } - private ExperienceTable loadExperienceTable(Object obj) { - if (obj instanceof ConfigurationSection) - return new ExperienceTable((ConfigurationSection) obj); - - if (obj instanceof String) - return MMOCore.plugin.experience.getTableOrThrow(obj.toString()); - - throw new IllegalArgumentException("Please provide either a string (exp table name) or a config section (locally define an exp table)"); - } public boolean getOption(ProfessionOption option) { return options.getOrDefault(option, option.getDefault()); @@ -96,6 +88,12 @@ public class Profession { return name; } + @Override + public String geyKey() { + return "profession." + getId(); + } + + @Override public ExpCurve getExpCurve() { return expCurve; } diff --git a/src/main/java/net/Indyuce/mmocore/experience/droptable/ExperienceTable.java b/src/main/java/net/Indyuce/mmocore/experience/droptable/ExperienceTable.java index 9501bea0..e4dbd0d3 100644 --- a/src/main/java/net/Indyuce/mmocore/experience/droptable/ExperienceTable.java +++ b/src/main/java/net/Indyuce/mmocore/experience/droptable/ExperienceTable.java @@ -2,7 +2,7 @@ package net.Indyuce.mmocore.experience.droptable; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; -import net.Indyuce.mmocore.experience.PlayerProfessions; +import net.Indyuce.mmocore.experience.ExperienceObject; import org.apache.commons.lang.Validate; import org.bukkit.configuration.ConfigurationSection; @@ -40,15 +40,15 @@ public class ExperienceTable { * * @param levelingUp Player leveling up * @param professionLevel New profession level - * @param professionData Player profession data + * @param object Either profession or class leveling up */ - public void claim(PlayerData levelingUp, int professionLevel, PlayerProfessions professionData) { + public void claim(PlayerData levelingUp, int professionLevel, ExperienceObject object) { for (ExperienceItem item : items) { - int timesClaimed = professionData.getTimesClaimed(this, item); + int timesClaimed = levelingUp.getClaims(object, this, item); if (!item.roll(professionLevel, timesClaimed)) continue; - professionData.setTimesClaimed(this, item, timesClaimed + 1); + levelingUp.setClaims(object, this, item, timesClaimed + 1); item.applyTriggers(levelingUp); } } diff --git a/src/main/java/net/Indyuce/mmocore/guild/GuildModule.java b/src/main/java/net/Indyuce/mmocore/guild/GuildModule.java index 7222fd40..0ff7be86 100644 --- a/src/main/java/net/Indyuce/mmocore/guild/GuildModule.java +++ b/src/main/java/net/Indyuce/mmocore/guild/GuildModule.java @@ -1,4 +1,8 @@ package net.Indyuce.mmocore.guild; +import net.Indyuce.mmocore.api.player.PlayerData; + public interface GuildModule { + + public AbstractGuild getGuild(PlayerData playerData); } diff --git a/src/main/java/net/Indyuce/mmocore/api/player/social/guilds/Guild.java b/src/main/java/net/Indyuce/mmocore/guild/provided/Guild.java similarity index 91% rename from src/main/java/net/Indyuce/mmocore/api/player/social/guilds/Guild.java rename to src/main/java/net/Indyuce/mmocore/guild/provided/Guild.java index da145dad..32106ae8 100644 --- a/src/main/java/net/Indyuce/mmocore/api/player/social/guilds/Guild.java +++ b/src/main/java/net/Indyuce/mmocore/guild/provided/Guild.java @@ -1,165 +1,164 @@ -package net.Indyuce.mmocore.api.player.social.guilds; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.function.Consumer; - -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; - -import net.Indyuce.mmocore.MMOCore; -import net.Indyuce.mmocore.api.ConfigMessage; -import net.Indyuce.mmocore.api.player.PlayerData; -import net.Indyuce.mmocore.api.player.social.Request; -import net.Indyuce.mmocore.gui.api.PluginInventory; -import net.Indyuce.mmocore.gui.social.guild.EditableGuildView.GuildViewInventory; -import net.Indyuce.mmocore.manager.InventoryManager; - -public class Guild { - private final GuildMembers members = new GuildMembers(); - private final Map invites = new HashMap<>(); - private final String guildId; - private final String guildName; - private final String guildTag; - - /* - * owner changes when the old owner leaves guild - */ - private UUID owner; - - public Guild(UUID owner, String name, String tag) { - this.owner = owner; - this.guildId = tag.toLowerCase(); - this.guildName = name; - this.guildTag = tag; - } - - public UUID getOwner() { - return owner; - } - - public String getName() { - return guildName; - } - - public String getId() { - return guildId; - } - - public String getTag() { - return guildTag; - } - - public GuildMembers getMembers() { - return members; - } - - public long getLastInvite(Player player) { - return invites.containsKey(player.getUniqueId()) ? invites.get(player.getUniqueId()) : 0; - } - - public void removeLastInvite(Player player) { - invites.remove(player.getUniqueId()); - } - - public void removeMember(UUID uuid) - { removeMember(uuid, false); } - - // Disband boolean is to prevent co-modification exception when disbanding a guild - public void removeMember(UUID uuid, boolean disband) { - PlayerData data = PlayerData.get(uuid); - if (data != null && data.isOnline() && data.getPlayer().getOpenInventory() != null && data.getPlayer().getOpenInventory().getTopInventory().getHolder() instanceof GuildViewInventory) - InventoryManager.GUILD_CREATION.newInventory(data).open(); - - if(!disband) members.remove(uuid); - if(data != null) data.setGuild(null); - reopenInventories(); - - //if(!disband) { - - // disband the guild if no member left - if (members.count() < 1) { - MMOCore.plugin.dataProvider.getGuildManager().unregisterGuild(this); - return; - } - - // transfer ownership - if (owner.equals(uuid)) { - owner = members.get(0); - MMOCore.plugin.configManager.getSimpleMessage("transfer-guild-ownership").send(Bukkit.getPlayer(owner)); - } - //} - } - - public void addMember(UUID uuid) { - PlayerData data = PlayerData.get(uuid); - if (data.inGuild()) - data.getGuild().removeMember(uuid); - - data.setGuild(this); - members.add(uuid); - - reopenInventories(); - } - - public void registerMember(UUID uuid) { - members.add(uuid); - } - - public void reopenInventories() { - for (UUID uuid : members.members) { - PlayerData member = PlayerData.get(uuid); - if (member != null && member.isOnline() && member.getPlayer().getOpenInventory() != null && member.getPlayer().getOpenInventory().getTopInventory().getHolder() instanceof GuildViewInventory) - ((PluginInventory) member.getPlayer().getOpenInventory().getTopInventory().getHolder()).open(); - } - } - - public void sendGuildInvite(PlayerData inviter, PlayerData target) { - invites.put(target.getUniqueId(), System.currentTimeMillis()); - Request request = new GuildInvite(this, inviter, target); - new ConfigMessage("guild-invite").addPlaceholders("player", inviter.getPlayer().getName(), "uuid", request.getUniqueId().toString()).sendAsJSon(target.getPlayer()); - MMOCore.plugin.requestManager.registerRequest(request); - } - - public static class GuildMembers { - private final List members = new ArrayList<>(); - - public UUID get(int count) { - return members.get(count); - } - - public boolean has(UUID player) { - return members.contains(player); - } - - public void add(UUID player) { - members.add(player); - } - - public void remove(UUID player) { - members.remove(player); - } - - public void forEach(Consumer action) { - members.forEach(action); - } - - public int countOnline() { - int online = 0; - - for(UUID member : members) - if(Bukkit.getOfflinePlayer(member).isOnline()) - online += 1; - - return online; - } - - public int count() - { return members.size(); } - public void clear() - { members.clear(); } - } -} +package net.Indyuce.mmocore.guild.provided; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.function.Consumer; + +import net.Indyuce.mmocore.guild.AbstractGuild; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import net.Indyuce.mmocore.MMOCore; +import net.Indyuce.mmocore.api.ConfigMessage; +import net.Indyuce.mmocore.api.player.PlayerData; +import net.Indyuce.mmocore.api.player.social.Request; +import net.Indyuce.mmocore.gui.api.PluginInventory; +import net.Indyuce.mmocore.gui.social.guild.EditableGuildView.GuildViewInventory; +import net.Indyuce.mmocore.manager.InventoryManager; + +public class Guild implements AbstractGuild { + private final GuildMembers members = new GuildMembers(); + private final Map invites = new HashMap<>(); + private final String guildId, guildName, guildTag; + + /** + * Owner changes when the old owner leaves guild + */ + private UUID owner; + + public Guild(UUID owner, String name, String tag) { + this.owner = owner; + this.guildId = tag.toLowerCase(); + this.guildName = name; + this.guildTag = tag; + } + + public UUID getOwner() { + return owner; + } + + public String getName() { + return guildName; + } + + public String getId() { + return guildId; + } + + public String getTag() { + return guildTag; + } + + public GuildMembers getMembers() { + return members; + } + + public long getLastInvite(Player player) { + return invites.containsKey(player.getUniqueId()) ? invites.get(player.getUniqueId()) : 0; + } + + public void removeLastInvite(Player player) { + invites.remove(player.getUniqueId()); + } + + public void removeMember(UUID uuid) + { removeMember(uuid, false); } + + // Disband boolean is to prevent co-modification exception when disbanding a guild + public void removeMember(UUID uuid, boolean disband) { + PlayerData data = PlayerData.get(uuid); + if (data != null && data.isOnline() && data.getPlayer().getOpenInventory() != null && data.getPlayer().getOpenInventory().getTopInventory().getHolder() instanceof GuildViewInventory) + InventoryManager.GUILD_CREATION.newInventory(data).open(); + + if(!disband) members.remove(uuid); + if(data != null) data.setGuild(null); + reopenInventories(); + + //if(!disband) { + + // disband the guild if no member left + if (members.count() < 1) { + MMOCore.plugin.dataProvider.getGuildManager().unregisterGuild(this); + return; + } + + // transfer ownership + if (owner.equals(uuid)) { + owner = members.get(0); + MMOCore.plugin.configManager.getSimpleMessage("transfer-guild-ownership").send(Bukkit.getPlayer(owner)); + } + //} + } + + public void addMember(UUID uuid) { + PlayerData data = PlayerData.get(uuid); + if (data.inGuild()) + data.getGuild().removeMember(uuid); + + data.setGuild(this); + members.add(uuid); + + reopenInventories(); + } + + public void registerMember(UUID uuid) { + members.add(uuid); + } + + public void reopenInventories() { + for (UUID uuid : members.members) { + PlayerData member = PlayerData.get(uuid); + if (member != null && member.isOnline() && member.getPlayer().getOpenInventory() != null && member.getPlayer().getOpenInventory().getTopInventory().getHolder() instanceof GuildViewInventory) + ((PluginInventory) member.getPlayer().getOpenInventory().getTopInventory().getHolder()).open(); + } + } + + public void sendGuildInvite(PlayerData inviter, PlayerData target) { + invites.put(target.getUniqueId(), System.currentTimeMillis()); + Request request = new GuildInvite(this, inviter, target); + new ConfigMessage("guild-invite").addPlaceholders("player", inviter.getPlayer().getName(), "uuid", request.getUniqueId().toString()).sendAsJSon(target.getPlayer()); + MMOCore.plugin.requestManager.registerRequest(request); + } + + public static class GuildMembers { + private final List members = new ArrayList<>(); + + public UUID get(int count) { + return members.get(count); + } + + public boolean has(UUID player) { + return members.contains(player); + } + + public void add(UUID player) { + members.add(player); + } + + public void remove(UUID player) { + members.remove(player); + } + + public void forEach(Consumer action) { + members.forEach(action); + } + + public int countOnline() { + int online = 0; + + for(UUID member : members) + if(Bukkit.getOfflinePlayer(member).isOnline()) + online += 1; + + return online; + } + + public int count() + { return members.size(); } + public void clear() + { members.clear(); } + } +} diff --git a/src/main/java/net/Indyuce/mmocore/api/player/social/guilds/GuildInvite.java b/src/main/java/net/Indyuce/mmocore/guild/provided/GuildInvite.java similarity index 96% rename from src/main/java/net/Indyuce/mmocore/api/player/social/guilds/GuildInvite.java rename to src/main/java/net/Indyuce/mmocore/guild/provided/GuildInvite.java index fb8ff833..3db014dc 100644 --- a/src/main/java/net/Indyuce/mmocore/api/player/social/guilds/GuildInvite.java +++ b/src/main/java/net/Indyuce/mmocore/guild/provided/GuildInvite.java @@ -1,4 +1,4 @@ -package net.Indyuce.mmocore.api.player.social.guilds; +package net.Indyuce.mmocore.guild.provided; import org.bukkit.Bukkit; diff --git a/src/main/java/net/Indyuce/mmocore/guild/provided/MMOCoreGuildModule.java b/src/main/java/net/Indyuce/mmocore/guild/provided/MMOCoreGuildModule.java new file mode 100644 index 00000000..6c23397a --- /dev/null +++ b/src/main/java/net/Indyuce/mmocore/guild/provided/MMOCoreGuildModule.java @@ -0,0 +1,13 @@ +package net.Indyuce.mmocore.guild.provided; + +import net.Indyuce.mmocore.api.player.PlayerData; +import net.Indyuce.mmocore.guild.AbstractGuild; +import net.Indyuce.mmocore.guild.GuildModule; + +public class MMOCoreGuildModule implements GuildModule { + + @Override + public AbstractGuild getGuild(PlayerData playerData) { + return playerData.getGuild(); + } +} diff --git a/src/main/java/net/Indyuce/mmocore/manager/ExperienceManager.java b/src/main/java/net/Indyuce/mmocore/manager/ExperienceManager.java index c52a56a7..8fe36b42 100644 --- a/src/main/java/net/Indyuce/mmocore/manager/ExperienceManager.java +++ b/src/main/java/net/Indyuce/mmocore/manager/ExperienceManager.java @@ -7,6 +7,7 @@ import net.Indyuce.mmocore.experience.droptable.ExperienceTable; import net.Indyuce.mmocore.experience.source.type.ExperienceSource; import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager; import org.apache.commons.lang.Validate; +import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.event.HandlerList; @@ -58,6 +59,18 @@ public class ExperienceManager implements MMOCoreManager { return Objects.requireNonNull(expTables.get(id), "Could not find exp table with ID '" + id + "'"); } + @Deprecated + public ExperienceTable loadExperienceTable(Object obj) { + + if (obj instanceof ConfigurationSection) + return new ExperienceTable((ConfigurationSection) obj); + + if (obj instanceof String) + return MMOCore.plugin.experience.getTableOrThrow(obj.toString()); + + throw new IllegalArgumentException("Please provide either a string (exp table name) or a config section (locally define an exp table)"); + } + public Collection getCurves() { return expCurves.values(); } diff --git a/src/main/java/net/Indyuce/mmocore/manager/data/DataProvider.java b/src/main/java/net/Indyuce/mmocore/manager/data/DataProvider.java index f1afaf38..1114a86a 100644 --- a/src/main/java/net/Indyuce/mmocore/manager/data/DataProvider.java +++ b/src/main/java/net/Indyuce/mmocore/manager/data/DataProvider.java @@ -1,14 +1,15 @@ package net.Indyuce.mmocore.manager.data; +/** + * Used to separate MySQL data storage from YAML data storage. + *

+ * There is one data provider per storage mecanism (one for YAML, one for MySQL). + * A data provider provides corresponding MMOManagers to correctly save and load + * data + */ 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 getDataManager(); - PlayerDataManager getDataManager(); - GuildDataManager getGuildManager(); + GuildDataManager getGuildManager(); } diff --git a/src/main/java/net/Indyuce/mmocore/manager/data/GuildDataManager.java b/src/main/java/net/Indyuce/mmocore/manager/data/GuildDataManager.java index 93da635a..cedf04aa 100644 --- a/src/main/java/net/Indyuce/mmocore/manager/data/GuildDataManager.java +++ b/src/main/java/net/Indyuce/mmocore/manager/data/GuildDataManager.java @@ -9,7 +9,7 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.FileConfiguration; import net.Indyuce.mmocore.api.ConfigFile; -import net.Indyuce.mmocore.api.player.social.guilds.Guild; +import net.Indyuce.mmocore.guild.provided.Guild; public abstract class GuildDataManager { protected final Map guilds = new HashMap<>(); @@ -39,14 +39,6 @@ public abstract class GuildDataManager { delete(guild); } - // TODO has nothing to do here - public Guild stillInGuild(UUID uuid, String id) { - Guild guild = getGuild(id); - if (guild != null && guild.getMembers().has(uuid)) - return guild; - return null; - } - public Guild getGuild(String guild) { return guilds.get(guild); } diff --git a/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java b/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java index 4c951239..20549d26 100644 --- a/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java +++ b/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java @@ -138,7 +138,7 @@ public abstract class PlayerDataManager { */ public abstract void saveData(PlayerData data); - public static class DefaultPlayerData { + public class DefaultPlayerData { private final int level, classPoints, skillPoints, attributePoints, attrReallocPoints; public DefaultPlayerData(ConfigurationSection config) { diff --git a/src/main/java/net/Indyuce/mmocore/manager/data/mysql/MySQLGuildDataManager.java b/src/main/java/net/Indyuce/mmocore/manager/data/mysql/MySQLGuildDataManager.java deleted file mode 100644 index 4688a0b2..00000000 --- a/src/main/java/net/Indyuce/mmocore/manager/data/mysql/MySQLGuildDataManager.java +++ /dev/null @@ -1,49 +0,0 @@ -package net.Indyuce.mmocore.manager.data.mysql; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; - -import net.Indyuce.mmocore.MMOCore; -import net.Indyuce.mmocore.api.ConfigFile; -import net.Indyuce.mmocore.api.player.social.guilds.Guild; -import net.Indyuce.mmocore.manager.data.GuildDataManager; - -public class MySQLGuildDataManager extends GuildDataManager { - @Override - public void save(Guild guild) { - ConfigFile config = new ConfigFile(guild); - config.getConfig().set("name", guild.getName()); - config.getConfig().set("tag", guild.getTag()); - config.getConfig().set("owner", guild.getOwner().toString()); - - List memberList = new ArrayList<>(); - guild.getMembers().forEach(uuid -> memberList.add(uuid.toString())); - config.getConfig().set("members", memberList); - - config.save(); - } - - @Override - public void load() { - File guildsFolder = new File(MMOCore.plugin.getDataFolder(), "guilds"); - if(!guildsFolder.exists()) guildsFolder.mkdirs(); - for (File file : guildsFolder.listFiles()) { - if (!file.isDirectory() && file.getName().substring(file.getName().lastIndexOf('.')).equalsIgnoreCase(".yml")) { - FileConfiguration c = YamlConfiguration.loadConfiguration(file); - Guild guild = newRegisteredGuild(UUID.fromString(c.getString("owner")), c.getString("name"), c.getString("tag")); - for(String m : c.getStringList("members")) - guild.registerMember(UUID.fromString(m)); - } - } - } - - @Override - public void delete(Guild guild) { - new ConfigFile(guild).delete(); - } -} diff --git a/src/main/java/net/Indyuce/mmocore/manager/data/mysql/MySQLPlayerDataManager.java b/src/main/java/net/Indyuce/mmocore/manager/data/mysql/MySQLPlayerDataManager.java index d001d09d..1d09f87a 100644 --- a/src/main/java/net/Indyuce/mmocore/manager/data/mysql/MySQLPlayerDataManager.java +++ b/src/main/java/net/Indyuce/mmocore/manager/data/mysql/MySQLPlayerDataManager.java @@ -2,26 +2,22 @@ package net.Indyuce.mmocore.manager.data.mysql; import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import io.lumine.mythic.lib.MythicLib; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.OfflinePlayerData; 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; +import net.Indyuce.mmocore.guild.provided.Guild; import net.Indyuce.mmocore.manager.data.PlayerDataManager; import net.Indyuce.mmocore.manager.data.mysql.MySQLTableEditor.Table; -import io.lumine.mythic.lib.MythicLib; import org.apache.commons.lang.Validate; import org.jetbrains.annotations.NotNull; -import java.sql.ResultSet; import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; +import java.util.*; import java.util.Map.Entry; -import java.util.UUID; import java.util.logging.Level; import java.util.stream.Collectors; @@ -73,8 +69,10 @@ public class MySQLPlayerDataManager extends PlayerDataManager { data.setStellium(data.getStats().getStat(StatType.MAX_STELLIUM)); } - if (!isEmpty(result.getString("guild"))) - data.setGuild(MMOCore.plugin.dataProvider.getGuildManager().stillInGuild(data.getUniqueId(), result.getString("guild"))); + if (!isEmpty(result.getString("guild"))) { + Guild guild = provider.getGuildManager().getGuild(result.getString("guild")); + data.setGuild(guild.getMembers().has(data.getUniqueId()) ? guild : null); + } if (!isEmpty(result.getString("attributes"))) data.getAttributes().load(result.getString("attributes")); if (!isEmpty(result.getString("professions"))) data.getCollectionSkills().load(result.getString("professions")); diff --git a/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLDataProvider.java b/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLDataProvider.java index bcf89817..d6ea6a2b 100644 --- a/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLDataProvider.java +++ b/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLDataProvider.java @@ -5,7 +5,7 @@ import net.Indyuce.mmocore.manager.data.GuildDataManager; import net.Indyuce.mmocore.manager.data.PlayerDataManager; public class YAMLDataProvider implements DataProvider { - private final YAMLPlayerDataManager playerManager = new YAMLPlayerDataManager(); + private final YAMLPlayerDataManager playerManager = new YAMLPlayerDataManager(this); private final YAMLGuildDataManager guildManager = new YAMLGuildDataManager(); @Override diff --git a/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLGuildDataManager.java b/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLGuildDataManager.java index 26fd8559..8c4e0808 100644 --- a/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLGuildDataManager.java +++ b/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLGuildDataManager.java @@ -10,7 +10,7 @@ import org.bukkit.configuration.file.YamlConfiguration; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.ConfigFile; -import net.Indyuce.mmocore.api.player.social.guilds.Guild; +import net.Indyuce.mmocore.guild.provided.Guild; import net.Indyuce.mmocore.manager.data.GuildDataManager; public class YAMLGuildDataManager extends GuildDataManager { diff --git a/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLOfflinePlayerData.java b/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLOfflinePlayerData.java index edc5f122..c2eb4047 100644 --- a/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLOfflinePlayerData.java +++ b/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLOfflinePlayerData.java @@ -11,8 +11,8 @@ import net.Indyuce.mmocore.api.player.profess.PlayerClass; public class YAMLOfflinePlayerData extends OfflinePlayerData { private final ConfigFile config; - /* - * supports offline player data operations like friend removals which can't + /** + * Supports offline player data operations like friend removals which can't * be handled when their player data is not loaded in the data map. */ public YAMLOfflinePlayerData(UUID uuid) { diff --git a/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLPlayerDataManager.java b/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLPlayerDataManager.java index 72d7e5ec..d4f64dc7 100644 --- a/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLPlayerDataManager.java +++ b/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLPlayerDataManager.java @@ -1,14 +1,5 @@ package net.Indyuce.mmocore.manager.data.yaml; -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.OfflinePlayerData; @@ -16,10 +7,25 @@ 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; +import net.Indyuce.mmocore.guild.provided.Guild; +import net.Indyuce.mmocore.manager.data.DataProvider; import net.Indyuce.mmocore.manager.data.PlayerDataManager; +import org.apache.commons.lang.Validate; +import org.bukkit.configuration.file.FileConfiguration; import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.logging.Level; +import java.util.stream.Collectors; + public class YAMLPlayerDataManager extends PlayerDataManager { + private final DataProvider provider; + + public YAMLPlayerDataManager(DataProvider provider) { + this.provider = provider; + } @Override public void loadData(PlayerData data) { @@ -40,8 +46,10 @@ public class YAMLPlayerDataManager extends PlayerDataManager { data.setStellium(data.getStats().getStat(StatType.MAX_STELLIUM)); } - if (config.contains("guild")) - data.setGuild(MMOCore.plugin.dataProvider.getGuildManager().stillInGuild(data.getUniqueId(), config.getString("guild"))); + if (config.contains("guild")) { + Guild guild = provider.getGuildManager().getGuild(config.getString("guild")); + data.setGuild(guild.getMembers().has(data.getUniqueId()) ? guild : null); + } if (config.contains("attribute")) data.getAttributes().load(config.getConfigurationSection("attribute")); if (config.contains("profession")) diff --git a/src/main/java/net/Indyuce/mmocore/tree/IntegerCoordinates.java b/src/main/java/net/Indyuce/mmocore/tree/IntegerCoordinates.java new file mode 100644 index 00000000..f5bb5427 --- /dev/null +++ b/src/main/java/net/Indyuce/mmocore/tree/IntegerCoordinates.java @@ -0,0 +1,48 @@ +package net.Indyuce.mmocore.tree; + +import org.apache.commons.lang.Validate; + +import java.util.Objects; + +public class IntegerCoordinates { + private final int x, y; + + public IntegerCoordinates(int x, int y) { + this.x = x; + this.y = y; + } + + @Deprecated + public IntegerCoordinates(String str) { + String[] split = str.split("\\."); + Validate.isTrue(split.length == 2, "Invalid format"); + x = Integer.parseInt(split[0]); + y = Integer.parseInt(split[1]); + } + + public int getX() { + return x; + } + + public int getY() { + return y; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + IntegerCoordinates that = (IntegerCoordinates) o; + return x == that.x && y == that.y; + } + + @Override + public int hashCode() { + return Objects.hash(x, y); + } + + @Override + public String toString() { + return x + "." + y; + } +} diff --git a/src/main/java/net/Indyuce/mmocore/tree/SkillTree.java b/src/main/java/net/Indyuce/mmocore/tree/SkillTree.java new file mode 100644 index 00000000..d372be11 --- /dev/null +++ b/src/main/java/net/Indyuce/mmocore/tree/SkillTree.java @@ -0,0 +1,71 @@ +package net.Indyuce.mmocore.tree; + +import net.Indyuce.mmocore.MMOCore; +import org.apache.commons.lang.Validate; +import org.bukkit.configuration.ConfigurationSection; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.logging.Level; + +/** + * A passive skill tree that features nodes, or passive skills. + *

+ * The player can explore the passive skill tree using the right GUI + * and unlock nodes by spending passive skill points. Unlocking nodes + * grant permanent player modifiers, including + * - stats + * - active or passive MythicLib skills + * - active or passive MMOCore skills + * - extra attribute pts + * - particle or potion effects + * + * @author jules + * @see {@link SkillTreeNode} + */ +public class SkillTree { + private final String id, name; + private final Map nodes = new HashMap<>(); + + public SkillTree(ConfigurationSection config) { + this.id = config.getName(); + this.name = Objects.requireNonNull(config.getString("name"), "Could not find skill tree name"); + Validate.isTrue(config.isConfigurationSection("nodes"), "Could not find tree passive skills"); + for (String xKey : config.getConfigurationSection("nodes").getKeys(false)) + for (String yKey : config.getConfigurationSection("nodes." + xKey).getKeys(false)) + try { + int x = Integer.parseInt(xKey), y = Integer.parseInt(yKey); + SkillTreeNode node = new SkillTreeNode(this, x, y, config.getConfigurationSection("nodes." + xKey + "." + yKey)); + nodes.put(node.getCoordinates(), node); + } catch (RuntimeException exception) { + MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load tree node '" + xKey + "." + yKey + "' for skill tree '" + id + "': " + exception.getMessage()); + } + } + + public String getId() { + return id; + } + + public String getName() { + return name; + } + + public Collection getNodes() { + return nodes.values(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + SkillTree skillTree = (SkillTree) o; + return id.equals(skillTree.id); + } + + @Override + public int hashCode() { + return Objects.hash(id); + } +} diff --git a/src/main/java/net/Indyuce/mmocore/tree/SkillTreeNode.java b/src/main/java/net/Indyuce/mmocore/tree/SkillTreeNode.java new file mode 100644 index 00000000..2ef69251 --- /dev/null +++ b/src/main/java/net/Indyuce/mmocore/tree/SkillTreeNode.java @@ -0,0 +1,70 @@ +package net.Indyuce.mmocore.tree; + +import io.lumine.mythic.lib.MythicLib; +import io.lumine.mythic.lib.player.modifier.PlayerModifier; +import io.lumine.mythic.lib.util.configobject.ConfigSectionObject; +import net.Indyuce.mmocore.api.player.Unlockable; +import org.apache.commons.lang.Validate; +import org.bukkit.configuration.ConfigurationSection; + +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Set; + +public class SkillTreeNode implements Unlockable { + private final SkillTree tree; + private final String name; + private final IntegerCoordinates coordinates; + private final List lore; + private final Set modifiers = new HashSet<>(); + + public SkillTreeNode(SkillTree tree, int x, int y, ConfigurationSection config) { + Validate.notNull(config, "Config cannot be null"); + this.tree = tree; + name = Objects.requireNonNull(config.getString("name"), "Could not find node name"); + coordinates = new IntegerCoordinates(x, y); + lore = config.getStringList("lore"); + for (String key : config.getConfigurationSection("modifiers").getKeys(false)) { + PlayerModifier mod = MythicLib.plugin.getModifiers().loadPlayerModifier(new ConfigSectionObject(config.getConfigurationSection(key))); + modifiers.add(mod); + } + } + + public String getName() { + return name; + } + + public IntegerCoordinates getCoordinates() { + return coordinates; + } + + public Set getModifiers() { + return modifiers; + } + + /** + * @return Uncolored lore with no placeholders + */ + public List getLore() { + return lore; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + SkillTreeNode that = (SkillTreeNode) o; + return tree.equals(that.tree) && coordinates.equals(that.coordinates); + } + + @Override + public int hashCode() { + return Objects.hash(tree, coordinates); + } + + @Override + public String getUnlockNamespacedKey() { + return "skill_tree:" + tree.getId() + "_" + coordinates.getX() + "_" + coordinates.getY(); + } +}