diff --git a/SpigotCore/SpigotCore_20/src/de/steamwar/core/WorldEditRenderer20.java b/SpigotCore/SpigotCore_20/src/de/steamwar/core/WorldEditRenderer20.java
deleted file mode 100644
index d84f4abb..00000000
--- a/SpigotCore/SpigotCore_20/src/de/steamwar/core/WorldEditRenderer20.java
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * This file is a part of the SteamWar software.
- *
- * Copyright (C) 2020 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.core;
-
-import com.sk89q.worldedit.EmptyClipboardException;
-import com.sk89q.worldedit.IncompleteRegionException;
-import com.sk89q.worldedit.LocalSession;
-import com.sk89q.worldedit.WorldEdit;
-import com.sk89q.worldedit.bukkit.WorldEditPlugin;
-import com.sk89q.worldedit.regions.CuboidRegion;
-import com.sk89q.worldedit.regions.Region;
-import com.sk89q.worldedit.regions.RegionSelector;
-import com.sk89q.worldedit.world.World;
-import de.steamwar.core.renderers.CuboidRegionRenderer;
-import de.steamwar.core.renderers.RegionRenderer;
-import de.steamwar.entity.REntityServer;
-import org.bukkit.Bukkit;
-import org.bukkit.Material;
-import org.bukkit.entity.Player;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.EventPriority;
-import org.bukkit.event.Listener;
-import org.bukkit.event.block.BlockBreakEvent;
-import org.bukkit.event.player.*;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.function.Supplier;
-
-public class WorldEditRenderer20 implements WorldEditRenderer, Listener {
-
- private static final Map servers = new HashMap<>();
- private static final Map clipboards = new HashMap<>();
- private static final Map regionSelections = new HashMap<>();
-
- private static final Material WAND = FlatteningWrapper.impl.getMaterial("WOOD_AXE");
-
- private final WorldEditPlugin we;
-
- private static final Map, Supplier>> rendererMap = new HashMap<>();
-
- static {
- rendererMap.put(CuboidRegion.class, CuboidRegionRenderer::new);
- }
-
- public WorldEditRenderer20() {
- we = WorldEditWrapper.getWorldEditPlugin();
- Bukkit.getPluginManager().registerEvents(this, Core.getInstance());
- Bukkit.getScheduler().runTaskTimer(Core.getInstance(), () -> {
- for (Player player : Bukkit.getOnlinePlayers()) {
- render(player);
- }
- }, 10, 10);
- }
-
- @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
- public void onPlayerJoin(PlayerJoinEvent event) {
- Bukkit.getScheduler().runTaskLater(Core.getInstance(), () -> {
- render(event.getPlayer());
- }, 0);
- }
-
- @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
- public void onPlayerSwapHandItems(PlayerSwapHandItemsEvent event) {
- Bukkit.getScheduler().runTaskLater(Core.getInstance(), () -> {
- render(event.getPlayer());
- }, 0);
- }
-
- @EventHandler
- public void onPlayerDropItem(PlayerDropItemEvent event) {
- Bukkit.getScheduler().runTaskLater(Core.getInstance(), () -> {
- render(event.getPlayer());
- }, 0);
- }
-
- @EventHandler
- public void onPlayerItemHeld(PlayerItemHeldEvent event) {
- Bukkit.getScheduler().runTaskLater(Core.getInstance(), () -> {
- render(event.getPlayer());
- }, 0);
- }
-
- @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
- public void onBlockBreak(BlockBreakEvent event) {
- Bukkit.getScheduler().runTaskLater(Core.getInstance(), () -> {
- render(event.getPlayer());
- }, 0);
- }
-
- @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
- public void onPlayerInteract(PlayerInteractEvent event) {
- Bukkit.getScheduler().runTaskLater(Core.getInstance(), () -> {
- render(event.getPlayer());
- }, 0);
- }
-
- @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
- public void onPlayerMove(PlayerMoveEvent event) {
- Bukkit.getScheduler().runTaskLater(Core.getInstance(), () -> {
- render(event.getPlayer(), true, false);
- }, 0);
- }
-
- @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
- public void onPlayerQuit(PlayerQuitEvent event) {
- REntityServer server = servers.remove(event.getPlayer());
- clipboards.remove(event.getPlayer());
- regionSelections.remove(event.getPlayer());
- if (server == null) return;
- server.close();
- }
-
- @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
- public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) {
- String command = event.getMessage().split(" ")[0];
- command = command.replaceFirst("/", "");
- command = command.toLowerCase();
- if (WorldEdit.getInstance().getPlatformManager().getPlatformCommandManager().getCommandManager().containsCommand(command)) {
- Bukkit.getScheduler().runTaskLater(Core.getInstance(), () -> {
- render(event.getPlayer());
- }, 10);
- }
- }
-
- private void render(Player player) {
- render(player, true, true);
- }
-
- private void render(Player player, boolean renderClipboard, boolean renderRegionSelection) {
- if (player.getInventory().getItemInMainHand().getType() != WAND) {
- REntityServer entityServer = servers.remove(player);
- clipboards.remove(player);
- regionSelections.remove(player);
- if (entityServer != null) entityServer.close();
- return;
- }
-
- REntityServer server = servers.computeIfAbsent(player, __ -> {
- REntityServer _server = new REntityServer();
- _server.addPlayer(player);
- return _server;
- });
-
- LocalSession session = we.getSession(player);
- if (renderClipboard) {
- renderClipboard(server, session, player);
- }
- if (renderRegionSelection) {
- renderSelection(server, session, player);
- }
- }
-
- @SuppressWarnings("unchecked")
- private void renderClipboard(REntityServer server, LocalSession session, Player player) {
- try {
- Region region = session.getClipboard().getClipboard().getRegion();
- clipboards.compute(player, (__, regionRenderer) -> {
- if (regionRenderer != null && !regionRenderer.canDisplay(region)) {
- regionRenderer.clear();
- regionRenderer = null;
- }
- if (regionRenderer == null) {
- return rendererMap.getOrDefault(region.getClass(), RegionRenderer.NOOPImpl::new).get();
- } else {
- return regionRenderer;
- }
- }).update(server, region, session.getClipboard(), Material.LIME_CONCRETE.createBlockData());
- } catch (EmptyClipboardException e) {
- RegionRenderer regionRenderer = clipboards.remove(player);
- if (regionRenderer != null) regionRenderer.clear();
- }
- }
-
- @SuppressWarnings("unchecked")
- private void renderSelection(REntityServer server, LocalSession session, Player player) {
- World world = session.getSelectionWorld();
- if (world == null) {
- return;
- }
- RegionSelector regionSelector = session.getRegionSelector(world);
- try {
- Region region = regionSelector.getRegion();
- regionSelections.compute(player, (__, regionRenderer) -> {
- if (regionRenderer != null && !regionRenderer.canDisplay(region)) {
- regionRenderer.clear();
- regionRenderer = null;
- }
- if (regionRenderer == null) {
- return rendererMap.getOrDefault(region.getClass(), RegionRenderer.NOOPImpl::new).get();
- } else {
- return regionRenderer;
- }
- }).update(server, region, null, Material.PURPLE_CONCRETE.createBlockData());
- } catch (IncompleteRegionException e) {
- RegionRenderer regionRenderer = regionSelections.remove(player);
- if (regionRenderer != null) regionRenderer.clear();
- }
- }
-}
diff --git a/SpigotCore/SpigotCore_20/src/de/steamwar/core/WorldEditRendererWrapper20.java b/SpigotCore/SpigotCore_20/src/de/steamwar/core/WorldEditRendererWrapper20.java
new file mode 100644
index 00000000..5bffe84f
--- /dev/null
+++ b/SpigotCore/SpigotCore_20/src/de/steamwar/core/WorldEditRendererWrapper20.java
@@ -0,0 +1,145 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2020 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.core;
+
+import de.steamwar.entity.CAABox;
+import de.steamwar.entity.CAALine;
+import de.steamwar.entity.REntityServer;
+import org.bukkit.Material;
+import org.bukkit.block.data.BlockData;
+import org.bukkit.entity.Player;
+import org.bukkit.util.Vector;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+public class WorldEditRendererWrapper20 implements WorldEditRendererWrapper {
+
+ private static final class BoxPair {
+ private CAABox regionBox;
+ private CAABox clipboardBox;
+
+ public CAABox get(boolean clipboard) {
+ if (clipboard) {
+ return clipboardBox;
+ } else {
+ return regionBox;
+ }
+ }
+
+ public void set(boolean clipboard, CAABox box) {
+ if (clipboard) {
+ this.clipboardBox = box;
+ } else {
+ this.regionBox = box;
+ }
+ }
+
+ public void die() {
+ if (clipboardBox != null) {
+ clipboardBox.die();
+ }
+ if (regionBox != null) {
+ regionBox.die();
+ }
+ }
+ }
+
+ private static final Map servers = new HashMap<>();
+ private static final Map> boxes = new HashMap<>();
+
+ @Override
+ public void draw(Player player, Player owner, boolean clipboard, Vector pos1, Vector pos2) {
+ REntityServer server = servers.computeIfAbsent(player, __ -> {
+ REntityServer entityServer = new REntityServer();
+ entityServer.addPlayer(player);
+ return entityServer;
+ });
+
+ float width = CAALine.DEFAULT_WIDTH;
+ if (player != owner) {
+ width = 1 / 64f;
+ }
+
+ BlockData block;
+ if (player == owner) {
+ if (clipboard) {
+ block = Material.LIME_CONCRETE.createBlockData();
+ } else {
+ block = Material.PURPLE_CONCRETE.createBlockData();
+ }
+ } else {
+ block = Material.GRAY_CONCRETE.createBlockData();
+ }
+
+ BoxPair boxPair = boxes.computeIfAbsent(player, __ -> new HashMap<>()).computeIfAbsent(owner, __ -> new BoxPair());
+ CAABox box = boxPair.get(clipboard);
+ if (box == null) {
+ box = new CAABox(server);
+ boxPair.set(clipboard, box);
+ }
+ box.setPos1(null).setPos2(null);
+ box.setPos1(pos1.toLocation(player.getWorld()));
+ box.setPos2(pos2.toLocation(player.getWorld()));
+ box.setWidth(width);
+ box.setBlock(block);
+ }
+
+ @Override
+ public void tick(Player player) {
+ REntityServer server = servers.get(player);
+ if (server != null) server.tick();
+ }
+
+ @Override
+ public void hide(Player player, Player owner, boolean clipboard, boolean hide) {
+ Map pairs = boxes.getOrDefault(player, Collections.emptyMap());
+ if (owner != null) {
+ BoxPair boxPair = pairs.get(owner);
+ if (boxPair == null) return;
+ CAABox box = boxPair.get(clipboard);
+ if (box != null) box.hide(hide);
+ } else {
+ pairs.values().forEach(boxPair -> {
+ CAABox box = boxPair.get(clipboard);
+ if (box != null) box.hide(hide);
+ });
+ }
+ }
+
+ @Override
+ public void remove(Player player) {
+ Map removed = boxes.remove(player);
+ if (removed != null) {
+ removed.values().forEach(boxPair -> {
+ boxPair.die();
+ });
+ }
+ boxes.values().forEach(map -> {
+ BoxPair boxPair = map.remove(player);
+ if (boxPair == null) return;
+ boxPair.die();
+ });
+
+ REntityServer server = servers.remove(player);
+ if (server != null) server.close();
+ }
+}
diff --git a/SpigotCore/SpigotCore_20/src/de/steamwar/core/renderers/CuboidRegionRenderer.java b/SpigotCore/SpigotCore_20/src/de/steamwar/core/renderers/CuboidRegionRenderer.java
deleted file mode 100644
index 70391d3d..00000000
--- a/SpigotCore/SpigotCore_20/src/de/steamwar/core/renderers/CuboidRegionRenderer.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * This file is a part of the SteamWar software.
- *
- * Copyright (C) 2020 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.core.renderers;
-
-import com.sk89q.worldedit.math.transform.Transform;
-import com.sk89q.worldedit.regions.CuboidRegion;
-import com.sk89q.worldedit.regions.Region;
-import com.sk89q.worldedit.session.ClipboardHolder;
-import de.steamwar.core.WorldEditWrapper;
-import de.steamwar.entity.RBlockDisplay;
-import de.steamwar.entity.REntityServer;
-import org.bukkit.Bukkit;
-import org.bukkit.Location;
-import org.bukkit.World;
-import org.bukkit.block.data.BlockData;
-import org.bukkit.entity.Display;
-import org.bukkit.entity.Player;
-import org.bukkit.util.Transformation;
-import org.bukkit.util.Vector;
-import org.joml.Quaternionf;
-import org.joml.Vector3f;
-
-public class CuboidRegionRenderer implements RegionRenderer {
-
- private static final World WORLD = Bukkit.getWorlds().get(0);
- private static final float offset = 1 / 1024f;
- private static final float width = 1 / 16f;
-
- private Vector lastA = null;
- private Vector lastB = null;
-
- private RBlockDisplay bd01;
- private RBlockDisplay bd02;
- private RBlockDisplay bd03;
- private RBlockDisplay bd04;
- private RBlockDisplay bd05;
- private RBlockDisplay bd06;
- private RBlockDisplay bd07;
- private RBlockDisplay bd08;
- private RBlockDisplay bd09;
- private RBlockDisplay bd10;
- private RBlockDisplay bd11;
- private RBlockDisplay bd12;
-
- @Override
- public boolean canDisplay(Region region) {
- return region instanceof CuboidRegion;
- }
-
- public void update(REntityServer server, CuboidRegion region, ClipboardHolder holder, BlockData block) {
- Vector a;
- Vector b;
- if (holder != null) {
- Player player = server.getPlayers().stream().findFirst().orElse(null);
- if (player == null) return;
- Vector pos = player.getLocation().toVector();
- Transform transform = holder.getTransform();
- a = WorldEditWrapper.impl.applyTransform(WorldEditWrapper.impl.getMinimum(region).subtract(WorldEditWrapper.impl.getOrigin(holder.getClipboard())), transform).add(pos);
- b = WorldEditWrapper.impl.applyTransform(WorldEditWrapper.impl.getMaximum(region).subtract(WorldEditWrapper.impl.getOrigin(holder.getClipboard())), transform).add(pos);
- } else {
- a = WorldEditWrapper.impl.getMinimum(region);
- b = WorldEditWrapper.impl.getMaximum(region);
- }
-
- if (a.equals(lastA) && b.equals(lastB)) {
- return;
- }
-
- drawCuboid(server, toBlockVector(a), toBlockVector(b), block);
- }
-
- @Override
- public void clear() {
- if (bd01 != null) bd01.die();
- if (bd02 != null) bd02.die();
- if (bd03 != null) bd03.die();
- if (bd04 != null) bd04.die();
- if (bd05 != null) bd05.die();
- if (bd06 != null) bd06.die();
- if (bd07 != null) bd07.die();
- if (bd08 != null) bd08.die();
- if (bd09 != null) bd09.die();
- if (bd10 != null) bd10.die();
- if (bd11 != null) bd11.die();
- if (bd12 != null) bd12.die();
- }
-
- private void drawCuboid(REntityServer server, Vector min, Vector max, BlockData block) {
- max.add(new Vector(1 - width, 1 - width, 1 - width));
-
- bd01 = drawLine(bd01, server, new Vector(min.getX() - offset, min.getY(), min.getZ()), new Vector(max.getX() + width, min.getY(), min.getZ()), block);
- bd02 = drawLine(bd02, server, new Vector(min.getX() - offset, max.getY(), min.getZ()), new Vector(max.getX() + width, max.getY(), min.getZ()), block);
- bd03 = drawLine(bd03, server, new Vector(min.getX() - offset, min.getY(), max.getZ()), new Vector(max.getX() + width, min.getY(), max.getZ()), block);
- bd04 = drawLine(bd04, server, new Vector(min.getX() - offset, max.getY(), max.getZ()), new Vector(max.getX() + width, max.getY(), max.getZ()), block);
-
- bd05 = drawLine(bd05, server, new Vector(min.getX(), min.getY() - offset, min.getZ()), new Vector(min.getX(), max.getY() + width, min.getZ()), block);
- bd06 = drawLine(bd06, server, new Vector(max.getX(), min.getY() - offset, min.getZ()), new Vector(max.getX(), max.getY() + width, min.getZ()), block);
- bd07 = drawLine(bd07, server, new Vector(min.getX(), min.getY() - offset, max.getZ()), new Vector(min.getX(), max.getY() + width, max.getZ()), block);
- bd08 = drawLine(bd08, server, new Vector(max.getX(), min.getY() - offset, max.getZ()), new Vector(max.getX(), max.getY() + width, max.getZ()), block);
-
- bd09 = drawLine(bd09, server, new Vector(min.getX(), min.getY(), min.getZ() - offset), new Vector(min.getX(), min.getY(), max.getZ() + width), block);
- bd10 = drawLine(bd10, server, new Vector(max.getX(), min.getY(), min.getZ() - offset), new Vector(max.getX(), min.getY(), max.getZ() + width), block);
- bd11 = drawLine(bd11, server, new Vector(min.getX(), max.getY(), min.getZ() - offset), new Vector(min.getX(), max.getY(), max.getZ() + width), block);
- bd12 = drawLine(bd12, server, new Vector(max.getX(), max.getY(), min.getZ() - offset), new Vector(max.getX(), max.getY(), max.getZ() + width), block);
- }
-
- private RBlockDisplay drawLine(RBlockDisplay display, REntityServer server, Vector from, Vector to, BlockData block) {
- Location spawnLocation = from.clone().add(to).divide(new Vector(2, 2, 2)).toLocation(WORLD);
- if (display == null) {
- display = new RBlockDisplay(server, spawnLocation);
- }
-
- Vector vector = to.clone().subtract(from);
- if (vector.getX() == 0) {
- vector.setX(vector.getX() + width + offset * 2);
- }
- if (vector.getY() == 0) {
- vector.setY(vector.getY() + width + offset * 2);
- }
- if (vector.getZ() == 0) {
- vector.setZ(vector.getZ() + width + offset * 2);
- }
-
- Vector transformVec = from.subtract(spawnLocation.toVector());
- transformVec.subtract(new Vector(offset, offset, offset));
-
- display.setTransform(new Transformation(toVec3f(transformVec), new Quaternionf(0, 0, 0, 1), toVec3f(vector), new Quaternionf(0, 0, 0, 1)));
- display.setBrightness(new Display.Brightness(15, 15));
- display.setBlock(block);
- display.move(spawnLocation);
-
- return display;
- }
-
- private Vector toBlockVector(Vector vector) {
- return new Vector(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ());
- }
-
- private Vector3f toVec3f(Vector vector) {
- return new Vector3f((float) vector.getX(), (float) vector.getY(), (float) vector.getZ());
- }
-}
diff --git a/SpigotCore/SpigotCore_20/src/de/steamwar/core/renderers/RegionRenderer.java b/SpigotCore/SpigotCore_8/src/de/steamwar/core/WorldEditRendererWrapper8.java
similarity index 50%
rename from SpigotCore/SpigotCore_20/src/de/steamwar/core/renderers/RegionRenderer.java
rename to SpigotCore/SpigotCore_8/src/de/steamwar/core/WorldEditRendererWrapper8.java
index 53121deb..1ca68b2d 100644
--- a/SpigotCore/SpigotCore_20/src/de/steamwar/core/renderers/RegionRenderer.java
+++ b/SpigotCore/SpigotCore_8/src/de/steamwar/core/WorldEditRendererWrapper8.java
@@ -17,31 +17,14 @@
* along with this program. If not, see .
*/
-package de.steamwar.core.renderers;
+package de.steamwar.core;
-import com.sk89q.worldedit.regions.Region;
-import com.sk89q.worldedit.session.ClipboardHolder;
-import de.steamwar.entity.REntityServer;
-import org.bukkit.block.data.BlockData;
+import org.bukkit.entity.Player;
+import org.bukkit.util.Vector;
-public interface RegionRenderer {
+public class WorldEditRendererWrapper8 implements WorldEditRendererWrapper {
- boolean canDisplay(Region region);
- void update(REntityServer server, R region, ClipboardHolder holder, BlockData block);
- void clear();
-
- final class NOOPImpl implements RegionRenderer {
- @Override
- public boolean canDisplay(Region region) {
- return false;
- }
-
- @Override
- public void update(REntityServer server, Region region, ClipboardHolder holder, BlockData block) {
- }
-
- @Override
- public void clear() {
- }
+ @Override
+ public void draw(Player player, Player owner, boolean clipboard, Vector pos1, Vector pos2) {
}
}
diff --git a/SpigotCore/SpigotCore_9/src/de/steamwar/core/WorldEditRenderer9.java b/SpigotCore/SpigotCore_9/src/de/steamwar/core/WorldEditRenderer9.java
deleted file mode 100644
index 971a759c..00000000
--- a/SpigotCore/SpigotCore_9/src/de/steamwar/core/WorldEditRenderer9.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * This file is a part of the SteamWar software.
- *
- * Copyright (C) 2020 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.core;
-
-import com.sk89q.worldedit.EmptyClipboardException;
-import com.sk89q.worldedit.IncompleteRegionException;
-import com.sk89q.worldedit.LocalSession;
-import com.sk89q.worldedit.bukkit.WorldEditPlugin;
-import com.sk89q.worldedit.extent.clipboard.Clipboard;
-import com.sk89q.worldedit.math.transform.Transform;
-import com.sk89q.worldedit.regions.Region;
-import com.sk89q.worldedit.regions.RegionSelector;
-import com.sk89q.worldedit.world.World;
-import org.bukkit.Bukkit;
-import org.bukkit.Location;
-import org.bukkit.Material;
-import org.bukkit.Particle;
-import org.bukkit.entity.Player;
-import org.bukkit.util.Vector;
-
-public class WorldEditRenderer9 implements WorldEditRenderer {
-
- private static final int VIEW_DISTANCE = 64;
- private static final int SQ_VIEW_DISTANCE = VIEW_DISTANCE * VIEW_DISTANCE;
-
- private static final double STEP_SIZE = 0.5;
-
- private static final Vector ONES = new Vector(1, 1, 1);
-
- private static final Material WAND = FlatteningWrapper.impl.getMaterial("WOOD_AXE");
-
- private final WorldEditPlugin we;
-
- public WorldEditRenderer9() {
- we = WorldEditWrapper.getWorldEditPlugin();
-
- Bukkit.getScheduler().runTaskTimer(Core.getInstance(), this::render, 20, 20);
- }
-
- private void render() {
- for(Player player : Bukkit.getOnlinePlayers()) {
- if(player.getInventory().getItemInMainHand().getType() != WAND)
- continue;
-
- LocalSession session = we.getSession(player);
- try {
- Clipboard clipboard = session.getClipboard().getClipboard();
- Vector pos = player.getLocation().toVector();
- Region region = clipboard.getRegion();
- Transform transform = session.getClipboard().getTransform();
- Vector a = WorldEditWrapper.impl.applyTransform(WorldEditWrapper.impl.getMinimum(region).subtract(WorldEditWrapper.impl.getOrigin(clipboard)), transform).add(pos);
- Vector b = WorldEditWrapper.impl.applyTransform(WorldEditWrapper.impl.getMaximum(region).subtract(WorldEditWrapper.impl.getOrigin(clipboard)), transform).add(pos);
- drawCuboid(Vector.getMinimum(a, b), Vector.getMaximum(a, b), TrickyParticleWrapper.impl.getVillagerHappy(), player);
- } catch (EmptyClipboardException e) {
- //ignore
- }
-
- World world = session.getSelectionWorld();
- if(world != null) {
- RegionSelector regionSelector = session.getRegionSelector(world);
- try {
- Region region = regionSelector.getRegion();
- drawCuboid(WorldEditWrapper.impl.getMinimum(region), WorldEditWrapper.impl.getMaximum(region), Particle.DRAGON_BREATH, player);
- } catch (IncompleteRegionException e) {
- //ignore
- }
- }
- }
- }
-
- private void drawCuboid(Vector min, Vector max, Particle particle, Player owner) {
- max.add(ONES);
-
- for(double x = min.getBlockX(); x <= max.getBlockX(); x += STEP_SIZE) {
- draw(x, min.getBlockY(), min.getBlockZ(), particle, owner);
- draw(x, min.getBlockY(), max.getBlockZ(), particle, owner);
- draw(x, max.getBlockY(), min.getBlockZ(), particle, owner);
- draw(x, max.getBlockY(), max.getBlockZ(), particle, owner);
- }
-
- for(double y = min.getBlockY() + STEP_SIZE; y <= max.getBlockY() - STEP_SIZE; y += STEP_SIZE) {
- draw(min.getBlockX(), y, min.getBlockZ(), particle, owner);
- draw(min.getBlockX(), y, max.getBlockZ(), particle, owner);
- draw(max.getBlockX(), y, min.getBlockZ(), particle, owner);
- draw(max.getBlockX(), y, max.getBlockZ(), particle, owner);
- }
-
- for(double z = min.getBlockZ() + STEP_SIZE; z <= max.getBlockZ() - STEP_SIZE; z += STEP_SIZE) {
- draw(min.getBlockX(), min.getBlockY(), z, particle, owner);
- draw(min.getBlockX(), max.getBlockY(), z, particle, owner);
- draw(max.getBlockX(), min.getBlockY(), z, particle, owner);
- draw(max.getBlockX(), max.getBlockY(), z, particle, owner);
- }
- }
-
- private void draw(double x, double y, double z, Particle particle, Player owner) {
- for(Player player : Bukkit.getOnlinePlayers()) {
- Location location = player.getLocation();
- double dx = x - location.getX();
- double dy = y - location.getY();
- double dz = z - location.getZ();
- if(dx*dx + dy*dy + dz*dz > SQ_VIEW_DISTANCE)
- continue;
-
- player.spawnParticle(player == owner ? particle : org.bukkit.Particle.TOWN_AURA, x, y, z, 1, 0.0, 0.0, 0.0, 0.0);
- }
- }
-}
diff --git a/SpigotCore/SpigotCore_9/src/de/steamwar/core/WorldEditRendererWrapper9.java b/SpigotCore/SpigotCore_9/src/de/steamwar/core/WorldEditRendererWrapper9.java
new file mode 100644
index 00000000..6a06be45
--- /dev/null
+++ b/SpigotCore/SpigotCore_9/src/de/steamwar/core/WorldEditRendererWrapper9.java
@@ -0,0 +1,80 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2020 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.core;
+
+import org.bukkit.Location;
+import org.bukkit.Particle;
+import org.bukkit.entity.Player;
+import org.bukkit.util.Vector;
+
+public class WorldEditRendererWrapper9 implements WorldEditRendererWrapper {
+
+ private static final int VIEW_DISTANCE = 64;
+ private static final int SQ_VIEW_DISTANCE = VIEW_DISTANCE * VIEW_DISTANCE;
+
+ private static final double STEP_SIZE = 0.5;
+ private static final Vector ONES = new Vector(1, 1, 1);
+ private static final Vector STEPS = new Vector(STEP_SIZE, STEP_SIZE, STEP_SIZE);
+
+ @Override
+ public void draw(Player player, Player owner, boolean clipboard, Vector min, Vector max) {
+ max = max.clone().add(ONES);
+ drawLine(player, owner, clipboard, new Vector(min.getX(), min.getY(), min.getZ()), new Vector(max.getX(), min.getY(), min.getZ()));
+ drawLine(player, owner, clipboard, new Vector(min.getX(), max.getY(), min.getZ()), new Vector(max.getX(), max.getY(), min.getZ()));
+ drawLine(player, owner, clipboard, new Vector(min.getX(), min.getY(), max.getZ()), new Vector(max.getX(), min.getY(), max.getZ()));
+ drawLine(player, owner, clipboard, new Vector(min.getX(), max.getY(), max.getZ()), new Vector(max.getX(), max.getY(), max.getZ()));
+
+ drawLine(player, owner, clipboard, new Vector(min.getX(), min.getY(), min.getZ()), new Vector(min.getX(), max.getY(), min.getZ()));
+ drawLine(player, owner, clipboard, new Vector(max.getX(), min.getY(), min.getZ()), new Vector(max.getX(), max.getY(), min.getZ()));
+ drawLine(player, owner, clipboard, new Vector(min.getX(), min.getY(), max.getZ()), new Vector(min.getX(), max.getY(), max.getZ()));
+ drawLine(player, owner, clipboard, new Vector(max.getX(), min.getY(), max.getZ()), new Vector(max.getX(), max.getY(), max.getZ()));
+
+ drawLine(player, owner, clipboard, new Vector(min.getX(), min.getY(), min.getZ()), new Vector(min.getX(), min.getY(), max.getZ()));
+ drawLine(player, owner, clipboard, new Vector(max.getX(), min.getY(), min.getZ()), new Vector(max.getX(), min.getY(), max.getZ()));
+ drawLine(player, owner, clipboard, new Vector(min.getX(), max.getY(), min.getZ()), new Vector(min.getX(), max.getY(), max.getZ()));
+ drawLine(player, owner, clipboard, new Vector(max.getX(), max.getY(), min.getZ()), new Vector(max.getX(), max.getY(), max.getZ()));
+ }
+
+ public void drawLine(Player player, Player owner, boolean clipboard, Vector min, Vector max) {
+ Particle particle;
+ if (player == owner) {
+ if (clipboard) {
+ particle = TrickyParticleWrapper.impl.getVillagerHappy();
+ } else {
+ particle = Particle.DRAGON_BREATH;
+ }
+ } else {
+ particle = Particle.TOWN_AURA;
+ }
+
+ Vector stepSize = max.clone().subtract(min).normalize().multiply(STEPS);
+ while (min.getX() <= max.getX() && min.getY() <= max.getY() && min.getZ() <= max.getZ()) {
+ Location location = player.getLocation();
+ double dx = min.getX() - location.getX();
+ double dy = min.getY() - location.getY();
+ double dz = min.getZ() - location.getZ();
+ if (dx * dx + dy * dy + dz * dz > SQ_VIEW_DISTANCE)
+ continue;
+
+ player.spawnParticle(particle, min.getX(), min.getY(), min.getZ(), 1, 0.0, 0.0, 0.0, 0.0);
+ min.add(stepSize);
+ }
+ }
+}
diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/Core.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/Core.java
index 24b207e8..ca2467b3 100644
--- a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/Core.java
+++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/Core.java
@@ -20,10 +20,15 @@
package de.steamwar.core;
import com.comphenix.tinyprotocol.TinyProtocol;
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
import de.steamwar.Reflection;
import de.steamwar.command.*;
import de.steamwar.core.authlib.AuthlibInjector;
-import de.steamwar.core.events.*;
+import de.steamwar.core.events.AntiNocom;
+import de.steamwar.core.events.ChattingEvent;
+import de.steamwar.core.events.PlayerJoinedEvent;
+import de.steamwar.core.events.WorldLoadEvent;
import de.steamwar.message.Message;
import de.steamwar.network.NetworkReceiver;
import de.steamwar.network.handlers.ServerDataHandler;
@@ -32,23 +37,42 @@ import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.internal.Statement;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
+import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.plugin.java.JavaPlugin;
+import org.bukkit.plugin.messaging.PluginMessageListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
import java.util.logging.Level;
-public class Core extends JavaPlugin{
+public class Core extends JavaPlugin implements PluginMessageListener, Listener {
public static final Message MESSAGE = new Message("SpigotCore", Core.class.getClassLoader());
+ private static final String CHANNEL = "vv:proxy_details";
+ private static final Gson GSON = new Gson();
+ private static final Map playerVersions = new HashMap<>();
+
public static int getVersion(){
return Reflection.MAJOR_VERSION;
}
+ public static int getPlayerVersion(Player player) {
+ return playerVersions.getOrDefault(player, -1);
+ }
+
+ public static boolean isBedrockPlayer(Player player) {
+ return player.getName().startsWith(".");
+ }
+
private static JavaPlugin instance;
public static JavaPlugin getInstance() {
return instance;
@@ -67,6 +91,9 @@ public class Core extends JavaPlugin{
@Override
public void onEnable() {
+ this.getServer().getMessenger().registerIncomingPluginChannel(this, CHANNEL, this);
+ Bukkit.getPluginManager().registerEvents(this, this);
+
errorHandler = new ErrorHandler();
crashDetector = new CrashDetector();
@@ -103,7 +130,7 @@ public class Core extends JavaPlugin{
new ServerDataHandler();
if(Bukkit.getPluginManager().getPlugin("WorldEdit") != null)
- WorldEditRenderer.impl.init();
+ new WorldEditRenderer();
Bukkit.getScheduler().runTaskTimer(this, TabCompletionCache::invalidateOldEntries, 20, 20);
Bukkit.getScheduler().runTaskTimer(Core.getInstance(), SteamwarUser::clear, 72000, 72000);
@@ -122,5 +149,22 @@ public class Core extends JavaPlugin{
errorHandler.unregister();
if(crashDetector.onMainThread())
Statement.closeAll();
+ this.getServer().getMessenger().unregisterIncomingPluginChannel(this);
+ }
+
+ @Override
+ public void onPluginMessageReceived(String channel, Player player, byte[] bytes) {
+ if (!channel.equals(CHANNEL)) {
+ return;
+ }
+
+ final JsonObject payload = GSON.fromJson(new String(bytes), JsonObject.class);
+ final String version = payload.get("versionName").getAsString();
+ playerVersions.put(player, Integer.parseInt(version.split("-")[0].split("\\.")[1]));
+ }
+
+ @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
+ public void onPlayerQuit(PlayerQuitEvent event) {
+ playerVersions.remove(event.getPlayer());
}
}
diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/VersionDependent.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/VersionDependent.java
index 5e8ec241..2fe94ce5 100644
--- a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/VersionDependent.java
+++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/VersionDependent.java
@@ -31,8 +31,16 @@ public class VersionDependent {
}
public static T getVersionImpl(Plugin plugin, String className){
+ return getVersionImpl(plugin, Core.getVersion(), className);
+ }
+
+ public static T getVersionImpl(Plugin plugin, int fromVersion){
+ return getVersionImpl(plugin, fromVersion, (new Exception()).getStackTrace()[1].getClassName());
+ }
+
+ public static T getVersionImpl(Plugin plugin, int fromVersion, String className){
ClassLoader loader = plugin.getClass().getClassLoader();
- for(int version = Core.getVersion(); version >= 8; version--) {
+ for(int version = fromVersion; version >= 8; version--) {
try {
return ((Class extends T>) Class.forName(className + version, true, loader)).getDeclaredConstructor().newInstance();
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/WorldEditRenderer.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/WorldEditRenderer.java
index 6b90f1d2..7bf68c99 100644
--- a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/WorldEditRenderer.java
+++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/WorldEditRenderer.java
@@ -1,27 +1,166 @@
/*
- * This file is a part of the SteamWar software.
+ * This file is a part of the SteamWar software.
*
- * Copyright (C) 2020 SteamWar.de-Serverteam
+ * 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 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.
+ * 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 .
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
*/
package de.steamwar.core;
-public interface WorldEditRenderer {
- WorldEditRenderer impl = VersionDependent.getVersionImpl(Core.getInstance());
+import com.sk89q.worldedit.EmptyClipboardException;
+import com.sk89q.worldedit.IncompleteRegionException;
+import com.sk89q.worldedit.LocalSession;
+import com.sk89q.worldedit.bukkit.WorldEditPlugin;
+import com.sk89q.worldedit.extent.clipboard.Clipboard;
+import com.sk89q.worldedit.math.transform.Transform;
+import com.sk89q.worldedit.regions.Region;
+import com.sk89q.worldedit.regions.RegionSelector;
+import com.sk89q.worldedit.world.World;
+import org.bukkit.Bukkit;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.block.BlockBreakEvent;
+import org.bukkit.event.player.*;
+import org.bukkit.util.Vector;
- default void init() {
+public class WorldEditRenderer implements Listener {
+
+ private static final Material WAND = FlatteningWrapper.impl.getMaterial("WOOD_AXE");
+
+ private final WorldEditPlugin we;
+
+ public WorldEditRenderer() {
+ we = WorldEditWrapper.getWorldEditPlugin();
+ Bukkit.getPluginManager().registerEvents(this, Core.getInstance());
+
+ Bukkit.getScheduler().runTaskTimer(Core.getInstance(), this::render, 20, 20);
+ }
+
+ private void render() {
+ for(Player player : Bukkit.getOnlinePlayers()) {
+ renderPlayer(player);
+ }
+ }
+
+ private void renderPlayer(Player player) {
+ LocalSession session = we.getSession(player);
+ renderClipboard(player, session);
+ renderRegion(player, session);
+ }
+
+ private void renderClipboard(Player player, LocalSession session) {
+ try {
+ Clipboard clipboard = session.getClipboard().getClipboard();
+ Vector pos = player.getLocation().toVector();
+ Region region = clipboard.getRegion();
+ Transform transform = session.getClipboard().getTransform();
+ Vector a = WorldEditWrapper.impl.applyTransform(WorldEditWrapper.impl.getMinimum(region).subtract(WorldEditWrapper.impl.getOrigin(clipboard)), transform).add(pos);
+ Vector b = WorldEditWrapper.impl.applyTransform(WorldEditWrapper.impl.getMaximum(region).subtract(WorldEditWrapper.impl.getOrigin(clipboard)), transform).add(pos);
+ a = new Vector(a.getBlockX(), a.getBlockY(), a.getBlockZ());
+ b = new Vector(b.getBlockX(), b.getBlockY(), b.getBlockZ());
+ WorldEditRendererWrapper.impl.hide(player, player, true, false);
+ drawCuboid(Vector.getMinimum(a, b), Vector.getMaximum(a, b), true, player);
+ } catch (EmptyClipboardException e) {
+ WorldEditRendererWrapper.impl.hide(player, player, true, true);
+ }
+ }
+
+ private void renderRegion(Player player, LocalSession session) {
+ World world = session.getSelectionWorld();
+ if(world != null) {
+ RegionSelector regionSelector = session.getRegionSelector(world);
+ try {
+ Region region = regionSelector.getRegion();
+ WorldEditRendererWrapper.impl.hide(player, player, false, false);
+ drawCuboid(WorldEditWrapper.impl.getMinimum(region), WorldEditWrapper.impl.getMaximum(region), false, player);
+ } catch (IncompleteRegionException e) {
+ WorldEditRendererWrapper.impl.hide(player, player, false, true);
+ }
+ }
+ }
+
+ private void drawCuboid(Vector min, Vector max, boolean clipboard, Player owner) {
+ for (Player player : Bukkit.getOnlinePlayers()) {
+ //noinspection deprecation
+ if(player.getItemInHand().getType() != WAND) {
+ WorldEditRendererWrapper.impl.hide(player, owner, true, true);
+ WorldEditRendererWrapper.impl.hide(player, owner, false, true);
+ } else {
+ WorldEditRendererWrapper.impl.hide(player, owner, true, false);
+ WorldEditRendererWrapper.impl.hide(player, owner, false, false);
+ WorldEditRendererWrapper.safeDraw(player, owner, clipboard, min, max);
+ }
+ }
+ }
+
+ @EventHandler
+ public void onPlayerJoin(PlayerJoinEvent event) {
+ renderPlayer(event.getPlayer());
+ }
+
+ @EventHandler
+ public void onPlayerMove(PlayerMoveEvent event) {
+ WorldEditRendererWrapper.impl.tick(event.getPlayer());
+
+ renderClipboard(event.getPlayer(), we.getSession(event.getPlayer()));
+ }
+
+ @EventHandler
+ public void onPlayerInteract(PlayerInteractEvent event) {
+ renderRegion(event.getPlayer(), we.getSession(event.getPlayer()));
+ }
+
+ @EventHandler
+ public void onBlockBreak(BlockBreakEvent event) {
+ renderRegion(event.getPlayer(), we.getSession(event.getPlayer()));
+ }
+
+ @EventHandler
+ public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) {
+ if (event.getMessage().startsWith("//")) {
+ Bukkit.getScheduler().runTaskLater(Core.getInstance(), () -> {
+ LocalSession session = we.getSession(event.getPlayer());
+ renderRegion(event.getPlayer(), session);
+ renderClipboard(event.getPlayer(), session);
+ }, 5);
+ }
+ }
+
+ @EventHandler
+ public void onPlayerSwapHandItems(PlayerSwapHandItemsEvent event) {
+ Bukkit.getScheduler().runTaskLater(Core.getInstance(), () -> {
+ renderPlayer(event.getPlayer());
+ }, 1);
+ }
+
+ @EventHandler
+ public void onPlayerDropItem(PlayerDropItemEvent event) {
+ renderPlayer(event.getPlayer());
+ }
+
+ @EventHandler
+ public void onPlayerItemHeld(PlayerItemHeldEvent event) {
+ Bukkit.getScheduler().runTaskLater(Core.getInstance(), () -> {
+ renderPlayer(event.getPlayer());
+ }, 1);
+ }
+
+ @EventHandler
+ public void onPlayerQuit(PlayerQuitEvent event) {
+ WorldEditRendererWrapper.impl.remove(event.getPlayer());
}
}
diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/WorldEditRendererWrapper.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/WorldEditRendererWrapper.java
new file mode 100644
index 00000000..63380fdc
--- /dev/null
+++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/WorldEditRendererWrapper.java
@@ -0,0 +1,47 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2020 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.core;
+
+import org.bukkit.entity.Player;
+import org.bukkit.util.Vector;
+
+public interface WorldEditRendererWrapper {
+ WorldEditRendererWrapper fallback = VersionDependent.getVersionImpl(Core.getInstance(), 9);
+ WorldEditRendererWrapper impl = VersionDependent.getVersionImpl(Core.getInstance());
+
+ static void safeDraw(Player player, Player owner, boolean clipboard, Vector pos1, Vector pos2) {
+ if (Core.isBedrockPlayer(player) || Core.getPlayerVersion(player) < 20) {
+ fallback.draw(player, owner, clipboard, pos1, pos2);
+ } else {
+ impl.draw(player, owner, clipboard, pos1, pos2);
+ }
+ }
+
+ void draw(Player player, Player owner, boolean clipboard, Vector pos1, Vector pos2);
+
+ default void tick(Player player) {
+ }
+
+ default void hide(Player player, Player owner, boolean clipboard, boolean hide) {
+ }
+
+ default void remove(Player player) {
+ }
+}
diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/entity/CAABox.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/entity/CAABox.java
new file mode 100644
index 00000000..80d94c88
--- /dev/null
+++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/entity/CAABox.java
@@ -0,0 +1,103 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2020 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.entity;
+
+import org.bukkit.Location;
+import org.bukkit.World;
+import org.bukkit.block.data.BlockData;
+import org.bukkit.util.Vector;
+
+import java.util.List;
+
+/**
+ * Compound Axis Aligned Box (12 CAALine)
+ */
+public class CAABox extends CEntity {
+
+ public static final float DEFAULT_WIDTH = 1 / 16f;
+ private float width = DEFAULT_WIDTH;
+
+ private Location pos1;
+ private Location pos2;
+
+ public CAABox(REntityServer server) {
+ super(server);
+ }
+
+ public CAABox setPos1(Location pos1) {
+ this.pos1 = pos1;
+ updateAndSpawnLines();
+ return this;
+ }
+
+ public CAABox setPos2(Location pos2) {
+ this.pos2 = pos2;
+ updateAndSpawnLines();
+ return this;
+ }
+
+ public CAABox setWidth(float width) {
+ this.width = width;
+ updateAndSpawnLines();
+ getEntitiesByType(CAALine.class).forEach(haaLine -> {
+ haaLine.setWidth(width);
+ });
+ return this;
+ }
+
+ public CAABox setBlock(BlockData blockData) {
+ getEntitiesByType(CAALine.class).forEach(haaLine -> {
+ haaLine.setBlock(blockData);
+ });
+ return this;
+ }
+
+ private void updateAndSpawnLines() {
+ if (pos1 == null || pos2 == null) return;
+ if (entities.isEmpty()) {
+ for (int i = 0; i < 12; i++) {
+ entities.add(new CAALine(server));
+ }
+ }
+
+ World world = pos1.getWorld();
+ Vector min = Vector.getMinimum(pos1.toVector(), pos2.toVector());
+ Vector max = Vector.getMaximum(pos1.toVector(), pos2.toVector())
+ .add(new Vector(1 - width, 1 - width, 1 - width));
+
+ List lines = getEntitiesByType(CAALine.class);
+ lines.forEach(line -> line.setFrom(null).setTo(null));
+
+ lines.get(0).setFrom(new Vector(min.getX(), min.getY(), min.getZ()).toLocation(world)).setTo(new Vector(max.getX() + width, min.getY(), min.getZ()).toLocation(world));
+ lines.get(1).setFrom(new Vector(min.getX(), max.getY(), min.getZ()).toLocation(world)).setTo(new Vector(max.getX() + width, max.getY(), min.getZ()).toLocation(world));
+ lines.get(2).setFrom(new Vector(min.getX(), min.getY(), max.getZ()).toLocation(world)).setTo(new Vector(max.getX() + width, min.getY(), max.getZ()).toLocation(world));
+ lines.get(3).setFrom(new Vector(min.getX(), max.getY(), max.getZ()).toLocation(world)).setTo(new Vector(max.getX() + width, max.getY(), max.getZ()).toLocation(world));
+
+ lines.get(4).setFrom(new Vector(min.getX(), min.getY(), min.getZ()).toLocation(world)).setTo(new Vector(min.getX(), max.getY() + width, min.getZ()).toLocation(world));
+ lines.get(5).setFrom(new Vector(max.getX(), min.getY(), min.getZ()).toLocation(world)).setTo(new Vector(max.getX(), max.getY() + width, min.getZ()).toLocation(world));
+ lines.get(6).setFrom(new Vector(min.getX(), min.getY(), max.getZ()).toLocation(world)).setTo(new Vector(min.getX(), max.getY() + width, max.getZ()).toLocation(world));
+ lines.get(7).setFrom(new Vector(max.getX(), min.getY(), max.getZ()).toLocation(world)).setTo(new Vector(max.getX(), max.getY() + width, max.getZ()).toLocation(world));
+
+ lines.get(8).setFrom(new Vector(min.getX(), min.getY(), min.getZ()).toLocation(world)).setTo(new Vector(min.getX(), min.getY(), max.getZ() + width).toLocation(world));
+ lines.get(9).setFrom(new Vector(max.getX(), min.getY(), min.getZ()).toLocation(world)).setTo(new Vector(max.getX(), min.getY(), max.getZ() + width).toLocation(world));
+ lines.get(10).setFrom(new Vector(min.getX(), max.getY(), min.getZ()).toLocation(world)).setTo(new Vector(min.getX(), max.getY(), max.getZ() + width).toLocation(world));
+ lines.get(11).setFrom(new Vector(max.getX(), max.getY(), min.getZ()).toLocation(world)).setTo(new Vector(max.getX(), max.getY(), max.getZ() + width).toLocation(world));
+ }
+}
diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/entity/CAALine.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/entity/CAALine.java
new file mode 100644
index 00000000..19a6ef9f
--- /dev/null
+++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/entity/CAALine.java
@@ -0,0 +1,246 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2020 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.entity;
+
+import org.bukkit.Location;
+import org.bukkit.block.data.BlockData;
+import org.bukkit.entity.Display;
+import org.bukkit.entity.Player;
+import org.bukkit.util.Transformation;
+import org.bukkit.util.Vector;
+import org.joml.Quaternionf;
+import org.joml.Vector3f;
+
+import java.util.Objects;
+
+public class CAALine extends CEntity {
+
+ public static final float DEFAULT_WIDTH = 1 / 16f;
+ private static final float offset = 1 / 1024f;
+ private static final Vector offsetVec = new Vector(offset, offset, offset);
+
+ private Location from;
+ private Location to;
+ private float width = DEFAULT_WIDTH;
+ private BlockData blockData = RBlockDisplay.DEFAULT_BLOCK;
+
+ public CAALine(REntityServer server) {
+ super(server);
+ tick();
+ }
+
+ public CAALine setFrom(Location from) {
+ if (Objects.equals(from, this.from)) return this;
+ this.from = from;
+ tick();
+ return this;
+ }
+
+ public CAALine setTo(Location to) {
+ if (Objects.equals(to, this.to)) return this;
+ this.to = to;
+ tick();
+ return this;
+ }
+
+ public CAALine setWidth(float width) {
+ if (this.width == width) return this;
+ this.width = width;
+ tick();
+ return this;
+ }
+
+ public CAALine setBlock(BlockData blockData) {
+ if (this.blockData.equals(blockData)) return this;
+ if (blockData == null) {
+ this.blockData = RBlockDisplay.DEFAULT_BLOCK;
+ } else {
+ this.blockData = blockData;
+ }
+ getEntitiesByType(RBlockDisplay.class).forEach(display -> {
+ display.setBlock(blockData);
+ });
+ return this;
+ }
+
+ private boolean hide = false;
+
+ @Override
+ public void hide(boolean hide) {
+ if (hide == this.hide) return;
+ this.hide = hide;
+ if (hide) {
+ if (startLine != null) startLine.hide(true);
+ if (middleLine != null) middleLine.hide(true);
+ if (endLine != null) endLine.hide(true);
+ } else {
+ tick();
+ }
+ }
+
+ @Override
+ void tick() {
+ if (from == null || to == null) return;
+ if (hide) return;
+ updateStart();
+ updateMiddle();
+ updateEnd();
+ }
+
+ private RBlockDisplay startLine;
+ private void updateStart() {
+ Vector vec = to.clone().subtract(from).toVector();
+ if (vec.length() > 35) vec.normalize().multiply(35);
+
+ if (startLine == null) {
+ startLine = new RBlockDisplay(server, new Location(null, 0, 0, 0));
+ startLine.setBrightness(new Display.Brightness(15, 15));
+ startLine.setViewRange(560);
+ startLine.setBlock(blockData);
+ entities.add(startLine);
+ } else {
+ startLine.hide(false);
+ }
+
+ startLine.move(from.clone().subtract(offsetVec));
+ startLine.setTransform(new Transformation(new Vector3f(0, 0, 0), new Quaternionf(0, 0, 0, 1), addWidth(vec).toVector3f(), new Quaternionf(0, 0, 0, 1)));
+ }
+
+ private RBlockDisplay middleLine;
+ private void updateMiddle() {
+ Vector vec = to.clone().subtract(from).toVector();
+ if (vec.length() <= 70) {
+ if (middleLine != null) middleLine.hide(true);
+ return;
+ }
+ if (vec.length() > 280) vec.normalize().multiply(280);
+ else vec = vec.clone().normalize().multiply(vec.length() - 60);
+
+ if (middleLine == null) {
+ middleLine = new RBlockDisplay(server, new Location(null, 0, 0, 0));
+ middleLine.setBrightness(new Display.Brightness(15, 15));
+ middleLine.setViewRange(560);
+ middleLine.setBlock(blockData);
+ entities.add(middleLine);
+ } else {
+ middleLine.hide(false);
+ }
+
+ Player player = server.getPlayers().stream().findFirst().orElse(null);
+ if (player == null) return;
+
+ Vector tempVector = vec.clone().normalize().multiply(30);
+ Location from = this.from.clone().add(tempVector);
+ Location to = this.to.clone().subtract(tempVector);
+
+ Vector lineVec = to.clone().subtract(from).toVector();
+ Vector playerVec = player.getLocation().toVector().subtract(from.toVector());
+ double lineVecDotItself = lineVec.dot(lineVec);
+ Vector projectionVec = lineVec.clone().multiply(lineVec.dot(playerVec)).divide(new Vector(lineVecDotItself, lineVecDotItself, lineVecDotItself));
+
+ Vector moveVec = from.toVector().add(projectionVec);
+ if (moveVec.getX() < from.getX()) {
+ moveVec.setX(from.getX());
+ }
+ if (moveVec.getX() > to.getX()) {
+ moveVec.setX(to.getX());
+ }
+ if (moveVec.getY() < from.getY()) {
+ moveVec.setY(from.getY());
+ }
+ if (moveVec.getY() > to.getY()) {
+ moveVec.setY(to.getY());
+ }
+ if (moveVec.getZ() < from.getZ()) {
+ moveVec.setZ(from.getZ());
+ }
+ if (moveVec.getZ() > to.getZ()) {
+ moveVec.setZ(to.getZ());
+ }
+
+ Vector translation = vec.clone().divide(new Vector(2, 2, 2));
+ translation.setX(-translation.getX());
+ translation.setY(-translation.getY());
+ translation.setZ(-translation.getZ());
+
+ Vector first = moveVec.clone().add(translation).subtract(from.toVector());
+ if (first.getX() < 0) {
+ translation.setX(translation.getX() - first.getX());
+ }
+ if (first.getY() < 0) {
+ translation.setY(translation.getY() - first.getY());
+ }
+ if (first.getZ() < 0) {
+ translation.setZ(translation.getZ() - first.getZ());
+ }
+
+ Vector second = to.toVector().subtract(moveVec.clone().subtract(translation));
+ if (second.getX() < 0) {
+ translation.setX(translation.getX() + second.getX());
+ }
+ if (second.getY() < 0) {
+ translation.setY(translation.getY() + second.getY());
+ }
+ if (second.getZ() < 0) {
+ translation.setZ(translation.getZ() + second.getZ());
+ }
+
+ middleLine.move(moveVec.toLocation(player.getWorld()).subtract(offsetVec));
+ middleLine.setTransform(new Transformation(translation.toVector3f(), new Quaternionf(0, 0, 0, 1), addWidth(vec).toVector3f(), new Quaternionf(0, 0, 0, 1)));
+ }
+
+ private RBlockDisplay endLine;
+ private void updateEnd() {
+ Vector vec = to.clone().subtract(from).toVector();
+ if (vec.length() <= 35) {
+ if (endLine != null) endLine.hide(true);
+ return;
+ }
+ if (vec.length() > 35) vec.normalize().multiply(35);
+
+ if (endLine == null) {
+ endLine = new RBlockDisplay(server, new Location(null, 0, 0, 0));
+ endLine.setBrightness(new Display.Brightness(15, 15));
+ endLine.setViewRange(560);
+ endLine.setBlock(blockData);
+ entities.add(endLine);
+ } else {
+ endLine.hide(false);
+ }
+
+ endLine.move(to.clone().subtract(offsetVec));
+ endLine.setTransform(new Transformation(vec.toVector3f().negate(), new Quaternionf(0, 0, 0, 1), addWidth(vec).toVector3f(), new Quaternionf(0, 0, 0, 1)));
+ }
+
+ private Vector addWidth(Vector vector) {
+ vector = vector.clone();
+ if (vector.getX() == 0) {
+ vector.setX(vector.getX() + width);
+ }
+ if (vector.getY() == 0) {
+ vector.setY(vector.getY() + width);
+ }
+ if (vector.getZ() == 0) {
+ vector.setZ(vector.getZ() + width);
+ }
+ vector.add(offsetVec).add(offsetVec);
+ return vector;
+ }
+}