1+ package cc.modlabs.kpaper.packets
2+
3+ import cc.modlabs.kpaper.extensions.connection
4+ import io.netty.channel.Channel
5+ import io.netty.channel.ChannelDuplexHandler
6+ import io.netty.channel.ChannelHandlerContext
7+ import net.minecraft.network.protocol.Packet
8+ import org.bukkit.entity.Player
9+ import org.jetbrains.annotations.ApiStatus
10+
11+ object PacketInterceptor {
12+
13+ private val packetCallbacks = mutableMapOf<Int , Pair <Class <out Packet <* >>, (Packet <* >) -> Unit >> ()
14+ private var counter = 0
15+
16+ /* *
17+ * Registers a packet callback.
18+ * The callback will be called when the given packet is received.
19+ * Don't forget to inject the packet interceptor into the player before you can receive packets.
20+ *
21+ * @param packet the packet to register the callback for
22+ * @param callback the callback to be called when the packet is received
23+ * @return the ID of the callback
24+ */
25+ fun <T : Packet <* >> registerPacketCallback (packet : Class <T >, callback : (T ) -> Unit ): Int {
26+ val id = counter++
27+ packetCallbacks[id] = Pair (packet, callback as (Packet <* >) -> Unit )
28+ return id
29+ }
30+
31+ /* *
32+ * Unregisters a packet callback.
33+ *
34+ * @param id the ID of the callback to unregister
35+ */
36+ fun unregisterPacketCallback (id : Int ) {
37+ packetCallbacks.remove(id)
38+ }
39+
40+ /* *
41+ * Handles a received packet. (This method is called by the packet interceptor)
42+ * Don't call this method directly.
43+ *
44+ * @param packet the packet to handle
45+ */
46+ @ApiStatus.Internal
47+ internal fun handlePacket (packet : Packet <* >) {
48+ packetCallbacks.filter { it.value.first.javaClass == packet.javaClass }.forEach { (id, pair) ->
49+ pair.second(packet)
50+ }
51+ }
52+ }
53+
54+ /* *
55+ * Injects a packet interceptor into the player.
56+ * You need to call this method on the player before you can receive packets.
57+ * This should be called in the PlayerJoinEvent.
58+ */
59+ fun Player.injectPacketInterceptor () {
60+ val channelDuplexHandler = object : ChannelDuplexHandler () {
61+ override fun channelRead (channelHandlerContext : ChannelHandlerContext , packet : Any ) {
62+ if (packet !is Packet <* >) return
63+ PacketInterceptor .handlePacket(packet)
64+ super .channelRead(channelHandlerContext, packet)
65+ }
66+ }
67+ var channel: Channel ? = null
68+ try {
69+ channel = connection.connection.channel
70+ channel.pipeline().addBefore(" packet_handler" , name, channelDuplexHandler)
71+ } catch (e: IllegalArgumentException ) {
72+ // Bei Plugin-Neuladen, um doppelte Handler-Namen-Ausnahme zu verhindern
73+ if (channel == null ) {
74+ return
75+ }
76+ if (! channel.pipeline().names().contains(name)) return
77+ channel.pipeline().remove(name)
78+ injectPacketInterceptor()
79+ } catch (_: IllegalAccessException ) {
80+ } catch (_: NoSuchFieldException ) {
81+ }
82+ }
0 commit comments