From aee872ee42efc4808ed76601d8f495ac70e1a23b Mon Sep 17 00:00:00 2001 From: Boy Date: Mon, 23 Sep 2024 13:56:48 +0200 Subject: [PATCH] refactor: improve pre-joinworld pack-loading --- .../com/mineinabyss/packy/PackyPlugin.kt | 1 - .../com/mineinabyss/packy/PackyServer.kt | 55 ------------------- .../packy/listener/PlayerListener.kt | 46 ++++++++++++++++ 3 files changed, 46 insertions(+), 56 deletions(-) diff --git a/src/main/kotlin/com/mineinabyss/packy/PackyPlugin.kt b/src/main/kotlin/com/mineinabyss/packy/PackyPlugin.kt index b66a1fd..b7ac5df 100644 --- a/src/main/kotlin/com/mineinabyss/packy/PackyPlugin.kt +++ b/src/main/kotlin/com/mineinabyss/packy/PackyPlugin.kt @@ -65,7 +65,6 @@ class PackyPlugin : JavaPlugin() { PackyDownloader.downloadTemplates() TemplateLoadTriggers.registerTemplateHandlers() PackyGenerator.setupRequiredPackTemplates() - PackyServer.registerConfigPacketHandler() } private val templateFormat = ConfigFormats( diff --git a/src/main/kotlin/com/mineinabyss/packy/PackyServer.kt b/src/main/kotlin/com/mineinabyss/packy/PackyServer.kt index ea4b54f..198b8aa 100644 --- a/src/main/kotlin/com/mineinabyss/packy/PackyServer.kt +++ b/src/main/kotlin/com/mineinabyss/packy/PackyServer.kt @@ -2,38 +2,21 @@ package com.mineinabyss.packy import com.github.shynixn.mccoroutine.bukkit.launch import com.github.shynixn.mccoroutine.bukkit.ticks -import com.mineinabyss.geary.papermc.datastore.decode -import com.mineinabyss.idofront.nms.interceptClientbound -import com.mineinabyss.idofront.nms.nbt.getOfflinePDC import com.mineinabyss.idofront.resourcepacks.ResourcePacks import com.mineinabyss.idofront.textcomponents.miniMsg -import com.mineinabyss.packy.PackyGenerator.cachedPacks import com.mineinabyss.packy.PackyGenerator.cachedPacksByteArray -import com.mineinabyss.packy.components.PackyData -import com.mineinabyss.packy.components.PackyPack import com.mineinabyss.packy.components.packyData import com.mineinabyss.packy.config.packy import com.mineinabyss.packy.helpers.TemplateIds -import io.papermc.paper.adventure.PaperAdventure import kotlinx.coroutines.delay import kotlinx.coroutines.isActive import net.kyori.adventure.resource.ResourcePackRequest import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.NamedTextColor -import net.minecraft.network.Connection -import net.minecraft.network.protocol.Packet -import net.minecraft.network.protocol.common.ClientboundCustomPayloadPacket -import net.minecraft.network.protocol.configuration.ClientboundSelectKnownPacks -import net.minecraft.server.MinecraftServer -import net.minecraft.server.network.ConfigurationTask -import net.minecraft.server.network.ServerConfigurationPacketListenerImpl -import net.minecraft.server.network.config.ServerResourcePackConfigurationTask import org.bukkit.entity.Player -import team.unnamed.creative.ResourcePack import team.unnamed.creative.server.ResourcePackServer import team.unnamed.creative.server.handler.ResourcePackRequestHandler import java.net.URI -import java.util.* import java.util.concurrent.Executors @@ -61,44 +44,6 @@ object PackyServer { delay(10.ticks) } - private val configurationTasks = ServerConfigurationPacketListenerImpl::class.java.getDeclaredField("configurationTasks").apply { isAccessible = true } - private val currentTask = ServerConfigurationPacketListenerImpl::class.java.getDeclaredField("currentTask").apply { isAccessible = true } - private val startNextTaskMethod = ServerConfigurationPacketListenerImpl::class.java.getDeclaredMethod("startNextTask").apply { isAccessible = true } - fun registerConfigPacketHandler() { - - packy.plugin.interceptClientbound { packet: Packet<*>, connection: Connection -> - if (packet !is ClientboundCustomPayloadPacket) return@interceptClientbound packet - val configListener = connection.packetListener as? ServerConfigurationPacketListenerImpl ?: return@interceptClientbound packet - val taskQueue = configurationTasks.get(configListener) as? Queue ?: return@interceptClientbound packet - val offlinePdc = connection.player?.bukkitEntity?.getOfflinePDC() ?: return@interceptClientbound packet - val packyData = offlinePdc.decode() ?: PackyData() - - // Removes the JoinWorldTask from the Queue - val headTask = taskQueue.poll() - - // Runs next tick, after the queue progresses and is empty - packy.plugin.launch { - val info = PackyGenerator.getOrCreateCachedPack(packyData.enabledPackIds).await().resourcePackInfo - taskQueue.add( - ServerResourcePackConfigurationTask( - MinecraftServer.ServerResourcePackInfo( - info.id(), info.uri().toString(), info.hash(), - packy.config.force && !packyData.bypassForced, - PaperAdventure.asVanilla(packy.config.prompt?.miniMsg()) - )) - ) - - headTask?.let(taskQueue::add) - while (currentTask.get(configListener) != null) delay(1.ticks) - startNextTaskMethod.invoke(configListener) - } - - // Returns the ClientboundSelectKnownPacks packet, which causes the queue to continue - // Since it is now empty it does nothing, until our coroutine finishes and triggers startNextTask - return@interceptClientbound packet - } - } - fun startServer() { packy.logger.s("Starting Packy-Server...") val (ip, port) = packy.config.server.let { it.ip to it.port } diff --git a/src/main/kotlin/com/mineinabyss/packy/listener/PlayerListener.kt b/src/main/kotlin/com/mineinabyss/packy/listener/PlayerListener.kt index e144936..eca0773 100644 --- a/src/main/kotlin/com/mineinabyss/packy/listener/PlayerListener.kt +++ b/src/main/kotlin/com/mineinabyss/packy/listener/PlayerListener.kt @@ -1,12 +1,28 @@ package com.mineinabyss.packy.listener +import com.github.shynixn.mccoroutine.bukkit.launch +import com.mineinabyss.geary.papermc.datastore.decode +import com.mineinabyss.idofront.nms.nbt.getOfflinePDC +import com.mineinabyss.idofront.textcomponents.miniMsg +import com.mineinabyss.packy.PackyGenerator +import com.mineinabyss.packy.components.PackyData import com.mineinabyss.packy.components.packyData import com.mineinabyss.packy.config.PackyTemplate import com.mineinabyss.packy.config.packy +import io.papermc.paper.adventure.PaperAdventure +import kotlinx.coroutines.runBlocking +import net.kyori.adventure.resource.ResourcePackRequest +import net.minecraft.server.MinecraftServer.ServerResourcePackInfo +import net.minecraft.server.network.ConfigurationTask +import net.minecraft.server.network.ServerConfigurationPacketListenerImpl +import net.minecraft.server.network.config.ServerResourcePackConfigurationTask +import org.bukkit.craftbukkit.entity.CraftPlayer import org.bukkit.event.EventHandler import org.bukkit.event.EventPriority import org.bukkit.event.Listener import org.bukkit.event.player.PlayerJoinEvent +import org.bukkit.event.player.PlayerLinksSendEvent +import java.util.* class PlayerListener : Listener { @@ -18,4 +34,34 @@ class PlayerListener : Listener { // Add missing template keys packy.templates.forEach { template -> packyData.templates.computeIfAbsent(template.id) { template.default || template.required } } } + + private val configurationTasks = ServerConfigurationPacketListenerImpl::class.java.getDeclaredField("configurationTasks").apply { isAccessible = true } + @EventHandler + fun PlayerLinksSendEvent.sendResourcePackPreJoin() { + if (player.isOnline) return + + val packetListener = (player as CraftPlayer).handle.server.connection.connections + .map { it.packetListener }.filterIsInstance() + .firstOrNull { it.craftPlayer.uniqueId == player.uniqueId } ?: return + val taskQueue = configurationTasks.get(packetListener) as? Queue ?: return + val packyData = player.getOfflinePDC()?.decode() ?: PackyData() + + val info = PackyGenerator.getCachedPack(packyData.enabledPackIds)?.resourcePackInfo + if (info != null) { + if (player.isOnline) player.sendResourcePacks(ResourcePackRequest.addingRequest(info)) + else { + taskQueue.offer( + ServerResourcePackConfigurationTask( + ServerResourcePackInfo(info.id(), info.uri().toString(), info.hash(), packy.config.force && !packyData.bypassForced, PaperAdventure.asVanilla( + packy.config.prompt?.miniMsg())) + ) + ) + } + } else { + packy.plugin.launch { + val info = PackyGenerator.getOrCreateCachedPack(packyData.enabledPackIds).await().resourcePackInfo + if (player.isOnline) player.sendResourcePacks(ResourcePackRequest.addingRequest(info)) + } + } + } }