Archived
0

Chunk generations & basic saving

This commit is contained in:
Forwolk
2018-08-01 17:49:59 +03:00
parent 62d4ec6768
commit 75bec3ed93
16 changed files with 422 additions and 21 deletions

View File

@@ -25,6 +25,30 @@ import mc.core.Location;
public interface Block { 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 */ /** Block id */
int getId(); int getId();

View File

@@ -1,5 +1,7 @@
package mc.core.block; package mc.core.block;
import mc.core.Location;
public class BlockFactory { public class BlockFactory {
public Block create(BlockType blockType, int meta) { public Block create(BlockType blockType, int meta) {
@@ -12,6 +14,7 @@ public class BlockFactory {
private class EmbeddedBlock extends AbstractBlock { private class EmbeddedBlock extends AbstractBlock {
EmbeddedBlock(BlockType type, int meta) { EmbeddedBlock(BlockType type, int meta) {
super(type, meta); super(type, meta);
super.setLocation(new Location(0,0,0));
} }
} }
} }

View File

@@ -9,7 +9,8 @@ public enum BlockType {
BEDROCK(7, "Bedrock"), BEDROCK(7, "Bedrock"),
WATER(8, "Water"), WATER(8, "Water"),
SAND(12, "Sand"), SAND(12, "Sand"),
SNOW(32, "Snow"); SNOW(32, "Snow"),
AIR(0, "Air");
@Getter @Getter
private final int id; private final int id;

View File

@@ -47,6 +47,7 @@ public interface Chunk {
int getY(); int getY();
int getZ(); int getZ();
Block[] getNotAirBlocks(); Block[] getModifiedBlocks();
void setBlock (int x, int y, int z, Block block); void setBlock (int x, int y, int z, Block block);
Block getBlock (int x, int y, int z);
} }

View File

@@ -1,5 +1,9 @@
package mc.core.world; package mc.core.world;
import mc.core.serialization.Serializer;
import java.io.IOException;
/** /**
* Simple world generation unit * Simple world generation unit
* 16x16x16 chunks * 16x16x16 chunks
@@ -23,4 +27,6 @@ public interface Region {
Biome getBiomeAt (int x, int z); Biome getBiomeAt (int x, int z);
void setBiome (int x, int z, Biome biome); void setBiome (int x, int z, Biome biome);
void save(Serializer<Chunk> chunkSerializer, Serializer<Region> regionSerializer) throws IOException;
} }

View File

@@ -5,6 +5,8 @@
package mc.world.flat; package mc.world.flat;
import mc.core.block.Block; import mc.core.block.Block;
import mc.core.block.BlockFactory;
import mc.core.block.BlockType;
import mc.core.world.Biome; import mc.core.world.Biome;
import mc.core.world.Chunk; import mc.core.world.Chunk;
@@ -89,7 +91,7 @@ public class SimpleChunk implements Chunk {
} }
@Override @Override
public Block[] getNotAirBlocks() { public Block[] getModifiedBlocks() {
return new Block[0]; return new Block[0];
} }
@@ -97,4 +99,14 @@ public class SimpleChunk implements Chunk {
public void setBlock(int x, int y, int z, Block block) { 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);
}
} }

View File

@@ -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;
}
}

View File

@@ -16,25 +16,25 @@ public class CubicWorld implements World {
public CubicWorld(UUID worldId, int seed) { public CubicWorld(UUID worldId, int seed) {
this.worldId = worldId; this.worldId = worldId;
chunkLoader = new InMemoryCacheChunkLoader(worldId); chunkLoader = new InMemoryCacheChunkLoader(this);
this.seed = seed; this.seed = seed;
} }
public CubicWorld(int seed) { public CubicWorld(int seed) {
this.worldId = UUID.randomUUID(); this.worldId = UUID.randomUUID();
chunkLoader = new InMemoryCacheChunkLoader(worldId); chunkLoader = new InMemoryCacheChunkLoader(this);
this.seed = seed; this.seed = seed;
} }
public CubicWorld(UUID worldId) { public CubicWorld(UUID worldId) {
this.worldId = worldId; this.worldId = worldId;
chunkLoader = new InMemoryCacheChunkLoader(worldId); chunkLoader = new InMemoryCacheChunkLoader(this);
this.seed = 0; this.seed = 0;
} }
public CubicWorld () { public CubicWorld () {
this.worldId = UUID.randomUUID(); this.worldId = UUID.randomUUID();
chunkLoader = new InMemoryCacheChunkLoader(worldId); chunkLoader = new InMemoryCacheChunkLoader(this);
this.seed = 0; this.seed = 0;
} }

View File

@@ -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<Region> regionSerializer;
@Autowired
private Deserializer<Region> 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<Chunk> 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);
}
}
}
}
}
}

View File

@@ -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<Region>, Deserializer<Region> {
@Override
public Region deserialize(byte[] bytes) {
return null;
}
@Override
public byte[] serialize(Region region) {
return new byte[0];
}
}

View File

@@ -2,6 +2,7 @@ package mc.world.generated_world;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import mc.core.block.BlockFactory; import mc.core.block.BlockFactory;
import mc.core.block.BlockType;
import mc.core.world.*; import mc.core.world.*;
import mc.world.generated_world.region.RegionImpl; import mc.world.generated_world.region.RegionImpl;
import mc.world.generated_world.word.Temperature; import mc.world.generated_world.word.Temperature;
@@ -19,7 +20,8 @@ public class SeedBasedWorldGenerator implements WorldGenerator {
public static void main(String[] args) throws Exception{ public static void main(String[] args) throws Exception{
WorldGenerator worldGenerator = new SeedBasedWorldGenerator(); WorldGenerator worldGenerator = new SeedBasedWorldGenerator();
World world = new CubicWorld(UUID.fromString("00000000-0000-0000-C000-000000000046"), 123); 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(-1, 0, world); worldGenerator.generateRegion(-1, 0, world);
worldGenerator.generateRegion(0, 1, world); worldGenerator.generateRegion(0, 1, world);
@@ -83,7 +85,7 @@ public class SeedBasedWorldGenerator implements WorldGenerator {
@Override @Override
public Region generateRegion(int x, int z, World world) { 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 regionGenerator = new RegionGenerator(world, region);
regionGenerator.generate(); regionGenerator.generate();
return region; return region;
@@ -233,7 +235,7 @@ public class SeedBasedWorldGenerator implements WorldGenerator {
} catch (Exception e) {} } catch (Exception e) {}
// ================================ DEBUG FINISH ======================================= // ================================ 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 ++) { for (int z = 0; z < WorldConstants.WORLD_REGION_SIZE; z ++) {
region.setBiome(x, z, biomes[x][z]); region.setBiome(x, z, biomes[x][z]);
if (heightMap[x][z] < WORLD_SEA_LEVEL) { 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) { private Biome selectBiome (Temperature temperature, Wetness wetness, int height) {

View File

@@ -3,13 +3,14 @@ package mc.world.generated_world;
public final class WorldConstants { public final class WorldConstants {
public static final String CHUNK_FILE_NAME_TEMPLATE = "chunk_{0}_{1}_{2}.dat"; 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 String REGION_FILE_NAME_TEMPLATE = "r.{0}.{1}";
public static final int WORLD_MIN_HEIGHT = 28; public static final int WORLD_MIN_HEIGHT = 28;
public static final int WORLD_SEA_LEVEL = 64; public static final int WORLD_SEA_LEVEL = 64;
public static final int WORLD_MAX_HEIGHT = 128; public static final int WORLD_MAX_HEIGHT = 128;
public static final int WORLD_REGION_SIZE = 256; 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_TEMPERATURE = 100;
public static final int WORLD_MAX_WETNESS = 100; public static final int WORLD_MAX_WETNESS = 100;
public static final int WORLD_BASE_WETNESS = 80; 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 int LANDFILL_GRASS_SURFACE_THIN = 5;
public static final double WORLD_ROUGHNRESS = 0.35; public static final double WORLD_ROUGHNESS = 0.35;
private WorldConstants () {} private WorldConstants () {}
} }

View File

@@ -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<Block> 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];
}
}

View File

@@ -115,9 +115,9 @@ public class ChunkProxy implements Chunk {
} }
@Override @Override
public Block[] getNotAirBlocks() { public Block[] getModifiedBlocks() {
use(); use();
return chunk.getNotAirBlocks(); return chunk.getModifiedBlocks();
} }
@Override @Override
@@ -125,4 +125,10 @@ public class ChunkProxy implements Chunk {
use(); use();
chunk.setBlock(x, y, z, block); chunk.setBlock(x, y, z, block);
} }
@Override
public Block getBlock(int x, int y, int z) {
use();
return chunk.getBlock(x, y, z);
}
} }

View File

@@ -2,14 +2,21 @@ package mc.world.generated_world.region;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import mc.core.serialization.Serializer;
import mc.core.world.*; 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 mc.world.generated_world.chunk.ChunkProxy;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.MessageFormat; import java.text.MessageFormat;
import static mc.world.generated_world.WorldConstants.*;
@Slf4j @Slf4j
@RequiredArgsConstructor @RequiredArgsConstructor
public class RegionImpl implements Region{ public class RegionImpl implements Region{
@@ -17,10 +24,10 @@ public class RegionImpl implements Region{
private final int x; private final int x;
@Getter @Getter
private final int z; private final int z;
private final ChunkProxy[][][] chunks = new ChunkProxy[16][16][16]; 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[16][16]; private final Biome[][] biomes = new Biome[WORLD_REGION_SIZE][WORLD_REGION_SIZE];
@Getter@Setter @Getter
private transient World world; private final transient World world;
@Autowired @Autowired
private ChunkLoader chunkLoader; 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) { 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)); 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]; Chunk chunk = chunks[x][y][z];
if (chunk == null) { 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); chunks[x][y][z] = new ChunkProxy(chunk);
} }
return chunk; return chunk;
@@ -60,4 +70,30 @@ public class RegionImpl implements Region{
} }
biomes[x][z] = biome; biomes[x][z] = biome;
} }
@Override
public void save(Serializer<Chunk> chunkSerializer, Serializer<Region> 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);
}
}
}
}
}
} }

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="[%d{HH:mm:ss}] [%-5p] %m%n"/>
</Console>
<RollingFile name="File" fileName="log/log_file.log" filePattern="log/log_file-%d{MM-dd-yyyy}.log.gz">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n"/>
<TimeBasedTriggeringPolicy />
</RollingFile>
</Appenders>
<Loggers>
<Root level="Trace">
<AppenderRef ref="Console"/>
<AppenderRef ref="File"/>
</Root>
</Loggers>
</Configuration>