mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-10-25 21:40:08 +00:00
cli serialization
This commit is contained in:
1 parent
d49ee4f3fc
commit
4c9cfbfdf9
7 files changed
+265
-14
No files matched your search
@@ -0,0 +1,5 @@
|
|||||||
|
package com.dfsek.terra.cli;
|
||||||
|
|
||||||
|
public interface NBTSerializable<T> {
|
||||||
|
T serialize();
|
||||||
|
}
|
||||||
@@ -3,9 +3,15 @@ package com.dfsek.terra.cli;
|
|||||||
import com.dfsek.terra.api.config.ConfigPack;
|
import com.dfsek.terra.api.config.ConfigPack;
|
||||||
import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent;
|
import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.util.vector.Vector2Int;
|
||||||
|
import com.dfsek.terra.cli.world.CLIWorld;
|
||||||
|
|
||||||
|
import net.querz.mca.MCAUtil;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
|
||||||
public final class TerraCLI {
|
public final class TerraCLI {
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(TerraCLI.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(TerraCLI.class);
|
||||||
@@ -17,7 +23,22 @@ public final class TerraCLI {
|
|||||||
platform.getEventManager().callEvent(new PlatformInitializationEvent());
|
platform.getEventManager().callEvent(new PlatformInitializationEvent());
|
||||||
|
|
||||||
ConfigPack generate = platform.getConfigRegistry().get("OVERWORLD").orElseThrow(); // TODO: make this a cli argument
|
ConfigPack generate = platform.getConfigRegistry().get("OVERWORLD").orElseThrow(); // TODO: make this a cli argument
|
||||||
|
|
||||||
|
CLIWorld world = new CLIWorld(1, 2, 384, -64, generate);
|
||||||
|
|
||||||
|
world.generate();
|
||||||
|
|
||||||
|
world.serialize().forEach(mcaFile -> {
|
||||||
|
Vector2Int pos = mcaFile.getLeft();
|
||||||
|
String name = MCAUtil.createNameFromRegionLocation(pos.getX(), pos.getZ());
|
||||||
|
LOGGER.info("Writing region ({}, {}) to {}", pos.getX(), pos.getZ(), name);
|
||||||
|
mcaFile.getRight().cleanupPalettesAndBlockStates();
|
||||||
|
|
||||||
|
try {
|
||||||
|
MCAUtil.write(mcaFile.getRight(), name);
|
||||||
|
} catch(IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,11 +4,14 @@ import com.dfsek.terra.api.block.BlockType;
|
|||||||
import com.dfsek.terra.api.block.state.BlockState;
|
import com.dfsek.terra.api.block.state.BlockState;
|
||||||
import com.dfsek.terra.api.block.state.properties.Property;
|
import com.dfsek.terra.api.block.state.properties.Property;
|
||||||
|
|
||||||
|
import net.querz.nbt.tag.CompoundTag;
|
||||||
|
|
||||||
|
|
||||||
public class CLIBlockState implements BlockState {
|
public class CLIBlockState implements BlockState {
|
||||||
private final String value;
|
private final String value;
|
||||||
private final CLIBlockType type;
|
private final CLIBlockType type;
|
||||||
private final boolean isAir;
|
private final boolean isAir;
|
||||||
|
private final CompoundTag nbt;
|
||||||
|
|
||||||
public CLIBlockState(String value) {
|
public CLIBlockState(String value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
@@ -18,6 +21,8 @@ public class CLIBlockState implements BlockState {
|
|||||||
this.type = new CLIBlockType(value);
|
this.type = new CLIBlockType(value);
|
||||||
}
|
}
|
||||||
this.isAir = value.startsWith("minecraft:air");
|
this.isAir = value.startsWith("minecraft:air");
|
||||||
|
this.nbt = new CompoundTag();
|
||||||
|
this.nbt.putString("Name", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -59,4 +64,8 @@ public class CLIBlockState implements BlockState {
|
|||||||
public boolean isAir() {
|
public boolean isAir() {
|
||||||
return isAir;
|
return isAir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CompoundTag getNbt() {
|
||||||
|
return nbt;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -25,4 +25,8 @@ public class CLIWorldHandle implements WorldHandle {
|
|||||||
public @NotNull EntityType getEntity(@NotNull String id) {
|
public @NotNull EntityType getEntity(@NotNull String id) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static CLIBlockState getAIR() {
|
||||||
|
return AIR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,12 @@
|
|||||||
package com.dfsek.terra.cli.world;
|
package com.dfsek.terra.cli.world;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.util.generic.pair.Pair;
|
||||||
|
import com.dfsek.terra.api.util.vector.Vector2Int;
|
||||||
|
import com.dfsek.terra.api.world.chunk.generation.ProtoWorld;
|
||||||
|
import com.dfsek.terra.cli.NBTSerializable;
|
||||||
|
|
||||||
|
import com.dfsek.terra.cli.world.chunk.CLIChunk;
|
||||||
|
|
||||||
import net.jafama.FastMath;
|
import net.jafama.FastMath;
|
||||||
|
|
||||||
import com.dfsek.terra.api.block.entity.BlockEntity;
|
import com.dfsek.terra.api.block.entity.BlockEntity;
|
||||||
@@ -10,11 +17,25 @@ import com.dfsek.terra.api.entity.EntityType;
|
|||||||
import com.dfsek.terra.api.util.vector.Vector3;
|
import com.dfsek.terra.api.util.vector.Vector3;
|
||||||
import com.dfsek.terra.api.world.ServerWorld;
|
import com.dfsek.terra.api.world.ServerWorld;
|
||||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||||
import com.dfsek.terra.api.world.chunk.Chunk;
|
|
||||||
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
|
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
|
||||||
|
|
||||||
|
import net.querz.mca.MCAFile;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class CLIWorld implements ServerWorld {
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
|
||||||
|
public class CLIWorld implements ServerWorld, NBTSerializable<Stream<Pair<Vector2Int, MCAFile>>> {
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(CLIWorld.class);
|
||||||
private static final int regionBlocks = 32 * 16;
|
private static final int regionBlocks = 32 * 16;
|
||||||
private final Region[] regions;
|
private final Region[] regions;
|
||||||
private final int size;
|
private final int size;
|
||||||
@@ -24,6 +45,9 @@ public class CLIWorld implements ServerWorld {
|
|||||||
private final ChunkGenerator chunkGenerator;
|
private final ChunkGenerator chunkGenerator;
|
||||||
private final BiomeProvider biomeProvider;
|
private final BiomeProvider biomeProvider;
|
||||||
private final ConfigPack pack;
|
private final ConfigPack pack;
|
||||||
|
private final AtomicInteger amount = new AtomicInteger(0);
|
||||||
|
|
||||||
|
private final ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()-1);
|
||||||
|
|
||||||
public CLIWorld(int size,
|
public CLIWorld(int size,
|
||||||
long seed,
|
long seed,
|
||||||
@@ -31,13 +55,50 @@ public class CLIWorld implements ServerWorld {
|
|||||||
int minHeight,
|
int minHeight,
|
||||||
ConfigPack pack) {
|
ConfigPack pack) {
|
||||||
this.size = size;
|
this.size = size;
|
||||||
this.regions = new Region[size * size];
|
|
||||||
this.seed = seed;
|
|
||||||
this.maxHeight = maxHeight;
|
this.maxHeight = maxHeight;
|
||||||
this.minHeight = minHeight;
|
this.minHeight = minHeight;
|
||||||
|
this.seed = seed;
|
||||||
this.chunkGenerator = pack.getGeneratorProvider().newInstance(pack);
|
this.chunkGenerator = pack.getGeneratorProvider().newInstance(pack);
|
||||||
this.biomeProvider = pack.getBiomeProvider();
|
this.biomeProvider = pack.getBiomeProvider();
|
||||||
this.pack = pack;
|
this.pack = pack;
|
||||||
|
|
||||||
|
|
||||||
|
this.regions = new Region[(size + 1) * (size + 1)];
|
||||||
|
for(int x = 0; x < size + 1; x++) {
|
||||||
|
for(int z = 0; z < size + 1; z++) {
|
||||||
|
regions[x + z * (size + 1)] = new Region(this, x, z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void generate() {
|
||||||
|
int sizeChunks = size * 32;
|
||||||
|
List<Future<?>> futures = new ArrayList<>();
|
||||||
|
final long start = System.nanoTime();
|
||||||
|
for(int x = -sizeChunks + 1; x < sizeChunks; x++) {
|
||||||
|
for(int z = -sizeChunks + 1; z < sizeChunks; z++) {
|
||||||
|
int finalX = x;
|
||||||
|
int finalZ = z;
|
||||||
|
futures.add(executor.submit(() -> {
|
||||||
|
int num = amount.getAndIncrement();
|
||||||
|
long time = System.nanoTime();
|
||||||
|
double cps = num / ((double) (time - start) / 1000000000);
|
||||||
|
LOGGER.info("Generating chunk at ({}, {}), generated {} chunks at {}cps", finalX, finalZ, num, cps);
|
||||||
|
CLIChunk chunk = getChunkAt(finalX, finalZ);
|
||||||
|
chunkGenerator.generateChunkData(chunk, this, finalX, finalZ);
|
||||||
|
CLIProtoWorld protoWorld = new CLIProtoWorld(this, finalX, finalZ);
|
||||||
|
pack.getStages().forEach(stage -> stage.populate(protoWorld));
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Future<?> future : futures) {
|
||||||
|
try {
|
||||||
|
future.get();
|
||||||
|
} catch(InterruptedException | ExecutionException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -92,7 +153,9 @@ public class CLIWorld implements ServerWorld {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Chunk getChunkAt(int x, int z) {
|
public CLIChunk getChunkAt(int x, int z) {
|
||||||
|
x += (size + 1) * 16;
|
||||||
|
z += (size + 1) * 16;
|
||||||
return regions[FastMath.floorDiv(x, regionBlocks) + regionBlocks * FastMath.floorDiv(z, regionBlocks)]
|
return regions[FastMath.floorDiv(x, regionBlocks) + regionBlocks * FastMath.floorDiv(z, regionBlocks)]
|
||||||
.get(FastMath.floorMod(FastMath.floorDiv(x, 16), 32), FastMath.floorMod(FastMath.floorDiv(z, 16), 32));
|
.get(FastMath.floorMod(FastMath.floorDiv(x, 16), 32), FastMath.floorMod(FastMath.floorDiv(z, 16), 32));
|
||||||
}
|
}
|
||||||
@@ -137,4 +200,90 @@ public class CLIWorld implements ServerWorld {
|
|||||||
public Entity spawnEntity(double x, double y, double z, EntityType entityType) {
|
public Entity spawnEntity(double x, double y, double z, EntityType entityType) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<Pair<Vector2Int, MCAFile>> serialize() {
|
||||||
|
return Arrays.stream(regions).map(region -> Pair.of(Vector2Int.of(region.getX(), region.getZ()), region.serialize()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class CLIProtoWorld implements ProtoWorld {
|
||||||
|
private final CLIWorld delegate;
|
||||||
|
private final int x, z;
|
||||||
|
|
||||||
|
private CLIProtoWorld(CLIWorld delegate, int x, int z) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
this.x = x;
|
||||||
|
this.z = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getHandle() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockState getBlockState(int x, int y, int z) {
|
||||||
|
return delegate.getBlockState(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockEntity getBlockEntity(int x, int y, int z) {
|
||||||
|
return delegate.getBlockEntity(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getSeed() {
|
||||||
|
return delegate.seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxHeight() {
|
||||||
|
return delegate.maxHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMinHeight() {
|
||||||
|
return delegate.minHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChunkGenerator getGenerator() {
|
||||||
|
return delegate.chunkGenerator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BiomeProvider getBiomeProvider() {
|
||||||
|
return delegate.biomeProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ConfigPack getPack() {
|
||||||
|
return delegate.pack;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBlockState(int x, int y, int z, BlockState data, boolean physics) {
|
||||||
|
delegate.setBlockState(x, y, z, data, physics);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Entity spawnEntity(double x, double y, double z, EntityType entityType) {
|
||||||
|
return delegate.spawnEntity(x, y, z, entityType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int centerChunkX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int centerChunkZ() {
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ServerWorld getWorld() {
|
||||||
|
return delegate;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,16 +1,23 @@
|
|||||||
package com.dfsek.terra.cli.world;
|
package com.dfsek.terra.cli.world;
|
||||||
|
|
||||||
|
import com.dfsek.terra.cli.NBTSerializable;
|
||||||
import com.dfsek.terra.cli.world.chunk.CLIChunk;
|
import com.dfsek.terra.cli.world.chunk.CLIChunk;
|
||||||
|
|
||||||
|
import net.querz.mca.MCAFile;
|
||||||
|
import net.querz.mca.MCAUtil;
|
||||||
|
|
||||||
public class Region {
|
|
||||||
|
public class Region implements NBTSerializable<MCAFile> {
|
||||||
private final CLIChunk[] chunks;
|
private final CLIChunk[] chunks;
|
||||||
|
private final int x, z;
|
||||||
|
|
||||||
public Region(CLIWorld world) {
|
public Region(CLIWorld world, int x, int z) {
|
||||||
|
this.x = x;
|
||||||
|
this.z = z;
|
||||||
CLIChunk[] chunks = new CLIChunk[32 * 32];
|
CLIChunk[] chunks = new CLIChunk[32 * 32];
|
||||||
for(int x = 0; x < 32; x++) {
|
for(int cx = 0; cx < 32; cx++) {
|
||||||
for(int z = 0; z < 32; z++) {
|
for(int cz = 0; cz < 32; cz++) {
|
||||||
chunks[x * z * 32] = new CLIChunk(x, z, world);
|
chunks[cx + cz * 32] = new CLIChunk(cx, cz, world);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.chunks = chunks;
|
this.chunks = chunks;
|
||||||
@@ -19,4 +26,23 @@ public class Region {
|
|||||||
public CLIChunk get(int x, int z) {
|
public CLIChunk get(int x, int z) {
|
||||||
return chunks[x + z*32];
|
return chunks[x + z*32];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MCAFile serialize() {
|
||||||
|
MCAFile mcaFile = new MCAFile(x, z);
|
||||||
|
for(int cx = 0; cx < 32; cx++) {
|
||||||
|
for(int cz = 0; cz < 32; cz++) {
|
||||||
|
mcaFile.setChunk(cx, cz, chunks[cx + cz * 32].serialize());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mcaFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getZ() {
|
||||||
|
return z;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -4,26 +4,37 @@ import com.dfsek.terra.api.block.state.BlockState;
|
|||||||
import com.dfsek.terra.api.world.ServerWorld;
|
import com.dfsek.terra.api.world.ServerWorld;
|
||||||
import com.dfsek.terra.api.world.chunk.Chunk;
|
import com.dfsek.terra.api.world.chunk.Chunk;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.world.chunk.generation.ProtoChunk;
|
||||||
|
import com.dfsek.terra.cli.NBTSerializable;
|
||||||
import com.dfsek.terra.cli.block.CLIBlockState;
|
import com.dfsek.terra.cli.block.CLIBlockState;
|
||||||
|
|
||||||
|
import com.dfsek.terra.cli.handle.CLIWorldHandle;
|
||||||
import com.dfsek.terra.cli.world.CLIWorld;
|
import com.dfsek.terra.cli.world.CLIWorld;
|
||||||
|
|
||||||
|
import net.querz.mca.MCAFile;
|
||||||
|
import net.querz.nbt.tag.CompoundTag;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import static com.dfsek.terra.cli.handle.CLIWorldHandle.getAIR;
|
||||||
|
|
||||||
|
|
||||||
public class CLIChunk implements Chunk {
|
public class CLIChunk implements Chunk, ProtoChunk, NBTSerializable<net.querz.mca.Chunk> {
|
||||||
private final int x;
|
private final int x;
|
||||||
private final int z;
|
private final int z;
|
||||||
private final CLIBlockState[][][] blocks;
|
private final CLIBlockState[][][] blocks;
|
||||||
private final int minHeight;
|
private final int minHeight;
|
||||||
|
private final int maxHeight;
|
||||||
private final CLIWorld world;
|
private final CLIWorld world;
|
||||||
|
|
||||||
public CLIChunk(int x, int z, CLIWorld world) {
|
public CLIChunk(int x, int z, CLIWorld world) {
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.z = z;
|
this.z = z;
|
||||||
this.minHeight = world.getMinHeight();
|
this.minHeight = world.getMinHeight();
|
||||||
|
this.maxHeight = world.getMaxHeight();
|
||||||
this.world = world;
|
this.world = world;
|
||||||
this.blocks= new CLIBlockState[16][16][world.getMaxHeight() - minHeight];
|
this.blocks= new CLIBlockState[16][16][maxHeight - minHeight];
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -37,8 +48,10 @@ public class CLIChunk implements Chunk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull BlockState getBlock(int x, int y, int z) {
|
public @NotNull CLIBlockState getBlock(int x, int y, int z) {
|
||||||
return blocks[x][z][y - minHeight];
|
CLIBlockState blockState = blocks[x][z][y - minHeight];
|
||||||
|
if(blockState == null) return getAIR();
|
||||||
|
return blockState;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -55,4 +68,28 @@ public class CLIChunk implements Chunk {
|
|||||||
public ServerWorld getWorld() {
|
public ServerWorld getWorld() {
|
||||||
return world;
|
return world;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public net.querz.mca.Chunk serialize() {
|
||||||
|
net.querz.mca.Chunk chunk = net.querz.mca.Chunk.newChunk();
|
||||||
|
for(int x = 0; x < blocks.length; x++) {
|
||||||
|
for(int z = 0; z < blocks[x].length; z++) {
|
||||||
|
for(int y = 0; y < blocks[z][z].length; y++) {
|
||||||
|
CLIBlockState blockState = blocks[x][z][y];
|
||||||
|
if(blockState == null) {
|
||||||
|
blockState = CLIWorldHandle.getAIR();
|
||||||
|
}
|
||||||
|
int yi = y + minHeight;
|
||||||
|
if(yi < 0 || yi >= 256) continue;
|
||||||
|
chunk.setBlockStateAt(x, yi, z, blockState.getNbt(), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxHeight() {
|
||||||
|
return maxHeight;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user