--- a/net/minecraft/world/level/storage/PlayerDataStorage.java
+++ b/net/minecraft/world/level/storage/PlayerDataStorage.java
@@ -14,8 +_,10 @@
 import net.minecraft.nbt.NbtAccounter;
 import net.minecraft.nbt.NbtIo;
 import net.minecraft.nbt.NbtUtils;
+import net.minecraft.server.level.ServerPlayer;
 import net.minecraft.util.datafix.DataFixTypes;
 import net.minecraft.world.entity.player.Player;
+import org.bukkit.craftbukkit.entity.CraftPlayer;
 import org.slf4j.Logger;
 
 public class PlayerDataStorage {
@@ -31,6 +_,7 @@
     }
 
     public void save(Player player) {
+        if (org.spigotmc.SpigotConfig.disablePlayerDataSaving) return; // Spigot
         try {
             CompoundTag compoundTag = player.saveWithoutId(new CompoundTag());
             Path path = this.playerDir.toPath();
@@ -40,30 +_,46 @@
             Path path3 = path.resolve(player.getStringUUID() + ".dat_old");
             Util.safeReplaceFile(path2, path1, path3);
         } catch (Exception var7) {
-            LOGGER.warn("Failed to save player data for {}", player.getName().getString());
+            LOGGER.warn("Failed to save player data for {}", player.getScoreboardName(), var7); // Paper - Print exception
         }
     }
 
-    private void backup(Player player, String suffix) {
+    private void backup(String name, String stringUuid, String suffix) { // CraftBukkit
         Path path = this.playerDir.toPath();
-        Path path1 = path.resolve(player.getStringUUID() + suffix);
-        Path path2 = path.resolve(player.getStringUUID() + "_corrupted_" + LocalDateTime.now().format(FORMATTER) + suffix);
+        Path path1 = path.resolve(stringUuid + suffix); // CraftBukkit
+        Path path2 = path.resolve(stringUuid + "_corrupted_" + LocalDateTime.now().format(FORMATTER) + suffix); // CraftBukkit
         if (Files.isRegularFile(path1)) {
             try {
                 Files.copy(path1, path2, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES);
             } catch (Exception var7) {
-                LOGGER.warn("Failed to copy the player.dat file for {}", player.getName().getString(), var7);
+                LOGGER.warn("Failed to copy the player.dat file for {}", name, var7); // CraftBukkit
             }
         }
     }
 
-    private Optional<CompoundTag> load(Player player, String suffix) {
-        File file = new File(this.playerDir, player.getStringUUID() + suffix);
+    private Optional<CompoundTag> load(String name, String stringUuid, String suffix) { // CraftBukkit
+        File file = new File(this.playerDir, stringUuid + suffix); // CraftBukkit
+        // Spigot start
+        boolean usingWrongFile = false;
+        if (org.bukkit.Bukkit.getOnlineMode() && !file.exists()) { // Paper - Check online mode first
+            file = new File(this.playerDir, java.util.UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(java.nio.charset.StandardCharsets.UTF_8)).toString() + suffix);
+            if (file.exists()) {
+                usingWrongFile = true;
+                LOGGER.warn("Using offline mode UUID file for player {} as it is the only copy we can find.", name);
+            }
+        }
+        // Spigot end
         if (file.exists() && file.isFile()) {
             try {
-                return Optional.of(NbtIo.readCompressed(file.toPath(), NbtAccounter.unlimitedHeap()));
+                // Spigot start
+                Optional<CompoundTag> optional = Optional.of(NbtIo.readCompressed(file.toPath(), NbtAccounter.unlimitedHeap()));
+                if (usingWrongFile) {
+                    file.renameTo(new File(file.getPath() + ".offline-read"));
+                }
+                return optional;
+                // Spigot end
             } catch (Exception var5) {
-                LOGGER.warn("Failed to load player data for {}", player.getName().getString());
+                LOGGER.warn("Failed to load player data for {}", name); // CraftBukkit
             }
         }
 
@@ -71,16 +_,40 @@
     }
 
     public Optional<CompoundTag> load(Player player) {
-        Optional<CompoundTag> optional = this.load(player, ".dat");
+        // CraftBukkit start
+        return this.load(player.getName().getString(), player.getStringUUID()).map((tag) -> {
+            if (player instanceof ServerPlayer serverPlayer) {
+                CraftPlayer craftPlayer = serverPlayer.getBukkitEntity();
+                // Only update first played if it is older than the one we have
+                long modified = new File(this.playerDir, player.getStringUUID() + ".dat").lastModified();
+                if (modified < craftPlayer.getFirstPlayed()) {
+                    craftPlayer.setFirstPlayed(modified);
+                }
+            }
+
+            player.load(tag); // From below
+            return tag;
+        });
+    }
+
+    public Optional<CompoundTag> load(String name, String uuid) {
+        // CraftBukkit end
+        Optional<CompoundTag> optional = this.load(name, uuid, ".dat"); // CraftBukkit
         if (optional.isEmpty()) {
-            this.backup(player, ".dat");
+            this.backup(name, uuid, ".dat"); // CraftBukkit
         }
 
-        return optional.or(() -> this.load(player, ".dat_old")).map(compoundTag -> {
+        return optional.or(() -> this.load(name, uuid, ".dat_old")).map(compoundTag -> { // CraftBukkit
             int dataVersion = NbtUtils.getDataVersion(compoundTag, -1);
-            compoundTag = DataFixTypes.PLAYER.updateToCurrentVersion(this.fixerUpper, compoundTag, dataVersion);
-            player.load(compoundTag);
+            compoundTag = ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.PLAYER, compoundTag, dataVersion, net.minecraft.SharedConstants.getCurrentVersion().getDataVersion().getVersion()); // Paper - rewrite data conversion system
+            // player.load(compoundTag); // CraftBukkit - handled above
             return compoundTag;
         });
     }
+
+    // CraftBukkit start
+    public File getPlayerDir() {
+        return this.playerDir;
+    }
+    // CraftBukkit end
 }
