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