More compact serialization
This commit is contained in:
@@ -45,7 +45,6 @@ public interface Chunk extends Serializable{
|
|||||||
int getY();
|
int getY();
|
||||||
int getZ();
|
int getZ();
|
||||||
|
|
||||||
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);
|
Block getBlock (int x, int y, int z);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,10 +14,10 @@ import java.io.Serializable;
|
|||||||
* +-------------+----------------+------------+
|
* +-------------+----------------+------------+
|
||||||
* | param | range | bits |
|
* | 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{
|
public interface Region extends Serializable{
|
||||||
|
|||||||
@@ -90,11 +90,6 @@ public class SimpleChunk implements Chunk {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Block[] getModifiedBlocks() {
|
|
||||||
return new Block[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setBlock(int x, int y, int z, Block block) {
|
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.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import mc.core.block.Block;
|
import mc.core.block.Block;
|
||||||
|
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;
|
||||||
import mc.core.world.Region;
|
import mc.core.world.Region;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static mc.world.generated_world.WorldConstants.WORLD_CHUNK_SIZE;
|
import static mc.world.generated_world.WorldConstants.WORLD_CHUNK_SIZE;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@@ -21,7 +19,6 @@ public class ChunkImpl implements Chunk{
|
|||||||
@Getter
|
@Getter
|
||||||
private final int z;
|
private final int z;
|
||||||
private final Block[][][] blocks = new Block[WORLD_CHUNK_SIZE][WORLD_CHUNK_SIZE][WORLD_CHUNK_SIZE];
|
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;
|
private final transient Region region;
|
||||||
|
|
||||||
@Override
|
@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);
|
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
|
@Override
|
||||||
public void setBlock(int x, int y, int z, Block block) {
|
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;
|
blocks[x][y][z] = block;
|
||||||
modifiedBlocks.add(block);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -118,12 +118,6 @@ public class ChunkProxy implements Chunk {
|
|||||||
return chunk.getZ();
|
return chunk.getZ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Block[] getModifiedBlocks() {
|
|
||||||
use();
|
|
||||||
return chunk.getModifiedBlocks();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setBlock(int x, int y, int z, Block block) {
|
public void setBlock(int x, int y, int z, Block block) {
|
||||||
use();
|
use();
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import mc.core.block.BlockFactory;
|
|||||||
import mc.core.block.BlockType;
|
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.serialization.ChunkSerializer;
|
||||||
|
import mc.world.generated_world.serialization.RegionReaderWriter;
|
||||||
import mc.world.generated_world.world.CubicWorld;
|
import mc.world.generated_world.world.CubicWorld;
|
||||||
import mc.world.generated_world.world.Temperature;
|
import mc.world.generated_world.world.Temperature;
|
||||||
import mc.world.generated_world.world.Wetness;
|
import mc.world.generated_world.world.Wetness;
|
||||||
@@ -24,8 +26,8 @@ public class SeedBasedWorldGenerator implements WorldGenerator {
|
|||||||
WorldGenerator worldGenerator = new SeedBasedWorldGenerator();
|
WorldGenerator worldGenerator = new SeedBasedWorldGenerator();
|
||||||
World world = new CubicWorld(UUID.fromString("00000000-0000-0000-C000-000000000046"), 2626949);
|
World world = new CubicWorld(UUID.fromString("00000000-0000-0000-C000-000000000046"), 2626949);
|
||||||
Region region = worldGenerator.generateRegion(0, 0, world);
|
Region region = worldGenerator.generateRegion(0, 0, world);
|
||||||
//region.save(new ChunkSerializer(), new RegionSerializerDeserializer());
|
region.save(new ChunkSerializer(), new RegionReaderWriter(new File("worlds", world.getWorldId().toString())));
|
||||||
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);
|
||||||
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));
|
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
|
@Override
|
||||||
|
|||||||
@@ -84,10 +84,13 @@ public class RegionImpl implements Region{
|
|||||||
for (int x = 0; x < WORLD_CHUNK_SIZE; x ++) {
|
for (int x = 0; x < WORLD_CHUNK_SIZE; x ++) {
|
||||||
for (int z = 0; z < WORLD_CHUNK_SIZE; z ++) {
|
for (int z = 0; z < WORLD_CHUNK_SIZE; z ++) {
|
||||||
for (int y = 0; y < WORLD_CHUNK_SIZE; y++) {
|
for (int y = 0; y < WORLD_CHUNK_SIZE; y++) {
|
||||||
File chunkFile = new File(regionFile, MessageFormat.format(CHUNK_FILE_NAME_TEMPLATE, x, y, z));
|
Chunk chunk = this.getChunkAt(x, y, z);
|
||||||
byte[] chunkBytes = chunkSerializer.serialize(this.getChunkAt(x, y, z));
|
byte[] chunkBytes = chunkSerializer.serialize(chunk);
|
||||||
try (FileOutputStream fileOutputStream = new FileOutputStream(chunkFile)){
|
if (chunkBytes.length > 0) {
|
||||||
fileOutputStream.write(chunkBytes);
|
File chunkFile = new File(regionFile, MessageFormat.format(CHUNK_FILE_NAME_TEMPLATE, x, y, z));
|
||||||
|
try (FileOutputStream fileOutputStream = new FileOutputStream(chunkFile)) {
|
||||||
|
fileOutputStream.write(chunkBytes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,19 @@
|
|||||||
package mc.world.generated_world.serialization;
|
package mc.world.generated_world.serialization;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import mc.core.block.Block;
|
import mc.core.block.Block;
|
||||||
|
import mc.core.block.BlockFactory;
|
||||||
|
import mc.core.block.BlockType;
|
||||||
import mc.core.serialization.Serializer;
|
import mc.core.serialization.Serializer;
|
||||||
import mc.core.world.Chunk;
|
import mc.core.world.Chunk;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
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> {
|
public class ChunkSerializer implements Serializer<Chunk> {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@@ -12,15 +21,23 @@ public class ChunkSerializer implements Serializer<Chunk> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] serialize(Chunk chunk) {
|
public byte[] serialize(Chunk chunk) {
|
||||||
int blocks = chunk.getModifiedBlocks().length;
|
Serializer<Block> blockSerializer = new BlockSerializerDeserializer(new BlockFactory(), chunk);
|
||||||
byte[] bytes = new byte[3 * blocks];
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
Block current;
|
||||||
for (int i = 0; i < blocks; i ++) {
|
for (int x = 0; x < WORLD_CHUNK_SIZE; x ++) {
|
||||||
byte[] blockSerialized = blockSerializer.serialize(chunk.getModifiedBlocks()[i]);
|
for (int y = 0; y < WORLD_CHUNK_SIZE; y ++) {
|
||||||
for (int j = 0; j < 3; j ++) {
|
for (int z = 0; z < WORLD_CHUNK_SIZE; z ++) {
|
||||||
bytes[i * 3 + j] = blockSerialized[j];
|
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
|
@Override
|
||||||
public void write (Region region) throws IOException{
|
public void write (Region region) throws IOException{
|
||||||
File regionFolder = new File(worldFolder, MessageFormat.format(REGION_FILE_NAME_TEMPLATE, region.getX(), region.getZ()));
|
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);
|
File biomesFile = new File(regionFolder, BIOME_FILE_NAME_TEMPLATE);
|
||||||
byte[] biomesBytes = new byte[WORLD_REGION_SIZE * WORLD_REGION_SIZE];
|
byte[] biomesBytes = new byte[WORLD_REGION_SIZE * WORLD_REGION_SIZE];
|
||||||
for (int x = 0; x < WORLD_REGION_SIZE; x ++) {
|
for (int x = 0; x < WORLD_REGION_SIZE; x ++) {
|
||||||
|
|||||||
Reference in New Issue
Block a user