Skip to content

Commit 41fb502

Browse files
Create PacketInterceptor.kt
1 parent 1853ce1 commit 41fb502

File tree

1 file changed

+82
-0
lines changed

1 file changed

+82
-0
lines changed
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
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

Comments
 (0)