Let's not serialize entire Zone objects to deserialize them as POJOs

This commit is contained in:
kuroppoi 2022-07-20 19:27:09 +02:00
parent bf485a6983
commit 5ce226813f
4 changed files with 60 additions and 40 deletions

View file

@ -79,6 +79,7 @@ public class Zone {
this(documentId, config.getName(), config.getBiome(), config.getWidth(), config.getHeight());
surface = data.getSurface();
sunlight = data.getSunlight();
pendingSunlight.addAll(data.getPendingSunlight());
chunksExplored = data.getChunksExplored();
}
@ -764,6 +765,10 @@ public class Zone {
}
}
public Set<Integer> getPendingSunlight() {
return Collections.unmodifiableSet(pendingSunlight);
}
public void setSunlight(int x, int sunlight) {
if(x < 0 || x >= width) {
return;

View file

@ -12,6 +12,10 @@ public class ZoneConfig {
private final int width;
private final int height;
public ZoneConfig(Zone zone) {
this(zone.getName(), zone.getBiome(), zone.getWidth(), zone.getHeight());
}
@ConstructorProperties({"name", "biome", "width", "height"})
public ZoneConfig(String name, Biome biome, int width, int height) {
this.name = name;

View file

@ -1,19 +1,24 @@
package brainwine.gameserver.zone;
import java.beans.ConstructorProperties;
import java.util.Collection;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@JsonIgnoreProperties(ignoreUnknown = true)
public class ZoneData {
private int[] surface;
private int[] sunlight;
private int[] pendingSunlight;
private boolean[] chunksExplored;
private final int[] surface;
private final int[] sunlight;
private final Collection<Integer> pendingSunlight;
private final boolean[] chunksExplored;
public ZoneData(Zone zone) {
this(zone.getSurface(), zone.getSunlight(), zone.getPendingSunlight(), zone.getChunksExplored());
}
@ConstructorProperties({"surface", "sunlight", "pending_sunlight", "chunks_explored"})
public ZoneData(int[] surface, int[] sunlight, int[] pendingSunlight, boolean[] chunksExplored) {
public ZoneData(int[] surface, int[] sunlight, Collection<Integer> pendingSunlight, boolean[] chunksExplored) {
this.surface = surface;
this.sunlight = sunlight;
this.pendingSunlight = pendingSunlight;
@ -28,7 +33,7 @@ public class ZoneData {
return sunlight;
}
public int[] getPendingSunlight() {
public Collection<Integer> getPendingSunlight() {
return pendingSunlight;
}

View file

@ -1,6 +1,7 @@
package brainwine.gameserver.zone;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collection;
@ -10,6 +11,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import java.util.zip.DataFormatException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -66,40 +68,14 @@ public class ZoneManager {
private void loadZone(File file) {
String id = file.getName();
File dataFile = new File(file, "zone.dat");
File shapeFile = new File(file, "shape.cmp");
File legacyDataFile = new File(file, "shape.cmp");
try {
ZoneData data = null;
if(shapeFile.exists() && !dataFile.exists()) {
MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(ZipUtils.inflateBytes(Files.readAllBytes(shapeFile.toPath())));
int[] surface = new int[unpacker.unpackArrayHeader()];
for(int i = 0; i < surface.length; i++) {
surface[i] = unpacker.unpackInt();
}
int[] sunlight = new int[unpacker.unpackArrayHeader()];
for(int i = 0; i < sunlight.length; i++) {
sunlight[i] = unpacker.unpackInt();
}
int[] pendingSunlight = new int[unpacker.unpackArrayHeader()];
for(int i = 0; i < pendingSunlight.length; i++) {
pendingSunlight[i] = unpacker.unpackInt();
}
boolean[] chunksExplored = new boolean[unpacker.unpackArrayHeader()];
for(int i = 0; i < pendingSunlight.length; i++) {
chunksExplored[i] = unpacker.unpackBoolean();
}
data = new ZoneData(surface, sunlight, pendingSunlight, chunksExplored);
mapper.writeValue(dataFile, data);
shapeFile.delete();
if(legacyDataFile.exists() && !dataFile.exists()) {
data = convertLegacyDataFile(legacyDataFile, dataFile);
legacyDataFile.delete();
} else {
data = mapper.readValue(ZipUtils.inflateBytes(Files.readAllBytes(dataFile.toPath())), ZoneData.class);
}
@ -113,6 +89,38 @@ public class ZoneManager {
}
}
private ZoneData convertLegacyDataFile(File legacyFile, File outputFile) throws IOException, DataFormatException {
MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(ZipUtils.inflateBytes(Files.readAllBytes(legacyFile.toPath())));
int[] surface = new int[unpacker.unpackArrayHeader()];
for(int i = 0; i < surface.length; i++) {
surface[i] = unpacker.unpackInt();
}
int[] sunlight = new int[unpacker.unpackArrayHeader()];
for(int i = 0; i < sunlight.length; i++) {
sunlight[i] = unpacker.unpackInt();
}
List<Integer> pendingSunlight = new ArrayList<>();
int pendingSunlightSize = unpacker.unpackArrayHeader();
for(int i = 0; i < pendingSunlightSize; i++) {
pendingSunlight.add(unpacker.unpackInt());
}
boolean[] chunksExplored = new boolean[unpacker.unpackArrayHeader()];
for(int i = 0; i < chunksExplored.length; i++) {
chunksExplored[i] = unpacker.unpackBoolean();
}
ZoneData data = new ZoneData(surface, sunlight, pendingSunlight, chunksExplored);
mapper.writeValue(outputFile, data);
return data;
}
public void saveZones() {
for(Zone zone : getZones()) {
saveZone(zone);
@ -125,11 +133,9 @@ public class ZoneManager {
try {
zone.saveChunks();
ZoneConfig config = JsonHelper.readValue(zone, ZoneConfig.class);
ZoneData data = JsonHelper.readValue(zone, ZoneData.class);
JsonHelper.writeValue(new File(file, "metablocks.json"), zone.getMetaBlocks());
JsonHelper.writeValue(new File(file, "config.json"), config);
Files.write(new File(file, "zone.dat").toPath(), ZipUtils.deflateBytes(mapper.writeValueAsBytes(data)));
JsonHelper.writeValue(new File(file, "config.json"), new ZoneConfig(zone));
Files.write(new File(file, "zone.dat").toPath(), ZipUtils.deflateBytes(mapper.writeValueAsBytes(new ZoneData(zone))));
} catch(Exception e) {
logger.error("Zone save failure. id: {}", zone.getDocumentId(), e);
}