Browse Source

Merge branch 'master' of github.com:mcMMO-Dev/mcMMO into tridentsxbows

nossr50 5 years ago
parent
commit
f390e6a78a
17 changed files with 241 additions and 110 deletions
  1. 7 1
      Changelog.txt
  2. 20 0
      src/main/java/com/gmail/nossr50/datatypes/meta/UUIDMeta.java
  3. 1 4
      src/main/java/com/gmail/nossr50/listeners/BlockListener.java
  4. 2 5
      src/main/java/com/gmail/nossr50/listeners/InventoryListener.java
  5. 0 23
      src/main/java/com/gmail/nossr50/runnables/skills/FurnaceCleanupTask.java
  6. 0 16
      src/main/java/com/gmail/nossr50/skills/smelting/Smelting.java
  7. 23 17
      src/main/java/com/gmail/nossr50/util/compat/CompatibilityManager.java
  8. 2 1
      src/main/java/com/gmail/nossr50/util/compat/CompatibilityType.java
  9. 0 7
      src/main/java/com/gmail/nossr50/util/compat/layers/AbstractCompatibilityLayer.java
  10. 30 0
      src/main/java/com/gmail/nossr50/util/compat/layers/AbstractNMSCompatibilityLayer.java
  11. 1 1
      src/main/java/com/gmail/nossr50/util/compat/layers/attackcooldown/DummyPlayerAttackCooldownExploitPreventionLayer.java
  12. 3 2
      src/main/java/com/gmail/nossr50/util/compat/layers/attackcooldown/PlayerAttackCooldownExploitPreventionLayer.java
  13. 1 1
      src/main/java/com/gmail/nossr50/util/compat/layers/attackcooldown/PlayerAttackCooldownMethods.java
  14. 19 0
      src/main/java/com/gmail/nossr50/util/compat/layers/persistentdata/AbstractPersistentDataLayer.java
  15. 60 0
      src/main/java/com/gmail/nossr50/util/compat/layers/persistentdata/SpigotPersistentDataLayer.java
  16. 44 0
      src/main/java/com/gmail/nossr50/util/compat/layers/persistentdata/SpigotTemporaryDataLayer.java
  17. 28 32
      src/main/java/com/gmail/nossr50/util/skills/SmeltingTracker.java

+ 7 - 1
Changelog.txt

@@ -49,7 +49,13 @@ Version 2.2.000
     Notes:
     These are the first new skills that I've written for mcMMO in about 9 years, I'll be listening closely to feedback and tweaking them often.
 Version 2.1.136
-    Furnace ownership was made more reliable
+    Furnace ownership is no longer lost when the furnace stops doing a job
+    Furnaces remember owners between restarts (requires MC 1.14 or higher)
+
+    NOTES:
+        I'm making use of a Spigot API for persistent data for versions of MC 1.14 and above, for versions below the data will be temporary as it has been up until this point.
+        In the future I'll wire up NMS to make use of NBT and all versions will have persistent data support.
+
 
 Version 2.1.135
     Furnaces no longer simulate block break checks when assigning ownership as it caused some unwanted plugin conflicts

+ 20 - 0
src/main/java/com/gmail/nossr50/datatypes/meta/UUIDMeta.java

@@ -0,0 +1,20 @@
+package com.gmail.nossr50.datatypes.meta;
+
+import org.bukkit.metadata.FixedMetadataValue;
+import org.bukkit.plugin.Plugin;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.UUID;
+
+public class UUIDMeta extends FixedMetadataValue {
+    /**
+     * Initializes a FixedMetadataValue with an Object
+     *
+     * @param owningPlugin the {@link Plugin} that created this metadata value
+     * @param value        the value assigned to this metadata value
+     */
+    public UUIDMeta(@NotNull Plugin owningPlugin, @Nullable UUID value) {
+        super(owningPlugin, value);
+    }
+}

+ 1 - 4
src/main/java/com/gmail/nossr50/listeners/BlockListener.java

@@ -18,7 +18,6 @@ import com.gmail.nossr50.skills.herbalism.HerbalismManager;
 import com.gmail.nossr50.skills.mining.MiningManager;
 import com.gmail.nossr50.skills.repair.Repair;
 import com.gmail.nossr50.skills.salvage.Salvage;
-import com.gmail.nossr50.skills.smelting.Smelting;
 import com.gmail.nossr50.skills.woodcutting.WoodcuttingManager;
 import com.gmail.nossr50.util.BlockUtils;
 import com.gmail.nossr50.util.EventUtils;
@@ -39,10 +38,8 @@ import org.bukkit.event.EventPriority;
 import org.bukkit.event.Listener;
 import org.bukkit.event.block.*;
 import org.bukkit.inventory.ItemStack;
-import org.bukkit.metadata.MetadataValue;
 
 import java.util.HashSet;
-import java.util.List;
 
 public class BlockListener implements Listener {
     private final mcMMO plugin;
@@ -666,7 +663,7 @@ public class BlockListener implements Listener {
                 if(mcMMO.getSmeltingTracker().isFurnaceOwned(furnace))
                 {
                     player.sendMessage("[mcMMO DEBUG] This furnace has a registered owner");
-                    OfflinePlayer furnacePlayer = mcMMO.getSmeltingTracker().getPlayerFromFurnace(furnace);
+                    OfflinePlayer furnacePlayer = mcMMO.getSmeltingTracker().getFurnaceOwner(furnace);
                     if(furnacePlayer != null)
                     {
                         player.sendMessage("[mcMMO DEBUG] This furnace is owned by player "+furnacePlayer.getName());

+ 2 - 5
src/main/java/com/gmail/nossr50/listeners/InventoryListener.java

@@ -8,7 +8,6 @@ import com.gmail.nossr50.datatypes.skills.SubSkillType;
 import com.gmail.nossr50.events.fake.FakeBrewEvent;
 import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.runnables.player.PlayerUpdateInventoryTask;
-import com.gmail.nossr50.runnables.skills.FurnaceCleanupTask;
 import com.gmail.nossr50.skills.alchemy.Alchemy;
 import com.gmail.nossr50.skills.alchemy.AlchemyPotionBrewer;
 import com.gmail.nossr50.util.ItemUtils;
@@ -56,7 +55,7 @@ public class InventoryListener implements Listener {
 
         Furnace furnace = (Furnace) furnaceState;
 
-        OfflinePlayer offlinePlayer = mcMMO.getSmeltingTracker().getPlayerFromFurnace(furnace);
+        OfflinePlayer offlinePlayer = mcMMO.getSmeltingTracker().getFurnaceOwner(furnace);
 
         if(offlinePlayer != null && offlinePlayer.isOnline()) {
 
@@ -94,7 +93,7 @@ public class InventoryListener implements Listener {
 
         if(blockState instanceof Furnace) {
             Furnace furnace = (Furnace) blockState;
-            OfflinePlayer offlinePlayer = mcMMO.getSmeltingTracker().getPlayerFromFurnace(furnace);
+            OfflinePlayer offlinePlayer = mcMMO.getSmeltingTracker().getFurnaceOwner(furnace);
 
             if(offlinePlayer != null) {
 
@@ -105,8 +104,6 @@ public class InventoryListener implements Listener {
                     event.setResult(offlineProfile.getSmeltingManager().smeltProcessing(smelting, event.getResult()));
                 }
             }
-
-            new FurnaceCleanupTask(furnace).runTaskLater(mcMMO.p, 1);
         }
     }
 

+ 0 - 23
src/main/java/com/gmail/nossr50/runnables/skills/FurnaceCleanupTask.java

@@ -1,23 +0,0 @@
-package com.gmail.nossr50.runnables.skills;
-
-import com.gmail.nossr50.mcMMO;
-import org.bukkit.block.Furnace;
-import org.bukkit.scheduler.BukkitRunnable;
-
-public class FurnaceCleanupTask extends BukkitRunnable {
-
-    private final Furnace furnace;
-
-    public FurnaceCleanupTask(Furnace furnace) {
-        this.furnace = furnace;
-    }
-
-    @Override
-    public void run() {
-        if(furnace != null
-                && furnace.getInventory().getSmelting() == null) {
-            //Furnace is empty so stop tracking it
-            mcMMO.getSmeltingTracker().untrackFurnace(furnace);
-        }
-    }
-}

+ 0 - 16
src/main/java/com/gmail/nossr50/skills/smelting/Smelting.java

@@ -2,24 +2,8 @@ package com.gmail.nossr50.skills.smelting;
 
 import com.gmail.nossr50.config.experience.ExperienceConfig;
 import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
-import com.gmail.nossr50.datatypes.skills.SubSkillType;
 import com.gmail.nossr50.mcMMO;
-import com.gmail.nossr50.util.EventUtils;
-import com.gmail.nossr50.util.Permissions;
-import com.gmail.nossr50.util.player.UserManager;
-import com.gmail.nossr50.util.skills.RankUtils;
-import org.bukkit.Bukkit;
-import org.bukkit.OfflinePlayer;
-import org.bukkit.block.Furnace;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.FurnaceInventory;
-import org.bukkit.inventory.Inventory;
 import org.bukkit.inventory.ItemStack;
-import org.bukkit.metadata.MetadataValue;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.HashMap;
-import java.util.List;
 
 public class Smelting {
 

+ 23 - 17
src/main/java/com/gmail/nossr50/util/compat/CompatibilityManager.java

@@ -3,7 +3,10 @@ package com.gmail.nossr50.util.compat;
 import com.gmail.nossr50.locale.LocaleLoader;
 import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.util.StringUtils;
-import com.gmail.nossr50.util.compat.layers.PlayerAttackCooldownExploitPreventionLayer;
+import com.gmail.nossr50.util.compat.layers.attackcooldown.PlayerAttackCooldownExploitPreventionLayer;
+import com.gmail.nossr50.util.compat.layers.persistentdata.AbstractPersistentDataLayer;
+import com.gmail.nossr50.util.compat.layers.persistentdata.SpigotPersistentDataLayer;
+import com.gmail.nossr50.util.compat.layers.persistentdata.SpigotTemporaryDataLayer;
 import com.gmail.nossr50.util.nms.NMSVersion;
 import com.gmail.nossr50.util.platform.MinecraftGameVersion;
 import org.bukkit.command.CommandSender;
@@ -24,6 +27,7 @@ public class CompatibilityManager {
 
     /* Compatibility Layers */
     private PlayerAttackCooldownExploitPreventionLayer playerAttackCooldownExploitPreventionLayer;
+    private AbstractPersistentDataLayer persistentDataLayer;
 
     public CompatibilityManager(MinecraftGameVersion minecraftGameVersion) {
         mcMMO.p.getLogger().info("Loading compatibility layers...");
@@ -42,6 +46,10 @@ public class CompatibilityManager {
         supportedLayers = new HashMap<>(); //Init map
 
         for(CompatibilityType compatibilityType : CompatibilityType.values()) {
+            //TODO: Remove later
+            if(compatibilityType == CompatibilityType.PLAYER_ATTACK_COOLDOWN_EXPLOIT_PREVENTION)
+                continue;
+
             supportedLayers.put(compatibilityType, false); //All layers are set to false when initialized
         }
     }
@@ -51,26 +59,21 @@ public class CompatibilityManager {
      * For any unsupported layers, load a dummy layer
      */
     private void initCompatibilityLayers() {
-        isFullyCompatibleServerSoftware = true;
+        initPersistentDataLayer();
 
-//        if(nmsVersion == NMSVersion.UNSUPPORTED) {
-//            mcMMO.p.getLogger().info("NMS not supported for this version of Minecraft, possible solutions include updating mcMMO or updating your server software. NMS Support is not available on every version of Minecraft.");
-//            mcMMO.p.getLogger().info("Certain features of mcMMO that require NMS will be disabled, you can check what is disabled by running the /mmocompat command!");
-//            //Load dummy compatibility layers
-//            isFullyCompatibleServerSoftware = false;
-//            loadDummyCompatibilityLayers();
-//        } else {
-//            playerAttackCooldownExploitPreventionLayer = new PlayerAttackCooldownExploitPreventionLayer(nmsVersion);
-//
-//            //Mark as operational
-//            if(playerAttackCooldownExploitPreventionLayer.noErrorsOnInitialize()) {
-//                supportedLayers.put(CompatibilityType.PLAYER_ATTACK_COOLDOWN_EXPLOIT_PREVENTION, true);
-//            }
-//        }
+        isFullyCompatibleServerSoftware = true;
     }
 
-    private void loadDummyCompatibilityLayers() {
+    private void initPersistentDataLayer() {
+        if(minecraftGameVersion.getMinorVersion().asInt() >= 14 || minecraftGameVersion.getMajorVersion().asInt() >= 2) {
+
+            persistentDataLayer = new SpigotPersistentDataLayer();
+        } else {
+
+            persistentDataLayer = new SpigotTemporaryDataLayer();
+        }
 
+        supportedLayers.put(CompatibilityType.PERSISTENT_DATA, true);
     }
 
     //TODO: move to text manager
@@ -128,4 +131,7 @@ public class CompatibilityManager {
         return playerAttackCooldownExploitPreventionLayer;
     }
 
+    public AbstractPersistentDataLayer getPersistentDataLayer() {
+        return persistentDataLayer;
+    }
 }

+ 2 - 1
src/main/java/com/gmail/nossr50/util/compat/CompatibilityType.java

@@ -1,5 +1,6 @@
 package com.gmail.nossr50.util.compat;
 
 public enum CompatibilityType {
-    PLAYER_ATTACK_COOLDOWN_EXPLOIT_PREVENTION
+    PLAYER_ATTACK_COOLDOWN_EXPLOIT_PREVENTION,
+    PERSISTENT_DATA
 }

+ 0 - 7
src/main/java/com/gmail/nossr50/util/compat/layers/AbstractCompatibilityLayer.java

@@ -1,8 +1,6 @@
 package com.gmail.nossr50.util.compat.layers;
 
 import com.gmail.nossr50.util.compat.CompatibilityLayer;
-import com.gmail.nossr50.util.nms.NMSVersion;
-import org.jetbrains.annotations.NotNull;
 
 /**
  *
@@ -13,11 +11,6 @@ import org.jetbrains.annotations.NotNull;
 public abstract class AbstractCompatibilityLayer implements CompatibilityLayer {
 
     protected boolean noErrorsOnInitialize = true;
-    protected final @NotNull NMSVersion nmsVersion;
-
-    public AbstractCompatibilityLayer(@NotNull NMSVersion nmsVersion) {
-        this.nmsVersion = nmsVersion;
-    }
 
     /**
      * Initialize the CompatibilityLayer

+ 30 - 0
src/main/java/com/gmail/nossr50/util/compat/layers/AbstractNMSCompatibilityLayer.java

@@ -0,0 +1,30 @@
+package com.gmail.nossr50.util.compat.layers;
+
+import com.gmail.nossr50.util.nms.NMSVersion;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ *
+ * These classes are a band-aid solution for adding NMS support into 2.1.XXX
+ * In 2.2 we are switching to modules and that will clean things up significantly
+ *
+ */
+public abstract class AbstractNMSCompatibilityLayer extends AbstractCompatibilityLayer {
+
+    protected final @NotNull NMSVersion nmsVersion;
+
+    public AbstractNMSCompatibilityLayer(@NotNull NMSVersion nmsVersion) {
+        this.nmsVersion = nmsVersion;
+    }
+
+    /**
+     * Initialize the CompatibilityLayer
+     * @return true if the CompatibilityLayer initialized and should be functional
+     */
+    public abstract boolean initializeLayer();
+
+    @Override
+    public boolean noErrorsOnInitialize() {
+        return noErrorsOnInitialize;
+    }
+}

+ 1 - 1
src/main/java/com/gmail/nossr50/util/compat/layers/DummyPlayerAttackCooldownExploitPreventionLayer.java → src/main/java/com/gmail/nossr50/util/compat/layers/attackcooldown/DummyPlayerAttackCooldownExploitPreventionLayer.java

@@ -1,4 +1,4 @@
-package com.gmail.nossr50.util.compat.layers;
+package com.gmail.nossr50.util.compat.layers.attackcooldown;
 
 import com.gmail.nossr50.util.nms.NMSVersion;
 import org.bukkit.entity.Player;

+ 3 - 2
src/main/java/com/gmail/nossr50/util/compat/layers/PlayerAttackCooldownExploitPreventionLayer.java → src/main/java/com/gmail/nossr50/util/compat/layers/attackcooldown/PlayerAttackCooldownExploitPreventionLayer.java

@@ -1,6 +1,7 @@
-package com.gmail.nossr50.util.compat.layers;
+package com.gmail.nossr50.util.compat.layers.attackcooldown;
 
 import com.gmail.nossr50.mcMMO;
+import com.gmail.nossr50.util.compat.layers.AbstractNMSCompatibilityLayer;
 import com.gmail.nossr50.util.nms.NMSConstants;
 import com.gmail.nossr50.util.nms.NMSVersion;
 import org.bukkit.entity.Player;
@@ -16,7 +17,7 @@ import java.lang.reflect.Method;
  * In 2.2 we are switching to modules and that will clean things up significantly
  *
  */
-public class PlayerAttackCooldownExploitPreventionLayer extends AbstractCompatibilityLayer implements PlayerAttackCooldownMethods{
+public class PlayerAttackCooldownExploitPreventionLayer extends AbstractNMSCompatibilityLayer implements PlayerAttackCooldownMethods{
 
     private final String cbNMSVersionPath;
 

+ 1 - 1
src/main/java/com/gmail/nossr50/util/compat/layers/PlayerAttackCooldownMethods.java → src/main/java/com/gmail/nossr50/util/compat/layers/attackcooldown/PlayerAttackCooldownMethods.java

@@ -1,4 +1,4 @@
-package com.gmail.nossr50.util.compat.layers;
+package com.gmail.nossr50.util.compat.layers.attackcooldown;
 
 import org.bukkit.entity.Player;
 

+ 19 - 0
src/main/java/com/gmail/nossr50/util/compat/layers/persistentdata/AbstractPersistentDataLayer.java

@@ -0,0 +1,19 @@
+package com.gmail.nossr50.util.compat.layers.persistentdata;
+
+import com.gmail.nossr50.util.compat.layers.AbstractCompatibilityLayer;
+import org.bukkit.block.Furnace;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.UUID;
+
+public abstract class AbstractPersistentDataLayer extends AbstractCompatibilityLayer {
+
+    public AbstractPersistentDataLayer() {
+        initializeLayer();
+    }
+
+    public abstract @Nullable UUID getFurnaceOwner(Furnace furnace);
+
+    public abstract void setFurnaceOwner(Furnace furnace, UUID uuid);
+
+}

+ 60 - 0
src/main/java/com/gmail/nossr50/util/compat/layers/persistentdata/SpigotPersistentDataLayer.java

@@ -0,0 +1,60 @@
+package com.gmail.nossr50.util.compat.layers.persistentdata;
+
+import com.gmail.nossr50.mcMMO;
+import org.bukkit.NamespacedKey;
+import org.bukkit.block.Furnace;
+import org.bukkit.persistence.PersistentDataContainer;
+import org.bukkit.persistence.PersistentDataHolder;
+import org.bukkit.persistence.PersistentDataType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.UUID;
+
+public class SpigotPersistentDataLayer extends AbstractPersistentDataLayer {
+
+    private NamespacedKey furnaceOwner_MostSig_Key;
+    private NamespacedKey furnaceOwner_LeastSig_Key;
+
+    @Override
+    public boolean initializeLayer() {
+        initNamespacedKeys();
+        return true;
+    }
+
+    private void initNamespacedKeys() {
+        furnaceOwner_MostSig_Key = getNamespacedKey("furnace_uuid_most_sig");
+        furnaceOwner_LeastSig_Key = getNamespacedKey("furnace_uuid_least_sig");
+    }
+
+    @NotNull
+    public NamespacedKey getNamespacedKey(String key) {
+        return new NamespacedKey(mcMMO.p, key);
+    }
+
+    @Override
+    public @Nullable UUID getFurnaceOwner(Furnace furnace) {
+        //Get container from entity
+        PersistentDataContainer dataContainer = ((PersistentDataHolder) furnace).getPersistentDataContainer();
+
+        //Too lazy to make a custom data type for this stuff
+        Long mostSigBits = dataContainer.get(furnaceOwner_MostSig_Key, PersistentDataType.LONG);
+        Long leastSigBits = dataContainer.get(furnaceOwner_LeastSig_Key, PersistentDataType.LONG);
+
+        if(mostSigBits != null && leastSigBits != null) {
+            return new UUID(mostSigBits, leastSigBits);
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    public void setFurnaceOwner(Furnace furnace, UUID uuid) {
+        PersistentDataContainer dataContainer = ((PersistentDataHolder) furnace).getPersistentDataContainer();
+
+        dataContainer.set(furnaceOwner_MostSig_Key, PersistentDataType.LONG, uuid.getMostSignificantBits());
+        dataContainer.set(furnaceOwner_LeastSig_Key, PersistentDataType.LONG, uuid.getLeastSignificantBits());
+
+        furnace.update();
+    }
+}

+ 44 - 0
src/main/java/com/gmail/nossr50/util/compat/layers/persistentdata/SpigotTemporaryDataLayer.java

@@ -0,0 +1,44 @@
+package com.gmail.nossr50.util.compat.layers.persistentdata;
+
+import com.gmail.nossr50.datatypes.meta.UUIDMeta;
+import com.gmail.nossr50.mcMMO;
+import org.bukkit.block.Furnace;
+import org.bukkit.metadata.Metadatable;
+
+import java.util.UUID;
+
+/**
+ * Persistent Data API is unavailable
+ */
+public class SpigotTemporaryDataLayer extends AbstractPersistentDataLayer {
+
+    private final String FURNACE_OWNER_METADATA_KEY = "mcMMO_furnace_owner";
+
+    @Override
+    public boolean initializeLayer() {
+        return true;
+    }
+
+    @Override
+    public UUID getFurnaceOwner(Furnace furnace) {
+        Metadatable metadatable = (Metadatable) furnace;
+
+        if(metadatable.getMetadata(FURNACE_OWNER_METADATA_KEY).size() > 0) {
+            UUIDMeta uuidMeta = (UUIDMeta) metadatable.getMetadata(FURNACE_OWNER_METADATA_KEY).get(0);
+            return (UUID) uuidMeta.value();
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    public void setFurnaceOwner(Furnace furnace, UUID uuid) {
+        Metadatable metadatable = (Metadatable) furnace;
+
+        if(metadatable.getMetadata(FURNACE_OWNER_METADATA_KEY).size() > 0) {
+            metadatable.removeMetadata(FURNACE_OWNER_METADATA_KEY, mcMMO.p);
+        }
+
+        metadatable.setMetadata(FURNACE_OWNER_METADATA_KEY, new UUIDMeta(mcMMO.p, uuid));
+    }
+}

+ 28 - 32
src/main/java/com/gmail/nossr50/util/skills/SmeltingTracker.java

@@ -3,8 +3,6 @@ package com.gmail.nossr50.util.skills;
 import com.gmail.nossr50.datatypes.player.McMMOPlayer;
 import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
 import com.gmail.nossr50.mcMMO;
-import com.gmail.nossr50.skills.smelting.Smelting;
-import com.gmail.nossr50.util.EventUtils;
 import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.player.UserManager;
 import org.bukkit.Bukkit;
@@ -16,15 +14,11 @@ import org.bukkit.inventory.FurnaceInventory;
 import org.bukkit.inventory.Inventory;
 import org.jetbrains.annotations.Nullable;
 
-import java.util.HashMap;
+import java.util.UUID;
 
 public class SmeltingTracker {
 
-    private final HashMap<Furnace, OfflinePlayer> furnaceOwners;
-
-    public SmeltingTracker() {
-        furnaceOwners = new HashMap<>();
-    }
+//    private final HashMap<Furnace, OfflinePlayer> furnaceOwners;
 
     private void changeFurnaceOwnership(Furnace furnace, Player player) {
 
@@ -37,7 +31,11 @@ public class SmeltingTracker {
 
         printOwnershipLossDebug(furnace);
 
-        furnaceOwners.put(furnace, player);
+        setFurnaceOwner(furnace, player);
+    }
+
+    private void setFurnaceOwner(Furnace furnace, Player player) {
+        mcMMO.getCompatibilityManager().getPersistentDataLayer().setFurnaceOwner(furnace, player.getUniqueId());
     }
 
     private void printOwnershipGainDebug(Furnace furnace, McMMOPlayer mcMMOPlayer) {
@@ -52,23 +50,31 @@ public class SmeltingTracker {
     }
 
     private void printOwnershipLossDebug(Furnace furnace) {
-        if(furnaceOwners.get(furnace) != null) {
-            OfflinePlayer furnaceOwner = furnaceOwners.get(furnace);
-
-            if(furnaceOwner.isOnline()) {
-                McMMOPlayer furnaceOwnerProfile = UserManager.getPlayer(furnaceOwner.getPlayer());
-
-                if(furnaceOwnerProfile != null) {
-                    if(furnaceOwnerProfile.isDebugMode()) {
-                        furnaceOwnerProfile.getPlayer().sendMessage("Furnace ownership " +
-                                ChatColor.RED + "lost " + ChatColor.RESET +
-                                "at location: " + furnace.getLocation().toString());
-                    }
+        OfflinePlayer furnaceOwner = getFurnaceOwner(furnace);
+
+        if(furnaceOwner != null && furnaceOwner.isOnline()) {
+            McMMOPlayer furnaceOwnerProfile = UserManager.getPlayer(furnaceOwner.getPlayer());
+
+            if(furnaceOwnerProfile != null) {
+                if(furnaceOwnerProfile.isDebugMode()) {
+                    furnaceOwnerProfile.getPlayer().sendMessage("Furnace ownership " +
+                            ChatColor.RED + "lost " + ChatColor.RESET +
+                            "at location: " + furnace.getLocation().toString());
                 }
             }
         }
     }
 
+    public @Nullable OfflinePlayer getFurnaceOwner(Furnace furnace) {
+        UUID uuid = mcMMO.getCompatibilityManager().getPersistentDataLayer().getFurnaceOwner(furnace);
+
+        if(uuid != null) {
+            return Bukkit.getOfflinePlayer(uuid);
+        } else {
+            return null;
+        }
+    }
+
     @Nullable
     public Furnace getFurnaceFromInventory(Inventory inventory) {
         if (!(inventory instanceof FurnaceInventory)) {
@@ -78,13 +84,8 @@ public class SmeltingTracker {
         return (Furnace) inventory.getHolder();
     }
 
-    @Nullable
-    public OfflinePlayer getPlayerFromFurnace(Furnace furnace) {
-        return furnaceOwners.get(furnace);
-    }
-
     public boolean isFurnaceOwned(Furnace furnace) {
-        return furnaceOwners.get(furnace) != null;
+        return getFurnaceOwner(furnace) != null;
     }
 
     public void processFurnaceOwnership(Furnace furnace, Player player) {
@@ -93,9 +94,4 @@ public class SmeltingTracker {
 
         changeFurnaceOwnership(furnace, player);
     }
-
-    public void untrackFurnace(Furnace furnace) {
-        printOwnershipLossDebug(furnace);
-        furnaceOwners.remove(furnace);
-    }
 }