Shift
Shift is a compiled finite-state machine (FSM / HSM). A .shift graph becomes u8 state ids in out/. Invalid transitions are rejected by CanEnter / ChangeState; hierarchy walks ancestor enter/leave chains. Not Hive (ECS).
Header: #include <clpp/libs/shift.clh> or generated Npc.clh. Runtime: CluauppLibs.Shift. Hot path: one-byte WriteId / ReadId buffers for Flare — not JSON.
- One byte on the wire. Replicate state with
WriteId; apply on clients withReadId(skips guards — server owns truth). - Hierarchy.
state Chase parent Combat—OnEnter/OnLeaverun along the ancestor chain. - Side data on the machine via
GetData/ChangeDatawithout stringlyOnDataChangedevery frame.
Schema (Npc.shift)
Section titled “Schema (Npc.shift)”opt name = Npcstate Idlestate Combatstate Chase parent CombatIdle -> Chase when SeePlayerChase -> Idle when LostExample
Section titled “Example”#include "Npc.clh"
void OnChase() { post("chase");}
void init() { ShiftMachine brain = Npc.New(); brain.Guard("SeePlayer", CanSeePlayer); brain.OnEnter("Chase", OnChase); brain.ChangeState("Chase"); buffer id = brain.WriteId();}Pair Hive for component columns; Shift for combat / AI mode.
Shift.New
Section titled “Shift.New”Returns: ShiftMachine (generated Npc.New() passes compiled ids, transitions, and parents).
When: Create one machine per NPC, weapon mode, or UI flow that needs compiled states.
ShiftMachine brain = Shift.New();ShiftMachine.ChangeState
Section titled “ShiftMachine.ChangeState”Returns: nothing (no-op if destroyed, unknown state, same state, or CanEnter is false).
When: Authoritative transition on the server (or local-only UI states). Runs leave/enter callbacks along the hierarchy.
brain.ChangeState("Idle");ShiftMachine.GetState
Section titled “ShiftMachine.GetState”Returns: string — current state name.
When: Logging, UI labels, or guards in gameplay code.
string s = brain.GetState();ShiftMachine.GetCurrentState
Section titled “ShiftMachine.GetCurrentState”Returns: string — alias of GetState.
When: Same as GetState when you prefer explicit naming.
string s = brain.GetCurrentState();ShiftMachine.GetPreviousState
Section titled “ShiftMachine.GetPreviousState”Returns: string — state name before the last successful transition.
When: “Return to last mode” or animation that depends on where you came from.
string prev = brain.GetPreviousState();ShiftMachine.GetId
Section titled “ShiftMachine.GetId”Returns: int — current state id (u8 value as number).
When: Compare states cheaply or feed non-Shift buffers.
int id = brain.GetId();ShiftMachine.Guard
Section titled “ShiftMachine.Guard”Returns: nothing.
When: Register a named guard referenced by when GuardName edges in the .shift file.
brain.Guard("SeePlayer", CanSeePlayer);ShiftMachine.OnEnter
Section titled “ShiftMachine.OnEnter”Returns: nothing (if already in that state when registered, enter runs immediately).
When: Start animations, sounds, or Hive queries when a state becomes active.
brain.OnEnter("Chase", OnChase);ShiftMachine.OnLeave
Section titled “ShiftMachine.OnLeave”Returns: nothing.
When: Tear down chase VFX or reset timers when leaving a state.
brain.OnLeave("Chase", OnLeaveChase);ShiftMachine.CanEnter
Section titled “ShiftMachine.CanEnter”Returns: bool — whether ChangeState would succeed from the current state (explicit edges + guards + parent descent).
When: UI affordances, AI telegraphs, or client prediction checks before calling ChangeState.
if (brain.CanEnter("Chase")) { brain.ChangeState("Chase");}ShiftMachine.WriteId
Section titled “ShiftMachine.WriteId”Returns: buffer — 1 byte: current state id.
When: Pack into Flare packets or any replication that should stay JSON-free.
buffer id = brain.WriteId();ShiftMachine.ReadId
Section titled “ShiftMachine.ReadId”Returns: nothing.
When: Apply replicated state on a client or secondary machine without re-running guards (visual sync).
brain.ReadId(replicatedBuf);ShiftMachine.GetData
Section titled “ShiftMachine.GetData”Returns: auto — mutable string-keyed table on the machine.
When: Per-machine blackboard (target id, timer) that is not worth a Hive component.
auto data = brain.GetData();ShiftMachine.ChangeData
Section titled “ShiftMachine.ChangeData”Returns: nothing.
When: Set one key on the machine data table.
brain.ChangeData("Target", player);ShiftMachine.Destroy
Section titled “ShiftMachine.Destroy”Returns: nothing.
When: NPC despawn — clears data and callbacks; further transitions are ignored.
brain.Destroy();