From 85d9f8a42b6ed1483e89cd4a2fb2e2b5f6852785 Mon Sep 17 00:00:00 2001 From: Alexandra-Myers Date: Sat, 6 Apr 2024 23:05:45 -0400 Subject: [PATCH] Combatify 1.2.0 1.20.5 Beta 4 - Armour stuffs --- build.gradle | 2 +- gradle.properties | 2 +- .../config/ConfigurableItemData.java | 17 +- .../atlas/combatify/config/ItemConfig.java | 279 ++++++++++++++++-- .../combatify/extensions/ItemExtensions.java | 9 + .../combatify/item/TieredShieldItem.java | 2 +- .../combatify/mixin/CombatRulesMixin.java | 29 ++ .../combatify/mixin/ElytraItemMixin.java | 27 ++ .../net/atlas/combatify/mixin/ItemMixin.java | 46 +-- .../combatify/mixin/LivingEntityMixin.java | 2 +- .../atlas/combatify/mixin/MaceItemMixin.java | 9 + .../combatify/mixin/PlayerHeadItemMixin.java | 7 +- .../util/CurrentShieldBlockingType.java | 6 - .../atlas/combatify/util/MethodHandler.java | 62 +++- .../combatify/util/ShieldBlockingType.java | 6 - src/main/resources/combatify.mixins.json | 2 + 16 files changed, 436 insertions(+), 71 deletions(-) create mode 100644 src/main/java/net/atlas/combatify/mixin/CombatRulesMixin.java create mode 100644 src/main/java/net/atlas/combatify/mixin/ElytraItemMixin.java diff --git a/build.gradle b/build.gradle index 01effc3..b4a5573 100644 --- a/build.gradle +++ b/build.gradle @@ -72,7 +72,7 @@ processResources { tasks.withType(JavaCompile).configureEach { it.options.encoding = "UTF-8" - // Minecraft 1.18 (1.18-pre2) upwards uses Java 17. + // Minecraft 1.20.5 (24w14a) upwards uses Java 21. it.options.release = 21 } diff --git a/gradle.properties b/gradle.properties index e1df42f..eaa9faf 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ org.gradle.jvmargs = -Xmx3G org.gradle.parallel = true # Mod Properties -version = 1.20.5-1.2.0-BETA-3 +version = 1.20.5-1.2.0-BETA-4 maven_group = net.atlas archives_base_name = combatify owo_version=0.11.0+1.20 diff --git a/src/main/java/net/atlas/combatify/config/ConfigurableItemData.java b/src/main/java/net/atlas/combatify/config/ConfigurableItemData.java index b2696e8..5b3e165 100644 --- a/src/main/java/net/atlas/combatify/config/ConfigurableItemData.java +++ b/src/main/java/net/atlas/combatify/config/ConfigurableItemData.java @@ -3,6 +3,7 @@ import net.atlas.combatify.item.WeaponType; import net.atlas.combatify.util.BlockingType; import net.minecraft.world.item.Tier; +import net.minecraft.world.item.crafting.Ingredient; public class ConfigurableItemData { public final Double damage; @@ -25,7 +26,11 @@ public class ConfigurableItemData { public final Double piercingLevel; public final Boolean canSweep; public final Tier tier; - ConfigurableItemData(Double attackDamage, Double attackSpeed, Double attackReach, Double chargedReach, Integer stackSize, Integer cooldown, Boolean cooldownAfter, WeaponType weaponType, BlockingType blockingType, Double blockStrength, Double blockKbRes, Integer enchantability, Boolean isEnchantable, Boolean hasSwordEnchants, Boolean isPrimaryForSwordEnchants, Integer useDuration, Double piercingLevel, Boolean canSweep, Tier tier, Integer durability) { + public final Integer defense; + public final Double toughness; + public final Double armourKbRes; + public final Ingredient repairIngredient; + ConfigurableItemData(Double attackDamage, Double attackSpeed, Double attackReach, Double chargedReach, Integer stackSize, Integer cooldown, Boolean cooldownAfter, WeaponType weaponType, BlockingType blockingType, Double blockStrength, Double blockKbRes, Integer enchantability, Boolean isEnchantable, Boolean hasSwordEnchants, Boolean isPrimaryForSwordEnchants, Integer useDuration, Double piercingLevel, Boolean canSweep, Tier tier, Integer durability, Integer defense, Double toughness, Double armourKbRes, Ingredient repairIngredient) { damage = clamp(attackDamage, -10, 1000); speed = clamp(attackSpeed, -1, 7.5); reach = clamp(attackReach, 0, 1024); @@ -46,6 +51,10 @@ public class ConfigurableItemData { this.piercingLevel = clamp(piercingLevel, 0, 1); this.canSweep = canSweep; this.tier = tier; + this.defense = max(defense, 1); + this.toughness = max(toughness, 0); + this.armourKbRes = clamp(armourKbRes, 0, 1); + this.repairIngredient = repairIngredient; } public static Integer max(Integer value, int min) { if (value == null) @@ -53,6 +62,12 @@ public static Integer max(Integer value, int min) { return Math.max(value, min); } + public static Double max(Double value, double min) { + if (value == null) + return null; + return Math.max(value, min); + } + public static Integer clamp(Integer value, int min, int max) { if (value == null) return null; diff --git a/src/main/java/net/atlas/combatify/config/ItemConfig.java b/src/main/java/net/atlas/combatify/config/ItemConfig.java index abb9ee9..1df529f 100644 --- a/src/main/java/net/atlas/combatify/config/ItemConfig.java +++ b/src/main/java/net/atlas/combatify/config/ItemConfig.java @@ -17,20 +17,16 @@ import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.GsonHelper; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.Items; -import net.minecraft.world.item.Tier; -import net.minecraft.world.item.Tiers; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.item.*; import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.item.enchantment.EnchantmentHelper; import org.jetbrains.annotations.NotNull; import java.io.InputStream; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; -import java.util.Objects; +import java.util.*; import static net.atlas.combatify.Combatify.*; @@ -38,6 +34,7 @@ public class ItemConfig extends AtlasConfig { public Map configuredItems; public Map configuredWeapons; public BiMap tiers; + public Formula armourCalcs = null; public ItemConfig() { super(id("combatify-items")); @@ -148,6 +145,8 @@ protected void loadExtra(JsonObject object) { throw new ReportedException(CrashReport.forThrowable(new IllegalStateException("Not a JSON Object: " + jsonElement + " this may be due to an incorrectly written config file."), "Configuring Items")); }); } + if (object.has("armor_calculation")) + armourCalcs = new Formula(getString(object, "armor_calculation")); } @Override protected InputStream getDefaultedConfig() { @@ -166,28 +165,33 @@ public void alertChange(ConfigValue tConfigValue, T newValue) { } - public static String getString(JsonObject element, String name) { - return element.get(name).getAsString(); + public static String getString(JsonObject object, String name) { + return object.get(name).getAsString(); } - public static Integer getInt(JsonObject element, String name) { - return element.get(name).getAsInt(); + public static Integer getInt(JsonObject object, String name) { + return object.get(name).getAsInt(); } - public static Float getFloat(JsonObject element, String name) { - return element.get(name).getAsFloat(); + public static Integer getIntWithFallback(JsonObject object, String name, String fallback) { + if (!object.has(name)) + return object.get(fallback).getAsInt(); + return object.get(name).getAsInt(); } - public static Double getDouble(JsonObject element, String name) { - return element.get(name).getAsDouble(); + public static Float getFloat(JsonObject object, String name) { + return object.get(name).getAsFloat(); } - public static Boolean getBoolean(JsonObject element, String name) { - return element.get(name).getAsBoolean(); + + public static Double getDouble(JsonObject object, String name) { + return object.get(name).getAsDouble(); + } + public static Boolean getBoolean(JsonObject object, String name) { + return object.get(name).getAsBoolean(); } public static Item itemFromJson(JsonObject jsonObject) { - String string = GsonHelper.getAsString(jsonObject, "name"); - return itemFromName(string); + return itemFromName(GsonHelper.getAsString(jsonObject, "name")); } public static Item itemFromName(String string) { @@ -473,6 +477,11 @@ public int getEnchantmentValue() { int canSweepAsInt = buf1.readInt(); Boolean canSweep = null; Tier tier = getTier(buf1.readUtf()); + Integer defense = buf1.readInt(); + Double toughness = buf1.readDouble(); + Double armourKbRes = buf1.readDouble(); + String repairIngredient = buf1.readUtf(); + Ingredient ingredient = Objects.equals(repairIngredient, "empty") ? null : Ingredient.of(BuiltInRegistries.ITEM.get(new ResourceLocation(repairIngredient))); if (damage == -10) damage = null; if (speed == -10) @@ -507,7 +516,13 @@ public int getEnchantmentValue() { canSweep = canSweepAsInt == 1; if (registeredWeaponTypes.containsKey(weaponType)) type = WeaponType.fromID(weaponType); - return new ConfigurableItemData(damage, speed, reach, chargedReach, stackSize, cooldown, cooldownAfter, type, bType, blockStrength, blockKbRes, enchantlevel, isEnchantable, hasSwordEnchants, isPrimaryForSwordEnchants, useDuration, piercingLevel, canSweep, tier, durability); + if (defense == -10) + defense = null; + if (toughness == -10) + toughness = null; + if (armourKbRes == -10) + armourKbRes = null; + return new ConfigurableItemData(damage, speed, reach, chargedReach, stackSize, cooldown, cooldownAfter, type, bType, blockStrength, blockKbRes, enchantlevel, isEnchantable, hasSwordEnchants, isPrimaryForSwordEnchants, useDuration, piercingLevel, canSweep, tier, durability, defense, toughness, armourKbRes, ingredient); }); configuredWeapons = buf.readMap(buf1 -> WeaponType.fromID(buf1.readUtf()), buf1 -> { Double damageOffset = buf1.readDouble(); @@ -542,6 +557,11 @@ public int getEnchantmentValue() { canSweep = canSweepAsInt == 1; return new ConfigurableWeaponData(damageOffset, speed, reach, chargedReach, tierable, bType, hasSwordEnchants, isPrimaryForSwordEnchants, piercingLevel, canSweep); }); + String formula = buf.readUtf(); + if (formula.equals("empty")) + armourCalcs = null; + else + armourCalcs = new Formula(formula); return this; } @@ -630,6 +650,10 @@ public void saveToNetwork(FriendlyByteBuf buf) { buf12.writeDouble(configurableItemData.piercingLevel == null ? -10 : configurableItemData.piercingLevel); buf12.writeInt(configurableItemData.canSweep == null ? -10 : configurableItemData.canSweep ? 1 : 0); buf12.writeUtf(configurableItemData.tier == null ? "empty" : getTierName(configurableItemData.tier)); + buf12.writeInt(configurableItemData.defense == null ? -10 : configurableItemData.defense); + buf12.writeDouble(configurableItemData.toughness == null ? -10 : configurableItemData.toughness); + buf12.writeDouble(configurableItemData.armourKbRes == null ? -10 : configurableItemData.armourKbRes); + buf12.writeUtf(configurableItemData.repairIngredient == null ? "empty" : BuiltInRegistries.ITEM.getKey(configurableItemData.repairIngredient.getItems()[0].getItem()).toString()); }); buf.writeMap(configuredWeapons, (buf1, type) -> buf1.writeUtf(type.name), (buf12, configurableWeaponData) -> { buf12.writeDouble(configurableWeaponData.damageOffset == null ? -10 : configurableWeaponData.damageOffset); @@ -643,6 +667,7 @@ public void saveToNetwork(FriendlyByteBuf buf) { buf12.writeDouble(configurableWeaponData.piercingLevel == null ? -10 : configurableWeaponData.piercingLevel); buf12.writeInt(configurableWeaponData.canSweep == null ? -10 : configurableWeaponData.canSweep ? 1 : 0); }); + buf.writeUtf(armourCalcs == null ? "empty" : armourCalcs.written); } @Override @@ -673,6 +698,10 @@ public void parseItemConfig(Item item, JsonObject jsonObject) { Boolean canSweep = null; Tier tier = null; Integer durability = null; + Integer defense = null; + Double toughness = null; + Double armourKbRes = null; + Ingredient ingredient = null; if (configuredItems.containsKey(item)) { ConfigurableItemData oldData = configuredItems.get(item); damage = oldData.damage; @@ -755,11 +784,213 @@ public void parseItemConfig(Item item, JsonObject jsonObject) { canSweep = getBoolean(jsonObject, "can_sweep"); if (jsonObject.has("tier")) tier = getTier(getString(jsonObject, "tier")); - if (jsonObject.has("durability")) - durability = getInt(jsonObject, "durability"); + if (jsonObject.has("durability")) { + JsonElement durabilityE = jsonObject.get("durability"); + if (durabilityE instanceof JsonObject durabilityO) { + if (!durabilityO.has("any")) + throw new ReportedException(CrashReport.forThrowable(new JsonSyntaxException("The JSON must contain the integer 'any' when armour is configured!"), "Applying Item Durability")); + if (item instanceof ArmorItem armorItem) { + durability = getIntWithFallback(durabilityO, armorItem.getType().getName(), "any"); + } else durability = getInt(durabilityO, "any"); + } else durability = durabilityE.getAsInt(); + } if (jsonObject.has("sword_enchants_from_enchanting")) isPrimaryForSwordEnchants = getBoolean(jsonObject, "sword_enchants_from_enchanting"); - ConfigurableItemData configurableItemData = new ConfigurableItemData(damage, speed, reach, chargedReach, stack_size, cooldown, cooldownAfterUse, type, blockingType, blockStrength, blockKbRes, enchantment_level, isEnchantable, hasSwordEnchants, isPrimaryForSwordEnchants, useDuration, piercingLevel, canSweep, tier, durability); + if (jsonObject.has("armor")) { + JsonElement defenseE = jsonObject.get("armor"); + if (defenseE instanceof JsonObject defenseO) { + if (!defenseO.has("any")) + throw new ReportedException(CrashReport.forThrowable(new JsonSyntaxException("The JSON must contain the integer 'any' when armour is configured!"), "Applying Item Defense")); + if (item instanceof ArmorItem armorItem) { + defense = getIntWithFallback(defenseO, armorItem.getType().getName(), "any"); + } else defense = getInt(defenseO, "any"); + } else defense = defenseE.getAsInt(); + } + if (jsonObject.has("armor_toughness")) + toughness = getDouble(jsonObject, "armor_toughness"); + if (jsonObject.has("armor_knockback_resistance")) + armourKbRes = getDouble(jsonObject, "armor_knockback_resistance"); + if (jsonObject.has("repair_ingredient")) + ingredient = Ingredient.of(itemFromName(getString(jsonObject, "repair_ingredient"))); + ConfigurableItemData configurableItemData = new ConfigurableItemData(damage, speed, reach, chargedReach, stack_size, cooldown, cooldownAfterUse, type, blockingType, blockStrength, blockKbRes, enchantment_level, isEnchantable, hasSwordEnchants, isPrimaryForSwordEnchants, useDuration, piercingLevel, canSweep, tier, durability, defense, toughness, armourKbRes, ingredient); configuredItems.put(item, configurableItemData); } + public record Formula(String written) { + public float armourCalcs(float amount, DamageSource damageSource, float armour, float armourToughness) { + String armourFormula = written.split("enchMul", 1)[0]; + armourFormula = armourFormula.replaceAll("D", String.valueOf(amount)).replaceAll("P", String.valueOf(armour)).replaceAll("T", String.valueOf(armourToughness)); + float result = solveFormula(armourFormula); + result = 1.0F - EnchantmentHelper.calculateArmorBreach(damageSource.getEntity(), result); + return amount * result; + } + public float enchantCalcs(float amount, float enchantLevel) { + String enchantFormula = written.split("enchMul", 1)[1]; + enchantFormula = enchantFormula.replaceAll("D", String.valueOf(amount)).replaceAll("E", String.valueOf(enchantLevel)); + float result = solveFormula(enchantFormula); + return amount * result; + } + public float solveFormula(String formula) { + if (!formula.contains("(")) + return solveInner(formula); + float res = 0; + String par = formula; + while (par.contains("(")) { + par = simplifyParenthesis(par, 0); + } + return res; + } + public String simplifyParenthesis(String par, int recursion) { + if (recursion > 5) + throw new ReportedException(CrashReport.forThrowable(new IllegalStateException("Cannot have more than 5 mins/maxes inside of each other!"), "Handling armour calculations")); + String innermost = par.transform(string -> string.substring(string.lastIndexOf('(') + 1, string.indexOf(')', string.lastIndexOf('(')) - 1)); + if (par.contains("min")) { + String[] min = par.split("min\\(", 1)[1].split("\\)", 1)[0].split(","); + float[] minf = new float[2]; + for (int i = 0; i < min.length; i++) { + String minSt = min[i]; + while (minSt.contains("(")) { + minSt = simplifyParenthesis(minSt, recursion + 1); + } + minf[i] = solveInner(minSt); + } + par = par.replace("min(" + min[0] + "," + min[1] + ")", String.valueOf(Math.min(minf[0], minf[1]))); + } else if (par.contains("max")) { + String[] max = par.split("max\\(", 1)[1].split("\\)", 1)[0].split(","); + float[] maxf = new float[2]; + for (int i = 0; i < max.length; i++) { + String maxSt = max[i]; + while (maxSt.contains("(")) { + maxSt = simplifyParenthesis(maxSt, recursion + 1); + } + maxf[i] = solveInner(maxSt); + } + par = par.replace("max(" + max[0] + "," + max[1] + ")", String.valueOf(Math.max(maxf[0], maxf[1]))); + } else + par = par.replace("(" + innermost + ")", String.valueOf(solveInner(innermost))); + return par; + } + public float solveInner(String par) { + while (par.contains("^")) { + String[] pow = par.split("\\^", 1); + double[] powSides = new double[2]; + if (!pow[0].contains("*") && !pow[0].contains("/") && !pow[0].contains("+") && !pow[0].contains("-")) { + powSides[0] = Double.parseDouble(pow[0]); + if (pow[1].contains("+") || pow[1].contains("-") || pow[1].contains("*") || pow[1].contains("/")) { + int pIndex = pow[1].indexOf("+"); + int mIndex = pow[1].indexOf("-"); + int muIndex = pow[1].indexOf("*"); + int dIndex = pow[1].indexOf("/"); + int lIndex = min(min(pIndex, mIndex), min(muIndex, dIndex)); + powSides[1] = Double.parseDouble(pow[1].substring(0, lIndex)); + } else powSides[1] = Double.parseDouble(pow[1]); + } else { + int pIndex0 = pow[0].indexOf("+"); + int mIndex0 = pow[0].indexOf("-"); + int muIndex0 = pow[0].indexOf("*"); + int dIndex0 = pow[0].indexOf("/"); + int lIndex0 = min(min(pIndex0, mIndex0), min(muIndex0, dIndex0)); + powSides[0] = Double.parseDouble(pow[0].substring(lIndex0)); + if (pow[1].contains("+") || pow[1].contains("-") || pow[1].contains("*") || pow[1].contains("/")) { + int pIndex = pow[1].indexOf("+"); + int mIndex = pow[1].indexOf("-"); + int muIndex = pow[1].indexOf("*"); + int dIndex = pow[1].indexOf("/"); + int lIndex = min(min(pIndex, mIndex), min(muIndex, dIndex)); + powSides[1] = Double.parseDouble(pow[1].substring(0, lIndex)); + } else powSides[1] = Double.parseDouble(pow[1]); + } + par = par.replace(pow[0] + "^" + pow[1], String.valueOf(Math.pow(powSides[0], powSides[1]))); + } + while (par.contains("*") || par.contains("/")) { + boolean divide = par.indexOf("*") > par.indexOf("/"); + if (divide) { + String[] div = par.split("/", 1); + double[] divSides = new double[2]; + if (!div[0].contains("+") && !div[0].contains("-")) { + divSides[0] = Double.parseDouble(div[0]); + if (div[1].contains("+") || div[1].contains("-") || div[1].contains("*")) { + int pIndex = div[1].indexOf("+"); + int mIndex = div[1].indexOf("-"); + int muIndex = div[1].indexOf("*"); + int lIndex = min(min(pIndex, mIndex), muIndex); + divSides[1] = Double.parseDouble(div[1].substring(0, lIndex)); + } else divSides[1] = Double.parseDouble(div[1]); + } else { + int pIndex0 = div[0].indexOf("+"); + int mIndex0 = div[0].indexOf("-"); + int lIndex0 = min(pIndex0, mIndex0); + divSides[0] = Double.parseDouble(div[0].substring(lIndex0)); + if (div[1].contains("+") || div[1].contains("-") || div[1].contains("*")) { + int pIndex = div[1].indexOf("+"); + int mIndex = div[1].indexOf("-"); + int muIndex = div[1].indexOf("*"); + int lIndex = min(min(pIndex, mIndex), muIndex); + divSides[1] = Double.parseDouble(div[1].substring(0, lIndex)); + } else divSides[1] = Double.parseDouble(div[1]); + } + par = par.replace(div[0] + "/" + div[1], String.valueOf(divSides[0] / divSides[1])); + } else { + String[] mul = par.split("\\*", 1); + double[] mulSides = new double[2]; + if (!mul[0].contains("+") && !mul[0].contains("-")) { + mulSides[0] = Double.parseDouble(mul[0]); + if (mul[1].contains("+") || mul[1].contains("-") || mul[1].contains("/")) { + int pIndex = mul[1].indexOf("+"); + int mIndex = mul[1].indexOf("-"); + int dIndex = mul[1].indexOf("/"); + int lIndex = min(min(pIndex, mIndex), dIndex); + mulSides[1] = Double.parseDouble(mul[1].substring(0, lIndex)); + } else mulSides[1] = Double.parseDouble(mul[1]); + } else { + int pIndex0 = mul[0].indexOf("+"); + int mIndex0 = mul[0].indexOf("-"); + int lIndex0 = min(pIndex0, mIndex0); + mulSides[0] = Double.parseDouble(mul[0].substring(lIndex0)); + if (mul[1].contains("+") || mul[1].contains("-") || mul[1].contains("/")) { + int pIndex = mul[1].indexOf("+"); + int mIndex = mul[1].indexOf("-"); + int dIndex = mul[1].indexOf("/"); + int lIndex = min(min(pIndex, mIndex), dIndex); + mulSides[1] = Double.parseDouble(mul[1].substring(0, lIndex)); + } else mulSides[1] = Double.parseDouble(mul[1]); + } + par = par.replace(mul[0] + "*" + mul[1], String.valueOf(mulSides[0] * mulSides[1])); + } + } + while (par.contains("+") || par.contains("-")) { + boolean subtract = par.indexOf("+") > par.indexOf("-"); + if (subtract) { + String[] sub = par.split("-", 1); + double[] subSides = new double[2]; + subSides[0] = Double.parseDouble(sub[0]); + if (sub[1].contains("+") || sub[1].contains("-")) { + int pIndex = sub[1].indexOf("+"); + int mIndex = sub[1].indexOf("-"); + int lIndex = min(pIndex, mIndex); + subSides[1] = Double.parseDouble(sub[1].substring(0, lIndex)); + } else subSides[1] = Double.parseDouble(sub[1]); + par = par.replace(sub[0] + "-" + sub[1], String.valueOf(subSides[0] - subSides[1])); + } else { + String[] add = par.split("\\+", 1); + double[] addSides = new double[2]; + addSides[0] = Double.parseDouble(add[0]); + if (add[1].contains("+") || add[1].contains("-")) { + int pIndex = add[1].indexOf("+"); + int mIndex = add[1].indexOf("-"); + int lIndex = min(pIndex, mIndex); + addSides[1] = Double.parseDouble(add[1].substring(0, lIndex)); + } else addSides[1] = Double.parseDouble(add[1]); + par = par.replace(add[0] + "+" + add[1], String.valueOf(addSides[0] + addSides[1])); + } + } + return Float.parseFloat(par); + } + public static int min(int val, int comp) { + if (comp == -1) + comp = Integer.MAX_VALUE; + if (val == -1) + val = Integer.MAX_VALUE; + return Math.min(val, comp); + } + } } diff --git a/src/main/java/net/atlas/combatify/extensions/ItemExtensions.java b/src/main/java/net/atlas/combatify/extensions/ItemExtensions.java index 9acb31d..a4656cc 100644 --- a/src/main/java/net/atlas/combatify/extensions/ItemExtensions.java +++ b/src/main/java/net/atlas/combatify/extensions/ItemExtensions.java @@ -5,6 +5,7 @@ import net.atlas.combatify.item.WeaponType; import net.atlas.combatify.util.BlockingType; import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Tier; import net.minecraft.world.item.Tiers; import net.minecraft.world.item.component.ItemAttributeModifiers; @@ -85,4 +86,12 @@ default Tier getTierFromConfig() { return Combatify.ITEMS.configuredItems.get(self()).tier; return null; } + default boolean canRepairThroughConfig(ItemStack stack) { + if (Combatify.ITEMS != null && Combatify.ITEMS.configuredItems.containsKey(self())) { + ConfigurableItemData configurableItemData = Combatify.ITEMS.configuredItems.get(self()); + if (configurableItemData.repairIngredient != null) + return configurableItemData.repairIngredient.test(stack); + } + return false; + } } diff --git a/src/main/java/net/atlas/combatify/item/TieredShieldItem.java b/src/main/java/net/atlas/combatify/item/TieredShieldItem.java index 8053169..aca3b8c 100644 --- a/src/main/java/net/atlas/combatify/item/TieredShieldItem.java +++ b/src/main/java/net/atlas/combatify/item/TieredShieldItem.java @@ -44,7 +44,7 @@ public int getEnchantmentValue() { } public boolean isValidRepairItem(ItemStack itemStack, ItemStack itemStack2) { - return getConfigTier().getRepairIngredient().test(itemStack2) || super.isValidRepairItem(itemStack, itemStack2); + return getConfigTier().getRepairIngredient().test(itemStack2) || canRepairThroughConfig(itemStack2); } @Override diff --git a/src/main/java/net/atlas/combatify/mixin/CombatRulesMixin.java b/src/main/java/net/atlas/combatify/mixin/CombatRulesMixin.java new file mode 100644 index 0000000..7fdaf2e --- /dev/null +++ b/src/main/java/net/atlas/combatify/mixin/CombatRulesMixin.java @@ -0,0 +1,29 @@ +package net.atlas.combatify.mixin; + +import com.llamalad7.mixinextras.injector.ModifyReturnValue; +import com.llamalad7.mixinextras.sugar.Local; +import net.atlas.combatify.Combatify; +import net.minecraft.world.damagesource.CombatRules; +import net.minecraft.world.damagesource.DamageSource; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(CombatRules.class) +public class CombatRulesMixin { + @ModifyReturnValue(method = "getDamageAfterAbsorb", at = @At("RETURN")) + private static float changeArmourCalcs(float original, @Local(ordinal = 0, argsOnly = true) float amount, @Local(ordinal = 0, argsOnly = true) DamageSource source, @Local(ordinal = 1, argsOnly = true) float armour, @Local(ordinal = 2, argsOnly = true) float toughness) { + if (Combatify.ITEMS != null && Combatify.ITEMS.armourCalcs != null) { + original = Combatify.ITEMS.armourCalcs.armourCalcs(amount, source, armour, toughness); + Combatify.LOGGER.info("Damage: " + amount + " Result: " + original); + } else + Combatify.LOGGER.info("armour formula is null"); + return original; + } + @ModifyReturnValue(method = "getDamageAfterMagicAbsorb", at = @At("RETURN")) + private static float changeEnchant(float original, @Local(ordinal = 0, argsOnly = true) float amount, @Local(ordinal = 1, argsOnly = true) float enchantLevel) { + if (Combatify.ITEMS != null && Combatify.ITEMS.armourCalcs != null) { + return Combatify.ITEMS.armourCalcs.enchantCalcs(amount, enchantLevel); + } + return original; + } +} diff --git a/src/main/java/net/atlas/combatify/mixin/ElytraItemMixin.java b/src/main/java/net/atlas/combatify/mixin/ElytraItemMixin.java new file mode 100644 index 0000000..029494f --- /dev/null +++ b/src/main/java/net/atlas/combatify/mixin/ElytraItemMixin.java @@ -0,0 +1,27 @@ +package net.atlas.combatify.mixin; + +import com.llamalad7.mixinextras.injector.ModifyReturnValue; +import com.llamalad7.mixinextras.sugar.Local; +import net.atlas.combatify.extensions.ItemExtensions; +import net.minecraft.world.item.ElytraItem; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(ElytraItem.class) +public class ElytraItemMixin extends Item implements ItemExtensions { + public ElytraItemMixin(Properties properties) { + super(properties); + } + + @ModifyReturnValue(method = "isValidRepairItem", at = @At(value = "RETURN")) + public boolean canRepair(boolean original, @Local(ordinal = 1, argsOnly = true) ItemStack stack) { + return original || canRepairThroughConfig(stack); + } + + @Override + public Item self() { + return this; + } +} diff --git a/src/main/java/net/atlas/combatify/mixin/ItemMixin.java b/src/main/java/net/atlas/combatify/mixin/ItemMixin.java index 2b7373e..43be67c 100644 --- a/src/main/java/net/atlas/combatify/mixin/ItemMixin.java +++ b/src/main/java/net/atlas/combatify/mixin/ItemMixin.java @@ -1,5 +1,7 @@ package net.atlas.combatify.mixin; +import com.llamalad7.mixinextras.injector.ModifyReturnValue; +import com.llamalad7.mixinextras.sugar.Local; import net.atlas.combatify.Combatify; import net.atlas.combatify.config.ConfigurableItemData; import net.atlas.combatify.extensions.ItemExtensions; @@ -34,6 +36,29 @@ public abstract class ItemMixin implements ItemExtensions { @Inject(method = "verifyComponentsAfterLoad", at = @At(value = "HEAD")) public void editModifiers(ItemStack itemStack, CallbackInfo ci) { + editModifiers(itemStack); + } + + @Override + public Item self() { + return Item.class.cast(this); + } + @Unique + public void setDurability(ItemStack stack, int value) { + if (self() instanceof TieredShieldItem) + value *= 2; + if (!stack.has(DataComponents.DAMAGE)) + stack.set(DataComponents.DAMAGE, 0); + if ((!components.has(DataComponents.MAX_DAMAGE) && !stack.has(DataComponents.MAX_DAMAGE)) || Objects.equals(components.get(DataComponents.MAX_DAMAGE), stack.get(DataComponents.MAX_DAMAGE))) { + stack.set(DataComponents.MAX_DAMAGE, value); + } + } + @ModifyReturnValue(method = "isValidRepairItem", at = @At(value = "RETURN")) + public boolean canRepair(boolean original, @Local(ordinal = 1, argsOnly = true) ItemStack stack) { + return original || canRepairThroughConfig(stack); + } + @Unique + public void editModifiers(ItemStack itemStack) { boolean maxDamageChanged = false; if (Combatify.ITEMS != null && Combatify.ITEMS.configuredItems.containsKey(self())) { ConfigurableItemData configurableItemData = Combatify.ITEMS.configuredItems.get(self()); @@ -46,15 +71,15 @@ public void editModifiers(ItemStack itemStack, CallbackInfo ci) { } if (maxStackSize != null && ((!components.has(DataComponents.MAX_STACK_SIZE) && !itemStack.has(DataComponents.MAX_STACK_SIZE)) - || Objects.equals(components.get(DataComponents.MAX_STACK_SIZE), itemStack.get(DataComponents.MAX_STACK_SIZE)))) { + || Objects.equals(components.get(DataComponents.MAX_STACK_SIZE), itemStack.get(DataComponents.MAX_STACK_SIZE)))) { itemStack.set(DataComponents.MAX_STACK_SIZE, maxStackSize); } if (tier != null && self() instanceof DiggerItem && Objects.equals(components.get(DataComponents.TOOL), itemStack.get(DataComponents.TOOL))) { Tool original = components.get(DataComponents.TOOL); AtomicReference tool = new AtomicReference<>(); - assert original != null; - original.rules().forEach(rule -> { + assert original != null; + original.rules().forEach(rule -> { if (rule.blocks() instanceof HolderSet.Named named) { tool.set(tier.createToolProperties(named.key())); } @@ -67,19 +92,4 @@ public void editModifiers(ItemStack itemStack, CallbackInfo ci) { setDurability(itemStack, getTierFromConfig().getUses()); MethodHandler.updateModifiers(itemStack); } - - @Override - public Item self() { - return Item.class.cast(this); - } - @Unique - public void setDurability(ItemStack stack, int value) { - if (self() instanceof TieredShieldItem) - value *= 2; - if (!stack.has(DataComponents.DAMAGE)) - stack.set(DataComponents.DAMAGE, 0); - if ((!components.has(DataComponents.MAX_DAMAGE) && !stack.has(DataComponents.MAX_DAMAGE)) || Objects.equals(components.get(DataComponents.MAX_DAMAGE), stack.get(DataComponents.MAX_DAMAGE))) { - stack.set(DataComponents.MAX_DAMAGE, value); - } - } } diff --git a/src/main/java/net/atlas/combatify/mixin/LivingEntityMixin.java b/src/main/java/net/atlas/combatify/mixin/LivingEntityMixin.java index c019bfb..f184be7 100644 --- a/src/main/java/net/atlas/combatify/mixin/LivingEntityMixin.java +++ b/src/main/java/net/atlas/combatify/mixin/LivingEntityMixin.java @@ -220,7 +220,7 @@ public void isDamageSourceBlocked(DamageSource source, CallbackInfoReturnable speed = new AtomicReference<>(); boolean modReach = false; AtomicReference reach = new AtomicReference<>(); + boolean modDefense = false; + AtomicReference defense = new AtomicReference<>(); + boolean modToughness = false; + AtomicReference toughness = new AtomicReference<>(); + boolean modKnockbackResistance = false; + AtomicReference knockbackResistance = new AtomicReference<>(); modifier.modifiers().forEach(entry -> { - boolean bl = entry.attribute().is(Attributes.ATTACK_DAMAGE) - || entry.attribute().is(Attributes.ATTACK_SPEED) - || entry.attribute().is(Attributes.ENTITY_INTERACTION_RANGE); - if (!bl) - builder.add(entry.attribute(), entry.modifier(), entry.slot()); - else if (entry.attribute().is(Attributes.ATTACK_DAMAGE)) + if (entry.attribute().is(Attributes.ATTACK_DAMAGE)) damage.set(entry); else if (entry.attribute().is(Attributes.ENTITY_INTERACTION_RANGE)) reach.set(entry); - else + else if (entry.attribute().is(Attributes.ATTACK_SPEED)) speed.set(entry); + else if (entry.attribute().is(Attributes.ARMOR)) + defense.set(entry); + else if (entry.attribute().is(Attributes.ARMOR_TOUGHNESS)) + toughness.set(entry); + else if (entry.attribute().is(Attributes.KNOCKBACK_RESISTANCE)) + knockbackResistance.set(entry); + else + builder.add(entry.attribute(), entry.modifier(), entry.slot()); }); if (configurableItemData.damage != null) { modDamage = true; @@ -112,13 +121,50 @@ else if (entry.attribute().is(Attributes.ENTITY_INTERACTION_RANGE)) new AttributeModifier(WeaponType.BASE_ATTACK_REACH_UUID, "Config modifier", configurableItemData.reach - 2.5, AttributeModifier.Operation.ADD_VALUE), EquipmentSlotGroup.MAINHAND); } + UUID uuid = UUID.fromString("C1D3F271-8B8E-BA4A-ACE0-6020A98928B2"); + EquipmentSlotGroup slotGroup = EquipmentSlotGroup.ARMOR; + if (itemStack.getItem() instanceof Equipable equipable) + slotGroup = EquipmentSlotGroup.bySlot(equipable.getEquipmentSlot()); + uuid = switch (slotGroup) { + case HEAD -> UUID.fromString("2AD3F246-FEE1-4E67-B886-69FD380BB150"); + case CHEST -> UUID.fromString("9F3D476D-C118-4544-8365-64846904B48E"); + case LEGS -> UUID.fromString("D8499B04-0E66-4726-AB29-64469D734E0D"); + case FEET -> UUID.fromString("845DB27C-C624-495F-8C9F-6020A9A58B6B"); + case BODY -> UUID.fromString("C1C72771-8B8E-BA4A-ACE0-81A93C8928B2"); + default -> uuid; + }; + if (configurableItemData.defense != null) { + modDefense = true; + builder.add(Attributes.ARMOR, + new AttributeModifier(uuid, "Config modifier", configurableItemData.defense, AttributeModifier.Operation.ADD_VALUE), + slotGroup); + } + if (configurableItemData.toughness != null) { + modToughness = true; + builder.add(Attributes.ARMOR_TOUGHNESS, + new AttributeModifier(uuid, "Config modifier", configurableItemData.toughness, AttributeModifier.Operation.ADD_VALUE), + slotGroup); + } + if (configurableItemData.armourKbRes != null) { + modKnockbackResistance = true; + if (configurableItemData.armourKbRes > 0) + builder.add(Attributes.KNOCKBACK_RESISTANCE, + new AttributeModifier(uuid, "Config modifier", configurableItemData.armourKbRes, AttributeModifier.Operation.ADD_VALUE), + slotGroup); + } if (!modDamage && damage.get() != null) builder.add(damage.get().attribute(), damage.get().modifier(), damage.get().slot()); if (!modSpeed && speed.get() != null) builder.add(speed.get().attribute(), speed.get().modifier(), speed.get().slot()); if (!modReach && reach.get() != null) builder.add(reach.get().attribute(), reach.get().modifier(), reach.get().slot()); - if (modDamage || modSpeed || modReach) + if (!modDefense && defense.get() != null) + builder.add(defense.get().attribute(), defense.get().modifier(), defense.get().slot()); + if (!modToughness && toughness.get() != null) + builder.add(toughness.get().attribute(), toughness.get().modifier(), toughness.get().slot()); + if (!modKnockbackResistance && knockbackResistance.get() != null) + builder.add(knockbackResistance.get().attribute(), knockbackResistance.get().modifier(), knockbackResistance.get().slot()); + if (modDamage || modSpeed || modReach || modDefense || modToughness || modKnockbackResistance) itemStack.set(DataComponents.ATTRIBUTE_MODIFIERS, builder.build()); } } diff --git a/src/main/java/net/atlas/combatify/util/ShieldBlockingType.java b/src/main/java/net/atlas/combatify/util/ShieldBlockingType.java index 770ebf9..8a1ebb7 100644 --- a/src/main/java/net/atlas/combatify/util/ShieldBlockingType.java +++ b/src/main/java/net/atlas/combatify/util/ShieldBlockingType.java @@ -4,11 +4,7 @@ import com.llamalad7.mixinextras.sugar.ref.LocalFloatRef; import net.atlas.combatify.Combatify; import net.atlas.combatify.config.ConfigurableItemData; -import net.atlas.combatify.enchantment.CustomEnchantmentHelper; import net.atlas.combatify.enchantment.DefendingEnchantment; -import net.atlas.combatify.extensions.ItemExtensions; -import net.atlas.combatify.extensions.LivingEntityExtensions; -import net.atlas.combatify.extensions.PlayerExtensions; import net.minecraft.core.component.DataComponents; import net.minecraft.tags.DamageTypeTags; import net.minecraft.world.InteractionHand; @@ -17,9 +13,7 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.AxeItem; import net.minecraft.world.item.DyeColor; -import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.level.Level; diff --git a/src/main/resources/combatify.mixins.json b/src/main/resources/combatify.mixins.json index 0684e32..5277e0f 100644 --- a/src/main/resources/combatify.mixins.json +++ b/src/main/resources/combatify.mixins.json @@ -9,8 +9,10 @@ "AxeItemMixin", "BowItemMixin", "ClientboundUpdateAttributesPacketMixin", + "CombatRulesMixin", "DiggerItemMixin", "EggMixin", + "ElytraItemMixin", "EnchantmentHelperMixin", "EnchantmentMixin", "EnchantmentsMixin",