package com.zivilon.cinder_loe.mixins; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import lotr.common.LOTRConfig; import lotr.common.LOTRMod; import lotr.common.enchant.LOTREnchantment; import lotr.common.enchant.LOTREnchantmentCombining; import lotr.common.enchant.LOTREnchantmentHelper; import lotr.common.entity.npc.LOTREntityScrapTrader; import lotr.common.entity.npc.LOTRTradeable; import lotr.common.inventory.LOTRContainerAnvil; import lotr.common.item.AnvilNameColorProvider; import lotr.common.item.LOTRItemEnchantment; import lotr.common.item.LOTRItemModifierTemplate; import lotr.common.item.LOTRMaterial; import lotr.common.recipe.LOTRRecipePoisonWeapon; import net.minecraft.init.Items; import net.minecraft.inventory.IInventory; import net.minecraft.enchantment.Enchantment; import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; import net.minecraft.item.ItemArmor; import net.minecraft.item.ItemStack; import net.minecraft.item.ItemSword; import net.minecraft.item.ItemTool; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.MathHelper; import com.zivilon.cinder_loe.CinderLoE; import com.zivilon.cinder_loe.util.Utilities; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import org.apache.commons.lang3.StringUtils; @Mixin(LOTRContainerAnvil.class) public abstract class MixinLOTRContainerAnvil { @Shadow public IInventory invInput; @Shadow public IInventory invOutput; @Shadow public LOTRTradeable theTrader; @Shadow public EntityPlayer thePlayer; @Shadow public int materialCost; @Shadow public int reforgeCost; @Shadow public int engraveOwnerCost; @Shadow public boolean isSmithScrollCombine; @Shadow public boolean isTrader; @Shadow private String repairedItemName; @Shadow abstract void detectAndSendChanges(); @Shadow abstract float getTraderMaterialPrice(ItemStack inputItem); @Shadow static boolean costsToRename(ItemStack itemstack) { return false; } @Shadow static String stripFormattingCodes(String name) { return null; } @Shadow static String applyFormattingCodes(String name, List colors) { return null; } @Shadow static List getAppliedFormattingCodes(String name) { return null; } /** * @author Shinare * @reason KeyLime */ @Overwrite(remap = false) public boolean isRepairMaterial(ItemStack inputItem, ItemStack materialItem) { if (inputItem.getItem().getIsRepairable(inputItem, materialItem)) return true; Item item = inputItem.getItem(); if (item == Items.bow && LOTRMod.rohanBow.getIsRepairable(inputItem, materialItem)) return true; if (item instanceof net.minecraft.item.ItemFishingRod && materialItem.getItem() == Items.string) return true; if (item instanceof net.minecraft.item.ItemShears && materialItem.getItem() == Items.iron_ingot) return true; if (item instanceof lotr.common.item.LOTRItemChisel && materialItem.getItem() == Items.iron_ingot) return true; if (item instanceof net.minecraft.item.ItemEnchantedBook && materialItem.getItem() == Items.paper) return true; Item.ToolMaterial material = null; if (item instanceof ItemTool) { material = Item.ToolMaterial.valueOf(((ItemTool)item).getToolMaterialName()); } else if (item instanceof ItemSword) { material = Item.ToolMaterial.valueOf(((ItemSword)item).getToolMaterialName()); } if (material == Item.ToolMaterial.WOOD || material == LOTRMaterial.MOREDAIN_WOOD.toToolMaterial()) return LOTRMod.isOreNameEqual(materialItem, "plankWood"); if (material == LOTRMaterial.MALLORN.toToolMaterial()) return (materialItem.getItem() == Item.getItemFromBlock(LOTRMod.planks) && materialItem.getItemDamage() == 1); if (material == LOTRMaterial.MALLORN_MACE.toToolMaterial()) return (materialItem.getItem() == Item.getItemFromBlock(LOTRMod.wood) && materialItem.getItemDamage() == 1); if (material == CinderLoE.MATERIAL_RED_DWARF.toToolMaterial()) return (materialItem.getItem() == CinderLoE.redDwarfSteel); if (material == CinderLoE.MATERIAL_ASH.toToolMaterial()) return (materialItem.getItem() == CinderLoE.ingotAsh); if (material == CinderLoE.MATERIAL_BONEMOLD.toToolMaterial()) return (materialItem.getItem() == CinderLoE.bonemold); if (material == CinderLoE.EVENT.toToolMaterial()) return LOTRMod.isOreNameEqual(materialItem, "ice"); if (material == CinderLoE.MATERIAL_BREE.toToolMaterial()) return (materialItem.getItem() == Items.iron_ingot); if (material == CinderLoE.MATERIAL_WARLORD.toToolMaterial()) return (materialItem.getItem() == LOTRMod.bronze); if (item instanceof ItemArmor armor) { ItemArmor.ArmorMaterial armorMaterial = armor.getArmorMaterial(); if (armorMaterial == LOTRMaterial.BONE.toArmorMaterial()) return LOTRMod.isOreNameEqual(materialItem, "bone"); if (armorMaterial == CinderLoE.MATERIAL_RED_DWARF.toArmorMaterial()) return (materialItem.getItem() == CinderLoE.redDwarfSteel); if (armorMaterial == CinderLoE.MATERIAL_LIMWAITH_WOOD.toArmorMaterial()) return (materialItem.getItem() == Item.getItemFromBlock(LOTRMod.planks) && materialItem.getItemDamage() == 15); if (armorMaterial == CinderLoE.MATERIAL_BREE.toArmorMaterial()) return (materialItem.getItem() == Items.iron_ingot); if (armorMaterial == CinderLoE.MATERIAL_BATTLENUN.toArmorMaterial()) return (materialItem.getItem() == Items.iron_ingot); if (armorMaterial == CinderLoE.MATERIAL_BONEMOLD.toArmorMaterial()) return (materialItem.getItem() == CinderLoE.bonemold); if (armorMaterial == CinderLoE.MATERIAL_RHUDAUR.toArmorMaterial()) return (materialItem.getItem() == Items.iron_ingot); if (armorMaterial == CinderLoE.MATERIAL_JADE.toArmorMaterial()) return (materialItem.getItem() == LOTRMod.emerald); if (armorMaterial == CinderLoE.MATERIAL_SERPENT.toArmorMaterial()) return (materialItem.getItem() == LOTRMod.bronze); if (armorMaterial == CinderLoE.MATERIAL_WARLORD.toArmorMaterial()) return (materialItem.getItem() == LOTRMod.bronze); if (armorMaterial == CinderLoE.MATERIAL_USURPER.toArmorMaterial()) return (materialItem.getItem() == Items.iron_ingot); } return false; } /** * @author Shinare * @reason Adding repair kits and removing bad modifiers from 3 modifier limit **/ @Overwrite(remap = false) private void updateRepairOutput() { ItemStack inputItem = this.invInput.getStackInSlot(0); this.materialCost = 0; this.reforgeCost = 0; this.engraveOwnerCost = 0; this.isSmithScrollCombine = false; int baseAnvilCost = 0; int repairCost = 0; int combineCost = 0; int renameCost = 0; if (inputItem == null) { this.invOutput.setInventorySlotContents(0, null); this.materialCost = 0; } else { ItemStack inputCopy = inputItem.copy(); ItemStack combinerItem = this.invInput.getStackInSlot(1); ItemStack materialItem = this.isTrader ? null : this.invInput.getStackInSlot(2); Map inputEnchants = EnchantmentHelper.getEnchantments(inputCopy); boolean enchantingWithBook = false; List inputModifiers = LOTREnchantmentHelper.getEnchantList(inputCopy); baseAnvilCost = LOTREnchantmentHelper.getAnvilCost(inputItem) + ((combinerItem == null) ? 0 : LOTREnchantmentHelper.getAnvilCost(combinerItem)); this.materialCost = 0; String previousDisplayName = inputCopy.getDisplayName(); String defaultItemName = inputCopy.getItem().getItemStackDisplayName(inputCopy); String nameToApply = this.repairedItemName; String formattedNameToApply = nameToApply; List colorsToApply = new ArrayList(); colorsToApply.addAll(getAppliedFormattingCodes(inputCopy.getDisplayName())); boolean alteringNameColor = false; if (costsToRename(inputItem) && combinerItem != null) { if (combinerItem.getItem() instanceof AnvilNameColorProvider) { AnvilNameColorProvider nameColorProvider = (AnvilNameColorProvider)combinerItem.getItem(); EnumChatFormatting newColor = nameColorProvider.getAnvilNameColor(); boolean isDifferentColor = !colorsToApply.contains(newColor); if (isDifferentColor) { for (EnumChatFormatting ecf : EnumChatFormatting.values()) { if (ecf.isColor()) while (colorsToApply.contains(ecf)) colorsToApply.remove(ecf); } colorsToApply.add(newColor); alteringNameColor = true; } } else if (combinerItem.getItem() == Items.flint) { if (!colorsToApply.isEmpty()) { colorsToApply.clear(); alteringNameColor = true; } } if (alteringNameColor) renameCost++; } if (!colorsToApply.isEmpty()) { if (StringUtils.isBlank(formattedNameToApply)) formattedNameToApply = defaultItemName; formattedNameToApply = applyFormattingCodes(formattedNameToApply, colorsToApply); } boolean nameChange = false; if (formattedNameToApply != null && !formattedNameToApply.equals(previousDisplayName)) if (StringUtils.isBlank(formattedNameToApply) || formattedNameToApply.equals(defaultItemName)) { if (inputCopy.hasDisplayName()) { inputCopy.func_135074_t(); if (!stripFormattingCodes(previousDisplayName).equals(stripFormattingCodes(formattedNameToApply))) nameChange = true; } } else { inputCopy.setStackDisplayName(formattedNameToApply); if (!stripFormattingCodes(previousDisplayName).equals(stripFormattingCodes(formattedNameToApply))) nameChange = true; } if (nameChange) { boolean costRename = costsToRename(inputItem); if (costRename) renameCost++; } if (this.isTrader) { LOTREnchantmentCombining.CombineRecipe scrollCombine = LOTREnchantmentCombining.getCombinationResult(inputItem, combinerItem); if (scrollCombine != null) { this.invOutput.setInventorySlotContents(0, scrollCombine.createOutputItem()); this.materialCost = scrollCombine.cost; this.reforgeCost = 0; this.engraveOwnerCost = 0; this.isSmithScrollCombine = true; return; } } boolean combining = false; if (combinerItem != null) { enchantingWithBook = (combinerItem.getItem() == Items.enchanted_book && Items.enchanted_book.func_92110_g(combinerItem).tagCount() > 0); if (enchantingWithBook && !LOTRConfig.enchantingVanilla) { this.invOutput.setInventorySlotContents(0, null); this.materialCost = 0; return; } LOTREnchantment combinerItemEnchant = null; if (combinerItem.getItem() instanceof LOTRItemEnchantment) { combinerItemEnchant = ((LOTRItemEnchantment)combinerItem.getItem()).theEnchant; } else if (combinerItem.getItem() instanceof LOTRItemModifierTemplate) { combinerItemEnchant = LOTRItemModifierTemplate.getModifier(combinerItem); } if (!enchantingWithBook && combinerItemEnchant == null) if (inputCopy.isItemStackDamageable() && inputCopy.getItem() == combinerItem.getItem()) { int inputUseLeft = inputItem.getMaxDamage() - inputItem.getItemDamageForDisplay(); int combinerUseLeft = combinerItem.getMaxDamage() - combinerItem.getItemDamageForDisplay(); int restoredUses = combinerUseLeft + inputCopy.getMaxDamage() * 12 / 100; int newUsesLeft = inputUseLeft + restoredUses; int newDamage = inputCopy.getMaxDamage() - newUsesLeft; newDamage = Math.max(newDamage, 0); if (newDamage < inputCopy.getItemDamage()) { inputCopy.setItemDamage(newDamage); int restoredUses1 = inputCopy.getMaxDamage() - inputUseLeft; int restoredUses2 = inputCopy.getMaxDamage() - combinerUseLeft; combineCost += Math.max(0, Math.min(restoredUses1, restoredUses2) / 100); } combining = true; } else if (!alteringNameColor && combinerItem.getItem() != CinderLoE.forgingKit) { this.invOutput.setInventorySlotContents(0, null); this.materialCost = 0; return; } Map outputEnchants = new HashMap(inputEnchants); if (LOTRConfig.enchantingVanilla) { Map combinerEnchants = EnchantmentHelper.getEnchantments(combinerItem); for (Object obj : combinerEnchants.keySet()) { int combinedEnchLevel, combinerEnchID = ((Integer)obj).intValue(); Enchantment combinerEnch = Enchantment.enchantmentsList[combinerEnchID]; int inputEnchLevel = 0; if (outputEnchants.containsKey(Integer.valueOf(combinerEnchID))) inputEnchLevel = ((Integer)outputEnchants.get(Integer.valueOf(combinerEnchID))).intValue(); int combinerEnchLevel = ((Integer)combinerEnchants.get(Integer.valueOf(combinerEnchID))).intValue(); if (inputEnchLevel == combinerEnchLevel) { combinedEnchLevel = ++combinerEnchLevel; } else { combinedEnchLevel = Math.max(combinerEnchLevel, inputEnchLevel); } combinerEnchLevel = combinedEnchLevel; int levelsAdded = combinerEnchLevel - inputEnchLevel; boolean canApply = combinerEnch.canApply(inputItem); if (this.thePlayer.capabilities.isCreativeMode || inputItem.getItem() == Items.enchanted_book) canApply = true; for (Object objIn : outputEnchants.keySet()) { int inputEnchID = ((Integer)objIn).intValue(); Enchantment inputEnch = Enchantment.enchantmentsList[inputEnchID]; if (inputEnchID != combinerEnchID) if (!combinerEnch.canApplyTogether(inputEnch) || !inputEnch.canApplyTogether(combinerEnch)) { canApply = false; combineCost += levelsAdded; } } if (canApply) { combinerEnchLevel = Math.min(combinerEnchLevel, combinerEnch.getMaxLevel()); outputEnchants.put(Integer.valueOf(combinerEnchID), Integer.valueOf(combinerEnchLevel)); int costPerLevel = 0; int enchWeight = combinerEnch.getWeight(); if (enchWeight == 1) { costPerLevel = 8; } else if (enchWeight == 2) { costPerLevel = 4; } else if (enchWeight == 5) { costPerLevel = 2; } else if (enchWeight == 10) { costPerLevel = 1; } combineCost += costPerLevel * levelsAdded; } } } else { outputEnchants.clear(); } EnchantmentHelper.setEnchantments(outputEnchants, inputCopy); int maxMods = 3; List outputMods = new ArrayList(); outputMods.addAll(inputModifiers); List combinerMods = LOTREnchantmentHelper.getEnchantList(combinerItem); if (combinerItemEnchant != null) { combinerMods.add(combinerItemEnchant); if (combinerItemEnchant == LOTREnchantment.fire) { Item item = inputCopy.getItem(); if (LOTRRecipePoisonWeapon.poisonedToInput.containsKey(item)) { Item unpoisoned = (Item)LOTRRecipePoisonWeapon.poisonedToInput.get(item); inputCopy.func_150996_a(unpoisoned); } } } for (LOTREnchantment combinerMod : combinerMods) { boolean canApply = combinerMod.canApply(inputItem, false); if (canApply) for (LOTREnchantment mod : outputMods) { if (!mod.isCompatibleWith(combinerMod) || !combinerMod.isCompatibleWith(mod)) canApply = false; } int numOutputMods = 0; for (LOTREnchantment mod : outputMods) { if (!mod.bypassAnvilLimit()) numOutputMods++; } if (!combinerMod.bypassAnvilLimit() && numOutputMods >= maxMods) canApply = false; if (canApply) { outputMods.add(combinerMod); if (combinerMod.isBeneficial()) combineCost += Math.max(1, (int)combinerMod.getValueModifier()); } } if (combinerItem.getItem() == CinderLoE.forgingKit) { List newMods = new ArrayList(); if (combinerItem.getItemDamage() == 0) { for (LOTREnchantment mod : outputMods) { if (Utilities.isBadEnch(mod)) { combineCost += 2; } else { newMods.add(mod); } } } else { for (LOTREnchantment mod : outputMods) { if (Utilities.upgradedEnchants.containsKey(mod.enchantName)) { combineCost += 2; newMods.add(Utilities.upgradeEnch(inputCopy, mod)); } else { newMods.add(mod); } } } outputMods = newMods; } LOTREnchantmentHelper.setEnchantList(inputCopy, outputMods); } if (combineCost > 0) combining = true; int numEnchants = 0; for (Object obj : inputEnchants.keySet()) { int enchID = ((Integer)obj).intValue(); Enchantment ench = Enchantment.enchantmentsList[enchID]; int enchLevel = ((Integer)inputEnchants.get(Integer.valueOf(enchID))).intValue(); numEnchants++; int costPerLevel = 0; int enchWeight = ench.getWeight(); if (enchWeight == 1) { costPerLevel = 8; } else if (enchWeight == 2) { costPerLevel = 4; } else if (enchWeight == 5) { costPerLevel = 2; } else if (enchWeight == 10) { costPerLevel = 1; } baseAnvilCost += numEnchants + enchLevel * costPerLevel; } if (enchantingWithBook && !inputCopy.getItem().isBookEnchantable(inputCopy, combinerItem)) inputCopy = null; for (LOTREnchantment mod : inputModifiers) { if (mod.isBeneficial()) baseAnvilCost += Math.max(1, (int)mod.getValueModifier()); } if (inputCopy.isItemStackDamageable()) { boolean canRepair = false; int availableMaterials = 0; if (this.isTrader) { canRepair = (getTraderMaterialPrice(inputItem) > 0.0F); availableMaterials = Integer.MAX_VALUE; } else { canRepair = (materialItem != null && isRepairMaterial(inputItem, materialItem)); if (materialItem != null) availableMaterials = materialItem.stackSize - combineCost - renameCost; } int oneItemRepair = Math.min(inputCopy.getItemDamageForDisplay(), inputCopy.getMaxDamage() / 4); if (canRepair && availableMaterials > 0 && oneItemRepair > 0) { availableMaterials -= baseAnvilCost; if (availableMaterials > 0) { int usedMaterials = 0; while (oneItemRepair > 0 && usedMaterials < availableMaterials) { int newDamage = inputCopy.getItemDamageForDisplay() - oneItemRepair; inputCopy.setItemDamage(newDamage); oneItemRepair = Math.min(inputCopy.getItemDamageForDisplay(), inputCopy.getMaxDamage() / 4); usedMaterials++; } repairCost += usedMaterials; } else if (!nameChange && !combining) { repairCost = 1; int newDamage = inputCopy.getItemDamageForDisplay() - oneItemRepair; inputCopy.setItemDamage(newDamage); } } } boolean repairing = (repairCost > 0); if (combining || repairing) { this.materialCost = baseAnvilCost; this.materialCost += combineCost + repairCost; } else { this.materialCost = 0; } this.materialCost += renameCost; if (inputCopy != null) { int nextAnvilCost = LOTREnchantmentHelper.getAnvilCost(inputItem); if (combinerItem != null) { int combinerAnvilCost = LOTREnchantmentHelper.getAnvilCost(combinerItem); nextAnvilCost = Math.max(nextAnvilCost, combinerAnvilCost); } if (combining) { nextAnvilCost += 2; } else if (repairing) { nextAnvilCost++; } nextAnvilCost = Math.max(nextAnvilCost, 0); if (nextAnvilCost > 0) LOTREnchantmentHelper.setAnvilCost(inputCopy, nextAnvilCost); } if (LOTREnchantmentHelper.isReforgeable(inputItem)) { this.reforgeCost = 2; if (inputItem.getItem() instanceof ItemArmor) this.reforgeCost = 3; if (inputItem.isItemStackDamageable()) { ItemStack reforgeCopy = inputItem.copy(); int oneItemRepair = Math.min(reforgeCopy.getItemDamageForDisplay(), reforgeCopy.getMaxDamage() / 4); if (oneItemRepair > 0) { int usedMaterials = 0; while (oneItemRepair > 0) { int newDamage = reforgeCopy.getItemDamageForDisplay() - oneItemRepair; reforgeCopy.setItemDamage(newDamage); oneItemRepair = Math.min(reforgeCopy.getItemDamageForDisplay(), reforgeCopy.getMaxDamage() / 4); usedMaterials++; } this.reforgeCost += usedMaterials; } } this.engraveOwnerCost = 2; } else { this.reforgeCost = 0; this.engraveOwnerCost = 0; } if (isRepairMaterial(inputItem, new ItemStack(Items.string))) { int stringFactor = 3; this.materialCost *= stringFactor; this.reforgeCost *= stringFactor; this.engraveOwnerCost *= stringFactor; } if (this.isTrader) { boolean isCommonRenameOnly = (nameChange && this.materialCost == 0); float materialPrice = getTraderMaterialPrice(inputItem); if (materialPrice > 0.0F) { this.materialCost = Math.round(this.materialCost * materialPrice); this.materialCost = Math.max(this.materialCost, 1); this.reforgeCost = Math.round(this.reforgeCost * materialPrice); this.reforgeCost = Math.max(this.reforgeCost, 1); this.engraveOwnerCost = Math.round(this.engraveOwnerCost * materialPrice); this.engraveOwnerCost = Math.max(this.engraveOwnerCost, 1); if (this.theTrader instanceof LOTREntityScrapTrader) { this.materialCost = MathHelper.ceiling_float_int(this.materialCost * 0.5F); this.materialCost = Math.max(this.materialCost, 1); this.reforgeCost = MathHelper.ceiling_float_int(this.reforgeCost * 0.5F); this.reforgeCost = Math.max(this.reforgeCost, 1); this.engraveOwnerCost = MathHelper.ceiling_float_int(this.engraveOwnerCost * 0.5F); this.engraveOwnerCost = Math.max(this.engraveOwnerCost, 1); } } else if (!isCommonRenameOnly) { this.invOutput.setInventorySlotContents(0, null); this.materialCost = 0; this.reforgeCost = 0; this.engraveOwnerCost = 0; return; } } if (combining || repairing || nameChange || alteringNameColor) { this.invOutput.setInventorySlotContents(0, inputCopy); } else { this.invOutput.setInventorySlotContents(0, null); this.materialCost = 0; } detectAndSendChanges(); } } }