Загрузка данных
package releon.ru.api.module.impl.combat.aura;
import net.minecraft.client.Minecraft;
import net.minecraft.network.protocol.game.ClientboundPlayerPositionPacket;
import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.phys.Vec3;
import releon.ru.api.events.annotation.SubscribeEvent;
import releon.ru.api.events.impl.PacketEvent;
import releon.ru.api.events.impl.PlayerVelocityStrafeEvent;
import releon.ru.api.events.impl.RotationUpdateEvent;
import releon.ru.api.events.impl.TickEvent;
import releon.ru.api.events.types.EventPhase;
import releon.ru.api.module.Module;
import releon.ru.api.module.impl.combat.aura.back.BackAngle;
import releon.ru.api.module.impl.combat.aura.impl.RotateConstructor;
import releon.ru.api.module.impl.combat.aura.util.TaskPriority;
import releon.ru.api.module.impl.combat.aura.util.TaskProcessor;
import releon.ru.manager.Manager;
import releon.ru.utils.player.BaritoneMovementHelper;
public class AngleConnection {
public static final AngleConnection INSTANCE = new AngleConnection();
private static final RotateConstructor USE_ITEM_RETURN_SMOOTH = new BackAngle(0.95F);
private final TaskProcessor<AngleConstructor> rotationPlanTaskProcessor = new TaskProcessor<>();
private AngleConstructor lastRotationPlan;
private Angle currentAngle;
private Angle previousAngle;
private Angle serverAngle = Angle.DEFAULT;
private Angle fakeAngle;
private Angle previousFakeAngle;
private Float fakeBodyYaw;
private Float previousFakeBodyYaw;
private boolean returning;
private int forcePacketRotationTicks;
private boolean useItemReturnPending;
private int staleInactiveTicks;
private boolean rotationRequestedThisTick;
private boolean queuedRotationTaskThisTick;
public void setRotation(Angle value) {
if (value == null) {
previousAngle = currentAngle != null ? currentAngle : MathAngle.cameraAngle();
} else {
previousAngle = currentAngle;
}
currentAngle = value;
}
public Angle getCurrentAngle() {
return currentAngle;
}
public Angle getRotation() {
return currentAngle != null ? currentAngle : MathAngle.cameraAngle();
}
public Angle getServerAngle() {
return serverAngle;
}
public float getPacketYaw() {
return getPacketRotation().getYaw();
}
public float getPacketPitch() {
return Mth.clamp(getPacketRotation().getPitch(), -90.0F, 90.0F);
}
public boolean shouldApplyPacketRotation() {
if (BaritoneMovementHelper.isBaritoneActive(Minecraft.getInstance().player)) {
return false;
}
return currentAngle != null
|| fakeAngle != null
|| (forcePacketRotationTicks > 0 && previousAngle != null);
}
public void forcePacketRotation(int ticks) {
if (ticks > 0) {
forcePacketRotationTicks = Math.max(forcePacketRotationTicks, ticks);
}
}
public Angle getFakeRotation() {
if (fakeAngle != null) {
return fakeAngle;
}
return currentAngle != null ? currentAngle : previousAngle != null ? previousAngle : MathAngle.cameraAngle();
}
public Angle getFakeAngle() {
return fakeAngle;
}
public Angle getPreviousFakeRotation() {
if (previousFakeAngle != null) {
return previousFakeAngle;
}
return getFakeRotation();
}
public float getFakeBodyYaw() {
return fakeBodyYaw != null ? fakeBodyYaw : getFakeRotation().getYaw();
}
public float getPreviousFakeBodyYaw() {
return previousFakeBodyYaw != null ? previousFakeBodyYaw : getFakeBodyYaw();
}
public void setFakeRotation(Angle angle) {
angle = normalizeAngle(angle, fakeAngle);
if (angle == null) {
previousFakeAngle = null;
fakeAngle = null;
previousFakeBodyYaw = null;
fakeBodyYaw = null;
return;
}
previousFakeAngle = fakeAngle != null ? fakeAngle : angle;
fakeAngle = angle;
float targetYaw = angle.getYaw();
if (fakeBodyYaw == null) {
fakeBodyYaw = targetYaw;
previousFakeBodyYaw = targetYaw;
return;
}
previousFakeBodyYaw = fakeBodyYaw;
float diff = Mth.wrapDegrees(targetYaw - fakeBodyYaw);
fakeBodyYaw += Mth.clamp(diff, -8.0F, 8.0F);
}
public Angle getPreviousRotation() {
Minecraft client = Minecraft.getInstance();
if (client.player == null) {
return currentAngle != null ? currentAngle : Angle.DEFAULT;
}
return currentAngle != null && previousAngle != null ? previousAngle : new Angle(client.player.yRotO, client.player.xRotO);
}
public Angle getMoveRotation() {
Minecraft client = Minecraft.getInstance();
if (BaritoneMovementHelper.isBaritoneActive(client.player)) {
return MathAngle.cameraAngle();
}
AngleConstructor rotationPlan = getCurrentRotationPlan();
return currentAngle != null && rotationPlan != null && rotationPlan.isMoveCorrection()
? currentAngle
: MathAngle.cameraAngle();
}
public boolean isMoveCorrectionActive() {
Minecraft client = Minecraft.getInstance();
if (BaritoneMovementHelper.isBaritoneActive(client.player)) {
return false;
}
AngleConstructor rotationPlan = getCurrentRotationPlan();
return currentAngle != null && rotationPlan != null && rotationPlan.isMoveCorrection();
}
public boolean isFreeCorrectionActive() {
AngleConstructor rotationPlan = getCurrentRotationPlan();
return isMoveCorrectionActive() && rotationPlan != null && rotationPlan.isFreeCorrection();
}
public boolean isReturning() {
return returning;
}
public boolean isUseItemReturnPending() {
return useItemReturnPending;
}
public AngleConstructor getCurrentRotationPlan() {
AngleConstructor activePlan = rotationPlanTaskProcessor.fetchActiveTaskValue();
return activePlan != null ? activePlan : lastRotationPlan;
}
public void rotateTo(Angle.VecRotation vecRotation, LivingEntity entity, int reset, AngleConfig configurable, TaskPriority taskPriority, Module provider) {
rotateTo(configurable.createRotationPlan(vecRotation.getAngle(), vecRotation.getVec(), entity, reset), taskPriority, provider);
}
public void rotateTo(Angle angle, int reset, AngleConfig configurable, TaskPriority taskPriority, Module provider) {
rotateTo(configurable.createRotationPlan(angle, angle.toVector(), null, reset), taskPriority, provider);
}
public void rotateTo(Angle angle, AngleConfig configurable, TaskPriority taskPriority, Module provider) {
rotateTo(configurable.createRotationPlan(angle, angle.toVector(), null, 1), taskPriority, provider);
}
public void rotateTo(AngleConstructor plan, TaskPriority taskPriority, Module provider) {
Minecraft client = Minecraft.getInstance();
if (BaritoneMovementHelper.isBaritoneActive(client.player)) {
return;
}
returning = false;
useItemReturnPending = false;
rotationRequestedThisTick = true;
rotationPlanTaskProcessor.addTask(new TaskProcessor.Task<>(1, taskPriority.getPriority(), provider, plan));
}
public void update(Minecraft client) {
tick(client);
}
public void tick(Minecraft client) {
if (client == null || client.player == null || client.level == null) {
reset();
return;
}
if (BaritoneMovementHelper.isBaritoneActive(client.player)) {
if (hasAnyRotationState()) {
reset();
}
return;
}
if (forcePacketRotationTicks > 0) {
forcePacketRotationTicks--;
}
rotationRequestedThisTick = false;
queuedRotationTaskThisTick = false;
Manager.postEvent(new RotationUpdateEvent(EventPhase.PRE));
queuedRotationTaskThisTick = rotationPlanTaskProcessor.fetchActiveTaskValue() != null;
advanceRotation(client);
Manager.postEvent(new RotationUpdateEvent(EventPhase.POST));
if (useItemReturnPending && !shouldDelayUseAction()) {
useItemReturnPending = false;
}
if (!hasActiveRotationOwner() && hasAnyRotationState()) {
staleInactiveTicks++;
if (staleInactiveTicks >= 6) {
hardResetStaleRotationState();
return;
}
} else {
staleInactiveTicks = 0;
}
}
private void advanceRotation(Minecraft client) {
AngleConstructor activePlan = getCurrentRotationPlan();
if (activePlan == null) {
return;
}
Angle clientAngle = new Angle(client.player.getYRot(), client.player.getXRot());
if (returning && currentAngle != null && computeRotationDifference(currentAngle, clientAngle) < 1.0F) {
restoreVanillaLook();
return;
}
if (lastRotationPlan != null) {
double differenceFromCurrentToPlayer = computeRotationDifference(serverAngle, clientAngle);
if (activePlan.getTicksUntilReset() <= rotationPlanTaskProcessor.tickCounter() && differenceFromCurrentToPlayer < 1.0F) {
client.player.setYRot(getRotation().getYaw());
client.player.setXRot(getRotation().getPitch());
setRotation(null);
setFakeRotation(null);
lastRotationPlan = null;
rotationPlanTaskProcessor.clear();
returning = false;
useItemReturnPending = false;
return;
}
}
Angle baseAngle = currentAngle != null ? currentAngle : clientAngle;
Angle newAngle = activePlan.nextRotation(baseAngle, rotationPlanTaskProcessor.fetchActiveTaskValue() == null).adjustSensitivity();
setRotation(newAngle);
lastRotationPlan = activePlan;
rotationPlanTaskProcessor.tick(1);
}
public void applyPlayerRotation(Minecraft client) {
if (client == null || client.player == null || currentAngle == null) {
return;
}
client.player.setYRot(currentAngle.getYaw());
client.player.setXRot(currentAngle.getPitch());
client.player.setYHeadRot(currentAngle.getYaw());
client.player.setYBodyRot(currentAngle.getYaw());
}
public void clear() {
rotationPlanTaskProcessor.clear();
currentAngle = null;
previousAngle = null;
lastRotationPlan = null;
useItemReturnPending = false;
}
public void startReturning() {
startReturning(null);
}
public void startReturningForUse() {
useItemReturnPending = true;
startReturning(USE_ITEM_RETURN_SMOOTH);
}
public boolean requestUseRotationRestore() {
if (!shouldDelayUseAction()) {
useItemReturnPending = false;
return false;
}
if (!useItemReturnPending) {
startReturningForUse();
}
return true;
}
public boolean shouldDelayUseAction() {
Minecraft client = Minecraft.getInstance();
if (client.player == null) {
return false;
}
Angle cameraAngle = MathAngle.cameraAngle();
return returning
|| currentAngle != null && computeRotationDifference(currentAngle, cameraAngle) > 0.35D
|| fakeAngle != null && computeRotationDifference(fakeAngle, cameraAngle) > 0.35D
|| forcePacketRotationTicks > 0 && previousAngle != null && computeRotationDifference(previousAngle, cameraAngle) > 0.35D;
}
public void reset() {
clear();
fakeAngle = null;
previousFakeAngle = null;
fakeBodyYaw = null;
previousFakeBodyYaw = null;
serverAngle = Angle.DEFAULT;
returning = false;
forcePacketRotationTicks = 0;
staleInactiveTicks = 0;
rotationRequestedThisTick = false;
queuedRotationTaskThisTick = false;
}
public void restoreVanillaLook() {
reset();
syncVanillaHeadAndBody();
}
public void syncAfterFirstPersonRestore() {
Minecraft client = Minecraft.getInstance();
if (client.player == null) {
reset();
return;
}
Angle playerAngle = MathAngle.cameraAngle();
Angle syncedAngle = normalizeAngle(playerAngle, currentAngle != null ? currentAngle : playerAngle);
currentAngle = syncedAngle;
previousAngle = syncedAngle;
fakeAngle = null;
previousFakeAngle = null;
fakeBodyYaw = null;
previousFakeBodyYaw = null;
returning = false;
forcePacketRotationTicks = 0;
useItemReturnPending = false;
}
public void onMovePacket(ServerboundMovePlayerPacket packet) {
if (packet != null && packet.hasRotation()) {
serverAngle = new Angle(packet.getYRot(1), packet.getXRot(1));
}
}
public void onPlayerPosition(ClientboundPlayerPositionPacket packet) {
if (packet != null) {
serverAngle = new Angle(packet.change().yRot(), packet.change().xRot());
}
}
public static double computeRotationDifference(Angle a, Angle b) {
return Math.hypot(Math.abs(computeAngleDifference(a.getYaw(), b.getYaw())), Math.abs(a.getPitch() - b.getPitch()));
}
public static float computeAngleDifference(float a, float b) {
return Mth.wrapDegrees(a - b);
}
private Vec3 fixVelocity(Vec3 currentVelocity, Vec3 movementInput, float speed) {
if (currentAngle == null) {
return currentVelocity;
}
double length = movementInput.lengthSqr();
if (length < 1.0E-7D) {
return Vec3.ZERO;
}
Vec3 scaled = (length > 1.0D ? movementInput.normalize() : movementInput).scale(speed);
float sin = Mth.sin(currentAngle.getYaw() * Mth.DEG_TO_RAD);
float cos = Mth.cos(currentAngle.getYaw() * Mth.DEG_TO_RAD);
return new Vec3(scaled.x * cos - scaled.z * sin, scaled.y, scaled.z * cos + scaled.x * sin);
}
private Angle getPacketRotation() {
if (currentAngle != null) {
return currentAngle;
}
if (fakeAngle != null) {
return fakeAngle;
}
if (forcePacketRotationTicks > 0 && previousAngle != null) {
return previousAngle;
}
return MathAngle.cameraAngle();
}
private Angle normalizeAngle(Angle angle, Angle reference) {
if (angle == null) {
return null;
}
float yaw = angle.getYaw();
if (reference != null) {
yaw = reference.getYaw() + Mth.wrapDegrees(yaw - reference.getYaw());
} else {
yaw = Mth.wrapDegrees(yaw);
}
return new Angle(yaw, Mth.clamp(angle.getPitch(), -90.0F, 90.0F));
}
private void startReturning(RotateConstructor returnSmooth) {
AngleConstructor sourcePlan = rotationPlanTaskProcessor.fetchActiveTaskValue();
AngleConstructor returnPlan = sourcePlan != null ? sourcePlan : lastRotationPlan;
if (returnPlan != null && returnSmooth != null) {
returnPlan = cloneRotationPlan(returnPlan, returnSmooth);
} else if (returnPlan == null && returnSmooth != null && currentAngle != null) {
returnPlan = new AngleConstructor(currentAngle, currentAngle.toVector(), null, returnSmooth, 1, 1.0F, false, false);
}
lastRotationPlan = returnPlan;
rotationPlanTaskProcessor.clear();
returning = currentAngle != null && lastRotationPlan != null;
if (!returning && !shouldDelayUseAction()) {
useItemReturnPending = false;
}
}
private AngleConstructor cloneRotationPlan(AngleConstructor sourcePlan, RotateConstructor returnSmooth) {
return new AngleConstructor(
sourcePlan.getAngle(),
sourcePlan.getVec3d(),
sourcePlan.getEntity(),
returnSmooth,
sourcePlan.getTicksUntilReset(),
sourcePlan.getResetThreshold(),
sourcePlan.isMoveCorrection(),
sourcePlan.isFreeCorrection()
);
}
private boolean hasAnyRotationState() {
return currentAngle != null
|| fakeAngle != null
|| previousAngle != null
|| previousFakeAngle != null
|| lastRotationPlan != null
|| returning
|| useItemReturnPending;
}
private boolean hasActiveRotationOwner() {
return rotationRequestedThisTick
|| queuedRotationTaskThisTick
|| returning
|| useItemReturnPending
|| forcePacketRotationTicks > 0;
}
private void hardResetStaleRotationState() {
restoreVanillaLook();
}
private void syncVanillaHeadAndBody() {
Minecraft client = Minecraft.getInstance();
if (client.player != null) {
float yaw = client.player.getYRot();
client.player.setYHeadRot(yaw);
client.player.setYBodyRot(yaw);
}
}
@SubscribeEvent
private void onPlayerVelocityStrafe(PlayerVelocityStrafeEvent event) {
Minecraft client = Minecraft.getInstance();
if (BaritoneMovementHelper.isBaritoneActive(client.player)) {
return;
}
if (isMoveCorrectionActive()) {
event.setVelocity(fixVelocity(event.getVelocity(), event.getMovementInput(), event.getSpeed()));
}
}
@SubscribeEvent
private void onTick(TickEvent.Pre event) {
tick(event.getClient());
}
@SubscribeEvent
private void onPacket(PacketEvent event) {
if (event.isCancelled()) {
return;
}
if (event.isSend()) {
if (event.getPacket() instanceof ServerboundMovePlayerPacket movePacket) {
onMovePacket(movePacket);
}
return;
}
if (event.getPacket() instanceof ClientboundPlayerPositionPacket positionPacket) {
onPlayerPosition(positionPacket);
}
}
}