Подписывайтесь на наш Telegram и не пропускайте важные новости! Перейти

Вопрос Почему удары по увеличенным хитбоксам криво идут?

Начинающий
Начинающий
Статус
Оффлайн
Регистрация
12 Янв 2026
Сообщения
8
Реакции
0
Ситуация такая , что удары по хитбоксам(увеличенной части) нормально проходят только при фрилук или ф5 , а от 1 лица не идут чё за хуня

Java:
Expand Collapse Copy
package zov.polyak.module.list.combat;

import com.google.common.eventbus.Subscribe;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.mob.MobEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.AxeItem;
import net.minecraft.item.ItemStack;
import net.minecraft.item.MaceItem;
import net.minecraft.item.SwordItem;
import net.minecraft.item.TridentItem;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.EntityHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import zov.polyak.event.EventGameUpdate;
import zov.polyak.event.list.EventAttack;
import zov.polyak.event.list.EventTick;
import zov.polyak.event.list.EventUseItem;
import zov.polyak.module.Module;
import zov.polyak.module.ModuleCategory;
import zov.polyak.module.ModuleInformation;
import zov.polyak.module.settings.BooleanSetting;
import zov.polyak.module.settings.ModeSetting;
import zov.polyak.module.settings.SliderSetting;
import zov.polyak.util.friend.FriendRepository;
import zov.polyak.util.rotation.FreeLookComponent;
import zov.polyak.util.rotation.Rotation;
import zov.polyak.util.rotation.RotationComponent;

import java.util.concurrent.ThreadLocalRandom;

@ModuleInformation(
        moduleName = "Hitbox",
        moduleDesc = "Увеличивает размер хитбокса игрока",
        moduleCategory = ModuleCategory.COMBAT
)
public class Hitbox extends Module {

    private static final String ROTATION_DEFAULT = "Обычная";
    private static final String ROTATION_NEW = "Новая";

    private static final String TARGET_PLAYERS = "Игроки";
    private static final String TARGET_MOBS = "Мобы";
    private static final String TARGET_ALL = "Все";

    private static final float VANILLA_SIZE = 0.3F;
    private static final double EXTRA_VERTICAL_RAY = 0.5;
    private static final long NANOS_PER_SECOND = 1_000_000_000L;

    /* === Настройки === */

    private final ModeSetting targets = new ModeSetting(
            "Цели", TARGET_PLAYERS, TARGET_PLAYERS, TARGET_MOBS, TARGET_ALL
    );

    private final BooleanSetting onlyWithWeapon = new BooleanSetting("Только с оружием", true);
    private final BooleanSetting onlyArmored = new BooleanSetting("Только в броне", false);
    private final BooleanSetting onlyTarget = new BooleanSetting("Только на противнике", false);
    private final SliderSetting resetTime = new SliderSetting("Время сброса", 3.0, 1.0, 7.0, 0.5)
            .setVisible(onlyTarget::getValue);

    private final BooleanSetting invisibleHitbox = new BooleanSetting("Невидимый хитбокс", false);

    private final BooleanSetting fixedSize = new BooleanSetting("Фиксированный размер", true);
    private final SliderSetting fixedSizeValue = new SliderSetting("Фикс. размер", 0.7, 0.3, 1.2, 0.05)
            .setVisible(fixedSize::getValue);

    private final SliderSetting minSize = new SliderSetting("Мин. размер", 0.3, 0.2, 1.0, 0.05)
            .setVisible(() -> !fixedSize.getValue());
    private final SliderSetting maxSize = new SliderSetting("Макс. размер", 2.0, 0.5, 5.0, 0.1)
            .setVisible(() -> !fixedSize.getValue());
    private final SliderSetting step = new SliderSetting("Шаг", 0.1, 0.05, 0.5, 0.05)
            .setVisible(() -> !fixedSize.getValue());
    private final SliderSetting size = new SliderSetting("Размер", 0.3, 0.3, 5.0, 0.05)
            .setVisible(() -> !fixedSize.getValue());

    private final BooleanSetting animation = new BooleanSetting("Анимация", true);
    private final SliderSetting animationSpeed = new SliderSetting("Скорость анимации", 6.0, 1.0, 15.0, 0.5)
            .setVisible(animation::getValue);

    private final BooleanSetting bypass = new BooleanSetting("Обход", true);
    private final ModeSetting rotationMode = new ModeSetting("Ротация", ROTATION_NEW, ROTATION_DEFAULT, ROTATION_NEW)
            .setVisible(bypass::getValue);
    private final BooleanSetting antiReach = new BooleanSetting("Anti-Reach", true)
            .setVisible(bypass::getValue);
    private final SliderSetting antiReachDistance = new SliderSetting("Дистанция Anti-Reach", 2.85, 1.0, 3.0, 0.01)
            .setVisible(() -> bypass.getValue() && antiReach.getValue());
    private final BooleanSetting fakeSwing = new BooleanSetting("Фейк свинг", true)
            .setVisible(bypass::getValue);
    private final SliderSetting searchDistance = new SliderSetting("Дистанция", 5.0, 3.0, 10.0, 0.5)
            .setVisible(bypass::getValue);
    private final SliderSetting aimSpeed = new SliderSetting("Скорость наводки", 0.85, 0.1, 2.0, 0.05)
            .setVisible(bypass::getValue);
    private final SliderSetting trackingSpeed = new SliderSetting("Скорость слежения", 0.85, 0.1, 2.0, 0.05)
            .setVisible(bypass::getValue);

    /* === Состояние === */

    private final boolean clientLook = false;
    private double lastVariableSize = VANILLA_SIZE;

    private LivingEntity rotationTarget;
    private Vec3d aimPoint;
    private LivingEntity onlyTargetEntity;
    private long onlyTargetTime;

    private boolean usingItem;

    private float currentYaw;
    private float currentPitch;
    private boolean hasRotation;
    private boolean rotating;
    private boolean fastAimPhase;
    private boolean verticalAim;

    private float animatedSize = VANILLA_SIZE;
    private long lastAnimationTime;

    private long rotationDeltaTime;
    private long targetStartTime;
    private long returnStartTime;
    private LivingEntity previousTarget;
    private boolean returning;
    private LivingEntity queuedSnapAttackTarget;
    private int queuedSnapAttackTicks;
    private boolean ignoreAttackEvent;

    /* === Жизненный цикл === */

    @Override
    public void onEnable() {
        super.onEnable();

        if (fixedSize.getValue()) {
            size.setValue(fixedSizeValue.getValue());
        } else {
            size.setValue(lastVariableSize);
        }

        animatedSize = VANILLA_SIZE;
        lastAnimationTime = System.nanoTime();
        applyHitboxes();
        clearQueuedSnapAttack();
        ignoreAttackEvent = false;
        resetRotation();
    }

    @Override
    public void onDisable() {
        size.setValue(VANILLA_SIZE);
        animatedSize = VANILLA_SIZE;
        resetAllBoxes();
        clearQueuedSnapAttack();
        ignoreAttackEvent = false;
        resetRotation();
        super.onDisable();
    }

    /* === Tick: бокс + анимация === */

    @Subscribe
    private void onTick(EventTick event) {
        if (mc.player == null || mc.world == null) return;

        updateAnimation();
        updateOnlyTarget();
        applyHitboxes();
        processQueuedSnapAttack();
    }

    /* === GameUpdate: bypass-ротация === */

    @Subscribe
    private void onGameUpdate(EventGameUpdate event) {
        if (mc.player == null || mc.world == null) return;

        applyHitboxes();

        // Игрок использует предмет — временно сбрасываем размер до vanilla.
        if (mc.player.isUsingItem() && !usingItem) {
            usingItem = true;
            if (!fixedSize.getValue()) {
                lastVariableSize = size.getValue();
            }
            size.setValue(VANILLA_SIZE);
        } else if (!mc.player.isUsingItem() && usingItem) {
            usingItem = false;
            double restore = fixedSize.getValue() ? fixedSizeValue.getValue() : lastVariableSize;
            size.setValue(restore);
        }

        float currentSize = size.getFloatValue();

        if (currentSize <= VANILLA_SIZE) {
            if (rotating) returnToCamera();
            return;
        }

        if (!bypass.getValue()) {
            returnToCamera();
            return;
        }

        if (onlyWithWeapon.getValue() && !hasWeapon()) {
            returnToCamera();
            return;
        }

        LivingEntity target = findTarget();
        if (target == null) {
            returnToCamera();
            return;
        }

        boolean expandedHit = isLookingAtBox(target, true, false);
        if (ROTATION_NEW.equals(rotationMode.getValue()) && !expandedHit) {
            expandedHit = isLookingAtBox(target, true, true);
        }

        if (!expandedHit) {
            returnToCamera();
            return;
        }

        boolean realHit = isLookingAtBox(target, false, false);
        if (realHit && !rotating) {
            returnToCamera();
            return;
        }

        boolean verticalOutside = isVerticalOutside(target);
        rotationTarget = target;
        rotating = true;

        if (!hasRotation) {
            currentYaw = mc.player.getYaw();
            currentPitch = mc.player.getPitch();
            hasRotation = true;
            fastAimPhase = true;
        }

        if (previousTarget != target) {
            previousTarget = target;
            targetStartTime = System.currentTimeMillis();
            fastAimPhase = true;
        }

        if (verticalOutside) {
            Vec3d edge = getVerticalEdgePoint(target);
            if (edge != null) {
                aimPoint = edge;
                verticalAim = true;
            } else {
                aimPoint = getDefaultAimPoint(target);
                verticalAim = false;
            }
        } else {
            aimPoint = getDefaultAimPoint(target);
            verticalAim = false;
        }

        if (ROTATION_NEW.equals(rotationMode.getValue())) {
            updateNewRotation(aimPoint);
        } else {
            updateDefaultRotation(aimPoint);
        }

        returning = false;
        applyRotation();
    }

    /* === Атака: only-target + AntiReach === */

    @Subscribe
    private void onAttack(EventAttack event) {
        if (mc.player == null || mc.world == null) return;
        if (ignoreAttackEvent) {
            ignoreAttackEvent = false;
            return;
        }
        if (!(event.getEntity() instanceof LivingEntity living)) return;
        if (!isTargetEntity(living)) return;

        if (bypass.getValue()
                && ROTATION_NEW.equals(rotationMode.getValue())
                && size.getFloatValue() > VANILLA_SIZE) {
            boolean realHit = isLookingAtBox(living, false, false);
            boolean expandedHit = isLookingAtBox(living, true, true);
            if (expandedHit && !realHit) {
                event.cancelEvent();
                queueSnapAttack(living);
                return;
            }
        }

        // Запоминаем последнего ударенного
        if (onlyTarget.getValue()) {
            onlyTargetEntity = living;
            onlyTargetTime = System.currentTimeMillis();
        }

        if (antiReach.getValue() && shouldCancelByAntiReach(living)) {
            event.cancelEvent();
            doFakeSwing();
        }
    }

    /* === Использование предмета: AntiReach + cancel в новом режиме === */

    @Subscribe
    private void onUseItem(EventUseItem event) {
        if (mc.player == null || mc.world == null) return;

        HitResult hitResult = event.getTarget();
        if (!(hitResult instanceof EntityHitResult entityHit)) return;
        if (!(entityHit.getEntity() instanceof LivingEntity living)) return;
        if (!isTargetEntity(living)) return;

        if (onlyTarget.getValue() && isWithinTarget(living)) {
            onlyTargetEntity = living;
            onlyTargetTime = System.currentTimeMillis();
        }

        // В новой ротации режем удар по entity, в которого попали только из-за расширения
        if (bypass.getValue()
                && ROTATION_NEW.equals(rotationMode.getValue())
                && size.getFloatValue() > VANILLA_SIZE) {
            boolean realHit = isLookingAtBox(living, false, false);
            boolean expandedHit = isLookingAtBox(living, true, true);
            if (expandedHit && !realHit) {
                event.cancelEvent();
                queueSnapAttack(living);
                return;
            }
        }

        if (antiReach.getValue() && shouldCancelByAntiReach(living)) {
            event.cancelEvent();
            doFakeSwing();
        }
    }

    /* === Расширение хитбоксов === */

    private void applyHitboxes() {
        if (mc.world == null || mc.player == null) return;
        float currentSize = size.getFloatValue();
        for (Entity entity : mc.world.getEntities()) {
            if (entity instanceof LivingEntity living && living != mc.player) {
                if (isValidBypassTarget(living) && isWithinTarget(living) && currentSize > VANILLA_SIZE) {
                    living.setBoundingBox(getExpandedBox(living));
                } else {
                    resetBox(living);
                }
            }
        }
    }

    private float getCurrentExpandRadius(LivingEntity living) {
        float baseRadius = getBaseRadius(living);
        if (invisibleHitbox.getValue()) return baseRadius;

        float visualSize = animation.getValue() ? animatedSize : size.getFloatValue();
        return baseRadius + (visualSize - VANILLA_SIZE);
    }

    /* === Анимация === */

    private void updateAnimation() {
        long now = System.nanoTime();
        if (lastAnimationTime == 0L || now - lastAnimationTime > NANOS_PER_SECOND) {
            lastAnimationTime = now;
            return;
        }

        float dt = (float) (now - lastAnimationTime) / NANOS_PER_SECOND;
        lastAnimationTime = now;

        float target = invisibleHitbox.getValue() ? VANILLA_SIZE : size.getFloatValue();
        float diff = target - animatedSize;

        if (Math.abs(diff) > 0.001F) {
            float speed = animationSpeed.getFloatValue();
            float k = 1.0F - (float) Math.exp(-dt * speed);
            animatedSize += diff * k;
        } else {
            animatedSize = target;
        }
    }

    /* === Only-target reset === */

    private void updateOnlyTarget() {
        if (!onlyTarget.getValue() || onlyTargetEntity == null) return;

        long elapsed = System.currentTimeMillis() - onlyTargetTime;
        long limit = (long) (resetTime.getValue() * 1000.0);
        if (elapsed >= limit) {
            onlyTargetEntity = null;
            onlyTargetTime = 0L;
        }
    }

    private boolean isWithinTarget(LivingEntity living) {
        return !onlyTarget.getValue() || living == onlyTargetEntity;
    }

    /* === Поиск цели === */

    private LivingEntity findTarget() {
        LivingEntity best = null;
        double bestDistance = searchDistance.getValue();

        for (Entity entity : mc.world.getEntities()) {
            if (!(entity instanceof LivingEntity living)) continue;
            if (living == mc.player) continue;
            if (!isValidBypassTarget(living)) continue;
            if (!isWithinTarget(living)) continue;

            double distance = mc.player.distanceTo(living);
            if (distance >= bestDistance) continue;

            bestDistance = distance;
            best = living;
        }
        return best;
    }

    private boolean isValidBypassTarget(LivingEntity living) {
        if (!living.isAlive()) return false;
        if (!isTargetEntity(living)) return false;

        if (living instanceof PlayerEntity player) {
            if (player.isSpectator()) return false;
            if (!FriendRepository.shouldAttack(player)) return false;
            if (onlyArmored.getValue() && !hasArmor(player)) return false;
        }
        return true;
    }

    /* === Обычная ротация === */

    private void updateDefaultRotation(Vec3d point) {
        float targetYaw = getYawTo(point);
        float targetPitch = getPitchTo(point);

        float yawDiff = Math.abs(wrapDegrees(targetYaw - currentYaw));

        if (yawDiff > 2.0F) {
            fastAimPhase = true;
            currentYaw = lerpAngle(currentYaw, targetYaw, aimSpeed.getValue());
        } else {
            fastAimPhase = false;
            currentYaw = lerpAngle(currentYaw, targetYaw, trackingSpeed.getValue());
        }

        if (verticalAim) {
            float pitchDiff = Math.abs(targetPitch - currentPitch);
            if (pitchDiff > 2.0F) {
                currentPitch = lerpPitch(currentPitch, targetPitch, aimSpeed.getValue());
            } else {
                currentPitch = lerpPitch(currentPitch, targetPitch, trackingSpeed.getValue());
            }
        } else {
            float playerPitch = mc.player.getPitch();
            float pitchDiff = Math.abs(playerPitch - currentPitch);
            if (pitchDiff > 1.0F) {
                currentPitch = lerpPitch(currentPitch, playerPitch, aimSpeed.getValue());
            } else {
                currentPitch = playerPitch;
            }
        }
    }

    /* === Новая ротация === */

    private void updateNewRotation(Vec3d point) {
        long now = System.nanoTime();
        double dt = rotationDeltaTime > 0L ? (now - rotationDeltaTime) / 16_666_666.7 : 1.0;
        dt = MathHelper.clamp(dt, 0.05, 3.0);
        rotationDeltaTime = now;

        if (rotationTarget != previousTarget) {
            previousTarget = rotationTarget;
            targetStartTime = System.currentTimeMillis();
        }

        float targetYaw = getYawTo(point);
        float targetPitch = verticalAim ? getPitchTo(point) : mc.player.getPitch();

        double yawDelta = wrapDegrees(targetYaw - currentYaw);
        double pitchDelta = targetPitch - currentPitch;

        double distance = Math.sqrt(yawDelta * yawDelta + pitchDelta * pitchDelta);
        if (distance < 0.05) return;

        fastAimPhase = distance > 2.0;
        double speed = fastAimPhase ? aimSpeed.getValue() : trackingSpeed.getValue();

        double reaction = MathHelper.clamp((System.currentTimeMillis() - targetStartTime) / 200.0, 0.0, 1.0);
        double smoothReaction = reaction * reaction * (3.0 - 2.0 * reaction);
        double distanceFactor = MathHelper.clamp(distance / 15.0, 0.15, 1.0);
        double rng = 0.9 + ThreadLocalRandom.current().nextDouble(0.2);
        double mult = speed * smoothReaction * distanceFactor * dt * rng;

        double yawStep = yawDelta * mult;
        double pitchStep = pitchDelta * mult;

        double gcd = getGcd();
        yawStep = applyStepGcd(yawStep, gcd);
        pitchStep = applyStepGcd(pitchStep, gcd);

        if (yawStep == 0.0 && Math.abs(yawDelta) > gcd) yawStep = Math.signum(yawDelta) * gcd;
        if (pitchStep == 0.0 && Math.abs(pitchDelta) > gcd) pitchStep = Math.signum(pitchDelta) * gcd;
        if (Math.abs(yawStep) > Math.abs(yawDelta)) yawStep = applyStepGcd(yawDelta, gcd);
        if (Math.abs(pitchStep) > Math.abs(pitchDelta)) pitchStep = applyStepGcd(pitchDelta, gcd);

        currentYaw += (float) yawStep;
        currentPitch = MathHelper.clamp(currentPitch + (float) pitchStep, -90.0F, 90.0F);
    }

    /* === Возврат камеры === */

    private void returnToCamera() {
        if (!hasRotation || mc.player == null) {
            resetRotation();
            return;
        }

        if (!returning) {
            returning = true;
            returnStartTime = System.currentTimeMillis();
        }

        float playerYaw = mc.player.getYaw();
        float playerPitch = mc.player.getPitch();
        float yawDelta = Math.abs(wrapDegrees(currentYaw - playerYaw));
        float pitchDelta = Math.abs(currentPitch - playerPitch);

        if (ROTATION_NEW.equals(rotationMode.getValue())) {
            updateReturnNew(playerYaw, playerPitch);
        } else {
            currentYaw = lerpAngle(currentYaw, playerYaw, aimSpeed.getValue());
            currentPitch = lerpPitch(currentPitch, playerPitch, aimSpeed.getValue());
        }

        applyRotation();

        if (yawDelta < 5.0F && pitchDelta < 5.0F) {
            resetRotation();
        }
    }

    private void updateReturnNew(float playerYaw, float playerPitch) {
        long now = System.nanoTime();
        double dt = rotationDeltaTime > 0L ? (now - rotationDeltaTime) / 16_666_666.7 : 1.0;
        dt = MathHelper.clamp(dt, 0.05, 3.0);
        rotationDeltaTime = now;

        double yawDelta = wrapDegrees(playerYaw - currentYaw);
        double pitchDelta = playerPitch - currentPitch;

        double distance = Math.sqrt(yawDelta * yawDelta + pitchDelta * pitchDelta);
        if (distance < 0.05) return;

        double speed = aimSpeed.getValue();
        double reaction = MathHelper.clamp((System.currentTimeMillis() - returnStartTime) / 200.0, 0.0, 1.0);
        double smoothReaction = reaction * reaction * (3.0 - 2.0 * reaction);
        double distanceFactor = MathHelper.clamp(distance / 15.0, 0.15, 1.0);
        double rng = 0.9 + ThreadLocalRandom.current().nextDouble(0.2);
        double mult = speed * smoothReaction * distanceFactor * dt * rng;

        double yawStep = yawDelta * mult;
        double pitchStep = pitchDelta * mult;

        double gcd = getGcd();
        yawStep = applyStepGcd(yawStep, gcd);
        pitchStep = applyStepGcd(pitchStep, gcd);

        if (yawStep == 0.0 && Math.abs(yawDelta) > gcd) yawStep = Math.signum(yawDelta) * gcd;
        if (pitchStep == 0.0 && Math.abs(pitchDelta) > gcd) pitchStep = Math.signum(pitchDelta) * gcd;

        currentYaw += (float) yawStep;
        currentPitch = MathHelper.clamp(currentPitch + (float) pitchStep, -90.0F, 90.0F);
    }

    /* === AntiReach === */

    private boolean shouldCancelByAntiReach(LivingEntity target) {
        if (size.getFloatValue() <= VANILLA_SIZE) return false;

        Box realBox = getDefaultBox(target);
        Vec3d eye = mc.player.getEyePos();
        Vec3d nearest = clampToBox(eye, realBox);
        return eye.distanceTo(nearest) > antiReachDistance.getValue();
    }

    /* === Raytrace === */

    private Vec3d getMouseLookVec() {
        if (FreeLookComponent.isActive()) {
            float f = FreeLookComponent.getFreePitch() * 0.017453292F;
            float g = -FreeLookComponent.getFreeYaw() * 0.017453292F;
            float h = MathHelper.cos(g);
            float i = MathHelper.sin(g);
            float j = MathHelper.cos(f);
            float k = MathHelper.sin(f);
            return new Vec3d((double) (i * j), (double) (-k), (double) (h * j));
        }
        return mc.player.getRotationVec(1.0F);
    }

    private boolean isLookingAtBox(LivingEntity target, boolean expanded, boolean addVertical) {
        Vec3d eye = mc.player.getEyePos();
        Vec3d look = getMouseLookVec();
        Vec3d end = eye.add(look.multiply(searchDistance.getValue()));

        Box box = expanded ? getExpandedBox(target) : getDefaultBox(target);
        if (addVertical) {
            box = box.expand(0.0, EXTRA_VERTICAL_RAY, 0.0);
        }

        if (box.contains(eye)) {
            double dx = target.getX() - eye.x;
            double dz = target.getZ() - eye.z;
            double lx = look.x;
            double lz = look.z;
            double horiz = Math.sqrt(dx * dx + dz * dz);
            double lookHoriz = Math.sqrt(lx * lx + lz * lz);
            if (horiz < 0.01 || lookHoriz < 0.01) return true;
            double dot = (dx / horiz) * (lx / lookHoriz) + (dz / horiz) * (lz / lookHoriz);
            return dot > -0.5;
        }
        return box.raycast(eye, end).isPresent();
    }

    private Vec3d getDefaultAimPoint(LivingEntity target) {
        Vec3d eye = mc.player.getEyePos();
        Vec3d look = mc.player.getRotationVec(1.0F);
        Vec3d end = eye.add(look.multiply(searchDistance.getValue()));

        Box realBox = getDefaultBox(target);
        Box safe = new Box(
                realBox.minX + 0.2, realBox.minY,
                realBox.minZ + 0.2, realBox.maxX - 0.2,
                realBox.maxY, realBox.maxZ - 0.2
        );
        Box expanded = getExpandedBox(target);
        Vec3d projected = expanded.raycast(eye, end).orElse(expanded.getCenter());
        return clampToBox(projected, safe);
    }

    private boolean isVerticalOutside(LivingEntity target) {
        Vec3d eye = mc.player.getEyePos();
        Box box = getDefaultBox(target);
        double y = projectVerticalIntersection(target, eye, mc.player.getPitch());
        return y < box.minY || y > box.maxY;
    }

    private Vec3d getVerticalEdgePoint(LivingEntity target) {
        Vec3d eye = mc.player.getEyePos();
        Box box = getDefaultBox(target);
        double y = projectVerticalIntersection(target, eye, mc.player.getPitch());
        double picked;
        if (y < box.minY) {
            picked = box.minY + 0.1;
        } else if (y > box.maxY) {
            picked = box.maxY - 0.1;
        } else {
            return null;
        }
        return new Vec3d(target.getX(), picked, target.getZ());
    }

    private double projectVerticalIntersection(LivingEntity target, Vec3d eye, float pitch) {
        double dx = target.getX() - eye.x;
        double dz = target.getZ() - eye.z;
        double horiz = Math.sqrt(dx * dx + dz * dz);
        double rad = Math.toRadians(pitch);
        return horiz < 0.5 ? eye.y - Math.tan(rad) * 0.5 : eye.y - Math.tan(rad) * horiz;
    }

    /* === Боксы === */

    private Box getDefaultBox(Entity entity) {
        return entity.getType().getDimensions().getBoxAt(entity.getPos());
    }

    private Box getExpandedBox(Entity entity) {
        float radius = getBaseRadius(entity) + Math.max(0.0F, size.getFloatValue() - VANILLA_SIZE);
        return buildBoxAround(entity, radius);
    }

    private Box buildBoxAround(Entity entity, float radius) {
        return new Box(
                entity.getX() - radius,
                entity.getY(),
                entity.getZ() - radius,
                entity.getX() + radius,
                entity.getY() + entity.getHeight(),
                entity.getZ() + radius
        );
    }

    private float getBaseRadius(Entity entity) {
        return (float) (getDefaultBox(entity).getLengthX() / 2.0);
    }

    private void resetBox(LivingEntity entity) {
        entity.setBoundingBox(getDefaultBox(entity));
    }

    private void resetAllBoxes() {
        if (mc.world == null || mc.player == null) return;
        for (Entity entity : mc.world.getEntities()) {
            if (entity instanceof LivingEntity living && living != mc.player) {
                resetBox(living);
            }
        }
    }

    /* === Цели === */

    private boolean isTargetEntity(Entity entity) {
        if (TARGET_ALL.equals(targets.getValue())) return entity instanceof LivingEntity;
        if (TARGET_PLAYERS.equals(targets.getValue())) return entity instanceof PlayerEntity;
        if (TARGET_MOBS.equals(targets.getValue())) return entity instanceof MobEntity;
        return false;
    }

    /* === Оружие / броня === */

    private boolean hasWeapon() {
        if (mc.player == null) return false;
        return isWeapon(mc.player.getMainHandStack()) || isWeapon(mc.player.getOffHandStack());
    }

    private boolean isWeapon(ItemStack stack) {
        if (stack == null || stack.isEmpty()) return false;
        return stack.getItem() instanceof SwordItem
                || stack.getItem() instanceof AxeItem
                || stack.getItem() instanceof TridentItem
                || stack.getItem() instanceof MaceItem;
    }

    private boolean hasArmor(PlayerEntity player) {
        return !player.getInventory().armor.get(0).isEmpty()
                || !player.getInventory().armor.get(1).isEmpty()
                || !player.getInventory().armor.get(2).isEmpty()
                || !player.getInventory().armor.get(3).isEmpty();
    }

    /* === Ротация / геометрия === */

    private float getYawTo(Vec3d point) {
        Vec3d eye = mc.player.getEyePos();
        Vec3d adj = point;
        if (rotationTarget != null) {
            adj = adj.add(rotationTarget.getVelocity().multiply(0.1));
        }
        double dx = adj.x - eye.x;
        double dz = adj.z - eye.z;
        return (float) Math.toDegrees(Math.atan2(dz, dx)) - 90.0F;
    }

    private float getPitchTo(Vec3d point) {
        Vec3d eye = mc.player.getEyePos();
        double dx = point.x - eye.x;
        double dy = point.y - eye.y;
        double dz = point.z - eye.z;
        double horiz = Math.sqrt(dx * dx + dz * dz);
        return (float) -Math.toDegrees(Math.atan2(dy, horiz));
    }

    private float lerpAngle(float from, float to, double speed) {
        return from + wrapDegrees(to - from) * (float) speed;
    }

    private float lerpPitch(float from, float to, double speed) {
        return MathHelper.clamp(from + (to - from) * (float) speed, -90.0F, 90.0F);
    }

    private static float wrapDegrees(float value) {
        return ((value + 180.0F) % 360.0F + 360.0F) % 360.0F - 180.0F;
    }

    private static double wrapDegrees(double value) {
        value %= 360.0;
        if (value > 180.0) value -= 360.0;
        if (value < -180.0) value += 360.0;
        return value;
    }

    private double getGcd() {
        double sens = mc.options.getMouseSensitivity().getValue();
        double f = sens * 0.6 + 0.2;
        return f * f * f * 1.2;
    }

    private double applyStepGcd(double value, double gcd) {
        return gcd <= 1.0E-4 ? value : value - value % gcd;
    }

    private Vec3d clampToBox(Vec3d point, Box box) {
        return new Vec3d(
                Math.max(box.minX, Math.min(point.x, box.maxX)),
                Math.max(box.minY, Math.min(point.y, box.maxY)),
                Math.max(box.minZ, Math.min(point.z, box.maxZ))
        );
    }

    private void applyRotation() {
        RotationComponent.update(
                new Rotation(currentYaw, currentPitch),
                360, 360, 360, 360, 0, 1, clientLook
        );
    }

    private void snapToTarget(LivingEntity target) {
        rotationTarget = target;
        Vec3d point;
        if (isVerticalOutside(target)) {
            Vec3d edge = getVerticalEdgePoint(target);
            point = edge != null ? edge : getDefaultAimPoint(target);
        } else {
            point = getDefaultAimPoint(target);
        }

        currentYaw = getYawTo(point);
        currentPitch = MathHelper.clamp(getPitchTo(point), -90.0F, 90.0F);
        hasRotation = true;
        rotating = true;
        returning = false;
        applyRotation();
    }

    private void queueSnapAttack(LivingEntity target) {
        snapToTarget(target);
        
        // Выполняем удар сразу же, чтобы не было задержки в 1 тик.
        // Это поможет, если цель быстро движется.
        ignoreAttackEvent = true;
        if (mc.interactionManager != null && mc.player != null) {
            mc.interactionManager.attackEntity(mc.player, target);
            mc.player.swingHand(Hand.MAIN_HAND);
        }
    }

    private void processQueuedSnapAttack() {
        // Метод оставлен для совместимости, но теперь атака происходит мгновенно в queueSnapAttack
        clearQueuedSnapAttack();
    }

    private void clearQueuedSnapAttack() {
        queuedSnapAttackTarget = null;
        queuedSnapAttackTicks = 0;
    }

    private void doFakeSwing() {
        if (!fakeSwing.getValue() || mc.player == null) return;
        mc.player.swingHand(Hand.MAIN_HAND);
        mc.player.resetLastAttackedTicks();
    }

    private void resetRotation() {
        rotationTarget = null;
        aimPoint = null;
        previousTarget = null;
        hasRotation = false;
        rotating = false;
        fastAimPhase = false;
        verticalAim = false;
        returning = false;
        currentYaw = 0.0F;
        currentPitch = 0.0F;
        rotationDeltaTime = 0L;
        targetStartTime = 0L;
        returnStartTime = 0L;
    }
}
 
Последнее редактирование:
Ситуация такая , что удары по хитбоксам(увеличенной части) нормально проходят только при фрилук или ф5 , а от 1 лица не идут чё за хуня

package zov.polyak.module.list.combat;

import com.google.common.eventbus.Subscribe;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.mob.MobEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.AxeItem;
import net.minecraft.item.ItemStack;
import net.minecraft.item.MaceItem;
import net.minecraft.item.SwordItem;
import net.minecraft.item.TridentItem;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.EntityHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import zov.polyak.event.EventGameUpdate;
import zov.polyak.event.list.EventAttack;
import zov.polyak.event.list.EventTick;
import zov.polyak.event.list.EventUseItem;
import zov.polyak.module.Module;
import zov.polyak.module.ModuleCategory;
import zov.polyak.module.ModuleInformation;
import zov.polyak.module.settings.BooleanSetting;
import zov.polyak.module.settings.ModeSetting;
import zov.polyak.module.settings.SliderSetting;
import zov.polyak.util.friend.FriendRepository;
import zov.polyak.util.rotation.FreeLookComponent;
import zov.polyak.util.rotation.Rotation;
import zov.polyak.util.rotation.RotationComponent;

import java.util.concurrent.ThreadLocalRandom;

@ModuleInformation(
moduleName = "Hitbox",
moduleDesc = "Увеличивает размер хитбокса игрока",
moduleCategory = ModuleCategory.COMBAT
)
public class Hitbox extends Module {

private static final String ROTATION_DEFAULT = "Обычная";
private static final String ROTATION_NEW = "Новая";

private static final String TARGET_PLAYERS = "Игроки";
private static final String TARGET_MOBS = "Мобы";
private static final String TARGET_ALL = "Все";

private static final float VANILLA_SIZE = 0.3F;
private static final double EXTRA_VERTICAL_RAY = 0.5;
private static final long NANOS_PER_SECOND = 1_000_000_000L;

/* === Настройки === */

private final ModeSetting targets = new ModeSetting(
"Цели", TARGET_PLAYERS, TARGET_PLAYERS, TARGET_MOBS, TARGET_ALL
);

private final BooleanSetting onlyWithWeapon = new BooleanSetting("Только с оружием", true);
private final BooleanSetting onlyArmored = new BooleanSetting("Только в броне", false);
private final BooleanSetting onlyTarget = new BooleanSetting("Только на противнике", false);
private final SliderSetting resetTime = new SliderSetting("Время сброса", 3.0, 1.0, 7.0, 0.5)
.setVisible(onlyTarget::getValue);

private final BooleanSetting invisibleHitbox = new BooleanSetting("Невидимый хитбокс", false);

private final BooleanSetting fixedSize = new BooleanSetting("Фиксированный размер", true);
private final SliderSetting fixedSizeValue = new SliderSetting("Фикс. размер", 0.7, 0.3, 1.2, 0.05)
.setVisible(fixedSize::getValue);

private final SliderSetting minSize = new SliderSetting("Мин. размер", 0.3, 0.2, 1.0, 0.05)
.setVisible(() -> !fixedSize.getValue());
private final SliderSetting maxSize = new SliderSetting("Макс. размер", 2.0, 0.5, 5.0, 0.1)
.setVisible(() -> !fixedSize.getValue());
private final SliderSetting step = new SliderSetting("Шаг", 0.1, 0.05, 0.5, 0.05)
.setVisible(() -> !fixedSize.getValue());
private final SliderSetting size = new SliderSetting("Размер", 0.3, 0.3, 5.0, 0.05)
.setVisible(() -> !fixedSize.getValue());

private final BooleanSetting animation = new BooleanSetting("Анимация", true);
private final SliderSetting animationSpeed = new SliderSetting("Скорость анимации", 6.0, 1.0, 15.0, 0.5)
.setVisible(animation::getValue);

private final BooleanSetting bypass = new BooleanSetting("Обход", true);
private final ModeSetting rotationMode = new ModeSetting("Ротация", ROTATION_NEW, ROTATION_DEFAULT, ROTATION_NEW)
.setVisible(bypass::getValue);
private final BooleanSetting antiReach = new BooleanSetting("Anti-Reach", true)
.setVisible(bypass::getValue);
private final SliderSetting antiReachDistance = new SliderSetting("Дистанция Anti-Reach", 2.85, 1.0, 3.0, 0.01)
.setVisible(() -> bypass.getValue() && antiReach.getValue());
private final BooleanSetting fakeSwing = new BooleanSetting("Фейк свинг", true)
.setVisible(bypass::getValue);
private final SliderSetting searchDistance = new SliderSetting("Дистанция", 5.0, 3.0, 10.0, 0.5)
.setVisible(bypass::getValue);
private final SliderSetting aimSpeed = new SliderSetting("Скорость наводки", 0.85, 0.1, 2.0, 0.05)
.setVisible(bypass::getValue);
private final SliderSetting trackingSpeed = new SliderSetting("Скорость слежения", 0.85, 0.1, 2.0, 0.05)
.setVisible(bypass::getValue);

/* === Состояние === */

private final boolean clientLook = false;
private double lastVariableSize = VANILLA_SIZE;

private LivingEntity rotationTarget;
private Vec3d aimPoint;
private LivingEntity onlyTargetEntity;
private long onlyTargetTime;

private boolean usingItem;

private float currentYaw;
private float currentPitch;
private boolean hasRotation;
private boolean rotating;
private boolean fastAimPhase;
private boolean verticalAim;

private float animatedSize = VANILLA_SIZE;
private long lastAnimationTime;

private long rotationDeltaTime;
private long targetStartTime;
private long returnStartTime;
private LivingEntity previousTarget;
private boolean returning;
private LivingEntity queuedSnapAttackTarget;
private int queuedSnapAttackTicks;
private boolean ignoreAttackEvent;

/* === Жизненный цикл === */

@override
public void onEnable() {
super.onEnable();

if (fixedSize.getValue()) {
size.setValue(fixedSizeValue.getValue());
} else {
size.setValue(lastVariableSize);
}

animatedSize = VANILLA_SIZE;
lastAnimationTime = System.nanoTime();
applyHitboxes();
clearQueuedSnapAttack();
ignoreAttackEvent = false;
resetRotation();
}

@override
public void onDisable() {
size.setValue(VANILLA_SIZE);
animatedSize = VANILLA_SIZE;
resetAllBoxes();
clearQueuedSnapAttack();
ignoreAttackEvent = false;
resetRotation();
super.onDisable();
}

/* === Tick: бокс + анимация === */

@Subscribe
private void onTick(EventTick event) {
if (mc.player == null || mc.world == null) return;

updateAnimation();
updateOnlyTarget();
applyHitboxes();
processQueuedSnapAttack();
}

/* === GameUpdate: bypass-ротация === */

@Subscribe
private void onGameUpdate(EventGameUpdate event) {
if (mc.player == null || mc.world == null) return;

applyHitboxes();

// Игрок использует предмет — временно сбрасываем размер до vanilla.
if (mc.player.isUsingItem() && !usingItem) {
usingItem = true;
if (!fixedSize.getValue()) {
lastVariableSize = size.getValue();
}
size.setValue(VANILLA_SIZE);
} else if (!mc.player.isUsingItem() && usingItem) {
usingItem = false;
double restore = fixedSize.getValue() ? fixedSizeValue.getValue() : lastVariableSize;
size.setValue(restore);
}

float currentSize = size.getFloatValue();

if (currentSize <= VANILLA_SIZE) {
if (rotating) returnToCamera();
return;
}

if (!bypass.getValue()) {
returnToCamera();
return;
}

if (onlyWithWeapon.getValue() && !hasWeapon()) {
returnToCamera();
return;
}

LivingEntity target = findTarget();
if (target == null) {
returnToCamera();
return;
}

boolean expandedHit = isLookingAtBox(target, true, false);
if (ROTATION_NEW.equals(rotationMode.getValue()) && !expandedHit) {
expandedHit = isLookingAtBox(target, true, true);
}

if (!expandedHit) {
returnToCamera();
return;
}

boolean realHit = isLookingAtBox(target, false, false);
if (realHit && !rotating) {
returnToCamera();
return;
}

boolean verticalOutside = isVerticalOutside(target);
rotationTarget = target;
rotating = true;

if (!hasRotation) {
currentYaw = mc.player.getYaw();
currentPitch = mc.player.getPitch();
hasRotation = true;
fastAimPhase = true;
}

if (previousTarget != target) {
previousTarget = target;
targetStartTime = System.currentTimeMillis();
fastAimPhase = true;
}

if (verticalOutside) {
Vec3d edge = getVerticalEdgePoint(target);
if (edge != null) {
aimPoint = edge;
verticalAim = true;
} else {
aimPoint = getDefaultAimPoint(target);
verticalAim = false;
}
} else {
aimPoint = getDefaultAimPoint(target);
verticalAim = false;
}

if (ROTATION_NEW.equals(rotationMode.getValue())) {
updateNewRotation(aimPoint);
} else {
updateDefaultRotation(aimPoint);
}

returning = false;
applyRotation();
}

/* === Атака: only-target + AntiReach === */

@Subscribe
private void onAttack(EventAttack event) {
if (mc.player == null || mc.world == null) return;
if (ignoreAttackEvent) {
ignoreAttackEvent = false;
return;
}
if (!(event.getEntity() instanceof LivingEntity living)) return;
if (!isTargetEntity(living)) return;

if (bypass.getValue()
&& ROTATION_NEW.equals(rotationMode.getValue())
&& size.getFloatValue() > VANILLA_SIZE) {
boolean realHit = isLookingAtBox(living, false, false);
boolean expandedHit = isLookingAtBox(living, true, true);
if (expandedHit && !realHit) {
event.cancelEvent();
queueSnapAttack(living);
return;
}
}

// Запоминаем последнего ударенного
if (onlyTarget.getValue()) {
onlyTargetEntity = living;
onlyTargetTime = System.currentTimeMillis();
}

if (antiReach.getValue() && shouldCancelByAntiReach(living)) {
event.cancelEvent();
doFakeSwing();
}
}

/* === Использование предмета: AntiReach + cancel в новом режиме === */

@Subscribe
private void onUseItem(EventUseItem event) {
if (mc.player == null || mc.world == null) return;

HitResult hitResult = event.getTarget();
if (!(hitResult instanceof EntityHitResult entityHit)) return;
if (!(entityHit.getEntity() instanceof LivingEntity living)) return;
if (!isTargetEntity(living)) return;

if (onlyTarget.getValue() && isWithinTarget(living)) {
onlyTargetEntity = living;
onlyTargetTime = System.currentTimeMillis();
}

// В новой ротации режем удар по entity, в которого попали только из-за расширения
if (bypass.getValue()
&& ROTATION_NEW.equals(rotationMode.getValue())
&& size.getFloatValue() > VANILLA_SIZE) {
boolean realHit = isLookingAtBox(living, false, false);
boolean expandedHit = isLookingAtBox(living, true, true);
if (expandedHit && !realHit) {
event.cancelEvent();
queueSnapAttack(living);
return;
}
}

if (antiReach.getValue() && shouldCancelByAntiReach(living)) {
event.cancelEvent();
doFakeSwing();
}
}

/* === Расширение хитбоксов === */

private void applyHitboxes() {
if (mc.world == null || mc.player == null) return;
float currentSize = size.getFloatValue();
for (Entity entity : mc.world.getEntities()) {
if (entity instanceof LivingEntity living && living != mc.player) {
if (isValidBypassTarget(living) && isWithinTarget(living) && currentSize > VANILLA_SIZE) {
living.setBoundingBox(getExpandedBox(living));
} else {
resetBox(living);
}
}
}
}

private float getCurrentExpandRadius(LivingEntity living) {
float baseRadius = getBaseRadius(living);
if (invisibleHitbox.getValue()) return baseRadius;

float visualSize = animation.getValue() ? animatedSize : size.getFloatValue();
return baseRadius + (visualSize - VANILLA_SIZE);
}

/* === Анимация === */

private void updateAnimation() {
long now = System.nanoTime();
if (lastAnimationTime == 0L || now - lastAnimationTime > NANOS_PER_SECOND) {
lastAnimationTime = now;
return;
}

float dt = (float) (now - lastAnimationTime) / NANOS_PER_SECOND;
lastAnimationTime = now;

float target = invisibleHitbox.getValue() ? VANILLA_SIZE : size.getFloatValue();
float diff = target - animatedSize;

if (Math.abs(diff) > 0.001F) {
float speed = animationSpeed.getFloatValue();
float k = 1.0F - (float) Math.exp(-dt * speed);
animatedSize += diff * k;
} else {
animatedSize = target;
}
}

/* === Only-target reset === */

private void updateOnlyTarget() {
if (!onlyTarget.getValue() || onlyTargetEntity == null) return;

long elapsed = System.currentTimeMillis() - onlyTargetTime;
long limit = (long) (resetTime.getValue() * 1000.0);
if (elapsed >= limit) {
onlyTargetEntity = null;
onlyTargetTime = 0L;
}
}

private boolean isWithinTarget(LivingEntity living) {
return !onlyTarget.getValue() || living == onlyTargetEntity;
}

/* === Поиск цели === */

private LivingEntity findTarget() {
LivingEntity best = null;
double bestDistance = searchDistance.getValue();

for (Entity entity : mc.world.getEntities()) {
if (!(entity instanceof LivingEntity living)) continue;
if (living == mc.player) continue;
if (!isValidBypassTarget(living)) continue;
if (!isWithinTarget(living)) continue;

double distance = mc.player.distanceTo(living);
if (distance >= bestDistance) continue;

bestDistance = distance;
best = living;
}
return best;
}

private boolean isValidBypassTarget(LivingEntity living) {
if (!living.isAlive()) return false;
if (!isTargetEntity(living)) return false;

if (living instanceof PlayerEntity player) {
if (player.isSpectator()) return false;
if (!FriendRepository.shouldAttack(player)) return false;
if (onlyArmored.getValue() && !hasArmor(player)) return false;
}
return true;
}

/* === Обычная ротация === */

private void updateDefaultRotation(Vec3d point) {
float targetYaw = getYawTo(point);
float targetPitch = getPitchTo(point);

float yawDiff = Math.abs(wrapDegrees(targetYaw - currentYaw));

if (yawDiff > 2.0F) {
fastAimPhase = true;
currentYaw = lerpAngle(currentYaw, targetYaw, aimSpeed.getValue());
} else {
fastAimPhase = false;
currentYaw = lerpAngle(currentYaw, targetYaw, trackingSpeed.getValue());
}

if (verticalAim) {
float pitchDiff = Math.abs(targetPitch - currentPitch);
if (pitchDiff > 2.0F) {
currentPitch = lerpPitch(currentPitch, targetPitch, aimSpeed.getValue());
} else {
currentPitch = lerpPitch(currentPitch, targetPitch, trackingSpeed.getValue());
}
} else {
float playerPitch = mc.player.getPitch();
float pitchDiff = Math.abs(playerPitch - currentPitch);
if (pitchDiff > 1.0F) {
currentPitch = lerpPitch(currentPitch, playerPitch, aimSpeed.getValue());
} else {
currentPitch = playerPitch;
}
}
}

/* === Новая ротация === */

private void updateNewRotation(Vec3d point) {
long now = System.nanoTime();
double dt = rotationDeltaTime > 0L ? (now - rotationDeltaTime) / 16_666_666.7 : 1.0;
dt = MathHelper.clamp(dt, 0.05, 3.0);
rotationDeltaTime = now;

if (rotationTarget != previousTarget) {
previousTarget = rotationTarget;
targetStartTime = System.currentTimeMillis();
}

float targetYaw = getYawTo(point);
float targetPitch = verticalAim ? getPitchTo(point) : mc.player.getPitch();

double yawDelta = wrapDegrees(targetYaw - currentYaw);
double pitchDelta = targetPitch - currentPitch;

double distance = Math.sqrt(yawDelta * yawDelta + pitchDelta * pitchDelta);
if (distance < 0.05) return;

fastAimPhase = distance > 2.0;
double speed = fastAimPhase ? aimSpeed.getValue() : trackingSpeed.getValue();

double reaction = MathHelper.clamp((System.currentTimeMillis() - targetStartTime) / 200.0, 0.0, 1.0);
double smoothReaction = reaction * reaction * (3.0 - 2.0 * reaction);
double distanceFactor = MathHelper.clamp(distance / 15.0, 0.15, 1.0);
double rng = 0.9 + ThreadLocalRandom.current().nextDouble(0.2);
double mult = speed * smoothReaction * distanceFactor * dt * rng;

double yawStep = yawDelta * mult;
double pitchStep = pitchDelta * mult;

double gcd = getGcd();
yawStep = applyStepGcd(yawStep, gcd);
pitchStep = applyStepGcd(pitchStep, gcd);

if (yawStep == 0.0 && Math.abs(yawDelta) > gcd) yawStep = Math.signum(yawDelta) * gcd;
if (pitchStep == 0.0 && Math.abs(pitchDelta) > gcd) pitchStep = Math.signum(pitchDelta) * gcd;
if (Math.abs(yawStep) > Math.abs(yawDelta)) yawStep = applyStepGcd(yawDelta, gcd);
if (Math.abs(pitchStep) > Math.abs(pitchDelta)) pitchStep = applyStepGcd(pitchDelta, gcd);

currentYaw += (float) yawStep;
currentPitch = MathHelper.clamp(currentPitch + (float) pitchStep, -90.0F, 90.0F);
}

/* === Возврат камеры === */

private void returnToCamera() {
if (!hasRotation || mc.player == null) {
resetRotation();
return;
}

if (!returning) {
returning = true;
returnStartTime = System.currentTimeMillis();
}

float playerYaw = mc.player.getYaw();
float playerPitch = mc.player.getPitch();
float yawDelta = Math.abs(wrapDegrees(currentYaw - playerYaw));
float pitchDelta = Math.abs(currentPitch - playerPitch);

if (ROTATION_NEW.equals(rotationMode.getValue())) {
updateReturnNew(playerYaw, playerPitch);
} else {
currentYaw = lerpAngle(currentYaw, playerYaw, aimSpeed.getValue());
currentPitch = lerpPitch(currentPitch, playerPitch, aimSpeed.getValue());
}

applyRotation();

if (yawDelta < 5.0F && pitchDelta < 5.0F) {
resetRotation();
}
}

private void updateReturnNew(float playerYaw, float playerPitch) {
long now = System.nanoTime();
double dt = rotationDeltaTime > 0L ? (now - rotationDeltaTime) / 16_666_666.7 : 1.0;
dt = MathHelper.clamp(dt, 0.05, 3.0);
rotationDeltaTime = now;

double yawDelta = wrapDegrees(playerYaw - currentYaw);
double pitchDelta = playerPitch - currentPitch;

double distance = Math.sqrt(yawDelta * yawDelta + pitchDelta * pitchDelta);
if (distance < 0.05) return;

double speed = aimSpeed.getValue();
double reaction = MathHelper.clamp((System.currentTimeMillis() - returnStartTime) / 200.0, 0.0, 1.0);
double smoothReaction = reaction * reaction * (3.0 - 2.0 * reaction);
double distanceFactor = MathHelper.clamp(distance / 15.0, 0.15, 1.0);
double rng = 0.9 + ThreadLocalRandom.current().nextDouble(0.2);
double mult = speed * smoothReaction * distanceFactor * dt * rng;

double yawStep = yawDelta * mult;
double pitchStep = pitchDelta * mult;

double gcd = getGcd();
yawStep = applyStepGcd(yawStep, gcd);
pitchStep = applyStepGcd(pitchStep, gcd);

if (yawStep == 0.0 && Math.abs(yawDelta) > gcd) yawStep = Math.signum(yawDelta) * gcd;
if (pitchStep == 0.0 && Math.abs(pitchDelta) > gcd) pitchStep = Math.signum(pitchDelta) * gcd;

currentYaw += (float) yawStep;
currentPitch = MathHelper.clamp(currentPitch + (float) pitchStep, -90.0F, 90.0F);
}

/* === AntiReach === */

private boolean shouldCancelByAntiReach(LivingEntity target) {
if (size.getFloatValue() <= VANILLA_SIZE) return false;

Box realBox = getDefaultBox(target);
Vec3d eye = mc.player.getEyePos();
Vec3d nearest = clampToBox(eye, realBox);
return eye.distanceTo(nearest) > antiReachDistance.getValue();
}

/* === Raytrace === */

private Vec3d getMouseLookVec() {
if (FreeLookComponent.isActive()) {
float f = FreeLookComponent.getFreePitch() * 0.017453292F;
float g = -FreeLookComponent.getFreeYaw() * 0.017453292F;
float h = MathHelper.cos(g);
float i = MathHelper.sin(g);
float j = MathHelper.cos(f);
float k = MathHelper.sin(f);
return new Vec3d((double) (i * j), (double) (-k), (double) (h * j));
}
return mc.player.getRotationVec(1.0F);
}

private boolean isLookingAtBox(LivingEntity target, boolean expanded, boolean addVertical) {
Vec3d eye = mc.player.getEyePos();
Vec3d look = getMouseLookVec();
Vec3d end = eye.add(look.multiply(searchDistance.getValue()));

Box box = expanded ? getExpandedBox(target) : getDefaultBox(target);
if (addVertical) {
box = box.expand(0.0, EXTRA_VERTICAL_RAY, 0.0);
}

if (box.contains(eye)) {
double dx = target.getX() - eye.x;
double dz = target.getZ() - eye.z;
double lx = look.x;
double lz = look.z;
double horiz = Math.sqrt(dx * dx + dz * dz);
double lookHoriz = Math.sqrt(lx * lx + lz * lz);
if (horiz < 0.01 || lookHoriz < 0.01) return true;
double dot = (dx / horiz) * (lx / lookHoriz) + (dz / horiz) * (lz / lookHoriz);
return dot > -0.5;
}
return box.raycast(eye, end).isPresent();
}

private Vec3d getDefaultAimPoint(LivingEntity target) {
Vec3d eye = mc.player.getEyePos();
Vec3d look = mc.player.getRotationVec(1.0F);
Vec3d end = eye.add(look.multiply(searchDistance.getValue()));

Box realBox = getDefaultBox(target);
Box safe = new Box(
realBox.minX + 0.2, realBox.minY,
realBox.minZ + 0.2, realBox.maxX - 0.2,
realBox.maxY, realBox.maxZ - 0.2
);
Box expanded = getExpandedBox(target);
Vec3d projected = expanded.raycast(eye, end).orElse(expanded.getCenter());
return clampToBox(projected, safe);
}

private boolean isVerticalOutside(LivingEntity target) {
Vec3d eye = mc.player.getEyePos();
Box box = getDefaultBox(target);
double y = projectVerticalIntersection(target, eye, mc.player.getPitch());
return y < box.minY || y > box.maxY;
}

private Vec3d getVerticalEdgePoint(LivingEntity target) {
Vec3d eye = mc.player.getEyePos();
Box box = getDefaultBox(target);
double y = projectVerticalIntersection(target, eye, mc.player.getPitch());
double picked;
if (y < box.minY) {
picked = box.minY + 0.1;
} else if (y > box.maxY) {
picked = box.maxY - 0.1;
} else {
return null;
}
return new Vec3d(target.getX(), picked, target.getZ());
}

private double projectVerticalIntersection(LivingEntity target, Vec3d eye, float pitch) {
double dx = target.getX() - eye.x;
double dz = target.getZ() - eye.z;
double horiz = Math.sqrt(dx * dx + dz * dz);
double rad = Math.toRadians(pitch);
return horiz < 0.5 ? eye.y - Math.tan(rad) * 0.5 : eye.y - Math.tan(rad) * horiz;
}

/* === Боксы === */

private Box getDefaultBox(Entity entity) {
return entity.getType().getDimensions().getBoxAt(entity.getPos());
}

private Box getExpandedBox(Entity entity) {
float radius = getBaseRadius(entity) + Math.max(0.0F, size.getFloatValue() - VANILLA_SIZE);
return buildBoxAround(entity, radius);
}

private Box buildBoxAround(Entity entity, float radius) {
return new Box(
entity.getX() - radius,
entity.getY(),
entity.getZ() - radius,
entity.getX() + radius,
entity.getY() + entity.getHeight(),
entity.getZ() + radius
);
}

private float getBaseRadius(Entity entity) {
return (float) (getDefaultBox(entity).getLengthX() / 2.0);
}

private void resetBox(LivingEntity entity) {
entity.setBoundingBox(getDefaultBox(entity));
}

private void resetAllBoxes() {
if (mc.world == null || mc.player == null) return;
for (Entity entity : mc.world.getEntities()) {
if (entity instanceof LivingEntity living && living != mc.player) {
resetBox(living);
}
}
}

/* === Цели === */

private boolean isTargetEntity(Entity entity) {
if (TARGET_ALL.equals(targets.getValue())) return entity instanceof LivingEntity;
if (TARGET_PLAYERS.equals(targets.getValue())) return entity instanceof PlayerEntity;
if (TARGET_MOBS.equals(targets.getValue())) return entity instanceof MobEntity;
return false;
}

/* === Оружие / броня === */

private boolean hasWeapon() {
if (mc.player == null) return false;
return isWeapon(mc.player.getMainHandStack()) || isWeapon(mc.player.getOffHandStack());
}

private boolean isWeapon(ItemStack stack) {
if (stack == null || stack.isEmpty()) return false;
return stack.getItem() instanceof SwordItem
|| stack.getItem() instanceof AxeItem
|| stack.getItem() instanceof TridentItem
|| stack.getItem() instanceof MaceItem;
}

private boolean hasArmor(PlayerEntity player) {
return !player.getInventory().armor.get(0).isEmpty()
|| !player.getInventory().armor.get(1).isEmpty()
|| !player.getInventory().armor.get(2).isEmpty()
|| !player.getInventory().armor.get(3).isEmpty();
}

/* === Ротация / геометрия === */

private float getYawTo(Vec3d point) {
Vec3d eye = mc.player.getEyePos();
Vec3d adj = point;
if (rotationTarget != null) {
adj = adj.add(rotationTarget.getVelocity().multiply(0.1));
}
double dx = adj.x - eye.x;
double dz = adj.z - eye.z;
return (float) Math.toDegrees(Math.atan2(dz, dx)) - 90.0F;
}

private float getPitchTo(Vec3d point) {
Vec3d eye = mc.player.getEyePos();
double dx = point.x - eye.x;
double dy = point.y - eye.y;
double dz = point.z - eye.z;
double horiz = Math.sqrt(dx * dx + dz * dz);
return (float) -Math.toDegrees(Math.atan2(dy, horiz));
}

private float lerpAngle(float from, float to, double speed) {
return from + wrapDegrees(to - from) * (float) speed;
}

private float lerpPitch(float from, float to, double speed) {
return MathHelper.clamp(from + (to - from) * (float) speed, -90.0F, 90.0F);
}

private static float wrapDegrees(float value) {
return ((value + 180.0F) % 360.0F + 360.0F) % 360.0F - 180.0F;
}

private static double wrapDegrees(double value) {
value %= 360.0;
if (value > 180.0) value -= 360.0;
if (value < -180.0) value += 360.0;
return value;
}

private double getGcd() {
double sens = mc.options.getMouseSensitivity().getValue();
double f = sens * 0.6 + 0.2;
return f * f * f * 1.2;
}

private double applyStepGcd(double value, double gcd) {
return gcd <= 1.0E-4 ? value : value - value % gcd;
}

private Vec3d clampToBox(Vec3d point, Box box) {
return new Vec3d(
Math.max(box.minX, Math.min(point.x, box.maxX)),
Math.max(box.minY, Math.min(point.y, box.maxY)),
Math.max(box.minZ, Math.min(point.z, box.maxZ))
);
}

private void applyRotation() {
RotationComponent.update(
new Rotation(currentYaw, currentPitch),
360, 360, 360, 360, 0, 1, clientLook
);
}

private void snapToTarget(LivingEntity target) {
rotationTarget = target;
Vec3d point;
if (isVerticalOutside(target)) {
Vec3d edge = getVerticalEdgePoint(target);
point = edge != null ? edge : getDefaultAimPoint(target);
} else {
point = getDefaultAimPoint(target);
}

currentYaw = getYawTo(point);
currentPitch = MathHelper.clamp(getPitchTo(point), -90.0F, 90.0F);
hasRotation = true;
rotating = true;
returning = false;
applyRotation();
}

private void queueSnapAttack(LivingEntity target) {
snapToTarget(target);

// Выполняем удар сразу же, чтобы не было задержки в 1 тик.
// Это поможет, если цель быстро движется.
ignoreAttackEvent = true;
if (mc.interactionManager != null && mc.player != null) {
mc.interactionManager.attackEntity(mc.player, target);
mc.player.swingHand(Hand.MAIN_HAND);
}
}

private void processQueuedSnapAttack() {
// Метод оставлен для совместимости, но теперь атака происходит мгновенно в queueSnapAttack
clearQueuedSnapAttack();
}

private void clearQueuedSnapAttack() {
queuedSnapAttackTarget = null;
queuedSnapAttackTicks = 0;
}

private void doFakeSwing() {
if (!fakeSwing.getValue() || mc.player == null) return;
mc.player.swingHand(Hand.MAIN_HAND);
mc.player.resetLastAttackedTicks();
}

private void resetRotation() {
rotationTarget = null;
aimPoint = null;
previousTarget = null;
hasRotation = false;
rotating = false;
fastAimPhase = false;
verticalAim = false;
returning = false;
currentYaw = 0.0F;
currentPitch = 0.0F;
rotationDeltaTime = 0L;
targetStartTime = 0L;
returnStartTime = 0L;
}
}
1778316074735.png
 
Ситуация такая , что удары по хитбоксам(увеличенной части) нормально проходят только при фрилук или ф5 , а от 1 лица не идут чё за хуня

Java:
Expand Collapse Copy
package zov.polyak.module.list.combat;

import com.google.common.eventbus.Subscribe;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.mob.MobEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.AxeItem;
import net.minecraft.item.ItemStack;
import net.minecraft.item.MaceItem;
import net.minecraft.item.SwordItem;
import net.minecraft.item.TridentItem;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.EntityHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import zov.polyak.event.EventGameUpdate;
import zov.polyak.event.list.EventAttack;
import zov.polyak.event.list.EventTick;
import zov.polyak.event.list.EventUseItem;
import zov.polyak.module.Module;
import zov.polyak.module.ModuleCategory;
import zov.polyak.module.ModuleInformation;
import zov.polyak.module.settings.BooleanSetting;
import zov.polyak.module.settings.ModeSetting;
import zov.polyak.module.settings.SliderSetting;
import zov.polyak.util.friend.FriendRepository;
import zov.polyak.util.rotation.FreeLookComponent;
import zov.polyak.util.rotation.Rotation;
import zov.polyak.util.rotation.RotationComponent;

import java.util.concurrent.ThreadLocalRandom;

@ModuleInformation(
        moduleName = "Hitbox",
        moduleDesc = "Увеличивает размер хитбокса игрока",
        moduleCategory = ModuleCategory.COMBAT
)
public class Hitbox extends Module {

    private static final String ROTATION_DEFAULT = "Обычная";
    private static final String ROTATION_NEW = "Новая";

    private static final String TARGET_PLAYERS = "Игроки";
    private static final String TARGET_MOBS = "Мобы";
    private static final String TARGET_ALL = "Все";

    private static final float VANILLA_SIZE = 0.3F;
    private static final double EXTRA_VERTICAL_RAY = 0.5;
    private static final long NANOS_PER_SECOND = 1_000_000_000L;

    /* === Настройки === */

    private final ModeSetting targets = new ModeSetting(
            "Цели", TARGET_PLAYERS, TARGET_PLAYERS, TARGET_MOBS, TARGET_ALL
    );

    private final BooleanSetting onlyWithWeapon = new BooleanSetting("Только с оружием", true);
    private final BooleanSetting onlyArmored = new BooleanSetting("Только в броне", false);
    private final BooleanSetting onlyTarget = new BooleanSetting("Только на противнике", false);
    private final SliderSetting resetTime = new SliderSetting("Время сброса", 3.0, 1.0, 7.0, 0.5)
            .setVisible(onlyTarget::getValue);

    private final BooleanSetting invisibleHitbox = new BooleanSetting("Невидимый хитбокс", false);

    private final BooleanSetting fixedSize = new BooleanSetting("Фиксированный размер", true);
    private final SliderSetting fixedSizeValue = new SliderSetting("Фикс. размер", 0.7, 0.3, 1.2, 0.05)
            .setVisible(fixedSize::getValue);

    private final SliderSetting minSize = new SliderSetting("Мин. размер", 0.3, 0.2, 1.0, 0.05)
            .setVisible(() -> !fixedSize.getValue());
    private final SliderSetting maxSize = new SliderSetting("Макс. размер", 2.0, 0.5, 5.0, 0.1)
            .setVisible(() -> !fixedSize.getValue());
    private final SliderSetting step = new SliderSetting("Шаг", 0.1, 0.05, 0.5, 0.05)
            .setVisible(() -> !fixedSize.getValue());
    private final SliderSetting size = new SliderSetting("Размер", 0.3, 0.3, 5.0, 0.05)
            .setVisible(() -> !fixedSize.getValue());

    private final BooleanSetting animation = new BooleanSetting("Анимация", true);
    private final SliderSetting animationSpeed = new SliderSetting("Скорость анимации", 6.0, 1.0, 15.0, 0.5)
            .setVisible(animation::getValue);

    private final BooleanSetting bypass = new BooleanSetting("Обход", true);
    private final ModeSetting rotationMode = new ModeSetting("Ротация", ROTATION_NEW, ROTATION_DEFAULT, ROTATION_NEW)
            .setVisible(bypass::getValue);
    private final BooleanSetting antiReach = new BooleanSetting("Anti-Reach", true)
            .setVisible(bypass::getValue);
    private final SliderSetting antiReachDistance = new SliderSetting("Дистанция Anti-Reach", 2.85, 1.0, 3.0, 0.01)
            .setVisible(() -> bypass.getValue() && antiReach.getValue());
    private final BooleanSetting fakeSwing = new BooleanSetting("Фейк свинг", true)
            .setVisible(bypass::getValue);
    private final SliderSetting searchDistance = new SliderSetting("Дистанция", 5.0, 3.0, 10.0, 0.5)
            .setVisible(bypass::getValue);
    private final SliderSetting aimSpeed = new SliderSetting("Скорость наводки", 0.85, 0.1, 2.0, 0.05)
            .setVisible(bypass::getValue);
    private final SliderSetting trackingSpeed = new SliderSetting("Скорость слежения", 0.85, 0.1, 2.0, 0.05)
            .setVisible(bypass::getValue);

    /* === Состояние === */

    private final boolean clientLook = false;
    private double lastVariableSize = VANILLA_SIZE;

    private LivingEntity rotationTarget;
    private Vec3d aimPoint;
    private LivingEntity onlyTargetEntity;
    private long onlyTargetTime;

    private boolean usingItem;

    private float currentYaw;
    private float currentPitch;
    private boolean hasRotation;
    private boolean rotating;
    private boolean fastAimPhase;
    private boolean verticalAim;

    private float animatedSize = VANILLA_SIZE;
    private long lastAnimationTime;

    private long rotationDeltaTime;
    private long targetStartTime;
    private long returnStartTime;
    private LivingEntity previousTarget;
    private boolean returning;
    private LivingEntity queuedSnapAttackTarget;
    private int queuedSnapAttackTicks;
    private boolean ignoreAttackEvent;

    /* === Жизненный цикл === */

    @Override
    public void onEnable() {
        super.onEnable();

        if (fixedSize.getValue()) {
            size.setValue(fixedSizeValue.getValue());
        } else {
            size.setValue(lastVariableSize);
        }

        animatedSize = VANILLA_SIZE;
        lastAnimationTime = System.nanoTime();
        applyHitboxes();
        clearQueuedSnapAttack();
        ignoreAttackEvent = false;
        resetRotation();
    }

    @Override
    public void onDisable() {
        size.setValue(VANILLA_SIZE);
        animatedSize = VANILLA_SIZE;
        resetAllBoxes();
        clearQueuedSnapAttack();
        ignoreAttackEvent = false;
        resetRotation();
        super.onDisable();
    }

    /* === Tick: бокс + анимация === */

    @Subscribe
    private void onTick(EventTick event) {
        if (mc.player == null || mc.world == null) return;

        updateAnimation();
        updateOnlyTarget();
        applyHitboxes();
        processQueuedSnapAttack();
    }

    /* === GameUpdate: bypass-ротация === */

    @Subscribe
    private void onGameUpdate(EventGameUpdate event) {
        if (mc.player == null || mc.world == null) return;

        applyHitboxes();

        // Игрок использует предмет — временно сбрасываем размер до vanilla.
        if (mc.player.isUsingItem() && !usingItem) {
            usingItem = true;
            if (!fixedSize.getValue()) {
                lastVariableSize = size.getValue();
            }
            size.setValue(VANILLA_SIZE);
        } else if (!mc.player.isUsingItem() && usingItem) {
            usingItem = false;
            double restore = fixedSize.getValue() ? fixedSizeValue.getValue() : lastVariableSize;
            size.setValue(restore);
        }

        float currentSize = size.getFloatValue();

        if (currentSize <= VANILLA_SIZE) {
            if (rotating) returnToCamera();
            return;
        }

        if (!bypass.getValue()) {
            returnToCamera();
            return;
        }

        if (onlyWithWeapon.getValue() && !hasWeapon()) {
            returnToCamera();
            return;
        }

        LivingEntity target = findTarget();
        if (target == null) {
            returnToCamera();
            return;
        }

        boolean expandedHit = isLookingAtBox(target, true, false);
        if (ROTATION_NEW.equals(rotationMode.getValue()) && !expandedHit) {
            expandedHit = isLookingAtBox(target, true, true);
        }

        if (!expandedHit) {
            returnToCamera();
            return;
        }

        boolean realHit = isLookingAtBox(target, false, false);
        if (realHit && !rotating) {
            returnToCamera();
            return;
        }

        boolean verticalOutside = isVerticalOutside(target);
        rotationTarget = target;
        rotating = true;

        if (!hasRotation) {
            currentYaw = mc.player.getYaw();
            currentPitch = mc.player.getPitch();
            hasRotation = true;
            fastAimPhase = true;
        }

        if (previousTarget != target) {
            previousTarget = target;
            targetStartTime = System.currentTimeMillis();
            fastAimPhase = true;
        }

        if (verticalOutside) {
            Vec3d edge = getVerticalEdgePoint(target);
            if (edge != null) {
                aimPoint = edge;
                verticalAim = true;
            } else {
                aimPoint = getDefaultAimPoint(target);
                verticalAim = false;
            }
        } else {
            aimPoint = getDefaultAimPoint(target);
            verticalAim = false;
        }

        if (ROTATION_NEW.equals(rotationMode.getValue())) {
            updateNewRotation(aimPoint);
        } else {
            updateDefaultRotation(aimPoint);
        }

        returning = false;
        applyRotation();
    }

    /* === Атака: only-target + AntiReach === */

    @Subscribe
    private void onAttack(EventAttack event) {
        if (mc.player == null || mc.world == null) return;
        if (ignoreAttackEvent) {
            ignoreAttackEvent = false;
            return;
        }
        if (!(event.getEntity() instanceof LivingEntity living)) return;
        if (!isTargetEntity(living)) return;

        if (bypass.getValue()
                && ROTATION_NEW.equals(rotationMode.getValue())
                && size.getFloatValue() > VANILLA_SIZE) {
            boolean realHit = isLookingAtBox(living, false, false);
            boolean expandedHit = isLookingAtBox(living, true, true);
            if (expandedHit && !realHit) {
                event.cancelEvent();
                queueSnapAttack(living);
                return;
            }
        }

        // Запоминаем последнего ударенного
        if (onlyTarget.getValue()) {
            onlyTargetEntity = living;
            onlyTargetTime = System.currentTimeMillis();
        }

        if (antiReach.getValue() && shouldCancelByAntiReach(living)) {
            event.cancelEvent();
            doFakeSwing();
        }
    }

    /* === Использование предмета: AntiReach + cancel в новом режиме === */

    @Subscribe
    private void onUseItem(EventUseItem event) {
        if (mc.player == null || mc.world == null) return;

        HitResult hitResult = event.getTarget();
        if (!(hitResult instanceof EntityHitResult entityHit)) return;
        if (!(entityHit.getEntity() instanceof LivingEntity living)) return;
        if (!isTargetEntity(living)) return;

        if (onlyTarget.getValue() && isWithinTarget(living)) {
            onlyTargetEntity = living;
            onlyTargetTime = System.currentTimeMillis();
        }

        // В новой ротации режем удар по entity, в которого попали только из-за расширения
        if (bypass.getValue()
                && ROTATION_NEW.equals(rotationMode.getValue())
                && size.getFloatValue() > VANILLA_SIZE) {
            boolean realHit = isLookingAtBox(living, false, false);
            boolean expandedHit = isLookingAtBox(living, true, true);
            if (expandedHit && !realHit) {
                event.cancelEvent();
                queueSnapAttack(living);
                return;
            }
        }

        if (antiReach.getValue() && shouldCancelByAntiReach(living)) {
            event.cancelEvent();
            doFakeSwing();
        }
    }

    /* === Расширение хитбоксов === */

    private void applyHitboxes() {
        if (mc.world == null || mc.player == null) return;
        float currentSize = size.getFloatValue();
        for (Entity entity : mc.world.getEntities()) {
            if (entity instanceof LivingEntity living && living != mc.player) {
                if (isValidBypassTarget(living) && isWithinTarget(living) && currentSize > VANILLA_SIZE) {
                    living.setBoundingBox(getExpandedBox(living));
                } else {
                    resetBox(living);
                }
            }
        }
    }

    private float getCurrentExpandRadius(LivingEntity living) {
        float baseRadius = getBaseRadius(living);
        if (invisibleHitbox.getValue()) return baseRadius;

        float visualSize = animation.getValue() ? animatedSize : size.getFloatValue();
        return baseRadius + (visualSize - VANILLA_SIZE);
    }

    /* === Анимация === */

    private void updateAnimation() {
        long now = System.nanoTime();
        if (lastAnimationTime == 0L || now - lastAnimationTime > NANOS_PER_SECOND) {
            lastAnimationTime = now;
            return;
        }

        float dt = (float) (now - lastAnimationTime) / NANOS_PER_SECOND;
        lastAnimationTime = now;

        float target = invisibleHitbox.getValue() ? VANILLA_SIZE : size.getFloatValue();
        float diff = target - animatedSize;

        if (Math.abs(diff) > 0.001F) {
            float speed = animationSpeed.getFloatValue();
            float k = 1.0F - (float) Math.exp(-dt * speed);
            animatedSize += diff * k;
        } else {
            animatedSize = target;
        }
    }

    /* === Only-target reset === */

    private void updateOnlyTarget() {
        if (!onlyTarget.getValue() || onlyTargetEntity == null) return;

        long elapsed = System.currentTimeMillis() - onlyTargetTime;
        long limit = (long) (resetTime.getValue() * 1000.0);
        if (elapsed >= limit) {
            onlyTargetEntity = null;
            onlyTargetTime = 0L;
        }
    }

    private boolean isWithinTarget(LivingEntity living) {
        return !onlyTarget.getValue() || living == onlyTargetEntity;
    }

    /* === Поиск цели === */

    private LivingEntity findTarget() {
        LivingEntity best = null;
        double bestDistance = searchDistance.getValue();

        for (Entity entity : mc.world.getEntities()) {
            if (!(entity instanceof LivingEntity living)) continue;
            if (living == mc.player) continue;
            if (!isValidBypassTarget(living)) continue;
            if (!isWithinTarget(living)) continue;

            double distance = mc.player.distanceTo(living);
            if (distance >= bestDistance) continue;

            bestDistance = distance;
            best = living;
        }
        return best;
    }

    private boolean isValidBypassTarget(LivingEntity living) {
        if (!living.isAlive()) return false;
        if (!isTargetEntity(living)) return false;

        if (living instanceof PlayerEntity player) {
            if (player.isSpectator()) return false;
            if (!FriendRepository.shouldAttack(player)) return false;
            if (onlyArmored.getValue() && !hasArmor(player)) return false;
        }
        return true;
    }

    /* === Обычная ротация === */

    private void updateDefaultRotation(Vec3d point) {
        float targetYaw = getYawTo(point);
        float targetPitch = getPitchTo(point);

        float yawDiff = Math.abs(wrapDegrees(targetYaw - currentYaw));

        if (yawDiff > 2.0F) {
            fastAimPhase = true;
            currentYaw = lerpAngle(currentYaw, targetYaw, aimSpeed.getValue());
        } else {
            fastAimPhase = false;
            currentYaw = lerpAngle(currentYaw, targetYaw, trackingSpeed.getValue());
        }

        if (verticalAim) {
            float pitchDiff = Math.abs(targetPitch - currentPitch);
            if (pitchDiff > 2.0F) {
                currentPitch = lerpPitch(currentPitch, targetPitch, aimSpeed.getValue());
            } else {
                currentPitch = lerpPitch(currentPitch, targetPitch, trackingSpeed.getValue());
            }
        } else {
            float playerPitch = mc.player.getPitch();
            float pitchDiff = Math.abs(playerPitch - currentPitch);
            if (pitchDiff > 1.0F) {
                currentPitch = lerpPitch(currentPitch, playerPitch, aimSpeed.getValue());
            } else {
                currentPitch = playerPitch;
            }
        }
    }

    /* === Новая ротация === */

    private void updateNewRotation(Vec3d point) {
        long now = System.nanoTime();
        double dt = rotationDeltaTime > 0L ? (now - rotationDeltaTime) / 16_666_666.7 : 1.0;
        dt = MathHelper.clamp(dt, 0.05, 3.0);
        rotationDeltaTime = now;

        if (rotationTarget != previousTarget) {
            previousTarget = rotationTarget;
            targetStartTime = System.currentTimeMillis();
        }

        float targetYaw = getYawTo(point);
        float targetPitch = verticalAim ? getPitchTo(point) : mc.player.getPitch();

        double yawDelta = wrapDegrees(targetYaw - currentYaw);
        double pitchDelta = targetPitch - currentPitch;

        double distance = Math.sqrt(yawDelta * yawDelta + pitchDelta * pitchDelta);
        if (distance < 0.05) return;

        fastAimPhase = distance > 2.0;
        double speed = fastAimPhase ? aimSpeed.getValue() : trackingSpeed.getValue();

        double reaction = MathHelper.clamp((System.currentTimeMillis() - targetStartTime) / 200.0, 0.0, 1.0);
        double smoothReaction = reaction * reaction * (3.0 - 2.0 * reaction);
        double distanceFactor = MathHelper.clamp(distance / 15.0, 0.15, 1.0);
        double rng = 0.9 + ThreadLocalRandom.current().nextDouble(0.2);
        double mult = speed * smoothReaction * distanceFactor * dt * rng;

        double yawStep = yawDelta * mult;
        double pitchStep = pitchDelta * mult;

        double gcd = getGcd();
        yawStep = applyStepGcd(yawStep, gcd);
        pitchStep = applyStepGcd(pitchStep, gcd);

        if (yawStep == 0.0 && Math.abs(yawDelta) > gcd) yawStep = Math.signum(yawDelta) * gcd;
        if (pitchStep == 0.0 && Math.abs(pitchDelta) > gcd) pitchStep = Math.signum(pitchDelta) * gcd;
        if (Math.abs(yawStep) > Math.abs(yawDelta)) yawStep = applyStepGcd(yawDelta, gcd);
        if (Math.abs(pitchStep) > Math.abs(pitchDelta)) pitchStep = applyStepGcd(pitchDelta, gcd);

        currentYaw += (float) yawStep;
        currentPitch = MathHelper.clamp(currentPitch + (float) pitchStep, -90.0F, 90.0F);
    }

    /* === Возврат камеры === */

    private void returnToCamera() {
        if (!hasRotation || mc.player == null) {
            resetRotation();
            return;
        }

        if (!returning) {
            returning = true;
            returnStartTime = System.currentTimeMillis();
        }

        float playerYaw = mc.player.getYaw();
        float playerPitch = mc.player.getPitch();
        float yawDelta = Math.abs(wrapDegrees(currentYaw - playerYaw));
        float pitchDelta = Math.abs(currentPitch - playerPitch);

        if (ROTATION_NEW.equals(rotationMode.getValue())) {
            updateReturnNew(playerYaw, playerPitch);
        } else {
            currentYaw = lerpAngle(currentYaw, playerYaw, aimSpeed.getValue());
            currentPitch = lerpPitch(currentPitch, playerPitch, aimSpeed.getValue());
        }

        applyRotation();

        if (yawDelta < 5.0F && pitchDelta < 5.0F) {
            resetRotation();
        }
    }

    private void updateReturnNew(float playerYaw, float playerPitch) {
        long now = System.nanoTime();
        double dt = rotationDeltaTime > 0L ? (now - rotationDeltaTime) / 16_666_666.7 : 1.0;
        dt = MathHelper.clamp(dt, 0.05, 3.0);
        rotationDeltaTime = now;

        double yawDelta = wrapDegrees(playerYaw - currentYaw);
        double pitchDelta = playerPitch - currentPitch;

        double distance = Math.sqrt(yawDelta * yawDelta + pitchDelta * pitchDelta);
        if (distance < 0.05) return;

        double speed = aimSpeed.getValue();
        double reaction = MathHelper.clamp((System.currentTimeMillis() - returnStartTime) / 200.0, 0.0, 1.0);
        double smoothReaction = reaction * reaction * (3.0 - 2.0 * reaction);
        double distanceFactor = MathHelper.clamp(distance / 15.0, 0.15, 1.0);
        double rng = 0.9 + ThreadLocalRandom.current().nextDouble(0.2);
        double mult = speed * smoothReaction * distanceFactor * dt * rng;

        double yawStep = yawDelta * mult;
        double pitchStep = pitchDelta * mult;

        double gcd = getGcd();
        yawStep = applyStepGcd(yawStep, gcd);
        pitchStep = applyStepGcd(pitchStep, gcd);

        if (yawStep == 0.0 && Math.abs(yawDelta) > gcd) yawStep = Math.signum(yawDelta) * gcd;
        if (pitchStep == 0.0 && Math.abs(pitchDelta) > gcd) pitchStep = Math.signum(pitchDelta) * gcd;

        currentYaw += (float) yawStep;
        currentPitch = MathHelper.clamp(currentPitch + (float) pitchStep, -90.0F, 90.0F);
    }

    /* === AntiReach === */

    private boolean shouldCancelByAntiReach(LivingEntity target) {
        if (size.getFloatValue() <= VANILLA_SIZE) return false;

        Box realBox = getDefaultBox(target);
        Vec3d eye = mc.player.getEyePos();
        Vec3d nearest = clampToBox(eye, realBox);
        return eye.distanceTo(nearest) > antiReachDistance.getValue();
    }

    /* === Raytrace === */

    private Vec3d getMouseLookVec() {
        if (FreeLookComponent.isActive()) {
            float f = FreeLookComponent.getFreePitch() * 0.017453292F;
            float g = -FreeLookComponent.getFreeYaw() * 0.017453292F;
            float h = MathHelper.cos(g);
            float i = MathHelper.sin(g);
            float j = MathHelper.cos(f);
            float k = MathHelper.sin(f);
            return new Vec3d((double) (i * j), (double) (-k), (double) (h * j));
        }
        return mc.player.getRotationVec(1.0F);
    }

    private boolean isLookingAtBox(LivingEntity target, boolean expanded, boolean addVertical) {
        Vec3d eye = mc.player.getEyePos();
        Vec3d look = getMouseLookVec();
        Vec3d end = eye.add(look.multiply(searchDistance.getValue()));

        Box box = expanded ? getExpandedBox(target) : getDefaultBox(target);
        if (addVertical) {
            box = box.expand(0.0, EXTRA_VERTICAL_RAY, 0.0);
        }

        if (box.contains(eye)) {
            double dx = target.getX() - eye.x;
            double dz = target.getZ() - eye.z;
            double lx = look.x;
            double lz = look.z;
            double horiz = Math.sqrt(dx * dx + dz * dz);
            double lookHoriz = Math.sqrt(lx * lx + lz * lz);
            if (horiz < 0.01 || lookHoriz < 0.01) return true;
            double dot = (dx / horiz) * (lx / lookHoriz) + (dz / horiz) * (lz / lookHoriz);
            return dot > -0.5;
        }
        return box.raycast(eye, end).isPresent();
    }

    private Vec3d getDefaultAimPoint(LivingEntity target) {
        Vec3d eye = mc.player.getEyePos();
        Vec3d look = mc.player.getRotationVec(1.0F);
        Vec3d end = eye.add(look.multiply(searchDistance.getValue()));

        Box realBox = getDefaultBox(target);
        Box safe = new Box(
                realBox.minX + 0.2, realBox.minY,
                realBox.minZ + 0.2, realBox.maxX - 0.2,
                realBox.maxY, realBox.maxZ - 0.2
        );
        Box expanded = getExpandedBox(target);
        Vec3d projected = expanded.raycast(eye, end).orElse(expanded.getCenter());
        return clampToBox(projected, safe);
    }

    private boolean isVerticalOutside(LivingEntity target) {
        Vec3d eye = mc.player.getEyePos();
        Box box = getDefaultBox(target);
        double y = projectVerticalIntersection(target, eye, mc.player.getPitch());
        return y < box.minY || y > box.maxY;
    }

    private Vec3d getVerticalEdgePoint(LivingEntity target) {
        Vec3d eye = mc.player.getEyePos();
        Box box = getDefaultBox(target);
        double y = projectVerticalIntersection(target, eye, mc.player.getPitch());
        double picked;
        if (y < box.minY) {
            picked = box.minY + 0.1;
        } else if (y > box.maxY) {
            picked = box.maxY - 0.1;
        } else {
            return null;
        }
        return new Vec3d(target.getX(), picked, target.getZ());
    }

    private double projectVerticalIntersection(LivingEntity target, Vec3d eye, float pitch) {
        double dx = target.getX() - eye.x;
        double dz = target.getZ() - eye.z;
        double horiz = Math.sqrt(dx * dx + dz * dz);
        double rad = Math.toRadians(pitch);
        return horiz < 0.5 ? eye.y - Math.tan(rad) * 0.5 : eye.y - Math.tan(rad) * horiz;
    }

    /* === Боксы === */

    private Box getDefaultBox(Entity entity) {
        return entity.getType().getDimensions().getBoxAt(entity.getPos());
    }

    private Box getExpandedBox(Entity entity) {
        float radius = getBaseRadius(entity) + Math.max(0.0F, size.getFloatValue() - VANILLA_SIZE);
        return buildBoxAround(entity, radius);
    }

    private Box buildBoxAround(Entity entity, float radius) {
        return new Box(
                entity.getX() - radius,
                entity.getY(),
                entity.getZ() - radius,
                entity.getX() + radius,
                entity.getY() + entity.getHeight(),
                entity.getZ() + radius
        );
    }

    private float getBaseRadius(Entity entity) {
        return (float) (getDefaultBox(entity).getLengthX() / 2.0);
    }

    private void resetBox(LivingEntity entity) {
        entity.setBoundingBox(getDefaultBox(entity));
    }

    private void resetAllBoxes() {
        if (mc.world == null || mc.player == null) return;
        for (Entity entity : mc.world.getEntities()) {
            if (entity instanceof LivingEntity living && living != mc.player) {
                resetBox(living);
            }
        }
    }

    /* === Цели === */

    private boolean isTargetEntity(Entity entity) {
        if (TARGET_ALL.equals(targets.getValue())) return entity instanceof LivingEntity;
        if (TARGET_PLAYERS.equals(targets.getValue())) return entity instanceof PlayerEntity;
        if (TARGET_MOBS.equals(targets.getValue())) return entity instanceof MobEntity;
        return false;
    }

    /* === Оружие / броня === */

    private boolean hasWeapon() {
        if (mc.player == null) return false;
        return isWeapon(mc.player.getMainHandStack()) || isWeapon(mc.player.getOffHandStack());
    }

    private boolean isWeapon(ItemStack stack) {
        if (stack == null || stack.isEmpty()) return false;
        return stack.getItem() instanceof SwordItem
                || stack.getItem() instanceof AxeItem
                || stack.getItem() instanceof TridentItem
                || stack.getItem() instanceof MaceItem;
    }

    private boolean hasArmor(PlayerEntity player) {
        return !player.getInventory().armor.get(0).isEmpty()
                || !player.getInventory().armor.get(1).isEmpty()
                || !player.getInventory().armor.get(2).isEmpty()
                || !player.getInventory().armor.get(3).isEmpty();
    }

    /* === Ротация / геометрия === */

    private float getYawTo(Vec3d point) {
        Vec3d eye = mc.player.getEyePos();
        Vec3d adj = point;
        if (rotationTarget != null) {
            adj = adj.add(rotationTarget.getVelocity().multiply(0.1));
        }
        double dx = adj.x - eye.x;
        double dz = adj.z - eye.z;
        return (float) Math.toDegrees(Math.atan2(dz, dx)) - 90.0F;
    }

    private float getPitchTo(Vec3d point) {
        Vec3d eye = mc.player.getEyePos();
        double dx = point.x - eye.x;
        double dy = point.y - eye.y;
        double dz = point.z - eye.z;
        double horiz = Math.sqrt(dx * dx + dz * dz);
        return (float) -Math.toDegrees(Math.atan2(dy, horiz));
    }

    private float lerpAngle(float from, float to, double speed) {
        return from + wrapDegrees(to - from) * (float) speed;
    }

    private float lerpPitch(float from, float to, double speed) {
        return MathHelper.clamp(from + (to - from) * (float) speed, -90.0F, 90.0F);
    }

    private static float wrapDegrees(float value) {
        return ((value + 180.0F) % 360.0F + 360.0F) % 360.0F - 180.0F;
    }

    private static double wrapDegrees(double value) {
        value %= 360.0;
        if (value > 180.0) value -= 360.0;
        if (value < -180.0) value += 360.0;
        return value;
    }

    private double getGcd() {
        double sens = mc.options.getMouseSensitivity().getValue();
        double f = sens * 0.6 + 0.2;
        return f * f * f * 1.2;
    }

    private double applyStepGcd(double value, double gcd) {
        return gcd <= 1.0E-4 ? value : value - value % gcd;
    }

    private Vec3d clampToBox(Vec3d point, Box box) {
        return new Vec3d(
                Math.max(box.minX, Math.min(point.x, box.maxX)),
                Math.max(box.minY, Math.min(point.y, box.maxY)),
                Math.max(box.minZ, Math.min(point.z, box.maxZ))
        );
    }

    private void applyRotation() {
        RotationComponent.update(
                new Rotation(currentYaw, currentPitch),
                360, 360, 360, 360, 0, 1, clientLook
        );
    }

    private void snapToTarget(LivingEntity target) {
        rotationTarget = target;
        Vec3d point;
        if (isVerticalOutside(target)) {
            Vec3d edge = getVerticalEdgePoint(target);
            point = edge != null ? edge : getDefaultAimPoint(target);
        } else {
            point = getDefaultAimPoint(target);
        }

        currentYaw = getYawTo(point);
        currentPitch = MathHelper.clamp(getPitchTo(point), -90.0F, 90.0F);
        hasRotation = true;
        rotating = true;
        returning = false;
        applyRotation();
    }

    private void queueSnapAttack(LivingEntity target) {
        snapToTarget(target);
       
        // Выполняем удар сразу же, чтобы не было задержки в 1 тик.
        // Это поможет, если цель быстро движется.
        ignoreAttackEvent = true;
        if (mc.interactionManager != null && mc.player != null) {
            mc.interactionManager.attackEntity(mc.player, target);
            mc.player.swingHand(Hand.MAIN_HAND);
        }
    }

    private void processQueuedSnapAttack() {
        // Метод оставлен для совместимости, но теперь атака происходит мгновенно в queueSnapAttack
        clearQueuedSnapAttack();
    }

    private void clearQueuedSnapAttack() {
        queuedSnapAttackTarget = null;
        queuedSnapAttackTicks = 0;
    }

    private void doFakeSwing() {
        if (!fakeSwing.getValue() || mc.player == null) return;
        mc.player.swingHand(Hand.MAIN_HAND);
        mc.player.resetLastAttackedTicks();
    }

    private void resetRotation() {
        rotationTarget = null;
        aimPoint = null;
        previousTarget = null;
        hasRotation = false;
        rotating = false;
        fastAimPhase = false;
        verticalAim = false;
        returning = false;
        currentYaw = 0.0F;
        currentPitch = 0.0F;
        rotationDeltaTime = 0L;
        targetStartTime = 0L;
        returnStartTime = 0L;
    }
}
проблема в том что код спащен из system
 
Назад
Сверху Снизу