Archived
0

Serialization/Deserialization of world

This commit is contained in:
Forwolk
2018-08-02 10:34:55 +03:00
parent 7115da905b
commit aa44d70897
13 changed files with 174 additions and 97 deletions

View File

@@ -1,16 +1,15 @@
package mc.world.generated_world.chunk;
import lombok.extern.slf4j.Slf4j;
import mc.core.serialization.Deserializer;
import mc.core.serialization.Serializer;
import mc.core.world.*;
import mc.world.generated_world.serialization.ChunkReader;
import mc.world.generated_world.serialization.RegionReaderWriter;
import org.springframework.beans.factory.annotation.Autowired;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.MessageFormat;
import java.util.Optional;
@@ -23,15 +22,12 @@ public class InMemoryCacheChunkLoader implements ChunkLoader {
private File worldFolder;
@Autowired
private WorldGenerator worldGenerator;
@Autowired
private Deserializer<Chunk> chunkDeserializer;
private ChunkReader chunkReader;
@Autowired
private Serializer<Chunk> chunkSerializer;
@Autowired
private Serializer<Region> regionSerializer;
@Autowired
private Deserializer<Region> regionDeserializer;
private RegionReaderWriter regionReaderWritter;
public InMemoryCacheChunkLoader(World world) {
this.world = world;
@@ -54,8 +50,8 @@ public class InMemoryCacheChunkLoader implements ChunkLoader {
return Optional.empty();
} else {
try {
byte[] bytes = Files.readAllBytes(Paths.get(file.toURI()));
return Optional.of(chunkDeserializer.deserialize(bytes));
Chunk chunk = chunkReader.read(world.getRegion(x / WORLD_CHUNK_SIZE, z / WORLD_CHUNK_SIZE), x, y, z);
return Optional.of(chunk);
} catch (IOException e) {
log.error("Error occurred while reading chunk file: " + file.getAbsolutePath(), e);
return Optional.empty();
@@ -65,8 +61,8 @@ public class InMemoryCacheChunkLoader implements ChunkLoader {
@Override
public Chunk loadOrGenerateChunk(int x, int y, int z) {
int regX = x / WORLD_REGION_SIZE;
int regZ = z / WORLD_REGION_SIZE;
int regX = x / WORLD_CHUNK_SIZE;
int regZ = z / WORLD_CHUNK_SIZE;
File regionFile = new File(worldFolder, MessageFormat.format(REGION_FILE_NAME_TEMPLATE, regX, regZ));
Region region;
Chunk chunk;
@@ -74,32 +70,22 @@ public class InMemoryCacheChunkLoader implements ChunkLoader {
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);
try {
regionReaderWritter.write(region);
} 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);
region = regionReaderWritter.read(regX, regZ, world);
chunk = chunkReader.read(region, x, y, z);
} 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;
}

View File

@@ -24,7 +24,7 @@ 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 ChunkSerializerDeserializer(), new RegionSerializerDeserializer());
//region.save(new ChunkSerializer(), new RegionSerializerDeserializer());
worldGenerator.generateRegion(1, 0, world);
worldGenerator.generateRegion(-1, 0, world);
worldGenerator.generateRegion(0, 1, world);

View File

@@ -3,6 +3,7 @@ package mc.world.generated_world.region;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import mc.core.serialization.IRegionReaderWriter;
import mc.core.serialization.Serializer;
import mc.core.world.*;
import mc.world.generated_world.chunk.InMemoryCacheChunkLoader;
@@ -72,18 +73,14 @@ public class RegionImpl implements Region{
}
@Override
public void save(Serializer<Chunk> chunkSerializer, Serializer<Region> regionSerializer) throws IOException {
public void save(Serializer<Chunk> chunkSerializer, IRegionReaderWriter regionReaderWriter) 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);
}
regionReaderWriter.write(this);
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++) {

View File

@@ -0,0 +1,49 @@
package mc.world.generated_world.serialization;
import mc.core.Location;
import mc.core.block.Block;
import mc.core.serialization.Deserializer;
import mc.core.serialization.IChunkReader;
import mc.core.world.Chunk;
import mc.core.world.Region;
import mc.world.generated_world.chunk.ChunkImpl;
import org.springframework.beans.factory.annotation.Autowired;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.MessageFormat;
import static mc.world.generated_world.WorldConstants.*;
public class ChunkReader implements IChunkReader{
private final File worldFolder;
@Autowired
private Deserializer<Block> blockDeserializer;
public ChunkReader (File worldFolder) {
this.worldFolder = worldFolder;
}
@Override
public Chunk read (Region region, int x, int y, int z) throws IOException {
x %= WORLD_REGION_SIZE;
y %= WORLD_REGION_SIZE;
z %= WORLD_REGION_SIZE;
File chunkFile = new File(new File(worldFolder, MessageFormat.format(REGION_FILE_NAME_TEMPLATE, region.getX(), region.getZ())), MessageFormat.format(CHUNK_FILE_NAME_TEMPLATE, x, y, z));
byte[] chunkBytes = Files.readAllBytes(Paths.get(chunkFile.toURI()));
int blocks = (chunkBytes.length) / 3;
Chunk chunk = new ChunkImpl(x, y, z, region);
for (int i = 0; i < blocks; i ++) {
byte[] blockBytes = new byte[3];
blockBytes[0] = chunkBytes[3 * i];
blockBytes[1] = chunkBytes[1 + 3 * i];
blockBytes[2] = chunkBytes[2 + 3 * i];
Block block = blockDeserializer.deserialize(blockBytes);
Location blockLocation = block.getLocation();
chunk.setBlock(blockLocation.getBlockX(), blockLocation.getBlockY(), blockLocation.getBlockZ(), block);
}
return chunk;
}
}

View File

@@ -0,0 +1,26 @@
package mc.world.generated_world.serialization;
import mc.core.block.Block;
import mc.core.serialization.Serializer;
import mc.core.world.Chunk;
import org.springframework.beans.factory.annotation.Autowired;
public class ChunkSerializer implements Serializer<Chunk> {
@Autowired
private Serializer<Block> blockSerializer;
@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];
}
}
return bytes;
}
}

View File

@@ -1,40 +0,0 @@
package mc.world.generated_world.serialization;
import mc.core.block.Block;
import mc.core.block.BlockFactory;
import mc.core.serialization.Deserializer;
import mc.core.serialization.Serializer;
import mc.core.world.Chunk;
public class ChunkSerializerDeserializer implements Serializer<Chunk>, Deserializer<Chunk> {
private Serializer<Block> blockSerializer;
private Deserializer<Block> blockDeserializer;
@Override
public Chunk deserialize(byte[] bytes) {
return null;
}
@Override
public byte[] serialize(Chunk chunk) {
Serializer<Block> 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

@@ -0,0 +1,53 @@
package mc.world.generated_world.serialization;
import mc.core.serialization.IRegionReaderWriter;
import mc.core.world.Biome;
import mc.core.world.Region;
import mc.core.world.World;
import mc.world.generated_world.region.RegionImpl;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.MessageFormat;
import static mc.world.generated_world.WorldConstants.*;
public class RegionReaderWriter implements IRegionReaderWriter {
private final File worldFolder;
public RegionReaderWriter(File worldFolder) {
this.worldFolder = worldFolder;
}
@Override
public Region read (int x, int z, World world) throws IOException{
File regionFolder = new File(worldFolder, MessageFormat.format(REGION_FILE_NAME_TEMPLATE, x, z));
File biomesFile = new File(regionFolder, BIOME_FILE_NAME_TEMPLATE);
byte[] biomesBytes = Files.readAllBytes(Paths.get(biomesFile.toURI()));
Region region = new RegionImpl(x, z, world);
for (int tx = 0; tx < WORLD_REGION_SIZE; tx ++) {
for (int tz = 0; tz < WORLD_REGION_SIZE; tz ++) {
region.setBiome(tx, tz, Biome.getById(biomesBytes[tx * WORLD_REGION_SIZE + tz]));
}
}
return region;
}
@Override
public void write (Region region) throws IOException{
File regionFolder = new File(worldFolder, MessageFormat.format(REGION_FILE_NAME_TEMPLATE, region.getX(), region.getZ()));
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 ++) {
for (int z = 0; z < WORLD_REGION_SIZE; z ++) {
biomesBytes[x * WORLD_REGION_SIZE + z] = (byte) region.getBiomeAt(x, z).getId();
}
}
try (FileOutputStream fos = new FileOutputStream(biomesFile)) {
fos.write(biomesBytes);
}
}
}

View File

@@ -1,17 +0,0 @@
package mc.world.generated_world.serialization;
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];
}
}