Вопрос Как зафиксить RotationEvent в 1.21.4 mcp

Начинающий
Начинающий
Статус
Оффлайн
Регистрация
13 Май 2025
Сообщения
95
Реакции
1
как пофиксить ротация когда работает ротация голову начинает трести а руки улетать (мотрит куда смотрит голова) ss
AttackAura:
Expand Collapse Copy
package i.chuppachups.reek.client.module.impl.combat;

import net.minecraft.util.Mth;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.animal.Animal;
import net.minecraft.world.entity.monster.Monster;
import net.minecraft.world.entity.npc.Villager;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.item.ArmorItem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.equipment.*;
import net.minecraft.world.phys.Vec3;

import i.chuppachups.reek.client.event.impl.packet.RotationEvent;
import i.chuppachups.reek.client.event.impl.player.EventUpdate;
import i.chuppachups.reek.client.module.api.Category;
import i.chuppachups.reek.client.module.api.Module;
import i.chuppachups.reek.client.module.setting.api.Setting;
import i.chuppachups.reek.client.module.setting.impl.*;
import i.chuppachups.reek.client.event.impl.player.EventInput;
import i.chuppachups.reek.client.module.api.ModuleAnnotation;
import i.chuppachups.reek.client.util.impl.move.MoveUtil;

import com.darkmagician6.eventapi.EventTarget;

import org.joml.Vector2f;

import java.util.List;

@ModuleAnnotation(name = "Attack Aura", category = Category.COMBAT)
public class AttackAura extends Module {

    public final ModeListSetting targetTypes = new ModeListSetting("Кого атаковать", this, new String[]{"Игроков"}, new String[]{"Игроков","Мобов","Жителей","Невидимых","Голых"});
    public final ModeSetting priorityMode = new ModeSetting("Приоритет по ", this,"Дистанции", new String[]{"Дистанции","Здоровью","Броне","Полю зрению","Всем сразу"});
    public final ModeSetting rotationMode = new ModeSetting("Тип наведения", this,"Grim/Vulcan", new String[]{"Grim/Vulcan","Matrix/Vulcan","FunTime Snap","FunTime Smooth"});
    public final ModeSetting correctionMoveMode = new ModeSetting("Коррекция движения", this,"Свободная", new String[]{"Свободная","Сфокусированная","Не корректировать"});
    public final ModeListSetting noHit = new ModeListSetting("Не бить если ", this, new String[]{"Открыт инвентарь"}, new String[]{"Открыт инвентарь","Используешь еду"});
    public final ModeSetting dopRange = new ModeSetting("Расширенная дистанция", this, "Отключена", new String[]{"Отключена","HolyWorld","FunTime/ReallyWorld"});
    public final ModeSetting sprintMode = new ModeSetting("Режим бега", this, "Легитный", new String[]{"Легитный","Пакетный"});
    public final NumberSetting range = new NumberSetting("Дистанция удара", this, 4.0f, 3.0f, 6.0f, 0.1f);

    public final BooleanSetting focusSingleTarget = new BooleanSetting("Фокусировать одну цель", this, false);
    public final BooleanSetting throughWalls = new BooleanSetting("Бить через стены", this, false);

    public static LivingEntity target;
    public Vector2f rotateVector = new Vector2f(0,0);
    public boolean isRotated;
    public long lastAttackTime = 0;

    public AttackAura() {
        this.addSettings(new Setting[]{targetTypes, priorityMode, rotationMode, correctionMoveMode, noHit, dopRange, sprintMode, range,focusSingleTarget,throughWalls});
    }

    @EventTarget
    public void onPlayerInput(EventInput event) {
        if (target == null || !isRotated) return;

        switch(correctionMoveMode.getMode()) {
            case "Сфокусированная":
                MoveUtil.fixMovement(event, rotateVector.x);
                break;
            case "Свободная":

                break;
            case "Не корректировать":

                break;
        }
    }

    @EventTarget
    public void onUpdate(EventUpdate event) {
        updateTarget();

        if(target != null) {

            rotateToTarget();

            if(isLookingAtTarget() && canAttack()) {
                attackTarget();
            }


        }
    }


    private boolean isLookingAtTarget() {
        if(target == null) return false;

        Vec3 eyePos = mc.player.getEyePosition(1.0F);
        Vec3 targetPos = target.position().add(0, target.getBbHeight() / 2.0, 0);
        Vec3 delta = targetPos.subtract(eyePos);

        float yawToTarget = (float) Math.toDegrees(Math.atan2(delta.z, delta.x)) - 90f;
        float pitchToTarget = (float) -Math.toDegrees(Math.atan2(delta.y, Math.hypot(delta.x, delta.z)));

        float yawDiff = Math.abs(Mth.wrapDegrees(yawToTarget - rotateVector.x));
        float pitchDiff = Math.abs(Mth.wrapDegrees(pitchToTarget - rotateVector.y));

        return yawDiff < 5f && pitchDiff < 5f;
    }

    @EventTarget
    public void onPacketRotation(RotationEvent e) {
        if (target == null) return;
        e.setYRot(rotateVector.x);
        e.setXRot(rotateVector.y);
    }

    private void updateTarget() {
        target = null;

        double attackDistance = range.getValue();
        double rotationDistance = attackDistance;

        switch(dopRange.getMode()) {
            case "HolyWorld":
                rotationDistance += 2.0;
                break;
            case "FunTime/ReallyWorld":
                rotationDistance += 1.5;
                break;
            default:
                break;
        }

        List<LivingEntity> entities = mc.level.getEntitiesOfClass(LivingEntity.class, mc.player.getBoundingBox().inflate(rotationDistance));
        LivingEntity bestTarget = null;
        double bestScore = Double.MAX_VALUE;

        for(LivingEntity entity : entities) {
            if(!isValid(entity)) continue;

            if(mc.player.distanceTo(entity) > rotationDistance) continue;

            if(noHit.getSelectedModes().contains("Открыт инвентарь") && mc.screen != null) continue;
            if(noHit.getSelectedModes().contains("Используешь еду") && mc.player.isUsingItem()) continue;
            if(!throughWalls.isToggled() && !mc.player.hasLineOfSight(entity)) continue;

            double score = calculatePriority(entity);
            if(score < bestScore) {
                bestScore = score;
                bestTarget = entity;
            }
        }

        if (bestTarget != null && mc.player.distanceTo(bestTarget) <= attackDistance) {
            target = bestTarget;
        }
    }

    private double calculatePriority(LivingEntity entity) {
        switch(priorityMode.getMode()) {
            case "Дистанции":
                return mc.player.distanceTo(entity);
            case "Здоровью":
                return entity.getHealth();
            case "Броне":
                return getArmorValue(entity);
            case "Полю зрению":
                return !mc.player.hasLineOfSight(entity) ? Double.MAX_VALUE : mc.player.distanceTo(entity);
            case "Всем сразу":
                return mc.player.distanceTo(entity) + entity.getHealth() + getArmorValue(entity);
            default:
                return mc.player.distanceTo(entity);
        }
    }
    private double getArmorValue(LivingEntity entity) {
        double totalArmor = 0;
        for (ItemStack stack : entity.getArmorSlots()) {
            if (stack != null && stack.getItem() instanceof ArmorItem armor) {
                ArmorMaterial material = armor.getArmorMaterial();
                ArmorType type = armor.getArmorType();
                int defenseValue = material.defense().getOrDefault(type, 0);
                totalArmor += defenseValue;
            }
        }
        return totalArmor;
    }


    private boolean isValid(LivingEntity entity) {
        if (entity == mc.player || !entity.isAlive() || entity.isInvulnerable()) {
            return false;
        }

        boolean allowPlayers = targetTypes.getSelectedModes().contains("Игроков");
        boolean allowMobs = targetTypes.getSelectedModes().contains("Мобов");
        boolean allowVillagers = targetTypes.getSelectedModes().contains("Жителей");
        boolean allowInvisible = targetTypes.getSelectedModes().contains("Невидимых");
        boolean allowNaked = targetTypes.getSelectedModes().contains("Голых");

        if (entity instanceof Player p) {
            if (!allowPlayers) return false;
            if (p.isInvisible() && !allowInvisible) return false;
            if (getArmorValue(p) == 0 && !allowNaked && allowPlayers) return false;
            return true;
        }

        if (entity instanceof Monster || entity instanceof Animal) {
            return allowMobs;
        }

        if (entity instanceof Villager) {
            return allowVillagers;
        }

        return false;
    }


    private boolean canAttack() {
        return mc.player.getAttackStrengthScale(0) >= 1;
    }

    /**
     * MODIFIED METHOD
     * This method now contains the logic for the visual head-snap during an attack.
     */
    private void attackTarget() {
        if(target == null) return;

            mc.gameMode.attack(mc.player, target);
            mc.player.swing(InteractionHand.MAIN_HAND);
            lastAttackTime = System.currentTimeMillis();

    }


    private void rotateToTarget() {
        if(target == null) return;

        double rotationDistance = range.getValue();
        switch(dopRange.getMode()) {
            case "HolyWorld":
                rotationDistance += 2.0;
                break;
            case "FunTime/ReallyWorld":
                rotationDistance += 4.0;
                break;
        }

        if(mc.player.distanceTo(target) > rotationDistance) return;

        Vec3 eyePos = mc.player.getEyePosition(1.0F);
        Vec3 targetPos = target.position().add(0, target.getBbHeight() / 2.0, 0);
        Vec3 delta = targetPos.subtract(eyePos);

        float yawToTarget = (float) Math.toDegrees(Math.atan2(delta.z, delta.x)) - 90f;
        float pitchToTarget = (float) -Math.toDegrees(Math.atan2(delta.y, Math.hypot(delta.x, delta.z)));

        switch(rotationMode.getMode()) {
            case "Grim/Vulcan": {

                break;
            } case "Matrix/Vulcan": {
                if(target == null) break;

                 eyePos = mc.player.getEyePosition(1.0F);
                 targetPos = target.position().add(0, target.getBbHeight() / 2.0, 0);
                 delta = targetPos.subtract(eyePos);

                 yawToTarget = (float) Math.toDegrees(Math.atan2(delta.z, delta.x)) - 90f;
                 pitchToTarget = (float) -Math.toDegrees(Math.atan2(delta.y, Math.hypot(delta.x, delta.z)));

                float yawDelta = Mth.wrapDegrees(yawToTarget - rotateVector.x);
                float pitchDelta = Mth.wrapDegrees(pitchToTarget - rotateVector.y);

                float distanceYaw = yawDelta;
                float distancePitch = pitchDelta;

                float rotationDifference = (float) Math.hypot(distanceYaw, distancePitch);
                if (rotationDifference < 0.001f) rotationDifference = 1f;

                float maxYawChange = Math.abs(distanceYaw / rotationDifference) * 60f;
                float maxPitchChange = Math.abs(distancePitch / rotationDifference) * 45f;

                float moveYaw = Mth.clamp(distanceYaw, -maxYawChange, maxYawChange);
                float movePitch = Mth.clamp(distancePitch, -maxPitchChange, maxPitchChange);

                float baseYawSpeed = 0.45f + (float) (Math.abs(moveYaw) * (0.4f + Math.random() * 0.3f));
                float basePitchSpeed = 0.45f + (float) (Math.abs(movePitch) * (0.3f + Math.random() * 0.2f));

                float dynamicYawSpeed = Math.min(baseYawSpeed, 40f);
                float dynamicPitchSpeed = Math.min(basePitchSpeed, 40f);

                float yawStep = Math.copySign(Math.min(Math.abs(moveYaw), dynamicYawSpeed), moveYaw);
                float pitchStep = Math.copySign(Math.min(Math.abs(movePitch), dynamicPitchSpeed), movePitch);

                if(canAttack()) {
                    yawStep *= 1.4f + (float) (Math.random() * 0.2f);
                    pitchStep *= 1.3f + (float) (Math.random() * 0.15f);
                }

                float newYaw = rotateVector.x + yawStep;
                float newPitch = Mth.clamp(rotateVector.y + pitchStep, -89f, 89f);

                float gcd = getGCDValue();
                newYaw -= (newYaw - rotateVector.x) % gcd;
                newPitch -= (newPitch - rotateVector.y) % gcd;

                rotateVector.x = newYaw;
                rotateVector.y = newPitch;
                break;
            } case "FunTime Snap": {

                float yawDiff = Mth.wrapDegrees(yawToTarget - rotateVector.x);
                float pitchDiff = Mth.wrapDegrees(pitchToTarget - rotateVector.y);

                float newYaw = rotateVector.x + applyGCD(yawDiff);
                float newPitch = rotateVector.y + applyGCD(pitchDiff);

                rotateVector.x = newYaw;
                rotateVector.y = Mth.clamp(newPitch, -90f, 90f);
                break;
            } case "FunTime Smooth":
                break;
        }

        isRotated = true;
    }

    private float getGCDValue() {
        double sensitivity = mc.options.sensitivity().get();
        float sens = (float) (sensitivity * 0.6F + 0.2F);
        return (sens * sens * sens) * 8.0F * 0.15f;
    }

    private float applyGCD(float angle) {
        float gcd = getGCDValue();
        return Math.round(angle / gcd) * gcd;
    }


    @Override
    public void onEnable() {
        super.onEnable();
        if (mc.player != null) {
            rotateVector.set(mc.player.getYRot(), mc.player.getXRot());
        }
        target = null;
    }

    @Override
    public void onDisable() {
        super.onDisable();
        target = null;
        if (mc.player != null) {
            rotateVector.set(mc.player.getYRot(), mc.player.getXRot());
        }
    }
}
RotationEvent:
Expand Collapse Copy
package i.chuppachups.reek.client.event.impl.packet;


import i.chuppachups.reek.client.event.Event;

public class RotationEvent extends Event {
    private float xRot, yRot;
    private final float staticXrot, staticYrot;
    public RotationEvent(float xRot, float yRot) {
        this.staticXrot = xRot;
        this.staticYrot = yRot;
        this.xRot = xRot;
        this.yRot = yRot;
    }


    public float getXRot() {
        return xRot;
    }

    public float getYRot() {
        return yRot;
    }

    public void setXRot(float xRot) {
        this.xRot = xRot;
    }

    public void setYRot(float yRot) {
        this.yRot = yRot;
    }


    public float getStaticXrot() {
        return staticXrot;
    }

    public float getStaticYrot() {
        return staticYrot;
    }

    public boolean isEquals() {
        return xRot == staticXrot && yRot == staticYrot;
    }
}
LocalPlayer:
Expand Collapse Copy
 private RotationEvent rotationEvent = new RotationEvent(0, 0);
    public float packetYaw;
    public float packetPitch;
    @Override
    public void tick() {
        rotationEvent = new RotationEvent(this.getXRot(), this.getYRot());
        EventManager.call(rotationEvent);
        this.setXRot(rotationEvent.getXRot());
        this.setYRot(rotationEvent.getYRot());
        this.tickClientLoadTimeout();
        if (this.hasClientLoaded()) {
            this.dropSpamThrottler.tick();
            super.tick();
            this.sendShiftKeyState();
            if (!this.lastSentInput.equals(this.input.keyPresses)) {
                this.connection.send(new ServerboundPlayerInputPacket(this.input.keyPresses));
                this.lastSentInput = this.input.keyPresses;
            }

            if (this.isPassenger()) {
                this.connection.send(new ServerboundMovePlayerPacket.Rot(this.getYRot(), this.getXRot(), this.onGround(), this.horizontalCollision));
                Entity entity = this.getRootVehicle();
                if (entity != this && entity.isControlledByLocalInstance()) {
                    this.connection.send(ServerboundMoveVehiclePacket.fromEntity(entity));
                    this.sendIsSprintingIfNeeded();
                }
            } else {
                packetPitch = this.getXRot();
                packetYaw = this.getYRot();
                this.sendPosition();
            }

            for (AmbientSoundHandler ambientsoundhandler : this.ambientSoundHandlers) {
                ambientsoundhandler.tick();
            }
        }
        setXRot(rotationEvent.getStaticXrot());
        setYRot(rotationEvent.getStaticYrot());
    }
 
Тряска и "улетание" рук - визуальный баг, видимый лишь на клиенте, его природа - некорректное значения ротаций последнего кадра, используемые для сглаживания(путем интерполяции) этих самых поворотов модельки. Правильным фиксом этого бага, я бы назвал создания отдельного класса, котоырй будет хранить состояния ротаций и использовать их для рендера(LivingEntityRenderer.uppdateRenderState(T livingEntity, S livingEntityRenderState, float f) и д.р.).
 
Тряска и "улетание" рук - визуальный баг, видимый лишь на клиенте, его природа - некорректное значения ротаций последнего кадра, используемые для сглаживания(путем интерполяции) этих самых поворотов модельки. Правильным фиксом этого бага, я бы назвал создания отдельного класса, котоырй будет хранить состояния ротаций и использовать их для рендера(LivingEntityRenderer.uppdateRenderState(T livingEntity, S livingEntityRenderState, float f) и д.р.).
я просил помощь, а не нейросеть
 
как пофиксить ротация когда работает ротация голову начинает трести а руки улетать (мотрит куда смотрит голова) ss
AttackAura:
Expand Collapse Copy
package i.chuppachups.reek.client.module.impl.combat;

import net.minecraft.util.Mth;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.animal.Animal;
import net.minecraft.world.entity.monster.Monster;
import net.minecraft.world.entity.npc.Villager;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.item.ArmorItem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.equipment.*;
import net.minecraft.world.phys.Vec3;

import i.chuppachups.reek.client.event.impl.packet.RotationEvent;
import i.chuppachups.reek.client.event.impl.player.EventUpdate;
import i.chuppachups.reek.client.module.api.Category;
import i.chuppachups.reek.client.module.api.Module;
import i.chuppachups.reek.client.module.setting.api.Setting;
import i.chuppachups.reek.client.module.setting.impl.*;
import i.chuppachups.reek.client.event.impl.player.EventInput;
import i.chuppachups.reek.client.module.api.ModuleAnnotation;
import i.chuppachups.reek.client.util.impl.move.MoveUtil;

import com.darkmagician6.eventapi.EventTarget;

import org.joml.Vector2f;

import java.util.List;

@ModuleAnnotation(name = "Attack Aura", category = Category.COMBAT)
public class AttackAura extends Module {

    public final ModeListSetting targetTypes = new ModeListSetting("Кого атаковать", this, new String[]{"Игроков"}, new String[]{"Игроков","Мобов","Жителей","Невидимых","Голых"});
    public final ModeSetting priorityMode = new ModeSetting("Приоритет по ", this,"Дистанции", new String[]{"Дистанции","Здоровью","Броне","Полю зрению","Всем сразу"});
    public final ModeSetting rotationMode = new ModeSetting("Тип наведения", this,"Grim/Vulcan", new String[]{"Grim/Vulcan","Matrix/Vulcan","FunTime Snap","FunTime Smooth"});
    public final ModeSetting correctionMoveMode = new ModeSetting("Коррекция движения", this,"Свободная", new String[]{"Свободная","Сфокусированная","Не корректировать"});
    public final ModeListSetting noHit = new ModeListSetting("Не бить если ", this, new String[]{"Открыт инвентарь"}, new String[]{"Открыт инвентарь","Используешь еду"});
    public final ModeSetting dopRange = new ModeSetting("Расширенная дистанция", this, "Отключена", new String[]{"Отключена","HolyWorld","FunTime/ReallyWorld"});
    public final ModeSetting sprintMode = new ModeSetting("Режим бега", this, "Легитный", new String[]{"Легитный","Пакетный"});
    public final NumberSetting range = new NumberSetting("Дистанция удара", this, 4.0f, 3.0f, 6.0f, 0.1f);

    public final BooleanSetting focusSingleTarget = new BooleanSetting("Фокусировать одну цель", this, false);
    public final BooleanSetting throughWalls = new BooleanSetting("Бить через стены", this, false);

    public static LivingEntity target;
    public Vector2f rotateVector = new Vector2f(0,0);
    public boolean isRotated;
    public long lastAttackTime = 0;

    public AttackAura() {
        this.addSettings(new Setting[]{targetTypes, priorityMode, rotationMode, correctionMoveMode, noHit, dopRange, sprintMode, range,focusSingleTarget,throughWalls});
    }

    @EventTarget
    public void onPlayerInput(EventInput event) {
        if (target == null || !isRotated) return;

        switch(correctionMoveMode.getMode()) {
            case "Сфокусированная":
                MoveUtil.fixMovement(event, rotateVector.x);
                break;
            case "Свободная":

                break;
            case "Не корректировать":

                break;
        }
    }

    @EventTarget
    public void onUpdate(EventUpdate event) {
        updateTarget();

        if(target != null) {

            rotateToTarget();

            if(isLookingAtTarget() && canAttack()) {
                attackTarget();
            }


        }
    }


    private boolean isLookingAtTarget() {
        if(target == null) return false;

        Vec3 eyePos = mc.player.getEyePosition(1.0F);
        Vec3 targetPos = target.position().add(0, target.getBbHeight() / 2.0, 0);
        Vec3 delta = targetPos.subtract(eyePos);

        float yawToTarget = (float) Math.toDegrees(Math.atan2(delta.z, delta.x)) - 90f;
        float pitchToTarget = (float) -Math.toDegrees(Math.atan2(delta.y, Math.hypot(delta.x, delta.z)));

        float yawDiff = Math.abs(Mth.wrapDegrees(yawToTarget - rotateVector.x));
        float pitchDiff = Math.abs(Mth.wrapDegrees(pitchToTarget - rotateVector.y));

        return yawDiff < 5f && pitchDiff < 5f;
    }

    @EventTarget
    public void onPacketRotation(RotationEvent e) {
        if (target == null) return;
        e.setYRot(rotateVector.x);
        e.setXRot(rotateVector.y);
    }

    private void updateTarget() {
        target = null;

        double attackDistance = range.getValue();
        double rotationDistance = attackDistance;

        switch(dopRange.getMode()) {
            case "HolyWorld":
                rotationDistance += 2.0;
                break;
            case "FunTime/ReallyWorld":
                rotationDistance += 1.5;
                break;
            default:
                break;
        }

        List<LivingEntity> entities = mc.level.getEntitiesOfClass(LivingEntity.class, mc.player.getBoundingBox().inflate(rotationDistance));
        LivingEntity bestTarget = null;
        double bestScore = Double.MAX_VALUE;

        for(LivingEntity entity : entities) {
            if(!isValid(entity)) continue;

            if(mc.player.distanceTo(entity) > rotationDistance) continue;

            if(noHit.getSelectedModes().contains("Открыт инвентарь") && mc.screen != null) continue;
            if(noHit.getSelectedModes().contains("Используешь еду") && mc.player.isUsingItem()) continue;
            if(!throughWalls.isToggled() && !mc.player.hasLineOfSight(entity)) continue;

            double score = calculatePriority(entity);
            if(score < bestScore) {
                bestScore = score;
                bestTarget = entity;
            }
        }

        if (bestTarget != null && mc.player.distanceTo(bestTarget) <= attackDistance) {
            target = bestTarget;
        }
    }

    private double calculatePriority(LivingEntity entity) {
        switch(priorityMode.getMode()) {
            case "Дистанции":
                return mc.player.distanceTo(entity);
            case "Здоровью":
                return entity.getHealth();
            case "Броне":
                return getArmorValue(entity);
            case "Полю зрению":
                return !mc.player.hasLineOfSight(entity) ? Double.MAX_VALUE : mc.player.distanceTo(entity);
            case "Всем сразу":
                return mc.player.distanceTo(entity) + entity.getHealth() + getArmorValue(entity);
            default:
                return mc.player.distanceTo(entity);
        }
    }
    private double getArmorValue(LivingEntity entity) {
        double totalArmor = 0;
        for (ItemStack stack : entity.getArmorSlots()) {
            if (stack != null && stack.getItem() instanceof ArmorItem armor) {
                ArmorMaterial material = armor.getArmorMaterial();
                ArmorType type = armor.getArmorType();
                int defenseValue = material.defense().getOrDefault(type, 0);
                totalArmor += defenseValue;
            }
        }
        return totalArmor;
    }


    private boolean isValid(LivingEntity entity) {
        if (entity == mc.player || !entity.isAlive() || entity.isInvulnerable()) {
            return false;
        }

        boolean allowPlayers = targetTypes.getSelectedModes().contains("Игроков");
        boolean allowMobs = targetTypes.getSelectedModes().contains("Мобов");
        boolean allowVillagers = targetTypes.getSelectedModes().contains("Жителей");
        boolean allowInvisible = targetTypes.getSelectedModes().contains("Невидимых");
        boolean allowNaked = targetTypes.getSelectedModes().contains("Голых");

        if (entity instanceof Player p) {
            if (!allowPlayers) return false;
            if (p.isInvisible() && !allowInvisible) return false;
            if (getArmorValue(p) == 0 && !allowNaked && allowPlayers) return false;
            return true;
        }

        if (entity instanceof Monster || entity instanceof Animal) {
            return allowMobs;
        }

        if (entity instanceof Villager) {
            return allowVillagers;
        }

        return false;
    }


    private boolean canAttack() {
        return mc.player.getAttackStrengthScale(0) >= 1;
    }

    /**
     * MODIFIED METHOD
     * This method now contains the logic for the visual head-snap during an attack.
     */
    private void attackTarget() {
        if(target == null) return;

            mc.gameMode.attack(mc.player, target);
            mc.player.swing(InteractionHand.MAIN_HAND);
            lastAttackTime = System.currentTimeMillis();

    }


    private void rotateToTarget() {
        if(target == null) return;

        double rotationDistance = range.getValue();
        switch(dopRange.getMode()) {
            case "HolyWorld":
                rotationDistance += 2.0;
                break;
            case "FunTime/ReallyWorld":
                rotationDistance += 4.0;
                break;
        }

        if(mc.player.distanceTo(target) > rotationDistance) return;

        Vec3 eyePos = mc.player.getEyePosition(1.0F);
        Vec3 targetPos = target.position().add(0, target.getBbHeight() / 2.0, 0);
        Vec3 delta = targetPos.subtract(eyePos);

        float yawToTarget = (float) Math.toDegrees(Math.atan2(delta.z, delta.x)) - 90f;
        float pitchToTarget = (float) -Math.toDegrees(Math.atan2(delta.y, Math.hypot(delta.x, delta.z)));

        switch(rotationMode.getMode()) {
            case "Grim/Vulcan": {

                break;
            } case "Matrix/Vulcan": {
                if(target == null) break;

                 eyePos = mc.player.getEyePosition(1.0F);
                 targetPos = target.position().add(0, target.getBbHeight() / 2.0, 0);
                 delta = targetPos.subtract(eyePos);

                 yawToTarget = (float) Math.toDegrees(Math.atan2(delta.z, delta.x)) - 90f;
                 pitchToTarget = (float) -Math.toDegrees(Math.atan2(delta.y, Math.hypot(delta.x, delta.z)));

                float yawDelta = Mth.wrapDegrees(yawToTarget - rotateVector.x);
                float pitchDelta = Mth.wrapDegrees(pitchToTarget - rotateVector.y);

                float distanceYaw = yawDelta;
                float distancePitch = pitchDelta;

                float rotationDifference = (float) Math.hypot(distanceYaw, distancePitch);
                if (rotationDifference < 0.001f) rotationDifference = 1f;

                float maxYawChange = Math.abs(distanceYaw / rotationDifference) * 60f;
                float maxPitchChange = Math.abs(distancePitch / rotationDifference) * 45f;

                float moveYaw = Mth.clamp(distanceYaw, -maxYawChange, maxYawChange);
                float movePitch = Mth.clamp(distancePitch, -maxPitchChange, maxPitchChange);

                float baseYawSpeed = 0.45f + (float) (Math.abs(moveYaw) * (0.4f + Math.random() * 0.3f));
                float basePitchSpeed = 0.45f + (float) (Math.abs(movePitch) * (0.3f + Math.random() * 0.2f));

                float dynamicYawSpeed = Math.min(baseYawSpeed, 40f);
                float dynamicPitchSpeed = Math.min(basePitchSpeed, 40f);

                float yawStep = Math.copySign(Math.min(Math.abs(moveYaw), dynamicYawSpeed), moveYaw);
                float pitchStep = Math.copySign(Math.min(Math.abs(movePitch), dynamicPitchSpeed), movePitch);

                if(canAttack()) {
                    yawStep *= 1.4f + (float) (Math.random() * 0.2f);
                    pitchStep *= 1.3f + (float) (Math.random() * 0.15f);
                }

                float newYaw = rotateVector.x + yawStep;
                float newPitch = Mth.clamp(rotateVector.y + pitchStep, -89f, 89f);

                float gcd = getGCDValue();
                newYaw -= (newYaw - rotateVector.x) % gcd;
                newPitch -= (newPitch - rotateVector.y) % gcd;

                rotateVector.x = newYaw;
                rotateVector.y = newPitch;
                break;
            } case "FunTime Snap": {

                float yawDiff = Mth.wrapDegrees(yawToTarget - rotateVector.x);
                float pitchDiff = Mth.wrapDegrees(pitchToTarget - rotateVector.y);

                float newYaw = rotateVector.x + applyGCD(yawDiff);
                float newPitch = rotateVector.y + applyGCD(pitchDiff);

                rotateVector.x = newYaw;
                rotateVector.y = Mth.clamp(newPitch, -90f, 90f);
                break;
            } case "FunTime Smooth":
                break;
        }

        isRotated = true;
    }

    private float getGCDValue() {
        double sensitivity = mc.options.sensitivity().get();
        float sens = (float) (sensitivity * 0.6F + 0.2F);
        return (sens * sens * sens) * 8.0F * 0.15f;
    }

    private float applyGCD(float angle) {
        float gcd = getGCDValue();
        return Math.round(angle / gcd) * gcd;
    }


    @Override
    public void onEnable() {
        super.onEnable();
        if (mc.player != null) {
            rotateVector.set(mc.player.getYRot(), mc.player.getXRot());
        }
        target = null;
    }

    @Override
    public void onDisable() {
        super.onDisable();
        target = null;
        if (mc.player != null) {
            rotateVector.set(mc.player.getYRot(), mc.player.getXRot());
        }
    }
}
RotationEvent:
Expand Collapse Copy
package i.chuppachups.reek.client.event.impl.packet;


import i.chuppachups.reek.client.event.Event;

public class RotationEvent extends Event {
    private float xRot, yRot;
    private final float staticXrot, staticYrot;
    public RotationEvent(float xRot, float yRot) {
        this.staticXrot = xRot;
        this.staticYrot = yRot;
        this.xRot = xRot;
        this.yRot = yRot;
    }


    public float getXRot() {
        return xRot;
    }

    public float getYRot() {
        return yRot;
    }

    public void setXRot(float xRot) {
        this.xRot = xRot;
    }

    public void setYRot(float yRot) {
        this.yRot = yRot;
    }


    public float getStaticXrot() {
        return staticXrot;
    }

    public float getStaticYrot() {
        return staticYrot;
    }

    public boolean isEquals() {
        return xRot == staticXrot && yRot == staticYrot;
    }
}
LocalPlayer:
Expand Collapse Copy
 private RotationEvent rotationEvent = new RotationEvent(0, 0);
    public float packetYaw;
    public float packetPitch;
    @Override
    public void tick() {
        rotationEvent = new RotationEvent(this.getXRot(), this.getYRot());
        EventManager.call(rotationEvent);
        this.setXRot(rotationEvent.getXRot());
        this.setYRot(rotationEvent.getYRot());
        this.tickClientLoadTimeout();
        if (this.hasClientLoaded()) {
            this.dropSpamThrottler.tick();
            super.tick();
            this.sendShiftKeyState();
            if (!this.lastSentInput.equals(this.input.keyPresses)) {
                this.connection.send(new ServerboundPlayerInputPacket(this.input.keyPresses));
                this.lastSentInput = this.input.keyPresses;
            }

            if (this.isPassenger()) {
                this.connection.send(new ServerboundMovePlayerPacket.Rot(this.getYRot(), this.getXRot(), this.onGround(), this.horizontalCollision));
                Entity entity = this.getRootVehicle();
                if (entity != this && entity.isControlledByLocalInstance()) {
                    this.connection.send(ServerboundMoveVehiclePacket.fromEntity(entity));
                    this.sendIsSprintingIfNeeded();
                }
            } else {
                packetPitch = this.getXRot();
                packetYaw = this.getYRot();
                this.sendPosition();
            }

            for (AmbientSoundHandler ambientsoundhandler : this.ambientSoundHandlers) {
                ambientsoundhandler.tick();
            }
        }
        setXRot(rotationEvent.getStaticXrot());
        setYRot(rotationEvent.getStaticYrot());
    }


Краткое описание (ИИ-агент) (?)

Проблема заключается в визуальных артефактах, таких как "трясущаяся голова" и "улетающие руки", возникающих при работе модуля AttackAura, который использует RotationEvent для изменения ротаций (направления взгляда игрока) в Minecraft 1.21.4. Это происходит из-за того, что в методе tick(), после вызова RotationEvent и применения измененных значений YRot (yaw, горизонтальное вращение) и XRot (pitch, вертикальное вращение) для отправки серверных пакетов, игровые ротации немедленно сбрасываются обратно к их статическим исходным значениям. В результате такого быстрого сброса возникает десинхронизация между отправленными пакетами с модифицированными ротациями и визуальным состоянием клиента, что приводит к наблюдаемым некорректным движениям головы и рук игрока.
 
как пофиксить ротация когда работает ротация голову начинает трести а руки улетать (мотрит куда смотрит голова) ss
AttackAura:
Expand Collapse Copy
package i.chuppachups.reek.client.module.impl.combat;

import net.minecraft.util.Mth;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.animal.Animal;
import net.minecraft.world.entity.monster.Monster;
import net.minecraft.world.entity.npc.Villager;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.item.ArmorItem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.equipment.*;
import net.minecraft.world.phys.Vec3;

import i.chuppachups.reek.client.event.impl.packet.RotationEvent;
import i.chuppachups.reek.client.event.impl.player.EventUpdate;
import i.chuppachups.reek.client.module.api.Category;
import i.chuppachups.reek.client.module.api.Module;
import i.chuppachups.reek.client.module.setting.api.Setting;
import i.chuppachups.reek.client.module.setting.impl.*;
import i.chuppachups.reek.client.event.impl.player.EventInput;
import i.chuppachups.reek.client.module.api.ModuleAnnotation;
import i.chuppachups.reek.client.util.impl.move.MoveUtil;

import com.darkmagician6.eventapi.EventTarget;

import org.joml.Vector2f;

import java.util.List;

@ModuleAnnotation(name = "Attack Aura", category = Category.COMBAT)
public class AttackAura extends Module {

    public final ModeListSetting targetTypes = new ModeListSetting("Кого атаковать", this, new String[]{"Игроков"}, new String[]{"Игроков","Мобов","Жителей","Невидимых","Голых"});
    public final ModeSetting priorityMode = new ModeSetting("Приоритет по ", this,"Дистанции", new String[]{"Дистанции","Здоровью","Броне","Полю зрению","Всем сразу"});
    public final ModeSetting rotationMode = new ModeSetting("Тип наведения", this,"Grim/Vulcan", new String[]{"Grim/Vulcan","Matrix/Vulcan","FunTime Snap","FunTime Smooth"});
    public final ModeSetting correctionMoveMode = new ModeSetting("Коррекция движения", this,"Свободная", new String[]{"Свободная","Сфокусированная","Не корректировать"});
    public final ModeListSetting noHit = new ModeListSetting("Не бить если ", this, new String[]{"Открыт инвентарь"}, new String[]{"Открыт инвентарь","Используешь еду"});
    public final ModeSetting dopRange = new ModeSetting("Расширенная дистанция", this, "Отключена", new String[]{"Отключена","HolyWorld","FunTime/ReallyWorld"});
    public final ModeSetting sprintMode = new ModeSetting("Режим бега", this, "Легитный", new String[]{"Легитный","Пакетный"});
    public final NumberSetting range = new NumberSetting("Дистанция удара", this, 4.0f, 3.0f, 6.0f, 0.1f);

    public final BooleanSetting focusSingleTarget = new BooleanSetting("Фокусировать одну цель", this, false);
    public final BooleanSetting throughWalls = new BooleanSetting("Бить через стены", this, false);

    public static LivingEntity target;
    public Vector2f rotateVector = new Vector2f(0,0);
    public boolean isRotated;
    public long lastAttackTime = 0;

    public AttackAura() {
        this.addSettings(new Setting[]{targetTypes, priorityMode, rotationMode, correctionMoveMode, noHit, dopRange, sprintMode, range,focusSingleTarget,throughWalls});
    }

    @EventTarget
    public void onPlayerInput(EventInput event) {
        if (target == null || !isRotated) return;

        switch(correctionMoveMode.getMode()) {
            case "Сфокусированная":
                MoveUtil.fixMovement(event, rotateVector.x);
                break;
            case "Свободная":

                break;
            case "Не корректировать":

                break;
        }
    }

    @EventTarget
    public void onUpdate(EventUpdate event) {
        updateTarget();

        if(target != null) {

            rotateToTarget();

            if(isLookingAtTarget() && canAttack()) {
                attackTarget();
            }


        }
    }


    private boolean isLookingAtTarget() {
        if(target == null) return false;

        Vec3 eyePos = mc.player.getEyePosition(1.0F);
        Vec3 targetPos = target.position().add(0, target.getBbHeight() / 2.0, 0);
        Vec3 delta = targetPos.subtract(eyePos);

        float yawToTarget = (float) Math.toDegrees(Math.atan2(delta.z, delta.x)) - 90f;
        float pitchToTarget = (float) -Math.toDegrees(Math.atan2(delta.y, Math.hypot(delta.x, delta.z)));

        float yawDiff = Math.abs(Mth.wrapDegrees(yawToTarget - rotateVector.x));
        float pitchDiff = Math.abs(Mth.wrapDegrees(pitchToTarget - rotateVector.y));

        return yawDiff < 5f && pitchDiff < 5f;
    }

    @EventTarget
    public void onPacketRotation(RotationEvent e) {
        if (target == null) return;
        e.setYRot(rotateVector.x);
        e.setXRot(rotateVector.y);
    }

    private void updateTarget() {
        target = null;

        double attackDistance = range.getValue();
        double rotationDistance = attackDistance;

        switch(dopRange.getMode()) {
            case "HolyWorld":
                rotationDistance += 2.0;
                break;
            case "FunTime/ReallyWorld":
                rotationDistance += 1.5;
                break;
            default:
                break;
        }

        List<LivingEntity> entities = mc.level.getEntitiesOfClass(LivingEntity.class, mc.player.getBoundingBox().inflate(rotationDistance));
        LivingEntity bestTarget = null;
        double bestScore = Double.MAX_VALUE;

        for(LivingEntity entity : entities) {
            if(!isValid(entity)) continue;

            if(mc.player.distanceTo(entity) > rotationDistance) continue;

            if(noHit.getSelectedModes().contains("Открыт инвентарь") && mc.screen != null) continue;
            if(noHit.getSelectedModes().contains("Используешь еду") && mc.player.isUsingItem()) continue;
            if(!throughWalls.isToggled() && !mc.player.hasLineOfSight(entity)) continue;

            double score = calculatePriority(entity);
            if(score < bestScore) {
                bestScore = score;
                bestTarget = entity;
            }
        }

        if (bestTarget != null && mc.player.distanceTo(bestTarget) <= attackDistance) {
            target = bestTarget;
        }
    }

    private double calculatePriority(LivingEntity entity) {
        switch(priorityMode.getMode()) {
            case "Дистанции":
                return mc.player.distanceTo(entity);
            case "Здоровью":
                return entity.getHealth();
            case "Броне":
                return getArmorValue(entity);
            case "Полю зрению":
                return !mc.player.hasLineOfSight(entity) ? Double.MAX_VALUE : mc.player.distanceTo(entity);
            case "Всем сразу":
                return mc.player.distanceTo(entity) + entity.getHealth() + getArmorValue(entity);
            default:
                return mc.player.distanceTo(entity);
        }
    }
    private double getArmorValue(LivingEntity entity) {
        double totalArmor = 0;
        for (ItemStack stack : entity.getArmorSlots()) {
            if (stack != null && stack.getItem() instanceof ArmorItem armor) {
                ArmorMaterial material = armor.getArmorMaterial();
                ArmorType type = armor.getArmorType();
                int defenseValue = material.defense().getOrDefault(type, 0);
                totalArmor += defenseValue;
            }
        }
        return totalArmor;
    }


    private boolean isValid(LivingEntity entity) {
        if (entity == mc.player || !entity.isAlive() || entity.isInvulnerable()) {
            return false;
        }

        boolean allowPlayers = targetTypes.getSelectedModes().contains("Игроков");
        boolean allowMobs = targetTypes.getSelectedModes().contains("Мобов");
        boolean allowVillagers = targetTypes.getSelectedModes().contains("Жителей");
        boolean allowInvisible = targetTypes.getSelectedModes().contains("Невидимых");
        boolean allowNaked = targetTypes.getSelectedModes().contains("Голых");

        if (entity instanceof Player p) {
            if (!allowPlayers) return false;
            if (p.isInvisible() && !allowInvisible) return false;
            if (getArmorValue(p) == 0 && !allowNaked && allowPlayers) return false;
            return true;
        }

        if (entity instanceof Monster || entity instanceof Animal) {
            return allowMobs;
        }

        if (entity instanceof Villager) {
            return allowVillagers;
        }

        return false;
    }


    private boolean canAttack() {
        return mc.player.getAttackStrengthScale(0) >= 1;
    }

    /**
     * MODIFIED METHOD
     * This method now contains the logic for the visual head-snap during an attack.
     */
    private void attackTarget() {
        if(target == null) return;

            mc.gameMode.attack(mc.player, target);
            mc.player.swing(InteractionHand.MAIN_HAND);
            lastAttackTime = System.currentTimeMillis();

    }


    private void rotateToTarget() {
        if(target == null) return;

        double rotationDistance = range.getValue();
        switch(dopRange.getMode()) {
            case "HolyWorld":
                rotationDistance += 2.0;
                break;
            case "FunTime/ReallyWorld":
                rotationDistance += 4.0;
                break;
        }

        if(mc.player.distanceTo(target) > rotationDistance) return;

        Vec3 eyePos = mc.player.getEyePosition(1.0F);
        Vec3 targetPos = target.position().add(0, target.getBbHeight() / 2.0, 0);
        Vec3 delta = targetPos.subtract(eyePos);

        float yawToTarget = (float) Math.toDegrees(Math.atan2(delta.z, delta.x)) - 90f;
        float pitchToTarget = (float) -Math.toDegrees(Math.atan2(delta.y, Math.hypot(delta.x, delta.z)));

        switch(rotationMode.getMode()) {
            case "Grim/Vulcan": {

                break;
            } case "Matrix/Vulcan": {
                if(target == null) break;

                 eyePos = mc.player.getEyePosition(1.0F);
                 targetPos = target.position().add(0, target.getBbHeight() / 2.0, 0);
                 delta = targetPos.subtract(eyePos);

                 yawToTarget = (float) Math.toDegrees(Math.atan2(delta.z, delta.x)) - 90f;
                 pitchToTarget = (float) -Math.toDegrees(Math.atan2(delta.y, Math.hypot(delta.x, delta.z)));

                float yawDelta = Mth.wrapDegrees(yawToTarget - rotateVector.x);
                float pitchDelta = Mth.wrapDegrees(pitchToTarget - rotateVector.y);

                float distanceYaw = yawDelta;
                float distancePitch = pitchDelta;

                float rotationDifference = (float) Math.hypot(distanceYaw, distancePitch);
                if (rotationDifference < 0.001f) rotationDifference = 1f;

                float maxYawChange = Math.abs(distanceYaw / rotationDifference) * 60f;
                float maxPitchChange = Math.abs(distancePitch / rotationDifference) * 45f;

                float moveYaw = Mth.clamp(distanceYaw, -maxYawChange, maxYawChange);
                float movePitch = Mth.clamp(distancePitch, -maxPitchChange, maxPitchChange);

                float baseYawSpeed = 0.45f + (float) (Math.abs(moveYaw) * (0.4f + Math.random() * 0.3f));
                float basePitchSpeed = 0.45f + (float) (Math.abs(movePitch) * (0.3f + Math.random() * 0.2f));

                float dynamicYawSpeed = Math.min(baseYawSpeed, 40f);
                float dynamicPitchSpeed = Math.min(basePitchSpeed, 40f);

                float yawStep = Math.copySign(Math.min(Math.abs(moveYaw), dynamicYawSpeed), moveYaw);
                float pitchStep = Math.copySign(Math.min(Math.abs(movePitch), dynamicPitchSpeed), movePitch);

                if(canAttack()) {
                    yawStep *= 1.4f + (float) (Math.random() * 0.2f);
                    pitchStep *= 1.3f + (float) (Math.random() * 0.15f);
                }

                float newYaw = rotateVector.x + yawStep;
                float newPitch = Mth.clamp(rotateVector.y + pitchStep, -89f, 89f);

                float gcd = getGCDValue();
                newYaw -= (newYaw - rotateVector.x) % gcd;
                newPitch -= (newPitch - rotateVector.y) % gcd;

                rotateVector.x = newYaw;
                rotateVector.y = newPitch;
                break;
            } case "FunTime Snap": {

                float yawDiff = Mth.wrapDegrees(yawToTarget - rotateVector.x);
                float pitchDiff = Mth.wrapDegrees(pitchToTarget - rotateVector.y);

                float newYaw = rotateVector.x + applyGCD(yawDiff);
                float newPitch = rotateVector.y + applyGCD(pitchDiff);

                rotateVector.x = newYaw;
                rotateVector.y = Mth.clamp(newPitch, -90f, 90f);
                break;
            } case "FunTime Smooth":
                break;
        }

        isRotated = true;
    }

    private float getGCDValue() {
        double sensitivity = mc.options.sensitivity().get();
        float sens = (float) (sensitivity * 0.6F + 0.2F);
        return (sens * sens * sens) * 8.0F * 0.15f;
    }

    private float applyGCD(float angle) {
        float gcd = getGCDValue();
        return Math.round(angle / gcd) * gcd;
    }


    @Override
    public void onEnable() {
        super.onEnable();
        if (mc.player != null) {
            rotateVector.set(mc.player.getYRot(), mc.player.getXRot());
        }
        target = null;
    }

    @Override
    public void onDisable() {
        super.onDisable();
        target = null;
        if (mc.player != null) {
            rotateVector.set(mc.player.getYRot(), mc.player.getXRot());
        }
    }
}
RotationEvent:
Expand Collapse Copy
package i.chuppachups.reek.client.event.impl.packet;


import i.chuppachups.reek.client.event.Event;

public class RotationEvent extends Event {
    private float xRot, yRot;
    private final float staticXrot, staticYrot;
    public RotationEvent(float xRot, float yRot) {
        this.staticXrot = xRot;
        this.staticYrot = yRot;
        this.xRot = xRot;
        this.yRot = yRot;
    }


    public float getXRot() {
        return xRot;
    }

    public float getYRot() {
        return yRot;
    }

    public void setXRot(float xRot) {
        this.xRot = xRot;
    }

    public void setYRot(float yRot) {
        this.yRot = yRot;
    }


    public float getStaticXrot() {
        return staticXrot;
    }

    public float getStaticYrot() {
        return staticYrot;
    }

    public boolean isEquals() {
        return xRot == staticXrot && yRot == staticYrot;
    }
}
LocalPlayer:
Expand Collapse Copy
 private RotationEvent rotationEvent = new RotationEvent(0, 0);
    public float packetYaw;
    public float packetPitch;
    @Override
    public void tick() {
        rotationEvent = new RotationEvent(this.getXRot(), this.getYRot());
        EventManager.call(rotationEvent);
        this.setXRot(rotationEvent.getXRot());
        this.setYRot(rotationEvent.getYRot());
        this.tickClientLoadTimeout();
        if (this.hasClientLoaded()) {
            this.dropSpamThrottler.tick();
            super.tick();
            this.sendShiftKeyState();
            if (!this.lastSentInput.equals(this.input.keyPresses)) {
                this.connection.send(new ServerboundPlayerInputPacket(this.input.keyPresses));
                this.lastSentInput = this.input.keyPresses;
            }

            if (this.isPassenger()) {
                this.connection.send(new ServerboundMovePlayerPacket.Rot(this.getYRot(), this.getXRot(), this.onGround(), this.horizontalCollision));
                Entity entity = this.getRootVehicle();
                if (entity != this && entity.isControlledByLocalInstance()) {
                    this.connection.send(ServerboundMoveVehiclePacket.fromEntity(entity));
                    this.sendIsSprintingIfNeeded();
                }
            } else {
                packetPitch = this.getXRot();
                packetYaw = this.getYRot();
                this.sendPosition();
            }

            for (AmbientSoundHandler ambientsoundhandler : this.ambientSoundHandlers) {
                ambientsoundhandler.tick();
            }
        }
        setXRot(rotationEvent.getStaticXrot());
        setYRot(rotationEvent.getStaticYrot());
    }

:kekw12:
 
в LivingEntityRenderer значения ротации передай в метод
extractRenderState
 
я просил помощь, а не нейросеть
Ты еблан совсем?
Если к тебе только таким словом и обращаются, а для описания словарного запаса твоих собеседников хватит одного листочка А6, то вопросов больше к кубоголовым "югеймерам" не имею
1760033154903.png
:warpath:
 
Назад
Сверху Снизу