From a94f5747a0bd90905a6e7be4500171b721dd3490 Mon Sep 17 00:00:00 2001 From: D4rkr34lm Date: Thu, 21 Mar 2024 14:03:20 +0100 Subject: [PATCH] Implemented trace isolate --- .../bausystem/features/tracer/Recorder.java | 19 +++--- .../bausystem/features/tracer/Trace.java | 35 ++++++---- .../features/tracer/TraceCommand.java | 66 +++++++++++++++++-- .../features/tracer/TraceManager.java | 6 ++ .../tracer/rendering/BundleFilter.java | 2 +- .../tracer/rendering/TraceEntity.java | 22 +++++++ .../features/tracer/rendering/ViewFlag.java | 44 +++++++++---- .../rendering/dynamicFlags/IsolateFlag.java | 59 +++++++++++++++++ 8 files changed, 211 insertions(+), 42 deletions(-) create mode 100644 BauSystem_Main/src/de/steamwar/bausystem/features/tracer/rendering/dynamicFlags/IsolateFlag.java diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/Recorder.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/Recorder.java index 116da2e7..30f5d0d9 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/Recorder.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/Recorder.java @@ -63,16 +63,16 @@ public class Recorder implements Listener { */ private final Set 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> recordsToAddMap = new HashMap<>(); + /** * Maps a tracked tnt entity to its entire recording history */ private final Map> historyMap = new HashMap<>(); - /** - * Maps Traces to their next open unique TNTRecord id - */ - private final Map nextOpenTNTRecordIdMap = new HashMap<>(); - /** * Regions where auto-trace is enabled */ @@ -116,7 +116,6 @@ public class Recorder implements Listener { Trace trace = new Trace(region); noExplosionRecorded.add(trace); activeTraces.put(region, trace); - nextOpenTNTRecordIdMap.put(trace, 0); return manager.add(trace); } @@ -147,7 +146,8 @@ public class Recorder implements Listener { for(TNTPrimed tnt : trackedTNT.getOrDefault(region, Collections.emptyList())){ record(tnt, trace, Collections.emptyList()); } - trace.commitAdd(); + trace.addAll(recordsToAddMap.get(trace)); + recordsToAddMap.get(trace).clear(); } } @@ -162,8 +162,7 @@ public class Recorder implements Listener { if(history.size() == 0){ historyMap.put(tntPrimed, history); - tntID = nextOpenTNTRecordIdMap.get(trace); - nextOpenTNTRecordIdMap.put(trace, tntID + 1); + tntID = trace.getAndIncrementNextOpenRecordId(); } else tntID = history.get(0).getTntId(); @@ -176,7 +175,7 @@ public class Recorder implements Listener { TNTRecord record = new TNTRecord(tntID, tntPrimed, isExplosion, afterFirstExplosion, TPSUtils.currentTick.get() - trace.getStartTime(), history, destroyedBlocks); history.add(record); - trace.add(record); + recordsToAddMap.get(trace).add(record); } /** Event for TNTs beeing spawn. diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/Trace.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/Trace.java index 705964fc..0028f6ab 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/Trace.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/Trace.java @@ -50,9 +50,10 @@ public class Trace { private List records = new ArrayList<>(); /** - * Records to be added + * ID that should be asigned to the next record of a unique tnt */ - private List newRecords = new ArrayList<>(); + @Getter + private int nextOpenRecordId = -1; /** * A map of players -> REntityServers for rendering traces to a player @@ -73,28 +74,28 @@ public class Trace { this.region = region; } - /** Methode to add a records to add staging - * - * @param records records to add + /** + * Gets and increments the next open record id + * @return next open record id */ - protected void add (TNTRecord records){ - newRecords.add(records); + protected int getAndIncrementNextOpenRecordId(){ + nextOpenRecordId++; + return nextOpenRecordId; } /** - * Commits the additions made to this trace and updates active renders of this trace + * Adds the given records and updates potential trace renderings */ - protected void commitAdd(){ - records.addAll(newRecords); + protected void addAll(List records){ + this.records.addAll(records); for(Player player: serverMap.keySet()){ REntityServer server = serverMap.get(player); BundleFilter bundleFilter = bundleFilterMap.get(player); ViewFlag[] viewFlags = viewFlagMap.get(player); - render(server, newRecords, viewFlags, bundleFilter); + render(server, records, viewFlags, bundleFilter); } - newRecords.clear(); } /** Internal methode to make records immutable after recording is finished @@ -105,8 +106,9 @@ public class Trace { this.records = records; } - /** + /** Gets the historys of all tnts in this trace * + * @return the historys of this trace */ public Set> getHistories() { Set> histories = new HashSet<>(); @@ -233,6 +235,13 @@ public class Trace { server.close(); } + /** Returns the flags used by the given player to render the trace or null if not present + * + * @param player + * @return + */ + protected ViewFlag[] getViewFlags(Player player){return viewFlagMap.get(player);} + @Override public String toString() { return "Trace{" + diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TraceCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TraceCommand.java index 51a63461..d51d7cfc 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TraceCommand.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TraceCommand.java @@ -21,20 +21,21 @@ 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.TraceEntity; import de.steamwar.bausystem.features.tracer.rendering.ViewFlag; +import de.steamwar.bausystem.features.tracer.rendering.dynamicFlags.IsolateFlag; import de.steamwar.bausystem.region.Region; import de.steamwar.command.PreviousArguments; import de.steamwar.command.SWCommand; import de.steamwar.command.TypeMapper; +import de.steamwar.command.TypeValidator; +import de.steamwar.entity.REntityServer; import de.steamwar.linkage.Linked; import de.steamwar.linkage.LinkedInstance; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; +import java.util.*; import java.util.stream.Collectors; @Linked @@ -83,12 +84,67 @@ public class TraceCommand extends SWCommand { manager.clear(); } - //TODO Manage non exsistent trace @Register(value = "delete", description = "TRACE_COMMAND_HELP_SHOW") public void delete(Player player, int id){ manager.remove(id); } + @Register(value = "isolate", description = "TRACE_COMMAND_HELP_SHOW") + public void isolate(Player player, Trace trace, @ErrorMessage("test") TNTRecord... records){ + IsolateFlag isolationFlag = null; + + ViewFlag[] viewFlags = trace.getViewFlags(player); + if(viewFlags != null) + for(ViewFlag flag: viewFlags) + if(flag.name.equals("isolate")) + isolationFlag = (IsolateFlag) flag; + + if(isolationFlag == null) + isolationFlag = new IsolateFlag(); + + for(TNTRecord record: records) + isolationFlag.toggleId(record.getTntId()); + } + + @ClassMapper(value = Trace.class, local = true) + public TypeMapper traceClassMapper(){ + return new TypeMapper() { + @Override + public Trace map(CommandSender commandSender, String[] previousArguments, String s) { + int id = Integer.parseInt(s); + + Optional trace = manager.get(id); + + return trace.orElse(null); + } + + @Override + public Collection tabCompletes(CommandSender sender, PreviousArguments previousArguments, String s) { + return manager.getAllIds().stream() + .map(id -> id.toString()) + .collect(Collectors.toList()); + } + }; + } + + @ClassMapper(value = TNTRecord.class, local = true) + public TypeMapper recordMapper() { + return new TypeMapper() { + @Override + public TNTRecord map(CommandSender commandSender, PreviousArguments previousArguments, String s) { + Trace trace = previousArguments.getFirst(Trace.class).orElse(null); + if(trace == null) return null; + + int id = Integer.parseInt(s); + + return trace.getRecords().stream() + .filter(record -> record.getTntId() == id) + .findFirst() + .orElse(null); + } + }; + } + @ClassMapper(value = BundleFilter.class, local = true) public TypeMapper bundleFilterClassMapper() { return new TypeMapper() { diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TraceManager.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TraceManager.java index ccd89e1c..c000c0b1 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TraceManager.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TraceManager.java @@ -72,6 +72,7 @@ public class TraceManager implements Listener { */ public boolean remove(int id){ if(id >= nextOpenId) return false; + if(traces.get(id) == null) return false; for(Player player: viewFlagMap.keySet()) traces.get(id).hide(player); traces.remove(id); @@ -119,6 +120,11 @@ public class TraceManager implements Listener { return new ArrayList<>(traces.values()); } + /** + * @return all ids of active traces + */ + public Set getAllIds(){return traces.keySet();} + /** Toggles trace show on for player * * @param player diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/rendering/BundleFilter.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/rendering/BundleFilter.java index 3ce9e03e..e511c923 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/rendering/BundleFilter.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/rendering/BundleFilter.java @@ -26,7 +26,7 @@ import java.util.function.BiFunction; public enum BundleFilter { - + //TODO chagne optional to true flase null LOOSE((TNTRecord a, TNTRecord b) -> { if(a.isExplosion() != b.isExplosion()) return Optional.of(false); if(a.getLocation().distance(b.getLocation()) <= BundleFilter.pixelSize) return Optional.of(false); diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/rendering/TraceEntity.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/rendering/TraceEntity.java index a930ec57..9f6439b3 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/rendering/TraceEntity.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/rendering/TraceEntity.java @@ -19,12 +19,16 @@ package de.steamwar.bausystem.features.tracer.rendering; +import de.steamwar.bausystem.BauSystem; import de.steamwar.bausystem.features.tracer.TNTRecord; import de.steamwar.entity.REntityServer; import de.steamwar.entity.RFallingBlockEntity; import lombok.Getter; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityInteractEvent; import java.util.List; @@ -40,5 +44,23 @@ public class TraceEntity extends RFallingBlockEntity { super(server, location, isExplosion ? Material.RED_STAINED_GLASS : Material.TNT); setNoGravity(true); this.records = records; + + server.setCallback(((player, rEntity, entityAction) -> { + if (entityAction != REntityServer.EntityAction.INTERACT) return; + + TNTRecord representative = records.get(0); + + BauSystem.MESSAGE.sendPrefixless("TNT_CLICK_HEADER", player); + BauSystem.MESSAGE.sendPrefixless("TNT_CLICK_FUSE_TIME", player, representative.getFuse()); + BauSystem.MESSAGE.sendPrefixless("TNT_CLICK_POSITION_X", player, representative.getLocation().getX() + ""); + BauSystem.MESSAGE.sendPrefixless("TNT_CLICK_POSITION_Y", player, representative.getLocation().getY() + ""); + BauSystem.MESSAGE.sendPrefixless("TNT_CLICK_POSITION_Z", player, representative.getLocation().getZ() + ""); + BauSystem.MESSAGE.sendPrefixless("TNT_CLICK_VELOCITY_X", player, representative.getVelocity().getX() + ""); + BauSystem.MESSAGE.sendPrefixless("TNT_CLICK_VELOCITY_Y", player, representative.getVelocity().getY() + ""); + BauSystem.MESSAGE.sendPrefixless("TNT_CLICK_VELOCITY_Z", player, representative.getVelocity().getZ() + ""); + + })); } + + } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/rendering/ViewFlag.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/rendering/ViewFlag.java index 7798a679..0a5cd21f 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/rendering/ViewFlag.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/rendering/ViewFlag.java @@ -68,7 +68,7 @@ public abstract class ViewFlag { public void modify(REntityServer server, List entities) {} }; - public static ViewFlag SOURCE = new ViewFlag(true, false, "source") { + public static ViewFlag SOURCE = new ViewFlag(true, false, IGNITE, "source") { @Override public List filter(List records) { return records.stream() @@ -107,7 +107,7 @@ public abstract class ViewFlag { public static ViewFlag MICROMOTION = new ViewFlag(true, false, "micromotion") { @Override public List filter(List records) { - Set seen = new HashSet<>(); + Set seen = new HashSet<>(); Set toRemove = new HashSet<>(); for(TNTRecord uniqueRecord: records){ @@ -146,23 +146,25 @@ public abstract class ViewFlag { @Override public void modify(REntityServer server, List entities) { for(TraceEntity entity: entities) { - TNTRecord example = entity.getRecords().get(0); + TNTRecord representaitv = entity.getRecords().get(0); - if(example.isExplosion()) continue; + if(representaitv.isExplosion()) continue; - Location pos = example.getLocation(); + Location pos = representaitv.getLocation(); - Vector xVelocity = new Vector(example.getVelocity().getX(), 0, 0); - Vector yVelocity = new Vector(0, example.getVelocity().getY(), 0); - Vector zVelocity = new Vector(0, 0, example.getVelocity().getZ()); + double xVelocity = representaitv.getVelocity().getX(); + double yVelocity = representaitv.getVelocity().getY(); + double zVelocity = representaitv.getVelocity().getZ(); - Vector firstVelocity = xVelocity.getX() >= zVelocity.getZ() ? xVelocity : zVelocity; - - pos = pos.add(yVelocity); + pos = pos.add(0,yVelocity,0); RFallingBlockEntity y = new RFallingBlockEntity(server, pos, Material.WHITE_STAINED_GLASS); y.setNoGravity(true); - pos = pos.add(firstVelocity); + if(xVelocity >= zVelocity) + pos.add(xVelocity, 0, 0); + else + pos.add(0,0,zVelocity); + RFallingBlockEntity secound = new RFallingBlockEntity(server, pos, Material.WHITE_STAINED_GLASS); secound.setNoGravity(true); } @@ -215,6 +217,11 @@ public abstract class ViewFlag { */ public final String[] aliases; + /** + * A flag that is used whenever this flag is used + */ + public final ViewFlag required; + public ViewFlag(boolean isStatic, boolean isInverse, String name, String... aliases) { this.name = name; this.aliases = aliases; @@ -222,7 +229,18 @@ public abstract class ViewFlag { flags.add(this); if(isInverse) inverseFlags.add(this); - } + required = null; + } + + public ViewFlag(boolean isStatic, boolean isInverse, ViewFlag required, String name, String... aliases){ + this.name = name; + this.aliases = aliases; + if(isStatic) + flags.add(this); + if(isInverse) + inverseFlags.add(this); + this.required = required; + } /** Filters the given records for a given condition * diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/rendering/dynamicFlags/IsolateFlag.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/rendering/dynamicFlags/IsolateFlag.java new file mode 100644 index 00000000..f112ecb6 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/rendering/dynamicFlags/IsolateFlag.java @@ -0,0 +1,59 @@ +/* + * 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 . + */ + +package de.steamwar.bausystem.features.tracer.rendering.dynamicFlags; + +import de.steamwar.bausystem.features.tracer.TNTRecord; +import de.steamwar.bausystem.features.tracer.rendering.TraceEntity; +import de.steamwar.bausystem.features.tracer.rendering.ViewFlag; +import de.steamwar.entity.REntityServer; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class IsolateFlag extends ViewFlag { + + private final List tntToIsolate = new ArrayList<>(); + + public IsolateFlag(){ + super(false, false, ViewFlag.IGNITE, "isolate"); + } + + /** + * Toggles the given id to be or not to be rendered + * @param id + */ + public void toggleId(int id){ + if(tntToIsolate.contains(id)) + tntToIsolate.remove(id); + else + tntToIsolate.add(id); + } + + @Override + public List filter(List records) { + return records.stream() + .filter(record -> tntToIsolate.contains(record.getTntId())) + .collect(Collectors.toList()); + } + + @Override + public void modify(REntityServer server, List entities) {} +}