From 084adea7efbfda28382a40c16d91a1c93edf7872 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Sat, 30 Jul 2022 14:21:56 +0200 Subject: [PATCH] Add XrayCommand Signed-off-by: yoyosource --- .../features/xray/XrayWrapper15.java | 39 ++++ .../features/xray/XrayWrapper18.java | 39 ++++ .../features/xray/XrayWrapper19.java | 39 ++++ .../features/techhider/TechHiderCommand.java | 15 +- .../bausystem/features/xray/XrayCommand.java | 168 ++++++++++++++++++ .../bausystem/features/xray/XrayWrapper.java | 30 ++++ .../steamwar/bausystem/utils/ProtocolAPI.java | 43 +++-- 7 files changed, 349 insertions(+), 24 deletions(-) create mode 100644 BauSystem_15/src/de/steamwar/bausystem/features/xray/XrayWrapper15.java create mode 100644 BauSystem_18/src/de/steamwar/bausystem/features/xray/XrayWrapper18.java create mode 100644 BauSystem_19/src/de/steamwar/bausystem/features/xray/XrayWrapper19.java create mode 100644 BauSystem_Main/src/de/steamwar/bausystem/features/xray/XrayCommand.java create mode 100644 BauSystem_Main/src/de/steamwar/bausystem/features/xray/XrayWrapper.java diff --git a/BauSystem_15/src/de/steamwar/bausystem/features/xray/XrayWrapper15.java b/BauSystem_15/src/de/steamwar/bausystem/features/xray/XrayWrapper15.java new file mode 100644 index 00000000..b48e4de5 --- /dev/null +++ b/BauSystem_15/src/de/steamwar/bausystem/features/xray/XrayWrapper15.java @@ -0,0 +1,39 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.features.xray; + +import net.minecraft.server.v1_15_R1.EntityPlayer; +import net.minecraft.server.v1_15_R1.PacketPlayInFlying; +import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer; +import org.bukkit.entity.Player; + +public class XrayWrapper15 implements XrayWrapper { + + @Override + public void setPosition(Player player, Object object) { + PacketPlayInFlying packetPlayInFlying = ((PacketPlayInFlying) object); + EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle(); + if (Float.isNaN(packetPlayInFlying.a(Float.NaN))) { + entityPlayer.e(packetPlayInFlying.a(0.0), packetPlayInFlying.b(0.0), packetPlayInFlying.c(0.0)); + } else { + entityPlayer.setLocation(packetPlayInFlying.a(0.0), packetPlayInFlying.b(0.0), packetPlayInFlying.c(0.0), packetPlayInFlying.a(0F), packetPlayInFlying.b(0F)); + } + } +} diff --git a/BauSystem_18/src/de/steamwar/bausystem/features/xray/XrayWrapper18.java b/BauSystem_18/src/de/steamwar/bausystem/features/xray/XrayWrapper18.java new file mode 100644 index 00000000..3acc74b3 --- /dev/null +++ b/BauSystem_18/src/de/steamwar/bausystem/features/xray/XrayWrapper18.java @@ -0,0 +1,39 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.features.xray; + +import net.minecraft.network.protocol.game.PacketPlayInFlying; +import net.minecraft.server.level.EntityPlayer; +import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer; +import org.bukkit.entity.Player; + +public class XrayWrapper18 implements XrayWrapper { + + @Override + public void setPosition(Player player, Object object) { + PacketPlayInFlying packetPlayInFlying = ((PacketPlayInFlying) object); + EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle(); + if (packetPlayInFlying.h) { + entityPlayer.b(packetPlayInFlying.a, packetPlayInFlying.b, packetPlayInFlying.c, packetPlayInFlying.d, packetPlayInFlying.e); + } else { + entityPlayer.e(packetPlayInFlying.a, packetPlayInFlying.b, packetPlayInFlying.c); + } + } +} diff --git a/BauSystem_19/src/de/steamwar/bausystem/features/xray/XrayWrapper19.java b/BauSystem_19/src/de/steamwar/bausystem/features/xray/XrayWrapper19.java new file mode 100644 index 00000000..83f5f61c --- /dev/null +++ b/BauSystem_19/src/de/steamwar/bausystem/features/xray/XrayWrapper19.java @@ -0,0 +1,39 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.features.xray; + +import net.minecraft.network.protocol.game.PacketPlayInFlying; +import net.minecraft.server.level.EntityPlayer; +import org.bukkit.craftbukkit.v1_19_R1.entity.CraftPlayer; +import org.bukkit.entity.Player; + +public class XrayWrapper19 implements XrayWrapper { + + @Override + public void setPosition(Player player, Object object) { + PacketPlayInFlying packetPlayInFlying = ((PacketPlayInFlying) object); + EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle(); + if (packetPlayInFlying.h) { + entityPlayer.b(packetPlayInFlying.a, packetPlayInFlying.b, packetPlayInFlying.c, packetPlayInFlying.d, packetPlayInFlying.e); + } else { + entityPlayer.e(packetPlayInFlying.a, packetPlayInFlying.b, packetPlayInFlying.c); + } + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/techhider/TechHiderCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/techhider/TechHiderCommand.java index 28e5966a..972cb23e 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/techhider/TechHiderCommand.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/techhider/TechHiderCommand.java @@ -20,8 +20,10 @@ package de.steamwar.bausystem.features.techhider; import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.features.xray.XrayCommand; import de.steamwar.bausystem.linkage.LinkageType; import de.steamwar.bausystem.linkage.Linked; +import de.steamwar.bausystem.linkage.LinkedInstance; import de.steamwar.bausystem.region.Region; import de.steamwar.command.SWCommand; import de.steamwar.core.CraftbukkitWrapper; @@ -50,6 +52,9 @@ public class TechHiderCommand extends SWCommand implements Listener { private Map> techHiders = new HashMap<>(); private Map> hidden = new HashMap<>(); + @LinkedInstance + private XrayCommand xrayCommand; + @Register(description = "TECHHIDER_HELP") public void toggleHider(Player player) { Region region = Region.getRegion(player.getLocation()); @@ -87,6 +92,7 @@ public class TechHiderCommand extends SWCommand implements Listener { return; } + xrayCommand.disable(region, player); if (hidden.get(region).contains(player)) { hidden.get(region).remove(player); BauSystem.MESSAGE.sendPrefixless("TECHHIDER_OFF", player, ChatMessageType.ACTION_BAR); @@ -101,6 +107,13 @@ public class TechHiderCommand extends SWCommand implements Listener { @EventHandler public void onPlayerQuit(PlayerQuitEvent event) { - hidden.forEach((rg, players) -> players.remove(event.getPlayer())); + hidden.values().forEach(set -> set.remove(event.getPlayer())); + } + + public void disable(Region region, Player player) { + hidden.computeIfPresent(region, (rg, set) -> { + set.remove(player); + return set; + }); } } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/xray/XrayCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/xray/XrayCommand.java new file mode 100644 index 00000000..2d3f9503 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/xray/XrayCommand.java @@ -0,0 +1,168 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.features.xray; + +import com.comphenix.tinyprotocol.Reflection; +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.features.techhider.TechHiderCommand; +import de.steamwar.bausystem.linkage.LinkageType; +import de.steamwar.bausystem.linkage.Linked; +import de.steamwar.bausystem.linkage.LinkedInstance; +import de.steamwar.bausystem.region.Region; +import de.steamwar.bausystem.utils.ProtocolAPI; +import de.steamwar.command.SWCommand; +import de.steamwar.core.CraftbukkitWrapper; +import de.steamwar.techhider.TechHider; +import net.md_5.bungee.api.ChatMessageType; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +import java.io.File; +import java.util.*; +import java.util.function.BiFunction; + +@Linked(LinkageType.COMMAND) +@Linked(LinkageType.LISTENER) +public class XrayCommand extends SWCommand implements Listener { + + public XrayCommand() { + super("xray"); + } + + private Map> techHiders = new HashMap<>(); + private Map> xrayedBlocks = new HashMap<>(); + private Map> hidden = new HashMap<>(); + + @LinkedInstance + private TechHiderCommand techHiderCommand; + + @Register(description = "XRAY_HELP") + public void toggleHider(Player player) { + Region region = Region.getRegion(player.getLocation()); + if (region.isGlobal()) { + BauSystem.MESSAGE.send("XRAY_GLOBAL", player); + return; + } + + Optional techHider = techHiders.computeIfAbsent(region, rg -> { + File file = rg.gameModeConfig(); + if (file == null) { + return Optional.empty(); + } + + FileConfiguration config = YamlConfiguration.loadConfiguration(file); + if (!config.getBoolean("Techhider.Active", false)) { + Set blocks = new HashSet<>(Arrays.asList(Material.END_STONE, Material.IRON_BLOCK)); + xrayedBlocks.put(region, blocks); + return Optional.of(createXray(rg, blocks)); + } + + hidden.put(rg, new HashSet<>()); + + String obfuscateWith = config.getString("Techhider.ObfuscateWith", "end_stone"); + + Set blocks = new HashSet<>(Arrays.asList(Material.getMaterial(obfuscateWith.toUpperCase()))); + xrayedBlocks.put(region, blocks); + return Optional.of(createXray(rg, blocks)); + }); + if (!techHider.isPresent()) { + return; + } + + techHiderCommand.disable(region, player); + if (hidden.get(region).contains(player)) { + hidden.get(region).remove(player); + BauSystem.MESSAGE.sendPrefixless("XRAY_OFF", player, ChatMessageType.ACTION_BAR); + } else { + hidden.get(region).add(player); + BauSystem.MESSAGE.sendPrefixless("XRAY_ON", player, ChatMessageType.ACTION_BAR); + } + region.forEachChunk((x, z) -> { + CraftbukkitWrapper.impl.sendChunk(player, x, z); + }); + } + + private static final Class position = Reflection.getClass("{nms.network.protocol.game}.PacketPlayInFlying$PacketPlayInPosition"); + private static final Class positionLook = Reflection.getClass("{nms.network.protocol.game}.PacketPlayInFlying$PacketPlayInPositionLook"); + + { + BiFunction positionSetter = (player, o) -> { + Region region = Region.getRegion(player.getLocation()); + if (hidden.containsKey(region) && hidden.get(region).contains(player)) { + Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> { + XrayWrapper.impl.setPosition(player, o); + }, 1L); + return null; + } + return o; + }; + + ProtocolAPI.setIncomingHandler(position, positionSetter); + ProtocolAPI.setIncomingHandler(positionLook, positionSetter); + } + + @EventHandler + public void onPlayerInteract(PlayerInteractEvent event) { + if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return; + Region region = Region.getRegion(event.getPlayer().getLocation()); + if (!(hidden.containsKey(region) && hidden.get(region).contains(event.getPlayer()))) { + return; + } + + Set types = xrayedBlocks.getOrDefault(region, new HashSet<>()); + if (event.getItem() != null && types.contains(event.getItem().getType())) { + return; + } + if (types.contains(event.getClickedBlock().getType())) { + event.getClickedBlock().setType(Material.AIR, false); + } else if (types.contains(event.getClickedBlock().getRelative(event.getBlockFace()).getType())) { + event.getClickedBlock().getRelative(event.getBlockFace()).setType(Material.AIR, false); + } + } + + private TechHider createXray(Region rg, Set obfuscate) { + TechHider current = new TechHider((p, cX, cY) -> { + if (rg.chunkOutside(cX, cY)) return true; + return !hidden.get(rg).contains(p); + }, Material.STRUCTURE_VOID, obfuscate, new HashSet<>()); + current.enable(); + return current; + } + + @EventHandler + public void onPlayerQuit(PlayerQuitEvent event) { + hidden.values().forEach(set -> set.remove(event.getPlayer())); + } + + public void disable(Region region, Player player) { + hidden.computeIfPresent(region, (rg, set) -> { + set.remove(player); + return set; + }); + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/xray/XrayWrapper.java b/BauSystem_Main/src/de/steamwar/bausystem/features/xray/XrayWrapper.java new file mode 100644 index 00000000..243b42e1 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/xray/XrayWrapper.java @@ -0,0 +1,30 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.features.xray; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.core.VersionDependent; +import org.bukkit.entity.Player; + +public interface XrayWrapper { + XrayWrapper impl = VersionDependent.getVersionImpl(BauSystem.getInstance()); + + void setPosition(Player player, Object object); +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/utils/ProtocolAPI.java b/BauSystem_Main/src/de/steamwar/bausystem/utils/ProtocolAPI.java index 8d0543ed..a0b650b1 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/utils/ProtocolAPI.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/utils/ProtocolAPI.java @@ -21,53 +21,50 @@ package de.steamwar.bausystem.utils; import com.comphenix.tinyprotocol.TinyProtocol; import lombok.experimental.UtilityClass; -import org.bukkit.Bukkit; import org.bukkit.entity.Player; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import java.util.function.BiFunction; @UtilityClass public class ProtocolAPI { - private static final Map, BiFunction> outgoingHandler = new HashMap<>(); - private static final Map, BiFunction> incomingHandler = new HashMap<>(); + private static final Map, Set>> outgoingHandler = new HashMap<>(); + private static final Map, Set>> incomingHandler = new HashMap<>(); static { TinyProtocol.instance.setOutFilter((receiver, channel, packet) -> { - BiFunction handler = outgoingHandler.get(packet.getClass()); - if (handler == null) + Set> handler = outgoingHandler.get(packet.getClass()); + if (handler == null || handler.isEmpty()) return packet; - return handler.apply(receiver, packet); + for (BiFunction function : handler) { + packet = function.apply(receiver, packet); + if (packet == null) return null; + } + return packet; }); TinyProtocol.instance.setInFilter((sender, channel, packet) -> { - BiFunction handler = incomingHandler.get(packet.getClass()); - if (handler == null) + Set> handler = incomingHandler.get(packet.getClass()); + if (handler == null || handler.isEmpty()) return packet; - return handler.apply(sender, packet); + for (BiFunction function : handler) { + packet = function.apply(sender, packet); + if (packet == null) return null; + } + return packet; }); } public static void setOutgoingHandler (Class packetClass, BiFunction handler) { - outgoingHandler.put(packetClass, handler); - } - - public static void removeOutgoingHandler(Class packetClass) { - outgoingHandler.remove(packetClass); + outgoingHandler.computeIfAbsent(packetClass, i -> new HashSet<>()).add(handler); } public static void setIncomingHandler (Class packetClass, BiFunction handler) { - incomingHandler.put(packetClass, handler); - } - - public static void removeIncomingHandler(Class packetClass) { - incomingHandler.remove(packetClass); - } - - public static void broadcastPacket(Object packet) { - Bukkit.getOnlinePlayers().stream().map(TinyProtocol.instance::getChannel).filter(TinyProtocol.instance::hasInjected).forEach(channel -> TinyProtocol.instance.sendPacket(channel, packet)); + incomingHandler.computeIfAbsent(packetClass, i -> new HashSet<>()).add(handler); } }