4cdbb0c86c
Upstream has released updates that appear to apply and compile correctly. This update has not been tested by PaperMC and as with ANY update, please do your own testing Bukkit Changes: 044d4ee9 SPIGOT-7283, SPIGOT-7318: Add AsyncStructureGenerateEvent and BlockState cloning 57b73d57 PR-913: Deprecate Projectile#doesBounce() and #setBounce() 43373c44 PR-904: Update FeatureFlag for 1.20.2 a7bbbf0c PR-911: Expand DataPack API with 1.20.2 pack version methods 0341e3a0 SPIGOT-7489: Add TeleportDuration to Display Entity bcd8d2aa PR-912: Update Minecraft Wiki URLs CraftBukkit Changes: 99aafc222 Increase outdated build delay dab849f08 SPIGOT-7283, SPIGOT-7318: Add AsyncStructureGenerateEvent and BlockState cloning 041b29ae3 Upgrade specialsource-maven-plugin 851a32cff PR-1263: Remove unused implementation of AbstractProjectile#doesBounce() and #setBounce() 251af0da3 PR-1261: Expand DataPack API with 1.20.2 pack version methods 46e4ba627 Upgrade specialsource-maven-plugin df3738a24 SPIGOT-7489: Add TeleportDuration to Display Entity 8d0fea457 PR-1262: Update Minecraft Wiki URLs e62905aab SPIGOT-7490: Fix entity equipment updates Spigot Changes: a0f3d486 Rebuild patches
168 Zeilen
10 KiB
Diff
168 Zeilen
10 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Aikar <aikar@aikar.co>
|
|
Date: Sat, 25 Apr 2020 06:46:35 -0400
|
|
Subject: [PATCH] Fix numerous item duplication issues and teleport issues
|
|
|
|
This notably fixes the newest "Donkey Dupe", but also fixes a lot
|
|
of dupe bugs in general around nether portals and entity world transfer
|
|
|
|
We also fix item duplication generically by anytime we clone an item
|
|
to drop it on the ground, destroy the source item.
|
|
|
|
This avoid an itemstack ever existing twice in the world state pre
|
|
clean up stage.
|
|
|
|
So even if something NEW comes up, it would be impossible to drop the
|
|
same item twice because the source was destroyed.
|
|
|
|
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
|
index eed16b541a9c39ed4697e783612e6f7b7ff23b70..1d2dd9b8ae43f22d875cb530130118df247b87dc 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
|
@@ -2457,11 +2457,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
|
} else {
|
|
// CraftBukkit start - Capture drops for death event
|
|
if (this instanceof net.minecraft.world.entity.LivingEntity && !((net.minecraft.world.entity.LivingEntity) this).forceDrops) {
|
|
- ((net.minecraft.world.entity.LivingEntity) this).drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(stack));
|
|
+ ((net.minecraft.world.entity.LivingEntity) this).drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(stack)); // Paper - mirror so we can destroy it later
|
|
return null;
|
|
}
|
|
// CraftBukkit end
|
|
- ItemEntity entityitem = new ItemEntity(this.level(), this.getX(), this.getY() + (double) yOffset, this.getZ(), stack);
|
|
+ ItemEntity entityitem = new ItemEntity(this.level(), this.getX(), this.getY() + (double) yOffset, this.getZ(), stack.copy()); // Paper - copy so we can destroy original
|
|
+ stack.setCount(0); // Paper - destroy this item - if this ever leaks due to game bugs, ensure it doesn't dupe
|
|
|
|
entityitem.setDefaultPickUpDelay();
|
|
// CraftBukkit start
|
|
@@ -3263,6 +3264,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
|
@Nullable
|
|
public Entity teleportTo(ServerLevel worldserver, Vec3 location) {
|
|
// CraftBukkit end
|
|
+ // Paper start - fix bad state entities causing dupes
|
|
+ if (!this.isAlive() || !this.valid) {
|
|
+ LOGGER.warn("Illegal Entity Teleport " + this + " to " + worldserver + ":" + location, new Throwable());
|
|
+ return null;
|
|
+ }
|
|
+ // Paper end
|
|
if (this.level() instanceof ServerLevel && !this.isRemoved()) {
|
|
this.level().getProfiler().push("changeDimension");
|
|
// CraftBukkit start
|
|
@@ -3289,6 +3296,11 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
|
// CraftBukkit end
|
|
|
|
this.level().getProfiler().popPush("reloading");
|
|
+ // Paper start - Change lead drop timing to prevent dupe
|
|
+ if (this instanceof Mob) {
|
|
+ ((Mob) this).dropLeash(true, true); // Paper drop lead
|
|
+ }
|
|
+ // Paper end
|
|
Entity entity = this.getType().create(worldserver);
|
|
|
|
if (entity != null) {
|
|
@@ -3302,10 +3314,6 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
|
// CraftBukkit start - Forward the CraftEntity to the new entity
|
|
this.getBukkitEntity().setHandle(entity);
|
|
entity.bukkitEntity = this.getBukkitEntity();
|
|
-
|
|
- if (this instanceof Mob) {
|
|
- ((Mob) this).dropLeash(true, false); // Unleash to prevent duping of leads.
|
|
- }
|
|
// CraftBukkit end
|
|
}
|
|
|
|
@@ -3426,7 +3434,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
|
}
|
|
|
|
public boolean canChangeDimensions() {
|
|
- return !this.isPassenger() && !this.isVehicle();
|
|
+ return !this.isPassenger() && !this.isVehicle() && isAlive() && valid; // Paper
|
|
}
|
|
|
|
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 4edf7a989f12cae065977d1f529e856a7d3a932b..f01a5ba97d391292192100b6cd7fa018cdeb7e05 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
|
@@ -1711,9 +1711,9 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
|
// Paper start
|
|
org.bukkit.event.entity.EntityDeathEvent deathEvent = this.dropAllDeathLoot(damageSource);
|
|
if (deathEvent == null || !deathEvent.isCancelled()) {
|
|
- if (this.deathScore >= 0 && entityliving != null) {
|
|
- entityliving.awardKillScore(this, this.deathScore, damageSource);
|
|
- }
|
|
+ // 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, damageSource);
|
|
+ // }
|
|
// Paper start - clear equipment if event is not cancelled
|
|
if (this instanceof Mob) {
|
|
for (EquipmentSlot slot : this.clearedEquipmentSlots) {
|
|
@@ -1814,8 +1814,13 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
|
this.dropCustomDeathLoot(source, i, flag);
|
|
this.clearEquipmentSlots = prev; // 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 86c08e36779af6f85932c1c346c54594f543db0d..7e996a527a632a2b382f5eea6df6be839a7a0ef4 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
|
|
@@ -637,7 +637,7 @@ public class ArmorStand extends LivingEntity {
|
|
for (i = 0; i < this.handItems.size(); ++i) {
|
|
itemstack = (ItemStack) this.handItems.get(i);
|
|
if (!itemstack.isEmpty()) {
|
|
- drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops
|
|
+ drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)); // CraftBukkit - add to drops // Paper - mirror so we can destroy it later - though this call site was safe
|
|
this.handItems.set(i, ItemStack.EMPTY);
|
|
}
|
|
}
|
|
@@ -645,7 +645,7 @@ public class ArmorStand extends LivingEntity {
|
|
for (i = 0; i < this.armorItems.size(); ++i) {
|
|
itemstack = (ItemStack) this.armorItems.get(i);
|
|
if (!itemstack.isEmpty()) {
|
|
- drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops
|
|
+ drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)); // CraftBukkit - add to drops // Paper - mirror so we can destroy it later - though this call site was safe
|
|
this.armorItems.set(i, ItemStack.EMPTY);
|
|
}
|
|
}
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
|
index accf3399f813ad062a3dba6eba99c16afe66045a..1a2f03895f348e4c2620caef74f12cb1f41dec1b 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
|
@@ -868,6 +868,11 @@ public class CraftEventFactory {
|
|
}
|
|
|
|
public static EntityDeathEvent callEntityDeathEvent(net.minecraft.world.entity.LivingEntity victim, List<org.bukkit.inventory.ItemStack> 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<org.bukkit.inventory.ItemStack> drops, Runnable lootCheck) {
|
|
+ // Paper end
|
|
CraftLivingEntity entity = (CraftLivingEntity) victim.getBukkitEntity();
|
|
EntityDeathEvent event = new EntityDeathEvent(entity, drops, victim.getExpReward());
|
|
populateFields(victim, event); // Paper - make cancellable
|
|
@@ -881,11 +886,13 @@ 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;
|
|
|
|
- world.dropItem(entity.getLocation(), stack);
|
|
+ world.dropItem(entity.getLocation(), stack); // Paper - note: dropItem already clones due to this being bukkit -> NMS
|
|
+ if (stack instanceof CraftItemStack) stack.setAmount(0); // Paper - destroy this item - if this ever leaks due to game bugs, ensure it doesn't dupe, but don't nuke bukkit stacks of manually added items
|
|
}
|
|
|
|
return event;
|