[Lib] [1.7.9] ProtocolLib 3.4.0 - Safely and easily modify sent and recieved packets

Discussion in 'Resources' started by Comphenix, Sep 15, 2012.

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


    First off, some truly impressive work there.

    Have you looked at Graphviz for auto graph generation? It should be possible to generate GV dot files from your Markov data structures with a little work. There are various language bindings (including Java), or you can just write a .dot file directly and run the "dot" program on it.

    Example: http://www.graphviz.org/content/fsm - a finite state machine representation, and here's the .dot file used to generate the graph: http://www.graphviz.org/Gallery/directed/fsm.gv.txt
  2. Offline


    Thanks. :)

    Graphviz seems to work reasonably well, so thanks for the tip. :D

    I wrote a little utility that converts the TSV-files generated by PacketStat into gv-files:
    digraph Probabilities {
        "#1 Login" -> "#250 Custom Payload" [label="100%"];
        "#2 Handshake" -> "#253 Key Request" [label="100%"];
        "#3 Chat" -> "#3 Chat" [label="57%"];
        "#6 Spawn Position" -> "#51 Map Chunk" [label="50%"];
        "#6 Spawn Position" -> "#202 Abilities" [label="50%"];
        "#7 Use Entity" -> "#12 Player Look" [label="60%"];
        "#10 Flying" -> "#51 Map Chunk" [label="100%"];
        "#14 Block Dig" -> "#18 Arm Animation" [label="44%"];
        "#15 Place" -> "#18 Arm Animation" [label="48%"];
        "#16 Block Item Switch" -> "#11 Player Position" [label="36%"];
        "#19 Entity Action" -> "#11 Player Position" [label="54%"];
        "#19 Entity Action" -> "#13 Player Look Move" [label="46%"];
        "#21 Pickup Spawn" -> "#28 Entity Velocity" [label="100%"];
        "#22 Collect" -> "#43 Set Experience" [label="43%"];
        "#22 Collect" -> "#103 Set Slot" [label="57%"];
        "#24 Mob Spawn" -> "#35 Entity Head Rotation" [label="100%"];
        "#25 Entity Painting" -> "#35 Entity Head Rotation" [label="100%"];
        "#26 Add Exp Orb" -> "#28 Entity Velocity" [label="100%"];
        "#28 Entity Velocity" -> "#31 Rel Entity Move" [label="38%"];
        "#31 Rel Entity Move" -> "#35 Entity Head Rotation" [label="50%"];
        "#32 Entity Look" -> "#35 Entity Head Rotation" [label="99%"];
        "#33 Rel Entity Move Look" -> "#35 Entity Head Rotation" [label="90%"];
        "#34 Entity Teleport" -> "#34 Entity Teleport" [label="76%"];
        "#38 Entity Status" -> "#62 Named Sound Effect" [label="83%"];
        "#51 Map Chunk" -> "#51 Map Chunk" [label="85%"];
        "#52 Multi Block Change" -> "#11 Player Position" [label="100%"];
        "#100 Open Window" -> "#104 Window Items" [label="100%"];
        "#101 Close Window" -> "#54 Play Note Block" [label="50%"];
        "#102 Window Click" -> "#106 Transaction" [label="100%"];
        "#103 Set Slot" -> "#103 Set Slot" [label="90%"];
        "#104 Window Items" -> "#103 Set Slot" [label="100%"];
        "#106 Transaction" -> "#28 Entity Velocity" [label="67%"];
        "#200 Statistic" -> "#53 Block Change" [label="42%"];
        "#201 Player Info" -> "#13 Player Look Move" [label="50%"];
        "#201 Player Info" -> "#201 Player Info" [label="50%"];
        "#202 Abilities" -> "#4 Update Time" [label="100%"];
        "#204 Locale And View Distance" -> "#51 Map Chunk" [label="100%"];
        "#205 Client Command" -> "#1 Login" [label="100%"];
        "#250 Custom Payload" -> "#6 Spawn Position" [label="100%"];
        "#252 Key Response" -> "#205 Client Command" [label="50%"];
        "#252 Key Response" -> "#252 Key Response" [label="50%"];
        "#253 Key Request" -> "#252 Key Response" [label="100%"];
        "#254 Get Info" -> "#255 Kick Disconnect" [label="100%"];
        "#255 Kick Disconnect" -> "#2 Handshake" [label="50%"];
        "#255 Kick Disconnect" -> "#32 Entity Look" [label="50%"];
    By using the layout engine fdp and the following parameters, ...
    ... I get the following diagram:

    It's much more readable than the Markov tables, at least, but I may need to tweak it a bit further.
    desht likes this.
  3. Offline


    Thank you, I'll definitely look into that!

    Somehow I'd never really thought about this one, but it makes sense. Out of curiosity, how/where does the packet store this information?
  4. Offline


    It's stored right after the data value. Minecraft Coalition explains it well:
    The data is compressed using the deflate() function in zlib. After uncompressing, the data consists of five (or six) sequential sections, in order:
        Block type array (1 byte per block, 4096 bytes per section)
        Block metadata array (half byte per block, 2048 bytes per section)
        Block light array (half byte per block, 2048 bytes per section)
        Sky light array (half byte per block, 2048 bytes per section)
        Add array (half byte per block, 2048 bytes per section, uses second bitmask)
        Biome array (1 byte per XZ coordinate, 256 bytes total, only sent if 'ground up continuous' is true) 
    You can also look at how I calculate the offsets in BlockPatcher.
  5. Offline


    Hey Comphenix

    My 50 slots server crashed when i tried to modify the dimension in the login packet. The console was spammed by this error here:
    2. 2012-10-27 19:21:55 [WARNING] [ProtocolLib] Unable to hook NetLoginHandler.
    3. com.comphenix.net.sf.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null
    4. at com.comphenix.net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:237)
    5. at com.comphenix.net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
    6. at com.comphenix.net.sf.cglib.proxy.Enhancer.create(Enhancer.java:285)
    7. at com.comphenix.protocol.injector.player.TemporaryPlayerFactory.createTemporaryPlayer(TemporaryPlayerFactory.java:140)
    8. at com.comphenix.protocol.injector.player.NetLoginInjector.onNetLoginCreated(NetLoginInjector.java:58)
    9. at com.comphenix.protocol.injector.player.InjectedServerConnection$1.onInserting(InjectedServerConnection.java:231)
    10. at com.comphenix.protocol.injector.player.ReplacedArrayList.add(ReplacedArrayList.java:80)
    11. at net.minecraft.server.DedicatedServerConnectionThread.a(DedicatedServerConnectionThread.java:104)
    12. at net.minecraft.server.DedicatedServerConnectionThread.run(DedicatedServerConnectionThread.java:88)
    13. Caused by: java.lang.reflect.InvocationTargetException
    14. at sun.reflect.GeneratedMethodAccessor7.invoke(Unknown Source)
    15. at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    16. at java.lang.reflect.Method.invoke(Method.java:616)
    17. at com.comphenix.net.sf.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:384)
    18. at com.comphenix.net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:219)
    19. ... 8 more
    20. Caused by: java.lang.OutOfMemoryError: PermGen space
  6. Offline


    I've seen this problem before, but I haven't been able to reproduce it on my test server without calling the "reload" command rapidly multiple times. Reload might be the cause, but then again, calling reload can easily crash a typicall Bukkit installation, even without ProtocolLib.

    So, what triggered the error? Did you use "reload" recently? Or perhaps it occurred after a string of player logins?

    Still, I suspect this is a reload issue, in which case it's definitely a ClassLoader memory leak. Unfortunately, that can be a pain to track down and fix properly. A simple workaround would be to set every static field to NULL, but that will reset the compiled structure cache, along with the reflected method and field references. Not exactly performance friendly, but it would definitely be worth the trade off.

    Of course, you can always try increasing the permanent generation space manually:
  7. Offline

    Devil Boy

    Now I'm curious as to why the MineCraft server would send a head rotation packet after a mob spawn. The mob spawn packet itself already contains the data for head rotation. (Added in 1.2)
    Comphenix likes this.
  8. Offline


    I didn't reload at all, it crashes in about 4 minutes after the server started. The latest dev version of disguisecraft which soft depends on protocollib causes the server to time out too
  9. Offline


    That's really strange.

    Hm, it might have something to do with DisguiseCraft. It's using ConnectionSide.CLIENT_SIDE, if I'm not mistaken, which I suspect may have a memory leak.

    Could you try running version 1.4.4-SNAPSHOT, just to check and see if you still get timeout? I've re-enabled the class cache in CGlib.

    Generally, you should be careful before you draw any conclusions from the diagram - the methodology behind PacketStat can only reveal correlations, without any understanding of the actual semantics of each packet. It might just be that Minecraft transmits a #35 Entity Head Look for an unrelated entity whenever a new entity is spawned.

    So, to lay our doubts to rest, you have to look at the source code. Fortunately, it's pretty easy to find the related source files when you have a packet number. By searching for Packet24MobSpawn (note the naming), you'll find two references in EntityTrackerEntry:
    1. if (this.isMoving && !(packet instanceof Packet24MobSpawn)) {
    2. return new Packet24MobSpawn((EntityLiving) this.tracker);
    EntityTrackerEntry represents a single entity on the server, and has a list of every player that is tracking/observing its position, velocity, etc. Next, search for Packet35EntityHeadRotation in the same file. You'll get two results. The first hit is in track, which is called when a player begins to receive information about the current entity:
    1. if (Math.abs(i2 - this.i) >= 4) {
    2. this.broadcast(new Packet35EntityHeadRotation(this.tracker.id, (byte) i2));
    3. this.i = i2;
    4. }

    By looking at the constructor, you'll discover that i is simply the roll angle, and that it's already properly initialized when the entity tracker is created. It's unlikely that this is our suspect.

    But, look at the second hit in updatePlayer (which is called by track through scanPlayers):
    1. // CraftBukkit start - Fix for nonsensical head yaw
    2. this.i = MathHelper.d(this.tracker.am() * 256.0F / 360.0F); // tracker.am() should be getHeadRotation
    3. this.broadcast(new Packet35EntityHeadRotation(this.tracker.id, (byte) i));
    4. // CraftBukkit end

    That's more like it. By using Git blame, you can get the commit that added the fix, which links to the relevant ticket on the Bukkit issue tracker:
    Interesting. Sending that packet for every single entity is a bit of a waste, though. It would have been better to address the underlying problem. Oh well.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
    Last edited by a moderator: May 28, 2016
  10. Offline

    Devil Boy

    Well that can very well explain why the heads of "player disguises" almost always spawn in the wrong direction. I've always thought this to be a MineCraft client issue we just had to deal with :x
    I wonder if I should replicate CraftBukkit's method of "fixing" it....
  11. Offline


    Tested it and I got this:
    2. 2012-10-28 16:02:35 [SEVERE] Could not pass event EntityDamageByEntityEvent to NoCheatPlus v3.7-b47
    3. org.bukkit.event.EventException
    4. at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:341)
    5. at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:62)
    6. at org.bukkit.plugin.SimplePluginManager.fireEvent(SimplePluginManager.java:477)
    7. at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:462)
    8. at org.bukkit.craftbukkit.event.CraftEventFactory.callEvent(CraftEventFactory.java:80)
    9. at org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDamageEvent(CraftEventFactory.java:364)
    10. at org.bukkit.craftbukkit.event.CraftEventFactory.handleEntityDamageEvent(CraftEventFactory.java:386)
    11. at net.minecraft.server.EntityLiving.damageEntity(EntityLiving.java:645)
    12. at net.minecraft.server.EntityHuman.damageEntity(EntityHuman.java:585)
    13. at net.minecraft.server.EntityPlayer.damageEntity(EntityPlayer.java:288)
    14. at net.minecraft.server.EntityHuman.attack(EntityHuman.java:765)
    15. at pgDev.bukkit.DisguiseCraft.listeners.DCMainListener.onDisguiseHit(DCMainListener.java:69)
    16. at sun.reflect.GeneratedMethodAccessor49.invoke(Unknown Source)
    17. at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    18. at java.lang.reflect.Method.invoke(Unknown Source)
    19. at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:339)
    20. at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:62)
    21. at org.bukkit.plugin.SimplePluginManager.fireEvent(SimplePluginManager.java:477)
    22. at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:462)
    23. at pgDev.bukkit.DisguiseCraft.listeners.DCPacketListener$1.onPacketReceiving(DCPacketListener.java:45)
    24. at com.comphenix.protocol.injector.SortedPacketListenerList.invokePacketRecieving(SortedPacketListenerList.java:50)
    25. at com.comphenix.protocol.injector.PacketFilterManager.handlePacket(PacketFilterManager.java:403)
    26. at com.comphenix.protocol.injector.PacketFilterManager.invokePacketRecieving(PacketFilterManager.java:377)
    27. at com.comphenix.protocol.injector.PacketInjector.packetRecieved(PacketInjector.java:219)
    28. at com.comphenix.protocol.injector.PacketInjector.packetRecieved(PacketInjector.java:204)
    29. at com.comphenix.protocol.injector.ReadPacketModifier.intercept(ReadPacketModifier.java:110)
    30. at net.minecraft.server.Packet7UseEntity$$EnhancerByCGLIB$$c860da7f.a(<generated>)
    31. at net.minecraft.server.Packet.a(Packet.java:111)
    32. at net.minecraft.server.NetworkManager.i(NetworkManager.java:193)
    33. at net.minecraft.server.NetworkManager.c(NetworkManager.java:332)
    34. at net.minecraft.server.NetworkReaderThread.run(SourceFile:101)
    35. Caused by: java.lang.NoClassDefFoundError: net/minecraft/server/EntityComplex
    36. at fr.neatmonster.nocheatplus.checks.fight.Direction.check(Direction.java:52)
    37. at fr.neatmonster.nocheatplus.checks.fight.FightListener.handleNormalDamage(FightListener.java:106)
    38. at fr.neatmonster.nocheatplus.checks.fight.FightListener.onEntityDamage(FightListener.java:151)
    39. at sun.reflect.GeneratedMethodAccessor22.invoke(Unknown Source)
    40. at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    41. at java.lang.reflect.Method.invoke(Unknown Source)
    42. at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:339)
    43. ... 30 more

    I removed NoCheatPlus but the server still times out
  12. Offline


    I think I got it fixed. :)

    Looks like CGLib was creating a completely new class every time a player logged on, which would quickly fill up the permanent generation space (default is 64 MB) on medium to large servers. I didn't notice it during testing as I haven't got access to large servers myself.

    I'll post a new version soon.

    ProtocolLib 1.5.0

    This update fixes a couple of serious problems, including the OutOfMemory-problem described above. Updating is recommended.

    I'll post it to BukkitDev soon, but in the meantime it can be downloaded from GitHub.

    Bug fixes:
    Small fixes:

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
    Last edited by a moderator: May 28, 2016
  13. I am trying to get the PlayerDigging if the Player starts digging and destroy the block if it is a chest...
    For some reason the reading always gets catched with an FieldAccesException

            protocolManager.addPacketListener(new PacketAdapter(this, ConnectionSide.CLIENT_SIDE, ListenerPriority.NORMAL, 0x0E) {
                public void onPacketReceiving(PacketEvent event){
                    System.out.println("Event called");
                        case 0x0E:
                            PacketContainer packet = event.getPacket();
                            try {
                                byte Status = packet.getSpecificModifier(byte.class).read(0);
                                if(Status != 0){return;}
                                int X = packet.getSpecificModifier(Integer.class).read(1);
                                byte Y = packet.getSpecificModifier(byte.class).read(2);
                                int Z = packet.getSpecificModifier(Integer.class).read(3);
                                Player player = event.getPlayer();
                                Location location = new Location(player.getWorld(),(double)X,(double)Y,(double)Z);
                                Block block = location.getBlock();
                            } catch (FieldAccessException ex) {
                                System.out.println("Packet read catched");
    Why is the reading always catched?
  14. Offline


    It's because Packet14PlayerDig only contains integer fields when it's stored in memory.

    You probably looked a the excellent Minecraft Coalition page. Unfortunately, that documents the data as it is sent through the wire, not how it is temporarily stored in the packet class. For instance, for packet #14, all five fields are actually integers:
    1. public class Packet14BlockDig extends Packet
    2. {
    3. public int a;
    4. public int b;
    5. public int c;
    6. public int face;
    7. public int e;
    9. public void a(DataInputStream paramDataInputStream)

    So you shouldn't use byte.class at all in your listener. Only int.class.

    And that's another thing. You MUST use the primitive field, not the wrapper field. So int.class, not Integer.class. I blame Java for that little gotcha. :p

    You can get more information in the mini-tutorial I wrote earlier in the thread.

    By the way, you should print the exception in the catch clause. Either with e.printStackTrace(), or by using the plugin logger. That way, you would at least gotten the error message (index out of bound).
  15. Ok thank you I just assumed the types were the same in the class. So do you have do kinda guess which field is what ( i.e. I assumed e was Status a,b,c were x,y,z and face the face obviously and that seems to be right) if you are looking at the decompiled code?
  16. Offline


    Generally, they'll be in the same order as on the Minecraft Coalition page, but you can confirm it by looking at the a(DataInputStream)-method.

    I explain all of that in that tutorial I mentioned. :p
  17. Offline


  18. Offline


    First off - awesome job Comphenix! ;) This sure is handy. I was hoping you'd be able to answer a question for me though. I'm a little confused as to how this works:
    PacketConstructor blockBreak = plugin.getProtocol().createPacketConstructor(Packets.Server.WORLD_EVENT, 2001, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), 35, false);
    PacketContainer packet = blockBreak.createPacket(2001, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), 35, false);
    I was under the impression that the createPacketConstructor method supplied all the needed information, but it appears that I cannot create a packet unless the same arguments are used. Is there a reason for this?
  19. Offline


    Thanks. :)

    Yeah, it's all done for the sake of efficiency. A packet constructor must search for the correct vanilla constructor to use at run-time, which is slightly expensive. So to speed things up, the API is designed to be cached:
    1. private PacketConstructor blockBreakConstructor;

    And then in your method:
    1. if (blockBreakConstructor == null) {
    2. blockBreakConstructor = plugin.getProtocol().createPacketConstructor(Packets.Server.WORLD_EVENT, 2001, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), 35, false);
    3. }
    5. PacketContainer packet = blockBreakConstructor.createPacket(2001, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), 35, false);

    Now, createPacketConstructor() doesn't need the exact values, only variables of the same type. So you could just give it dummy values like "0" or empty strings.
  20. Offline


    Thanks for the clarification. :)
  21. Offline


    ProtocolLib 1.5.1

    This update mainly addresses a couple of bugs (ticket 5 and ticket 6), but it also adds a couple of new features.

    As always, it can be downloaded from GitHub.

    The first feature is the ability to check and download a new version of ProtocolLib within the game. You still need to restart or reload the server in order to actually apply the new update, but it should be much easier to keep up with the new versions this way. It will also perform the update and download automatically, unless specifically disabled in the configuration.

    In addition, I've added a debug command (packet) that allows plugin authors to easily add a simple packet listener for any arbitrary packet ID. That way, it's not necessary to write a small debug plugin in order to just check when a packet is sent, and the content of the packet.

    Both commands are only available to operators, unless users are specifically given the permission "protocol.admin". In addition, the permission "protocol.info" controls whether or not users are notified of any errors or updates regarding ProtocolLib.

    There's also a new "packet timeout" listener. It allows plugins to specify a custom behavior when a packet has timed out during asynchronous processing. For instance, one might consider recreating the packet with updated data after a certain amount of time, instead of just dropping the packet.

    Bug fixes
    Small fixes
  22. Offline


    For some reason my server is still timing out with protocollib with no errors. I m gonna try to reproduce it again and see how it goes :/
  23. Offline


    You should use NoLagg when you're trying to reproduce the problem. That way, you'll get a stack trace if the main thread is stuck, which should make it much easier to track down the cause of the problem.
  24. Offline


    Ah that's convenient. But I used eclipse debugger to get the stack trace:
    2. SimplePluginManager.callEvent(Event) line: 461
    3. TagAPI.handlePacket(Packet20NamedEntitySpawn, Player) line: 254
    4. TagAPI.packet(Packet20NamedEntitySpawn, Player) line: 229
    5. ProtocolLibHandler$1.onPacketSending(PacketEvent) line: 30
    6. SortedPacketListenerList.invokePacketSending(ErrorReporter, PacketEvent) line: 69
    7. PacketFilterManager.handlePacket(SortedPacketListenerList, PacketEvent, boolean) line: 401
    8. PacketFilterManager.invokePacketSending(PacketEvent) line: 381
    9. NetworkServerInjector(PlayerInjector).handlePacketSending(Packet) line: 535
    10. NetworkServerInjector.handlePacketSending(Packet) line: 52
    11. NetworkServerInjector$1.intercept(Object, Method, Object[], MethodProxy) line: 159
    12. NetServerHandler$$EnhancerByCGLIB$$5765522a.sendPacket(Packet) line: not available
    13. EntityTrackerEntry.updatePlayer(EntityPlayer) line: 302
    14. EntityTrackerEntry.scanPlayers(List) line: 369
    15. EntityTracker.addEntity(Entity, int, int, boolean) line: 103
    16. EntityTracker.addEntity(Entity, int, int) line: 86
    17. EntityTracker.track(Entity) line: 23
    18. WorldManager.a(Entity) line: 18
    19. WorldServer(World).a(Entity) line: 910
    20. WorldServer.a(Entity) line: 696
    21. WorldServer(World).addEntity(Entity, CreatureSpawnEvent$SpawnReason) line: 899
    22. WorldServer(World).addEntity(Entity) line: 844
    23. ServerConfigurationManager(ServerConfigurationManagerAbstract).c(EntityPlayer) line: 172
    24. ServerConfigurationManager(ServerConfigurationManagerAbstract).a(INetworkManager, EntityPlayer) line: 93
    25. NetLoginHandler.d() line: 132
    26. NetLoginHandler.c() line: 45
    27. DedicatedServerConnectionThread.a() line: 44
    28. DedicatedServerConnection.b() line: 29
    29. DedicatedServer(MinecraftServer).r() line: 578
    30. DedicatedServer.r() line: 215
    31. DedicatedServer(MinecraftServer).q() line: 495
    32. DedicatedServer(MinecraftServer).run() line: 428
    33. ThreadServerApplication.run() line: 818

    This might be more of a bukkit issue? Another time when it got stuck was on firing PlayerVelocityEvent
    Comphenix likes this.
  25. Offline


    Oh, looks like it's caused by a deadlock:

    But I'm at a loss at thinking of how exactly. It must have something to do with callEvent or registerInterface (load plugin) being called by separate, dependent threads, but it's hard to imagine a situation where this would occur accidentally. Though, callEvent invokes arbitrary plugin code, so it's hard to know.

    Try posting the stack trace for every current thread instead. Maybe that will shed some more light on the problem.
  26. Offline


    could it be possible to make code that blocks it if you try to connect while ther eis already someone wiht your name on? i tried this with packet 0x02 but it said: 17:18:14 [WARNING] [ProtocolLib] [PlayerInjectionHandler] Unable to find stream: java.io.DataInputStream@4535b322
    protocolManager.addPacketListener(new PacketAdapter(this, ConnectionSide.CLIENT_SIDE, ListenerPriority.NORMAL, 0x02)
    public void onPacketSending(PacketEvent event)
    case 0x02:
    String name = event.getPacket().getSpecificModifier(String.class).read(1);
    for(Player player : ls.this.getServer().getOnlinePlayers())
    } catch(FieldAccessException e)
    getLogger().log(Level.SEVERE, "Couldn't acces field.", e);
    Comphenix likes this.
  27. Offline


    Manipulating the login sequence is not trivial. You should at least take a look at how it works (especially the source code) before you try to modify it.

    But more importantly, why aren't you just using the Bukkit API for this? You can kick a player before they have properly logged in by subscribing to the PlayerLoginEvent.
  28. Offline


    Hey it's me again :p
    I don't want to go offtopic on this thread here. I have opened a conversation with you so we can investigate the deadlock problem. It's not related to protocollib
  29. Offline


    ProtocolLib 1.6.0

    This update adds a slew of new wrappers for the DataWatcher class, along with WatchableObject. These are mainly necessary for parsing the mob spawn packets, but they can also be used on an entity directly with the getEntityWatcher() method.

    In addition, I've also added wrappers for ChunkPosition and ChunkCoordinates (there's nearly identical, except that the position class is immutable). That should make it easier to work with the explosion packet.

    The PacketContainer has been augmented with individual modifiers for each primitive type, allowing you to call "getIntegers" instead of "getSpecificModifier(int.class)" when you're reading or writing integer fields. That should make the class a whole lot easier to use. :)

    Finally, I've fixed a couple of bugs. The entity modifier bug is perhaps most significant - sometimes, it would fail to retrieve a spawned entity and just return NULL. I've changed it to use a more reliable method.

    New features:
    Bug fixes:
    Small fixes:
    Supertt007 likes this.
  30. Offline


    Thanks for another update Comphenix :)
Thread Status:
Not open for further replies.

Share This Page