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