Documentation
¶
Overview ¶
Package script is the deterministic COB bytecode virtual machine. A unit's compiled BOS script drives its piece animation (walking gaits, rotating turrets, opening build yards), weapon aim threads and death sequences; without it a unit is an inert model. The VM runs identically on the native authority and the wasm client because every operation is integer math through engine/fixed and the only entropy source is a seeded engine/rng stream, so two engines fed the same script and the same tick sequence evolve bit-identically.
The layering mirrors the rest of the engine: a Program is the immutable, shared compiled form of one unit type's script (parsed once from a COB), while the mutable per-unit state — threads, static variables, piece animators — lives on a Unit owned by a Runtime. sim drives the Runtime through the sim.Runtime interface and reads piece transforms through sim.Binding; neither requires sim to import this package, keeping the dependency arrow pointing in.
Index ¶
- Constants
- type Host
- type Instruction
- type Program
- type Runtime
- type ScriptSource
- type Unit
- func (u *Unit) AddBreakpoint(scriptIdx int, offset uint32)
- func (u *Unit) AimStatus(id int32) (done bool, ret int32)
- func (u *Unit) ClearBreakpointHits()
- func (u *Unit) ClearBreakpoints()
- func (u *Unit) CobState() frame.CobUnitState
- func (u *Unit) Coverage() map[int][]uint32
- func (u *Unit) DrainEffects() []frame.Event
- func (u *Unit) ExportCob() frame.CobSnapshot
- func (u *Unit) FinishedDying() bool
- func (u *Unit) HasScript(name string) bool
- func (u *Unit) ImportCob(snap frame.CobSnapshot)
- func (u *Unit) KillAllThreads()
- func (u *Unit) KillThread(id int32)
- func (u *Unit) KillThreadsByName(name string)
- func (u *Unit) KilledStatus(id int32) (done bool, corpsetype int32)
- func (u *Unit) Pieces() []frame.PieceState
- func (u *Unit) RemoveBreakpoint(scriptIdx int, offset uint32)
- func (u *Unit) ResetState()
- func (u *Unit) Restart(name string, args ...int)
- func (u *Unit) RunQuery(name string, args ...int) (int32, bool)
- func (u *Unit) ScriptNames() []string
- func (u *Unit) SetStatic(idx int, v int32)
- func (u *Unit) SetThreadLocal(id int32, idx int, v int32)
- func (u *Unit) SetThreadPC(id int32, pc int)
- func (u *Unit) SetUnitValuePort(port int, v int32)
- func (u *Unit) Start(name string, args ...int)
- func (u *Unit) StartAim(name string, args ...int) int32
- func (u *Unit) StepThread(id int32)
- func (u *Unit) TakeWeaponAimAborted(slot int) bool
- func (u *Unit) TakeWeaponReady(slot int) bool
- func (u *Unit) UnitValuePort(port int) int32
Constants ¶
const ( UVWeaponAimAborted = 21 UVWeaponReady = 22 UVWeaponLaunchNow = 23 UVFinishedDying = 26 UVCurrentSpeed = 29 )
TA: Kingdoms unit-value ports (21+, inert under the TA engine). The weapon trio backs TA:K's aim handshake: a v6 script signals aim state by WRITING the weapon index into WEAPON_READY / WEAPON_AIM_ABORTED via SET_VALUE instead of returning a value from the aim thread the way TA scripts do. CURRENT_SPEED feeds the MoveWatcher loops TA:K units poll to trigger their walk gaits (the world pushes it through SetUnitValuePort each tick).
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Host ¶
type Host interface {
GetUnitValue(port int) int32
SetUnitValue(port, value int)
EmitSfx(sfxType, piece int)
PlaySound(sound, volume int)
Explode(piece, sfxType int)
}
Host is the optional callback surface the world exposes to running scripts: unit-value ports the scripts poll/set and the effect opcodes (EMIT_SFX, PLAY_SOUND, EXPLODE). A nil Host makes the VM self-contained — GET reads return TA's engine defaults and effect opcodes are no-ops — which is what the VM's unit tests rely on. The world supplies a real Host once combat and effects are wired through.
type Instruction ¶
Instruction is one decoded COB instruction in VM-ready form: the 32-bit opcode plus its (up to two) inline operands and its byte offset within the script's code, which JUMP/JUMP_IF_FALSE targets resolve against.
type Program ¶
type Program struct {
// contains filtered or unexported fields
}
Program is the immutable compiled form of one unit type's COB. It is shared read-only across every unit instance of that type; all mutable execution state lives on Unit.
func NewProgram ¶
func NewProgram(pieceNames []string, numStatic int, scripts []ScriptSource) *Program
NewProgram assembles a Program from raw script sources. The piece-name list sizes the per-unit animator and visibility tables; numStatic sizes the static variable array.
func (*Program) PieceNames ¶
PieceNames returns the program's piece-name list (rest-pose order).
func (*Program) ScriptIndex ¶
ScriptIndex resolves a script name (case-insensitively) to its index.
func (*Program) ScriptNames ¶
ScriptNames returns the program's script entry-point names in index order. The studio's unit editor lists them so the Actions panel can offer a button per script (Create, Activate, AimPrimary, …).
type Runtime ¶
type Runtime struct {
// contains filtered or unexported fields
}
Runtime hosts every unit's script VM for one world and advances them in lockstep on a fixed tick. It owns the deterministic RNG that OP_RAND draws from, so the whole simulation reproduces from a seed. It satisfies sim.Runtime: the world calls Tick once per simulated tick with its running millisecond clock.
func NewRuntime ¶
NewRuntime builds a runtime whose script RNG is seeded deterministically. Every client seeded identically draws the same script randomness in the same order, which is what keeps script-driven outcomes in lockstep.
func (*Runtime) KillAllThreads ¶
func (r *Runtime) KillAllThreads()
KillAllThreads marks every live thread on every hosted unit dead. It backs the studio's "Terminate All Scripts" developer command; the next tickStep prunes the dead threads. Debug-only — a sandbox tool, never driven from gameplay — so it carries no determinism contract.
func (*Runtime) NewUnit ¶
NewUnit instantiates a unit of the given program with an optional Host and registers it for ticking. The returned *Unit satisfies sim.Binding.
func (*Runtime) Reset ¶
func (r *Runtime) Reset()
Reset drops every hosted unit and rewinds the tick clock. The world calls this when it rebuilds its unit set (a resync from an authoritative snapshot) so stale script state can't leak across the restore.
func (*Runtime) RestoreRng ¶
RestoreRng sets the script RNG's internal state, the inverse of SnapshotRng.
func (*Runtime) SnapshotRng ¶
SnapshotRng returns the script RNG's internal state so a resync can hand the joiner the exact draw position the authority reached. OP_RAND consumes this stream, so matching it keeps script-driven randomness (and thus animation) in lockstep across the join.
func (*Runtime) Tick ¶
Tick advances script time to the world's millisecond clock in fixed steps. The world increments its clock by exactly one tick before each call, so in steady state this runs a single step; the loop only matters if the clock ever jumps forward, and a fresh runtime aligns to the first observed time rather than fast-forwarding through history.
type ScriptSource ¶
type ScriptSource struct {
Name string
Insts []Instruction
}
ScriptSource is one named entry point's instruction stream, the input to NewProgram. FromCOB produces these from a parsed COB; a future in-tree assembler could target the same shape.
type Unit ¶
type Unit struct {
// contains filtered or unexported fields
}
Unit is one unit's live script state: its threads, static variables and per-piece animators. It satisfies sim.Binding.
func (*Unit) AddBreakpoint ¶
AddBreakpoint sets a breakpoint at a byte offset of one script; RemoveBreakpoint clears it; ClearBreakpoints drops every breakpoint on the unit. Threads park on a set offset before executing its instruction.
func (*Unit) AimStatus ¶
AimStatus reports whether the thread with the given id has finished and, if so, the value it returned. A still-running thread reports (false, 0). A thread that died this tick reports its captured return value from the death ledger. An id that is neither live nor in the ledger — already pruned, or never a real thread (id 0) — reports (true, 1): a vanished aim thread is treated as a completed, successful aim so the weapon SM degrades to firing rather than stalling forever.
func (*Unit) ClearBreakpointHits ¶
func (u *Unit) ClearBreakpointHits()
ClearBreakpointHits releases every thread parked on a breakpoint (the debugger's "Continue"): it clears the hit flag and arms bpResume so the thread runs past the breakpoint it is stopped on rather than re-parking immediately.
func (*Unit) ClearBreakpoints ¶
func (u *Unit) ClearBreakpoints()
func (*Unit) CobState ¶
func (u *Unit) CobState() frame.CobUnitState
CobState returns the unit's inspectable script state — a copy of its static variables plus a per-live-thread summary — for the studio's Runtime / Script Variables panels. Debug-only: it never feeds the world hash, so reporting it cannot perturb determinism.
func (*Unit) Coverage ¶
Coverage returns a stable snapshot of every executed byte offset, keyed by script index, for the debugger's coverage-dimming view.
func (*Unit) DrainEffects ¶
DrainEffects returns the effect events buffered since the last drain and clears the buffer. The world calls it each tick to harvest script-emitted SFX / sounds for the render snapshot.
func (*Unit) ExportCob ¶
func (u *Unit) ExportCob() frame.CobSnapshot
ExportCob captures the unit's full live VM state — statics, active animators, hidden pieces, running threads and the thread-id counter — so a late joiner can resume the exact piece poses (turret aim, rotation, mid-animation) the authority holds rather than re-deriving them by replaying Create/StartMoving. Idle animators and visible pieces are the rest state a freshly built unit already carries, so only the deviations are serialized.
func (*Unit) FinishedDying ¶
FinishedDying reports whether the unit's Dying script has signalled completion by setting FINISHED_DYING — TA:K's cue that the fall animation has landed and the corpse swap can happen.
func (*Unit) HasScript ¶
HasScript reports whether the unit's program defines the named entry point.
func (*Unit) ImportCob ¶
func (u *Unit) ImportCob(snap frame.CobSnapshot)
ImportCob overwrites the unit's live VM state with a previously exported snapshot, the inverse of ExportCob. The unit must already be built from the same program (so animator arrays are sized and scriptIndex values resolve); the caller rebuilds the unit via NewUnit, then applies this instead of running Create. Animators and visibility start from the freshly built rest state and are overwritten only where the snapshot deviates.
func (*Unit) KillAllThreads ¶
func (u *Unit) KillAllThreads()
KillAllThreads marks every live thread on this unit dead (the per-unit "Stop all threads" developer command). Animators keep their last pose; only the threads stop.
func (*Unit) KillThread ¶
KillThread marks the single thread with the given id dead (the per-thread kill button in the Runtime panel). Unknown ids are ignored.
func (*Unit) KillThreadsByName ¶
KillThreadsByName marks dead every live thread running the named script. The offline unit editor uses it to retract a transient pose handler (the RestoreAfterDelay / RestorePosition threads a one-shot aim leaves behind) before re-driving the unit. Unknown names are ignored.
func (*Unit) KilledStatus ¶
KilledStatus reports whether the tracked Killed thread has finished and, when it has, the corpsetype its second local held — TA's out-param convention (1 = intact corpse, 2 = damaged, 3 = nothing). A vanished or never-real id reports (true, 1) so a unit whose death script was pruned still leaves the default corpse.
func (*Unit) Pieces ¶
func (u *Unit) Pieces() []frame.PieceState
Pieces returns the current per-piece transform for the render snapshot. A piece with no active animator on an axis contributes its rest value (zero offset / rotation), and visibility reflects SHOW/HIDE.
func (*Unit) RemoveBreakpoint ¶
func (*Unit) ResetState ¶
func (u *Unit) ResetState()
ResetState returns the unit to a clean slate: every thread dies, static vars zero, animators snap back to rest, and all pieces become visible — the per-unit "Reset" developer command. It does not re-run Create; the caller decides whether to restart any entry point.
func (*Unit) Restart ¶
Restart spawns a thread on the named script, first marking any live thread already running that same script dead. It gives the world the COB START opcode's supersede semantics, so a continuously re-driven tracking thread (a weapon's aim loop, re-issued as its target moves) replaces its prior instance instead of accumulating a fresh thread every tick.
func (*Unit) RunQuery ¶
RunQuery executes a Query* script synchronously within the current tick and returns the value its first local ended up holding — the convention TA uses to report a firing piece. It fails (ok=false) if the script does not exist or would yield (sleep/wait/animate/spawn), keeping the synchronous contract honest.
func (*Unit) ScriptNames ¶
ScriptNames returns the unit type's script entry-point names in index order, the list the offline editor's Actions panel turns into a run-script button per entry (Create, Activate, AimPrimary, …).
func (*Unit) SetStatic ¶
SetStatic writes one of the unit's static variables (the debugger's editable Globals tray). Out-of-range indices are ignored.
func (*Unit) SetThreadLocal ¶
SetThreadLocal writes one of a thread's local variables (the debugger's editable Locals tray). Out-of-range indices are ignored.
func (*Unit) SetThreadPC ¶
SetThreadPC moves a thread's program counter to an instruction index and clears its sleep / wait / breakpoint-parked state so execution resumes from the new spot. The index is clamped to the current script's instruction range.
func (*Unit) SetUnitValuePort ¶
SetUnitValuePort writes a COB unit-value port that scripts read via GET_UNIT_VALUE (TA's GetUnitValue). The offline unit editor uses it to drive HEALTH / build-percent / activation / standing-orders from its inspector sliders. With no Host attached this store is the port source; a hosted unit routes through the Host instead. Debug/authoring-only — never feeds the hash.
func (*Unit) Start ¶
Start spawns a thread on the named script with the given integer arguments as its initial locals. Unknown names are ignored, matching the world's fire-and-forget calls into optional handlers (Create, StartMoving, ...).
func (*Unit) StartAim ¶
StartAim spawns the named aim script with the COB START supersede semantics (cancelling any live instance) and returns the new thread's id so the caller can poll its completion via AimStatus. It returns 0 if the script is unknown, which AimStatus reads as "already done" so a unit without the script never blocks its fire cadence.
func (*Unit) StepThread ¶
StepThread advances one thread by exactly one instruction (the debugger's "Step" button). It clears any sleep / wait so the instruction runs now and resumes past a breakpoint the thread is parked on. A missing or dead thread is a no-op. Debug-only — never driven from gameplay.
func (*Unit) TakeWeaponAimAborted ¶
TakeWeaponAimAborted reports whether the script has signalled WEAPON_AIM_ABORTED for the given weapon index since the last call, clearing the flag.
func (*Unit) TakeWeaponReady ¶
TakeWeaponReady reports whether the script has signalled WEAPON_READY for the given weapon index since the last call, clearing the flag. This is the TA:K equivalent of an aim thread returning TRUE.
func (*Unit) UnitValuePort ¶
UnitValuePort reports the current value of a COB unit-value port (the read the inspector's Ports panel surfaces). Returns the effective value GET_UNIT_VALUE would yield: an explicit port write, else TA's resting default.