Skip to content

Commit

Permalink
refactor: swap PackyData to record the toggle-state of a template
Browse files Browse the repository at this point in the history
  • Loading branch information
Boy0000 committed Aug 9, 2024
1 parent 33c8dea commit 3ae832d
Show file tree
Hide file tree
Showing 12 changed files with 91 additions and 67 deletions.
34 changes: 23 additions & 11 deletions src/main/kotlin/com/mineinabyss/packy/PackObfuscator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class PackObfuscator(private val resourcePack: ResourcePack) {
}

private fun obfuscateModels() {
resourcePack.models().filterNotNull().forEach { obfuscateModel(it) }
resourcePack.models().filterNotNull().forEach(::obfuscateModel)

obfuscatedModels.forEach {
resourcePack.removeModel(it.originalModel.key())
Expand Down Expand Up @@ -149,20 +149,20 @@ class PackObfuscator(private val resourcePack: ResourcePack) {


private fun obfuscateModel(model: Model) =
obfuscatedModels.findObf(model.key()) ?: model.obfuscateModelTextures().obfuscateOverrides()
obfuscatedModels.findObf(model.key()) ?: model.obfuscateModelTextures().obfuscateParentModel().obfuscateOverrides()

private fun Model.obfuscateModelTextures(): Model {
obfuscatedModels.findObf(this.key())?.let { return it }

val layers = textures().layers().filter { it.key() != null }.map { modelTexture ->
obfuscateItemTexture(modelTexture)?.key()?.let { ModelTexture.ofKey(it) } ?: modelTexture
obfuscateModelTexture(modelTexture)?.key()?.let(ModelTexture::ofKey) ?: modelTexture
}
val variables = textures().variables().map { variable ->
variable.key to (obfuscateItemTexture(variable.value)?.key()
?.let(ModelTexture::ofKey) ?: variable.value)
variable.key to (obfuscateModelTexture(variable.value)?.key()?.let(ModelTexture::ofKey) ?: variable.value)
}.toMap()

val particle = textures().particle()
?.let { p -> obfuscateItemTexture(p)?.key()?.let { ModelTexture.ofKey(it) } ?: p }
?.let { p -> obfuscateModelTexture(p)?.key()?.let { ModelTexture.ofKey(it) } ?: p }
val modelTextures = ModelTextures.builder().layers(layers).variables(variables).particle(particle).build()
return this.toBuilder().textures(modelTextures).build()
}
Expand All @@ -173,12 +173,24 @@ class PackObfuscator(private val resourcePack: ResourcePack) {
.uvLock(uvLock()).weight(weight()).x(x()).y(y()).build()
}

private fun Model.obfuscateParentModel(): Model {
val parent = parent() ?: return this
obfuscatedModels.findObf(key())?.let { return it }

return toBuilder().parent(
obfuscatedModels.findObf(parent)?.key()
?: resourcePack.takeUnless { parent == key() }?.model(parent)?.let(::obfuscateModel)?.key()
?: parent
).build()
}

private fun Model.obfuscateOverrides(): Model = obfuscatedModels.findObf(key()) ?: toBuilder().overrides(
overrides().filterNotNull().map { override ->
if (ResourcePacks.defaultVanillaResourcePack?.model(override.model()) != null) return@map override
val modelKey = obfuscatedModels.findObf(override.model())?.key()
?: resourcePack.takeUnless { override.model() == this.key() }?.model(override.model())?.let { obfuscateModel(it) }?.key()
?: override.model()
val overrideKey = override.model()
if (ResourcePacks.defaultVanillaResourcePack?.model(overrideKey) != null) return@map override
val modelKey = obfuscatedModels.findObf(overrideKey)?.key()
?: resourcePack.takeUnless { overrideKey == this.key() }?.model(overrideKey)?.let(::obfuscateModel)?.key()
?: overrideKey

return@map ItemOverride.of(modelKey, override.predicate())
}
Expand All @@ -193,7 +205,7 @@ class PackObfuscator(private val resourcePack: ResourcePack) {
this.toBuilder().key(this.key().obfuscateKey()).build()
.also { obfuscatedTextures += ObfuscatedTexture(this@obfuscate, it) }

private fun obfuscateItemTexture(modelTexture: ModelTexture): Texture? {
private fun obfuscateModelTexture(modelTexture: ModelTexture): Texture? {
val keyPng = modelTexture.key()?.removeSuffix(".png") ?: return null
return obfuscatedTextures.findObf(keyPng) ?: resourcePack.texture(keyPng)?.obfuscate()
}
Expand Down
22 changes: 22 additions & 0 deletions src/main/kotlin/com/mineinabyss/packy/PackyCommands.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@ import com.github.shynixn.mccoroutine.bukkit.launch
import com.mineinabyss.guiy.inventory.guiy
import com.mineinabyss.idofront.commands.brigadier.commands
import com.mineinabyss.idofront.messaging.error
import com.mineinabyss.idofront.messaging.info
import com.mineinabyss.idofront.messaging.success
import com.mineinabyss.idofront.textcomponents.miniMsg
import com.mineinabyss.packy.components.packyData
import com.mineinabyss.packy.config.packy
import com.mineinabyss.packy.menus.picker.PackyMainMenu
import io.papermc.paper.command.brigadier.argument.ArgumentTypes
import net.kyori.adventure.text.Component
import net.kyori.adventure.text.format.NamedTextColor
import org.bukkit.Bukkit
import org.bukkit.entity.Player

Expand Down Expand Up @@ -58,6 +62,24 @@ object PackyCommands {
}
}
}
"debug" {
playerExecutes {

player.packyData.templates.mapNotNull { (packy.templates[it.key] ?: return@mapNotNull null) to it.value }
.map {
Component.textOfChildren(
Component.text(it.first.id, when {
it.first.default && it.first.required -> NamedTextColor.GOLD
it.first.default -> NamedTextColor.YELLOW
it.first.required -> NamedTextColor.RED
else -> NamedTextColor.AQUA
}),
Component.text(": "),
Component.text(it.second, if (it.second) NamedTextColor.GREEN else NamedTextColor.DARK_RED),
)
}.forEach(sender::sendMessage)
}
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/com/mineinabyss/packy/PackyGenerator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import com.mineinabyss.packy.helpers.TemplateIds
import kotlinx.coroutines.*
import team.unnamed.creative.ResourcePack
import team.unnamed.creative.base.Writable
import team.unnamed.creative.sound.SoundRegistry
import kotlin.io.path.div
import kotlin.io.path.exists

Expand Down Expand Up @@ -62,6 +61,7 @@ object PackyGenerator {

PackObfuscator(cachedPack).obfuscatePack()

ResourcePacks.resourcePackWriter.writeToZipFile(packy.plugin.dataFolder.resolve("test2.zip"), cachedPack)
val builtPack = ResourcePacks.resourcePackWriter.build(cachedPack)
PackyPack(builtPack, templateIds).apply {
cachedPacks[templateIds] = this
Expand Down
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.cacheDefaultPackData()
PackyServer.registerConfigPacketHandler()
}

Expand Down
17 changes: 8 additions & 9 deletions src/main/kotlin/com/mineinabyss/packy/PackyServer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ 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
Expand All @@ -25,6 +28,7 @@ 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
Expand All @@ -34,7 +38,6 @@ import java.util.concurrent.Executors

object PackyServer {
var packServer: ResourcePackServer? = null
private lateinit var builtDefaultPack: ByteArray

suspend fun sendPack(player: Player) {
val templateIds = player.packyData.enabledPackIds
Expand All @@ -48,10 +51,6 @@ object PackyServer {
)
}

fun cacheDefaultPackData() {
builtDefaultPack = ResourcePacks.resourcePackWriter.build(packy.defaultPack).data().toByteArray()
}

private suspend fun Player.sendPackGeneratingActionBar() {
sendActionBar(Component.text("Generating ResourcePack.", NamedTextColor.RED))
delay(10.ticks)
Expand All @@ -68,9 +67,9 @@ object PackyServer {
packy.plugin.interceptClientbound { packet: Packet<*>, connection: Connection ->
if (packet !is ClientboundSelectKnownPacks) return@interceptClientbound packet
val configListener = connection.packetListener as? ServerConfigurationPacketListenerImpl ?: return@interceptClientbound packet
val player = connection.player?.bukkitEntity ?: return@interceptClientbound packet
val packyData = player.getOfflinePDC()?.decode<PackyData>() ?: 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()
Expand Down Expand Up @@ -118,8 +117,8 @@ object PackyServer {
}

private val handler = ResourcePackRequestHandler { _, exchange ->
val data = exchange.requestURI.parseTemplateIds()?.takeIf { it.isNotEmpty() }
?.let(PackyGenerator.cachedPacksByteArray::get) ?: builtDefaultPack
val data = exchange.requestURI.parseTemplateIds()?.let(cachedPacksByteArray::get)
?: ResourcePacks.resourcePackWriter.build(packy.defaultPack).data().toByteArray()
exchange.responseHeaders["Content-Type"] = "application/zip"
exchange.sendResponseHeaders(200, data.size.toLong())
exchange.responseBody.use { responseStream -> responseStream.write(data) }
Expand Down
18 changes: 4 additions & 14 deletions src/main/kotlin/com/mineinabyss/packy/components/PackyData.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,21 @@ import com.mineinabyss.geary.papermc.tracking.entities.toGeary
import com.mineinabyss.geary.serialization.getOrSetPersisting
import com.mineinabyss.geary.serialization.setPersisting
import com.mineinabyss.packy.config.PackyTemplate
import com.mineinabyss.packy.config.conflictsWith
import com.mineinabyss.packy.config.packy
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import org.bukkit.entity.Player
import java.util.SortedMap

@Serializable
@SerialName("packy:packy_data")
data class PackyData(
val enabledPackAddons: MutableSet<PackyTemplate> = packy.templates.filter { !it.required && it.default }.toMutableSet(),
val templates: MutableMap<String, Boolean> = packy.templates.associate { it.id to (it.default || it.required) }.toMutableMap(),
var bypassForced: Boolean = false
) {
val enabledPackIds get() = enabledPackAddons.map { it.id }.toSortedSet()
val enabledPackIds get() = templates.filterValues { it }.keys.toSortedSet()
}

var Player.packyData
get() = this.toGeary().getOrSetPersisting<PackyData> { PackyData() }
set(value) {
this.toGeary().setPersisting(value)
}

fun Player.removeConflictingPacks(template: PackyTemplate): Set<PackyTemplate> {
return mutableSetOf<PackyTemplate>().apply {
packyData.enabledPackAddons.removeIf { t ->
t.conflictsWith(template).let { if (it) this.add(t); it }
}
}.toSet()
}
set(value) { this.toGeary().setPersisting(value) }
11 changes: 4 additions & 7 deletions src/main/kotlin/com/mineinabyss/packy/config/PackyTemplate.kt
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
package com.mineinabyss.packy.config

import com.mineinabyss.geary.serialization.serializers.InnerSerializer
import com.mineinabyss.geary.serialization.serializers.PolymorphicListAsMapSerializer
import com.mineinabyss.idofront.messaging.broadcastVal
import com.mineinabyss.packy.listener.LoadTrigger
import kotlinx.serialization.*
import kotlinx.serialization.EncodeDefault.Mode.NEVER
import kotlinx.serialization.Transient
import kotlinx.serialization.builtins.MapSerializer
import kotlinx.serialization.builtins.serializer
import org.bukkit.event.Listener
import java.io.File
import java.nio.file.Path
import kotlin.io.path.*

Expand All @@ -24,6 +21,7 @@ data class PackyTemplates(private val templates: List<PackyTemplate> = listOf())
fun forEach(action: (PackyTemplate) -> Unit) = templates.forEach(action)
fun filter(filter: (PackyTemplate) -> Boolean) = templates.filter(filter)
fun find(predicate: (PackyTemplate) -> Boolean) = templates.find(predicate)
fun <K, V> associate(transform: (PackyTemplate) -> Pair<K, V>) = templates.associate(transform)
operator fun get(id: String) = templates.find { it.id == id }

class Serializer : InnerSerializer<Map<String, PackyTemplate>, PackyTemplates>(
Expand All @@ -49,6 +47,9 @@ data class PackyTemplate(
@EncodeDefault(NEVER) private val filePath: String? = null
) {

fun conflictsWith(template: PackyTemplate) =
template.id in this.conflictsWith || this.id in template.conflictsWith

@Transient var triggerListener: Listener? = null

val path: Path get() = filePath?.takeIf { it.isNotEmpty() }?.let { packy.plugin.dataFolder.parentFile.toPath() / it }
Expand All @@ -69,7 +70,3 @@ data class PackyTemplate(

@Serializable
data class PackyAccessToken(internal val token: String = "")

fun PackyTemplate.conflictsWith(template: PackyTemplate) =
template.id in this.conflictsWith || this.id in template.conflictsWith

13 changes: 6 additions & 7 deletions src/main/kotlin/com/mineinabyss/packy/listener/PlayerListener.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.mineinabyss.packy.listener

import com.mineinabyss.packy.components.packyData
import com.mineinabyss.packy.config.PackyTemplate
import com.mineinabyss.packy.config.packy
import org.bukkit.event.EventHandler
import org.bukkit.event.EventPriority
Expand All @@ -11,12 +12,10 @@ class PlayerListener : Listener {

@EventHandler(priority = EventPriority.NORMAL)
fun PlayerJoinEvent.filterPackyData() {
// Remove old or forced keys from enabledPackAddons
player.packyData.enabledPackAddons.removeIf { t -> t.id !in packy.templates || t.required }
// Ensure that PackyTemplates are up-to-date
player.packyData.enabledPackAddons.filter { it in packy.templates }.forEach { template ->
player.packyData.enabledPackAddons -= template
packy.templates[template.id]?.let { player.packyData.enabledPackAddons += it }
}
val packyData = player.packyData
// Remove old or required keys from templates
packyData.templates.keys.filter { packy.templates[it] == null }.forEach(packyData.templates::remove)
// Add missing template keys
packy.templates.forEach { template -> packyData.templates.computeIfAbsent(template.id) { template.default || template.required } }
}
}
24 changes: 15 additions & 9 deletions src/main/kotlin/com/mineinabyss/packy/menus/picker/PackPicker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,22 @@ import com.mineinabyss.idofront.messaging.success
import com.mineinabyss.idofront.messaging.warn
import com.mineinabyss.packy.components.PackyData
import com.mineinabyss.packy.components.packyData
import com.mineinabyss.packy.components.removeConflictingPacks
import com.mineinabyss.packy.config.PackyTemplate
import com.mineinabyss.packy.config.packy
import org.bukkit.command.CommandSender
import org.bukkit.entity.Player

object PackPicker {
fun addPack(scope: PackyUIScope, player: Player, packyData: PackyData, pack: String, sender: CommandSender = player): Unit? {
fun enablePack(scope: PackyUIScope, player: Player, packyData: PackyData, pack: String, sender: CommandSender = player): Unit? {
return packy.templates[pack]?.let { template ->
val removedConflicting = player.removeConflictingPacks(template).map { it.id }
packyData.enabledPackAddons += template
val disabledConflicting = disableConflictingPacks(player, template).map { it.id }
packyData.templates[template.id] = true

if ((sender as? Player)?.uniqueId != player.uniqueId) sender.success("TemplatePack ${template.id} was added to ${player.name}'s addon-packs")
scope.changedAction = {
player.success("The template ${template.id} was added to your addon-packs")
if (removedConflicting.isNotEmpty()) {
sender.warn("Removed conflicting pack-templates: ${removedConflicting.joinToString(", ")}")
if (disabledConflicting.isNotEmpty()) {
sender.warn("Disabled conflicting pack-templates: ${disabledConflicting.joinToString(", ")}")
}
}
} ?: run {
Expand All @@ -34,13 +34,13 @@ object PackPicker {
}
}

fun removePack(scope: PackyUIScope, player: Player, packyData: PackyData, pack: String, sender: CommandSender = player): Unit? {
fun disablePack(scope: PackyUIScope, player: Player, packyData: PackyData, pack: String, sender: CommandSender = player): Unit? {
return packy.templates.find { it.id == pack }?.let { template ->
packyData.enabledPackAddons -= template
packyData.templates[template.id] = false

scope.changedAction = {
if ((sender as? Player)?.uniqueId != player.uniqueId) sender.success("TemplatePack ${template.id} was removed from ${player.name}'s addon-packs")
player.success("TemplatePack ${template.id} was removed from your addon-packs")
player.success("TemplatePack ${template.id} was disabled from your addon-packs")
}
} ?: run {
scope.changedAction = {
Expand All @@ -52,4 +52,10 @@ object PackPicker {
}
}
}

private fun disableConflictingPacks(player: Player, template: PackyTemplate): Set<PackyTemplate> {
return player.packyData.templates.keys.mapNotNull(packy.templates::get).filter(template::conflictsWith).toSet().also {
player.packyData.templates.putAll(it.associate { it.id to false })
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ fun PackyMenu() {
Item(subMenu.button.toItemStack(), subMenu.modifiers.toModifier().clickable {
// Return if the task returns null, meaning button was spammed whilst a set was currently generating
when {
templateId !in packyData.enabledPackIds -> PackPicker.addPack(scope, player, packyData, templateId)
else -> PackPicker.removePack(scope, player, packyData, templateId)
templateId !in packyData.enabledPackIds -> PackPicker.enablePack(scope, player, packyData, templateId)
else -> PackPicker.disablePack(scope, player, packyData, templateId)
} ?: return@clickable

scope.nav.refresh()
Expand All @@ -42,14 +42,14 @@ fun PackyMenu() {
)

PackyConfig.SubMenuType.CYCLING -> {
val templateId = packyData.enabledPackAddons.firstOrNull { it.id in subMenu.packs.keys }?.id ?: packs.first().first
val templateId = packyData.enabledPackIds.firstOrNull(subMenu.packs.keys::contains) ?: packs.first().first
val pack = subMenu.packs[templateId] ?: return
val currentTemplateIndex = packs.indexOf(templateId to pack)
val nextTemplateId = packs[(currentTemplateIndex + 1) % packs.size].first

CycleButton(subMenu, pack) {
// Return if the task returns null, meaning button was spammed whilst a set was currently generating
PackPicker.addPack(scope, player, packyData, nextTemplateId) ?: return@CycleButton
PackPicker.enablePack(scope, player, packyData, nextTemplateId) ?: return@CycleButton

packs = packs.rotatedLeft()
scope.nav.refresh()
Expand Down
Loading

0 comments on commit 3ae832d

Please sign in to comment.