Trace Refactor #233
10
.gitignore
vendored
10
.gitignore
vendored
@ -1,5 +1,7 @@
|
||||
# Package Files
|
||||
# Build files
|
||||
*.jar
|
||||
**/bin
|
||||
**/build
|
||||
|
||||
# Gradle
|
||||
.gradle
|
||||
@ -10,6 +12,10 @@ steamwar.properties
|
||||
# IntelliJ IDEA
|
||||
.idea
|
||||
*.iml
|
||||
plugin.yml
|
||||
|
||||
# Other
|
||||
lib
|
||||
lib
|
||||
|
||||
#linkage
|
||||
LinkageUtils.java
|
@ -24,7 +24,7 @@ import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
|
||||
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
|
||||
import de.steamwar.bausystem.features.tracer.TNTPoint;
|
||||
import de.steamwar.bausystem.features.tracer.TraceRecorder;
|
||||
import de.steamwar.bausystem.features.tracer.TraceManager;
|
||||
import de.steamwar.bausystem.region.Point;
|
||||
import de.steamwar.bausystem.utils.FlatteningWrapper;
|
||||
import org.bukkit.Location;
|
||||
@ -59,7 +59,7 @@ public class ProcessingTracesState implements LaufbauState {
|
||||
this.factor = factor;
|
||||
|
||||
// TODO: Optimize only retrieving traces inside of the affected regions!
|
||||
TNTPoints = TraceRecorder.instance.manager.getAll()
|
||||
TNTPoints = TraceManager.instance.getAll()
|
||||
.stream()
|
||||
.flatMap(trace -> trace.getHistories().stream())
|
||||
.flatMap(Collection::stream)
|
||||
|
@ -23,73 +23,81 @@ import de.steamwar.bausystem.region.Region;
|
||||
import de.steamwar.bausystem.region.utils.RegionExtensionType;
|
||||
import de.steamwar.bausystem.region.utils.RegionType;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.TNTPrimed;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.io.Externalizable;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInput;
|
||||
import java.io.ObjectOutput;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Getter
|
||||
public class TNTPoint {
|
||||
|
||||
public class TNTPoint implements Externalizable {
|
||||
/**
|
||||
* Unique number to identify records being of the same tnt
|
||||
*/
|
||||
private final int tntId;
|
||||
private int tntId;
|
||||
|
||||
/**
|
||||
* Whether this is a record of a tnt explosion or an entity
|
||||
*/
|
||||
private final boolean explosion;
|
||||
private boolean explosion;
|
||||
|
||||
/**
|
||||
* Whether this is a record of a tnt that was in water
|
||||
*/
|
||||
private final boolean inWater;
|
||||
private boolean inWater;
|
||||
|
||||
/**
|
||||
* Whether this record was taken after the first tnt exploded
|
||||
*/
|
||||
private final boolean afterFirstExplosion;
|
||||
private boolean afterFirstExplosion;
|
||||
|
||||
/**
|
||||
* Whether this record has destroyed blocks in build area
|
||||
*/
|
||||
private final boolean destroyedBuildArea;
|
||||
private boolean destroyedBuildArea;
|
||||
|
||||
/**
|
||||
* Whether this record has destroyed blocks in testblock area
|
||||
*/
|
||||
private final boolean destroyedTestBlock;
|
||||
private boolean destroyedTestBlock;
|
||||
|
||||
/**
|
||||
* Tick offset, from this record being taken to the start of the trace
|
||||
*/
|
||||
private final long ticksSinceStart;
|
||||
private long ticksSinceStart;
|
||||
|
||||
/**
|
||||
* Fuse ticks of the recorded tnt (0 if this is an explosion)
|
||||
*/
|
||||
private final int fuse;
|
||||
private int fuse;
|
||||
|
||||
/**
|
||||
* Location of the recorded tnt
|
||||
*/
|
||||
private final Location location;
|
||||
private Location location;
|
||||
|
||||
/**
|
||||
* Velocity of the recorded tnt
|
||||
*/
|
||||
private final Vector velocity;
|
||||
private Vector velocity;
|
||||
|
||||
/**
|
||||
* List of all tnt records, that are represent the same tnt
|
||||
*/
|
||||
private final List<TNTPoint> history;
|
||||
private List<TNTPoint> history;
|
||||
|
||||
public TNTPoint(int tntId, TNTPrimed tnt, boolean explosion, boolean afterFirstExplosion, long ticksSinceStart, List<TNTPoint> history, List<Block> destroyedBlocks) {
|
||||
public TNTPoint() {
|
||||
}
|
||||
|
||||
public TNTPoint(int tntId, TNTPrimed tnt, boolean explosion, boolean afterFirstExplosion, long ticksSinceStart,
|
||||
List<TNTPoint> history, List<Block> destroyedBlocks) {
|
||||
this.tntId = tntId;
|
||||
this.explosion = explosion;
|
||||
this.inWater = tnt.isInWater();
|
||||
@ -103,10 +111,12 @@ public class TNTPoint {
|
||||
boolean buildDestroy = false;
|
||||
boolean testblockDestroy = false;
|
||||
for (Block destroyedBlock : destroyedBlocks) {
|
||||
if (Region.getRegion(destroyedBlock.getLocation()).inRegion(destroyedBlock.getLocation(), RegionType.BUILD, RegionExtensionType.EXTENSION)) {
|
||||
if (Region.getRegion(destroyedBlock.getLocation()).inRegion(destroyedBlock.getLocation(), RegionType.BUILD,
|
||||
RegionExtensionType.EXTENSION)) {
|
||||
buildDestroy = true;
|
||||
}
|
||||
if (Region.getRegion(destroyedBlock.getLocation()).inRegion(destroyedBlock.getLocation(), RegionType.TESTBLOCK, RegionExtensionType.EXTENSION)) {
|
||||
if (Region.getRegion(destroyedBlock.getLocation()).inRegion(destroyedBlock.getLocation(),
|
||||
RegionType.TESTBLOCK, RegionExtensionType.EXTENSION)) {
|
||||
testblockDestroy = true;
|
||||
}
|
||||
}
|
||||
@ -125,6 +135,50 @@ public class TNTPoint {
|
||||
return index == 0 ? Optional.empty() : Optional.of(history.get(index - 1));
|
||||
}
|
||||
|
||||
void setHistory(List<TNTPoint> history) {
|
||||
this.history = history;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeExternal(ObjectOutput objectOutput) throws IOException {
|
||||
objectOutput.writeInt(tntId);
|
||||
objectOutput.writeBoolean(explosion);
|
||||
objectOutput.writeBoolean(inWater);
|
||||
objectOutput.writeBoolean(afterFirstExplosion);
|
||||
objectOutput.writeBoolean(destroyedBuildArea);
|
||||
objectOutput.writeBoolean(destroyedTestBlock);
|
||||
objectOutput.writeLong(ticksSinceStart);
|
||||
objectOutput.writeInt(fuse);
|
||||
objectOutput.writeUTF(location.getWorld().getName());
|
||||
objectOutput.writeDouble(location.getX());
|
||||
objectOutput.writeDouble(location.getY());
|
||||
objectOutput.writeDouble(location.getZ());
|
||||
objectOutput.writeDouble(velocity.getX());
|
||||
objectOutput.writeDouble(velocity.getY());
|
||||
objectOutput.writeDouble(velocity.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readExternal(ObjectInput objectInput) throws IOException, ClassNotFoundException {
|
||||
tntId = objectInput.readInt();
|
||||
explosion = objectInput.readBoolean();
|
||||
inWater = objectInput.readBoolean();
|
||||
afterFirstExplosion = objectInput.readBoolean();
|
||||
destroyedBuildArea = objectInput.readBoolean();
|
||||
destroyedTestBlock = objectInput.readBoolean();
|
||||
ticksSinceStart = objectInput.readLong();
|
||||
fuse = objectInput.readInt();
|
||||
String worldName = objectInput.readUTF();
|
||||
double locX = objectInput.readDouble();
|
||||
double locY = objectInput.readDouble();
|
||||
double locZ = objectInput.readDouble();
|
||||
location = new Location(Bukkit.getWorld(worldName), locX, locY, locZ);
|
||||
double velX = objectInput.readDouble();
|
||||
double velY = objectInput.readDouble();
|
||||
double velZ = objectInput.readDouble();
|
||||
velocity = new Vector(velX, velY, velZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TNTRecord{" +
|
||||
@ -138,11 +192,15 @@ public class TNTPoint {
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof TNTPoint)) return false;
|
||||
if (!(obj instanceof TNTPoint))
|
||||
return false;
|
||||
TNTPoint record = (TNTPoint) obj;
|
||||
if (record.isExplosion() != explosion) return false;
|
||||
if (!record.getLocation().equals(location)) return false;
|
||||
if (!record.getVelocity().equals(velocity)) return false;
|
||||
if (record.isExplosion() != explosion)
|
||||
return false;
|
||||
if (!record.getLocation().equals(location))
|
||||
return false;
|
||||
if (!record.getVelocity().equals(velocity))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -19,102 +19,104 @@
|
||||
|
||||
package de.steamwar.bausystem.features.tracer;
|
||||
|
||||
import de.steamwar.bausystem.features.tpslimit.TPSUtils;
|
||||
import de.steamwar.bausystem.features.tracer.rendering.BundleFilter;
|
||||
import de.steamwar.bausystem.features.tracer.rendering.PlayerTraceShowData;
|
||||
import de.steamwar.bausystem.features.tracer.rendering.TraceEntity;
|
||||
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 org.bukkit.entity.Player;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Trace { // TODO: Add UUID for file saving and so on!
|
||||
public class Trace {
|
||||
/**
|
||||
* UUID of the trace used for
|
||||
*/
|
||||
@Getter
|
||||
private final UUID uuid;
|
||||
|
||||
/**
|
||||
* Region this trace has been recorded in
|
||||
* File the records are saved in
|
||||
*/
|
||||
@Getter
|
||||
private final File recordsSaveFile;
|
||||
|
||||
/**
|
||||
* File the metadata are saved in
|
||||
*/
|
||||
@Getter
|
||||
private final File metadataSaveFile;
|
||||
|
||||
/**
|
||||
* Region the trace was recorded in
|
||||
*/
|
||||
@Getter
|
||||
private final Region region;
|
||||
|
||||
/**
|
||||
* Tick the recording started at
|
||||
* Date the trace was recorded at
|
||||
*/
|
||||
@Getter
|
||||
private final long startTime = TPSUtils.currentTick.get();
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Getter
|
||||
private final Date date = new Date();
|
||||
private final Date date;
|
||||
|
||||
/**
|
||||
* Records of TNTs, making up the trace
|
||||
*/
|
||||
@Getter
|
||||
private List<TNTPoint> records = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* ID that should be assigned to the next record of a unique tnt
|
||||
*/
|
||||
@Getter
|
||||
private int nextOpenRecordId = -1;
|
||||
private SoftReference<List<TNTPoint>> records;
|
||||
|
||||
private final Map<Player, REntityServer> entityServerMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* List of all used ids
|
||||
*/
|
||||
public List<String> getUsedIds() {
|
||||
return getRecords()
|
||||
.stream()
|
||||
.map(TNTPoint::getTntId)
|
||||
.map(i -> i + "")
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public Trace(Region region) {
|
||||
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();
|
||||
records = new SoftReference<>(recordList);
|
||||
metadataSaveFile = new File(TraceManager.tracesFolder, uuid + ".meta");
|
||||
|
||||
/**
|
||||
* Gets and increments the next open record id
|
||||
*
|
||||
* @return next open record id
|
||||
*/
|
||||
protected int getAndIncrementNextOpenRecordId() {
|
||||
return ++nextOpenRecordId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given records and updates potential trace renderings
|
||||
*/
|
||||
protected void addAll(List<TNTPoint> records, Function<Player, PlayerTraceShowData> getter) {
|
||||
this.getRecords().addAll(records);
|
||||
Iterator<Player> keySetIterator = entityServerMap.keySet().iterator();
|
||||
while (keySetIterator.hasNext()) {
|
||||
Player player = keySetIterator.next();
|
||||
PlayerTraceShowData playerTraceShowData = getter.apply(player);
|
||||
if (playerTraceShowData == null) {
|
||||
keySetIterator.remove();
|
||||
continue;
|
||||
}
|
||||
render(records, entityServerMap.get(player), playerTraceShowData);
|
||||
try {
|
||||
@Cleanup
|
||||
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(metadataSaveFile));
|
||||
outputStream.writeUTF(uuid.toString());
|
||||
outputStream.writeUTF(region.getName());
|
||||
outputStream.writeObject(date);
|
||||
} catch (IOException | ClassCastException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal methode to make records immutable after recording is finished
|
||||
*
|
||||
* @param records immutable records list
|
||||
*/
|
||||
protected void setRecords(List<TNTPoint> records) {
|
||||
this.records = records;
|
||||
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();
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
this.uuid = UUID.fromString(uuid);
|
||||
this.region = region;
|
||||
this.date = date;
|
||||
recordsSaveFile = new File(TraceManager.tracesFolder, uuid + ".records");
|
||||
this.records = new SoftReference<>(null);
|
||||
}
|
||||
|
||||
System.out.println(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -132,6 +134,17 @@ public class Trace { // TODO: Add UUID for file saving and so on!
|
||||
return histories;
|
||||
}
|
||||
|
||||
/**
|
||||
* List of all used ids
|
||||
*/
|
||||
public List<String> getUsedIds() {
|
||||
return getRecords()
|
||||
.stream()
|
||||
.map(TNTPoint::getTntId)
|
||||
.map(i -> i + "")
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders this traces
|
||||
*
|
||||
@ -150,34 +163,41 @@ public class Trace { // TODO: Add UUID for file saving and so on!
|
||||
render(getRecords(), entityServer, playerTraceShowData);
|
||||
}
|
||||
|
||||
protected void render(List<TNTPoint> records, Player player, PlayerTraceShowData playerTraceShowData) {
|
||||
render(records, entityServerMap.get(player), playerTraceShowData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal methode to render records to a REntityServer
|
||||
*
|
||||
* @param records Records to render
|
||||
* @param entityServer The show server the trace will be renderd to
|
||||
* @param playerTraceShowData The showData for modifying the rendering
|
||||
*/
|
||||
private void render(List<TNTPoint> records, REntityServer entityServer, PlayerTraceShowData playerTraceShowData) {
|
||||
if (records.isEmpty()) return;
|
||||
if (records.isEmpty())
|
||||
return;
|
||||
|
||||
List<TNTPoint> workingRecords = new ArrayList<>(records);
|
||||
Set<ViewFlag> flagList = playerTraceShowData.getEffectiveViewFlags();
|
||||
|
||||
//Apply filters
|
||||
// Apply filters
|
||||
for (ViewFlag flag : flagList) {
|
||||
workingRecords = flag.filter(workingRecords);
|
||||
}
|
||||
|
||||
//Bundle records at unique positions
|
||||
// Bundle records at unique positions
|
||||
List<List<TNTPoint>> bundles = bundleRecords(workingRecords, playerTraceShowData.getBundleFilter());
|
||||
|
||||
//Render bundled records
|
||||
// Render bundled records
|
||||
List<TraceEntity> entities = new LinkedList<>();
|
||||
|
||||
for (List<TNTPoint> bundle : bundles) {
|
||||
entities.add(new TraceEntity(entityServer, bundle.get(0).getLocation(), bundle.get(0).isExplosion(), bundle));
|
||||
entities.add(
|
||||
new TraceEntity(entityServer, bundle.get(0).getLocation(), bundle.get(0).isExplosion(), bundle));
|
||||
}
|
||||
|
||||
//Apply modifiers
|
||||
// Apply modifiers
|
||||
for (ViewFlag flag : flagList) {
|
||||
flag.modify(entityServer, entities);
|
||||
}
|
||||
@ -195,13 +215,13 @@ public class Trace { // TODO: Add UUID for file saving and so on!
|
||||
* Bundles the passed TNTRecords based on whether they are at the same location
|
||||
*
|
||||
* @param records The TNTRecords that are supposed to be bundled
|
||||
* @param filter A filter specefieng whether records can be bundled
|
||||
* @return A list of bundles
|
||||
*/
|
||||
private List<List<TNTPoint>> bundleRecords(List<TNTPoint> records, BundleFilter filter) {
|
||||
List<List<TNTPoint>> bundles = new ArrayList<>();
|
||||
|
||||
recordsLoop:
|
||||
for (TNTPoint record : records) {
|
||||
recordsLoop: for (TNTPoint record : records) {
|
||||
if (bundles.isEmpty()) {
|
||||
List<TNTPoint> firstBundle = new ArrayList<>();
|
||||
firstBundle.add(record);
|
||||
@ -226,6 +246,26 @@ public class Trace { // TODO: Add UUID for file saving and so on!
|
||||
return bundles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the first passed player follow the trace render of the second passed
|
||||
* player
|
||||
*
|
||||
* @param player
|
||||
* @param toFollow
|
||||
*/
|
||||
public void follow(Player player, Player toFollow) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the passed player stop following any other players trace render
|
||||
*
|
||||
* @param player
|
||||
*/
|
||||
public void unfollow(Player player) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides this trail for the given player
|
||||
*
|
||||
@ -233,8 +273,11 @@ public class Trace { // TODO: Add UUID for file saving and so on!
|
||||
*/
|
||||
public void hide(Player player) {
|
||||
REntityServer entityServer = entityServerMap.remove(player);
|
||||
if (entityServer == null) return;
|
||||
entityServer.close();
|
||||
if (entityServer == null)
|
||||
return;
|
||||
entityServer.removePlayer(player);
|
||||
if (entityServer.getPlayers().isEmpty())
|
||||
entityServer.close();
|
||||
}
|
||||
|
||||
public void hide() {
|
||||
@ -244,12 +287,47 @@ public class Trace { // TODO: Add UUID for file saving and so on!
|
||||
entityServerMap.clear();
|
||||
}
|
||||
|
||||
private void loadRecords() {
|
||||
try {
|
||||
List<TNTPoint> records = new ArrayList<>();
|
||||
@Cleanup
|
||||
FileInputStream fileInputStream = new FileInputStream(recordsSaveFile);
|
||||
@Cleanup
|
||||
ObjectInputStream inputStream = new ObjectInputStream(fileInputStream);
|
||||
while (fileInputStream.getChannel().position() < recordsSaveFile.length()) {
|
||||
records.add((TNTPoint) inputStream.readObject());
|
||||
}
|
||||
|
||||
System.out.println("Loaded... " + records);
|
||||
|
||||
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);
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public List<TNTPoint> getRecords() {
|
||||
if (records.get() == null)
|
||||
loadRecords();
|
||||
return records.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Trace{" +
|
||||
"region=" + region +
|
||||
", startTime=" + startTime +
|
||||
", records=" + records +
|
||||
"uuid=" + uuid +
|
||||
", region=" + region +
|
||||
", creationTime=" + date +
|
||||
", recordsSaveFile=" + recordsSaveFile.getName() +
|
||||
", records=" + getRecords() +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ package de.steamwar.bausystem.features.tracer;
|
||||
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.bausystem.features.tracer.rendering.BundleFilter;
|
||||
import de.steamwar.bausystem.features.tracer.rendering.PlayerTraceShowData;
|
||||
import de.steamwar.bausystem.features.tracer.rendering.ViewFlag;
|
||||
import de.steamwar.bausystem.features.tracer.rendering.dynamicflags.AtFlag;
|
||||
import de.steamwar.bausystem.region.Region;
|
||||
@ -28,7 +29,6 @@ import de.steamwar.command.PreviousArguments;
|
||||
import de.steamwar.command.SWCommand;
|
||||
import de.steamwar.command.TypeMapper;
|
||||
import de.steamwar.linkage.Linked;
|
||||
import de.steamwar.linkage.LinkedInstance;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@ -41,12 +41,6 @@ import java.util.stream.Stream;
|
||||
@Linked
|
||||
public class TraceCommand extends SWCommand {
|
||||
|
||||
@LinkedInstance
|
||||
public TraceRecorder traceRecorder;
|
||||
|
||||
@LinkedInstance
|
||||
public TraceManager manager;
|
||||
|
||||
public TraceCommand() {
|
||||
super("trace", "trail");
|
||||
}
|
||||
@ -54,21 +48,21 @@ public class TraceCommand extends SWCommand {
|
||||
@Register(value = "start", description = "TRACE_COMMAND_HELP_START")
|
||||
public void start(@Validator Player player) {
|
||||
Region region = Region.getRegion(player.getLocation());
|
||||
traceRecorder.startRecording(region);
|
||||
TraceRecorder.instance.startRecording(region);
|
||||
BauSystem.MESSAGE.send("TRACE_MESSAGE_START", player);
|
||||
}
|
||||
|
||||
@Register(value = "stop", description = "TRACE_COMMAND_HELP_STOP")
|
||||
public void stop(@Validator Player player) {
|
||||
Region region = Region.getRegion(player.getLocation());
|
||||
traceRecorder.stopRecording(region);
|
||||
TraceRecorder.instance.stopRecording(region);
|
||||
BauSystem.MESSAGE.send("TRACE_MESSAGE_STOP", player);
|
||||
}
|
||||
|
||||
@Register(value = "auto", description = "TRACE_COMMAND_HELP_AUTO")
|
||||
public void auto(@Validator Player player) {
|
||||
Region region = Region.getRegion(player.getLocation());
|
||||
traceRecorder.toggleAutoTrace(region);
|
||||
TraceRecorder.instance.toggleAutoTrace(region);
|
||||
// TODO: Add Auto toggle Message!
|
||||
}
|
||||
|
||||
@ -78,20 +72,24 @@ public class TraceCommand extends SWCommand {
|
||||
BauSystem.MESSAGE.send("TRACE_MESSAGE_SHOW", player);
|
||||
}
|
||||
|
||||
@Register(value = {"show", "at"}, description = "TRACE_COMMAND_HELP_SHOW_AT_WITH")
|
||||
public void showAt(@Validator Player player, @Min(intValue = 0) int time, @StaticValue("with") String with, @OptionalValue("STRICT") BundleFilter bundleFilter, @ArrayLength(min = 1) ViewFlag... flags) {
|
||||
@Register(value = { "show", "at" }, description = "TRACE_COMMAND_HELP_SHOW_AT_WITH")
|
||||
public void showAt(@Validator Player player, @Min(intValue = 0) int time, @StaticValue("with") String with,
|
||||
@OptionalValue("STRICT") BundleFilter bundleFilter, @ArrayLength(min = 1) ViewFlag... flags) {
|
||||
showInternal(player, time, time, bundleFilter, flags);
|
||||
BauSystem.MESSAGE.send("TRACE_MESSAGE_SHOW_AT", player, time);
|
||||
}
|
||||
|
||||
@Register(value = {"show", "from"}, description = "TRACE_COMMAND_HELP_SHOW_FROM_WITH")
|
||||
public void showFromTo(@Validator Player player, @Min(intValue = 0) int from, @StaticValue("with") String with, @OptionalValue("STRICT") BundleFilter bundleFilter, @ArrayLength(min = 1) ViewFlag... flags) {
|
||||
@Register(value = { "show", "from" }, description = "TRACE_COMMAND_HELP_SHOW_FROM_WITH")
|
||||
public void showFromTo(@Validator Player player, @Min(intValue = 0) int from, @StaticValue("with") String with,
|
||||
@OptionalValue("STRICT") BundleFilter bundleFilter, @ArrayLength(min = 1) ViewFlag... flags) {
|
||||
showInternal(player, from, Integer.MAX_VALUE, bundleFilter, flags);
|
||||
BauSystem.MESSAGE.send("TRACE_MESSAGE_SHOW_FROM", player, from);
|
||||
}
|
||||
|
||||
@Register(value = {"show", "from"}, description = "TRACE_COMMAND_HELP_SHOW_FROM_TO_WITH")
|
||||
public void showFromTo(@Validator Player player, @Min(intValue = 0) int from, @StaticValue("to") String toString, int to, @StaticValue("with") String with, @OptionalValue("STRICT") BundleFilter bundleFilter, @ArrayLength(min = 1) ViewFlag... flags) {
|
||||
@Register(value = { "show", "from" }, description = "TRACE_COMMAND_HELP_SHOW_FROM_TO_WITH")
|
||||
public void showFromTo(@Validator Player player, @Min(intValue = 0) int from, @StaticValue("to") String toString,
|
||||
int to, @StaticValue("with") String with, @OptionalValue("STRICT") BundleFilter bundleFilter,
|
||||
@ArrayLength(min = 1) ViewFlag... flags) {
|
||||
if (to < from) {
|
||||
BauSystem.MESSAGE.send("TRACE_MESSAGE_SHOW_TO_SMALLER", player);
|
||||
return;
|
||||
@ -103,71 +101,73 @@ public class TraceCommand extends SWCommand {
|
||||
private void showInternal(Player player, int from, int to, BundleFilter bundleFilter, ViewFlag... flags) {
|
||||
PlayerTraceShowData playerTraceShowData = new PlayerTraceShowData(bundleFilter, flags);
|
||||
playerTraceShowData.addViewFlag(new AtFlag(from, to));
|
||||
manager.show(player, playerTraceShowData);
|
||||
TraceManager.instance.show(player, playerTraceShowData);
|
||||
}
|
||||
|
||||
@Register(value = {"show", "at"}, description = "TRACE_COMMAND_HELP_SHOW_AT")
|
||||
@Register(value = { "show", "at" }, description = "TRACE_COMMAND_HELP_SHOW_AT")
|
||||
public void showAt(@Validator Player player, @Min(intValue = 0) int time) {
|
||||
manager.renderAt(player, time, time);
|
||||
TraceManager.instance.renderAt(player, time, time);
|
||||
BauSystem.MESSAGE.send("TRACE_MESSAGE_SHOW_AT", player, time);
|
||||
}
|
||||
|
||||
@Register(value = {"show", "from"}, description = "TRACE_COMMAND_HELP_SHOW_FROM")
|
||||
@Register(value = { "show", "from" }, description = "TRACE_COMMAND_HELP_SHOW_FROM")
|
||||
public void showFrom(@Validator Player player, @Min(intValue = 0) int from) {
|
||||
manager.renderAt(player, from, Integer.MAX_VALUE);
|
||||
TraceManager.instance.renderAt(player, from, Integer.MAX_VALUE);
|
||||
BauSystem.MESSAGE.send("TRACE_MESSAGE_SHOW_FROM", player, from);
|
||||
}
|
||||
|
||||
@Register(value = {"show", "from"}, description = "TRACE_COMMAND_HELP_SHOW_FROM_TO")
|
||||
public void showFromTo(@Validator Player player, @Min(intValue = 0) int from, @StaticValue("to") String toString, int to) {
|
||||
manager.renderAt(player, from, to);
|
||||
@Register(value = { "show", "from" }, description = "TRACE_COMMAND_HELP_SHOW_FROM_TO")
|
||||
public void showFromTo(@Validator Player player, @Min(intValue = 0) int from, @StaticValue("to") String toString,
|
||||
int to) {
|
||||
TraceManager.instance.renderAt(player, from, to);
|
||||
BauSystem.MESSAGE.send("TRACE_MESSAGE_SHOW_FROM_TO", player, from, to);
|
||||
}
|
||||
|
||||
@Register(value = "hide", description = "TRACE_COMMAND_HELP_HIDE")
|
||||
public void hide(@Validator Player player) {
|
||||
manager.hide(player);
|
||||
TraceManager.instance.hide(player);
|
||||
BauSystem.MESSAGE.send("TRACE_MESSAGE_HIDE", player);
|
||||
}
|
||||
|
||||
@Register(value = "delete", description = "TRACE_COMMAND_HELP_DELETE")
|
||||
@Register(value = "clear")
|
||||
public void delete(@Validator Player player) {
|
||||
manager.clear();
|
||||
TraceManager.instance.clear();
|
||||
BauSystem.MESSAGE.send("TRACE_MESSAGE_DELETE", player);
|
||||
}
|
||||
|
||||
@Register(value = "delete")
|
||||
public void delete(@Validator Player player, Trace trace) {
|
||||
manager.remove(trace);
|
||||
TraceManager.instance.remove(trace);
|
||||
BauSystem.MESSAGE.send("TRACE_MESSAGE_DELETE_SPECIFIC", player);
|
||||
}
|
||||
|
||||
@Register(value = "isolate", description = "TRACE_COMMAND_HELP_ISOLATE")
|
||||
public void isolate(@Validator Player player, Trace trace, @ErrorMessage("TRACE_RECORD_ID_INVALID") TNTPoint... records) {
|
||||
manager.isolate(player, records);
|
||||
public void isolate(@Validator Player player, Trace trace,
|
||||
@ErrorMessage("TRACE_RECORD_ID_INVALID") TNTPoint... records) {
|
||||
TraceManager.instance.isolate(player, records);
|
||||
// TODO: Add Message!
|
||||
}
|
||||
|
||||
@Register(value = "share", description = "TRACE_COMMAND_HELP_SHOW")
|
||||
public void share(@Validator Player player) {
|
||||
//TODO Rücksprache
|
||||
// TODO Rücksprache
|
||||
}
|
||||
|
||||
@Register(value = "follow", description = "TRACE_COMMAND_HELP_SHOW")
|
||||
public void follow(@Validator Player player, Player toFollow) {
|
||||
if (player == toFollow) {
|
||||
// TODO: Implement message
|
||||
return;
|
||||
// TODO: Implement
|
||||
for (Trace trace : TraceManager.instance.getAll()) {
|
||||
trace.follow(player, toFollow);
|
||||
}
|
||||
manager.follow(player, toFollow);
|
||||
// TODO: Implement message
|
||||
}
|
||||
|
||||
@Register(value = "unfollow", description = "TRACE_COMMAND_HELP_SHOW")
|
||||
public void unfollow(@Validator Player player) {
|
||||
manager.unfollow(player);
|
||||
// TODO: Implement message
|
||||
// TODO: Implement
|
||||
for (Trace trace : TraceManager.instance.getAll()) {
|
||||
trace.unfollow(player);
|
||||
}
|
||||
}
|
||||
|
||||
@ClassMapper(value = Trace.class, local = true)
|
||||
@ -175,12 +175,13 @@ public class TraceCommand extends SWCommand {
|
||||
return new TypeMapper<>() {
|
||||
@Override
|
||||
public Trace map(CommandSender commandSender, String[] previousArguments, String s) {
|
||||
return manager.get(Integer.parseInt(s)).orElse(null);
|
||||
return TraceManager.instance.get(Integer.parseInt(s)).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> tabCompletes(CommandSender sender, PreviousArguments previousArguments, String s) {
|
||||
return manager.getAllIds().stream()
|
||||
public Collection<String> tabCompletes(CommandSender sender, PreviousArguments previousArguments,
|
||||
String s) {
|
||||
return TraceManager.instance.getAllIds().stream()
|
||||
.map(Object::toString)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
@ -193,7 +194,8 @@ public class TraceCommand extends SWCommand {
|
||||
@Override
|
||||
public TNTPoint map(CommandSender commandSender, PreviousArguments previousArguments, String s) {
|
||||
Trace trace = previousArguments.getFirst(Trace.class).orElse(null);
|
||||
if (trace == null) return null;
|
||||
if (trace == null)
|
||||
return null;
|
||||
|
||||
int id = Integer.parseInt(s);
|
||||
return trace.getRecords().stream()
|
||||
@ -202,11 +204,13 @@ public class TraceCommand extends SWCommand {
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
//TODO change when new command framework update
|
||||
// TODO change when new command framework update
|
||||
@Override
|
||||
public Collection<String> tabCompletes(CommandSender sender, PreviousArguments previousArguments, String s) {
|
||||
public Collection<String> tabCompletes(CommandSender sender, PreviousArguments previousArguments,
|
||||
String s) {
|
||||
Trace trace = previousArguments.getFirst(Trace.class).orElse(null);
|
||||
if (trace == null) return null;
|
||||
if (trace == null)
|
||||
return null;
|
||||
return trace.getUsedIds();
|
||||
}
|
||||
};
|
||||
@ -226,7 +230,8 @@ public class TraceCommand extends SWCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> tabCompletes(CommandSender sender, PreviousArguments previousArguments, String s) {
|
||||
public Collection<String> tabCompletes(CommandSender sender, PreviousArguments previousArguments,
|
||||
String s) {
|
||||
if (s.length() == 0) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
@ -258,7 +263,8 @@ public class TraceCommand extends SWCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> tabCompletes(CommandSender sender, PreviousArguments previousArguments, String s) {
|
||||
public Collection<String> tabCompletes(CommandSender sender, PreviousArguments previousArguments,
|
||||
String s) {
|
||||
return ViewFlag.flags.stream()
|
||||
.flatMap(viewFlag -> Stream.concat(Stream.of("--" + viewFlag.name),
|
||||
Arrays.stream(viewFlag.aliases).map(name -> "-" + name)))
|
||||
|
@ -20,19 +20,47 @@
|
||||
package de.steamwar.bausystem.features.tracer;
|
||||
|
||||
import de.steamwar.bausystem.features.tracer.rendering.BundleFilter;
|
||||
import de.steamwar.bausystem.features.tracer.rendering.PlayerTraceShowData;
|
||||
import de.steamwar.bausystem.features.tracer.rendering.dynamicflags.AtFlag;
|
||||
import de.steamwar.bausystem.features.tracer.rendering.dynamicflags.IsolateFlag;
|
||||
import de.steamwar.bausystem.region.Region;
|
||||
import de.steamwar.linkage.Linked;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
@Linked
|
||||
public class TraceManager implements Listener {
|
||||
|
||||
public static TraceManager instance;
|
||||
|
||||
{
|
||||
instance = this;
|
||||
}
|
||||
|
||||
public static File tracesFolder = new File(Bukkit.getWorlds().get(0).getWorldFolder(), "traces");
|
||||
|
||||
public TraceManager() {
|
||||
if (!tracesFolder.exists())
|
||||
tracesFolder.mkdir();
|
||||
|
||||
File[] traceFiles = tracesFolder.listFiles();
|
||||
if (traceFiles == null)
|
||||
return;
|
||||
|
||||
for (File traceFile : traceFiles) {
|
||||
if (traceFile.getName().contains(".records"))
|
||||
continue;
|
||||
|
||||
add(new Trace(traceFile));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List of all current traces
|
||||
*/
|
||||
@ -56,31 +84,15 @@ public class TraceManager implements Listener {
|
||||
* @return id of the created trace
|
||||
*/
|
||||
protected int add(Trace trace) {
|
||||
showDataPerRegionPerPlayer.getOrDefault(trace.getRegion(), Collections.emptyMap()).forEach((player, playerTraceShowData) -> {
|
||||
trace.render(player, playerTraceShowData);
|
||||
followerMap.getOrDefault(player, Collections.emptySet()).forEach(follower -> {
|
||||
trace.render(follower, playerTraceShowData);
|
||||
});
|
||||
});
|
||||
showDataPerRegionPerPlayer.getOrDefault(trace.getRegion(), Collections.emptyMap()).forEach(trace::render);
|
||||
traces.put(nextOpenId, trace);
|
||||
tracesByRegion.computeIfAbsent(trace.getRegion(), region -> new HashMap<>()).put(nextOpenId, trace);
|
||||
nextOpenId++;
|
||||
return nextOpenId;
|
||||
}
|
||||
|
||||
protected void addAll(Trace trace, List<TNTPoint> TNTPoints) {
|
||||
trace.addAll(TNTPoints, player -> {
|
||||
Map.Entry<Player, Set<Player>> entry = followerMap.entrySet()
|
||||
.stream()
|
||||
.filter(playerSetEntry -> playerSetEntry.getValue().contains(player))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (entry == null) {
|
||||
return showDataPerRegionPerPlayer.getOrDefault(trace.getRegion(), Collections.emptyMap()).get(player);
|
||||
} else {
|
||||
return showDataPerRegionPerPlayer.getOrDefault(trace.getRegion(), Collections.emptyMap()).get(entry.getKey());
|
||||
}
|
||||
});
|
||||
protected Map<Player, PlayerTraceShowData> getTraceShowDataPlayerMapping(Region region) {
|
||||
return showDataPerRegionPerPlayer.getOrDefault(region, new HashMap<>());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -94,7 +106,8 @@ public class TraceManager implements Listener {
|
||||
.map(Map.Entry::getKey)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (traceId == null) return false;
|
||||
if (traceId == null)
|
||||
return false;
|
||||
traces.remove(traceId);
|
||||
tracesByRegion.getOrDefault(trace.getRegion(), Collections.emptyMap()).remove(traceId);
|
||||
trace.hide();
|
||||
@ -116,6 +129,10 @@ public class TraceManager implements Listener {
|
||||
players.forEach(trace::hide);
|
||||
});
|
||||
});
|
||||
traces.forEach((i, trace) -> {
|
||||
trace.getMetadataSaveFile().delete();
|
||||
trace.getRecordsSaveFile().delete();
|
||||
});
|
||||
traces.clear();
|
||||
tracesByRegion.clear();
|
||||
nextOpenId = 0;
|
||||
@ -135,7 +152,7 @@ public class TraceManager implements Listener {
|
||||
* Methode to get the trace with specific id
|
||||
*
|
||||
* @param index index of the trace
|
||||
* @return the trace with given id or null if no trace with id is found
|
||||
* @return the trace with given id
|
||||
*/
|
||||
public Optional<Trace> get(int index) {
|
||||
return Optional.ofNullable(traces.get(index));
|
||||
@ -185,16 +202,19 @@ public class TraceManager implements Listener {
|
||||
unfollow(player);
|
||||
|
||||
Region region = Region.getRegion(player.getLocation());
|
||||
PlayerTraceShowData previous = showDataPerRegionPerPlayer.getOrDefault(region, Collections.emptyMap()).remove(player);
|
||||
if (previous == null) return;
|
||||
tracesByRegion.getOrDefault(region, Collections.emptyMap()).forEach((integer, trace) -> {
|
||||
PlayerTraceShowData previous = showDataPerRegionPerPlayer.getOrDefault(region, Collections.emptyMap())
|
||||
.remove(player);
|
||||
if (previous == null)
|
||||
return;
|
||||
tracesByRegion.getOrDefault(player, Collections.emptyMap()).forEach((integer, trace) -> {
|
||||
trace.hide(player);
|
||||
followerMap.getOrDefault(player, Collections.emptySet()).forEach(trace::hide);
|
||||
});
|
||||
}
|
||||
|
||||
public boolean follow(Player follower, Player following) {
|
||||
if (followerMap.containsKey(follower)) return false;
|
||||
if (followerMap.containsKey(follower))
|
||||
return false;
|
||||
if (followerMap.entrySet().stream().anyMatch(playerSetEntry -> playerSetEntry.getValue().contains(follower))) {
|
||||
unfollow(follower);
|
||||
}
|
||||
@ -209,7 +229,8 @@ public class TraceManager implements Listener {
|
||||
}
|
||||
|
||||
PlayerTraceShowData playerTraceShowData = playerPlayerTraceShowDataMap.get(following);
|
||||
if (playerTraceShowData == null) return;
|
||||
if (playerTraceShowData == null)
|
||||
return;
|
||||
tracesByRegion.getOrDefault(region, Collections.emptyMap()).forEach((integer, trace) -> {
|
||||
trace.render(follower, playerTraceShowData);
|
||||
});
|
||||
@ -218,25 +239,30 @@ public class TraceManager implements Listener {
|
||||
}
|
||||
|
||||
public void unfollow(Player follower) {
|
||||
if (followerMap.containsKey(follower)) return;
|
||||
if (followerMap.containsKey(follower))
|
||||
return;
|
||||
List<Player> toRemove = new ArrayList<>();
|
||||
Set<Player> toHide = new HashSet<>();
|
||||
followerMap.forEach((player, players) -> {
|
||||
if (players.remove(follower)) toHide.add(follower);
|
||||
if (players.isEmpty()) toRemove.add(player);
|
||||
if (players.remove(follower))
|
||||
toHide.add(follower);
|
||||
if (players.isEmpty())
|
||||
toRemove.add(player);
|
||||
});
|
||||
toRemove.forEach(followerMap::remove);
|
||||
|
||||
showDataPerRegionPerPlayer.forEach((region, playerPlayerTraceShowDataMap) -> {
|
||||
toHide.forEach(player -> {
|
||||
if (!playerPlayerTraceShowDataMap.containsKey(player)) return;
|
||||
if (!playerPlayerTraceShowDataMap.containsKey(player))
|
||||
return;
|
||||
tracesByRegion.getOrDefault(region, Collections.emptyMap()).forEach((integer, trace) -> {
|
||||
trace.hide(follower);
|
||||
});
|
||||
});
|
||||
|
||||
PlayerTraceShowData playerTraceShowData = playerPlayerTraceShowDataMap.get(follower);
|
||||
if (playerTraceShowData == null) return;
|
||||
if (playerTraceShowData == null)
|
||||
return;
|
||||
tracesByRegion.getOrDefault(region, Collections.emptyMap()).forEach((integer, trace) -> {
|
||||
trace.render(follower, playerTraceShowData);
|
||||
});
|
||||
@ -244,7 +270,8 @@ public class TraceManager implements Listener {
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies the render for the given player, to only show tnts at the given time interval
|
||||
* Modifies the render for the given player, to only show tnts at the given time
|
||||
* interval
|
||||
*
|
||||
* @param player
|
||||
* @param from start of time interval
|
||||
@ -254,7 +281,9 @@ public class TraceManager implements Listener {
|
||||
unfollow(player);
|
||||
|
||||
Region region = Region.getRegion(player.getLocation());
|
||||
PlayerTraceShowData playerTraceShowData = showDataPerRegionPerPlayer.computeIfAbsent(region, ignored -> new HashMap<>()).computeIfAbsent(player, ignored -> new PlayerTraceShowData(BundleFilter.STRICT));
|
||||
PlayerTraceShowData playerTraceShowData = showDataPerRegionPerPlayer
|
||||
.computeIfAbsent(region, ignored -> new HashMap<>())
|
||||
.computeIfAbsent(player, ignored -> new PlayerTraceShowData(BundleFilter.STRICT));
|
||||
|
||||
AtFlag atFlag = playerTraceShowData.getViewFlag(AtFlag.class);
|
||||
if (atFlag == null) {
|
||||
@ -282,7 +311,9 @@ public class TraceManager implements Listener {
|
||||
unfollow(player);
|
||||
|
||||
Region region = Region.getRegion(player.getLocation());
|
||||
PlayerTraceShowData playerTraceShowData = showDataPerRegionPerPlayer.computeIfAbsent(region, ignored -> new HashMap<>()).computeIfAbsent(player, ignored -> new PlayerTraceShowData(BundleFilter.STRICT));
|
||||
PlayerTraceShowData playerTraceShowData = showDataPerRegionPerPlayer
|
||||
.computeIfAbsent(region, ignored -> new HashMap<>())
|
||||
.computeIfAbsent(player, ignored -> new PlayerTraceShowData(BundleFilter.STRICT));
|
||||
|
||||
IsolateFlag isolateFlag;
|
||||
if (playerTraceShowData.hasViewFlagOnly(IsolateFlag.class)) {
|
||||
|
@ -23,7 +23,6 @@ import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.bausystem.features.tpslimit.TPSUtils;
|
||||
import de.steamwar.bausystem.region.Region;
|
||||
import de.steamwar.linkage.Linked;
|
||||
import de.steamwar.linkage.LinkedInstance;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.TNTPrimed;
|
||||
import org.bukkit.event.EventHandler;
|
||||
@ -43,16 +42,10 @@ public class TraceRecorder implements Listener {
|
||||
instance = this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Linked instance of TraceManager
|
||||
*/
|
||||
@LinkedInstance
|
||||
public TraceManager manager;
|
||||
|
||||
/**
|
||||
* Map for all traces being actively recorded
|
||||
*/
|
||||
private final Map<Region, Trace> activeTraces = new HashMap<>();
|
||||
private final Map<Region, TraceRecordingWrapper> activeTraces = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Map for all TNTs being traced, by region
|
||||
@ -64,16 +57,6 @@ public class TraceRecorder implements Listener {
|
||||
*/
|
||||
private final Map<TNTPrimed, Region> tntSpawnRegion = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Set of all active traces that no explosion has been recorded on
|
||||
*/
|
||||
private final Set<Trace> noExplosionRecorded = new HashSet<>();
|
||||
|
||||
/**
|
||||
* A map for records that have been taken in the same tick and now have to be added to the traces
|
||||
*/
|
||||
private final Map<Trace, List<TNTPoint>> recordsToAddMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Maps a tracked tnt entity to its entire recording history
|
||||
*/
|
||||
@ -109,7 +92,8 @@ public class TraceRecorder implements Listener {
|
||||
*/
|
||||
public void checkForAutoTraceFinish() {
|
||||
for (Region region : autoTraceRegions) {
|
||||
if (autoTraceRegions.contains(region) && trackedTNT.getOrDefault(region, Collections.emptyList()).size() == 0) {
|
||||
if (autoTraceRegions.contains(region)
|
||||
&& trackedTNT.getOrDefault(region, Collections.emptyList()).size() == 0) {
|
||||
stopRecording(region);
|
||||
}
|
||||
}
|
||||
@ -121,12 +105,12 @@ public class TraceRecorder implements Listener {
|
||||
* @param region region to be recorded
|
||||
*/
|
||||
public int startRecording(Region region) {
|
||||
if (activeTraces.containsKey(region)) return -1;
|
||||
Trace trace = new Trace(region);
|
||||
noExplosionRecorded.add(trace);
|
||||
activeTraces.put(region, trace);
|
||||
recordsToAddMap.put(trace, new ArrayList<>());
|
||||
return manager.add(trace);
|
||||
if (activeTraces.containsKey(region))
|
||||
return -1;
|
||||
|
||||
TraceRecordingWrapper wrappedTrace = new TraceRecordingWrapper(region);
|
||||
activeTraces.put(region, wrappedTrace);
|
||||
return TraceManager.instance.add(wrappedTrace.getTrace());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -135,17 +119,14 @@ public class TraceRecorder implements Listener {
|
||||
* @param region region to stop recording
|
||||
*/
|
||||
public void stopRecording(Region region) {
|
||||
Trace trace = activeTraces.getOrDefault(region, null);
|
||||
if (trace == null) return;
|
||||
trace.setRecords(Collections.unmodifiableList(trace.getRecords()));
|
||||
TraceRecordingWrapper wrappedTrace = activeTraces.getOrDefault(region, null);
|
||||
if (wrappedTrace == null)
|
||||
return;
|
||||
|
||||
noExplosionRecorded.remove(trace);
|
||||
activeTraces.remove(region);
|
||||
for (TNTPrimed tnt : trackedTNT.getOrDefault(region, Collections.emptyList())) {
|
||||
historyMap.remove(tnt);
|
||||
}
|
||||
|
||||
recordsToAddMap.remove(trace);
|
||||
trackedTNT.put(region, new ArrayList<>());
|
||||
}
|
||||
|
||||
@ -154,45 +135,45 @@ public class TraceRecorder implements Listener {
|
||||
*/
|
||||
private void record() {
|
||||
for (Region region : activeTraces.keySet()) {
|
||||
Trace trace = activeTraces.get(region);
|
||||
|
||||
TraceRecordingWrapper wrappedTrace = activeTraces.get(region);
|
||||
for (TNTPrimed tnt : trackedTNT.getOrDefault(region, Collections.emptyList())) {
|
||||
record(tnt, trace, Collections.emptyList());
|
||||
TNTPoint record = record(tnt, wrappedTrace, Collections.emptyList());
|
||||
wrappedTrace.addRecord(record);
|
||||
}
|
||||
|
||||
List<TNTPoint> TNTPoints = recordsToAddMap.get(trace);
|
||||
manager.addAll(trace, TNTPoints);
|
||||
TNTPoints.clear();
|
||||
wrappedTrace.commitRecorded();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal methode to record exploded tnt
|
||||
*
|
||||
* @param tntPrimed tnt exploding
|
||||
* @param trace trace to record the tnt for
|
||||
* @param tntPrimed tnt exploding
|
||||
* @param wrappedTrace the trace to record the tnt for wrapped with metadata
|
||||
* @param destroyedBlocks the blocks destoryed by the passed tnt
|
||||
* @return the record creaded of the passed tnt
|
||||
*/
|
||||
private void record(TNTPrimed tntPrimed, Trace trace, List<Block> destroyedBlocks) {
|
||||
private TNTPoint record(TNTPrimed tntPrimed, TraceRecordingWrapper wrappedTrace, List<Block> destroyedBlocks) {
|
||||
List<TNTPoint> history = historyMap.getOrDefault(tntPrimed, new ArrayList<>());
|
||||
int tntID;
|
||||
|
||||
if (history.size() == 0) {
|
||||
historyMap.put(tntPrimed, history);
|
||||
tntID = trace.getAndIncrementNextOpenRecordId();
|
||||
tntID = wrappedTrace.getNextOpenRecordIdAndIncrement();
|
||||
} else {
|
||||
tntID = history.get(0).getTntId();
|
||||
}
|
||||
|
||||
boolean isExplosion = tntPrimed.getFuseTicks() == 0;
|
||||
if (isExplosion) {
|
||||
noExplosionRecorded.remove(trace);
|
||||
wrappedTrace.activateExplosionRecorded();
|
||||
}
|
||||
boolean afterFirstExplosion = noExplosionRecorded.contains(trace);
|
||||
boolean afterFirstExplosion = wrappedTrace.isExplosionRecorded();
|
||||
|
||||
TNTPoint record = new TNTPoint(tntID, tntPrimed, isExplosion, afterFirstExplosion, TPSUtils.currentTick.get() - trace.getStartTime(), history, destroyedBlocks);
|
||||
TNTPoint record = new TNTPoint(tntID, tntPrimed, isExplosion, afterFirstExplosion,
|
||||
TPSUtils.currentTick.get() - wrappedTrace.getStartTick(), history, destroyedBlocks);
|
||||
history.add(record);
|
||||
|
||||
recordsToAddMap.get(trace).add(record);
|
||||
return record;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -203,7 +184,8 @@ public class TraceRecorder implements Listener {
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
|
||||
public void onTNTSpawn(EntitySpawnEvent event) {
|
||||
if (!(event.getEntity() instanceof TNTPrimed)) return;
|
||||
if (!(event.getEntity() instanceof TNTPrimed))
|
||||
return;
|
||||
|
||||
Region region = Region.getRegion(event.getLocation());
|
||||
|
||||
@ -219,7 +201,8 @@ public class TraceRecorder implements Listener {
|
||||
|
||||
trackedTNT.get(region).add((TNTPrimed) event.getEntity());
|
||||
tntSpawnRegion.put((TNTPrimed) event.getEntity(), region);
|
||||
record((TNTPrimed) event.getEntity(), activeTraces.get(region), Collections.emptyList());
|
||||
activeTraces.get(region).addRecord(
|
||||
record((TNTPrimed) event.getEntity(), activeTraces.get(region), Collections.emptyList()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -231,13 +214,16 @@ public class TraceRecorder implements Listener {
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
public void onTNTExplode(EntityExplodeEvent event) {
|
||||
if (!(event.getEntity() instanceof TNTPrimed)) return;
|
||||
if (!(event.getEntity() instanceof TNTPrimed))
|
||||
return;
|
||||
|
||||
Region region = tntSpawnRegion.getOrDefault((TNTPrimed) event.getEntity(), null);
|
||||
if (region == null) return;
|
||||
if (region == null)
|
||||
return;
|
||||
trackedTNT.get(region).remove((TNTPrimed) event.getEntity());
|
||||
tntSpawnRegion.remove((TNTPrimed) event.getEntity());
|
||||
|
||||
record((TNTPrimed) event.getEntity(), activeTraces.get(region), event.blockList());
|
||||
activeTraces.get(region)
|
||||
.addRecord(record((TNTPrimed) event.getEntity(), activeTraces.get(region), event.blockList()));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2024 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.features.tracer;
|
||||
|
||||
import de.steamwar.bausystem.features.tpslimit.TPSUtils;
|
||||
import de.steamwar.bausystem.region.Region;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
//TODO Rename ?
|
||||
public class TraceRecordingWrapper {
|
||||
private final Region region;
|
||||
@Getter
|
||||
private final long startTick;
|
||||
private final List<TNTPoint> recordsToAdd;
|
||||
private final List<TNTPoint> recordList;
|
||||
private ObjectOutputStream recordsOutputStream;
|
||||
private int nextOpenRecordId = 0;
|
||||
@Getter
|
||||
private boolean explosionRecorded = false;
|
||||
|
||||
@Getter
|
||||
private final Trace trace;
|
||||
|
||||
public TraceRecordingWrapper(Region region) {
|
||||
this.region = region;
|
||||
startTick = TPSUtils.currentTick.get();
|
||||
recordsToAdd = new ArrayList<>();
|
||||
recordList = new ArrayList<>();
|
||||
|
||||
trace = new Trace(region, recordList);
|
||||
TraceManager.instance.add(trace);
|
||||
File recordsSaveFile = new File(TraceManager.tracesFolder, trace.getUuid() + ".records");
|
||||
try {
|
||||
recordsOutputStream = new ObjectOutputStream(new FileOutputStream(recordsSaveFile));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public int getNextOpenRecordIdAndIncrement() {
|
||||
return nextOpenRecordId++;
|
||||
}
|
||||
|
||||
public void activateExplosionRecorded() {
|
||||
explosionRecorded = true;
|
||||
}
|
||||
|
||||
public void addRecord(TNTPoint record) {
|
||||
recordsToAdd.add(record);
|
||||
}
|
||||
|
||||
public void commitRecorded() {
|
||||
TraceManager.instance.getTraceShowDataPlayerMapping(region).forEach((key, value) -> trace.render(recordsToAdd, key, value));
|
||||
|
||||
recordsToAdd.forEach(record -> {
|
||||
try {
|
||||
recordsOutputStream.writeObject(record);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
|
||||
recordList.addAll(recordsToAdd);
|
||||
recordsToAdd.clear();
|
||||
|
||||
System.out.println(recordList);
|
||||
}
|
||||
|
||||
protected void finalizeRecording() {
|
||||
try {
|
||||
recordsOutputStream.flush();
|
||||
recordsOutputStream.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
@ -17,10 +17,8 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.features.tracer;
|
||||
package de.steamwar.bausystem.features.tracer.rendering;
|
||||
|
||||
import de.steamwar.bausystem.features.tracer.rendering.BundleFilter;
|
||||
import de.steamwar.bausystem.features.tracer.rendering.ViewFlag;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@ -42,7 +40,7 @@ public class PlayerTraceShowData {
|
||||
}
|
||||
|
||||
public Set<ViewFlag> getEffectiveViewFlags() {
|
||||
//Manage flags and required flags
|
||||
// Manage flags and required flags
|
||||
Set<ViewFlag> flagList = new HashSet<>();
|
||||
for (ViewFlag flag : viewFlags.values()) {
|
||||
flagList.add(flag);
|
||||
@ -51,7 +49,7 @@ public class PlayerTraceShowData {
|
||||
}
|
||||
}
|
||||
|
||||
//Manage inverse flags
|
||||
// Manage inverse flags
|
||||
ViewFlag.inverseFlags.forEach(viewFlag -> {
|
||||
if (!flagList.remove(viewFlag)) {
|
||||
flagList.add(viewFlag);
|
||||
@ -73,6 +71,8 @@ public class PlayerTraceShowData {
|
||||
return viewFlags.containsKey(clazz) && viewFlags.size() == 1;
|
||||
}
|
||||
|
||||
// TODO ?
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends ViewFlag> T getViewFlag(Class<T> clazz) {
|
||||
return (T) viewFlags.get(clazz);
|
||||
}
|
In neuem Issue referenzieren
Einen Benutzer sperren