11package dev.slne.surf.surfapi.bukkit.server.packet.listener
22
3+ import com.github.benmanes.caffeine.cache.Caffeine
4+ import com.sksamuel.aedile.core.expireAfterAccess
35import dev.slne.surf.surfapi.bukkit.api.nms.NmsUseWithCaution
46import dev.slne.surf.surfapi.bukkit.api.nms.nmsBridge
57import dev.slne.surf.surfapi.bukkit.server.impl.nms.SurfBukkitNmsBridgeImpl
@@ -13,26 +15,27 @@ import dev.slne.surf.surfapi.core.api.reflection.SurfProxy
1315import dev.slne.surf.surfapi.core.api.reflection.createProxy
1416import dev.slne.surf.surfapi.core.api.reflection.surfReflection
1517import dev.slne.surf.surfapi.core.api.util.logger
16- import dev.slne.surf.surfapi.core.api.util.mutableObject2ObjectMapOf
1718import dev.slne.surf.surfapi.core.api.util.mutableObjectSetOf
1819import dev.slne.surf.surfapi.core.api.util.synchronize
1920import io.netty.channel.Channel
2021import io.netty.channel.ChannelDuplexHandler
2122import io.netty.channel.ChannelHandlerContext
2223import io.netty.channel.ChannelPromise
24+ import io.papermc.paper.connection.PaperPlayerLoginConnection
2325import io.papermc.paper.connection.ReadablePlayerCookieConnectionImpl
2426import io.papermc.paper.event.connection.PlayerConnectionValidateLoginEvent
2527import io.papermc.paper.network.ChannelInitializeListenerHolder
2628import net.kyori.adventure.key.Key
2729import net.minecraft.network.Connection
2830import net.minecraft.network.HandlerNames
2931import net.minecraft.network.protocol.Packet
30- import net.minecraft.server.level.ServerPlayer
32+ import net.minecraft.network.protocol.login.ClientboundLoginFinishedPacket
3133import org.bukkit.event.EventHandler
3234import org.bukkit.event.EventPriority
3335import org.bukkit.event.Listener
3436import org.bukkit.event.player.PlayerJoinEvent
3537import java.util.*
38+ import kotlin.time.Duration.Companion.minutes
3639import dev.slne.surf.surfapi.bukkit.api.event.register as registerListener
3740import dev.slne.surf.surfapi.bukkit.api.event.unregister as unregisterListener
3841
@@ -42,7 +45,11 @@ object PlayerChannelInjector : Listener {
4245 private val CHANNEL_KEY = Key .key(" surf-api" , " packet-listener" )
4346 private const val CHANNEL_NAME = " surf_api_packet_listener"
4447
45- private val playerInjectorCache = mutableObject2ObjectMapOf<UUID , ServerPlayer >().synchronize()
48+ private val playerInjectorCache = Caffeine .newBuilder()
49+ .weakValues()
50+ .expireAfterAccess(1 .minutes)
51+ .build<UUID , Connection >()
52+
4653 private val injectedChannels = mutableObjectSetOf<Channel >().synchronize()
4754
4855 fun register () {
@@ -76,21 +83,29 @@ object PlayerChannelInjector : Listener {
7683 @EventHandler
7784 fun onPlayerLogin (event : PlayerConnectionValidateLoginEvent ) {
7885 val paperConnection = event.connection
79- if (paperConnection is ReadablePlayerCookieConnectionImpl ) {
86+ if (paperConnection is PaperPlayerLoginConnection ) {
87+ val profile =
88+ paperConnection.authenticatedProfile ? : error(" Authenticated profile is null" )
8089 val connection =
8190 ReadablePlayerCookieConnectionImplProxy .instance.getConnection(paperConnection)
82- injectChannel(connection.channel).connection = connection
91+ playerInjectorCache.put(
92+ profile.id ? : error(" PlayerProfile does not provide a uuid" ),
93+ connection
94+ )
8395 }
8496 }
8597
8698 @EventHandler(priority = EventPriority .LOWEST )
8799 fun onPlayerJoin (event : PlayerJoinEvent ) {
88100 val player = event.player.toNms()
89-
90101 val connection = player.connection.connection
91102 val channelHandler = connection.channel.pipeline().get(CHANNEL_NAME )
92103
93104 if (channelHandler != null ) {
105+ if (channelHandler is PacketHandler ) {
106+ channelHandler.connection = connection
107+ playerInjectorCache.invalidate(player.uuid)
108+ }
94109 return
95110 }
96111
@@ -119,8 +134,17 @@ object PlayerChannelInjector : Listener {
119134 return
120135 }
121136
122- val connection = this @PacketHandler.connection
123- if (connection == null ) {
137+ if (connection == null && msg is ClientboundLoginFinishedPacket ) {
138+ val uuid = msg.gameProfile().id
139+ val cachedConnection = playerInjectorCache.getIfPresent(uuid)
140+ if (cachedConnection != null ) {
141+ connection = cachedConnection
142+ }
143+ }
144+
145+ val connection = connection
146+ val player = connection?.player
147+ if (connection == null || player == null ) {
124148 super .write(ctx, msg, promise)
125149 return
126150 }
@@ -161,8 +185,9 @@ object PlayerChannelInjector : Listener {
161185 return
162186 }
163187
164- val connection = this @PacketHandler.connection
165- if (connection == null ) {
188+ val connection = connection
189+ val player = connection?.player
190+ if (connection == null || player == null ) {
166191 super .channelRead(ctx, msg)
167192 return
168193 }
0 commit comments