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.
This commit is contained in:
2026-02-17 01:41:31 +01:00
parent e1037422c5
commit 98af11f893

View File

@@ -4,11 +4,14 @@ import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.attribute.EntityAttributes; import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.*; import net.minecraft.item.*;
import net.minecraft.registry.tag.ItemTags; import net.minecraft.registry.tag.ItemTags;
import net.minecraft.registry.tag.TagKey; import net.minecraft.registry.tag.TagKey;
import net.minecraft.util.Hand; import net.minecraft.util.Hand;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Vec3d;
import java.util.Comparator; import java.util.Comparator;
@@ -23,6 +26,7 @@ public class ElytraMace implements ClientModInitializer
return i; return i;
} }
} }
return -1; return -1;
} }
@@ -43,6 +47,14 @@ public class ElytraMace implements ClientModInitializer
return index; 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 @Override
public void onInitializeClient() public void onInitializeClient()
{ {
@@ -51,7 +63,7 @@ public class ElytraMace implements ClientModInitializer
{ {
return; 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) if (target == null || client.player.fallDistance < 1.5)
{ {
return; return;
@@ -70,21 +82,24 @@ public class ElytraMace implements ClientModInitializer
else else
{ {
int mace = getItem(inventory, Items.MACE); int mace = getItem(inventory, Items.MACE);
int elytra = getItem(inventory, Items.ELYTRA); if (mace == -1)
if (mace == -1 || elytra == -1)
{ {
return; return;
} }
inventory.setSelectedSlot(elytra);
client.interactionManager.interactItem(client.player, Hand.MAIN_HAND);
int axe = getBestItem(inventory, ItemTags.AXES); int axe = getBestItem(inventory, ItemTags.AXES);
if (target.isBlocking() && axe > -1) if (axe > -1 && target.isBlocking())
{ {
inventory.setSelectedSlot(axe); inventory.setSelectedSlot(axe);
client.interactionManager.attackEntity(client.player, target); client.interactionManager.attackEntity(client.player, target);
} }
inventory.setSelectedSlot(mace); inventory.setSelectedSlot(mace);
client.interactionManager.attackEntity(client.player, target); 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); int fireworks = getItem(inventory, Items.FIREWORK_ROCKET);
if (fireworks != -1) if (fireworks != -1)
{ {