Apply different numeric stats according to player/item
I am a plugin developer. I'd like to modify actually numeric stats value (e.g. damage, armor) without edit item when player/item hit some condition. > Actual Scene: Player A soulbound a weapon by my plugin, and player B borrow it from player A. Then weapon damage will cut off a half when player B held it, but do nothing to the damage when player A held it. I noticed that MMOItems apply item numeric stats to player in [InventoryResolver#applyModifiers](https://gitlab.com/phoenix-dvpmt/mmoitems/-/blob/d98831a1a239580563ccdda7e8c962d06baf6465/MMOItems-API/src/main/java/net/Indyuce/mmoitems/inventory/InventoryResolver.java#L224-242). So I wonder, what if we modify `statValue` when apply modifiers. I know nothing of your design mode. There is my implementation below. I design it in a Paper server patch style, feel free to re-design it. `top.mrxiaom.mmoitems.api.INumericStatsInjector` ```java package top.mrxiaom.mmoitems.api; import net.Indyuce.mmoitems.inventory.EquippedItem; import net.Indyuce.mmoitems.inventory.InventoryResolver; import net.Indyuce.mmoitems.stat.type.ItemStat; /** * Temporary numeric stats injector */ public interface INumericStatsInjector { default int getPriority() { return 1000; } /** * Handle inject logic when apply modifiers * @param resolver Instance of InventoryResolver, you can get PlayerData instance here. * @param equippedItem The item that player to equip * @param stat The stat type instance that player to apply * @param statValue The stat value from item data * @return stat value after modified */ double applyModifier(InventoryResolver resolver, EquippedItem equippedItem, ItemStat<?, ?> stat, double statValue); } ``` `net.Indyuce.mmoitems.inventory.InventoryResolver#applyModifiers` ```java double statValue = equippedItem.getItem().getStat(stat.getId()); if (statValue == 0) continue; // MCIO start: Inject into numeric stat values. for (top.mrxiaom.mmoitems.api.INumericStatsInjector injector : MMOItems.plugin.ext().getNumericStatsInjectors()) { statValue = injector.applyModifier(this, equippedItem, stat, statValue); } // MCIO end: Inject into numeric stat values. StatInstance statInstance = playerData.getMMOPlayerData().getStatMap().getInstance(stat.getId()); final ModifierSource modifierSource = equippedItem.getModifierSource(); ``` `net.Indyuce.mmoitems.MMOItems` ```java // MCIO start: Add extension API. private final top.mrxiaom.mmoitems.api.MMOItemsExt ext = new top.mrxiaom.mmoitems.api.MMOItemsExt(this); public top.mrxiaom.mmoitems.api.MMOItemsExt ext() { return ext; } // MCIO end: Add extension API. ``` `top.mrxiaom.mmoitems.api.MMOItemsExt` ```java package top.mrxiaom.mmoitems.api; import net.Indyuce.mmoitems.MMOItems; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; public class MMOItemsExt { public final MMOItems plugin; private final List<INumericStatsInjector> numericStatsInjectorRegistry = new ArrayList<>(); public MMOItemsExt(MMOItems plugin) { this.plugin = plugin; } public List<INumericStatsInjector> getNumericStatsInjectors() { return Collections.unmodifiableList(numericStatsInjectorRegistry); } public void registerNumericStatsInjector(INumericStatsInjector injector) { numericStatsInjectorRegistry.add(injector); numericStatsInjectorRegistry.sort(Comparator.comparingInt(INumericStatsInjector::getPriority)); } public void unregisterNumericStatsInjector(INumericStatsInjector injector) { numericStatsInjectorRegistry.add(injector); numericStatsInjectorRegistry.sort(Comparator.comparingInt(INumericStatsInjector::getPriority)); } } ```
issue