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());
+ }
}