From 2e07241eea17d18ffb27c47bf2c83462e5fecb18 Mon Sep 17 00:00:00 2001 From: Auxilor Date: Sat, 21 Aug 2021 11:33:19 +0100 Subject: [PATCH] Added stat modifier implementations --- .../willfp/ecoskills/api/EcoSkillsAPI.java | 48 ++++++++- .../ItemStatModifier.java} | 31 ++---- .../api/modifier/PlayerStatModifier.java | 52 +++++++++ .../ecoskills/api/modifier/StatModifier.java | 27 +++++ ...coSkillsItem.kt => StatModifierMethods.kt} | 80 +++++++++++--- .../willfp/ecoskills/api/EcoSkillsAPIImpl.kt | 26 ++++- .../stats/modifier/StatModifierListener.kt | 101 ++++++++++++++++++ 7 files changed, 321 insertions(+), 44 deletions(-) rename eco-core/core-plugin/src/main/java/com/willfp/ecoskills/api/{StatModifier.java => modifier/ItemStatModifier.java} (66%) create mode 100644 eco-core/core-plugin/src/main/java/com/willfp/ecoskills/api/modifier/PlayerStatModifier.java create mode 100644 eco-core/core-plugin/src/main/java/com/willfp/ecoskills/api/modifier/StatModifier.java rename eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/{EcoSkillsItem.kt => StatModifierMethods.kt} (54%) create mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/stats/modifier/StatModifierListener.kt diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecoskills/api/EcoSkillsAPI.java b/eco-core/core-plugin/src/main/java/com/willfp/ecoskills/api/EcoSkillsAPI.java index eb4d432..c2b060c 100644 --- a/eco-core/core-plugin/src/main/java/com/willfp/ecoskills/api/EcoSkillsAPI.java +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecoskills/api/EcoSkillsAPI.java @@ -1,5 +1,7 @@ package com.willfp.ecoskills.api; +import com.willfp.ecoskills.api.modifier.ItemStatModifier; +import com.willfp.ecoskills.api.modifier.StatModifier; import com.willfp.ecoskills.effects.Effect; import com.willfp.ecoskills.skills.Skill; import com.willfp.ecoskills.stats.Stat; @@ -90,7 +92,7 @@ public interface EcoSkillsAPI { * @param modifier The modifier. */ void addStatModifier(@NotNull ItemStack itemStack, - @NotNull StatModifier modifier); + @NotNull ItemStatModifier modifier); /** * Remove a stat modifier from an item. @@ -99,7 +101,7 @@ public interface EcoSkillsAPI { * @param modifier The modifier. */ void removeStatModifier(@NotNull ItemStack itemStack, - @NotNull StatModifier modifier); + @NotNull ItemStatModifier modifier); /** * Get stat modifier keys on an item. @@ -115,17 +117,53 @@ public interface EcoSkillsAPI { * @param itemStack The item. * @return The modifiers. */ - Set getStatModifiers(@NotNull ItemStack itemStack); + Set getStatModifiers(@NotNull ItemStack itemStack); /** * Get stat modifier on an item. * * @param itemStack The item. - * @param key The key + * @param key The key * @return The modifier. */ @Nullable - StatModifier getStatModifier(@NotNull ItemStack itemStack, + ItemStatModifier getStatModifier(@NotNull ItemStack itemStack, + @NotNull NamespacedKey key); + + /** + * Remove a stat modifier from a player. + * + * @param player The player. + * @param modifier The modifier. + */ + void removeStatModifier(@NotNull Player player, + @NotNull ItemStatModifier modifier); + + /** + * Get stat modifier keys on a player. + * + * @param player The player. + * @return The modifier keys. + */ + Set getStatModifierKeys(@NotNull Player player); + + /** + * Get stat modifiers on a player. + * + * @param player The player. + * @return The modifiers. + */ + Set getStatModifiers(@NotNull Player player); + + /** + * Get stat modifier on a player. + * + * @param player The player. + * @param key The key. + * @return The modifier. + */ + @Nullable + StatModifier getStatModifier(@NotNull Player player, @NotNull NamespacedKey key); /** diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecoskills/api/StatModifier.java b/eco-core/core-plugin/src/main/java/com/willfp/ecoskills/api/modifier/ItemStatModifier.java similarity index 66% rename from eco-core/core-plugin/src/main/java/com/willfp/ecoskills/api/StatModifier.java rename to eco-core/core-plugin/src/main/java/com/willfp/ecoskills/api/modifier/ItemStatModifier.java index abf4a04..bf32e4e 100644 --- a/eco-core/core-plugin/src/main/java/com/willfp/ecoskills/api/StatModifier.java +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecoskills/api/modifier/ItemStatModifier.java @@ -1,12 +1,11 @@ -package com.willfp.ecoskills.api; +package com.willfp.ecoskills.api.modifier; -import com.willfp.eco.util.NamespacedKeyUtils; import com.willfp.ecoskills.stats.Stat; import org.bukkit.NamespacedKey; import org.bukkit.inventory.EquipmentSlot; import org.jetbrains.annotations.NotNull; -public class StatModifier { +public class ItemStatModifier implements StatModifier { /** * The key. */ @@ -35,39 +34,27 @@ public class StatModifier { * @param amount The amount. * @param slot The slots. (Empty is the same as all). */ - public StatModifier(@NotNull final NamespacedKey key, - @NotNull final Stat stat, - final int amount, - @NotNull final EquipmentSlot... slot) { + public ItemStatModifier(@NotNull final NamespacedKey key, + @NotNull final Stat stat, + final int amount, + @NotNull final EquipmentSlot... slot) { this.key = key; this.stat = stat; this.amount = amount; this.slots = slot; } - /** - * Get the key. - * - * @return The key. - */ + @Override public NamespacedKey getKey() { return key; } - /** - * Get the stat. - * - * @return The stat. - */ + @Override public Stat getStat() { return stat; } - /** - * Get the amount. - * - * @return The amount. - */ + @Override public int getAmount() { return amount; } diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecoskills/api/modifier/PlayerStatModifier.java b/eco-core/core-plugin/src/main/java/com/willfp/ecoskills/api/modifier/PlayerStatModifier.java new file mode 100644 index 0000000..8d83e96 --- /dev/null +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecoskills/api/modifier/PlayerStatModifier.java @@ -0,0 +1,52 @@ +package com.willfp.ecoskills.api.modifier; + +import com.willfp.ecoskills.stats.Stat; +import org.bukkit.NamespacedKey; +import org.jetbrains.annotations.NotNull; + +public class PlayerStatModifier implements StatModifier { + /** + * The key. + */ + private final NamespacedKey key; + + /** + * The stat. + */ + private final Stat stat; + + /** + * The amount. + */ + private final int amount; + + /** + * Create a stat modifier. + * + * @param key The key. + * @param stat The stat. + * @param amount The amount. + */ + public PlayerStatModifier(@NotNull final NamespacedKey key, + @NotNull final Stat stat, + final int amount) { + this.key = key; + this.stat = stat; + this.amount = amount; + } + + @Override + public NamespacedKey getKey() { + return key; + } + + @Override + public Stat getStat() { + return stat; + } + + @Override + public int getAmount() { + return amount; + } +} diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecoskills/api/modifier/StatModifier.java b/eco-core/core-plugin/src/main/java/com/willfp/ecoskills/api/modifier/StatModifier.java new file mode 100644 index 0000000..0fb5f68 --- /dev/null +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecoskills/api/modifier/StatModifier.java @@ -0,0 +1,27 @@ +package com.willfp.ecoskills.api.modifier; + +import com.willfp.ecoskills.stats.Stat; +import org.bukkit.NamespacedKey; + +public interface StatModifier { + /** + * Get the key. + * + * @return The key. + */ + NamespacedKey getKey(); + + /** + * Get the stat. + * + * @return The stat. + */ + Stat getStat(); + + /** + * Get the amount. + * + * @return The amount. + */ + int getAmount(); +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/EcoSkillsItem.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/StatModifierMethods.kt similarity index 54% rename from eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/EcoSkillsItem.kt rename to eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/StatModifierMethods.kt index fe6151c..a34dde9 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/EcoSkillsItem.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/StatModifierMethods.kt @@ -1,20 +1,16 @@ package com.willfp.ecoskills -import com.google.common.collect.ImmutableSet import com.willfp.eco.util.NamespacedKeyUtils -import com.willfp.ecoskills.api.StatModifier -import com.willfp.ecoskills.effects.Effect -import com.willfp.ecoskills.skills.Skill -import com.willfp.ecoskills.stats.Stat +import com.willfp.ecoskills.api.modifier.ItemStatModifier +import com.willfp.ecoskills.api.modifier.PlayerStatModifier +import com.willfp.ecoskills.api.modifier.StatModifier import com.willfp.ecoskills.stats.Stats import org.bukkit.NamespacedKey import org.bukkit.entity.Player import org.bukkit.inventory.EquipmentSlot import org.bukkit.inventory.ItemStack import org.bukkit.inventory.meta.ItemMeta -import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataContainer -import org.bukkit.persistence.PersistentDataHolder import org.bukkit.persistence.PersistentDataType private val modifierKey: NamespacedKey = NamespacedKeyUtils.create("ecoskills", "modifiers") @@ -28,7 +24,13 @@ private fun getModifiersTag(meta: ItemMeta): PersistentDataContainer { return container.getOrDefault(modifierKey, PersistentDataType.TAG_CONTAINER, context.newPersistentDataContainer()) } -fun ItemStack.addStatModifier(modifier: StatModifier) { +private fun getModifiersTag(player: Player): PersistentDataContainer { + val container = player.persistentDataContainer + val context = container.adapterContext + return container.getOrDefault(modifierKey, PersistentDataType.TAG_CONTAINER, context.newPersistentDataContainer()) +} + +fun ItemStack.addStatModifier(modifier: ItemStatModifier) { val meta = this.itemMeta ?: return val modifiers = getModifiersTag(meta) @@ -45,7 +47,7 @@ fun ItemStack.addStatModifier(modifier: StatModifier) { this.itemMeta = meta } -fun ItemStack.removeStatModifier(modifier: StatModifier) { +fun ItemStack.removeStatModifier(modifier: ItemStatModifier) { val meta = this.itemMeta ?: return val modifiers = getModifiersTag(meta) @@ -61,8 +63,8 @@ fun ItemStack.getStatModifierKeys(): MutableSet { return modifiers.keys } -fun ItemStack.getStatModifiers(): MutableSet { - val keys = HashSet() +fun ItemStack.getStatModifiers(): MutableSet { + val keys = HashSet() for (modifier in this.getStatModifierKeys().stream().map { key -> this.getStatModifier(key) }) { if (modifier != null) { keys.add(modifier) @@ -71,7 +73,7 @@ fun ItemStack.getStatModifiers(): MutableSet { return keys } -fun ItemStack.getStatModifier(key: NamespacedKey): StatModifier? { +fun ItemStack.getStatModifier(key: NamespacedKey): ItemStatModifier? { val meta = this.itemMeta ?: return null val modifiers = getModifiersTag(meta) @@ -84,7 +86,59 @@ fun ItemStack.getStatModifier(key: NamespacedKey): StatModifier? { .map { s -> EquipmentSlot.valueOf(s) } .toCollection(ArrayList()) - StatModifier(key, stat, amount, *slots.toTypedArray()) + ItemStatModifier(key, stat, amount, *slots.toTypedArray()) + } else { + null + } +} + +/* +Player Modifiers + */ + +fun Player.addStatModifier(modifier: StatModifier) { + val modifiers = getModifiersTag(this) + + modifiers.remove(modifier.key) + + val modifierTag = modifiers.adapterContext.newPersistentDataContainer() + + modifierTag.set(statKey, PersistentDataType.STRING, modifier.stat.id) + modifierTag.set(amountKey, PersistentDataType.INTEGER, modifier.amount) + + modifiers.set(modifier.key, PersistentDataType.TAG_CONTAINER, modifierTag) +} + +fun Player.removeStatModifier(modifier: StatModifier) { + val modifiers = getModifiersTag(this) + modifiers.remove(modifier.key) +} + +fun Player.getStatModifierKeys(): MutableSet { + val modifiers = getModifiersTag(this) + return modifiers.keys +} + +fun Player.getStatModifiers(): MutableSet { + val keys = HashSet() + for (modifier in this.getStatModifierKeys().stream().map { key -> this.getStatModifier(key) }) { + if (modifier != null) { + keys.add(modifier) + } + } + return keys +} + +fun Player.getStatModifier(key: NamespacedKey): StatModifier? { + val modifiers = getModifiersTag(this) + + return if (modifiers.has(key, PersistentDataType.TAG_CONTAINER)) { + val modifierTag = modifiers.get(key, PersistentDataType.TAG_CONTAINER)!! + + val stat = Stats.getByID(modifierTag.get(statKey, PersistentDataType.STRING)!!)!! + val amount = modifierTag.get(amountKey, PersistentDataType.INTEGER)!! + + PlayerStatModifier(key, stat, amount) } else { null } diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/api/EcoSkillsAPIImpl.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/api/EcoSkillsAPIImpl.kt index 92f119b..cf4597d 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/api/EcoSkillsAPIImpl.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/api/EcoSkillsAPIImpl.kt @@ -1,6 +1,8 @@ package com.willfp.ecoskills.api import com.willfp.ecoskills.* +import com.willfp.ecoskills.api.modifier.ItemStatModifier +import com.willfp.ecoskills.api.modifier.StatModifier import com.willfp.ecoskills.effects.Effect import com.willfp.ecoskills.skills.Skill import com.willfp.ecoskills.stats.Stat @@ -37,23 +39,39 @@ object EcoSkillsAPIImpl: EcoSkillsAPI { return player.getStatLevel(stat) } - override fun addStatModifier(itemStack: ItemStack, modifier: StatModifier) { + override fun addStatModifier(itemStack: ItemStack, modifier: ItemStatModifier) { itemStack.addStatModifier(modifier) } - override fun removeStatModifier(itemStack: ItemStack, modifier: StatModifier) { + override fun removeStatModifier(itemStack: ItemStack, modifier: ItemStatModifier) { itemStack.removeStatModifier(modifier) } + override fun removeStatModifier(player: Player, modifier: ItemStatModifier) { + player.removeStatModifier(modifier) + } + override fun getStatModifierKeys(itemStack: ItemStack): MutableSet { return itemStack.getStatModifierKeys() } - override fun getStatModifiers(itemStack: ItemStack): MutableSet { + override fun getStatModifierKeys(player: Player): MutableSet { + return player.getStatModifierKeys() + } + + override fun getStatModifiers(itemStack: ItemStack): MutableSet { return itemStack.getStatModifiers() } - override fun getStatModifier(itemStack: ItemStack, key: NamespacedKey): StatModifier? { + override fun getStatModifiers(player: Player): MutableSet { + return player.getStatModifiers() + } + + override fun getStatModifier(itemStack: ItemStack, key: NamespacedKey): ItemStatModifier? { return itemStack.getStatModifier(key) } + + override fun getStatModifier(player: Player, key: NamespacedKey): StatModifier? { + return player.getStatModifier(key) + } } \ No newline at end of file diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/stats/modifier/StatModifierListener.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/stats/modifier/StatModifierListener.kt new file mode 100644 index 0000000..a562ab0 --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/stats/modifier/StatModifierListener.kt @@ -0,0 +1,101 @@ +package com.willfp.ecoskills.stats.modifier + +import com.willfp.eco.core.EcoPlugin +import com.willfp.eco.core.events.ArmorChangeEvent +import com.willfp.ecoskills.addStatModifier +import com.willfp.ecoskills.getStatModifiers +import com.willfp.ecoskills.removeStatModifier +import org.bukkit.event.EventHandler +import org.bukkit.event.EventPriority +import org.bukkit.event.Listener +import org.bukkit.event.player.PlayerItemHeldEvent +import org.bukkit.event.player.PlayerSwapHandItemsEvent +import org.bukkit.inventory.EquipmentSlot + +class StatModifierListener( + private val plugin: EcoPlugin +): Listener { + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + fun onHold(event: PlayerItemHeldEvent) { + val player = event.player + + val old = player.inventory.getItem(event.previousSlot) + val new = player.inventory.getItem(event.newSlot) + + val oldMods = old?.getStatModifiers() ?: HashSet() + val newMods = new?.getStatModifiers() ?: HashSet() + + for (oldMod in oldMods) { + player.removeStatModifier(oldMod) + } + for (newMod in newMods) { + if (newMod.slots.contains(EquipmentSlot.HAND)) { + player.addStatModifier(newMod) + } + } + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + fun onHold(event: PlayerSwapHandItemsEvent) { + val player = event.player + + val offhandMods = event.offHandItem?.getStatModifiers() ?: HashSet() + val mainhandMods = event.mainHandItem?.getStatModifiers() ?: HashSet() + + for (offhandMod in offhandMods) { + player.removeStatModifier(offhandMod) + } + for (mainhandMod in mainhandMods) { + player.removeStatModifier(mainhandMod) + } + + for (mod in offhandMods) { + if (mod.slots.contains(EquipmentSlot.OFF_HAND)) { + player.addStatModifier(mod) + } + } + + for (mod in mainhandMods) { + if (mod.slots.contains(EquipmentSlot.HAND)) { + player.addStatModifier(mod) + } + } + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + fun onHold(event: ArmorChangeEvent) { + for (itemStack in event.before) { + val mods = itemStack.getStatModifiers() + for (mod in mods) { + event.player.removeStatModifier(mod) + } + } + for (itemStack in event.after) { + val mods = itemStack.getStatModifiers() + for (mod in mods) { + when (itemStack) { + event.player.inventory.helmet -> { + if (mod.slots.contains(EquipmentSlot.HEAD)) { + event.player.addStatModifier(mod) + } + } + event.player.inventory.chestplate -> { + if (mod.slots.contains(EquipmentSlot.CHEST)) { + event.player.addStatModifier(mod) + } + } + event.player.inventory.leggings -> { + if (mod.slots.contains(EquipmentSlot.LEGS)) { + event.player.addStatModifier(mod) + } + } + event.player.inventory.boots -> { + if (mod.slots.contains(EquipmentSlot.FEET)) { + event.player.addStatModifier(mod) + } + } + } + } + } + } +} \ No newline at end of file