Fixed item equipment; removed EquippedPlayerItem

This commit is contained in:
Indyuce 2022-07-05 12:26:53 +02:00
parent 3d59810741
commit 611c901e8f
8 changed files with 185 additions and 211 deletions

View File

@ -1,7 +1,7 @@
package net.Indyuce.mmoitems.api.event; package net.Indyuce.mmoitems.api.event;
import net.Indyuce.mmoitems.api.player.PlayerData; import net.Indyuce.mmoitems.api.player.PlayerData;
import net.Indyuce.mmoitems.api.player.inventory.EquippedPlayerItem; import net.Indyuce.mmoitems.api.player.inventory.EquippedItem;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.Event; import org.bukkit.event.Event;
import org.bukkit.event.HandlerList; import org.bukkit.event.HandlerList;
@ -11,8 +11,8 @@ import java.util.List;
public class RefreshInventoryEvent extends Event { public class RefreshInventoryEvent extends Event {
@NotNull final List<EquippedPlayerItem> itemsToEquip; @NotNull final List<EquippedItem> itemsToEquip;
@NotNull public List<EquippedPlayerItem> getItemsToEquip() { return itemsToEquip; } @NotNull public List<EquippedItem> getItemsToEquip() { return itemsToEquip; }
@NotNull @NotNull
public Player getPlayer() { public Player getPlayer() {
@ -27,7 +27,7 @@ public class RefreshInventoryEvent extends Event {
@NotNull final Player player; @NotNull final Player player;
@NotNull final PlayerData playerData; @NotNull final PlayerData playerData;
public RefreshInventoryEvent(@NotNull List<EquippedPlayerItem> itemsToEquip, @NotNull Player player, @NotNull PlayerData playerData) { public RefreshInventoryEvent(@NotNull List<EquippedItem> itemsToEquip, @NotNull Player player, @NotNull PlayerData playerData) {
this.itemsToEquip = itemsToEquip; this.itemsToEquip = itemsToEquip;
this.player = player; this.player = player;
this.playerData = playerData; this.playerData = playerData;

View File

@ -4,7 +4,6 @@ import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.item.NBTItem; import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.api.player.EquipmentSlot; import io.lumine.mythic.lib.api.player.EquipmentSlot;
import io.lumine.mythic.lib.api.player.MMOPlayerData; import io.lumine.mythic.lib.api.player.MMOPlayerData;
import io.lumine.mythic.lib.api.util.ui.SilentNumbers;
import io.lumine.mythic.lib.damage.AttackMetadata; import io.lumine.mythic.lib.damage.AttackMetadata;
import io.lumine.mythic.lib.player.PlayerMetadata; import io.lumine.mythic.lib.player.PlayerMetadata;
import io.lumine.mythic.lib.player.modifier.ModifierSource; import io.lumine.mythic.lib.player.modifier.ModifierSource;
@ -15,15 +14,12 @@ import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.ConfigFile; import net.Indyuce.mmoitems.api.ConfigFile;
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.crafting.CraftingStatus; import net.Indyuce.mmoitems.api.crafting.CraftingStatus;
import net.Indyuce.mmoitems.api.event.RefreshInventoryEvent; import net.Indyuce.mmoitems.api.event.RefreshInventoryEvent;
import net.Indyuce.mmoitems.api.interaction.Tool; import net.Indyuce.mmoitems.api.interaction.Tool;
import net.Indyuce.mmoitems.api.item.ItemReference; import net.Indyuce.mmoitems.api.item.ItemReference;
import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem;
import net.Indyuce.mmoitems.api.item.mmoitem.VolatileMMOItem; import net.Indyuce.mmoitems.api.item.mmoitem.VolatileMMOItem;
import net.Indyuce.mmoitems.api.player.inventory.EquippedItem; 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.api.player.inventory.InventoryUpdateHandler;
import net.Indyuce.mmoitems.particle.api.ParticleRunnable; import net.Indyuce.mmoitems.particle.api.ParticleRunnable;
import net.Indyuce.mmoitems.stat.data.*; import net.Indyuce.mmoitems.stat.data.*;
@ -44,32 +40,27 @@ import org.jetbrains.annotations.Nullable;
import java.util.*; import java.util.*;
public class PlayerData { public class PlayerData {
private static final Map<UUID, PlayerData> data = new HashMap<>();
@NotNull @NotNull
private final MMOPlayerData mmoData; private final MMOPlayerData mmoData;
/* // Reloaded everytime the player reconnects in case of major change.
* reloaded everytime the player reconnects in case of major change.
*/
private RPGPlayer rpgPlayer; private RPGPlayer rpgPlayer;
private final InventoryUpdateHandler inventory = new InventoryUpdateHandler(this); private final InventoryUpdateHandler inventory = new InventoryUpdateHandler(this);
private final CraftingStatus craftingStatus = new CraftingStatus(); private final CraftingStatus craftingStatus = new CraftingStatus();
/* // Specific stat calculation TODO compress it in Map<ItemStat, DynamicStatData>
* specific stat calculation TODO compress it in Map<ItemStat, DynamicStatData>
*/
private final Map<PotionEffectType, PotionEffect> permanentEffects = new HashMap<>(); private final Map<PotionEffectType, PotionEffect> permanentEffects = new HashMap<>();
private final Set<ParticleRunnable> itemParticles = new HashSet<>(); private final Set<ParticleRunnable> itemParticles = new HashSet<>();
private ParticleRunnable overridingItemParticles = null; private ParticleRunnable overridingItemParticles = null;
private boolean fullHands = false; private boolean handsFull = false;
@Nullable @Nullable
private SetBonuses setBonuses = null; private SetBonuses setBonuses = null;
private final PlayerStats stats; private final PlayerStats stats;
// Cached so they can be properly removed again
private final Set<String> permissions = new HashSet<>(); private final Set<String> permissions = new HashSet<>();
private static final Map<UUID, PlayerData> data = new HashMap<>();
private PlayerData(@NotNull MMOPlayerData mmoData) { private PlayerData(@NotNull MMOPlayerData mmoData) {
this.mmoData = mmoData; this.mmoData = mmoData;
rpgPlayer = MMOItems.plugin.getRPG().getInfo(this); rpgPlayer = MMOItems.plugin.getRPG().getInfo(this);
@ -127,9 +118,9 @@ public class PlayerData {
overridingItemParticles.cancel(); overridingItemParticles.cancel();
} }
/* /**
* returns true if the player hands are full, i.e if the player is holding * @return If the player hands are full i.e if the player is holding
* one two handed item and one other item at the same time * two items in their hands, one being two handed
*/ */
public boolean areHandsFull() { public boolean areHandsFull() {
if (!mmoData.isOnline()) if (!mmoData.isOnline())
@ -166,7 +157,7 @@ public class PlayerData {
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)
*/ */
inventory.getEquipped().clear(); inventory.getEquipped().clear();
@ -177,21 +168,23 @@ public class PlayerData {
overridingItemParticles = null; overridingItemParticles = null;
if (MMOItems.plugin.hasPermissions()) { if (MMOItems.plugin.hasPermissions()) {
Permission perms = MMOItems.plugin.getVault().getPermissions(); Permission perms = MMOItems.plugin.getVault().getPermissions();
permissions.forEach(perm -> { if (perms.has(getPlayer(), perm)) { perms.playerRemove(getPlayer(), perm); } }); permissions.forEach(perm -> {
if (perms.has(getPlayer(), perm)) {
perms.playerRemove(getPlayer(), perm);
}
});
} }
permissions.clear(); permissions.clear();
/* /*
* updates the full-hands boolean, this way it can be cached and used in * Updates the full-hands boolean, this way it can be cached and used in
* the updateEffects() method * the updateEffects() method
*/ */
fullHands = areHandsFull(); handsFull = 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.getItem(); NBTItem nbtItem = item.getNBT();
if (nbtItem.getItem() == null || nbtItem.getItem().getType() == Material.AIR) if (nbtItem.getItem() == null || nbtItem.getItem().getType() == Material.AIR)
continue; continue;
@ -199,31 +192,31 @@ public class PlayerData {
* If the item is a custom item, apply slot and item use * If the item is a custom item, apply slot and item use
* restrictions (items which only work in a specific equipment slot) * restrictions (items which only work in a specific equipment slot)
*/ */
Type type = Type.get(nbtItem.getType()); if (!item.isPlacementLegal() || !getRPG().canUse(nbtItem, false, false))
if (type == null || !item.matches(type) || !getRPG().canUse(nbtItem, false, false))
continue; continue;
inventory.getEquipped().add(new EquippedPlayerItem(item)); item.cacheItem();
inventory.getEquipped().add(item);
} }
RefreshInventoryEvent riev = new RefreshInventoryEvent(inventory.getEquipped(), getPlayer(), this); // Call Bukkit event
Bukkit.getPluginManager().callEvent(riev); Bukkit.getPluginManager().callEvent(new RefreshInventoryEvent(inventory.getEquipped(), getPlayer(), this));
for (EquippedPlayerItem equipped : inventory.getEquipped()) { for (EquippedItem equipped : inventory.getEquipped()) {
VolatileMMOItem item = equipped.getItem(); VolatileMMOItem item = equipped.getCached();
/* // Stats which don't apply from off hand
* Apply permanent potion effects if (equipped.getSlot() == EquipmentSlot.OFF_HAND && equipped.getCached().getType().getEquipmentType() != EquipmentSlot.OFF_HAND)
*/ continue;
// 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 -> {
if (getPermanentPotionEffectAmplifier(effect.getType()) < effect.getLevel() - 1) if (getPermanentPotionEffectAmplifier(effect.getType()) < effect.getLevel() - 1)
permanentEffects.put(effect.getType(), effect.toEffect()); permanentEffects.put(effect.getType(), effect.toEffect());
}); });
/* // 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);
@ -234,46 +227,41 @@ public class PlayerData {
itemParticles.add(particleData.start(this)); itemParticles.add(particleData.start(this));
} }
/* // Abilities
* Apply abilities if (item.hasData(ItemStats.ABILITIES) && (MMOItems.plugin.getConfig().getBoolean("abilities-bypass-encumbering") || !handsFull))
*/ for (AbilityData abilityData : ((AbilityListData) item.getData(ItemStats.ABILITIES)).getAbilities()) {
if (item.hasData(ItemStats.ABILITIES) && (MMOItems.plugin.getConfig().getBoolean("abilities-bypass-encumbering") || !fullHands)) ModifierSource modSource = equipped.getCached().getType() == null ? ModifierSource.OTHER : equipped.getCached().getType().getItemSet().getModifierSource();
if (equipped.getSlot() != EquipmentSlot.OFF_HAND || !MMOItems.plugin.getConfig().getBoolean("disable-abilities-in-offhand")) mmoData.getPassiveSkillMap().addModifier(new PassiveSkill("MMOItemsItem", abilityData, equipped.getSlot(), modSource));
for (AbilityData abilityData : ((AbilityListData) item.getData(ItemStats.ABILITIES)).getAbilities()) { }
ModifierSource modSource = equipped.getItem().getType() == null ? ModifierSource.OTHER : equipped.getItem().getType().getItemSet().getModifierSource();
mmoData.getPassiveSkillMap().addModifier(new PassiveSkill("MMOItemsItem", abilityData, equipped.getSlot(), modSource));
}
/* // 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());
Permission perms = MMOItems.plugin.getVault().getPermissions(); Permission perms = MMOItems.plugin.getVault().getPermissions();
permissions.forEach(perm -> { if (!perms.has(getPlayer(), perm)) { perms.playerAdd(getPlayer(), perm); } }); permissions.forEach(perm -> {
if (!perms.has(getPlayer(), perm)) {
perms.playerAdd(getPlayer(), perm);
}
});
} }
} }
/* // Calculate the player's item set
* calculate the player's item set and add the bonus permanent effects /
* bonus abilities to the playerdata maps
*/
Map<ItemSet, Integer> sets = new HashMap<>(); Map<ItemSet, Integer> sets = new HashMap<>();
for (EquippedPlayerItem equipped : inventory.getEquipped()) { for (EquippedItem equipped : inventory.getEquipped()) {
VolatileMMOItem item = equipped.getItem(); VolatileMMOItem item = equipped.getCached();
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)
continue; continue;
int nextInt = (sets.getOrDefault(itemSet, 0)) + 1; sets.put(itemSet, sets.getOrDefault(itemSet, 0) + 1);
sets.put(itemSet, nextInt);
} }
// Reset // Reset and compute item set bonuses
setBonuses = null; setBonuses = null;
for (Map.Entry<ItemSet,Integer> equippedSetBonus : sets.entrySet()) { for (Map.Entry<ItemSet, Integer> equippedSetBonus : sets.entrySet()) {
if (setBonuses == null) { if (setBonuses == null) {
@ -287,10 +275,12 @@ public class PlayerData {
} }
} }
// Apply item set bonuses
if (setBonuses != null) { if (setBonuses != null) {
Permission perms = MMOItems.plugin.getVault().getPermissions(); final Permission perms = MMOItems.plugin.getVault().getPermissions();
for (String perm : setBonuses.getPermissions()) for (String perm : setBonuses.getPermissions())
if (!perms.has(getPlayer(), perm)) { perms.playerAdd(getPlayer(), perm); } if (!perms.has(getPlayer(), perm))
perms.playerAdd(getPlayer(), perm);
for (AbilityData ability : setBonuses.getAbilities()) for (AbilityData ability : setBonuses.getAbilities())
mmoData.getPassiveSkillMap().addModifier(new PassiveSkill("MMOItemsItem", ability, EquipmentSlot.OTHER, ModifierSource.OTHER)); mmoData.getPassiveSkillMap().addModifier(new PassiveSkill("MMOItemsItem", ability, EquipmentSlot.OTHER, ModifierSource.OTHER));
for (ParticleData particle : setBonuses.getParticles()) for (ParticleData particle : setBonuses.getParticles())
@ -300,22 +290,13 @@ public class PlayerData {
permanentEffects.put(effect.getType(), effect); permanentEffects.put(effect.getType(), effect);
} }
/* // Calculate player stats
* calculate all stats.
*/
stats.updateStats(); stats.updateStats();
/* // Update stats from external plugins
* update stuff from the external MMOCore plugins. the 'max mana' stat
* currently only supports Heroes since other APIs do not allow other
* plugins to easily increase this type of stat.
*/
MMOItems.plugin.getRPG().refreshStats(this); MMOItems.plugin.getRPG().refreshStats(this);
/* // Actually update cached player inventory so the task doesn't infinitely loop
* actually update the player inventory so the task doesn't infinitely
* loop on updating
*/
inventory.helmet = getPlayer().getInventory().getHelmet(); inventory.helmet = getPlayer().getInventory().getHelmet();
inventory.chestplate = getPlayer().getInventory().getChestplate(); inventory.chestplate = getPlayer().getInventory().getChestplate();
inventory.leggings = getPlayer().getInventory().getLeggings(); inventory.leggings = getPlayer().getInventory().getLeggings();
@ -326,11 +307,11 @@ public class PlayerData {
public void updateStats() { public void updateStats() {
// Perm effects // Permanent effects
permanentEffects.values().forEach(effect -> getPlayer().addPotionEffect(effect)); permanentEffects.values().forEach(effect -> getPlayer().addPotionEffect(effect));
// Two handed slowness // Two handed slowness
if (fullHands) if (handsFull)
getPlayer().addPotionEffect(new PotionEffect(PotionEffectType.SLOW, 40, 1, true, false)); getPlayer().addPotionEffect(new PotionEffect(PotionEffectType.SLOW, 40, 1, true, false));
} }

View File

@ -9,7 +9,7 @@ import io.lumine.mythic.lib.player.modifier.ModifierSource;
import io.lumine.mythic.lib.player.modifier.ModifierType; import io.lumine.mythic.lib.player.modifier.ModifierType;
import net.Indyuce.mmoitems.MMOItems; import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.Type; import net.Indyuce.mmoitems.api.Type;
import net.Indyuce.mmoitems.api.player.inventory.EquippedPlayerItem; import net.Indyuce.mmoitems.api.player.inventory.EquippedItem;
import net.Indyuce.mmoitems.stat.type.AttackWeaponStat; import net.Indyuce.mmoitems.stat.type.AttackWeaponStat;
import net.Indyuce.mmoitems.stat.type.ItemStat; import net.Indyuce.mmoitems.stat.type.ItemStat;
@ -66,12 +66,12 @@ public class PlayerStats {
// The index of the mmoitem stat modifier being added // The index of the mmoitem stat modifier being added
int index = 0; int index = 0;
for (EquippedPlayerItem item : playerData.getInventory().getEquipped()) { for (EquippedItem item : playerData.getInventory().getEquipped()) {
double value = item.getItem().getNBT().getStat(stat.getId()); double value = item.getNBT().getStat(stat.getId());
if (value != 0) { if (value != 0) {
Type type = item.getItem().getType(); Type type = item.getCached().getType();
ModifierSource source = type == null ? ModifierSource.OTHER : type.getItemSet().getModifierSource(); ModifierSource source = type == null ? ModifierSource.OTHER : type.getItemSet().getModifierSource();
// Apply hand weapon stat offset // Apply hand weapon stat offset

View File

@ -3,59 +3,82 @@ package net.Indyuce.mmoitems.api.player.inventory;
import io.lumine.mythic.lib.api.item.NBTItem; import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.api.player.EquipmentSlot; import io.lumine.mythic.lib.api.player.EquipmentSlot;
import net.Indyuce.mmoitems.api.Type; import net.Indyuce.mmoitems.api.Type;
import net.Indyuce.mmoitems.api.item.mmoitem.VolatileMMOItem;
import org.apache.commons.lang.Validate;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
public class EquippedItem { public class EquippedItem {
private final NBTItem item; private final NBTItem item;
private final EquipmentSlot slot; private final EquipmentSlot slot;
/** private VolatileMMOItem cached;
* 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(NBTItem.get(item), slot);
}
/** /**
* An item equipped by a player in a specific slot * An item equipped by a player in a specific slot
* *
* @param item The item equipped * @param item The item equipped
* @param slot The corresponding MMOItems slot type, must not be null! * @param slot Slot in which the item is placed
*/ */
public EquippedItem(NBTItem item, EquipmentSlot slot) { public EquippedItem(ItemStack item, EquipmentSlot slot) {
this.item = item; this(NBTItem.get(item), slot);
this.slot = slot; }
}
public NBTItem getItem() { /**
return item; * An item equipped by a player in a specific slot
} *
* @param item The item equipped
* @param slot Slot in which the item is placed
*/
public EquippedItem(NBTItem item, EquipmentSlot slot) {
this.item = item;
this.slot = slot;
}
public EquipmentSlot getSlot() { public VolatileMMOItem getCached() {
return slot; return Objects.requireNonNull(cached, "Item not cached yet");
} }
/** public void cacheItem() {
* The slot this equipped item is defined to be, will this <code>Type</code> Validate.isTrue(cached == null, "MMOItem has already been cached");
* actually add its stats to the player when held here? cached = new VolatileMMOItem(item);
* <p></p> }
* An <code>OFF_CATALYST</code> may only add in the <code>OFFHAND</code>, and such.
*/
public boolean matches(@NotNull Type type) {
if (slot == EquipmentSlot.ANY)
return true;
/* public NBTItem getNBT() {
* Main hand items apply their stats and options in off return item;
* hand as well but the reciprocal is false }
*/
if (type.getEquipmentType() == EquipmentSlot.MAIN_HAND)
return slot.isHand();
return slot == type.getEquipmentType(); public EquipmentSlot getSlot() {
} return slot;
}
/**
* The slot this equipped item is defined to be, will this <code>Type</code>
* actually add its stats to the player when held here?
* <p></p>
* An <code>OFF_CATALYST</code> may only add in the <code>OFFHAND</code>, and such.
*/
public boolean isPlacementLegal() {
// Find item type
final String typeFormat = item.getString("MMOITEMS_ITEM_TYPE");
final Type type = typeFormat == null ? null : Type.get(typeFormat);
// Vanilla items are ignored
if (type == null)
return false;
if (slot == EquipmentSlot.ANY)
return true;
/*
* Main hand items apply their stats and options in off
* hand as well but the reciprocal is false
*/
if (type.getEquipmentType() == EquipmentSlot.MAIN_HAND)
return slot.isHand();
return slot == type.getEquipmentType();
}
} }

View File

@ -1,32 +0,0 @@
package net.Indyuce.mmoitems.api.player.inventory;
import io.lumine.mythic.lib.api.player.EquipmentSlot;
import net.Indyuce.mmoitems.api.item.mmoitem.VolatileMMOItem;
public class EquippedPlayerItem {
private final VolatileMMOItem item;
private final EquipmentSlot slot;
private final EquippedItem equipped;
/**
* An item equipped by a player in a specific slot
*
* @param item The item equipped
*/
public EquippedPlayerItem(EquippedItem item) {
this.equipped = item;
this.item = new VolatileMMOItem(item.getItem());
this.slot = item.getSlot();
}
/**
* @return honestly I do not know why EquippedPlayerItem even exists?
* you can get all the values from the {@link EquippedItem}
* it came from. Its like a funny wrapper.
*/
public EquippedItem getEquipped() { return equipped; }
public VolatileMMOItem getItem() { return item; }
public EquipmentSlot getSlot() { return slot; }
}

View File

@ -1,6 +1,5 @@
package net.Indyuce.mmoitems.api.player.inventory; package net.Indyuce.mmoitems.api.player.inventory;
import io.lumine.mythic.lib.api.player.EquipmentSlot;
import net.Indyuce.mmoitems.MMOItems; import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.player.PlayerData; import net.Indyuce.mmoitems.api.player.PlayerData;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -9,7 +8,6 @@ import org.bukkit.inventory.PlayerInventory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects;
/** /**
* TODO * TODO
@ -20,43 +18,54 @@ import java.util.Objects;
* @author indyuce * @author indyuce
*/ */
public class InventoryUpdateHandler { public class InventoryUpdateHandler {
private final PlayerData player; private final PlayerData player;
private final List<EquippedPlayerItem> items = new ArrayList<>(); private final List<EquippedItem> items = new ArrayList<>();
@Deprecated @Deprecated
public ItemStack helmet = null, chestplate = null, leggings = null, boots = null, hand = null, offhand = null; public ItemStack helmet = null, chestplate = null, leggings = null, boots = null, hand = null, offhand = null;
/** /**
* Used to handle player inventory updates. * Used to handle player inventory updates.
*/ */
public InventoryUpdateHandler(PlayerData player) { this.player = player; } public InventoryUpdateHandler(PlayerData player) {
this.player = player;
}
/** /**
* @return All equipped MMOItems in the player's inventory. Also includes * This list includes items which satisfy the following conditions
* items from custom inventory plugins like MMOInventory * - inventory placement is legal (a hand item placed in a hand slot, an armor placed in an armor slot)
*/ * - the player meets the item requirements (class, level etc)
public List<EquippedPlayerItem> getEquipped() { *
return items; * @return All equipped MMOItems in the player's inventory. Also includes
} * items from custom inventory plugins like MMOInventory
*/
public List<EquippedItem> getEquipped() {
return items;
}
public void updateCheck() { public void updateCheck() {
if (!player.isOnline()) { return; } PlayerInventory inv = player.getPlayer().getInventory();
if (isDifferent(helmet, inv.getHelmet()) || isDifferent(chestplate, inv.getChestplate()) || isDifferent(leggings, inv.getLeggings())
|| isDifferent(boots, inv.getBoots()) || isDifferent(hand, inv.getItemInMainHand()) || isDifferent(offhand, inv.getItemInOffHand()))
player.updateInventory();
}
PlayerInventory inv = player.getPlayer().getInventory(); /**
if (isNotSame(helmet, inv.getHelmet()) || isNotSame(chestplate, inv.getChestplate()) || isNotSame(leggings, inv.getLeggings()) * Schedules an inventory update in one tick
|| isNotSame(boots, inv.getBoots()) || isNotSame(hand, inv.getItemInMainHand()) || isNotSame(offhand, inv.getItemInOffHand())) */
player.updateInventory(); public void scheduleUpdate() {
} Bukkit.getScheduler().scheduleSyncDelayedTask(MMOItems.plugin, player::updateInventory);
}
/** private boolean isDifferent(ItemStack item, ItemStack item1) {
* Schedules an inventory update in one tick if (item == null && item1 == null)
*/ return false;
public void scheduleUpdate() {
Bukkit.getScheduler().scheduleSyncDelayedTask(MMOItems.plugin, player::updateInventory);
}
private boolean isNotSame(ItemStack item, ItemStack item1) { if ((item == null && item1 != null) || (item != null && item1 == null))
return !Objects.equals(item, item1); return true;
}
// Check hash code first to spare calculations
return item.hashCode() != item1.hashCode() && !item.equals(item1);
}
} }

View File

@ -9,7 +9,7 @@ import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem;
import net.Indyuce.mmoitems.api.item.mmoitem.VolatileMMOItem; import net.Indyuce.mmoitems.api.item.mmoitem.VolatileMMOItem;
import net.Indyuce.mmoitems.api.player.PlayerData; import net.Indyuce.mmoitems.api.player.PlayerData;
import net.Indyuce.mmoitems.api.player.inventory.EditableEquippedItem; import net.Indyuce.mmoitems.api.player.inventory.EditableEquippedItem;
import net.Indyuce.mmoitems.api.player.inventory.EquippedPlayerItem; import net.Indyuce.mmoitems.api.player.inventory.EquippedItem;
import net.Indyuce.mmoitems.api.player.inventory.InventoryUpdateHandler; import net.Indyuce.mmoitems.api.player.inventory.InventoryUpdateHandler;
import net.Indyuce.mmoitems.api.util.message.Message; import net.Indyuce.mmoitems.api.util.message.Message;
import net.Indyuce.mmoitems.stat.data.UpgradeData; import net.Indyuce.mmoitems.stat.data.UpgradeData;
@ -22,7 +22,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
@ -51,17 +50,17 @@ public class DeathDowngrading {
// Make sure the equipped items list is up to date and retrieve it // Make sure the equipped items list is up to date and retrieve it
data.updateInventory(); data.updateInventory();
List<EquippedPlayerItem> items = data.getInventory().getEquipped(); List<EquippedItem> items = data.getInventory().getEquipped();
ArrayList<EditableEquippedItem> equipped = new ArrayList<>(); ArrayList<EditableEquippedItem> equipped = new ArrayList<>();
// Equipped Player Items yeah... // Equipped Player Items yeah...
for (EquippedPlayerItem playerItem : items) { for (EquippedItem playerItem : items) {
// Cannot downgrade? skip // Cannot downgrade? skip
if (!canDeathDowngrade(playerItem)) { continue; } if (!canDeathDowngrade(playerItem)) { continue; }
// Okay explore stat // Okay explore stat
equipped.add((EditableEquippedItem) playerItem.getEquipped()); equipped.add((EditableEquippedItem) playerItem);
//DET//MMOItems.log("\u00a78DETH \u00a7cDG\u00a77 Yes. \u00a7aAccepted"); //DET//MMOItems.log("\u00a78DETH \u00a7cDG\u00a77 Yes. \u00a7aAccepted");
} }
@ -88,7 +87,7 @@ public class DeathDowngrading {
EditableEquippedItem equip = equipped.get(deathChosen); EditableEquippedItem equip = equipped.get(deathChosen);
// Downgrade and remove from list // Downgrade and remove from list
equip.setItem(downgrade(new LiveMMOItem(equip.getItem()), player)); equip.setItem(downgrade(new LiveMMOItem(equip.getNBT()), player));
equipped.remove(deathChosen); equipped.remove(deathChosen);
//DET//MMOItems.log("\u00a78DETH \u00a7cDG\u00a77 Autodegrading\u00a7a " + mmo.getData(ItemStats.NAME)); //DET//MMOItems.log("\u00a78DETH \u00a7cDG\u00a77 Autodegrading\u00a7a " + mmo.getData(ItemStats.NAME));
@ -106,7 +105,7 @@ public class DeathDowngrading {
EditableEquippedItem equip = equipped.get(d); EditableEquippedItem equip = equipped.get(d);
// Downgrade and remove from list // Downgrade and remove from list
equip.setItem(downgrade(new LiveMMOItem(equip.getItem()), player)); equip.setItem(downgrade(new LiveMMOItem(equip.getNBT()), player));
equipped.remove(d); equipped.remove(d);
//DET//MMOItems.log("\u00a78DETH \u00a7cDG\u00a77 Chancedegrade\u00a7a " + mmo.getData(ItemStats.NAME)); //DET//MMOItems.log("\u00a78DETH \u00a7cDG\u00a77 Chancedegrade\u00a7a " + mmo.getData(ItemStats.NAME));
@ -271,7 +270,7 @@ public class DeathDowngrading {
* @return If this is an instance of {@link EditableEquippedItem} and meets {@link #canDeathDowngrade(MMOItem)} * @return If this is an instance of {@link EditableEquippedItem} and meets {@link #canDeathDowngrade(MMOItem)}
*/ */
@Contract("null->false") @Contract("null->false")
public static boolean canDeathDowngrade(@Nullable EquippedPlayerItem playerItem) { public static boolean canDeathDowngrade(@Nullable EquippedItem playerItem) {
// Null // Null
if (playerItem == null) { return false; } if (playerItem == null) { return false; }
@ -279,12 +278,12 @@ public class DeathDowngrading {
//DET//MMOItems.log("\u00a78DETH \u00a7cDG\u00a77 Item:\u00a7b " + playerItem.getItem().getData(ItemStats.NAME)); //DET//MMOItems.log("\u00a78DETH \u00a7cDG\u00a77 Item:\u00a7b " + playerItem.getItem().getData(ItemStats.NAME));
// Cannot perform operations of items that are uneditable // Cannot perform operations of items that are uneditable
if (!(playerItem.getEquipped() instanceof EditableEquippedItem)) { if (!(playerItem instanceof EditableEquippedItem)) {
//DET//MMOItems.log("\u00a78DETH \u00a7cDG\u00a77 Not equippable. \u00a7cCancel"); //DET//MMOItems.log("\u00a78DETH \u00a7cDG\u00a77 Not equippable. \u00a7cCancel");
return false; } return false; }
// Delegate to MMOItem Method // Delegate to MMOItem Method
return canDeathDowngrade(playerItem.getItem()); return canDeathDowngrade(playerItem.getCached());
} }
/** /**

View File

@ -16,12 +16,6 @@ iterate-whole-inventory: false
# When this is set to true, skins can only be applied to an item ONCE. # When this is set to true, skins can only be applied to an item ONCE.
locked-skins: true locked-skins: true
# Enable/Disable abilities in the players offhand, stops
# players using abilities when interacting with chests, mining etc.
# Very useful if your have a lot of items that your players use in their
# off-hand like tomes!
disable-abilities-in-offhand: false
# By default, all player inventories will be updated every # By default, all player inventories will be updated every
# 10 ticks which corresponds to 2 inventory updates a second. # 10 ticks which corresponds to 2 inventory updates a second.
inventory-update-delay: 10 inventory-update-delay: 10