Class RotationManager
Modules submit a rotation each tick they want to be active. Higher
priority replaces a lower-priority active request. The active
request lives for one tick — the owner must re-submit each tick
to keep it active. There is no queue, no suppliers, no instant flag.
Three submission entry points:
requestRotation(String, double, float, float)— uses the global mode from theRotationssettings module.requestMotionRotation(String, double, float, float)— forces MOTION (rotation piggy-backs on the next vanillasendPositionpacket so movement physics see the spoofed yaw).requestSilentRotation(String, double, float, float)— forces SILENT: an extraServerboundMovePlayerPacket.PosRotis sent immediately so the server validates following action packets against the spoofed angles. The next vanillasendPositionnaturally restores the real client rotation. Where a look of its own is not free (separateLooksFree()false: 1.21+), the look rides the tick's own flying packet instead, and that tick's movement follows it.
-
Method Summary
Modifier and TypeMethodDescriptionvoidRuns at the very start of every tick — before any module's tick handler has had a chance to (re)submit.static RotationManagerget()The id of the active request, ornull.doubleThe priority of the active request, orDouble.NEGATIVE_INFINITY.booleanfloatdoubledoublefloatdoublefloatgetPitch()Current rotation target pitch — clamped to [-90, 90].floatThe player's real (un-spoofed) pitch at the start of this tick.floatThe player's real (un-spoofed) yaw at the start of this tick.floatThe pitch the server most recently saw.floatThe yaw the server most recently saw.floatgetYaw()Current rotation target yaw — the angle that gets sent in the next packet.voidinit()booleanWhether the active request is a look on the tick's flying packet (requestSilentRotation(java.lang.String, double, float, float)on these wires).booleanWhether the active request is in MOTION mode.booleanWhether any rotation request is currently active.booleanWhether the packet being sent right now is our own silent-aim PosRot (for SEND listeners).booleanWhether the active request is in SILENT mode.booleanjustTeleported(int withinTicks) True withinwithinTicksclient ticks of the last server teleport.static booleanWhether silent looks ride the tick's flying packet here (seerequestSilentRotation(java.lang.String, double, float, float)): on a wire where a look of its own is a Grim tick, on foot.voidThe tick's flying packet is sent: a look claimed for it has been carried and ends here.voidsendPosition is starting: the window for claiming this tick's look is over.voidonTravel()travel() is starting this tick: a look claimed from here on could not steer the movement.booleanpulseSilentRotation(double priority, float yaw, float pitch) One-shot silent look that does NOT take the rotation slot: the extraPosRotgoes out now and whoever owns the slot keeps it.voidExplicitly release the active request if it is owned byid.booleanrequestMotionRotation(String id, double priority, float yaw, float pitch) Force MOTION mode — rotation is applied via vanillasendPosition.booleanrequestMotionRotationCameraAnchored(String id, double priority, float yaw, float pitch) Force MOTION mode, anchoring the sent yaw to the real CAMERA yaw instead of the last-sent yaw.booleanrequestMotionRotationExact(String id, double priority, float yaw, float pitch) Force MOTION mode, sending the yaw and pitch bit for bit as given: no re-basing onto the last-sent or camera yaw, whose float arithmetic can land an ulp off.booleanrequestRotation(String id, double priority, float yaw, float pitch) Submit a rotation using the global mode from theRotationssettings module (defaults to MOTION if the module is missing).booleanrequestSilentRotation(String id, double priority, float yaw, float pitch) Force SILENT mode — an extraPosRotpacket is sent immediately so following action packets validate against the spoofed angles.booleanrequestSilentRotation(String id, double priority, float yaw, float pitch, net.minecraft.world.phys.AABB target) requestSilentRotation(String, double, float, float)for an action aimed attarget(a clicked block's box, an attacked entity's): where the look rides the flying packet and the tick's look is claimed already, the request is served by that look if its ray hitstarget, so a second action on the same spot needs no look of its own.voidMakes the next flying packet carry the motion look even if vanilla would leave it out: it sends a look only when it differs from the last onesendPositionsent, which a packet sent around it (a teleport's confirm, a silent look) can leave stale, so a held look never reaches the server.static booleanWhether a look sent in a packet of its own, beside the tick's flying packet, is free with Grim on this wire.static voidsetContainerScreenClientOnly(boolean clientOnly) Declares that the container GUI currently drawn has no menu behind it on the server — the caller closed the container server-side and is keeping the screen up only so the player does not see it blink.booleanWhether this tick's flying packet must carry a look whatever vanilla thinks: one a packet the server may have dropped after a teleport carried (see mirrorMove).intHow many server teleports have arrived; compare two reads to tell whether one came in between.floatusePitch(float pitch) The pitch counterpart ofuseYaw(float).floatuseYaw(float yaw) The yaw a use-item packet sent under the active request must carry: on a wire where silent looks ride the flying packet, exactly the one it will carry (Grim's BadPacketsJ compares the two bit for bit); elsewhereyawas given.
-
Method Details
-
get
-
init
public void init() -
teleportCount
public int teleportCount()How many server teleports have arrived; compare two reads to tell whether one came in between. -
justTeleported
public boolean justTeleported(int withinTicks) True withinwithinTicksclient ticks of the last server teleport. Used by ClientInputMixin to suppress a frame-perfect jump on the ack tick: Grim resets its sim to the teleport position and doesn't know the client's ground state there yet, so a jump (or a KB verified) on that exact tick is unpredictable — the one-offSimulation .42(unpredicted jump) andAntiKB .078 / A: 0.0(airborne-vs-grounded phase mismatch) flags while jump-spamming through pearl teleports. No human times a jump onto the ack tick, so a one-tick suppression is vanilla-invisible. -
requestRotation
Submit a rotation using the global mode from theRotationssettings module (defaults to MOTION if the module is missing).- Returns:
trueif accepted (took the active slot),falseif a higher-priority request already owns the slot this tick.
-
requestMotionRotation
Force MOTION mode — rotation is applied via vanillasendPosition. -
requestMotionRotationCameraAnchored
public boolean requestMotionRotationCameraAnchored(String id, double priority, float yaw, float pitch) Force MOTION mode, anchoring the sent yaw to the real CAMERA yaw instead of the last-sent yaw. For movement rotations (Sprint) whose target oscillates ~180° via WASD flips: serverYaw-anchoring resolves every 180° flip the same way (−180) and spirals the sent yaw unbounded (−298→−478→−658…). Camera-anchoring keeps it oscillating around the stable camera yaw. Do NOT use for combat aim — an aim target hovering exactly 180° from the camera would flip 360° on tiny changes (AimModulo360). -
requestMotionRotationExact
Force MOTION mode, sending the yaw and pitch bit for bit as given: no re-basing onto the last-sent or camera yaw, whose float arithmetic can land an ulp off. For a look a packet already carried, which the flying packet must repeat exactly (Grim's BadPacketsJ compares a use's look with the tick's by float equality). The caller keeps the yaw within 180° of the last one sent. -
requestSilentRotation
Force SILENT mode — an extraPosRotpacket is sent immediately so following action packets validate against the spoofed angles. The next vanillasendPositionrestores the real yaw.Where that packet is a Grim tick of its own (
looksRideFlying()), nothing is sent: the look is claimed for the tick's flying packet, and the action packets sent before it are judged against it. The caller sends them right away, as on any wire. One look per flying packet: once a tick's look is claimed, a request for another one is refused (unless withinSAME_LOOK), and so is one made after travel(), or between ticks, where the movement can no longer follow it. A refused caller sends no action this tick.release(java.lang.String)keeps a claimed look until the flying packet has carried it. -
requestSilentRotation
public boolean requestSilentRotation(String id, double priority, float yaw, float pitch, net.minecraft.world.phys.AABB target) requestSilentRotation(String, double, float, float)for an action aimed attarget(a clicked block's box, an attacked entity's): where the look rides the flying packet and the tick's look is claimed already, the request is served by that look if its ray hitstarget, so a second action on the same spot needs no look of its own. -
looksRideFlying
public static boolean looksRideFlying()Whether silent looks ride the tick's flying packet here (seerequestSilentRotation(java.lang.String, double, float, float)): on a wire where a look of its own is a Grim tick, on foot. Gliding the look steers the glide and the movement module's travel() overrides the physics, and riding the vehicle moves the player, so there a silent look is still sent as a packet of its own (a TickTimer setback on these wires: the accepted price of acting in flight). -
isFlyingLook
public boolean isFlyingLook()Whether the active request is a look on the tick's flying packet (requestSilentRotation(java.lang.String, double, float, float)on these wires). -
useYaw
public float useYaw(float yaw) The yaw a use-item packet sent under the active request must carry: on a wire where silent looks ride the flying packet, exactly the one it will carry (Grim's BadPacketsJ compares the two bit for bit); elsewhereyawas given. -
usePitch
public float usePitch(float pitch) The pitch counterpart ofuseYaw(float). -
separateLooksFree
public static boolean separateLooksFree()Whether a look sent in a packet of its own, beside the tick's flying packet, is free with Grim on this wire. Only a 1.17-1.20.x client has the 1.17 duplicate: aPosRotat the last position Grim neither counts (Timer) nor simulates. From 1.21 every flying packet is a tick to it (Timer, and the start of Post's window), and on 1.21.2+ TickTimer sets back a second one before the tick's end. There a look has to ride the tick's own flying packet, as a motion rotation. -
resendMotionLook
public void resendMotionLook()Makes the next flying packet carry the motion look even if vanilla would leave it out: it sends a look only when it differs from the last onesendPositionsent, which a packet sent around it (a teleport's confirm, a silent look) can leave stale, so a held look never reaches the server. -
pulseSilentRotation
public boolean pulseSilentRotation(double priority, float yaw, float pitch) One-shot silent look that does NOT take the rotation slot: the extraPosRotgoes out now and whoever owns the slot keeps it. For a caller that fires right before the tick's flying packet, where taking and releasing the slot would strip a motion rotation off that packet. The caller is responsible for not pulsing with a container screen open.- Returns:
falseif a higher-priority request owns the slot (nothing is sent)
-
release
Explicitly release the active request if it is owned byid. Modules normally don't need this — just stop re-submitting. A look claimed for this tick's flying packet stays until that packet has carried it (the actions sent under it are judged against it there). -
onTravel
public void onTravel()travel() is starting this tick: a look claimed from here on could not steer the movement. -
takeLookResend
public boolean takeLookResend()Whether this tick's flying packet must carry a look whatever vanilla thinks: one a packet the server may have dropped after a teleport carried (see mirrorMove). Asked once, by sendPosition. -
onPreSendPosition
public void onPreSendPosition()sendPosition is starting: the window for claiming this tick's look is over. -
onFlyingSent
public void onFlyingSent()The tick's flying packet is sent: a look claimed for it has been carried and ends here. -
isRotating
public boolean isRotating()Whether any rotation request is currently active. -
isMotionActive
public boolean isMotionActive()Whether the active request is in MOTION mode. -
isSilentActive
public boolean isSilentActive()Whether the active request is in SILENT mode. -
getActiveId
The id of the active request, ornull. -
getActivePriority
public double getActivePriority()The priority of the active request, orDouble.NEGATIVE_INFINITY. -
getYaw
public float getYaw()Current rotation target yaw — the angle that gets sent in the next packet. Returns the real client yaw when no request is active. -
getPitch
public float getPitch()Current rotation target pitch — clamped to [-90, 90]. Returns the real client pitch when no request is active. -
getRealYaw
public float getRealYaw()The player's real (un-spoofed) yaw at the start of this tick. -
getRealPitch
public float getRealPitch()The player's real (un-spoofed) pitch at the start of this tick. -
getServerYaw
public float getServerYaw()The yaw the server most recently saw. -
getServerPitch
public float getServerPitch()The pitch the server most recently saw. -
getLastSentX
public double getLastSentX() -
getLastSentY
public double getLastSentY() -
getLastSentZ
public double getLastSentZ() -
getLastSentYaw
public float getLastSentYaw() -
getLastSentPitch
public float getLastSentPitch() -
getLastSentOnGround
public boolean getLastSentOnGround() -
isSendingSilent
public boolean isSendingSilent()Whether the packet being sent right now is our own silent-aim PosRot (for SEND listeners). -
beginTick
public void beginTick()Runs at the very start of every tick — before any module's tick handler has had a chance to (re)submit. We snapshot the real rotation here sogetRealYaw()reflects the user's current intent, and we expire any active request that was submitted in a previous tick (the owner failed to re-submit). Called fromMinecraft.tick's head right beforeTickStartEventis posted, so that no listener of it, whatever its priority, requests before the tick has begun here. -
setContainerScreenClientOnly
public static void setContainerScreenClientOnly(boolean clientOnly) Declares that the container GUI currently drawn has no menu behind it on the server — the caller closed the container server-side and is keeping the screen up only so the player does not see it blink. While set, a rotation request does not dismiss the screen: from the server's point of view no container is open, so the look change is vanilla-legal. Callers set it around the rotation and clear it in afinally.
-