--- a/net/minecraft/world/inventory/ItemCombinerMenu.java
+++ b/net/minecraft/world/inventory/ItemCombinerMenu.java
@@ -1,5 +1,6 @@
 package net.minecraft.world.inventory;
 
+import java.util.Iterator;
 import java.util.List;
 import javax.annotation.Nullable;
 import net.minecraft.world.Container;
@@ -10,13 +11,14 @@
 import net.minecraft.world.level.block.state.BlockState;
 
 public abstract class ItemCombinerMenu extends AbstractContainerMenu {
+
     private static final int INVENTORY_SLOTS_PER_ROW = 9;
     private static final int INVENTORY_SLOTS_PER_COLUMN = 3;
     protected final ContainerLevelAccess access;
     protected final Player player;
     protected final Container inputSlots;
     private final List<Integer> inputSlotIndexes;
-    protected final ResultContainer resultSlots = new ResultContainer();
+    protected final ResultContainer resultSlots; // Paper - delay field init
     private final int resultSlotIndex;
 
     protected abstract boolean mayPickup(Player player, boolean present);
@@ -28,22 +30,28 @@
     public ItemCombinerMenu(@Nullable MenuType<?> type, int syncId, Inventory playerInventory, ContainerLevelAccess context) {
         super(type, syncId);
         this.access = context;
+        this.resultSlots = new ResultContainer(this.createBlockHolder(this.access)); // Paper - delay field init
         this.player = playerInventory.player;
-        ItemCombinerMenuSlotDefinition itemCombinerMenuSlotDefinition = this.createInputSlotDefinitions();
-        this.inputSlots = this.createContainer(itemCombinerMenuSlotDefinition.getNumOfInputSlots());
-        this.inputSlotIndexes = itemCombinerMenuSlotDefinition.getInputSlotIndexes();
-        this.resultSlotIndex = itemCombinerMenuSlotDefinition.getResultSlotIndex();
-        this.createInputSlots(itemCombinerMenuSlotDefinition);
-        this.createResultSlot(itemCombinerMenuSlotDefinition);
+        ItemCombinerMenuSlotDefinition itemcombinermenuslotdefinition = this.createInputSlotDefinitions();
+
+        this.inputSlots = this.createContainer(itemcombinermenuslotdefinition.getNumOfInputSlots());
+        this.inputSlotIndexes = itemcombinermenuslotdefinition.getInputSlotIndexes();
+        this.resultSlotIndex = itemcombinermenuslotdefinition.getResultSlotIndex();
+        this.createInputSlots(itemcombinermenuslotdefinition);
+        this.createResultSlot(itemcombinermenuslotdefinition);
         this.createInventorySlots(playerInventory);
     }
 
     private void createInputSlots(ItemCombinerMenuSlotDefinition forgingSlotsManager) {
-        for(final ItemCombinerMenuSlotDefinition.SlotDefinition slotDefinition : forgingSlotsManager.getSlots()) {
-            this.addSlot(new Slot(this.inputSlots, slotDefinition.slotIndex(), slotDefinition.x(), slotDefinition.y()) {
+        Iterator iterator = forgingSlotsManager.getSlots().iterator();
+
+        while (iterator.hasNext()) {
+            final ItemCombinerMenuSlotDefinition.SlotDefinition itemcombinermenuslotdefinition_b = (ItemCombinerMenuSlotDefinition.SlotDefinition) iterator.next();
+
+            this.addSlot(new Slot(this.inputSlots, itemcombinermenuslotdefinition_b.slotIndex(), itemcombinermenuslotdefinition_b.x(), itemcombinermenuslotdefinition_b.y()) {
                 @Override
                 public boolean mayPlace(ItemStack stack) {
-                    return slotDefinition.mayPlace().test(stack);
+                    return itemcombinermenuslotdefinition_b.mayPlace().test(stack);
                 }
             });
         }
@@ -70,14 +78,16 @@
     }
 
     private void createInventorySlots(Inventory playerInventory) {
-        for(int i = 0; i < 3; ++i) {
-            for(int j = 0; j < 9; ++j) {
+        int i;
+
+        for (i = 0; i < 3; ++i) {
+            for (int j = 0; j < 9; ++j) {
                 this.addSlot(new Slot(playerInventory, j + i * 9 + 9, 8 + j * 18, 84 + i * 18));
             }
         }
 
-        for(int k = 0; k < 9; ++k) {
-            this.addSlot(new Slot(playerInventory, k, 8 + k * 18, 142));
+        for (i = 0; i < 9; ++i) {
+            this.addSlot(new Slot(playerInventory, i, 8 + i * 18, 142));
         }
 
     }
@@ -87,7 +97,7 @@
     protected abstract ItemCombinerMenuSlotDefinition createInputSlotDefinitions();
 
     private SimpleContainer createContainer(int size) {
-        return new SimpleContainer(size) {
+        return new SimpleContainer(this.createBlockHolder(this.access), size) { // Paper
             @Override
             public void setChanged() {
                 super.setChanged();
@@ -101,6 +111,7 @@
         super.slotsChanged(inventory);
         if (inventory == this.inputSlots) {
             this.createResult();
+            org.bukkit.craftbukkit.v1_20_R2.event.CraftEventFactory.callPrepareResultEvent(this, this instanceof SmithingMenu ? 3 : 2); // Paper
         }
 
     }
@@ -108,64 +119,69 @@
     @Override
     public void removed(Player player) {
         super.removed(player);
-        this.access.execute((world, pos) -> {
+        this.access.execute((world, blockposition) -> {
             this.clearContainer(player, this.inputSlots);
         });
     }
 
     @Override
     public boolean stillValid(Player player) {
-        return this.access.evaluate((world, pos) -> {
-            return !this.isValidBlock(world.getBlockState(pos)) ? false : player.distanceToSqr((double)pos.getX() + 0.5D, (double)pos.getY() + 0.5D, (double)pos.getZ() + 0.5D) <= 64.0D;
+        if (!this.checkReachable) return true; // CraftBukkit
+        return (Boolean) this.access.evaluate((world, blockposition) -> {
+            return !this.isValidBlock(world.getBlockState(blockposition)) ? false : player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) <= 64.0D;
         }, true);
     }
 
     @Override
     public ItemStack quickMoveStack(Player player, int slot) {
-        ItemStack itemStack = ItemStack.EMPTY;
-        Slot slot2 = this.slots.get(slot);
-        if (slot2 != null && slot2.hasItem()) {
-            ItemStack itemStack2 = slot2.getItem();
-            itemStack = itemStack2.copy();
-            int i = this.getInventorySlotStart();
-            int j = this.getUseRowEnd();
+        ItemStack itemstack = ItemStack.EMPTY;
+        Slot slot1 = (Slot) this.slots.get(slot);
+
+        if (slot1 != null && slot1.hasItem()) {
+            ItemStack itemstack1 = slot1.getItem();
+
+            itemstack = itemstack1.copy();
+            int j = this.getInventorySlotStart();
+            int k = this.getUseRowEnd();
+
             if (slot == this.getResultSlot()) {
-                if (!this.moveItemStackTo(itemStack2, i, j, true)) {
+                if (!this.moveItemStackTo(itemstack1, j, k, true)) {
                     return ItemStack.EMPTY;
                 }
 
-                slot2.onQuickCraft(itemStack2, itemStack);
+                slot1.onQuickCraft(itemstack1, itemstack);
             } else if (this.inputSlotIndexes.contains(slot)) {
-                if (!this.moveItemStackTo(itemStack2, i, j, false)) {
+                if (!this.moveItemStackTo(itemstack1, j, k, false)) {
                     return ItemStack.EMPTY;
                 }
-            } else if (this.canMoveIntoInputSlots(itemStack2) && slot >= this.getInventorySlotStart() && slot < this.getUseRowEnd()) {
-                int k = this.getSlotToQuickMoveTo(itemStack);
-                if (!this.moveItemStackTo(itemStack2, k, this.getResultSlot(), false)) {
+            } else if (this.canMoveIntoInputSlots(itemstack1) && slot >= this.getInventorySlotStart() && slot < this.getUseRowEnd()) {
+                int l = this.getSlotToQuickMoveTo(itemstack);
+
+                if (!this.moveItemStackTo(itemstack1, l, this.getResultSlot(), false)) {
                     return ItemStack.EMPTY;
                 }
             } else if (slot >= this.getInventorySlotStart() && slot < this.getInventorySlotEnd()) {
-                if (!this.moveItemStackTo(itemStack2, this.getUseRowStart(), this.getUseRowEnd(), false)) {
+                if (!this.moveItemStackTo(itemstack1, this.getUseRowStart(), this.getUseRowEnd(), false)) {
                     return ItemStack.EMPTY;
                 }
-            } else if (slot >= this.getUseRowStart() && slot < this.getUseRowEnd() && !this.moveItemStackTo(itemStack2, this.getInventorySlotStart(), this.getInventorySlotEnd(), false)) {
+            } else if (slot >= this.getUseRowStart() && slot < this.getUseRowEnd() && !this.moveItemStackTo(itemstack1, this.getInventorySlotStart(), this.getInventorySlotEnd(), false)) {
                 return ItemStack.EMPTY;
             }
 
-            if (itemStack2.isEmpty()) {
-                slot2.setByPlayer(ItemStack.EMPTY);
+            if (itemstack1.isEmpty()) {
+                slot1.setByPlayer(ItemStack.EMPTY);
             } else {
-                slot2.setChanged();
+                slot1.setChanged();
             }
 
-            if (itemStack2.getCount() == itemStack.getCount()) {
+            if (itemstack1.getCount() == itemstack.getCount()) {
                 return ItemStack.EMPTY;
             }
 
-            slot2.onTake(player, itemStack2);
+            slot1.onTake(player, itemstack1);
         }
 
-        return itemStack;
+        return itemstack;
     }
 
     protected boolean canMoveIntoInputSlots(ItemStack stack) {
@@ -173,7 +189,7 @@
     }
 
     public int getSlotToQuickMoveTo(ItemStack stack) {
-        return this.inputSlots.isEmpty() ? 0 : this.inputSlotIndexes.get(0);
+        return this.inputSlots.isEmpty() ? 0 : (Integer) this.inputSlotIndexes.get(0);
     }
 
     public int getResultSlot() {
