mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-29 12:27:59 +01:00
Fix NPE and StackOverflowError for dispensers
This commit is contained in:
parent
eb6f344912
commit
b501e56e80
@ -0,0 +1,309 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||||
|
Date: Sat, 29 Oct 2022 17:02:42 -0700
|
||||||
|
Subject: [PATCH] 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.
|
||||||
|
|
||||||
|
== AT ==
|
||||||
|
public net.minecraft.world.level.block.DispenserBlock getDispenseMethod(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;)Lnet/minecraft/core/dispenser/DispenseItemBehavior;
|
||||||
|
|
||||||
|
diff --git a/src/main/java/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java
|
||||||
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||||
|
--- a/src/main/java/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java
|
||||||
|
+++ b/src/main/java/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java
|
||||||
|
@@ -0,0 +0,0 @@ public class BoatDispenseItemBehavior extends DefaultDispenseItemBehavior {
|
||||||
|
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;
|
||||||
|
diff --git a/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java
|
||||||
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||||
|
--- a/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java
|
||||||
|
+++ b/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java
|
||||||
|
@@ -0,0 +0,0 @@ public class DefaultDispenseItemBehavior implements DispenseItemBehavior {
|
||||||
|
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 {
|
||||||
|
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 {
|
||||||
|
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;
|
||||||
|
@@ -0,0 +0,0 @@ public interface DispenseItemBehavior {
|
||||||
|
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;
|
||||||
|
@@ -0,0 +0,0 @@ public interface DispenseItemBehavior {
|
||||||
|
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 != EquipmentDispenseItemBehavior.INSTANCE && idispensebehavior != this) { // Paper - fix possible StackOverflowError
|
||||||
|
idispensebehavior.dispense(pointer, eventStack);
|
||||||
|
return stack;
|
||||||
|
}
|
||||||
|
@@ -0,0 +0,0 @@ public interface DispenseItemBehavior {
|
||||||
|
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 != EquipmentDispenseItemBehavior.INSTANCE && idispensebehavior != this) { // Paper - fix possible StackOverflowError
|
||||||
|
idispensebehavior.dispense(pointer, eventStack);
|
||||||
|
return stack;
|
||||||
|
}
|
||||||
|
@@ -0,0 +0,0 @@ public interface DispenseItemBehavior {
|
||||||
|
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;
|
||||||
|
@@ -0,0 +0,0 @@ public interface DispenseItemBehavior {
|
||||||
|
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;
|
||||||
|
@@ -0,0 +0,0 @@ public interface DispenseItemBehavior {
|
||||||
|
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;
|
||||||
|
@@ -0,0 +0,0 @@ public interface DispenseItemBehavior {
|
||||||
|
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;
|
||||||
|
@@ -0,0 +0,0 @@ public interface DispenseItemBehavior {
|
||||||
|
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;
|
||||||
|
@@ -0,0 +0,0 @@ public interface DispenseItemBehavior {
|
||||||
|
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;
|
||||||
|
@@ -0,0 +0,0 @@ public interface DispenseItemBehavior {
|
||||||
|
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;
|
||||||
|
@@ -0,0 +0,0 @@ public interface DispenseItemBehavior {
|
||||||
|
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;
|
||||||
|
@@ -0,0 +0,0 @@ public interface DispenseItemBehavior {
|
||||||
|
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;
|
||||||
|
@@ -0,0 +0,0 @@ public interface DispenseItemBehavior {
|
||||||
|
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;
|
||||||
|
@@ -0,0 +0,0 @@ public interface DispenseItemBehavior {
|
||||||
|
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 != EquipmentDispenseItemBehavior.INSTANCE && idispensebehavior != this) { // Paper - fix possible StackOverflowError
|
||||||
|
idispensebehavior.dispense(pointer, eventStack);
|
||||||
|
return stack;
|
||||||
|
}
|
||||||
|
diff --git a/src/main/java/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java
|
||||||
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||||
|
--- a/src/main/java/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java
|
||||||
|
+++ b/src/main/java/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java
|
||||||
|
@@ -0,0 +0,0 @@ public class EquipmentDispenseItemBehavior extends DefaultDispenseItemBehavior {
|
||||||
|
|
||||||
|
@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);
|
||||||
|
@@ -0,0 +0,0 @@ public class EquipmentDispenseItemBehavior extends DefaultDispenseItemBehavior {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
diff --git a/src/main/java/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java
|
||||||
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||||
|
--- a/src/main/java/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java
|
||||||
|
+++ b/src/main/java/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java
|
||||||
|
@@ -0,0 +0,0 @@ public class MinecartDispenseItemBehavior extends DefaultDispenseItemBehavior {
|
||||||
|
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;
|
||||||
|
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 {
|
||||||
|
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;
|
||||||
|
diff --git a/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java
|
||||||
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||||
|
--- a/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java
|
||||||
|
+++ b/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java
|
||||||
|
@@ -0,0 +0,0 @@ public class ShearsDispenseItemBehavior extends OptionalDispenseItemBehavior {
|
||||||
|
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;
|
||||||
|
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 {
|
||||||
|
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;
|
||||||
|
diff --git a/src/main/java/net/minecraft/world/level/block/DispenserBlock.java b/src/main/java/net/minecraft/world/level/block/DispenserBlock.java
|
||||||
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||||
|
--- a/src/main/java/net/minecraft/world/level/block/DispenserBlock.java
|
||||||
|
+++ b/src/main/java/net/minecraft/world/level/block/DispenserBlock.java
|
||||||
|
@@ -0,0 +0,0 @@ public class DispenserBlock extends BaseEntityBlock {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Paper start - Fix NPE with equippable and items without behavior
|
||||||
|
+ public static DispenseItemBehavior getDispenseBehavior(BlockSource pointer, ItemStack stack) {
|
||||||
|
+ return ((DispenserBlock) pointer.state().getBlock()).getDispenseMethod(pointer.level(), stack);
|
||||||
|
+ }
|
||||||
|
+ // Paper end - Fix NPE with equippable and items without behavior
|
||||||
|
+
|
||||||
|
public DispenseItemBehavior getDispenseMethod(Level world, ItemStack stack) {
|
||||||
|
if (!stack.isItemEnabled(world.enabledFeatures())) {
|
||||||
|
return DispenserBlock.DEFAULT_BEHAVIOR;
|
||||||
|
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||||
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||||
|
--- 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 {
|
||||||
|
if (!event.getItem().equals(craftItem)) {
|
||||||
|
// Chain to handler for new item
|
||||||
|
ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||||
|
- net.minecraft.core.dispenser.DispenseItemBehavior itemBehavior = net.minecraft.world.level.block.DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||||
|
+ net.minecraft.core.dispenser.DispenseItemBehavior itemBehavior = net.minecraft.world.level.block.DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||||
|
if (itemBehavior != net.minecraft.core.dispenser.DispenseItemBehavior.NOOP && itemBehavior != instance) {
|
||||||
|
itemBehavior.dispense(pointer, eventStack);
|
||||||
|
return itemStack;
|
@ -1,95 +0,0 @@
|
|||||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
|
||||||
Date: Sat, 29 Oct 2022 17:02:42 -0700
|
|
||||||
Subject: [PATCH] Fix possible StackOverflowError 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.
|
|
||||||
|
|
||||||
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 {
|
|
||||||
// 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) {
|
|
||||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != EquipmentDispenseItemBehavior.INSTANCE && idispensebehavior != this) { // Paper - fix possible StackOverflowError
|
|
||||||
idispensebehavior.dispense(pointer, eventStack);
|
|
||||||
return stack;
|
|
||||||
}
|
|
||||||
@@ -0,0 +0,0 @@ public interface DispenseItemBehavior {
|
|
||||||
// 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) {
|
|
||||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != EquipmentDispenseItemBehavior.INSTANCE && idispensebehavior != this) { // Paper - fix possible StackOverflowError
|
|
||||||
idispensebehavior.dispense(pointer, eventStack);
|
|
||||||
return stack;
|
|
||||||
}
|
|
||||||
@@ -0,0 +0,0 @@ public interface DispenseItemBehavior {
|
|
||||||
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;
|
|
||||||
@@ -0,0 +0,0 @@ public interface DispenseItemBehavior {
|
|
||||||
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;
|
|
||||||
@@ -0,0 +0,0 @@ public interface DispenseItemBehavior {
|
|
||||||
// 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) {
|
|
||||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != EquipmentDispenseItemBehavior.INSTANCE && idispensebehavior != this) { // Paper - fix possible StackOverflowError
|
|
||||||
idispensebehavior.dispense(pointer, eventStack);
|
|
||||||
return stack;
|
|
||||||
}
|
|
||||||
diff --git a/src/main/java/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java
|
|
||||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
|
||||||
--- a/src/main/java/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java
|
|
||||||
+++ b/src/main/java/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java
|
|
||||||
@@ -0,0 +0,0 @@ public class EquipmentDispenseItemBehavior extends DefaultDispenseItemBehavior {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ItemStack execute(BlockSource pointer, ItemStack stack) {
|
|
||||||
- return EquipmentDispenseItemBehavior.dispenseEquipment(pointer, stack) ? stack : super.execute(pointer, stack);
|
|
||||||
+ return EquipmentDispenseItemBehavior.dispenseEquipment(pointer, stack, null) ? 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);
|
|
||||||
@@ -0,0 +0,0 @@ public class EquipmentDispenseItemBehavior extends DefaultDispenseItemBehavior {
|
|
||||||
// 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) {
|
|
||||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && (currentBehavior == null || idispensebehavior != EquipmentDispenseItemBehavior.INSTANCE)) { // Paper - fix possible StackOverflowError
|
|
||||||
idispensebehavior.dispense(pointer, eventStack);
|
|
||||||
return true;
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user