Skip to content

Commit

Permalink
refactor: improve pre-joinworld pack-loading
Browse files Browse the repository at this point in the history
  • Loading branch information
Boy0000 committed Sep 23, 2024
1 parent 3dedcec commit aee872e
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 56 deletions.
1 change: 0 additions & 1 deletion src/main/kotlin/com/mineinabyss/packy/PackyPlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ class PackyPlugin : JavaPlugin() {
PackyDownloader.downloadTemplates()
TemplateLoadTriggers.registerTemplateHandlers()
PackyGenerator.setupRequiredPackTemplates()
PackyServer.registerConfigPacketHandler()
}

private val templateFormat = ConfigFormats(
Expand Down
55 changes: 0 additions & 55 deletions src/main/kotlin/com/mineinabyss/packy/PackyServer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down Expand Up @@ -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<ConfigurationTask> ?: return@interceptClientbound packet
val offlinePdc = connection.player?.bukkitEntity?.getOfflinePDC() ?: return@interceptClientbound packet
val packyData = offlinePdc.decode<PackyData>() ?: 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 }
Expand Down
46 changes: 46 additions & 0 deletions src/main/kotlin/com/mineinabyss/packy/listener/PlayerListener.kt
Original file line number Diff line number Diff line change
@@ -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 {

Expand All @@ -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<ServerConfigurationPacketListenerImpl>()
.firstOrNull { it.craftPlayer.uniqueId == player.uniqueId } ?: return
val taskQueue = configurationTasks.get(packetListener) as? Queue<ConfigurationTask> ?: return
val packyData = player.getOfflinePDC()?.decode<PackyData>() ?: 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))
}
}
}
}

0 comments on commit aee872e

Please sign in to comment.