update a open sign editor (Sign Gui)

Discussion in 'Plugin Development' started by TH_Marinho, May 14, 2021.

  1. Offline

    TH_Marinho

    Hi, I've been trying unsuccessfully to update a opened sign editor (Sign Gui).

    I've already tried:
    Code:
    sign.setLine(0, TEXT);
    sign.update();
    but this only updates the block placed text, not the player's open gui,
    and I tried that too:
    Code:
    player.sendSignChange(location, text);
    Reflection.sendPacket(player, "PacketPlayOutOpenSignEditor",
    Reflection.callConstructor(Reflection.getClass(Reflection.getPackage()
    + ".BlockPosition"), block.getX(), block.getY(), block.getZ()));
    but the same thing happens.

    Take a look at how I'm opening the sign editor (Sign Gui):
    Code:
    location = player.getLocation().clone().subtract(0, 5, 0);
    block = location.getBlock();
    
    player.sendBlockChange(location, Material.SIGN_POST, (byte) 0);
    player.sendSignChange(location, text);
    
    Reflection.sendPacket(player, "PacketPlayOutOpenSignEditor",
    Reflection.callConstructor(Reflection.getClass(Reflection.getPackage()
    + ".BlockPosition"), block.getX(), block.getY(), block.getZ()));
    Reflection.java
    Code:
    package org.marinho.sign.bukkit.util;
    
    import io.netty.channel.Channel;
    import org.bukkit.Bukkit;
    import org.bukkit.entity.Player;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    public class Reflection {
    
        public static String getPackage() {
            String pkg = Bukkit.getServer().getClass().getPackage().getName();
            String version = pkg.substring(pkg.lastIndexOf(".") + 1);
    
            return "net.minecraft.server." + version;
        }
    
        public static Class<?> toPrimitive(Class<?> clazz) {
            if(clazz == Boolean.class) return boolean.class;
            if(clazz == Integer.class) return int.class;
            if(clazz == Double.class) return double.class;
            if(clazz == Float.class) return float.class;
            if(clazz == Long.class) return long.class;
            if(clazz == Short.class) return short.class;
            if(clazz == Byte.class) return byte.class;
            if(clazz == Void.class) return void.class;
            if(clazz == Character.class) return char.class;
    
            return clazz;
        }
    
        public static Class<?>[] toParamTypes(Object... params) {
            Class<?>[] classes = new Class<?>[params.length];
    
            for (int i = 0; i < params.length; i++)
                classes[i] = toPrimitive(params[i].getClass());
    
            return classes;
        }
    
        public static void sendPacket(Player player, String name, Object... params) {
            Object connection = getConnection(player);
    
            try {
              connection.getClass().getMethod("sendPacket", getClass(getPackage() +
                      ".Packet")).invoke(connection, callConstructor(getClass(getPackage() +
                              "." + name), params));
            } catch (Exception e) {
               e.printStackTrace();
            }
        }
    
        public static Object invokeMethod(Object object, String name, Object... params) {
            try {
                Method method = object.getClass().getDeclaredMethod(name, toParamTypes(params));
                method.setAccessible(true);
    
                return method.invoke(object, params);
            } catch (Exception exception) {
                exception.printStackTrace();
    
                return null;
            }
        }
    
        public static Object callConstructor(Class<?> clazz, Object... params) {
            try {
                Constructor<?> connection = clazz.getDeclaredConstructor(toParamTypes(params));
                connection.setAccessible(true);
    
                return connection.newInstance(params);
            } catch (Exception exception) {
                exception.printStackTrace();
    
                return null;
            }
        }
    
        public static Object getConnection(Player player) {
            return getField(invokeMethod(player, "getHandle"), "playerConnection");
        }
    
        public static Channel getChannel(Player player) {
            Object connection = getConnection(player);
            Object network = getField(connection, "networkManager");
    
            return (Channel) getField(network, "channel");
        }
    
        public static Class<?> getClass(String name) {
            try {
                return Class.forName(name);
            } catch (Exception exception) {
                return null;
            }
        }
    
        public static Object getField(Object object, String field) {
            try {
                Field f = object.getClass().getDeclaredField(field);
                f.setAccessible(true);
    
                return f.get(object);
            } catch (Exception exception) {
                exception.printStackTrace();
    
                return null;
            }
        }
    }
     
  2. Offline

    KarimAKL

    @TH_Marinho You should send the PacketPlayOutOpenSignEditor packet (you are already doing this) and listen for the PacketPlayInUpdateSign packet to get when the player has finished writing the sign.

    I recommend using ProtocolLib for this.
     

Share This Page