diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/combat/AutoWeapon.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/combat/AutoWeapon.java index e1326e99b2..d925420966 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/combat/AutoWeapon.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/combat/AutoWeapon.java @@ -9,10 +9,10 @@ import meteordevelopment.meteorclient.settings.*; import meteordevelopment.meteorclient.systems.modules.Categories; import meteordevelopment.meteorclient.systems.modules.Module; -import meteordevelopment.meteorclient.utils.entity.EntityUtils; +import meteordevelopment.meteorclient.utils.entity.DamageUtils; import meteordevelopment.meteorclient.utils.player.InvUtils; import meteordevelopment.orbit.EventHandler; -import net.minecraft.entity.EntityType; +import net.minecraft.entity.LivingEntity; import net.minecraft.item.AxeItem; import net.minecraft.item.ItemStack; import net.minecraft.item.SwordItem; @@ -47,10 +47,12 @@ public AutoWeapon() { @EventHandler private void onAttack(AttackEntityEvent event) { - InvUtils.swap(getBestWeapon(EntityUtils.getGroup(event.entity)), false); + if (event.entity instanceof LivingEntity livingEntity) { + InvUtils.swap(getBestWeapon(livingEntity), false); + } } - private int getBestWeapon(EntityType group) { + private int getBestWeapon(LivingEntity target) { int slotS = mc.player.getInventory().selectedSlot; int slotA = mc.player.getInventory().selectedSlot; double damageS = 0; @@ -59,16 +61,16 @@ private int getBestWeapon(EntityType group) { double currentDamageA; for (int i = 0; i < 9; i++) { ItemStack stack = mc.player.getInventory().getStack(i); - if (stack.getItem() instanceof SwordItem swordItem + if (stack.getItem() instanceof SwordItem && (!antiBreak.get() || (stack.getMaxDamage() - stack.getDamage()) > 10)) { - currentDamageS = swordItem.getMaterial().getAttackDamage() /*fixme + EnchantmentHelper.getAttackDamage(stack, group)*/ + 2; + currentDamageS = DamageUtils.getAttackDamage(mc.player, target, stack); if (currentDamageS > damageS) { damageS = currentDamageS; slotS = i; } - } else if (stack.getItem() instanceof AxeItem axeItem + } else if (stack.getItem() instanceof AxeItem && (!antiBreak.get() || (stack.getMaxDamage() - stack.getDamage()) > 10)) { - currentDamageA = axeItem.getMaterial().getAttackDamage() /*fixme + EnchantmentHelper.getAttackDamage(stack, group)*/ + 2; + currentDamageA = DamageUtils.getAttackDamage(mc.player, target, stack); if (currentDamageA > damageA) { damageA = currentDamageA; slotA = i; diff --git a/src/main/java/meteordevelopment/meteorclient/utils/entity/DamageUtils.java b/src/main/java/meteordevelopment/meteorclient/utils/entity/DamageUtils.java index e2f65ee36b..e9bacbe6c9 100644 --- a/src/main/java/meteordevelopment/meteorclient/utils/entity/DamageUtils.java +++ b/src/main/java/meteordevelopment/meteorclient/utils/entity/DamageUtils.java @@ -5,10 +5,17 @@ package meteordevelopment.meteorclient.utils.entity; +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import meteordevelopment.meteorclient.utils.Utils; import meteordevelopment.meteorclient.utils.entity.fakeplayer.FakePlayerEntity; import meteordevelopment.meteorclient.utils.player.PlayerUtils; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; +import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.AttributeModifiersComponent; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.enchantment.Enchantments; import net.minecraft.entity.*; import net.minecraft.entity.attribute.*; import net.minecraft.entity.damage.DamageSource; @@ -16,6 +23,9 @@ import net.minecraft.entity.effect.StatusEffects; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.*; +import net.minecraft.registry.entry.RegistryEntry; +import net.minecraft.registry.tag.DamageTypeTags; +import net.minecraft.registry.tag.EntityTypeTags; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.hit.HitResult; import net.minecraft.util.math.*; @@ -30,7 +40,6 @@ import static meteordevelopment.meteorclient.MeteorClient.mc; -@SuppressWarnings("JavadocReference") public class DamageUtils { private DamageUtils() { } @@ -137,27 +146,82 @@ public static float getAttackDamage(LivingEntity attacker, LivingEntity target) float itemDamage = (float) attacker.getAttributeValue(EntityAttributes.GENERIC_ATTACK_DAMAGE); DamageSource damageSource = attacker instanceof PlayerEntity player ? mc.world.getDamageSources().playerAttack(player) : mc.world.getDamageSources().mobAttack(attacker); + float damage = modifyAttackDamage(attacker, target, attacker.getWeaponStack(), damageSource, itemDamage); + return calculateReductions(damage, target, damageSource); + } + + public static float getAttackDamage(LivingEntity attacker, LivingEntity target, ItemStack weapon) { + EntityAttributeInstance original = attacker.getAttributeInstance(EntityAttributes.GENERIC_ATTACK_DAMAGE); + EntityAttributeInstance copy = new EntityAttributeInstance(EntityAttributes.GENERIC_ATTACK_DAMAGE, o -> {}); + + copy.setBaseValue(original.getBaseValue()); + for (EntityAttributeModifier modifier : original.getModifiers()) { + copy.addTemporaryModifier(modifier); + } + copy.removeModifier(Item.BASE_ATTACK_DAMAGE_MODIFIER_ID); + + AttributeModifiersComponent attributeModifiers = weapon.get(DataComponentTypes.ATTRIBUTE_MODIFIERS); + if (attributeModifiers != null) { + attributeModifiers.applyModifiers(EquipmentSlot.MAINHAND, (entry, modifier) -> { + if (entry == EntityAttributes.GENERIC_ATTACK_DAMAGE) copy.updateModifier(modifier); + }); + } + + float itemDamage = (float) copy.getValue(); + DamageSource damageSource = attacker instanceof PlayerEntity player ? mc.world.getDamageSources().playerAttack(player) : mc.world.getDamageSources().mobAttack(attacker); + + float damage = modifyAttackDamage(attacker, target, weapon, damageSource, itemDamage); + return calculateReductions(damage, target, damageSource); + } + + private static float modifyAttackDamage(LivingEntity attacker, LivingEntity target, ItemStack weapon, DamageSource damageSource, float damage) { // Get enchant damage - ItemStack stack = attacker.getWeaponStack(); - float enchantDamage = /*fixme EnchantmentHelper.getDamage(attacker.getWorld() instanceof ServerWorld serverWorld ? serverWorld : null, stack, target, damageSource, itemDamage) - itemDamage*/ 0; + Object2IntMap> enchantments = new Object2IntOpenHashMap<>(); + Utils.getEnchantments(weapon, enchantments); + float enchantDamage = 0f; + + int sharpness = Utils.getEnchantmentLevel(enchantments, Enchantments.SHARPNESS); + if (sharpness > 0) { + enchantDamage += 1 + 0.5f * (sharpness - 1); + } + + int baneOfArthropods = Utils.getEnchantmentLevel(enchantments, Enchantments.BANE_OF_ARTHROPODS); + if (baneOfArthropods > 0 && target.getType().isIn(EntityTypeTags.SENSITIVE_TO_BANE_OF_ARTHROPODS)) { + enchantDamage += 2.5f * baneOfArthropods; + } + + int impaling = Utils.getEnchantmentLevel(enchantments, Enchantments.IMPALING); + if (impaling > 0 && target.getType().isIn(EntityTypeTags.SENSITIVE_TO_IMPALING)) { + enchantDamage += 2.5f * impaling; + } + + int smite = Utils.getEnchantmentLevel(enchantments, Enchantments.SMITE); + if (smite > 0 && target.getType().isIn(EntityTypeTags.SENSITIVE_TO_SMITE)) { + enchantDamage += 2.5f * smite; + } // Factor charge if (attacker instanceof PlayerEntity playerEntity) { float charge = playerEntity.getAttackCooldownProgress(0.5f); - itemDamage *= 0.2f + charge * charge * 0.8f; + damage *= 0.2f + charge * charge * 0.8f; enchantDamage *= charge; + if (weapon.getItem() instanceof MaceItem item) { + float bonusDamage = item.getBonusAttackDamage(target, damage, damageSource); + if (bonusDamage > 0f) { + int density = Utils.getEnchantmentLevel(weapon, Enchantments.DENSITY); + if (density > 0) bonusDamage += 0.5f * attacker.fallDistance; + damage += bonusDamage; + } + } + // Factor critical hit if (charge > 0.9f && attacker.fallDistance > 0f && !attacker.isOnGround() && !attacker.isClimbing() && !attacker.isTouchingWater() && !attacker.hasStatusEffect(StatusEffects.BLINDNESS) && !attacker.hasVehicle()) { - itemDamage *= 1.5f; + damage *= 1.5f; } } - float damage = itemDamage + enchantDamage; - - damage = calculateReductions(damage, target, damageSource); - - return damage; + return damage + enchantDamage; } // Fall Damage @@ -221,8 +285,41 @@ private static float getArmor(LivingEntity entity) { * @see LivingEntity#modifyAppliedDamage(DamageSource, float) */ private static float protectionReduction(LivingEntity player, float damage, DamageSource source) { - //fixme float protLevel = EnchantmentHelper.getProtectionAmount(player.getWorld() instanceof ServerWorld serverWorld ? serverWorld : null, player, source); - return DamageUtil.getInflictedDamage(damage, /*protLevel*/ 0); + if (source.isIn(DamageTypeTags.BYPASSES_INVULNERABILITY)) return damage; + + int damageProtection = 0; + + for (ItemStack stack : player.getAllArmorItems()) { + Object2IntMap> enchantments = new Object2IntOpenHashMap<>(); + Utils.getEnchantments(stack, enchantments); + + int protection = Utils.getEnchantmentLevel(enchantments, Enchantments.PROTECTION); + if (protection > 0) { + damageProtection += protection; + } + + int fireProtection = Utils.getEnchantmentLevel(enchantments, Enchantments.FIRE_PROTECTION); + if (fireProtection > 0 && source.isIn(DamageTypeTags.IS_FIRE)) { + damageProtection += 2 * fireProtection; + } + + int blastProtection = Utils.getEnchantmentLevel(enchantments, Enchantments.BLAST_PROTECTION); + if (blastProtection > 0 && source.isIn(DamageTypeTags.IS_EXPLOSION)) { + damageProtection += 2 * blastProtection; + } + + int projectileProtection = Utils.getEnchantmentLevel(enchantments, Enchantments.PROJECTILE_PROTECTION); + if (projectileProtection > 0 && source.isIn(DamageTypeTags.IS_PROJECTILE)) { + damageProtection += 2 * projectileProtection; + } + + int featherFalling = Utils.getEnchantmentLevel(enchantments, Enchantments.FEATHER_FALLING); + if (featherFalling > 0 && source.isIn(DamageTypeTags.IS_FALL)) { + damageProtection += 3 * featherFalling; + } + } + + return DamageUtil.getInflictedDamage(damage, damageProtection); } /** diff --git a/src/main/java/meteordevelopment/meteorclient/utils/world/BlockUtils.java b/src/main/java/meteordevelopment/meteorclient/utils/world/BlockUtils.java index f8b5c8f02a..c3a5ca04e6 100644 --- a/src/main/java/meteordevelopment/meteorclient/utils/world/BlockUtils.java +++ b/src/main/java/meteordevelopment/meteorclient/utils/world/BlockUtils.java @@ -21,6 +21,7 @@ import net.minecraft.block.enums.BlockHalf; import net.minecraft.block.enums.SlabType; import net.minecraft.enchantment.Enchantments; +import net.minecraft.entity.attribute.EntityAttributes; import net.minecraft.entity.effect.StatusEffectUtil; import net.minecraft.entity.effect.StatusEffects; import net.minecraft.item.BlockItem; @@ -368,6 +369,9 @@ public static double getBreakDelta(int slot, BlockState state) { } } + /** + * @see net.minecraft.entity.player.PlayerEntity#getBlockBreakingSpeed(BlockState) + */ private static double getBlockBreakingSpeed(int slot, BlockState block) { double speed = mc.player.getInventory().main.get(slot).getMiningSpeedMultiplier(block); @@ -394,8 +398,8 @@ private static double getBlockBreakingSpeed(int slot, BlockState block) { speed *= k; } - if (mc.player.isSubmergedIn(FluidTags.WATER) /*fixme && !EnchantmentHelper.hasAquaAffinity(mc.player)*/) { - speed /= 5.0F; + if (mc.player.isSubmergedIn(FluidTags.WATER)) { + speed *= mc.player.getAttributeValue(EntityAttributes.PLAYER_SUBMERGED_MINING_SPEED); } if (!mc.player.isOnGround()) {