package net.minecraft.inventory; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.MathHelper; public abstract class Container { /** the list of all items(stacks) for the corresponding slot */ public List inventoryItemStacks = Lists.newArrayList(); /** the list of all slots in the inventory */ public List inventorySlots = Lists.newArrayList(); public int windowId; /** * The current drag mode (0 : evenly split, 1 : one item by slot, 2 : not used ?) */ private int dragMode = -1; /** The current drag event (0 : start, 1 : add slot : 2 : end) */ private int dragEvent; /** The list of slots where the itemstack holds will be distributed */ private final Set dragSlots = Sets.newHashSet(); /** * list of all people that need to be notified when this craftinventory changes */ protected List crafters = Lists.newArrayList(); private Set playerList = Sets.newHashSet(); private static final String __OBFID = "CL_00001730"; /** * Adds an item slot to this container */ protected Slot addSlotToContainer(Slot p_75146_1_) { p_75146_1_.slotNumber = this.inventorySlots.size(); this.inventorySlots.add(p_75146_1_); this.inventoryItemStacks.add((Object)null); return p_75146_1_; } public void onCraftGuiOpened(ICrafting p_75132_1_) { if (this.crafters.contains(p_75132_1_)) { throw new IllegalArgumentException("Listener already listening"); } else { this.crafters.add(p_75132_1_); p_75132_1_.updateCraftingInventory(this, this.getInventory()); this.detectAndSendChanges(); } } /** * returns a list if itemStacks, for each slot. */ public List getInventory() { ArrayList var1 = Lists.newArrayList(); for (int var2 = 0; var2 < this.inventorySlots.size(); ++var2) { var1.add(((Slot)this.inventorySlots.get(var2)).getStack()); } return var1; } /** * Looks for changes made in the container, sends them to every listener. */ public void detectAndSendChanges() { for (int var1 = 0; var1 < this.inventorySlots.size(); ++var1) { ItemStack var2 = ((Slot)this.inventorySlots.get(var1)).getStack(); ItemStack var3 = (ItemStack)this.inventoryItemStacks.get(var1); if (!ItemStack.areItemStacksEqual(var3, var2)) { var3 = var2 == null ? null : var2.copy(); this.inventoryItemStacks.set(var1, var3); for (int var4 = 0; var4 < this.crafters.size(); ++var4) { ((ICrafting)this.crafters.get(var4)).sendSlotContents(this, var1, var3); } } } } /** * enchants the item on the table using the specified slot; also deducts XP from player */ public boolean enchantItem(EntityPlayer playerIn, int id) { return false; } public Slot getSlotFromInventory(IInventory p_75147_1_, int p_75147_2_) { for (int var3 = 0; var3 < this.inventorySlots.size(); ++var3) { Slot var4 = (Slot)this.inventorySlots.get(var3); if (var4.isHere(p_75147_1_, p_75147_2_)) { return var4; } } return null; } public Slot getSlot(int p_75139_1_) { return (Slot)this.inventorySlots.get(p_75139_1_); } /** * Take a stack from the specified inventory slot. */ public ItemStack transferStackInSlot(EntityPlayer playerIn, int index) { Slot var3 = (Slot)this.inventorySlots.get(index); return var3 != null ? var3.getStack() : null; } /** * Handles slot click. Args : slotId, clickedButton, mode (0 = basic click, 1 = shift click, 2 = Hotbar, 3 = * pickBlock, 4 = Drop, 5 = ?, 6 = Double click), player */ public ItemStack slotClick(int slotId, int clickedButton, int mode, EntityPlayer playerIn) { ItemStack var5 = null; InventoryPlayer var6 = playerIn.inventory; int var9; ItemStack var17; if (mode == 5) { int var7 = this.dragEvent; this.dragEvent = getDragEvent(clickedButton); if ((var7 != 1 || this.dragEvent != 2) && var7 != this.dragEvent) { this.resetDrag(); } else if (var6.getItemStack() == null) { this.resetDrag(); } else if (this.dragEvent == 0) { this.dragMode = extractDragMode(clickedButton); if (func_180610_a(this.dragMode, playerIn)) { this.dragEvent = 1; this.dragSlots.clear(); } else { this.resetDrag(); } } else if (this.dragEvent == 1) { Slot var8 = (Slot)this.inventorySlots.get(slotId); if (var8 != null && canAddItemToSlot(var8, var6.getItemStack(), true) && var8.isItemValid(var6.getItemStack()) && var6.getItemStack().stackSize > this.dragSlots.size() && this.canDragIntoSlot(var8)) { this.dragSlots.add(var8); } } else if (this.dragEvent == 2) { if (!this.dragSlots.isEmpty()) { var17 = var6.getItemStack().copy(); var9 = var6.getItemStack().stackSize; Iterator var10 = this.dragSlots.iterator(); while (var10.hasNext()) { Slot var11 = (Slot)var10.next(); if (var11 != null && canAddItemToSlot(var11, var6.getItemStack(), true) && var11.isItemValid(var6.getItemStack()) && var6.getItemStack().stackSize >= this.dragSlots.size() && this.canDragIntoSlot(var11)) { ItemStack var12 = var17.copy(); int var13 = var11.getHasStack() ? var11.getStack().stackSize : 0; computeStackSize(this.dragSlots, this.dragMode, var12, var13); if (var12.stackSize > var12.getMaxStackSize()) { var12.stackSize = var12.getMaxStackSize(); } if (var12.stackSize > var11.func_178170_b(var12)) { var12.stackSize = var11.func_178170_b(var12); } var9 -= var12.stackSize - var13; var11.putStack(var12); } } var17.stackSize = var9; if (var17.stackSize <= 0) { var17 = null; } var6.setItemStack(var17); } this.resetDrag(); } else { this.resetDrag(); } } else if (this.dragEvent != 0) { this.resetDrag(); } else { Slot var16; int var21; ItemStack var23; if ((mode == 0 || mode == 1) && (clickedButton == 0 || clickedButton == 1)) { if (slotId == -999) { if (var6.getItemStack() != null) { if (clickedButton == 0) { playerIn.dropPlayerItemWithRandomChoice(var6.getItemStack(), true); var6.setItemStack((ItemStack)null); } if (clickedButton == 1) { playerIn.dropPlayerItemWithRandomChoice(var6.getItemStack().splitStack(1), true); if (var6.getItemStack().stackSize == 0) { var6.setItemStack((ItemStack)null); } } } } else if (mode == 1) { if (slotId < 0) { return null; } var16 = (Slot)this.inventorySlots.get(slotId); if (var16 != null && var16.canTakeStack(playerIn)) { var17 = this.transferStackInSlot(playerIn, slotId); if (var17 != null) { Item var19 = var17.getItem(); var5 = var17.copy(); if (var16.getStack() != null && var16.getStack().getItem() == var19) { this.retrySlotClick(slotId, clickedButton, true, playerIn); } } } } else { if (slotId < 0) { return null; } var16 = (Slot)this.inventorySlots.get(slotId); if (var16 != null) { var17 = var16.getStack(); ItemStack var20 = var6.getItemStack(); if (var17 != null) { var5 = var17.copy(); } if (var17 == null) { if (var20 != null && var16.isItemValid(var20)) { var21 = clickedButton == 0 ? var20.stackSize : 1; if (var21 > var16.func_178170_b(var20)) { var21 = var16.func_178170_b(var20); } if (var20.stackSize >= var21) { var16.putStack(var20.splitStack(var21)); } if (var20.stackSize == 0) { var6.setItemStack((ItemStack)null); } } } else if (var16.canTakeStack(playerIn)) { if (var20 == null) { var21 = clickedButton == 0 ? var17.stackSize : (var17.stackSize + 1) / 2; var23 = var16.decrStackSize(var21); var6.setItemStack(var23); if (var17.stackSize == 0) { var16.putStack((ItemStack)null); } var16.onPickupFromSlot(playerIn, var6.getItemStack()); } else if (var16.isItemValid(var20)) { if (var17.getItem() == var20.getItem() && var17.getMetadata() == var20.getMetadata() && ItemStack.areItemStackTagsEqual(var17, var20)) { var21 = clickedButton == 0 ? var20.stackSize : 1; if (var21 > var16.func_178170_b(var20) - var17.stackSize) { var21 = var16.func_178170_b(var20) - var17.stackSize; } if (var21 > var20.getMaxStackSize() - var17.stackSize) { var21 = var20.getMaxStackSize() - var17.stackSize; } var20.splitStack(var21); if (var20.stackSize == 0) { var6.setItemStack((ItemStack)null); } var17.stackSize += var21; } else if (var20.stackSize <= var16.func_178170_b(var20)) { var16.putStack(var20); var6.setItemStack(var17); } } else if (var17.getItem() == var20.getItem() && var20.getMaxStackSize() > 1 && (!var17.getHasSubtypes() || var17.getMetadata() == var20.getMetadata()) && ItemStack.areItemStackTagsEqual(var17, var20)) { var21 = var17.stackSize; if (var21 > 0 && var21 + var20.stackSize <= var20.getMaxStackSize()) { var20.stackSize += var21; var17 = var16.decrStackSize(var21); if (var17.stackSize == 0) { var16.putStack((ItemStack)null); } var16.onPickupFromSlot(playerIn, var6.getItemStack()); } } } var16.onSlotChanged(); } } } else if (mode == 2 && clickedButton >= 0 && clickedButton < 9) { var16 = (Slot)this.inventorySlots.get(slotId); if (var16.canTakeStack(playerIn)) { var17 = var6.getStackInSlot(clickedButton); boolean var18 = var17 == null || var16.inventory == var6 && var16.isItemValid(var17); var21 = -1; if (!var18) { var21 = var6.getFirstEmptyStack(); var18 |= var21 > -1; } if (var16.getHasStack() && var18) { var23 = var16.getStack(); var6.setInventorySlotContents(clickedButton, var23.copy()); if ((var16.inventory != var6 || !var16.isItemValid(var17)) && var17 != null) { if (var21 > -1) { var6.addItemStackToInventory(var17); var16.decrStackSize(var23.stackSize); var16.putStack((ItemStack)null); var16.onPickupFromSlot(playerIn, var23); } } else { var16.decrStackSize(var23.stackSize); var16.putStack(var17); var16.onPickupFromSlot(playerIn, var23); } } else if (!var16.getHasStack() && var17 != null && var16.isItemValid(var17)) { var6.setInventorySlotContents(clickedButton, (ItemStack)null); var16.putStack(var17); } } } else if (mode == 3 && playerIn.capabilities.isCreativeMode && var6.getItemStack() == null && slotId >= 0) { var16 = (Slot)this.inventorySlots.get(slotId); if (var16 != null && var16.getHasStack()) { var17 = var16.getStack().copy(); var17.stackSize = var17.getMaxStackSize(); var6.setItemStack(var17); } } else if (mode == 4 && var6.getItemStack() == null && slotId >= 0) { var16 = (Slot)this.inventorySlots.get(slotId); if (var16 != null && var16.getHasStack() && var16.canTakeStack(playerIn)) { var17 = var16.decrStackSize(clickedButton == 0 ? 1 : var16.getStack().stackSize); var16.onPickupFromSlot(playerIn, var17); playerIn.dropPlayerItemWithRandomChoice(var17, true); } } else if (mode == 6 && slotId >= 0) { var16 = (Slot)this.inventorySlots.get(slotId); var17 = var6.getItemStack(); if (var17 != null && (var16 == null || !var16.getHasStack() || !var16.canTakeStack(playerIn))) { var9 = clickedButton == 0 ? 0 : this.inventorySlots.size() - 1; var21 = clickedButton == 0 ? 1 : -1; for (int var22 = 0; var22 < 2; ++var22) { for (int var24 = var9; var24 >= 0 && var24 < this.inventorySlots.size() && var17.stackSize < var17.getMaxStackSize(); var24 += var21) { Slot var25 = (Slot)this.inventorySlots.get(var24); if (var25.getHasStack() && canAddItemToSlot(var25, var17, true) && var25.canTakeStack(playerIn) && this.func_94530_a(var17, var25) && (var22 != 0 || var25.getStack().stackSize != var25.getStack().getMaxStackSize())) { int var14 = Math.min(var17.getMaxStackSize() - var17.stackSize, var25.getStack().stackSize); ItemStack var15 = var25.decrStackSize(var14); var17.stackSize += var14; if (var15.stackSize <= 0) { var25.putStack((ItemStack)null); } var25.onPickupFromSlot(playerIn, var15); } } } } this.detectAndSendChanges(); } } return var5; } public boolean func_94530_a(ItemStack p_94530_1_, Slot p_94530_2_) { return true; } protected void retrySlotClick(int p_75133_1_, int p_75133_2_, boolean p_75133_3_, EntityPlayer p_75133_4_) { this.slotClick(p_75133_1_, p_75133_2_, 1, p_75133_4_); } /** * Called when the container is closed. */ public void onContainerClosed(EntityPlayer p_75134_1_) { InventoryPlayer var2 = p_75134_1_.inventory; if (var2.getItemStack() != null) { p_75134_1_.dropPlayerItemWithRandomChoice(var2.getItemStack(), false); var2.setItemStack((ItemStack)null); } } /** * Callback for when the crafting matrix is changed. */ public void onCraftMatrixChanged(IInventory p_75130_1_) { this.detectAndSendChanges(); } /** * args: slotID, itemStack to put in slot */ public void putStackInSlot(int p_75141_1_, ItemStack p_75141_2_) { this.getSlot(p_75141_1_).putStack(p_75141_2_); } /** * gets whether or not the player can craft in this inventory or not */ public boolean getCanCraft(EntityPlayer p_75129_1_) { return !this.playerList.contains(p_75129_1_); } /** * sets whether the player can craft in this inventory or not */ public void setCanCraft(EntityPlayer p_75128_1_, boolean p_75128_2_) { if (p_75128_2_) { this.playerList.remove(p_75128_1_); } else { this.playerList.add(p_75128_1_); } } public abstract boolean canInteractWith(EntityPlayer playerIn); /** * Merges provided ItemStack with the first avaliable one in the container/player inventor between minIndex * (included) and maxIndex (excluded). Args : stack, minIndex, maxIndex, negativDirection. /!\ the Container * implementation do not check if the item is valid for the slot */ protected boolean mergeItemStack(ItemStack stack, int startIndex, int endIndex, boolean useEndIndex) { boolean var5 = false; int var6 = startIndex; if (useEndIndex) { var6 = endIndex - 1; } Slot var7; ItemStack var8; if (stack.isStackable()) { while (stack.stackSize > 0 && (!useEndIndex && var6 < endIndex || useEndIndex && var6 >= startIndex)) { var7 = (Slot)this.inventorySlots.get(var6); var8 = var7.getStack(); if (var8 != null && var8.getItem() == stack.getItem() && (!stack.getHasSubtypes() || stack.getMetadata() == var8.getMetadata()) && ItemStack.areItemStackTagsEqual(stack, var8)) { int var9 = var8.stackSize + stack.stackSize; if (var9 <= stack.getMaxStackSize()) { stack.stackSize = 0; var8.stackSize = var9; var7.onSlotChanged(); var5 = true; } else if (var8.stackSize < stack.getMaxStackSize()) { stack.stackSize -= stack.getMaxStackSize() - var8.stackSize; var8.stackSize = stack.getMaxStackSize(); var7.onSlotChanged(); var5 = true; } } if (useEndIndex) { --var6; } else { ++var6; } } } if (stack.stackSize > 0) { if (useEndIndex) { var6 = endIndex - 1; } else { var6 = startIndex; } while (!useEndIndex && var6 < endIndex || useEndIndex && var6 >= startIndex) { var7 = (Slot)this.inventorySlots.get(var6); var8 = var7.getStack(); if (var8 == null) { var7.putStack(stack.copy()); var7.onSlotChanged(); stack.stackSize = 0; var5 = true; break; } if (useEndIndex) { --var6; } else { ++var6; } } } return var5; } /** * Extracts the drag mode. Args : eventButton. Return (0 : evenly split, 1 : one item by slot, 2 : not used ?) */ public static int extractDragMode(int p_94529_0_) { return p_94529_0_ >> 2 & 3; } /** * Args : clickedButton, Returns (0 : start drag, 1 : add slot, 2 : end drag) */ public static int getDragEvent(int p_94532_0_) { return p_94532_0_ & 3; } public static boolean func_180610_a(int p_180610_0_, EntityPlayer p_180610_1_) { return p_180610_0_ == 0 ? true : (p_180610_0_ == 1 ? true : p_180610_0_ == 2 && p_180610_1_.capabilities.isCreativeMode); } /** * Reset the drag fields */ protected void resetDrag() { this.dragEvent = 0; this.dragSlots.clear(); } /** * Checks if it's possible to add the given itemstack to the given slot. */ public static boolean canAddItemToSlot(Slot slotIn, ItemStack stack, boolean stackSizeMatters) { boolean var3 = slotIn == null || !slotIn.getHasStack(); if (slotIn != null && slotIn.getHasStack() && stack != null && stack.isItemEqual(slotIn.getStack()) && ItemStack.areItemStackTagsEqual(slotIn.getStack(), stack)) { int var10002 = stackSizeMatters ? 0 : stack.stackSize; var3 |= slotIn.getStack().stackSize + var10002 <= stack.getMaxStackSize(); } return var3; } /** * Compute the new stack size, Returns the stack with the new size. Args : dragSlots, dragMode, dragStack, * slotStackSize */ public static void computeStackSize(Set p_94525_0_, int p_94525_1_, ItemStack p_94525_2_, int p_94525_3_) { switch (p_94525_1_) { case 0: p_94525_2_.stackSize = MathHelper.floor_float((float)p_94525_2_.stackSize / (float)p_94525_0_.size()); break; case 1: p_94525_2_.stackSize = 1; break; case 2: p_94525_2_.stackSize = p_94525_2_.getItem().getItemStackLimit(); } p_94525_2_.stackSize += p_94525_3_; } /** * Returns true if the player can "drag-spilt" items into this slot,. returns true by default. Called to check if * the slot can be added to a list of Slots to split the held ItemStack across. */ public boolean canDragIntoSlot(Slot p_94531_1_) { return true; } /** * Like the version that takes an inventory. If the given TileEntity is not an Inventory, 0 is returned instead. */ public static int calcRedstoneFromInventory(TileEntity te) { return te instanceof IInventory ? calcRedstoneFromInventory((IInventory)te) : 0; } public static int calcRedstoneFromInventory(IInventory inv) { if (inv == null) { return 0; } else { int var1 = 0; float var2 = 0.0F; for (int var3 = 0; var3 < inv.getSizeInventory(); ++var3) { ItemStack var4 = inv.getStackInSlot(var3); if (var4 != null) { var2 += (float)var4.stackSize / (float)Math.min(inv.getInventoryStackLimit(), var4.getMaxStackSize()); ++var1; } } var2 /= (float)inv.getSizeInventory(); return MathHelper.floor_float(var2 * 14.0F) + (var1 > 0 ? 1 : 0); } } }