001 package net.minecraft.inventory; 002 003 import cpw.mods.fml.common.Side; 004 import cpw.mods.fml.common.asm.SideOnly; 005 import java.util.ArrayList; 006 import java.util.HashSet; 007 import java.util.List; 008 import java.util.Set; 009 import net.minecraft.entity.player.EntityPlayer; 010 import net.minecraft.entity.player.InventoryPlayer; 011 import net.minecraft.item.ItemStack; 012 013 public abstract class Container 014 { 015 /** the list of all items(stacks) for the corresponding slot */ 016 public List inventoryItemStacks = new ArrayList(); 017 018 /** the list of all slots in the inventory */ 019 public List inventorySlots = new ArrayList(); 020 public int windowId = 0; 021 private short transactionID = 0; 022 023 /** 024 * list of all people that need to be notified when this craftinventory changes 025 */ 026 protected List crafters = new ArrayList(); 027 private Set playerList = new HashSet(); 028 029 /** 030 * the slot is assumed empty 031 */ 032 protected Slot addSlotToContainer(Slot par1Slot) 033 { 034 par1Slot.slotNumber = this.inventorySlots.size(); 035 this.inventorySlots.add(par1Slot); 036 this.inventoryItemStacks.add((Object)null); 037 return par1Slot; 038 } 039 040 public void addCraftingToCrafters(ICrafting par1ICrafting) 041 { 042 if (this.crafters.contains(par1ICrafting)) 043 { 044 throw new IllegalArgumentException("Listener already listening"); 045 } 046 else 047 { 048 this.crafters.add(par1ICrafting); 049 par1ICrafting.sendContainerAndContentsToPlayer(this, this.getInventory()); 050 this.updateCraftingResults(); 051 } 052 } 053 054 /** 055 * returns a list if itemStacks, for each slot. 056 */ 057 public List getInventory() 058 { 059 ArrayList var1 = new ArrayList(); 060 061 for (int var2 = 0; var2 < this.inventorySlots.size(); ++var2) 062 { 063 var1.add(((Slot)this.inventorySlots.get(var2)).getStack()); 064 } 065 066 return var1; 067 } 068 069 @SideOnly(Side.CLIENT) 070 071 /** 072 * Remove this crafting listener from the listener list. 073 */ 074 public void removeCraftingFromCrafters(ICrafting par1ICrafting) 075 { 076 this.crafters.remove(par1ICrafting); 077 } 078 079 /** 080 * Updates crafting matrix; called from onCraftMatrixChanged. Args: none 081 */ 082 public void updateCraftingResults() 083 { 084 for (int var1 = 0; var1 < this.inventorySlots.size(); ++var1) 085 { 086 ItemStack var2 = ((Slot)this.inventorySlots.get(var1)).getStack(); 087 ItemStack var3 = (ItemStack)this.inventoryItemStacks.get(var1); 088 089 if (!ItemStack.areItemStacksEqual(var3, var2)) 090 { 091 var3 = var2 == null ? null : var2.copy(); 092 this.inventoryItemStacks.set(var1, var3); 093 094 for (int var4 = 0; var4 < this.crafters.size(); ++var4) 095 { 096 ((ICrafting)this.crafters.get(var4)).sendSlotContents(this, var1, var3); 097 } 098 } 099 } 100 } 101 102 /** 103 * enchants the item on the table using the specified slot; also deducts XP from player 104 */ 105 public boolean enchantItem(EntityPlayer par1EntityPlayer, int par2) 106 { 107 return false; 108 } 109 110 public Slot getSlotFromInventory(IInventory par1IInventory, int par2) 111 { 112 for (int var3 = 0; var3 < this.inventorySlots.size(); ++var3) 113 { 114 Slot var4 = (Slot)this.inventorySlots.get(var3); 115 116 if (var4.isSlotInInventory(par1IInventory, par2)) 117 { 118 return var4; 119 } 120 } 121 122 return null; 123 } 124 125 public Slot getSlot(int par1) 126 { 127 return (Slot)this.inventorySlots.get(par1); 128 } 129 130 /** 131 * Called when a player shift-clicks on a slot. You must override this or you will crash when someone does that. 132 */ 133 public ItemStack transferStackInSlot(EntityPlayer par1EntityPlayer, int par2) 134 { 135 Slot var3 = (Slot)this.inventorySlots.get(par2); 136 return var3 != null ? var3.getStack() : null; 137 } 138 139 public ItemStack slotClick(int par1, int par2, int par3, EntityPlayer par4EntityPlayer) 140 { 141 ItemStack var5 = null; 142 InventoryPlayer var6 = par4EntityPlayer.inventory; 143 Slot var7; 144 ItemStack var8; 145 int var10; 146 ItemStack var11; 147 148 if ((par3 == 0 || par3 == 1) && (par2 == 0 || par2 == 1)) 149 { 150 if (par1 == -999) 151 { 152 if (var6.getItemStack() != null && par1 == -999) 153 { 154 if (par2 == 0) 155 { 156 par4EntityPlayer.dropPlayerItem(var6.getItemStack()); 157 var6.setItemStack((ItemStack)null); 158 } 159 160 if (par2 == 1) 161 { 162 par4EntityPlayer.dropPlayerItem(var6.getItemStack().splitStack(1)); 163 164 if (var6.getItemStack().stackSize == 0) 165 { 166 var6.setItemStack((ItemStack)null); 167 } 168 } 169 } 170 } 171 else if (par3 == 1) 172 { 173 var7 = (Slot)this.inventorySlots.get(par1); 174 175 if (var7 != null && var7.canTakeStack(par4EntityPlayer)) 176 { 177 var8 = this.transferStackInSlot(par4EntityPlayer, par1); 178 179 if (var8 != null) 180 { 181 int var12 = var8.itemID; 182 var5 = var8.copy(); 183 184 if (var7 != null && var7.getStack() != null && var7.getStack().itemID == var12) 185 { 186 this.retrySlotClick(par1, par2, true, par4EntityPlayer); 187 } 188 } 189 } 190 } 191 else 192 { 193 if (par1 < 0) 194 { 195 return null; 196 } 197 198 var7 = (Slot)this.inventorySlots.get(par1); 199 200 if (var7 != null) 201 { 202 var8 = var7.getStack(); 203 ItemStack var13 = var6.getItemStack(); 204 205 if (var8 != null) 206 { 207 var5 = var8.copy(); 208 } 209 210 if (var8 == null) 211 { 212 if (var13 != null && var7.isItemValid(var13)) 213 { 214 var10 = par2 == 0 ? var13.stackSize : 1; 215 216 if (var10 > var7.getSlotStackLimit()) 217 { 218 var10 = var7.getSlotStackLimit(); 219 } 220 221 var7.putStack(var13.splitStack(var10)); 222 223 if (var13.stackSize == 0) 224 { 225 var6.setItemStack((ItemStack)null); 226 } 227 } 228 } 229 else if (var7.canTakeStack(par4EntityPlayer)) 230 { 231 if (var13 == null) 232 { 233 var10 = par2 == 0 ? var8.stackSize : (var8.stackSize + 1) / 2; 234 var11 = var7.decrStackSize(var10); 235 var6.setItemStack(var11); 236 237 if (var8.stackSize == 0) 238 { 239 var7.putStack((ItemStack)null); 240 } 241 242 var7.onPickupFromSlot(par4EntityPlayer, var6.getItemStack()); 243 } 244 else if (var7.isItemValid(var13)) 245 { 246 if (var8.itemID == var13.itemID && (!var8.getHasSubtypes() || var8.getItemDamage() == var13.getItemDamage()) && ItemStack.areItemStackTagsEqual(var8, var13)) 247 { 248 var10 = par2 == 0 ? var13.stackSize : 1; 249 250 if (var10 > var7.getSlotStackLimit() - var8.stackSize) 251 { 252 var10 = var7.getSlotStackLimit() - var8.stackSize; 253 } 254 255 if (var10 > var13.getMaxStackSize() - var8.stackSize) 256 { 257 var10 = var13.getMaxStackSize() - var8.stackSize; 258 } 259 260 var13.splitStack(var10); 261 262 if (var13.stackSize == 0) 263 { 264 var6.setItemStack((ItemStack)null); 265 } 266 267 var8.stackSize += var10; 268 } 269 else if (var13.stackSize <= var7.getSlotStackLimit()) 270 { 271 var7.putStack(var13); 272 var6.setItemStack(var8); 273 } 274 } 275 else if (var8.itemID == var13.itemID && var13.getMaxStackSize() > 1 && (!var8.getHasSubtypes() || var8.getItemDamage() == var13.getItemDamage()) && ItemStack.areItemStackTagsEqual(var8, var13)) 276 { 277 var10 = var8.stackSize; 278 279 if (var10 > 0 && var10 + var13.stackSize <= var13.getMaxStackSize()) 280 { 281 var13.stackSize += var10; 282 var8 = var7.decrStackSize(var10); 283 284 if (var8.stackSize == 0) 285 { 286 var7.putStack((ItemStack)null); 287 } 288 289 var7.onPickupFromSlot(par4EntityPlayer, var6.getItemStack()); 290 } 291 } 292 } 293 294 var7.onSlotChanged(); 295 } 296 } 297 } 298 else if (par3 == 2 && par2 >= 0 && par2 < 9) 299 { 300 var7 = (Slot)this.inventorySlots.get(par1); 301 302 if (var7.canTakeStack(par4EntityPlayer)) 303 { 304 var8 = var6.getStackInSlot(par2); 305 boolean var9 = var8 == null || var7.inventory == var6 && var7.isItemValid(var8); 306 var10 = -1; 307 308 if (!var9) 309 { 310 var10 = var6.getFirstEmptyStack(); 311 var9 |= var10 > -1; 312 } 313 314 if (var7.getHasStack() && var9) 315 { 316 var11 = var7.getStack(); 317 var6.setInventorySlotContents(par2, var11); 318 319 if ((var7.inventory != var6 || !var7.isItemValid(var8)) && var8 != null) 320 { 321 if (var10 > -1) 322 { 323 var6.addItemStackToInventory(var8); 324 var7.putStack((ItemStack)null); 325 var7.onPickupFromSlot(par4EntityPlayer, var11); 326 } 327 } 328 else 329 { 330 var7.putStack(var8); 331 var7.onPickupFromSlot(par4EntityPlayer, var11); 332 } 333 } 334 else if (!var7.getHasStack() && var8 != null && var7.isItemValid(var8)) 335 { 336 var6.setInventorySlotContents(par2, (ItemStack)null); 337 var7.putStack(var8); 338 } 339 } 340 } 341 else if (par3 == 3 && par4EntityPlayer.capabilities.isCreativeMode && var6.getItemStack() == null && par1 >= 0) 342 { 343 var7 = (Slot)this.inventorySlots.get(par1); 344 345 if (var7 != null && var7.getHasStack()) 346 { 347 var8 = var7.getStack().copy(); 348 var8.stackSize = var8.getMaxStackSize(); 349 var6.setItemStack(var8); 350 } 351 } 352 353 return var5; 354 } 355 356 protected void retrySlotClick(int par1, int par2, boolean par3, EntityPlayer par4EntityPlayer) 357 { 358 this.slotClick(par1, par2, 1, par4EntityPlayer); 359 } 360 361 /** 362 * Callback for when the crafting gui is closed. 363 */ 364 public void onCraftGuiClosed(EntityPlayer par1EntityPlayer) 365 { 366 InventoryPlayer var2 = par1EntityPlayer.inventory; 367 368 if (var2.getItemStack() != null) 369 { 370 par1EntityPlayer.dropPlayerItem(var2.getItemStack()); 371 var2.setItemStack((ItemStack)null); 372 } 373 } 374 375 /** 376 * Callback for when the crafting matrix is changed. 377 */ 378 public void onCraftMatrixChanged(IInventory par1IInventory) 379 { 380 this.updateCraftingResults(); 381 } 382 383 /** 384 * args: slotID, itemStack to put in slot 385 */ 386 public void putStackInSlot(int par1, ItemStack par2ItemStack) 387 { 388 this.getSlot(par1).putStack(par2ItemStack); 389 } 390 391 @SideOnly(Side.CLIENT) 392 393 /** 394 * places itemstacks in first x slots, x being aitemstack.lenght 395 */ 396 public void putStacksInSlots(ItemStack[] par1ArrayOfItemStack) 397 { 398 for (int var2 = 0; var2 < par1ArrayOfItemStack.length; ++var2) 399 { 400 this.getSlot(var2).putStack(par1ArrayOfItemStack[var2]); 401 } 402 } 403 404 @SideOnly(Side.CLIENT) 405 public void updateProgressBar(int par1, int par2) {} 406 407 @SideOnly(Side.CLIENT) 408 409 /** 410 * Gets a unique transaction ID. Parameter is unused. 411 */ 412 public short getNextTransactionID(InventoryPlayer par1InventoryPlayer) 413 { 414 ++this.transactionID; 415 return this.transactionID; 416 } 417 418 /** 419 * NotUsing because adding a player twice is an error 420 */ 421 public boolean isPlayerNotUsingContainer(EntityPlayer par1EntityPlayer) 422 { 423 return !this.playerList.contains(par1EntityPlayer); 424 } 425 426 /** 427 * adds or removes the player from the container based on par2 428 */ 429 public void setPlayerIsPresent(EntityPlayer par1EntityPlayer, boolean par2) 430 { 431 if (par2) 432 { 433 this.playerList.remove(par1EntityPlayer); 434 } 435 else 436 { 437 this.playerList.add(par1EntityPlayer); 438 } 439 } 440 441 public abstract boolean canInteractWith(EntityPlayer var1); 442 443 /** 444 * merges provided ItemStack with the first avaliable one in the container/player inventory 445 */ 446 protected boolean mergeItemStack(ItemStack par1ItemStack, int par2, int par3, boolean par4) 447 { 448 boolean var5 = false; 449 int var6 = par2; 450 451 if (par4) 452 { 453 var6 = par3 - 1; 454 } 455 456 Slot var7; 457 ItemStack var8; 458 459 if (par1ItemStack.isStackable()) 460 { 461 while (par1ItemStack.stackSize > 0 && (!par4 && var6 < par3 || par4 && var6 >= par2)) 462 { 463 var7 = (Slot)this.inventorySlots.get(var6); 464 var8 = var7.getStack(); 465 466 if (var8 != null && var8.itemID == par1ItemStack.itemID && (!par1ItemStack.getHasSubtypes() || par1ItemStack.getItemDamage() == var8.getItemDamage()) && ItemStack.areItemStackTagsEqual(par1ItemStack, var8)) 467 { 468 int var9 = var8.stackSize + par1ItemStack.stackSize; 469 470 if (var9 <= par1ItemStack.getMaxStackSize()) 471 { 472 par1ItemStack.stackSize = 0; 473 var8.stackSize = var9; 474 var7.onSlotChanged(); 475 var5 = true; 476 } 477 else if (var8.stackSize < par1ItemStack.getMaxStackSize()) 478 { 479 par1ItemStack.stackSize -= par1ItemStack.getMaxStackSize() - var8.stackSize; 480 var8.stackSize = par1ItemStack.getMaxStackSize(); 481 var7.onSlotChanged(); 482 var5 = true; 483 } 484 } 485 486 if (par4) 487 { 488 --var6; 489 } 490 else 491 { 492 ++var6; 493 } 494 } 495 } 496 497 if (par1ItemStack.stackSize > 0) 498 { 499 if (par4) 500 { 501 var6 = par3 - 1; 502 } 503 else 504 { 505 var6 = par2; 506 } 507 508 while (!par4 && var6 < par3 || par4 && var6 >= par2) 509 { 510 var7 = (Slot)this.inventorySlots.get(var6); 511 var8 = var7.getStack(); 512 513 if (var8 == null) 514 { 515 var7.putStack(par1ItemStack.copy()); 516 var7.onSlotChanged(); 517 par1ItemStack.stackSize = 0; 518 var5 = true; 519 break; 520 } 521 522 if (par4) 523 { 524 --var6; 525 } 526 else 527 { 528 ++var6; 529 } 530 } 531 } 532 533 return var5; 534 } 535 }