From 98af11f893e79fe1666aadcdb6da3e6c041f5b18 Mon Sep 17 00:00:00 2001 From: KaseToatz Date: Tue, 17 Feb 2026 01:41:31 +0100 Subject: [PATCH] Add predictive targeting and adjust combat flow Introduce predictive targeting based on entity eye positions and relative velocity (predictDistance) and change entity query to use a Box around the player's eye position and the prediction check. Rework combat item handling: ensure axe-block breaking logic checks axe availability first, perform mace attack before equipping Elytra, and only equip Elytra if present. Add necessary imports and small refactors for readability. --- .../com/kasetoatz/elytramace/ElytraMace.java | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/kasetoatz/elytramace/ElytraMace.java b/src/main/java/com/kasetoatz/elytramace/ElytraMace.java index 1550884..241afd1 100644 --- a/src/main/java/com/kasetoatz/elytramace/ElytraMace.java +++ b/src/main/java/com/kasetoatz/elytramace/ElytraMace.java @@ -4,11 +4,14 @@ import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.attribute.EntityAttributes; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.item.*; import net.minecraft.registry.tag.ItemTags; import net.minecraft.registry.tag.TagKey; import net.minecraft.util.Hand; +import net.minecraft.util.math.Box; +import net.minecraft.util.math.Vec3d; import java.util.Comparator; @@ -23,6 +26,7 @@ public class ElytraMace implements ClientModInitializer return i; } } + return -1; } @@ -43,6 +47,14 @@ public class ElytraMace implements ClientModInitializer return index; } + private double predictDistance(PlayerEntity source, LivingEntity target) + { + Vec3d difference = target.getEyePos().subtract(source.getEyePos()); + Vec3d relativeVelocity = source.getVelocity().subtract(target.getVelocity()); + double speed = relativeVelocity.dotProduct(difference.normalize()); + return source.getAttributeValue(EntityAttributes.ENTITY_INTERACTION_RANGE) + speed * 2; + } + @Override public void onInitializeClient() { @@ -51,7 +63,7 @@ public class ElytraMace implements ClientModInitializer { return; } - LivingEntity target = client.world.getEntitiesByClass(LivingEntity.class, client.player.getBoundingBox().expand(client.player.getAttributeValue(EntityAttributes.ENTITY_INTERACTION_RANGE) + client.player.getVelocity().length() * 2), e -> e != client.player).stream().min(Comparator.comparingDouble(client.player::squaredDistanceTo)).orElse(null); + LivingEntity target = client.world.getEntitiesByClass(LivingEntity.class, Box.of(client.player.getEyePos(), 10.0, 10.0, 10.0), e -> e != client.player && client.player.distanceTo(e) <= predictDistance(client.player, e)).stream().min(Comparator.comparingDouble(client.player::squaredDistanceTo)).orElse(null); if (target == null || client.player.fallDistance < 1.5) { return; @@ -70,21 +82,24 @@ public class ElytraMace implements ClientModInitializer else { int mace = getItem(inventory, Items.MACE); - int elytra = getItem(inventory, Items.ELYTRA); - if (mace == -1 || elytra == -1) + if (mace == -1) { return; } - inventory.setSelectedSlot(elytra); - client.interactionManager.interactItem(client.player, Hand.MAIN_HAND); int axe = getBestItem(inventory, ItemTags.AXES); - if (target.isBlocking() && axe > -1) + if (axe > -1 && target.isBlocking()) { inventory.setSelectedSlot(axe); client.interactionManager.attackEntity(client.player, target); } inventory.setSelectedSlot(mace); client.interactionManager.attackEntity(client.player, target); + int elytra = getItem(inventory, Items.ELYTRA); + if (elytra != -1) + { + inventory.setSelectedSlot(elytra); + client.interactionManager.interactItem(client.player, Hand.MAIN_HAND); + } int fireworks = getItem(inventory, Items.FIREWORK_ROCKET); if (fireworks != -1) {