diff --git a/BauSystem_Main/build.gradle b/BauSystem_Main/build.gradle index 744e575c..62d604cf 100644 --- a/BauSystem_Main/build.gradle +++ b/BauSystem_Main/build.gradle @@ -54,12 +54,11 @@ dependencies { implementation project(":BauSystem_Linkage") annotationProcessor project(":BauSystem_Linkage") - compileOnly 'org.spigotmc:spigot-api:1.19-R0.1-SNAPSHOT' + compileOnly 'org.spigotmc:spigot-api:1.20-R0.1-SNAPSHOT' compileOnly 'com.mojang:authlib:1.5.25' compileOnly 'io.netty:netty-all:4.1.68.Final' - compileOnly swdep('Spigot-1.19') - // compileOnly swdep('WorldEdit-1.15') + compileOnly swdep('Spigot-1.20') compileOnly swdep('SpigotCore') annotationProcessor swdep('SpigotCore') diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/world/SignEditFrom20.java b/BauSystem_Main/src/de/steamwar/bausystem/features/world/SignEditFrom20.java new file mode 100644 index 00000000..4f7ad67a --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/world/SignEditFrom20.java @@ -0,0 +1,123 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2023 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.world; + +import com.comphenix.tinyprotocol.Reflection; +import com.comphenix.tinyprotocol.TinyProtocol; +import de.steamwar.bausystem.BauSystem; +import de.steamwar.linkage.Linked; +import de.steamwar.linkage.MinVersion; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.Sign; +import org.bukkit.block.data.BlockData; +import org.bukkit.block.data.Rotatable; +import org.bukkit.block.sign.Side; +import org.bukkit.block.sign.SignSide; +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.util.Vector; + +@Linked +@MinVersion(20) +public class SignEditFrom20 implements Listener { + + private static final Class blockPosition = Reflection.getClass("{nms.core}.BlockPosition"); + private static final Class craftBlock = Reflection.getClass("{obc}.block.CraftBlock"); + private static final Class craftWorld = Reflection.getClass("{obc}.CraftWorld"); + private static final Class generatorAccess = Reflection.getClass("{nms.world.level}.GeneratorAccess"); + private static final Reflection.MethodInvoker getPosition = Reflection.getTypedMethod(craftBlock, "getPosition", blockPosition); + private static final Reflection.MethodInvoker getWorldHandle = Reflection.getTypedMethod(craftWorld, "getHandle", null); + private static final Reflection.MethodInvoker at = Reflection.getTypedMethod(craftBlock, "at", craftBlock, generatorAccess, blockPosition); + + private static final Class openSign = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutOpenSignEditor"); + private static final Reflection.FieldAccessor blockPositionFieldAccessor = Reflection.getField(openSign, blockPosition, 0); + private static final Reflection.FieldAccessor sideFieldAccessor = Reflection.getField(openSign, boolean.class, 0); + + private static final Class updateSign = Reflection.getClass("{nms.network.protocol.game}.PacketPlayInUpdateSign"); + private static final Reflection.FieldAccessor getBlockPositionFieldAccessor = Reflection.getField(updateSign, blockPosition, 0); + private static final Reflection.FieldAccessor stringFieldAccessor = Reflection.getField(updateSign, String[].class, 0); + + @EventHandler + public void editSign(PlayerInteractEvent event) { + if (event.getClickedBlock() == null || !event.getClickedBlock().getType().name().contains("SIGN")) return; + if (event.getAction() == Action.RIGHT_CLICK_BLOCK) event.setCancelled(true); + if (!event.getPlayer().isSneaking()) return; + event.setCancelled(true); + + if (event.getAction() == Action.RIGHT_CLICK_BLOCK && (event.getItem() == null || event.getItem().getType() == Material.AIR) || event.getAction() == Action.LEFT_CLICK_BLOCK) { + Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> { + edit(event.getPlayer(), event.getClickedBlock()); + }, 1); + } + } + + private void edit(Player player, Block block) { + Sign sign = (Sign) block.getState(); + Side side = signSide(player, block); + SignSide signSide = sign.getSide(side); + String[] lines = signSide.getLines(); + for (int i = 0; i < lines.length; i++) { + signSide.setLine(i, lines[i].replace('ยง', '&')); + } + sign.update(true); + + Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> { + Object openSignObject = Reflection.newInstance(openSign); + blockPositionFieldAccessor.set(openSignObject, getPosition.invoke(block)); + sideFieldAccessor.set(openSignObject, side == Side.FRONT); + TinyProtocol.instance.sendPacket(player, openSignObject); + }, 1); + + } + + private Side signSide(Player entity, Block sign) { + Vector vector = entity.getEyeLocation().toVector().subtract(sign.getLocation().add(0.5, 0.5, 0.5).toVector()); + BlockFace blockFace = ((org.bukkit.block.data.type.Sign) sign.getBlockData()).getRotation(); + Vector signDirection = new Vector(blockFace.getModX(), blockFace.getModY(), blockFace.getModZ()); + return vector.dot(signDirection) > 0 ? Side.FRONT : Side.BACK; + } + + { + TinyProtocol.instance.addFilter(updateSign, (player, o) -> { + Bukkit.getScheduler().runTask(BauSystem.getInstance(), () -> { + String[] lines = stringFieldAccessor.get(o); + + Block signLoc = (Block) at.invoke(null, getWorldHandle.invoke(player.getWorld()), getBlockPositionFieldAccessor.get(o)); + if (!signLoc.getType().name().contains("SIGN")) + return; + + Sign sign = ((Sign) signLoc.getState()); + SignSide signSide = sign.getSide(signSide(player, signLoc)); + for (int i = 0; i < lines.length; i++) { + signSide.setLine(i, ChatColor.translateAlternateColorCodes('&', lines[i])); + } + sign.update(true); + }); + return o; + }); + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/world/SignEdit.java b/BauSystem_Main/src/de/steamwar/bausystem/features/world/SignEditUntil19.java similarity index 97% rename from BauSystem_Main/src/de/steamwar/bausystem/features/world/SignEdit.java rename to BauSystem_Main/src/de/steamwar/bausystem/features/world/SignEditUntil19.java index 2f8e154e..19184032 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/world/SignEdit.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/world/SignEditUntil19.java @@ -23,6 +23,7 @@ import com.comphenix.tinyprotocol.Reflection; import com.comphenix.tinyprotocol.TinyProtocol; import de.steamwar.bausystem.BauSystem; import de.steamwar.linkage.Linked; +import de.steamwar.linkage.MaxVersion; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Material; @@ -35,7 +36,8 @@ import org.bukkit.event.block.Action; import org.bukkit.event.player.PlayerInteractEvent; @Linked -public class SignEdit implements Listener { +@MaxVersion(19) +public class SignEditUntil19 implements Listener { private static final Class blockPosition = Reflection.getClass("{nms.core}.BlockPosition"); private static final Class craftBlock = Reflection.getClass("{obc}.block.CraftBlock");