diff --git a/core/src/main/java/mc/core/block/Block.java b/core/src/main/java/mc/core/block/Block.java index ea03afb..81d662a 100644 --- a/core/src/main/java/mc/core/block/Block.java +++ b/core/src/main/java/mc/core/block/Block.java @@ -25,6 +25,30 @@ import mc.core.Location; public interface Block { + static Block airBlock (int x, int y, int z) { + return new Block() { + @Override + public int getId() { + return 0; + } + + @Override + public int getMeta() { + return 0; + } + + @Override + public BlockType getBlockType() { + return BlockType.AIR; + } + + @Override + public Location getLocation() { + return new Location(x, y, z); + } + }; + } + /** Block id */ int getId(); diff --git a/core/src/main/java/mc/core/block/BlockFactory.java b/core/src/main/java/mc/core/block/BlockFactory.java index 2007c48..8552e4c 100644 --- a/core/src/main/java/mc/core/block/BlockFactory.java +++ b/core/src/main/java/mc/core/block/BlockFactory.java @@ -1,5 +1,7 @@ package mc.core.block; +import mc.core.Location; + public class BlockFactory { public Block create(BlockType blockType, int meta) { @@ -12,6 +14,7 @@ public class BlockFactory { private class EmbeddedBlock extends AbstractBlock { EmbeddedBlock(BlockType type, int meta) { super(type, meta); + super.setLocation(new Location(0,0,0)); } } } diff --git a/core/src/main/java/mc/core/block/BlockType.java b/core/src/main/java/mc/core/block/BlockType.java index f4a8648..4b4b467 100644 --- a/core/src/main/java/mc/core/block/BlockType.java +++ b/core/src/main/java/mc/core/block/BlockType.java @@ -9,7 +9,8 @@ public enum BlockType { BEDROCK(7, "Bedrock"), WATER(8, "Water"), SAND(12, "Sand"), - SNOW(32, "Snow"); + SNOW(32, "Snow"), + AIR(0, "Air"); @Getter private final int id; diff --git a/core/src/main/java/mc/core/world/Chunk.java b/core/src/main/java/mc/core/world/Chunk.java index 4138f4d..95b49b9 100644 --- a/core/src/main/java/mc/core/world/Chunk.java +++ b/core/src/main/java/mc/core/world/Chunk.java @@ -47,6 +47,7 @@ public interface Chunk { int getY(); int getZ(); - Block[] getNotAirBlocks(); + Block[] getModifiedBlocks(); void setBlock (int x, int y, int z, Block block); + Block getBlock (int x, int y, int z); } diff --git a/core/src/main/java/mc/core/world/Region.java b/core/src/main/java/mc/core/world/Region.java index 11b197c..2d72766 100644 --- a/core/src/main/java/mc/core/world/Region.java +++ b/core/src/main/java/mc/core/world/Region.java @@ -1,5 +1,9 @@ package mc.core.world; +import mc.core.serialization.Serializer; + +import java.io.IOException; + /** * Simple world generation unit * 16x16x16 chunks @@ -23,4 +27,6 @@ public interface Region { Biome getBiomeAt (int x, int z); void setBiome (int x, int z, Biome biome); + + void save(Serializer chunkSerializer, Serializer regionSerializer) throws IOException; } diff --git a/flat_world/src/main/java/mc/world/flat/SimpleChunk.java b/flat_world/src/main/java/mc/world/flat/SimpleChunk.java index 09cbb5d..4e95a4d 100644 --- a/flat_world/src/main/java/mc/world/flat/SimpleChunk.java +++ b/flat_world/src/main/java/mc/world/flat/SimpleChunk.java @@ -5,6 +5,8 @@ package mc.world.flat; import mc.core.block.Block; +import mc.core.block.BlockFactory; +import mc.core.block.BlockType; import mc.core.world.Biome; import mc.core.world.Chunk; @@ -89,7 +91,7 @@ public class SimpleChunk implements Chunk { } @Override - public Block[] getNotAirBlocks() { + public Block[] getModifiedBlocks() { return new Block[0]; } @@ -97,4 +99,14 @@ public class SimpleChunk implements Chunk { public void setBlock(int x, int y, int z, Block block) { } + + @Override + public Block getBlock(int x, int y, int z) { + BlockFactory blockFactory = new BlockFactory(); + + if (y == 0) return blockFactory.create(BlockType.BEDROCK, 0); + else if (y >= 1 && y <= 2) return blockFactory.create(BlockType.DIRT, 0); + else if (y == 3) return blockFactory.create(BlockType.GRASS, 0); + else return Block.airBlock(x, y, z); + } } diff --git a/generated_world/src/main/java/mc/world/generated_world/ChunkSerializerDeserializer.java b/generated_world/src/main/java/mc/world/generated_world/ChunkSerializerDeserializer.java new file mode 100644 index 0000000..1f2df79 --- /dev/null +++ b/generated_world/src/main/java/mc/world/generated_world/ChunkSerializerDeserializer.java @@ -0,0 +1,41 @@ +package mc.world.generated_world; + +import mc.core.block.BlockFactory; +import mc.core.serialization.BlockDeserializer; +import mc.core.serialization.BlockSerializer; +import mc.core.serialization.ChunkSerializer; +import mc.core.serialization.ChunkDeserializer; +import mc.core.world.Chunk; + +public class ChunkSerializerDeserializer implements ChunkSerializer, ChunkDeserializer { + + private BlockSerializer blockSerializer; + private BlockDeserializer blockDeserializer; + + @Override + public Chunk deserialize(byte[] bytes) { + return null; + } + + @Override + public byte[] serialize(Chunk chunk) { + BlockSerializer blockSerializer = new BlockSerializerDeserializer(new BlockFactory(), chunk); + int blocks = chunk.getModifiedBlocks().length; + byte[] bytes = new byte[6 + 3 * blocks]; + + bytes[0] = (byte) ((chunk.getX() >> 6) & 0xff); + bytes[1] = (byte) (((chunk.getX() & 0x3f) << 2) | ((chunk.getY()) >> 2) & 0x03); + bytes[2] = (byte) (((chunk.getY() & 0x03) << 6) | ((chunk.getZ() >> 8) & 0x3f)); + bytes[3] = (byte) (chunk.getZ() & 0xff); + bytes[4] = (byte) ((blocks >> 5) & 0xff); + bytes[5] = (byte) ((blocks & 0x1f) << 3); + + for (int i = 0; i < blocks; i ++) { + byte[] blockSerialized = blockSerializer.serialize(chunk.getModifiedBlocks()[i]); + for (int j = 0; j < 3; j ++) { + bytes[6 + i * 3 + j] = blockSerialized[j]; + } + } + return bytes; + } +} diff --git a/generated_world/src/main/java/mc/world/generated_world/CubicWorld.java b/generated_world/src/main/java/mc/world/generated_world/CubicWorld.java index d22fed4..1f21785 100644 --- a/generated_world/src/main/java/mc/world/generated_world/CubicWorld.java +++ b/generated_world/src/main/java/mc/world/generated_world/CubicWorld.java @@ -16,25 +16,25 @@ public class CubicWorld implements World { public CubicWorld(UUID worldId, int seed) { this.worldId = worldId; - chunkLoader = new InMemoryCacheChunkLoader(worldId); + chunkLoader = new InMemoryCacheChunkLoader(this); this.seed = seed; } public CubicWorld(int seed) { this.worldId = UUID.randomUUID(); - chunkLoader = new InMemoryCacheChunkLoader(worldId); + chunkLoader = new InMemoryCacheChunkLoader(this); this.seed = seed; } public CubicWorld(UUID worldId) { this.worldId = worldId; - chunkLoader = new InMemoryCacheChunkLoader(worldId); + chunkLoader = new InMemoryCacheChunkLoader(this); this.seed = 0; } public CubicWorld () { this.worldId = UUID.randomUUID(); - chunkLoader = new InMemoryCacheChunkLoader(worldId); + chunkLoader = new InMemoryCacheChunkLoader(this); this.seed = 0; } diff --git a/generated_world/src/main/java/mc/world/generated_world/InMemoryCacheChunkLoader.java b/generated_world/src/main/java/mc/world/generated_world/InMemoryCacheChunkLoader.java new file mode 100644 index 0000000..1cef35d --- /dev/null +++ b/generated_world/src/main/java/mc/world/generated_world/InMemoryCacheChunkLoader.java @@ -0,0 +1,127 @@ +package mc.world.generated_world; + +import lombok.extern.slf4j.Slf4j; +import mc.core.serialization.ChunkDeserializer; +import mc.core.serialization.ChunkSerializer; +import mc.core.serialization.Deserializer; +import mc.core.serialization.Serializer; +import mc.core.world.*; +import mc.world.generated_world.region.RegionImpl; +import org.springframework.beans.factory.annotation.Autowired; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.text.MessageFormat; +import java.util.Optional; +import java.util.UUID; + +import static mc.world.generated_world.WorldConstants.*; + +@Slf4j +public class InMemoryCacheChunkLoader implements ChunkLoader { + + private final World world; + private File worldFolder; + @Autowired + private WorldGenerator worldGenerator; + + @Autowired + private ChunkDeserializer chunkDeserializer; + @Autowired + private ChunkSerializer chunkSerializer; + @Autowired + private Serializer regionSerializer; + @Autowired + private Deserializer regionDeserializer; + + public InMemoryCacheChunkLoader(World world) { + this.world = world; + String worldPath = System.getProperty("worlds.folder", "worlds"); + worldFolder = new File(worldPath, world.getWorldId().toString()); + if (!worldFolder.exists()) { + log.info("Created folder for world with uuid '{}'", world.getWorldId()); + worldFolder.mkdirs(); + } + } + + private File getChuckFile(int x, int y, int z) { + return new File(worldFolder, MessageFormat.format(CHUNK_FILE_NAME_TEMPLATE, x, y, z)); + } + + @Override + public Optional loadChunk(int x, int y, int z) { + File file = getChuckFile(x, y, z); + if (!file.exists()) { + return Optional.empty(); + } else { + try { + byte[] bytes = Files.readAllBytes(Paths.get(file.toURI())); + return Optional.of(chunkDeserializer.deserialize(bytes)); + } catch (IOException e) { + log.error("Error occurred while reading chunk file: " + file.getAbsolutePath(), e); + return Optional.empty(); + } + } + } + + @Override + public Chunk loadOrGenerateChunk(int x, int y, int z) { + int regX = x / WORLD_REGION_SIZE; + int regZ = z / WORLD_REGION_SIZE; + File regionFile = new File(worldFolder, MessageFormat.format(REGION_FILE_NAME_TEMPLATE, regX, regZ)); + Region region; + Chunk chunk; + if (!regionFile.exists()) { + log.debug("Region [{}, {}] not found. Generating!", regX, regZ); + regionFile.mkdirs(); + region = worldGenerator.generateRegion(regX, regZ, world); + File biomeMapFile = new File(regionFile, BIOME_FILE_NAME_TEMPLATE); + byte[] biomeMapBytes = regionSerializer.serialize(region); + try (FileOutputStream writer = new FileOutputStream(biomeMapFile)) { + writer.write(biomeMapBytes); + } catch (IOException e) { + log.error("Error occurred while writting biome file", e); + } + saveRegion(region); + chunk = region.getChunkAt(x % WORLD_CHUNK_SIZE, y % WORLD_CHUNK_SIZE, z % WORLD_CHUNK_SIZE); + } else { + File chunkFile = new File(regionFile, MessageFormat.format(CHUNK_FILE_NAME_TEMPLATE, x % WORLD_CHUNK_SIZE, y % WORLD_CHUNK_SIZE, z % WORLD_CHUNK_SIZE)); + try { + byte[] chunkBytes = Files.readAllBytes(Paths.get(chunkFile.toURI())); + byte[] regionBytes = Files.readAllBytes(Paths.get(new File(regionFile, BIOME_FILE_NAME_TEMPLATE).toURI())); + region = regionDeserializer.deserialize(regionBytes); + chunk = chunkDeserializer.deserialize(chunkBytes); + } catch (IOException e) { + log.error("Error occurred while reading chunk file", e); + return null; + } + } + for (int tx = 0; tx < WORLD_CHUNK_SIZE; tx++) { + for (int tz = 0; tz < WORLD_CHUNK_SIZE; tz ++) { + chunk.setBiome(tx, tz, region.getBiomeAt(chunk.getX() * WORLD_CHUNK_SIZE + x, chunk.getZ() * WORLD_CHUNK_SIZE + z)); + } + } + return chunk; + } + + private void saveRegion (Region region) { + File file = new File(worldFolder, MessageFormat.format(REGION_FILE_NAME_TEMPLATE, region.getX(), region.getZ())); + for (int x = 0; x < WORLD_REGION_SIZE / WORLD_CHUNK_SIZE; x ++) { + for (int y = 0; y < WORLD_REGION_SIZE / WORLD_CHUNK_SIZE; y ++) { + for (int z = 0; z < WORLD_REGION_SIZE / WORLD_CHUNK_SIZE; z ++) { + byte[] chunkBytes = chunkSerializer.serialize(region.getChunkAt(x, y, z)); + File chunkFile = new File(file, MessageFormat.format(CHUNK_FILE_NAME_TEMPLATE, x, y, z)); + try (FileOutputStream writer = new FileOutputStream(chunkFile)) { + writer.write(chunkBytes); + } catch (IOException e) { + log.error("Error occurred while writting chunk to file", e); + } + } + } + } + } +} diff --git a/generated_world/src/main/java/mc/world/generated_world/RegionSerializerDeserializer.java b/generated_world/src/main/java/mc/world/generated_world/RegionSerializerDeserializer.java new file mode 100644 index 0000000..f5a1218 --- /dev/null +++ b/generated_world/src/main/java/mc/world/generated_world/RegionSerializerDeserializer.java @@ -0,0 +1,17 @@ +package mc.world.generated_world; + +import mc.core.serialization.Deserializer; +import mc.core.serialization.Serializer; +import mc.core.world.Region; + +public class RegionSerializerDeserializer implements Serializer, Deserializer { + @Override + public Region deserialize(byte[] bytes) { + return null; + } + + @Override + public byte[] serialize(Region region) { + return new byte[0]; + } +} diff --git a/generated_world/src/main/java/mc/world/generated_world/SeedBasedWorldGenerator.java b/generated_world/src/main/java/mc/world/generated_world/SeedBasedWorldGenerator.java index a972154..c1e768a 100644 --- a/generated_world/src/main/java/mc/world/generated_world/SeedBasedWorldGenerator.java +++ b/generated_world/src/main/java/mc/world/generated_world/SeedBasedWorldGenerator.java @@ -2,6 +2,7 @@ package mc.world.generated_world; import lombok.RequiredArgsConstructor; import mc.core.block.BlockFactory; +import mc.core.block.BlockType; import mc.core.world.*; import mc.world.generated_world.region.RegionImpl; import mc.world.generated_world.word.Temperature; @@ -19,7 +20,8 @@ public class SeedBasedWorldGenerator implements WorldGenerator { public static void main(String[] args) throws Exception{ WorldGenerator worldGenerator = new SeedBasedWorldGenerator(); World world = new CubicWorld(UUID.fromString("00000000-0000-0000-C000-000000000046"), 123); - worldGenerator.generateRegion(0, 0, world); + Region region = worldGenerator.generateRegion(0, 0, world); + region.save(new ChunkSerializerDeserializer(), new RegionSerializerDeserializer()); /*worldGenerator.generateRegion(1, 0, world); worldGenerator.generateRegion(-1, 0, world); worldGenerator.generateRegion(0, 1, world); @@ -83,7 +85,7 @@ public class SeedBasedWorldGenerator implements WorldGenerator { @Override public Region generateRegion(int x, int z, World world) { - Region region = new RegionImpl(x,z); + Region region = new RegionImpl(x, z, world); RegionGenerator regionGenerator = new RegionGenerator(world, region); regionGenerator.generate(); return region; @@ -233,7 +235,7 @@ public class SeedBasedWorldGenerator implements WorldGenerator { } catch (Exception e) {} // ================================ DEBUG FINISH ======================================= - /*for (int x = 0; x < WorldConstants.WORLD_REGION_SIZE; x ++) { + for (int x = 0; x < WorldConstants.WORLD_REGION_SIZE; x ++) { for (int z = 0; z < WorldConstants.WORLD_REGION_SIZE; z ++) { region.setBiome(x, z, biomes[x][z]); if (heightMap[x][z] < WORLD_SEA_LEVEL) { @@ -274,7 +276,7 @@ public class SeedBasedWorldGenerator implements WorldGenerator { } } } - }*/ + } } private Biome selectBiome (Temperature temperature, Wetness wetness, int height) { diff --git a/generated_world/src/main/java/mc/world/generated_world/WorldConstants.java b/generated_world/src/main/java/mc/world/generated_world/WorldConstants.java index acc500d..7cc050c 100644 --- a/generated_world/src/main/java/mc/world/generated_world/WorldConstants.java +++ b/generated_world/src/main/java/mc/world/generated_world/WorldConstants.java @@ -3,13 +3,14 @@ package mc.world.generated_world; public final class WorldConstants { public static final String CHUNK_FILE_NAME_TEMPLATE = "chunk_{0}_{1}_{2}.dat"; - public static final String BIOME_FILE_NAME_TEMPLATE = "biome_{0}_{1}.dat"; + public static final String BIOME_FILE_NAME_TEMPLATE = "biomes.dat"; public static final String REGION_FILE_NAME_TEMPLATE = "r.{0}.{1}"; public static final int WORLD_MIN_HEIGHT = 28; public static final int WORLD_SEA_LEVEL = 64; public static final int WORLD_MAX_HEIGHT = 128; public static final int WORLD_REGION_SIZE = 256; + public static final int WORLD_CHUNK_SIZE = 16; public static final int WORLD_MAX_TEMPERATURE = 100; public static final int WORLD_MAX_WETNESS = 100; public static final int WORLD_BASE_WETNESS = 80; @@ -23,7 +24,7 @@ public final class WorldConstants { public static final int LANDFILL_GRASS_SURFACE_THIN = 5; - public static final double WORLD_ROUGHNRESS = 0.35; + public static final double WORLD_ROUGHNESS = 0.35; private WorldConstants () {} } diff --git a/generated_world/src/main/java/mc/world/generated_world/chunk/ChunkImpl.java b/generated_world/src/main/java/mc/world/generated_world/chunk/ChunkImpl.java new file mode 100644 index 0000000..4ffcc69 --- /dev/null +++ b/generated_world/src/main/java/mc/world/generated_world/chunk/ChunkImpl.java @@ -0,0 +1,106 @@ +package mc.world.generated_world.chunk; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import mc.core.block.Block; +import mc.core.world.Biome; +import mc.core.world.Chunk; +import mc.core.world.Region; + +import java.util.LinkedList; +import java.util.List; + +import static mc.world.generated_world.WorldConstants.WORLD_CHUNK_SIZE; + +@RequiredArgsConstructor +public class ChunkImpl implements Chunk{ + @Getter + private final int x; + @Getter + private final int y; + @Getter + private final int z; + private final Block[][][] blocks = new Block[WORLD_CHUNK_SIZE][WORLD_CHUNK_SIZE][WORLD_CHUNK_SIZE]; + private final transient List modifiedBlocks = new LinkedList<>(); + private final transient Region region; + + @Override + public int getBlockType(int x, int y, int z) { + return blocks[x][y][z].getId(); + } + + @Override + public void setBlockType(int x, int y, int z, int type) { + + } + + @Override + public int getBlockMetadata(int x, int y, int z) { + return 0; + } + + @Override + public void setBlockMetadata(int x, int y, int z, int metadata) { + + } + + @Override + public int getBlockLight(int x, int y, int z) { + return 15; + } + + @Override + public void setBlockLight(int x, int y, int z, int lightLevel) { + + } + + @Override + public int getSkyLight(int x, int y, int z) { + return 15; + } + + @Override + public void setSkyLight(int x, int y, int z, int lightLevel) { + + } + + @Override + public int getAddition(int x, int y, int z) { + return 0; + } + + @Override + public void setAddition(int x, int y, int z, int value) { + + } + + @Override + public Biome getBiome(int x, int z) { + return region.getBiomeAt(x + this.x * WORLD_CHUNK_SIZE,z + this.z * WORLD_CHUNK_SIZE); + } + + @Override + public void setBiome(int x, int z, Biome biome) { + region.setBiome(x + this.x * WORLD_CHUNK_SIZE,z + this.z * WORLD_CHUNK_SIZE, biome); + } + + @Override + public Block[] getModifiedBlocks() { + return modifiedBlocks.toArray(new Block[modifiedBlocks.size()]); + } + + @Override + public void setBlock(int x, int y, int z, Block block) { + blocks[x][y][z] = block; + modifiedBlocks.add(block); + } + + @Override + public Block getBlock(int x, int y, int z) { + Block block = blocks[x][y][z]; + if (block == null) { + return Block.airBlock(x, y, z); + } + return blocks[x][y][z]; + } +} diff --git a/generated_world/src/main/java/mc/world/generated_world/chunk/ChunkProxy.java b/generated_world/src/main/java/mc/world/generated_world/chunk/ChunkProxy.java index e1c1d47..d135759 100644 --- a/generated_world/src/main/java/mc/world/generated_world/chunk/ChunkProxy.java +++ b/generated_world/src/main/java/mc/world/generated_world/chunk/ChunkProxy.java @@ -115,9 +115,9 @@ public class ChunkProxy implements Chunk { } @Override - public Block[] getNotAirBlocks() { + public Block[] getModifiedBlocks() { use(); - return chunk.getNotAirBlocks(); + return chunk.getModifiedBlocks(); } @Override @@ -125,4 +125,10 @@ public class ChunkProxy implements Chunk { use(); chunk.setBlock(x, y, z, block); } + + @Override + public Block getBlock(int x, int y, int z) { + use(); + return chunk.getBlock(x, y, z); + } } diff --git a/generated_world/src/main/java/mc/world/generated_world/region/RegionImpl.java b/generated_world/src/main/java/mc/world/generated_world/region/RegionImpl.java index b61f053..8d73364 100644 --- a/generated_world/src/main/java/mc/world/generated_world/region/RegionImpl.java +++ b/generated_world/src/main/java/mc/world/generated_world/region/RegionImpl.java @@ -2,14 +2,21 @@ package mc.world.generated_world.region; import lombok.Getter; import lombok.RequiredArgsConstructor; -import lombok.Setter; import lombok.extern.slf4j.Slf4j; +import mc.core.serialization.Serializer; import mc.core.world.*; +import mc.world.generated_world.InMemoryCacheChunkLoader; +import mc.world.generated_world.chunk.ChunkImpl; import mc.world.generated_world.chunk.ChunkProxy; import org.springframework.beans.factory.annotation.Autowired; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; import java.text.MessageFormat; +import static mc.world.generated_world.WorldConstants.*; + @Slf4j @RequiredArgsConstructor public class RegionImpl implements Region{ @@ -17,10 +24,10 @@ public class RegionImpl implements Region{ private final int x; @Getter private final int z; - private final ChunkProxy[][][] chunks = new ChunkProxy[16][16][16]; - private final Biome[][] biomes = new Biome[16][16]; - @Getter@Setter - private transient World world; + private final ChunkProxy[][][] chunks = new ChunkProxy[WORLD_REGION_SIZE/WORLD_CHUNK_SIZE][WORLD_REGION_SIZE/WORLD_CHUNK_SIZE][WORLD_REGION_SIZE/WORLD_CHUNK_SIZE]; + private final Biome[][] biomes = new Biome[WORLD_REGION_SIZE][WORLD_REGION_SIZE]; + @Getter + private final transient World world; @Autowired private ChunkLoader chunkLoader; @@ -29,9 +36,12 @@ public class RegionImpl implements Region{ if (x < 0 || y < 0 || z < 0 || x >= 16 || y >= 16 || z >= 16) { throw new RuntimeException(MessageFormat.format("Invalid chunk coordinates [{0} {1} {2}]", x, y, z)); } + if (chunkLoader == null) { + chunkLoader = new InMemoryCacheChunkLoader(world); + } Chunk chunk = chunks[x][y][z]; if (chunk == null) { - chunk = chunkLoader.loadOrGenerateChunk(x, y, z); + chunk = chunkLoader.loadChunk(x + this.x * WORLD_REGION_SIZE, y, this.z * WORLD_REGION_SIZE).orElse(new ChunkImpl(x, y, z, this)); chunks[x][y][z] = new ChunkProxy(chunk); } return chunk; @@ -60,4 +70,30 @@ public class RegionImpl implements Region{ } biomes[x][z] = biome; } + + @Override + public void save(Serializer chunkSerializer, Serializer regionSerializer) throws IOException { + String worldPath = System.getProperty("worlds.folder", "worlds"); + File worldFile = new File(worldPath, world.getWorldId().toString()); + File regionFile = new File(worldFile, MessageFormat.format(REGION_FILE_NAME_TEMPLATE, this.getX(), this.getZ())); + if (!regionFile.exists()) { + regionFile.mkdirs(); + } + File biomeMapFile = new File(regionFile, BIOME_FILE_NAME_TEMPLATE); + byte[] biomeBytes = regionSerializer.serialize(this); + try (FileOutputStream fileOutputStream = new FileOutputStream(biomeMapFile)){ + fileOutputStream.write(biomeBytes); + } + for (int x = 0; x < WORLD_CHUNK_SIZE; x ++) { + for (int z = 0; z < WORLD_CHUNK_SIZE; z ++) { + for (int y = 0; y < WORLD_CHUNK_SIZE; y++) { + File chunkFile = new File(regionFile, MessageFormat.format(CHUNK_FILE_NAME_TEMPLATE, x, y, z)); + byte[] chunkBytes = chunkSerializer.serialize(this.getChunkAt(x, y, z)); + try (FileOutputStream fileOutputStream = new FileOutputStream(chunkFile)){ + fileOutputStream.write(chunkBytes); + } + } + } + } + } } diff --git a/generated_world/src/main/resources/log4j2.xml b/generated_world/src/main/resources/log4j2.xml new file mode 100644 index 0000000..0ea354b --- /dev/null +++ b/generated_world/src/main/resources/log4j2.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + +