diff --git a/.idea/dictionaries/project.xml b/.idea/dictionaries/project.xml
index 8a39c187d..5596fa788 100644
--- a/.idea/dictionaries/project.xml
+++ b/.idea/dictionaries/project.xml
@@ -38,6 +38,7 @@
unloadinv
userdev
vanillaplus
+ veinmine
worldedit
xodium
xparser
diff --git a/.idea/libraries/Gradle__io_papermc_paper_paper_api_1_21_10_R0_1_SNAPSHOT.xml b/.idea/libraries/Gradle__io_papermc_paper_paper_api_1_21_10_R0_1_SNAPSHOT.xml
index 9cef7876f..5b9ccd7c3 100644
--- a/.idea/libraries/Gradle__io_papermc_paper_paper_api_1_21_10_R0_1_SNAPSHOT.xml
+++ b/.idea/libraries/Gradle__io_papermc_paper_paper_api_1_21_10_R0_1_SNAPSHOT.xml
@@ -6,6 +6,7 @@
+
diff --git a/.idea/modules/VanillaPlus.main.iml b/.idea/modules/VanillaPlus.main.iml
index db9206a2c..167b72c2b 100644
--- a/.idea/modules/VanillaPlus.main.iml
+++ b/.idea/modules/VanillaPlus.main.iml
@@ -11,7 +11,7 @@
-
+
@@ -55,7 +55,7 @@
-
+
diff --git a/.idea/modules/VanillaPlus.test.iml b/.idea/modules/VanillaPlus.test.iml
index 4c8849308..3712be1c4 100644
--- a/.idea/modules/VanillaPlus.test.iml
+++ b/.idea/modules/VanillaPlus.test.iml
@@ -12,7 +12,7 @@
-
+
VanillaPlus:main
@@ -54,7 +54,7 @@
-
+
diff --git a/build.gradle.kts b/build.gradle.kts
index 82b7e6027..9284e7051 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -62,6 +62,7 @@ paperPluginYaml {
main.set(group.toString())
authors.add("Xodium")
apiVersion.set(version)
+ bootstrapper.set("org.xodium.vanillaplus.VanillaPlusBootstrap")
dependencies {
server(name = "WorldEdit", load = PaperPluginYaml.Load.BEFORE, required = false, joinClasspath = true)
}
diff --git a/src/main/kotlin/org/xodium/vanillaplus/VanillaPlusBootstrap.kt b/src/main/kotlin/org/xodium/vanillaplus/VanillaPlusBootstrap.kt
new file mode 100644
index 000000000..c47877f34
--- /dev/null
+++ b/src/main/kotlin/org/xodium/vanillaplus/VanillaPlusBootstrap.kt
@@ -0,0 +1,49 @@
+package org.xodium.vanillaplus
+
+import io.papermc.paper.plugin.bootstrap.BootstrapContext
+import io.papermc.paper.plugin.bootstrap.PluginBootstrap
+import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents
+import io.papermc.paper.registry.RegistryKey
+import io.papermc.paper.registry.event.RegistryEvents
+import io.papermc.paper.registry.keys.tags.EnchantmentTagKeys
+import io.papermc.paper.registry.keys.tags.ItemTypeTagKeys
+import org.xodium.vanillaplus.enchantments.DriftEnchantment
+import org.xodium.vanillaplus.enchantments.FortitudeEnchantment
+import org.xodium.vanillaplus.enchantments.NimbusEnchantment
+import org.xodium.vanillaplus.enchantments.ZephyrEnchantment
+
+/** Main bootstrap class of the plugin. */
+@Suppress("UnstableApiUsage", "Unused")
+internal class VanillaPlusBootstrap : PluginBootstrap {
+ companion object {
+ const val INSTANCE = "vanillaplus"
+ val DRIFT = DriftEnchantment.key
+ val FORTITUDE = FortitudeEnchantment.key
+ val NIMBUS = NimbusEnchantment.key
+ val ZEPHYR = ZephyrEnchantment.key
+ val ENCHANTS = setOf(DRIFT, FORTITUDE, NIMBUS, ZEPHYR)
+ }
+
+ override fun bootstrap(ctx: BootstrapContext) {
+ ctx.lifecycleManager.apply {
+ registerEventHandler(
+ RegistryEvents.ENCHANTMENT.compose().newHandler { event ->
+ val harnessesTag = event.getOrCreateTag(ItemTypeTagKeys.HARNESSES)
+ event.registry().apply {
+ register(DRIFT) { DriftEnchantment.init(it).supportedItems(harnessesTag) }
+ register(FORTITUDE) { FortitudeEnchantment.init(it).supportedItems(harnessesTag) }
+ register(NIMBUS) { NimbusEnchantment.init(it).supportedItems(harnessesTag) }
+ register(ZEPHYR) { ZephyrEnchantment.init(it).supportedItems(harnessesTag) }
+ }
+ },
+ )
+ registerEventHandler(LifecycleEvents.TAGS.postFlatten(RegistryKey.ENCHANTMENT)) { event ->
+ event.registrar().apply {
+ addToTag(EnchantmentTagKeys.TRADEABLE, ENCHANTS)
+ addToTag(EnchantmentTagKeys.NON_TREASURE, ENCHANTS)
+ addToTag(EnchantmentTagKeys.IN_ENCHANTING_TABLE, ENCHANTS)
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/kotlin/org/xodium/vanillaplus/enchantments/DriftEnchantment.kt b/src/main/kotlin/org/xodium/vanillaplus/enchantments/DriftEnchantment.kt
new file mode 100644
index 000000000..d3c5a0ea9
--- /dev/null
+++ b/src/main/kotlin/org/xodium/vanillaplus/enchantments/DriftEnchantment.kt
@@ -0,0 +1,43 @@
+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.entity.Player
+import org.bukkit.inventory.EquipmentSlotGroup
+import org.bukkit.potion.PotionEffect
+import org.bukkit.potion.PotionEffectType
+import org.xodium.vanillaplus.VanillaPlusBootstrap.Companion.INSTANCE
+import org.xodium.vanillaplus.interfaces.EnchantmentInterface
+import org.xodium.vanillaplus.utils.ExtUtils.mm
+
+@Suppress("UnstableApiUsage")
+internal object DriftEnchantment : EnchantmentInterface {
+ override val key: TypedKey = TypedKey.create(RegistryKey.ENCHANTMENT, Key.key(INSTANCE, "drift"))
+
+ override fun init(builder: EnchantmentRegistryEntry.Builder) =
+ builder
+ .description(key.value().replaceFirstChar { it.uppercase() }.mm())
+ .anvilCost(2)
+ .maxLevel(2)
+ .weight(5)
+ .minimumCost(EnchantmentRegistryEntry.EnchantmentCost.of(4, 6))
+ .maximumCost(EnchantmentRegistryEntry.EnchantmentCost.of(24, 6))
+ .activeSlots(EquipmentSlotGroup.BODY)
+
+ fun effect(): PotionEffect =
+ PotionEffect(
+ PotionEffectType.SLOW_FALLING,
+ 100,
+ 0,
+ true,
+ true,
+ true,
+ )
+
+ fun Player.drift() {
+ addPotionEffect(effect())
+ }
+}
diff --git a/src/main/kotlin/org/xodium/vanillaplus/enchantments/FortitudeEnchantment.kt b/src/main/kotlin/org/xodium/vanillaplus/enchantments/FortitudeEnchantment.kt
new file mode 100644
index 000000000..26770f345
--- /dev/null
+++ b/src/main/kotlin/org/xodium/vanillaplus/enchantments/FortitudeEnchantment.kt
@@ -0,0 +1,47 @@
+package org.xodium.vanillaplus.enchantments
+
+import io.papermc.paper.datacomponent.DataComponentTypes
+import io.papermc.paper.datacomponent.item.ItemAttributeModifiers
+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.NamespacedKey
+import org.bukkit.attribute.Attribute
+import org.bukkit.attribute.AttributeModifier
+import org.bukkit.enchantments.Enchantment
+import org.bukkit.inventory.EquipmentSlotGroup
+import org.bukkit.inventory.ItemStack
+import org.xodium.vanillaplus.VanillaPlusBootstrap.Companion.FORTITUDE
+import org.xodium.vanillaplus.VanillaPlusBootstrap.Companion.INSTANCE
+import org.xodium.vanillaplus.interfaces.EnchantmentInterface
+import org.xodium.vanillaplus.utils.ExtUtils.mm
+
+@Suppress("UnstableApiUsage")
+internal object FortitudeEnchantment : EnchantmentInterface {
+ override val key: TypedKey = TypedKey.create(RegistryKey.ENCHANTMENT, Key.key(INSTANCE, "fortitude"))
+
+ override fun init(builder: EnchantmentRegistryEntry.Builder) =
+ builder
+ .description(FORTITUDE.value().replaceFirstChar { it.uppercase() }.mm())
+ .anvilCost(2)
+ .maxLevel(4)
+ .weight(5)
+ .minimumCost(EnchantmentRegistryEntry.EnchantmentCost.of(4, 6))
+ .maximumCost(EnchantmentRegistryEntry.EnchantmentCost.of(24, 6))
+ .activeSlots(EquipmentSlotGroup.BODY)
+
+ fun effect(level: Int): AttributeModifier =
+ AttributeModifier(
+ NamespacedKey(INSTANCE, "fortitude_armor"),
+ 2.0 + (level - 1.0) * 2.0,
+ AttributeModifier.Operation.ADD_NUMBER,
+ )
+
+ fun ItemStack.fortitude(level: Int) {
+ setData(
+ DataComponentTypes.ATTRIBUTE_MODIFIERS,
+ ItemAttributeModifiers.itemAttributes().addModifier(Attribute.ARMOR, effect(level)),
+ )
+ }
+}
diff --git a/src/main/kotlin/org/xodium/vanillaplus/enchantments/NimbusEnchantment.kt b/src/main/kotlin/org/xodium/vanillaplus/enchantments/NimbusEnchantment.kt
new file mode 100644
index 000000000..cc3b6bc30
--- /dev/null
+++ b/src/main/kotlin/org/xodium/vanillaplus/enchantments/NimbusEnchantment.kt
@@ -0,0 +1,55 @@
+package org.xodium.vanillaplus.enchantments
+
+import io.papermc.paper.datacomponent.DataComponentTypes
+import io.papermc.paper.datacomponent.item.ItemAttributeModifiers
+import io.papermc.paper.registry.RegistryKey
+import io.papermc.paper.registry.TypedKey
+import io.papermc.paper.registry.data.EnchantmentRegistryEntry
+import io.papermc.paper.registry.set.RegistrySet
+import net.kyori.adventure.key.Key
+import org.bukkit.NamespacedKey
+import org.bukkit.attribute.Attribute
+import org.bukkit.attribute.AttributeModifier
+import org.bukkit.enchantments.Enchantment
+import org.bukkit.inventory.EquipmentSlotGroup
+import org.bukkit.inventory.ItemStack
+import org.xodium.vanillaplus.VanillaPlusBootstrap.Companion.INSTANCE
+import org.xodium.vanillaplus.VanillaPlusBootstrap.Companion.NIMBUS
+import org.xodium.vanillaplus.VanillaPlusBootstrap.Companion.ZEPHYR
+import org.xodium.vanillaplus.interfaces.EnchantmentInterface
+import org.xodium.vanillaplus.utils.ExtUtils.mm
+
+@Suppress("UnstableApiUsage")
+internal object NimbusEnchantment : EnchantmentInterface {
+ override val key: TypedKey = TypedKey.create(RegistryKey.ENCHANTMENT, Key.key(INSTANCE, "nimbus"))
+
+ override fun init(builder: EnchantmentRegistryEntry.Builder) =
+ builder
+ .description(NIMBUS.value().replaceFirstChar { it.uppercase() }.mm())
+ .anvilCost(2)
+ .maxLevel(3)
+ .weight(5)
+ .minimumCost(EnchantmentRegistryEntry.EnchantmentCost.of(4, 6))
+ .maximumCost(EnchantmentRegistryEntry.EnchantmentCost.of(24, 6))
+ .activeSlots(EquipmentSlotGroup.BODY)
+ .exclusiveWith(
+ RegistrySet.keySet(
+ RegistryKey.ENCHANTMENT,
+ setOf(RegistryKey.ENCHANTMENT.typedKey(ZEPHYR)),
+ ),
+ )
+
+ fun effect(level: Int): AttributeModifier =
+ AttributeModifier(
+ NamespacedKey(INSTANCE, "nimbus_flying_speed"),
+ 0.85 + (level - 1.0) * 0.25,
+ AttributeModifier.Operation.ADD_SCALAR,
+ )
+
+ fun ItemStack.nimbus(level: Int) {
+ setData(
+ DataComponentTypes.ATTRIBUTE_MODIFIERS,
+ ItemAttributeModifiers.itemAttributes().addModifier(Attribute.ARMOR, effect(level)),
+ )
+ }
+}
diff --git a/src/main/kotlin/org/xodium/vanillaplus/enchantments/ZephyrEnchantment.kt b/src/main/kotlin/org/xodium/vanillaplus/enchantments/ZephyrEnchantment.kt
new file mode 100644
index 000000000..7835595c7
--- /dev/null
+++ b/src/main/kotlin/org/xodium/vanillaplus/enchantments/ZephyrEnchantment.kt
@@ -0,0 +1,55 @@
+package org.xodium.vanillaplus.enchantments
+
+import io.papermc.paper.datacomponent.DataComponentTypes
+import io.papermc.paper.datacomponent.item.ItemAttributeModifiers
+import io.papermc.paper.registry.RegistryKey
+import io.papermc.paper.registry.TypedKey
+import io.papermc.paper.registry.data.EnchantmentRegistryEntry
+import io.papermc.paper.registry.set.RegistrySet
+import net.kyori.adventure.key.Key
+import org.bukkit.NamespacedKey
+import org.bukkit.attribute.Attribute
+import org.bukkit.attribute.AttributeModifier
+import org.bukkit.enchantments.Enchantment
+import org.bukkit.inventory.EquipmentSlotGroup
+import org.bukkit.inventory.ItemStack
+import org.xodium.vanillaplus.VanillaPlusBootstrap.Companion.INSTANCE
+import org.xodium.vanillaplus.VanillaPlusBootstrap.Companion.NIMBUS
+import org.xodium.vanillaplus.VanillaPlusBootstrap.Companion.ZEPHYR
+import org.xodium.vanillaplus.interfaces.EnchantmentInterface
+import org.xodium.vanillaplus.utils.ExtUtils.mm
+
+@Suppress("UnstableApiUsage")
+internal object ZephyrEnchantment : EnchantmentInterface {
+ override val key: TypedKey = TypedKey.create(RegistryKey.ENCHANTMENT, Key.key(INSTANCE, "zephyr"))
+
+ override fun init(builder: EnchantmentRegistryEntry.Builder) =
+ builder
+ .description(ZEPHYR.value().replaceFirstChar { it.uppercase() }.mm())
+ .anvilCost(2)
+ .maxLevel(5)
+ .weight(5)
+ .minimumCost(EnchantmentRegistryEntry.EnchantmentCost.of(4, 6))
+ .maximumCost(EnchantmentRegistryEntry.EnchantmentCost.of(24, 6))
+ .activeSlots(EquipmentSlotGroup.BODY)
+ .exclusiveWith(
+ RegistrySet.keySet(
+ RegistryKey.ENCHANTMENT,
+ setOf(RegistryKey.ENCHANTMENT.typedKey(NIMBUS)),
+ ),
+ )
+
+ fun effect(level: Int): AttributeModifier =
+ AttributeModifier(
+ NamespacedKey(INSTANCE, "zephyr_flying_speed"),
+ 0.25 + (level - 1.0) * 0.15,
+ AttributeModifier.Operation.ADD_SCALAR,
+ )
+
+ fun ItemStack.zephyr(level: Int) {
+ setData(
+ DataComponentTypes.ATTRIBUTE_MODIFIERS,
+ ItemAttributeModifiers.itemAttributes().addModifier(Attribute.ARMOR, effect(level)),
+ )
+ }
+}
diff --git a/src/main/kotlin/org/xodium/vanillaplus/interfaces/DataInterface.kt b/src/main/kotlin/org/xodium/vanillaplus/interfaces/DataInterface.kt
index 1928ceede..0383f3fcc 100644
--- a/src/main/kotlin/org/xodium/vanillaplus/interfaces/DataInterface.kt
+++ b/src/main/kotlin/org/xodium/vanillaplus/interfaces/DataInterface.kt
@@ -74,7 +74,7 @@ interface DataInterface {
* @param key the UUID key whose associated value is to be returned.
* @return the value associated with the specified key, or `null` if no mapping exists.
*/
- fun get(key: K): T? {
+ operator fun get(key: K): T? {
if (cache.isEmpty() && filePath.toFile().exists()) load()
return cache[key]
}
diff --git a/src/main/kotlin/org/xodium/vanillaplus/interfaces/EnchantmentInterface.kt b/src/main/kotlin/org/xodium/vanillaplus/interfaces/EnchantmentInterface.kt
new file mode 100644
index 000000000..e252fb96d
--- /dev/null
+++ b/src/main/kotlin/org/xodium/vanillaplus/interfaces/EnchantmentInterface.kt
@@ -0,0 +1,32 @@
+package org.xodium.vanillaplus.interfaces
+
+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 org.bukkit.enchantments.Enchantment
+
+/** Represents a contract for enchantments within the system. */
+@Suppress("UnstableApiUsage")
+internal interface EnchantmentInterface {
+ /**
+ * The unique typed key that identifies this enchantment in the registry.
+ * @see TypedKey
+ * @see RegistryKey.ENCHANTMENT
+ */
+ val key: TypedKey
+
+ /**
+ * Initializes the Drift enchantment.
+ * @param builder The builder used to define the enchantment properties.
+ * @return The builder for method chaining.
+ */
+ fun init(builder: EnchantmentRegistryEntry.Builder): EnchantmentRegistryEntry.Builder
+
+ /**
+ * Retrieves the enchantment from the registry.
+ * @return The [Enchantment] instance corresponding to the key.
+ * @throws NoSuchElementException if the enchantment is not found in the registry.
+ */
+ fun get(): Enchantment = RegistryAccess.registryAccess().getRegistry(RegistryKey.ENCHANTMENT).getOrThrow(key)
+}
diff --git a/src/main/kotlin/org/xodium/vanillaplus/modules/EntityModule.kt b/src/main/kotlin/org/xodium/vanillaplus/modules/EntityModule.kt
index 45a49cdf8..b413ba3ef 100644
--- a/src/main/kotlin/org/xodium/vanillaplus/modules/EntityModule.kt
+++ b/src/main/kotlin/org/xodium/vanillaplus/modules/EntityModule.kt
@@ -2,14 +2,15 @@
package org.xodium.vanillaplus.modules
+import io.papermc.paper.event.entity.EntityMoveEvent
import org.bukkit.Material
import org.bukkit.entity.*
import org.bukkit.event.EventHandler
import org.bukkit.event.entity.EntityChangeBlockEvent
import org.bukkit.event.entity.EntityDeathEvent
import org.bukkit.event.entity.EntityExplodeEvent
-import org.bukkit.inventory.ItemStack
import org.xodium.vanillaplus.interfaces.ModuleInterface
+import org.bukkit.inventory.ItemStack
import kotlin.random.Random
/** Represents a module handling entity mechanics within the system. */
@@ -29,11 +30,16 @@ internal class EntityModule : ModuleInterface {
}
@EventHandler
- fun on(event: EntityDeathEvent) {
- if (!enabled() || event.entity.killer == null) return
+ fun on(event: EntityMoveEvent) {
+ if (!enabled()) return
+ if (event.entity.killer == null) return //FIX: make it inside the if statement below.
if (Random.nextDouble() <= config.entityEggDropChance) {
event.drops.add(ItemStack.of(Material.matchMaterial("${event.entity.type.name}_SPAWN_EGG") ?: return))
}
+ val entity = event.entity as? HappyGhast ?: return
+ val location = entity.location
+ if (location.y <= 187) return
+ // TODO: implement nimbus
}
/**