added WIP 'custom_dimension' to the API

This commit is contained in:
gnembon committed 2020-08-17 00:36:01 -03:00
1 parent e2c8b9cc41
commit 598219608b
5 files changed
+152

No files matched your search

@@ -26,6 +26,7 @@ import carpet.script.exception.ExitStatement;
import carpet.script.exception.ExpressionException;
import carpet.script.exception.InternalExpressionException;
import carpet.script.utils.ShapeDispatcher;
import carpet.script.utils.WorldTools;
import carpet.script.value.BlockValue;
import carpet.script.value.EntityValue;
import carpet.script.value.FormattedTextValue;
@@ -1292,6 +1293,33 @@ public class CarpetExpression
return (_c, _t) -> ret;
});
this.expr.addLazyFunction("custom_dimension", -1, (c, t, lv) ->
{
if (lv.size() == 0) throw new InternalExpressionException("'custom_dimension' requires at least one argument");
CarpetContext cc = (CarpetContext)c;
String worldKey = lv.get(0).evalValue(c).getString();
Long seed = null;
if (lv.size() > 1)
{
String seedKey = lv.get(1).evalValue(c).getString();
try
{
seed = Long.parseLong(seedKey);
}
catch (NumberFormatException ignored)
{
throw new InternalExpressionException("Incorrect number format for seed: " + seedKey);
}
}
boolean success = WorldTools.createWorld(cc.s.getMinecraftServer(), worldKey, seed);
if (!success) return LazyValue.FALSE;
CarpetServer.settingsManager.notifyPlayersCommandsChanged();
return LazyValue.TRUE;
});
this.expr.addLazyFunction("reset_chunk", -1, (c, t, lv) ->
{
CarpetContext cc = (CarpetContext)c;
@@ -1,15 +1,36 @@
package carpet.script.utils;
import carpet.fakes.MinecraftServerInterface;
import com.google.common.collect.ImmutableList;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.WorldGenerationProgressListener;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.registry.RegistryKey;
import net.minecraft.util.registry.SimpleRegistry;
import net.minecraft.world.World;
import net.minecraft.world.biome.source.BiomeAccess;
import net.minecraft.world.border.WorldBorderListener;
import net.minecraft.world.chunk.ChunkStatus;
import net.minecraft.world.dimension.DimensionOptions;
import net.minecraft.world.dimension.DimensionType;
import net.minecraft.world.gen.GeneratorOptions;
import net.minecraft.world.gen.Spawner;
import net.minecraft.world.gen.chunk.ChunkGenerator;
import net.minecraft.world.level.ServerWorldProperties;
import net.minecraft.world.level.UnmodifiableLevelProperties;
import net.minecraft.world.storage.RegionFile;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
public class WorldTools
{
@@ -43,4 +64,68 @@ public class WorldTools
catch (IOException ignored) { }
return true;
}
public static boolean createWorld(MinecraftServer server, String worldKey, Long seed)
{
Identifier worldId = new Identifier(worldKey);
ServerWorld overWorld = server.getOverworld();
Set<RegistryKey<World>> worldKeys = server.getWorldRegistryKeys();
for (RegistryKey<World> worldRegistryKey : worldKeys)
{
if (worldRegistryKey.getValue().equals(worldId))
{
// world with this id already exists
return false;
}
}
ServerWorldProperties serverWorldProperties = server.getSaveProperties().getMainWorldProperties();
GeneratorOptions generatorOptions = server.getSaveProperties().getGeneratorOptions();
boolean bl = generatorOptions.isDebugWorld();
long l = generatorOptions.getSeed();
long m = BiomeAccess.hashSeed(l);
List<Spawner> list = ImmutableList.of();
SimpleRegistry<DimensionOptions> simpleRegistry = generatorOptions.getDimensions();
DimensionOptions dimensionOptions = simpleRegistry.get(DimensionOptions.OVERWORLD);
ChunkGenerator chunkGenerator2;
DimensionType dimensionType2;
if (dimensionOptions == null) {
dimensionType2 = (DimensionType)server.getRegistryManager().getDimensionTypes().getOrThrow(DimensionType.OVERWORLD_REGISTRY_KEY);
chunkGenerator2 = GeneratorOptions.createOverworldGenerator(server.getRegistryManager().get(Registry.BIOME_KEY), server.getRegistryManager().get(Registry.NOISE_SETTINGS_WORLDGEN), (new Random()).nextLong());
} else {
dimensionType2 = dimensionOptions.getDimensionType();
chunkGenerator2 = dimensionOptions.getChunkGenerator();
}
RegistryKey<World> customWorld = RegistryKey.of(Registry.DIMENSION, worldId);
chunkGenerator2 = GeneratorOptions.createOverworldGenerator(server.getRegistryManager().get(Registry.BIOME_KEY), server.getRegistryManager().get(Registry.NOISE_SETTINGS_WORLDGEN), (seed==null)?l:seed);
ServerWorld serverWorld = new ServerWorld(
server,
Util.getMainWorkerExecutor(),
((MinecraftServerInterface) server).getCMSession(),
new UnmodifiableLevelProperties(server.getSaveProperties(), serverWorldProperties),
customWorld,
dimensionType2,
NOOP_LISTENER,
chunkGenerator2,
bl,
(seed==null)?l:seed,
list,
false);
overWorld.getWorldBorder().addListener(new WorldBorderListener.WorldBorderSyncer(serverWorld.getWorldBorder()));
((MinecraftServerInterface) server).getCMWorlds().put(customWorld, serverWorld);
return true;
}
private static class NoopWorldGenerationProgressListener implements WorldGenerationProgressListener
{
@Override public void start(ChunkPos spawnPos) { }
@Override public void setChunkStatus(ChunkPos pos, ChunkStatus status) { }
@Override public void stop() { }
}
private static final WorldGenerationProgressListener NOOP_LISTENER = new NoopWorldGenerationProgressListener();
}