mirror of
https://github.com/PurpurMC/Purpur.git
synced 2026-02-17 16:37:43 +01:00
Fix advancement triggers on entity death
Fixes PaperMC/Paper#3729 Fixes PaperMC/Paper#4252
This commit is contained in:
@@ -0,0 +1,209 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <blake.galbreath@gmail.com>
|
||||
Date: Fri, 28 May 2021 12:24:45 -0500
|
||||
Subject: [PATCH] Fix advancement triggers on entity death
|
||||
|
||||
This fixes PaperMC/Paper#3729 and PaperMC/Paper#4252
|
||||
|
||||
Paper changes logical order revolving around making the EntityDeathEvent
|
||||
cancellable. Reordering this logic has ended up with entity equipment being
|
||||
cleared _before_ advancement criteria can run, causing things like killing
|
||||
raid captains not giving the voluntary exile advancement.
|
||||
|
||||
This fixes the issue by storing a copy of the equipment in a new field just
|
||||
before doing the death event logic where the equipment is cleared and then
|
||||
restoring it back to the entity just before the criterion triggers run and
|
||||
then finally clearing the equipment again right after the criterion is done.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java
|
||||
index b895288e0aa49e5a1222f7c5897f3dc43ff946fe..e4f5a5ffd25d4d4e427938a633675be46805af66 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java
|
||||
@@ -106,9 +106,9 @@ public abstract class EntityInsentient extends EntityLiving {
|
||||
public PathfinderGoalSelector targetSelector;
|
||||
private EntityLiving goalTarget;
|
||||
private final EntitySenses bo;
|
||||
- private final NonNullList<ItemStack> bp;
|
||||
+ private final NonNullList<ItemStack> bp; public List<ItemStack> getHandEquipment() { return this.bp; } // Purpur - OBFHELPER
|
||||
public final float[] dropChanceHand;
|
||||
- private final NonNullList<ItemStack> bq;
|
||||
+ private final NonNullList<ItemStack> bq; public List<ItemStack> getArmorEquipment() { return this.bq; } // Purpur - OBFHELPER
|
||||
public final float[] dropChanceArmor;
|
||||
// private boolean canPickUpLoot; // CraftBukkit - moved up to EntityLiving
|
||||
public boolean persistent;
|
||||
@@ -1013,6 +1013,41 @@ public abstract class EntityInsentient extends EntityLiving {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Purpur start
|
||||
+ public List<List<ItemStack>> cloneEquipment() {
|
||||
+ List<List<ItemStack>> list = new java.util.ArrayList<>();
|
||||
+ List<ItemStack> handItems = new java.util.ArrayList<>();
|
||||
+ for (ItemStack item : this.getHandEquipment()) {
|
||||
+ handItems.add(item.cloneItemStack());
|
||||
+ }
|
||||
+ list.add(handItems);
|
||||
+ List<ItemStack> armorItems = new java.util.ArrayList<>();
|
||||
+ for (ItemStack item : this.getArmorEquipment()) {
|
||||
+ armorItems.add(item.cloneItemStack());
|
||||
+ }
|
||||
+ list.add(armorItems);
|
||||
+ return list;
|
||||
+ }
|
||||
+
|
||||
+ public void restoreEquipment(List<List<ItemStack>> list) {
|
||||
+ this.getHandEquipment().clear();
|
||||
+ List<ItemStack> handItems = list.get(0);
|
||||
+ for (int i = 0; i < handItems.size(); i++) {
|
||||
+ this.getHandEquipment().set(i, handItems.get(1));
|
||||
+ }
|
||||
+ this.getArmorEquipment().clear();
|
||||
+ List<ItemStack> armorItems = list.get(1);
|
||||
+ for (int i = 0; i < armorItems.size(); i++) {
|
||||
+ this.getArmorEquipment().set(i, armorItems.get(i));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public void clearEquipment() {
|
||||
+ this.getHandEquipment().clear();
|
||||
+ this.getArmorEquipment().clear();
|
||||
+ }
|
||||
+ // Purpur end
|
||||
+
|
||||
@Override
|
||||
public void setSlot(EnumItemSlot enumitemslot, ItemStack itemstack) {
|
||||
switch (enumitemslot.a()) {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java
|
||||
index 6b65b17d6b100adacd628d08a24a68164d2bb9aa..2f7352d7ae99ecdefe0f7b56cebf008906607d4d 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java
|
||||
@@ -1560,10 +1560,13 @@ public abstract class EntityLiving extends Entity {
|
||||
}
|
||||
|
||||
// Paper start
|
||||
+ List<List<ItemStack>> equipmentSnapshotBefore = this.cloneEquipment(); // Purpur
|
||||
org.bukkit.event.entity.EntityDeathEvent deathEvent = this.d(damagesource);
|
||||
if (deathEvent == null || !deathEvent.isCancelled()) {
|
||||
if (this.getKillCount() >= 0 && entityliving != null) {
|
||||
+ this.restoreEquipment(equipmentSnapshotBefore); // Purpur
|
||||
entityliving.runKillTrigger(this, this.getKillCount(), damagesource);
|
||||
+ this.clearEquipment(); // Purpur
|
||||
}
|
||||
if (this.isSleeping()) {
|
||||
this.entityWakeup();
|
||||
@@ -2274,6 +2277,12 @@ public abstract class EntityLiving extends Entity {
|
||||
|
||||
public abstract ItemStack getEquipment(EnumItemSlot enumitemslot);
|
||||
|
||||
+ // Purpur start
|
||||
+ public abstract List<List<ItemStack>> cloneEquipment();
|
||||
+ public abstract void restoreEquipment(List<List<ItemStack>> list);
|
||||
+ public abstract void clearEquipment();
|
||||
+ // Purpur end
|
||||
+
|
||||
// CraftBukkit start
|
||||
public void setSlot(EnumItemSlot enumitemslot, ItemStack itemstack, boolean silent) {
|
||||
this.setSlot(enumitemslot, itemstack);
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java
|
||||
index ddc1c3383cdc32fa832485f3922c74185731557a..e28a2d983ae7b83f435c9dea606a92e2fbd3391a 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java
|
||||
@@ -171,6 +171,41 @@ public class EntityArmorStand extends EntityLiving {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Purpur start
|
||||
+ public List<List<ItemStack>> cloneEquipment() {
|
||||
+ List<List<ItemStack>> list = new java.util.ArrayList<>();
|
||||
+ List<ItemStack> handItems = new java.util.ArrayList<>();
|
||||
+ for (ItemStack item : this.handItems) {
|
||||
+ handItems.add(item.cloneItemStack());
|
||||
+ }
|
||||
+ list.add(handItems);
|
||||
+ List<ItemStack> armorItems = new java.util.ArrayList<>();
|
||||
+ for (ItemStack item : this.armorItems) {
|
||||
+ armorItems.add(item.cloneItemStack());
|
||||
+ }
|
||||
+ list.add(armorItems);
|
||||
+ return list;
|
||||
+ }
|
||||
+
|
||||
+ public void restoreEquipment(List<List<ItemStack>> list) {
|
||||
+ this.handItems.clear();
|
||||
+ List<ItemStack> handItems = list.get(0);
|
||||
+ for (int i = 0; i < handItems.size(); i++) {
|
||||
+ this.handItems.set(i, handItems.get(1));
|
||||
+ }
|
||||
+ this.armorItems.clear();
|
||||
+ List<ItemStack> armorItems = list.get(1);
|
||||
+ for (int i = 0; i < armorItems.size(); i++) {
|
||||
+ this.armorItems.set(i, armorItems.get(1));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public void clearEquipment() {
|
||||
+ this.handItems.clear();
|
||||
+ this.armorItems.clear();
|
||||
+ }
|
||||
+ // Purpur end
|
||||
+
|
||||
@Override
|
||||
public void setSlot(EnumItemSlot enumitemslot, ItemStack itemstack) {
|
||||
// CraftBukkit start
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java
|
||||
index abac4b996c7935ac6115a9ad96191f2a57afc95f..0443aaa9fc4058cc4ce61977a89cdf6ea6452b65 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java
|
||||
@@ -1892,6 +1892,52 @@ public abstract class EntityHuman extends EntityLiving {
|
||||
return enumitemslot == EnumItemSlot.MAINHAND ? this.inventory.getItemInHand() : (enumitemslot == EnumItemSlot.OFFHAND ? (ItemStack) this.inventory.extraSlots.get(0) : (enumitemslot.a() == EnumItemSlot.Function.ARMOR ? (ItemStack) this.inventory.armor.get(enumitemslot.b()) : ItemStack.b));
|
||||
}
|
||||
|
||||
+ // Purpur start
|
||||
+ public List<List<ItemStack>> cloneEquipment() {
|
||||
+ List<List<ItemStack>> list = new java.util.ArrayList<>();
|
||||
+ List<ItemStack> invItems = new java.util.ArrayList<>();
|
||||
+ for (ItemStack item : this.inventory.items) {
|
||||
+ invItems.add(item.cloneItemStack());
|
||||
+ }
|
||||
+ list.add(invItems);
|
||||
+ List<ItemStack> armorItems = new java.util.ArrayList<>();
|
||||
+ for (ItemStack item : this.inventory.armor) {
|
||||
+ armorItems.add(item.cloneItemStack());
|
||||
+ }
|
||||
+ list.add(armorItems);
|
||||
+ List<ItemStack> extraItems = new java.util.ArrayList<>();
|
||||
+ for (ItemStack item : this.inventory.extraSlots) {
|
||||
+ extraItems.add(item.cloneItemStack());
|
||||
+ }
|
||||
+ list.add(extraItems);
|
||||
+ return list;
|
||||
+ }
|
||||
+
|
||||
+ public void restoreEquipment(List<List<ItemStack>> list) {
|
||||
+ this.inventory.items.clear();
|
||||
+ List<ItemStack> invItems = list.get(0);
|
||||
+ for (int i = 0; i < invItems.size(); i++) {
|
||||
+ this.inventory.items.set(i, invItems.get(1));
|
||||
+ }
|
||||
+ this.inventory.armor.clear();
|
||||
+ List<ItemStack> armorItems = list.get(1);
|
||||
+ for (int i = 0; i < armorItems.size(); i++) {
|
||||
+ this.inventory.armor.set(i, armorItems.get(1));
|
||||
+ }
|
||||
+ this.inventory.extraSlots.clear();
|
||||
+ List<ItemStack> extraItems = list.get(2);
|
||||
+ for (int i = 0; i < extraItems.size(); i++) {
|
||||
+ this.inventory.extraSlots.set(i, extraItems.get(1));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public void clearEquipment() {
|
||||
+ this.inventory.items.clear();
|
||||
+ this.inventory.armor.clear();
|
||||
+ this.inventory.extraSlots.clear();
|
||||
+ }
|
||||
+ // Purpur end
|
||||
+
|
||||
@Override
|
||||
public void setSlot(EnumItemSlot enumitemslot, ItemStack itemstack) {
|
||||
// CraftBukkit start
|
||||
@@ -1,77 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <blake.galbreath@gmail.com>
|
||||
Date: Fri, 28 May 2021 12:24:45 -0500
|
||||
Subject: [PATCH] Fix raid captains not giving voluntary exile advancement
|
||||
|
||||
This fixes PaperMC/Paper#3729 where killing a raid captain does not give the
|
||||
voluntary exile advancement. The problem is 2 fold on Paper's end.
|
||||
|
||||
Firstly, Paper changes logical order revolving around making the EntityDeathEvent
|
||||
cancellable. Reordering this logic has ended up with raid captains unsetting the
|
||||
banner on their head _before_ the criterion triggers for the advancement leaving
|
||||
the criterion to believe a regular pillager has been killed, not a captain.
|
||||
|
||||
Secondly, Paper sets itemstacks to count of 0 too early in an attempt to reduce
|
||||
the amount of dupes caused by leaking them through various gameplay mechanics. This
|
||||
means the banner on their head get converted to air before the criterion triggers
|
||||
leaving the criterion to believe a regular pillager has been killed.
|
||||
|
||||
This fixes both issues by storing a copy of the banner in a new field that is set
|
||||
back to the head slot just before the criterion triggers and then removed again
|
||||
right after the criterion is finished running.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java
|
||||
index 6b65b17d6b100adacd628d08a24a68164d2bb9aa..6acef38b805b35e1f2ae9e6f4d2f387a5050d0f7 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java
|
||||
@@ -1563,7 +1563,9 @@ public abstract class EntityLiving extends Entity {
|
||||
org.bukkit.event.entity.EntityDeathEvent deathEvent = this.d(damagesource);
|
||||
if (deathEvent == null || !deathEvent.isCancelled()) {
|
||||
if (this.getKillCount() >= 0 && entityliving != null) {
|
||||
+ this.fixHead(); // Purpur
|
||||
entityliving.runKillTrigger(this, this.getKillCount(), damagesource);
|
||||
+ this.fixHead(); // Purpur
|
||||
}
|
||||
if (this.isSleeping()) {
|
||||
this.entityWakeup();
|
||||
@@ -3902,4 +3904,6 @@ public abstract class EntityLiving extends Entity {
|
||||
this.shieldBlockingDelay = shieldBlockingDelay;
|
||||
}
|
||||
// Paper end
|
||||
+
|
||||
+ public void fixHead() {} // Purpur
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/raid/EntityRaider.java b/src/main/java/net/minecraft/world/entity/raid/EntityRaider.java
|
||||
index 8eec32af12c69e1963dcd304a25ec4811b2f1f5a..d0cf1eca6f077673aa353e92ef9732f0fe5d0b54 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/raid/EntityRaider.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/raid/EntityRaider.java
|
||||
@@ -152,6 +152,10 @@ public abstract class EntityRaider extends EntityMonsterPatrolling {
|
||||
}
|
||||
|
||||
if (!itemstack.isEmpty() && ItemStack.matches(itemstack, Raid.s()) && entityhuman != null) {
|
||||
+ // Purpur start
|
||||
+ this.fixHead = itemstack.cloneItemStack();
|
||||
+ this.fixHead.setCount(1);
|
||||
+ // Purpur end
|
||||
MobEffect mobeffect = entityhuman.getEffect(MobEffects.BAD_OMEN);
|
||||
byte b0 = 1;
|
||||
int i;
|
||||
@@ -564,4 +568,18 @@ public abstract class EntityRaider extends EntityMonsterPatrolling {
|
||||
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // Purpur start
|
||||
+ private ItemStack fixHead = null;
|
||||
+
|
||||
+ @Override
|
||||
+ public void fixHead() {
|
||||
+ if (this.fixHead != null) {
|
||||
+ setSlot(EnumItemSlot.HEAD, this.fixHead);
|
||||
+ this.fixHead = null;
|
||||
+ } else {
|
||||
+ setSlot(EnumItemSlot.HEAD, ItemStack.NULL_ITEM);
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end
|
||||
}
|
||||
Reference in New Issue
Block a user