001package net.minecraft.inventory; 002 003import cpw.mods.fml.relauncher.Side; 004import cpw.mods.fml.relauncher.SideOnly; 005import java.util.Iterator; 006import java.util.Map; 007import net.minecraft.block.Block; 008import net.minecraft.enchantment.Enchantment; 009import net.minecraft.enchantment.EnchantmentHelper; 010import net.minecraft.entity.player.EntityPlayer; 011import net.minecraft.entity.player.InventoryPlayer; 012import net.minecraft.item.Item; 013import net.minecraft.item.ItemEnchantedBook; 014import net.minecraft.item.ItemStack; 015import net.minecraft.world.World; 016 017public class ContainerRepair extends Container 018{ 019 /** Here comes out item you merged and/or renamed. */ 020 private IInventory outputSlot = new InventoryCraftResult(); 021 022 /** 023 * The 2slots where you put your items in that you want to merge and/or rename. 024 */ 025 private IInventory inputSlots = new InventoryRepair(this, "Repair", true, 2); 026 private World theWorld; 027 private int field_82861_i; 028 private int field_82858_j; 029 private int field_82859_k; 030 031 /** The maximum cost of repairing/renaming in the anvil. */ 032 public int maximumCost = 0; 033 034 /** determined by damage of input item and stackSize of repair materials */ 035 private int stackSizeToBeUsedInRepair = 0; 036 private String repairedItemName; 037 038 /** The player that has this container open. */ 039 private final EntityPlayer thePlayer; 040 041 public ContainerRepair(InventoryPlayer par1InventoryPlayer, World par2World, int par3, int par4, int par5, EntityPlayer par6EntityPlayer) 042 { 043 this.theWorld = par2World; 044 this.field_82861_i = par3; 045 this.field_82858_j = par4; 046 this.field_82859_k = par5; 047 this.thePlayer = par6EntityPlayer; 048 this.addSlotToContainer(new Slot(this.inputSlots, 0, 27, 47)); 049 this.addSlotToContainer(new Slot(this.inputSlots, 1, 76, 47)); 050 this.addSlotToContainer(new SlotRepair(this, this.outputSlot, 2, 134, 47, par2World, par3, par4, par5)); 051 int l; 052 053 for (l = 0; l < 3; ++l) 054 { 055 for (int i1 = 0; i1 < 9; ++i1) 056 { 057 this.addSlotToContainer(new Slot(par1InventoryPlayer, i1 + l * 9 + 9, 8 + i1 * 18, 84 + l * 18)); 058 } 059 } 060 061 for (l = 0; l < 9; ++l) 062 { 063 this.addSlotToContainer(new Slot(par1InventoryPlayer, l, 8 + l * 18, 142)); 064 } 065 } 066 067 /** 068 * Callback for when the crafting matrix is changed. 069 */ 070 public void onCraftMatrixChanged(IInventory par1IInventory) 071 { 072 super.onCraftMatrixChanged(par1IInventory); 073 074 if (par1IInventory == this.inputSlots) 075 { 076 this.updateRepairOutput(); 077 } 078 } 079 080 /** 081 * called when the Anvil Input Slot changes, calculates the new result and puts it in the output slot 082 */ 083 public void updateRepairOutput() 084 { 085 ItemStack itemstack = this.inputSlots.getStackInSlot(0); 086 this.maximumCost = 0; 087 int i = 0; 088 byte b0 = 0; 089 int j = 0; 090 091 if (itemstack == null) 092 { 093 this.outputSlot.setInventorySlotContents(0, (ItemStack)null); 094 this.maximumCost = 0; 095 } 096 else 097 { 098 ItemStack itemstack1 = itemstack.copy(); 099 ItemStack itemstack2 = this.inputSlots.getStackInSlot(1); 100 Map map = EnchantmentHelper.getEnchantments(itemstack1); 101 boolean flag = false; 102 int k = b0 + itemstack.getRepairCost() + (itemstack2 == null ? 0 : itemstack2.getRepairCost()); 103 this.stackSizeToBeUsedInRepair = 0; 104 int l; 105 int i1; 106 int j1; 107 int k1; 108 int l1; 109 Iterator iterator; 110 Enchantment enchantment; 111 112 if (itemstack2 != null) 113 { 114 flag = itemstack2.itemID == Item.enchantedBook.itemID && Item.enchantedBook.func_92110_g(itemstack2).tagCount() > 0; 115 116 if (itemstack1.isItemStackDamageable() && Item.itemsList[itemstack1.itemID].getIsRepairable(itemstack, itemstack2)) 117 { 118 l = Math.min(itemstack1.getItemDamageForDisplay(), itemstack1.getMaxDamage() / 4); 119 120 if (l <= 0) 121 { 122 this.outputSlot.setInventorySlotContents(0, (ItemStack)null); 123 this.maximumCost = 0; 124 return; 125 } 126 127 for (i1 = 0; l > 0 && i1 < itemstack2.stackSize; ++i1) 128 { 129 j1 = itemstack1.getItemDamageForDisplay() - l; 130 itemstack1.setItemDamage(j1); 131 i += Math.max(1, l / 100) + map.size(); 132 l = Math.min(itemstack1.getItemDamageForDisplay(), itemstack1.getMaxDamage() / 4); 133 } 134 135 this.stackSizeToBeUsedInRepair = i1; 136 } 137 else 138 { 139 if (!flag && (itemstack1.itemID != itemstack2.itemID || !itemstack1.isItemStackDamageable())) 140 { 141 this.outputSlot.setInventorySlotContents(0, (ItemStack)null); 142 this.maximumCost = 0; 143 return; 144 } 145 146 if (itemstack1.isItemStackDamageable() && !flag) 147 { 148 l = itemstack.getMaxDamage() - itemstack.getItemDamageForDisplay(); 149 i1 = itemstack2.getMaxDamage() - itemstack2.getItemDamageForDisplay(); 150 j1 = i1 + itemstack1.getMaxDamage() * 12 / 100; 151 int i2 = l + j1; 152 k1 = itemstack1.getMaxDamage() - i2; 153 154 if (k1 < 0) 155 { 156 k1 = 0; 157 } 158 159 if (k1 < itemstack1.getItemDamage()) 160 { 161 itemstack1.setItemDamage(k1); 162 i += Math.max(1, j1 / 100); 163 } 164 } 165 166 Map map1 = EnchantmentHelper.getEnchantments(itemstack2); 167 iterator = map1.keySet().iterator(); 168 169 while (iterator.hasNext()) 170 { 171 j1 = ((Integer)iterator.next()).intValue(); 172 enchantment = Enchantment.enchantmentsList[j1]; 173 k1 = map.containsKey(Integer.valueOf(j1)) ? ((Integer)map.get(Integer.valueOf(j1))).intValue() : 0; 174 l1 = ((Integer)map1.get(Integer.valueOf(j1))).intValue(); 175 int j2; 176 177 if (k1 == l1) 178 { 179 ++l1; 180 j2 = l1; 181 } 182 else 183 { 184 j2 = Math.max(l1, k1); 185 } 186 187 l1 = j2; 188 int k2 = l1 - k1; 189 boolean flag1 = enchantment.func_92089_a(itemstack); 190 191 if (this.thePlayer.capabilities.isCreativeMode || itemstack.itemID == ItemEnchantedBook.enchantedBook.itemID) 192 { 193 flag1 = true; 194 } 195 196 Iterator iterator1 = map.keySet().iterator(); 197 198 while (iterator1.hasNext()) 199 { 200 int l2 = ((Integer)iterator1.next()).intValue(); 201 202 if (l2 != j1 && !enchantment.canApplyTogether(Enchantment.enchantmentsList[l2])) 203 { 204 flag1 = false; 205 i += k2; 206 } 207 } 208 209 if (flag1) 210 { 211 if (l1 > enchantment.getMaxLevel()) 212 { 213 l1 = enchantment.getMaxLevel(); 214 } 215 216 map.put(Integer.valueOf(j1), Integer.valueOf(l1)); 217 int i3 = 0; 218 219 switch (enchantment.getWeight()) 220 { 221 case 1: 222 i3 = 8; 223 break; 224 case 2: 225 i3 = 4; 226 case 3: 227 case 4: 228 case 6: 229 case 7: 230 case 8: 231 case 9: 232 default: 233 break; 234 case 5: 235 i3 = 2; 236 break; 237 case 10: 238 i3 = 1; 239 } 240 241 if (flag) 242 { 243 i3 = Math.max(1, i3 / 2); 244 } 245 246 i += i3 * k2; 247 } 248 } 249 } 250 } 251 252 if (this.repairedItemName != null && !this.repairedItemName.equalsIgnoreCase(itemstack.getDisplayName()) && this.repairedItemName.length() > 0) 253 { 254 j = itemstack.isItemStackDamageable() ? 7 : itemstack.stackSize * 5; 255 i += j; 256 257 if (itemstack.hasDisplayName()) 258 { 259 k += j / 2; 260 } 261 262 itemstack1.setItemName(this.repairedItemName); 263 } 264 265 l = 0; 266 267 for (iterator = map.keySet().iterator(); iterator.hasNext(); k += l + k1 * l1) 268 { 269 j1 = ((Integer)iterator.next()).intValue(); 270 enchantment = Enchantment.enchantmentsList[j1]; 271 k1 = ((Integer)map.get(Integer.valueOf(j1))).intValue(); 272 l1 = 0; 273 ++l; 274 275 switch (enchantment.getWeight()) 276 { 277 case 1: 278 l1 = 8; 279 break; 280 case 2: 281 l1 = 4; 282 case 3: 283 case 4: 284 case 6: 285 case 7: 286 case 8: 287 case 9: 288 default: 289 break; 290 case 5: 291 l1 = 2; 292 break; 293 case 10: 294 l1 = 1; 295 } 296 297 if (flag) 298 { 299 l1 = Math.max(1, l1 / 2); 300 } 301 } 302 303 if (flag) 304 { 305 k = Math.max(1, k / 2); 306 } 307 308 if (flag && itemstack1!=null && !Item.itemsList[itemstack1.itemID].isBookEnchantable(itemstack1,itemstack2)) 309 { 310 itemstack1 = null; 311 } 312 313 this.maximumCost = k + i; 314 315 if (i <= 0) 316 { 317 itemstack1 = null; 318 } 319 320 if (j == i && j > 0 && this.maximumCost >= 40) 321 { 322 this.theWorld.getWorldLogAgent().logInfo("Naming an item only, cost too high; giving discount to cap cost to 39 levels"); 323 this.maximumCost = 39; 324 } 325 326 if (this.maximumCost >= 40 && !this.thePlayer.capabilities.isCreativeMode) 327 { 328 itemstack1 = null; 329 } 330 331 332 if (itemstack1 != null) 333 { 334 i1 = itemstack1.getRepairCost(); 335 336 if (itemstack2 != null && i1 < itemstack2.getRepairCost()) 337 { 338 i1 = itemstack2.getRepairCost(); 339 } 340 341 if (itemstack1.hasDisplayName()) 342 { 343 i1 -= 9; 344 } 345 346 if (i1 < 0) 347 { 348 i1 = 0; 349 } 350 351 i1 += 2; 352 itemstack1.setRepairCost(i1); 353 EnchantmentHelper.setEnchantments(map, itemstack1); 354 } 355 356 this.outputSlot.setInventorySlotContents(0, itemstack1); 357 this.detectAndSendChanges(); 358 } 359 } 360 361 public void addCraftingToCrafters(ICrafting par1ICrafting) 362 { 363 super.addCraftingToCrafters(par1ICrafting); 364 par1ICrafting.sendProgressBarUpdate(this, 0, this.maximumCost); 365 } 366 367 @SideOnly(Side.CLIENT) 368 public void updateProgressBar(int par1, int par2) 369 { 370 if (par1 == 0) 371 { 372 this.maximumCost = par2; 373 } 374 } 375 376 /** 377 * Callback for when the crafting gui is closed. 378 */ 379 public void onCraftGuiClosed(EntityPlayer par1EntityPlayer) 380 { 381 super.onCraftGuiClosed(par1EntityPlayer); 382 383 if (!this.theWorld.isRemote) 384 { 385 for (int i = 0; i < this.inputSlots.getSizeInventory(); ++i) 386 { 387 ItemStack itemstack = this.inputSlots.getStackInSlotOnClosing(i); 388 389 if (itemstack != null) 390 { 391 par1EntityPlayer.dropPlayerItem(itemstack); 392 } 393 } 394 } 395 } 396 397 public boolean canInteractWith(EntityPlayer par1EntityPlayer) 398 { 399 return this.theWorld.getBlockId(this.field_82861_i, this.field_82858_j, this.field_82859_k) != Block.anvil.blockID ? false : par1EntityPlayer.getDistanceSq((double)this.field_82861_i + 0.5D, (double)this.field_82858_j + 0.5D, (double)this.field_82859_k + 0.5D) <= 64.0D; 400 } 401 402 /** 403 * Called when a player shift-clicks on a slot. You must override this or you will crash when someone does that. 404 */ 405 public ItemStack transferStackInSlot(EntityPlayer par1EntityPlayer, int par2) 406 { 407 ItemStack itemstack = null; 408 Slot slot = (Slot)this.inventorySlots.get(par2); 409 410 if (slot != null && slot.getHasStack()) 411 { 412 ItemStack itemstack1 = slot.getStack(); 413 itemstack = itemstack1.copy(); 414 415 if (par2 == 2) 416 { 417 if (!this.mergeItemStack(itemstack1, 3, 39, true)) 418 { 419 return null; 420 } 421 422 slot.onSlotChange(itemstack1, itemstack); 423 } 424 else if (par2 != 0 && par2 != 1) 425 { 426 if (par2 >= 3 && par2 < 39 && !this.mergeItemStack(itemstack1, 0, 2, false)) 427 { 428 return null; 429 } 430 } 431 else if (!this.mergeItemStack(itemstack1, 3, 39, false)) 432 { 433 return null; 434 } 435 436 if (itemstack1.stackSize == 0) 437 { 438 slot.putStack((ItemStack)null); 439 } 440 else 441 { 442 slot.onSlotChanged(); 443 } 444 445 if (itemstack1.stackSize == itemstack.stackSize) 446 { 447 return null; 448 } 449 450 slot.onPickupFromSlot(par1EntityPlayer, itemstack1); 451 } 452 453 return itemstack; 454 } 455 456 /** 457 * used by the Anvil GUI to update the Item Name being typed by the player 458 */ 459 public void updateItemName(String par1Str) 460 { 461 this.repairedItemName = par1Str; 462 463 if (this.getSlot(2).getHasStack()) 464 { 465 this.getSlot(2).getStack().setItemName(this.repairedItemName); 466 } 467 468 this.updateRepairOutput(); 469 } 470 471 static IInventory getRepairInputInventory(ContainerRepair par0ContainerRepair) 472 { 473 return par0ContainerRepair.inputSlots; 474 } 475 476 static int getStackSizeUsedInRepair(ContainerRepair par0ContainerRepair) 477 { 478 return par0ContainerRepair.stackSizeToBeUsedInRepair; 479 } 480}