--- a/net/minecraft/world/inventory/MerchantContainer.java
+++ b/net/minecraft/world/inventory/MerchantContainer.java
@@ -1,24 +1,76 @@
 package net.minecraft.world.inventory;
 
+import java.util.Iterator;
 import javax.annotation.Nullable;
 import net.minecraft.core.NonNullList;
 import net.minecraft.world.Container;
 import net.minecraft.world.ContainerHelper;
+import net.minecraft.world.entity.npc.AbstractVillager;
+import net.minecraft.world.entity.npc.Villager;
 import net.minecraft.world.entity.player.Player;
 import net.minecraft.world.item.ItemStack;
 import net.minecraft.world.item.trading.Merchant;
 import net.minecraft.world.item.trading.MerchantOffer;
 import net.minecraft.world.item.trading.MerchantOffers;
+// CraftBukkit start
+import java.util.List;
+import org.bukkit.Location;
+import org.bukkit.craftbukkit.entity.CraftHumanEntity;
+import org.bukkit.craftbukkit.entity.CraftAbstractVillager;
+import org.bukkit.entity.HumanEntity;
+// CraftBukkit end
 
 public class MerchantContainer implements Container {
+
     private final Merchant merchant;
-    private final NonNullList<ItemStack> itemStacks = NonNullList.withSize(3, ItemStack.EMPTY);
+    private final NonNullList<ItemStack> itemStacks;
     @Nullable
     private MerchantOffer activeOffer;
     public int selectionHint;
     private int futureXp;
 
+    // CraftBukkit start - add fields and methods
+    public List<HumanEntity> transaction = new java.util.ArrayList<HumanEntity>();
+    private int maxStack = MAX_STACK;
+
+    public List<ItemStack> getContents() {
+        return this.itemStacks;
+    }
+
+    public void onOpen(CraftHumanEntity who) {
+        this.transaction.add(who);
+    }
+
+    public void onClose(CraftHumanEntity who) {
+        this.transaction.remove(who);
+        this.merchant.setTradingPlayer((Player) null); // SPIGOT-4860
+    }
+
+    public List<HumanEntity> getViewers() {
+        return this.transaction;
+    }
+
+    @Override
+    public int getMaxStackSize() {
+        return this.maxStack;
+    }
+
+    public void setMaxStackSize(int i) {
+        this.maxStack = i;
+    }
+
+    public org.bukkit.inventory.InventoryHolder getOwner() {
+        return (this.merchant instanceof AbstractVillager) ? (CraftAbstractVillager) ((AbstractVillager) this.merchant).getBukkitEntity() : null;
+    }
+
+    @Override
+    public Location getLocation() {
+        return (this.merchant instanceof AbstractVillager) ? ((AbstractVillager) this.merchant).getBukkitEntity().getLocation() : null; // Paper - Fix inventories returning null Locations
+    }
+    // CraftBukkit end
+
     public MerchantContainer(Merchant merchant) {
+        this.itemStacks = NonNullList.withSize(3, ItemStack.EMPTY);
         this.merchant = merchant;
     }
 
@@ -29,32 +81,40 @@
 
     @Override
     public boolean isEmpty() {
-        for (ItemStack itemStack : this.itemStacks) {
-            if (!itemStack.isEmpty()) {
-                return false;
+        Iterator iterator = this.itemStacks.iterator();
+
+        ItemStack itemstack;
+
+        do {
+            if (!iterator.hasNext()) {
+                return true;
             }
-        }
 
-        return true;
+            itemstack = (ItemStack) iterator.next();
+        } while (itemstack.isEmpty());
+
+        return false;
     }
 
     @Override
     public ItemStack getItem(int slot) {
-        return this.itemStacks.get(slot);
+        return (ItemStack) this.itemStacks.get(slot);
     }
 
     @Override
     public ItemStack removeItem(int slot, int amount) {
-        ItemStack itemStack = this.itemStacks.get(slot);
-        if (slot == 2 && !itemStack.isEmpty()) {
-            return ContainerHelper.removeItem(this.itemStacks, slot, itemStack.getCount());
+        ItemStack itemstack = (ItemStack) this.itemStacks.get(slot);
+
+        if (slot == 2 && !itemstack.isEmpty()) {
+            return ContainerHelper.removeItem(this.itemStacks, slot, itemstack.getCount());
         } else {
-            ItemStack itemStack2 = ContainerHelper.removeItem(this.itemStacks, slot, amount);
-            if (!itemStack2.isEmpty() && this.isPaymentSlot(slot)) {
+            ItemStack itemstack1 = ContainerHelper.removeItem(this.itemStacks, slot, amount);
+
+            if (!itemstack1.isEmpty() && this.isPaymentSlot(slot)) {
                 this.updateSellItem();
             }
 
-            return itemStack2;
+            return itemstack1;
         }
     }
 
@@ -74,6 +134,7 @@
         if (this.isPaymentSlot(slot)) {
             this.updateSellItem();
         }
+
     }
 
     @Override
@@ -88,32 +149,35 @@
 
     public void updateSellItem() {
         this.activeOffer = null;
-        ItemStack itemStack;
-        ItemStack itemStack2;
-        if (this.itemStacks.get(0).isEmpty()) {
-            itemStack = this.itemStacks.get(1);
-            itemStack2 = ItemStack.EMPTY;
+        ItemStack itemstack;
+        ItemStack itemstack1;
+
+        if (((ItemStack) this.itemStacks.get(0)).isEmpty()) {
+            itemstack = (ItemStack) this.itemStacks.get(1);
+            itemstack1 = ItemStack.EMPTY;
         } else {
-            itemStack = this.itemStacks.get(0);
-            itemStack2 = this.itemStacks.get(1);
+            itemstack = (ItemStack) this.itemStacks.get(0);
+            itemstack1 = (ItemStack) this.itemStacks.get(1);
         }
 
-        if (itemStack.isEmpty()) {
+        if (itemstack.isEmpty()) {
             this.setItem(2, ItemStack.EMPTY);
             this.futureXp = 0;
         } else {
-            MerchantOffers merchantOffers = this.merchant.getOffers();
-            if (!merchantOffers.isEmpty()) {
-                MerchantOffer merchantOffer = merchantOffers.getRecipeFor(itemStack, itemStack2, this.selectionHint);
-                if (merchantOffer == null || merchantOffer.isOutOfStock()) {
-                    this.activeOffer = merchantOffer;
-                    merchantOffer = merchantOffers.getRecipeFor(itemStack2, itemStack, this.selectionHint);
+            MerchantOffers merchantrecipelist = this.merchant.getOffers();
+
+            if (!merchantrecipelist.isEmpty()) {
+                MerchantOffer merchantrecipe = merchantrecipelist.getRecipeFor(itemstack, itemstack1, this.selectionHint);
+
+                if (merchantrecipe == null || merchantrecipe.isOutOfStock()) {
+                    this.activeOffer = merchantrecipe;
+                    merchantrecipe = merchantrecipelist.getRecipeFor(itemstack1, itemstack, this.selectionHint);
                 }
 
-                if (merchantOffer != null && !merchantOffer.isOutOfStock()) {
-                    this.activeOffer = merchantOffer;
-                    this.setItem(2, merchantOffer.assemble());
-                    this.futureXp = merchantOffer.getXp();
+                if (merchantrecipe != null && !merchantrecipe.isOutOfStock()) {
+                    this.activeOffer = merchantrecipe;
+                    this.setItem(2, merchantrecipe.assemble());
+                    this.futureXp = merchantrecipe.getXp();
                 } else {
                     this.setItem(2, ItemStack.EMPTY);
                     this.futureXp = 0;
