diff --git a/BauSystem_12/src/de/steamwar/bausystem/world/TNTTracer_12.java b/BauSystem_12/src/de/steamwar/bausystem/tracer/TNTTracer_12.java similarity index 99% rename from BauSystem_12/src/de/steamwar/bausystem/world/TNTTracer_12.java rename to BauSystem_12/src/de/steamwar/bausystem/tracer/TNTTracer_12.java index 291c68b..9b28cdc 100644 --- a/BauSystem_12/src/de/steamwar/bausystem/world/TNTTracer_12.java +++ b/BauSystem_12/src/de/steamwar/bausystem/tracer/TNTTracer_12.java @@ -1,4 +1,4 @@ -package de.steamwar.bausystem.world; +package de.steamwar.bausystem.tracer; import org.bukkit.Bukkit; import org.bukkit.Location; diff --git a/BauSystem_15/src/de/steamwar/bausystem/tracer/PlayerTraceCache_15.java b/BauSystem_15/src/de/steamwar/bausystem/tracer/PlayerTraceCache_15.java new file mode 100644 index 0000000..16fc7e9 --- /dev/null +++ b/BauSystem_15/src/de/steamwar/bausystem/tracer/PlayerTraceCache_15.java @@ -0,0 +1,147 @@ +package de.steamwar.bausystem.tracer; + +import de.steamwar.bausystem.tracer.showcallback.TNTShowCallback_15; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Particle; +import org.bukkit.entity.Player; + +import static de.steamwar.bausystem.tracer.TNTTracer_15.square; + +public class PlayerTraceCache_15 { + + private static Location location; + + public static void init() { + location = new Location(Bukkit.getWorlds().get(0), 0, 0, 0); + } + + private float[] positions = new float[0]; + private float[] updatePoints = new float[0]; + + private float[] pLocation; + private float locationThreshold = square(10.0F); + + public PlayerTraceCache_15() { + this.pLocation = new float[]{0.0F, 0.0F, 0.0F}; + } + + public void setPositions(float[] positions) { + this.positions = positions; + } + + public void setUpdatePoints(float[] updatePoints) { + this.updatePoints = updatePoints; + } + + public synchronized boolean nearLastLocation(Player player) { + float x = (float)player.getLocation().getX(); + float y = (float)player.getLocation().getY(); + float z = (float)player.getLocation().getZ(); + + if (square(pLocation[0] - x) + square(pLocation[1] - y) + square(pLocation[2] - z) > locationThreshold) { + pLocation[0] = x; + pLocation[1] = y; + pLocation[2] = z; + return true; + } + return false; + } + + public synchronized void show(Player player, TNTShowCallback_15.ShowMode showMode) { + if (positions.length == 0 || positions.length % 3 != 0) return; + for (int i = 0; i < positions.length; i += 3) { + float x = positions[i + 0]; + float y = positions[i + 1]; + float z = positions[i + 2]; + + if (showMode == TNTShowCallback_15.ShowMode.PARTICLE && positions.length / 3 < 1000) { + showCorner(player, x - 0.49F, y, z - 0.49F, Particle.FLAME); + } else { + showBlock(player, x, y + 0.49F, z, Material.RED_STAINED_GLASS, (byte) 14); + } + } + + if (positions.length / 3 >= 1000) { + return; + } + + if (updatePoints.length == 0 || updatePoints.length % 3 != 0) return; + for (int i = 0; i < updatePoints.length; i += 3) { + float x = updatePoints[i + 0]; + float y = updatePoints[i + 1]; + float z = updatePoints[i + 2]; + + if (hasBlock(positions, x, y, z)) continue; + + if (showMode == TNTShowCallback_15.ShowMode.PARTICLE) { + showCorner(player, x - 0.49F, y, z - 0.49F, Particle.VILLAGER_HAPPY); + } else { + showBlock(player, x, y + 0.49F, z, Material.LIME_STAINED_GLASS, (byte) 5); + } + } + } + + public synchronized void hide(Player player) { + if (positions.length == 0 || positions.length % 3 != 0) return; + for (int i = 0; i < positions.length; i += 3) { + float x = positions[i + 0]; + float y = positions[i + 1]; + float z = positions[i + 2]; + + hideBlock(player, x, y + 0.49F, z); + } + + if (updatePoints.length == 0 || updatePoints.length % 3 != 0) return; + for (int i = 0; i < updatePoints.length; i += 3) { + float x = updatePoints[i + 0]; + float y = updatePoints[i + 1]; + float z = updatePoints[i + 2]; + + hideBlock(player, x, y + 0.49F, z); + } + updatePoints = new float[0]; + } + + private static void showCorner(Player player, float x, float y, float z, Particle particle) { + player.spawnParticle(particle, makeLocation(x + 0.00F, y + 0.00F, z + 0.00F), 1, 0F, 0F, 0F, 0.001); + player.spawnParticle(particle, makeLocation(x + 0.98F, y + 0.00F, z + 0.00F), 1, 0F, 0F, 0F, 0.001); + player.spawnParticle(particle, makeLocation(x + 0.00F, y + 0.00F, z + 0.98F), 1, 0F, 0F, 0F, 0.001); + player.spawnParticle(particle, makeLocation(x + 0.98F, y + 0.00F, z + 0.98F), 1, 0F, 0F, 0F, 0.001); + + player.spawnParticle(particle, makeLocation(x + 0.00F, y + 0.98F, z + 0.00F), 1, 0F, 0F, 0F, 0.001); + player.spawnParticle(particle, makeLocation(x + 0.98F, y + 0.98F, z + 0.00F), 1, 0F, 0F, 0F, 0.001); + player.spawnParticle(particle, makeLocation(x + 0.00F, y + 0.98F, z + 0.98F), 1, 0F, 0F, 0F, 0.001); + player.spawnParticle(particle, makeLocation(x + 0.98F, y + 0.98F, z + 0.98F), 1, 0F, 0F, 0F, 0.001); + } + + private static void showBlock(Player p, float x, float y, float z, Material block, byte b) { + if (makeLocation(x, y, z).getBlock().getType() == Material.AIR) { + p.sendBlockChange(makeLocation(x, y, z), block, b); + } + } + + private static void hideBlock(Player p, float x, float y, float z) { + if (makeLocation(x, y, z).getBlock().getType() == Material.AIR) { + p.sendBlockChange(makeLocation(x, y, z), Material.AIR, (byte) 0); + } + } + + private static boolean hasBlock(float[] floats, float x, float y, float z) { + for (int i = 0; i < floats.length; i += 3) { + if (square(floats[i + 0] - x) + square(floats[i + 1] - y) + square(floats[i + 2] - z) < 1) { + return true; + } + } + return false; + } + + private static Location makeLocation(float x, float y, float z) { + location.setX(x); + location.setY(y); + location.setZ(z); + return location; + } + +} diff --git a/BauSystem_15/src/de/steamwar/bausystem/tracer/TNTTracerGUI_15.java b/BauSystem_15/src/de/steamwar/bausystem/tracer/TNTTracerGUI_15.java new file mode 100644 index 0000000..fa2664a --- /dev/null +++ b/BauSystem_15/src/de/steamwar/bausystem/tracer/TNTTracerGUI_15.java @@ -0,0 +1,95 @@ +package de.steamwar.bausystem.tracer; + +import de.steamwar.bausystem.tracer.guicallback.RecordingCallback_15; +import de.steamwar.bausystem.tracer.guicallback.TNTFrameCallback_15; +import de.steamwar.bausystem.tracer.guicallback.TNTTraceCallback_15; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemFlag; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.Arrays; +import java.util.List; + +public class TNTTracerGUI_15 { + + private static TNTFrameCallback_15 tntFrameCallback_15; + private static TNTTraceCallback_15 tntTraceCallback_15; + private static RecordingCallback_15 recordingCallback_15; + + private static Inventory getEmpty(String title) { + Inventory inventory = Bukkit.createInventory(null, 54, title); + ItemStack i1 = createItem(Material.LIGHT_GRAY_STAINED_GLASS_PANE, false, ""); + for (int i = 0; i < 9; i++) { + inventory.setItem(i, i1); + } + ItemStack i2 = createItem(Material.RED_STAINED_GLASS, false, ""); + for (int i = 9; i < 54; i++) { + inventory.setItem(i, i2); + } + return inventory; + } + + public static ItemStack createItem(Material material, boolean selected, String name, String... lore) { + ItemStack item = new ItemStack(material, 1); + ItemMeta im = item.getItemMeta(); + + if (im == null) return item; + if (name == null) name = "§f"; + if (name.isEmpty()) name = "§f"; + im.setDisplayName(name); + if (selected) { + im.addEnchant(Enchantment.PROTECTION_ENVIRONMENTAL, 1, true); + } + im.addItemFlags(ItemFlag.HIDE_ENCHANTS); + + if (lore != null) { + List lorelist = Arrays.asList(lore); + im.setLore(lorelist); + } + + item.setItemMeta(im); + return item; + } + + private static void frameControls(Inventory inventory, int page, int allPages) { + inventory.setItem(1, createItem(Material.HONEYCOMB, false, "§eShow§8/§eHide")); + inventory.setItem(4, createItem(Material.BARRIER, false, "§eClear ausgewählte Positionen")); + inventory.setItem(5, createItem(Material.OBSERVER, false, "§eToggle AUTO-Trace")); + inventory.setItem(6, recordingCallback_15.run()); + inventory.setItem(8, createItem(Material.PAPER, false, "§7PAGE §e§l" + page + "§8/§e§l" + allPages)); + } + + private static Inventory getFrameInventory(Player p, int page) { + ItemStack[] items = tntFrameCallback_15.run(p); + + Inventory inventory = getEmpty("§7§lTRACE §8- §e§lAufnahmen"); + if (items.length == 0) { + frameControls(inventory, page + 1, 1); + } else { + frameControls(inventory, page + 1, items.length / 45 + (items.length % 45 == 0 ? 0 : 1)); + } + return inventory; + } + + public static void init(TNTFrameCallback_15 tntFrameCallback_15, TNTTraceCallback_15 tntTraceCallback_15, RecordingCallback_15 recordingCallback_15) { + TNTTracerGUI_15.tntFrameCallback_15 = tntFrameCallback_15; + TNTTracerGUI_15.tntTraceCallback_15 = tntTraceCallback_15; + TNTTracerGUI_15.recordingCallback_15 = recordingCallback_15; + } + + public enum Menu { + FRAME, + TRACE, + BLOCK + } + + public static void show(Player p, int page, Menu menu) { + + } + +} diff --git a/BauSystem_15/src/de/steamwar/bausystem/tracer/TNTTracer_15.java b/BauSystem_15/src/de/steamwar/bausystem/tracer/TNTTracer_15.java new file mode 100644 index 0000000..5c1cc63 --- /dev/null +++ b/BauSystem_15/src/de/steamwar/bausystem/tracer/TNTTracer_15.java @@ -0,0 +1,157 @@ +package de.steamwar.bausystem.tracer; + +import de.steamwar.bausystem.tracer.showcallback.*; +import net.md_5.bungee.api.ChatMessageType; +import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.entity.TNTPrimed; +import org.bukkit.plugin.Plugin; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.Map; + +class TNTTracer_15 { + + private TNTTracer_15(){} + + private static TracerCallback_15 tracerCallback; + private static TracerCallbackUpdatePoints_15 tracerCallbackUpdatePoints; + private static TracerActionBarCallback_15 tracerActionBarCallback; + private static TNTShowCallback_15 tntShowCallback; + private static CacheUpdateCallback_15 cacheUpdateCallback; + + private static Map playerMap = new HashMap<>(); + + private static boolean actionBar = false; + + private static final float showRadius = square(50.0F); + + private static class Synchronizer {} + + private static final Synchronizer synchronizer = new Synchronizer(); + + public static float square(float d) { + return d * d; + } + + static void init(Plugin plugin, TracerCallback_15 tracerCallback, TracerCallbackUpdatePoints_15 tracerCallbackUpdatePoints, TracerActionBarCallback_15 tracerActionBarCallback, TNTShowCallback_15 tntShowCallback, CacheUpdateCallback_15 cacheUpdateCallback) { + Bukkit.getScheduler().runTaskTimer(plugin, () -> { + synchronized (synchronizer) { + synchronizer.notifyAll(); + } + }, 1, 20); + Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { + while (true) { + synchronized (synchronizer) { + try { + synchronizer.wait(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + run(); + } + }); + + TNTTracer_15.tracerCallback = tracerCallback; + TNTTracer_15.tracerCallbackUpdatePoints = tracerCallbackUpdatePoints; + TNTTracer_15.tracerActionBarCallback = tracerActionBarCallback; + TNTTracer_15.tntShowCallback = tntShowCallback; + TNTTracer_15.cacheUpdateCallback = cacheUpdateCallback; + } + + static void initWorld() { + PlayerTraceCache_15.init(); + } + + static boolean isInWater(TNTPrimed tnt) { + return tnt.getLocation().getBlock().getType() == Material.WATER; + } + + private static void run() { + if (actionBar) { + String actionBar = tracerActionBarCallback.run(); + Bukkit.getOnlinePlayers().forEach(player -> player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(actionBar))); + } + for (Player p : Bukkit.getOnlinePlayers()) { + PlayerTraceCache_15 traceCache; + if (!playerMap.containsKey(p)) { + traceCache = new PlayerTraceCache_15(); + playerMap.put(p, traceCache); + } else { + traceCache = playerMap.get(p); + } + + if (!traceCache.nearLastLocation(p) && !cacheUpdateCallback.run(p)) { + traceCache.show(p, tntShowCallback.run(p)); + continue; + } + + update(p, traceCache); + traceCache.show(p, tntShowCallback.run(p)); + } + } + + private static float[] noValue = new float[0]; + + private static void update(Player p, PlayerTraceCache_15 traceCache) { + float[] floats = tracerCallback.run(p); + if (floats.length == 0 || floats.length % 3 != 0) { + traceCache.setPositions(noValue); + traceCache.setUpdatePoints(noValue); + return; + } + + Location location = p.getLocation(); + float px = (float)location.getX(); + float py = (float)location.getY(); + float pz = (float)location.getZ(); + + traceCache.setPositions(accumulatePositions(floats, px, py, pz)); + + floats = tracerCallbackUpdatePoints.run(p); + if (floats.length == 0 || floats.length % 3 != 0) { + traceCache.setUpdatePoints(noValue); + return; + } + + traceCache.setUpdatePoints(accumulatePositions(floats, px, py, pz)); + } + + private static float[] accumulatePositions(float[] floats, float px, float py, float pz) { + LinkedList linkedList = new LinkedList<>(); + + for (int i = 0; i < floats.length; i += 3) { + float x = floats[i + 0]; + float y = floats[i + 1]; + float z = floats[i + 2]; + + if (square(x - px) + square(y + 0.49F - py) + square(z - pz) > showRadius) continue; + + linkedList.add(x); + linkedList.add(y); + linkedList.add(z); + } + + float[] result = new float[linkedList.size()]; + Iterator floatIterator = linkedList.iterator(); + int index = 0; + while (floatIterator.hasNext()) { + result[index] = floatIterator.next(); + index++; + } + return result; + } + + static void hide(Player p) { + PlayerTraceCache_15 tracerCache15 = playerMap.get(p); + if (tracerCache15 == null) return; + tracerCache15.hide(p); + } + +} diff --git a/BauSystem_15/src/de/steamwar/bausystem/tracer/guicallback/RecordingCallback_15.java b/BauSystem_15/src/de/steamwar/bausystem/tracer/guicallback/RecordingCallback_15.java new file mode 100644 index 0000000..91bb725 --- /dev/null +++ b/BauSystem_15/src/de/steamwar/bausystem/tracer/guicallback/RecordingCallback_15.java @@ -0,0 +1,10 @@ +package de.steamwar.bausystem.tracer.guicallback; + +import org.bukkit.inventory.ItemStack; + +@FunctionalInterface +public interface RecordingCallback_15 { + + ItemStack run(); + +} diff --git a/BauSystem_15/src/de/steamwar/bausystem/tracer/guicallback/TNTFrameCallback_15.java b/BauSystem_15/src/de/steamwar/bausystem/tracer/guicallback/TNTFrameCallback_15.java new file mode 100644 index 0000000..d06da2d --- /dev/null +++ b/BauSystem_15/src/de/steamwar/bausystem/tracer/guicallback/TNTFrameCallback_15.java @@ -0,0 +1,11 @@ +package de.steamwar.bausystem.tracer.guicallback; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +@FunctionalInterface +public interface TNTFrameCallback_15 { + + ItemStack[] run(Player p); + +} diff --git a/BauSystem_15/src/de/steamwar/bausystem/tracer/guicallback/TNTTraceCallback_15.java b/BauSystem_15/src/de/steamwar/bausystem/tracer/guicallback/TNTTraceCallback_15.java new file mode 100644 index 0000000..46b5d93 --- /dev/null +++ b/BauSystem_15/src/de/steamwar/bausystem/tracer/guicallback/TNTTraceCallback_15.java @@ -0,0 +1,11 @@ +package de.steamwar.bausystem.tracer.guicallback; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +@FunctionalInterface +public interface TNTTraceCallback_15 { + + ItemStack[] run(Player p); + +} diff --git a/BauSystem_15/src/de/steamwar/bausystem/tracer/showcallback/CacheUpdateCallback_15.java b/BauSystem_15/src/de/steamwar/bausystem/tracer/showcallback/CacheUpdateCallback_15.java new file mode 100644 index 0000000..f05d2cb --- /dev/null +++ b/BauSystem_15/src/de/steamwar/bausystem/tracer/showcallback/CacheUpdateCallback_15.java @@ -0,0 +1,10 @@ +package de.steamwar.bausystem.tracer.showcallback; + +import org.bukkit.entity.Player; + +@FunctionalInterface +public interface CacheUpdateCallback_15 { + + boolean run(Player p); + +} diff --git a/BauSystem_15/src/de/steamwar/bausystem/tracer/showcallback/TNTShowCallback_15.java b/BauSystem_15/src/de/steamwar/bausystem/tracer/showcallback/TNTShowCallback_15.java new file mode 100644 index 0000000..4a874c6 --- /dev/null +++ b/BauSystem_15/src/de/steamwar/bausystem/tracer/showcallback/TNTShowCallback_15.java @@ -0,0 +1,15 @@ +package de.steamwar.bausystem.tracer.showcallback; + +import org.bukkit.entity.Player; + +@FunctionalInterface +public interface TNTShowCallback_15 { + + public static enum ShowMode { + BLOCK, + PARTICLE + } + + ShowMode run(Player p); + +} diff --git a/BauSystem_15/src/de/steamwar/bausystem/tracer/showcallback/TracerActionBarCallback_15.java b/BauSystem_15/src/de/steamwar/bausystem/tracer/showcallback/TracerActionBarCallback_15.java new file mode 100644 index 0000000..adc5cef --- /dev/null +++ b/BauSystem_15/src/de/steamwar/bausystem/tracer/showcallback/TracerActionBarCallback_15.java @@ -0,0 +1,8 @@ +package de.steamwar.bausystem.tracer.showcallback; + +@FunctionalInterface +public interface TracerActionBarCallback_15 { + + String run(); + +} diff --git a/BauSystem_15/src/de/steamwar/bausystem/tracer/showcallback/TracerCallbackUpdatePoints_15.java b/BauSystem_15/src/de/steamwar/bausystem/tracer/showcallback/TracerCallbackUpdatePoints_15.java new file mode 100644 index 0000000..7d810c3 --- /dev/null +++ b/BauSystem_15/src/de/steamwar/bausystem/tracer/showcallback/TracerCallbackUpdatePoints_15.java @@ -0,0 +1,10 @@ +package de.steamwar.bausystem.tracer.showcallback; + +import org.bukkit.entity.Player; + +@FunctionalInterface +public interface TracerCallbackUpdatePoints_15 { + + float[] run(Player p); + +} diff --git a/BauSystem_15/src/de/steamwar/bausystem/tracer/showcallback/TracerCallback_15.java b/BauSystem_15/src/de/steamwar/bausystem/tracer/showcallback/TracerCallback_15.java new file mode 100644 index 0000000..9f36e06 --- /dev/null +++ b/BauSystem_15/src/de/steamwar/bausystem/tracer/showcallback/TracerCallback_15.java @@ -0,0 +1,10 @@ +package de.steamwar.bausystem.tracer.showcallback; + +import org.bukkit.entity.Player; + +@FunctionalInterface +public interface TracerCallback_15 { + + float[] run(Player p); + +} diff --git a/BauSystem_15/src/de/steamwar/bausystem/world/TNTTracer_15.java b/BauSystem_15/src/de/steamwar/bausystem/world/TNTTracer_15.java deleted file mode 100644 index 306342b..0000000 --- a/BauSystem_15/src/de/steamwar/bausystem/world/TNTTracer_15.java +++ /dev/null @@ -1,38 +0,0 @@ -package de.steamwar.bausystem.world; - -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.entity.TNTPrimed; - -import java.util.LinkedList; -import java.util.Map; -import java.util.Set; - -class TNTTracer_15 { - private TNTTracer_15(){} - - static void remove(Map> locations, TNTPrimed tnt){ - Material material = tnt.getLocation().getBlock().getType(); - if(material == Material.WATER) - locations.remove(tnt); - } - - static int show(Map> locations, Set printedLocs){ - - for(LinkedList tntTrace : locations.values()){ - for(Location location : tntTrace){ - if(location.getBlock().getType() == Material.AIR){ - location.getBlock().setType(Material.RED_STAINED_GLASS); - printedLocs.add(location); - } - } - } - locations.clear(); - return printedLocs.size(); - } - - static boolean airOrBrick(Block block){ - return block.getType() == Material.RED_STAINED_GLASS; - } -} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java b/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java index f60499f..16a81d8 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java @@ -1,6 +1,9 @@ package de.steamwar.bausystem; import de.steamwar.bausystem.commands.*; +import de.steamwar.bausystem.tracer.TNTListener; +import de.steamwar.bausystem.tracer.TNTTracer15; +import de.steamwar.bausystem.tracer.trace.ShowManager; import de.steamwar.bausystem.world.*; import de.steamwar.core.CommandRemover; import de.steamwar.core.Core; @@ -75,6 +78,7 @@ public class BauSystem extends JavaPlugin implements Listener { } getCommand("trace").setExecutor(new CommandTrace()); + getCommand("trace").setTabCompleter(new CommandTraceTabCompleter()); getCommand("nightvision").setExecutor(new CommandNV()); getCommand("reset").setExecutor(new CommandReset()); getCommand("speed").setExecutor(new CommandSpeed()); @@ -94,6 +98,9 @@ public class BauSystem extends JavaPlugin implements Listener { Bukkit.getPluginManager().registerEvents(new TNTListener(), this); Bukkit.getPluginManager().registerEvents(new BauScoreboard(), this); new AFKStopper(); + if (Core.getVersion() == 15) { + TNTTracer15.initTNTTracer_15(); + } autoShutdown = Bukkit.getScheduler().runTaskLater(this, Bukkit::shutdown, 1200); } @@ -257,14 +264,20 @@ public class BauSystem extends JavaPlugin implements Listener { attachment.setPermission("worldedit.extinguish", true); attachment.setPermission("worldedit.calc", true); attachment.setPermission("worldedit.fill", true);*/ + + if (Core.getVersion() == 15) ShowManager.add(p); } @EventHandler public void onLeave(PlayerQuitEvent e) { Player player = e.getPlayer(); SWScoreboard.removeScoreboard(player); - if(Bukkit.getOnlinePlayers().isEmpty() || (Bukkit.getOnlinePlayers().size() == 1 && Bukkit.getOnlinePlayers().contains(player))) + if (Bukkit.getOnlinePlayers().isEmpty() || (Bukkit.getOnlinePlayers().size() == 1 && Bukkit.getOnlinePlayers().contains(player))) { Bukkit.shutdown(); + return; + } + + if (Core.getVersion() == 15) ShowManager.remove(e.getPlayer()); } @EventHandler diff --git a/BauSystem_Main/src/de/steamwar/bausystem/commands/CommandTrace.java b/BauSystem_Main/src/de/steamwar/bausystem/commands/CommandTrace.java index 5fbdae4..22eb928 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/commands/CommandTrace.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/commands/CommandTrace.java @@ -2,8 +2,12 @@ package de.steamwar.bausystem.commands; import de.steamwar.bausystem.BauSystem; import de.steamwar.bausystem.Permission; -import de.steamwar.bausystem.world.TNTTracer; +import de.steamwar.bausystem.tracer.TNTTracer12; +import de.steamwar.bausystem.tracer.TNTTracer15; +import de.steamwar.bausystem.tracer.trace.ShowManager; +import de.steamwar.bausystem.tracer.trace.ShowStatus; import de.steamwar.bausystem.world.Welt; +import de.steamwar.core.Core; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; @@ -11,44 +15,233 @@ import org.bukkit.entity.Player; public class CommandTrace implements CommandExecutor { - private void help(Player player){ + private void help12(Player player) { player.sendMessage("§8/§etrace start §8- §7Startet die Aufnahme aller TNT-Positionen"); player.sendMessage("§8/§etrace show §8- §7Zeigt alle TNT-Positionen"); player.sendMessage("§8/§etrace stop §8- §7Stoppt den TNT-Tracer"); } + private void help15(Player player) { + player.sendMessage("§8/§etrace start §8- §7Startet die Aufnahme aller TNT-Positionen"); + player.sendMessage("§8/§etrace stop §8- §7Stoppt den TNT-Tracer"); + player.sendMessage("§8/§etrace toggleauto §8- §7Automatischer Aufnahmenstart"); + player.sendMessage("§8/§etrace togglewater §8- §7Tracet auch TNT im Wasser"); + player.sendMessage("§8/§etrace show §8<§eblock§8|§eparticle§8|§7TNT-ID§8> §8- §7Zeigt alle TNT-Positionen"); + player.sendMessage("§8/§etrace hide §8<§7TNT-ID§8> §8- §7Versteckt alle TNT-Positionen"); + player.sendMessage("§8/§etrace toggleshow §8<§7TNT-ID§8> §8- §7Zeigt/Versteckt ein TNT"); + player.sendMessage("§8/§etrace delete §8<§7TNT-ID§8> §8- §7Löscht alle TNT-Positionen"); + player.sendMessage("§8/§etrace interpolate §8[§eall§8|§eyaxis§8|§enone§8] §8- §7Interpolationsoptionen"); + player.sendMessage("§8/§etrace list §8<§7FRAME-ID§8>§8- §7Listet alle TNT auf"); + //player.sendMessage("§8/§etrace gui §8- §7Zeigt die Trace Oberfläche an"); + player.sendMessage("§7Optionale Parameter mit §8<>§7, Benötigte Parameter mit §8[]"); + } + @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if(!(sender instanceof Player)) - return false; + if(!(sender instanceof Player)) return false; Player player = (Player) sender; - if(args.length == 0){ - help(player); - return false; + switch (Core.getVersion()) { + case 15: + return tracer15(player, args); + default: + return tracer12(player, args); } + } + private boolean permissionCheck(Player player) { if(Welt.noPermission(player, Permission.world)){ player.sendMessage(BauSystem.PREFIX + "§cDu darfst hier nicht den TNT-Tracer nutzen"); return false; } + return true; + } + + private boolean tracer12(Player player, String[] args) { + if(args.length == 0){ + help12(player); + return false; + } + + if (!permissionCheck(player)) return false; switch(args[0].toLowerCase()){ case "start": - TNTTracer.start(); + TNTTracer12.start(); player.sendMessage(BauSystem.PREFIX + "§aAufnahme gestartet"); break; case "show": - int blocks = TNTTracer.show(); + int blocks = TNTTracer12.show(); player.sendMessage(BauSystem.PREFIX + "§a" + blocks + " TNT-Positionen angezeigt"); break; case "stop": - TNTTracer.stop(); + TNTTracer12.stop(); player.sendMessage(BauSystem.PREFIX + "§cTNT-Tracer gestoppt"); break; default: - help(player); + help12(player); } return false; } + + private boolean tracer15(Player player, String[] args) { + if(args.length == 0){ + help15(player); + return false; + } + + if (!permissionCheck(player)) return false; + + switch(args[0].toLowerCase()){ + case "start": + if (TNTTracer15.getStatus() == TNTTracer15.Status.IDLE_AUTO || TNTTracer15.getStatus() == TNTTracer15.Status.RECORD_AUTO) { + TNTTracer15.toggleAuto(); + } + TNTTracer15.start(); + player.sendMessage(BauSystem.PREFIX + "§aAufnahme gestartet"); + break; + case "stop": + if (TNTTracer15.getStatus() == TNTTracer15.Status.IDLE_AUTO || TNTTracer15.getStatus() == TNTTracer15.Status.RECORD_AUTO) { + TNTTracer15.toggleAuto(); + } + TNTTracer15.stop(); + player.sendMessage(BauSystem.PREFIX + "§cTNT-Tracer gestoppt"); + break; + case "toggleauto": + boolean mode = TNTTracer15.toggleAuto(); + if (mode) { + player.sendMessage(BauSystem.PREFIX + "§aAutomatischer TNT-Tracer aktiviert"); + } else { + player.sendMessage(BauSystem.PREFIX + "§cAutomatischer TNT-Tracer deaktiviert"); + } + break; + case "togglewater": + mode = TNTTracer15.toggleRemoveInWater(); + if (mode) { + player.sendMessage(BauSystem.PREFIX + "§aTraces im Wasser werden gelöscht"); + } else { + player.sendMessage(BauSystem.PREFIX + "§cTraces im Wasser werden behalten"); + } + break; + case "show": + if (args.length == 2) { + switch (args[1].toLowerCase()) { + case "block": + case "blocks": + ShowManager.get(player).setShowMode(ShowStatus.ShowMode.BLOCK); + break; + case "particle": + case "particles": + TNTTracer15.hideBlockTraces(player); + ShowManager.get(player).setShowMode(ShowStatus.ShowMode.PARTICLE); + break; + default: + try { + int tntID = Integer.parseInt(args[1]); + ShowManager.get(player).addSelection(tntID); + player.sendMessage(BauSystem.PREFIX + "§aTNT-Positionen des TNT mit ID " + tntID + " angezeigt"); + player.sendMessage(BauSystem.PREFIX + "§eBei zu vielen zu zeigenden Positionen wird der Block Tracer aktiviert"); + player.sendMessage(BauSystem.PREFIX + "§eBitte aktiviere animiertes Feuer in den Grafikeinstellungen"); + } catch (NumberFormatException e) { + help15(player); + } + return false; + } + } + ShowManager.get(player).show(); + player.sendMessage(BauSystem.PREFIX + "§aAlle TNT-Positionen angezeigt"); + player.sendMessage(BauSystem.PREFIX + "§eBei zu vielen zu zeigenden Positionen wird der Block Tracer aktiviert"); + player.sendMessage(BauSystem.PREFIX + "§eBitte aktiviere animiertes Feuer in den Grafikeinstellungen"); + break; + case "hide": + if (args.length == 2) { + try { + int tntID = Integer.parseInt(args[1]); + ShowManager.get(player).removeSelection(tntID); + player.sendMessage(BauSystem.PREFIX + "§aTNT-Positionen des TNT mit ID " + tntID + " versteckt"); + } catch (NumberFormatException e) { + help15(player); + } + return false; + } + ShowManager.get(player).hide(); + player.sendMessage(BauSystem.PREFIX + "§aAlle TNT-Positionen versteckt"); + break; + case "toggleshow": + if (args.length == 2) { + try { + int tntID = Integer.parseInt(args[1]); + mode = ShowManager.get(player).toggleShow(tntID); + if (mode) { + player.sendMessage(BauSystem.PREFIX + "§aTNT-Positionen des TNT mit ID " + tntID + " angezeigt"); + } else { + player.sendMessage(BauSystem.PREFIX + "§aTNT-Positionen des TNT mit ID " + tntID + " versteckt"); + } + } catch (NumberFormatException e) { + help15(player); + } + } else { + help15(player); + } + break; + case "delete": + if (args.length == 2) { + try { + int tntID = Integer.parseInt(args[1]); + ShowManager.removeTrace(tntID); + TNTTracer15.remove(tntID); + player.sendMessage(BauSystem.PREFIX + "§cTNT-Positionen mit ID " + tntID + " gelöscht"); + } catch (NumberFormatException e) { + help15(player); + } + return false; + } + TNTTracer15.clear(); + player.sendMessage(BauSystem.PREFIX + "§cAlle TNT-Positionen gelöscht"); + break; + case "interpolate": + if (args.length != 2) { + help15(player); + return false; + } + switch (args[1].toLowerCase()) { + case "none": + TNTTracer15.hideBlockTraces(player); + ShowManager.get(player).setUpdatePoints(ShowStatus.UpdatePoints.NONE); + player.sendMessage(BauSystem.PREFIX + "§aInterpolation auf §enone §agesetzt"); + break; + case "yaxis": + TNTTracer15.hideBlockTraces(player); + ShowManager.get(player).setUpdatePoints(ShowStatus.UpdatePoints.Y_AXIS); + player.sendMessage(BauSystem.PREFIX + "§aInterpolation auf §eyaxis §agesetzt"); + break; + case "all": + ShowManager.get(player).setUpdatePoints(ShowStatus.UpdatePoints.ALL); + player.sendMessage(BauSystem.PREFIX + "§aInterpolation auf §eall §agesetzt"); + break; + default: + help15(player); + break; + } + break; + case "list": + if (args.length == 2) { + try { + TNTTracer15.printFrames(player, Integer.parseInt(args[1])); + } catch (NumberFormatException e) { + help15(player); + } + return false; + } + TNTTracer15.printList(player); + break; + case "gui": + //player.sendMessage(BauSystem.PREFIX + "§cNoch in Bau"); + //break; + default: + help15(player); + } + return false; + } + } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/commands/CommandTraceTabCompleter.java b/BauSystem_Main/src/de/steamwar/bausystem/commands/CommandTraceTabCompleter.java new file mode 100644 index 0000000..cebbd09 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/commands/CommandTraceTabCompleter.java @@ -0,0 +1,76 @@ +package de.steamwar.bausystem.commands; + +import de.steamwar.bausystem.tracer.TNTTracer15; +import de.steamwar.core.Core; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class CommandTraceTabCompleter implements TabCompleter { + + @Override + public List onTabComplete(CommandSender sender, Command command, String label, String[] args) { + if(!(sender instanceof Player)) return new ArrayList<>(); + Player player = (Player) sender; + + switch (Core.getVersion()) { + case 15: + return tracer15TabComplete(player, args); + default: + return tracer12TabComplete(player, args); + } + } + + private List tracer12TabComplete(Player player, String[] args) { + List tabComplete = new ArrayList<>(); + tabComplete.add("start"); + tabComplete.add("show"); + tabComplete.add("stop"); + + return manageList(tabComplete, args, 0); + } + + private List tracer15TabComplete(Player player, String[] args) { + List tabComplete = new ArrayList<>(); + if (TNTTracer15.getStatus() == TNTTracer15.Status.IDLE || TNTTracer15.getStatus() == TNTTracer15.Status.IDLE_AUTO) { + tabComplete.add("start"); + } else { + tabComplete.add("stop"); + } + tabComplete.add("toggleauto"); + tabComplete.add("togglewater"); + tabComplete.add("toggleshow"); + tabComplete.add("show"); + if (args[0].equalsIgnoreCase("show") && args.length == 2) { + return manageList(new ArrayList<>(Arrays.asList("block", "particle")), args, 1); + } + tabComplete.add("hide"); + tabComplete.add("delete"); + tabComplete.add("interpolate"); + if (args[0].equalsIgnoreCase("interpolate") && args.length == 2) { + return manageList(new ArrayList<>(Arrays.asList("all", "yaxis", "none")), args, 1); + } + //tabComplete.add("gui"); + tabComplete.add("list"); + + if (args.length == 2) { + return new ArrayList<>(); + } + return manageList(tabComplete, args, 0); + } + + private List manageList(List strings, String[] args, int index) { + for (int i = strings.size() - 1; i >= 0; i--) { + if (!strings.get(i).startsWith(args[index])) { + strings.remove(i); + } + } + return strings; + } + +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/tracer/TNTListener.java b/BauSystem_Main/src/de/steamwar/bausystem/tracer/TNTListener.java new file mode 100644 index 0000000..04fa1bb --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/tracer/TNTListener.java @@ -0,0 +1,36 @@ +package de.steamwar.bausystem.tracer; + +import de.steamwar.core.Core; +import org.bukkit.entity.TNTPrimed; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityExplodeEvent; + +public class TNTListener implements Listener { + + @EventHandler + public void onEntityExplode(EntityExplodeEvent event) { + switch (Core.getVersion()) { + case 15: + onEntityExplode15(event); + break; + default: + onEntityExplode12(event); + } + } + + private void onEntityExplode12(EntityExplodeEvent event) { + if(TNTTracer12.getStatus() != TNTTracer12.Status.RECORD) return; + if(!(event.getEntity() instanceof TNTPrimed)) return; + TNTPrimed entity = (TNTPrimed) event.getEntity(); + TNTTracer12.remove(entity); + } + + private void onEntityExplode15(EntityExplodeEvent event) { + if(!(event.getEntity() instanceof TNTPrimed)) return; + if (TNTTracer15.getStatus() == TNTTracer15.Status.IDLE_AUTO || TNTTracer15.getStatus() == TNTTracer15.Status.RECORD_AUTO) { + TNTTracer15.start(); + } + TNTTracer15.explode((TNTPrimed) event.getEntity()); + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/world/TNTTracer.java b/BauSystem_Main/src/de/steamwar/bausystem/tracer/TNTTracer12.java similarity index 63% rename from BauSystem_Main/src/de/steamwar/bausystem/world/TNTTracer.java rename to BauSystem_Main/src/de/steamwar/bausystem/tracer/TNTTracer12.java index 6b5c831..37fc4fb 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/world/TNTTracer.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/tracer/TNTTracer12.java @@ -1,4 +1,4 @@ -package de.steamwar.bausystem.world; +package de.steamwar.bausystem.tracer; import de.steamwar.bausystem.BauSystem; import de.steamwar.core.Core; @@ -12,7 +12,7 @@ import org.bukkit.scheduler.BukkitTask; import java.util.*; -public class TNTTracer { +public class TNTTracer12 { private static BukkitTask task; private static final Set printedLocs = new HashSet<>(); @@ -26,13 +26,7 @@ public class TNTTracer { private static Status status = Status.IDLE; static void remove(TNTPrimed tnt){ - switch (Core.getVersion()){ - case 15: - TNTTracer_15.remove(locations, tnt); - break; - default: - TNTTracer_12.remove(locations, tnt); - } + TNTTracer_12.remove(locations, tnt); } public static void start(){ @@ -42,7 +36,7 @@ public class TNTTracer { locations.clear(); status = Status.RECORD; - task = Bukkit.getScheduler().runTaskTimer(BauSystem.getPlugin(), TNTTracer::run, 1, 1); + task = Bukkit.getScheduler().runTaskTimer(BauSystem.getPlugin(), TNTTracer12::run, 1, 1); } public static int show(){ @@ -51,12 +45,7 @@ public class TNTTracer { stop(); status = Status.SHOW; - switch (Core.getVersion()){ - case 15: - return TNTTracer_15.show(locations, printedLocs); - default: - return TNTTracer_12.show(locations, printedLocs); - } + return TNTTracer_12.show(locations, printedLocs); } public static void stop(){ @@ -73,18 +62,15 @@ public class TNTTracer { } private static boolean airOrBrick(Block block){ - switch(Core.getVersion()){ - case 15: - return TNTTracer_15.airOrBrick(block); - default: - return TNTTracer_12.airOrBrick(block); - } + return TNTTracer_12.airOrBrick(block); } private static void run() { - for(TNTPrimed tnt : world.getEntitiesByClass(TNTPrimed.class)){ - locations.computeIfAbsent(tnt, k -> new LinkedList<>()).add(tnt.getLocation()); - } + world.getEntities() + .stream() + .filter(e -> e instanceof TNTPrimed) + .map(e -> (TNTPrimed)e) + .forEach(tnt -> locations.computeIfAbsent(tnt, k -> new LinkedList<>()).add(tnt.getLocation())); } enum Status{ diff --git a/BauSystem_Main/src/de/steamwar/bausystem/tracer/TNTTracer15.java b/BauSystem_Main/src/de/steamwar/bausystem/tracer/TNTTracer15.java new file mode 100644 index 0000000..2d49dba --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/tracer/TNTTracer15.java @@ -0,0 +1,477 @@ +package de.steamwar.bausystem.tracer; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.tracer.showcallback.TNTShowCallback_15; +import de.steamwar.bausystem.tracer.trace.ShowManager; +import de.steamwar.bausystem.tracer.trace.ShowStatus; +import de.steamwar.bausystem.tracer.trace.TNTFrame; +import de.steamwar.bausystem.tracer.trace.TNTTrace; +import net.md_5.bungee.api.ChatMessageType; +import net.md_5.bungee.api.chat.ClickEvent; +import net.md_5.bungee.api.chat.HoverEvent; +import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.entity.Player; +import org.bukkit.entity.TNTPrimed; +import org.bukkit.scheduler.BukkitTask; + +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.stream.Collectors; + +public class TNTTracer15 { + + private static BukkitTask task; + private static long current = System.currentTimeMillis(); + + private static boolean removeInWater = true; + + private static World world; + public static void worldInit() { + if (world != null) return; + world = Bukkit.getWorlds().get(0); + TNTTracer_15.initWorld(); + } + + private static LinkedList tntFrames = new LinkedList<>(); + + public static TNTTracer15.Status getStatus() { + return status; + } + + private static TNTTracer15.Status status = Status.IDLE; + private static final float[] noValue = new float[0]; + + public static void initTNTTracer_15() { + TNTTracer_15.init(BauSystem.getPlugin(), TNTTracer15::getTracePoints, TNTTracer15::getTraceUpdatePoints, TNTTracer15::getActionBar, TNTTracer15::showMode, p -> ShowManager.get(p).isDirty()); + } + + private static float[] accumulate(LinkedList traces) { + Map locations = new HashMap<>(); + Iterator traceIterator = traces.iterator(); + while (traceIterator.hasNext()) { + float[] positions = traceIterator.next().getPositions(); + for (int i = 0; i < positions.length; i += 3) { + float x = positions[i + 0]; + float y = positions[i + 1]; + float z = positions[i + 2]; + locations.computeIfAbsent(round(x) + ":" + round(y) + ":" + round(z), t -> new float[]{x, y, z}); + } + } + + float[] floats = new float[locations.size() * 3]; + int index = 0; + for (Map.Entry entry : locations.entrySet()) { + floats[index + 0] = entry.getValue()[0]; + floats[index + 1] = entry.getValue()[1]; + floats[index + 2] = entry.getValue()[2]; + index += 3; + } + return floats; + } + + private static float[] accumulateInterpolate(LinkedList traces, ShowStatus.UpdatePoints updatePoints) { + Map locations = new HashMap<>(); + Iterator traceIterator = traces.iterator(); + while (traceIterator.hasNext()) { + float[] positions = interpolate(traceIterator.next().getPositions(), updatePoints); + for (int i = 0; i < positions.length; i += 3) { + float x = positions[i + 0]; + float y = positions[i + 1]; + float z = positions[i + 2]; + locations.computeIfAbsent(round(x) + ":" + round(y) + ":" + round(z), t -> new float[]{x, y, z}); + } + } + + float[] floats = new float[locations.size() * 3]; + int index = 0; + for (Map.Entry entry : locations.entrySet()) { + floats[index + 0] = entry.getValue()[0]; + floats[index + 1] = entry.getValue()[1]; + floats[index + 2] = entry.getValue()[2]; + index += 3; + } + return floats; + } + + private static float[] getTracePoints(Player p) { + ShowStatus showStatus = ShowManager.get(p); + if (showStatus.getShow() == ShowStatus.Show.NONE) return noValue; + if (showStatus.getShow() == ShowStatus.Show.ALL) { + return getAllTraces(); + } + LinkedList selection = showStatus.getSelection(); + + Iterator frameIterator = tntFrames.iterator(); + LinkedList traces = new LinkedList<>(); + while (frameIterator.hasNext()) { + traces.addAll(frameIterator.next().getTraces(selection)); + } + + return accumulate(traces); + } + + private static float[] getAllTraces() { + Iterator frameIterator = tntFrames.iterator(); + LinkedList traces = new LinkedList<>(); + while (frameIterator.hasNext()) { + traces.addAll(frameIterator.next().getTraces()); + } + + return accumulate(traces); + } + + private static float[] getTraceUpdatePoints(Player p) { + ShowStatus showStatus = ShowManager.get(p); + if (showStatus.getShow() == ShowStatus.Show.NONE) return noValue; + if (showStatus.getShow() == ShowStatus.Show.ALL) { + return getTraceUpdatePointsAll(showStatus); + } + if (showStatus.getUpdatePoints() == ShowStatus.UpdatePoints.NONE) return noValue; + LinkedList selection = showStatus.getSelection(); + + Iterator frameIterator = tntFrames.iterator(); + LinkedList traces = new LinkedList<>(); + while (frameIterator.hasNext()) { + traces.addAll(frameIterator.next().getTraces(selection)); + } + + return accumulateInterpolate(traces, showStatus.getUpdatePoints()); + } + + private static float[] getTraceUpdatePointsAll(ShowStatus showStatus) { + if (showStatus.getUpdatePoints() == ShowStatus.UpdatePoints.NONE) return noValue; + Iterator frameIterator = tntFrames.iterator(); + LinkedList traces = new LinkedList<>(); + while (frameIterator.hasNext()) { + traces.addAll(frameIterator.next().getTraces()); + } + + return accumulateInterpolate(traces, showStatus.getUpdatePoints()); + } + + private static int roundValue = 100; + + private static float round(float toRound) { + float r = (toRound * roundValue); + if (r - (int)r >= 0.5) { + return (((float)(int)r) + 1) / roundValue; + } else { + return (((float)(int)r) + 0) / roundValue; + } + } + + private static double round(double toRound, int digits) { + int x = (int)Math.pow(10, digits); + + double r = (toRound * x); + double t = r - (int) r; + + if (t >= 0.5) { + return (((double)(int)r) + 1) / x; + } else { + return (((double)(int)r) + 0) / x; + } + } + + private static String getActionBar() { + StringBuilder st = new StringBuilder(); + st.append("§7Frames: §e").append(tntFrames.size()).append(" "); + int traces = calcTraces(); + st.append("§7Traces: §e").append(traces).append(" "); + st.append("§7RAM: §c").append(round(traces * 32 / 8.0 / 1024 / 1024, 8)).append("MB"); + return st.toString(); + } + + private static int calcTraces() { + int traces = 0; + Iterator frameIterator = tntFrames.iterator(); + while (frameIterator.hasNext()) { + Iterator traceIterator = frameIterator.next().getTraces().iterator(); + while (traceIterator.hasNext()) { + traces += traceIterator.next().realLength(); + } + } + return traces; + } + + private static TNTShowCallback_15.ShowMode showMode(Player player) { + if (ShowManager.get(player).getShowMode() == ShowStatus.ShowMode.BLOCK) { + return TNTShowCallback_15.ShowMode.BLOCK; + } else { + return TNTShowCallback_15.ShowMode.PARTICLE; + } + } + + private static float[] interpolate(float[] floats, ShowStatus.UpdatePoints updatePoints) { + LinkedList linkedList = new LinkedList<>(); + if (floats.length < 6) { + return noValue; + } + for (int i = 0; i < floats.length - 3; i += 3) { + float x1 = floats[i + 0]; + float y1 = floats[i + 1]; + float z1 = floats[i + 2]; + + float x2 = floats[i + 3]; + float y2 = floats[i + 4]; + float z2 = floats[i + 5]; + + if (!isEqual(y2, y1)) { + linkedList.add(x1); + linkedList.add(y2); + linkedList.add(z1); + } + if (updatePoints != ShowStatus.UpdatePoints.ALL) { + continue; + } + if (abs(x2 - x1) > abs(z2 - z1)) { + if (!isEqual(x2, x1)) { + linkedList.add(x2); + linkedList.add(y2); + linkedList.add(z1); + } + } else { + if (!isEqual(z2, z1)) { + linkedList.add(x1); + linkedList.add(y2); + linkedList.add(z2); + } + } + } + return toFloat(linkedList); + } + + private static boolean isEqual(float d1, float d2) { + return TNTTracer_15.square(d2 - d1) < 0.01; + } + + private static float[] toFloat(LinkedList floats) { + float[] value = new float[floats.size()]; + Iterator linkedListIterator = floats.listIterator(); + int index = 0; + while (linkedListIterator.hasNext()) { + value[index] = linkedListIterator.next(); + index++; + } + return value; + } + + private static float abs(float x) { + return x < 0 ? -x : x; + } + + static void explode(TNTPrimed tntPrimed) { + if (tntFrames.isEmpty()) return; + tntFrames.getLast().explode(tntPrimed); + } + + public static boolean isInWater(TNTPrimed tntPrimed) { + return TNTTracer_15.isInWater(tntPrimed) && removeInWater; + } + + public static boolean toggleRemoveInWater() { + removeInWater = !removeInWater; + return removeInWater; + } + + public static void clear() { + if (status == Status.RECORD || status == Status.RECORD_AUTO) { + stop(); + } + tntFrames.clear(); + ShowManager.removeAllTraces(); + } + + public static void remove(int tntID) { + Iterator frameIterator = tntFrames.iterator(); + while (frameIterator.hasNext()) { + frameIterator.next().remove(tntID); + } + } + + public static void hideBlockTraces(Player p) { + TNTTracer_15.hide(p); + } + + public static void start() { + if (status == Status.IDLE || status == Status.IDLE_AUTO) { + if (status == Status.IDLE) { + status = Status.RECORD; + } else { + Bukkit.getOnlinePlayers().forEach(player -> player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText("§7Automatischer TNT-Tracer §8- §aAufnahme gestartet"))); + status = Status.RECORD_AUTO; + } + tntFrames.addLast(new TNTFrame()); + task = Bukkit.getScheduler().runTaskTimer(BauSystem.getPlugin(), TNTTracer15::run, 1, 1); + current = System.currentTimeMillis(); + if (status == Status.RECORD_AUTO) { + run(); + } + } + if (status == Status.RECORD_AUTO) { + current = System.currentTimeMillis(); + } + } + + public static void stop() { + if (status == Status.IDLE || status == Status.IDLE_AUTO) { + return; + } + if (status == Status.RECORD) { + status = Status.IDLE; + } + if (status == Status.RECORD_AUTO) { + Bukkit.getOnlinePlayers().forEach(player -> player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText("§7Automatischer TNT-Tracer §8- §aAufnahme gestoppt"))); + status = Status.IDLE_AUTO; + } + if (task != null) task.cancel(); + if (tntFrames.getLast().finish()) { + tntFrames.removeLast(); + } + } + + public static boolean toggleAuto() { + if (status == Status.IDLE) { + status = Status.IDLE_AUTO; + return true; + } + if (status == Status.RECORD) { + status = Status.RECORD_AUTO; + current = System.currentTimeMillis(); + return true; + } + if (status == Status.IDLE_AUTO) { + status = Status.IDLE; + return false; + } + if (status == Status.RECORD_AUTO) { + status = Status.RECORD; + return false; + } + return false; + } + + private static void run() { + if (status == Status.RECORD_AUTO && System.currentTimeMillis() - current > 4500) { + stop(); + } + tntFrames.getLast().add(world.getEntities() + .stream() + .filter(e -> e instanceof TNTPrimed) + .map(e -> (TNTPrimed)e) + ); + } + + private static String format(long time) { + return new SimpleDateFormat("HH:mm:ss").format(new Date(time)); + } + + private static long calcTick(long startTime, long time) { + return (time - startTime) / 50; + } + + private static String format(long startTime, long time, int length) { + return calcTick(startTime, time) + "-" + (calcTick(startTime, time) + length); + } + + private static String format(int length, int uniqueID) { + if (length == 0) { + return uniqueID + ""; + } + return repeat(length - (int)Math.log10(uniqueID) - 1) + uniqueID; + } + + private static String repeat(int length) { + StringBuilder st = new StringBuilder(); + for (int i = 0; i < length; i++) st.append('0'); + return st.toString(); + } + + public static void printFrames(Player player, int uniqueID) { + Iterator frameIterator = tntFrames.iterator(); + LinkedList integerList = ShowManager.get(player).getSelection(); + TNTFrame tntFrame = null; + while (frameIterator.hasNext()) { + TNTFrame frame = frameIterator.next(); + if (frame.getUniqueID() == uniqueID) { + tntFrame = frame; + break; + } + } + if (tntFrame == null) { + player.sendMessage("§cUnbekannte Aufnahme"); + return; + } + + player.sendMessage(""); + player.sendMessage("§eAufnahme §7aufgenommen um §e" + format(tntFrame.getStartTime()) + " §7mit §a" + tntFrame.getTraces().size() + " TNT"); + int length = (int)Math.log10(tntFrame.getTraces().getLast().getUniqueID()) + 1; + Iterator traceIterator = tntFrame.getTraces().iterator(); + while (traceIterator.hasNext()) { + TNTTrace tntTrace = traceIterator.next(); + + StringBuilder st = new StringBuilder(); + st.append("§8 "); + if (integerList.contains(tntTrace.getUniqueID()) || ShowManager.get(player).getShow() == ShowStatus.Show.ALL) st.append("§a"); + else st.append("§c"); + st.append(format(length, tntTrace.getUniqueID())).append(" §eTick: ").append(format(tntFrame.getStartTime(), tntTrace.getStartTime(), tntTrace.length())); + + TextComponent textComponent = new TextComponent(); + textComponent.setText(st.toString()); + textComponent.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText("§7Zeigt die Positionen dieses TNT's an"))); + textComponent.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/trace toggleshow " + tntTrace.getUniqueID())); + player.spigot().sendMessage(textComponent); + } + } + + public static void printList(Player player) { + if (tntFrames.isEmpty()) { + player.sendMessage("§cKeine Aufnahme vorhanden"); + return; + } + Iterator frameIterator = tntFrames.iterator(); + while (frameIterator.hasNext()) { + TNTFrame tntFrame = frameIterator.next(); + + TextComponent textComponent = new TextComponent(); + textComponent.setText("§eAufnahme §7aufgenommen um §e" + format(tntFrame.getStartTime()) + " §7mit §a" + tntFrame.getTraces().size() + " TNT"); + textComponent.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText("§7Zeige die TNT dieser Aufnahme an"))); + textComponent.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/trace list " + tntFrame.getUniqueID())); + player.spigot().sendMessage(textComponent); + } + } + + public static LinkedList allTraces() { + LinkedList allTraces = new LinkedList<>(); + Iterator frameIterator = tntFrames.iterator(); + while (frameIterator.hasNext()) { + TNTFrame tntFrame = frameIterator.next(); + allTraces.addAll(tntFrame.getTraces().stream().map(TNTTrace::getUniqueID).collect(Collectors.toSet())); + } + return allTraces; + } + + public static long sidebar_startTime() { + if (tntFrames.isEmpty()) { + return 0; + } + return tntFrames.getLast().getStartTime(); + } + + public static int sidebar_TNT() { + if (tntFrames.isEmpty()) { + return 0; + } + return tntFrames.getLast().getTraces().size(); + } + + public enum Status{ + RECORD, + RECORD_AUTO, + IDLE, + IDLE_AUTO + } + +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/tracer/trace/ShowManager.java b/BauSystem_Main/src/de/steamwar/bausystem/tracer/trace/ShowManager.java new file mode 100644 index 0000000..5506762 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/tracer/trace/ShowManager.java @@ -0,0 +1,40 @@ +package de.steamwar.bausystem.tracer.trace; + +import de.steamwar.bausystem.tracer.TNTTracer15; +import org.bukkit.entity.Player; + +import java.util.HashMap; +import java.util.Map; + +public class ShowManager { + + private static Map showMap = new HashMap<>(); + + public static void add(Player player) { + showMap.put(player, new ShowStatus(player)); + TNTTracer15.worldInit(); + } + + public static void remove(Player player) { + showMap.remove(player); + } + + public static ShowStatus get(Player player) { + return showMap.get(player); + } + + public static void removeTrace(int traceID) { + for (Map.Entry entry : showMap.entrySet()) { + entry.getValue().removeSelection(traceID); + TNTTracer15.hideBlockTraces(entry.getKey()); + } + } + + public static void removeAllTraces() { + for (Map.Entry entry : showMap.entrySet()) { + entry.getValue().clear(); + TNTTracer15.hideBlockTraces(entry.getKey()); + } + } + +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/tracer/trace/ShowStatus.java b/BauSystem_Main/src/de/steamwar/bausystem/tracer/trace/ShowStatus.java new file mode 100644 index 0000000..0b65c54 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/tracer/trace/ShowStatus.java @@ -0,0 +1,158 @@ +package de.steamwar.bausystem.tracer.trace; + +import de.steamwar.bausystem.tracer.TNTTracer15; +import org.bukkit.entity.Player; + +import java.util.Iterator; +import java.util.LinkedList; + +public class ShowStatus { + + private Show show = Show.NONE; + private UpdatePoints updatePoints = UpdatePoints.ALL; + private ShowMode showMode = ShowMode.PARTICLE; + + private LinkedList selected = new LinkedList<>(); + + private Player p; + + private boolean dirty = false; + + public ShowStatus(Player p) { + this.p = p; + } + + public enum Show { + NONE, + ALL, + SELECTIVE + } + + public enum UpdatePoints { + NONE, + Y_AXIS, + ALL + } + + public enum ShowMode { + BLOCK, + PARTICLE + } + + public boolean toggleShow() { + dirty = true; + if (show == Show.NONE) { + show = Show.ALL; + return true; + } else { + selected.clear(); + show = Show.NONE; + return false; + } + } + + public boolean toggleShow(int tntID) { + dirty = true; + + if (show == Show.ALL) { + removeSelection(tntID); + return false; + } + Iterator selection = selected.iterator(); + while (selection.hasNext()) { + if (selection.next() == tntID) { + removeSelection(tntID); + return false; + } + } + addSelection(tntID); + return true; + } + + public void show() { + dirty = true; + show = Show.ALL; + } + + public void hide() { + dirty = true; + selected.clear(); + TNTTracer15.hideBlockTraces(p); + show = Show.NONE; + } + + public void addSelection(int uniqueID) { + dirty = true; + if (show == Show.ALL) return; + if (show == Show.NONE) { + show = Show.SELECTIVE; + } + selected.add(uniqueID); + if (selected.size() == TNTTracer15.allTraces().size()) { + show = Show.ALL; + selected.clear(); + } + } + + public void removeSelection(int uniqueID) { + dirty = true; + if (show == Show.NONE) return; + TNTTracer15.hideBlockTraces(p); + if (show == Show.ALL) { + selected = TNTTracer15.allTraces(); + show = Show.SELECTIVE; + } + selected.remove((Integer) uniqueID); + if (selected.isEmpty()) { + show = Show.NONE; + } + } + + public void clear() { + dirty = true; + if (show == Show.NONE) return; + selected.clear(); + TNTTracer15.hideBlockTraces(p); + } + + public Show getShow() { + return show; + } + + public UpdatePoints getUpdatePoints() { + return updatePoints; + } + + public void setUpdatePoints(UpdatePoints updatePoints) { + this.updatePoints = updatePoints; + } + + public ShowMode getShowMode() { + return showMode; + } + + public void setShowMode(ShowMode showMode) { + this.showMode = showMode; + } + + public LinkedList getSelection() { + return selected; + } + + public boolean isDirty() { + if (dirty) { + dirty = false; + return true; + } + return false; + } + + @Override + public String toString() { + return "ShowStatus{" + + "status=" + show + + ", selected=" + selected + + '}'; + } + +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/tracer/trace/TNTFrame.java b/BauSystem_Main/src/de/steamwar/bausystem/tracer/trace/TNTFrame.java new file mode 100644 index 0000000..ca9364b --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/tracer/trace/TNTFrame.java @@ -0,0 +1,101 @@ +package de.steamwar.bausystem.tracer.trace; + +import de.steamwar.bausystem.tracer.TNTTracer15; +import org.bukkit.entity.TNTPrimed; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.Map; +import java.util.stream.Stream; + +public class TNTFrame { + + private static int uniqueIdentifierFrame = 0; + private static int uniqueIdentifier = 0; + + private long startTime = System.currentTimeMillis(); + private long endTime = System.currentTimeMillis(); + private Map positions = new HashMap<>(); + private Map aliveTNT = new HashMap<>(); + + private final TNTFrame instance = this; + + private final int uniqueID = uniqueIdentifierFrame++; + + public int getUniqueID() { + return uniqueID; + } + + public void add(Stream tntPrimedStream) { + if (aliveTNT == null) return; + tntPrimedStream.forEach(tnt -> aliveTNT.computeIfAbsent(tnt, k -> { + synchronized (instance) { + TNTTrace trace = new TNTTrace(uniqueIdentifier); + positions.put(uniqueIdentifier, trace); + uniqueIdentifier++; + return trace; + } + }).addLocation(tnt.getLocation())); + } + + public void explode(TNTPrimed tntPrimed) { + delete(tntPrimed); + } + + void delete(TNTPrimed tntPrimed) { + delete(tntPrimed, true); + } + + private void delete(TNTPrimed tntPrimed, boolean delete) { + if (aliveTNT == null) return; + TNTTrace tntTrace = aliveTNT.get(tntPrimed); + tntTrace.addLocation(tntPrimed.getLocation()); + if (delete) { + aliveTNT.remove(tntPrimed); + } + if (TNTTracer15.isInWater(tntPrimed)) { + positions.remove(tntTrace.getUniqueID()); + } + } + + public void remove(int tntID) { + positions.remove(tntID); + } + + public LinkedList getTraces(LinkedList selection) { + LinkedList traces = new LinkedList<>(); + Iterator iterator = selection.iterator(); + while (iterator.hasNext()) { + TNTTrace trace = positions.get(iterator.next()); + if (trace != null) { + traces.add(trace); + } + } + return traces; + } + + public LinkedList getTraces() { + LinkedList traces = new LinkedList<>(); + for (Map.Entry entry : positions.entrySet()) { + traces.add(entry.getValue()); + } + return traces; + } + + public boolean finish() { + for (Map.Entry entry : aliveTNT.entrySet()) { + entry.getValue().cleanUp(); + delete(entry.getKey(), false); + } + endTime = System.currentTimeMillis(); + aliveTNT.clear(); + aliveTNT = null; + return positions.isEmpty(); + } + + public long getStartTime() { + return startTime; + } + +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/tracer/trace/TNTTrace.java b/BauSystem_Main/src/de/steamwar/bausystem/tracer/trace/TNTTrace.java new file mode 100644 index 0000000..b20f6b5 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/tracer/trace/TNTTrace.java @@ -0,0 +1,58 @@ +package de.steamwar.bausystem.tracer.trace; + +import org.bukkit.Location; + +import java.util.Arrays; + +public class TNTTrace { + + private long startTime = System.currentTimeMillis(); + private int uniqueID; + + private int index = 0; + private float[] positions = new float[243]; + + public TNTTrace(int uniqueID) { + this.uniqueID = uniqueID; + } + + public void addLocation(Location location) { + addLocation(location.getX(), location.getY(), location.getZ()); + } + + public void addLocation(double x, double y, double z) { + positions[index + 0] = (float)x; + positions[index + 1] = (float)y; + positions[index + 2] = (float)z; + index += 3; + } + + public float[] getPositions() { + return Arrays.copyOf(positions, positions.length); + } + + public int size() { + return index / 3; + } + + public int length() { + return size(); + } + + public int realLength() { + return positions.length; + } + + public long getStartTime() { + return startTime; + } + + public int getUniqueID() { + return uniqueID; + } + + void cleanUp() { + positions = Arrays.copyOf(positions, index); + } + +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/world/BauScoreboard.java b/BauSystem_Main/src/de/steamwar/bausystem/world/BauScoreboard.java index 70e2c5e..5ae81d6 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/world/BauScoreboard.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/world/BauScoreboard.java @@ -3,6 +3,8 @@ package de.steamwar.bausystem.world; import de.steamwar.bausystem.commands.CommandFreeze; import de.steamwar.bausystem.commands.CommandInfo; import de.steamwar.bausystem.commands.CommandTNT; +import de.steamwar.bausystem.tracer.TNTTracer15; +import de.steamwar.core.Core; import de.steamwar.scoreboard.SWScoreboard; import de.steamwar.scoreboard.ScoreboardCallback; import org.bukkit.entity.Player; @@ -11,8 +13,7 @@ import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerJoinEvent; import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.HashMap; +import java.util.*; public class BauScoreboard implements Listener { @@ -24,13 +25,18 @@ public class BauScoreboard implements Listener { @Override public HashMap getData() { HashMap data = new HashMap<>(); - data.put("§1 ", 7); - data.put("§eUhrzeit§8: §7" + new SimpleDateFormat("HH:mm:ss").format(Calendar.getInstance().getTime()), 6); - data.put("§2 ", 5); - data.put("§eTNT§8: " + (!CommandTNT.getInstance().isOn() ? "§aan" : "§caus"), 4); - data.put("§eFreeze§8: " + (CommandFreeze.getInstance().isOn() ? "§aan" : "§caus"), 3); - data.put("§3 ", 2); - data.put("§eTPS§8: §7" + CommandInfo.getTps()[0], 1); + + switch (Core.getVersion()) { + case 15: + render(getSidebar_15(), data); + break; + case 12: + render(getSidebar_12(), data); + break; + default: + break; + } + return data; } @@ -41,5 +47,47 @@ public class BauScoreboard implements Listener { }); } + private void render(List strings, HashMap data) { + String[] elements = strings.toArray(new String[0]); + for (int i = elements.length - 1; i >= 0; i--) { + data.put(elements[i], elements.length - i - 1); + } + } + + private List getSidebar_15() { + List strings = new ArrayList<>(); + strings.add("§1"); + strings.add("§eUhrzeit§8: §7" + new SimpleDateFormat("HH:mm:ss").format(Calendar.getInstance().getTime())); + strings.add("§2"); + strings.add("§eTNT§8: " + (!CommandTNT.getInstance().isOn() ? "§aan" : "§caus")); + strings.add("§eFreeze§8: " + (CommandFreeze.getInstance().isOn() ? "§aan" : "§caus")); + + boolean tracing = TNTTracer15.getStatus() == TNTTracer15.Status.RECORD || TNTTracer15.getStatus() == TNTTracer15.Status.RECORD_AUTO; + boolean autoTracer = TNTTracer15.getStatus() == TNTTracer15.Status.IDLE_AUTO; + strings.add("§eTrace§8: " + (tracing ? "§aan" : (autoTracer ? "§eauto" : "§caus"))); + + if (tracing) { + strings.add("§3"); + strings.add("§eTrace-Start§8: §7" + new SimpleDateFormat("HH:mm:ss").format(new Date(TNTTracer15.sidebar_startTime()))); + strings.add("§eTicks§8: §7" + ((System.currentTimeMillis() - TNTTracer15.sidebar_startTime()) / 50)); + strings.add("§eAnzahl TNT§8: §7" + TNTTracer15.sidebar_TNT()); + } + + strings.add("§4"); + strings.add("§eTPS§8: §7" + CommandInfo.getTps()[0]); + return strings; + } + + private List getSidebar_12() { + List strings = new ArrayList<>(); + strings.add("§1"); + strings.add("§eUhrzeit§8: §7" + new SimpleDateFormat("HH:mm:ss").format(Calendar.getInstance().getTime())); + strings.add("§2"); + strings.add("§eTNT§8: " + (!CommandTNT.getInstance().isOn() ? "§aan" : "§caus")); + strings.add("§eFreeze§8: " + (CommandFreeze.getInstance().isOn() ? "§aan" : "§caus")); + strings.add("§3"); + strings.add("§eTPS§8: §7" + CommandInfo.getTps()[0]); + return strings; + } } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/world/TNTListener.java b/BauSystem_Main/src/de/steamwar/bausystem/world/TNTListener.java deleted file mode 100644 index 94cec78..0000000 --- a/BauSystem_Main/src/de/steamwar/bausystem/world/TNTListener.java +++ /dev/null @@ -1,20 +0,0 @@ -package de.steamwar.bausystem.world; - -import org.bukkit.entity.TNTPrimed; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.entity.EntityExplodeEvent; - -public class TNTListener implements Listener { - - @EventHandler - public void onEntityExplode(EntityExplodeEvent event){ - if(TNTTracer.getStatus() != TNTTracer.Status.RECORD) - return; - if(!(event.getEntity() instanceof TNTPrimed)) - return; - TNTPrimed entity = (TNTPrimed) event.getEntity(); - - TNTTracer.remove(entity); - } -}