diff --git a/src/main/java/com/zivilon/cinder_loe/mixins/MixinLOTRContainerAnvil.java b/src/main/java/com/zivilon/cinder_loe/mixins/MixinLOTRContainerAnvil.java index a4e5884..a06af28 100644 --- a/src/main/java/com/zivilon/cinder_loe/mixins/MixinLOTRContainerAnvil.java +++ b/src/main/java/com/zivilon/cinder_loe/mixins/MixinLOTRContainerAnvil.java @@ -2,23 +2,88 @@ 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.inventory.LOTRContainerAnvil; +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 class MixinLOTRContainerAnvil { +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 @@ -75,7 +140,7 @@ public class MixinLOTRContainerAnvil { return (materialItem.getItem() == Items.iron_ingot); if (armorMaterial == CinderLoE.MATERIAL_BONEMOLD.toArmorMaterial()) return (materialItem.getItem() == CinderLoE.bonemold); - if (armorMaterial == CinderLoE.MATERIAL_RHUDUAR.toArmorMaterial()) + if (armorMaterial == CinderLoE.MATERIAL_RHUDAUR.toArmorMaterial()) return (materialItem.getItem() == Items.iron_ingot); if (armorMaterial == CinderLoE.MATERIAL_JADE.toArmorMaterial()) return (materialItem.getItem() == LOTRMod.emerald); @@ -83,4 +148,371 @@ public class MixinLOTRContainerAnvil { 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.repairKit) { + 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.repairKit) { + List repairedMods = new ArrayList(); + for (LOTREnchantment mod : outputMods) { + if (Utilities.isBadEnch(mod)) { + combineCost += 2; + } else { + repairedMods.add(mod); + } + } + outputMods = repairedMods; + } + 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(); + } + } } diff --git a/src/main/java/com/zivilon/cinder_loe/mixins/MixinLOTREnchantment.java b/src/main/java/com/zivilon/cinder_loe/mixins/MixinLOTREnchantment.java index b6bb4b7..aa9678f 100644 --- a/src/main/java/com/zivilon/cinder_loe/mixins/MixinLOTREnchantment.java +++ b/src/main/java/com/zivilon/cinder_loe/mixins/MixinLOTREnchantment.java @@ -1,11 +1,14 @@ package com.zivilon.cinder_loe.mixins; import com.zivilon.cinder_loe.enchants.LOTREnchantmentWeakProtectionRanged; +import com.zivilon.cinder_loe.util.Utilities; import lotr.common.enchant.LOTREnchantment; import lotr.common.enchant.LOTREnchantmentDamage; import lotr.common.enchant.LOTREnchantmentProtectionRanged; import lotr.common.enchant.LOTREnchantmentRangedDamage; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -15,6 +18,9 @@ import java.util.Map; @Mixin(LOTREnchantment.class) public class MixinLOTREnchantment { + @Shadow + private boolean bypassAnvilLimit; + @Inject(method = "", at = @At("TAIL")) private static void onStaticInit(CallbackInfo ci) { // Add your new enchantments here @@ -44,5 +50,16 @@ public class MixinLOTREnchantment { } } + /** + * @author Shinare + * @reason Bad enchantments will not count towards 3 modifier limit now + **/ + @Overwrite(remap = false) + public boolean bypassAnvilLimit() { + if (Utilities.isBadEnch((LOTREnchantment)(Object)this)) + return true; + return this.bypassAnvilLimit; + } + } diff --git a/src/main/java/com/zivilon/cinder_loe/util/Utilities.java b/src/main/java/com/zivilon/cinder_loe/util/Utilities.java index 92b95a1..9e20475 100644 --- a/src/main/java/com/zivilon/cinder_loe/util/Utilities.java +++ b/src/main/java/com/zivilon/cinder_loe/util/Utilities.java @@ -15,6 +15,8 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.UUID; import java.util.Vector; +import java.util.ArrayList; +import java.util.List; import lotr.common.LOTRCreativeTabs; import lotr.common.world.biome.LOTRBiome; @@ -47,6 +49,24 @@ public class Utilities { public static int[] LOTRIntCache = null; public static LOTRBiome reflected_river; public static LOTRCreativeTabs reflected_tab_block; + public static List badEnchants = new ArrayList<>(); + + static { + badEnchants.add("weak1"); + badEnchants.add("weak2"); + badEnchants.add("weak3"); + badEnchants.add("weak4"); + badEnchants.add("meleeSlow1"); + badEnchants.add("meleeUnreach1"); + badEnchants.add("toolSlow1"); + badEnchants.add("protectWeak1"); + badEnchants.add("protectWeak2"); + badEnchants.add("rangedWeak1"); + badEnchants.add("rangedWeak2"); + badEnchants.add("rangedWeak3"); + badEnchants.add("protectRangedWeak1"); + badEnchants.add("protectRangedWeak2"); + } public static void initialize_reflects() { try { @@ -292,4 +312,13 @@ public class Utilities { // Ensure the motion is applied target.velocityChanged = true; } + + public static boolean isBadEnch(LOTREnchantment ench) { + if (ench == null) return false; + String ench_name = ench.enchantName; + if (badEnchants.contains(ench_name)) { + return true; + } + return false; + } }