From e63c8e34201f4afdd4e85ef96a898cffd3825e93 Mon Sep 17 00:00:00 2001 From: Boy Date: Sun, 14 Jan 2024 17:14:49 +0100 Subject: [PATCH] fix: properly handle custom smithing-transform recipes (durability/displayName/enchantments/...) --- .../looty/features/recipes/ItemRecipeQuery.kt | 1 + .../looty/features/recipes/ItemRecipes.kt | 4 +- .../features/recipes/RecipeCraftingSystem.kt | 52 ++++++++++++++++++- 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/com/mineinabyss/looty/features/recipes/ItemRecipeQuery.kt b/src/main/kotlin/com/mineinabyss/looty/features/recipes/ItemRecipeQuery.kt index 41cb71a..8992a19 100644 --- a/src/main/kotlin/com/mineinabyss/looty/features/recipes/ItemRecipeQuery.kt +++ b/src/main/kotlin/com/mineinabyss/looty/features/recipes/ItemRecipeQuery.kt @@ -5,6 +5,7 @@ import com.mineinabyss.geary.prefabs.PrefabKey import com.mineinabyss.geary.systems.accessors.Pointer import com.mineinabyss.geary.systems.query.GearyQuery import com.mineinabyss.idofront.recipes.register +import com.mineinabyss.idofront.serialization.recipes.SerializableRecipeIngredients import com.mineinabyss.looty.config.looty import org.bukkit.Bukkit import org.bukkit.NamespacedKey diff --git a/src/main/kotlin/com/mineinabyss/looty/features/recipes/ItemRecipes.kt b/src/main/kotlin/com/mineinabyss/looty/features/recipes/ItemRecipes.kt index a1bace5..ad47b26 100644 --- a/src/main/kotlin/com/mineinabyss/looty/features/recipes/ItemRecipes.kt +++ b/src/main/kotlin/com/mineinabyss/looty/features/recipes/ItemRecipes.kt @@ -10,13 +10,15 @@ interface ItemRecipes { val query: ItemRecipeQuery companion object : GearyAddonWithDefault { + val recipes by lazy { default().query.registerRecipes() } + override fun default() = object : ItemRecipes { override val query = ItemRecipeQuery() } override fun ItemRecipes.install() { geary.pipeline.runOnOrAfter(GearyPhase.ENABLE) { - val autoDiscoveredRecipes = query.registerRecipes() + val autoDiscoveredRecipes = recipes gearyPaper.plugin.listeners( RecipeDiscoverySystem(autoDiscoveredRecipes), diff --git a/src/main/kotlin/com/mineinabyss/looty/features/recipes/RecipeCraftingSystem.kt b/src/main/kotlin/com/mineinabyss/looty/features/recipes/RecipeCraftingSystem.kt index 0c69200..ecd8932 100644 --- a/src/main/kotlin/com/mineinabyss/looty/features/recipes/RecipeCraftingSystem.kt +++ b/src/main/kotlin/com/mineinabyss/looty/features/recipes/RecipeCraftingSystem.kt @@ -1,11 +1,31 @@ package com.mineinabyss.looty.features.recipes -import com.mineinabyss.geary.papermc.datastore.decodePrefabs +import com.mineinabyss.geary.papermc.datastore.* +import com.mineinabyss.geary.papermc.tracking.items.components.SetItemIgnoredProperties +import com.mineinabyss.geary.papermc.tracking.items.migration.SetItemIgnoredPropertyListener +import com.mineinabyss.geary.prefabs.PrefabKey +import com.mineinabyss.idofront.items.editItemMeta +import com.mineinabyss.idofront.messaging.broadcast +import com.mineinabyss.idofront.messaging.broadcastVal +import com.mineinabyss.idofront.nms.nbt.fastPDC +import com.mineinabyss.idofront.serialization.SerializableItemStack +import com.mineinabyss.idofront.serialization.toSerializable +import org.bukkit.Bukkit import org.bukkit.Keyed +import org.bukkit.Material import org.bukkit.event.EventHandler import org.bukkit.event.EventPriority import org.bukkit.event.Listener +import org.bukkit.event.inventory.CraftItemEvent +import org.bukkit.event.inventory.PrepareAnvilEvent import org.bukkit.event.inventory.PrepareItemCraftEvent +import org.bukkit.event.inventory.PrepareSmithingEvent +import org.bukkit.inventory.ItemStack +import org.bukkit.inventory.ShapedRecipe +import org.bukkit.inventory.ShapelessRecipe +import org.bukkit.inventory.SmithingTransformRecipe +import org.bukkit.inventory.meta.Damageable +import java.util.* class RecipeCraftingSystem : Listener { /** @@ -27,4 +47,34 @@ class RecipeCraftingSystem : Listener { inventory.result = null } } + + @EventHandler + fun PrepareSmithingEvent.onCustomSmithingTransform() { + // Smithing will cache the last recipe, so even with 0 input + // recipe will return as not null if say a Diamond Hoe was put in before + if (inventory.contents.any { it?.isEmpty != false }) return + // Return if no item is custom, as then vanilla should handle it fine + if (inventory.contents.none { it?.fastPDC?.hasComponentsEncoded == true }) return + + val (template, mineral) = (inventory.inputTemplate ?: return) to (inventory.inputMineral ?: return) + val equipment = inventory.inputEquipment ?: return + + val inputGearyEntity = equipment.fastPDC?.decodePrefabs()?.firstOrNull() ?: return + val smithingTransformRecipes = Bukkit.recipeIterator().asSequence().filter { (it as? SmithingTransformRecipe)?.result?.fastPDC?.hasComponentsEncoded == true }.filterIsInstance() + val customRecipeResult = smithingTransformRecipes.filter { it.template.test(template) && it.addition.test(mineral) && it.base.itemStack.itemMeta?.persistentDataContainer?.decodePrefabs()?.firstOrNull() == inputGearyEntity }.firstOrNull()?.result + var recipeResultItem = (customRecipeResult ?: ItemStack.empty()).let { result?.toSerializable()?.toItemStack(it, EnumSet.of(SerializableItemStack.Properties.DISPLAY_NAME)) } + + recipeResultItem = recipeResultItem?.editItemMeta { + displayName( + equipment.fastPDC?.decode()?.let { properties -> + persistentDataContainer.encode(properties) + if (SerializableItemStack.Properties.DISPLAY_NAME in properties.ignore && result?.itemMeta?.hasDisplayName() == true) + result?.itemMeta?.displayName()?.compact() + else displayName()?.compact() + } ?: displayName()?.compact() + ) + } + + result = recipeResultItem + } }