Fixed an issue with custom dur

This commit is contained in:
Indyuce 2022-11-04 14:33:17 +01:00
parent 1eb8bde5d4
commit a48041b756
2 changed files with 62 additions and 55 deletions

View File

@ -104,7 +104,7 @@ public class DurabilityItem {
/**
* @return If both this is a VALID custom durability item and if the item is broken.
* This will return <code>false</code> if it is not a valid item
* This will return <code>false</code> if it is not a valid item
*/
public boolean isBroken() {
return maxDurability > 0 && durability <= 0;
@ -120,7 +120,7 @@ public class DurabilityItem {
/**
* @return If the item actually supports custom durability. It is completely
* disabled when the player is in creative mode just like vanilla durability.
* disabled when the player is in creative mode just like vanilla durability.
*/
public boolean isValid() {
return maxDurability > 0 && player.getGameMode() != GameMode.CREATIVE;
@ -140,20 +140,24 @@ public class DurabilityItem {
public DurabilityItem decreaseDurability(int loss) {
// Do nothing
// This happens when Unbreaking applies for a damageable item
if (loss == 0)
return this;
Validate.isTrue(loss > 0, "Loss must be greater than 0");
/*
* Calculate the chance of the item not losing any durability because of
* the vanilla unbreaking enchantment ; an item with unbreaking X has 1
* 1 chance out of (X + 1) to lose a durability point, that's 50% chance
* -> 33% chance -> 25% chance -> 20% chance...
*
* This should only be taken into account if the item being damaged is
* UNDAMAGEABLE since Bukkit already applies the enchant for damageable items.
*/
if (getUnbreakingLevel() > 0 && RANDOM.nextInt(getUnbreakingLevel()) != 0)
return this;
if (nbtItem.getItem().getType().getMaxDurability() == 0) {
final int unbreakingLevel = getUnbreakingLevel();
if (unbreakingLevel > 0 && RANDOM.nextInt(unbreakingLevel + 1) != 0)
return this;
}
CustomDurabilityDamage event = new CustomDurabilityDamage(this, loss);
Bukkit.getPluginManager().callEvent(event);
@ -178,8 +182,8 @@ public class DurabilityItem {
* 3) item downgrade
*
* @return Newest version of the damaged item.
* <code>null</code> if the item breaks. That method CANNOT
* return a null value if the item has no decreased its durability.
* <code>null</code> if the item breaks. That method CANNOT
* return a null value if the item has no decreased its durability.
*/
@Nullable
public ItemStack toItem() {

View File

@ -22,24 +22,47 @@ import java.util.Arrays;
import java.util.List;
public class DurabilityListener implements Listener {
private final List<DamageCause> ignoredCauses = Arrays.asList(DamageCause.DROWNING, DamageCause.SUICIDE, DamageCause.FALL, DamageCause.VOID,
DamageCause.FIRE_TICK, DamageCause.SUFFOCATION, DamageCause.POISON, DamageCause.WITHER, DamageCause.STARVATION, DamageCause.MAGIC);
private final EquipmentSlot[] armorSlots = {EquipmentSlot.HEAD, EquipmentSlot.CHEST, EquipmentSlot.LEGS, EquipmentSlot.FEET};
/**
* Handles custom durability for non-'vanilla durability' items
* Handles durability for ANY damageable items.
*/
@EventHandler(ignoreCancelled = true)
public void itemDamage(PlayerItemDamageEvent event) {
final DurabilityItem item = new DurabilityItem(event.getPlayer(), event.getItem());
if (!item.isValid())
return;
// Calculate item durability loss
item.decreaseDurability(event.getDamage());
/*
* If the item is broken and if it is meant to be lost when broken,
* do NOT cancel the event and make sure the item is destroyed
*/
final ItemStack newVersion = item.toItem();
if (newVersion == null) {
event.setDamage(999);
return;
}
event.setCancelled(true);
event.getItem().setItemMeta(newVersion.getItemMeta());
}
private static final List<DamageCause> IGNORED_CAUSES = Arrays.asList(DamageCause.DROWNING, DamageCause.SUICIDE, DamageCause.FALL, DamageCause.VOID,
DamageCause.FIRE_TICK, DamageCause.SUFFOCATION, DamageCause.POISON, DamageCause.WITHER, DamageCause.STARVATION, DamageCause.MAGIC);
private static final EquipmentSlot[] ARMOR_SLOTS = {EquipmentSlot.HEAD, EquipmentSlot.CHEST, EquipmentSlot.LEGS, EquipmentSlot.FEET};
@EventHandler(ignoreCancelled = true)
public void playerDamage(EntityDamageEvent event) {
if (event.getEntityType() != EntityType.PLAYER || ignoredCauses.contains(event.getCause()))
if (event.getEntityType() != EntityType.PLAYER || IGNORED_CAUSES.contains(event.getCause()))
return;
Player player = (Player) event.getEntity();
int damage = Math.max((int) event.getDamage() / 4, 1);
for (EquipmentSlot slot : armorSlots)
for (EquipmentSlot slot : ARMOR_SLOTS)
if (hasItem(player, slot))
handleVanillaDamage(player.getInventory().getItem(slot), player, slot, damage);
handleUndamageableItem(player.getInventory().getItem(slot), player, slot, damage);
}
@EventHandler(ignoreCancelled = true)
@ -50,7 +73,7 @@ public class DurabilityListener implements Listener {
Player player = (Player) event.getDamager();
ItemStack item = player.getInventory().getItemInMainHand();
handleVanillaDamage(item, player, EquipmentSlot.HAND, 1);
handleUndamageableItem(item, player, EquipmentSlot.HAND, 1);
}
@EventHandler(ignoreCancelled = true)
@ -60,30 +83,7 @@ public class DurabilityListener implements Listener {
Player player = (Player) event.getEntity();
ItemStack item = event.getBow();
handleVanillaDamage(item, player, EquipmentSlot.HAND, 1);
}
@EventHandler(ignoreCancelled = true)
public void itemDamage(PlayerItemDamageEvent event) {
DurabilityItem item = new DurabilityItem(event.getPlayer(), event.getItem());
if (item.isValid()) {
// Calculate item durability loss
item.decreaseDurability(event.getDamage());
/*
* If the item is broken and if it is meant to be lost when broken,
* do NOT cancel the event and make sure the item is destroyed
*/
ItemStack newVersion = item.toItem();
if (newVersion == null) {
event.setDamage(999);
return;
}
event.setCancelled(true);
event.getItem().setItemMeta(newVersion.getItemMeta());
}
handleUndamageableItem(item, player, EquipmentSlot.HAND, 1);
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
@ -96,24 +96,27 @@ public class DurabilityListener implements Listener {
}
/**
* This method is for all the items which have 0 max durability
* i.E which are not breakable hence the {@link Material#getMaxDurability()} call
* This method is for all the items which have 0 max durability i.e
* which are not breakable hence the {@link Material#getMaxDurability()}
*/
private void handleVanillaDamage(ItemStack stack, Player player, EquipmentSlot slot, int damage) {
DurabilityItem item = new DurabilityItem(player, stack);
private void handleUndamageableItem(ItemStack stack, Player player, EquipmentSlot slot, int damage) {
if (stack.getType().getMaxDurability() != 0)
return;
if (item.isValid() && stack.getType().getMaxDurability() == 0) {
item.decreaseDurability(damage);
final DurabilityItem item = new DurabilityItem(player, stack);
if (!item.isValid())
return;
ItemStack newVersion = item.toItem();
if (newVersion == null) {
player.getInventory().setItem(slot, null);
player.getWorld().playSound(player.getLocation(), Sound.ENTITY_ITEM_BREAK, 1.0f, 1.0f);
return;
}
item.decreaseDurability(damage);
player.getInventory().getItem(slot).setItemMeta(newVersion.getItemMeta());
ItemStack newVersion = item.toItem();
if (newVersion == null) {
player.getInventory().setItem(slot, null);
player.getWorld().playSound(player.getLocation(), Sound.ENTITY_ITEM_BREAK, 1.0f, 1.0f);
return;
}
player.getInventory().getItem(slot).setItemMeta(newVersion.getItemMeta());
}
private boolean hasItem(Player player, EquipmentSlot slot) {