From 3164b05d30e796dab800c6c24fb19f2e959e322c Mon Sep 17 00:00:00 2001 From: Auxilor Date: Mon, 26 Sep 2022 17:11:23 +0100 Subject: [PATCH] Added soulbound --- .../willfp/ecoenchants/EcoEnchantsPlugin.kt | 2 + .../willfp/ecoenchants/enchants/EcoEnchant.kt | 12 +- .../enchants/impl/EnchantmentSoulbound.kt | 136 ++++++++++++++++++ .../src/main/resources/enchants/soulbound.yml | 17 +++ 4 files changed, 160 insertions(+), 7 deletions(-) create mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchants/impl/EnchantmentSoulbound.kt create mode 100644 eco-core/core-plugin/src/main/resources/enchants/soulbound.yml 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 266f727c..022116df 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 @@ -16,6 +16,7 @@ import com.willfp.ecoenchants.enchants.impl.EnchantmentPermanenceCurse import com.willfp.ecoenchants.enchants.impl.EnchantmentRapid 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.enchants.impl.EnchantmentTelekinesis import com.willfp.ecoenchants.enchants.registerVanillaEnchants import com.willfp.ecoenchants.integrations.EnchantRegistrations @@ -54,6 +55,7 @@ class EcoEnchantsPlugin : LibReforgePlugin() { EnchantmentRepairing(this) EnchantmentRapid(this) EnchantmentReplenish(this) + EnchantmentSoulbound(this) registerVanillaEnchants(this) 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 779c34e0..e67eb3d5 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 @@ -6,11 +6,7 @@ import com.willfp.eco.core.config.TransientConfig import com.willfp.eco.core.config.config 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.PlayerStaticPlaceholder -import com.willfp.eco.core.placeholder.StaticPlaceholder -import com.willfp.eco.util.NumberUtils import com.willfp.eco.util.StringUtils import com.willfp.eco.util.containsIgnoreCase import com.willfp.ecoenchants.EcoEnchantsPlugin @@ -36,7 +32,7 @@ import org.bukkit.inventory.ItemStack import org.bukkit.permissions.Permission import org.bukkit.permissions.PermissionDefault import java.io.File -import java.util.* +import java.util.Objects @Suppress("DEPRECATION") @@ -45,7 +41,7 @@ abstract class EcoEnchant( configProvider: (EcoEnchant) -> Config, protected val plugin: EcoEnchantsPlugin ) : Enchantment(NamespacedKey.minecraft(id)), EcoEnchantLike { - override val config by lazy { configProvider(this) } + final override val config by lazy { configProvider(this) } override val enchant by lazy { this } private val levels = Caffeine.newBuilder() @@ -153,7 +149,9 @@ abstract class EcoEnchant( // and that way the enchantment isn't registered. if (!config.getBool("dont-register")) { register() - doOnInit() + if (plugin.isEnabled) { + doOnInit() + } } } 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/enchants/impl/EnchantmentSoulbound.kt new file mode 100644 index 00000000..2bda8c21 --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoenchants/enchants/impl/EnchantmentSoulbound.kt @@ -0,0 +1,136 @@ +package com.willfp.ecoenchants.enchants.impl + +import com.willfp.eco.core.data.keys.PersistentDataKey +import com.willfp.eco.core.data.keys.PersistentDataKeyType +import com.willfp.eco.core.data.profile +import com.willfp.eco.core.drops.DropQueue +import com.willfp.eco.core.fast.fast +import com.willfp.eco.core.items.Items +import com.willfp.ecoenchants.EcoEnchantsPlugin +import com.willfp.ecoenchants.enchants.EcoEnchant +import com.willfp.ecoenchants.target.EnchantLookup.getActiveEnchantLevelInSlot +import com.willfp.ecoenchants.target.EnchantLookup.hasEnchantActive +import org.bukkit.entity.Player +import org.bukkit.event.EventHandler +import org.bukkit.event.EventPriority +import org.bukkit.event.Listener +import org.bukkit.event.entity.PlayerDeathEvent +import org.bukkit.event.player.PlayerJoinEvent +import org.bukkit.event.player.PlayerRespawnEvent +import org.bukkit.inventory.ItemStack +import org.bukkit.persistence.PersistentDataType + +class EnchantmentSoulbound( + plugin: EcoEnchantsPlugin +) : EcoEnchant( + "soulbound", + plugin, + force = false +) { + init { + this.registerListener(SoulboundHandler(plugin, this)) + } + + private class SoulboundHandler( + private val plugin: EcoEnchantsPlugin, + private val enchant: EcoEnchant + ) : Listener { + private val savedSoulboundItems = PersistentDataKey( + plugin.namespacedKeyFactory.create("soulbound_items"), + PersistentDataKeyType.STRING_LIST, + emptyList() + ) + + private val soulboundKey = plugin.namespacedKeyFactory.create("soulbound") + + @EventHandler( + priority = EventPriority.LOW, + ignoreCancelled = true + ) + fun handle(event: PlayerDeathEvent) { + if (event.keepInventory) { + return + } + + val player = event.entity + val items = mutableListOf() + + if (!player.hasEnchantActive(enchant)) { + return + } + + for ((slot, item) in player.inventory.withIndex()) { + if (item == null) { + continue + } + + val level = player.getActiveEnchantLevelInSlot(enchant, slot) + + if (level == 0) { + continue + } + + items.add(item) + } + + if (items.isEmpty()) { + return + } + + event.drops.removeAll(items) + + for (item in items) { + item.fast().persistentDataContainer.set(soulboundKey, PersistentDataType.INTEGER, 1) + + if (enchant.config.getBool("single-use")) { + val meta = item.itemMeta + meta.removeEnchant(enchant) + item.itemMeta = meta + } + } + + player.profile.write(savedSoulboundItems, items.map { Items.toSNBT(it) }) + } + + @EventHandler( + ignoreCancelled = true + ) + fun onJoin(event: PlayerJoinEvent) { + giveItems(event.player) + } + + @EventHandler( + ignoreCancelled = true + ) + fun onJoin(event: PlayerRespawnEvent) { + giveItems(event.player) + } + + private fun giveItems(player: Player) { + val itemStrings = player.profile.read(savedSoulboundItems) + + if (itemStrings.isEmpty()) { + return + } + + val items = itemStrings.map { Items.fromSNBT(it) } + + plugin.scheduler.run { + DropQueue(player) + .addItems(items) + .forceTelekinesis() + .push() + } + + player.profile.write(savedSoulboundItems, emptyList()) + } + + @EventHandler( + priority = EventPriority.HIGHEST, + ignoreCancelled = true + ) + fun preventDroppingSoulboundItems(event: PlayerDeathEvent) { + event.drops.removeIf { it.fast().persistentDataContainer.has(soulboundKey, PersistentDataType.INTEGER) } + } + } +} diff --git a/eco-core/core-plugin/src/main/resources/enchants/soulbound.yml b/eco-core/core-plugin/src/main/resources/enchants/soulbound.yml new file mode 100644 index 00000000..709888a2 --- /dev/null +++ b/eco-core/core-plugin/src/main/resources/enchants/soulbound.yml @@ -0,0 +1,17 @@ +display-name: "Soulbound" +description: "Keep this item on death" +type: special + +targets: + - all +conflicts: [ ] +rarity: veryspecial +max-level: 1 + +tradeable: true +discoverable: true +enchantable: true + +conditions: [ ] + +single-use: false # If soulbound should be removed from the items after death