Hook PlayerConnection.sendPacket(Packet) (no libs)

Discussion in 'Plugin Development' started by Crunkle, Feb 4, 2013.

  1. Offline

    Crunkle

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    Hello,

    I'm wondering how exactly I could inject/insert into the PlayerConnection.sendPacket(Packet) method so I can then modify the packet's data (similarly to ProtocolLib).

    Yes, I know I will need reflector (cglib?) and/or other APIs although I can't use ProtocolLib or plugins that Bukkit will load (apart from my one).

    Any ideas?

    Thanks.

    This post has been edited 3 times. It was last edited by Crunkle Feb 4, 2013.
    Comphenix likes this.
  2. Offline

    Comphenix

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    You don't need CGlib - I only use it in ProtocolLib to stay compatible with Spout, Spigot and other custom modifications, as well as improving performance in certain key areas. I also abuse it in order to make ProtocolLib compatible with CraftBukkit Beta 1.0.0 (yes, really).

    As far as making your own injector - I'd take a look at how Orebfuscator (both in new and the old method) or TagAPI does it, and use what works for you. It really depends on what kind of packets you're trying to intercept, and whether or not you're getting the packets sent by the server, or the packets received from all the clients.

    I know of three methods for intercepting packets sent by the server, though there might be more:
    1. Proxy the PlayerConnection class and insert it into DedicatedServerConnection (in order to get every ping packet among other things) and the player entity itself. To read the sent packets, override the sendPacket() method.

      This is generally the most versatile option, and should be enough to intercept all the packets sent by the server. In the past, this was necessary in order to intercept map chunk (51) and map chunk bulk (56) packets, though it's no longer the case in 1.4.7.
    2. Implement the INetworkManager interface and forward all method calls to the NetworkManager in the player's PlayerConnection. This usually works (though I've seen plugins crash because they expect a NetworkManager), but it does require Minecraft 1.3.1 as INetworkManager didn't exist prior to this version. Use the queue() method to intercept packets.
    3. And last, but not least (it's what TagAPI use), you have the highPriorityQueue and lowPriorityQueue lists in NetworkManager. Packets that are intended for transmission, are first enqueued here before they're sent in the player's NetworkWriterThread. Remember to synchronize with h = new Object(), the object lock!
    You can generally just choose one, but I've implemented all three in ProtocolLib. I use method #2 when the player logs in (and we're dealing with a PendingConnection), and then method #1 when Minecraft has switched to a PlayerConnection.

    For intercepting packets that have been received from the client, you generally have to methods, depending on how versatile your interception is:
    1. Override the packet-id-to-class registry in Packet and insert your own overriden proxy classes here (class MyProxy extends Packet40EntityMetadata). This is how I do it in ProtocolLib, though I use CGLib to generate the proxies in order to not specifically reference CraftBukkit.

      Once Minecraft/CraftBukkit constructs an instance of your proxy packet, you can intercept the handle(Connection paramConnection) method to stop the packet from being processed or modify it before it is.

    2. Override PlayerConnection like in method #1, then override any of the handle(Packet40EntityMetadata) methods in it (called a in the current version).
    I'll end by referencing the source code for both ProtocolLib and Orebfuscator, along with CraftBukkit and Minecraft itself. You should definitely familiarize yourself with the source code before you starting poking into the internals, especially if you intend to actually maintain this plugin.

    Good luck! :)

    This post has been edited 1 time. It was last edited by Comphenix Feb 4, 2013.
  3. Offline

    Crunkle

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    Thanks! This really helped, a lot.
    Managed to intercept the packets I need thanks to you.

    I owe you one.
  4. Offline

    Comphenix

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    That was quick. I guess you went with PlayerConnection then?

    No problem. :)
    Crunkle likes this.
  5. Offline

    DJSanderrr

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    Can anyone maybe explain me how Packet sending actuly works? Or give a link? Thanks!
    @Comphenix @Crunkle
  6. Offline

    Crunkle

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    Went with the first one simply because it looked the easiest, haha.
    I was already trying to do this although didn't particularly understand anything I wrote.

    This isn't about sending packets. However, to send something, you may want to do something along the lines of:
    Code:
    ((CraftPlayer) yourBukkitPlayer).getHandle().playerConnection.sendPacket(Packet);
    Packets are basically how the client and server communicate with each other. For example, you may send a packet telling the client that someone has wrote a chat message.

    This post has been edited 4 times. It was last edited by Crunkle Feb 4, 2013.
  7. Offline

    DJSanderrr

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    okay tnx. i'll try

Share This Page