From 12008676bb864d9e5164a5669682bb6737a6f51d Mon Sep 17 00:00:00 2001 From: NichtStudioCode <51272202+NichtStudioCode@users.noreply.github.com> Date: Thu, 26 Oct 2023 19:23:04 +0200 Subject: [PATCH 01/12] Fix BlockPlaceContext#forApi --- .../xyz/xenondevs/nova/world/block/context/BlockContexts.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/nova/src/main/kotlin/xyz/xenondevs/nova/world/block/context/BlockContexts.kt b/nova/src/main/kotlin/xyz/xenondevs/nova/world/block/context/BlockContexts.kt index dec1726d5f6..e0b0aad9868 100644 --- a/nova/src/main/kotlin/xyz/xenondevs/nova/world/block/context/BlockContexts.kt +++ b/nova/src/main/kotlin/xyz/xenondevs/nova/world/block/context/BlockContexts.kt @@ -1,7 +1,6 @@ package xyz.xenondevs.nova.world.block.context import org.bukkit.Location -import org.bukkit.Material import org.bukkit.block.BlockFace import org.bukkit.entity.Entity import org.bukkit.inventory.EquipmentSlot @@ -52,10 +51,10 @@ data class BlockPlaceContext( val pos = location.pos return BlockPlaceContext( pos, - material.item?.createItemStack(1) ?: ItemStack(Material.AIR), + material.item?.createItemStack(1) ?: throw IllegalArgumentException("Block needs an item"), source, getSourceLocation(source) ?: location, - getOwnerUUID(source) ?: UUID(0L, 0L), + getOwnerUUID(source), pos.add(0, -1, 0), BlockFace.UP ) From 2a4a60536cfe7ff0e11baade55cbd1ade5fcacea Mon Sep 17 00:00:00 2001 From: NichtStudioCode <51272202+NichtStudioCode@users.noreply.github.com> Date: Sun, 5 Nov 2023 00:42:09 +0100 Subject: [PATCH 02/12] Fix plugin dependencies Fixes #303 --- nova-loader/src/main/resources/paper-plugin.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nova-loader/src/main/resources/paper-plugin.yml b/nova-loader/src/main/resources/paper-plugin.yml index 75b0f371358..cf1140f5f36 100644 --- a/nova-loader/src/main/resources/paper-plugin.yml +++ b/nova-loader/src/main/resources/paper-plugin.yml @@ -15,8 +15,6 @@ dependencies: required: false PlotSquared: required: false - GriefDefender: - required: false ProtectionStones: required: false Towny: @@ -39,6 +37,8 @@ dependencies: required: false WorldEdit: required: false + LuckPerms: + required: false permissions: nova.command.*: From 48c4c260860b0b48dc4fc6356264afe449f9b39c Mon Sep 17 00:00:00 2001 From: NichtStudioCode <51272202+NichtStudioCode@users.noreply.github.com> Date: Sun, 5 Nov 2023 00:45:33 +0100 Subject: [PATCH 03/12] Bump version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index f3e58c08dd7..5a65c10105d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,3 @@ -version = 0.15-alpha.5 +version = 0.15-alpha.6 kotlin.daemon.jvmargs=-Xmx2g org.gradle.jvmargs=-Xmx2g From 579fc9f90c03101b13241a9f33833986f4a3621e Mon Sep 17 00:00:00 2001 From: NichtStudioCode <51272202+NichtStudioCode@users.noreply.github.com> Date: Mon, 6 Nov 2023 10:43:22 +0100 Subject: [PATCH 04/12] Update bug_report.yml --- .github/ISSUE_TEMPLATE/bug_report.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 57fb7dd0b93..8616782a1cb 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -59,14 +59,16 @@ body: required: true - type: textarea attributes: - label: Full server log - description: Please provide the complete server log. Just drag & drop the .log file into this text area to upload it to GitHub. Alternatively, you can also upload your log to sites such as [pastebin](https://pastebin.com) or [mclo.gs](https://mclo.gs). __Please always upload your server log, even if you can't see any errors.__ + label: Server log + description: Upload the complete server log here. Alternatively, you can also upload your log to sites such as [pastebin](https://pastebin.com) or [mclo.gs](https://mclo.gs) and link to it here. __Please always upload your server log, even if you can't see any errors.__ + placeholder: Drag & drop latest.log here validations: required: true - type: textarea attributes: label: Errors - description: If any errors or stacktraces appeared in the console, paste them here. + description: If any errors or stacktraces appeared in the console, post them here. + placeholder: Paste error here render: log validations: required: false From 991cb290f85e30fff23f089a413aa734191091f9 Mon Sep 17 00:00:00 2001 From: NichtStudioCode <51272202+NichtStudioCode@users.noreply.github.com> Date: Mon, 6 Nov 2023 18:13:58 +0100 Subject: [PATCH 05/12] Fix #305 --- nova/src/main/kotlin/xyz/xenondevs/nova/util/AdvancementUtils.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/nova/src/main/kotlin/xyz/xenondevs/nova/util/AdvancementUtils.kt b/nova/src/main/kotlin/xyz/xenondevs/nova/util/AdvancementUtils.kt index fd79464975d..340e12dd3e9 100644 --- a/nova/src/main/kotlin/xyz/xenondevs/nova/util/AdvancementUtils.kt +++ b/nova/src/main/kotlin/xyz/xenondevs/nova/util/AdvancementUtils.kt @@ -77,6 +77,7 @@ fun obtainNovaItemsAdvancement( for (item in items) { val criterionName = "obtain_${item.id.name}" addCriterion(criterionName, createObtainNovaItemCriterion(item)) + criteriaNames += criterionName } if (requireAll) { From 94bb9804cf466f69609fa6fc5f3d08a7c818d1db Mon Sep 17 00:00:00 2001 From: NichtStudioCode <51272202+NichtStudioCode@users.noreply.github.com> Date: Mon, 6 Nov 2023 18:18:22 +0100 Subject: [PATCH 06/12] Fix #302 --- .../nova/transformer/patch/item/EnchantmentPatches.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nova/src/main/kotlin/xyz/xenondevs/nova/transformer/patch/item/EnchantmentPatches.kt b/nova/src/main/kotlin/xyz/xenondevs/nova/transformer/patch/item/EnchantmentPatches.kt index 256d16afab4..0eb3337e229 100644 --- a/nova/src/main/kotlin/xyz/xenondevs/nova/transformer/patch/item/EnchantmentPatches.kt +++ b/nova/src/main/kotlin/xyz/xenondevs/nova/transformer/patch/item/EnchantmentPatches.kt @@ -22,7 +22,7 @@ private val ENCHANTMENT_MENU_SLOTS_CHANGED_LAMBDA = ReflectionUtils.getMethod( EnchantmentMenu::class, true, // not remapped - if (ServerUtils.SERVER_SOFTWARE == ServerSoftware.PAPER) "lambda\$slotsChanged\$0" else "lambda\$slotsChanged$1", + if (ServerUtils.SERVER_SOFTWARE == ServerSoftware.PURPUR) "lambda\$slotsChanged\$1" else "lambda\$slotsChanged$0", ItemStack::class, Level::class, BlockPos::class ) @@ -31,7 +31,7 @@ private val ENCHANTMENT_MENU_CLICK_MENU_BUTTON_LAMBDA = ReflectionUtils.getMetho EnchantmentMenu::class, true, // not remapped - if (ServerUtils.SERVER_SOFTWARE == ServerSoftware.PAPER) "lambda\$clickMenuButton\$1" else "lambda\$clickMenuButton$2", + if (ServerUtils.SERVER_SOFTWARE == ServerSoftware.PURPUR) "lambda\$clickMenuButton\$2" else "lambda\$clickMenuButton$1", ItemStack::class, Int::class, Player::class, Int::class, ItemStack::class, Level::class, BlockPos::class ) From 1b6dd44becc31e437a0b1aeacf9faba0e88c2f60 Mon Sep 17 00:00:00 2001 From: NichtStudioCode <51272202+NichtStudioCode@users.noreply.github.com> Date: Mon, 6 Nov 2023 18:18:29 +0100 Subject: [PATCH 07/12] Bump version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 5a65c10105d..e1edceba86f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,3 @@ -version = 0.15-alpha.6 +version = 0.15-alpha.7 kotlin.daemon.jvmargs=-Xmx2g org.gradle.jvmargs=-Xmx2g From 03abe054bac1e11b56ee7c5e73514fe9a8293ca2 Mon Sep 17 00:00:00 2001 From: NichtStudioCode <51272202+NichtStudioCode@users.noreply.github.com> Date: Sun, 12 Nov 2023 11:47:50 +0100 Subject: [PATCH 08/12] Remove RemainingItemPatches#patchCraftServerCraftItem This patch should no longer be necessary because CraftServer#craftItem indirectly calls net.minecraft.world.item.crafting.Recipe#getRemainingItems now --- .../patch/item/RemainingItemPatches.kt | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/nova/src/main/kotlin/xyz/xenondevs/nova/transformer/patch/item/RemainingItemPatches.kt b/nova/src/main/kotlin/xyz/xenondevs/nova/transformer/patch/item/RemainingItemPatches.kt index f3103f84e2a..538a6b2e3e3 100644 --- a/nova/src/main/kotlin/xyz/xenondevs/nova/transformer/patch/item/RemainingItemPatches.kt +++ b/nova/src/main/kotlin/xyz/xenondevs/nova/transformer/patch/item/RemainingItemPatches.kt @@ -9,7 +9,6 @@ import net.minecraft.world.item.crafting.Recipe import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity import net.minecraft.world.level.block.entity.BrewingStandBlockEntity import org.bukkit.craftbukkit.v1_20_R2.CraftServer -import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack import org.bukkit.craftbukkit.v1_20_R2.util.CraftMagicNumbers import org.bukkit.inventory.ItemStack import org.objectweb.asm.Opcodes @@ -47,7 +46,6 @@ internal object RemainingItemPatches : MultiTransformer( patchRecipeGetRemainingItems() patchAbstractFurnaceBlockEntityServerTick() - patchCraftServerCraftItem() } /** @@ -129,26 +127,6 @@ internal object RemainingItemPatches : MultiTransformer( ) } - /** - * Replaces this range: https://i.imgur.com/HTZXwHp.png with a call to [getRemainingBukkitItemStack]. - */ - private fun patchCraftServerCraftItem() { - val methodNode = VirtualClassPath[CraftServer::craftItem] - methodNode.localVariables.clear() - methodNode.replaceEveryRange( - { it.opcode == Opcodes.INVOKEVIRTUAL && (it as MethodInsnNode).calls(MojangStack::getItem) }, - { it.opcode == Opcodes.INVOKESTATIC && (it as MethodInsnNode).calls(CraftItemStack::asBukkitCopy) }, - 0, 3, - { - invokeStatic(::getRemainingBukkitItemStack) - aLoad(1) // ItemStack[] - swap() - iLoad(12) // for loop index - swap() - } - ) - } - @JvmStatic fun hasCraftingRemainingItem(itemStack: MojangStack): Boolean { val novaItem = itemStack.novaItem From 1bf4ee820bda5f94c752c4d203f4ea1fc763a776 Mon Sep 17 00:00:00 2001 From: NichtStudioCode <51272202+NichtStudioCode@users.noreply.github.com> Date: Sun, 12 Nov 2023 11:54:14 +0100 Subject: [PATCH 09/12] Add overrides for new bukkit enchantment methods --- .../xyz/xenondevs/nova/item/enchantment/Enchantment.kt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/nova/src/main/kotlin/xyz/xenondevs/nova/item/enchantment/Enchantment.kt b/nova/src/main/kotlin/xyz/xenondevs/nova/item/enchantment/Enchantment.kt index 4912e85ac15..4af721db9cc 100644 --- a/nova/src/main/kotlin/xyz/xenondevs/nova/item/enchantment/Enchantment.kt +++ b/nova/src/main/kotlin/xyz/xenondevs/nova/item/enchantment/Enchantment.kt @@ -106,15 +106,17 @@ sealed interface Enchantment { return object : BukkitEnchantment(key) { - override fun translationKey() = enchantment.localizedName - override fun getName() = key.toString() + override fun translationKey(): String = enchantment.localizedName + override fun getName(): String = key.toString() override fun getMaxLevel(): Int = enchantment.maxLevel override fun getStartLevel(): Int = enchantment.minLevel override fun getItemTarget(): EnchantmentTarget = EnchantmentTarget.ALL override fun isTreasure(): Boolean = enchantment.isTreasure override fun isCursed(): Boolean = enchantment.isCurse - override fun isTradeable() = enchantment.isTradeable + override fun isTradeable(): Boolean = enchantment.isTradeable override fun isDiscoverable() = enchantment.isTableDiscoverable + override fun getMinModifiedCost(level: Int): Int = enchantment.getTableLevelRequirement(level).first + override fun getMaxModifiedCost(level: Int): Int = enchantment.getTableLevelRequirement(level).last override fun getRarity(): EnchantmentRarity = EnchantmentRarity.COMMON // TODO: find closest match override fun getDamageIncrease(level: Int, entityCategory: EntityCategory): Float = 0f override fun getActiveSlots(): Set = emptySet() // TODO From 2214284b41ffa28bcb1d2e778e049863f4684c6b Mon Sep 17 00:00:00 2001 From: NichtStudioCode <51272202+NichtStudioCode@users.noreply.github.com> Date: Sun, 12 Nov 2023 13:10:14 +0100 Subject: [PATCH 10/12] Fix NovaItem#hasBehavior only looking for exact matches --- nova/src/main/kotlin/xyz/xenondevs/nova/item/NovaItem.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/src/main/kotlin/xyz/xenondevs/nova/item/NovaItem.kt b/nova/src/main/kotlin/xyz/xenondevs/nova/item/NovaItem.kt index aef40ac1559..e07e5fa6ef7 100644 --- a/nova/src/main/kotlin/xyz/xenondevs/nova/item/NovaItem.kt +++ b/nova/src/main/kotlin/xyz/xenondevs/nova/item/NovaItem.kt @@ -186,7 +186,7 @@ class NovaItem internal constructor( * Checks whether this [NovaItem] has an [ItemBehavior] of the specified class [behavior], or a subclass of it. */ fun hasBehavior(type: KClass): Boolean = - behaviors.any { it::class == type } + behaviors.any { type.isSuperclassOf(it::class) } /** * Gets the first [ItemBehavior] that is an instance of [T], or null if there is none. From 28f3382a4e0610b0814993e169f71777af1c3bf4 Mon Sep 17 00:00:00 2001 From: NichtStudioCode <51272202+NichtStudioCode@users.noreply.github.com> Date: Sun, 12 Nov 2023 13:10:33 +0100 Subject: [PATCH 11/12] Fix anvil logic ignoring Nova enchantments --- .../nova/item/behavior/Enchantable.kt | 80 +++++++++++++++++ .../patch/item/AnvilResultPatch.kt | 87 +++++++++++-------- 2 files changed, 131 insertions(+), 36 deletions(-) diff --git a/nova/src/main/kotlin/xyz/xenondevs/nova/item/behavior/Enchantable.kt b/nova/src/main/kotlin/xyz/xenondevs/nova/item/behavior/Enchantable.kt index b0a8e67471f..cfb019db31a 100644 --- a/nova/src/main/kotlin/xyz/xenondevs/nova/item/behavior/Enchantable.kt +++ b/nova/src/main/kotlin/xyz/xenondevs/nova/item/behavior/Enchantable.kt @@ -3,6 +3,7 @@ package xyz.xenondevs.nova.item.behavior import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.ListTag import net.minecraft.nbt.StringTag +import net.minecraft.world.item.Items import org.bukkit.inventory.meta.EnchantmentStorageMeta import xyz.xenondevs.commons.collections.isNotNullOrEmpty import xyz.xenondevs.commons.provider.Provider @@ -90,6 +91,9 @@ interface Enchantable { fun isEnchanted(itemStack: BukkitStack): Boolean = isEnchanted(itemStack.nmsCopy) + fun isEnchantedBook(itemStack: BukkitStack): Boolean = + isEnchantedBook(itemStack.nmsCopy) + fun hasStoredEnchantments(itemStack: BukkitStack): Boolean = hasStoredEnchantments(itemStack.nmsCopy) @@ -99,6 +103,9 @@ interface Enchantable { fun getStoredEnchantments(itemStack: BukkitStack): Map = getStoredEnchantments(itemStack.nmsCopy) + fun getEnchantmentsOrStoredEnchantments(itemStack: BukkitStack): Map = + getEnchantmentsOrStoredEnchantments(itemStack.nmsCopy) + fun setEnchantments(itemStack: BukkitStack, enchantments: Map) { // clear vanilla enchants for ((enchantment, _) in itemStack.enchantments) @@ -116,6 +123,14 @@ interface Enchantable { setEnchantments(STORED_ENCHANTMENTS_CBF, { ench, lvl -> meta.addStoredEnchant(ench, lvl, true) }, itemStack, enchantments) } + fun setEnchantmentsOrStoredEnchantments(itemStack: BukkitStack, enchantments: Map) { + if (isEnchantedBook(itemStack)) { + setStoredEnchantments(itemStack, enchantments) + } else { + setEnchantments(itemStack, enchantments) + } + } + private fun setEnchantments(cbfName: String, addVanillaEnchantment: (BukkitEnchantment, Int) -> Unit, itemStack: BukkitStack, enchantments: Map) { val novaEnchantmentsMap = HashMap() for ((enchantment, level) in enchantments) { @@ -141,6 +156,14 @@ interface Enchantable { addEnchantment(STORED_ENCHANTMENTS_CBF, { ench, lvl -> meta.addStoredEnchant(ench, lvl, true) }, itemStack, enchantment, level) } + fun addEnchantmentOrStoredEnchantment(itemStack: BukkitStack, enchantment: Enchantment, level: Int) { + if (isEnchantedBook(itemStack)) { + addStoredEnchantment(itemStack, enchantment, level) + } else { + addEnchantment(itemStack, enchantment, level) + } + } + private fun addEnchantment(cbfName: String, addVanillaEnchantment: (BukkitEnchantment, Int) -> Unit, itemStack: BukkitStack, enchantment: Enchantment, level: Int) { if (enchantment is VanillaEnchantment) { addVanillaEnchantment(Enchantment.asBukkitEnchantment(enchantment), level) @@ -157,6 +180,14 @@ interface Enchantable { removeEnchantment(STORED_ENCHANTMENTS_CBF, meta::removeStoredEnchant, itemStack, enchantment) } + fun removeEnchantmentOrStoredEnchantment(itemStack: BukkitStack, enchantment: Enchantment) { + if (isEnchantedBook(itemStack)) { + removeStoredEnchantment(itemStack, enchantment) + } else { + removeEnchantment(itemStack, enchantment) + } + } + private fun removeEnchantment(cbfName: String, removeVanillaEnchantment: (BukkitEnchantment) -> Unit, itemStack: BukkitStack, enchantment: Enchantment) { if (enchantment is VanillaEnchantment) { removeVanillaEnchantment(Enchantment.asBukkitEnchantment(enchantment)) @@ -178,6 +209,14 @@ interface Enchantable { itemStack.novaCompoundOrNull?.remove("nova", STORED_ENCHANTMENTS_CBF) } + fun removeAllEnchantmentsOrStoredEnchantments(itemStack: BukkitStack) { + if (isEnchantedBook(itemStack)) { + removeAllStoredEnchantments(itemStack) + } else { + removeAllEnchantments(itemStack) + } + } + // -- Mojang ItemStack -- @JvmStatic @@ -191,6 +230,9 @@ interface Enchantable { fun isEnchanted(itemStack: MojangStack): Boolean = isEnchanted(ENCHANTMENTS_CBF, ENCHANTMENTS_NBT, itemStack) + fun isEnchantedBook(itemStack: MojangStack): Boolean = + itemStack.novaItem == null && itemStack.item == Items.ENCHANTED_BOOK + fun hasStoredEnchantments(itemStack: MojangStack): Boolean = isEnchanted(STORED_ENCHANTMENTS_CBF, STORED_ENCHANTMENTS_NBT, itemStack) @@ -206,6 +248,12 @@ interface Enchantable { fun getStoredEnchantments(itemStack: MojangStack): Map = getEnchantments(STORED_ENCHANTMENTS_CBF, STORED_ENCHANTMENTS_NBT, itemStack) + fun getEnchantmentsOrStoredEnchantments(itemStack: MojangStack): Map { + if (isEnchantedBook(itemStack)) + return getStoredEnchantments(itemStack) + return getEnchantments(itemStack) + } + private fun getEnchantments(cbfName: String, nbtName: String, itemStack: MojangStack): Map { val enchantments = HashMap() itemStack.tag?.getOrNull(nbtName)?.asSequence() @@ -226,6 +274,14 @@ interface Enchantable { fun setStoredEnchantments(itemStack: MojangStack, enchantments: Map) = setEnchantments(STORED_ENCHANTMENTS_CBF, STORED_ENCHANTMENTS_NBT, itemStack, enchantments) + fun setEnchantmentsOrStoredEnchantments(itemStack: MojangStack, enchantments: Map) { + if (isEnchantedBook(itemStack)) { + setStoredEnchantments(itemStack, enchantments) + } else { + setEnchantments(itemStack, enchantments) + } + } + private fun setEnchantments(cbfName: String, nbtName: String, itemStack: MojangStack, enchantments: Map) { val vanillaEnchantmentsTag = ListTag() val novaEnchantmentsMap = HashMap() @@ -261,6 +317,14 @@ interface Enchantable { fun addStoredEnchantment(itemStack: MojangStack, enchantment: Enchantment, level: Int) = addEnchantment(STORED_ENCHANTMENTS_CBF, STORED_ENCHANTMENTS_NBT, itemStack, enchantment, level) + fun addEnchantmentOrStoredEnchantment(itemStack: MojangStack, enchantment: Enchantment, level: Int) { + if (isEnchantedBook(itemStack)) { + addStoredEnchantment(itemStack, enchantment, level) + } else { + addEnchantment(itemStack, enchantment, level) + } + } + private fun addEnchantment(cbfName: String, nbtName: String, itemStack: MojangStack, enchantment: Enchantment, level: Int) { if (enchantment is VanillaEnchantment) { val id = enchantment.id.toString() @@ -281,6 +345,14 @@ interface Enchantable { fun removeStoredEnchantment(itemStack: MojangStack, enchantment: Enchantment) = removeEnchantment(STORED_ENCHANTMENTS_CBF, STORED_ENCHANTMENTS_NBT, itemStack, enchantment) + fun removeEnchantmentOrStoredEnchantment(itemStack: MojangStack, enchantment: Enchantment) { + if (isEnchantedBook(itemStack)) { + removeStoredEnchantment(itemStack, enchantment) + } else { + removeEnchantment(itemStack, enchantment) + } + } + private fun removeEnchantment(cbfName: String, nbtName: String, itemStack: MojangStack, enchantment: Enchantment) { if (enchantment is VanillaEnchantment) { val id = enchantment.id.toString() @@ -297,6 +369,14 @@ interface Enchantable { fun removeAllStoredEnchantments(itemStack: MojangStack) = removeAllEnchantments(STORED_ENCHANTMENTS_CBF, STORED_ENCHANTMENTS_NBT, itemStack) + fun removeAllEnchantmentsOrStoredEnchantments(itemStack: MojangStack) { + if (isEnchantedBook(itemStack)) { + removeAllStoredEnchantments(itemStack) + } else { + removeAllEnchantments(itemStack) + } + } + private fun removeAllEnchantments(cbfName: String, nbtName: String, itemStack: MojangStack) { itemStack.tag?.remove(nbtName) itemStack.novaCompoundOrNull?.remove("nova", cbfName) diff --git a/nova/src/main/kotlin/xyz/xenondevs/nova/transformer/patch/item/AnvilResultPatch.kt b/nova/src/main/kotlin/xyz/xenondevs/nova/transformer/patch/item/AnvilResultPatch.kt index 607727facae..34e5f0868e0 100644 --- a/nova/src/main/kotlin/xyz/xenondevs/nova/transformer/patch/item/AnvilResultPatch.kt +++ b/nova/src/main/kotlin/xyz/xenondevs/nova/transformer/patch/item/AnvilResultPatch.kt @@ -5,11 +5,8 @@ import net.minecraft.server.level.ServerPlayer import net.minecraft.world.Container import net.minecraft.world.entity.player.Player import net.minecraft.world.inventory.AnvilMenu -import net.minecraft.world.item.EnchantedBookItem import net.minecraft.world.item.ItemStack -import net.minecraft.world.item.Items import net.minecraft.world.item.enchantment.Enchantment.Rarity.* -import net.minecraft.world.item.enchantment.EnchantmentHelper import org.bukkit.event.inventory.PrepareAnvilEvent import org.bukkit.inventory.InventoryView import xyz.xenondevs.bytebase.asm.buildInsnList @@ -18,6 +15,9 @@ import xyz.xenondevs.nova.item.behavior.Damageable.Companion.getMaxDurability import xyz.xenondevs.nova.item.behavior.Damageable.Companion.isDamageable import xyz.xenondevs.nova.item.behavior.Damageable.Companion.isValidRepairItem import xyz.xenondevs.nova.item.behavior.Damageable.Companion.setDamage +import xyz.xenondevs.nova.item.behavior.Enchantable +import xyz.xenondevs.nova.item.enchantment.Enchantment +import xyz.xenondevs.nova.registry.NovaRegistries import xyz.xenondevs.nova.transformer.MethodTransformer import xyz.xenondevs.nova.util.bukkitMirror import xyz.xenondevs.nova.util.callEvent @@ -28,6 +28,7 @@ import xyz.xenondevs.nova.util.reflection.ReflectionRegistry import kotlin.math.max import kotlin.math.min +// fixme: when shift-clicking items into the anvil menu the result will not be shown client-side @Suppress("unused") internal object AnvilResultPatch : MethodTransformer(AnvilMenu::createResult) { @@ -46,9 +47,9 @@ internal object AnvilResultPatch : MethodTransformer(AnvilMenu::createResult) { @JvmStatic fun createResult(menu: AnvilMenu, inputSlots: Container, player: Player) { - val inputStack = inputSlots.getItem(0) + val primaryStack = inputSlots.getItem(0) - if (inputStack.isEmpty) { + if (primaryStack.isEmpty) { callPrepareAnvilEvent(menu.bukkitView, ItemStack.EMPTY) menu.cost.set(-1) return @@ -56,15 +57,15 @@ internal object AnvilResultPatch : MethodTransformer(AnvilMenu::createResult) { menu.repairItemCountCost = 0 - var resultStack = inputStack.copy() - val secondStack = inputSlots.getItem(1) + var resultStack = primaryStack.copy() + val secondaryStack = inputSlots.getItem(1) var extraCost = 0 - if (!secondStack.isEmpty) { - if (isDamageable(inputStack) && isValidRepairItem(inputStack, secondStack)) { + if (!secondaryStack.isEmpty) { + if (isDamageable(primaryStack) && isValidRepairItem(primaryStack, secondaryStack)) { // - val maxDurability = getMaxDurability(inputStack) - var damageValue = getDamage(inputStack) + val maxDurability = getMaxDurability(primaryStack) + var damageValue = getDamage(primaryStack) var repairValue = min(damageValue, maxDurability / 4) if (repairValue <= 0) { @@ -74,7 +75,7 @@ internal object AnvilResultPatch : MethodTransformer(AnvilMenu::createResult) { } var itemsUsed = 0 - while (repairValue > 0 && itemsUsed < secondStack.count) { + while (repairValue > 0 && itemsUsed < secondaryStack.count) { itemsUsed++ extraCost++ @@ -86,22 +87,24 @@ internal object AnvilResultPatch : MethodTransformer(AnvilMenu::createResult) { menu.repairItemCountCost = itemsUsed // } else { - val isEnchantedBook = secondStack.item == Items.ENCHANTED_BOOK - && EnchantedBookItem.getEnchantments(secondStack).isNotEmpty() + val isPrimaryEnchantedBook = Enchantable.isEnchantedBook(primaryStack) + val isSecondaryEnchantedBook = Enchantable.isEnchantedBook(secondaryStack) - if (!isEnchantedBook && (!isSameItemType(inputStack, secondStack) || !isDamageable(inputStack))) { + if (!isSecondaryEnchantedBook && (!isSameItemType(primaryStack, secondaryStack) || !isDamageable(primaryStack))) { callPrepareAnvilEvent(menu.bukkitView, ItemStack.EMPTY) menu.cost.set(-1) return } + // assert secondaryStack is enchanted book or the same item type as primaryStack + // - if (!isEnchantedBook && isDamageable(inputStack)) { - val inputStackMaxDurability = getMaxDurability(inputStack) - val inputStackDamage = getDamage(inputStack) + if (!isSecondaryEnchantedBook && isDamageable(primaryStack)) { + val inputStackMaxDurability = getMaxDurability(primaryStack) + val inputStackDamage = getDamage(primaryStack) val firstDurability = inputStackMaxDurability - inputStackDamage - val secondDurability = getMaxDurability(secondStack) - getDamage(secondStack) + val secondDurability = getMaxDurability(secondaryStack) - getDamage(secondaryStack) val resultDurability = firstDurability + secondDurability + (inputStackMaxDurability * 12 / 100) val resultDamage = inputStackMaxDurability - max(0, resultDurability) @@ -116,11 +119,14 @@ internal object AnvilResultPatch : MethodTransformer(AnvilMenu::createResult) { var incompatibleEnchantments = false var hasChanged = false - val enchantments = EnchantmentHelper.getEnchantments(inputStack) - val extraEnchantments = EnchantmentHelper.getEnchantments(secondStack) + val enchantments = Enchantable.getEnchantmentsOrStoredEnchantments(primaryStack).toMutableMap() + val extraEnchantments = Enchantable.getEnchantmentsOrStoredEnchantments(secondaryStack) for ((enchantment, level) in extraEnchantments) { - var isCompatible = enchantment.canEnchant(inputStack) || player.abilities.instabuild || inputStack.item == Items.ENCHANTED_BOOK + var isCompatible = player.abilities.instabuild + || isPrimaryEnchantedBook + || canEnchant(primaryStack, enchantment) + for (previousEnchantment in enchantments.keys) { if (previousEnchantment != enchantment && !enchantment.isCompatibleWith(previousEnchantment)) { isCompatible = false @@ -134,16 +140,19 @@ internal object AnvilResultPatch : MethodTransformer(AnvilMenu::createResult) { enchantments[enchantment] = newLevel - val costMultiplier = when (enchantment.rarity) { - COMMON -> 1 - UNCOMMON -> 2 - RARE -> 4 - VERY_RARE -> 8 - }.let { if (isEnchantedBook) max(1, it / 2) else it } + val rarity = enchantment.rarity + var costMultiplier = when { + rarity > COMMON.weight -> 1 + rarity > UNCOMMON.weight -> 2 + rarity > RARE.weight -> 4 + else -> 8 + } + if (isSecondaryEnchantedBook) + costMultiplier = max(1, costMultiplier / 2) extraCost += costMultiplier * level - if (inputStack.count > 1) { + if (primaryStack.count > 1) { extraCost = menu.maximumRepairCost } @@ -157,7 +166,7 @@ internal object AnvilResultPatch : MethodTransformer(AnvilMenu::createResult) { return } - EnchantmentHelper.setEnchantments(enchantments, resultStack) + Enchantable.setEnchantmentsOrStoredEnchantments(resultStack, enchantments) // } } @@ -165,19 +174,19 @@ internal object AnvilResultPatch : MethodTransformer(AnvilMenu::createResult) { // var renamed = false if (menu.itemName.isNullOrBlank()) { - if (inputStack.hasCustomHoverName()) { + if (primaryStack.hasCustomHoverName()) { renamed = true extraCost += 1 resultStack.resetHoverName() } - } else if (menu.itemName != getHoverName(player, inputStack)) { + } else if (menu.itemName != getHoverName(player, primaryStack)) { renamed = true extraCost += 1 resultStack.hoverName = menu.itemName?.let(Component::literal) } // // - var totalCost = inputStack.baseRepairCost + secondStack.baseRepairCost + extraCost + var totalCost = primaryStack.baseRepairCost + secondaryStack.baseRepairCost + extraCost if (extraCost == 0) { resultStack = ItemStack.EMPTY @@ -192,10 +201,10 @@ internal object AnvilResultPatch : MethodTransformer(AnvilMenu::createResult) { resultStack = ItemStack.EMPTY } else { // calculate base repair cost for new item - var resultRepairCost = inputStack.baseRepairCost + var resultRepairCost = primaryStack.baseRepairCost - if (!secondStack.isEmpty && resultRepairCost < secondStack.baseRepairCost) { - resultRepairCost = secondStack.baseRepairCost + if (!secondaryStack.isEmpty && resultRepairCost < secondaryStack.baseRepairCost) { + resultRepairCost = secondaryStack.baseRepairCost } if (!renamed || extraCost > 1) { @@ -234,4 +243,10 @@ internal object AnvilResultPatch : MethodTransformer(AnvilMenu::createResult) { event.inventory.setItem(2, event.result) } + private fun canEnchant(itemStack: ItemStack, enchantment: Enchantment): Boolean { + return NovaRegistries.ENCHANTMENT_CATEGORY.any { category -> + enchantment in category.enchantments && category.canEnchant(itemStack) + } + } + } \ No newline at end of file From eeb2d60056798e5bda296629a2503570dfe7cf06 Mon Sep 17 00:00:00 2001 From: NichtStudioCode <51272202+NichtStudioCode@users.noreply.github.com> Date: Sun, 12 Nov 2023 13:11:13 +0100 Subject: [PATCH 12/12] Bump version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index e1edceba86f..087a189cc65 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,3 @@ -version = 0.15-alpha.7 +version = 0.15-alpha.8 kotlin.daemon.jvmargs=-Xmx2g org.gradle.jvmargs=-Xmx2g