Added soulbound

This commit is contained in:
Auxilor 2022-09-26 17:11:23 +01:00
parent 2fda386748
commit 3164b05d30
4 changed files with 160 additions and 7 deletions

View File

@ -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)

View File

@ -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,9 +149,11 @@ abstract class EcoEnchant(
// and that way the enchantment isn't registered.
if (!config.getBool("dont-register")) {
register()
if (plugin.isEnabled) {
doOnInit()
}
}
}
private fun doOnInit() {
onInit()

View File

@ -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<ItemStack>()
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) }
}
}
}

View File

@ -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