diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java index 0d5fa43c..8376f0f1 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java @@ -19,6 +19,7 @@ package de.steamwar.bausystem; +import de.steamwar.core.WorldEditRendererCUIEditor; import de.steamwar.bausystem.config.BauServer; import de.steamwar.bausystem.configplayer.Config; import de.steamwar.bausystem.configplayer.ConfigConverter; @@ -206,6 +207,8 @@ public class BauSystem extends JavaPlugin { TraceManager.instance.init(); TraceRecorder.instance.init(); + + new WorldEditRendererCUIEditor(); } @Override diff --git a/CommonCore/Network/src/de/steamwar/network/packets/server/ClientVersionPacket.java b/CommonCore/Network/src/de/steamwar/network/packets/server/ClientVersionPacket.java new file mode 100644 index 00000000..c8f43446 --- /dev/null +++ b/CommonCore/Network/src/de/steamwar/network/packets/server/ClientVersionPacket.java @@ -0,0 +1,37 @@ +/* + * 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.network.packets.server; + +import de.steamwar.network.packets.NetworkPacket; +import lombok.*; + +import java.util.UUID; + +@EqualsAndHashCode(callSuper = true) +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ToString +public class ClientVersionPacket extends NetworkPacket { + private static final long serialVersionUID = 3686482311704273200L; + + private UUID player; + private int version; +} diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java index ce47ee34..9ebc4f0c 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java @@ -20,6 +20,7 @@ package de.steamwar.fightsystem; import com.comphenix.tinyprotocol.TinyProtocol; +import de.steamwar.core.WorldEditRendererCUIEditor; import de.steamwar.core.Core; import de.steamwar.fightsystem.commands.*; import de.steamwar.fightsystem.countdown.*; @@ -28,8 +29,8 @@ import de.steamwar.fightsystem.fight.Fight; import de.steamwar.fightsystem.fight.FightTeam; import de.steamwar.fightsystem.fight.FightWorld; import de.steamwar.fightsystem.fight.HotbarKit; -import de.steamwar.fightsystem.listener.Shutdown; import de.steamwar.fightsystem.listener.*; +import de.steamwar.fightsystem.listener.Shutdown; import de.steamwar.fightsystem.record.FileRecorder; import de.steamwar.fightsystem.record.FileSource; import de.steamwar.fightsystem.record.GlobalRecorder; @@ -106,6 +107,7 @@ public class FightSystem extends JavaPlugin { new HotbarKit.HotbarKitListener(); new JoinRequestListener(); new OneShotStateDependent(ArenaMode.All, FightState.PreSchemSetup, () -> Fight.playSound(SWSound.BLOCK_NOTE_PLING.getSound(), 100.0f, 2.0f)); + new OneShotStateDependent(ArenaMode.Test, FightState.All, WorldEditRendererCUIEditor::new); new EnterHandler(); techHider = new TechHiderWrapper(); diff --git a/SpigotCore/SpigotCore_20/build.gradle.kts b/SpigotCore/SpigotCore_20/build.gradle.kts index 3e894ccc..79f667e0 100644 --- a/SpigotCore/SpigotCore_20/build.gradle.kts +++ b/SpigotCore/SpigotCore_20/build.gradle.kts @@ -26,5 +26,6 @@ dependencies { compileOnly(libs.spigotapi) + compileOnly(libs.fawe18) compileOnly(libs.nms20) } 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..36ded8ef --- /dev/null +++ b/SpigotCore/SpigotCore_20/src/de/steamwar/core/WorldEditRendererWrapper20.java @@ -0,0 +1,119 @@ +/* + * 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.CWireframe; +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.HashMap; +import java.util.Map; + +public class WorldEditRendererWrapper20 implements WorldEditRendererWrapper { + + private static final class BoxPair { + private CWireframe regionBox; + private CWireframe clipboardBox; + + public CWireframe get(boolean clipboard) { + if (clipboard) { + return clipboardBox; + } else { + return regionBox; + } + } + + public void set(boolean clipboard, CWireframe 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, boolean scheduled, boolean clipboard, Vector pos1, Vector pos2) { + REntityServer server = servers.computeIfAbsent(player, __ -> { + REntityServer entityServer = new REntityServer(); + entityServer.addPlayer(player); + return entityServer; + }); + + WorldEditRendererCUIEditor.Type type = clipboard ? WorldEditRendererCUIEditor.Type.CLIPBOARD : WorldEditRendererCUIEditor.Type.SELECTION; + float width = type.getWidth(player).value; + Material material = type.getMaterial(player); + if (material == Material.BARRIER) { + hide(player, clipboard, true); + return; + } + BlockData block = material.createBlockData(); + + BoxPair boxPair = boxes.computeIfAbsent(player, __ -> new BoxPair()); + CWireframe box = boxPair.get(clipboard); + if (box == null) { + box = new CWireframe(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, boolean clipboard, boolean hide) { + BoxPair boxPair = boxes.get(player); + if (boxPair == null) return; + CWireframe box = boxPair.get(clipboard); + if (box == null) return; + box.hide(hide); + } + + @Override + public void remove(Player player) { + BoxPair boxPair = boxes.remove(player); + if (boxPair != null) boxPair.die(); + REntityServer server = servers.remove(player); + if (server != null) server.close(); + } +} diff --git a/SpigotCore/SpigotCore_8/src/de/steamwar/core/WorldEditRendererWrapper8.java b/SpigotCore/SpigotCore_8/src/de/steamwar/core/WorldEditRendererWrapper8.java new file mode 100644 index 00000000..68f64c46 --- /dev/null +++ b/SpigotCore/SpigotCore_8/src/de/steamwar/core/WorldEditRendererWrapper8.java @@ -0,0 +1,42 @@ +/* + * 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 class WorldEditRendererWrapper8 implements WorldEditRendererWrapper { + + @Override + public void draw(Player player, boolean scheduled, boolean clipboard, Vector pos1, Vector pos2) { + } + + @Override + public void tick(Player player) { + } + + @Override + public void hide(Player player, boolean clipboard, boolean hide) { + } + + @Override + public void remove(Player player) { + } +} diff --git a/SpigotCore/SpigotCore_9/build.gradle.kts b/SpigotCore/SpigotCore_9/build.gradle.kts index a888faf1..c149a3fd 100644 --- a/SpigotCore/SpigotCore_9/build.gradle.kts +++ b/SpigotCore/SpigotCore_9/build.gradle.kts @@ -26,4 +26,5 @@ dependencies { compileOnly(project(":SpigotCore:SpigotCore_8", "default")) compileOnly(libs.nms9) + compileOnly(libs.worldedit12) } 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..5da6104a --- /dev/null +++ b/SpigotCore/SpigotCore_9/src/de/steamwar/core/WorldEditRendererWrapper9.java @@ -0,0 +1,92 @@ +/* + * 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, boolean scheduled, boolean clipboard, Vector min, Vector max) { + if (!scheduled) return; + + max = max.clone().add(ONES); + drawLine(player, clipboard, new Vector(min.getX(), min.getY(), min.getZ()), new Vector(max.getX(), min.getY(), min.getZ())); + drawLine(player, clipboard, new Vector(min.getX(), max.getY(), min.getZ()), new Vector(max.getX(), max.getY(), min.getZ())); + drawLine(player, clipboard, new Vector(min.getX(), min.getY(), max.getZ()), new Vector(max.getX(), min.getY(), max.getZ())); + drawLine(player, clipboard, new Vector(min.getX(), max.getY(), max.getZ()), new Vector(max.getX(), max.getY(), max.getZ())); + + drawLine(player, clipboard, new Vector(min.getX(), min.getY(), min.getZ()), new Vector(min.getX(), max.getY(), min.getZ())); + drawLine(player, clipboard, new Vector(max.getX(), min.getY(), min.getZ()), new Vector(max.getX(), max.getY(), min.getZ())); + drawLine(player, clipboard, new Vector(min.getX(), min.getY(), max.getZ()), new Vector(min.getX(), max.getY(), max.getZ())); + drawLine(player, clipboard, new Vector(max.getX(), min.getY(), max.getZ()), new Vector(max.getX(), max.getY(), max.getZ())); + + drawLine(player, clipboard, new Vector(min.getX(), min.getY(), min.getZ()), new Vector(min.getX(), min.getY(), max.getZ())); + drawLine(player, clipboard, new Vector(max.getX(), min.getY(), min.getZ()), new Vector(max.getX(), min.getY(), max.getZ())); + drawLine(player, clipboard, new Vector(min.getX(), max.getY(), min.getZ()), new Vector(min.getX(), max.getY(), max.getZ())); + drawLine(player, clipboard, new Vector(max.getX(), max.getY(), min.getZ()), new Vector(max.getX(), max.getY(), max.getZ())); + } + + private void drawLine(Player player, boolean clipboard, Vector min, Vector max) { + Particle particle; + if (clipboard) { + particle = TrickyParticleWrapper.impl.getVillagerHappy(); + } else { + particle = Particle.DRAGON_BREATH; + } + + 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) { + min.add(stepSize); + continue; + } + + player.spawnParticle(particle, min.getX(), min.getY(), min.getZ(), 1, 0.0, 0.0, 0.0, 0.0); + min.add(stepSize); + } + } + + @Override + public void tick(Player player) { + } + + @Override + public void hide(Player player, boolean clipboard, boolean hide) { + } + + @Override + public void remove(Player player) { + } +} diff --git a/SpigotCore/SpigotCore_Main/src/SpigotCore.properties b/SpigotCore/SpigotCore_Main/src/SpigotCore.properties index 10c64603..94e57d6c 100644 --- a/SpigotCore/SpigotCore_Main/src/SpigotCore.properties +++ b/SpigotCore/SpigotCore_Main/src/SpigotCore.properties @@ -105,3 +105,22 @@ NOSCHEMSUBMITTING_PERMA=§7You are §epermanently§7 excluded from submitting § NOSCHEMSUBMITTING_UNTIL=§7You are excluded from submitting §e§lschematics §euntil {0}§8: §e{1} UNNOSCHEMSUBMITTING_ERROR=§cThe player is not excluded from submitting schematics. UNNOSCHEMSUBMITTING=§e{0} §7may now submit §e§lschematics§7 again§8. + +WORLDEDIT_CUI_TITLE = WorldEdit CUI +WORLDEDIT_CUI_TITLE_SUBMENU = WorldEdit CUI - {0} +WORLDEDIT_CUI_SELECTION = Own Selection +WORLDEDIT_CUI_CLIPBOARD = Own Clipboard +WORLDEDIT_CUI_SELECTION_OTHER = Other Selection +WORLDEDIT_CUI_CLIPBOARD_OTHER = Other Clipboard + +WORLDEDIT_CUI_MATERIAL_NAME = §eWorldEdit {0} +WORLDEDIT_CUI_MATERIAL_CLICK = §7Click to edit + +WORLDEDIT_CUI_WIDTH_NAME = §eWidth {0} +WORLDEDIT_CUI_WIDTH_LORE = §8> §7{0} +WORLDEDIT_CUI_WIDTH_LORE_SELECTED = §8> §e{0} +WORLDEDIT_CUI_WIDTH_CLICK = §7Click to change +WORLDEDIT_CUI_WIDTH_HUGE = 1/ 8 Block +WORLDEDIT_CUI_WIDTH_LARGE = 1/16 Block +WORLDEDIT_CUI_WIDTH_MEDIUM = 1/32 Block +WORLDEDIT_CUI_WIDTH_SLIM = 1/64 Block \ No newline at end of file diff --git a/SpigotCore/SpigotCore_Main/src/SpigotCore_de.properties b/SpigotCore/SpigotCore_Main/src/SpigotCore_de.properties index 83fa39f5..1f573eff 100644 --- a/SpigotCore/SpigotCore_Main/src/SpigotCore_de.properties +++ b/SpigotCore/SpigotCore_Main/src/SpigotCore_de.properties @@ -99,4 +99,15 @@ NOSCHEMSUBMITTING_TEAM={0} §e{1} §7wurde von §e{2} {3} §7vom §e§lSchematic NOSCHEMSUBMITTING_PERMA=§7Du bist §epermanent §7vom §e§lEinsenden von Schematics§7 ausgeschlossen§8: §e{0} NOSCHEMSUBMITTING_UNTIL=§7Du bist §ebis zum {0} §7vom §e§lEinsenden von Schematics§7 ausgeschlossen§8: §e{1} UNNOSCHEMSUBMITTING_ERROR=§cDer Spieler ist nicht vom Einsenden von Schematics ausgeschlossen. -UNNOSCHEMSUBMITTING=§e{0} §7darf nun wieder §e§lSchematis§7 einsenden§8. \ No newline at end of file +UNNOSCHEMSUBMITTING=§e{0} §7darf nun wieder §e§lSchematis§7 einsenden§8. + +WORLDEDIT_CUI_SELECTION = Eigene Auswahl +WORLDEDIT_CUI_CLIPBOARD = Eigene Kopie +WORLDEDIT_CUI_SELECTION_OTHER = Auswahl Anderer +WORLDEDIT_CUI_CLIPBOARD_OTHER = Kopie Anderer + +WORLDEDIT_CUI_MATERIAL_NAME = §eWorldEdit {0} +WORLDEDIT_CUI_MATERIAL_CLICK = §7Klicke zum Editieren + +WORLDEDIT_CUI_WIDTH_NAME = §eDicke - {0} +WORLDEDIT_CUI_WIDTH_CLICK = §7Klicke zum ändern \ No newline at end of file diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/Core.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/Core.java index 4e7b7576..c2086b0b 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/Core.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/Core.java @@ -23,7 +23,10 @@ import com.comphenix.tinyprotocol.TinyProtocol; 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; @@ -41,7 +44,7 @@ import java.io.InputStreamReader; import java.util.Collection; import java.util.logging.Level; -public class Core extends JavaPlugin{ +public class Core extends JavaPlugin { public static final Message MESSAGE = new Message("SpigotCore", Core.class.getClassLoader()); @@ -67,6 +70,8 @@ public class Core extends JavaPlugin{ @Override public void onEnable() { + new PlayerVersion(); + errorHandler = new ErrorHandler(); crashDetector = new CrashDetector(); @@ -102,7 +107,7 @@ public class Core extends JavaPlugin{ if(Core.getVersion() >= 19) new ServerDataHandler(); - if(Core.getVersion() > 8 && Bukkit.getPluginManager().getPlugin("WorldEdit") != null) + if(Bukkit.getPluginManager().getPlugin("WorldEdit") != null) new WorldEditRenderer(); Bukkit.getScheduler().runTaskTimer(this, TabCompletionCache::invalidateOldEntries, 20, 20); diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/PlayerVersion.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/PlayerVersion.java new file mode 100644 index 00000000..512df0d3 --- /dev/null +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/PlayerVersion.java @@ -0,0 +1,61 @@ +/* + * 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.network.packets.PacketHandler; +import de.steamwar.network.packets.server.ClientVersionPacket; +import org.bukkit.Bukkit; +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 java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class PlayerVersion extends PacketHandler implements Listener { + + private static final Map playerVersions = new HashMap<>(); + + public static int getVersion(Player player) { + return playerVersions.getOrDefault(player.getUniqueId(), -1); + } + + public static boolean isBedrock(Player player) { + return player.getName().startsWith("."); + } + + public PlayerVersion() { + Bukkit.getPluginManager().registerEvents(this, Core.getInstance()); + register(); + } + + @Handler + public void handlePacket(ClientVersionPacket clientVersionPacket) { + playerVersions.put(clientVersionPacket.getPlayer(), clientVersionPacket.getVersion()); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onPlayerQuit(PlayerQuitEvent event) { + playerVersions.remove(event.getPlayer().getUniqueId()); + } +} 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) 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 377efe13..5e359512 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/WorldEditRenderer.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/WorldEditRenderer.java @@ -29,20 +29,15 @@ 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.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.player.*; import org.bukkit.util.Vector; -public class 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); +public class WorldEditRenderer implements Listener { private static final Material WAND = FlatteningWrapper.impl.getMaterial("WOOD_AXE"); @@ -50,77 +45,116 @@ public class WorldEditRenderer { public WorldEditRenderer() { we = WorldEditWrapper.getWorldEditPlugin(); + Bukkit.getPluginManager().registerEvents(this, Core.getInstance()); - Bukkit.getScheduler().runTaskTimer(Core.getInstance(), this::render, 20, 20); + Bukkit.getScheduler().runTaskTimer(Core.getInstance(), () -> { + for (Player player : Bukkit.getOnlinePlayers()) { + renderPlayer(player, true); + } + }, 20, 20); } - private void render() { - for(Player player : Bukkit.getOnlinePlayers()) { - //noinspection deprecation - if(player.getItemInHand().getType() != WAND) - continue; + private void renderPlayer(Player player, boolean scheduled) { + LocalSession session = we.getSession(player); + renderClipboard(player, session, scheduled); + renderRegion(player, session, scheduled); + } - LocalSession session = we.getSession(player); + private void renderClipboard(Player player, LocalSession session, boolean scheduled) { + 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()); + drawCuboid(Vector.getMinimum(a, b), Vector.getMaximum(a, b), scheduled, true, player); + } catch (EmptyClipboardException e) { + WorldEditRendererWrapper.impl.hide(player, true, true); + } + } + + private void renderRegion(Player player, LocalSession session, boolean scheduled) { + World world = session.getSelectionWorld(); + if(world != null) { + RegionSelector regionSelector = session.getRegionSelector(world); 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 - } + Region region = regionSelector.getRegion(); + drawCuboid(WorldEditWrapper.impl.getMinimum(region), WorldEditWrapper.impl.getMaximum(region), scheduled, false, player); + } catch (IncompleteRegionException e) { + WorldEditRendererWrapper.impl.hide(player, false, true); } } } - 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 drawCuboid(Vector min, Vector max, boolean scheduled, boolean clipboard, Player owner) { + //noinspection deprecation + if(owner.getItemInHand().getType() != WAND) { + WorldEditRendererWrapper.impl.hide(owner, true, true); + WorldEditRendererWrapper.impl.hide(owner, false, true); + } else { + WorldEditRendererWrapper.impl.hide(owner, true, false); + WorldEditRendererWrapper.impl.hide(owner, false, false); + WorldEditRendererWrapper.safeDraw(owner, scheduled, clipboard, min, max); } } - 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 : Particle.TOWN_AURA, x, y, z, 1, 0.0, 0.0, 0.0, 0.0); + @EventHandler + public void onPlayerMove(PlayerMoveEvent event) { + if(event.getPlayer().getItemInHand().getType() == WAND) { + WorldEditRendererWrapper.impl.tick(event.getPlayer()); } + renderClipboard(event.getPlayer(), we.getSession(event.getPlayer()), false); + } + + @EventHandler + public void onPlayerInteract(PlayerInteractEvent event) { + Bukkit.getScheduler().runTaskLater(Core.getInstance(), () -> { + renderRegion(event.getPlayer(), we.getSession(event.getPlayer()), false); + }, 0); + } + + @EventHandler + public void onBlockBreak(BlockBreakEvent event) { + Bukkit.getScheduler().runTaskLater(Core.getInstance(), () -> { + renderRegion(event.getPlayer(), we.getSession(event.getPlayer()), false); + }, 0); + } + + @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, false); + renderClipboard(event.getPlayer(), session, false); + }, 5); + } + } + + @EventHandler + public void onPlayerSwapHandItems(PlayerSwapHandItemsEvent event) { + Bukkit.getScheduler().runTaskLater(Core.getInstance(), () -> { + renderPlayer(event.getPlayer(), false); + }, 1); + } + + @EventHandler + public void onPlayerDropItem(PlayerDropItemEvent event) { + renderPlayer(event.getPlayer(), false); + } + + @EventHandler + public void onPlayerItemHeld(PlayerItemHeldEvent event) { + Bukkit.getScheduler().runTaskLater(Core.getInstance(), () -> { + renderPlayer(event.getPlayer(), false); + }, 1); + } + + @EventHandler + public void onPlayerQuit(PlayerQuitEvent event) { + WorldEditRendererWrapper.impl.remove(event.getPlayer()); } } diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/WorldEditRendererCUIEditor.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/WorldEditRendererCUIEditor.java new file mode 100644 index 00000000..e50eac9d --- /dev/null +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/WorldEditRendererCUIEditor.java @@ -0,0 +1,155 @@ +/* + * 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.command.SWCommand; +import de.steamwar.inventory.SWInventory; +import de.steamwar.inventory.SWItem; +import de.steamwar.sql.UserConfig; +import lombok.AllArgsConstructor; +import org.bukkit.Material; +import org.bukkit.block.data.type.Light; +import org.bukkit.entity.Player; +import org.bukkit.inventory.meta.BlockDataMeta; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class WorldEditRendererCUIEditor { + + @AllArgsConstructor + public enum Type { + SELECTION("cui_selection_material", "cui_selection_width", Material.PURPLE_CONCRETE, Width.MEDIUM), + CLIPBOARD("cui_clipboard_material", "cui_clipboard_width", Material.LIME_CONCRETE, Width.SLIM), + ; + + private final String configMaterial; + private final String configWidth; + private final Material defaultMaterial; + private final Width defaultWidth; + + public Material getMaterial(Player player) { + String material = UserConfig.getConfig(player.getUniqueId(), configMaterial); + if (material == null) { + return defaultMaterial; + } else { + return Material.valueOf(material); + } + } + + public void setMaterial(Player player, Material material) { + UserConfig.updatePlayerConfig(player.getUniqueId(), configMaterial, material.name()); + } + + public Width getWidth(Player player) { + String width = UserConfig.getConfig(player.getUniqueId(), configWidth); + if (width == null) { + return defaultWidth; + } else { + return Width.valueOf(width); + } + } + + public void setWidth(Player player, Width width) { + UserConfig.updatePlayerConfig(player.getUniqueId(), configWidth, width.name()); + } + } + + @AllArgsConstructor + public enum Width { + HUGE(15, "WORLDEDIT_CUI_WIDTH_HUGE", 2/16f), + LARGE(8, "WORLDEDIT_CUI_WIDTH_LARGE", 1/16f), + MEDIUM(4, "WORLDEDIT_CUI_WIDTH_MEDIUM", 1/32f), + SLIM(0, "WORLDEDIT_CUI_WIDTH_SLIM", 1/64f); + + public final int lightLevel; + public final String name; + public final float value; + } + + public WorldEditRendererCUIEditor() { + if (Core.getVersion() >= 20) { + new Command(); + } + } + + private static class Command extends SWCommand { + + public Command() { + super("cui"); + } + + @Register + public void cuiEditor(Player player) { + SWInventory inv = new SWInventory(player, 9 * 2, Core.MESSAGE.parse("WORLDEDIT_CUI_TITLE", player)); + setElement(inv, player, 3, "WORLDEDIT_CUI_SELECTION", Type.SELECTION); + setElement(inv, player, 5, "WORLDEDIT_CUI_CLIPBOARD", Type.CLIPBOARD); + inv.open(); + } + + private void setElement(SWInventory inv, Player player, int index, String uiName, Type type) { + Material material = type.getMaterial(player); + Width width = type.getWidth(player); + + inv.setItem(index, new SWItem(material, Core.MESSAGE.parse("WORLDEDIT_CUI_MATERIAL_NAME", player, Core.MESSAGE.parse(uiName, player)), Arrays.asList(Core.MESSAGE.parse("WORLDEDIT_CUI_MATERIAL_CLICK", player)), false, click -> { + cuiMaterial(player, uiName, type, material); + })); + + List lore = new ArrayList<>(); + lore.add(Core.MESSAGE.parse("WORLDEDIT_CUI_WIDTH_CLICK", player)); + lore.add(""); + for (Width value : Width.values()) { + if (value == width) { + lore.add(Core.MESSAGE.parse("WORLDEDIT_CUI_WIDTH_LORE_SELECTED", player, Core.MESSAGE.parse(value.name, player))); + } else { + lore.add(Core.MESSAGE.parse("WORLDEDIT_CUI_WIDTH_LORE", player, Core.MESSAGE.parse(value.name, player))); + } + } + SWItem lightItem = new SWItem(Material.LIGHT, Core.MESSAGE.parse("WORLDEDIT_CUI_WIDTH_NAME", player, Core.MESSAGE.parse(uiName, player)), lore, false, click -> { + type.setWidth(player, Width.values()[(width.ordinal() + 1) % Width.values().length]); + setElement(inv, player, index, uiName, type); + }); + ItemMeta itemMeta = lightItem.getItemMeta(); + Light light = (Light) Material.LIGHT.createBlockData(); + light.setLevel(width.lightLevel); + ((BlockDataMeta) itemMeta).setBlockData(light); + lightItem.setItemMeta(itemMeta); + inv.setItem(index + 9, lightItem); + } + + private final Material[] materials = {Material.WHITE_CONCRETE, Material.LIGHT_GRAY_CONCRETE, Material.GRAY_CONCRETE, Material.BLACK_CONCRETE, Material.BROWN_CONCRETE, Material.RED_CONCRETE, Material.ORANGE_CONCRETE, Material.YELLOW_CONCRETE, Material.LIME_CONCRETE, Material.GREEN_CONCRETE, Material.CYAN_CONCRETE, Material.LIGHT_BLUE_CONCRETE, Material.BLUE_CONCRETE, Material.PURPLE_CONCRETE, Material.MAGENTA_CONCRETE, Material.PINK_CONCRETE, null, Material.BARRIER}; + + private void cuiMaterial(Player player, String subMenu, Type type, Material currentSelection) { + SWInventory inv = new SWInventory(player, 9 * 2, Core.MESSAGE.parse("WORLDEDIT_CUI_TITLE_SUBMENU", player, Core.MESSAGE.parse(subMenu, player))); + for (int i = 0; i < materials.length; i++) { + Material material = materials[i]; + if (material == null) continue; + inv.setItem(i, new SWItem(material, "", Collections.emptyList(), material == currentSelection, click -> { + type.setMaterial(player, material); + cuiEditor(player); + })); + } + inv.open(); + } + } +} 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..2439d40d --- /dev/null +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/WorldEditRendererWrapper.java @@ -0,0 +1,44 @@ +/* + * 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, boolean scheduled, boolean clipboard, Vector pos1, Vector pos2) { + if (PlayerVersion.isBedrock(player) || PlayerVersion.getVersion(player) < 20) { + fallback.draw(player, scheduled, clipboard, pos1, pos2); + } else { + impl.draw(player, scheduled, clipboard, pos1, pos2); + } + } + + void draw(Player player, boolean scheduled, boolean clipboard, Vector pos1, Vector pos2); + + void tick(Player player); + + void hide(Player player, boolean clipboard, boolean hide); + + void remove(Player player); +} diff --git a/Teamserver/src/de/steamwar/teamserver/Builder.java b/Teamserver/src/de/steamwar/teamserver/Builder.java index 137906ad..55aeed2d 100644 --- a/Teamserver/src/de/steamwar/teamserver/Builder.java +++ b/Teamserver/src/de/steamwar/teamserver/Builder.java @@ -19,6 +19,7 @@ package de.steamwar.teamserver; +import de.steamwar.core.WorldEditRendererCUIEditor; import de.steamwar.message.Message; import de.steamwar.teamserver.command.*; import de.steamwar.teamserver.listener.AxiomHandshakeListener; @@ -58,6 +59,7 @@ public final class Builder extends JavaPlugin { Bukkit.getPluginManager().registerEvents(materialCommand, this); Bukkit.getWorlds().get(0).setGameRule(GameRule.REDUCED_DEBUG_INFO, false); + new WorldEditRendererCUIEditor(); } @Override diff --git a/VelocityCore/src/de/steamwar/velocitycore/listeners/VersionAnnouncer.java b/VelocityCore/src/de/steamwar/velocitycore/listeners/VersionAnnouncer.java index c28a8fee..cf39f843 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/listeners/VersionAnnouncer.java +++ b/VelocityCore/src/de/steamwar/velocitycore/listeners/VersionAnnouncer.java @@ -27,19 +27,33 @@ import com.velocitypowered.api.proxy.server.ServerInfo; import com.viaversion.viaversion.api.Via; import com.viaversion.viaversion.velocity.platform.VelocityViaConfig; import de.steamwar.messages.Chatter; +import de.steamwar.network.packets.server.ClientVersionPacket; import de.steamwar.persistent.Subserver; +import de.steamwar.velocitycore.VelocityCore; +import de.steamwar.velocitycore.network.NetworkSender; + +import java.time.Duration; +import java.time.temporal.ChronoUnit; public class VersionAnnouncer extends BasicListener { @Subscribe public void postConnect(ServerConnectedEvent e) { ServerInfo server = e.getServer().getServerInfo(); - if(!Subserver.isBuild(Subserver.getSubserver(server))) - return; - Player player = e.getPlayer(); int serverVersion = ((VelocityViaConfig) Via.getConfig()).getVelocityServerProtocols().get(server.getName()); - if(Via.getAPI().getPlayerVersion(player) == serverVersion) + + int playerVersion = Via.getAPI().getPlayerVersion(player); + String version = ProtocolVersion.getProtocolVersion(playerVersion).getVersionIntroducedIn(); + // PluginChannel 'vv:proxy_details' from ViaVersion apparently does not work any longer! + VelocityCore.schedule(() -> { + NetworkSender.send(player, new ClientVersionPacket(player.getUniqueId(), Integer.parseInt(version.split("-")[0].split("\\.")[1]))); + }).delay(Duration.of(100, ChronoUnit.MILLIS)).schedule(); + + if(playerVersion == serverVersion) + return; + + if(!Subserver.isBuild(Subserver.getSubserver(server))) return; player.sendActionBar(Chatter.of(player).parse("SERVER_VERSION", ProtocolVersion.getProtocolVersion(serverVersion).getMostRecentSupportedVersion()));