    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}