Fix possible StackOverflowError and NPE for some dispenses
For saddles, carpets, horse armor, and chests for horse-likes a BlockDispenseEvent handler that always mutated the item without changing the type would result in a SO error because when it went to find the replacement dispense behavior (since the item "changed") it didn't properly handle if the replacement was the same instance of dispense behavior. Additionally equippable mob heads, wither skulls, and carved pumpkins are subject to the same possible error. Furthermore since 1.21.2, the DISPENSER_REGISTRY map doesn't have a default return value anymore and some dispense behaviors like equippable and regular items will not have a defined behavior in that map and might throw a NPE in that case.
This commit is contained in:
@@ -35,7 +35,7 @@
|
||||
+ stack.grow(1);
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
+ if (!dropper && !event.getItem().getType().equals(craftItem.getType())) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(sourceblock, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior.getClass() != DefaultDispenseItemBehavior.class) {
|
||||
+ idispensebehavior.dispense(sourceblock, eventStack);
|
||||
+ } else {
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
+ stack.grow(1);
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
@@ -105,7 +105,7 @@
|
||||
+ stack.grow(1);
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
@@ -149,8 +149,8 @@
|
||||
+ stack.grow(1);
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != EquipmentDispenseItemBehavior.INSTANCE) {
|
||||
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { // Paper - fix possible StackOverflowError
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
+ }
|
||||
@@ -185,8 +185,8 @@
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != EquipmentDispenseItemBehavior.INSTANCE) {
|
||||
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { // Paper - fix possible StackOverflowError
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
+ }
|
||||
@@ -229,7 +229,7 @@
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
@@ -272,7 +272,7 @@
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
@@ -306,7 +306,7 @@
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
@@ -354,7 +354,7 @@
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
@@ -425,7 +425,7 @@
|
||||
+ stack.grow(1);
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
@@ -464,7 +464,7 @@
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
@@ -475,6 +475,15 @@
|
||||
if (worldserver.isEmptyBlock(blockposition) && WitherSkullBlock.canSpawnMob(worldserver, blockposition, stack)) {
|
||||
worldserver.setBlock(blockposition, (BlockState) Blocks.WITHER_SKELETON_SKULL.defaultBlockState().setValue(SkullBlock.ROTATION, RotationSegment.convertToSegment(enumdirection)), 3);
|
||||
worldserver.gameEvent((Entity) null, (Holder) GameEvent.BLOCK_PLACE, blockposition);
|
||||
@@ -326,7 +645,7 @@
|
||||
stack.shrink(1);
|
||||
this.setSuccess(true);
|
||||
} else {
|
||||
- this.setSuccess(EquipmentDispenseItemBehavior.dispenseEquipment(pointer, stack));
|
||||
+ this.setSuccess(EquipmentDispenseItemBehavior.dispenseEquipment(pointer, stack, this)); // Paper - fix possible StackOverflowError
|
||||
}
|
||||
|
||||
return stack;
|
||||
@@ -339,6 +658,30 @@
|
||||
BlockPos blockposition = pointer.pos().relative((Direction) pointer.state().getValue(DispenserBlock.FACING));
|
||||
CarvedPumpkinBlock blockpumpkincarved = (CarvedPumpkinBlock) Blocks.CARVED_PUMPKIN;
|
||||
@@ -495,7 +504,7 @@
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
@@ -506,6 +515,15 @@
|
||||
if (worldserver.isEmptyBlock(blockposition) && blockpumpkincarved.canSpawnGolem(worldserver, blockposition)) {
|
||||
if (!worldserver.isClientSide) {
|
||||
worldserver.setBlock(blockposition, blockpumpkincarved.defaultBlockState(), 3);
|
||||
@@ -348,7 +691,7 @@
|
||||
stack.shrink(1);
|
||||
this.setSuccess(true);
|
||||
} else {
|
||||
- this.setSuccess(EquipmentDispenseItemBehavior.dispenseEquipment(pointer, stack));
|
||||
+ this.setSuccess(EquipmentDispenseItemBehavior.dispenseEquipment(pointer, stack, this)); // Paper - fix possible StackOverflowError
|
||||
}
|
||||
|
||||
return stack;
|
||||
@@ -377,6 +720,30 @@
|
||||
BlockPos blockposition = pointer.pos().relative((Direction) pointer.state().getValue(DispenserBlock.FACING));
|
||||
BlockState iblockdata = worldserver.getBlockState(blockposition);
|
||||
@@ -526,7 +544,7 @@
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
@@ -573,8 +591,8 @@
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != EquipmentDispenseItemBehavior.INSTANCE) {
|
||||
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { // Paper - fix possible StackOverflowError
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
+ }
|
||||
|
||||
@@ -14,7 +14,25 @@
|
||||
|
||||
public class EquipmentDispenseItemBehavior extends DefaultDispenseItemBehavior {
|
||||
|
||||
@@ -34,7 +39,34 @@
|
||||
@@ -18,10 +23,15 @@
|
||||
|
||||
@Override
|
||||
protected ItemStack execute(BlockSource pointer, ItemStack stack) {
|
||||
- return EquipmentDispenseItemBehavior.dispenseEquipment(pointer, stack) ? stack : super.execute(pointer, stack);
|
||||
+ return EquipmentDispenseItemBehavior.dispenseEquipment(pointer, stack, this) ? stack : super.execute(pointer, stack); // Paper - fix possible StackOverflowError
|
||||
}
|
||||
|
||||
- public static boolean dispenseEquipment(BlockSource pointer, ItemStack stack) {
|
||||
+ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper
|
||||
+ public static boolean dispenseEquipment(BlockSource pointer, ItemStack armor) {
|
||||
+ // Paper start
|
||||
+ return dispenseEquipment(pointer, armor, null);
|
||||
+ }
|
||||
+ public static boolean dispenseEquipment(BlockSource pointer, ItemStack stack, @javax.annotation.Nullable DispenseItemBehavior currentBehavior) {
|
||||
BlockPos blockposition = pointer.pos().relative((Direction) pointer.state().getValue(DispenserBlock.FACING));
|
||||
List<LivingEntity> list = pointer.level().getEntitiesOfClass(LivingEntity.class, new AABB(blockposition), (entityliving) -> {
|
||||
return entityliving.canEquipWithDispenser(stack);
|
||||
@@ -34,7 +44,34 @@
|
||||
EquipmentSlot enumitemslot = entityliving.getEquipmentSlotForItem(stack);
|
||||
ItemStack itemstack1 = stack.split(1);
|
||||
|
||||
@@ -38,8 +56,8 @@
|
||||
+ stack.grow(1);
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != EquipmentDispenseItemBehavior.INSTANCE) {
|
||||
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && (currentBehavior == null || idispensebehavior != currentBehavior)) { // Paper - fix possible StackOverflowError
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return true;
|
||||
+ }
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
+ stack.grow(1);
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
+ stack.grow(1);
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
|
||||
Reference in New Issue
Block a user