--- a/net/minecraft/world/level/storage/LevelStorageSource.java
+++ b/net/minecraft/world/level/storage/LevelStorageSource.java
@@ -2,6 +2,7 @@
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Maps;
+import com.google.common.collect.UnmodifiableIterator;
 import com.mojang.datafixers.DataFixer;
 import com.mojang.datafixers.util.Pair;
 import com.mojang.logging.LogUtils;
@@ -15,6 +16,7 @@
 import java.io.UncheckedIOException;
 import java.nio.file.FileVisitResult;
 import java.nio.file.Files;
+import java.nio.file.LinkOption;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.nio.file.SimpleFileVisitor;
@@ -61,13 +63,13 @@
 import net.minecraft.world.level.Level;
 import net.minecraft.world.level.LevelSettings;
 import net.minecraft.world.level.WorldDataConfiguration;
-import net.minecraft.world.level.dimension.DimensionType;
 import net.minecraft.world.level.dimension.LevelStem;
 import net.minecraft.world.level.levelgen.WorldDimensions;
 import net.minecraft.world.level.levelgen.WorldGenSettings;
 import org.slf4j.Logger;
 
 public class LevelStorageSource {
+
     static final Logger LOGGER = LogUtils.getLogger();
     static final DateTimeFormatter FORMATTER = (new DateTimeFormatterBuilder()).appendValue(ChronoField.YEAR, 4, 10, SignStyle.EXCEEDS_PAD).appendLiteral('-').appendValue(ChronoField.MONTH_OF_YEAR, 2).appendLiteral('-').appendValue(ChronoField.DAY_OF_MONTH, 2).appendLiteral('_').appendValue(ChronoField.HOUR_OF_DAY, 2).appendLiteral('-').appendValue(ChronoField.MINUTE_OF_HOUR, 2).appendLiteral('-').appendValue(ChronoField.SECOND_OF_MINUTE, 2).toFormatter();
     private static final ImmutableList<String> OLD_SETTINGS_KEYS = ImmutableList.of("RandomSeed", "generatorName", "generatorOptions", "generatorVersion", "legacy_custom_options", "MapFeatures", "BonusChest");
@@ -81,8 +83,8 @@
 
         try {
             FileUtil.createDirectoriesSafe(savesDirectory);
-        } catch (IOException var5) {
-            throw new RuntimeException(var5);
+        } catch (IOException ioexception) {
+            throw new RuntimeException(ioexception);
         }
 
         this.baseDir = savesDirectory;
@@ -94,21 +96,29 @@
     }
 
     private static <T> DataResult<WorldGenSettings> readWorldGenSettings(Dynamic<T> levelData, DataFixer dataFixer, int version) {
-        Dynamic<T> dynamic = levelData.get("WorldGenSettings").orElseEmptyMap();
+        Dynamic<T> dynamic1 = levelData.get("WorldGenSettings").orElseEmptyMap();
+        UnmodifiableIterator unmodifiableiterator = LevelStorageSource.OLD_SETTINGS_KEYS.iterator();
+
+        while (unmodifiableiterator.hasNext()) {
+            String s = (String) unmodifiableiterator.next();
+            Optional<? extends Dynamic<?>> optional = levelData.get(s).result();
 
-        for(String string : OLD_SETTINGS_KEYS) {
-            Optional<? extends Dynamic<?>> optional = levelData.get(string).result();
             if (optional.isPresent()) {
-                dynamic = dynamic.set(string, optional.get());
+                dynamic1 = dynamic1.set(s, (Dynamic) optional.get());
             }
         }
 
-        Dynamic<T> dynamic2 = dataFixer.update(References.WORLD_GEN_SETTINGS, dynamic, version, SharedConstants.getCurrentVersion().getWorldVersion());
+        Dynamic<T> dynamic2 = dataFixer.update(References.WORLD_GEN_SETTINGS, dynamic1, version, SharedConstants.getCurrentVersion().getWorldVersion());
+
         return WorldGenSettings.CODEC.parse(dynamic2);
     }
 
     private static WorldDataConfiguration readDataConfig(Dynamic<?> dynamic) {
-        return WorldDataConfiguration.CODEC.parse(dynamic).resultOrPartial(LOGGER::error).orElse(WorldDataConfiguration.DEFAULT);
+        DataResult<WorldDataConfiguration> dataresult = WorldDataConfiguration.CODEC.parse(dynamic); // CraftBukkit - decompile error
+        Logger logger = LevelStorageSource.LOGGER;
+
+        Objects.requireNonNull(logger);
+        return (WorldDataConfiguration) dataresult.resultOrPartial(logger::error).orElse(WorldDataConfiguration.DEFAULT);
     }
 
     public String getName() {
@@ -116,53 +126,59 @@
     }
 
     public LevelStorageSource.LevelCandidates findLevelCandidates() throws LevelStorageException {
-        if (!Files.isDirectory(this.baseDir)) {
+        if (!Files.isDirectory(this.baseDir, new LinkOption[0])) {
             throw new LevelStorageException(Component.translatable("selectWorld.load_folder_access"));
         } else {
             try {
                 List<LevelStorageSource.LevelDirectory> list = Files.list(this.baseDir).filter((path) -> {
-                    return Files.isDirectory(path);
-                }).map(LevelStorageSource.LevelDirectory::new).filter((levelSave) -> {
-                    return Files.isRegularFile(levelSave.dataFile()) || Files.isRegularFile(levelSave.oldDataFile());
+                    return Files.isDirectory(path, new LinkOption[0]);
+                }).map(LevelStorageSource.LevelDirectory::new).filter((convertable_b) -> {
+                    return Files.isRegularFile(convertable_b.dataFile(), new LinkOption[0]) || Files.isRegularFile(convertable_b.oldDataFile(), new LinkOption[0]);
                 }).toList();
+
                 return new LevelStorageSource.LevelCandidates(list);
-            } catch (IOException var2) {
+            } catch (IOException ioexception) {
                 throw new LevelStorageException(Component.translatable("selectWorld.load_folder_access"));
             }
         }
     }
 
     public CompletableFuture<List<LevelSummary>> loadLevelSummaries(LevelStorageSource.LevelCandidates levels) {
-        List<CompletableFuture<LevelSummary>> list = new ArrayList<>(levels.levels.size());
+        List<CompletableFuture<LevelSummary>> list = new ArrayList(levels.levels.size());
+        Iterator iterator = levels.levels.iterator();
+
+        while (iterator.hasNext()) {
+            LevelStorageSource.LevelDirectory convertable_b = (LevelStorageSource.LevelDirectory) iterator.next();
 
-        for(LevelStorageSource.LevelDirectory levelDirectory : levels.levels) {
             list.add(CompletableFuture.supplyAsync(() -> {
-                boolean bl;
+                boolean flag;
+
                 try {
-                    bl = DirectoryLock.isLocked(levelDirectory.path());
-                } catch (Exception var6) {
-                    LOGGER.warn("Failed to read {} lock", levelDirectory.path(), var6);
+                    flag = DirectoryLock.isLocked(convertable_b.path());
+                } catch (Exception exception) {
+                    LevelStorageSource.LOGGER.warn("Failed to read {} lock", convertable_b.path(), exception);
                     return null;
                 }
 
                 try {
-                    LevelSummary levelSummary = this.readLevelData(levelDirectory, this.levelSummaryReader(levelDirectory, bl));
-                    return levelSummary != null ? levelSummary : null;
-                } catch (OutOfMemoryError var4) {
+                    LevelSummary worldinfo = (LevelSummary) this.readLevelData(convertable_b, this.levelSummaryReader(convertable_b, flag));
+
+                    return worldinfo != null ? worldinfo : null;
+                } catch (OutOfMemoryError outofmemoryerror) {
                     MemoryReserve.release();
                     System.gc();
-                    LOGGER.error(LogUtils.FATAL_MARKER, "Ran out of memory trying to read summary of {}", (Object)levelDirectory.directoryName());
-                    throw var4;
-                } 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.", (Object)levelDirectory.directoryName());
-                    Util.safeReplaceOrMoveFile(levelDirectory.dataFile(), levelDirectory.oldDataFile(), levelDirectory.corruptedDataFile(LocalDateTime.now()), true);
-                    throw var5;
+                    LevelStorageSource.LOGGER.error(LogUtils.FATAL_MARKER, "Ran out of memory trying to read summary of {}", convertable_b.directoryName());
+                    throw outofmemoryerror;
+                } catch (StackOverflowError stackoverflowerror) {
+                    LevelStorageSource.LOGGER.error(LogUtils.FATAL_MARKER, "Ran out of stack trying to read summary of {}. Assuming corruption; attempting to restore from from level.dat_old.", convertable_b.directoryName());
+                    Util.safeReplaceOrMoveFile(convertable_b.dataFile(), convertable_b.oldDataFile(), convertable_b.corruptedDataFile(LocalDateTime.now()), true);
+                    throw stackoverflowerror;
                 }
             }, Util.backgroundExecutor()));
         }
 
-        return Util.sequenceFailFastAndCancel(list).thenApply((summaries) -> {
-            return summaries.stream().filter(Objects::nonNull).sorted().toList();
+        return Util.sequenceFailFastAndCancel(list).thenApply((list1) -> {
+            return list1.stream().filter(Objects::nonNull).sorted().toList();
         });
     }
 
@@ -172,122 +188,142 @@
 
     @Nullable
     <T> T readLevelData(LevelStorageSource.LevelDirectory levelSave, BiFunction<Path, DataFixer, T> levelDataParser) {
-        if (!Files.exists(levelSave.path())) {
-            return (T)null;
+        if (!Files.exists(levelSave.path(), new LinkOption[0])) {
+            return null;
         } else {
             Path path = levelSave.dataFile();
-            if (Files.exists(path)) {
-                T object = levelDataParser.apply(path, this.fixerUpper);
-                if (object != null) {
-                    return object;
+
+            if (Files.exists(path, new LinkOption[0])) {
+                T t0 = levelDataParser.apply(path, this.fixerUpper);
+
+                if (t0 != null) {
+                    return t0;
                 }
             }
 
             path = levelSave.oldDataFile();
-            return (T)(Files.exists(path) ? levelDataParser.apply(path, this.fixerUpper) : null);
+            return Files.exists(path, new LinkOption[0]) ? levelDataParser.apply(path, this.fixerUpper) : null;
         }
     }
 
     @Nullable
     private static WorldDataConfiguration getDataConfiguration(Path path, DataFixer dataFixer) {
         try {
-            Tag tag = readLightweightData(path);
-            if (tag instanceof CompoundTag compoundTag) {
-                CompoundTag compoundTag2 = compoundTag.getCompound("Data");
-                int i = compoundTag2.contains("DataVersion", 99) ? compoundTag2.getInt("DataVersion") : -1;
-                Dynamic<Tag> dynamic = dataFixer.update(DataFixTypes.LEVEL.getType(), new Dynamic<>(NbtOps.INSTANCE, compoundTag2), i, SharedConstants.getCurrentVersion().getWorldVersion());
-                return readDataConfig(dynamic);
+            Tag nbtbase = LevelStorageSource.readLightweightData(path);
+
+            if (nbtbase instanceof CompoundTag) {
+                CompoundTag nbttagcompound = (CompoundTag) nbtbase;
+                CompoundTag nbttagcompound1 = nbttagcompound.getCompound("Data");
+                int i = nbttagcompound1.contains("DataVersion", 99) ? nbttagcompound1.getInt("DataVersion") : -1;
+                Dynamic<Tag> dynamic = dataFixer.update(DataFixTypes.LEVEL.getType(), new Dynamic(NbtOps.INSTANCE, nbttagcompound1), i, SharedConstants.getCurrentVersion().getWorldVersion());
+
+                return LevelStorageSource.readDataConfig(dynamic);
             }
-        } catch (Exception var7) {
-            LOGGER.error("Exception reading {}", path, var7);
+        } catch (Exception exception) {
+            LevelStorageSource.LOGGER.error("Exception reading {}", path, exception);
         }
 
         return null;
     }
 
     static BiFunction<Path, DataFixer, Pair<WorldData, WorldDimensions.Complete>> getLevelData(DynamicOps<Tag> ops, WorldDataConfiguration dataConfiguration, Registry<LevelStem> dimensionOptionsRegistry, Lifecycle lifecycle) {
-        return (path, dataFixer) -> {
-            CompoundTag compoundTag;
+        return (path, datafixer) -> {
+            CompoundTag nbttagcompound;
+
             try {
-                compoundTag = NbtIo.readCompressed(path.toFile());
-            } catch (IOException var17) {
-                throw new UncheckedIOException(var17);
+                nbttagcompound = NbtIo.readCompressed(path.toFile());
+            } catch (IOException ioexception) {
+                throw new UncheckedIOException(ioexception);
             }
 
-            CompoundTag compoundTag3 = compoundTag.getCompound("Data");
-            CompoundTag compoundTag4 = compoundTag3.contains("Player", 10) ? compoundTag3.getCompound("Player") : null;
-            compoundTag3.remove("Player");
-            int i = compoundTag3.contains("DataVersion", 99) ? compoundTag3.getInt("DataVersion") : -1;
-            Dynamic<Tag> dynamic = dataFixer.update(DataFixTypes.LEVEL.getType(), new Dynamic<>(ops, compoundTag3), i, SharedConstants.getCurrentVersion().getWorldVersion());
-            WorldGenSettings worldGenSettings = readWorldGenSettings(dynamic, dataFixer, i).getOrThrow(false, Util.prefix("WorldGenSettings: ", LOGGER::error));
-            LevelVersion levelVersion = LevelVersion.parse(dynamic);
-            LevelSettings levelSettings = LevelSettings.parse(dynamic, dataConfiguration);
-            WorldDimensions.Complete complete = worldGenSettings.dimensions().bake(dimensionOptionsRegistry);
-            Lifecycle lifecycle2 = complete.lifecycle().add(lifecycle);
-            PrimaryLevelData primaryLevelData = PrimaryLevelData.parse(dynamic, dataFixer, i, compoundTag4, levelSettings, levelVersion, complete.specialWorldProperty(), worldGenSettings.options(), lifecycle2);
-            return Pair.of(primaryLevelData, complete);
+            CompoundTag nbttagcompound1 = nbttagcompound.getCompound("Data");
+            CompoundTag nbttagcompound2 = nbttagcompound1.contains("Player", 10) ? nbttagcompound1.getCompound("Player") : null;
+
+            nbttagcompound1.remove("Player");
+            int i = nbttagcompound1.contains("DataVersion", 99) ? nbttagcompound1.getInt("DataVersion") : -1;
+            Dynamic<Tag> dynamic = datafixer.update(DataFixTypes.LEVEL.getType(), new Dynamic(ops, nbttagcompound1), i, SharedConstants.getCurrentVersion().getWorldVersion());
+            DataResult dataresult = LevelStorageSource.readWorldGenSettings(dynamic, datafixer, i);
+            Logger logger = LevelStorageSource.LOGGER;
+
+            Objects.requireNonNull(logger);
+            WorldGenSettings generatorsettings = (WorldGenSettings) dataresult.getOrThrow(false, Util.prefix("WorldGenSettings: ", logger::error));
+            LevelVersion levelversion = LevelVersion.parse(dynamic);
+            LevelSettings worldsettings = LevelSettings.parse(dynamic, dataConfiguration);
+            WorldDimensions.Complete worlddimensions_b = generatorsettings.dimensions().bake(dimensionOptionsRegistry);
+            Lifecycle lifecycle1 = worlddimensions_b.lifecycle().add(lifecycle);
+            PrimaryLevelData worlddataserver = PrimaryLevelData.parse(dynamic, datafixer, i, nbttagcompound2, worldsettings, levelversion, worlddimensions_b.specialWorldProperty(), generatorsettings.options(), lifecycle1);
+            worlddataserver.pdc = nbttagcompound1.get("BukkitValues"); // CraftBukkit - Add PDC to world
+
+            return Pair.of(worlddataserver, worlddimensions_b);
         };
     }
 
     BiFunction<Path, DataFixer, LevelSummary> levelSummaryReader(LevelStorageSource.LevelDirectory levelSave, boolean locked) {
-        return (path, dataFixer) -> {
+        return (path, datafixer) -> {
             try {
-                Tag tag = readLightweightData(path);
-                if (tag instanceof CompoundTag compoundTag) {
-                    CompoundTag compoundTag2 = compoundTag.getCompound("Data");
-                    int i = compoundTag2.contains("DataVersion", 99) ? compoundTag2.getInt("DataVersion") : -1;
-                    Dynamic<Tag> dynamic = dataFixer.update(DataFixTypes.LEVEL.getType(), new Dynamic<>(NbtOps.INSTANCE, compoundTag2), i, SharedConstants.getCurrentVersion().getWorldVersion());
-                    LevelVersion levelVersion = LevelVersion.parse(dynamic);
-                    int j = levelVersion.levelDataVersion();
+                Tag nbtbase = LevelStorageSource.readLightweightData(path);
+
+                if (nbtbase instanceof CompoundTag) {
+                    CompoundTag nbttagcompound = (CompoundTag) nbtbase;
+                    CompoundTag nbttagcompound1 = nbttagcompound.getCompound("Data");
+                    int i = nbttagcompound1.contains("DataVersion", 99) ? nbttagcompound1.getInt("DataVersion") : -1;
+                    Dynamic<Tag> dynamic = datafixer.update(DataFixTypes.LEVEL.getType(), new Dynamic(NbtOps.INSTANCE, nbttagcompound1), i, SharedConstants.getCurrentVersion().getWorldVersion());
+                    LevelVersion levelversion = LevelVersion.parse(dynamic);
+                    int j = levelversion.levelDataVersion();
+
                     if (j == 19132 || j == 19133) {
-                        boolean bl2 = j != this.getStorageVersion();
-                        Path path2 = levelSave.iconFile();
-                        WorldDataConfiguration worldDataConfiguration = readDataConfig(dynamic);
-                        LevelSettings levelSettings = LevelSettings.parse(dynamic, worldDataConfiguration);
-                        FeatureFlagSet featureFlagSet = parseFeatureFlagsFromSummary(dynamic);
-                        boolean bl3 = FeatureFlags.isExperimental(featureFlagSet);
-                        return new LevelSummary(levelSettings, levelVersion, levelSave.directoryName(), bl2, locked, bl3, path2);
+                        boolean flag1 = j != this.getStorageVersion();
+                        Path path1 = levelSave.iconFile();
+                        WorldDataConfiguration worlddataconfiguration = LevelStorageSource.readDataConfig(dynamic);
+                        LevelSettings worldsettings = LevelSettings.parse(dynamic, worlddataconfiguration);
+                        FeatureFlagSet featureflagset = LevelStorageSource.parseFeatureFlagsFromSummary(dynamic);
+                        boolean flag2 = FeatureFlags.isExperimental(featureflagset);
+
+                        return new LevelSummary(worldsettings, levelversion, levelSave.directoryName(), flag1, locked, flag2, path1);
                     }
                 } else {
-                    LOGGER.warn("Invalid root tag in {}", (Object)path);
+                    LevelStorageSource.LOGGER.warn("Invalid root tag in {}", path);
                 }
 
                 return null;
-            } catch (Exception var18) {
-                LOGGER.error("Exception reading {}", path, var18);
+            } catch (Exception exception) {
+                LevelStorageSource.LOGGER.error("Exception reading {}", path, exception);
                 return null;
             }
         };
     }
 
     private static FeatureFlagSet parseFeatureFlagsFromSummary(Dynamic<Tag> levelData) {
-        Set<ResourceLocation> set = levelData.get("enabled_features").asStream().flatMap((featureFlag) -> {
-            return featureFlag.asString().result().map(ResourceLocation::tryParse).stream();
+        Set<ResourceLocation> set = (Set) levelData.get("enabled_features").asStream().flatMap((dynamic1) -> {
+            return dynamic1.asString().result().map(ResourceLocation::tryParse).stream();
         }).collect(Collectors.toSet());
-        return FeatureFlags.REGISTRY.fromNames(set, (id) -> {
+
+        return FeatureFlags.REGISTRY.fromNames(set, (minecraftkey) -> {
         });
     }
 
     @Nullable
     private static Tag readLightweightData(Path path) throws IOException {
-        SkipFields skipFields = new SkipFields(new FieldSelector("Data", CompoundTag.TYPE, "Player"), new FieldSelector("Data", CompoundTag.TYPE, "WorldGenSettings"));
-        NbtIo.parseCompressed(path.toFile(), skipFields);
-        return skipFields.getResult();
+        SkipFields skipfields = new SkipFields(new FieldSelector[]{new FieldSelector("Data", CompoundTag.TYPE, "Player"), new FieldSelector("Data", CompoundTag.TYPE, "WorldGenSettings")});
+
+        NbtIo.parseCompressed(path.toFile(), skipfields);
+        return skipfields.getResult();
     }
 
     public boolean isNewLevelIdAcceptable(String name) {
         try {
             Path path = this.baseDir.resolve(name);
+
             Files.createDirectory(path);
             Files.deleteIfExists(path);
             return true;
-        } catch (IOException var3) {
+        } catch (IOException ioexception) {
             return false;
         }
     }
 
     public boolean levelExists(String name) {
-        return Files.isDirectory(this.baseDir.resolve(name));
+        return Files.isDirectory(this.baseDir.resolve(name), new LinkOption[0]);
     }
 
     public Path getBaseDir() {
@@ -298,22 +334,37 @@
         return this.backupDir;
     }
 
-    public LevelStorageSource.LevelStorageAccess createAccess(String directoryName) throws IOException {
-        return new LevelStorageSource.LevelStorageAccess(directoryName);
+    // CraftBukkit start
+    public LevelStorageSource.LevelStorageAccess createAccess(String s, ResourceKey<LevelStem> dimensionType) throws IOException {
+        return new LevelStorageSource.LevelStorageAccess(s, dimensionType);
+    }
+
+    public static Path getStorageFolder(Path path, ResourceKey<LevelStem> dimensionType) {
+        if (dimensionType == LevelStem.OVERWORLD) {
+            return path;
+        } else if (dimensionType == LevelStem.NETHER) {
+            return path.resolve("DIM-1");
+        } else if (dimensionType == LevelStem.END) {
+            return path.resolve("DIM1");
+        } else {
+            return path.resolve("dimensions").resolve(dimensionType.location().getNamespace()).resolve(dimensionType.location().getPath());
+        }
     }
+    // CraftBukkit end
 
     public static record LevelCandidates(List<LevelStorageSource.LevelDirectory> levels) implements Iterable<LevelStorageSource.LevelDirectory> {
+
         public boolean isEmpty() {
             return this.levels.isEmpty();
         }
 
-        @Override
         public Iterator<LevelStorageSource.LevelDirectory> iterator() {
             return this.levels.iterator();
         }
     }
 
     public static record LevelDirectory(Path path) {
+
         public String directoryName() {
             return this.path.getFileName().toString();
         }
@@ -327,7 +378,10 @@
         }
 
         public Path corruptedDataFile(LocalDateTime dateTime) {
-            return this.path.resolve(LevelResource.LEVEL_DATA_FILE.getId() + "_corrupted_" + dateTime.format(LevelStorageSource.FORMATTER));
+            Path path = this.path;
+            String s = LevelResource.LEVEL_DATA_FILE.getId();
+
+            return path.resolve(s + "_corrupted_" + dateTime.format(LevelStorageSource.FORMATTER));
         }
 
         public Path iconFile() {
@@ -344,14 +398,19 @@
     }
 
     public class LevelStorageAccess implements AutoCloseable {
+
         final DirectoryLock lock;
         public final LevelStorageSource.LevelDirectory levelDirectory;
         private final String levelId;
         private final Map<LevelResource, Path> resources = Maps.newHashMap();
+        // CraftBukkit start
+        public final ResourceKey<LevelStem> dimensionType;
 
-        public LevelStorageAccess(String directoryName) throws IOException {
-            this.levelId = directoryName;
-            this.levelDirectory = new LevelStorageSource.LevelDirectory(LevelStorageSource.this.baseDir.resolve(directoryName));
+        public LevelStorageAccess(String s, ResourceKey<LevelStem> dimensionType) throws IOException {
+            this.dimensionType = dimensionType;
+            // CraftBukkit end
+            this.levelId = s;
+            this.levelDirectory = new LevelStorageSource.LevelDirectory(LevelStorageSource.this.baseDir.resolve(s));
             this.lock = DirectoryLock.create(this.levelDirectory.path());
         }
 
@@ -360,11 +419,15 @@
         }
 
         public Path getLevelPath(LevelResource savePath) {
-            return this.resources.computeIfAbsent(savePath, this.levelDirectory::resourcePath);
+            Map<LevelResource, Path> map = this.resources; // CraftBukkit - decompile error
+            LevelStorageSource.LevelDirectory convertable_b = this.levelDirectory;
+
+            Objects.requireNonNull(this.levelDirectory);
+            return (Path) map.computeIfAbsent(savePath, convertable_b::resourcePath);
         }
 
         public Path getDimensionPath(ResourceKey<Level> key) {
-            return DimensionType.getStorageFolder(key, this.levelDirectory.path());
+            return LevelStorageSource.getStorageFolder(this.levelDirectory.path(), this.dimensionType); // CraftBukkit
         }
 
         private void checkLock() {
@@ -381,39 +444,42 @@
         @Nullable
         public LevelSummary getSummary() {
             this.checkLock();
-            return LevelStorageSource.this.readLevelData(this.levelDirectory, LevelStorageSource.this.levelSummaryReader(this.levelDirectory, false));
+            return (LevelSummary) LevelStorageSource.this.readLevelData(this.levelDirectory, LevelStorageSource.this.levelSummaryReader(this.levelDirectory, false));
         }
 
         @Nullable
         public Pair<WorldData, WorldDimensions.Complete> getDataTag(DynamicOps<Tag> ops, WorldDataConfiguration dataConfiguration, Registry<LevelStem> dimensionOptionsRegistry, Lifecycle lifecycle) {
             this.checkLock();
-            return LevelStorageSource.this.readLevelData(this.levelDirectory, LevelStorageSource.getLevelData(ops, dataConfiguration, dimensionOptionsRegistry, lifecycle));
+            return (Pair) LevelStorageSource.this.readLevelData(this.levelDirectory, LevelStorageSource.getLevelData(ops, dataConfiguration, dimensionOptionsRegistry, lifecycle));
         }
 
         @Nullable
         public WorldDataConfiguration getDataConfiguration() {
             this.checkLock();
-            return LevelStorageSource.this.readLevelData(this.levelDirectory, LevelStorageSource::getDataConfiguration);
+            return (WorldDataConfiguration) LevelStorageSource.this.readLevelData(this.levelDirectory, LevelStorageSource::getDataConfiguration);
         }
 
         public void saveDataTag(RegistryAccess registryManager, WorldData saveProperties) {
-            this.saveDataTag(registryManager, saveProperties, (CompoundTag)null);
+            this.saveDataTag(registryManager, saveProperties, (CompoundTag) null);
         }
 
         public void saveDataTag(RegistryAccess registryManager, WorldData saveProperties, @Nullable CompoundTag nbt) {
             File file = this.levelDirectory.path().toFile();
-            CompoundTag compoundTag = saveProperties.createTag(registryManager, nbt);
-            CompoundTag compoundTag2 = new CompoundTag();
-            compoundTag2.put("Data", compoundTag);
+            CompoundTag nbttagcompound1 = saveProperties.createTag(registryManager, nbt);
+            CompoundTag nbttagcompound2 = new CompoundTag();
+
+            nbttagcompound2.put("Data", nbttagcompound1);
 
             try {
-                File file2 = File.createTempFile("level", ".dat", file);
-                NbtIo.writeCompressed(compoundTag2, file2);
-                File file3 = this.levelDirectory.oldDataFile().toFile();
-                File file4 = this.levelDirectory.dataFile().toFile();
-                Util.safeReplaceFile(file4, file2, file3);
-            } catch (Exception var10) {
-                LevelStorageSource.LOGGER.error("Failed to save level {}", file, var10);
+                File file1 = File.createTempFile("level", ".dat", file);
+
+                NbtIo.writeCompressed(nbttagcompound2, file1);
+                File file2 = this.levelDirectory.oldDataFile().toFile();
+                File file3 = this.levelDirectory.dataFile().toFile();
+
+                Util.safeReplaceFile(file3, file1, file2);
+            } catch (Exception exception) {
+                LevelStorageSource.LOGGER.error("Failed to save level {}", file, exception);
             }
 
         }
@@ -425,50 +491,53 @@
         public void deleteLevel() throws IOException {
             this.checkLock();
             final Path path = this.levelDirectory.lockFile();
-            LevelStorageSource.LOGGER.info("Deleting level {}", (Object)this.levelId);
 
-            for(int i = 1; i <= 5; ++i) {
-                LevelStorageSource.LOGGER.info("Attempt {}...", (int)i);
+            LevelStorageSource.LOGGER.info("Deleting level {}", this.levelId);
+            int i = 1;
+
+            while (i <= 5) {
+                LevelStorageSource.LOGGER.info("Attempt {}...", i);
 
                 try {
                     Files.walkFileTree(this.levelDirectory.path(), new SimpleFileVisitor<Path>() {
-                        @Override
-                        public FileVisitResult visitFile(Path pathx, BasicFileAttributes basicFileAttributes) throws IOException {
-                            if (!path.equals(path)) {
-                                LevelStorageSource.LOGGER.debug("Deleting {}", (Object)path);
-                                Files.delete(path);
+                        public FileVisitResult visitFile(Path path1, BasicFileAttributes basicfileattributes) throws IOException {
+                            if (!path1.equals(path)) {
+                                LevelStorageSource.LOGGER.debug("Deleting {}", path1);
+                                Files.delete(path1);
                             }
 
                             return FileVisitResult.CONTINUE;
                         }
 
-                        @Override
-                        public FileVisitResult postVisitDirectory(Path pathx, IOException iOException) throws IOException {
-                            if (iOException != null) {
-                                throw iOException;
+                        public FileVisitResult postVisitDirectory(Path path1, IOException ioexception) throws IOException {
+                            if (ioexception != null) {
+                                throw ioexception;
                             } else {
-                                if (path.equals(LevelStorageAccess.this.levelDirectory.path())) {
+                                if (path1.equals(LevelStorageAccess.this.levelDirectory.path())) {
                                     LevelStorageAccess.this.lock.close();
                                     Files.deleteIfExists(path);
                                 }
 
-                                Files.delete(path);
+                                Files.delete(path1);
                                 return FileVisitResult.CONTINUE;
                             }
                         }
                     });
                     break;
-                } catch (IOException var6) {
+                } catch (IOException ioexception) {
                     if (i >= 5) {
-                        throw var6;
+                        throw ioexception;
                     }
 
-                    LevelStorageSource.LOGGER.warn("Failed to delete {}", this.levelDirectory.path(), var6);
+                    LevelStorageSource.LOGGER.warn("Failed to delete {}", this.levelDirectory.path(), ioexception);
 
                     try {
                         Thread.sleep(500L);
-                    } catch (InterruptedException var5) {
+                    } catch (InterruptedException interruptedexception) {
+                        ;
                     }
+
+                    ++i;
                 }
             }
 
@@ -477,51 +546,64 @@
         public void renameLevel(String name) throws IOException {
             this.checkLock();
             Path path = this.levelDirectory.dataFile();
-            if (Files.exists(path)) {
-                CompoundTag compoundTag = NbtIo.readCompressed(path.toFile());
-                CompoundTag compoundTag2 = compoundTag.getCompound("Data");
-                compoundTag2.putString("LevelName", name);
-                NbtIo.writeCompressed(compoundTag, path.toFile());
+
+            if (Files.exists(path, new LinkOption[0])) {
+                CompoundTag nbttagcompound = NbtIo.readCompressed(path.toFile());
+                CompoundTag nbttagcompound1 = nbttagcompound.getCompound("Data");
+
+                nbttagcompound1.putString("LevelName", name);
+                NbtIo.writeCompressed(nbttagcompound, path.toFile());
             }
 
         }
 
         public long makeWorldBackup() throws IOException {
             this.checkLock();
-            String string = LocalDateTime.now().format(LevelStorageSource.FORMATTER) + "_" + this.levelId;
+            String s = LocalDateTime.now().format(LevelStorageSource.FORMATTER);
+            String s1 = s + "_" + this.levelId;
             Path path = LevelStorageSource.this.getBackupPath();
 
             try {
                 FileUtil.createDirectoriesSafe(path);
-            } catch (IOException var9) {
-                throw new RuntimeException(var9);
+            } catch (IOException ioexception) {
+                throw new RuntimeException(ioexception);
             }
 
-            Path path2 = path.resolve(FileUtil.findAvailableName(path, string, ".zip"));
+            Path path1 = path.resolve(FileUtil.findAvailableName(path, s1, ".zip"));
+            final ZipOutputStream zipoutputstream = new ZipOutputStream(new BufferedOutputStream(Files.newOutputStream(path1)));
+
+            try {
+                final Path path2 = Paths.get(this.levelId);
 
-            try (final ZipOutputStream zipOutputStream = new ZipOutputStream(new BufferedOutputStream(Files.newOutputStream(path2)))) {
-                final Path path3 = Paths.get(this.levelId);
                 Files.walkFileTree(this.levelDirectory.path(), new SimpleFileVisitor<Path>() {
-                    @Override
-                    public FileVisitResult visitFile(Path path, BasicFileAttributes basicFileAttributes) throws IOException {
-                        if (path.endsWith("session.lock")) {
+                    public FileVisitResult visitFile(Path path3, BasicFileAttributes basicfileattributes) throws IOException {
+                        if (path3.endsWith("session.lock")) {
                             return FileVisitResult.CONTINUE;
                         } else {
-                            String string = path3.resolve(LevelStorageAccess.this.levelDirectory.path().relativize(path)).toString().replace('\\', '/');
-                            ZipEntry zipEntry = new ZipEntry(string);
-                            zipOutputStream.putNextEntry(zipEntry);
-                            com.google.common.io.Files.asByteSource(path.toFile()).copyTo(zipOutputStream);
-                            zipOutputStream.closeEntry();
+                            String s2 = path2.resolve(LevelStorageAccess.this.levelDirectory.path().relativize(path3)).toString().replace('\\', '/');
+                            ZipEntry zipentry = new ZipEntry(s2);
+
+                            zipoutputstream.putNextEntry(zipentry);
+                            com.google.common.io.Files.asByteSource(path3.toFile()).copyTo(zipoutputstream);
+                            zipoutputstream.closeEntry();
                             return FileVisitResult.CONTINUE;
                         }
                     }
                 });
+            } catch (Throwable throwable) {
+                try {
+                    zipoutputstream.close();
+                } catch (Throwable throwable1) {
+                    throwable.addSuppressed(throwable1);
+                }
+
+                throw throwable;
             }
 
-            return Files.size(path2);
+            zipoutputstream.close();
+            return Files.size(path1);
         }
 
-        @Override
         public void close() throws IOException {
             this.lock.close();
         }
