The sign update bug (continued)

Discussion in 'Plugin Development' started by eisental, Feb 9, 2011.

Thread Status:
Not open for further replies.
  1. Offline

    eisental

    Hi, I've been trying to investigate the sign update bug (on redmine) for the last few nights and still have no idea what might be causing it. Basically what happens is that I have a circuit that will update a sign text according to redstone change events. When i connect a lever or button directly to make the current change the sign won't update until I rejoin with the client. If the source is a redstone torch instead (connected as an inverter between the circuit and lever/button or just by placing and breaking) it works fine.
    I started digging into the CraftBukkit code (for the 1st time...) with no luck but I now understand that for the sign to be updated on the client the server should send a 0x82 sign update packet so I thought it might be a good idea to check if the packet is actually being sent out.
    Does anybody know how to check if the server sends the packet or not? Is there any packet sniffer for minecraft? Using tcpdump was not very helpful...

    Thanks
     
  2. Offline

    Raphfrk

    I wrote a proxy server for server port (CraftProxy).

    You could use that for packet processing.

    One thing to note is that it prints packets twice, once with the old entity ids and once with the fake entity id.

    It also prints out if you type in a command, so you can search the file for that.

    Code:
    java -jar CraftProxy.jar <port to bind to> <hostname of server> <port of server> verbose info > some_file.txt
    
    It generates lots of text so, best to redirect the output to a text file.
     
  3. Offline

    eisental

    Thanks! it looks like exactly what I need but I can't get the client to connect to the proxy.
    I set it up to 25566 and when I try to login it just stays on the Logging in... message.
    The server spits out:
    Attempting to connect to: localhost:25565 from 127.0.1.2

    (what the hell is 127.0.1.2??) and nothing happens until the client eventually times out.

    EDIT: sorry, ignore this. I managed to crash the craftbukkit server somehow.
     
  4. Offline

    Raphfrk

    The entire 127.x.y.z range counts as a loopback. The problem is that the minecraft server implements a 5 second per IP address login timeout. Since the proxy was connecting from the same IP for everyone, it meant that no more than 1 person every 5 seconds could login (or use the teleports).

    One of the posters pointed out that you could use any addresses in the range (as long as the proxy and server were on localhost). This means that each connection counts as a separate link.
     
  5. Offline

    eisental

    Ok, so as far as I can tell, the packet is not sent to the client unless I use the redstone torches. So I believe this rules out a client bug.
    Any ideas? Is there a way to force craftbukkit to send an 0x82 packet to all the necessary clients?
     
  6. Offline

    Raphfrk

    You could search the CraftBukkit source for where is sends the 0x82 packet and see what conditions trigger it

    It's possible that they have targeted the wrong function.
     
  7. Offline

    eisental

    Well it seems that TileEntity.java and TileEntitySign.java are missing from the github source repository, though you can see the sources on the Doxygen javadocs. This is the also the case for NetHandler.java and some other stuff apparently. Why is that?

    I've come to the conclusion that there are 2 places where this packet might be used. Either in NetHandler / NetServerHandler.a(Packet130UpdateSign p) or in PlayerInstance.a() which calls PlayerInstance.a(packet) with the packet it gets from TileEntity.g() in the case of a TileEntitySign this would result in a call to PlayerInstance.a(sign's Packet130UpdateSign).
    So basically I have no idea how to continue from here :)
    It seems that there's no specific use of that packet anywhere.

    EDIT: I added some debug messages and found the exact place where the packet is sent when I'm using redstone torches.
    This is PlayerInstance line 154:
    Code:
                        this.a((Packet) (new Packet51MapChunk(i, j, k, l, i1, j1, a.world))); // Craftbukkit
                        List list = a.world.d(i, j, k, i + l, j + i1, k + j1); // Craftbukkit
                        for (int k1 = 0; k1 < list.size(); ++k1) {
                            this.a((TileEntity) list.get(k1)); <--- sends a 0x82 packet when using torches
                        }
    
    If anyone carse, I'll continue to check it out when I get back home... :)
    --- merged: Feb 9, 2011 11:26 PM ---
    CONCLUSION:
    I managed to make it consistently work by moving all the code to the scheduler using
    getServer().getScheduler().scheduleSyncDelayedTask(plugin, updateSignsTask) with no delay.

    this is the updateSignsTask code:
    Code:
            updateSignsTask = new Runnable() {
                @Override
                public void run() {
                    for (Block b : blocksToUpdate) {
                        if (b.getType()==Material.WALL_SIGN) {
                            Sign sign = (Sign)b.getState();
                            sign.setLine(0, lines[0]);
                            sign.setLine(1, lines[1]);
                            sign.setLine(2, lines[2]);
                            sign.setLine(3, lines[3]);
                            sign.update();
                        }
                    }
                }
            };
    
    So my lesson for this is:
    1. Always use sign.update() after setLine calls. Some people have suggested it wasn't necessary but apparently it is. Don't bother with sign.update(true), i.e. the forced version. The only difference is that Bukkit will force the block type into a sign if it's not.
    2. The sign update doesn't work when triggered by certain events. There are a few reports here and there about people using other events than redstoneChange and having the same problem. I believe this is some bukkit/craftbukkit bug that should be ironed out but I have no idea what's causing it. When it happens just use the scheduler.
    So thanks again Raphfrk, both for your help in this thread and for writing the invaluable scheduler :)
     
  8. Offline

    Raphfrk

    Wow, the scheduler is great :).

    Presumably, it depends on timing of some kind. For example, at some point in the clock tick it could check if there has been any sign updates and then process them. Any sign updates between the time it checks the list and the time it clears if for the next tick would be missed.

    By using the scheduler, you are moving it to a well defined part of the clock tick, so it will always work or always not, luckily, it does :).
     
  9. Offline

    eisental

    Yes, that makes sense. I have no idea how the server processes these events but would it be possible then to change the order things are processed to solve this problem?

    Also, I ran into an interesting bug. Calling sign.update() for 2 different signs on the same task caused the server to freeze. No exceptions are thrown, it just stop responding to anything. The only way to stop it is type ^C.
     
  10. Offline

    Raphfrk

    That is weird. Have you tried spamming the scheduler (so it does 2 in one tick)? It could be that no more than 1 sign update is allowed per server tick.
     
  11. Offline

    eisental

    2 tasks in a one tick also resulted in freezing. I changed it so that each task updates 1 sign and calls the sync with no delay method to schedule the next sign update. Now i think it only happens when the redstone happens to trigger the whole sign update process twice on the same tick. Anyway, It's odd that there's no exception. It's the first time I see something like that happen.
     
  12. Offline

    Raphfrk

    Hopefully, when they get to the bottom of it, this issue will also be fixed.

    It seems like signs are sensitive to when in the tick they operation happens.
     
  13. Offline

    freman

    I added a testcase to the bug - basically if you update just one sign (or signs far enough apart - I can't quantify that but my TimeAnnounce plugin demonstrates it) it *usually* works.

    But if you update two signs at the same time neither update

    Don't know if that help...
     
  14. Offline

    eisental

    Did you try my workaround with the scheduler?
     
  15. Offline

    freman

    not yet... tomorrow - already spent 7 hours coding - wanted to play for a bit :D
     
  16. Offline

    Raphfrk

    Btw, the server freeze thing was probably the scheduler deadlock bug, so it should be fixed now?
     
  17. Offline

    eisental

    Yes yes, I haven't seen any server freeze since you fixed it.
     
  18. Offline

    freman

    gah too much work to do plugin by plugin - perhaps we need a "sign updater" plugin that we just post updates to :D
     
  19. Hey, I tried your code, but it still won't work for me :(
    Any ideas?
     
  20. Offline

    eisental

    Hmm, I assume you changed it a bit to suit your needs. My code only works with WALL_SIGNs but you should probably add a check for SIGN_POST as well. Other than that I don't really have any ideas. Did you put a System.out somewhere inside the run() method of the Runnable to see that it actually executes?
    Anyway, you can post your code and I'll have a look.
     
  21. http://pastebin.com/GaxPY00P

    http://pastebin.com/QrrfAKhD
     
  22. Offline

    eisental

    I couldn't find any problem by just looking at it and I would have to write a lot of code to actually compile and run your SignUpdate class. So, did you verify that the task is scheduled and executed?
     
  23. Yup, I checked it, and it runs the whole script.
     
  24. Offline

    Afforess

  25. Offline

    eisental

    Another thing I forgot to mention is that the sign should update in the client after rejoining the server even if you don't use the scheduler workaround. If the sign text doesn't update it means you have a different problem.
     
  26. It is a sign block, I know it is changed (check that). Pretty weird uh..
     
Thread Status:
Not open for further replies.

Share This Page