diff --git a/build.gradle.kts b/build.gradle.kts index f7a8d1fb..36e62bf5 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,7 +3,7 @@ plugins { `java-library` `maven-publish` kotlin("jvm") version "1.9.20" - id("com.github.johnrengelman.shadow") version "8.0.0" + id("io.github.goooler.shadow") version "8.1.7" id("com.willfp.libreforge-gradle-plugin") version "1.0.0" } @@ -26,13 +26,14 @@ dependencies { implementation(project(":eco-core:core-nms:v1_20_R1")) implementation(project(":eco-core:core-nms:v1_20_R2")) implementation(project(":eco-core:core-nms:v1_20_R3", configuration = "reobf")) + implementation(project(":eco-core:core-nms:v1_20_6", configuration = "reobf")) } allprojects { apply(plugin = "java") apply(plugin = "kotlin") apply(plugin = "maven-publish") - apply(plugin = "com.github.johnrengelman.shadow") + apply(plugin = "io.github.goooler.shadow") repositories { mavenLocal() @@ -47,17 +48,12 @@ allprojects { } dependencies { - compileOnly("com.willfp:eco:6.67.1") + compileOnly("com.willfp:eco:6.70.0") compileOnly("org.jetbrains:annotations:23.0.0") compileOnly("org.jetbrains.kotlin:kotlin-stdlib:1.9.20") compileOnly("com.github.ben-manes.caffeine:caffeine:3.1.5") } - java { - withSourcesJar() - toolchain.languageVersion.set(JavaLanguageVersion.of(17)) - } - tasks { shadowJar { relocate("com.willfp.libreforge.loader", "com.willfp.ecoenchants.libreforge.loader") @@ -69,6 +65,12 @@ allprojects { } } + java { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + withSourcesJar() + } + compileJava { options.isDeprecation = true options.encoding = "UTF-8" @@ -91,3 +93,10 @@ allprojects { } } } + +// Root is Java 21 to support 1.20.6+, rest use Java 17 +java { + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 + withSourcesJar() +} diff --git a/eco-core/core-nms/build.gradle.kts b/eco-core/core-nms/build.gradle.kts index 6765eca3..d15ed517 100644 --- a/eco-core/core-nms/build.gradle.kts +++ b/eco-core/core-nms/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("io.papermc.paperweight.userdev") version "1.5.3" apply false + id("io.papermc.paperweight.userdev") version "1.6.2" apply false } diff --git a/eco-core/core-nms/v1_17_R1/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_17_R1/HideStoredEnchants.kt b/eco-core/core-nms/v1_17_R1/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_17_R1/HideStoredEnchants.kt new file mode 100644 index 00000000..71d3df5c --- /dev/null +++ b/eco-core/core-nms/v1_17_R1/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_17_R1/HideStoredEnchants.kt @@ -0,0 +1,19 @@ +package com.willfp.ecoenchants.proxy.v1_17_R1 + +import com.willfp.eco.core.fast.FastItemStack +import com.willfp.ecoenchants.display.HideStoredEnchantsProxy +import org.bukkit.inventory.ItemFlag + +class HideStoredEnchants: HideStoredEnchantsProxy { + override fun hideStoredEnchants(fis: FastItemStack) { + fis.addItemFlags(ItemFlag.HIDE_POTION_EFFECTS) + } + + override fun areStoredEnchantsHidden(fis: FastItemStack): Boolean { + return fis.hasItemFlag(ItemFlag.HIDE_POTION_EFFECTS) + } + + override fun showStoredEnchants(fis: FastItemStack) { + fis.removeItemFlags(ItemFlag.HIDE_POTION_EFFECTS) + } +} diff --git a/eco-core/core-nms/v1_18_R1/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_18_R1/HideStoredEnchants.kt b/eco-core/core-nms/v1_18_R1/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_18_R1/HideStoredEnchants.kt new file mode 100644 index 00000000..5f452fb9 --- /dev/null +++ b/eco-core/core-nms/v1_18_R1/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_18_R1/HideStoredEnchants.kt @@ -0,0 +1,19 @@ +package com.willfp.ecoenchants.proxy.v1_18_R1 + +import com.willfp.eco.core.fast.FastItemStack +import com.willfp.ecoenchants.display.HideStoredEnchantsProxy +import org.bukkit.inventory.ItemFlag + +class HideStoredEnchants: HideStoredEnchantsProxy { + override fun hideStoredEnchants(fis: FastItemStack) { + fis.addItemFlags(ItemFlag.HIDE_POTION_EFFECTS) + } + + override fun areStoredEnchantsHidden(fis: FastItemStack): Boolean { + return fis.hasItemFlag(ItemFlag.HIDE_POTION_EFFECTS) + } + + override fun showStoredEnchants(fis: FastItemStack) { + fis.removeItemFlags(ItemFlag.HIDE_POTION_EFFECTS) + } +} diff --git a/eco-core/core-nms/v1_18_R2/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_18_R2/HideStoredEnchants.kt b/eco-core/core-nms/v1_18_R2/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_18_R2/HideStoredEnchants.kt new file mode 100644 index 00000000..2e8ba9ac --- /dev/null +++ b/eco-core/core-nms/v1_18_R2/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_18_R2/HideStoredEnchants.kt @@ -0,0 +1,19 @@ +package com.willfp.ecoenchants.proxy.v1_18_R2 + +import com.willfp.eco.core.fast.FastItemStack +import com.willfp.ecoenchants.display.HideStoredEnchantsProxy +import org.bukkit.inventory.ItemFlag + +class HideStoredEnchants: HideStoredEnchantsProxy { + override fun hideStoredEnchants(fis: FastItemStack) { + fis.addItemFlags(ItemFlag.HIDE_POTION_EFFECTS) + } + + override fun areStoredEnchantsHidden(fis: FastItemStack): Boolean { + return fis.hasItemFlag(ItemFlag.HIDE_POTION_EFFECTS) + } + + override fun showStoredEnchants(fis: FastItemStack) { + fis.removeItemFlags(ItemFlag.HIDE_POTION_EFFECTS) + } +} diff --git a/eco-core/core-nms/v1_19_R1/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_19_R1/HideStoredEnchants.kt b/eco-core/core-nms/v1_19_R1/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_19_R1/HideStoredEnchants.kt new file mode 100644 index 00000000..3239eedc --- /dev/null +++ b/eco-core/core-nms/v1_19_R1/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_19_R1/HideStoredEnchants.kt @@ -0,0 +1,19 @@ +package com.willfp.ecoenchants.proxy.v1_19_R1 + +import com.willfp.eco.core.fast.FastItemStack +import com.willfp.ecoenchants.display.HideStoredEnchantsProxy +import org.bukkit.inventory.ItemFlag + +class HideStoredEnchants: HideStoredEnchantsProxy { + override fun hideStoredEnchants(fis: FastItemStack) { + fis.addItemFlags(ItemFlag.HIDE_POTION_EFFECTS) + } + + override fun areStoredEnchantsHidden(fis: FastItemStack): Boolean { + return fis.hasItemFlag(ItemFlag.HIDE_POTION_EFFECTS) + } + + override fun showStoredEnchants(fis: FastItemStack) { + fis.removeItemFlags(ItemFlag.HIDE_POTION_EFFECTS) + } +} diff --git a/eco-core/core-nms/v1_19_R2/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_19_R2/HideStoredEnchants.kt b/eco-core/core-nms/v1_19_R2/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_19_R2/HideStoredEnchants.kt new file mode 100644 index 00000000..2a6cc6a0 --- /dev/null +++ b/eco-core/core-nms/v1_19_R2/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_19_R2/HideStoredEnchants.kt @@ -0,0 +1,19 @@ +package com.willfp.ecoenchants.proxy.v1_19_R2 + +import com.willfp.eco.core.fast.FastItemStack +import com.willfp.ecoenchants.display.HideStoredEnchantsProxy +import org.bukkit.inventory.ItemFlag + +class HideStoredEnchants: HideStoredEnchantsProxy { + override fun hideStoredEnchants(fis: FastItemStack) { + fis.addItemFlags(ItemFlag.HIDE_POTION_EFFECTS) + } + + override fun areStoredEnchantsHidden(fis: FastItemStack): Boolean { + return fis.hasItemFlag(ItemFlag.HIDE_POTION_EFFECTS) + } + + override fun showStoredEnchants(fis: FastItemStack) { + fis.removeItemFlags(ItemFlag.HIDE_POTION_EFFECTS) + } +} diff --git a/eco-core/core-nms/v1_19_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_19_R3/HideStoredEnchants.kt b/eco-core/core-nms/v1_19_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_19_R3/HideStoredEnchants.kt new file mode 100644 index 00000000..c4b52273 --- /dev/null +++ b/eco-core/core-nms/v1_19_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_19_R3/HideStoredEnchants.kt @@ -0,0 +1,19 @@ +package com.willfp.ecoenchants.proxy.v1_19_R3 + +import com.willfp.eco.core.fast.FastItemStack +import com.willfp.ecoenchants.display.HideStoredEnchantsProxy +import org.bukkit.inventory.ItemFlag + +class HideStoredEnchants: HideStoredEnchantsProxy { + override fun hideStoredEnchants(fis: FastItemStack) { + fis.addItemFlags(ItemFlag.HIDE_POTION_EFFECTS) + } + + override fun areStoredEnchantsHidden(fis: FastItemStack): Boolean { + return fis.hasItemFlag(ItemFlag.HIDE_POTION_EFFECTS) + } + + override fun showStoredEnchants(fis: FastItemStack) { + fis.removeItemFlags(ItemFlag.HIDE_POTION_EFFECTS) + } +} diff --git a/eco-core/core-nms/v1_20_6/build.gradle.kts b/eco-core/core-nms/v1_20_6/build.gradle.kts new file mode 100644 index 00000000..517a56f6 --- /dev/null +++ b/eco-core/core-nms/v1_20_6/build.gradle.kts @@ -0,0 +1,28 @@ +plugins { + id("io.papermc.paperweight.userdev") +} + +group = "com.willfp" +version = rootProject.version + +dependencies { + paperweight.paperDevBundle("1.20.6-R0.1-SNAPSHOT") +} + +tasks { + build { + dependsOn(reobfJar) + } + + java { + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 + withSourcesJar() + } + + compileKotlin { + kotlinOptions { + jvmTarget = "21" + } + } +} diff --git a/eco-core/core-nms/v1_20_6/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_6/CodecReplacer.kt b/eco-core/core-nms/v1_20_6/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_6/CodecReplacer.kt new file mode 100644 index 00000000..cea97aef --- /dev/null +++ b/eco-core/core-nms/v1_20_6/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_6/CodecReplacer.kt @@ -0,0 +1,229 @@ +package com.willfp.ecoenchants.proxy.v1_20_6 + +import com.willfp.eco.core.Prerequisite +import com.willfp.ecoenchants.CodecReplacerProxy +import com.willfp.ecoenchants.proxy.v1_20_6.registration.VanillaEcoEnchantsEnchantment +import com.willfp.ecoenchants.setStaticFinal +import net.minecraft.core.Holder +import net.minecraft.core.NonNullList +import net.minecraft.core.component.DataComponentPatch +import net.minecraft.core.component.DataComponents +import net.minecraft.core.registries.BuiltInRegistries +import net.minecraft.core.registries.Registries +import net.minecraft.nbt.CompoundTag +import net.minecraft.nbt.ListTag +import net.minecraft.network.RegistryFriendlyByteBuf +import net.minecraft.network.chat.ComponentSerialization +import net.minecraft.network.codec.ByteBufCodecs +import net.minecraft.network.codec.StreamCodec +import net.minecraft.network.protocol.game.ServerboundSetCreativeModeSlotPacket +import net.minecraft.resources.ResourceLocation +import net.minecraft.world.item.Item +import net.minecraft.world.item.ItemStack +import net.minecraft.world.item.component.CustomData +import net.minecraft.world.item.enchantment.Enchantment +import net.minecraft.world.item.enchantment.ItemEnchantments +import org.bukkit.craftbukkit.util.CraftMagicNumbers + +class CodecReplacer : CodecReplacerProxy { + override fun replaceItemCodec() { + ItemStack::class.java + .getDeclaredField("OPTIONAL_STREAM_CODEC") + .setStaticFinal(PatchedStreamCodec) + + ItemStack::class.java + .getDeclaredField("OPTIONAL_LIST_STREAM_CODEC") + .setStaticFinal( + PatchedStreamCodec.apply(ByteBufCodecs.collection { size -> + NonNullList.createWithCapacity(size) + }) + ) + + ServerboundSetCreativeModeSlotPacket.STREAM_CODEC::class.java + .getDeclaredField("val\$codec2") + .apply { + isAccessible = true + set( + ServerboundSetCreativeModeSlotPacket.STREAM_CODEC, + ItemStack.validatedStreamCodec(PatchedStreamCodec) + ) + } + } + + private object PatchedStreamCodec : StreamCodec { + private const val nbtKey = "ecoenchants:client_enchs_patch" + private const val nbtKeyShow = "ecoenchants:client_enchs_patch_show" + private const val nbtKeyGlint = "ecoenchants:client_enchs_patch_glint" + + private val itemStreamCodec = ByteBufCodecs.holderRegistry(Registries.ITEM) + + fun Enchantment.isEco() = this is VanillaEcoEnchantsEnchantment + + fun Map.toComponent(): ItemEnchantments { + val component = ItemEnchantments.Mutable(ItemEnchantments.EMPTY) + for ((enchant, level) in this) { + component.set(enchant, level) + } + return component.toImmutable() + } + + fun serialize(itemStack: ItemStack): ItemStack { + val enchantments = itemStack.get(DataComponents.ENCHANTMENTS) ?: return itemStack + + // Separate out enchantments into vanilla and custom + val vanillaEnchantments = mutableMapOf() + val customEnchantments = mutableMapOf() + + for ((holder, level) in enchantments.entrySet()) { + val enchant = holder.value() + if (enchant.isEco()) { + customEnchantments[enchant] = level + } else { + vanillaEnchantments[enchant] = level + } + } + + if (customEnchantments.isEmpty()) { + return itemStack + } + + // Only keep vanilla enchants in NBT + itemStack.set( + DataComponents.ENCHANTMENTS, + vanillaEnchantments + .toComponent() + .withTooltip(enchantments.showInTooltip) + ) + + // Override glint + val hasGlint = itemStack.get(DataComponents.ENCHANTMENT_GLINT_OVERRIDE) + itemStack.set(DataComponents.ENCHANTMENT_GLINT_OVERRIDE, true) + + // Put custom enchants in custom data + val customData = itemStack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).update { + it.remove(nbtKey) + + val tag = ListTag() + + for ((enchant, level) in customEnchantments) { + val id = BuiltInRegistries.ENCHANTMENT.getKey(enchant) ?: continue + + tag.add(CompoundTag().apply { + putString("id", id.toString()) + putInt("lvl", level) + }) + } + + it.put(nbtKey, tag) + it.putBoolean(nbtKeyShow, enchantments.showInTooltip) + if (hasGlint != null) { + it.putBoolean(nbtKeyGlint, hasGlint) + } + } + + itemStack.set(DataComponents.CUSTOM_DATA, customData) + + return itemStack + } + + fun deserialize(itemStack: ItemStack): ItemStack { + val customData = itemStack.get(DataComponents.CUSTOM_DATA) ?: return itemStack + + // Fetch enchantments from custom data + val enchantments = ItemEnchantments.Mutable( + itemStack.getOrDefault(DataComponents.ENCHANTMENTS, ItemEnchantments.EMPTY) + ) + + val customDataTag = customData.copyTag() + + customDataTag.getList(nbtKey, CraftMagicNumbers.NBT.TAG_COMPOUND) + .filterIsInstance() + .forEach { tag -> + val id = tag.getString("id") + val level = tag.getInt("lvl") + + val enchant = BuiltInRegistries.ENCHANTMENT.get( + ResourceLocation(id) + ) ?: return@forEach + + enchantments.set(enchant, level) + } + + if (enchantments.keySet().isEmpty()) { + return itemStack + } + + enchantments.showInTooltip = customDataTag.getBoolean(nbtKeyShow) + + // Remove extra data + val cleaned = customData.update { + it.remove(nbtKey) + it.remove(nbtKeyShow) + it.remove(nbtKeyGlint) + } + + // Set to item + itemStack.set(DataComponents.ENCHANTMENTS, enchantments.toImmutable()) + + // Reset glint + val hasGlint = if (customDataTag.contains(nbtKeyGlint)) { + customDataTag.getBoolean(nbtKeyGlint) + } else { + null + } + + itemStack.set(DataComponents.ENCHANTMENT_GLINT_OVERRIDE, hasGlint) + + // Set cleaned data + if (cleaned.isEmpty) { + itemStack.remove(DataComponents.CUSTOM_DATA) + } else { + itemStack.set(DataComponents.CUSTOM_DATA, cleaned) + } + + return itemStack + } + + override fun decode(buf: RegistryFriendlyByteBuf): ItemStack { + val i = buf.readVarInt() + return if (i <= 0) { + ItemStack.EMPTY + } else { + val holder: Holder = + itemStreamCodec.decode(buf) as Holder + val dataComponentPatch = + DataComponentPatch.STREAM_CODEC.decode(buf) as DataComponentPatch + + deserialize(ItemStack(holder, i, dataComponentPatch)) + } + } + + override fun encode(buf: RegistryFriendlyByteBuf, itemStack: ItemStack) { + @Suppress("SENSELESS_COMPARISON") + if (itemStack.isEmpty || itemStack.item == null) { + buf.writeVarInt(0) + } else { + val remapped = serialize(itemStack) + + buf.writeVarInt(remapped.count) + + itemStreamCodec.encode( + buf, + remapped.itemHolder + ) + + if (Prerequisite.HAS_PAPER.isMet) { + // Paper start - adventure; conditionally render translatable components + val prev = ComponentSerialization.DONT_RENDER_TRANSLATABLES.get() + try { + ComponentSerialization.DONT_RENDER_TRANSLATABLES.set(true) + DataComponentPatch.STREAM_CODEC.encode(buf, remapped.componentsPatch) + } finally { + ComponentSerialization.DONT_RENDER_TRANSLATABLES.set(prev) + } + // Paper end - adventure; conditionally render translatable components + } + } + } + } +} diff --git a/eco-core/core-nms/v1_20_6/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_6/HideStoredEnchants.kt b/eco-core/core-nms/v1_20_6/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_6/HideStoredEnchants.kt new file mode 100644 index 00000000..1744808f --- /dev/null +++ b/eco-core/core-nms/v1_20_6/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_6/HideStoredEnchants.kt @@ -0,0 +1,19 @@ +package com.willfp.ecoenchants.proxy.v1_20_6 + +import com.willfp.eco.core.fast.FastItemStack +import com.willfp.ecoenchants.display.HideStoredEnchantsProxy +import org.bukkit.inventory.ItemFlag + +class HideStoredEnchants: HideStoredEnchantsProxy { + override fun hideStoredEnchants(fis: FastItemStack) { + fis.addItemFlags(ItemFlag.HIDE_STORED_ENCHANTS) + } + + override fun areStoredEnchantsHidden(fis: FastItemStack): Boolean { + return fis.hasItemFlag(ItemFlag.HIDE_STORED_ENCHANTS) + } + + override fun showStoredEnchants(fis: FastItemStack) { + fis.removeItemFlags(ItemFlag.HIDE_STORED_ENCHANTS) + } +} diff --git a/eco-core/core-nms/v1_20_6/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_6/ModernEnchantmentRegisterer.kt b/eco-core/core-nms/v1_20_6/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_6/ModernEnchantmentRegisterer.kt new file mode 100644 index 00000000..36d1d19a --- /dev/null +++ b/eco-core/core-nms/v1_20_6/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_6/ModernEnchantmentRegisterer.kt @@ -0,0 +1,97 @@ +package com.willfp.ecoenchants.proxy.v1_20_6 + +import com.willfp.ecoenchants.enchant.EcoEnchant +import com.willfp.ecoenchants.enchant.EcoEnchants +import com.willfp.ecoenchants.enchant.impl.EcoEnchantBase +import com.willfp.ecoenchants.enchant.registration.modern.ModernEnchantmentRegistererProxy +import com.willfp.ecoenchants.proxy.v1_20_6.registration.EcoEnchantsCraftEnchantment +import com.willfp.ecoenchants.proxy.v1_20_6.registration.ModifiedVanillaCraftEnchantment +import com.willfp.ecoenchants.proxy.v1_20_6.registration.VanillaEcoEnchantsEnchantment +import net.minecraft.core.Holder +import net.minecraft.core.MappedRegistry +import net.minecraft.core.Registry +import net.minecraft.core.registries.BuiltInRegistries +import net.minecraft.world.item.ItemStack +import net.minecraft.world.item.enchantment.Enchantments +import org.bukkit.NamespacedKey +import org.bukkit.craftbukkit.CraftRegistry +import org.bukkit.craftbukkit.util.CraftNamespacedKey +import org.bukkit.enchantments.Enchantment +import java.util.IdentityHashMap +import java.util.function.BiFunction + +class ModernEnchantmentRegisterer : ModernEnchantmentRegistererProxy { + private val frozenField = MappedRegistry::class.java + .declaredFields + .filter { it.type.isPrimitive }[0] + .apply { isAccessible = true } + + private val unregisteredIntrusiveHoldersField = MappedRegistry::class.java + .declaredFields + .last { it.type == Map::class.java } + .apply { isAccessible = true } + + private val minecraftToBukkit = CraftRegistry::class.java + .getDeclaredField("minecraftToBukkit") + .apply { isAccessible = true } + + private val vanillaEnchantments = Enchantments::class.java + .declaredFields + .filter { it.type == net.minecraft.world.item.enchantment.Enchantment::class.java } + .map { it.get(null) as net.minecraft.world.item.enchantment.Enchantment } + .mapNotNull { BuiltInRegistries.ENCHANTMENT.getKey(it) } + .map { CraftNamespacedKey.fromMinecraft(it) } + .toSet() + + override fun replaceRegistry() { + val newRegistryMTB = + BiFunction { key, registry -> + val isVanilla = vanillaEnchantments.contains(key) + val eco = EcoEnchants.getByID(key.key) + + if (isVanilla) { + ModifiedVanillaCraftEnchantment(key, registry) + } else if (eco != null) { + eco as Enchantment + } else { + null + } + } + + // Update bukkit registry + minecraftToBukkit.set(org.bukkit.Registry.ENCHANTMENT, newRegistryMTB) + + // Unfreeze NMS registry + frozenField.set(BuiltInRegistries.ENCHANTMENT, false) + unregisteredIntrusiveHoldersField.set( + BuiltInRegistries.ENCHANTMENT, + IdentityHashMap>() + ) + } + + override fun register(enchant: EcoEnchantBase): Enchantment { + if (BuiltInRegistries.ENCHANTMENT.containsKey(CraftNamespacedKey.toMinecraft(enchant.enchantmentKey))) { + val nms = BuiltInRegistries.ENCHANTMENT[CraftNamespacedKey.toMinecraft(enchant.enchantmentKey)] + + if (nms != null) { + return EcoEnchantsCraftEnchantment(enchant, nms) + } else { + throw IllegalStateException("Enchantment ${enchant.id} wasn't registered") + } + } + + Registry.register(BuiltInRegistries.ENCHANTMENT, enchant.id, VanillaEcoEnchantsEnchantment(enchant)) + + return register(enchant) + } + + override fun unregister(enchant: EcoEnchant) { + /* + + You can't unregister from a minecraft registry, so we simply leave the stale reference there. + This shouldn't cause many issues in production as the bukkit registry is replaced on each reload. + + */ + } +} diff --git a/eco-core/core-nms/v1_20_6/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_6/OpenInventory.kt b/eco-core/core-nms/v1_20_6/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_6/OpenInventory.kt new file mode 100644 index 00000000..f513173d --- /dev/null +++ b/eco-core/core-nms/v1_20_6/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_6/OpenInventory.kt @@ -0,0 +1,11 @@ +package com.willfp.ecoenchants.proxy.v1_20_6 + +import com.willfp.ecoenchants.mechanics.OpenInventoryProxy +import org.bukkit.craftbukkit.entity.CraftPlayer +import org.bukkit.entity.Player + +class OpenInventory : OpenInventoryProxy { + override fun getOpenInventory(player: Player): Any { + return (player as CraftPlayer).handle.containerMenu + } +} diff --git a/eco-core/core-nms/v1_20_6/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_6/registration/EcoEnchantsCraftEnchantment.kt b/eco-core/core-nms/v1_20_6/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_6/registration/EcoEnchantsCraftEnchantment.kt new file mode 100644 index 00000000..0b3f029b --- /dev/null +++ b/eco-core/core-nms/v1_20_6/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_6/registration/EcoEnchantsCraftEnchantment.kt @@ -0,0 +1,105 @@ +package com.willfp.ecoenchants.proxy.v1_20_6.registration + +import com.willfp.eco.util.toComponent +import com.willfp.ecoenchants.display.getFormattedName +import com.willfp.ecoenchants.enchant.EcoEnchant +import com.willfp.ecoenchants.enchant.impl.EcoEnchantBase +import net.kyori.adventure.text.Component +import net.minecraft.world.item.enchantment.Enchantment +import org.bukkit.craftbukkit.enchantments.CraftEnchantment +import org.bukkit.enchantments.EnchantmentTarget +import org.bukkit.inventory.ItemStack + +class EcoEnchantsCraftEnchantment( + private val enchant: EcoEnchantBase, + nmsEnchantment: Enchantment +) : CraftEnchantment(enchant.enchantmentKey, nmsEnchantment), EcoEnchant by enchant { + init { + enchant.enchantment = this + } + + override fun onRegister() { + // Fix for hardcoded enchantments + if (plugin.isLoaded) { + enchant.onRegister() + } + } + + override fun onRemove() { + enchant.onRemove() + } + + override fun canEnchantItem(item: ItemStack): Boolean { + return enchant.canEnchantItem(item) + } + + override fun conflictsWith(other: org.bukkit.enchantments.Enchantment): Boolean { + return enchant.conflictsWith(other) + } + + override fun translationKey(): String { + return "ecoenchants:enchantment.$id" + } + + @Deprecated( + message = "getName is a legacy Spigot API", + replaceWith = ReplaceWith("this.displayName(level)") + ) + override fun getName(): String = this.id.uppercase() + override fun getMaxLevel(): Int = enchant.maximumLevel + + override fun getStartLevel(): Int = 1 + + @Deprecated( + message = "getItemTargets is an incompatible Spigot API", + replaceWith = ReplaceWith("this.targets") + ) + @Suppress("DEPRECATION") + override fun getItemTarget(): EnchantmentTarget = EnchantmentTarget.ALL + + @Deprecated( + message = "Treasure enchantments do not exist in EcoEnchants", + replaceWith = ReplaceWith("this.isEnchantable") + ) + override fun isTreasure(): Boolean = !enchant.isObtainableThroughEnchanting + + @Deprecated( + message = "Use EnchantmentType instead", + replaceWith = ReplaceWith("type.id") + ) + override fun isCursed(): Boolean { + return false + } + + override fun displayName(level: Int): Component { + return enchant.getFormattedName(level).toComponent() + } + + override fun isTradeable(): Boolean { + return enchant.isObtainableThroughTrading + } + + override fun isDiscoverable(): Boolean { + return enchant.isObtainableThroughDiscovery + } + + override fun getMinModifiedCost(level: Int): Int { + return Int.MAX_VALUE + } + + override fun getMaxModifiedCost(level: Int): Int { + return Int.MAX_VALUE + } + + override fun equals(other: Any?): Boolean { + return other is EcoEnchant && this.enchantmentKey == other.enchantmentKey + } + + override fun hashCode(): Int { + return this.enchantmentKey.hashCode() + } + + override fun toString(): String { + return "EcoEnchantsCraftEnchantment(key=$key)" + } +} diff --git a/eco-core/core-nms/v1_20_6/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_6/registration/ModifiedVanillaCraftEnchantment.kt b/eco-core/core-nms/v1_20_6/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_6/registration/ModifiedVanillaCraftEnchantment.kt new file mode 100644 index 00000000..b9200c4e --- /dev/null +++ b/eco-core/core-nms/v1_20_6/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_6/registration/ModifiedVanillaCraftEnchantment.kt @@ -0,0 +1,23 @@ +package com.willfp.ecoenchants.proxy.v1_20_6.registration + +import com.willfp.ecoenchants.enchant.vanillaEnchantmentData +import net.minecraft.world.item.enchantment.Enchantment +import org.bukkit.NamespacedKey +import org.bukkit.craftbukkit.enchantments.CraftEnchantment + +class ModifiedVanillaCraftEnchantment( + key: NamespacedKey, + target: Enchantment +) : CraftEnchantment(key, target) { + override fun getMaxLevel(): Int = this.vanillaEnchantmentData?.maxLevel ?: super.getMaxLevel() + + override fun conflictsWith(other: org.bukkit.enchantments.Enchantment): Boolean { + val otherConflicts = when (other) { + is ModifiedVanillaCraftEnchantment -> other.vanillaEnchantmentData?.conflicts?.contains(this.key) == true + else -> other.conflictsWith(this) + } + + return this.vanillaEnchantmentData?.conflicts?.contains(other.key) ?: super.conflictsWith(other) + || otherConflicts + } +} diff --git a/eco-core/core-nms/v1_20_6/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_6/registration/VanillaEcoEnchantsEnchantment.kt b/eco-core/core-nms/v1_20_6/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_6/registration/VanillaEcoEnchantsEnchantment.kt new file mode 100644 index 00000000..16fdd5fa --- /dev/null +++ b/eco-core/core-nms/v1_20_6/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_6/registration/VanillaEcoEnchantsEnchantment.kt @@ -0,0 +1,116 @@ +package com.willfp.ecoenchants.proxy.v1_20_6.registration + +import com.willfp.eco.core.Prerequisite +import com.willfp.eco.util.toComponent +import com.willfp.ecoenchants.display.getFormattedName +import com.willfp.ecoenchants.enchant.EcoEnchant +import com.willfp.ecoenchants.enchant.EcoEnchants +import io.papermc.paper.adventure.PaperAdventure +import net.minecraft.network.chat.Component +import net.minecraft.tags.ItemTags +import net.minecraft.world.entity.EquipmentSlot +import net.minecraft.world.entity.LivingEntity +import net.minecraft.world.inventory.AnvilMenu +import net.minecraft.world.item.ItemStack +import net.minecraft.world.item.enchantment.Enchantment +import org.bukkit.craftbukkit.enchantments.CraftEnchantment +import org.bukkit.craftbukkit.inventory.CraftItemStack +import java.util.Objects + +class VanillaEcoEnchantsEnchantment( + enchant: EcoEnchant +) : Enchantment( + definition( + ItemTags.DURABILITY_ENCHANTABLE, 0, // Weight is 0, so we can use our own rarity system + enchant.maximumLevel, + constantCost(1), + constantCost(1), + 0 + ) +) { + private val id = enchant.id + + // Fetch on each call to ensure we get the latest enchantment + private val enchant: EcoEnchant? + get() = EcoEnchants[id] + + override fun canEnchant(stack: ItemStack): Boolean { + /* + + This is the mother of all jank solutions. + + Because I want the EcoEnchants anvil code to handle all custom enchantment logic, + I need to prevent the NMS anvil code from processing the EcoEnchants enchantments. + + However, there's no API method that I can use to do this - **however**, + this method is called once in the NMS anvil code, and if it returns false then + the anvil will not allow this enchantment to be applied to the item. + + So, I can check if the calling method is the anvil merge method, and if it is, + I can return false. + + */ + + val caller = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE).callerClass + + if (caller.name == AnvilMenu::class.java.name) { + return false + } + + // End disgusting bodge + + val item = CraftItemStack.asCraftMirror(stack) + return enchant?.canEnchantItem(item) ?: false + } + + override fun isCurse(): Boolean { + return enchant?.type?.noGrindstone == true + } + + override fun isDiscoverable(): Boolean { + return false + } + + override fun isTradeable(): Boolean { + return false + } + + override fun isTreasureOnly(): Boolean { + return true + } + + override fun checkCompatibility(other: Enchantment): Boolean { + val bukkit = CraftEnchantment.minecraftToBukkit(other) + + if (enchant != null) { + return !enchant!!.conflictsWith(bukkit) + } + + return false + } + + override fun getSlotItems(entity: LivingEntity): MutableMap { + return mutableMapOf() + } + + override fun getFullname(level: Int): Component { + val enchant = this.enchant + return if (Prerequisite.HAS_PAPER.isMet && enchant != null) { + PaperAdventure.asVanilla(enchant.getFormattedName(level).toComponent()) + } else { + super.getFullname(level) + } + } + + override fun toString(): String { + return "VanillaEcoEnchantsEnchantment(id='$id')" + } + + override fun equals(other: Any?): Boolean { + return other is VanillaEcoEnchantsEnchantment && other.id == this.id + } + + override fun hashCode(): Int { + return Objects.hash(id) + } +} diff --git a/eco-core/core-nms/v1_20_R1/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R1/HideStoredEnchants.kt b/eco-core/core-nms/v1_20_R1/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R1/HideStoredEnchants.kt new file mode 100644 index 00000000..2c61fd72 --- /dev/null +++ b/eco-core/core-nms/v1_20_R1/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R1/HideStoredEnchants.kt @@ -0,0 +1,19 @@ +package com.willfp.ecoenchants.proxy.v1_20_R1 + +import com.willfp.eco.core.fast.FastItemStack +import com.willfp.ecoenchants.display.HideStoredEnchantsProxy +import org.bukkit.inventory.ItemFlag + +class HideStoredEnchants: HideStoredEnchantsProxy { + override fun hideStoredEnchants(fis: FastItemStack) { + fis.addItemFlags(ItemFlag.HIDE_POTION_EFFECTS) + } + + override fun areStoredEnchantsHidden(fis: FastItemStack): Boolean { + return fis.hasItemFlag(ItemFlag.HIDE_POTION_EFFECTS) + } + + override fun showStoredEnchants(fis: FastItemStack) { + fis.removeItemFlags(ItemFlag.HIDE_POTION_EFFECTS) + } +} diff --git a/eco-core/core-nms/v1_20_R2/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R2/HideStoredEnchants.kt b/eco-core/core-nms/v1_20_R2/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R2/HideStoredEnchants.kt new file mode 100644 index 00000000..00c9fe76 --- /dev/null +++ b/eco-core/core-nms/v1_20_R2/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R2/HideStoredEnchants.kt @@ -0,0 +1,19 @@ +package com.willfp.ecoenchants.proxy.v1_20_R2 + +import com.willfp.eco.core.fast.FastItemStack +import com.willfp.ecoenchants.display.HideStoredEnchantsProxy +import org.bukkit.inventory.ItemFlag + +class HideStoredEnchants: HideStoredEnchantsProxy { + override fun hideStoredEnchants(fis: FastItemStack) { + fis.addItemFlags(ItemFlag.HIDE_POTION_EFFECTS) + } + + override fun areStoredEnchantsHidden(fis: FastItemStack): Boolean { + return fis.hasItemFlag(ItemFlag.HIDE_POTION_EFFECTS) + } + + override fun showStoredEnchants(fis: FastItemStack) { + fis.removeItemFlags(ItemFlag.HIDE_POTION_EFFECTS) + } +} diff --git a/eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R3/HideStoredEnchants.kt b/eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R3/HideStoredEnchants.kt new file mode 100644 index 00000000..362a0d3b --- /dev/null +++ b/eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R3/HideStoredEnchants.kt @@ -0,0 +1,20 @@ +package com.willfp.ecoenchants.proxy.v1_20_R3 + +import com.willfp.eco.core.fast.FastItemStack +import com.willfp.ecoenchants.display.HideStoredEnchantsProxy +import org.bukkit.inventory.ItemFlag + +@Suppress("DEPRECATION") +class HideStoredEnchants: HideStoredEnchantsProxy { + override fun hideStoredEnchants(fis: FastItemStack) { + fis.addItemFlags(ItemFlag.HIDE_POTION_EFFECTS) + } + + override fun areStoredEnchantsHidden(fis: FastItemStack): Boolean { + return fis.hasItemFlag(ItemFlag.HIDE_POTION_EFFECTS) + } + + override fun showStoredEnchants(fis: FastItemStack) { + fis.removeItemFlags(ItemFlag.HIDE_POTION_EFFECTS) + } +} diff --git a/eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R3/registration/EcoEnchantsCraftEnchantment.kt b/eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R3/registration/EcoEnchantsCraftEnchantment.kt index 5488636a..5029b9de 100644 --- a/eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R3/registration/EcoEnchantsCraftEnchantment.kt +++ b/eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R3/registration/EcoEnchantsCraftEnchantment.kt @@ -12,7 +12,6 @@ import org.bukkit.enchantments.EnchantmentTarget import org.bukkit.entity.EntityCategory import org.bukkit.inventory.EquipmentSlot import org.bukkit.inventory.ItemStack -import java.util.Objects class EcoEnchantsCraftEnchantment( private val enchant: EcoEnchantBase, diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/CodecReplacerProxy.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/CodecReplacerProxy.kt new file mode 100644 index 00000000..4c733bfb --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/CodecReplacerProxy.kt @@ -0,0 +1,5 @@ +package com.willfp.ecoenchants + +interface CodecReplacerProxy { + fun replaceItemCodec() +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/EcoEnchantsPlugin.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/EcoEnchantsPlugin.kt index eb5492b0..fffe02ef 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/EcoEnchantsPlugin.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/EcoEnchantsPlugin.kt @@ -4,6 +4,7 @@ import com.willfp.eco.core.Prerequisite import com.willfp.eco.core.command.impl.PluginCommand import com.willfp.eco.core.display.DisplayModule import com.willfp.eco.core.integrations.IntegrationLoader +import com.willfp.eco.core.packet.PacketListener import com.willfp.ecoenchants.commands.CommandEcoEnchants import com.willfp.ecoenchants.commands.CommandEnchant import com.willfp.ecoenchants.commands.CommandEnchantInfo @@ -65,6 +66,13 @@ class EcoEnchantsPlugin : LibreforgePlugin() { if (Prerequisite.HAS_1_20_3.isMet) { plugin.getProxy(ModernEnchantmentRegistererProxy::class.java).replaceRegistry() } + + if (Prerequisite.HAS_1_20_5.isMet) { + if (!this.configYml.getBool("enable-1-20-6")) { + throw IllegalStateException("EcoEnchants should not be ran in production on 1.20.6. " + + "If this is a development environment, please set 'enable-1-20-6' to true in config.yml. ") + } + } } override fun loadConfigCategories(): List { @@ -85,6 +93,10 @@ class EcoEnchantsPlugin : LibreforgePlugin() { NamedValue("level", it.level), ) } + + if (Prerequisite.HAS_1_20_5.isMet) { + getProxy(CodecReplacerProxy::class.java).replaceItemCodec() + } } override fun handleAfterLoad() { diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/display/EnchantDisplay.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/display/EnchantDisplay.kt index 3227a4b4..6d8daf14 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/display/EnchantDisplay.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/display/EnchantDisplay.kt @@ -6,10 +6,12 @@ import com.willfp.eco.core.display.DisplayPriority import com.willfp.eco.core.display.DisplayProperties import com.willfp.eco.core.fast.FastItemStack import com.willfp.eco.core.fast.fast +import com.willfp.eco.core.items.builder.modify import com.willfp.ecoenchants.EcoEnchantsPlugin import com.willfp.ecoenchants.commands.CommandToggleDescriptions.Companion.seesEnchantmentDescriptions import com.willfp.ecoenchants.display.EnchantSorter.sortForDisplay import com.willfp.ecoenchants.enchant.EcoEnchant +import com.willfp.ecoenchants.enchant.EcoEnchants import com.willfp.ecoenchants.enchant.wrap import com.willfp.ecoenchants.target.EnchantmentTargets.isEnchantable import com.willfp.libreforge.ItemProvidedHolder @@ -23,11 +25,20 @@ import kotlin.collections.component1 import kotlin.collections.component2 import kotlin.collections.set +// Works around HIDE_POTION_EFFECTS not existing in 1.20.5+ +interface HideStoredEnchantsProxy { + fun hideStoredEnchants(fis: FastItemStack) + fun showStoredEnchants(fis: FastItemStack) + fun areStoredEnchantsHidden(fis: FastItemStack): Boolean +} + @Suppress("DEPRECATION") class EnchantDisplay(private val plugin: EcoEnchantsPlugin) : DisplayModule(plugin, DisplayPriority.HIGH) { private val hideStateKey = plugin.namespacedKeyFactory.create("ecoenchantlore-skip") // Same for backwards compatibility + private val hse = plugin.getProxy(HideStoredEnchantsProxy::class.java) + override fun display( itemStack: ItemStack, player: Player?, @@ -45,7 +56,7 @@ class EnchantDisplay(private val plugin: EcoEnchantsPlugin) : DisplayModule(plug if (args[0] == true) { fast.addItemFlags(ItemFlag.HIDE_ENCHANTS) if (itemStack.type == Material.ENCHANTED_BOOK) { - fast.addItemFlags(ItemFlag.HIDE_POTION_EFFECTS) + hse.hideStoredEnchants(fast) } pdc.set(hideStateKey, PersistentDataType.INTEGER, 1) return @@ -114,7 +125,7 @@ class EnchantDisplay(private val plugin: EcoEnchantsPlugin) : DisplayModule(plug fast.addItemFlags(ItemFlag.HIDE_ENCHANTS) if (itemStack.type == Material.ENCHANTED_BOOK) { - fast.addItemFlags(ItemFlag.HIDE_POTION_EFFECTS) + hse.hideStoredEnchants(fast) } fast.lore = enchantLore + lore + notMetLines @@ -132,7 +143,7 @@ class EnchantDisplay(private val plugin: EcoEnchantsPlugin) : DisplayModule(plug fast.removeItemFlags(ItemFlag.HIDE_ENCHANTS) if (itemStack.type == Material.ENCHANTED_BOOK) { - fast.removeItemFlags(ItemFlag.HIDE_POTION_EFFECTS) + hse.showStoredEnchants(fast) } } @@ -147,7 +158,7 @@ class EnchantDisplay(private val plugin: EcoEnchantsPlugin) : DisplayModule(plug 0 -> arrayOf(false) else -> arrayOf( fast.hasItemFlag(ItemFlag.HIDE_ENCHANTS) - || fast.hasItemFlag(ItemFlag.HIDE_POTION_EFFECTS) + || hse.areStoredEnchantsHidden(fast) ) } } diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/EnchantGUI.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/EnchantGUI.kt index 3680d422..ee728389 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/EnchantGUI.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/EnchantGUI.kt @@ -18,6 +18,7 @@ import com.willfp.eco.core.gui.slot.Slot import com.willfp.eco.core.items.Items import com.willfp.eco.core.items.builder.EnchantedBookBuilder import com.willfp.eco.core.items.builder.ItemStackBuilder +import com.willfp.eco.core.items.isEcoEmpty import com.willfp.eco.core.items.isEmpty import com.willfp.eco.util.formatEco import com.willfp.eco.util.lineWrap @@ -72,7 +73,7 @@ object EnchantGUI { onRender { player, menu -> val atCaptive = menu.getCaptiveItem(player, captiveRow, captiveColumn) - if (atCaptive.isEmpty || atCaptive == null || atCaptive.type == Material.BOOK) { + if (atCaptive.isEcoEmpty || atCaptive == null || atCaptive.type == Material.BOOK) { menu.setState(player, "enchants", EcoEnchants.values().map { it.enchantment }.sortForDisplay()) } else { menu.setState( diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/impl/EcoEnchantBase.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/impl/EcoEnchantBase.kt index 17d9009f..412729c5 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/impl/EcoEnchantBase.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/impl/EcoEnchantBase.kt @@ -122,7 +122,7 @@ abstract class EcoEnchantBase( protected abstract fun createLevel(level: Int): EcoEnchantLevel override fun conflictsWithDirectly(other: Enchantment): Boolean { - return other.key.key in conflictIds + return other.key.key in conflictIds || this.conflictsWithEverything } final override fun equals(other: Any?): Boolean { diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/impl/hardcoded/EnchantmentSoulbound.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/impl/hardcoded/EnchantmentSoulbound.kt index 193f2349..d21f7811 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/impl/hardcoded/EnchantmentSoulbound.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/impl/hardcoded/EnchantmentSoulbound.kt @@ -124,8 +124,9 @@ class EnchantmentSoulbound( ignoreCancelled = true ) fun preventDroppingSoulboundItems(event: PlayerDeathEvent) { - event.drops.removeIf { it.fast().persistentDataContainer.has(soulboundKey, PersistentDataType.INTEGER) - && it.itemMeta.hasEnchant(enchant.enchantment) + event.drops.removeIf { + it.fast().persistentDataContainer.has(soulboundKey, PersistentDataType.INTEGER) + && it.itemMeta.hasEnchant(enchant.enchantment) } } } diff --git a/eco-core/core-plugin/src/main/resources/config.yml b/eco-core/core-plugin/src/main/resources/config.yml index 492114ca..9f3dda02 100644 --- a/eco-core/core-plugin/src/main/resources/config.yml +++ b/eco-core/core-plugin/src/main/resources/config.yml @@ -167,3 +167,11 @@ enchant-gui: lore-conversion: enabled: false # If lore conversion should be enabled aggressive: false # Will convert all items in all inventories when opened, likely to use a lot of performance + +# DO NOT USE IN PRODUCTION! +# EcoEnchants should not be run on 1.20.6 in production environments. This is for testing purposes only. +# This will allow the plugin to run on 1.20.6, but it is not recommended. +# Enabling this option may cause irreversible damage to your server and may corrupt all items. +# If you want to use EcoEnchants on 1.20, please only run 1.20.4. +# 1.21 will work as expected when it releases. +enable-1-20-6: false diff --git a/gradle.properties b/gradle.properties index 83d22945..3805315e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,4 +2,4 @@ #Wed Apr 17 20:35:15 BST 2024 kotlin.code.style=official libreforge-version=4.58.1 -version=12.5.1 +version=12.6.0 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index ccebba77..e6441136 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index bdc9a83b..b82aa23a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 79a61d42..1aa94a42 100755 --- a/gradlew +++ b/gradlew @@ -83,10 +83,8 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -133,10 +131,13 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. @@ -144,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -152,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -197,11 +198,15 @@ if "$cygwin" || "$msys" ; then done fi -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/gradlew.bat b/gradlew.bat index 93e3f59f..25da30db 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -43,11 +43,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/settings.gradle.kts b/settings.gradle.kts index 6db2ec69..6685935d 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -22,3 +22,4 @@ include(":eco-core:core-nms:v1_19_R3") include(":eco-core:core-nms:v1_20_R1") include(":eco-core:core-nms:v1_20_R2") include(":eco-core:core-nms:v1_20_R3") +include(":eco-core:core-nms:v1_20_6")