001 package net.minecraft.inventory; 002 003 import cpw.mods.fml.relauncher.Side; 004 import cpw.mods.fml.relauncher.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.detectAndSendChanges(); 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 * Looks for changes made in the container, sends them to every listener. 081 */ 082 public void detectAndSendChanges() 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.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.decrStackSize(var11.stackSize); 325 var7.putStack((ItemStack)null); 326 var7.onPickupFromSlot(par4EntityPlayer, var11); 327 } 328 } 329 else 330 { 331 var7.decrStackSize(var11.stackSize); 332 var7.putStack(var8); 333 var7.onPickupFromSlot(par4EntityPlayer, var11); 334 } 335 } 336 else if (!var7.getHasStack() && var8 != null && var7.isItemValid(var8)) 337 { 338 var6.setInventorySlotContents(par2, (ItemStack)null); 339 var7.putStack(var8); 340 } 341 } 342 } 343 else if (par3 == 3 && par4EntityPlayer.capabilities.isCreativeMode && var6.getItemStack() == null && par1 >= 0) 344 { 345 var7 = (Slot)this.inventorySlots.get(par1); 346 347 if (var7 != null && var7.getHasStack()) 348 { 349 var8 = var7.getStack().copy(); 350 var8.stackSize = var8.getMaxStackSize(); 351 var6.setItemStack(var8); 352 } 353 } 354 355 return var5; 356 } 357 358 protected void retrySlotClick(int par1, int par2, boolean par3, EntityPlayer par4EntityPlayer) 359 { 360 this.slotClick(par1, par2, 1, par4EntityPlayer); 361 } 362 363 /** 364 * Callback for when the crafting gui is closed. 365 */ 366 public void onCraftGuiClosed(EntityPlayer par1EntityPlayer) 367 { 368 InventoryPlayer var2 = par1EntityPlayer.inventory; 369 370 if (var2.getItemStack() != null) 371 { 372 par1EntityPlayer.dropPlayerItem(var2.getItemStack()); 373 var2.setItemStack((ItemStack)null); 374 } 375 } 376 377 /** 378 * Callback for when the crafting matrix is changed. 379 */ 380 public void onCraftMatrixChanged(IInventory par1IInventory) 381 { 382 this.detectAndSendChanges(); 383 } 384 385 /** 386 * args: slotID, itemStack to put in slot 387 */ 388 public void putStackInSlot(int par1, ItemStack par2ItemStack) 389 { 390 this.getSlot(par1).putStack(par2ItemStack); 391 } 392 393 @SideOnly(Side.CLIENT) 394 395 /** 396 * places itemstacks in first x slots, x being aitemstack.lenght 397 */ 398 public void putStacksInSlots(ItemStack[] par1ArrayOfItemStack) 399 { 400 for (int var2 = 0; var2 < par1ArrayOfItemStack.length; ++var2) 401 { 402 this.getSlot(var2).putStack(par1ArrayOfItemStack[var2]); 403 } 404 } 405 406 @SideOnly(Side.CLIENT) 407 public void updateProgressBar(int par1, int par2) {} 408 409 @SideOnly(Side.CLIENT) 410 411 /** 412 * Gets a unique transaction ID. Parameter is unused. 413 */ 414 public short getNextTransactionID(InventoryPlayer par1InventoryPlayer) 415 { 416 ++this.transactionID; 417 return this.transactionID; 418 } 419 420 /** 421 * NotUsing because adding a player twice is an error 422 */ 423 public boolean isPlayerNotUsingContainer(EntityPlayer par1EntityPlayer) 424 { 425 return !this.playerList.contains(par1EntityPlayer); 426 } 427 428 /** 429 * adds or removes the player from the container based on par2 430 */ 431 public void setPlayerIsPresent(EntityPlayer par1EntityPlayer, boolean par2) 432 { 433 if (par2) 434 { 435 this.playerList.remove(par1EntityPlayer); 436 } 437 else 438 { 439 this.playerList.add(par1EntityPlayer); 440 } 441 } 442 443 public abstract boolean canInteractWith(EntityPlayer var1); 444 445 /** 446 * merges provided ItemStack with the first avaliable one in the container/player inventory 447 */ 448 protected boolean mergeItemStack(ItemStack par1ItemStack, int par2, int par3, boolean par4) 449 { 450 boolean var5 = false; 451 int var6 = par2; 452 453 if (par4) 454 { 455 var6 = par3 - 1; 456 } 457 458 Slot var7; 459 ItemStack var8; 460 461 if (par1ItemStack.isStackable()) 462 { 463 while (par1ItemStack.stackSize > 0 && (!par4 && var6 < par3 || par4 && var6 >= par2)) 464 { 465 var7 = (Slot)this.inventorySlots.get(var6); 466 var8 = var7.getStack(); 467 468 if (var8 != null && var8.itemID == par1ItemStack.itemID && (!par1ItemStack.getHasSubtypes() || par1ItemStack.getItemDamage() == var8.getItemDamage()) && ItemStack.areItemStackTagsEqual(par1ItemStack, var8)) 469 { 470 int var9 = var8.stackSize + par1ItemStack.stackSize; 471 472 if (var9 <= par1ItemStack.getMaxStackSize()) 473 { 474 par1ItemStack.stackSize = 0; 475 var8.stackSize = var9; 476 var7.onSlotChanged(); 477 var5 = true; 478 } 479 else if (var8.stackSize < par1ItemStack.getMaxStackSize()) 480 { 481 par1ItemStack.stackSize -= par1ItemStack.getMaxStackSize() - var8.stackSize; 482 var8.stackSize = par1ItemStack.getMaxStackSize(); 483 var7.onSlotChanged(); 484 var5 = true; 485 } 486 } 487 488 if (par4) 489 { 490 --var6; 491 } 492 else 493 { 494 ++var6; 495 } 496 } 497 } 498 499 if (par1ItemStack.stackSize > 0) 500 { 501 if (par4) 502 { 503 var6 = par3 - 1; 504 } 505 else 506 { 507 var6 = par2; 508 } 509 510 while (!par4 && var6 < par3 || par4 && var6 >= par2) 511 { 512 var7 = (Slot)this.inventorySlots.get(var6); 513 var8 = var7.getStack(); 514 515 if (var8 == null) 516 { 517 var7.putStack(par1ItemStack.copy()); 518 var7.onSlotChanged(); 519 par1ItemStack.stackSize = 0; 520 var5 = true; 521 break; 522 } 523 524 if (par4) 525 { 526 --var6; 527 } 528 else 529 { 530 ++var6; 531 } 532 } 533 } 534 535 return var5; 536 } 537 }