From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Mon, 12 Dec 2022 12:14:03 -0800 Subject: [PATCH] Properly track the changed item from dispense events diff --git a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java +++ b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java @@ -0,0 +0,0 @@ public interface DispenseItemBehavior { idispensebehavior.dispense(pointer, eventStack); return stack; } + // Paper start - track changed items in the dispense event + itemstack1 = CraftItemStack.unwrap(event.getItem()); // unwrap is safe because the stack won't be modified + entitytypes = ((SpawnEggItem) itemstack1.getItem()).getType(itemstack1); + // Paper end - track changed item from dispense event } try { - entitytypes.spawn(pointer.level(), stack, (Player) null, pointer.pos().relative(enumdirection), EntitySpawnReason.DISPENSER, enumdirection != Direction.UP, false); + entitytypes.spawn(pointer.level(), itemstack1, (Player) null, pointer.pos().relative(enumdirection), EntitySpawnReason.DISPENSER, enumdirection != Direction.UP, false); // Paper - track changed item in dispense event } catch (Exception exception) { DispenseItemBehavior.LOGGER.error("Error while dispensing spawn egg from dispenser at {}", pointer.pos(), exception); // CraftBukkit - decompile error return ItemStack.EMPTY; @@ -0,0 +0,0 @@ public interface DispenseItemBehavior { } // CraftBukkit end + final ItemStack newStack = CraftItemStack.unwrap(event.getItem()); // Paper - use event itemstack (unwrap is fine here because the stack won't be modified) Consumer consumer = EntityType.appendDefaultStackConfig((entityarmorstand) -> { entityarmorstand.setYRot(enumdirection.toYRot()); - }, worldserver, stack, (Player) null); + }, worldserver, newStack, (Player) null); // Paper - track changed items in the dispense event ArmorStand entityarmorstand = (ArmorStand) EntityType.ARMOR_STAND.spawn(worldserver, consumer, blockposition, EntitySpawnReason.DISPENSER, false, false); if (entityarmorstand != null) { @@ -0,0 +0,0 @@ public interface DispenseItemBehavior { return stack; } } - ((Saddleable) list.get(0)).equipSaddle(itemstack1, SoundSource.BLOCKS); + ((Saddleable) list.get(0)).equipSaddle(CraftItemStack.asNMSCopy(event.getItem()), SoundSource.BLOCKS); // Paper - track changed items in dispense event // CraftBukkit end this.setSuccess(true); return stack; @@ -0,0 +0,0 @@ public interface DispenseItemBehavior { int y = blockposition.getY(); int z = blockposition.getZ(); BlockState iblockdata = worldserver.getBlockState(blockposition); + ItemStack dispensedItem = stack; // Paper - track changed item from the dispense event // Paper start - correctly check if the bucket place will succeed /* Taken from SolidBucketItem#emptyContents */ boolean willEmptyContentsSolidBucketItem = dispensiblecontaineritem instanceof net.minecraft.world.item.SolidBucketItem && worldserver.isInWorldBounds(blockposition) && iblockdata.isAir(); @@ -0,0 +0,0 @@ public interface DispenseItemBehavior { } } - dispensiblecontaineritem = (DispensibleContainerItem) CraftItemStack.asNMSCopy(event.getItem()).getItem(); + // Paper start - track changed item from dispense event + dispensedItem = CraftItemStack.unwrap(event.getItem()); // unwrap is safe here as the stack isn't mutated + dispensiblecontaineritem = (DispensibleContainerItem) dispensedItem.getItem(); + // Paper end - track changed item from dispense event } // CraftBukkit end if (dispensiblecontaineritem.emptyContents((Player) null, worldserver, blockposition, (BlockHitResult) null)) { - dispensiblecontaineritem.checkExtraContent((Player) null, worldserver, stack, blockposition); + dispensiblecontaineritem.checkExtraContent((Player) null, worldserver, dispensedItem, blockposition); // Paper - track changed item from dispense event return this.consumeWithRemainder(pointer, stack, new ItemStack(Items.BUCKET)); } else { return this.defaultDispenseItemBehavior.dispense(pointer, stack); diff --git a/src/main/java/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java b/src/main/java/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java +++ b/src/main/java/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java @@ -0,0 +0,0 @@ public class ProjectileDispenseBehavior extends DefaultDispenseItemBehavior { // SPIGOT-7923: Avoid create projectiles with empty item if (!itemstack1.isEmpty()) { - Projectile iprojectile = Projectile.spawnProjectileUsingShoot(this.projectileItem.asProjectile(worldserver, iposition, itemstack1, enumdirection), worldserver, itemstack1, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), this.dispenseConfig.power(), this.dispenseConfig.uncertainty()); + Projectile iprojectile = Projectile.spawnProjectileUsingShoot(this.projectileItem.asProjectile(worldserver, iposition, CraftItemStack.unwrap(event.getItem()), enumdirection), worldserver, itemstack1, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), this.dispenseConfig.power(), this.dispenseConfig.uncertainty()); // Paper - track changed items in the dispense event; unwrap is safe here because all uses of the stack make their own copies iprojectile.projectileSource = new org.bukkit.craftbukkit.projectiles.CraftBlockProjectileSource(pointer.blockEntity()); } // itemstack.shrink(1); // CraftBukkit - Handled during event processing diff --git a/src/main/java/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java b/src/main/java/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java +++ b/src/main/java/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java @@ -0,0 +0,0 @@ public class ShulkerBoxDispenseBehavior extends OptionalDispenseItemBehavior { // CraftBukkit end try { - this.setSuccess(((BlockItem) item).place(new DirectionalPlaceContext(pointer.level(), blockposition, enumdirection, stack, enumdirection1)).consumesAction()); + // Paper start - track changed items in the dispense event + this.setSuccess(((BlockItem) item).place(new DirectionalPlaceContext(pointer.level(), blockposition, enumdirection, CraftItemStack.asNMSCopy(event.getItem()), enumdirection1)).consumesAction()); + if (this.isSuccess()) { + stack.shrink(1); // vanilla shrink is in the place function above, manually handle it here + } + // Paper end - track changed items in the dispense event } catch (Exception exception) { ShulkerBoxDispenseBehavior.LOGGER.error("Error trying to place shulker box at {}", blockposition, exception); }