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            this.maximumCost = k + i;
309
310            if (i <= 0)
311            {
312                itemstack1 = null;
313            }
314
315            if (j == i && j > 0 && this.maximumCost >= 40)
316            {
317                this.theWorld.getWorldLogAgent().logInfo("Naming an item only, cost too high; giving discount to cap cost to 39 levels");
318                this.maximumCost = 39;
319            }
320
321            if (this.maximumCost >= 40 && !this.thePlayer.capabilities.isCreativeMode)
322            {
323                itemstack1 = null;
324            }
325
326            if (itemstack1 != null)
327            {
328                i1 = itemstack1.getRepairCost();
329
330                if (itemstack2 != null && i1 < itemstack2.getRepairCost())
331                {
332                    i1 = itemstack2.getRepairCost();
333                }
334
335                if (itemstack1.hasDisplayName())
336                {
337                    i1 -= 9;
338                }
339
340                if (i1 < 0)
341                {
342                    i1 = 0;
343                }
344
345                i1 += 2;
346                itemstack1.setRepairCost(i1);
347                EnchantmentHelper.setEnchantments(map, itemstack1);
348            }
349
350            this.outputSlot.setInventorySlotContents(0, itemstack1);
351            this.detectAndSendChanges();
352        }
353    }
354
355    public void addCraftingToCrafters(ICrafting par1ICrafting)
356    {
357        super.addCraftingToCrafters(par1ICrafting);
358        par1ICrafting.sendProgressBarUpdate(this, 0, this.maximumCost);
359    }
360
361    @SideOnly(Side.CLIENT)
362    public void updateProgressBar(int par1, int par2)
363    {
364        if (par1 == 0)
365        {
366            this.maximumCost = par2;
367        }
368    }
369
370    /**
371     * Callback for when the crafting gui is closed.
372     */
373    public void onCraftGuiClosed(EntityPlayer par1EntityPlayer)
374    {
375        super.onCraftGuiClosed(par1EntityPlayer);
376
377        if (!this.theWorld.isRemote)
378        {
379            for (int i = 0; i < this.inputSlots.getSizeInventory(); ++i)
380            {
381                ItemStack itemstack = this.inputSlots.getStackInSlotOnClosing(i);
382
383                if (itemstack != null)
384                {
385                    par1EntityPlayer.dropPlayerItem(itemstack);
386                }
387            }
388        }
389    }
390
391    public boolean canInteractWith(EntityPlayer par1EntityPlayer)
392    {
393        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;
394    }
395
396    /**
397     * Called when a player shift-clicks on a slot. You must override this or you will crash when someone does that.
398     */
399    public ItemStack transferStackInSlot(EntityPlayer par1EntityPlayer, int par2)
400    {
401        ItemStack itemstack = null;
402        Slot slot = (Slot)this.inventorySlots.get(par2);
403
404        if (slot != null && slot.getHasStack())
405        {
406            ItemStack itemstack1 = slot.getStack();
407            itemstack = itemstack1.copy();
408
409            if (par2 == 2)
410            {
411                if (!this.mergeItemStack(itemstack1, 3, 39, true))
412                {
413                    return null;
414                }
415
416                slot.onSlotChange(itemstack1, itemstack);
417            }
418            else if (par2 != 0 && par2 != 1)
419            {
420                if (par2 >= 3 && par2 < 39 && !this.mergeItemStack(itemstack1, 0, 2, false))
421                {
422                    return null;
423                }
424            }
425            else if (!this.mergeItemStack(itemstack1, 3, 39, false))
426            {
427                return null;
428            }
429
430            if (itemstack1.stackSize == 0)
431            {
432                slot.putStack((ItemStack)null);
433            }
434            else
435            {
436                slot.onSlotChanged();
437            }
438
439            if (itemstack1.stackSize == itemstack.stackSize)
440            {
441                return null;
442            }
443
444            slot.onPickupFromSlot(par1EntityPlayer, itemstack1);
445        }
446
447        return itemstack;
448    }
449
450    /**
451     * used by the Anvil GUI to update the Item Name being typed by the player
452     */
453    public void updateItemName(String par1Str)
454    {
455        this.repairedItemName = par1Str;
456
457        if (this.getSlot(2).getHasStack())
458        {
459            this.getSlot(2).getStack().setItemName(this.repairedItemName);
460        }
461
462        this.updateRepairOutput();
463    }
464
465    static IInventory getRepairInputInventory(ContainerRepair par0ContainerRepair)
466    {
467        return par0ContainerRepair.inputSlots;
468    }
469
470    static int getStackSizeUsedInRepair(ContainerRepair par0ContainerRepair)
471    {
472        return par0ContainerRepair.stackSizeToBeUsedInRepair;
473    }
474}