Solved Open SignGui with packets (not ProtocolLib)

Discussion in 'Plugin Development' started by FisheyLP, May 8, 2015.

Thread Status:
Not open for further replies.
  1. Thats my code to open the Gui:
    Code:
    public void openGui(Player p, Sign s) {
            Location loc = s.getLocation();
            PacketPlayOutOpenSignEditor packet = new PacketPlayOutOpenSignEditor(loc.getBlockX(), loc.getBlockY(),
                    loc.getBlockZ());
            ((CraftPlayer) p).getHandle().playerConnection.sendPacket(packet);
        }
    It does open it, and shows the current lines, but when I click done, the edited stuff isn't there anymore and I get this warning in the console:
    [18:59:58 WARN]: Player FisheyLP just tried to change non-editable sign

    How can I make this working?

    EDIT: I decompiled bukkit and found out that the TileEntitySign has a boolean called "isEditable". I'm trying to work on this soon

    Yay I got it working :D
    Code:
    public void openGui(Player p, Sign s) {
            try {
                Field field = s.getClass().getDeclaredField("sign"); //Get the "TileEntity sign" field
                field.setAccessible(true); //Make it accessible
                Object tileEntity = field.get(s); //Get the TileEntity from the field.
                Field editable = tileEntity.getClass().getDeclaredField("isEditable"); //Get the field "editable" from TileEntity
                editable.set(tileEntity, true); //Set it to true
               
                Location loc = s.getLocation();
                PacketPlayOutOpenSignEditor packet = new PacketPlayOutOpenSignEditor(loc.getBlockX(), loc.getBlockY(),
                        loc.getBlockZ());
                ((CraftPlayer) p).getHandle().playerConnection.sendPacket(packet);
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 12, 2016
  2. Offline

    jerome_coder

    Hello,
    thanks for your code but I tried to use it but I always have this same warning:
    Player jerome_coder just tried to change non-editable sign

    Can you please help me?
    Thanks !!
     
  3. Offline

    Tecno_Wizard

    @FisheyLP, I actually attempted to do the same thing a few months ago with no success. Bookmarking this thread.
     
  4. Offline

    N00BHUN73R

    @FisheyLP
    I attempted to use your code as mine kept telling me its not editable but your code does not work either D:
     
  5. Offline

    jerome_coder

    This code works but the only thing is that the sign cannot be edited.
    I'm sure someone has the solution.
    Please tell us.
     
  6. replace
    loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()
    with
    s.getX(), s.getY(), s.getZ()
     
  7. Offline

    jerome_coder

    Thanks! But same issue.
    Have always this warning.
     
  8. Offline

    N00BHUN73R

    Still doesn't work haha, One of these days we will figure it out :p
     
  9. Offline

    jerome_coder

    I'm so sad...
    I searched all other the Internet and didn't find any answer...
    Even German forums.
     
    cojicos likes this.
  10. Offline

    Ungemonstert

    I didn't know the issue, but if you give me links to the German forums, I can translate it for you @jerome_coder . :)
     
  11. Offline

    Tecno_Wizard

    When I was trying to do this I placed blocks at a random location in the sky while this was running, then deleted them when it was done.
     
  12. Updated code (might work):
    Code:
    public void openGui(Player p, Sign s) {
            try {
                Field field = s.getClass().getDeclaredField("sign"); //Get the "TileEntitySign sign" field
                field.setAccessible(true); //Make it accessible
                Object tileEntity = field.get(s); //Get the TileEntitySign from the field.
    
                Field editable = tileEntity.getClass().getDeclaredField("isEditable"); //Get the field "editable" from TileEntitySign
                editable.set(tileEntity, true); //Set it to true
    
                Field owner = tileEntity.getClass().getDeclaredField("k"); //Get the field "k" from TileEntitySign
                owner.setAccessible(true); //Make it accessible
                owner.set(tileEntity, ((CraftPlayer) p).getHandle()); //Set it to the craftplayer
          
                PacketPlayOutOpenSignEditor packet = new PacketPlayOutOpenSignEditor(s.getX(), s.getY(), s.getZ());
                ((CraftPlayer) p).getHandle().playerConnection.sendPacket(packet);
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
     
    Last edited: May 30, 2015
  13. Offline

    jerome_coder

    @FisheyLP thanks for your help!
    But k is not a Field from TileEntity.

    Code:
    java.lang.NoSuchFieldException: k
    [18:58:12] [Server thread/WARN]:     at java.lang.Class.getDeclaredField(Class.java:1961)
    [18:58:12] [Server thread/WARN]:     at fr.jerome_coder.ecouteur.openGui(ecouteur.java:280)
    
     
  14. @jerome_coder
    Sorry, I forgot to make it accessible (it's fixed now)

    EDIT: Do you want a method without nms to make it (hopefully) full version independant?
     
    Last edited: May 30, 2015
  15. Offline

    jerome_coder

    @FisheyLP same error. NoSuchFieldException
    Full version? Yeah it will be really nice!
    Thank you so much !!

    EDIT: the error is on this line:
    Field owner = tileEntity.getClass().getDeclaredField("k"); //Get the field "k" from TileEntitySign
     
  16. Thats strange... Heres the decompiled class:
    [​IMG]
     
  17. Offline

    crolemol

    @FisheyLP
    that's what they call nms obfuscation, changes every version so it depends on which version he uses it
     
  18. Thanks! I didn't knew that, but you're not completely right..
    I decompiled a few different versions of craftbukkit and came to this result:
    1.7.2 - 1.7.9: the field is "k"
    1.8+: the field is "h"

    @jerome_coder
    Here is the working and version independent code:
    My Reflections class: http://pastebin.com/62dPDdJs
    Code:
    public void openGui(Player p, Sign s) {
        Object tileEntity = Reflections.getDeclaredField(s,  "sign");
        Reflections.setDeclaredField(tileEntity, "isEditable", true);
        Reflections.setDeclaredField(tileEntity, Reflections.ver().startsWith("v1_7") ? "k" : "h", Reflections.getHandle(p));
      
        Reflections.sendPacket(p,  Reflections.getPacket("PacketPlayOutOpenSignEditor", s.getX(), s.getY(), s.getZ()));
    }
     
    Last edited: May 31, 2015
    crolemol likes this.
  19. Offline

    jerome_coder

    Hello,
    sorry for the late answer @FisheyLP I was in hospital.

    I tried with your Reflections Class but now I have this error:
    Code:
    [12:37:19] [Server thread/WARN]: java.lang.NoSuchMethodException: net.minecraft.server.v1_8_R1.PacketPlayOutOpenSignEditor.<init>(int, int, int)
    [12:37:19] [Server thread/WARN]:    at java.lang.Class.getConstructor0(Class.java:2902)
    [12:37:19] [Server thread/WARN]:    at java.lang.Class.getDeclaredConstructor(Class.java:2066)
    [12:37:19] [Server thread/WARN]:    at fr.jerome_coder.reflection.callDeclaredConstructor(reflection.java:110)
    [12:37:19] [Server thread/WARN]:    at fr.jerome_coder.reflection.getPacket(reflection.java:66)
    [12:37:19] [Server thread/WARN]:    at fr.jerome_coder.ecouteur.openGui(ecouteur.java:260)
    [12:37:19] [Server thread/WARN]:    at fr.jerome_coder.ecouteur.onInventoryClick(ecouteur.java:246)
    [12:37:19] [Server thread/WARN]:    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    [12:37:19] [Server thread/WARN]:    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    [12:37:19] [Server thread/WARN]:    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    [12:37:19] [Server thread/WARN]:    at java.lang.reflect.Method.invoke(Method.java:606)
    [12:37:19] [Server thread/WARN]:    at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:301)
    [12:37:19] [Server thread/WARN]:    at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:62)
    [12:37:19] [Server thread/WARN]:    at org.bukkit.plugin.SimplePluginManager.fireEvent(SimplePluginManager.java:502)
    [12:37:19] [Server thread/WARN]:    at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:487)
    [12:37:19] [Server thread/WARN]:    at net.minecraft.server.v1_8_R1.PlayerConnection.a(PlayerConnection.java:1588)
    [12:37:19] [Server thread/WARN]:    at net.minecraft.server.v1_8_R1.PacketPlayInWindowClick.a(SourceFile:31)
    [12:37:19] [Server thread/WARN]:    at net.minecraft.server.v1_8_R1.PacketPlayInWindowClick.a(SourceFile:9)
    [12:37:19] [Server thread/WARN]:    at net.minecraft.server.v1_8_R1.PacketHandleTask.run(SourceFile:13)
    [12:37:19] [Server thread/WARN]:    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
    [12:37:19] [Server thread/WARN]:    at java.util.concurrent.FutureTask.run(FutureTask.java:262)
    [12:37:19] [Server thread/WARN]:    at net.minecraft.server.v1_8_R1.MinecraftServer.z(MinecraftServer.java:696)
    [12:37:19] [Server thread/WARN]:    at net.minecraft.server.v1_8_R1.DedicatedServer.z(DedicatedServer.java:316)
    [12:37:19] [Server thread/WARN]:    at net.minecraft.server.v1_8_R1.MinecraftServer.y(MinecraftServer.java:634)
    [12:37:19] [Server thread/WARN]:    at net.minecraft.server.v1_8_R1.MinecraftServer.run(MinecraftServer.java:537)
    [12:37:19] [Server thread/WARN]:    at java.lang.Thread.run(Thread.java:745)
    
    [EDIT]
    I found the problem!!
    The problem was here:
    Code:
    reflection.sendPacket(p,  reflection.getPacket("PacketPlayOutOpenSignEditor", s.getX(), s.getY(), s.getZ()));
    
    Because it need a blockposition and not int values.
    For all wich are interested here is the working code:
    Code:
    public void openGui(Player p, Sign s) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException{    
          Object tileEntity = reflection.getDeclaredField(s,  "sign");
          reflection.setDeclaredField(tileEntity, "isEditable", true);
          reflection.setDeclaredField(tileEntity, reflection.ver().startsWith("v1_7") ? "k" : "h", reflection.getHandle(p));  
          reflection.sendPacket(p,  reflection.getPacket("PacketPlayOutOpenSignEditor", new BlockPosition(s.getX(), s.getY(), s.getZ())));
         }
    @FisheyLP I want to thank you so much!!! Your the best thanks a lot!!!
    Sorry for my bad English I'm French ;)
     
    Last edited: Jun 10, 2015
    N00BHUN73R and FisheyLP like this.
  20. Offline

    N00BHUN73R

  21. @jerome_coder
    BlockPosition is still in the nms package .. let me fix that :D
    Code:
    public void openGui(Player p, Sign s) {   
          Object tileEntity = Reflections.getDeclaredField(s,  "sign");
          Reflections.setDeclaredField(tileEntity, "isEditable", true);
          Reflections.setDeclaredField(tileEntity, Reflections.ver().startsWith("v1_7") ? "k" : "h", Reflections.getHandle(p)); 
          Reflections.sendPacket(p,  Reflections.getPacket("PacketPlayOutOpenSignEditor",
          Reflections.ver().startsWith("v1_7") ? s.getX(), s.getY(), s.getZ() :
          Reflections.callDeclaredConstructor(Reflections.getNmsClass("BlockPosition"), s.getX(), s.getY(), s.getZ())));
         }
     
    jerome_coder and N00BHUN73R like this.
  22. Offline

    jerome_coder

    @FisheyLP
    Sorry just a litte question ^^
    I set the first line from the sign before open the signgui but when the signgui opens the first line has not the text i set up.
    I tried to edit you code but no way get it work.
    Can you please help me?
     
  23. Show your code
     
  24. Offline

    jerome_coder

    Hello @FisheyLP
    here is the code:
    Code:
     Block b = loc.getBlock();
                      b.setTypeId(63);
                      if (b.getState() instanceof Sign) {                    
                          Sign s = (Sign) b.getState();
                          s.setLine(0, "Nom du joueur");
                          s.update;
                          openGui(p, s);
                      } 
     
    Last edited: Jun 20, 2015
  25. @jerome_coder thats strange.. :confused: try running the openGui method 1 tick later​
     
  26. Offline

    jerome_coder

    @FisheyLP I tried 1 tick later but same problem.
    I tried 20 tick later too already same problem. :(
     
Thread Status:
Not open for further replies.

Share This Page