forked from SteamWar/SteamWar
Improved trace serialisation through versioning
This commit is contained in:
@@ -99,7 +99,25 @@ public class TNTPoint implements Externalizable {
|
||||
/**
|
||||
* Constructor for deserialization only !! Do not Call !!
|
||||
*/
|
||||
public TNTPoint() {
|
||||
protected TNTPoint(int tntId, boolean explosion,
|
||||
boolean inWater,
|
||||
boolean afterFirstExplosion,
|
||||
boolean destroyedBuildArea,
|
||||
boolean destroyedTestBlock,
|
||||
long ticksSinceStart,
|
||||
int fuse,
|
||||
Location location,
|
||||
Vector velocity) {
|
||||
this.tntId = tntId;
|
||||
this.explosion = explosion;
|
||||
this.inWater = inWater;
|
||||
this.afterFirstExplosion = afterFirstExplosion;
|
||||
this.destroyedBuildArea = destroyedBuildArea;
|
||||
this.destroyedTestBlock = destroyedTestBlock;
|
||||
this.ticksSinceStart = ticksSinceStart;
|
||||
this.fuse = fuse;
|
||||
this.location = location;
|
||||
this.velocity = velocity;
|
||||
}
|
||||
|
||||
public TNTPoint(int tntId, TNTPrimed tnt, boolean explosion, boolean afterFirstExplosion, long ticksSinceStart,
|
||||
|
||||
@@ -26,20 +26,15 @@ import de.steamwar.bausystem.features.tracer.rendering.ViewFlag;
|
||||
import de.steamwar.bausystem.region.Region;
|
||||
import de.steamwar.entity.REntity;
|
||||
import de.steamwar.entity.REntityServer;
|
||||
import lombok.Cleanup;
|
||||
import lombok.Getter;
|
||||
import lombok.SneakyThrows;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.File;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
public class Trace {
|
||||
/**
|
||||
@@ -77,6 +72,9 @@ public class Trace {
|
||||
*/
|
||||
private SoftReference<List<TNTPoint>> records;
|
||||
|
||||
@Getter
|
||||
private final int recordsCount;
|
||||
|
||||
/**
|
||||
* A map of all REntityServers rendering this trace
|
||||
*/
|
||||
@@ -91,46 +89,26 @@ public class Trace {
|
||||
@SneakyThrows
|
||||
public Trace(Region region, List<TNTPoint> recordList) {
|
||||
this.uuid = UUID.randomUUID();
|
||||
recordsSaveFile = new File(TraceManager.tracesFolder, uuid + ".records");
|
||||
this.region = region;
|
||||
this.date = new Date();
|
||||
recordsCount = recordList.size();
|
||||
records = new SoftReference<>(recordList);
|
||||
recordsSaveFile = new File(TraceManager.tracesFolder, uuid + ".records");
|
||||
metadataSaveFile = new File(TraceManager.tracesFolder, uuid + ".meta");
|
||||
|
||||
@Cleanup
|
||||
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(metadataSaveFile));
|
||||
outputStream.writeUTF(uuid.toString());
|
||||
outputStream.writeUTF(region.getName());
|
||||
outputStream.writeObject(date);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for serialising a trace from the file system
|
||||
*
|
||||
* @param metadataSaveFile the file for this traces metadata
|
||||
* Constructor for deserialising a trace from the file system
|
||||
*/
|
||||
@SneakyThrows
|
||||
public Trace(File metadataSaveFile) {
|
||||
String uuid = null;
|
||||
Region region = null;
|
||||
Date date = null;
|
||||
|
||||
this.metadataSaveFile = metadataSaveFile;
|
||||
|
||||
try {
|
||||
@Cleanup
|
||||
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(metadataSaveFile));
|
||||
uuid = inputStream.readUTF();
|
||||
region = Region.getREGION_MAP().get(inputStream.readUTF());
|
||||
date = (Date) inputStream.readObject();
|
||||
inputStream.close();
|
||||
} finally {
|
||||
this.uuid = UUID.fromString(uuid);
|
||||
this.region = region;
|
||||
this.date = date;
|
||||
recordsSaveFile = new File(TraceManager.tracesFolder, uuid + ".records");
|
||||
this.records = new SoftReference<>(null);
|
||||
}
|
||||
protected Trace(UUID uuid, Region region, Date date, File metadataFile, File recordsFile, int recordsCount) {
|
||||
this.metadataSaveFile = metadataFile;
|
||||
recordsSaveFile = recordsFile;
|
||||
this.uuid = uuid;
|
||||
this.region = region;
|
||||
this.date = date;
|
||||
this.records = new SoftReference<>(null);
|
||||
this.recordsCount = recordsCount;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -173,7 +151,8 @@ public class Trace {
|
||||
entityServer = new REntityServer();
|
||||
entityServer.addPlayer(player);
|
||||
entityServer.setCallback((p, rEntity, entityAction) -> {
|
||||
if (entityAction != REntityServer.EntityAction.INTERACT) return;
|
||||
if (entityAction != REntityServer.EntityAction.INTERACT)
|
||||
return;
|
||||
if (rEntity instanceof TraceEntity) {
|
||||
((TraceEntity) rEntity).printIntoChat(p);
|
||||
}
|
||||
@@ -195,7 +174,8 @@ public class Trace {
|
||||
REntityServer newEntityServer = new REntityServer();
|
||||
newEntityServer.addPlayer(k);
|
||||
newEntityServer.setCallback((p, rEntity, entityAction) -> {
|
||||
if (entityAction != REntityServer.EntityAction.INTERACT) return;
|
||||
if (entityAction != REntityServer.EntityAction.INTERACT)
|
||||
return;
|
||||
if (rEntity instanceof TraceEntity) {
|
||||
((TraceEntity) rEntity).printIntoChat(p);
|
||||
}
|
||||
@@ -234,7 +214,8 @@ public class Trace {
|
||||
List<TraceEntity> entities = new LinkedList<>();
|
||||
|
||||
for (List<TNTPoint> bundle : bundles) {
|
||||
entities.add(new TraceEntity(entityServer, bundle.get(0).getLocation(), bundle.get(0).isExplosion(), bundle, this));
|
||||
entities.add(new TraceEntity(entityServer, bundle.get(0).getLocation(), bundle.get(0).isExplosion(), bundle,
|
||||
this));
|
||||
}
|
||||
|
||||
// Apply modifiers
|
||||
@@ -312,38 +293,7 @@ public class Trace {
|
||||
* Loads the records of this trace from storage to memory
|
||||
*/
|
||||
private void loadRecords() {
|
||||
List<TNTPoint> records = new ArrayList<>();
|
||||
long readBytes = 0;
|
||||
try {
|
||||
FileInputStream fileInputStream = new FileInputStream(recordsSaveFile);
|
||||
|
||||
@Cleanup
|
||||
ObjectInputStream inputStream = new ObjectInputStream(new GZIPInputStream(fileInputStream));
|
||||
long fileLenght = recordsSaveFile.length();
|
||||
while (fileInputStream.getChannel().position() < fileLenght) {
|
||||
records.add((TNTPoint) inputStream.readObject());
|
||||
readBytes = fileInputStream.getChannel().position();
|
||||
}
|
||||
} catch (EOFException e) {
|
||||
Logger logger = Bukkit.getLogger();
|
||||
logger.log(Level.WARNING, "EOF in trace read detected in " + uuid);
|
||||
logger.log(Level.WARNING, "Read " + readBytes + "/" + recordsSaveFile.length() + " Bytes");
|
||||
logger.log(Level.WARNING, "Read so far: " + records);
|
||||
|
||||
e.printStackTrace();
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
Map<Integer, List<TNTPoint>> histories = new HashMap<>();
|
||||
for (TNTPoint record : records) {
|
||||
int tntId = record.getTntId();
|
||||
List<TNTPoint> history = histories.computeIfAbsent(tntId, id -> new ArrayList<>());
|
||||
history.add(record);
|
||||
record.setHistory(history);
|
||||
}
|
||||
|
||||
this.records = new SoftReference<>(records);
|
||||
records = new SoftReference<>(TraceRepository.readTraceRecords(this));
|
||||
}
|
||||
|
||||
public synchronized List<TNTPoint> getRecords() {
|
||||
|
||||
+1
-1
@@ -58,7 +58,7 @@ public class TraceManager implements Listener {
|
||||
if (traceFile.getName().contains(".records"))
|
||||
continue;
|
||||
|
||||
add(new Trace(traceFile));
|
||||
add(TraceRepository.readTrace(traceFile));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-22
@@ -24,28 +24,21 @@ import de.steamwar.bausystem.region.Region;
|
||||
import lombok.Getter;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
public class TraceRecordingWrapper {
|
||||
|
||||
private final Trace trace;
|
||||
|
||||
@Getter
|
||||
private final long startTick;
|
||||
private final List<TNTPoint> recordsToAdd;
|
||||
private final List<TNTPoint> recordList;
|
||||
private final ObjectOutputStream recordsOutputStream;
|
||||
private int nextOpenRecordId = 0;
|
||||
@Getter
|
||||
private boolean explosionRecorded = false;
|
||||
|
||||
@Getter
|
||||
private final Trace trace;
|
||||
|
||||
@SneakyThrows
|
||||
public TraceRecordingWrapper(Region region) {
|
||||
startTick = TPSUtils.currentRealTick.get();
|
||||
@@ -53,8 +46,6 @@ public class TraceRecordingWrapper {
|
||||
recordList = new ArrayList<>();
|
||||
|
||||
trace = new Trace(region, recordList);
|
||||
File recordsSaveFile = new File(TraceManager.tracesFolder, trace.getUuid() + ".records");
|
||||
recordsOutputStream = new ObjectOutputStream(new GZIPOutputStream(new FileOutputStream(recordsSaveFile)));
|
||||
}
|
||||
|
||||
public int getNextOpenRecordIdAndIncrement() {
|
||||
@@ -72,23 +63,13 @@ public class TraceRecordingWrapper {
|
||||
public void commitRecorded() {
|
||||
TraceManager.instance.showPartial(trace, recordsToAdd);
|
||||
|
||||
recordsToAdd.forEach(record -> {
|
||||
try {
|
||||
recordsOutputStream.writeObject(record);
|
||||
recordsOutputStream.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
|
||||
recordList.addAll(recordsToAdd);
|
||||
recordsToAdd.clear();
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
protected void finalizeRecording() {
|
||||
recordsOutputStream.flush();
|
||||
recordsOutputStream.close();
|
||||
TraceRepository.writeTrace(trace, recordList);
|
||||
TraceManager.instance.add(trace);
|
||||
}
|
||||
}
|
||||
|
||||
+41
-5
@@ -7,10 +7,7 @@ import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
@@ -37,7 +34,7 @@ public class TraceRepository {
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
protected static Trace readTrace(File metadataFile) {
|
||||
public static Trace readTrace(File metadataFile) {
|
||||
@Cleanup
|
||||
ObjectInputStream reader = new ObjectInputStream(new FileInputStream(metadataFile));
|
||||
UUID uuid = UUID.fromString(reader.readUTF());
|
||||
@@ -49,6 +46,43 @@ public class TraceRepository {
|
||||
return new Trace(uuid, region, date, metadataFile, recordsFile, recordsCount);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
protected static void writeTrace(Trace trace, List<TNTPoint> records) {
|
||||
@Cleanup
|
||||
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(trace.getMetadataSaveFile()));
|
||||
outputStream.writeUTF(trace.getUuid().toString());
|
||||
outputStream.writeUTF(trace.getRegion().getName());
|
||||
outputStream.writeObject(trace.getDate());
|
||||
outputStream.writeInt(SERIALISATION_VERSION);
|
||||
outputStream.writeInt(records.size());
|
||||
|
||||
|
||||
writeTraceRecords(trace.getRecordsSaveFile(), records);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
protected static void writeTraceRecords(File recordsFile, List<TNTPoint> records) {
|
||||
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(recordsFile));
|
||||
for (TNTPoint record : records) {
|
||||
outputStream.writeInt(record.getTntId());
|
||||
outputStream.writeBoolean(record.isExplosion());
|
||||
outputStream.writeBoolean(record.isInWater());
|
||||
outputStream.writeBoolean(record.isAfterFirstExplosion());
|
||||
outputStream.writeBoolean(record.isDestroyedBuildArea());
|
||||
outputStream.writeBoolean(record.isDestroyedTestBlock());
|
||||
outputStream.writeLong(record.getTicksSinceStart());
|
||||
outputStream.writeInt(record.getFuse());
|
||||
Location location = record.getLocation();
|
||||
outputStream.writeDouble(location.getX());
|
||||
outputStream.writeDouble(location.getY());
|
||||
outputStream.writeDouble(location.getZ());
|
||||
Vector velocity = record.getVelocity();
|
||||
outputStream.writeDouble(velocity.getX());
|
||||
outputStream.writeDouble(velocity.getY());
|
||||
outputStream.writeDouble(velocity.getZ());
|
||||
}
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
protected static TNTPoint readTraceRecord(ObjectInputStream objectInput) {
|
||||
|
||||
@@ -60,10 +94,12 @@ public class TraceRepository {
|
||||
boolean destroyedTestBlock = objectInput.readBoolean();
|
||||
long ticksSinceStart = objectInput.readLong();
|
||||
int fuse = objectInput.readInt();
|
||||
|
||||
double locX = objectInput.readDouble();
|
||||
double locY = objectInput.readDouble();
|
||||
double locZ = objectInput.readDouble();
|
||||
Location location = new Location(Bukkit.getWorlds().get(0), locX, locY, locZ);
|
||||
|
||||
double velX = objectInput.readDouble();
|
||||
double velY = objectInput.readDouble();
|
||||
double velZ = objectInput.readDouble();
|
||||
|
||||
Reference in New Issue
Block a user