Skip to main content

The Local Player

session.entityState.localPlayer is an EntityLocalPlayer — you. It extends EntityPlayer (and thus AbstractEntity), so it has all the entity/player state (position, health, rotation, uuid, gamemode, …) plus the action verbs and controllers below.

const player = ctx.session.entityState.localPlayer;
ctx.on("tick", () => player.jump());

Identity & session state

MemberTypeDescription
xuidstringXUID of the local player.
serverAddressstringAddress of the connected server.
gameVersionstringClient game version string.
isInitializedbooleanWhether the local player has finished initializing.
tickbigintThe player's current tick counter.

Movement state

MemberTypeDescription
moveVectorVector2Raw strafe input vector.
isMovingbooleanMovement keys pressed (false when only coasting on inertia).
sneaking / sprinting / swimming / gliding / crawlingbooleanPose/movement flags.
verticalCollisionbooleanCollided vertically last tick.
horizontalCollisionbooleanCollided horizontally last tick.
prevServerSideYawnumberServer-side yaw on the previous tick.
inputFlagsInputFlagMutable auth-input flags for the current tick (e.g. start_jumping).
get predictedMotionVector3Predicted motion ignoring collision (what motion would be with no blocks in the way).
get serverSideRotationVector2Rotation currently sent to the server (scheduled override or actual).

Action verbs

These queue actions for the current/next tick. Rotations are Vector2 — build one with new utils.Vector2(...) (see Utilities) or reuse the player's own serverSideRotation.

MethodDescription
setPosition(position, movementTakeover?)Set the player's position (optionally take over movement).
setMotion(motion)Set the player's motion.
addMotion(motion)Add to the current motion.
strafe(speed?, strength?)Apply strafe motion in the movement direction. speed defaults to current horizontal speed; strength (0–1, default 1) blends between current and new motion.
jump()Apply a jump (accounts for jump-boost).
swingItem(source?)Swing the arm once this tick (optionally tagged with a source string).
click(rotation)Queue an interact/attack click at the given rotation.
missClick(rotation)Queue a deliberate miss-click.
interactEntity(entity, swing, rotation, action, positionOverride?)Attack or interact with an entity. action is "attack" or "interact".
interactBlock(position, face, swingSource?, consumeItem?)Use/place against a block face.
sendChatMessage(message)Send a chat message to the server as the player.
import { EntityNetworkPlayer } from "@protohax/userscript";

ctx.on("tick", () => {
const player = ctx.session.entityState.localPlayer;

// simple killaura-ish: attack the first attackable player,
// keeping the rotation currently being sent to the server
for (const e of ctx.session.entityState.entities.values()) {
if (e instanceof EntityNetworkPlayer && e.canBeAttacked) {
player.interactEntity(e, true, player.serverSideRotation, "attack");
break;
}
}
});

Inventories

The local player owns three containers (full detail on the Inventory page):

MemberType
inventoryPlayerInventory
inventoryArmorPlayerInventoryArmor
inventoryOffhandPlayerInventoryOffhand

breakingController

Controls block breaking. Type: AbstractBreakingController.

MemberSignatureDescription
breakingVector3 | nullPosition of the block currently being broken, or null.
canInjectBreak()booleanWhether a break can currently be injected.
startBreak(position, face, range?, callback?)voidBegin breaking a block. callback(progress, tickProgress) reports each tick; pass range: 0 to disable auto-abort.
abortBreak()voidAbort the current injected break.
forceStopBreak()voidFinish the current break early, as if it completed normally.
const bc = ctx.session.entityState.localPlayer.breakingController;
if (bc.canInjectBreak()) {
// position is any IVector3 ({ x, y, z }); face is a block face index
bc.startBreak({ x: 10, y: 64, z: 20 }, 1, 5, (progress) => {
if (progress === null) console.log("break finished/aborted");
});
}

rotationScheduler

Schedules server-side rotation overrides (aim). Type: Scheduler<Vector2>.

MemberSignatureDescription
request(value, priority, provider, expiryMillis)voidRequest a rotation override. Highest priority wins; provider identifies the requester; expiryMillis is how long it lingers.
cancel(provider)voidCancel this provider's request.
get currentT | undefinedThe currently-winning value.
subscribe(listener)() => voidObserve the current value; returns an unsubscribe fn.

SchedulerPriority is a string enum. It is reached through the utils namespace (not a top-level export):

import { utils } from "@protohax/userscript";
// utils.SchedulerPriority.Lowest | Low | Medium | High | Highest
import { utils } from "@protohax/userscript";

const player = ctx.session.entityState.localPlayer;
const OWNER = {}; // stable identity for this module's request

ctx.on("tick", () => {
player.rotationScheduler.request(
new utils.Vector2(90, 0), // (yaw, pitch)
utils.SchedulerPriority.High,
OWNER,
50,
);
});
ctx.onDisable(() => player.rotationScheduler.cancel(OWNER));