From 3dceea0b38e416595c789728b79d2642e5ad16a8 Mon Sep 17 00:00:00 2001 From: Will FP Date: Thu, 7 Dec 2023 14:38:13 +0000 Subject: [PATCH] Began reworking enchantment registration --- build.gradle.kts | 8 +- eco-core/core-nms/build.gradle.kts | 5 + eco-core/core-nms/v1_20_R3/build.gradle.kts | 16 +++ .../proxy/v1_20_R3/EcoCraftEnchantment.kt | 28 ++++ .../v1_20_R3/EcoCraftEnchantmentManager.kt | 26 ++++ .../v1_20_R3/ModernEnchantmentRegisterer.kt | 73 ++++++++++ .../proxy/v1_20_R3/OpenInventory.kt | 11 ++ .../registration/DelegatedCraftEnchantment.kt | 115 ++++++++++++++++ .../VanillaEcoEnchantsEnchantment.kt | 80 +++++++++++ .../willfp/ecoenchants/EcoEnchantsPlugin.kt | 3 + .../willfp/ecoenchants/enchant/EcoEnchant.kt | 82 +++++++++++ .../ecoenchants/enchant/EcoEnchantLevel.kt | 42 ++++++ .../ecoenchants/enchant/EcoEnchantLike.kt | 130 ++++++++++++++++++ .../willfp/ecoenchants/enchant/EcoEnchants.kt | 80 +++++++++++ .../com/willfp/ecoenchants/enchant/Util.kt | 23 ++++ .../enchant/impl/EcoEnchantBase.kt | 74 ++++++++++ .../enchant/impl/HardcodedEcoEnchant.kt | 25 ++++ .../enchant/impl/LibreforgeEcoEnchant.kt | 26 ++++ .../enchant/impl/VanillaEcoEnchantLike.kt | 39 ++++++ .../hardcoded/EnchantmentPermanenceCurse.kt | 13 ++ .../impl/hardcoded}/EnchantmentRepairing.kt | 2 +- .../impl/hardcoded}/EnchantmentReplenish.kt | 2 +- .../impl/hardcoded}/EnchantmentSoulbound.kt | 2 +- .../registration/EnchantmentRegisterer.kt | 9 ++ .../legacy/LegacyDelegatedEnchantment.kt | 87 ++++++++++++ .../legacy/LegacyEnchantmentRegisterer.kt | 33 +++++ .../ModernEnchantmentRegistererProxy.kt | 6 + .../willfp/ecoenchants/enchants/EcoEnchant.kt | 5 +- .../ecoenchants/enchants/EcoEnchantLike.kt | 53 ------- .../ecoenchants/enchants/EcoEnchants.kt | 86 +----------- .../impl/EnchantmentPermanenceCurse.kt | 12 -- .../EnchantRegistrationIntegration.kt | 3 +- .../plugins/EssentialsIntegration.kt | 13 +- settings.gradle.kts | 2 + 34 files changed, 1052 insertions(+), 162 deletions(-) create mode 100644 eco-core/core-nms/v1_20_R3/build.gradle.kts create mode 100644 eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R3/EcoCraftEnchantment.kt create mode 100644 eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R3/EcoCraftEnchantmentManager.kt create mode 100644 eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R3/ModernEnchantmentRegisterer.kt create mode 100644 eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R3/OpenInventory.kt create mode 100644 eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R3/registration/DelegatedCraftEnchantment.kt create mode 100644 eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R3/registration/VanillaEcoEnchantsEnchantment.kt create mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/EcoEnchant.kt create mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/EcoEnchantLevel.kt create mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/EcoEnchantLike.kt create mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/EcoEnchants.kt create mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/Util.kt create mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/impl/EcoEnchantBase.kt create mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/impl/HardcodedEcoEnchant.kt create mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/impl/LibreforgeEcoEnchant.kt create mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/impl/VanillaEcoEnchantLike.kt create mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/impl/hardcoded/EnchantmentPermanenceCurse.kt rename eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/{enchants/impl => enchant/impl/hardcoded}/EnchantmentRepairing.kt (96%) rename eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/{enchants/impl => enchant/impl/hardcoded}/EnchantmentReplenish.kt (98%) rename eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/{enchants/impl => enchant/impl/hardcoded}/EnchantmentSoulbound.kt (98%) create mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/registration/EnchantmentRegisterer.kt create mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/registration/legacy/LegacyDelegatedEnchantment.kt create mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/registration/legacy/LegacyEnchantmentRegisterer.kt create mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/registration/modern/ModernEnchantmentRegistererProxy.kt delete mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchants/impl/EnchantmentPermanenceCurse.kt diff --git a/build.gradle.kts b/build.gradle.kts index e703407f..02463a47 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,7 +2,7 @@ plugins { java `java-library` `maven-publish` - kotlin("jvm") version "1.7.10" + kotlin("jvm") version "1.9.20" id("com.github.johnrengelman.shadow") version "8.0.0" id("com.willfp.libreforge-gradle-plugin") version "1.0.0" } @@ -40,10 +40,10 @@ allprojects { } dependencies { - compileOnly("com.willfp:eco:6.58.0") + compileOnly("com.willfp:eco:6.67.0") compileOnly("org.jetbrains:annotations:23.0.0") - compileOnly("org.jetbrains.kotlin:kotlin-stdlib:1.7.10") - compileOnly("com.github.ben-manes.caffeine:caffeine:3.1.0") + compileOnly("org.jetbrains.kotlin:kotlin-stdlib:1.9.20") + compileOnly("com.github.ben-manes.caffeine:caffeine:3.1.5") } java { diff --git a/eco-core/core-nms/build.gradle.kts b/eco-core/core-nms/build.gradle.kts index 29e72f5d..468525a9 100644 --- a/eco-core/core-nms/build.gradle.kts +++ b/eco-core/core-nms/build.gradle.kts @@ -1,3 +1,8 @@ +plugins { + id("io.papermc.paperweight.userdev") version "1.5.3" apply false +} + + group = "com.willfp" version = rootProject.version diff --git a/eco-core/core-nms/v1_20_R3/build.gradle.kts b/eco-core/core-nms/v1_20_R3/build.gradle.kts new file mode 100644 index 00000000..dc278e4a --- /dev/null +++ b/eco-core/core-nms/v1_20_R3/build.gradle.kts @@ -0,0 +1,16 @@ +plugins { + id("io.papermc.paperweight.userdev") +} + +group = "com.willfp" +version = rootProject.version + +dependencies { + paperweight.paperDevBundle("1.20.3-R0.1-SNAPSHOT") +} + +tasks { + build { + dependsOn(reobfJar) + } +} diff --git a/eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R3/EcoCraftEnchantment.kt b/eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R3/EcoCraftEnchantment.kt new file mode 100644 index 00000000..13446a33 --- /dev/null +++ b/eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R3/EcoCraftEnchantment.kt @@ -0,0 +1,28 @@ +package com.willfp.ecoenchants.proxy.v1_20_R3 + +import com.willfp.ecoenchants.enchants.EcoEnchant +import com.willfp.ecoenchants.enchants.EcoEnchants +import com.willfp.ecoenchants.vanilla.VanillaEnchantmentData +import net.minecraft.world.item.enchantment.Enchantment +import org.bukkit.NamespacedKey +import org.bukkit.craftbukkit.v1_20_R3.enchantments.CraftEnchantment + +class EcoCraftEnchantment( + target: Enchantment, + key: NamespacedKey, + private val data: VanillaEnchantmentData +) : CraftEnchantment(key, target) { + override fun getMaxLevel(): Int = data.maxLevel ?: super.getMaxLevel() + + override fun conflictsWith(other: org.bukkit.enchantments.Enchantment): Boolean { + if (other is EcoEnchant) { + return other.conflictsWith(this) + } + + return data.conflicts?.contains(other.key) ?: super.conflictsWith(other) + } + + fun register() { + EcoEnchants.register(this) + } +} diff --git a/eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R3/EcoCraftEnchantmentManager.kt b/eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R3/EcoCraftEnchantmentManager.kt new file mode 100644 index 00000000..9e7bbc3b --- /dev/null +++ b/eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R3/EcoCraftEnchantmentManager.kt @@ -0,0 +1,26 @@ +package com.willfp.ecoenchants.proxy.v1_20_R3 + +import com.willfp.ecoenchants.proxy.proxies.EcoCraftEnchantmentManagerProxy +import com.willfp.ecoenchants.proxy.v1_20_R3.EcoCraftEnchantment +import com.willfp.ecoenchants.vanilla.VanillaEnchantmentData +import net.minecraft.core.registries.BuiltInRegistries +import org.bukkit.enchantments.Enchantment + +class EcoCraftEnchantmentManager : EcoCraftEnchantmentManagerProxy { + override fun registerNewCraftEnchantment( + enchantment: Enchantment, + data: VanillaEnchantmentData + ) { + for (enchant in BuiltInRegistries.ENCHANTMENT) { + val key = org.bukkit.craftbukkit.v1_20_R3.util.CraftNamespacedKey.fromMinecraft( + BuiltInRegistries.ENCHANTMENT.getKey(enchant) + ) + + if (key.key != enchantment.key.key) { + continue + } + + EcoCraftEnchantment(enchant, key, data).register() + } + } +} 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 new file mode 100644 index 00000000..0023447a --- /dev/null +++ b/eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R3/ModernEnchantmentRegisterer.kt @@ -0,0 +1,73 @@ +package com.willfp.ecoenchants.proxy.v1_20_R3 + +import com.willfp.ecoenchants.enchant.EcoEnchant +import com.willfp.ecoenchants.enchant.EcoEnchants +import com.willfp.ecoenchants.enchant.registration.modern.ModernEnchantmentRegistererProxy +import com.willfp.ecoenchants.proxy.v1_20_R3.registration.DelegatedCraftEnchantment +import com.willfp.ecoenchants.proxy.v1_20_R3.registration.VanillaEcoEnchantsEnchantment +import net.minecraft.core.MappedRegistry +import net.minecraft.core.Registry +import net.minecraft.core.registries.BuiltInRegistries +import net.minecraft.core.registries.Registries +import org.bukkit.Bukkit +import org.bukkit.craftbukkit.v1_20_R3.CraftRegistry +import org.bukkit.craftbukkit.v1_20_R3.CraftServer +import org.bukkit.craftbukkit.v1_20_R3.enchantments.CraftEnchantment +import org.bukkit.craftbukkit.v1_20_R3.util.CraftNamespacedKey +import org.bukkit.enchantments.Enchantment + +class ModernEnchantmentRegisterer : ModernEnchantmentRegistererProxy { + private val frozenField = MappedRegistry::class.java + .declaredFields + .filter { it.type.isPrimitive }[0] + .apply { isAccessible = true } + + @Suppress("UNCHECKED_CAST") + private val registries = CraftServer::class.java + .getDeclaredField("registries") + .apply { isAccessible = true } + .get(Bukkit.getServer()) + as HashMap, org.bukkit.Registry<*>> + + // Replace bukkit enchantment registry + init { + val server = Bukkit.getServer() as CraftServer + + registries[Enchantment::class.java] = CraftRegistry( + Enchantment::class.java, + server.handle.server.registryAccess().registryOrThrow(Registries.ENCHANTMENT) + ) { key, registry -> + val enchant = EcoEnchants.getByID(key.key) + + if (enchant == null) { + CraftEnchantment(key, registry) + } else { + DelegatedCraftEnchantment(enchant, registry) + } + } + } + + override fun register(enchant: EcoEnchant) { + if (BuiltInRegistries.ENCHANTMENT.containsKey(CraftNamespacedKey.toMinecraft(enchant.key))) { + return + } + + // Unfreeze registry + frozenField.set(BuiltInRegistries.ENCHANTMENT, false) + + Registry.register( + BuiltInRegistries.ENCHANTMENT, enchant.id, VanillaEcoEnchantsEnchantment( + enchant.id + ) + ) + } + + 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. + + */ + } +} diff --git a/eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R3/OpenInventory.kt b/eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R3/OpenInventory.kt new file mode 100644 index 00000000..614a8a84 --- /dev/null +++ b/eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R3/OpenInventory.kt @@ -0,0 +1,11 @@ +package com.willfp.ecoenchants.proxy.v1_20_R3 + +import com.willfp.ecoenchants.proxy.proxies.OpenInventoryProxy +import org.bukkit.craftbukkit.v1_20_R3.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_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R3/registration/DelegatedCraftEnchantment.kt b/eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R3/registration/DelegatedCraftEnchantment.kt new file mode 100644 index 00000000..f72d7375 --- /dev/null +++ b/eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R3/registration/DelegatedCraftEnchantment.kt @@ -0,0 +1,115 @@ +package com.willfp.ecoenchants.proxy.v1_20_R3.registration + +import com.willfp.eco.util.StringUtils +import com.willfp.ecoenchants.display.getFormattedName +import com.willfp.ecoenchants.enchant.EcoEnchant +import com.willfp.ecoenchants.enchants.wrap +import io.papermc.paper.enchantments.EnchantmentRarity +import net.kyori.adventure.text.Component +import net.minecraft.world.item.enchantment.Enchantment +import org.bukkit.craftbukkit.v1_20_R3.enchantments.CraftEnchantment +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 DelegatedCraftEnchantment( + private val enchant: EcoEnchant, + nmsEnchantment: Enchantment +) : CraftEnchantment(enchant.key, nmsEnchantment), EcoEnchant by enchant { + 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 { + return maxLevel + } + + override fun getStartLevel(): Int { + return 1 + } + + @Deprecated( + message = "getItemTargets is an incompatible Spigot API", + replaceWith = ReplaceWith("this.targets") + ) + override fun getItemTarget(): EnchantmentTarget = EnchantmentTarget.ALL + + @Deprecated( + message = "Treasure enchantments do not exist in EcoEnchants", + replaceWith = ReplaceWith("this.isEnchantable") + ) + override fun isTreasure(): Boolean = !isEnchantable + + @Deprecated( + message = "Use EnchantmentType instead", + replaceWith = ReplaceWith("type.id") + ) + override fun isCursed(): Boolean { + return false + } + + override fun displayName(level: Int): Component { + return StringUtils.toComponent(this.wrap().getFormattedName(level)) + } + + override fun isTradeable(): Boolean { + return isTradeable + } + + override fun isDiscoverable(): Boolean { + return isDiscoverable + } + + override fun getMinModifiedCost(level: Int): Int { + return Int.MAX_VALUE + } + + override fun getMaxModifiedCost(level: Int): Int { + return Int.MAX_VALUE + } + + @Deprecated( + message = "EcoEnchants uses a custom system for enchantment rarity", + replaceWith = ReplaceWith("this.enchantRarity") + ) + override fun getRarity(): EnchantmentRarity { + return EnchantmentRarity.RARE + } + + @Deprecated( + message = "EcoEnchants do not have damage increase, this method is for sharpness/boa/smite", + replaceWith = ReplaceWith("0.0f") + ) + override fun getDamageIncrease(level: Int, entityCategory: EntityCategory): Float = 0.0f + + @Deprecated( + message = "getActiveSlots is an incompatible Paper API", + replaceWith = ReplaceWith("this.slots") + ) + override fun getActiveSlots() = emptySet() + + override fun equals(other: Any?): Boolean { + return other is DelegatedCraftEnchantment && + other.key == this.key + } + + override fun hashCode(): Int { + return Objects.hash(this.key) + } +} \ No newline at end of file diff --git a/eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R3/registration/VanillaEcoEnchantsEnchantment.kt b/eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R3/registration/VanillaEcoEnchantsEnchantment.kt new file mode 100644 index 00000000..39a7d64f --- /dev/null +++ b/eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/ecoenchants/proxy/v1_20_R3/registration/VanillaEcoEnchantsEnchantment.kt @@ -0,0 +1,80 @@ +package com.willfp.ecoenchants.proxy.v1_20_R3.registration + +import com.willfp.ecoenchants.enchant.EcoEnchant +import com.willfp.ecoenchants.enchant.EcoEnchants +import net.minecraft.world.damagesource.DamageSource +import net.minecraft.world.entity.Entity +import net.minecraft.world.entity.EquipmentSlot +import net.minecraft.world.entity.LivingEntity +import net.minecraft.world.entity.MobType +import net.minecraft.world.item.ItemStack +import net.minecraft.world.item.enchantment.Enchantment +import net.minecraft.world.item.enchantment.EnchantmentCategory +import org.bukkit.craftbukkit.v1_20_R3.enchantments.CraftEnchantment +import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftItemStack + +class VanillaEcoEnchantsEnchantment( + private val id: String +) : Enchantment( + Rarity.VERY_RARE, + EnchantmentCategory.VANISHABLE, + EquipmentSlot.values() +) { + private val enchant: EcoEnchant + get() = EcoEnchants[id] ?: throw IllegalStateException("Enchantment $id not found") + + override fun canEnchant(stack: ItemStack): Boolean { + val item = CraftItemStack.asCraftMirror(stack) + return enchant.canEnchantItem(item) + } + + override fun doPostAttack(user: LivingEntity, target: Entity, level: Int) { + // Do nothing + } + + override fun doPostHurt(user: LivingEntity, attacker: Entity, level: Int) { + // Do nothing + } + + override fun getDamageBonus(level: Int, group: MobType): Float { + return 0f + } + + override fun getDamageProtection(level: Int, source: DamageSource): Int { + return 0 + } + + override fun getMinLevel(): Int { + return 1 + } + + override fun getMaxLevel(): Int { + return enchant.maxLevel + } + + override fun isCurse(): Boolean { + return false + } + + 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) + + return !enchant.conflictsWith(bukkit) + } + + override fun getSlotItems(entity: LivingEntity): MutableMap { + return mutableMapOf() + } +} 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 e2bf8743..24c61308 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 @@ -13,6 +13,7 @@ import com.willfp.ecoenchants.config.VanillaEnchantsYml import com.willfp.ecoenchants.display.DisplayCache import com.willfp.ecoenchants.display.EnchantDisplay import com.willfp.ecoenchants.display.EnchantSorter +import com.willfp.ecoenchants.enchant.registration.EnchantmentRegisterer import com.willfp.ecoenchants.enchants.EcoEnchantLevel import com.willfp.ecoenchants.enchants.EcoEnchants import com.willfp.ecoenchants.enchants.EnchantGUI @@ -47,6 +48,8 @@ class EcoEnchantsPlugin : LibreforgePlugin() { var isLoaded = false private set + val enchantmentRegisterer: EnchantmentRegisterer = TODO() + init { instance = this } diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/EcoEnchant.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/EcoEnchant.kt new file mode 100644 index 00000000..9e6cfebd --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/EcoEnchant.kt @@ -0,0 +1,82 @@ +package com.willfp.ecoenchants.enchant + +import com.willfp.eco.core.registry.KRegistrable +import com.willfp.ecoenchants.target.EnchantmentTarget +import com.willfp.libreforge.conditions.ConditionList +import com.willfp.libreforge.slot.SlotType +import org.bukkit.NamespacedKey +import org.bukkit.enchantments.Enchantment + +interface EcoEnchant : KRegistrable, EcoEnchantLike { + /** + * The key. + */ + val key: NamespacedKey + + /** + * The enchantment. + */ + override val enchantment: Enchantment + get() = this as Enchantment + + /** + * The max enchantment level. + */ + val maxLevel: Int + + /** + * The enchantment targets. + */ + val targets: Set + + /** + * The enchantment slots. + */ + val slots: Set + get() = targets.map { it.slot }.toSet() + + /** + * The conditions to use the enchantment. + */ + val conditions: ConditionList + + /** + * If the enchantment is enchantable. + */ + val isEnchantable: Boolean + + /** + * If the enchantment is tradeable. + */ + val isTradeable: Boolean + + /** + * If the enchantment is discoverable. + */ + val isDiscoverable: Boolean + + /** + * Get a certain [level]. + */ + fun getLevel(level: Int): EcoEnchantLevel + + /** + * Get if this enchantment conflicts with [other], only checking one way. + */ + fun conflictsWithDirectly(other: Enchantment): Boolean + + /** + * Get if this enchantment conflicts with [other]. + */ + fun conflictsWith(other: Enchantment): Boolean { + if (this.conflictsWithDirectly(other)) { + return true + } + + if (other is EcoEnchant) { + return other.conflictsWithDirectly(this as Enchantment) + } + + return false + } +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/EcoEnchantLevel.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/EcoEnchantLevel.kt new file mode 100644 index 00000000..55eda49b --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/EcoEnchantLevel.kt @@ -0,0 +1,42 @@ +package com.willfp.ecoenchants.enchant + +import com.willfp.eco.core.EcoPlugin +import com.willfp.libreforge.Holder +import com.willfp.libreforge.conditions.ConditionList +import com.willfp.libreforge.effects.EffectList +import java.util.Objects + +class EcoEnchantLevel( + val enchant: EcoEnchant, + val level: Int, + override val effects: EffectList, + override val conditions: ConditionList, + plugin: EcoPlugin +) : Holder { + override val id = plugin.createNamespacedKey("${enchant.id}_$level") + + override fun equals(other: Any?): Boolean { + if (other !is EcoEnchantLevel) { + return false + } + + return this.id == other.id + } + + override fun toString(): String { + return id.toString() + } + + override fun hashCode(): Int { + return Objects.hash(this.id) + } +} + +data class FoundEcoEnchantLevel( + val level: EcoEnchantLevel, + val activeLevel: Int +): Holder { + override val effects = level.effects + override val conditions = level.conditions + override val id = level.id +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/EcoEnchantLike.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/EcoEnchantLike.kt new file mode 100644 index 00000000..1f768a81 --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/EcoEnchantLike.kt @@ -0,0 +1,130 @@ +package com.willfp.ecoenchants.enchant + +import com.willfp.eco.core.config.interfaces.Config +import com.willfp.eco.core.fast.fast +import com.willfp.eco.core.placeholder.InjectablePlaceholder +import com.willfp.eco.core.placeholder.PlaceholderInjectable +import com.willfp.eco.core.placeholder.StaticPlaceholder +import com.willfp.eco.core.placeholder.context.placeholderContext +import com.willfp.eco.util.NumberUtils +import com.willfp.ecoenchants.EcoEnchantsPlugin +import com.willfp.ecoenchants.enchants.DescriptionPlaceholder +import com.willfp.ecoenchants.enchants.wrap +import com.willfp.ecoenchants.mechanics.infiniteIfNegative +import com.willfp.ecoenchants.rarity.EnchantmentRarity +import com.willfp.ecoenchants.type.EnchantmentType +import org.bukkit.Material +import org.bukkit.enchantments.Enchantment +import org.bukkit.entity.Player +import org.bukkit.inventory.ItemStack + +interface EcoEnchantLike { + /** + * The config. + */ + val config: Config + + /** + * The plugin. + */ + val plugin: EcoEnchantsPlugin + + /** + * The bukkit enchantment. + */ + val enchantment: Enchantment + + /** + * The raw display name. + */ + val rawDisplayName: String + + /** + * The enchantment type. + */ + val type: EnchantmentType + + /** + * The enchantment rarity. + */ + val rarity: EnchantmentRarity + + /** + * Get if this enchantment can be applied to [item]. + */ + fun canEnchantItem(item: ItemStack): Boolean { + if ( + item.fast().getEnchants(true).keys + .map { it.wrap() } + .count { it.type == this.type } >= this.type.limit + ) { + return false + } + + if (item.fast().getEnchants(true).any { (enchant, _) -> enchant.conflictsWithDeep(this.enchantment) }) { + return false + } + + if (item.fast().getEnchants(true).size >= plugin.configYml.getInt("anvil.enchant-limit").infiniteIfNegative()) { + return false + } + + if (item.type == Material.ENCHANTED_BOOK) { + return true + } + + return enchantment.canEnchantItem(item) + } + + /** + * Get the raw description for the enchantment. + */ + fun getRawDescription(level: Int, player: Player?): String { + // Fetch custom placeholders other than %placeholder% + val uncompiledPlaceholders = config.getSubsection("placeholders").getKeys(false).associateWith { + config.getString("placeholders.$it") + }.toMutableMap() + + // Add %placeholder% placeholder in + uncompiledPlaceholders["placeholder"] = config.getString("placeholder") + + // Evaluate each placeholder + val placeholders = uncompiledPlaceholders.map { (id, expr) -> + DescriptionPlaceholder( + id, + NumberUtils.evaluateExpression( + expr, + placeholderContext( + player = player, + injectable = object : PlaceholderInjectable { + override fun getPlaceholderInjections(): List { + return listOf( + StaticPlaceholder( + "level", + ) { level.toString() } + ) + } + + override fun addInjectablePlaceholder(p0: MutableIterable) { + // Do nothing + } + + override fun clearInjectedPlaceholders() { + // Do nothing + } + } + ) + ) + ) + } + + // Apply placeholders to description + val rawDescription = config.getString("description") + var description = rawDescription + for (placeholder in placeholders) { + description = description.replace("%${placeholder.id}%", NumberUtils.format(placeholder.value)) + } + + return description + } +} 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 new file mode 100644 index 00000000..cb945746 --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/EcoEnchants.kt @@ -0,0 +1,80 @@ +package com.willfp.ecoenchants.enchant + +import com.willfp.eco.core.config.interfaces.Config +import com.willfp.ecoenchants.EcoEnchantsPlugin +import com.willfp.ecoenchants.enchant.impl.LibreforgeEcoEnchant +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.enchants.sendPrompts +import com.willfp.ecoenchants.integrations.EnchantRegistrations +import com.willfp.ecoenchants.rarity.EnchantmentRarities +import com.willfp.ecoenchants.target.EnchantmentTargets +import com.willfp.ecoenchants.type.EnchantmentTypes +import com.willfp.libreforge.loader.LibreforgePlugin +import com.willfp.libreforge.loader.configs.RegistrableCategory + +@Suppress("UNUSED") +object EcoEnchants : RegistrableCategory("enchant", "enchants") { + override fun clear(plugin: LibreforgePlugin) { + plugin as EcoEnchantsPlugin + + for (enchant in registry.values()) { + plugin.enchantmentRegisterer.unregister(enchant) + EnchantRegistrations.removeEnchant(enchant) + } + + registry.clear() + } + + override fun beforeReload(plugin: LibreforgePlugin) { + plugin as EcoEnchantsPlugin + + EnchantmentRarities.update(plugin) + EnchantmentTargets.update(plugin) + EnchantmentTypes.update(plugin) + } + + override fun afterReload(plugin: LibreforgePlugin) { + plugin as EcoEnchantsPlugin + + sendPrompts(plugin) + registerHardcodedEnchantments(plugin) + } + + override fun acceptConfig(plugin: LibreforgePlugin, id: String, config: Config) { + plugin as EcoEnchantsPlugin + + val enchant = createEnchantment(plugin, id, config) ?: return + + registry.register(enchant) + plugin.enchantmentRegisterer.register(enchant) + EnchantRegistrations.registerEnchantments() + } + + private fun createEnchantment(plugin: LibreforgePlugin, id: String, config: Config): EcoEnchant? { + plugin as EcoEnchantsPlugin + + if (config.has("effects")) { + // Libreforge + return LibreforgeEcoEnchant( + id, + config, + plugin + ) + } else { + TODO() + } + } + + /** Register the hardcoded enchantments. */ + private fun registerHardcodedEnchantments( + plugin: EcoEnchantsPlugin + ) { + EnchantmentPermanenceCurse(plugin) + EnchantmentRepairing(plugin) + EnchantmentReplenish(plugin) + EnchantmentSoulbound(plugin) + } +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/Util.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/Util.kt new file mode 100644 index 00000000..2cd838b9 --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/Util.kt @@ -0,0 +1,23 @@ +package com.willfp.ecoenchants.enchant + +import com.willfp.ecoenchants.EcoEnchantsPlugin +import com.willfp.ecoenchants.enchant.impl.VanillaEcoEnchantLike +import org.bukkit.NamespacedKey +import org.bukkit.enchantments.Enchantment + + +private val ecoEnchantLikes = mutableMapOf() + +fun Enchantment.wrap(): EcoEnchantLike { + if (this is EcoEnchant) { + return this + } + + return ecoEnchantLikes.getOrPut(this.key) { + VanillaEcoEnchantLike(this, EcoEnchantsPlugin.instance) + } +} + +fun Enchantment.conflictsWithDeep(other: Enchantment): Boolean { + return this.conflictsWith(other) || other.conflictsWith(this) +} 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 new file mode 100644 index 00000000..141aebb2 --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/impl/EcoEnchantBase.kt @@ -0,0 +1,74 @@ +package com.willfp.ecoenchants.enchant.impl + +import com.willfp.eco.core.config.interfaces.Config +import com.willfp.ecoenchants.EcoEnchantsPlugin +import com.willfp.ecoenchants.enchant.EcoEnchant +import com.willfp.ecoenchants.enchant.EcoEnchantLevel +import com.willfp.ecoenchants.rarity.EnchantmentRarities +import com.willfp.ecoenchants.rarity.EnchantmentRarity +import com.willfp.ecoenchants.target.EnchantmentTargets +import com.willfp.ecoenchants.type.EnchantmentType +import com.willfp.ecoenchants.type.EnchantmentTypes +import com.willfp.libreforge.ViolationContext +import com.willfp.libreforge.conditions.Conditions +import org.bukkit.NamespacedKey +import org.bukkit.enchantments.Enchantment + +abstract class EcoEnchantBase( + final override val id: String, + final override val plugin: EcoEnchantsPlugin, +) : EcoEnchant { + protected val context = ViolationContext(plugin, "enchantment $id") + + final override val config by lazy { loadConfig() } + + private val levels = mutableMapOf() + + private val conflictIds = config.getStrings("conflicts").toSet() + + override val key = NamespacedKey.minecraft(id) + + override val rawDisplayName = config.getString("display-name") + + override val maxLevel = config.getInt("max-level") + + override val targets = config.getStrings("targets") + .mapNotNull { EnchantmentTargets[it] } + .toSet() + + override val type: EnchantmentType = config.getString("type") + .let { EnchantmentTypes[it] } + ?: EnchantmentTypes.values().first() + + override val rarity: EnchantmentRarity = config.getString("rarity") + .let { EnchantmentRarities[it] } + ?: EnchantmentRarities.values().first() + + override val conditions = Conditions.compile( + config.getSubsections("conditions"), + context.with("conditions") + ) + + override val isEnchantable = config.getBool("enchantable") + + override val isTradeable = config.getBool("tradeable") + + override val isDiscoverable = config.getBool("discoverable") + + /** + * Load the config for this enchant. + */ + protected abstract fun loadConfig(): Config + + override fun getLevel(level: Int): EcoEnchantLevel { + return levels.getOrPut(level) { + createLevel(level) + } + } + + protected abstract fun createLevel(level: Int): EcoEnchantLevel + + override fun conflictsWithDirectly(other: Enchantment): Boolean { + return other.key.key in conflictIds + } +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/impl/HardcodedEcoEnchant.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/impl/HardcodedEcoEnchant.kt new file mode 100644 index 00000000..667a86b4 --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/impl/HardcodedEcoEnchant.kt @@ -0,0 +1,25 @@ +package com.willfp.ecoenchants.enchant.impl + +import com.willfp.eco.core.config.ConfigType +import com.willfp.eco.core.config.interfaces.Config +import com.willfp.eco.core.config.readConfig +import com.willfp.ecoenchants.EcoEnchantsPlugin +import com.willfp.ecoenchants.enchant.EcoEnchantLevel +import com.willfp.libreforge.effects.emptyEffectList +import java.io.File + +abstract class HardcodedEcoEnchant( + id: String, + plugin: EcoEnchantsPlugin +) : EcoEnchantBase(id, plugin) { + final override fun loadConfig(): Config { + return File(plugin.dataFolder, "enchants") + .walk() + .firstOrNull { file -> file.nameWithoutExtension == id } + .readConfig(ConfigType.YAML) + } + + override fun createLevel(level: Int): EcoEnchantLevel { + return EcoEnchantLevel(this, level, emptyEffectList(), conditions, plugin) + } +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/impl/LibreforgeEcoEnchant.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/impl/LibreforgeEcoEnchant.kt new file mode 100644 index 00000000..b511c7d9 --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/impl/LibreforgeEcoEnchant.kt @@ -0,0 +1,26 @@ +package com.willfp.ecoenchants.enchant.impl + +import com.willfp.eco.core.config.interfaces.Config +import com.willfp.ecoenchants.EcoEnchantsPlugin +import com.willfp.ecoenchants.enchant.EcoEnchantLevel +import com.willfp.libreforge.SilentViolationContext +import com.willfp.libreforge.effects.Effects + +class LibreforgeEcoEnchant( + id: String, + private val _config: Config, + plugin: EcoEnchantsPlugin +) : EcoEnchantBase(id, plugin) { + private val effects = Effects.compile( + config.getSubsections("effects"), + if (plugin.isLoaded) context.with("effects") else SilentViolationContext + ) + + override fun loadConfig(): Config { + return _config + } + + override fun createLevel(level: Int): EcoEnchantLevel { + return EcoEnchantLevel(this, level, effects, conditions, plugin) + } +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/impl/VanillaEcoEnchantLike.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/impl/VanillaEcoEnchantLike.kt new file mode 100644 index 00000000..22899c9f --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/impl/VanillaEcoEnchantLike.kt @@ -0,0 +1,39 @@ +package com.willfp.ecoenchants.enchant.impl + +import com.willfp.ecoenchants.EcoEnchantsPlugin +import com.willfp.ecoenchants.enchant.EcoEnchantLike +import com.willfp.ecoenchants.rarity.EnchantmentRarities +import com.willfp.ecoenchants.rarity.EnchantmentRarity +import com.willfp.ecoenchants.type.EnchantmentType +import com.willfp.ecoenchants.type.EnchantmentTypes +import org.bukkit.enchantments.Enchantment +import java.util.Objects + +class VanillaEcoEnchantLike( + override val enchantment: Enchantment, + override val plugin: EcoEnchantsPlugin +) : EcoEnchantLike { + override val config = plugin.vanillaEnchantsYml.getSubsection(enchantment.key.key) + + override val type: EnchantmentType = + EnchantmentTypes[plugin.vanillaEnchantsYml.getString("${enchantment.key.key}.type")] + ?: EnchantmentTypes.values().first() + + override val rarity: EnchantmentRarity = + EnchantmentRarities[plugin.vanillaEnchantsYml.getString("${enchantment.key.key}.rarity")] + ?: EnchantmentRarities.values().first() + + override val rawDisplayName = plugin.vanillaEnchantsYml.getString("${enchantment.key.key}.name") + + override fun equals(other: Any?): Boolean { + if (other !is VanillaEcoEnchantLike) { + return false + } + + return this.enchantment == other.enchantment + } + + override fun hashCode(): Int { + return Objects.hash(this.enchantment) + } +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/impl/hardcoded/EnchantmentPermanenceCurse.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/impl/hardcoded/EnchantmentPermanenceCurse.kt new file mode 100644 index 00000000..3886f6b9 --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/impl/hardcoded/EnchantmentPermanenceCurse.kt @@ -0,0 +1,13 @@ +package com.willfp.ecoenchants.enchant.impl.hardcoded + +import com.willfp.ecoenchants.EcoEnchantsPlugin +import com.willfp.ecoenchants.enchant.impl.HardcodedEcoEnchant + +class EnchantmentPermanenceCurse( + plugin: EcoEnchantsPlugin +) : HardcodedEcoEnchant( + "permanence_curse", + plugin +) { + +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchants/impl/EnchantmentRepairing.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/impl/hardcoded/EnchantmentRepairing.kt similarity index 96% rename from eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchants/impl/EnchantmentRepairing.kt rename to eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/impl/hardcoded/EnchantmentRepairing.kt index 4a9434eb..f8dc6777 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchants/impl/EnchantmentRepairing.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/impl/hardcoded/EnchantmentRepairing.kt @@ -1,4 +1,4 @@ -package com.willfp.ecoenchants.enchants.impl +package com.willfp.ecoenchants.enchant.impl.hardcoded import com.willfp.eco.util.DurabilityUtils import com.willfp.ecoenchants.EcoEnchantsPlugin diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchants/impl/EnchantmentReplenish.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/impl/hardcoded/EnchantmentReplenish.kt similarity index 98% rename from eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchants/impl/EnchantmentReplenish.kt rename to eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/impl/hardcoded/EnchantmentReplenish.kt index bea67b96..dfe07358 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchants/impl/EnchantmentReplenish.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/impl/hardcoded/EnchantmentReplenish.kt @@ -1,4 +1,4 @@ -package com.willfp.ecoenchants.enchants.impl +package com.willfp.ecoenchants.enchant.impl.hardcoded import com.willfp.eco.core.EcoPlugin import com.willfp.ecoenchants.EcoEnchantsPlugin diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchants/impl/EnchantmentSoulbound.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/impl/hardcoded/EnchantmentSoulbound.kt similarity index 98% rename from eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchants/impl/EnchantmentSoulbound.kt rename to eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/impl/hardcoded/EnchantmentSoulbound.kt index e63a264e..856ca18d 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchants/impl/EnchantmentSoulbound.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/impl/hardcoded/EnchantmentSoulbound.kt @@ -1,4 +1,4 @@ -package com.willfp.ecoenchants.enchants.impl +package com.willfp.ecoenchants.enchant.impl.hardcoded import com.willfp.eco.core.EcoPlugin import com.willfp.eco.core.Prerequisite diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/registration/EnchantmentRegisterer.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/registration/EnchantmentRegisterer.kt new file mode 100644 index 00000000..61f675ab --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/registration/EnchantmentRegisterer.kt @@ -0,0 +1,9 @@ +package com.willfp.ecoenchants.enchant.registration + +import com.willfp.ecoenchants.enchant.EcoEnchant + +interface EnchantmentRegisterer { + fun register(enchant: EcoEnchant) + + fun unregister(enchant: EcoEnchant) +} \ No newline at end of file diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/registration/legacy/LegacyDelegatedEnchantment.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/registration/legacy/LegacyDelegatedEnchantment.kt new file mode 100644 index 00000000..542bb132 --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/registration/legacy/LegacyDelegatedEnchantment.kt @@ -0,0 +1,87 @@ +package com.willfp.ecoenchants.enchant.registration.legacy + +import com.willfp.eco.util.StringUtils +import com.willfp.ecoenchants.display.getFormattedName +import com.willfp.ecoenchants.enchant.EcoEnchant +import com.willfp.ecoenchants.enchants.wrap +import io.papermc.paper.enchantments.EnchantmentRarity +import net.kyori.adventure.text.Component +import org.bukkit.enchantments.Enchantment +import org.bukkit.enchantments.EnchantmentTarget +import org.bukkit.entity.EntityCategory +import org.bukkit.inventory.EquipmentSlot + +@Suppress("DEPRECATION") +class LegacyDelegatedEnchantment( + private val enchant: EcoEnchant +) : Enchantment(enchant.key), EcoEnchant by enchant { + 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 { + return maxLevel + } + + override fun getStartLevel(): Int { + return 1 + } + + @Deprecated( + message = "getItemTargets is an incompatible Spigot API", + replaceWith = ReplaceWith("this.targets") + ) + override fun getItemTarget(): EnchantmentTarget = EnchantmentTarget.ALL + + @Deprecated( + message = "Treasure enchantments do not exist in EcoEnchants", + replaceWith = ReplaceWith("this.isEnchantable") + ) + override fun isTreasure(): Boolean = !isEnchantable + + @Deprecated( + message = "Use EnchantmentType instead", + replaceWith = ReplaceWith("type.id") + ) + override fun isCursed(): Boolean { + return false + } + + override fun displayName(level: Int): Component { + return StringUtils.toComponent(this.wrap().getFormattedName(level)) + } + + override fun isTradeable(): Boolean { + return isTradeable + } + + override fun isDiscoverable(): Boolean { + return isDiscoverable + } + + @Deprecated( + message = "EcoEnchants uses a custom system for enchantment rarity", + replaceWith = ReplaceWith("this.enchantRarity") + ) + override fun getRarity(): EnchantmentRarity { + return EnchantmentRarity.RARE + } + + @Deprecated( + message = "EcoEnchants do not have damage increase, this method is for sharpness/boa/smite", + replaceWith = ReplaceWith("0.0f") + ) + override fun getDamageIncrease(level: Int, entityCategory: EntityCategory): Float = 0.0f + + @Deprecated( + message = "getActiveSlots is an incompatible Paper API", + replaceWith = ReplaceWith("this.slots") + ) + override fun getActiveSlots() = emptySet() +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/registration/legacy/LegacyEnchantmentRegisterer.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/registration/legacy/LegacyEnchantmentRegisterer.kt new file mode 100644 index 00000000..18fd586d --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/registration/legacy/LegacyEnchantmentRegisterer.kt @@ -0,0 +1,33 @@ +package com.willfp.ecoenchants.enchant.registration.legacy + +import com.willfp.ecoenchants.enchant.EcoEnchant +import com.willfp.ecoenchants.enchant.registration.EnchantmentRegisterer +import org.bukkit.NamespacedKey +import org.bukkit.enchantments.Enchantment + +@Suppress("UNCHECKED_CAST") +object LegacyEnchantmentRegisterer : EnchantmentRegisterer { + override fun register(enchant: EcoEnchant) { + Enchantment::class.java.getDeclaredField("acceptingNew") + .apply { + isAccessible = true + set(null, true) + } + + Enchantment.registerEnchantment(LegacyDelegatedEnchantment(enchant)) + } + + override fun unregister(enchant: EcoEnchant) { + Enchantment::class.java.getDeclaredField("byKey") + .apply { + isAccessible = true + (get(null) as MutableMap).apply { remove(enchant.key) } + } + + Enchantment::class.java.getDeclaredField("byName") + .apply { + isAccessible = true + (get(null) as MutableMap).apply { remove(enchant.id.uppercase()) } + } + } +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/registration/modern/ModernEnchantmentRegistererProxy.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/registration/modern/ModernEnchantmentRegistererProxy.kt new file mode 100644 index 00000000..4714493a --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchant/registration/modern/ModernEnchantmentRegistererProxy.kt @@ -0,0 +1,6 @@ +package com.willfp.ecoenchants.enchant.registration.modern + +import com.willfp.ecoenchants.enchant.registration.EnchantmentRegisterer + +interface ModernEnchantmentRegistererProxy : EnchantmentRegisterer { +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchants/EcoEnchant.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchants/EcoEnchant.kt index 2f46e5f4..0bf1efd2 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchants/EcoEnchant.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchants/EcoEnchant.kt @@ -9,6 +9,7 @@ import com.willfp.eco.core.fast.fast import com.willfp.eco.core.placeholder.PlayerlessPlaceholder import com.willfp.eco.core.placeholder.context.PlaceholderContext import com.willfp.eco.core.placeholder.templates.SimpleInjectablePlaceholder +import com.willfp.eco.core.registry.KRegistrable import com.willfp.eco.util.StringUtils import com.willfp.eco.util.containsIgnoreCase import com.willfp.ecoenchants.EcoEnchantsPlugin @@ -41,10 +42,10 @@ import java.util.Objects @Suppress("DEPRECATION") abstract class EcoEnchant( - val id: String, + override val id: String, configProvider: (EcoEnchant) -> Config, protected val plugin: EcoEnchantsPlugin -) : Enchantment(NamespacedKey.minecraft(id)), EcoEnchantLike { +) : Enchantment(NamespacedKey.minecraft(id)), EcoEnchantLike, KRegistrable { final override val config by lazy { configProvider(this) } override val enchant by lazy { this } diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchants/EcoEnchantLike.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchants/EcoEnchantLike.kt index f0db000e..58bff892 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchants/EcoEnchantLike.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchants/EcoEnchantLike.kt @@ -33,59 +33,6 @@ interface EcoEnchantLike { // Includes all extra logic not found in vanilla canEnchantItem fun canEnchantItem(item: ItemStack): Boolean - - // Method body goes here - fun getUnformattedDescription(level: Int, player: Player? = null): String { - // Fetch custom placeholders other than %placeholder% - val uncompiledPlaceholders = config.getSubsection("placeholders").getKeys(false).associateWith { - config.getString("placeholders.$it") - }.toMutableMap() - - // Add %placeholder% placeholder in - uncompiledPlaceholders["placeholder"] = config.getString("placeholder") - - - - // Evaluate each placeholder - val placeholders = uncompiledPlaceholders.map { (id, expr) -> - DescriptionPlaceholder( - id, - NumberUtils.evaluateExpression( - expr, - placeholderContext( - player = player, - injectable = object : PlaceholderInjectable { - override fun getPlaceholderInjections(): List { - return listOf( - StaticPlaceholder( - "level", - ) { level.toString() } - ) - } - - override fun addInjectablePlaceholder(p0: MutableIterable) { - // Do nothing - } - - override fun clearInjectedPlaceholders() { - // Do nothing - } - } - ) - ) - ) - } - - // Apply placeholders to description - val rawDescription = config.getString("description") - var description = rawDescription - for (placeholder in placeholders) { - description = description.replace("%${placeholder.id}%", NumberUtils.format(placeholder.value)) - } - - return description - } - // Java backwards compatibility fun getUnformattedDescription(level: Int): String { return getUnformattedDescription(level, null) diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchants/EcoEnchants.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchants/EcoEnchants.kt index ed525d97..30a8c675 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchants/EcoEnchants.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchants/EcoEnchants.kt @@ -1,90 +1,22 @@ package com.willfp.ecoenchants.enchants -import com.google.common.collect.HashBiMap -import com.google.common.collect.ImmutableSet import com.willfp.eco.core.config.interfaces.Config import com.willfp.ecoenchants.EcoEnchantsPlugin -import com.willfp.ecoenchants.enchants.impl.EnchantmentPermanenceCurse -import com.willfp.ecoenchants.enchants.impl.EnchantmentRepairing -import com.willfp.ecoenchants.enchants.impl.EnchantmentReplenish -import com.willfp.ecoenchants.enchants.impl.EnchantmentSoulbound +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.integrations.EnchantRegistrations import com.willfp.ecoenchants.rarity.EnchantmentRarities import com.willfp.ecoenchants.target.EnchantmentTargets import com.willfp.ecoenchants.type.EnchantmentTypes import com.willfp.libreforge.loader.LibreforgePlugin -import com.willfp.libreforge.loader.configs.ConfigCategory -import org.bukkit.ChatColor +import com.willfp.libreforge.loader.configs.RegistrableCategory import org.bukkit.NamespacedKey import org.bukkit.enchantments.Enchantment @Suppress("UNUSED") -object EcoEnchants : ConfigCategory("enchant", "enchants") { - private val BY_KEY = HashBiMap.create() - private val BY_NAME = HashBiMap.create() - - override val shouldPreload = true - - /** - * Get all registered [EcoEnchant]s. - * - * @return A list of all [EcoEnchant]s. - */ - @JvmStatic - fun values(): Set { - return ImmutableSet.copyOf(BY_KEY.values) - } - - /** - * Get [String]s for all registered [EcoEnchant]s. - * - * @return A list of all [EcoEnchant]s. - */ - @JvmStatic - fun keySet(): Set { - return ImmutableSet.copyOf(BY_KEY.keys) - } - - /** - * Get [EcoEnchant] matching id. - * - * @param id The id to search for. - * @return The matching [EcoEnchant], or null if not found. - */ - @JvmStatic - fun getByID(id: String?): EcoEnchant? { - return if (id == null) { - null - } else BY_KEY[id] - } - - /** - * Get [EcoEnchant] matching key. - * - * @param key The key to search for. - * @return The matching [EcoEnchant], or null if not found. - */ - @JvmStatic - fun getByKey(key: NamespacedKey?): EcoEnchant? { - return if (key == null) { - null - } else getByID(key.key) - } - - /** - * Get [EcoEnchant] matching name. - * - * @param name The name to search for. - * @return The matching [EcoEnchant], or null if not found. - */ - @JvmStatic - fun getByName(name: String?): EcoEnchant? { - return if (name == null) { - null - } else BY_NAME[name] - } - - +object EcoEnchants : RegistrableCategory("enchant", "enchants") { override fun clear(plugin: LibreforgePlugin) { for (enchant in values()) { removeEnchant(enchant) @@ -135,8 +67,7 @@ object EcoEnchants : ConfigCategory("enchant", "enchants") { @Suppress("UNCHECKED_CAST", "DEPRECATION") fun removeEnchant(enchant: Enchantment) { if (enchant is EcoEnchant) { - BY_KEY.remove(enchant.id) - BY_NAME.remove(ChatColor.stripColor(enchant.displayName)) + registry.remove(enchant.id) EnchantRegistrations.removeEnchant(enchant) } @@ -163,9 +94,6 @@ object EcoEnchants : ConfigCategory("enchant", "enchants") { */ internal fun addNewEnchant(enchant: EcoEnchant) { register(enchant) - - BY_KEY[enchant.id] = enchant - BY_NAME[ChatColor.stripColor(enchant.displayName)] = enchant } /** diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchants/impl/EnchantmentPermanenceCurse.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchants/impl/EnchantmentPermanenceCurse.kt deleted file mode 100644 index ae57a590..00000000 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchants/impl/EnchantmentPermanenceCurse.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.willfp.ecoenchants.enchants.impl - -import com.willfp.ecoenchants.EcoEnchantsPlugin -import com.willfp.ecoenchants.enchants.EcoEnchant - -class EnchantmentPermanenceCurse( - plugin: EcoEnchantsPlugin -) : EcoEnchant( - "permanence_curse", - plugin, - force = false -) diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/integrations/EnchantRegistrationIntegration.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/integrations/EnchantRegistrationIntegration.kt index 6ffc76f8..a985c35d 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/integrations/EnchantRegistrationIntegration.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/integrations/EnchantRegistrationIntegration.kt @@ -1,8 +1,7 @@ package com.willfp.ecoenchants.integrations import com.willfp.eco.core.integrations.Integration -import com.willfp.ecoenchants.enchants.EcoEnchant -import org.jetbrains.annotations.NotNull +import com.willfp.ecoenchants.enchant.EcoEnchant interface EnchantRegistrationIntegration : Integration { diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/integrations/plugins/EssentialsIntegration.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/integrations/plugins/EssentialsIntegration.kt index 2f8b2aab..81ed90ce 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/integrations/plugins/EssentialsIntegration.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/integrations/plugins/EssentialsIntegration.kt @@ -1,14 +1,13 @@ package com.willfp.ecoenchants.integrations.plugins import com.earth2me.essentials.Enchantments -import com.willfp.ecoenchants.enchants.EcoEnchant -import com.willfp.ecoenchants.enchants.EcoEnchants +import com.willfp.ecoenchants.enchant.EcoEnchant +import com.willfp.ecoenchants.enchant.EcoEnchants import com.willfp.ecoenchants.integrations.EnchantRegistrationIntegration -import org.bukkit.NamespacedKey import org.bukkit.enchantments.Enchantment @Suppress("UNCHECKED_CAST") -class EssentialsIntegration: EnchantRegistrationIntegration { +class EssentialsIntegration : EnchantRegistrationIntegration { override fun registerEnchants() { for (enchantment in EcoEnchants.values()) { // why aren't you using the api you PRd in @@ -18,8 +17,8 @@ class EssentialsIntegration: EnchantRegistrationIntegration { .apply { isAccessible = true (get(null) as MutableMap).apply { - put(enchantment.id, enchantment) - put(enchantment.id.replace("_",""), enchantment) + put(enchantment.id, enchantment.enchantment) + put(enchantment.id.replace("_", ""), enchantment.enchantment) } } } @@ -33,7 +32,7 @@ class EssentialsIntegration: EnchantRegistrationIntegration { isAccessible = true (get(null) as MutableMap).apply { remove(enchantment.id) - remove(enchantment.id.replace("_","")) + remove(enchantment.id.replace("_", "")) } } } diff --git a/settings.gradle.kts b/settings.gradle.kts index 1c3f8ddd..242bed00 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -3,6 +3,7 @@ pluginManagement { gradlePluginPortal() mavenLocal() maven("https://repo.auxilor.io/repository/maven-public/") + maven("https://repo.papermc.io/repository/maven-public/") } } @@ -21,3 +22,4 @@ include(":eco-core:core-nms:v1_19_R2") 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")