forked from SteamWar/SteamWar
Update TraceRepository to save quite a bit smaller traces
This commit is contained in:
@@ -50,12 +50,6 @@ public class Trace {
|
||||
@Getter
|
||||
private final File recordsSaveFile;
|
||||
|
||||
/**
|
||||
* File the metadata are saved in
|
||||
*/
|
||||
@Getter
|
||||
private final File metadataSaveFile;
|
||||
|
||||
/**
|
||||
* Region the trace was recorded in
|
||||
*/
|
||||
@@ -75,7 +69,7 @@ public class Trace {
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
private int recordsCount;
|
||||
private int tntIdCount;
|
||||
|
||||
/**
|
||||
* A map of all REntityServers rendering this trace
|
||||
@@ -95,21 +89,19 @@ public class Trace {
|
||||
this.date = new Date();
|
||||
records = new SoftReference<>(recordList);
|
||||
recordsSaveFile = new File(TraceRepository.tracesFolder, uuid + ".records");
|
||||
metadataSaveFile = new File(TraceRepository.tracesFolder, uuid + ".meta");
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for deserialising a trace from the file system
|
||||
*/
|
||||
@SneakyThrows
|
||||
protected Trace(UUID uuid, Region region, Date date, File metadataFile, File recordsFile, int recordsCount) {
|
||||
this.metadataSaveFile = metadataFile;
|
||||
protected Trace(UUID uuid, Region region, Date date, File recordsFile, int tntIdCount) {
|
||||
recordsSaveFile = recordsFile;
|
||||
this.uuid = uuid;
|
||||
this.region = region;
|
||||
this.date = date;
|
||||
this.records = new SoftReference<>(null);
|
||||
this.recordsCount = recordsCount;
|
||||
this.tntIdCount = tntIdCount;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -311,7 +303,7 @@ public class Trace {
|
||||
", region=" + region +
|
||||
", creationTime=" + date +
|
||||
", recordsSaveFile=" + recordsSaveFile.getName() +
|
||||
", recordCount=" + recordsCount +
|
||||
", tntCount=" + tntIdCount +
|
||||
", records=" + getRecords() +
|
||||
'}';
|
||||
}
|
||||
|
||||
+18
-12
@@ -57,19 +57,27 @@ public class TraceManager implements Listener {
|
||||
if (traceFiles == null)
|
||||
return;
|
||||
|
||||
boolean hasMetaFiles = false;
|
||||
for (File traceFile : traceFiles) {
|
||||
if (traceFile.getName().contains(".meta"))
|
||||
continue;
|
||||
|
||||
if (TraceRepository.getVersion(traceFile) == TraceRepository.SERIALISATION_VERSION) {
|
||||
add(TraceRepository.readTrace(traceFile));
|
||||
} else {
|
||||
String uuid = traceFile.getName().replace(".records", "");
|
||||
|
||||
new File(tracesFolder, uuid + ".records").deleteOnExit();
|
||||
new File(tracesFolder, uuid + ".meta").deleteOnExit();
|
||||
if (traceFile.getName().contains(".meta")) {
|
||||
hasMetaFiles = true;
|
||||
}
|
||||
}
|
||||
if (hasMetaFiles) {
|
||||
for (File traceFile : traceFiles) {
|
||||
traceFile.delete();
|
||||
}
|
||||
traceFiles = new File[0];
|
||||
}
|
||||
|
||||
// TODO: Cleanup all traces if a .meta is present!
|
||||
for (File traceFile : traceFiles) {
|
||||
Trace trace = TraceRepository.readTrace(traceFile);
|
||||
if (trace == null) {
|
||||
traceFile.delete();
|
||||
continue;
|
||||
}
|
||||
add(trace);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,7 +160,6 @@ public class TraceManager implements Listener {
|
||||
if (traceId == null) throw new RuntimeException("Trace not found while trying to remove see (c978eb98-b0b2-4009-91d8-acfa34e2831a)");
|
||||
traces.remove(traceId);
|
||||
trace.hide();
|
||||
trace.getMetadataSaveFile().delete();
|
||||
trace.getRecordsSaveFile().delete();
|
||||
}
|
||||
|
||||
@@ -172,7 +179,6 @@ public class TraceManager implements Listener {
|
||||
tracesByRegion.getOrDefault(region, new HashMap<>())
|
||||
.forEach((i, trace) -> {
|
||||
if (trace.getRegion() != region) return;
|
||||
trace.getMetadataSaveFile().delete();
|
||||
trace.getRecordsSaveFile().delete();
|
||||
});
|
||||
tracesByRegion.getOrDefault(region, new HashMap<>()).clear();
|
||||
|
||||
+1
-1
@@ -65,7 +65,7 @@ public class TraceRecordingWrapper {
|
||||
TraceManager.instance.showPartial(trace, recordsToAdd);
|
||||
|
||||
recordList.addAll(recordsToAdd);
|
||||
trace.setRecordsCount(recordList.size());
|
||||
trace.setTntIdCount((int) recordList.stream().map(TNTPoint::getTntId).distinct().count());
|
||||
recordsToAdd.clear();
|
||||
}
|
||||
|
||||
|
||||
+61
-49
@@ -9,60 +9,56 @@ import org.bukkit.util.Vector;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
public class TraceRepository {
|
||||
|
||||
/**
|
||||
* Increment this when changing serialisation format
|
||||
*/
|
||||
public static final int SERIALISATION_VERSION = 1;
|
||||
public static final int SERIALISATION_VERSION = 2;
|
||||
public static final int WRITE_TICK_DATA = 0x01;
|
||||
public static final int EXPLOSION = 0x02;
|
||||
public static final int IN_WATER = 0x04;
|
||||
public static final int AFTER_FIRST_EXPLOSION = 0x08;
|
||||
public static final int DESTROYED_BUILD_AREA = 0x10;
|
||||
public static final int DESTROYED_TEST_BLOCK = 0x20;
|
||||
public static File tracesFolder = new File(Bukkit.getWorlds().get(0).getWorldFolder(), "traces");
|
||||
|
||||
@SneakyThrows
|
||||
protected static int getVersion(File metadataFile) {
|
||||
@Cleanup
|
||||
ObjectInputStream reader = new ObjectInputStream(new FileInputStream(metadataFile));
|
||||
reader.readUTF();
|
||||
reader.readUTF();
|
||||
reader.readObject();
|
||||
try {
|
||||
int version = reader.readInt();
|
||||
return version;
|
||||
} catch (EOFException e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public static Trace readTrace(File recordsFile) {
|
||||
@Cleanup
|
||||
ObjectInputStream reader = new ObjectInputStream(new FileInputStream(recordsFile));
|
||||
ObjectInputStream reader = new ObjectInputStream(new GZIPInputStream(new FileInputStream(recordsFile)));
|
||||
UUID uuid = UUID.fromString(reader.readUTF());
|
||||
Region region = Region.getREGION_MAP().get(reader.readUTF());
|
||||
Date date = (Date) reader.readObject();
|
||||
int serialisationVersion = reader.readInt();
|
||||
int recordsCount = reader.readInt();
|
||||
if (serialisationVersion != SERIALISATION_VERSION) {
|
||||
return null;
|
||||
}
|
||||
int tntIdCount = reader.readInt();
|
||||
|
||||
return new Trace(uuid, region, date, recordsFile, recordsFile, recordsCount);
|
||||
return new Trace(uuid, region, date, recordsFile, tntIdCount);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
protected static void writeTrace(Trace trace, List<TNTPoint> records) {
|
||||
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(trace.getMetadataSaveFile()));
|
||||
ObjectOutputStream outputStream = new ObjectOutputStream(new GZIPOutputStream(new FileOutputStream(trace.getRecordsSaveFile())));
|
||||
outputStream.writeUTF(trace.getUuid().toString());
|
||||
outputStream.writeUTF(trace.getRegion().getName());
|
||||
outputStream.writeObject(trace.getDate());
|
||||
outputStream.writeInt(SERIALISATION_VERSION + 1);
|
||||
outputStream.writeInt(records.size());
|
||||
outputStream.writeInt(SERIALISATION_VERSION);
|
||||
|
||||
Map<Integer, List<TNTPoint>> pointsByTNTId = new HashMap<>();
|
||||
records.forEach(tntPoint -> {
|
||||
pointsByTNTId.computeIfAbsent(tntPoint.getTntId(), integer -> new ArrayList<>()).add(tntPoint);
|
||||
});
|
||||
|
||||
outputStream.writeInt(pointsByTNTId.size());
|
||||
for (Map.Entry<Integer, List<TNTPoint>> entry : pointsByTNTId.entrySet()) {
|
||||
outputStream.writeInt(entry.getKey());
|
||||
outputStream.write(entry.getValue().size());
|
||||
outputStream.writeInt(entry.getValue().size());
|
||||
|
||||
for (int i = 0; i < entry.getValue().size(); i++) {
|
||||
TNTPoint current = entry.getValue().get(i);
|
||||
@@ -89,12 +85,12 @@ public class TraceRepository {
|
||||
@SneakyThrows
|
||||
private static void writeTNTPoint(ObjectOutputStream outputStream, TNTPoint tntPoint, boolean writeTickData) {
|
||||
byte data = 0;
|
||||
if (writeTickData) data |= 0x01;
|
||||
if (tntPoint.isExplosion()) data |= 0x02;
|
||||
if (tntPoint.isInWater()) data |= 0x04;
|
||||
if (tntPoint.isAfterFirstExplosion()) data |= 0x08;
|
||||
if (tntPoint.isDestroyedBuildArea()) data |= 0x10;
|
||||
if (tntPoint.isDestroyedTestBlock()) data |= 0x20;
|
||||
if (writeTickData) data |= WRITE_TICK_DATA;
|
||||
if (tntPoint.isExplosion()) data |= EXPLOSION;
|
||||
if (tntPoint.isInWater()) data |= IN_WATER;
|
||||
if (tntPoint.isAfterFirstExplosion()) data |= AFTER_FIRST_EXPLOSION;
|
||||
if (tntPoint.isDestroyedBuildArea()) data |= DESTROYED_BUILD_AREA;
|
||||
if (tntPoint.isDestroyedTestBlock()) data |= DESTROYED_TEST_BLOCK;
|
||||
outputStream.write(data);
|
||||
|
||||
if (writeTickData) {
|
||||
@@ -114,16 +110,24 @@ public class TraceRepository {
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
protected static TNTPoint readTraceRecord(DataInputStream objectInput) {
|
||||
protected static TNTPoint readTraceRecord(int tntId, TNTPoint last, ObjectInputStream objectInput) {
|
||||
|
||||
int tntId = objectInput.readInt();
|
||||
boolean explosion = objectInput.readBoolean();
|
||||
boolean inWater = objectInput.readBoolean();
|
||||
boolean afterFirstExplosion = objectInput.readBoolean();
|
||||
boolean destroyedBuildArea = objectInput.readBoolean();
|
||||
boolean destroyedTestBlock = objectInput.readBoolean();
|
||||
long ticksSinceStart = objectInput.readLong();
|
||||
int fuse = objectInput.readInt();
|
||||
int data = objectInput.read();
|
||||
boolean explosion = (data & EXPLOSION) > 0;
|
||||
boolean inWater = (data & IN_WATER) > 0;
|
||||
boolean afterFirstExplosion = (data & AFTER_FIRST_EXPLOSION) > 0;
|
||||
boolean destroyedBuildArea = (data & DESTROYED_BUILD_AREA) > 0;
|
||||
boolean destroyedTestBlock = (data & DESTROYED_TEST_BLOCK) > 0;
|
||||
|
||||
long ticksSinceStart;
|
||||
int fuse;
|
||||
if ((data & WRITE_TICK_DATA) > 0) {
|
||||
ticksSinceStart = objectInput.readLong();
|
||||
fuse = objectInput.readInt();
|
||||
} else {
|
||||
ticksSinceStart = last.getTicksSinceStart() + 1;
|
||||
fuse = last.getFuse() - 1;
|
||||
}
|
||||
|
||||
double locX = objectInput.readDouble();
|
||||
double locY = objectInput.readDouble();
|
||||
@@ -142,21 +146,29 @@ public class TraceRepository {
|
||||
protected static List<TNTPoint> readTraceRecords(Trace trace) {
|
||||
File recordsFile = trace.getRecordsSaveFile();
|
||||
@Cleanup
|
||||
DataInputStream inputStream = new DataInputStream(new FileInputStream(recordsFile));
|
||||
ObjectInputStream inputStream = new ObjectInputStream(new GZIPInputStream(new FileInputStream(recordsFile)));
|
||||
inputStream.readUTF();
|
||||
inputStream.readUTF();
|
||||
inputStream.readObject();
|
||||
inputStream.readInt();
|
||||
inputStream.readInt();
|
||||
|
||||
List<TNTPoint> records = new ArrayList<>();
|
||||
for (int i = 0; i < trace.getRecordsCount(); i++) {
|
||||
records.add(readTraceRecord(inputStream));
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
for (int i = 0; i < trace.getTntIdCount(); i++) {
|
||||
int tntId = inputStream.readInt();
|
||||
int size = inputStream.readInt();
|
||||
List<TNTPoint> points = histories.computeIfAbsent(tntId, id -> new ArrayList<>());
|
||||
|
||||
TNTPoint last = null;
|
||||
for (int j = 0; j < size; j++) {
|
||||
TNTPoint point = readTraceRecord(tntId, last, inputStream);
|
||||
point.setHistory(points);
|
||||
points.add(point);
|
||||
last = point;
|
||||
records.add(point);
|
||||
}
|
||||
}
|
||||
return records;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user