From b895b00dd35301675b8279e86fcd505229e65250 Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Wed, 8 Dec 2021 10:25:57 -0800 Subject: [PATCH] Fix entity equipment on cancellation of EntityDeathEvent (#5740) --- build-data/paper.at | 2 + ...m-duplication-issues-and-teleport-is.patch | 50 +++++++++++++++++++ patches/server/Improve-death-events.patch | 30 ++++++++++- 3 files changed, 80 insertions(+), 2 deletions(-) diff --git a/build-data/paper.at b/build-data/paper.at index f18d4fd87a..8213dae874 100644 --- a/build-data/paper.at +++ b/build-data/paper.at @@ -75,6 +75,8 @@ public net.minecraft.server.level.ChunkMap getPoiManager()Lnet/minecraft/world/e # Improve death events public net.minecraft.world.entity.LivingEntity getDeathSound()Lnet/minecraft/sounds/SoundEvent; public net.minecraft.world.entity.LivingEntity getSoundVolume()F +public net.minecraft.world.entity.Mob handItems +public net.minecraft.world.entity.Mob armorItems # Add sun related api public net.minecraft.world.entity.Mob isSunBurnTick()Z diff --git a/patches/server/Fix-numerous-item-duplication-issues-and-teleport-is.patch b/patches/server/Fix-numerous-item-duplication-issues-and-teleport-is.patch index 1d9a42b1f9..ad8b0e6d92 100644 --- a/patches/server/Fix-numerous-item-duplication-issues-and-teleport-is.patch +++ b/patches/server/Fix-numerous-item-duplication-issues-and-teleport-is.patch @@ -79,6 +79,39 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } public float getBlockExplosionResistance(Explosion explosion, BlockGetter world, BlockPos pos, BlockState blockState, FluidState fluidState, float max) { +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + // Paper start + org.bukkit.event.entity.EntityDeathEvent deathEvent = this.dropAllDeathLoot(source); + if (deathEvent == null || !deathEvent.isCancelled()) { +- if (this.deathScore >= 0 && entityliving != null) { +- entityliving.awardKillScore(this, this.deathScore, source); +- } ++ // if (this.deathScore >= 0 && entityliving != null) { // Paper moved to be run earlier in #dropAllDeathLoot before destroying the drop items in CraftEventFactory#callEntityDeathEvent ++ // entityliving.awardKillScore(this, this.deathScore, source); ++ // } + // Paper start - clear equipment if event is not cancelled + if (this instanceof Mob mob) { + java.util.Collections.fill(mob.handItems, ItemStack.EMPTY); +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + this.dropCustomDeathLoot(source, i, flag); + this.clearEquipmentSlots = true; // Paper + } +- // CraftBukkit start - Call death event +- org.bukkit.event.entity.EntityDeathEvent deathEvent = CraftEventFactory.callEntityDeathEvent(this, this.drops); // Paper ++ // CraftBukkit start - Call death event // Paper start - call advancement triggers with correct entity equipment ++ org.bukkit.event.entity.EntityDeathEvent deathEvent = CraftEventFactory.callEntityDeathEvent(this, this.drops, () -> { ++ final LivingEntity entityliving = this.getKillCredit(); ++ if (this.deathScore >= 0 && entityliving != null) { ++ entityliving.awardKillScore(this, this.deathScore, source); ++ } ++ }); // Paper end + this.postDeathDropItems(deathEvent); // Paper + this.drops = new ArrayList<>(); + // CraftBukkit end diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java @@ -106,6 +139,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java @@ -0,0 +0,0 @@ public class CraftEventFactory { + } + + public static EntityDeathEvent callEntityDeathEvent(net.minecraft.world.entity.LivingEntity victim, List drops) { ++ // Paper start ++ return CraftEventFactory.callEntityDeathEvent(victim, drops, com.google.common.util.concurrent.Runnables.doNothing()); ++ } ++ public static EntityDeathEvent callEntityDeathEvent(net.minecraft.world.entity.LivingEntity victim, List drops, Runnable lootCheck) { ++ // Paper end + CraftLivingEntity entity = (CraftLivingEntity) victim.getBukkitEntity(); + EntityDeathEvent event = new EntityDeathEvent(entity, drops, victim.getExpReward()); + populateFields(victim, event); // Paper - make cancellable +@@ -0,0 +0,0 @@ public class CraftEventFactory { + playDeathSound(victim, event); + // Paper end + victim.expToDrop = event.getDroppedExp(); ++ lootCheck.run(); // Paper - advancement triggers before destroying items + for (org.bukkit.inventory.ItemStack stack : event.getDrops()) { if (stack == null || stack.getType() == Material.AIR || stack.getAmount() == 0) continue; diff --git a/patches/server/Improve-death-events.patch b/patches/server/Improve-death-events.patch index 2db3d825e1..a2f38bbfb2 100644 --- a/patches/server/Improve-death-events.patch +++ b/patches/server/Improve-death-events.patch @@ -104,7 +104,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 Entity entity = source.getEntity(); LivingEntity entityliving = this.getKillCredit(); - -+ /* // Paper - move down to make death event cancellable - this is the runKillTrigger below ++ /* // Paper - move down to make death event cancellable - this is the awardKillScore below if (this.deathScore >= 0 && entityliving != null) { entityliving.awardKillScore(this, this.deathScore, source); } @@ -112,7 +112,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (!this.level.isClientSide && this.hasCustomName()) { if (org.spigotmc.SpigotConfig.logNamedDeaths) LivingEntity.LOGGER.info("Named entity {} died: {}", this, this.getCombatTracker().getDeathMessage().getString()); // Spigot } -+ */ // Paper - move down to make death event cancellable - this is the runKillTrigger below ++ */ // Paper - move down to make death event cancellable - this is the awardKillScore below this.dead = true; - this.getCombatTracker().recheckStatus(); @@ -130,6 +130,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if (this.deathScore >= 0 && entityliving != null) { + entityliving.awardKillScore(this, this.deathScore, source); + } ++ // Paper start - clear equipment if event is not cancelled ++ if (this instanceof Mob mob) { ++ java.util.Collections.fill(mob.handItems, ItemStack.EMPTY); ++ java.util.Collections.fill(mob.armorItems, ItemStack.EMPTY); ++ } ++ // Paper end + + if (this.isSleeping()) { + this.stopSleeping(); @@ -172,12 +178,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } - protected void dropAllDeathLoot(DamageSource source) { ++ protected boolean clearEquipmentSlots = true; // Paper + protected org.bukkit.event.entity.EntityDeathEvent dropAllDeathLoot(DamageSource source) { // Paper Entity entity = source.getEntity(); int i; @@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + this.dropEquipment(); // CraftBukkit - from below + if (this.shouldDropLoot() && this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { + this.dropFromLootTable(source, flag); ++ this.clearEquipmentSlots = false; // Paper this.dropCustomDeathLoot(source, i, flag); ++ this.clearEquipmentSlots = true; // Paper } // CraftBukkit start - Call death event - CraftEventFactory.callEntityDeathEvent(this, this.drops); @@ -196,6 +208,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // CraftBukkit start public int getExpReward() { +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -0,0 +0,0 @@ public abstract class Mob extends LivingEntity { + } + + this.spawnAtLocation(itemstack); ++ if (this.clearEquipmentSlots) { // Paper + this.setItemSlot(enumitemslot, ItemStack.EMPTY); ++ } // Paper + } + } + diff --git a/src/main/java/net/minecraft/world/entity/animal/Fox.java b/src/main/java/net/minecraft/world/entity/animal/Fox.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Fox.java