!Statistics map moved to MMOLib

This commit is contained in:
Indyuce 2019-12-23 18:41:27 +01:00
parent c83dcf94b0
commit 6913e8b0cc
18 changed files with 141 additions and 325 deletions

View File

@ -362,7 +362,7 @@ public class PlayerData {
public void setLevel(int level) {
this.level = Math.max(1, level);
getStats().updateAll();
getStats().getMap().updateAll();
}
public void giveLevels(int value) {
@ -556,7 +556,7 @@ public class PlayerData {
new ConfigMessage("level-up").addPlaceholders("level", "" + level).send(player);
player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1, 1);
new SmallParticleEffect(player, Particle.SPELL_INSTANT);
getStats().updateAll();
getStats().getMap().updateAll();
}
refreshVanillaExp(needed);
@ -721,7 +721,7 @@ public class PlayerData {
// if (!getProfess().hasSkill(iterator.next().getSkill()))
// iterator.remove();
getStats().updateAll();
getStats().getMap().updateAll();
}
public void setProfess(PlayerClass profess) {

View File

@ -11,7 +11,7 @@ import org.bukkit.configuration.ConfigurationSection;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.stats.StatType;
import net.Indyuce.mmocore.api.player.stats.stat.modifier.StatModifier;
import net.mmogroup.mmolib.api.stat.modifier.StatModifier;
public class PlayerAttribute {
private final String id, name;

View File

@ -11,7 +11,7 @@ import org.bukkit.configuration.ConfigurationSection;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.stats.stat.modifier.StatModifier;
import net.mmogroup.mmolib.api.stat.modifier.StatModifier;
public class PlayerAttributes {
private final PlayerData data;

View File

@ -2,36 +2,45 @@ package net.Indyuce.mmocore.api.player.stats;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.stats.stat.modifier.StatModifier;
import net.Indyuce.mmocore.api.player.stats.stat.modifier.TemporaryStatModifier;
import net.mmogroup.mmolib.MMOLib;
import net.mmogroup.mmolib.api.AttackResult;
import net.mmogroup.mmolib.api.DamageType;
import net.mmogroup.mmolib.api.stat.StatMap;
import net.mmogroup.mmolib.api.stat.StatMap.StatInstance;
public class PlayerStats {
private final PlayerData data;
private final StatMap map;
/*
* allows for extra compatibility with extra MMOCore plugins like item
* plugins which can apply other stats onto the player.
* util class to manipulate more easily stat data from MMOLib
*/
private final Map<String, StatInstance> extra = new HashMap<>();
public PlayerStats(PlayerData data) {
this.data = data;
/*
* retrieve stat map (where all stat data is saved) and refresh MMOCore
* data
*/
this.map = StatMap.get(data.getPlayer());
map.getPlayerData().setMMOCore(data);
}
public PlayerData getData() {
return data;
}
public StatInstance getInstance(StatType stat) {
if (extra.containsKey(stat.name()))
return extra.get(stat.name());
public StatMap getMap() {
return map;
}
StatInstance ins = new StatInstance(stat);
extra.put(stat.name(), ins);
return ins;
public StatInstance getInstance(StatType stat) {
return map.getInstance(stat.name());
}
/*
@ -52,92 +61,35 @@ public class PlayerStats {
return getInstance(stat).getTotal(0);
}
public void updateAll() {
for (StatType stat : StatType.values())
update(stat);
public CachedStats cache() {
return new CachedStats();
}
public void update(StatType stat) {
if (stat.hasHandler())
stat.getHandler().refresh(data, getStat(stat));
}
public class CachedStats {
private final Player player;
public class StatInstance {
private final StatType stat;
private final Map<String, StatModifier> map = new HashMap<>();
private final Map<String, Double> stats = new HashMap<>();
public StatInstance(StatType stat) {
this.stat = stat;
public CachedStats() {
this.player = data.getPlayer();
for (StatType stat : StatType.values())
this.stats.put(stat.name(), getStat(stat));
}
public double getTotal() {
return getTotal(0);
public Player getPlayer() {
return player;
}
/*
* 1) two types of attributes: flat attributes which add X to the value,
* and relative attributes which add X% and which must be applied
* afterwards 2) the 'd' parameter lets you choose if the relative
* attributes also apply on the base stat, or if they only apply on the
* extra stat value
*/
public double getTotal(double d) {
for (StatModifier attr : map.values())
if (attr.isRelative())
d = attr.apply(d);
for (StatModifier attr : map.values())
if (!attr.isRelative())
d = attr.apply(d);
return d;
public PlayerData getData() {
return data;
}
public StatModifier getAttribute(String key) {
return map.get(key);
public double getStat(StatType stat) {
return stats.get(stat.name());
}
public void addModifier(String key, double value) {
addModifier(key, new StatModifier(value));
}
public void applyTemporaryModifier(String key, StatModifier modifier, long duration) {
addModifier(key, new TemporaryStatModifier(modifier.getValue(), duration, modifier.isRelative(), key, this));
}
public void addModifier(String key, StatModifier modifier) {
map.put(key, modifier);
update(stat);
}
public Set<String> getKeys() {
return map.keySet();
}
public boolean contains(String key) {
return map.containsKey(key);
}
public void remove(String key) {
/*
* closing stat is really important with temporary stats because
* otherwise the runnable will try to remove the key from the map
* even though the attribute was cancelled before hand
*/
if (map.containsKey(key)) {
map.get(key).close();
map.remove(key);
}
update(stat);
}
@Deprecated
public void setValue(String key, double value) {
addModifier(key, new StatModifier(value));
public void damage(LivingEntity target, double value, DamageType... types) {
MMOLib.plugin.getDamage().damage(data.getPlayer(), target, new AttackResult(true, value, types));
}
}
}

View File

@ -2,27 +2,23 @@ package net.Indyuce.mmocore.api.player.stats;
import java.text.DecimalFormat;
import org.bukkit.attribute.Attribute;
import org.bukkit.configuration.file.FileConfiguration;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.ConfigFile;
import net.Indyuce.mmocore.api.experience.Profession;
import net.Indyuce.mmocore.api.math.formula.LinearValue;
import net.Indyuce.mmocore.api.player.stats.stat.AttributeStat;
import net.Indyuce.mmocore.api.player.stats.stat.MovementSpeedStat;
import net.Indyuce.mmocore.api.player.stats.stat.PlayerStat;
public enum StatType {
ATTACK_DAMAGE(Attribute.GENERIC_ATTACK_DAMAGE),
ATTACK_SPEED(Attribute.GENERIC_ATTACK_SPEED),
MAX_HEALTH(Attribute.GENERIC_MAX_HEALTH),
ATTACK_DAMAGE,
ATTACK_SPEED,
MAX_HEALTH,
HEALTH_REGENERATION,
MOVEMENT_SPEED(new MovementSpeedStat()),
SPEED_MALUS_REDUCTION(new MovementSpeedStat()),
KNOCKBACK_RESISTANCE(Attribute.GENERIC_KNOCKBACK_RESISTANCE),
MOVEMENT_SPEED,
SPEED_MALUS_REDUCTION,
KNOCKBACK_RESISTANCE,
MAX_MANA,
MAX_STAMINA,
@ -31,8 +27,8 @@ public enum StatType {
STAMINA_REGENERATION,
STELLIUM_REGENERATION,
ARMOR(Attribute.GENERIC_ARMOR),
ARMOR_TOUGHNESS(Attribute.GENERIC_ARMOR_TOUGHNESS),
ARMOR,
ARMOR_TOUGHNESS,
ADDITIONAL_EXPERIENCE,
COOLDOWN_REDUCTION,
@ -64,7 +60,6 @@ public enum StatType {
;
private String profession;
private PlayerStat handler;
private LinearValue defaultInfo;
private DecimalFormat format;
@ -73,14 +68,6 @@ public enum StatType {
// completely custom stat.
}
private StatType(PlayerStat handler) {
this.handler = handler;
}
private StatType(Attribute attribute) {
this.handler = new AttributeStat(attribute);
}
private StatType(String profession) {
this.profession = profession;
}
@ -97,14 +84,6 @@ public enum StatType {
return profession != null;
}
public boolean hasHandler() {
return handler != null;
}
public PlayerStat getHandler() {
return handler;
}
public LinearValue getDefault() {
return defaultInfo;
}

View File

@ -1,43 +0,0 @@
package net.Indyuce.mmocore.api.player.stats;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.mmogroup.mmolib.MMOLib;
import net.mmogroup.mmolib.api.AttackResult;
import net.mmogroup.mmolib.api.DamageType;
public class TemporaryStats {
private final PlayerData playerData;
private final Player player;
private final Map<String, Double> stats = new HashMap<>();
public TemporaryStats(PlayerStats stats) {
this.playerData = stats.getData();
this.player = playerData.getPlayer();
for (StatType stat : StatType.values())
this.stats.put(stat.name(), stats.getStat(stat));
}
public Player getPlayer() {
return player;
}
public PlayerData getData() {
return playerData;
}
public double getStat(StatType stat) {
return stats.get(stat.name());
}
public void damage(LivingEntity target, double value, DamageType... types) {
MMOLib.plugin.getDamage().damage(playerData.getPlayer(), target, new AttackResult(true, value, types));
}
}

View File

@ -1,24 +0,0 @@
package net.Indyuce.mmocore.api.player.stats.stat;
import org.bukkit.attribute.Attribute;
import net.Indyuce.mmocore.api.player.PlayerData;
public class AttributeStat extends PlayerStat {
private final Attribute attribute;
public AttributeStat(Attribute attribute) {
super(attribute.name().substring(8));
this.attribute = attribute;
}
public Attribute getAttribute() {
return attribute;
}
@Override
public void refresh(PlayerData player, double val) {
player.getPlayer().getAttribute(attribute).setBaseValue(val);
}
}

View File

@ -1,32 +0,0 @@
package net.Indyuce.mmocore.api.player.stats.stat;
import org.bukkit.attribute.Attribute;
import org.bukkit.inventory.ItemStack;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.stats.StatType;
public class MovementSpeedStat extends AttributeStat {
/*
* both used for the 'movement speed' and for the 'speed malus reduction'
* stats because the movement speed must be refreshed every time one of
* these stats are changed.
*/
public MovementSpeedStat() {
super(Attribute.GENERIC_MOVEMENT_SPEED);
}
@Override
public void refresh(PlayerData player, double val) {
double speedMalus = MMOCore.plugin.configManager.speedMalus * (1 - player.getStats().getStat(StatType.SPEED_MALUS_REDUCTION) / 100);
double movementSpeed = player.getStats().getStat(StatType.MOVEMENT_SPEED);
for (ItemStack item : player.getPlayer().getEquipment().getArmorContents())
if (item != null)
if (item.getType().name().contains("IRON") || item.getType().name().contains("DIAMOND"))
movementSpeed *= 1 - speedMalus;
player.getPlayer().setWalkSpeed((float) Math.min(1, movementSpeed));
}
}

View File

@ -1,17 +0,0 @@
package net.Indyuce.mmocore.api.player.stats.stat;
import net.Indyuce.mmocore.api.player.PlayerData;
public abstract class PlayerStat {
private final String id;
public PlayerStat(String id) {
this.id = id;
}
public String getId() {
return id;
}
public abstract void refresh(PlayerData player, double val);
}

View File

@ -1,51 +0,0 @@
package net.Indyuce.mmocore.api.player.stats.stat.modifier;
import org.apache.commons.lang.Validate;
import net.Indyuce.mmocore.MMOCore;
public class StatModifier {
private final double d;
private final boolean relative;
public StatModifier(double d) {
this(d, false);
}
public StatModifier(double d, boolean relative) {
this.d = d;
this.relative = relative;
}
public StatModifier(String str) {
Validate.notNull(str, "String cannot be null");
Validate.notEmpty(str, "String cannot be empty");
relative = str.toCharArray()[str.length() - 1] == '%';
d = Double.parseDouble(relative ? str.substring(0, str.length() - 1) : str);
}
public StatModifier multiply(int coef) {
return new StatModifier(d * coef, relative);
}
public boolean isRelative() {
return relative;
}
public double getValue() {
return d;
}
public double apply(double in) {
return relative ? in * (1 + d / 100) : in + d;
}
public void close() {
}
@Override
public String toString() {
return MMOCore.plugin.configManager.decimal.format(d) + (relative ? "%" : "");
}
}

View File

@ -1,25 +0,0 @@
package net.Indyuce.mmocore.api.player.stats.stat.modifier;
import org.bukkit.scheduler.BukkitRunnable;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.stats.PlayerStats.StatInstance;
public class TemporaryStatModifier extends StatModifier {
private final BukkitRunnable runnable;
public TemporaryStatModifier(double d, long duration, boolean relative, String key, StatInstance ins) {
super(d, relative);
(runnable = new BukkitRunnable() {
public void run() {
ins.remove(key);
}
}).runTaskLater(MMOCore.plugin, duration);
}
public void close() {
if (!runnable.isCancelled())
runnable.cancel();
}
}

View File

@ -0,0 +1,76 @@
package net.Indyuce.mmocore.comp;
import java.util.Iterator;
import java.util.function.Consumer;
import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeInstance;
import org.bukkit.attribute.AttributeModifier;
import org.bukkit.inventory.ItemStack;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.stats.StatType;
import net.mmogroup.mmolib.api.player.MMOData;
import net.mmogroup.mmolib.api.stat.SharedStat;
import net.mmogroup.mmolib.api.stat.StatMap;
public class MMOLibHook {
public MMOLibHook() {
StatMap.registerUpdate(SharedStat.ARMOR, new AttributeStatHandler(Attribute.GENERIC_ARMOR, StatType.ARMOR));
StatMap.registerUpdate(SharedStat.ARMOR_TOUGHNESS, new AttributeStatHandler(Attribute.GENERIC_ARMOR_TOUGHNESS, StatType.ARMOR));
StatMap.registerUpdate(SharedStat.ATTACK_DAMAGE, new AttributeStatHandler(Attribute.GENERIC_ATTACK_DAMAGE, StatType.ATTACK_DAMAGE));
StatMap.registerUpdate(SharedStat.ATTACK_SPEED, new AttributeStatHandler(Attribute.GENERIC_ATTACK_SPEED, StatType.ATTACK_SPEED));
StatMap.registerUpdate(SharedStat.KNOCKBACK_RESISTANCE, new AttributeStatHandler(Attribute.GENERIC_KNOCKBACK_RESISTANCE, StatType.KNOCKBACK_RESISTANCE));
StatMap.registerUpdate(SharedStat.ARMOR, new AttributeStatHandler(Attribute.GENERIC_MAX_HEALTH, StatType.MAX_HEALTH));
Consumer<MMOData> moveSpeed = new MovementSpeedStat();
StatMap.registerUpdate(SharedStat.MOVEMENT_SPEED, moveSpeed);
StatMap.registerUpdate(SharedStat.SPEED_MALUS_REDUCTION, moveSpeed);
}
public class AttributeStatHandler implements Consumer<MMOData> {
private final Attribute attribute;
private final StatType stat;
public AttributeStatHandler(Attribute attribute, StatType stat) {
this.attribute = attribute;
this.stat = stat;
}
@Override
public void accept(MMOData data) {
AttributeInstance ins = data.getPlayer().getAttribute(attribute);
removeModifiers(ins);
ins.setBaseValue(data.getMMOCore().getStats().getStat(stat));
}
private void removeModifiers(AttributeInstance ins) {
for (Iterator<AttributeModifier> iterator = ins.getModifiers().iterator(); iterator.hasNext();) {
AttributeModifier attribute = iterator.next();
if (attribute.getName().startsWith("mmolib."))
ins.removeModifier(attribute);
}
}
}
/*
* both used for the 'movement speed' and for the 'speed malus reduction'
* stats because the movement speed must be refreshed every time one of
* these stats are changed.
*/
public class MovementSpeedStat implements Consumer<MMOData> {
@Override
public void accept(MMOData data) {
double speedMalus = MMOCore.plugin.configManager.speedMalus * (1 - data.getMMOCore().getStats().getStat(StatType.SPEED_MALUS_REDUCTION) / 100);
double movementSpeed = data.getMMOCore().getStats().getStat(StatType.MOVEMENT_SPEED);
for (ItemStack item : data.getPlayer().getEquipment().getArmorContents())
if (item != null)
if (item.getType().name().contains("IRON") || item.getType().name().contains("DIAMOND"))
movementSpeed *= 1 - speedMalus;
data.getPlayer().setWalkSpeed((float) Math.min(1, movementSpeed));
}
}
}

View File

@ -1,11 +1,12 @@
package net.Indyuce.mmocore.comp.rpg;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.stats.TemporaryStats;
import net.Indyuce.mmocore.api.player.stats.PlayerStats.CachedStats;
public class DefaultRPGUtilHandler implements RPGUtilHandler {
@Override
public TemporaryStats cachePlayerStats(PlayerData playerData) {
return new TemporaryStats(playerData.getStats());
public CachedStats cachePlayerStats(PlayerData playerData) {
return playerData.getStats().cache();
}
}

View File

@ -1,9 +1,8 @@
package net.Indyuce.mmocore.comp.rpg;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.stats.TemporaryStats;
import net.Indyuce.mmocore.api.player.stats.PlayerStats.CachedStats;
public interface RPGUtilHandler {
public TemporaryStats cachePlayerStats(PlayerData playerData);
public CachedStats cachePlayerStats(PlayerData playerData);
}

View File

@ -9,7 +9,6 @@ import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.attribute.PlayerAttribute;
import net.Indyuce.mmocore.api.player.attribute.PlayerAttributes.AttributeInstance;
import net.Indyuce.mmocore.api.player.stats.StatType;
import net.Indyuce.mmocore.api.player.stats.stat.modifier.StatModifier;
import net.Indyuce.mmocore.gui.api.EditableInventory;
import net.Indyuce.mmocore.gui.api.GeneratedInventory;
import net.Indyuce.mmocore.gui.api.PluginInventory;
@ -17,6 +16,7 @@ import net.Indyuce.mmocore.gui.api.item.InventoryItem;
import net.Indyuce.mmocore.gui.api.item.InventoryPlaceholderItem;
import net.Indyuce.mmocore.gui.api.item.NoPlaceholderItem;
import net.Indyuce.mmocore.gui.api.item.Placeholders;
import net.mmogroup.mmolib.api.stat.modifier.StatModifier;
public class AttributeView extends EditableInventory {
public AttributeView() {

View File

@ -21,6 +21,7 @@ import net.Indyuce.mmocore.api.player.stats.PlayerStats;
import net.Indyuce.mmocore.api.player.stats.StatType;
import net.Indyuce.mmocore.gui.api.PluginInventory;
import net.mmogroup.mmolib.api.DamageType;
import net.mmogroup.mmolib.api.stat.SharedStat;
public class PlayerListener implements Listener {
@ -30,7 +31,7 @@ public class PlayerListener implements Listener {
@EventHandler(priority = EventPriority.LOWEST)
public void a(PlayerJoinEvent event) {
Player player = event.getPlayer();
PlayerData.setup(player).getStats().updateAll();
PlayerData.setup(player).getStats().getMap().updateAll();
}
/*
@ -90,7 +91,7 @@ public class PlayerListener implements Listener {
*/
@EventHandler
public void g(ArmorEquipEvent event) {
PlayerData.get(event.getPlayer()).getStats().update(StatType.MOVEMENT_SPEED);
PlayerData.get(event.getPlayer()).getStats().getMap().runUpdates(SharedStat.MOVEMENT_SPEED);
}
/*

View File

@ -12,8 +12,8 @@ import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.social.Party;
import net.Indyuce.mmocore.api.player.stats.StatType;
import net.Indyuce.mmocore.api.player.stats.stat.modifier.StatModifier;
import net.Indyuce.mmocore.manager.MMOManager;
import net.mmogroup.mmolib.api.stat.modifier.StatModifier;
public class PartyManager extends MMOManager {
private final Set<Party> parties = new HashSet<>();

View File

@ -21,7 +21,7 @@ import net.Indyuce.mmocore.api.event.PlayerAttackEvent;
import net.Indyuce.mmocore.api.math.formula.LinearValue;
import net.Indyuce.mmocore.api.math.particle.ParabolicProjectile;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.stats.TemporaryStats;
import net.Indyuce.mmocore.api.player.stats.PlayerStats.CachedStats;
import net.Indyuce.mmocore.api.skill.Skill;
import net.Indyuce.mmocore.api.skill.SkillResult;
import net.mmogroup.mmolib.api.DamageType;
@ -59,7 +59,7 @@ public class Power_Mark extends Skill implements Listener {
public class PowerMark extends BukkitRunnable implements Listener {
private final PlayerData data;
private final Location loc;
private final TemporaryStats stats;
private final CachedStats stats;
private double duration, ratio, stun;