Fixed additive attack speed

This commit is contained in:
Indyuce 2020-12-27 19:11:43 +01:00
parent 1ae4262e75
commit 79f9265118
24 changed files with 379 additions and 208 deletions

View File

@ -29,6 +29,7 @@ import net.Indyuce.mmoitems.command.completion.UpdateItemCompletion;
import net.Indyuce.mmoitems.comp.AdvancedEnchantmentsHook; import net.Indyuce.mmoitems.comp.AdvancedEnchantmentsHook;
import net.Indyuce.mmoitems.comp.MMOItemsMetrics; import net.Indyuce.mmoitems.comp.MMOItemsMetrics;
import net.Indyuce.mmoitems.comp.MMOItemsRewardTypes; import net.Indyuce.mmoitems.comp.MMOItemsRewardTypes;
import net.Indyuce.mmoitems.comp.McMMONonRPGHook;
import net.Indyuce.mmoitems.comp.RealDualWieldHook; import net.Indyuce.mmoitems.comp.RealDualWieldHook;
import net.Indyuce.mmoitems.comp.WorldEditSupport; import net.Indyuce.mmoitems.comp.WorldEditSupport;
import net.Indyuce.mmoitems.comp.eco.VaultSupport; import net.Indyuce.mmoitems.comp.eco.VaultSupport;
@ -155,6 +156,9 @@ public class MMOItems extends JavaPlugin {
if (Bukkit.getPluginManager().getPlugin("MMOCore") != null) if (Bukkit.getPluginManager().getPlugin("MMOCore") != null)
new MMOCoreMMOLoader(); new MMOCoreMMOLoader();
if (Bukkit.getPluginManager().getPlugin("mcMMO") != null)
statManager.register(McMMOHook.disableMcMMORepair);
} }
public void onEnable() { public void onEnable() {
@ -232,17 +236,17 @@ public class MMOItems extends JavaPlugin {
*/ */
Bukkit.getScheduler().runTaskTimer(this, () -> { Bukkit.getScheduler().runTaskTimer(this, () -> {
for (Player player : Bukkit.getOnlinePlayers()) for (Player player : Bukkit.getOnlinePlayers())
PlayerData.get(player).checkForInventoryUpdate(); PlayerData.get(player).getInventory().updateCheck();
}, 100, getConfig().getInt("inventory-update-delay")); }, 100, getConfig().getInt("inventory-update-delay"));
if (Bukkit.getPluginManager().getPlugin("mcMMO") != null)
statManager.register(McMMOHook.disableMcMMORepair);
if (Bukkit.getPluginManager().getPlugin("Residence") != null) { if (Bukkit.getPluginManager().getPlugin("Residence") != null) {
flagPlugin = new ResidenceFlags(); flagPlugin = new ResidenceFlags();
getLogger().log(Level.INFO, "Hooked onto Residence"); getLogger().log(Level.INFO, "Hooked onto Residence");
} }
if (Bukkit.getPluginManager().getPlugin("mcMMO") != null)
Bukkit.getPluginManager().registerEvents(new McMMONonRPGHook(), this);
if (Bukkit.getPluginManager().getPlugin("RPGInventory") != null) { if (Bukkit.getPluginManager().getPlugin("RPGInventory") != null) {
inventory = new RPGInventoryHook(); inventory = new RPGInventoryHook();
getLogger().log(Level.INFO, "Hooked onto RPGInventory"); getLogger().log(Level.INFO, "Hooked onto RPGInventory");

View File

@ -145,7 +145,7 @@ public class Type {
return melee; return melee;
} }
public boolean isSpecialActionOnRightClick() { public boolean rightClickInteraction() {
return rightClickSpecial; return rightClickSpecial;
} }
@ -258,32 +258,50 @@ public class Type {
return id != null && MMOItems.plugin.getTypes().has(id.toUpperCase().replace("-", "_").replace(" ", "_")); return id != null && MMOItems.plugin.getTypes().has(id.toUpperCase().replace("-", "_").replace(" ", "_"));
} }
/**
* Used by player inventory updates to store where the items are equipped
* and if they should be updated when some specific event happens.
*
* @author cympe
*
*/
public enum EquipmentSlot { public enum EquipmentSlot {
/* /**
* can only apply stats in armor * Can only apply stats in armor slots
*/ */
ARMOR, ARMOR,
/* /**
* can't apply stats in vanilla slots * Can't apply stats in vanilla slots
*/ */
ACCESSORY, ACCESSORY,
/* /**
* cannot apply its stats anywhere * Cannot apply its stats anywhere
*/ */
OTHER, OTHER,
/* /**
* always apply its stats. may only be used by EquippedItems, and not * Always apply its stats. may only be used by EquippedItems, and not
* Types since default types do not use it and extra types keep their * Types since default types do not use it and extra types keep their
* parent equipment slot * parent equipment slot
*/ */
ANY, ANY,
/**
* Apply stats in main hands only
*/
MAIN_HAND, MAIN_HAND,
/**
* Apply stats in off hand slot only (off hand catalysts mainly)
*/
OFF_HAND, OFF_HAND,
/**
* Apply stats in both hands, ie shields or bows
*/
BOTH_HANDS; BOTH_HANDS;
public boolean isHand() { public boolean isHand() {

View File

@ -28,10 +28,8 @@ public class DurabilityItem {
* Use to handle durability changes for MMOItems without using heavy MMOItem * Use to handle durability changes for MMOItems without using heavy MMOItem
* class methods * class methods
* *
* @param player * @param player Player holding the item
* Player holding the item * @param item Item with durability
* @param item
* Item with durability
*/ */
public DurabilityItem(Player player, ItemStack item) { public DurabilityItem(Player player, ItemStack item) {
this(player, MMOLib.plugin.getVersion().getWrapper().getNBTItem(item)); this(player, MMOLib.plugin.getVersion().getWrapper().getNBTItem(item));
@ -41,10 +39,8 @@ public class DurabilityItem {
* Use to handle durability changes for MMOItems without using heavy MMOItem * Use to handle durability changes for MMOItems without using heavy MMOItem
* class methods * class methods
* *
* @param player * @param player Player holding the item
* Player holding the item * @param item Item with durability
* @param item
* Item with durability
*/ */
public DurabilityItem(Player player, NBTItem item) { public DurabilityItem(Player player, NBTItem item) {
this.player = player; this.player = player;
@ -109,13 +105,14 @@ public class DurabilityItem {
// When the item breaks // When the item breaks
if (durability <= 0) { if (durability <= 0) {
player.getWorld().playSound(player.getLocation(), Sound.ENTITY_ITEM_BREAK, 1, 1); player.getWorld().playSound(player.getLocation(), Sound.ENTITY_ITEM_BREAK, 1, 1);
PlayerData.get(player).scheduleDelayedInventoryUpdate(); PlayerData.get(player).getInventory().scheduleUpdate();
} }
return this; return this;
} }
public ItemStack toItem() { public ItemStack toItem() {
/* /*
* Cross multiplication to display the current item durability on the * Cross multiplication to display the current item durability on the
* item durability bar. (1 - ratio) because minecraft works with item * item durability bar. (1 - ratio) because minecraft works with item

View File

@ -1,5 +1,23 @@
package net.Indyuce.mmoitems.api.player; package net.Indyuce.mmoitems.api.player;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitRunnable;
import net.Indyuce.mmoitems.ItemStats; import net.Indyuce.mmoitems.ItemStats;
import net.Indyuce.mmoitems.MMOItems; import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.MMOUtils; import net.Indyuce.mmoitems.MMOUtils;
@ -8,6 +26,7 @@ import net.Indyuce.mmoitems.api.ItemAttackResult;
import net.Indyuce.mmoitems.api.ItemSet; import net.Indyuce.mmoitems.api.ItemSet;
import net.Indyuce.mmoitems.api.ItemSet.SetBonuses; import net.Indyuce.mmoitems.api.ItemSet.SetBonuses;
import net.Indyuce.mmoitems.api.Type; import net.Indyuce.mmoitems.api.Type;
import net.Indyuce.mmoitems.api.Type.EquipmentSlot;
import net.Indyuce.mmoitems.api.ability.Ability; import net.Indyuce.mmoitems.api.ability.Ability;
import net.Indyuce.mmoitems.api.ability.Ability.CastingMode; import net.Indyuce.mmoitems.api.ability.Ability.CastingMode;
import net.Indyuce.mmoitems.api.ability.AbilityResult; import net.Indyuce.mmoitems.api.ability.AbilityResult;
@ -15,8 +34,10 @@ import net.Indyuce.mmoitems.api.crafting.CraftingStatus;
import net.Indyuce.mmoitems.api.event.AbilityUseEvent; import net.Indyuce.mmoitems.api.event.AbilityUseEvent;
import net.Indyuce.mmoitems.api.item.mmoitem.VolatileMMOItem; import net.Indyuce.mmoitems.api.item.mmoitem.VolatileMMOItem;
import net.Indyuce.mmoitems.api.player.PlayerStats.CachedStats; import net.Indyuce.mmoitems.api.player.PlayerStats.CachedStats;
import net.Indyuce.mmoitems.api.player.inventory.EquippedItem;
import net.Indyuce.mmoitems.api.player.inventory.EquippedPlayerItem;
import net.Indyuce.mmoitems.api.player.inventory.InventoryUpdateHandler;
import net.Indyuce.mmoitems.comp.flags.FlagPlugin.CustomFlag; import net.Indyuce.mmoitems.comp.flags.FlagPlugin.CustomFlag;
import net.Indyuce.mmoitems.comp.inventory.PlayerInventory.EquippedItem;
import net.Indyuce.mmoitems.particle.api.ParticleRunnable; import net.Indyuce.mmoitems.particle.api.ParticleRunnable;
import net.Indyuce.mmoitems.stat.data.AbilityData; import net.Indyuce.mmoitems.stat.data.AbilityData;
import net.Indyuce.mmoitems.stat.data.AbilityListData; import net.Indyuce.mmoitems.stat.data.AbilityListData;
@ -28,27 +49,6 @@ import net.mmogroup.mmolib.MMOLib;
import net.mmogroup.mmolib.api.DamageType; import net.mmogroup.mmolib.api.DamageType;
import net.mmogroup.mmolib.api.item.NBTItem; import net.mmogroup.mmolib.api.item.NBTItem;
import net.mmogroup.mmolib.api.player.MMOPlayerData; import net.mmogroup.mmolib.api.player.MMOPlayerData;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
public class PlayerData { public class PlayerData {
private static final Map<UUID, PlayerData> data = new HashMap<>(); private static final Map<UUID, PlayerData> data = new HashMap<>();
@ -59,14 +59,7 @@ public class PlayerData {
*/ */
private RPGPlayer rpgPlayer; private RPGPlayer rpgPlayer;
/* private final InventoryUpdateHandler inventory = new InventoryUpdateHandler(this);
* the inventory is all the items the player can actually use. items are
* cached here to check if the player's items changed, if so just update
* inventory TODO improve player inventory checkup method
*/
private ItemStack helmet = null, chestplate = null, leggings = null, boots = null, hand = null, offhand = null;
private final List<VolatileMMOItem> playerInventory = new ArrayList<>();
private final CraftingStatus craftingStatus = new CraftingStatus(); private final CraftingStatus craftingStatus = new CraftingStatus();
private final PlayerAbilityData playerAbilityData = new PlayerAbilityData(); private final PlayerAbilityData playerAbilityData = new PlayerAbilityData();
private final Map<String, CooldownInformation> abilityCooldowns = new HashMap<>(); private final Map<String, CooldownInformation> abilityCooldowns = new HashMap<>();
@ -140,32 +133,6 @@ public class PlayerData {
return rpgPlayer; return rpgPlayer;
} }
/*
* returns all the usable MMOItems in the player inventory, this can be used
* to calculate stats. this list updates each time a player equips a new
* item.
*/
public List<VolatileMMOItem> getMMOItems() {
return playerInventory;
}
public void checkForInventoryUpdate() {
if (!mmoData.isOnline())
return;
PlayerInventory inv = getPlayer().getInventory();
if (isNotSame(helmet, inv.getHelmet()) || isNotSame(chestplate, inv.getChestplate()) || isNotSame(leggings, inv.getLeggings())
|| isNotSame(boots, inv.getBoots()) || isNotSame(hand, inv.getItemInMainHand()) || isNotSame(offhand, inv.getItemInOffHand()))
updateInventory();
}
public void scheduleDelayedInventoryUpdate() {
Bukkit.getScheduler().scheduleSyncDelayedTask(MMOItems.plugin, this::updateInventory);
}
private boolean isNotSame(ItemStack item, ItemStack item1) {
return !Objects.equals(item, item1);
}
public void cancelRunnables() { public void cancelRunnables() {
itemParticles.forEach(BukkitRunnable::cancel); itemParticles.forEach(BukkitRunnable::cancel);
if (overridingItemParticles != null) if (overridingItemParticles != null)
@ -179,20 +146,23 @@ public class PlayerData {
public boolean areHandsFull() { public boolean areHandsFull() {
if (!mmoData.isOnline()) if (!mmoData.isOnline())
return false; return false;
NBTItem main = MMOLib.plugin.getVersion().getWrapper().getNBTItem(getPlayer().getInventory().getItemInMainHand()); NBTItem main = MMOLib.plugin.getVersion().getWrapper().getNBTItem(getPlayer().getInventory().getItemInMainHand());
NBTItem off = MMOLib.plugin.getVersion().getWrapper().getNBTItem(getPlayer().getInventory().getItemInOffHand()); NBTItem off = MMOLib.plugin.getVersion().getWrapper().getNBTItem(getPlayer().getInventory().getItemInOffHand());
return (main.getBoolean("MMOITEMS_TWO_HANDED") && (off.getItem() != null && off.getItem().getType() != Material.AIR)) return (main.getBoolean("MMOITEMS_TWO_HANDED") && (off.getItem() != null && off.getItem().getType() != Material.AIR))
|| (off.getBoolean("MMOITEMS_TWO_HANDED") && (main.getItem() != null && main.getItem().getType() != Material.AIR)); || (off.getBoolean("MMOITEMS_TWO_HANDED") && (main.getItem() != null && main.getItem().getType() != Material.AIR));
} }
@SuppressWarnings("deprecation")
public void updateInventory() { public void updateInventory() {
if (!mmoData.isOnline()) if (!mmoData.isOnline())
return; return;
/* /*
* very important, clear particle data AFTER canceling the runnable * very important, clear particle data AFTER canceling the runnable
* otherwise it cannot cancel and the runnable keeps going (severe) * otherwise it cannot cancel and the runnable keeps going (severe)
*/ */
playerInventory.clear(); inventory.getEquipped().clear();
permanentEffects.clear(); permanentEffects.clear();
itemAbilities.clear(); itemAbilities.clear();
cancelRunnables(); cancelRunnables();
@ -213,32 +183,28 @@ public class PlayerData {
*/ */
fullHands = areHandsFull(); fullHands = areHandsFull();
// find all the items the player can actually use. /*
* Find all the items the player can actually use
*/
for (EquippedItem item : MMOItems.plugin.getInventory().getInventory(getPlayer())) { for (EquippedItem item : MMOItems.plugin.getInventory().getInventory(getPlayer())) {
NBTItem nbtItem = item.newNBTItem(); NBTItem nbtItem = item.getItem();
Type type = Type.get(nbtItem.getType()); Type type = Type.get(nbtItem.getType());
if (type == null)
continue;
/* /**
* if the player is holding an item the wrong way i.e if the item is * If the item is a custom item, apply slot and item use
* not in the right slot. intuitive methods with small exceptions * restrictions (items which only work in a specific equipment slot)
* like BOTH_HANDS and ANY
*/ */
if (!item.matches(type)) if (type != null && (!item.matches(type) || !getRPG().canUse(nbtItem, false)))
continue; continue;
if (!getRPG().canUse(nbtItem, false)) inventory.getEquipped().add(new EquippedPlayerItem(item));
continue;
playerInventory.add(new VolatileMMOItem(nbtItem));
} }
for (VolatileMMOItem item : getMMOItems()) { for (EquippedPlayerItem equipped : inventory.getEquipped()) {
VolatileMMOItem item = equipped.getItem();
/* /*
* apply permanent potion effects * Apply permanent potion effects
*/ */
if (item.hasData(ItemStats.PERM_EFFECTS)) if (item.hasData(ItemStats.PERM_EFFECTS))
((PotionEffectListData) item.getData(ItemStats.PERM_EFFECTS)).getEffects().forEach(effect -> { ((PotionEffectListData) item.getData(ItemStats.PERM_EFFECTS)).getEffects().forEach(effect -> {
@ -247,7 +213,7 @@ public class PlayerData {
}); });
/* /*
* apply item particles * Apply item particles
*/ */
if (item.hasData(ItemStats.ITEM_PARTICLES)) { if (item.hasData(ItemStats.ITEM_PARTICLES)) {
ParticleData particleData = (ParticleData) item.getData(ItemStats.ITEM_PARTICLES); ParticleData particleData = (ParticleData) item.getData(ItemStats.ITEM_PARTICLES);
@ -260,21 +226,14 @@ public class PlayerData {
} }
/* /*
* apply abilities * Apply abilities
*/ */
if (item.hasData(ItemStats.ABILITIES)) { if (item.hasData(ItemStats.ABILITIES))
// if the item with the abilities is in the players offhand AND if (equipped.getSlot() != EquipmentSlot.OFF_HAND || !MMOItems.plugin.getConfig().getBoolean("disable-abilities-in-offhand"))
// its disabled in the config then just move on, else add the
// ability
if (item.getNBT().getItem().equals(getPlayer().getInventory().getItemInOffHand())
&& MMOItems.plugin.getConfig().getBoolean("disable-abilities-in-offhand")) {
continue;
} else
itemAbilities.addAll(((AbilityListData) item.getData(ItemStats.ABILITIES)).getAbilities()); itemAbilities.addAll(((AbilityListData) item.getData(ItemStats.ABILITIES)).getAbilities());
}
/* /*
* apply permissions if vault exists * Apply permissions if vault exists
*/ */
if (MMOItems.plugin.hasPermissions() && item.hasData(ItemStats.GRANTED_PERMISSIONS)) { if (MMOItems.plugin.hasPermissions() && item.hasData(ItemStats.GRANTED_PERMISSIONS)) {
permissions.addAll(((StringListData) item.getData(ItemStats.GRANTED_PERMISSIONS)).getList()); permissions.addAll(((StringListData) item.getData(ItemStats.GRANTED_PERMISSIONS)).getList());
@ -293,7 +252,8 @@ public class PlayerData {
int max = 0; int max = 0;
ItemSet set = null; ItemSet set = null;
Map<ItemSet, Integer> sets = new HashMap<>(); Map<ItemSet, Integer> sets = new HashMap<>();
for (VolatileMMOItem item : getMMOItems()) { for (EquippedPlayerItem equipped : inventory.getEquipped()) {
VolatileMMOItem item = equipped.getItem();
String tag = item.getNBT().getString("MMOITEMS_ITEM_SET"); String tag = item.getNBT().getString("MMOITEMS_ITEM_SET");
ItemSet itemSet = MMOItems.plugin.getSets().get(tag); ItemSet itemSet = MMOItems.plugin.getSets().get(tag);
if (itemSet == null) if (itemSet == null)
@ -333,12 +293,12 @@ public class PlayerData {
* actually update the player inventory so the task doesn't infinitely * actually update the player inventory so the task doesn't infinitely
* loop on updating * loop on updating
*/ */
helmet = getPlayer().getInventory().getHelmet(); inventory.helmet = getPlayer().getInventory().getHelmet();
chestplate = getPlayer().getInventory().getChestplate(); inventory.chestplate = getPlayer().getInventory().getChestplate();
leggings = getPlayer().getInventory().getLeggings(); inventory.leggings = getPlayer().getInventory().getLeggings();
boots = getPlayer().getInventory().getBoots(); inventory.boots = getPlayer().getInventory().getBoots();
hand = getPlayer().getInventory().getItemInMainHand(); inventory.hand = getPlayer().getInventory().getItemInMainHand();
offhand = getPlayer().getInventory().getItemInOffHand(); inventory.offhand = getPlayer().getInventory().getItemInOffHand();
} }
public void updateStats() { public void updateStats() {
@ -353,6 +313,10 @@ public class PlayerData {
getPlayer().addPotionEffect(new PotionEffect(PotionEffectType.SLOW, 40, 1, true, false)); getPlayer().addPotionEffect(new PotionEffect(PotionEffectType.SLOW, 40, 1, true, false));
} }
public InventoryUpdateHandler getInventory() {
return inventory;
}
public SetBonuses getSetBonuses() { public SetBonuses getSetBonuses() {
return setBonuses; return setBonuses;
} }
@ -441,23 +405,29 @@ public class PlayerData {
} }
public void cast(CachedStats stats, LivingEntity target, ItemAttackResult attack, AbilityData ability) { public void cast(CachedStats stats, LivingEntity target, ItemAttackResult attack, AbilityData ability) {
AbilityUseEvent event = new AbilityUseEvent(this, ability, target);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled())
return;
/*
* Apply simple conditions including mana and stamina cost, permission
* and cooldown checks
*/
if (!rpgPlayer.canCast(ability)) if (!rpgPlayer.canCast(ability))
return; return;
/* /*
* check if ability can be cast (custom conditions) * Apply extra conditions which depend on the ability the player is
* casting
*/ */
AbilityResult abilityResult = ability.getAbility().whenRan(stats, target, ability, attack); AbilityResult abilityResult = ability.getAbility().whenRan(stats, target, ability, attack);
if (!abilityResult.isSuccessful()) if (!abilityResult.isSuccessful())
return; return;
AbilityUseEvent event = new AbilityUseEvent(this, ability, target);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled())
return;
/* /*
* the player can cast the ability, and it was successfully cast on its * The player can cast the ability, and it was successfully cast on its
* target, removes resources needed from the player * target, removes resources needed from the player
*/ */
if (ability.hasModifier("mana")) if (ability.hasModifier("mana"))
@ -470,7 +440,7 @@ public class PlayerData {
applyAbilityCooldown(ability.getAbility(), cooldown); applyAbilityCooldown(ability.getAbility(), cooldown);
/* /*
* finally cast the ability (BUG FIX) cooldown MUST be applied BEFORE * Finally cast the ability; BUG FIX: cooldown MUST be applied BEFORE
* the ability is cast otherwise instantaneously damaging abilities like * the ability is cast otherwise instantaneously damaging abilities like
* Sparkle can trigger deadly crash loops * Sparkle can trigger deadly crash loops
*/ */
@ -531,31 +501,30 @@ public class PlayerData {
} }
public static PlayerData get(UUID uuid) { public static PlayerData get(UUID uuid) {
if (PlayerData.data.containsKey(uuid)) return data.get(uuid);
return data.get(uuid);
return new PlayerData(MMOPlayerData.get(uuid));
} }
/* /**
* method called when the corresponding MMOPlayerData has already been * Called when the corresponding MMOPlayerData has already been initialized
* initialized
*/ */
public static void load(Player player) { public static void load(Player player) {
/* /*
* Double check they are online, for some reason even if this is fired * Double check they are online, for some reason even if this is fired
* from the join event the player can be offline if they left in the * from the join event the player can be offline if they left in the
* same tick or something. * same tick or something.
*/ */
if (!player.isOnline() || data.containsKey(player.getUniqueId())) if (!data.containsKey(player.getUniqueId())) {
data.put(player.getUniqueId(), new PlayerData(MMOPlayerData.get(player)));
return; return;
PlayerData newData = PlayerData.get(player.getUniqueId()); }
/* /*
* update the cached RPGPlayer in case of any major change in the player * Update the cached RPGPlayer in case of any major change in the player
* data of other rpg plugins * data of other rpg plugins
*/ */
newData.rpgPlayer = MMOItems.plugin.getRPG().getInfo(newData); PlayerData playerData = PlayerData.get(player.getUniqueId());
/* cache the playerdata */ playerData.rpgPlayer = MMOItems.plugin.getRPG().getInfo(playerData);
data.put(player.getUniqueId(), newData);
} }
public static Collection<PlayerData> getLoaded() { public static Collection<PlayerData> getLoaded() {
@ -564,16 +533,25 @@ public class PlayerData {
public enum CooldownType { public enum CooldownType {
// simple attack cooldown /**
* Basic attack cooldown like staffs and lutes
*/
ATTACK, ATTACK,
// elemental ttack /**
* Elemental attacks cooldown
*/
ELEMENTAL_ATTACK, ELEMENTAL_ATTACK,
// item type special effects /**
* Special attacks like staffs or gauntlets right clicks
*/
SPECIAL_ATTACK, SPECIAL_ATTACK,
// piercing / blunt / slashing passive effects /**
* Special item set attack effects including slashing, piercing and
* blunt attack effects
*/
SET_TYPE_ATTACK SET_TYPE_ATTACK
} }
} }

View File

@ -6,7 +6,8 @@ import java.util.Map;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import net.Indyuce.mmoitems.MMOItems; import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.item.mmoitem.VolatileMMOItem; import net.Indyuce.mmoitems.api.Type.EquipmentSlot;
import net.Indyuce.mmoitems.api.player.inventory.EquippedPlayerItem;
import net.Indyuce.mmoitems.stat.type.AttributeStat; import net.Indyuce.mmoitems.stat.type.AttributeStat;
import net.Indyuce.mmoitems.stat.type.ItemStat; import net.Indyuce.mmoitems.stat.type.ItemStat;
import net.mmogroup.mmolib.api.stat.StatInstance; import net.mmogroup.mmolib.api.stat.StatInstance;
@ -43,37 +44,49 @@ public class PlayerStats {
public void updateStats() { public void updateStats() {
getMap().getInstances().forEach(ins -> { getMap().getInstances().forEach(ins -> {
ins.remove("item"); ins.remove("MMOItem");
ins.remove("fullSetBonus"); ins.remove("MMOItemSetBonus");
}); });
if (playerData.hasSetBonuses()) if (playerData.hasSetBonuses())
playerData.getSetBonuses().getStats() playerData.getSetBonuses().getStats()
.forEach((stat, value) -> getInstance(stat).addModifier("fullSetBonus", new StatModifier(value, ModifierType.FLAT))); .forEach((stat, value) -> getInstance(stat).addModifier("MMOItemSetBonus", new StatModifier(value, ModifierType.FLAT)));
for (ItemStat stat : MMOItems.plugin.getStats().getNumericStats()) { for (ItemStat stat : MMOItems.plugin.getStats().getNumericStats()) {
double t = 0; double sum = 0;
for (VolatileMMOItem item : playerData.getMMOItems()) /*
t += item.getNBT().getStat(stat.getId()); * If the player is holding a weapon granting a certain stat, the
* final stat value should be applied the attribute stat offset like
* 4 for attack speed or 1 for attack damage
*/
boolean hasWeapon = false;
if (t != 0) for (EquippedPlayerItem item : playerData.getInventory().getEquipped()) {
getInstance(stat).addModifier("item", double value = item.getItem().getNBT().getStat(stat.getId());
new StatModifier(t - (stat instanceof AttributeStat ? ((AttributeStat) stat).getOffset() : 0), ModifierType.FLAT)); if (value != 0) {
sum += value;
if (!hasWeapon && item.getSlot() == EquipmentSlot.BOTH_HANDS)
hasWeapon = true;
}
}
if (sum != 0) {
double offset = hasWeapon && stat instanceof AttributeStat ? ((AttributeStat) stat).getOffset() : 0;
getInstance(stat).addModifier("MMOItem", new StatModifier(sum - offset, ModifierType.FLAT));
}
} }
} }
public class CachedStats { public class CachedStats {
/*
* this field is made final so even when the player logs out, the
* ability can still be cast without any additional errors. this allows
* not to add a safe check in every ability loop.
*/
private final Player player; private final Player player;
private final Map<String, Double> stats = new HashMap<>(); private final Map<String, Double> stats = new HashMap<>();
/**
* Used to cache stats when a player casts a skill so that if the player
* swaps items or changes any of his stat value before the end of the
* spell duration, the stat value is not updated
*/
public CachedStats() { public CachedStats() {
player = playerData.getPlayer(); player = playerData.getPlayer();
for (StatInstance ins : getMap().getInstances()) for (StatInstance ins : getMap().getInstances())

View File

@ -21,6 +21,14 @@ public abstract class RPGPlayer {
this(PlayerData.get(player)); this(PlayerData.get(player));
} }
/**
* Used to retrieve useful information like class name, level, mana and
* stamina from RPG plugins. This instance is reloaded everytime the player
* logs back on the server to ensure the object references are kept up to
* date
*
* @param playerData The corresponding player
*/
public RPGPlayer(PlayerData playerData) { public RPGPlayer(PlayerData playerData) {
this.player = playerData.getPlayer(); this.player = playerData.getPlayer();
this.playerData = playerData; this.playerData = playerData;

View File

@ -0,0 +1,47 @@
package net.Indyuce.mmoitems.api.player.inventory;
import org.bukkit.inventory.ItemStack;
import net.Indyuce.mmoitems.api.Type;
import net.Indyuce.mmoitems.api.Type.EquipmentSlot;
import net.mmogroup.mmolib.MMOLib;
import net.mmogroup.mmolib.api.item.NBTItem;
public class EquippedItem {
private final NBTItem item;
private final EquipmentSlot slot;
/**
* An item equipped by a player in a specific slot
*
* @param item The item equipped
* @param slot The corresponding MMOItems slot type
*/
public EquippedItem(ItemStack item, EquipmentSlot slot) {
this(MMOLib.plugin.getVersion().getWrapper().getNBTItem(item), slot);
}
/**
* An item equipped by a player in a specific slot
*
* @param item The item equipped
* @param slot The corresponding MMOItems slot type, must not be null!
*/
public EquippedItem(NBTItem item, EquipmentSlot slot) {
this.item = item;
this.slot = slot;
}
public NBTItem getItem() {
return item;
}
public EquipmentSlot getSlot() {
return slot;
}
public boolean matches(Type type) {
return slot == EquipmentSlot.ANY || (type.getEquipmentType() == EquipmentSlot.BOTH_HANDS ? slot.isHand()
: slot == EquipmentSlot.BOTH_HANDS ? type.getEquipmentType().isHand() : slot == type.getEquipmentType());
}
}

View File

@ -0,0 +1,34 @@
package net.Indyuce.mmoitems.api.player.inventory;
import net.Indyuce.mmoitems.api.Type;
import net.Indyuce.mmoitems.api.Type.EquipmentSlot;
import net.Indyuce.mmoitems.api.item.mmoitem.VolatileMMOItem;
public class EquippedPlayerItem {
private final VolatileMMOItem item;
private final EquipmentSlot slot;
/**
* An item equipped by a player in a specific slot
*
* @param item The item equipped
* @param slot The corresponding MMOItems slot type, must not be null!
*/
public EquippedPlayerItem(EquippedItem item) {
this.item = new VolatileMMOItem(item.getItem());
this.slot = item.getSlot();
}
public VolatileMMOItem getItem() {
return item;
}
public EquipmentSlot getSlot() {
return slot;
}
public boolean matches(Type type) {
return slot == EquipmentSlot.ANY || (type.getEquipmentType() == EquipmentSlot.BOTH_HANDS ? slot.isHand()
: slot == EquipmentSlot.BOTH_HANDS ? type.getEquipmentType().isHand() : slot == type.getEquipmentType());
}
}

View File

@ -0,0 +1,78 @@
package net.Indyuce.mmoitems.api.player.inventory;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import org.bukkit.Bukkit;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.Type.EquipmentSlot;
import net.Indyuce.mmoitems.api.player.PlayerData;
/**
* It's one of the most urgent systems to update. Moving everything to a new
* class to mark everything that needs to be changed
*
* @author cympe
*
*/
public class InventoryUpdateHandler {
private final PlayerData player;
private final List<EquippedPlayerItem> items = new ArrayList<>();
@Deprecated
public ItemStack helmet = null, chestplate = null, leggings = null, boots = null, hand = null, offhand = null;
/**
* Used to handle player inventory updates.
*/
public InventoryUpdateHandler(PlayerData player) {
this.player = player;
}
/**
* @return All equipped MMOItems in the player's inventory. Also includes
* items from custom inventory plugins like MMOInventory
*/
public List<EquippedPlayerItem> getEquipped() {
return items;
}
/**
* @return If the player has in his active item inventory an item with a
* specific equipment slot. This is ran by stat updates because MI
* needs to check if the player is holding a WEAPON before apply an
* attribute base stat value offset (attack damage/speed).
*/
public boolean hasItemWithType(EquipmentSlot checked) {
for (EquippedPlayerItem item : items)
if (item.getSlot() == checked)
return true;
return false;
}
public void updateCheck() {
if (!player.isOnline())
return;
PlayerInventory inv = player.getPlayer().getInventory();
if (isNotSame(helmet, inv.getHelmet()) || isNotSame(chestplate, inv.getChestplate()) || isNotSame(leggings, inv.getLeggings())
|| isNotSame(boots, inv.getBoots()) || isNotSame(hand, inv.getItemInMainHand()) || isNotSame(offhand, inv.getItemInOffHand()))
player.updateInventory();
}
/**
* Schedules an inventory update in one tick
*/
public void scheduleUpdate() {
Bukkit.getScheduler().scheduleSyncDelayedTask(MMOItems.plugin, player::updateInventory);
}
private boolean isNotSame(ItemStack item, ItemStack item1) {
return !Objects.equals(item, item1);
}
}

View File

@ -0,0 +1,27 @@
package net.Indyuce.mmoitems.comp;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import com.gmail.nossr50.events.skills.repair.McMMOPlayerRepairCheckEvent;
import net.mmogroup.mmolib.api.item.NBTItem;
/**
* The McMMOHook class is only instantiated if McMMO is being used by MMOItems
* as a RPGCore plugin however there are features which should enable even if
* McMMO is not detected as a RPG Core plugin if other RPG plugins are used at
* the same time.
*
* @author cympe
*
*/
public class McMMONonRPGHook implements Listener {
@EventHandler(ignoreCancelled = true)
public void handleNoMcMMORepair(McMMOPlayerRepairCheckEvent event) {
NBTItem nbt = NBTItem.get(event.getRepairedObject());
if (nbt.hasType() && nbt.getBoolean("MMOITEMS_DISABLE_MCMMO_REPAIR"))
event.setCancelled(true);
}
}

View File

@ -7,6 +7,7 @@ import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import net.Indyuce.mmoitems.api.Type.EquipmentSlot; import net.Indyuce.mmoitems.api.Type.EquipmentSlot;
import net.Indyuce.mmoitems.api.player.inventory.EquippedItem;
public class DefaultPlayerInventory implements PlayerInventory { public class DefaultPlayerInventory implements PlayerInventory {
@Override @Override

View File

@ -3,7 +3,6 @@ package net.Indyuce.mmoitems.comp.inventory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import net.Indyuce.mmoitems.api.Type;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -14,8 +13,10 @@ import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import net.Indyuce.mmoitems.MMOItems; import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.Type;
import net.Indyuce.mmoitems.api.Type.EquipmentSlot; import net.Indyuce.mmoitems.api.Type.EquipmentSlot;
import net.Indyuce.mmoitems.api.player.PlayerData; import net.Indyuce.mmoitems.api.player.PlayerData;
import net.Indyuce.mmoitems.api.player.inventory.EquippedItem;
import net.mmogroup.mmolib.MMOLib; import net.mmogroup.mmolib.MMOLib;
import net.mmogroup.mmolib.api.item.NBTItem; import net.mmogroup.mmolib.api.item.NBTItem;

View File

@ -3,36 +3,9 @@ package net.Indyuce.mmoitems.comp.inventory;
import java.util.List; import java.util.List;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import net.Indyuce.mmoitems.api.Type; import net.Indyuce.mmoitems.api.player.inventory.EquippedItem;
import net.Indyuce.mmoitems.api.Type.EquipmentSlot;
import net.mmogroup.mmolib.MMOLib;
import net.mmogroup.mmolib.api.item.NBTItem;
public interface PlayerInventory { public interface PlayerInventory {
List<EquippedItem> getInventory(Player player); List<EquippedItem> getInventory(Player player);
class EquippedItem {
private final NBTItem item;
private final EquipmentSlot slot;
public EquippedItem(ItemStack item, EquipmentSlot slot) {
this(MMOLib.plugin.getVersion().getWrapper().getNBTItem(item), slot);
}
public EquippedItem(NBTItem item, EquipmentSlot slot) {
this.item = item;
this.slot = slot;
}
public NBTItem newNBTItem() {
return item;
}
public boolean matches(Type type) {
return slot == EquipmentSlot.ANY || (type.getEquipmentType() == EquipmentSlot.BOTH_HANDS ? slot.isHand()
: slot == EquipmentSlot.BOTH_HANDS ? type.getEquipmentType().isHand() : slot == type.getEquipmentType());
}
}
} }

View File

@ -3,7 +3,6 @@ package net.Indyuce.mmoitems.comp.inventory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import net.Indyuce.mmoitems.api.Type;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
@ -12,8 +11,10 @@ import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import net.Indyuce.mmoitems.MMOItems; import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.Type;
import net.Indyuce.mmoitems.api.Type.EquipmentSlot; import net.Indyuce.mmoitems.api.Type.EquipmentSlot;
import net.Indyuce.mmoitems.api.player.PlayerData; import net.Indyuce.mmoitems.api.player.PlayerData;
import net.Indyuce.mmoitems.api.player.inventory.EquippedItem;
import net.mmogroup.mmolib.MMOLib; import net.mmogroup.mmolib.MMOLib;
import net.mmogroup.mmolib.api.item.NBTItem; import net.mmogroup.mmolib.api.item.NBTItem;
import ru.endlesscode.rpginventory.api.InventoryAPI; import ru.endlesscode.rpginventory.api.InventoryAPI;

View File

@ -43,17 +43,17 @@ public class MMOCoreHook implements RPGHandler, Listener {
@EventHandler @EventHandler
public void updateInventoryOnLevelUp(PlayerLevelUpEvent event) { public void updateInventoryOnLevelUp(PlayerLevelUpEvent event) {
net.Indyuce.mmoitems.api.player.PlayerData.get(event.getPlayer()).scheduleDelayedInventoryUpdate(); net.Indyuce.mmoitems.api.player.PlayerData.get(event.getPlayer()).getInventory().scheduleUpdate();
} }
@EventHandler @EventHandler
public void updateInventoryOnClassChange(PlayerChangeClassEvent event) { public void updateInventoryOnClassChange(PlayerChangeClassEvent event) {
net.Indyuce.mmoitems.api.player.PlayerData.get(event.getPlayer()).scheduleDelayedInventoryUpdate(); net.Indyuce.mmoitems.api.player.PlayerData.get(event.getPlayer()).getInventory().scheduleUpdate();
} }
@EventHandler @EventHandler
public void updateInventoryOnPlayerDataLoad(PlayerDataLoadEvent event) { public void updateInventoryOnPlayerDataLoad(PlayerDataLoadEvent event) {
net.Indyuce.mmoitems.api.player.PlayerData.get(event.getPlayer()).scheduleDelayedInventoryUpdate(); net.Indyuce.mmoitems.api.player.PlayerData.get(event.getPlayer()).getInventory().scheduleUpdate();
} }
public static class MMOCoreRPGPlayer extends RPGPlayer { public static class MMOCoreRPGPlayer extends RPGPlayer {

View File

@ -12,7 +12,7 @@ public class BattleLevelsHook implements RPGHandler, Listener {
@EventHandler @EventHandler
public void a(PlayerLevelUpEvent event) { public void a(PlayerLevelUpEvent event) {
PlayerData.get(event.getPlayer()).scheduleDelayedInventoryUpdate(); PlayerData.get(event.getPlayer()).getInventory().scheduleUpdate();
} }
@Override @Override

View File

@ -15,7 +15,7 @@ public class DefaultHook implements RPGHandler, Listener {
@EventHandler @EventHandler
public void a(PlayerLevelChangeEvent event) { public void a(PlayerLevelChangeEvent event) {
PlayerData.get(event.getPlayer()).scheduleDelayedInventoryUpdate(); PlayerData.get(event.getPlayer()).getInventory().scheduleUpdate();
} }
@Override @Override

View File

@ -63,12 +63,12 @@ public class HeroesHook implements RPGHandler, Listener, DamageHandler {
*/ */
@EventHandler @EventHandler
public void a(HeroChangeLevelEvent event) { public void a(HeroChangeLevelEvent event) {
PlayerData.get(event.getHero().getPlayer()).scheduleDelayedInventoryUpdate(); PlayerData.get(event.getHero().getPlayer()).getInventory().scheduleUpdate();
} }
@EventHandler @EventHandler
public void b(ClassChangeEvent event) { public void b(ClassChangeEvent event) {
PlayerData.get(event.getHero().getPlayer()).scheduleDelayedInventoryUpdate(); PlayerData.get(event.getHero().getPlayer()).getInventory().scheduleUpdate();
} }
// @EventHandler // @EventHandler

View File

@ -8,13 +8,11 @@ import com.gmail.nossr50.api.ExperienceAPI;
import com.gmail.nossr50.api.exceptions.McMMOPlayerNotFoundException; import com.gmail.nossr50.api.exceptions.McMMOPlayerNotFoundException;
import com.gmail.nossr50.events.experience.McMMOPlayerLevelDownEvent; import com.gmail.nossr50.events.experience.McMMOPlayerLevelDownEvent;
import com.gmail.nossr50.events.experience.McMMOPlayerLevelUpEvent; import com.gmail.nossr50.events.experience.McMMOPlayerLevelUpEvent;
import com.gmail.nossr50.events.skills.repair.McMMOPlayerRepairCheckEvent;
import net.Indyuce.mmoitems.api.player.PlayerData; import net.Indyuce.mmoitems.api.player.PlayerData;
import net.Indyuce.mmoitems.api.player.RPGPlayer; import net.Indyuce.mmoitems.api.player.RPGPlayer;
import net.Indyuce.mmoitems.stat.type.DisableStat; import net.Indyuce.mmoitems.stat.type.DisableStat;
import net.Indyuce.mmoitems.stat.type.ItemStat; import net.Indyuce.mmoitems.stat.type.ItemStat;
import net.mmogroup.mmolib.api.item.NBTItem;
public class McMMOHook implements RPGHandler, Listener { public class McMMOHook implements RPGHandler, Listener {
@ -29,19 +27,12 @@ public class McMMOHook implements RPGHandler, Listener {
@EventHandler(ignoreCancelled = true) @EventHandler(ignoreCancelled = true)
public void a(McMMOPlayerLevelUpEvent event) { public void a(McMMOPlayerLevelUpEvent event) {
PlayerData.get(event.getPlayer()).scheduleDelayedInventoryUpdate(); PlayerData.get(event.getPlayer()).getInventory().scheduleUpdate();
} }
@EventHandler(ignoreCancelled = true) @EventHandler(ignoreCancelled = true)
public void b(McMMOPlayerLevelDownEvent event) { public void b(McMMOPlayerLevelDownEvent event) {
PlayerData.get(event.getPlayer()).scheduleDelayedInventoryUpdate(); PlayerData.get(event.getPlayer()).getInventory().scheduleUpdate();
}
@EventHandler(ignoreCancelled = true)
public void c(McMMOPlayerRepairCheckEvent event) {
NBTItem nbt = NBTItem.get(event.getRepairedObject());
if (nbt.hasType() && nbt.getBoolean("MMOITEMS_DISABLE_MCMMO_REPAIR"))
event.setCancelled(true);
} }
@Override @Override

View File

@ -12,7 +12,7 @@ public class McRPGHook implements RPGHandler, Listener {
@EventHandler @EventHandler
public void a(McRPGPlayerLevelChangeEvent event) { public void a(McRPGPlayerLevelChangeEvent event) {
PlayerData.get(event.getMcRPGPlayer().getOfflineMcRPGPlayer()).scheduleDelayedInventoryUpdate(); PlayerData.get(event.getMcRPGPlayer().getOfflineMcRPGPlayer()).getInventory().scheduleUpdate();
} }
@Override @Override

View File

@ -30,12 +30,12 @@ public class RacesAndClassesHook implements RPGHandler, Listener {
*/ */
@EventHandler @EventHandler
public void a(LevelUpEvent event) { public void a(LevelUpEvent event) {
PlayerData.get(event.getPlayer()).scheduleDelayedInventoryUpdate(); PlayerData.get(event.getPlayer()).getInventory().scheduleUpdate();
} }
@EventHandler @EventHandler
public void b(LevelDownEvent event) { public void b(LevelDownEvent event) {
PlayerData.get(event.getPlayer()).scheduleDelayedInventoryUpdate(); PlayerData.get(event.getPlayer()).getInventory().scheduleUpdate();
} }
public static class RacePlayer extends RPGPlayer { public static class RacePlayer extends RPGPlayer {

View File

@ -61,7 +61,7 @@ public class SkillAPIHook implements RPGHandler, Listener, DamageHandler {
@EventHandler @EventHandler
public void b(PlayerLevelUpEvent event) { public void b(PlayerLevelUpEvent event) {
net.Indyuce.mmoitems.api.player.PlayerData.get(event.getPlayerData().getPlayer()).scheduleDelayedInventoryUpdate(); net.Indyuce.mmoitems.api.player.PlayerData.get(event.getPlayerData().getPlayer()).getInventory().scheduleUpdate();
} }
@Override @Override

View File

@ -17,7 +17,7 @@ public class SkillsHook implements RPGHandler, Listener {
public void a(SkillLevelUpEvent event) { public void a(SkillLevelUpEvent event) {
OfflinePlayer player = event.getPlayer(); OfflinePlayer player = event.getPlayer();
if (player.isOnline()) if (player.isOnline())
PlayerData.get(player).scheduleDelayedInventoryUpdate(); PlayerData.get(player).getInventory().scheduleUpdate();
} }
@Override @Override

View File

@ -16,7 +16,7 @@ public class SkillsProHook implements RPGHandler, Listener {
public void a(SkillLevelUpEvent event) { public void a(SkillLevelUpEvent event) {
OfflinePlayer player = event.getPlayer(); OfflinePlayer player = event.getPlayer();
if (player.isOnline()) if (player.isOnline())
PlayerData.get(player).scheduleDelayedInventoryUpdate(); PlayerData.get(player).getInventory().scheduleUpdate();
} }
@Override @Override