diff --git a/src/main/kotlin/org/xodium/vanillaplus/VanillaPlusBootstrap.kt b/src/main/kotlin/org/xodium/vanillaplus/VanillaPlusBootstrap.kt index 809cd4a96..9252a4009 100644 --- a/src/main/kotlin/org/xodium/vanillaplus/VanillaPlusBootstrap.kt +++ b/src/main/kotlin/org/xodium/vanillaplus/VanillaPlusBootstrap.kt @@ -13,6 +13,7 @@ import io.papermc.paper.registry.keys.tags.ItemTypeTagKeys import io.papermc.paper.registry.tag.TagKey import io.papermc.paper.tag.TagEntry import net.kyori.adventure.key.Key +import org.xodium.vanillaplus.enchantments.NightVisionEnchantment import org.xodium.vanillaplus.enchantments.PickupEnchantment import org.xodium.vanillaplus.enchantments.ReplantEnchantment @@ -23,7 +24,8 @@ internal class VanillaPlusBootstrap : PluginBootstrap { const val INSTANCE = "vanillaplus" val REPLANT = ReplantEnchantment.key val PICKUP = PickupEnchantment.key - val ENCHANTS = setOf(REPLANT, PICKUP) + val NIGHT_VISION = NightVisionEnchantment.key + val ENCHANTS = setOf(REPLANT, PICKUP, NIGHT_VISION) val TOOLS = TagKey.create(RegistryKey.ITEM, Key.key(INSTANCE, "tools")) } @@ -47,9 +49,20 @@ internal class VanillaPlusBootstrap : PluginBootstrap { RegistryEvents.ENCHANTMENT.compose().newHandler { event -> event.registry().apply { register(REPLANT) { - ReplantEnchantment.builder(it).supportedItems(event.getOrCreateTag(ItemTypeTagKeys.HOES)) + ReplantEnchantment + .builder(it) + .supportedItems(event.getOrCreateTag(ItemTypeTagKeys.HOES)) + } + register(PICKUP) { + PickupEnchantment + .builder(it) + .supportedItems(event.getOrCreateTag(TOOLS)) + } + register(NIGHT_VISION) { + NightVisionEnchantment + .builder(it) + .supportedItems(event.getOrCreateTag(ItemTypeTagKeys.HEAD_ARMOR)) } - register(PICKUP) { PickupEnchantment.builder(it).supportedItems(event.getOrCreateTag(TOOLS)) } } }, ) diff --git a/src/main/kotlin/org/xodium/vanillaplus/enchantments/NightVisionEnchantment.kt b/src/main/kotlin/org/xodium/vanillaplus/enchantments/NightVisionEnchantment.kt new file mode 100644 index 000000000..de5abbd47 --- /dev/null +++ b/src/main/kotlin/org/xodium/vanillaplus/enchantments/NightVisionEnchantment.kt @@ -0,0 +1,41 @@ +package org.xodium.vanillaplus.enchantments + +import io.papermc.paper.event.entity.EntityEquipmentChangedEvent +import io.papermc.paper.registry.data.EnchantmentRegistryEntry +import org.bukkit.entity.Player +import org.bukkit.inventory.EquipmentSlotGroup +import org.bukkit.potion.PotionEffect +import org.bukkit.potion.PotionEffectType +import org.xodium.vanillaplus.interfaces.EnchantmentInterface +import org.xodium.vanillaplus.utils.ExtUtils.mm + +/** Represents an object handling night vision enchantment implementation within the system. */ +@Suppress("UnstableApiUsage") +internal object NightVisionEnchantment : EnchantmentInterface { + override fun builder(builder: EnchantmentRegistryEntry.Builder): EnchantmentRegistryEntry.Builder = + builder + .description(key.value().replaceFirstChar { it.uppercase() }.mm()) + .anvilCost(2) + .maxLevel(1) + .weight(2) + .minimumCost(EnchantmentRegistryEntry.EnchantmentCost.of(25, 0)) + .maximumCost(EnchantmentRegistryEntry.EnchantmentCost.of(75, 0)) + .activeSlots(EquipmentSlotGroup.ARMOR) + + /** + * Handles the equipment change event to apply or remove night vision effect based on the helmet enchantment. + * @param event The EntityEquipmentChangedEvent triggered when an entity's equipment changes. + */ + fun nightVision(event: EntityEquipmentChangedEvent) { + val player = event.entity as? Player ?: return + val helmet = player.inventory.helmet + + if (helmet != null && helmet.hasItemMeta() && helmet.itemMeta.hasEnchant(get())) { + player.addPotionEffect(PotionEffect(PotionEffectType.NIGHT_VISION, -1, 0, true, false, true)) + } else { + player.activePotionEffects + .filter { it.type == PotionEffectType.NIGHT_VISION } + .forEach { if (it.duration == -1) player.removePotionEffect(PotionEffectType.NIGHT_VISION) } + } + } +} diff --git a/src/main/kotlin/org/xodium/vanillaplus/enchantments/PickupEnchantment.kt b/src/main/kotlin/org/xodium/vanillaplus/enchantments/PickupEnchantment.kt index b858921ce..ab82f4edb 100644 --- a/src/main/kotlin/org/xodium/vanillaplus/enchantments/PickupEnchantment.kt +++ b/src/main/kotlin/org/xodium/vanillaplus/enchantments/PickupEnchantment.kt @@ -1,29 +1,22 @@ package org.xodium.vanillaplus.enchantments -import io.papermc.paper.registry.RegistryKey -import io.papermc.paper.registry.TypedKey import io.papermc.paper.registry.data.EnchantmentRegistryEntry -import net.kyori.adventure.key.Key -import org.bukkit.enchantments.Enchantment import org.bukkit.event.block.BlockBreakEvent import org.bukkit.inventory.EquipmentSlotGroup -import org.xodium.vanillaplus.VanillaPlusBootstrap.Companion.INSTANCE import org.xodium.vanillaplus.interfaces.EnchantmentInterface import org.xodium.vanillaplus.utils.ExtUtils.mm +/** Represents an object handling pickup enchantment implementation within the system. */ @Suppress("UnstableApiUsage") internal object PickupEnchantment : EnchantmentInterface { - override val key: TypedKey = TypedKey.create(RegistryKey.ENCHANTMENT, Key.key(INSTANCE, "pickup")) - override fun builder(builder: EnchantmentRegistryEntry.Builder): EnchantmentRegistryEntry.Builder = builder .description(key.value().replaceFirstChar { it.uppercase() }.mm()) - // TODO: Adjust costs and levels as needed - .anvilCost(8) + .anvilCost(2) .maxLevel(1) - .weight(5) - .minimumCost(EnchantmentRegistryEntry.EnchantmentCost.of(1, 10)) - .maximumCost(EnchantmentRegistryEntry.EnchantmentCost.of(8, 20)) + .weight(2) + .minimumCost(EnchantmentRegistryEntry.EnchantmentCost.of(25, 0)) + .maximumCost(EnchantmentRegistryEntry.EnchantmentCost.of(75, 0)) .activeSlots(EquipmentSlotGroup.MAINHAND) /** diff --git a/src/main/kotlin/org/xodium/vanillaplus/enchantments/ReplantEnchantment.kt b/src/main/kotlin/org/xodium/vanillaplus/enchantments/ReplantEnchantment.kt index 9a7fb9c2f..1e5d7b69e 100644 --- a/src/main/kotlin/org/xodium/vanillaplus/enchantments/ReplantEnchantment.kt +++ b/src/main/kotlin/org/xodium/vanillaplus/enchantments/ReplantEnchantment.kt @@ -1,31 +1,24 @@ package org.xodium.vanillaplus.enchantments -import io.papermc.paper.registry.RegistryKey -import io.papermc.paper.registry.TypedKey import io.papermc.paper.registry.data.EnchantmentRegistryEntry -import net.kyori.adventure.key.Key import org.bukkit.block.data.Ageable -import org.bukkit.enchantments.Enchantment import org.bukkit.event.block.BlockBreakEvent import org.bukkit.inventory.EquipmentSlotGroup import org.xodium.vanillaplus.VanillaPlus.Companion.instance -import org.xodium.vanillaplus.VanillaPlusBootstrap.Companion.INSTANCE import org.xodium.vanillaplus.interfaces.EnchantmentInterface import org.xodium.vanillaplus.utils.ExtUtils.mm +/** Represents an object handling replant enchantment implementation within the system. */ @Suppress("UnstableApiUsage") internal object ReplantEnchantment : EnchantmentInterface { - override val key: TypedKey = TypedKey.create(RegistryKey.ENCHANTMENT, Key.key(INSTANCE, "replant")) - override fun builder(builder: EnchantmentRegistryEntry.Builder): EnchantmentRegistryEntry.Builder = builder .description(key.value().replaceFirstChar { it.uppercase() }.mm()) - // TODO: Adjust costs and levels as needed - .anvilCost(8) + .anvilCost(2) .maxLevel(1) - .weight(5) - .minimumCost(EnchantmentRegistryEntry.EnchantmentCost.of(1, 10)) - .maximumCost(EnchantmentRegistryEntry.EnchantmentCost.of(8, 20)) + .weight(2) + .minimumCost(EnchantmentRegistryEntry.EnchantmentCost.of(25, 0)) + .maximumCost(EnchantmentRegistryEntry.EnchantmentCost.of(75, 0)) .activeSlots(EquipmentSlotGroup.MAINHAND) /** diff --git a/src/main/kotlin/org/xodium/vanillaplus/interfaces/EnchantmentInterface.kt b/src/main/kotlin/org/xodium/vanillaplus/interfaces/EnchantmentInterface.kt index 3c972a266..d345b0ee3 100644 --- a/src/main/kotlin/org/xodium/vanillaplus/interfaces/EnchantmentInterface.kt +++ b/src/main/kotlin/org/xodium/vanillaplus/interfaces/EnchantmentInterface.kt @@ -4,17 +4,33 @@ import io.papermc.paper.registry.RegistryAccess import io.papermc.paper.registry.RegistryKey import io.papermc.paper.registry.TypedKey import io.papermc.paper.registry.data.EnchantmentRegistryEntry +import net.kyori.adventure.key.Key import org.bukkit.enchantments.Enchantment +import org.xodium.vanillaplus.VanillaPlusBootstrap.Companion.INSTANCE /** Represents a contract for enchantments within the system. */ @Suppress("UnstableApiUsage") internal interface EnchantmentInterface { /** - * The unique typed key that identifies this enchantment in the registry. + * The unique typed key identifies this enchantment in the registry. * @see TypedKey * @see RegistryKey.ENCHANTMENT */ val key: TypedKey + get() = + TypedKey.create( + RegistryKey.ENCHANTMENT, + Key.key( + INSTANCE, + this::class + .simpleName + ?.removeSuffix("Enchantment") + ?.split(Regex("(?=[A-Z])")) + ?.filter { it.isNotEmpty() } + ?.joinToString("_") { it.lowercase() } + .toString(), + ), + ) /** * Configures the properties of the enchantment using the provided builder. diff --git a/src/main/kotlin/org/xodium/vanillaplus/modules/PlayerModule.kt b/src/main/kotlin/org/xodium/vanillaplus/modules/PlayerModule.kt index e11671b6a..ce9c27ee6 100644 --- a/src/main/kotlin/org/xodium/vanillaplus/modules/PlayerModule.kt +++ b/src/main/kotlin/org/xodium/vanillaplus/modules/PlayerModule.kt @@ -5,6 +5,7 @@ import io.papermc.paper.command.brigadier.Commands import io.papermc.paper.datacomponent.DataComponentTypes import io.papermc.paper.datacomponent.item.ItemLore import io.papermc.paper.datacomponent.item.ResolvableProfile +import io.papermc.paper.event.entity.EntityEquipmentChangedEvent import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder import org.bukkit.Material import org.bukkit.entity.Player @@ -24,6 +25,7 @@ import org.bukkit.permissions.Permission import org.bukkit.permissions.PermissionDefault import org.xodium.vanillaplus.VanillaPlus.Companion.instance import org.xodium.vanillaplus.data.CommandData +import org.xodium.vanillaplus.enchantments.NightVisionEnchantment import org.xodium.vanillaplus.enchantments.PickupEnchantment import org.xodium.vanillaplus.enchantments.ReplantEnchantment import org.xodium.vanillaplus.interfaces.ModuleInterface @@ -168,6 +170,13 @@ internal class PlayerModule( PickupEnchantment.pickup(event) } + @EventHandler + fun on(event: EntityEquipmentChangedEvent) { + if (!enabled()) return + + NightVisionEnchantment.nightVision(event) + } + /** * Handles the interaction event where a player can convert their experience points into an experience bottle * if specific conditions are met.