Uploaded image for project: 'Minecraft: Java Edition'
  1. Minecraft: Java Edition
  2. MC-265541

player.dat_old won't be read even if player.dat doesn't exist

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • 23w51a
    • 1.20.2
    • None
    • Plausible
    • Save Data
    • Important
    • Platform

      Notice: player.dat represents to player data file(<PlayerUUID>.dat) here, you'll find them in world\playerdata

      Steps to Reproduce:
      1. Run your test server.
      2. Enter the server, /give yourself a bedrock or whatever, then quit the server.
      3. Delete your player.dat in world\playerdata, it may appear as 3752d12c-3924-4d32-8407-6c19a4bd409f.dat
      4. Enter the server again, and you'll find your stuff is gone even if your player.dat_old still stores your inventory. If you quit the server, your player.dat_old will be overwritten and you will never find your stuff back.

      Expected Results:
      In Step 4, your stuff shouldn't be gone since player.dat_old has stored it.
      (Rename it into player.dat when it is not overwritten and return to the server, you'll see your stuff)

      The behavior of player.dat_old should be the same as level.dat_old.
      If you delete the level.dat of a world, reenter it and you'll see the data is still there since the game will read the data of the level.dat_old if level_dat doesn't exist.

      Notes:
      You can't reproduce this in single-player mode since your data is stored in another place.
      This bug may cause player data lost if player.dat is corrupted somehow but player.dat_old isn't corrupted.

      Code analysis:
      This is from net.minecraft.world.WorldSaveHandler method, yarn mapping.
      You'll see the game won't do anything if player.dat doesn't exist.

      public NbtCompound loadPlayerData(PlayerEntity player) {
              NbtCompound nbtCompound = null;
      
              try {
                  File file = new File(this.playerDataDir, player.getUuidAsString() + ".dat");
                  if (file.exists() && file.isFile()) {
                      nbtCompound = NbtIo.readCompressed(file);
                  }
              } catch (Exception var4) {
                  LOGGER.warn("Failed to load player data for {}", player.getName().getString());
              }
      ...
          }
      

      However, the game does do something in loading level.dat. If it goes wrong, the game will restore the level.dat from level.dat_old.
      This is from net.minecraft.world.level.storage.LevelStorage method, yarn mapping.

      public CompletableFuture<List<LevelSummary>> loadSummaries(LevelList levels) {
             ...
              while(var3.hasNext()) {
                 ...
                      try {
                          LevelSummary levelSummary = (LevelSummary)this.readLevelProperties(levelSave, this.createLevelDataParser(levelSave, bl));
                          return levelSummary != null ? levelSummary : null;
                       ...
                      } catch (StackOverflowError var5) {
                          LOGGER.error(LogUtils.FATAL_MARKER, "Ran out of stack trying to read summary of {}. Assuming corruption; attempting to restore from from level.dat_old.", levelSave.getRootPath());
                          Util.backupAndReplace(levelSave.getLevelDatPath(), levelSave.getLevelDatOldPath(), levelSave.getCorruptedLevelDatPath(LocalDateTime.now()), true);
                          throw var5;
                      }
                  }...
              }
      

            TommyWallberg [Mojang] TommyWallberg
            HackerRouter HackerRouter
            Votes:
            5 Vote for this issue
            Watchers:
            6 Start watching this issue

              Created:
              Updated:
              Resolved:
              CHK: