From f3af2a0a751cd2c05c9fb22514639438ccf82890 Mon Sep 17 00:00:00 2001 From: Will FP Date: Sat, 9 Dec 2023 15:48:06 +0000 Subject: [PATCH] Got ModernEnchantmentRegisterer working --- .../v1_20_R3/ModernEnchantmentRegisterer.kt | 38 ++++++++++++------- .../willfp/ecoenchants/EcoEnchantsPlugin.kt | 7 +--- .../com/willfp/ecoenchants/ReflectionUtil.kt | 13 +++++++ .../willfp/ecoenchants/enchant/EcoEnchants.kt | 7 ++++ 4 files changed, 45 insertions(+), 20 deletions(-) create mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/ReflectionUtil.kt diff --git a/eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R3/ModernEnchantmentRegisterer.kt b/eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R3/ModernEnchantmentRegisterer.kt index 59a537ef..3b873845 100644 --- a/eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R3/ModernEnchantmentRegisterer.kt +++ b/eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R3/ModernEnchantmentRegisterer.kt @@ -6,6 +6,7 @@ import com.willfp.ecoenchants.enchant.registration.modern.ModernEnchantmentRegis import com.willfp.ecoenchants.proxy.v1_20_R3.registration.EcoEnchantsCraftEnchantment import com.willfp.ecoenchants.proxy.v1_20_R3.registration.ModifiedVanillaCraftEnchantment import com.willfp.ecoenchants.proxy.v1_20_R3.registration.VanillaEcoEnchantsEnchantment +import com.willfp.ecoenchants.setStaticFinal import net.minecraft.core.Holder import net.minecraft.core.MappedRegistry import net.minecraft.core.Registry @@ -49,7 +50,7 @@ class ModernEnchantmentRegisterer : ModernEnchantmentRegistererProxy { val server = Bukkit.getServer() as CraftServer @Suppress("UNCHECKED_CAST") - registries[Enchantment::class.java] = CraftRegistry( + val registry = CraftRegistry( Enchantment::class.java as Class, server.handle.server.registryAccess().registryOrThrow(Registries.ENCHANTMENT) ) { key, registry -> @@ -64,33 +65,42 @@ class ModernEnchantmentRegisterer : ModernEnchantmentRegistererProxy { null } } + + // Register to server + registries[Enchantment::class.java] = registry + + // Register to API + org.bukkit.Registry::class.java + .getDeclaredField("ENCHANTMENT") + .setStaticFinal(registry) + + // Unfreeze NMS registry + frozenField.set(BuiltInRegistries.ENCHANTMENT, false) + unregisteredIntrusiveHoldersField.set(BuiltInRegistries.ENCHANTMENT, IdentityHashMap>()) } override fun register(enchant: EcoEnchant): Enchantment { if (BuiltInRegistries.ENCHANTMENT.containsKey(CraftNamespacedKey.toMinecraft(enchant.enchantmentKey))) { - return org.bukkit.Registry.ENCHANTMENT.get(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") + } } - // Unfreeze registry - unfreeze(BuiltInRegistries.ENCHANTMENT) + Registry.register(BuiltInRegistries.ENCHANTMENT, enchant.id, VanillaEcoEnchantsEnchantment(enchant.id)) - val nms = VanillaEcoEnchantsEnchantment(enchant.id) - - Registry.register(BuiltInRegistries.ENCHANTMENT, enchant.id, nms) - - return EcoEnchantsCraftEnchantment(enchant, nms) + return register(enchant) } - private fun unfreeze(registry: Registry) { - frozenField.set(registry, false) - unregisteredIntrusiveHoldersField.set(registry, IdentityHashMap>()) - } 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 because unregistered enchantments can't be accessed. + This shouldn't cause many issues in production as the bukkit registry is replaced on each reload. */ } 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 bfa22b42..f1478607 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 @@ -64,7 +64,7 @@ class EcoEnchantsPlugin : LibreforgePlugin() { plugin = this if (Prerequisite.HAS_1_20_3.isMet) { - this.getProxy(ModernEnchantmentRegistererProxy::class.java).replaceRegistry() + plugin.getProxy(ModernEnchantmentRegistererProxy::class.java).replaceRegistry() } } @@ -106,11 +106,6 @@ class EcoEnchantsPlugin : LibreforgePlugin() { legacyRegisterVanillaEnchantmentData(this) } - // Replace registry on reload to manage some enchantment removal logic - if (Prerequisite.HAS_1_20_3.isMet) { - this.getProxy(ModernEnchantmentRegistererProxy::class.java).replaceRegistry() - } - DisplayCache.reload() EnchantSorter.reload(this) ExtraItemSupport.reload(this) diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/ReflectionUtil.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/ReflectionUtil.kt new file mode 100644 index 00000000..70f40870 --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/ReflectionUtil.kt @@ -0,0 +1,13 @@ +package com.willfp.ecoenchants + +import sun.misc.Unsafe +import java.lang.reflect.Field + +private val unsafe = Unsafe::class.java.getDeclaredField("theUnsafe") + .apply { isAccessible = true } + .get(null) as Unsafe + +fun Field.setStaticFinal(value: Any) { + val offset = unsafe.staticFieldOffset(this) + unsafe.putObject(unsafe.staticFieldBase(this), offset, value) +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/EcoEnchants.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/EcoEnchants.kt index 9724802b..d37bc3e6 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/EcoEnchants.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/EcoEnchants.kt @@ -1,6 +1,7 @@ package com.willfp.ecoenchants.enchant import com.google.common.collect.HashBiMap +import com.willfp.eco.core.Prerequisite import com.willfp.eco.core.config.interfaces.Config import com.willfp.ecoenchants.EcoEnchantsPlugin import com.willfp.ecoenchants.display.getFormattedName @@ -9,6 +10,7 @@ import com.willfp.ecoenchants.enchant.impl.hardcoded.EnchantmentPermanenceCurse import com.willfp.ecoenchants.enchant.impl.hardcoded.EnchantmentRepairing import com.willfp.ecoenchants.enchant.impl.hardcoded.EnchantmentReplenish import com.willfp.ecoenchants.enchant.impl.hardcoded.EnchantmentSoulbound +import com.willfp.ecoenchants.enchant.registration.modern.ModernEnchantmentRegistererProxy import com.willfp.ecoenchants.integrations.EnchantRegistrations import com.willfp.ecoenchants.rarity.EnchantmentRarities import com.willfp.ecoenchants.target.EnchantmentTargets @@ -34,6 +36,11 @@ object EcoEnchants : RegistrableCategory("enchant", "enchants") { } override fun beforeReload(plugin: LibreforgePlugin) { + // Replace registry on reload to manage some enchantment removal logic + if (Prerequisite.HAS_1_20_3.isMet) { + plugin.getProxy(ModernEnchantmentRegistererProxy::class.java).replaceRegistry() + } + plugin as EcoEnchantsPlugin EnchantmentRarities.update(plugin)