fix memory worlds

This commit is contained in:
Julian Krings 2024-10-07 16:58:59 +02:00
parent f6a354b890
commit eda44a8ace
8 changed files with 312 additions and 28 deletions

View File

@ -4,8 +4,10 @@ import com.google.common.collect.ImmutableList;
import com.mojang.serialization.Lifecycle; import com.mojang.serialization.Lifecycle;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.IMemoryWorld; import com.volmit.iris.core.nms.IMemoryWorld;
import com.volmit.iris.util.scheduling.J;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
@ -24,11 +26,13 @@ import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.dimension.LevelStem; import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.PatrolSpawner; import net.minecraft.world.level.levelgen.PatrolSpawner;
import net.minecraft.world.level.levelgen.PhantomSpawner; import net.minecraft.world.level.levelgen.PhantomSpawner;
import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.storage.PrimaryLevelData; import net.minecraft.world.level.storage.PrimaryLevelData;
import net.minecraft.world.level.storage.ServerLevelData;
import org.bukkit.*; import org.bukkit.*;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
@ -49,10 +53,12 @@ import org.jetbrains.annotations.NotNull;
import java.io.IOException; import java.io.IOException;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Files; import java.nio.file.Files;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
@ -75,7 +81,7 @@ public class MemoryWorld implements IMemoryWorld {
var tempDir = Files.createTempDirectory("MemoryGenerator"); var tempDir = Files.createTempDirectory("MemoryGenerator");
LevelStorageSource source = LevelStorageSource.createDefault(tempDir); LevelStorageSource source = LevelStorageSource.createDefault(tempDir);
ResourceKey<LevelStem> stemKey = ResourceKey.create(Registry.LEVEL_STEM_REGISTRY, new ResourceLocation(levelType.getKey(), levelType.getNamespace())); ResourceKey<LevelStem> stemKey = ResourceKey.create(Registry.LEVEL_STEM_REGISTRY, new ResourceLocation(levelType.getNamespace(), levelType.getKey()));
var access = source.createAccess(name, stemKey); var access = source.createAccess(name, stemKey);
var registry = server.registryAccess().registryOrThrow(Registry.LEVEL_STEM_REGISTRY); var registry = server.registryAccess().registryOrThrow(Registry.LEVEL_STEM_REGISTRY);
@ -90,7 +96,25 @@ public class MemoryWorld implements IMemoryWorld {
if (levelStem == null) if (levelStem == null)
throw new IllegalStateException("Unknown dimension type: " + stemKey); throw new IllegalStateException("Unknown dimension type: " + stemKey);
var worldInfo = new CraftWorldInfo(worldData, access, creator.environment(), levelStem.typeHolder().value()); CraftWorldInfo worldInfo;
try {
worldInfo = new CraftWorldInfo(worldData, access, creator.environment(), levelStem.typeHolder().value());
} catch (Throwable e) {
try {
var c = CraftWorldInfo.class.getDeclaredConstructor(
ServerLevelData.class,
LevelStorageSource.LevelStorageAccess.class,
World.Environment.class,
DimensionType.class,
net.minecraft.world.level.chunk.ChunkGenerator.class,
RegistryAccess.Frozen.class);
worldInfo = c.newInstance(worldData, access, creator.environment(), levelStem.typeHolder().value(), levelStem.generator(), server.registryAccess());
} catch (NoSuchMethodException | InvocationTargetException | InstantiationException |
IllegalAccessException ex) {
throw new RuntimeException(ex);
}
}
if (biomeProvider == null && generator != null) { if (biomeProvider == null && generator != null) {
biomeProvider = generator.getDefaultBiomeProvider(worldInfo); biomeProvider = generator.getDefaultBiomeProvider(worldInfo);
} }
@ -154,6 +178,20 @@ public class MemoryWorld implements IMemoryWorld {
@Override @Override
public void close() throws Exception { public void close() throws Exception {
if (!Bukkit.isPrimaryThread()) {
var future = new CompletableFuture<Void>();
J.s(() -> {
try {
close();
future.complete(null);
} catch (Exception e) {
future.completeExceptionally(e);
}
});
future.join();
return;
}
var level = this.level.get(); var level = this.level.get();
if (level == null || !this.level.compareAndSet(level, null)) if (level == null || !this.level.compareAndSet(level, null))
return; return;

View File

@ -5,6 +5,7 @@ import com.mojang.serialization.Lifecycle;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.IMemoryWorld; import com.volmit.iris.core.nms.IMemoryWorld;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
@ -27,12 +28,14 @@ import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.dimension.LevelStem; import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.PatrolSpawner; import net.minecraft.world.level.levelgen.PatrolSpawner;
import net.minecraft.world.level.levelgen.PhantomSpawner; import net.minecraft.world.level.levelgen.PhantomSpawner;
import net.minecraft.world.level.levelgen.WorldOptions; import net.minecraft.world.level.levelgen.WorldOptions;
import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.storage.PrimaryLevelData; import net.minecraft.world.level.storage.PrimaryLevelData;
import net.minecraft.world.level.storage.ServerLevelData;
import org.bukkit.*; import org.bukkit.*;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
@ -53,6 +56,7 @@ import org.jetbrains.annotations.NotNull;
import java.io.IOException; import java.io.IOException;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Files; import java.nio.file.Files;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
@ -78,7 +82,7 @@ public class MemoryWorld implements IMemoryWorld {
var tempDir = Files.createTempDirectory("MemoryGenerator"); var tempDir = Files.createTempDirectory("MemoryGenerator");
LevelStorageSource source = LevelStorageSource.createDefault(tempDir); LevelStorageSource source = LevelStorageSource.createDefault(tempDir);
ResourceKey<LevelStem> stemKey = ResourceKey.create(Registries.LEVEL_STEM, new ResourceLocation(levelType.getKey(), levelType.getNamespace())); ResourceKey<LevelStem> stemKey = ResourceKey.create(Registries.LEVEL_STEM, new ResourceLocation(levelType.getNamespace(), levelType.getKey()));
var access = source.createAccess(name, stemKey); var access = source.createAccess(name, stemKey);
var worldLoader = server.worldLoader; var worldLoader = server.worldLoader;
@ -98,7 +102,25 @@ public class MemoryWorld implements IMemoryWorld {
if (levelStem == null) if (levelStem == null)
throw new IllegalStateException("Unknown dimension type: " + stemKey); throw new IllegalStateException("Unknown dimension type: " + stemKey);
var worldInfo = new CraftWorldInfo(worldData, access, creator.environment(), levelStem.type().value()); CraftWorldInfo worldInfo;
try {
worldInfo = new CraftWorldInfo(worldData, access, creator.environment(), levelStem.type().value());
} catch (Throwable e) {
try {
var c = CraftWorldInfo.class.getDeclaredConstructor(
ServerLevelData.class,
LevelStorageSource.LevelStorageAccess.class,
World.Environment.class,
DimensionType.class,
net.minecraft.world.level.chunk.ChunkGenerator.class,
RegistryAccess.Frozen.class);
worldInfo = c.newInstance(worldData, access, creator.environment(), levelStem.type().value(), levelStem.generator(), server.registryAccess());
} catch (NoSuchMethodException | InvocationTargetException | InstantiationException |
IllegalAccessException ex) {
throw new RuntimeException(ex);
}
}
if (biomeProvider == null && generator != null) { if (biomeProvider == null && generator != null) {
biomeProvider = generator.getDefaultBiomeProvider(worldInfo); biomeProvider = generator.getDefaultBiomeProvider(worldInfo);
} }

View File

@ -4,7 +4,9 @@ import com.google.common.collect.ImmutableList;
import com.mojang.serialization.Lifecycle; import com.mojang.serialization.Lifecycle;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.IMemoryWorld; import com.volmit.iris.core.nms.IMemoryWorld;
import com.volmit.iris.util.scheduling.J;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
@ -27,12 +29,14 @@ import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.dimension.LevelStem; import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.PatrolSpawner; import net.minecraft.world.level.levelgen.PatrolSpawner;
import net.minecraft.world.level.levelgen.PhantomSpawner; import net.minecraft.world.level.levelgen.PhantomSpawner;
import net.minecraft.world.level.levelgen.WorldOptions; import net.minecraft.world.level.levelgen.WorldOptions;
import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.storage.PrimaryLevelData; import net.minecraft.world.level.storage.PrimaryLevelData;
import net.minecraft.world.level.storage.ServerLevelData;
import org.bukkit.*; import org.bukkit.*;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
@ -53,9 +57,11 @@ import org.jetbrains.annotations.NotNull;
import java.io.IOException; import java.io.IOException;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Files; import java.nio.file.Files;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
@ -78,7 +84,7 @@ public class MemoryWorld implements IMemoryWorld {
var tempDir = Files.createTempDirectory("MemoryGenerator"); var tempDir = Files.createTempDirectory("MemoryGenerator");
LevelStorageSource source = LevelStorageSource.createDefault(tempDir); LevelStorageSource source = LevelStorageSource.createDefault(tempDir);
ResourceKey<LevelStem> stemKey = ResourceKey.create(Registries.LEVEL_STEM, new ResourceLocation(levelType.getKey(), levelType.getNamespace())); ResourceKey<LevelStem> stemKey = ResourceKey.create(Registries.LEVEL_STEM, new ResourceLocation(levelType.getNamespace(), levelType.getKey()));
var access = source.createAccess(name, stemKey); var access = source.createAccess(name, stemKey);
var worldLoader = server.worldLoader; var worldLoader = server.worldLoader;
@ -98,7 +104,25 @@ public class MemoryWorld implements IMemoryWorld {
if (levelStem == null) if (levelStem == null)
throw new IllegalStateException("Unknown dimension type: " + stemKey); throw new IllegalStateException("Unknown dimension type: " + stemKey);
var worldInfo = new CraftWorldInfo(worldData, access, creator.environment(), levelStem.type().value()); CraftWorldInfo worldInfo;
try {
worldInfo = new CraftWorldInfo(worldData, access, creator.environment(), levelStem.type().value());
} catch (Throwable e) {
try {
var c = CraftWorldInfo.class.getDeclaredConstructor(
ServerLevelData.class,
LevelStorageSource.LevelStorageAccess.class,
World.Environment.class,
DimensionType.class,
net.minecraft.world.level.chunk.ChunkGenerator.class,
RegistryAccess.Frozen.class);
worldInfo = c.newInstance(worldData, access, creator.environment(), levelStem.type().value(), levelStem.generator(), server.registryAccess());
} catch (NoSuchMethodException | InvocationTargetException | InstantiationException |
IllegalAccessException ex) {
throw new RuntimeException(ex);
}
}
if (biomeProvider == null && generator != null) { if (biomeProvider == null && generator != null) {
biomeProvider = generator.getDefaultBiomeProvider(worldInfo); biomeProvider = generator.getDefaultBiomeProvider(worldInfo);
} }
@ -162,12 +186,25 @@ public class MemoryWorld implements IMemoryWorld {
@Override @Override
public void close() throws Exception { public void close() throws Exception {
if (!Bukkit.isPrimaryThread()) {
var future = new CompletableFuture<Void>();
J.s(() -> {
try {
close();
future.complete(null);
} catch (Exception e) {
future.completeExceptionally(e);
}
});
future.join();
return;
}
var level = this.level.get(); var level = this.level.get();
if (level == null || !this.level.compareAndSet(level, null)) if (level == null || !this.level.compareAndSet(level, null))
return; return;
level.getChunkSource().close(false); level.close();
level.entityManager.close(false);
level.convertable.deleteLevel(); level.convertable.deleteLevel();
level.convertable.close(); level.convertable.close();

View File

@ -4,7 +4,9 @@ import com.google.common.collect.ImmutableList;
import com.mojang.serialization.Lifecycle; import com.mojang.serialization.Lifecycle;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.IMemoryWorld; import com.volmit.iris.core.nms.IMemoryWorld;
import com.volmit.iris.util.scheduling.J;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
@ -27,12 +29,14 @@ import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.dimension.LevelStem; import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.PatrolSpawner; import net.minecraft.world.level.levelgen.PatrolSpawner;
import net.minecraft.world.level.levelgen.PhantomSpawner; import net.minecraft.world.level.levelgen.PhantomSpawner;
import net.minecraft.world.level.levelgen.WorldOptions; import net.minecraft.world.level.levelgen.WorldOptions;
import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.storage.PrimaryLevelData; import net.minecraft.world.level.storage.PrimaryLevelData;
import net.minecraft.world.level.storage.ServerLevelData;
import org.bukkit.*; import org.bukkit.*;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
@ -53,9 +57,11 @@ import org.jetbrains.annotations.NotNull;
import java.io.IOException; import java.io.IOException;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Files; import java.nio.file.Files;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
@ -78,7 +84,7 @@ public class MemoryWorld implements IMemoryWorld {
var tempDir = Files.createTempDirectory("MemoryGenerator"); var tempDir = Files.createTempDirectory("MemoryGenerator");
LevelStorageSource source = LevelStorageSource.createDefault(tempDir); LevelStorageSource source = LevelStorageSource.createDefault(tempDir);
ResourceKey<LevelStem> stemKey = ResourceKey.create(Registries.LEVEL_STEM, new ResourceLocation(levelType.getKey(), levelType.getNamespace())); ResourceKey<LevelStem> stemKey = ResourceKey.create(Registries.LEVEL_STEM, new ResourceLocation(levelType.getNamespace(), levelType.getKey()));
var access = source.createAccess(name, stemKey); var access = source.createAccess(name, stemKey);
var worldLoader = server.worldLoader; var worldLoader = server.worldLoader;
@ -98,7 +104,25 @@ public class MemoryWorld implements IMemoryWorld {
if (levelStem == null) if (levelStem == null)
throw new IllegalStateException("Unknown dimension type: " + stemKey); throw new IllegalStateException("Unknown dimension type: " + stemKey);
var worldInfo = new CraftWorldInfo(worldData, access, creator.environment(), levelStem.type().value()); CraftWorldInfo worldInfo;
try {
worldInfo = new CraftWorldInfo(worldData, access, creator.environment(), levelStem.type().value());
} catch (Throwable e) {
try {
var c = CraftWorldInfo.class.getDeclaredConstructor(
ServerLevelData.class,
LevelStorageSource.LevelStorageAccess.class,
World.Environment.class,
DimensionType.class,
net.minecraft.world.level.chunk.ChunkGenerator.class,
RegistryAccess.Frozen.class);
worldInfo = c.newInstance(worldData, access, creator.environment(), levelStem.type().value(), levelStem.generator(), server.registryAccess());
} catch (NoSuchMethodException | InvocationTargetException | InstantiationException |
IllegalAccessException ex) {
throw new RuntimeException(ex);
}
}
if (biomeProvider == null && generator != null) { if (biomeProvider == null && generator != null) {
biomeProvider = generator.getDefaultBiomeProvider(worldInfo); biomeProvider = generator.getDefaultBiomeProvider(worldInfo);
} }
@ -163,12 +187,25 @@ public class MemoryWorld implements IMemoryWorld {
@Override @Override
public void close() throws Exception { public void close() throws Exception {
if (!Bukkit.isPrimaryThread()) {
var future = new CompletableFuture<Void>();
J.s(() -> {
try {
close();
future.complete(null);
} catch (Exception e) {
future.completeExceptionally(e);
}
});
future.join();
return;
}
var level = this.level.get(); var level = this.level.get();
if (level == null || !this.level.compareAndSet(level, null)) if (level == null || !this.level.compareAndSet(level, null))
return; return;
level.getChunkSource().close(false); level.close();
level.entityManager.close(false);
level.convertable.deleteLevel(); level.convertable.deleteLevel();
level.convertable.close(); level.convertable.close();

View File

@ -4,7 +4,9 @@ import com.google.common.collect.ImmutableList;
import com.mojang.serialization.Lifecycle; import com.mojang.serialization.Lifecycle;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.IMemoryWorld; import com.volmit.iris.core.nms.IMemoryWorld;
import com.volmit.iris.util.scheduling.J;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
@ -27,12 +29,14 @@ import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.dimension.LevelStem; import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.PatrolSpawner; import net.minecraft.world.level.levelgen.PatrolSpawner;
import net.minecraft.world.level.levelgen.PhantomSpawner; import net.minecraft.world.level.levelgen.PhantomSpawner;
import net.minecraft.world.level.levelgen.WorldOptions; import net.minecraft.world.level.levelgen.WorldOptions;
import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.storage.PrimaryLevelData; import net.minecraft.world.level.storage.PrimaryLevelData;
import net.minecraft.world.level.storage.ServerLevelData;
import org.bukkit.*; import org.bukkit.*;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
@ -53,9 +57,11 @@ import org.jetbrains.annotations.NotNull;
import java.io.IOException; import java.io.IOException;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Files; import java.nio.file.Files;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
@ -78,7 +84,7 @@ public class MemoryWorld implements IMemoryWorld {
var tempDir = Files.createTempDirectory("MemoryGenerator"); var tempDir = Files.createTempDirectory("MemoryGenerator");
LevelStorageSource source = LevelStorageSource.createDefault(tempDir); LevelStorageSource source = LevelStorageSource.createDefault(tempDir);
ResourceKey<LevelStem> stemKey = ResourceKey.create(Registries.LEVEL_STEM, new ResourceLocation(levelType.getKey(), levelType.getNamespace())); ResourceKey<LevelStem> stemKey = ResourceKey.create(Registries.LEVEL_STEM, new ResourceLocation(levelType.getNamespace(), levelType.getKey()));
var access = source.createAccess(name, stemKey); var access = source.createAccess(name, stemKey);
var worldLoader = server.worldLoader; var worldLoader = server.worldLoader;
@ -98,7 +104,25 @@ public class MemoryWorld implements IMemoryWorld {
if (levelStem == null) if (levelStem == null)
throw new IllegalStateException("Unknown dimension type: " + stemKey); throw new IllegalStateException("Unknown dimension type: " + stemKey);
var worldInfo = new CraftWorldInfo(worldData, access, creator.environment(), levelStem.type().value()); CraftWorldInfo worldInfo;
try {
worldInfo = new CraftWorldInfo(worldData, access, creator.environment(), levelStem.type().value());
} catch (Throwable e) {
try {
var c = CraftWorldInfo.class.getDeclaredConstructor(
ServerLevelData.class,
LevelStorageSource.LevelStorageAccess.class,
World.Environment.class,
DimensionType.class,
net.minecraft.world.level.chunk.ChunkGenerator.class,
RegistryAccess.Frozen.class);
worldInfo = c.newInstance(worldData, access, creator.environment(), levelStem.type().value(), levelStem.generator(), server.registryAccess());
} catch (NoSuchMethodException | InvocationTargetException | InstantiationException |
IllegalAccessException ex) {
throw new RuntimeException(ex);
}
}
if (biomeProvider == null && generator != null) { if (biomeProvider == null && generator != null) {
biomeProvider = generator.getDefaultBiomeProvider(worldInfo); biomeProvider = generator.getDefaultBiomeProvider(worldInfo);
} }
@ -163,12 +187,25 @@ public class MemoryWorld implements IMemoryWorld {
@Override @Override
public void close() throws Exception { public void close() throws Exception {
if (!Bukkit.isPrimaryThread()) {
var future = new CompletableFuture<Void>();
J.s(() -> {
try {
close();
future.complete(null);
} catch (Exception e) {
future.completeExceptionally(e);
}
});
future.join();
return;
}
var level = this.level.get(); var level = this.level.get();
if (level == null || !this.level.compareAndSet(level, null)) if (level == null || !this.level.compareAndSet(level, null))
return; return;
level.getChunkSource().close(false); level.close();
level.entityManager.close(false);
level.convertable.deleteLevel(); level.convertable.deleteLevel();
level.convertable.close(); level.convertable.close();

View File

@ -4,7 +4,9 @@ import com.google.common.collect.ImmutableList;
import com.mojang.serialization.Lifecycle; import com.mojang.serialization.Lifecycle;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.IMemoryWorld; import com.volmit.iris.core.nms.IMemoryWorld;
import com.volmit.iris.util.scheduling.J;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
@ -27,12 +29,14 @@ import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.dimension.LevelStem; import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.PatrolSpawner; import net.minecraft.world.level.levelgen.PatrolSpawner;
import net.minecraft.world.level.levelgen.PhantomSpawner; import net.minecraft.world.level.levelgen.PhantomSpawner;
import net.minecraft.world.level.levelgen.WorldOptions; import net.minecraft.world.level.levelgen.WorldOptions;
import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.storage.PrimaryLevelData; import net.minecraft.world.level.storage.PrimaryLevelData;
import net.minecraft.world.level.storage.ServerLevelData;
import org.bukkit.*; import org.bukkit.*;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
@ -57,9 +61,11 @@ import org.jetbrains.annotations.NotNull;
import java.io.IOException; import java.io.IOException;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Files; import java.nio.file.Files;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
@ -82,7 +88,7 @@ public class MemoryWorld implements IMemoryWorld {
var tempDir = Files.createTempDirectory("MemoryGenerator"); var tempDir = Files.createTempDirectory("MemoryGenerator");
LevelStorageSource source = LevelStorageSource.createDefault(tempDir); LevelStorageSource source = LevelStorageSource.createDefault(tempDir);
ResourceKey<LevelStem> stemKey = ResourceKey.create(Registries.LEVEL_STEM, new ResourceLocation(levelType.getKey(), levelType.getNamespace())); ResourceKey<LevelStem> stemKey = ResourceKey.create(Registries.LEVEL_STEM, new ResourceLocation(levelType.getNamespace(), levelType.getKey()));
var access = source.createAccess(name, stemKey); var access = source.createAccess(name, stemKey);
var worldLoader = server.worldLoader; var worldLoader = server.worldLoader;
@ -102,7 +108,25 @@ public class MemoryWorld implements IMemoryWorld {
if (levelStem == null) if (levelStem == null)
throw new IllegalStateException("Unknown dimension type: " + stemKey); throw new IllegalStateException("Unknown dimension type: " + stemKey);
var worldInfo = new CraftWorldInfo(worldData, access, creator.environment(), levelStem.type().value()); CraftWorldInfo worldInfo;
try {
worldInfo = new CraftWorldInfo(worldData, access, creator.environment(), levelStem.type().value());
} catch (Throwable e) {
try {
var c = CraftWorldInfo.class.getDeclaredConstructor(
ServerLevelData.class,
LevelStorageSource.LevelStorageAccess.class,
World.Environment.class,
DimensionType.class,
net.minecraft.world.level.chunk.ChunkGenerator.class,
RegistryAccess.Frozen.class);
worldInfo = c.newInstance(worldData, access, creator.environment(), levelStem.type().value(), levelStem.generator(), server.registryAccess());
} catch (NoSuchMethodException | InvocationTargetException | InstantiationException |
IllegalAccessException ex) {
throw new RuntimeException(ex);
}
}
if (biomeProvider == null && generator != null) { if (biomeProvider == null && generator != null) {
biomeProvider = generator.getDefaultBiomeProvider(worldInfo); biomeProvider = generator.getDefaultBiomeProvider(worldInfo);
} }
@ -167,12 +191,25 @@ public class MemoryWorld implements IMemoryWorld {
@Override @Override
public void close() throws Exception { public void close() throws Exception {
if (!Bukkit.isPrimaryThread()) {
var future = new CompletableFuture<Void>();
J.s(() -> {
try {
close();
future.complete(null);
} catch (Exception e) {
future.completeExceptionally(e);
}
});
future.join();
return;
}
var level = this.level.get(); var level = this.level.get();
if (level == null || !this.level.compareAndSet(level, null)) if (level == null || !this.level.compareAndSet(level, null))
return; return;
level.getChunkSource().close(false); level.close();
level.entityManager.close(false);
level.convertable.deleteLevel(); level.convertable.deleteLevel();
level.convertable.close(); level.convertable.close();

View File

@ -4,7 +4,9 @@ import com.google.common.collect.ImmutableList;
import com.mojang.serialization.Lifecycle; import com.mojang.serialization.Lifecycle;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.IMemoryWorld; import com.volmit.iris.core.nms.IMemoryWorld;
import com.volmit.iris.util.scheduling.J;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
@ -27,12 +29,14 @@ import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.dimension.LevelStem; import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.PatrolSpawner; import net.minecraft.world.level.levelgen.PatrolSpawner;
import net.minecraft.world.level.levelgen.PhantomSpawner; import net.minecraft.world.level.levelgen.PhantomSpawner;
import net.minecraft.world.level.levelgen.WorldOptions; import net.minecraft.world.level.levelgen.WorldOptions;
import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.storage.PrimaryLevelData; import net.minecraft.world.level.storage.PrimaryLevelData;
import net.minecraft.world.level.storage.ServerLevelData;
import org.bukkit.*; import org.bukkit.*;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
@ -54,9 +58,11 @@ import org.jetbrains.annotations.NotNull;
import java.io.IOException; import java.io.IOException;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Files; import java.nio.file.Files;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
@ -79,7 +85,7 @@ public class MemoryWorld implements IMemoryWorld {
var tempDir = Files.createTempDirectory("MemoryGenerator"); var tempDir = Files.createTempDirectory("MemoryGenerator");
LevelStorageSource source = LevelStorageSource.createDefault(tempDir); LevelStorageSource source = LevelStorageSource.createDefault(tempDir);
ResourceKey<LevelStem> stemKey = ResourceKey.create(Registries.LEVEL_STEM, new ResourceLocation(levelType.getKey(), levelType.getNamespace())); ResourceKey<LevelStem> stemKey = ResourceKey.create(Registries.LEVEL_STEM, new ResourceLocation(levelType.getNamespace(), levelType.getKey()));
var access = source.createAccess(name, stemKey); var access = source.createAccess(name, stemKey);
var worldLoader = server.worldLoader; var worldLoader = server.worldLoader;
@ -100,7 +106,25 @@ public class MemoryWorld implements IMemoryWorld {
if (levelStem == null) if (levelStem == null)
throw new IllegalStateException("Unknown dimension type: " + stemKey); throw new IllegalStateException("Unknown dimension type: " + stemKey);
var worldInfo = new CraftWorldInfo(worldData, access, creator.environment(), levelStem.type().value()); CraftWorldInfo worldInfo;
try {
worldInfo = new CraftWorldInfo(worldData, access, creator.environment(), levelStem.type().value());
} catch (Throwable e) {
try {
var c = CraftWorldInfo.class.getDeclaredConstructor(
ServerLevelData.class,
LevelStorageSource.LevelStorageAccess.class,
World.Environment.class,
DimensionType.class,
net.minecraft.world.level.chunk.ChunkGenerator.class,
RegistryAccess.Frozen.class);
worldInfo = c.newInstance(worldData, access, creator.environment(), levelStem.type().value(), levelStem.generator(), server.registryAccess());
} catch (NoSuchMethodException | InvocationTargetException | InstantiationException |
IllegalAccessException ex) {
throw new RuntimeException(ex);
}
}
if (biomeProvider == null && generator != null) { if (biomeProvider == null && generator != null) {
biomeProvider = generator.getDefaultBiomeProvider(worldInfo); biomeProvider = generator.getDefaultBiomeProvider(worldInfo);
} }
@ -164,12 +188,25 @@ public class MemoryWorld implements IMemoryWorld {
@Override @Override
public void close() throws Exception { public void close() throws Exception {
if (!Bukkit.isPrimaryThread()) {
var future = new CompletableFuture<Void>();
J.s(() -> {
try {
close();
future.complete(null);
} catch (Exception e) {
future.completeExceptionally(e);
}
});
future.join();
return;
}
var level = this.level.get(); var level = this.level.get();
if (level == null || !this.level.compareAndSet(level, null)) if (level == null || !this.level.compareAndSet(level, null))
return; return;
level.getChunkSource().close(false); level.close();
level.entityManager.close(false);
level.convertable.deleteLevel(); level.convertable.deleteLevel();
level.convertable.close(); level.convertable.close();

View File

@ -4,7 +4,9 @@ import com.google.common.collect.ImmutableList;
import com.mojang.serialization.Lifecycle; import com.mojang.serialization.Lifecycle;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.IMemoryWorld; import com.volmit.iris.core.nms.IMemoryWorld;
import com.volmit.iris.util.scheduling.J;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
@ -27,12 +29,14 @@ import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.dimension.LevelStem; import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.PatrolSpawner; import net.minecraft.world.level.levelgen.PatrolSpawner;
import net.minecraft.world.level.levelgen.PhantomSpawner; import net.minecraft.world.level.levelgen.PhantomSpawner;
import net.minecraft.world.level.levelgen.WorldOptions; import net.minecraft.world.level.levelgen.WorldOptions;
import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.storage.PrimaryLevelData; import net.minecraft.world.level.storage.PrimaryLevelData;
import net.minecraft.world.level.storage.ServerLevelData;
import org.bukkit.*; import org.bukkit.*;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
@ -54,11 +58,15 @@ import org.jetbrains.annotations.NotNull;
import java.io.IOException; import java.io.IOException;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Files; import java.nio.file.Files;
import java.util.Arrays;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
public class MemoryWorld implements IMemoryWorld { public class MemoryWorld implements IMemoryWorld {
private static final AtomicLong C = new AtomicLong(); private static final AtomicLong C = new AtomicLong();
@ -79,7 +87,7 @@ public class MemoryWorld implements IMemoryWorld {
var tempDir = Files.createTempDirectory("MemoryGenerator"); var tempDir = Files.createTempDirectory("MemoryGenerator");
LevelStorageSource source = LevelStorageSource.createDefault(tempDir); LevelStorageSource source = LevelStorageSource.createDefault(tempDir);
ResourceKey<LevelStem> stemKey = ResourceKey.create(Registries.LEVEL_STEM, ResourceLocation.fromNamespaceAndPath(levelType.getKey(), levelType.getNamespace())); ResourceKey<LevelStem> stemKey = ResourceKey.create(Registries.LEVEL_STEM, ResourceLocation.fromNamespaceAndPath(levelType.getNamespace(), levelType.getKey()));
var access = source.createAccess(name, stemKey); var access = source.createAccess(name, stemKey);
var worldLoader = server.worldLoader; var worldLoader = server.worldLoader;
@ -100,7 +108,25 @@ public class MemoryWorld implements IMemoryWorld {
if (levelStem == null) if (levelStem == null)
throw new IllegalStateException("Unknown dimension type: " + stemKey); throw new IllegalStateException("Unknown dimension type: " + stemKey);
var worldInfo = new CraftWorldInfo(worldData, access, creator.environment(), levelStem.type().value()); CraftWorldInfo worldInfo;
try {
worldInfo = new CraftWorldInfo(worldData, access, creator.environment(), levelStem.type().value());
} catch (Throwable e) {
try {
var c = CraftWorldInfo.class.getDeclaredConstructor(
ServerLevelData.class,
LevelStorageSource.LevelStorageAccess.class,
World.Environment.class,
DimensionType.class,
net.minecraft.world.level.chunk.ChunkGenerator.class,
RegistryAccess.Frozen.class);
worldInfo = c.newInstance(worldData, access, creator.environment(), levelStem.type().value(), levelStem.generator(), server.registryAccess());
} catch (NoSuchMethodException | InvocationTargetException | InstantiationException |
IllegalAccessException ex) {
throw new RuntimeException(ex);
}
}
if (biomeProvider == null && generator != null) { if (biomeProvider == null && generator != null) {
biomeProvider = generator.getDefaultBiomeProvider(worldInfo); biomeProvider = generator.getDefaultBiomeProvider(worldInfo);
} }
@ -164,12 +190,25 @@ public class MemoryWorld implements IMemoryWorld {
@Override @Override
public void close() throws Exception { public void close() throws Exception {
if (!Bukkit.isPrimaryThread()) {
var future = new CompletableFuture<Void>();
J.s(() -> {
try {
close();
future.complete(null);
} catch (Exception e) {
future.completeExceptionally(e);
}
});
future.join();
return;
}
var level = this.level.get(); var level = this.level.get();
if (level == null || !this.level.compareAndSet(level, null)) if (level == null || !this.level.compareAndSet(level, null))
return; return;
level.getChunkSource().close(false); level.close();
level.entityManager.close(false);
level.convertable.deleteLevel(); level.convertable.deleteLevel();
level.convertable.close(); level.convertable.close();