From 547775a33e0ff9dd483e5ca7f34108448356907a Mon Sep 17 00:00:00 2001 From: Jules Date: Sat, 15 Apr 2023 00:27:58 +0200 Subject: [PATCH 01/14] Removed debug msg --- .../net/Indyuce/mmocore/skill/binding/BoundSkillInfo.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/binding/BoundSkillInfo.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/binding/BoundSkillInfo.java index 3d9683d7..35dbad71 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/binding/BoundSkillInfo.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/binding/BoundSkillInfo.java @@ -6,7 +6,6 @@ import net.Indyuce.mmocore.api.quest.trigger.SkillModifierTrigger; import net.Indyuce.mmocore.api.util.Closable; import net.Indyuce.mmocore.skill.ClassSkill; import org.apache.commons.lang.Validate; -import org.bukkit.Bukkit; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -37,7 +36,6 @@ public class BoundSkillInfo implements Closable { if (classSkill.getSkill().getTrigger().isPassive()) { registered = classSkill.toPassive(playerData); registered.register(playerData.getMMOPlayerData()); - Bukkit.broadcastMessage("Registering passive skill " + classSkill.getSkill().getHandler().getId()); } else registered = null; } @@ -66,10 +64,8 @@ public class BoundSkillInfo implements Closable { open = false; // Unregister skill if passive - if (isPassive()) { - Bukkit.broadcastMessage("Unregistered passive skill " + classSkill.getSkill().getHandler().getId()); + if (isPassive()) registered.unregister(playerData.getMMOPlayerData()); - } // Remove skill buffs associated to the slot skillSlot.getSkillBuffTriggers().forEach(skillBuffTrigger -> skillBuffTrigger.remove(playerData, classSkill.getSkill().getHandler())); From baf664a608b881983337002071c783e35dd03e02 Mon Sep 17 00:00:00 2001 From: Jules Date: Sun, 16 Apr 2023 00:56:17 +0200 Subject: [PATCH 02/14] SQL Update commit 1 --- .../java/net/Indyuce/mmocore/MMOCore.java | 41 +++-- .../api/event/AsyncPlayerDataEvent.java | 29 ---- .../api/event/AsyncPlayerDataLoadEvent.java | 27 --- .../mmocore/api/player/OfflinePlayerData.java | 32 ---- .../mmocore/api/player/PlayerData.java | 46 ++---- .../command/rpg/admin/ExportDataTreeNode.java | 13 +- .../command/rpg/admin/SaveDataTreeNode.java | 2 +- .../social/friend/EditableFriendRemoval.java | 2 +- .../gui/social/guild/EditableGuildView.java | 2 +- .../provided}/YAMLGuildDataManager.java | 2 +- .../data/AbstractOfflinePlayerData.java | 19 +++ .../mmocore/manager/data/DataProvider.java | 7 + .../manager/data/LegacyDataProvider.java | 18 ++ .../manager/data/OfflinePlayerData.java | 24 +++ .../manager/data/PlayerDataManager.java | 117 +------------ .../data/mysql/MMOCoreDataSynchronizer.java | 154 ------------------ .../manager/data/mysql/MySQLDataProvider.java | 94 ----------- .../data/sql/MMOCoreDataSynchronizer.java | 152 +++++++++++++++++ .../PlayerDataTableUpdater.java | 19 ++- .../SQLDataHandler.java} | 107 +++++++++--- .../manager/data/yaml/YAMLDataProvider.java | 20 --- .../data/yaml/YAMLOfflinePlayerData.java | 77 +++++---- ...anager.java => YAMLPlayerDataHandler.java} | 61 +++---- .../mmocore/listener/PlayerListener.java | 23 --- MMOCore-Dist/src/main/resources/config.yml | 1 + 25 files changed, 452 insertions(+), 637 deletions(-) delete mode 100644 MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/AsyncPlayerDataEvent.java delete mode 100644 MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/AsyncPlayerDataLoadEvent.java delete mode 100644 MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/OfflinePlayerData.java rename MMOCore-API/src/main/java/net/Indyuce/mmocore/{manager/data/yaml => guild/provided}/YAMLGuildDataManager.java (97%) create mode 100644 MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/AbstractOfflinePlayerData.java create mode 100644 MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/LegacyDataProvider.java create mode 100644 MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/OfflinePlayerData.java delete mode 100644 MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/mysql/MMOCoreDataSynchronizer.java delete mode 100644 MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/mysql/MySQLDataProvider.java create mode 100644 MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/MMOCoreDataSynchronizer.java rename MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/{mysql => sql}/PlayerDataTableUpdater.java (84%) rename MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/{mysql/MySQLPlayerDataManager.java => sql/SQLDataHandler.java} (68%) delete mode 100644 MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLDataProvider.java rename MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/{YAMLPlayerDataManager.java => YAMLPlayerDataHandler.java} (86%) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java index 9feb5e1c..6a0ee87d 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java @@ -2,6 +2,7 @@ package net.Indyuce.mmocore; import io.lumine.mythic.lib.MythicLib; import io.lumine.mythic.lib.UtilityMethods; +import io.lumine.mythic.lib.data.sql.SQLDataSource; import io.lumine.mythic.lib.metrics.bukkit.Metrics; import io.lumine.mythic.lib.version.SpigotPlugin; import net.Indyuce.mmocore.api.player.PlayerData; @@ -30,8 +31,11 @@ import net.Indyuce.mmocore.guild.provided.Guild; import net.Indyuce.mmocore.guild.provided.MMOCoreGuildModule; import net.Indyuce.mmocore.manager.*; import net.Indyuce.mmocore.manager.data.DataProvider; -import net.Indyuce.mmocore.manager.data.mysql.MySQLDataProvider; -import net.Indyuce.mmocore.manager.data.yaml.YAMLDataProvider; +import net.Indyuce.mmocore.manager.data.GuildDataManager; +import net.Indyuce.mmocore.manager.data.LegacyDataProvider; +import net.Indyuce.mmocore.manager.data.PlayerDataManager; +import net.Indyuce.mmocore.manager.data.sql.SQLDataHandler; +import net.Indyuce.mmocore.guild.provided.YAMLGuildDataManager; import net.Indyuce.mmocore.manager.profession.*; import net.Indyuce.mmocore.manager.social.BoosterManager; import net.Indyuce.mmocore.manager.social.PartyManager; @@ -48,6 +52,7 @@ import net.Indyuce.mmocore.skill.cast.SkillCastingMode; import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; import org.bukkit.ChatColor; +import org.bukkit.event.EventPriority; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.scheduler.BukkitRunnable; import org.jetbrains.annotations.NotNull; @@ -76,6 +81,10 @@ public class MMOCore extends JavaPlugin { public final RestrictionManager restrictionManager = new RestrictionManager(); public final SkillTreeManager skillTreeManager = new SkillTreeManager(); public final StatManager statManager = new StatManager(); + public final GuildDataManager nativeGuildManager = new YAMLGuildDataManager(); + public final PlayerDataManager playerDataManager = new PlayerDataManager(this); + @Deprecated + public final DataProvider dataProvider = new LegacyDataProvider(); // Profession managers public final CustomBlockManager mineManager = new CustomBlockManager(); @@ -89,7 +98,6 @@ public class MMOCore extends JavaPlugin { public VaultEconomy economy; public RegionHandler regionHandler = new DefaultRegionHandler(); public PlaceholderParser placeholderParser = new DefaultParser(); - public DataProvider dataProvider = new YAMLDataProvider(); // Modules @NotNull @@ -140,8 +148,10 @@ public class MMOCore extends JavaPlugin { getLogger().warning("(Your config version: '" + configVersion + "' | Expected config version: '" + defConfigVersion + "')"); } - if (getConfig().isConfigurationSection("mysql") && getConfig().getBoolean("mysql.enabled")) - dataProvider = new MySQLDataProvider(getConfig()); + if (getConfig().isConfigurationSection("mysql") && getConfig().getBoolean("mysql.enabled")) { + final SQLDataSource dataSource = new SQLDataSource(this); + playerDataManager.setDataHandler(new SQLDataHandler(dataSource)); + } if (getConfig().isConfigurationSection("default-playerdata")) dataProvider.getDataManager().loadDefaultData(getConfig().getConfigurationSection("default-playerdata")); @@ -237,6 +247,7 @@ public class MMOCore extends JavaPlugin { try { Class.forName("net.Indyuce.mmocore.MMOCoreBukkit").getConstructor(MMOCore.class).newInstance(this); } catch (Throwable exception) { + exception.printStackTrace(); throw new RuntimeException("Cannot run an API build on Spigot!"); } @@ -245,7 +256,8 @@ public class MMOCore extends JavaPlugin { * that after registering all the professses otherwise the player datas can't * recognize what profess the player has and professes will be lost */ - Bukkit.getOnlinePlayers().forEach(player -> dataProvider.getDataManager().setup(player.getUniqueId())); + playerDataManager.setupAll(); + playerDataManager.registerEvents(EventPriority.NORMAL); // load guild data after loading player data dataProvider.getGuildManager().load(); @@ -258,15 +270,17 @@ public class MMOCore extends JavaPlugin { getCommand("mmocore").setExecutor(mmoCoreCommand); getCommand("mmocore").setTabCompleter(mmoCoreCommand); - if (getConfig().getBoolean("auto-save.enabled")) { + if (getConfig().getBoolean("auto-save.enabled")) + + { int autosave = getConfig().getInt("auto-save.interval") * 20; new BukkitRunnable() { public void run() { // Save player data for (PlayerData data : PlayerData.getAll()) - if (data.isFullyLoaded()) - dataProvider.getDataManager().saveData(data, false); + if (data.isSynchronized()) + dataProvider.getDataManager().getDataHandler().saveData(data, false); // Save guild info for (Guild guild : dataProvider.getGuildManager().getAll()) @@ -288,11 +302,11 @@ public class MMOCore extends JavaPlugin { // Save player data for (PlayerData data : PlayerData.getAll()) - if (data.isFullyLoaded()) { + if (data.isSynchronized()) { data.close(); - //Saves player health before saveData as the player will be considered offline into it if it is async. + // Saves player health before saveData as the player will be considered offline into it if it is async. data.setHealth(data.getPlayer().getHealth()); - dataProvider.getDataManager().saveData(data, true); + dataProvider.getDataManager().getDataHandler().saveData(data, true); } // Save guild info @@ -300,8 +314,7 @@ public class MMOCore extends JavaPlugin { dataProvider.getGuildManager().save(guild); // Close MySQL data provider (memory leaks) - if (dataProvider instanceof MySQLDataProvider) - ((MySQLDataProvider) dataProvider).close(); + playerDataManager.getDataHandler().close(); // Reset active blocks mineManager.resetRemainingBlocks(); diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/AsyncPlayerDataEvent.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/AsyncPlayerDataEvent.java deleted file mode 100644 index 3208f5b3..00000000 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/AsyncPlayerDataEvent.java +++ /dev/null @@ -1,29 +0,0 @@ -package net.Indyuce.mmocore.api.event; - -import net.Indyuce.mmocore.api.player.PlayerData; -import org.bukkit.entity.Player; -import org.bukkit.event.Event; - -/** - * In order to create bukkit async events we must call - * the right constructor: - *

- * {@link Event#Event(boolean)} and have the boolean set to true - */ -public abstract class AsyncPlayerDataEvent extends Event { - private final PlayerData playerData; - - public AsyncPlayerDataEvent(PlayerData playerData) { - super(true); - - this.playerData = playerData; - } - - public PlayerData getData() { - return playerData; - } - - public Player getPlayer() { - return playerData.getPlayer(); - } -} diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/AsyncPlayerDataLoadEvent.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/AsyncPlayerDataLoadEvent.java deleted file mode 100644 index 4c8be27a..00000000 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/AsyncPlayerDataLoadEvent.java +++ /dev/null @@ -1,27 +0,0 @@ -package net.Indyuce.mmocore.api.event; - -import net.Indyuce.mmocore.api.player.PlayerData; -import org.bukkit.event.HandlerList; - -public class AsyncPlayerDataLoadEvent extends AsyncPlayerDataEvent { - private static final HandlerList handlers = new HandlerList(); - - /** - * Called when a player data is being loaded into the game. - * This event is called async. - * - * @param playerData Player data being loaded - */ - public AsyncPlayerDataLoadEvent(PlayerData playerData) { - super(playerData); - } - - @Override - public HandlerList getHandlers() { - return handlers; - } - - public static HandlerList getHandlerList() { - return handlers; - } -} diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/OfflinePlayerData.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/OfflinePlayerData.java deleted file mode 100644 index 308b464a..00000000 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/OfflinePlayerData.java +++ /dev/null @@ -1,32 +0,0 @@ -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 { - private final UUID uuid; - - public OfflinePlayerData(UUID uuid) { - this.uuid = uuid; - } - - public UUID getUniqueId() { - return uuid; - } - - public abstract void removeFriend(UUID uuid); - - public abstract boolean hasFriend(UUID uuid); - - public abstract PlayerClass getProfess(); - - public abstract int getLevel(); - - public abstract long getLastLogin(); - - public static OfflinePlayerData get(UUID uuid) { - return MMOCore.plugin.dataProvider.getDataManager().getOffline(uuid); - } -} diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java index 426100d4..3f4f9226 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java @@ -4,6 +4,7 @@ import io.lumine.mythic.lib.MythicLib; import io.lumine.mythic.lib.api.player.MMOPlayerData; import io.lumine.mythic.lib.api.stat.StatInstance; import io.lumine.mythic.lib.api.stat.modifier.StatModifier; +import io.lumine.mythic.lib.data.SynchronizedDataHolder; import io.lumine.mythic.lib.player.cooldown.CooldownMap; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.ConfigMessage; @@ -19,6 +20,7 @@ import net.Indyuce.mmocore.api.player.profess.PlayerClass; 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.manager.data.OfflinePlayerData; import net.Indyuce.mmocore.skill.binding.BoundSkillInfo; import net.Indyuce.mmocore.api.player.social.FriendRequest; import net.Indyuce.mmocore.api.player.stats.PlayerStats; @@ -68,14 +70,7 @@ import java.util.*; import java.util.logging.Level; import java.util.stream.Collectors; -public class PlayerData extends OfflinePlayerData implements Closable, ExperienceTableClaimer, ClassDataContainer { - - /** - * Corresponds to the MythicLib player data. It is used to keep - * track of the Player instance corresponding to that player data, - * as well as other things like the last time the player logged in/out - */ - private final MMOPlayerData mmoData; +public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerData, Closable, ExperienceTableClaimer, ClassDataContainer { /** * Can be null, the {@link #getProfess()} method will return the @@ -140,16 +135,9 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc // NON-FINAL player data stuff made public to facilitate field change public boolean noCooldown; - /** - * Player data is stored in the data map before it's actually fully loaded - * so that external plugins don't necessarily have to listen to the PlayerDataLoadEvent. - */ - private boolean fullyLoaded = false; - public PlayerData(MMOPlayerData mmoData) { - super(mmoData.getUniqueId()); + super(mmoData); - this.mmoData = mmoData; questData = new PlayerQuests(this); playerStats = new PlayerStats(this); } @@ -255,7 +243,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc } public void resetTriggerStats() { - for (StatInstance instance : mmoData.getStatMap().getInstances()) { + for (StatInstance instance : getMMOPlayerData().getStatMap().getInstances()) { Iterator iter = instance.getModifiers().iterator(); while (iter.hasNext()) { StatModifier modifier = iter.next(); @@ -459,10 +447,6 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc if (isCasting()) leaveSkillCasting(); } - public MMOPlayerData getMMOPlayerData() { - return mmoData; - } - public List getFriends() { return friends; } @@ -475,10 +459,6 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc return questData; } - public Player getPlayer() { - return mmoData.getPlayer(); - } - public long getLastActivity(PlayerActivity activity) { return this.lastActivity.getOrDefault(activity, 0l); } @@ -497,7 +477,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc @Override public long getLastLogin() { - return mmoData.getLastLogActivity(); + return getMMOPlayerData().getLastLogActivity(); } @Override @@ -592,7 +572,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc } public boolean isOnline() { - return mmoData.isOnline(); + return getMMOPlayerData().isOnline(); } public boolean inGuild() { @@ -1024,12 +1004,14 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc stellium = Math.max(0, Math.min(amount, getStats().getStat("MAX_STELLIUM"))); } + @Deprecated public boolean isFullyLoaded() { - return fullyLoaded; + return isSynchronized(); } + @Deprecated public void setFullyLoaded() { - this.fullyLoaded = true; + markAsSynchronized(); } public boolean isCasting() { @@ -1137,7 +1119,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc } public CooldownMap getCooldownMap() { - return mmoData.getCooldownMap(); + return getMMOPlayerData().getCooldownMap(); } public void setClass(@Nullable PlayerClass profess) { @@ -1230,12 +1212,12 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; PlayerData that = (PlayerData) o; - return getUniqueId().equals(that.mmoData.getUniqueId()); + return getUniqueId().equals(that.getUniqueId()); } @Override public int hashCode() { - return mmoData.hashCode(); + return getMMOPlayerData().hashCode(); } public static PlayerData get(OfflinePlayer player) { diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/ExportDataTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/ExportDataTreeNode.java index 34201898..250962cd 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/ExportDataTreeNode.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/ExportDataTreeNode.java @@ -2,9 +2,10 @@ package net.Indyuce.mmocore.command.rpg.admin; import io.lumine.mythic.lib.api.player.MMOPlayerData; import io.lumine.mythic.lib.command.api.CommandTreeNode; +import io.lumine.mythic.lib.data.sql.SQLDataSource; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; -import net.Indyuce.mmocore.manager.data.mysql.MySQLDataProvider; +import net.Indyuce.mmocore.manager.data.sql.SQLDataHandler; import org.bukkit.command.CommandSender; import org.bukkit.scheduler.BukkitRunnable; @@ -51,9 +52,9 @@ public class ExportDataTreeNode extends CommandTreeNode { .map(file -> UUID.fromString(file.getName().replace(".yml", ""))).collect(Collectors.toList()); // Initialize fake SQL data provider - final MySQLDataProvider sqlProvider; + final SQLDataHandler sqlHandler; try { - sqlProvider = new MySQLDataProvider(MMOCore.plugin.getConfig()); + sqlHandler = new SQLDataHandler(new SQLDataSource(MMOCore.plugin)); } catch (RuntimeException exception) { sender.sendMessage("Could not initialize SQL provider (see console for stack trace): " + exception.getMessage()); return CommandResult.FAILURE; @@ -80,7 +81,7 @@ public class ExportDataTreeNode extends CommandTreeNode { if (index >= playerIds.size()) { cancel(); - sqlProvider.close(); + sqlHandler.close(); MMOCore.plugin.getLogger().log(Level.WARNING, "Exported " + playerIds.size() + " player datas to SQL database. Total errors: " + errorCount); return; } @@ -88,10 +89,10 @@ public class ExportDataTreeNode extends CommandTreeNode { final UUID playerId = playerIds.get(index); try { final PlayerData offlinePlayerData = new PlayerData(new MMOPlayerData(playerId)); - MMOCore.plugin.dataProvider.getDataManager().loadData(offlinePlayerData); + MMOCore.plugin.dataProvider.getDataManager().getDataHandler().loadData(offlinePlayerData); // Player data is loaded, now it gets saved through SQL - sqlProvider.getDataManager().saveData(offlinePlayerData, true); + sqlHandler.saveData(offlinePlayerData, true); } catch (RuntimeException exception) { errorCount++; exception.printStackTrace(); diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/SaveDataTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/SaveDataTreeNode.java index 77b39237..5e389121 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/SaveDataTreeNode.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/SaveDataTreeNode.java @@ -30,7 +30,7 @@ public class SaveDataTreeNode extends CommandTreeNode { return CommandResult.FAILURE; } - MMOCore.plugin.dataProvider.getDataManager().saveData(PlayerData.get(player), false); + MMOCore.plugin.dataProvider.getDataManager().getDataHandler().saveData(PlayerData.get(player), false); return CommandResult.SUCCESS; } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/social/friend/EditableFriendRemoval.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/social/friend/EditableFriendRemoval.java index 29c9ba3e..2f07ed07 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/social/friend/EditableFriendRemoval.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/social/friend/EditableFriendRemoval.java @@ -5,7 +5,7 @@ import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.gui.api.InventoryClickContext; import net.Indyuce.mmocore.gui.api.GeneratedInventory; import net.Indyuce.mmocore.gui.api.item.InventoryItem; -import net.Indyuce.mmocore.api.player.OfflinePlayerData; +import net.Indyuce.mmocore.manager.data.OfflinePlayerData; import net.Indyuce.mmocore.gui.api.EditableInventory; import net.Indyuce.mmocore.gui.api.item.Placeholders; import org.bukkit.OfflinePlayer; diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/social/guild/EditableGuildView.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/social/guild/EditableGuildView.java index e36f48f8..797c42b9 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/social/guild/EditableGuildView.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/social/guild/EditableGuildView.java @@ -9,7 +9,7 @@ import net.Indyuce.mmocore.api.util.input.PlayerInput; import net.Indyuce.mmocore.gui.api.GeneratedInventory; import net.Indyuce.mmocore.gui.api.item.InventoryItem; import net.Indyuce.mmocore.gui.api.item.SimplePlaceholderItem; -import net.Indyuce.mmocore.api.player.OfflinePlayerData; +import net.Indyuce.mmocore.manager.data.OfflinePlayerData; import net.Indyuce.mmocore.gui.api.EditableInventory; import net.Indyuce.mmocore.gui.api.item.Placeholders; import org.apache.commons.lang.Validate; diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLGuildDataManager.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/guild/provided/YAMLGuildDataManager.java similarity index 97% rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLGuildDataManager.java rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/guild/provided/YAMLGuildDataManager.java index ab2557ce..9e863836 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLGuildDataManager.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/guild/provided/YAMLGuildDataManager.java @@ -1,4 +1,4 @@ -package net.Indyuce.mmocore.manager.data.yaml; +package net.Indyuce.mmocore.guild.provided; import java.io.File; import java.util.ArrayList; diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/AbstractOfflinePlayerData.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/AbstractOfflinePlayerData.java new file mode 100644 index 00000000..7e5455c1 --- /dev/null +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/AbstractOfflinePlayerData.java @@ -0,0 +1,19 @@ +package net.Indyuce.mmocore.manager.data; + +import net.Indyuce.mmocore.api.player.profess.PlayerClass; + +import java.util.UUID; + +public interface AbstractOfflinePlayerData { + + + public abstract void removeFriend(UUID uuid); + + public abstract boolean hasFriend(UUID uuid); + + public abstract PlayerClass getProfess(); + + public abstract int getLevel(); + + public abstract long getLastLogin(); +} diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/DataProvider.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/DataProvider.java index e992a5cd..e67f2838 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/DataProvider.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/DataProvider.java @@ -1,15 +1,22 @@ package net.Indyuce.mmocore.manager.data; +import net.Indyuce.mmocore.MMOCore; + /** * 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 + * + * @deprecated Not being used anymore, see {@link MMOCore#nativeGuildManager} and {@link MMOCore#playerDataManager} */ +@Deprecated public interface DataProvider { + @Deprecated PlayerDataManager getDataManager(); + @Deprecated GuildDataManager getGuildManager(); } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/LegacyDataProvider.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/LegacyDataProvider.java new file mode 100644 index 00000000..5c4359e0 --- /dev/null +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/LegacyDataProvider.java @@ -0,0 +1,18 @@ +package net.Indyuce.mmocore.manager.data; + + +import net.Indyuce.mmocore.MMOCore; + +@Deprecated +public class LegacyDataProvider implements DataProvider { + + @Override + public PlayerDataManager getDataManager() { + return MMOCore.plugin.playerDataManager; + } + + @Override + public GuildDataManager getGuildManager() { + return MMOCore.plugin.nativeGuildManager; + } +} diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/OfflinePlayerData.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/OfflinePlayerData.java new file mode 100644 index 00000000..1ee00c1c --- /dev/null +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/OfflinePlayerData.java @@ -0,0 +1,24 @@ +package net.Indyuce.mmocore.manager.data; + +import java.util.UUID; + +import io.lumine.mythic.lib.data.OfflineDataHolder; +import net.Indyuce.mmocore.MMOCore; +import net.Indyuce.mmocore.api.player.profess.PlayerClass; + +public interface OfflinePlayerData extends OfflineDataHolder { + + public abstract void removeFriend(UUID uuid); + + public abstract boolean hasFriend(UUID uuid); + + public abstract PlayerClass getProfess(); + + public abstract int getLevel(); + + public abstract long getLastLogin(); + + public static OfflinePlayerData get(UUID uuid) { + return MMOCore.plugin.dataProvider.getDataManager().getOffline(uuid); + } +} diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java index 882c6e3e..167569c8 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java @@ -1,102 +1,23 @@ package net.Indyuce.mmocore.manager.data; import io.lumine.mythic.lib.api.player.MMOPlayerData; +import io.lumine.mythic.lib.data.SynchronizedDataManager; import net.Indyuce.mmocore.MMOCore; -import net.Indyuce.mmocore.api.event.AsyncPlayerDataLoadEvent; -import net.Indyuce.mmocore.api.event.PlayerDataLoadEvent; -import net.Indyuce.mmocore.api.player.OfflinePlayerData; import net.Indyuce.mmocore.api.player.PlayerData; +import net.Indyuce.mmocore.manager.data.yaml.YAMLPlayerDataHandler; import net.Indyuce.mmocore.player.DefaultPlayerData; -import org.bukkit.Bukkit; -import org.bukkit.OfflinePlayer; import org.bukkit.configuration.ConfigurationSection; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.*; - -public abstract class PlayerDataManager { - private final static Map data = Collections.synchronizedMap(new HashMap<>()); +public class PlayerDataManager extends SynchronizedDataManager { private DefaultPlayerData defaultData = DefaultPlayerData.DEFAULT; - public PlayerData get(OfflinePlayer player) { - return get(player.getUniqueId()); + public PlayerDataManager(MMOCore plugin) { + super(plugin, new YAMLPlayerDataHandler(plugin)); } - /** - * Gets the player data, or throws an exception if not found. - * The player data should be loaded when the player logs in - * so it's really bad practice to setup the player data if it's not loaded. - * - * @param uuid Player UUID - * @return Player data, if it's loaded - */ - public PlayerData get(UUID uuid) { - return Objects.requireNonNull(data.get(uuid), "Player data is not loaded"); - } - - /** - * Safely unregisters the player data from the map. - * This saves the player data either through SQL or YAML, - * then closes the player data and clears it from the data map. - * - * @param playerData PLayer data to unregister - */ - public void unregisterSafe(PlayerData playerData) { - - // Close and unregister data instantly if no error occured - playerData.close(); - data.remove(playerData.getUniqueId()); - - // Save data async if required - if (playerData.isFullyLoaded()) - Bukkit.getScheduler().runTaskAsynchronously(MMOCore.plugin, () -> saveData(playerData, true)); - } - - /** - * Offline player data is used to handle processes like friend removal - * which can still occur if one of the two players is offline. - *

- * Unlike {@link #get(UUID)} this method never returns a null instance - * - * @param uuid Player unique id - * @return Offline player data - */ - @NotNull - public abstract OfflinePlayerData getOffline(UUID uuid); - - /** - * Called when a player logs in, loading the player data inside the map. - *

- * For YAML configs or SQL databases, data is loaded as not to overload - * the main thread with SQL requests. Therefore, the player data returned - * by that method, when the player joined for the first time, is not - * fully loaded YET. - * - * @param uniqueId Player UUID - * @return The loaded player data. - */ - public PlayerData setup(UUID uniqueId) { - - // Load player data if it does not exist - final @Nullable PlayerData current = data.get(uniqueId); - if (current != null) - return current; - - final PlayerData newData = new PlayerData(MMOPlayerData.get(uniqueId)); - - // Schedule async data loading - Bukkit.getScheduler().runTaskAsynchronously(MMOCore.plugin, () -> { - loadData(newData); - newData.getStats().updateStats(); - Bukkit.getPluginManager().callEvent(new AsyncPlayerDataLoadEvent(newData)); - Bukkit.getScheduler().runTask(MMOCore.plugin, () -> Bukkit.getPluginManager().callEvent(new PlayerDataLoadEvent(newData))); - }); - - // Update data map and return - data.put(uniqueId, newData); - return newData; + @Override + public PlayerData newPlayerData(MMOPlayerData playerData) { + return new PlayerData(playerData); } public DefaultPlayerData getDefaultData() { @@ -106,26 +27,4 @@ public abstract class PlayerDataManager { public void loadDefaultData(ConfigurationSection config) { defaultData = new DefaultPlayerData(config); } - - public boolean isLoaded(UUID uuid) { - return data.containsKey(uuid); - } - - public Collection getLoaded() { - return data.values(); - } - - public abstract void loadData(PlayerData data); - - /** - * Called when player data must be saved in configs or database. - * This method should always be called sync because it DOES register - * an async task in case MySQL storage is used. - * - * @param data Player data to save - * @param logout When logging out, is_saved is switched back to 1. This parameter - * must be turned off when auto-saving because the player doesn't - * actually leave the server. - */ - public abstract void saveData(PlayerData data, boolean logout); } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/mysql/MMOCoreDataSynchronizer.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/mysql/MMOCoreDataSynchronizer.java deleted file mode 100644 index 6da7df3b..00000000 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/mysql/MMOCoreDataSynchronizer.java +++ /dev/null @@ -1,154 +0,0 @@ -package net.Indyuce.mmocore.manager.data.mysql; - -import com.google.gson.*; -import io.lumine.mythic.lib.UtilityMethods; -import io.lumine.mythic.lib.sql.DataSynchronizer; -import net.Indyuce.mmocore.MMOCore; -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.util.MMOCoreUtils; -import net.Indyuce.mmocore.guild.provided.Guild; -import net.Indyuce.mmocore.skilltree.SkillTreeNode; -import net.Indyuce.mmocore.skilltree.tree.SkillTree; -import org.apache.commons.lang.Validate; -import org.bukkit.attribute.Attribute; -import org.jetbrains.annotations.Nullable; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.*; -import java.util.logging.Level; - -public class MMOCoreDataSynchronizer extends DataSynchronizer { - private final PlayerData data; - private final MySQLPlayerDataManager manager; - - public MMOCoreDataSynchronizer(MySQLPlayerDataManager manager, PlayerData data) { - super("mmocore_playerdata", "uuid", manager.getProvider(), data.getUniqueId()); - - this.manager = manager; - this.data = data; - } - - @Override - public void loadData(ResultSet result) throws SQLException { - //Reset stats linked to triggers - data.resetTriggerStats(); - - data.setClassPoints(result.getInt("class_points")); - data.setSkillPoints(result.getInt("skill_points")); - data.setSkillReallocationPoints(result.getInt("skill_reallocation_points")); - data.setSkillTreeReallocationPoints(result.getInt("skill_tree_reallocation_points")); - data.setAttributePoints(result.getInt("attribute_points")); - data.setAttributeReallocationPoints(result.getInt("attribute_realloc_points")); - data.setLevel(result.getInt("level")); - data.setExperience(result.getInt("experience")); - - if (!isEmpty(result.getString("class"))) - data.setClass(MMOCore.plugin.classManager.get(result.getString("class"))); - - if (!isEmpty(result.getString("times_claimed"))) { - JsonObject json = new JsonParser().parse(result.getString("times_claimed")).getAsJsonObject(); - json.entrySet().forEach(entry -> data.getItemClaims().put(entry.getKey(), entry.getValue().getAsInt())); - } - if (!isEmpty(result.getString("skill_tree_points"))) { - JsonObject json = new JsonParser().parse(result.getString("skill_tree_points")).getAsJsonObject(); - for (SkillTree skillTree : MMOCore.plugin.skillTreeManager.getAll()) { - data.setSkillTreePoints(skillTree.getId(), json.has(skillTree.getId()) ? json.get(skillTree.getId()).getAsInt() : 0); - } - data.setSkillTreePoints("global", json.has("global") ? json.get("global").getAsInt() : 0); - } - - if (!isEmpty(result.getString("skill_tree_levels"))) { - JsonObject json = new JsonParser().parse(result.getString("skill_tree_levels")).getAsJsonObject(); - for (SkillTreeNode skillTreeNode : MMOCore.plugin.skillTreeManager.getAllNodes()) { - data.setNodeLevel(skillTreeNode, json.has(skillTreeNode.getFullId()) ? json.get(skillTreeNode.getFullId()).getAsInt() : 0); - } - } - data.setupSkillTree(); - Set unlockedItems = new HashSet<>(); - if (!isEmpty(result.getString("unlocked_items"))) { - JsonArray unlockedItemsArray = new JsonParser().parse(result.getString("unlocked_items")).getAsJsonArray(); - for (JsonElement item : unlockedItemsArray) - unlockedItems.add(item.getAsString()); - } - data.setUnlockedItems(unlockedItems); - if (!isEmpty(result.getString("guild"))) { - final Guild guild = MMOCore.plugin.dataProvider.getGuildManager().getGuild(result.getString("guild")); - if (guild != null) - data.setGuild(guild.hasMember(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")); - if (!isEmpty(result.getString("quests"))) - data.getQuestData().load(result.getString("quests")); - data.getQuestData().updateBossBar(); - if (!isEmpty(result.getString("waypoints"))) - data.getWaypoints().addAll(MMOCoreUtils.jsonArrayToList(result.getString("waypoints"))); - if (!isEmpty(result.getString("friends"))) - MMOCoreUtils.jsonArrayToList(result.getString("friends")).forEach(str -> data.getFriends().add(UUID.fromString(str))); - if (!isEmpty(result.getString("skills"))) { - JsonObject object = new Gson().fromJson(result.getString("skills"), JsonObject.class); - for (Map.Entry entry : object.entrySet()) - data.setSkillLevel(entry.getKey(), entry.getValue().getAsInt()); - } - if (!isEmpty(result.getString("bound_skills"))) { - JsonObject object = new Gson().fromJson(result.getString("bound_skills"), JsonObject.class); - for (Map.Entry entry : object.entrySet()) - data.bindSkill(Integer.parseInt(entry.getKey()), data.getProfess().getSkill(entry.getValue().getAsString())); - } - if (!isEmpty(result.getString("class_info"))) { - JsonObject object = new Gson().fromJson(result.getString("class_info"), JsonObject.class); - for (Map.Entry entry : object.entrySet()) { - try { - PlayerClass profess = MMOCore.plugin.classManager.get(entry.getKey()); - Validate.notNull(profess, "Could not find class '" + entry.getKey() + "'"); - data.applyClassInfo(profess, new SavedClassInformation(entry.getValue().getAsJsonObject())); - } catch (IllegalArgumentException exception) { - MMOCore.log(Level.WARNING, "Could not load class info '" + entry.getKey() + "': " + exception.getMessage()); - } - } - } - - /* - * These should be loaded after to make sure that the - * MAX_MANA, MAX_STAMINA & MAX_STELLIUM stats are already loaded. - */ - data.setHealth(result.getDouble("health")); - data.setMana(result.getDouble("mana")); - data.setStamina(result.getDouble("stamina")); - data.setStellium(result.getDouble("stellium")); - - if (data.isOnline()) { - double health = data.getHealth(); - health = health == 0 ? data.getPlayer().getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue() : health; - health = Math.max(Math.min(health, data.getPlayer().getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue()), 0); - data.getPlayer().setHealth(health); - } - - UtilityMethods.debug(MMOCore.plugin, "SQL", String.format("{ class: %s, level: %d }", data.getProfess().getId(), data.getLevel())); - data.setFullyLoaded(); - } - - private boolean isEmpty(@Nullable String str) { - return str == null || str.equalsIgnoreCase("null") || str.equalsIgnoreCase("{}") || str.equalsIgnoreCase("[]") || str.equalsIgnoreCase(""); - } - - @Override - public void loadEmptyData() { - data.setLevel(manager.getDefaultData().getLevel()); - data.setClassPoints(manager.getDefaultData().getClassPoints()); - data.setSkillPoints(manager.getDefaultData().getSkillPoints()); - data.setSkillReallocationPoints(manager.getDefaultData().getSkillReallocationPoints()); - data.setAttributePoints(manager.getDefaultData().getAttributePoints()); - data.setAttributeReallocationPoints(manager.getDefaultData().getAttributeReallocationPoints()); - data.setExperience(0); - data.getQuestData().updateBossBar(); - - data.setFullyLoaded(); - UtilityMethods.debug(MMOCore.plugin, "SQL", "Loaded DEFAULT data for: '" + data.getUniqueId() + "' as no saved data was found."); - } -} diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/mysql/MySQLDataProvider.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/mysql/MySQLDataProvider.java deleted file mode 100644 index e2cc37ea..00000000 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/mysql/MySQLDataProvider.java +++ /dev/null @@ -1,94 +0,0 @@ -package net.Indyuce.mmocore.manager.data.mysql; - -import io.lumine.mythic.lib.sql.MMODataSource; -import net.Indyuce.mmocore.MMOCore; -import net.Indyuce.mmocore.manager.data.DataProvider; -import net.Indyuce.mmocore.manager.data.GuildDataManager; -import net.Indyuce.mmocore.manager.data.PlayerDataManager; -import net.Indyuce.mmocore.manager.data.yaml.YAMLGuildDataManager; -import org.bukkit.configuration.file.FileConfiguration; - -import java.sql.SQLException; - -public class MySQLDataProvider extends MMODataSource implements DataProvider { - private final MySQLPlayerDataManager playerManager = new MySQLPlayerDataManager(this); - private final YAMLGuildDataManager guildManager = new YAMLGuildDataManager(); - - private static final String[] NEW_COLUMNS = new String[]{ - "times_claimed", "LONGTEXT", - "is_saved", "TINYINT", - "skill_reallocation_points", "INT(11)", - "skill_tree_reallocation_points", "INT(11)", - "skill_tree_points", "LONGTEXT", - "skill_tree_levels", "LONGTEXT", - "unlocked_items","LONGTEXT", - "health", "FLOAT", - "mana", "FLOAT", - "stamina", "FLOAT", - "stellium", "FLOAT"}; - - public MySQLDataProvider(FileConfiguration config) { - super(MMOCore.plugin); - - this.setup(config); - } - - @Override - public void load() { - - // Fully create table - executeUpdateAsync("CREATE TABLE IF NOT EXISTS mmocore_playerdata(uuid VARCHAR(36)," + - "class_points INT(11) DEFAULT 0," + - "skill_points INT(11) DEFAULT 0," + - "attribute_points INT(11) DEFAULT 0," + - "attribute_realloc_points INT(11) DEFAULT 0," + - "skill_reallocation_points INT(11) DEFAULT 0," + - "skill_tree_reallocation_points INT(11) DEFAULT 0," + - "skill_tree_points LONGTEXT," + - "skill_tree_levels LONGTEXT," + - "level INT(11) DEFAULT 1," + - "experience INT(11) DEFAULT 0," + - "class VARCHAR(20),guild VARCHAR(20)," + - "last_login LONG," + - "attributes LONGTEXT," + - "professions LONGTEXT," + - "times_claimed LONGTEXT," + - "quests LONGTEXT," + - "waypoints LONGTEXT," + - "friends LONGTEXT," + - "skills LONGTEXT," + - "bound_skills LONGTEXT," + - "health FLOAT," + - "mana FLOAT," + - "stamina FLOAT," + - "stellium FLOAT," + - "unlocked_items LONGTEXT," + - "class_info LONGTEXT," + - "is_saved TINYINT," + - "PRIMARY KEY (uuid));"); - - // Add columns that might not be here by default - for (int i = 0; i < NEW_COLUMNS.length; i += 2) { - final String columnName = NEW_COLUMNS[i]; - final String dataType = NEW_COLUMNS[i + 1]; - getResultAsync("SELECT * FROM information_schema.COLUMNS WHERE TABLE_NAME = 'mmocore_playerdata' AND COLUMN_NAME = '" + columnName + "'", result -> { - try { - if (!result.next()) - executeUpdate("ALTER TABLE mmocore_playerdata ADD COLUMN " + columnName + " " + dataType); - } catch (SQLException exception) { - exception.printStackTrace(); - } - }); - } - } - - @Override - public PlayerDataManager getDataManager() { - return playerManager; - } - - @Override - public GuildDataManager getGuildManager() { - return guildManager; - } -} diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/MMOCoreDataSynchronizer.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/MMOCoreDataSynchronizer.java new file mode 100644 index 00000000..cc7fc895 --- /dev/null +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/MMOCoreDataSynchronizer.java @@ -0,0 +1,152 @@ +package net.Indyuce.mmocore.manager.data.sql; + +import com.google.gson.*; +import io.lumine.mythic.lib.MythicLib; +import io.lumine.mythic.lib.UtilityMethods; +import io.lumine.mythic.lib.data.sql.SQLDataSynchronizer; +import net.Indyuce.mmocore.MMOCore; +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.util.MMOCoreUtils; +import net.Indyuce.mmocore.guild.provided.Guild; +import net.Indyuce.mmocore.manager.data.PlayerDataManager; +import net.Indyuce.mmocore.skilltree.SkillTreeNode; +import net.Indyuce.mmocore.skilltree.tree.SkillTree; +import org.apache.commons.lang.Validate; +import org.bukkit.attribute.Attribute; +import org.jetbrains.annotations.Nullable; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.logging.Level; + +public class MMOCoreDataSynchronizer extends SQLDataSynchronizer { + public MMOCoreDataSynchronizer(SQLDataHandler handler, PlayerData data) { + super("mmocore_playerdata", "uuid", handler.getDataSource(), data); + } + + @Override + public void loadData(ResultSet result) throws SQLException { + //Reset stats linked to triggers + getData().resetTriggerStats(); + + getData().setClassPoints(result.getInt("class_points")); + getData().setSkillPoints(result.getInt("skill_points")); + getData().setSkillReallocationPoints(result.getInt("skill_reallocation_points")); + getData().setSkillTreeReallocationPoints(result.getInt("skill_tree_reallocation_points")); + getData().setAttributePoints(result.getInt("attribute_points")); + getData().setAttributeReallocationPoints(result.getInt("attribute_realloc_points")); + getData().setLevel(result.getInt("level")); + getData().setExperience(result.getInt("experience")); + + if (!isEmpty(result.getString("class"))) + getData().setClass(MMOCore.plugin.classManager.get(result.getString("class"))); + + if (!isEmpty(result.getString("times_claimed"))) { + JsonObject json = new JsonParser().parse(result.getString("times_claimed")).getAsJsonObject(); + json.entrySet().forEach(entry -> getData().getItemClaims().put(entry.getKey(), entry.getValue().getAsInt())); + } + if (!isEmpty(result.getString("skill_tree_points"))) { + JsonObject json = new JsonParser().parse(result.getString("skill_tree_points")).getAsJsonObject(); + for (SkillTree skillTree : MMOCore.plugin.skillTreeManager.getAll()) { + getData().setSkillTreePoints(skillTree.getId(), json.has(skillTree.getId()) ? json.get(skillTree.getId()).getAsInt() : 0); + } + getData().setSkillTreePoints("global", json.has("global") ? json.get("global").getAsInt() : 0); + } + + if (!isEmpty(result.getString("skill_tree_levels"))) { + JsonObject json = new JsonParser().parse(result.getString("skill_tree_levels")).getAsJsonObject(); + for (SkillTreeNode skillTreeNode : MMOCore.plugin.skillTreeManager.getAllNodes()) { + getData().setNodeLevel(skillTreeNode, json.has(skillTreeNode.getFullId()) ? json.get(skillTreeNode.getFullId()).getAsInt() : 0); + } + } + getData().setupSkillTree(); + Set unlockedItems = new HashSet<>(); + if (!isEmpty(result.getString("unlocked_items"))) { + JsonArray unlockedItemsArray = new JsonParser().parse(result.getString("unlocked_items")).getAsJsonArray(); + for (JsonElement item : unlockedItemsArray) + unlockedItems.add(item.getAsString()); + } + getData().setUnlockedItems(unlockedItems); + if (!isEmpty(result.getString("guild"))) { + final Guild guild = MMOCore.plugin.dataProvider.getGuildManager().getGuild(result.getString("guild")); + if (guild != null) + getData().setGuild(guild.hasMember(getData().getUniqueId()) ? guild : null); + } + if (!isEmpty(result.getString("attributes"))) + getData().getAttributes().load(result.getString("attributes")); + if (!isEmpty(result.getString("professions"))) + getData().getCollectionSkills().load(result.getString("professions")); + if (!isEmpty(result.getString("quests"))) + getData().getQuestData().load(result.getString("quests")); + getData().getQuestData().updateBossBar(); + if (!isEmpty(result.getString("waypoints"))) + getData().getWaypoints().addAll(MMOCoreUtils.jsonArrayToList(result.getString("waypoints"))); + if (!isEmpty(result.getString("friends"))) + MMOCoreUtils.jsonArrayToList(result.getString("friends")).forEach(str -> getData().getFriends().add(UUID.fromString(str))); + if (!isEmpty(result.getString("skills"))) { + JsonObject object = MythicLib.plugin.getGson().fromJson(result.getString("skills"), JsonObject.class); + for (Map.Entry entry : object.entrySet()) + getData().setSkillLevel(entry.getKey(), entry.getValue().getAsInt()); + } + if (!isEmpty(result.getString("bound_skills"))) { + JsonObject object = MythicLib.plugin.getGson().fromJson(result.getString("bound_skills"), JsonObject.class); + for (Map.Entry entry : object.entrySet()) + getData().bindSkill(Integer.parseInt(entry.getKey()), getData().getProfess().getSkill(entry.getValue().getAsString())); + } + if (!isEmpty(result.getString("class_info"))) { + JsonObject object = MythicLib.plugin.getGson().fromJson(result.getString("class_info"), JsonObject.class); + for (Map.Entry entry : object.entrySet()) { + try { + PlayerClass profess = MMOCore.plugin.classManager.get(entry.getKey()); + Validate.notNull(profess, "Could not find class '" + entry.getKey() + "'"); + getData().applyClassInfo(profess, new SavedClassInformation(entry.getValue().getAsJsonObject())); + } catch (IllegalArgumentException exception) { + MMOCore.log(Level.WARNING, "Could not load class info '" + entry.getKey() + "': " + exception.getMessage()); + } + } + } + + /* + * These should be loaded after to make sure that the + * MAX_MANA, MAX_STAMINA & MAX_STELLIUM stats are already loaded. + */ + getData().setHealth(result.getDouble("health")); + getData().setMana(result.getDouble("mana")); + getData().setStamina(result.getDouble("stamina")); + getData().setStellium(result.getDouble("stellium")); + + if (getData().isOnline()) { + double health = getData().getHealth(); + health = health == 0 ? getData().getPlayer().getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue() : health; + health = Math.max(Math.min(health, getData().getPlayer().getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue()), 0); + getData().getPlayer().setHealth(health); + } + + UtilityMethods.debug(MMOCore.plugin, "SQL", String.format("{ class: %s, level: %d }", getData().getProfess().getId(), getData().getLevel())); + } + + private boolean isEmpty(@Nullable String str) { + return str == null || str.equalsIgnoreCase("null") || str.equalsIgnoreCase("{}") || str.equalsIgnoreCase("[]") || str.equalsIgnoreCase(""); + } + + @Override + public void loadEmptyData() { + final PlayerDataManager manager = MMOCore.plugin.playerDataManager; + getData().setLevel(manager.getDefaultData().getLevel()); + getData().setClassPoints(manager.getDefaultData().getClassPoints()); + getData().setSkillPoints(manager.getDefaultData().getSkillPoints()); + getData().setSkillReallocationPoints(manager.getDefaultData().getSkillReallocationPoints()); + getData().setAttributePoints(manager.getDefaultData().getAttributePoints()); + getData().setAttributeReallocationPoints(manager.getDefaultData().getAttributeReallocationPoints()); + getData().setExperience(0); + getData().getQuestData().updateBossBar(); + + UtilityMethods.debug(MMOCore.plugin, "SQL", "Loaded DEFAULT data for: '" + getData().getUniqueId() + "' as no saved data was found."); + } +} diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/mysql/PlayerDataTableUpdater.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/PlayerDataTableUpdater.java similarity index 84% rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/mysql/PlayerDataTableUpdater.java rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/PlayerDataTableUpdater.java index 7f9652d1..95189691 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/mysql/PlayerDataTableUpdater.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/PlayerDataTableUpdater.java @@ -1,10 +1,11 @@ -package net.Indyuce.mmocore.manager.data.mysql; +package net.Indyuce.mmocore.manager.data.sql; import com.google.gson.JsonArray; import com.google.gson.JsonObject; +import io.lumine.mythic.lib.data.sql.SQLDataSource; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; -import net.Indyuce.mmocore.manager.data.yaml.YAMLPlayerDataManager; +import net.Indyuce.mmocore.manager.data.yaml.YAMLPlayerDataHandler; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -19,15 +20,15 @@ import java.util.logging.Level; public class PlayerDataTableUpdater { private final PlayerData playerData; - private final MySQLDataProvider provider; + private final SQLDataSource provider; private final Map requestMap = new HashMap<>(); - public PlayerDataTableUpdater(MySQLDataProvider provider, PlayerData playerData) { + public PlayerDataTableUpdater(SQLDataSource provider, PlayerData playerData) { this.playerData = playerData; this.provider = provider; } - public void executeRequest(boolean logout) { + public void executeRequest(boolean autosave) { final String request = "INSERT INTO mmocore_playerdata(uuid, " + formatCollection(requestMap.keySet(), false) + ") VALUES('" + playerData.getUniqueId() + "'," + formatCollection(requestMap.values(), true) + ")" + " ON DUPLICATE KEY UPDATE " + formatMap() + ";"; @@ -40,21 +41,21 @@ public class PlayerDataTableUpdater { statement.executeUpdate(); } catch (SQLException exception) { MMOCore.log(Level.WARNING, "Could not save player data of " + playerData.getUniqueId() + ", saving through YAML instead"); - new YAMLPlayerDataManager(provider).saveData(playerData, logout); + new YAMLPlayerDataHandler(MMOCore.plugin).saveData(playerData, autosave); exception.printStackTrace(); } finally { statement.close(); } } catch (SQLException exception) { MMOCore.log(Level.WARNING, "Could not save player data of " + playerData.getUniqueId() + ", saving through YAML instead"); - new YAMLPlayerDataManager(provider).saveData(playerData, logout); + new YAMLPlayerDataHandler(MMOCore.plugin).saveData(playerData, autosave); exception.printStackTrace(); } finally { connection.close(); } } catch (SQLException exception) { MMOCore.log(Level.WARNING, "Could not save player data of " + playerData.getUniqueId() + ", saving through YAML instead"); - new YAMLPlayerDataManager(provider).saveData(playerData, logout); + new YAMLPlayerDataHandler(MMOCore.plugin).saveData(playerData, autosave); exception.printStackTrace(); } } @@ -95,7 +96,7 @@ public class PlayerDataTableUpdater { addData(key, json.toString()); } - public void addJSONObject(String key, Set> collection) { + public void addJSONObject(String key, Set> collection) { JsonObject json = new JsonObject(); for (Map.Entry entry : collection) json.addProperty(entry.getKey().toString(), entry.getValue().toString()); diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/mysql/MySQLPlayerDataManager.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/SQLDataHandler.java similarity index 68% rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/mysql/MySQLPlayerDataManager.java rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/SQLDataHandler.java index 36a87b18..505506f0 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/mysql/MySQLPlayerDataManager.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/SQLDataHandler.java @@ -1,42 +1,100 @@ -package net.Indyuce.mmocore.manager.data.mysql; +package net.Indyuce.mmocore.manager.data.sql; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import io.lumine.mythic.lib.UtilityMethods; +import io.lumine.mythic.lib.data.sql.SQLDataSource; +import io.lumine.mythic.lib.data.sql.SQLSynchronizedDataHandler; import net.Indyuce.mmocore.MMOCore; -import net.Indyuce.mmocore.api.player.OfflinePlayerData; +import net.Indyuce.mmocore.manager.data.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.manager.data.PlayerDataManager; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.sql.SQLException; import java.util.List; import java.util.UUID; import java.util.stream.Collectors; -public class MySQLPlayerDataManager extends PlayerDataManager { - private final MySQLDataProvider provider; - - public MySQLPlayerDataManager(MySQLDataProvider provider) { - this.provider = provider; +public class SQLDataHandler extends SQLSynchronizedDataHandler { + public SQLDataHandler(SQLDataSource dataSource) { + super(dataSource); } - public MySQLDataProvider getProvider() { - return provider; + private static final String[] NEW_COLUMNS = new String[]{ + "times_claimed", "LONGTEXT", + "is_saved", "TINYINT", + "skill_reallocation_points", "INT(11)", + "skill_tree_reallocation_points", "INT(11)", + "skill_tree_points", "LONGTEXT", + "skill_tree_levels", "LONGTEXT", + "unlocked_items", "LONGTEXT", + "health", "FLOAT", + "mana", "FLOAT", + "stamina", "FLOAT", + "stellium", "FLOAT"}; + + @Override + public void setup() { + + // Fully create table + getDataSource().executeUpdateAsync("CREATE TABLE IF NOT EXISTS mmocore_playerdata(uuid VARCHAR(36)," + + "class_points INT(11) DEFAULT 0," + + "skill_points INT(11) DEFAULT 0," + + "attribute_points INT(11) DEFAULT 0," + + "attribute_realloc_points INT(11) DEFAULT 0," + + "skill_reallocation_points INT(11) DEFAULT 0," + + "skill_tree_reallocation_points INT(11) DEFAULT 0," + + "skill_tree_points LONGTEXT," + + "skill_tree_levels LONGTEXT," + + "level INT(11) DEFAULT 1," + + "experience INT(11) DEFAULT 0," + + "class VARCHAR(20),guild VARCHAR(20)," + + "last_login LONG," + + "attributes LONGTEXT," + + "professions LONGTEXT," + + "times_claimed LONGTEXT," + + "quests LONGTEXT," + + "waypoints LONGTEXT," + + "friends LONGTEXT," + + "skills LONGTEXT," + + "bound_skills LONGTEXT," + + "health FLOAT," + + "mana FLOAT," + + "stamina FLOAT," + + "stellium FLOAT," + + "unlocked_items LONGTEXT," + + "class_info LONGTEXT," + + "is_saved TINYINT," + + "PRIMARY KEY (uuid));"); + + // Add columns that might not be here by default + for (int i = 0; i < NEW_COLUMNS.length; i += 2) { + final String columnName = NEW_COLUMNS[i]; + final String dataType = NEW_COLUMNS[i + 1]; + getDataSource().getResultAsync("SELECT * FROM information_schema.COLUMNS WHERE TABLE_NAME = 'mmocore_playerdata' AND COLUMN_NAME = '" + columnName + "'", result -> { + try { + if (!result.next()) + getDataSource().executeUpdate("ALTER TABLE mmocore_playerdata ADD COLUMN " + columnName + " " + dataType); + } catch (SQLException exception) { + exception.printStackTrace(); + } + }); + } } @Override - public void loadData(PlayerData data) { - new MMOCoreDataSynchronizer(this, data).fetch(); + public MMOCoreDataSynchronizer newDataSynchronizer(PlayerData playerData) { + return new MMOCoreDataSynchronizer(this, playerData); } @Override - public void saveData(PlayerData data, boolean logout) { + public void saveData(PlayerData data, boolean autosave) { UtilityMethods.debug(MMOCore.plugin, "SQL", "Saving data for: '" + data.getUniqueId() + "'..."); - final PlayerDataTableUpdater updater = new PlayerDataTableUpdater(provider, data); + final PlayerDataTableUpdater updater = new PlayerDataTableUpdater(getDataSource(), data); updater.addData("class_points", data.getClassPoints()); updater.addData("skill_points", data.getSkillPoints()); updater.addData("skill_reallocation_points", data.getSkillReallocationPoints()); @@ -44,7 +102,7 @@ public class MySQLPlayerDataManager extends PlayerDataManager { updater.addData("attribute_realloc_points", data.getAttributeReallocationPoints()); updater.addJSONArray("waypoints", data.getWaypoints()); updater.addData("skill_tree_reallocation_points", data.getSkillTreeReallocationPoints()); - updater.addData("health",data.getHealth()); + updater.addData("health", data.getHealth()); updater.addData("mana", data.getMana()); updater.addData("stellium", data.getStellium()); updater.addData("stamina", data.getStamina()); @@ -65,10 +123,10 @@ public class MySQLPlayerDataManager extends PlayerDataManager { updater.addData("quests", data.getQuestData().toJsonString()); updater.addData("class_info", createClassInfoData(data).toString()); updater.addJSONArray("unlocked_items", data.getUnlockedItems()); - if (logout) + if (!autosave) updater.addData("is_saved", 1); - updater.executeRequest(logout); + updater.executeRequest(autosave); UtilityMethods.debug(MMOCore.plugin, "SQL", "Saved data for: " + data.getUniqueId()); UtilityMethods.debug(MMOCore.plugin, "SQL", String.format("{ class: %s, level: %d }", data.getProfess().getId(), data.getLevel())); @@ -132,17 +190,20 @@ public class MySQLPlayerDataManager extends PlayerDataManager { @NotNull @Override public OfflinePlayerData getOffline(UUID uuid) { - return isLoaded(uuid) ? get(uuid) : new MySQLOfflinePlayerData(uuid); + return new MySQLOfflinePlayerData(uuid); } - public class MySQLOfflinePlayerData extends OfflinePlayerData { + @Deprecated + public class MySQLOfflinePlayerData implements OfflinePlayerData { + private final UUID uuid; private int level; private long lastLogin; private PlayerClass profess; private List friends; + @Deprecated public MySQLOfflinePlayerData(UUID uuid) { - super(uuid); + this.uuid = uuid; /* provider.getResult("SELECT * FROM mmocore_playerdata WHERE uuid = '" + uuid + "';", (result) -> { try { @@ -168,6 +229,12 @@ public class MySQLPlayerDataManager extends PlayerDataManager { }); */ } + @Override + @NotNull + public UUID getUniqueId() { + return uuid; + } + @Override public void removeFriend(UUID uuid) { // TODO recode diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLDataProvider.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLDataProvider.java deleted file mode 100644 index 39d20dd5..00000000 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLDataProvider.java +++ /dev/null @@ -1,20 +0,0 @@ -package net.Indyuce.mmocore.manager.data.yaml; - -import net.Indyuce.mmocore.manager.data.DataProvider; -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(this); - private final YAMLGuildDataManager guildManager = new YAMLGuildDataManager(); - - @Override - public PlayerDataManager getDataManager() { - return playerManager; - } - - @Override - public GuildDataManager getGuildManager() { - return guildManager; - } -} diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLOfflinePlayerData.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLOfflinePlayerData.java index 67de7675..06e593f4 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLOfflinePlayerData.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLOfflinePlayerData.java @@ -6,46 +6,55 @@ import java.util.UUID; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.profess.PlayerClass; import net.Indyuce.mmocore.api.ConfigFile; -import net.Indyuce.mmocore.api.player.OfflinePlayerData; +import net.Indyuce.mmocore.manager.data.OfflinePlayerData; +import org.jetbrains.annotations.NotNull; -public class YAMLOfflinePlayerData extends OfflinePlayerData { - private final ConfigFile config; +@Deprecated +public class YAMLOfflinePlayerData implements OfflinePlayerData { + private final UUID uuid; + private final ConfigFile config; - /** - * 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) { - super(uuid); + /** + * Supports offline player data operations like friend removals which can't + * be handled when their player data is not loaded in the data map. + */ + @Deprecated + public YAMLOfflinePlayerData(UUID uuid) { + this.uuid = uuid; + config = new ConfigFile(uuid); + } - config = new ConfigFile(uuid); - } + @Override + @NotNull + public UUID getUniqueId() { + return uuid; + } - @Override - public void removeFriend(UUID uuid) { - List friends = config.getConfig().getStringList("friends"); - friends.remove(uuid.toString()); - config.getConfig().set("friends", friends); - config.save(); - } + @Override + public void removeFriend(UUID uuid) { + List friends = config.getConfig().getStringList("friends"); + friends.remove(uuid.toString()); + config.getConfig().set("friends", friends); + config.save(); + } - @Override - public boolean hasFriend(UUID uuid) { - return config.getConfig().getStringList("friends").contains(uuid.toString()); - } + @Override + public boolean hasFriend(UUID uuid) { + return config.getConfig().getStringList("friends").contains(uuid.toString()); + } - @Override - public PlayerClass getProfess() { - return config.getConfig().contains("class") ? MMOCore.plugin.classManager.get(config.getConfig().getString("class")) : MMOCore.plugin.classManager.getDefaultClass(); - } + @Override + public PlayerClass getProfess() { + return config.getConfig().contains("class") ? MMOCore.plugin.classManager.get(config.getConfig().getString("class")) : MMOCore.plugin.classManager.getDefaultClass(); + } - @Override - public int getLevel() { - return config.getConfig().getInt("level"); - } + @Override + public int getLevel() { + return config.getConfig().getInt("level"); + } - @Override - public long getLastLogin() { - return config.getConfig().getLong("last-login"); - } + @Override + public long getLastLogin() { + return config.getConfig().getLong("last-login"); + } } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLPlayerDataManager.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLPlayerDataHandler.java similarity index 86% rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLPlayerDataManager.java rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLPlayerDataHandler.java index b43e4040..581e8715 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLPlayerDataManager.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLPlayerDataHandler.java @@ -1,54 +1,61 @@ package net.Indyuce.mmocore.manager.data.yaml; +import io.lumine.mythic.lib.data.yaml.YAMLSynchronizedDataHandler; import net.Indyuce.mmocore.MMOCore; -import net.Indyuce.mmocore.api.ConfigFile; -import net.Indyuce.mmocore.api.player.OfflinePlayerData; +import net.Indyuce.mmocore.manager.data.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.util.MMOCoreUtils; import net.Indyuce.mmocore.guild.provided.Guild; -import net.Indyuce.mmocore.manager.data.DataProvider; -import net.Indyuce.mmocore.manager.data.PlayerDataManager; +import net.Indyuce.mmocore.player.DefaultPlayerData; import net.Indyuce.mmocore.skill.ClassSkill; import net.Indyuce.mmocore.skilltree.SkillTreeNode; import org.apache.commons.lang.Validate; import org.bukkit.attribute.Attribute; import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.NotNull; import java.util.*; 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; +public class YAMLPlayerDataHandler extends YAMLSynchronizedDataHandler { + public YAMLPlayerDataHandler(Plugin owning) { + super(owning); } @Override - public void loadData(PlayerData data) { - FileConfiguration config = new ConfigFile(data.getUniqueId()).getConfig(); + public void setup() { + + } + + @Override + public void close() { + + } + + @Override + public void loadFromSection(PlayerData data, ConfigurationSection config) { // Reset stats linked to triggers. data.resetTriggerStats(); - data.setClassPoints(config.getInt("class-points", getDefaultData().getClassPoints())); - data.setSkillPoints(config.getInt("skill-points", getDefaultData().getSkillPoints())); - data.setSkillReallocationPoints(config.getInt("skill-reallocation-points", getDefaultData().getSkillReallocationPoints())); - data.setSkillTreeReallocationPoints(config.getInt("skill-tree-reallocation-points", getDefaultData().getSkillTreeReallocationPoints())); - data.setAttributePoints(config.getInt("attribute-points", getDefaultData().getAttributePoints())); - data.setAttributeReallocationPoints(config.getInt("attribute-realloc-points", getDefaultData().getAttributeReallocationPoints())); - data.setLevel(config.getInt("level", getDefaultData().getLevel())); + final DefaultPlayerData defaultData = MMOCore.plugin.playerDataManager.getDefaultData(); + data.setClassPoints(config.getInt("class-points", defaultData.getClassPoints())); + data.setSkillPoints(config.getInt("skill-points", defaultData.getSkillPoints())); + data.setSkillReallocationPoints(config.getInt("skill-reallocation-points", defaultData.getSkillReallocationPoints())); + data.setSkillTreeReallocationPoints(config.getInt("skill-tree-reallocation-points", defaultData.getSkillTreeReallocationPoints())); + data.setAttributePoints(config.getInt("attribute-points", defaultData.getAttributePoints())); + data.setAttributeReallocationPoints(config.getInt("attribute-realloc-points", defaultData.getAttributeReallocationPoints())); + data.setLevel(config.getInt("level", defaultData.getLevel())); data.setExperience(config.getInt("experience")); if (config.contains("class")) data.setClass(MMOCore.plugin.classManager.get(config.getString("class"))); if (config.contains("guild")) { - Guild guild = provider.getGuildManager().getGuild(config.getString("guild")); + Guild guild = MMOCore.plugin.nativeGuildManager.getGuild(config.getString("guild")); data.setGuild(guild.hasMember(data.getUniqueId()) ? guild : null); } if (config.contains("attribute")) @@ -124,14 +131,10 @@ public class YAMLPlayerDataManager extends PlayerDataManager { if (data.isOnline()) data.getPlayer().setHealth(MMOCoreUtils.fixResource(config.getDouble("health"), data.getPlayer().getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue())); - - data.setFullyLoaded(); } @Override - public void saveData(PlayerData data, boolean logout) { - ConfigFile file = new ConfigFile(data.getUniqueId()); - FileConfiguration config = file.getConfig(); + public void saveInSection(PlayerData data, ConfigurationSection config) { config.set("class-points", data.getClassPoints()); config.set("skill-points", data.getSkillPoints()); @@ -149,11 +152,11 @@ public class YAMLPlayerDataManager extends PlayerDataManager { data.mapSkillTreePoints().forEach((key1, value) -> config.set("skill-tree-points." + key1, value)); config.set("skill-tree-reallocation-points", data.getSkillTreeReallocationPoints()); config.set("skill", null); - config.set("health",data.getHealth()); + config.set("health", data.getHealth()); config.set("mana", data.getMana()); config.set("stellium", data.getStellium()); config.set("stamina", data.getStamina()); - //Saves the nodes levels + // Saves the nodes levels MMOCore.plugin.skillTreeManager.getAllNodes().forEach(node -> config.set("skill-tree-level." + node.getFullId(), data.getNodeLevel(node))); data.mapSkillLevels().forEach((key1, value) -> config.set("skill." + key1, value)); data.getItemClaims().forEach((key, times) -> config.set("times-claimed." + key, times)); @@ -194,14 +197,12 @@ public class YAMLPlayerDataManager extends PlayerDataManager { info.mapBoundSkills().forEach((slot, skill) -> config.set("class-info." + key + ".bound-skills." + slot, skill)); config.set("class-info." + key + ".unlocked-items", new ArrayList<>(info.getUnlockedItems())); } - - file.save(); } @NotNull @Override public OfflinePlayerData getOffline(UUID uuid) { - return isLoaded(uuid) ? get(uuid) : new YAMLOfflinePlayerData(uuid); + return new YAMLOfflinePlayerData(uuid); } } diff --git a/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/PlayerListener.java b/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/PlayerListener.java index 66bae5bb..89cd34c9 100644 --- a/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/PlayerListener.java +++ b/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/PlayerListener.java @@ -18,22 +18,9 @@ import org.bukkit.event.entity.EntityRegainHealthEvent; import org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryCloseEvent; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.event.player.PlayerQuitEvent; public class PlayerListener implements Listener { - /** - * Load player data. Event priority is set to LOW as most plugins - * do not change their priority which is NORMAL by default. Making - * it low is important because MMOCore is a core plugin so other plugins - * might rely on its data on startup. - */ - @EventHandler(priority = EventPriority.LOW) - public void loadPlayerData(PlayerJoinEvent event) { - MMOCore.plugin.dataProvider.getDataManager().setup(event.getPlayer().getUniqueId()); - } - /** * Register custom inventory clicks */ @@ -70,16 +57,6 @@ public class PlayerListener implements Listener { PlayerData.get(event.getEntity().getUniqueId()).getCombat().update(); } - @EventHandler - public void saveDataOnQuit(PlayerQuitEvent event) { - PlayerData playerData = PlayerData.get(event.getPlayer()); - /** - * We save player health as it won't be accessible anymore when saving the player data (player will be offline). - */ - playerData.setHealth(event.getPlayer().getHealth()); - MMOCore.plugin.dataProvider.getDataManager().unregisterSafe(playerData); - } - /** * Using the Bukkit health update event is not a good way of * interacting with MMOCore health regeneration. The diff --git a/MMOCore-Dist/src/main/resources/config.yml b/MMOCore-Dist/src/main/resources/config.yml index 6744a1da..393c2ab3 100644 --- a/MMOCore-Dist/src/main/resources/config.yml +++ b/MMOCore-Dist/src/main/resources/config.yml @@ -7,6 +7,7 @@ config-version: 9 auto-save: enabled: true interval: 1800 # In seconds (1800 = 30 minutes) + log: true # MySQL Support mysql: From 590801203de78948c4950c0f66eebbee38510211 Mon Sep 17 00:00:00 2001 From: Jules Date: Sun, 23 Apr 2023 22:08:30 +0200 Subject: [PATCH 03/14] Fixed NPE with yaml data loading --- .../mmocore/manager/data/yaml/YAMLPlayerDataHandler.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLPlayerDataHandler.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLPlayerDataHandler.java index 581e8715..351fb0c3 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLPlayerDataHandler.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLPlayerDataHandler.java @@ -74,7 +74,8 @@ public class YAMLPlayerDataHandler extends YAMLSynchronizedDataHandler Date: Sun, 7 May 2023 09:33:18 +0200 Subject: [PATCH 04/14] API method to force into skill casting --- .../java/net/Indyuce/mmocore/MMOCore.java | 4 +- .../mmocore/api/player/PlayerData.java | 18 +++-- ...Handler.java => SkillCastingInstance.java} | 4 +- .../skill/cast/SkillCastingListener.java | 18 +++++ .../mmocore/skill/cast/SkillCastingMode.java | 32 ++++++--- .../skill/cast/listener/KeyCombos.java | 67 +++++++++---------- .../mmocore/skill/cast/listener/SkillBar.java | 36 +++++----- .../cast/listener/SkillCastingDisabled.java | 20 ++++++ .../skill/cast/listener/SkillScroller.java | 58 ++++++++-------- 9 files changed, 163 insertions(+), 94 deletions(-) rename MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/{SkillCastingHandler.java => SkillCastingInstance.java} (90%) create mode 100644 MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/SkillCastingListener.java create mode 100644 MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/listener/SkillCastingDisabled.java diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java index 6a0ee87d..634c741d 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java @@ -110,6 +110,7 @@ public class MMOCore extends JavaPlugin { @Override public void onLoad() { + getLogger().log(Level.INFO, "Plugin file is called '" + getFile().getName() + "'"); // Register MMOCore-specific objects MythicLib.plugin.getEntities().registerRelationHandler(new PartyRelationHandler()); @@ -238,7 +239,8 @@ public class MMOCore extends JavaPlugin { // Skill casting try { SkillCastingMode mode = SkillCastingMode.valueOf(UtilityMethods.enumName(getConfig().getString("skill-casting.mode"))); - Bukkit.getPluginManager().registerEvents(mode.loadFromConfig(getConfig().getConfigurationSection("skill-casting")), this); + mode.setCurrent(getConfig().getConfigurationSection("skill-casting")); + } catch (RuntimeException exception) { getLogger().log(Level.WARNING, "Could not load skill casting: " + exception.getMessage()); } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java index db4d9e90..aef3f302 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java @@ -46,7 +46,8 @@ import net.Indyuce.mmocore.player.Unlockable; import net.Indyuce.mmocore.skill.ClassSkill; import net.Indyuce.mmocore.skill.RegisteredSkill; import net.Indyuce.mmocore.skill.binding.SkillSlot; -import net.Indyuce.mmocore.skill.cast.SkillCastingHandler; +import net.Indyuce.mmocore.skill.cast.SkillCastingInstance; +import net.Indyuce.mmocore.skill.cast.SkillCastingMode; import net.Indyuce.mmocore.skilltree.IntegerCoordinates; import net.Indyuce.mmocore.skilltree.NodeStatus; import net.Indyuce.mmocore.skilltree.SkillTreeNode; @@ -88,7 +89,7 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD */ private double health; private Guild guild; - private SkillCastingHandler skillCasting; + private SkillCastingInstance skillCasting; private final PlayerQuests questData; private final PlayerStats playerStats; private final List friends = new ArrayList<>(); @@ -99,7 +100,6 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD @Deprecated private final Set waypoints = new HashSet<>(); private final Map skills = new HashMap<>(); - // TODO change it to an array....... Map is just BoundSkillInfo[] private final Map boundSkills = new HashMap<>(); private final PlayerProfessions collectSkills = new PlayerProfessions(this); private final PlayerAttributes attributes = new PlayerAttributes(this); @@ -1019,13 +1019,21 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD return skillCasting != null; } - public void setSkillCasting(SkillCastingHandler skillCasting) { + public void setSkillCasting(@NotNull SkillCastingInstance skillCasting) { Validate.isTrue(!isCasting(), "Player already in casting mode"); this.skillCasting = skillCasting; } + /** + * API Method + */ + public void setSkillCasting() { + Validate.isTrue(!isCasting(), "Player already in casting mode"); + setSkillCasting(SkillCastingMode.getCurrent().newInstance(this)); + } + @NotNull - public SkillCastingHandler getSkillCasting() { + public SkillCastingInstance getSkillCasting() { return Objects.requireNonNull(skillCasting, "Player not in casting mode"); } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/SkillCastingHandler.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/SkillCastingInstance.java similarity index 90% rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/SkillCastingHandler.java rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/SkillCastingInstance.java index 150863df..7dac62a8 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/SkillCastingHandler.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/SkillCastingInstance.java @@ -8,13 +8,13 @@ import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; import org.bukkit.scheduler.BukkitRunnable; -public abstract class SkillCastingHandler extends BukkitRunnable implements Listener { +public abstract class SkillCastingInstance extends BukkitRunnable implements Listener { private final PlayerData caster; private boolean open = true; private int j; - public SkillCastingHandler(PlayerData caster, int runnablePeriod) { + public SkillCastingInstance(PlayerData caster, int runnablePeriod) { this.caster = caster; runTaskTimer(MMOCore.plugin, 0, runnablePeriod); diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/SkillCastingListener.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/SkillCastingListener.java new file mode 100644 index 00000000..69d5f0e0 --- /dev/null +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/SkillCastingListener.java @@ -0,0 +1,18 @@ +package net.Indyuce.mmocore.skill.cast; + + +import net.Indyuce.mmocore.api.player.PlayerData; +import org.bukkit.event.Listener; +import org.jetbrains.annotations.NotNull; + +/** + * @apiNote Purely for API + */ +public interface SkillCastingListener extends Listener { + + @NotNull + public SkillCastingMode getCastingMode(); + + @NotNull + public SkillCastingInstance newInstance(@NotNull PlayerData player); +} diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/SkillCastingMode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/SkillCastingMode.java index 08c75d98..c9418fe4 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/SkillCastingMode.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/SkillCastingMode.java @@ -1,11 +1,16 @@ package net.Indyuce.mmocore.skill.cast; +import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.skill.cast.listener.SkillBar; import net.Indyuce.mmocore.skill.cast.listener.KeyCombos; +import net.Indyuce.mmocore.skill.cast.listener.SkillCastingDisabled; import net.Indyuce.mmocore.skill.cast.listener.SkillScroller; +import org.apache.commons.lang.Validate; +import org.bukkit.Bukkit; import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.event.Listener; +import org.jetbrains.annotations.NotNull; +import java.util.Objects; import java.util.function.Function; public enum SkillCastingMode { @@ -23,7 +28,7 @@ public enum SkillCastingMode { * to navigate through the entire castable skill list. Then press * one key to cast the one selected. */ - SKILL_SCROLL(config -> new SkillScroller(config)), + SKILL_SCROLLER(config -> new SkillScroller(config)), /** * Initialize your skill combo by pressing some key. @@ -37,8 +42,7 @@ public enum SkillCastingMode { /** * Entirely disables skill casting. */ - NONE(config -> new Listener() { - }); + NONE(config -> new SkillCastingDisabled()); /** * Not implemented yet. @@ -59,13 +63,25 @@ public enum SkillCastingMode { ; - private final Function listenerLoader; + private final Function listenerLoader; - SkillCastingMode(Function listenerLoader) { + private static SkillCastingListener current; + + SkillCastingMode(Function listenerLoader) { this.listenerLoader = listenerLoader; } - public Listener loadFromConfig(ConfigurationSection config) { - return listenerLoader.apply(config); + public void setCurrent(@NotNull ConfigurationSection config) { + Validate.isTrue(current == null, "Skill casting mode already initialized"); + current = listenerLoader.apply(config); + if (this == NONE) return; + + // Register listener + Bukkit.getPluginManager().registerEvents(current, MMOCore.plugin); + } + + @NotNull + public static SkillCastingListener getCurrent() { + return Objects.requireNonNull(current, "Skill casting mode hasn't been initialized yet"); } } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/listener/KeyCombos.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/listener/KeyCombos.java index e8039bf7..55628f04 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/listener/KeyCombos.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/listener/KeyCombos.java @@ -11,10 +11,7 @@ import net.Indyuce.mmocore.api.SoundObject; import net.Indyuce.mmocore.api.event.PlayerKeyPressEvent; import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.gui.api.item.Placeholders; -import net.Indyuce.mmocore.skill.cast.ComboMap; -import net.Indyuce.mmocore.skill.cast.KeyCombo; -import net.Indyuce.mmocore.skill.cast.PlayerKey; -import net.Indyuce.mmocore.skill.cast.SkillCastingHandler; +import net.Indyuce.mmocore.skill.cast.*; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -24,7 +21,7 @@ import org.jetbrains.annotations.NotNull; import javax.annotation.Nullable; import java.util.*; -public class KeyCombos implements Listener { +public class KeyCombos implements SkillCastingListener { private final ComboMap comboMap; @@ -56,8 +53,17 @@ public class KeyCombos implements Listener { failComboSound = config.contains("sound.fail-combo") ? new SoundObject(config.getConfigurationSection("sound.fail-combo")) : null; // Find initializer key - initializerKey = config.contains("initializer-key") ? PlayerKey.valueOf(UtilityMethods.enumName(Objects.requireNonNull( - config.getString("initializer-key"), "Could not find initializer key"))) : null; + initializerKey = config.contains("initializer-key") ? PlayerKey.valueOf(UtilityMethods.enumName(Objects.requireNonNull(config.getString("initializer-key"), "Could not find initializer key"))) : null; + } + + @Override + public SkillCastingInstance newInstance(@NotNull PlayerData player) { + return new CustomSkillCastingInstance(player); + } + + @Override + public SkillCastingMode getCastingMode() { + return SkillCastingMode.KEY_COMBOS; } @EventHandler @@ -70,46 +76,39 @@ public class KeyCombos implements Listener { if (event.getPressed() == initializerKey) { // Cancel event if necessary - if (event.getPressed().shouldCancelEvent()) - event.setCancelled(true); + if (event.getPressed().shouldCancelEvent()) event.setCancelled(true); // Start combo - playerData.setSkillCasting(new CustomSkillCastingHandler(playerData)); - if (beginComboSound != null) - beginComboSound.playTo(player); + playerData.setSkillCasting(new CustomSkillCastingInstance(playerData)); + if (beginComboSound != null) beginComboSound.playTo(player); } return; } - @Nullable CustomSkillCastingHandler casting = null; + @Nullable CustomSkillCastingInstance casting = null; // Player is already casting - if (event.getData().isCasting()) - casting = (CustomSkillCastingHandler) playerData.getSkillCasting(); + if (event.getData().isCasting()) casting = (CustomSkillCastingInstance) playerData.getSkillCasting(); // Start combo when there is NO initializer key else { final @NotNull ComboMap comboMap = Objects.requireNonNullElse(playerData.getProfess().getComboMap(), this.comboMap); if (comboMap.isComboStart(event.getPressed())) { - casting = new CustomSkillCastingHandler(playerData); + casting = new CustomSkillCastingInstance(playerData); playerData.setSkillCasting(casting); - if (beginComboSound != null) - beginComboSound.playTo(player); + if (beginComboSound != null) beginComboSound.playTo(player); } } - if (casting == null) - return; + if (casting == null) return; // Adding pressed key casting.current.registerKey(event.getPressed()); casting.onTick(); - if (comboClickSound != null) - comboClickSound.playTo(player); + if (comboClickSound != null) comboClickSound.playTo(player); // Cancel event if necessary - if (event.getPressed().shouldCancelEvent()) - event.setCancelled(true); + if (event.getPressed().shouldCancelEvent()) event.setCancelled(true); // Hash current combo and check if (casting.combos.getCombos().containsKey(casting.current)) { @@ -127,8 +126,7 @@ public class KeyCombos implements Listener { // Check if current combo is too large if (casting.current.countKeys() >= casting.combos.getLongest()) { playerData.leaveSkillCasting(); - if (failComboSound != null) - failComboSound.playTo(player); + if (failComboSound != null) failComboSound.playTo(player); } } @@ -157,13 +155,14 @@ public class KeyCombos implements Listener { } /** - * Loads the player current combos & the combos applicable to the player (combos defined in its class or the default combos of the config.yml) + * Loads the player current combos & the combos applicable to the player + * (combos defined in its class or the default combos of the config.yml) */ - private class CustomSkillCastingHandler extends SkillCastingHandler { + public class CustomSkillCastingInstance extends SkillCastingInstance { private final KeyCombo current = new KeyCombo(); private final ComboMap combos; - CustomSkillCastingHandler(PlayerData caster) { + CustomSkillCastingInstance(PlayerData caster) { super(caster, 10); combos = Objects.requireNonNullElse(caster.getProfess().getComboMap(), comboMap); @@ -171,11 +170,9 @@ public class KeyCombos implements Listener { @Override public void onTick() { - if (actionBarOptions != null) - if (actionBarOptions.isSubtitle) - getCaster().getPlayer().sendTitle(" ", actionBarOptions.format(this), 0, 20, 0); - else - getCaster().displayActionBar(actionBarOptions.format(this)); + if (actionBarOptions != null) if (actionBarOptions.isSubtitle) + getCaster().getPlayer().sendTitle(" ", actionBarOptions.format(this), 0, 20, 0); + else getCaster().displayActionBar(actionBarOptions.format(this)); } } @@ -199,7 +196,7 @@ public class KeyCombos implements Listener { keyNames.put(key, Objects.requireNonNull(config.getString("key-name." + key.name()), "Could not find translation for key " + key.name())); } - public String format(CustomSkillCastingHandler casting) { + public String format(CustomSkillCastingInstance casting) { StringBuilder builder = new StringBuilder(); Placeholders holders = MMOCore.plugin.actionBarManager.getActionBarPlaceholders(casting.getCaster()); diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/listener/SkillBar.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/listener/SkillBar.java index 66bfcdf4..a4f4e880 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/listener/SkillBar.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/listener/SkillBar.java @@ -10,8 +10,9 @@ import net.Indyuce.mmocore.api.event.PlayerKeyPressEvent; import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.skill.ClassSkill; import net.Indyuce.mmocore.skill.cast.PlayerKey; -import net.Indyuce.mmocore.skill.cast.SkillCastingHandler; -import org.bukkit.Bukkit; +import net.Indyuce.mmocore.skill.cast.SkillCastingInstance; +import net.Indyuce.mmocore.skill.cast.SkillCastingListener; +import net.Indyuce.mmocore.skill.cast.SkillCastingMode; import org.bukkit.GameMode; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; @@ -19,10 +20,11 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerItemHeldEvent; import org.bukkit.scheduler.BukkitRunnable; +import org.jetbrains.annotations.NotNull; import java.util.Objects; -public class SkillBar implements Listener { +public class SkillBar implements SkillCastingListener { private final PlayerKey mainKey; private final boolean disableSneak; @@ -31,6 +33,16 @@ public class SkillBar implements Listener { disableSneak = config.getBoolean("disable-sneak"); } + @Override + public SkillCastingInstance newInstance(@NotNull PlayerData player) { + return new CustomSkillCastingInstance(player); + } + + @Override + public SkillCastingMode getCastingMode() { + return SkillCastingMode.SKILL_BAR; + } + @EventHandler public void enterSkillCasting(PlayerKeyPressEvent event) { if (event.getPressed() != mainKey) return; @@ -44,14 +56,13 @@ public class SkillBar implements Listener { // Enter spell casting final PlayerData playerData = event.getData(); - if (player.getGameMode() != GameMode.SPECTATOR && (MMOCore.plugin.configManager.canCreativeCast || player.getGameMode() != GameMode.CREATIVE) && !playerData.isCasting() && !playerData.getBoundSkills() - .isEmpty()) { - playerData.setSkillCasting(new CustomSkillCastingHandler(playerData)); + if (player.getGameMode() != GameMode.SPECTATOR && (MMOCore.plugin.configManager.canCreativeCast || player.getGameMode() != GameMode.CREATIVE) && !playerData.isCasting() && !playerData.getBoundSkills().isEmpty()) { + playerData.setSkillCasting(new CustomSkillCastingInstance(playerData)); MMOCore.plugin.soundManager.getSound(SoundEvent.SPELL_CAST_BEGIN).playTo(player); } } - private class CustomSkillCastingHandler extends SkillCastingHandler { + public class CustomSkillCastingInstance extends SkillCastingInstance { private final String ready = MMOCore.plugin.configManager.getSimpleMessage("casting.action-bar.ready").message(); private final String onCooldown = MMOCore.plugin.configManager.getSimpleMessage("casting.action-bar.on-cooldown").message(); private final String noMana = MMOCore.plugin.configManager.getSimpleMessage("casting.action-bar.no-mana").message(); @@ -60,7 +71,7 @@ public class SkillBar implements Listener { private int j; - CustomSkillCastingHandler(PlayerData playerData) { + CustomSkillCastingInstance(PlayerData playerData) { super(playerData, 1); } @@ -119,11 +130,7 @@ public class SkillBar implements Listener { if (!data.isOnline()) return str.toString(); for (int slot : data.mapBoundSkills().keySet()) { ClassSkill skill = data.getBoundSkill(slot); - str.append(str.isEmpty() ? "" : split).append((onCooldown(data, skill) ? onCooldown.replace("{cooldown}", - String.valueOf(data.getCooldownMap().getInfo(skill).getRemaining() / 1000)) : noMana(data, skill) ? noMana : (noStamina( - data, skill) ? noStamina : ready)).replace("{index}", - String.valueOf(slot + (data.getPlayer().getInventory().getHeldItemSlot() < slot ? 1 : 0))) - .replace("{skill}", data.getBoundSkill(slot).getSkill().getName())); + str.append(str.isEmpty() ? "" : split).append((onCooldown(data, skill) ? onCooldown.replace("{cooldown}", String.valueOf(data.getCooldownMap().getInfo(skill).getRemaining() / 1000)) : noMana(data, skill) ? noMana : (noStamina(data, skill) ? noStamina : ready)).replace("{index}", String.valueOf(slot + (data.getPlayer().getInventory().getHeldItemSlot() < slot ? 1 : 0))).replace("{skill}", data.getBoundSkill(slot).getSkill().getName())); } return MMOCore.plugin.placeholderParser.parse(data.getPlayer(), str.toString()); } @@ -142,8 +149,7 @@ public class SkillBar implements Listener { } private boolean noStamina(PlayerData data, ClassSkill skill) { - return skill.getSkill().hasModifier("stamina") && skill.getModifier("stamina", - data.getSkillLevel(skill.getSkill())) > data.getStamina(); + return skill.getSkill().hasModifier("stamina") && skill.getModifier("stamina", data.getSkillLevel(skill.getSkill())) > data.getStamina(); } @Override diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/listener/SkillCastingDisabled.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/listener/SkillCastingDisabled.java new file mode 100644 index 00000000..6457f58b --- /dev/null +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/listener/SkillCastingDisabled.java @@ -0,0 +1,20 @@ +package net.Indyuce.mmocore.skill.cast.listener; + +import net.Indyuce.mmocore.api.player.PlayerData; +import net.Indyuce.mmocore.skill.cast.SkillCastingInstance; +import net.Indyuce.mmocore.skill.cast.SkillCastingListener; +import net.Indyuce.mmocore.skill.cast.SkillCastingMode; +import org.jetbrains.annotations.NotNull; + +public class SkillCastingDisabled implements SkillCastingListener { + + @Override + public SkillCastingInstance newInstance(@NotNull PlayerData player) { + throw new RuntimeException("Skill casting is disabled"); + } + + @Override + public SkillCastingMode getCastingMode() { + return SkillCastingMode.NONE; + } +} diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/listener/SkillScroller.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/listener/SkillScroller.java index 58906728..92acb49e 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/listener/SkillScroller.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/listener/SkillScroller.java @@ -8,17 +8,19 @@ import net.Indyuce.mmocore.api.SoundObject; import net.Indyuce.mmocore.api.event.PlayerKeyPressEvent; import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.skill.cast.PlayerKey; -import net.Indyuce.mmocore.skill.cast.SkillCastingHandler; +import net.Indyuce.mmocore.skill.cast.SkillCastingInstance; +import net.Indyuce.mmocore.skill.cast.SkillCastingListener; +import net.Indyuce.mmocore.skill.cast.SkillCastingMode; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerItemHeldEvent; +import org.jetbrains.annotations.NotNull; import javax.annotation.Nullable; import java.util.Objects; -public class SkillScroller implements Listener { +public class SkillScroller implements SkillCastingListener { /** * Key players need to press to start casting @@ -40,6 +42,16 @@ public class SkillScroller implements Listener { castKey = PlayerKey.valueOf(UtilityMethods.enumName(Objects.requireNonNull(config.getString("cast-key"), "Could not find cast key"))); } + @Override + public SkillCastingInstance newInstance(@NotNull PlayerData player) { + return new CustomSkillCastingInstance(player); + } + + @Override + public SkillCastingMode getCastingMode() { + return SkillCastingMode.SKILL_SCROLLER; + } + @EventHandler public void whenPressingKey(PlayerKeyPressEvent event) { PlayerData playerData = event.getData(); @@ -51,36 +63,30 @@ public class SkillScroller implements Listener { if (playerData.isCasting()) { // Cancel event if necessary - if (event.getPressed().shouldCancelEvent()) - event.setCancelled(true); + if (event.getPressed().shouldCancelEvent()) event.setCancelled(true); playerData.leaveSkillCasting(); - if (leaveSound != null) - leaveSound.playTo(player); + if (leaveSound != null) leaveSound.playTo(player); return; } // Check if there are skills bound - if (playerData.getBoundSkills().isEmpty()) - return; + if (playerData.getBoundSkills().isEmpty()) return; // Cancel event if necessary - if (event.getPressed().shouldCancelEvent()) - event.setCancelled(true); + if (event.getPressed().shouldCancelEvent()) event.setCancelled(true); // Enter casting mode - playerData.setSkillCasting(new CustomSkillCastingHandler(playerData)); - if (enterSound != null) - enterSound.playTo(player); + playerData.setSkillCasting(new CustomSkillCastingInstance(playerData)); + if (enterSound != null) enterSound.playTo(player); } if (event.getPressed() == castKey && playerData.isCasting()) { // Cancel event if necessary - if (event.getPressed().shouldCancelEvent()) - event.setCancelled(true); + if (event.getPressed().shouldCancelEvent()) event.setCancelled(true); - CustomSkillCastingHandler casting = (CustomSkillCastingHandler) playerData.getSkillCasting(); + CustomSkillCastingInstance casting = (CustomSkillCastingInstance) playerData.getSkillCasting(); PlayerMetadata caster = playerData.getMMOPlayerData().getStatMap().cache(EquipmentSlot.MAIN_HAND); playerData.getBoundSkill(casting.index).toCastable(playerData).cast(new TriggerMetadata(caster, null, null)); } @@ -89,8 +95,7 @@ public class SkillScroller implements Listener { @EventHandler public void onScroll(PlayerItemHeldEvent event) { PlayerData playerData = PlayerData.get(event.getPlayer()); - if (!playerData.isCasting()) - return; + if (!playerData.isCasting()) return; if (playerData.getBoundSkills().isEmpty()) { playerData.leaveSkillCasting(); @@ -104,29 +109,26 @@ public class SkillScroller implements Listener { int change = Math.abs(dist1) < Math.abs(dist2) ? (Math.abs(dist1) < Math.abs(dist3) ? dist1 : dist3) : (Math.abs(dist3) < Math.abs(dist2) ? dist3 : dist2); // Scroll trough items - CustomSkillCastingHandler casting = (CustomSkillCastingHandler) playerData.getSkillCasting(); + CustomSkillCastingInstance casting = (CustomSkillCastingInstance) playerData.getSkillCasting(); casting.index = mod(casting.index + change, playerData.getBoundSkills().size()); casting.onTick(); - if (changeSound != null) - changeSound.playTo(event.getPlayer()); + if (changeSound != null) changeSound.playTo(event.getPlayer()); } private int mod(int x, int n) { - while (x < 0) - x += n; + while (x < 0) x += n; - while (x >= n) - x -= n; + while (x >= n) x -= n; return x; } - private class CustomSkillCastingHandler extends SkillCastingHandler { + public class CustomSkillCastingInstance extends SkillCastingInstance { private int index = 0; - CustomSkillCastingHandler(PlayerData caster) { + CustomSkillCastingInstance(PlayerData caster) { super(caster, 10); } From c5dbf21694338ea3e246b9577153c4d4009f6ca6 Mon Sep 17 00:00:00 2001 From: Jules Date: Sun, 7 May 2023 15:24:41 +0200 Subject: [PATCH 05/14] Update repo URL --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3857dd1d..623cb90d 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Register the PhoenixDev repo ``` phoenix - https://nexus.phoenixdvpt.fr/repository/maven-public/ + https://nexus.phoenixdevt.fr/repository/maven-public/ ``` And then add MMOCore-API as dependency From 2bcd505bf8dd3eedd361d7996bbffbd137991e80 Mon Sep 17 00:00:00 2001 From: Jules Date: Sun, 7 May 2023 18:29:31 +0200 Subject: [PATCH 06/14] Support for profile placeholders --- MMOCore-API/pom.xml | 8 ++ .../java/net/Indyuce/mmocore/MMOCore.java | 2 +- .../player/attribute/PlayerAttributes.java | 9 ++- .../mmocore/api/quest/PlayerQuests.java | 1 + .../comp/placeholder/RPGPlaceholders.java | 11 ++- .../profile/MMOCoreProfileDataModule.java | 46 +++++++++++ .../mmocore/comp/vault/VaultEconomy.java | 2 + .../data/AbstractOfflinePlayerData.java | 19 ----- .../manager/data/PlayerDataManager.java | 7 ++ .../data/sql/PlayerDataTableUpdater.java | 12 ++- .../manager/data/sql/SQLDataHandler.java | 76 +---------------- .../data/sql/SQLOfflinePlayerData.java | 81 +++++++++++++++++++ .../data/yaml/YAMLOfflinePlayerData.java | 3 + MMOCore-Dist/src/main/resources/plugin.yml | 2 +- 14 files changed, 171 insertions(+), 108 deletions(-) create mode 100644 MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/profile/MMOCoreProfileDataModule.java delete mode 100644 MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/AbstractOfflinePlayerData.java create mode 100644 MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/SQLOfflinePlayerData.java diff --git a/MMOCore-API/pom.xml b/MMOCore-API/pom.xml index e06a0583..4de78a2a 100644 --- a/MMOCore-API/pom.xml +++ b/MMOCore-API/pom.xml @@ -139,6 +139,14 @@ provided + + fr.phoenixdevt + MMOProfiles-Dist + 1.0-SNAPSHOT + provided + true + + me.clip placeholderapi diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java index 634c741d..03ccdf50 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java @@ -259,7 +259,7 @@ public class MMOCore extends JavaPlugin { * recognize what profess the player has and professes will be lost */ playerDataManager.setupAll(); - playerDataManager.registerEvents(EventPriority.NORMAL); + playerDataManager.registerEvents(EventPriority.NORMAL, EventPriority.NORMAL); // load guild data after loading player data dataProvider.getGuildManager().load(); diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/attribute/PlayerAttributes.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/attribute/PlayerAttributes.java index 352c9c97..53738674 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/attribute/PlayerAttributes.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/attribute/PlayerAttributes.java @@ -128,6 +128,11 @@ public class PlayerAttributes { return spent; } + @Deprecated + public int getSpent() { + return getBase(); + } + public void setBase(int value) { spent = Math.max(0, value); @@ -165,10 +170,6 @@ public class PlayerAttributes { return (int) d; } - public int getSpent() { - return spent; - } - public AttributeModifier getModifier(String key) { return map.get(key); } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/PlayerQuests.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/PlayerQuests.java index 6acbd3b4..6e866a80 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/PlayerQuests.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/PlayerQuests.java @@ -38,6 +38,7 @@ public class PlayerQuests implements Closable { bossbarNamespacedKey = new NamespacedKey(MMOCore.plugin, "mmocore_quest_progress_" + playerData.getUniqueId().toString()); bossbar = Bukkit.createBossBar(bossbarNamespacedKey, "", BarColor.PURPLE, BarStyle.SEGMENTED_20); bossbar.addPlayer(playerData.getPlayer()); + bossbar.setVisible(false); // Safety // Bossbar is disabled } else { diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/placeholder/RPGPlaceholders.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/placeholder/RPGPlaceholders.java index 639c922d..c9c506cd 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/placeholder/RPGPlaceholders.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/placeholder/RPGPlaceholders.java @@ -17,7 +17,6 @@ import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.OfflinePlayer; import org.bukkit.attribute.Attribute; -import org.bukkit.attribute.AttributeInstance; import org.bukkit.entity.Player; import javax.annotation.Nullable; @@ -73,12 +72,12 @@ public class RPGPlaceholders extends PlaceholderExpansion { RegisteredSkill skill = Objects.requireNonNull(MMOCore.plugin.skillManager.getSkill(id), "Could not find skill with ID '" + id + "'"); return String.valueOf(playerData.getSkillLevel(skill)); } - else if(identifier.startsWith("mmocore_attribute_points_spent_")){ - String attributeId=identifier.substring(31); - PlayerAttributes.AttributeInstance attributeInstance=Objects.requireNonNull(playerData.getAttributes().getInstance(attributeId),"Could not find attribute with ID '"+attributeId+"'"); - return String.valueOf(attributeInstance.getSpent()); - } + else if (identifier.startsWith("mmocore_attribute_points_spent_")) { + String attributeId = identifier.substring(31); + PlayerAttributes.AttributeInstance attributeInstance = Objects.requireNonNull(playerData.getAttributes().getInstance(attributeId), "Could not find attribute with ID '" + attributeId + "'"); + return String.valueOf(attributeInstance.getBase()); + } else if (identifier.equals("level_percent")) { double current = playerData.getExperience(), next = playerData.getLevelUpExperience(); diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/profile/MMOCoreProfileDataModule.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/profile/MMOCoreProfileDataModule.java new file mode 100644 index 00000000..1f410f74 --- /dev/null +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/profile/MMOCoreProfileDataModule.java @@ -0,0 +1,46 @@ +package net.Indyuce.mmocore.comp.profile; + +import fr.phoenixdevt.profile.placeholder.PlaceholderRequest; +import io.lumine.mythic.lib.MythicLib; +import io.lumine.mythic.lib.api.player.MMOPlayerData; +import io.lumine.mythic.lib.comp.profile.ProfileDataModuleImpl; +import net.Indyuce.mmocore.MMOCore; +import net.Indyuce.mmocore.api.player.PlayerData; +import net.Indyuce.mmocore.api.player.attribute.PlayerAttribute; +import net.Indyuce.mmocore.experience.Profession; + +public class MMOCoreProfileDataModule extends ProfileDataModuleImpl { + public MMOCoreProfileDataModule() { + super(MMOCore.plugin); + } + + @Override + public boolean hasPlaceholders() { + return true; + } + + @Override + public String getIdentifier() { + return "mmocore"; + } + + @Override + public void processPlaceholderRequest(PlaceholderRequest placeholderRequest) { + final PlayerData fictiveData = new PlayerData(new MMOPlayerData(placeholderRequest.getProfile().getUniqueId())); + MMOCore.plugin.playerDataManager.getDataHandler().loadData(fictiveData).thenRun(() -> { + placeholderRequest.addPlaceholder("class", fictiveData.getProfess().getName()); + placeholderRequest.addPlaceholder("level", fictiveData.getLevel()); + + for (PlayerAttribute attribute : MMOCore.plugin.attributeManager.getAll()) + placeholderRequest.addPlaceholder("attribute_" + attribute.getId().replace("-", "_"), fictiveData.getAttributes().getInstance(attribute).getBase()); + + for (Profession profession : MMOCore.plugin.professionManager.getAll()) + placeholderRequest.addPlaceholder("profession_" + profession.getId().replace("-", "_"), fictiveData.getCollectionSkills().getLevel(profession)); + + placeholderRequest.addPlaceholder("exp", MythicLib.plugin.getMMOConfig().decimal.format(fictiveData.getExperience())); + placeholderRequest.addPlaceholder("exp_next_level", MythicLib.plugin.getMMOConfig().decimal.format(fictiveData.getLevelUpExperience())); + + placeholderRequest.validate(); + }); + } +} diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/vault/VaultEconomy.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/vault/VaultEconomy.java index efa2c729..c00d0a2f 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/vault/VaultEconomy.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/vault/VaultEconomy.java @@ -26,7 +26,9 @@ public class VaultEconomy { /** * @return If an economy plugin was found + * @deprecated Not needed. {@link MMOCore#economy} could be null and that's all */ + @Deprecated public boolean isValid() { return economy != null; } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/AbstractOfflinePlayerData.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/AbstractOfflinePlayerData.java deleted file mode 100644 index 7e5455c1..00000000 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/AbstractOfflinePlayerData.java +++ /dev/null @@ -1,19 +0,0 @@ -package net.Indyuce.mmocore.manager.data; - -import net.Indyuce.mmocore.api.player.profess.PlayerClass; - -import java.util.UUID; - -public interface AbstractOfflinePlayerData { - - - public abstract void removeFriend(UUID uuid); - - public abstract boolean hasFriend(UUID uuid); - - public abstract PlayerClass getProfess(); - - public abstract int getLevel(); - - public abstract long getLastLogin(); -} diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java index 167569c8..a84bf5d5 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java @@ -1,9 +1,11 @@ package net.Indyuce.mmocore.manager.data; import io.lumine.mythic.lib.api.player.MMOPlayerData; +import io.lumine.mythic.lib.comp.profile.ProfileDataModuleImpl; import io.lumine.mythic.lib.data.SynchronizedDataManager; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; +import net.Indyuce.mmocore.comp.profile.MMOCoreProfileDataModule; import net.Indyuce.mmocore.manager.data.yaml.YAMLPlayerDataHandler; import net.Indyuce.mmocore.player.DefaultPlayerData; import org.bukkit.configuration.ConfigurationSection; @@ -20,6 +22,11 @@ public class PlayerDataManager extends SynchronizedDataManager friends; - - @Deprecated - public MySQLOfflinePlayerData(UUID uuid) { - this.uuid = uuid; -/* - provider.getResult("SELECT * FROM mmocore_playerdata WHERE uuid = '" + uuid + "';", (result) -> { - try { - MythicLib.debug("MMOCoreSQL", "Loading OFFLINE data for '" + uuid + "'."); - if (!result.next()) { - level = 0; - lastLogin = 0; - profess = MMOCore.plugin.classManager.getDefaultClass(); - friends = new ArrayList<>(); - MythicLib.debug("MMOCoreSQL", "Default OFFLINE data loaded."); - } else { - level = result.getInt("level"); - lastLogin = result.getLong("last_login"); - profess = isEmpty(result.getString("class")) ? MMOCore.plugin.classManager.getDefaultClass() : MMOCore.plugin.classManager.get(result.getString("class")); - if (!isEmpty(result.getString("friends"))) - MMOCoreUtils.jsonArrayToList(result.getString("friends")).forEach(str -> friends.add(UUID.fromString(str))); - else friends = new ArrayList<>(); - MythicLib.debug("MMOCoreSQL", "Saved OFFLINE data loaded."); - } - } catch (SQLException e) { - e.printStackTrace(); - } - }); */ - } - - @Override - @NotNull - public UUID getUniqueId() { - return uuid; - } - - @Override - public void removeFriend(UUID uuid) { - // TODO recode - // friends.remove(uuid); - // new PlayerDataTableUpdater(provider, uuid).updateData("friends", friends.stream().map(UUID::toString).collect(Collectors.toList())); - } - - @Override - public boolean hasFriend(UUID uuid) { - return friends.contains(uuid); - } - - @Override - public PlayerClass getProfess() { - return profess; - } - - @Override - public int getLevel() { - return level; - } - - @Override - public long getLastLogin() { - return lastLogin; - } + return new SQLOfflinePlayerData(uuid); } } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/SQLOfflinePlayerData.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/SQLOfflinePlayerData.java new file mode 100644 index 00000000..0dd2ae9c --- /dev/null +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/SQLOfflinePlayerData.java @@ -0,0 +1,81 @@ +package net.Indyuce.mmocore.manager.data.sql; + +import net.Indyuce.mmocore.api.player.profess.PlayerClass; +import net.Indyuce.mmocore.manager.data.OfflinePlayerData; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.UUID; + +/** + * @deprecated Not implemented yet + */ +@Deprecated +public class SQLOfflinePlayerData implements OfflinePlayerData { + private final UUID uuid; + private int level; + private long lastLogin; + private PlayerClass profess; + private List friends; + + @Deprecated + public SQLOfflinePlayerData(UUID uuid) { + this.uuid = uuid; +/* + provider.getResult("SELECT * FROM mmocore_playerdata WHERE uuid = '" + uuid + "';", (result) -> { + try { + MythicLib.debug("MMOCoreSQL", "Loading OFFLINE data for '" + uuid + "'."); + if (!result.next()) { + level = 0; + lastLogin = 0; + profess = MMOCore.plugin.classManager.getDefaultClass(); + friends = new ArrayList<>(); + MythicLib.debug("MMOCoreSQL", "Default OFFLINE data loaded."); + } else { + level = result.getInt("level"); + lastLogin = result.getLong("last_login"); + profess = isEmpty(result.getString("class")) ? MMOCore.plugin.classManager.getDefaultClass() : MMOCore.plugin.classManager.get(result.getString("class")); + if (!isEmpty(result.getString("friends"))) + MMOCoreUtils.jsonArrayToList(result.getString("friends")).forEach(str -> friends.add(UUID.fromString(str))); + else friends = new ArrayList<>(); + MythicLib.debug("MMOCoreSQL", "Saved OFFLINE data loaded."); + } + } catch (SQLException e) { + e.printStackTrace(); + } + }); */ + } + + @Override + @NotNull + public UUID getUniqueId() { + return uuid; + } + + @Override + public void removeFriend(UUID uuid) { + // TODO recode + // friends.remove(uuid); + // new PlayerDataTableUpdater(provider, uuid).updateData("friends", friends.stream().map(UUID::toString).collect(Collectors.toList())); + } + + @Override + public boolean hasFriend(UUID uuid) { + return friends.contains(uuid); + } + + @Override + public PlayerClass getProfess() { + return profess; + } + + @Override + public int getLevel() { + return level; + } + + @Override + public long getLastLogin() { + return lastLogin; + } +} diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLOfflinePlayerData.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLOfflinePlayerData.java index 06e593f4..0ce81e67 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLOfflinePlayerData.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLOfflinePlayerData.java @@ -9,6 +9,9 @@ import net.Indyuce.mmocore.api.ConfigFile; import net.Indyuce.mmocore.manager.data.OfflinePlayerData; import org.jetbrains.annotations.NotNull; +/** + * @deprecated Not implemented yet + */ @Deprecated public class YAMLOfflinePlayerData implements OfflinePlayerData { private final UUID uuid; diff --git a/MMOCore-Dist/src/main/resources/plugin.yml b/MMOCore-Dist/src/main/resources/plugin.yml index 0b937b09..73f9f2c2 100644 --- a/MMOCore-Dist/src/main/resources/plugin.yml +++ b/MMOCore-Dist/src/main/resources/plugin.yml @@ -5,7 +5,7 @@ author: Indyuce description: ${project.description} loadbefore: [ MMOItems,MythicDungeons ] depend: [ MythicLib ] -softdepend: [ Vault,MythicMobs,PlaceholderAPI,Residence,Citizens,ProtocolLib,OBTeam ] +softdepend: [ Vault,MythicMobs,MMOProfiles,PlaceholderAPI,Residence,Citizens,ProtocolLib,OBTeam ] api-version: 1.13 commands: mmocore: From 27d5c93ba703f424b70073c89fb7a5a0d9cc5dac Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Sun, 7 May 2023 19:15:28 +0100 Subject: [PATCH 07/14] Heavy debugging and refactor for skill trees. --- .../mmocore/api/player/PlayerData.java | 12 +++-- .../net/Indyuce/mmocore/MMOCoreBukkit.java | 4 ++ .../listener/ForceChooseClassListener.java | 54 +++++++++++++++++++ MMOCore-Dist/src/main/resources/config.yml | 3 ++ 4 files changed, 69 insertions(+), 4 deletions(-) create mode 100644 MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/ForceChooseClassListener.java diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java index aef3f302..cafd7964 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java @@ -159,8 +159,8 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD MMOCore.log(Level.SEVERE, "[Userdata] Could not find class " + getProfess().getId() + " while refreshing player data."); } //We remove all the stats and buffs associated to triggers. - getMMOPlayerData().getStatMap().getInstances().forEach(statInstance -> statInstance.removeIf(key ->key.startsWith(Trigger.TRIGGER_PREFIX))); - getMMOPlayerData().getSkillModifierMap().getInstances().forEach(skillModifierInstance -> skillModifierInstance.removeIf(key ->key.startsWith(Trigger.TRIGGER_PREFIX))); + getMMOPlayerData().getStatMap().getInstances().forEach(statInstance -> statInstance.removeIf(key -> key.startsWith(Trigger.TRIGGER_PREFIX))); + getMMOPlayerData().getSkillModifierMap().getInstances().forEach(skillModifierInstance -> skillModifierInstance.removeIf(key -> key.startsWith(Trigger.TRIGGER_PREFIX))); final Iterator> ite = boundSkills.entrySet().iterator(); while (ite.hasNext()) try { @@ -376,7 +376,7 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD /** * @return If the item is unlocked by the player - * This is used for skills that can be locked & unlocked. + * This is used for skills that can be locked & unlocked. */ public boolean hasUnlocked(Unlockable unlockable) { return unlockable.isUnlockedByDefault() || unlockedItems.contains(unlockable.getUnlockNamespacedKey()); @@ -893,6 +893,10 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD return profess == null ? MMOCore.plugin.classManager.getDefaultClass() : profess; } + public boolean isProfessNull() { + return profess == null; + } + /** * @deprecated Provide reason with {@link #giveMana(double, PlayerResourceUpdateEvent.UpdateReason)} */ @@ -1198,7 +1202,7 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD * checks if they could potentially upgrade to one of these * * @return If the player can change its current class to - * a subclass + * a subclass */ @Deprecated public boolean canChooseSubclass() { diff --git a/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/MMOCoreBukkit.java b/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/MMOCoreBukkit.java index 160c0922..631b00b3 100644 --- a/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/MMOCoreBukkit.java +++ b/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/MMOCoreBukkit.java @@ -38,6 +38,10 @@ public class MMOCoreBukkit { if (plugin.getConfig().getBoolean("vanilla-exp-redirection.enabled")) Bukkit.getPluginManager().registerEvents(new RedirectVanillaExp(plugin.getConfig().getDouble("vanilla-exp-redirection.ratio")), plugin); + if (plugin.getConfig().getBoolean("force-class-choose-on-first-login")) + Bukkit.getPluginManager().registerEvents(new ForceChooseClassListener(), MMOCore.plugin); + + Bukkit.getPluginManager().registerEvents(new WaypointsListener(), plugin); Bukkit.getPluginManager().registerEvents(new PlayerListener(), plugin); Bukkit.getPluginManager().registerEvents(new GoldPouchesListener(), plugin); diff --git a/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/ForceChooseClassListener.java b/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/ForceChooseClassListener.java new file mode 100644 index 00000000..cb870de5 --- /dev/null +++ b/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/ForceChooseClassListener.java @@ -0,0 +1,54 @@ +package net.Indyuce.mmocore.listener; + +import io.lumine.mythic.lib.api.event.SynchronizedDataLoadEvent; +import io.lumine.mythic.lib.api.util.TemporaryListener; +import net.Indyuce.mmocore.MMOCore; +import net.Indyuce.mmocore.api.event.PlayerChangeClassEvent; +import net.Indyuce.mmocore.api.player.PlayerData; +import net.Indyuce.mmocore.manager.InventoryManager; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryCloseEvent; + +public class ForceChooseClassListener implements Listener { + @EventHandler + public void onJoin(SynchronizedDataLoadEvent event) { + if (event.getManager().getOwningPlugin().equals(MMOCore.plugin)) { + PlayerData playerData = PlayerData.get(event.getHolder().getProfileId()); + if (playerData.isProfessNull()) { + InventoryManager.CLASS_SELECT.newInventory(playerData).open(); + //Give 1 class point to make sure the player can choose a class. + playerData.setClassPoints(1); + TemporaryListener closeGUIListener = new TemporaryListener(InventoryCloseEvent.getHandlerList()) { + + @EventHandler + public void whenClosed(InventoryCloseEvent e) { + if (e.getPlayer().equals(playerData.getPlayer())) + InventoryManager.CLASS_SELECT.newInventory(playerData).open(); + } + + @Override + public void whenClosed() { + + } + }; + new TemporaryListener(PlayerChangeClassEvent.getHandlerList()) { + @EventHandler + public void whenChoose(PlayerChangeClassEvent e) { + if (e.getPlayer().equals(playerData.getPlayer())) { + closeGUIListener.close(); + close(); + } + + } + + @Override + public void whenClosed() { + + } + }; + } + } + } + +} diff --git a/MMOCore-Dist/src/main/resources/config.yml b/MMOCore-Dist/src/main/resources/config.yml index 75e698df..bfa568cf 100644 --- a/MMOCore-Dist/src/main/resources/config.yml +++ b/MMOCore-Dist/src/main/resources/config.yml @@ -193,6 +193,9 @@ vanilla-exp-redirection: # Requires a SERVER reload when changed. override-vanilla-exp: true +#Forces the player to choose a class at first join. +force-class-choose-on-first-login: false + # Check the target player's RPG profile when shift when shift right clicking. shift-click-player-profile-check: false From 1a1371b5f9820bcedd7aaa94e1c0a8024af2544a Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Mon, 8 May 2023 09:12:44 +0100 Subject: [PATCH 08/14] Little debug for placeholders --- .../net/Indyuce/mmocore/comp/placeholder/RPGPlaceholders.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/placeholder/RPGPlaceholders.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/placeholder/RPGPlaceholders.java index c9c506cd..e6ef8011 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/placeholder/RPGPlaceholders.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/placeholder/RPGPlaceholders.java @@ -73,8 +73,8 @@ public class RPGPlaceholders extends PlaceholderExpansion { return String.valueOf(playerData.getSkillLevel(skill)); } - else if (identifier.startsWith("mmocore_attribute_points_spent_")) { - String attributeId = identifier.substring(31); + else if (identifier.startsWith("attribute_points_spent_")) { + String attributeId = identifier.substring(23); PlayerAttributes.AttributeInstance attributeInstance = Objects.requireNonNull(playerData.getAttributes().getInstance(attributeId), "Could not find attribute with ID '" + attributeId + "'"); return String.valueOf(attributeInstance.getBase()); } From a09c23ecf5909e0e07059738ece1835a26fd1e50 Mon Sep 17 00:00:00 2001 From: Jules Date: Mon, 8 May 2023 11:43:01 +0200 Subject: [PATCH 09/14] Fixed NoClassDefFound --- .../manager/data/PlayerDataManager.java | 3 +- .../ForceChooseClassListener.java | 29 +++++++------------ MMOCore-Dist/src/main/resources/config.yml | 2 +- 3 files changed, 13 insertions(+), 21 deletions(-) rename MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/{ => option}/ForceChooseClassListener.java (67%) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java index a84bf5d5..a29131e0 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java @@ -1,7 +1,6 @@ package net.Indyuce.mmocore.manager.data; import io.lumine.mythic.lib.api.player.MMOPlayerData; -import io.lumine.mythic.lib.comp.profile.ProfileDataModuleImpl; import io.lumine.mythic.lib.data.SynchronizedDataManager; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; @@ -23,7 +22,7 @@ public class PlayerDataManager extends SynchronizedDataManager Date: Sun, 14 May 2023 16:34:43 +0200 Subject: [PATCH 10/14] force-class-selection fixes --- MMOCore-API/pom.xml | 2 +- .../java/net/Indyuce/mmocore/MMOCore.java | 26 +-- .../mmocore/api/player/PlayerData.java | 1 + .../profile/MMOCoreProfileDataModule.java | 35 +++- .../mmocore/gui/ClassConfirmation.java | 37 +++- .../net/Indyuce/mmocore/gui/ClassSelect.java | 41 +++- .../Indyuce/mmocore/gui/SubclassSelect.java | 2 +- .../mmocore/gui/api/GeneratedInventory.java | 3 + .../mmocore/manager/ConfigManager.java | 3 +- .../manager/data/GuildDataManager.java | 180 +++++++++--------- .../manager/data/PlayerDataManager.java | 5 + .../net/Indyuce/mmocore/MMOCoreBukkit.java | 4 - .../option/ForceChooseClassListener.java | 47 ----- MMOCore-Dist/src/main/resources/config.yml | 12 +- 14 files changed, 213 insertions(+), 185 deletions(-) delete mode 100644 MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/option/ForceChooseClassListener.java diff --git a/MMOCore-API/pom.xml b/MMOCore-API/pom.xml index 4de78a2a..5bc4fcb4 100644 --- a/MMOCore-API/pom.xml +++ b/MMOCore-API/pom.xml @@ -141,7 +141,7 @@ fr.phoenixdevt - MMOProfiles-Dist + Profile-API 1.0-SNAPSHOT provided true diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java index 03ccdf50..103362ea 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java @@ -29,13 +29,13 @@ import net.Indyuce.mmocore.guild.GuildModuleType; import net.Indyuce.mmocore.guild.GuildRelationHandler; import net.Indyuce.mmocore.guild.provided.Guild; import net.Indyuce.mmocore.guild.provided.MMOCoreGuildModule; +import net.Indyuce.mmocore.guild.provided.YAMLGuildDataManager; import net.Indyuce.mmocore.manager.*; import net.Indyuce.mmocore.manager.data.DataProvider; import net.Indyuce.mmocore.manager.data.GuildDataManager; import net.Indyuce.mmocore.manager.data.LegacyDataProvider; import net.Indyuce.mmocore.manager.data.PlayerDataManager; import net.Indyuce.mmocore.manager.data.sql.SQLDataHandler; -import net.Indyuce.mmocore.guild.provided.YAMLGuildDataManager; import net.Indyuce.mmocore.manager.profession.*; import net.Indyuce.mmocore.manager.social.BoosterManager; import net.Indyuce.mmocore.manager.social.PartyManager; @@ -258,8 +258,7 @@ public class MMOCore extends JavaPlugin { * that after registering all the professses otherwise the player datas can't * recognize what profess the player has and professes will be lost */ - playerDataManager.setupAll(); - playerDataManager.registerEvents(EventPriority.NORMAL, EventPriority.NORMAL); + playerDataManager.initialize(EventPriority.NORMAL, EventPriority.NORMAL); // load guild data after loading player data dataProvider.getGuildManager().load(); @@ -271,25 +270,6 @@ public class MMOCore extends JavaPlugin { MMOCoreCommandTreeRoot mmoCoreCommand = new MMOCoreCommandTreeRoot(); getCommand("mmocore").setExecutor(mmoCoreCommand); getCommand("mmocore").setTabCompleter(mmoCoreCommand); - - if (getConfig().getBoolean("auto-save.enabled")) - - { - int autosave = getConfig().getInt("auto-save.interval") * 20; - new BukkitRunnable() { - public void run() { - - // Save player data - for (PlayerData data : PlayerData.getAll()) - if (data.isSynchronized()) - dataProvider.getDataManager().getDataHandler().saveData(data, false); - - // Save guild info - for (Guild guild : dataProvider.getGuildManager().getAll()) - dataProvider.getGuildManager().save(guild); - } - }.runTaskTimerAsynchronously(MMOCore.plugin, autosave, autosave); - } } @Override @@ -306,8 +286,6 @@ public class MMOCore extends JavaPlugin { for (PlayerData data : PlayerData.getAll()) if (data.isSynchronized()) { data.close(); - // Saves player health before saveData as the player will be considered offline into it if it is async. - data.setHealth(data.getPlayer().getHealth()); dataProvider.getDataManager().getDataHandler().saveData(data, true); } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java index cafd7964..ba83c86c 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java @@ -427,6 +427,7 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD @Override public void close() { + // Saves player health before saveData as the player will be considered offline into it if it is async health = getPlayer().getHealth(); // Remove from party if it is MMO Party Module diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/profile/MMOCoreProfileDataModule.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/profile/MMOCoreProfileDataModule.java index 1f410f74..57f6c09b 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/profile/MMOCoreProfileDataModule.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/profile/MMOCoreProfileDataModule.java @@ -1,17 +1,26 @@ package net.Indyuce.mmocore.comp.profile; +import fr.phoenixdevt.profile.ProfileDataModule; +import fr.phoenixdevt.profile.event.ProfileCreateEvent; +import fr.phoenixdevt.profile.event.ProfileDeleteEvent; import fr.phoenixdevt.profile.placeholder.PlaceholderRequest; import io.lumine.mythic.lib.MythicLib; import io.lumine.mythic.lib.api.player.MMOPlayerData; -import io.lumine.mythic.lib.comp.profile.ProfileDataModuleImpl; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.api.player.attribute.PlayerAttribute; import net.Indyuce.mmocore.experience.Profession; +import net.Indyuce.mmocore.manager.InventoryManager; +import org.bukkit.Bukkit; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.plugin.java.JavaPlugin; -public class MMOCoreProfileDataModule extends ProfileDataModuleImpl { - public MMOCoreProfileDataModule() { - super(MMOCore.plugin); +public class MMOCoreProfileDataModule implements ProfileDataModule, Listener { + + @Override + public JavaPlugin getOwningPlugin() { + return MMOCore.plugin; } @Override @@ -43,4 +52,22 @@ public class MMOCoreProfileDataModule extends ProfileDataModuleImpl { placeholderRequest.validate(); }); } + + @EventHandler + public void onProfileCreate(ProfileCreateEvent event) { + + // Force to choose class first + if (MMOCore.plugin.configManager.forceClassSelection) { + final PlayerData playerData = PlayerData.get(event.getPlayerData().getUniqueId()); + InventoryManager.CLASS_SELECT.newInventory(playerData, () -> event.validate(this)).open(); + } + + // Validate event directly + else event.validate(this); + } + + @EventHandler + public void onProfileDelete(ProfileDeleteEvent event) { + event.validate(this); + } } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassConfirmation.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassConfirmation.java index fbdecc30..2d31af07 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassConfirmation.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassConfirmation.java @@ -20,8 +20,11 @@ import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.inventory.ItemStack; +import javax.annotation.Nullable; + public class ClassConfirmation extends EditableInventory { private final PlayerClass playerClass; @@ -37,7 +40,11 @@ public class ClassConfirmation extends EditableInventory { } public GeneratedInventory newInventory(PlayerData data, PluginInventory last, boolean subclass) { - return new ClassConfirmationInventory(data, this, playerClass, last, subclass); + return newInventory(data, last, subclass, null); + } + + public GeneratedInventory newInventory(PlayerData data, PluginInventory last, boolean subclass, @Nullable Runnable profileRunnable) { + return new ClassConfirmationInventory(data, this, playerClass, last, subclass, profileRunnable); } public class UnlockedItem extends InventoryItem { @@ -105,26 +112,33 @@ public class ClassConfirmation extends EditableInventory { private final PluginInventory last; private final boolean subclass; - public ClassConfirmationInventory(PlayerData playerData, EditableInventory editable, PlayerClass profess, PluginInventory last, boolean subclass) { + @Nullable + private final Runnable profileRunnable; + + private boolean canClose; + + public ClassConfirmationInventory(PlayerData playerData, EditableInventory editable, PlayerClass profess, PluginInventory last, boolean subclass, @Nullable Runnable profileRunnable) { super(playerData, editable); this.profess = profess; this.last = last; this.subclass = subclass; + this.profileRunnable = profileRunnable; } @Override public void whenClicked(InventoryClickContext context, InventoryItem item) { - if (item.getFunction().equals("back")) + if (item.getFunction().equals("back")) { + canClose = true; last.open(); - - else if (item.getFunction().equals("yes")) { + } else if (item.getFunction().equals("yes")) { PlayerChangeClassEvent called = new PlayerChangeClassEvent(playerData, profess); Bukkit.getPluginManager().callEvent(called); if (called.isCancelled()) return; + canClose = true; playerData.giveClassPoints(-1); if (subclass) playerData.setClass(profess); @@ -134,9 +148,22 @@ public class ClassConfirmation extends EditableInventory { MMOCore.plugin.configManager.getSimpleMessage("class-select", "class", profess.getName()).send(player); MMOCore.plugin.soundManager.getSound(SoundEvent.SELECT_CLASS).playTo(player); player.closeInventory(); + if (profileRunnable != null) profileRunnable.run(); } } + @Override + public void open() { + canClose = false; + super.open(); + } + + @Override + public void whenClosed(InventoryCloseEvent event) { + if (profileRunnable != null && !canClose) + Bukkit.getScheduler().runTaskLater(MMOCore.plugin, () -> open(), 2 * 20); + } + @Override public String calculateName() { return getName().replace("{class}", profess.getName()); diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassSelect.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassSelect.java index 7ada1ba9..7ae2667c 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassSelect.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassSelect.java @@ -16,14 +16,17 @@ import net.Indyuce.mmocore.gui.api.item.InventoryItem; import net.Indyuce.mmocore.gui.api.item.SimplePlaceholderItem; import net.Indyuce.mmocore.manager.InventoryManager; import org.apache.commons.lang.Validate; +import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.persistence.PersistentDataType; +import javax.annotation.Nullable; import java.util.ArrayList; import java.util.Comparator; import java.util.List; @@ -41,7 +44,11 @@ public class ClassSelect extends EditableInventory { } public GeneratedInventory newInventory(PlayerData data) { - return new ProfessSelectionInventory(data, this); + return newInventory(data, null); + } + + public GeneratedInventory newInventory(PlayerData data, @Nullable Runnable profileRunnable) { + return new ProfessSelectionInventory(data, this, profileRunnable); } public class ClassItem extends SimplePlaceholderItem { @@ -51,9 +58,10 @@ public class ClassSelect extends EditableInventory { public ClassItem(ConfigurationSection config) { super(Material.BARRIER, config); - Validate.isTrue(config.getString("function").length()>6,"Couldn't find the class associated to: "+config.getString("function")); + + Validate.isTrue(config.getString("function").length() > 6, "Couldn't find the class associated to: " + config.getString("function")); String classId = UtilityMethods.enumName(config.getString("function").substring(6)); - this.playerClass = Objects.requireNonNull(MMOCore.plugin.classManager.get(classId),classId+" does not correspond to any classId."); + this.playerClass = Objects.requireNonNull(MMOCore.plugin.classManager.get(classId), classId + " does not correspond to any classId."); this.name = config.getString("name"); this.lore = config.getStringList("lore"); } @@ -93,8 +101,16 @@ public class ClassSelect extends EditableInventory { } public class ProfessSelectionInventory extends GeneratedInventory { - public ProfessSelectionInventory(PlayerData playerData, EditableInventory editable) { + + @Nullable + private final Runnable profileRunnable; + + private boolean canClose; + + public ProfessSelectionInventory(PlayerData playerData, EditableInventory editable, @Nullable Runnable profileRunnable) { super(playerData, editable); + + this.profileRunnable = profileRunnable; } @Override @@ -107,7 +123,7 @@ public class ClassSelect extends EditableInventory { if (item instanceof ClassItem) { PlayerClass profess = ((ClassItem) item).playerClass; - if (playerData.getClassPoints() < 1) { + if (profileRunnable == null && playerData.getClassPoints() < 1) { MMOCore.plugin.soundManager.getSound(SoundEvent.CANT_SELECT_CLASS).playTo(player); new ConfigMessage("cant-choose-new-class").send(player); return; @@ -125,10 +141,23 @@ public class ClassSelect extends EditableInventory { return; } + canClose = true; final PlayerClass playerClass = findDeepestSubclass(playerData, profess); - InventoryManager.CLASS_CONFIRM.get(MMOCoreUtils.ymlName(playerClass.getId())).newInventory(playerData, this, false).open(); + InventoryManager.CLASS_CONFIRM.get(MMOCoreUtils.ymlName(playerClass.getId())).newInventory(playerData, this, false, profileRunnable).open(); } } + + @Override + public void open() { + canClose = false; + super.open(); + } + + @Override + public void whenClosed(InventoryCloseEvent event) { + if (profileRunnable != null && !canClose) + Bukkit.getScheduler().runTaskLater(MMOCore.plugin, () -> open(), 2 * 20); + } } /** diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/SubclassSelect.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/SubclassSelect.java index ad21f793..3ccb9b4c 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/SubclassSelect.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/SubclassSelect.java @@ -126,7 +126,7 @@ public class SubclassSelect extends EditableInventory { return; } - InventoryManager.CLASS_CONFIRM.get(classId).newInventory(playerData, this, true).open(); + InventoryManager.CLASS_CONFIRM.get(classId).newInventory(playerData, this, true, null).open(); } } } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/api/GeneratedInventory.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/api/GeneratedInventory.java index bbe3e3fc..daf76dd1 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/api/GeneratedInventory.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/api/GeneratedInventory.java @@ -22,6 +22,7 @@ public abstract class GeneratedInventory extends PluginInventory { public GeneratedInventory(PlayerData playerData, EditableInventory editable) { super(playerData); + this.editable = editable; this.adaptor = editable.getAdaptorType().supply(this); } @@ -66,6 +67,8 @@ public abstract class GeneratedInventory extends PluginInventory { @Override public void open() { + if (!getPlayerData().isOnline()) return; + /* * Very important, in order to prevent ghost items, the loaded items map * must be cleared when the inventory is updated or open at least twice diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/ConfigManager.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/ConfigManager.java index 3ebc70db..6d9bc27c 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/ConfigManager.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/ConfigManager.java @@ -28,7 +28,7 @@ public class ConfigManager { public final CommandVerbose commandVerbose = new CommandVerbose(); public boolean overrideVanillaExp, canCreativeCast, passiveSkillNeedBound, cobbleGeneratorXP, saveDefaultClassInfo, splitMainExp, splitProfessionExp, disableQuestBossBar, - pvpModeEnabled, pvpModeInvulnerabilityCanDamage; + pvpModeEnabled, pvpModeInvulnerabilityCanDamage, forceClassSelection; public String partyChatPrefix, noSkillBoundPlaceholder; public ChatColor staminaFull, staminaHalf, staminaEmpty; public long combatLogTimer, lootChestExpireTime, lootChestPlayerCooldown, globalSkillCooldown; @@ -133,6 +133,7 @@ public class ConfigManager { splitMainExp = MMOCore.plugin.getConfig().getBoolean("party.main-exp-split"); splitProfessionExp = MMOCore.plugin.getConfig().getBoolean("party.profession-exp-split"); disableQuestBossBar = MMOCore.plugin.getConfig().getBoolean("mmocore-quests.disable-boss-bar"); + forceClassSelection = MMOCore.plugin.getConfig().getBoolean("force-class-selection"); // Combat pvpModeEnabled = config.getBoolean("pvp_mode.enabled"); diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/GuildDataManager.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/GuildDataManager.java index ef81d0ee..2bd73fc5 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/GuildDataManager.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/GuildDataManager.java @@ -14,117 +14,121 @@ import net.Indyuce.mmocore.guild.provided.Guild; import javax.annotation.Nullable; public abstract class GuildDataManager { - protected final Map guilds = new HashMap<>(); + protected final Map guilds = new HashMap<>(); - public Guild newRegisteredGuild(UUID owner, String name, String tag) { - Guild guild = new Guild(owner, name, tag); - registerGuild(guild); - return guild; - } + public Guild newRegisteredGuild(UUID owner, String name, String tag) { + Guild guild = new Guild(owner, name, tag); + registerGuild(guild); + return guild; + } - public void registerGuild(Guild guild) { - guilds.put(guild.getId(), guild); - } + public void registerGuild(Guild guild) { + guilds.put(guild.getId(), guild); + } - public boolean isRegistered(Guild guild) { - return guilds.containsValue(guild); - } + public boolean isRegistered(Guild guild) { + return guilds.containsValue(guild); + } - public boolean isRegistered(String tag) { - return guilds.containsKey(tag); - } + public boolean isRegistered(String tag) { + return guilds.containsKey(tag); + } - public void unregisterGuild(Guild guild) { - guild.forEachMember(member -> guild.removeMember(member, true)); - // guild.getMembers().clear(); - guilds.remove(guild.getId()); - delete(guild); - } + public void unregisterGuild(Guild guild) { + guild.forEachMember(member -> guild.removeMember(member, true)); + // guild.getMembers().clear(); + guilds.remove(guild.getId()); + delete(guild); + } - @Nullable - public Guild getGuild(String guild) { - return guilds.get(guild); - } + public void saveAll() { + for (Guild guild : guilds.values()) save(guild); + } - public Collection getAll() { - return guilds.values(); - } + @Nullable + public Guild getGuild(String guild) { + return guilds.get(guild); + } - @Deprecated - public void reload() { - for (Guild guild : guilds.values()) - save(guild); - guilds.clear(); - load(); - config = new GuildConfiguration(); - } + public Collection getAll() { + return guilds.values(); + } - public abstract void save(Guild guild); + @Deprecated + public void reload() { + for (Guild guild : guilds.values()) + save(guild); + guilds.clear(); + load(); + config = new GuildConfiguration(); + } - // TODO move to constructor, useless to handle vie abstract method - public abstract void load(); + public abstract void save(Guild guild); - public abstract void delete(Guild guild); + // TODO move to constructor, useless to handle vie abstract method + public abstract void load(); - // TODO fix this - // Shitty code for loading config values for guilds. - private GuildConfiguration config; + public abstract void delete(Guild guild); - public GuildConfiguration getConfig() { - return config == null ? config = new GuildConfiguration() : config; - } + // TODO fix this + // Shitty code for loading config values for guilds. + private GuildConfiguration config; - public static class GuildConfiguration { - private final String prefix; - private final boolean uppercaseTags; - private final NamingRules tagRules, nameRules; + public GuildConfiguration getConfig() { + return config == null ? config = new GuildConfiguration() : config; + } - public GuildConfiguration() { - FileConfiguration config = new ConfigFile("guilds").getConfig(); + public static class GuildConfiguration { + private final String prefix; + private final boolean uppercaseTags; + private final NamingRules tagRules, nameRules; - this.prefix = config.getString("chat-prefix", "*"); - this.uppercaseTags = config.getBoolean("uppercase-tags", true); - this.tagRules = new NamingRules(config.getConfigurationSection("rules.tag")); - this.nameRules = new NamingRules(config.getConfigurationSection("rules.name")); - } + public GuildConfiguration() { + FileConfiguration config = new ConfigFile("guilds").getConfig(); - public String getPrefix() { - return prefix; - } + this.prefix = config.getString("chat-prefix", "*"); + this.uppercaseTags = config.getBoolean("uppercase-tags", true); + this.tagRules = new NamingRules(config.getConfigurationSection("rules.tag")); + this.nameRules = new NamingRules(config.getConfigurationSection("rules.name")); + } - public boolean shouldUppercaseTags() { - return uppercaseTags; - } + public String getPrefix() { + return prefix; + } - public NamingRules getTagRules() { - return tagRules; - } + public boolean shouldUppercaseTags() { + return uppercaseTags; + } - public NamingRules getNameRules() { - return nameRules; - } + public NamingRules getTagRules() { + return tagRules; + } - public static class NamingRules { - private final String regex; - private final int min, max; + public NamingRules getNameRules() { + return nameRules; + } - public NamingRules(ConfigurationSection config) { - regex = config.getString("matches", "[a-zA-Z-_!?]+"); - min = config.getInt("min-length", 3); - max = config.getInt("max-length", 5); - } + public static class NamingRules { + private final String regex; + private final int min, max; - public String getRegex() { - return regex; - } + public NamingRules(ConfigurationSection config) { + regex = config.getString("matches", "[a-zA-Z-_!?]+"); + min = config.getInt("min-length", 3); + max = config.getInt("max-length", 5); + } - public int getMin() { - return min; - } + public String getRegex() { + return regex; + } - public int getMax() { - return max; - } - } - } + public int getMin() { + return min; + } + + public int getMax() { + return max; + } + } + } } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java index a29131e0..b0aa2584 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java @@ -33,4 +33,9 @@ public class PlayerDataManager extends SynchronizedDataManager Date: Sun, 14 May 2023 23:27:11 +0200 Subject: [PATCH 11/14] Force class on profile selection --- .../mmocore/api/player/PlayerData.java | 6 +- .../profile/ForceClassProfileDataModule.java | 79 +++++++++++++++++++ .../profile/MMOCoreProfileDataModule.java | 16 +--- .../mmocore/gui/ClassConfirmation.java | 8 +- .../net/Indyuce/mmocore/gui/ClassSelect.java | 2 +- .../data/sql/MMOCoreDataSynchronizer.java | 19 ++--- .../data/yaml/YAMLPlayerDataHandler.java | 30 ++++--- .../mmocore/player/DefaultPlayerData.java | 5 +- .../net/Indyuce/mmocore/MMOCoreBukkit.java | 5 ++ MMOCore-Dist/src/main/resources/config.yml | 3 +- 10 files changed, 127 insertions(+), 46 deletions(-) create mode 100644 MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/profile/ForceClassProfileDataModule.java diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java index ba83c86c..5f90a2bc 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java @@ -669,7 +669,11 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD } public void unloadClassInfo(PlayerClass profess) { - classSlots.remove(profess.getId()); + unloadClassInfo(profess.getId()); + } + + public void unloadClassInfo(String profess) { + classSlots.remove(profess); } public Set getWaypoints() { diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/profile/ForceClassProfileDataModule.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/profile/ForceClassProfileDataModule.java new file mode 100644 index 00000000..2a411e3f --- /dev/null +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/profile/ForceClassProfileDataModule.java @@ -0,0 +1,79 @@ +package net.Indyuce.mmocore.comp.profile; + +import fr.phoenixdevt.profile.ProfileDataModule; +import fr.phoenixdevt.profile.ProfileProvider; +import fr.phoenixdevt.profile.event.ProfileCreateEvent; +import fr.phoenixdevt.profile.event.ProfileRemoveEvent; +import fr.phoenixdevt.profile.event.ProfileSelectEvent; +import fr.phoenixdevt.profile.event.ProfileUnloadEvent; +import fr.phoenixdevt.profile.placeholder.PlaceholderRequest; +import io.lumine.mythic.lib.api.event.SynchronizedDataLoadEvent; +import net.Indyuce.mmocore.MMOCore; +import net.Indyuce.mmocore.api.player.PlayerData; +import net.Indyuce.mmocore.manager.InventoryManager; +import org.bukkit.Bukkit; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.plugin.java.JavaPlugin; + +public class ForceClassProfileDataModule implements ProfileDataModule, Listener { + public ForceClassProfileDataModule() { + final ProfileProvider provider = Bukkit.getServicesManager().getRegistration(ProfileProvider.class).getProvider(); + provider.registerModule(this); + } + + @Override + public JavaPlugin getOwningPlugin() { + return MMOCore.plugin; + } + + @Override + public boolean hasPlaceholders() { + return false; + } + + @Override + public String getIdentifier() { + return "mmocore_force_class"; + } + + @Override + public void processPlaceholderRequest(PlaceholderRequest placeholderRequest) { + throw new RuntimeException("Not supported"); + } + + /** + * Force class before profile creation + */ + @EventHandler + public void onProfileCreate(ProfileCreateEvent event) { + final PlayerData playerData = PlayerData.get(event.getPlayerData().getUniqueId()); + InventoryManager.CLASS_SELECT.newInventory(playerData, () -> event.validate(this)).open(); + } + + /** + * Force class before profile selection once MMOCore loaded its data + */ + @EventHandler + public void onDataLoad(SynchronizedDataLoadEvent event) { + if (event.getManager().getOwningPlugin().equals(MMOCore.plugin)) { + final PlayerData playerData = (PlayerData) event.getHolder(); + final ProfileSelectEvent event1 = (ProfileSelectEvent) event.getProfileEvent(); + + // Validate if necessary + if (playerData.getProfess().equals(MMOCore.plugin.classManager.getDefaultClass())) + InventoryManager.CLASS_SELECT.newInventory(playerData, () -> event1.validate(this)).open(); + else event1.validate(this); + } + } + + @EventHandler + public void onProfileRemove(ProfileRemoveEvent event) { + event.validate(this); + } + + @EventHandler + public void onProfileUnload(ProfileUnloadEvent event) { + event.validate(this); + } +} diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/profile/MMOCoreProfileDataModule.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/profile/MMOCoreProfileDataModule.java index 57f6c09b..76dfe6d5 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/profile/MMOCoreProfileDataModule.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/profile/MMOCoreProfileDataModule.java @@ -2,7 +2,7 @@ package net.Indyuce.mmocore.comp.profile; import fr.phoenixdevt.profile.ProfileDataModule; import fr.phoenixdevt.profile.event.ProfileCreateEvent; -import fr.phoenixdevt.profile.event.ProfileDeleteEvent; +import fr.phoenixdevt.profile.event.ProfileRemoveEvent; import fr.phoenixdevt.profile.placeholder.PlaceholderRequest; import io.lumine.mythic.lib.MythicLib; import io.lumine.mythic.lib.api.player.MMOPlayerData; @@ -10,8 +10,6 @@ import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.api.player.attribute.PlayerAttribute; import net.Indyuce.mmocore.experience.Profession; -import net.Indyuce.mmocore.manager.InventoryManager; -import org.bukkit.Bukkit; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.plugin.java.JavaPlugin; @@ -55,19 +53,11 @@ public class MMOCoreProfileDataModule implements ProfileDataModule, Listener { @EventHandler public void onProfileCreate(ProfileCreateEvent event) { - - // Force to choose class first - if (MMOCore.plugin.configManager.forceClassSelection) { - final PlayerData playerData = PlayerData.get(event.getPlayerData().getUniqueId()); - InventoryManager.CLASS_SELECT.newInventory(playerData, () -> event.validate(this)).open(); - } - - // Validate event directly - else event.validate(this); + event.validate(this); } @EventHandler - public void onProfileDelete(ProfileDeleteEvent event) { + public void onProfileDelete(ProfileRemoveEvent event) { event.validate(this); } } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassConfirmation.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassConfirmation.java index 2d31af07..d94443a4 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassConfirmation.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassConfirmation.java @@ -39,12 +39,12 @@ public class ClassConfirmation extends EditableInventory { return function.equalsIgnoreCase("yes") ? new YesItem(config) : new SimplePlaceholderItem(config); } - public GeneratedInventory newInventory(PlayerData data, PluginInventory last, boolean subclass) { - return newInventory(data, last, subclass, null); + public GeneratedInventory newInventory(PlayerData data, PluginInventory last, boolean setClass) { + return newInventory(data, last, setClass, null); } - public GeneratedInventory newInventory(PlayerData data, PluginInventory last, boolean subclass, @Nullable Runnable profileRunnable) { - return new ClassConfirmationInventory(data, this, playerClass, last, subclass, profileRunnable); + public GeneratedInventory newInventory(PlayerData data, PluginInventory last, boolean setClass, @Nullable Runnable profileRunnable) { + return new ClassConfirmationInventory(data, this, playerClass, last, setClass, profileRunnable); } public class UnlockedItem extends InventoryItem { diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassSelect.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassSelect.java index 7ae2667c..ddb1833a 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassSelect.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassSelect.java @@ -143,7 +143,7 @@ public class ClassSelect extends EditableInventory { canClose = true; final PlayerClass playerClass = findDeepestSubclass(playerData, profess); - InventoryManager.CLASS_CONFIRM.get(MMOCoreUtils.ymlName(playerClass.getId())).newInventory(playerData, this, false, profileRunnable).open(); + InventoryManager.CLASS_CONFIRM.get(MMOCoreUtils.ymlName(playerClass.getId())).newInventory(playerData, this, profileRunnable != null, profileRunnable).open(); } } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/MMOCoreDataSynchronizer.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/MMOCoreDataSynchronizer.java index cc7fc895..16ddddc3 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/MMOCoreDataSynchronizer.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/MMOCoreDataSynchronizer.java @@ -1,6 +1,9 @@ package net.Indyuce.mmocore.manager.data.sql; -import com.google.gson.*; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; import io.lumine.mythic.lib.MythicLib; import io.lumine.mythic.lib.UtilityMethods; import io.lumine.mythic.lib.data.sql.SQLDataSynchronizer; @@ -32,7 +35,8 @@ public class MMOCoreDataSynchronizer extends SQLDataSynchronizer { @Override public void loadData(ResultSet result) throws SQLException { - //Reset stats linked to triggers + + // Reset stats linked to triggers getData().resetTriggerStats(); getData().setClassPoints(result.getInt("class_points")); @@ -137,16 +141,7 @@ public class MMOCoreDataSynchronizer extends SQLDataSynchronizer { @Override public void loadEmptyData() { - final PlayerDataManager manager = MMOCore.plugin.playerDataManager; - getData().setLevel(manager.getDefaultData().getLevel()); - getData().setClassPoints(manager.getDefaultData().getClassPoints()); - getData().setSkillPoints(manager.getDefaultData().getSkillPoints()); - getData().setSkillReallocationPoints(manager.getDefaultData().getSkillReallocationPoints()); - getData().setAttributePoints(manager.getDefaultData().getAttributePoints()); - getData().setAttributeReallocationPoints(manager.getDefaultData().getAttributeReallocationPoints()); - getData().setExperience(0); - getData().getQuestData().updateBossBar(); - + MMOCore.plugin.playerDataManager.getDefaultData().apply(getData()); UtilityMethods.debug(MMOCore.plugin, "SQL", "Loaded DEFAULT data for: '" + getData().getUniqueId() + "' as no saved data was found."); } } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLPlayerDataHandler.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLPlayerDataHandler.java index 351fb0c3..0d11a606 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLPlayerDataHandler.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLPlayerDataHandler.java @@ -2,13 +2,12 @@ package net.Indyuce.mmocore.manager.data.yaml; import io.lumine.mythic.lib.data.yaml.YAMLSynchronizedDataHandler; import net.Indyuce.mmocore.MMOCore; -import net.Indyuce.mmocore.manager.data.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.util.MMOCoreUtils; import net.Indyuce.mmocore.guild.provided.Guild; -import net.Indyuce.mmocore.player.DefaultPlayerData; +import net.Indyuce.mmocore.manager.data.OfflinePlayerData; import net.Indyuce.mmocore.skill.ClassSkill; import net.Indyuce.mmocore.skilltree.SkillTreeNode; import org.apache.commons.lang.Validate; @@ -17,7 +16,8 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.NotNull; -import java.util.*; +import java.util.ArrayList; +import java.util.UUID; import java.util.logging.Level; import java.util.stream.Collectors; @@ -42,17 +42,21 @@ public class YAMLPlayerDataHandler extends YAMLSynchronizedDataHandler Date: Mon, 15 May 2023 00:06:34 +0200 Subject: [PATCH 12/14] Removed unused sound --- .../src/main/java/net/Indyuce/mmocore/api/SoundEvent.java | 1 - MMOCore-Dist/src/main/resources/default/sounds.yml | 2 -- 2 files changed, 3 deletions(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/SoundEvent.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/SoundEvent.java index efcb287c..2b465470 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/SoundEvent.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/SoundEvent.java @@ -6,7 +6,6 @@ public enum SoundEvent { WARP_CANCELLED, WARP_CHARGE, WARP_UNLOCK, - HOTBAR_SWAP, SPELL_CAST_BEGIN, SPELL_CAST_END, CANT_SELECT_CLASS, diff --git a/MMOCore-Dist/src/main/resources/default/sounds.yml b/MMOCore-Dist/src/main/resources/default/sounds.yml index c2060944..2f4bd2ae 100644 --- a/MMOCore-Dist/src/main/resources/default/sounds.yml +++ b/MMOCore-Dist/src/main/resources/default/sounds.yml @@ -9,8 +9,6 @@ warp-teleport: ENTITY_ENDERMAN_TELEPORT,1,0.5 warp-charge: BLOCK_NOTE_BLOCK_BELL #Uses a special pitch method, so pitch and volume is not changeable warp-unlock: UI_TOAST_CHALLENGE_COMPLETE,1,1.2 -hotbar-swap: ITEM_ARMOR_EQUIP_LEATHER - spell-cast-begin: BLOCK_END_PORTAL_FRAME_FILL,1,2 spell-cast-end: BLOCK_FIRE_EXTINGUISH,1,2 From f1d90589a4c5160fb2301f958a921cf6cd127d08 Mon Sep 17 00:00:00 2001 From: Jules Date: Mon, 15 May 2023 00:07:54 +0200 Subject: [PATCH 13/14] Update lib --- MMOCore-API/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MMOCore-API/pom.xml b/MMOCore-API/pom.xml index 5bc4fcb4..e75e68ab 100644 --- a/MMOCore-API/pom.xml +++ b/MMOCore-API/pom.xml @@ -142,7 +142,7 @@ fr.phoenixdevt Profile-API - 1.0-SNAPSHOT + 1.0 provided true From c0373750cd5a3566c6ded11580a3952fdeda7b2e Mon Sep 17 00:00:00 2001 From: Jules Date: Mon, 15 May 2023 00:10:06 +0200 Subject: [PATCH 14/14] Fixed compile errors --- .../java/net/Indyuce/mmocore/api/player/PlayerData.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java index b951bec9..40c7e380 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java @@ -20,9 +20,6 @@ import net.Indyuce.mmocore.api.player.profess.PlayerClass; 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.manager.data.OfflinePlayerData; -import net.Indyuce.mmocore.api.quest.trigger.Trigger; -import net.Indyuce.mmocore.skill.binding.BoundSkillInfo; import net.Indyuce.mmocore.api.player.social.FriendRequest; import net.Indyuce.mmocore.api.player.stats.PlayerStats; import net.Indyuce.mmocore.api.quest.PlayerQuests; @@ -38,6 +35,7 @@ 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.loot.chest.particle.SmallParticleEffect; +import net.Indyuce.mmocore.manager.data.OfflinePlayerData; import net.Indyuce.mmocore.party.AbstractParty; import net.Indyuce.mmocore.party.provided.MMOCorePartyModule; import net.Indyuce.mmocore.party.provided.Party; @@ -50,8 +48,6 @@ import net.Indyuce.mmocore.skill.binding.BoundSkillInfo; import net.Indyuce.mmocore.skill.binding.SkillSlot; import net.Indyuce.mmocore.skill.cast.SkillCastingInstance; import net.Indyuce.mmocore.skill.cast.SkillCastingMode; -import net.Indyuce.mmocore.skilltree.IntegerCoordinates; -import net.Indyuce.mmocore.skill.cast.SkillCastingHandler; import net.Indyuce.mmocore.skilltree.NodeStatus; import net.Indyuce.mmocore.skilltree.SkillTreeNode; import net.Indyuce.mmocore.skilltree.tree.SkillTree;