More compact serialization
This commit is contained in:
@@ -45,7 +45,6 @@ public interface Chunk extends Serializable{
|
||||
int getY();
|
||||
int getZ();
|
||||
|
||||
Block[] getModifiedBlocks();
|
||||
void setBlock (int x, int y, int z, Block block);
|
||||
Block getBlock (int x, int y, int z);
|
||||
}
|
||||
|
||||
@@ -14,10 +14,10 @@ import java.io.Serializable;
|
||||
* +-------------+----------------+------------+
|
||||
* | param | range | bits |
|
||||
* +-------------+----------------+------------+
|
||||
* | biome_map | 256x256 0-32 | 2097152 |
|
||||
* | biome_map | 256x256 0-128 | 524288 |
|
||||
* +-------------+----------------+------------+
|
||||
*
|
||||
* Total: 2097152 bits (256 Kb)
|
||||
* Total: 524288 bits (64 Kb)
|
||||
*
|
||||
*/
|
||||
public interface Region extends Serializable{
|
||||
|
||||
@@ -90,11 +90,6 @@ public class SimpleChunk implements Chunk {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block[] getModifiedBlocks() {
|
||||
return new Block[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlock(int x, int y, int z, Block block) {
|
||||
|
||||
|
||||
@@ -3,13 +3,11 @@ package mc.world.generated_world.chunk;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import mc.core.block.Block;
|
||||
import mc.core.block.BlockType;
|
||||
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
|
||||
@@ -21,7 +19,6 @@ public class ChunkImpl implements Chunk{
|
||||
@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
|
||||
@@ -84,15 +81,12 @@ public class ChunkImpl implements Chunk{
|
||||
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) {
|
||||
if (block.getBlockType() == BlockType.AIR) {
|
||||
blocks[x][y][z] = null;
|
||||
}
|
||||
blocks[x][y][z] = block;
|
||||
modifiedBlocks.add(block);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -118,12 +118,6 @@ public class ChunkProxy implements Chunk {
|
||||
return chunk.getZ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block[] getModifiedBlocks() {
|
||||
use();
|
||||
return chunk.getModifiedBlocks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlock(int x, int y, int z, Block block) {
|
||||
use();
|
||||
|
||||
@@ -6,6 +6,8 @@ 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.serialization.ChunkSerializer;
|
||||
import mc.world.generated_world.serialization.RegionReaderWriter;
|
||||
import mc.world.generated_world.world.CubicWorld;
|
||||
import mc.world.generated_world.world.Temperature;
|
||||
import mc.world.generated_world.world.Wetness;
|
||||
@@ -24,8 +26,8 @@ public class SeedBasedWorldGenerator implements WorldGenerator {
|
||||
WorldGenerator worldGenerator = new SeedBasedWorldGenerator();
|
||||
World world = new CubicWorld(UUID.fromString("00000000-0000-0000-C000-000000000046"), 2626949);
|
||||
Region region = worldGenerator.generateRegion(0, 0, world);
|
||||
//region.save(new ChunkSerializer(), new RegionSerializerDeserializer());
|
||||
worldGenerator.generateRegion(1, 0, world);
|
||||
region.save(new ChunkSerializer(), new RegionReaderWriter(new File("worlds", world.getWorldId().toString())));
|
||||
/*worldGenerator.generateRegion(1, 0, world);
|
||||
worldGenerator.generateRegion(-1, 0, world);
|
||||
worldGenerator.generateRegion(0, 1, world);
|
||||
worldGenerator.generateRegion(0, -1, world);
|
||||
@@ -127,7 +129,7 @@ public class SeedBasedWorldGenerator implements WorldGenerator {
|
||||
image.setRGB(tx, ty, currentImage.getRGB(x, y));
|
||||
}
|
||||
}
|
||||
ImageIO.write(image, "png", new File("out", "merged.png"));
|
||||
ImageIO.write(image, "png", new File("out", "merged.png"));*/
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -84,8 +84,10 @@ public class RegionImpl implements Region{
|
||||
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++) {
|
||||
Chunk chunk = this.getChunkAt(x, y, z);
|
||||
byte[] chunkBytes = chunkSerializer.serialize(chunk);
|
||||
if (chunkBytes.length > 0) {
|
||||
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);
|
||||
}
|
||||
@@ -94,3 +96,4 @@ public class RegionImpl implements Region{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,19 @@
|
||||
package mc.world.generated_world.serialization;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import mc.core.block.Block;
|
||||
import mc.core.block.BlockFactory;
|
||||
import mc.core.block.BlockType;
|
||||
import mc.core.serialization.Serializer;
|
||||
import mc.core.world.Chunk;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import static mc.world.generated_world.WorldConstants.WORLD_CHUNK_SIZE;
|
||||
|
||||
@Slf4j
|
||||
public class ChunkSerializer implements Serializer<Chunk> {
|
||||
|
||||
@Autowired
|
||||
@@ -12,15 +21,23 @@ public class ChunkSerializer implements Serializer<Chunk> {
|
||||
|
||||
@Override
|
||||
public byte[] serialize(Chunk chunk) {
|
||||
int blocks = chunk.getModifiedBlocks().length;
|
||||
byte[] bytes = new byte[3 * blocks];
|
||||
|
||||
for (int i = 0; i < blocks; i ++) {
|
||||
byte[] blockSerialized = blockSerializer.serialize(chunk.getModifiedBlocks()[i]);
|
||||
for (int j = 0; j < 3; j ++) {
|
||||
bytes[i * 3 + j] = blockSerialized[j];
|
||||
Serializer<Block> blockSerializer = new BlockSerializerDeserializer(new BlockFactory(), chunk);
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
Block current;
|
||||
for (int x = 0; x < WORLD_CHUNK_SIZE; x ++) {
|
||||
for (int y = 0; y < WORLD_CHUNK_SIZE; y ++) {
|
||||
for (int z = 0; z < WORLD_CHUNK_SIZE; z ++) {
|
||||
current = chunk.getBlock(x, y, z);
|
||||
if (current != null && current.getBlockType() != BlockType.AIR) {
|
||||
try {
|
||||
baos.write(blockSerializer.serialize(current));
|
||||
} catch (IOException e) {
|
||||
log.error("Error occurred while writing serialized block to byte array", e);
|
||||
}
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
return baos.toByteArray();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,9 @@ public class RegionReaderWriter implements IRegionReaderWriter {
|
||||
@Override
|
||||
public void write (Region region) throws IOException{
|
||||
File regionFolder = new File(worldFolder, MessageFormat.format(REGION_FILE_NAME_TEMPLATE, region.getX(), region.getZ()));
|
||||
if (!regionFolder.exists()) {
|
||||
regionFolder.mkdirs();
|
||||
}
|
||||
File biomesFile = new File(regionFolder, BIOME_FILE_NAME_TEMPLATE);
|
||||
byte[] biomesBytes = new byte[WORLD_REGION_SIZE * WORLD_REGION_SIZE];
|
||||
for (int x = 0; x < WORLD_REGION_SIZE; x ++) {
|
||||
|
||||
Reference in New Issue
Block a user