From 2f358f2a80fa3a225c84ca9466fad61dd60e0503 Mon Sep 17 00:00:00 2001 From: totemo Date: Wed, 28 May 2014 23:45:02 +0930 Subject: [PATCH] Fix duplication of dropped items on mob death. * The EntityDeathEvent handler contains a work-around for a vanilla Minecraft bug wherein mob equipment with a drop chance of 100% does not always drop. * Prior to Bukkit commit d611cff, the EntityDeathEvent did not include mob equipment in the list of drops, so it was safe for Doppelganger to simply strip the mob of its gear and add those items to the drops. * In newer versions of Bukkit, the equipment is present in the drops and is also still on the mob itself, so the Doppelganger work-around code leads to duplicate items in the drops. This commit avoids adding equipment to the drops when an identical item is already present in the dropped item list. * This fix works for older Bukkit versions as well. * As described at https://github.com/Bukkit/CraftBukkit/commit/fb58cc92375d85bfe7a3dc8671c70d1a4e308e3c the new Bukkit item dropping code is still reliant on vanilla code to drop items and that vanilla code still sometimes fails to drop items even though the drop probability is 100%. The work-around code still corrects that issue. --- pom.xml | 2 +- .../totemo/doppelganger/Doppelganger.java | 64 +++++++++++++------ 2 files changed, 46 insertions(+), 20 deletions(-) diff --git a/pom.xml b/pom.xml index 7eb4931..2c152b9 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 io.github.totemo Doppelganger - 0.9.0 + 0.9.1 jar Doppelganger diff --git a/src/io/github/totemo/doppelganger/Doppelganger.java b/src/io/github/totemo/doppelganger/Doppelganger.java index 613e465..dd1ed9b 100644 --- a/src/io/github/totemo/doppelganger/Doppelganger.java +++ b/src/io/github/totemo/doppelganger/Doppelganger.java @@ -1,6 +1,7 @@ package io.github.totemo.doppelganger; import java.util.ArrayList; +import java.util.List; import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -170,10 +171,13 @@ public void onBlockPlace(BlockPlaceEvent event) // -------------------------------------------------------------------------- /** - * Bukkit or vanilla Minecraft doesn't always drop equipment, when the drop - * chance is 1.0 (or more). Try to work around that by moving the equipment - * into the drops. Normally the equipment is not part of the drops. It is - * dropped by some other mechanism. + * Vanilla Minecraft doesn't always drop equipment when the drop chance is 1.0 + * (or more). Try to work around that by moving the equipment into the drops + * if it is not already there. + * + * In Bukkit versions prior to 1.7.9, the equipment was not part of the drops + * list in the EntityDeathEvent. Bukkit fixed that issue with the API, but had + * to retain vanilla's handling of drop probabilities, which is still faulty. * * This handler will process any entity death, but naturally spawned monsters * probably won't have a (near) 1.0 drop chance for the their equipment, and @@ -182,39 +186,61 @@ public void onBlockPlace(BlockPlaceEvent event) @EventHandler(ignoreCancelled = true) public void onEntityDeath(EntityDeathEvent event) { + final float NEAR_UNITY = 0.999f; boolean forcedDrops = false; if (event.getEntity() instanceof Creature) { EntityEquipment equipment = event.getEntity().getEquipment(); - if (equipment.getHelmetDropChance() > 0.999f) + List drops = event.getDrops(); + if (equipment.getHelmetDropChance() > NEAR_UNITY) { - event.getDrops().add(equipment.getHelmet()); - equipment.setHelmet(null); forcedDrops = true; + ItemStack helmet = equipment.getHelmet(); + if (helmet != null && !drops.contains(helmet)) + { + drops.add(helmet); + equipment.setHelmet(null); + } } - if (equipment.getChestplateDropChance() > 0.999f) + if (equipment.getChestplateDropChance() > NEAR_UNITY) { - event.getDrops().add(equipment.getChestplate()); - equipment.setChestplate(null); forcedDrops = true; + ItemStack chestplate = equipment.getChestplate(); + if (chestplate != null && !drops.contains(chestplate)) + { + drops.add(chestplate); + equipment.setChestplate(null); + } } - if (equipment.getLeggingsDropChance() > 0.999f) + if (equipment.getLeggingsDropChance() > NEAR_UNITY) { - event.getDrops().add(equipment.getLeggings()); - equipment.setLeggings(null); forcedDrops = true; + ItemStack leggings = equipment.getLeggings(); + if (leggings != null && !drops.contains(leggings)) + { + drops.add(leggings); + equipment.setLeggings(null); + } } - if (equipment.getBootsDropChance() > 0.999f) + if (equipment.getBootsDropChance() > NEAR_UNITY) { - event.getDrops().add(equipment.getBoots()); - equipment.setBoots(null); forcedDrops = true; + ItemStack boots = equipment.getBoots(); + if (boots != null && !drops.contains(boots)) + { + drops.add(boots); + equipment.setBoots(null); + } } - if (equipment.getItemInHandDropChance() > 0.999f) + if (equipment.getItemInHandDropChance() > NEAR_UNITY) { - event.getDrops().add(equipment.getItemInHand()); - equipment.setItemInHand(null); forcedDrops = true; + ItemStack itemInHand = equipment.getItemInHand(); + if (itemInHand != null && !drops.contains(itemInHand)) + { + drops.add(itemInHand); + equipment.setItemInHand(null); + } } }