forked from SteamWar/SteamWar
Merge pull request 'Add a simple smaller Trace file' (#25) from BauSystem/SmallerTraces into main
Reviewed-on: SteamWar/SteamWar#25 Reviewed-by: D4rkr34lm <dark@steamwar.de>
This commit is contained in:
@@ -50,12 +50,6 @@ public class Trace {
|
|||||||
@Getter
|
@Getter
|
||||||
private final File recordsSaveFile;
|
private final File recordsSaveFile;
|
||||||
|
|
||||||
/**
|
|
||||||
* File the metadata are saved in
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final File metadataSaveFile;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Region the trace was recorded in
|
* Region the trace was recorded in
|
||||||
*/
|
*/
|
||||||
@@ -75,7 +69,7 @@ public class Trace {
|
|||||||
|
|
||||||
@Setter
|
@Setter
|
||||||
@Getter
|
@Getter
|
||||||
private int recordsCount;
|
private int tntIdCount;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A map of all REntityServers rendering this trace
|
* A map of all REntityServers rendering this trace
|
||||||
@@ -95,21 +89,19 @@ public class Trace {
|
|||||||
this.date = new Date();
|
this.date = new Date();
|
||||||
records = new SoftReference<>(recordList);
|
records = new SoftReference<>(recordList);
|
||||||
recordsSaveFile = new File(TraceRepository.tracesFolder, uuid + ".records");
|
recordsSaveFile = new File(TraceRepository.tracesFolder, uuid + ".records");
|
||||||
metadataSaveFile = new File(TraceRepository.tracesFolder, uuid + ".meta");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for deserialising a trace from the file system
|
* Constructor for deserialising a trace from the file system
|
||||||
*/
|
*/
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
protected Trace(UUID uuid, Region region, Date date, File metadataFile, File recordsFile, int recordsCount) {
|
protected Trace(UUID uuid, Region region, Date date, File recordsFile, int tntIdCount) {
|
||||||
this.metadataSaveFile = metadataFile;
|
|
||||||
recordsSaveFile = recordsFile;
|
recordsSaveFile = recordsFile;
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
this.region = region;
|
this.region = region;
|
||||||
this.date = date;
|
this.date = date;
|
||||||
this.records = new SoftReference<>(null);
|
this.records = new SoftReference<>(null);
|
||||||
this.recordsCount = recordsCount;
|
this.tntIdCount = tntIdCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -311,7 +303,7 @@ public class Trace {
|
|||||||
", region=" + region +
|
", region=" + region +
|
||||||
", creationTime=" + date +
|
", creationTime=" + date +
|
||||||
", recordsSaveFile=" + recordsSaveFile.getName() +
|
", recordsSaveFile=" + recordsSaveFile.getName() +
|
||||||
", recordCount=" + recordsCount +
|
", tntCount=" + tntIdCount +
|
||||||
", records=" + getRecords() +
|
", records=" + getRecords() +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-12
@@ -57,19 +57,26 @@ public class TraceManager implements Listener {
|
|||||||
if (traceFiles == null)
|
if (traceFiles == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
boolean hasMetaFiles = false;
|
||||||
for (File traceFile : traceFiles) {
|
for (File traceFile : traceFiles) {
|
||||||
if (traceFile.getName().contains(".records"))
|
if (traceFile.getName().contains(".meta")) {
|
||||||
continue;
|
hasMetaFiles = true;
|
||||||
|
|
||||||
if (TraceRepository.getVersion(traceFile) == TraceRepository.SERIALISATION_VERSION) {
|
|
||||||
add(TraceRepository.readTrace(traceFile));
|
|
||||||
} else {
|
|
||||||
String uuid = traceFile.getName().replace(".meta", "");
|
|
||||||
|
|
||||||
new File(tracesFolder, uuid + ".records").deleteOnExit();
|
|
||||||
new File(tracesFolder, uuid + ".meta").deleteOnExit();
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (hasMetaFiles) {
|
||||||
|
for (File traceFile : traceFiles) {
|
||||||
|
traceFile.delete();
|
||||||
|
}
|
||||||
|
traceFiles = new File[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (File traceFile : traceFiles) {
|
||||||
|
Trace trace = TraceRepository.readTrace(traceFile);
|
||||||
|
if (trace == null) {
|
||||||
|
traceFile.delete();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
add(trace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,7 +159,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)");
|
if (traceId == null) throw new RuntimeException("Trace not found while trying to remove see (c978eb98-b0b2-4009-91d8-acfa34e2831a)");
|
||||||
traces.remove(traceId);
|
traces.remove(traceId);
|
||||||
trace.hide();
|
trace.hide();
|
||||||
trace.getMetadataSaveFile().delete();
|
|
||||||
trace.getRecordsSaveFile().delete();
|
trace.getRecordsSaveFile().delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,7 +178,6 @@ public class TraceManager implements Listener {
|
|||||||
tracesByRegion.getOrDefault(region, new HashMap<>())
|
tracesByRegion.getOrDefault(region, new HashMap<>())
|
||||||
.forEach((i, trace) -> {
|
.forEach((i, trace) -> {
|
||||||
if (trace.getRegion() != region) return;
|
if (trace.getRegion() != region) return;
|
||||||
trace.getMetadataSaveFile().delete();
|
|
||||||
trace.getRecordsSaveFile().delete();
|
trace.getRecordsSaveFile().delete();
|
||||||
});
|
});
|
||||||
tracesByRegion.getOrDefault(region, new HashMap<>()).clear();
|
tracesByRegion.getOrDefault(region, new HashMap<>()).clear();
|
||||||
|
|||||||
+1
-1
@@ -65,7 +65,7 @@ public class TraceRecordingWrapper {
|
|||||||
TraceManager.instance.showPartial(trace, recordsToAdd);
|
TraceManager.instance.showPartial(trace, recordsToAdd);
|
||||||
|
|
||||||
recordList.addAll(recordsToAdd);
|
recordList.addAll(recordsToAdd);
|
||||||
trace.setRecordsCount(recordList.size());
|
trace.setTntIdCount((int) recordList.stream().map(TNTPoint::getTntId).distinct().count());
|
||||||
recordsToAdd.clear();
|
recordsToAdd.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+105
-67
@@ -9,95 +9,125 @@ import org.bukkit.util.Vector;
|
|||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.zip.GZIPInputStream;
|
||||||
|
import java.util.zip.GZIPOutputStream;
|
||||||
|
|
||||||
public class TraceRepository {
|
public class TraceRepository {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Increment this when changing serialisation format
|
* 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 = 0b00000001;
|
||||||
|
public static final int EXPLOSION = 0b00000010;
|
||||||
|
public static final int IN_WATER = 0b00000100;
|
||||||
|
public static final int AFTER_FIRST_EXPLOSION = 0b00001000;
|
||||||
|
public static final int DESTROYED_BUILD_AREA = 0b00010000;
|
||||||
|
public static final int DESTROYED_TEST_BLOCK = 0b00100000;
|
||||||
public static File tracesFolder = new File(Bukkit.getWorlds().get(0).getWorldFolder(), "traces");
|
public static File tracesFolder = new File(Bukkit.getWorlds().get(0).getWorldFolder(), "traces");
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
protected static int getVersion(File metadataFile) {
|
public static Trace readTrace(File recordsFile) {
|
||||||
@Cleanup
|
@Cleanup
|
||||||
ObjectInputStream reader = new ObjectInputStream(new FileInputStream(metadataFile));
|
ObjectInputStream reader = new ObjectInputStream(new GZIPInputStream(new FileInputStream(recordsFile)));
|
||||||
reader.readUTF();
|
|
||||||
reader.readUTF();
|
|
||||||
reader.readObject();
|
|
||||||
try {
|
|
||||||
int version = reader.readInt();
|
|
||||||
return version;
|
|
||||||
} catch (EOFException e) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SneakyThrows
|
|
||||||
public static Trace readTrace(File metadataFile) {
|
|
||||||
@Cleanup
|
|
||||||
ObjectInputStream reader = new ObjectInputStream(new FileInputStream(metadataFile));
|
|
||||||
UUID uuid = UUID.fromString(reader.readUTF());
|
UUID uuid = UUID.fromString(reader.readUTF());
|
||||||
Region region = Region.getREGION_MAP().get(reader.readUTF());
|
Region region = Region.getREGION_MAP().get(reader.readUTF());
|
||||||
Date date = (Date) reader.readObject();
|
Date date = (Date) reader.readObject();
|
||||||
File recordsFile = new File(tracesFolder,uuid + ".records");
|
|
||||||
int serialisationVersion = reader.readInt();
|
int serialisationVersion = reader.readInt();
|
||||||
int recordsCount = reader.readInt();
|
if (serialisationVersion != SERIALISATION_VERSION) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
int tntIdCount = reader.readInt();
|
||||||
|
|
||||||
return new Trace(uuid, region, date, metadataFile, recordsFile, recordsCount);
|
return new Trace(uuid, region, date, recordsFile, tntIdCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
protected static void writeTrace(Trace trace, List<TNTPoint> records) {
|
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.getUuid().toString());
|
||||||
outputStream.writeUTF(trace.getRegion().getName());
|
outputStream.writeUTF(trace.getRegion().getName());
|
||||||
outputStream.writeObject(trace.getDate());
|
outputStream.writeObject(trace.getDate());
|
||||||
outputStream.writeInt(SERIALISATION_VERSION);
|
outputStream.writeInt(SERIALISATION_VERSION);
|
||||||
outputStream.writeInt(records.size());
|
|
||||||
outputStream.flush();
|
|
||||||
outputStream.close();
|
|
||||||
|
|
||||||
|
Map<Integer, List<TNTPoint>> pointsByTNTId = new HashMap<>();
|
||||||
|
records.forEach(tntPoint -> {
|
||||||
|
pointsByTNTId.computeIfAbsent(tntPoint.getTntId(), integer -> new ArrayList<>()).add(tntPoint);
|
||||||
|
});
|
||||||
|
|
||||||
writeTraceRecords(trace.getRecordsSaveFile(), records);
|
outputStream.writeInt(pointsByTNTId.size());
|
||||||
}
|
for (Map.Entry<Integer, List<TNTPoint>> entry : pointsByTNTId.entrySet()) {
|
||||||
|
outputStream.writeInt(entry.getKey());
|
||||||
|
outputStream.writeInt(entry.getValue().size());
|
||||||
|
|
||||||
@SneakyThrows
|
for (int i = 0; i < entry.getValue().size(); i++) {
|
||||||
protected static void writeTraceRecords(File recordsFile, List<TNTPoint> records) {
|
TNTPoint current = entry.getValue().get(i);
|
||||||
DataOutputStream outputStream = new DataOutputStream(new FileOutputStream(recordsFile));
|
if (i == 0) {
|
||||||
for (TNTPoint record : records) {
|
writeTNTPoint(outputStream, current, true);
|
||||||
outputStream.writeInt(record.getTntId());
|
continue;
|
||||||
outputStream.writeBoolean(record.isExplosion());
|
}
|
||||||
outputStream.writeBoolean(record.isInWater());
|
|
||||||
outputStream.writeBoolean(record.isAfterFirstExplosion());
|
TNTPoint last = entry.getValue().get(i - 1);
|
||||||
outputStream.writeBoolean(record.isDestroyedBuildArea());
|
|
||||||
outputStream.writeBoolean(record.isDestroyedTestBlock());
|
boolean writeTickData = true;
|
||||||
outputStream.writeLong(record.getTicksSinceStart());
|
if (last.getTicksSinceStart() + 1 == current.getTicksSinceStart() && last.getFuse() - 1 == current.getFuse()) {
|
||||||
outputStream.writeInt(record.getFuse());
|
writeTickData = false;
|
||||||
Location location = record.getLocation();
|
}
|
||||||
outputStream.writeDouble(location.getX());
|
|
||||||
outputStream.writeDouble(location.getY());
|
writeTNTPoint(outputStream, current, writeTickData);
|
||||||
outputStream.writeDouble(location.getZ());
|
}
|
||||||
Vector velocity = record.getVelocity();
|
|
||||||
outputStream.writeDouble(velocity.getX());
|
|
||||||
outputStream.writeDouble(velocity.getY());
|
|
||||||
outputStream.writeDouble(velocity.getZ());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
outputStream.flush();
|
outputStream.flush();
|
||||||
outputStream.close();
|
outputStream.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
protected static TNTPoint readTraceRecord(DataInputStream objectInput) {
|
private static void writeTNTPoint(ObjectOutputStream outputStream, TNTPoint tntPoint, boolean writeTickData) {
|
||||||
|
byte data = 0;
|
||||||
|
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);
|
||||||
|
|
||||||
int tntId = objectInput.readInt();
|
if (writeTickData) {
|
||||||
boolean explosion = objectInput.readBoolean();
|
outputStream.writeLong(tntPoint.getTicksSinceStart());
|
||||||
boolean inWater = objectInput.readBoolean();
|
outputStream.writeInt(tntPoint.getFuse());
|
||||||
boolean afterFirstExplosion = objectInput.readBoolean();
|
}
|
||||||
boolean destroyedBuildArea = objectInput.readBoolean();
|
|
||||||
boolean destroyedTestBlock = objectInput.readBoolean();
|
Location location = tntPoint.getLocation();
|
||||||
long ticksSinceStart = objectInput.readLong();
|
outputStream.writeDouble(location.getX());
|
||||||
int fuse = objectInput.readInt();
|
outputStream.writeDouble(location.getY());
|
||||||
|
outputStream.writeDouble(location.getZ());
|
||||||
|
|
||||||
|
Vector velocity = tntPoint.getVelocity();
|
||||||
|
outputStream.writeDouble(velocity.getX());
|
||||||
|
outputStream.writeDouble(velocity.getY());
|
||||||
|
outputStream.writeDouble(velocity.getZ());
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
protected static TNTPoint readTraceRecord(int tntId, TNTPoint last, ObjectInputStream objectInput) {
|
||||||
|
|
||||||
|
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 locX = objectInput.readDouble();
|
||||||
double locY = objectInput.readDouble();
|
double locY = objectInput.readDouble();
|
||||||
@@ -116,21 +146,29 @@ public class TraceRepository {
|
|||||||
protected static List<TNTPoint> readTraceRecords(Trace trace) {
|
protected static List<TNTPoint> readTraceRecords(Trace trace) {
|
||||||
File recordsFile = trace.getRecordsSaveFile();
|
File recordsFile = trace.getRecordsSaveFile();
|
||||||
@Cleanup
|
@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<>();
|
List<TNTPoint> records = new ArrayList<>();
|
||||||
for (int i = 0; i < trace.getRecordsCount(); i++) {
|
|
||||||
records.add(readTraceRecord(inputStream));
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<Integer, List<TNTPoint>> histories = new HashMap<>();
|
Map<Integer, List<TNTPoint>> histories = new HashMap<>();
|
||||||
for (TNTPoint record : records) {
|
for (int i = 0; i < trace.getTntIdCount(); i++) {
|
||||||
int tntId = record.getTntId();
|
int tntId = inputStream.readInt();
|
||||||
List<TNTPoint> history = histories.computeIfAbsent(tntId, id -> new ArrayList<>());
|
int size = inputStream.readInt();
|
||||||
history.add(record);
|
List<TNTPoint> points = histories.computeIfAbsent(tntId, id -> new ArrayList<>());
|
||||||
record.setHistory(history);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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;
|
return records;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user