diff --git a/pom.xml b/pom.xml index f308891d..e9730ddf 100644 --- a/pom.xml +++ b/pom.xml @@ -125,7 +125,7 @@ io.lumine MythicLib - 1.1.3 + 1.1.4 provided diff --git a/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java b/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java index 927dedf1..94f17fad 100644 --- a/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java +++ b/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java @@ -1,8 +1,8 @@ package net.Indyuce.mmocore.api.player; -import io.lumine.mythic.lib.api.player.MMOPlayerData; -import io.lumine.mythic.lib.player.CooldownInfo; -import io.lumine.mythic.lib.player.CooldownMap; +import io.lumine.mythic.lib.player.MMOPlayerData; +import io.lumine.mythic.lib.player.cooldown.CooldownInfo; +import io.lumine.mythic.lib.player.cooldown.CooldownMap; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.ConfigMessage; import net.Indyuce.mmocore.api.Waypoint; @@ -19,6 +19,7 @@ import net.Indyuce.mmocore.api.player.social.guilds.Guild; import net.Indyuce.mmocore.api.player.stats.PlayerStats; import net.Indyuce.mmocore.api.player.stats.StatType; import net.Indyuce.mmocore.api.quest.PlayerQuests; +import net.Indyuce.mmocore.api.util.Closable; import net.Indyuce.mmocore.api.util.MMOCoreUtils; import net.Indyuce.mmocore.api.util.math.particle.SmallParticleEffect; import net.Indyuce.mmocore.experience.EXPSource; @@ -45,7 +46,7 @@ import java.util.*; import java.util.logging.Level; -public class PlayerData extends OfflinePlayerData { +public class PlayerData extends OfflinePlayerData implements Closable { /** * Corresponds to the MythicLib player data. It is used to keep @@ -127,6 +128,11 @@ public class PlayerData extends OfflinePlayerData { } } + @Override + public void close() { + questData.close(); + } + public MMOPlayerData getMMOPlayerData() { return mmoData; } @@ -896,7 +902,23 @@ public class PlayerData extends OfflinePlayerData { * @return If player data for that player is loaded */ public static boolean has(Player player) { - return MMOCore.plugin.dataProvider.getDataManager().isLoaded(player.getUniqueId()); + return has(player.getUniqueId()); + } + + /** + * This is used to check if the player data is loaded for a + * specific player. This might seem redundant because the given + * Player instance is linked to an online player, and data + * is always loaded for an online player. + *

+ * In fact a Player instance can be attached to a Citizens NPC + * which has no player data loaded hence this method + * + * @param uuid A (real or fictive) player UUID + * @return If player data for that player is loaded + */ + public static boolean has(UUID uuid) { + return MMOCore.plugin.dataProvider.getDataManager().isLoaded(uuid); } public static Collection getAll() { diff --git a/src/main/java/net/Indyuce/mmocore/api/quest/ObjectiveProgress.java b/src/main/java/net/Indyuce/mmocore/api/quest/ObjectiveProgress.java index cb747478..92e56216 100644 --- a/src/main/java/net/Indyuce/mmocore/api/quest/ObjectiveProgress.java +++ b/src/main/java/net/Indyuce/mmocore/api/quest/ObjectiveProgress.java @@ -1,5 +1,6 @@ package net.Indyuce.mmocore.api.quest; +import net.Indyuce.mmocore.api.util.Closable; import org.bukkit.Bukkit; import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; @@ -8,7 +9,7 @@ import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.api.quest.objective.Objective; -public abstract class ObjectiveProgress { +public abstract class ObjectiveProgress implements Closable { private final Objective objective; private final QuestProgress questProgress; @@ -32,6 +33,7 @@ public abstract class ObjectiveProgress { return questProgress; } + @Override public void close() { if (this instanceof Listener) HandlerList.unregisterAll((Listener) this); diff --git a/src/main/java/net/Indyuce/mmocore/api/quest/PlayerQuests.java b/src/main/java/net/Indyuce/mmocore/api/quest/PlayerQuests.java index dbb3a980..37b66d9d 100644 --- a/src/main/java/net/Indyuce/mmocore/api/quest/PlayerQuests.java +++ b/src/main/java/net/Indyuce/mmocore/api/quest/PlayerQuests.java @@ -6,6 +6,7 @@ import com.google.gson.JsonObject; import io.lumine.mythic.lib.MythicLib; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; +import net.Indyuce.mmocore.api.util.Closable; import org.bukkit.NamespacedKey; import org.bukkit.boss.BarColor; import org.bukkit.boss.BarStyle; @@ -19,7 +20,7 @@ import java.util.Map.Entry; import java.util.Set; import java.util.logging.Level; -public class PlayerQuests { +public class PlayerQuests implements Closable { private final PlayerData playerData; private final BossBar bossbar; private final Map finished = new HashMap<>(); @@ -36,12 +37,6 @@ public class PlayerQuests { bossbar.addPlayer(playerData.getPlayer()); } - @Deprecated - public PlayerQuests(PlayerData playerData, BossBar bar) { - this.playerData = playerData; - this.bossbar = bar; - } - public PlayerQuests load(ConfigurationSection config) { if (config.contains("current")) try { @@ -148,15 +143,20 @@ public class PlayerQuests { public void start(Quest quest) { - // close current objective progress if quest is active - if (hasCurrent()) - current.getProgress().close(); + // Close current objective progress if quest is active + close(); - // apply newer quest + // Apply newest quest current = quest == null ? null : quest.generateNewProgress(playerData); updateBossBar(); } + @Override + public void close() { + if (current != null) + current.getProgress().close(); + } + public boolean checkCooldownAvailability(Quest quest) { return (finished.get(quest.getId()) + quest.getDelayMillis()) < System.currentTimeMillis(); } diff --git a/src/main/java/net/Indyuce/mmocore/api/util/Closable.java b/src/main/java/net/Indyuce/mmocore/api/util/Closable.java new file mode 100644 index 00000000..4b5283f3 --- /dev/null +++ b/src/main/java/net/Indyuce/mmocore/api/util/Closable.java @@ -0,0 +1,15 @@ +package net.Indyuce.mmocore.api.util; + +/** + * Indicates that a class temporarily registers something + * such as a Bukkit event, which needs to be unregistered + * when the class is finally garbage collected. + */ +public interface Closable { + + /** + * Method that must be called before the class + * is garbage collected + */ + void close(); +} diff --git a/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java b/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java index 27294614..e9a8cc7e 100644 --- a/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java +++ b/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java @@ -34,7 +34,12 @@ public abstract class PlayerDataManager { return Objects.requireNonNull(data.get(uuid), "Player data is not loaded"); } - public void remove(UUID uuid) { + /** + * Clears the data map from a certain key + * + * @param uuid Player UUID to clear + */ + protected void unregisterData(UUID uuid) { data.remove(uuid); } diff --git a/src/main/java/net/Indyuce/mmocore/manager/data/mysql/MySQLPlayerDataManager.java b/src/main/java/net/Indyuce/mmocore/manager/data/mysql/MySQLPlayerDataManager.java index 9383b1e4..ddde0b4a 100644 --- a/src/main/java/net/Indyuce/mmocore/manager/data/mysql/MySQLPlayerDataManager.java +++ b/src/main/java/net/Indyuce/mmocore/manager/data/mysql/MySQLPlayerDataManager.java @@ -238,7 +238,10 @@ public class MySQLPlayerDataManager extends PlayerDataManager { @Override public void remove(PlayerData data) { - if (data.isFullyLoaded()) saveData(data); - remove(data.getUniqueId()); + if (data.isFullyLoaded()) + saveData(data); + + data.close(); + unregisterData(data.getUniqueId()); } } diff --git a/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLPlayerDataManager.java b/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLPlayerDataManager.java index cc0e4f4b..baf7b9ad 100644 --- a/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLPlayerDataManager.java +++ b/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLPlayerDataManager.java @@ -129,5 +129,8 @@ public class YAMLPlayerDataManager extends PlayerDataManager { } @Override - public void remove(PlayerData data) {} + public void remove(PlayerData data) { + data.close(); + unregisterData(data.getUniqueId()); + } }