--- a/net/minecraft/world/level/storage/LevelStorageSource.java
+++ b/net/minecraft/world/level/storage/LevelStorageSource.java
@@ -84,7 +_,7 @@
     public static final String ALLOWED_SYMLINKS_CONFIG_NAME = "allowed_symlinks.txt";
     private static final int UNCOMPRESSED_NBT_QUOTA = 104857600;
     private static final int DISK_SPACE_WARNING_THRESHOLD = 67108864;
-    private final Path baseDir;
+    public final Path baseDir;
     private final Path backupDir;
     final DataFixer fixerUpper;
     private final DirectoryValidator worldDirValidator;
@@ -145,6 +_,7 @@
         PrimaryLevelData primaryLevelData = PrimaryLevelData.parse(
             dynamic, levelSettings, complete.specialWorldProperty(), worldGenSettings.options(), lifecycle
         );
+        primaryLevelData.pdc = (Tag) dynamic.getElement("BukkitValues", null); // CraftBukkit - Add PDC to world
         return new LevelDataAndDimensions(primaryLevelData, complete);
     }
 
@@ -226,7 +_,7 @@
         CompoundTag compoundOrEmpty = levelDataTagRaw.getCompoundOrEmpty("Data");
         int dataVersion = NbtUtils.getDataVersion(compoundOrEmpty, -1);
         Dynamic<?> dynamic = DataFixTypes.LEVEL.updateToCurrentVersion(dataFixer, new Dynamic<>(NbtOps.INSTANCE, compoundOrEmpty), dataVersion);
-        dynamic = dynamic.update("Player", dynamic1 -> DataFixTypes.PLAYER.updateToCurrentVersion(dataFixer, dynamic1, dataVersion));
+        dynamic = dynamic.update("Player", dynamic1 -> new Dynamic(dynamic1.getOps(), ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.PLAYER, (net.minecraft.nbt.CompoundTag)dynamic1.getValue(), dataVersion, ca.spottedleaf.dataconverter.minecraft.util.Version.getCurrentVersion()))); // Paper - replace data conversion system
         return dynamic.update("WorldGenSettings", dynamic1 -> DataFixTypes.WORLD_GEN_SETTINGS.updateToCurrentVersion(dataFixer, dynamic1, dataVersion));
     }
 
@@ -341,25 +_,39 @@
         return this.backupDir;
     }
 
-    public LevelStorageSource.LevelStorageAccess validateAndCreateAccess(String saveName) throws IOException, ContentValidationException {
+    public LevelStorageSource.LevelStorageAccess validateAndCreateAccess(String saveName, ResourceKey<LevelStem> dimensionType) throws IOException, ContentValidationException { // CraftBukkit
         Path levelPath = this.getLevelPath(saveName);
-        List<ForbiddenSymlinkInfo> list = this.worldDirValidator.validateDirectory(levelPath, true);
+        List<ForbiddenSymlinkInfo> list = Boolean.getBoolean("paper.disableWorldSymlinkValidation") ? List.of() : this.worldDirValidator.validateDirectory(levelPath, true); // Paper - add skipping of symlinks scan
         if (!list.isEmpty()) {
             throw new ContentValidationException(levelPath, list);
         } else {
-            return new LevelStorageSource.LevelStorageAccess(saveName, levelPath);
+            return new LevelStorageSource.LevelStorageAccess(saveName, levelPath, dimensionType); // CraftBukkit
         }
     }
 
-    public LevelStorageSource.LevelStorageAccess createAccess(String saveName) throws IOException {
+    public LevelStorageSource.LevelStorageAccess createAccess(String saveName, ResourceKey<LevelStem> dimensionType) throws IOException { // CraftBukkit
         Path levelPath = this.getLevelPath(saveName);
-        return new LevelStorageSource.LevelStorageAccess(saveName, levelPath);
+        return new LevelStorageSource.LevelStorageAccess(saveName, levelPath, dimensionType); // CraftBukkit
     }
 
     public DirectoryValidator getWorldDirValidator() {
         return this.worldDirValidator;
     }
 
+    // CraftBukkit start
+    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 record LevelCandidates(List<LevelStorageSource.LevelDirectory> levels) implements Iterable<LevelStorageSource.LevelDirectory> {
         public boolean isEmpty() {
             return this.levels.isEmpty();
@@ -407,11 +_,15 @@
 
     public class LevelStorageAccess implements AutoCloseable {
         final DirectoryLock lock;
-        final LevelStorageSource.LevelDirectory levelDirectory;
+        public final LevelStorageSource.LevelDirectory levelDirectory;
         private final String levelId;
         private final Map<LevelResource, Path> resources = Maps.newHashMap();
+        // CraftBukkit start
+        public final ResourceKey<LevelStem> dimensionType;
 
-        LevelStorageAccess(final String levelId, final Path levelDir) throws IOException {
+        LevelStorageAccess(final String levelId, final Path levelDir, final ResourceKey<LevelStem> dimensionType) throws IOException {
+            this.dimensionType = dimensionType;
+            // CraftBukkit end
             this.levelId = levelId;
             this.levelDirectory = new LevelStorageSource.LevelDirectory(levelDir);
             this.lock = DirectoryLock.create(levelDir);
@@ -454,7 +_,7 @@
         }
 
         public Path getDimensionPath(ResourceKey<Level> dimensionPath) {
-            return DimensionType.getStorageFolder(dimensionPath, this.levelDirectory.path());
+            return LevelStorageSource.getStorageFolder(this.levelDirectory.path(), this.dimensionType); // CraftBukkit
         }
 
         private void checkLock() {
