Axel Meyer c9c53cc43b chore: add Tier-1 LICENSE file
Adds the proprietary all-rights-reserved license that applies to this
library. The text is identical to the engine LICENSE — this lib is
Tier-1 official platform content, distributed under the same terms.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 18:04:24 +02:00
2026-05-16 18:04:24 +02:00

lib-core.command

Move-commands for registered units. RTS-style click-to-move: press a bound action (e.g., RMB) and selected units move to the world-coord under the cursor. Lib-driven auto-wire via action-binding + target-provider; per-frame movement via direction-normalize + step-vs-distance + arrive-snap.

Version: 0.1.0
Lib-ID: lib-core.command
Requires: lib-core.input v>=0.4.0, lib-core.camera v>=0.3.0
Tags: command, movement, rts, click-to-move

Topology

graph LR
  this["lib-core.command"]
  lib_core_input["lib-core.input"]
  this --> lib_core_input
  lib_core_camera["lib-core.camera"]
  this --> lib_core_camera
  engine["engine.*"]
  this --> engine

API

command.register(get_pos_fn, set_pos_fn, speed)

Syntax: command.register(get_pos_fn: fun() -> {x: number, y: number}, set_pos_fn: fun(x: number, y: number), speed: number) -> handle

Example:

local handle = command.register(
    function() return { x = unit.x, y = unit.y } end,
    function(nx, ny) unit.x = nx; unit.y = ny end,
    100   -- px/s
)

Description: Registers a movable unit. Caller supplies read-callback (returns {x, y}) + write-callback (applies new pos) + speed in pixels per second. Returns an opaque handle used for all subsequent calls.

command.unregister(handle)

Syntax: command.unregister(handle: handle) -> void

Description: Removes a unit from the registry. No-op if the handle is unknown. Cancels any active command on that handle.

command.count_registered()

Syntax: command.count_registered() -> number

Description: Returns the count of currently registered units. Debug-friendly.

command.set_speed(handle, n)

Syntax: command.set_speed(handle: handle, n: number) -> void

Description: Updates a unit's move-speed (px/s). Takes effect on the next update(dt) tick.

command.speed(handle)

Syntax: command.speed(handle: handle) -> number

Description: Returns current speed for the handle.

command.move_to(handles, target_x, target_y)

Syntax: command.move_to(handles: handle[], target_x: number, target_y: number) -> void

Example:

command.move_to({ h1, h2, h3 }, 512, 384)

Description: Programmatic move-issue for a batch of handles. All listed units start moving toward (target_x, target_y) (world-coords). Replaces any active command per handle.

command.cancel(handle)

Syntax: command.cancel(handle: handle) -> void

Description: Cancels the active command for one handle. No-op if no command is active.

command.cancel_all()

Syntax: command.cancel_all() -> void

Description: Cancels active commands for all registered handles.

command.current(handle)

Syntax: command.current(handle: handle) -> {type: string, target_x: number, target_y: number} | nil

Example:

local cmd = command.current(h)
if cmd then print(cmd.type, cmd.target_x, cmd.target_y) end

Description: Returns the active command for a handle, or nil if idle. v0.1.0 always has type == "move".

command.is_moving(handle)

Syntax: command.is_moving(handle: handle) -> bool

Description: Convenience predicate. Equivalent to command.current(h) ~= nil.

command.bind_move_action(action_name)

Syntax: command.bind_move_action(action_name: string) -> void

Example:

input.bind("rmb", { "mouse_right" })
command.bind_move_action("rmb")

Description: Binds an input-action whose press-edge issues a move-command to all targets returned by the registered target-provider. Cursor world-coord is computed via lib-core.camera.screen_to_world.

command.bind_target_provider(fn)

Syntax: command.bind_target_provider(fn: fun() -> handle[]) -> void

Example:

local selection = require("lib-core.selection")
command.bind_target_provider(function() return selection.list() end)

Description: Registers a callback that returns the current target-handle-list whenever the move-action fires. Typical wiring: forward lib-core.selection.list().

command.set_arrive_threshold(n)

Syntax: command.set_arrive_threshold(n: number) -> void

Description: Sets the arrival-distance in pixels. Once a unit is within n px of its target, the command completes (snap-to-target).

command.arrive_threshold()

Syntax: command.arrive_threshold() -> number

Description: Returns the current arrive-threshold.

command.set_enabled(b)

Syntax: command.set_enabled(b: bool) -> void

Description: Master enable/disable. When disabled, update(dt) is a no-op and the bound action is ignored.

command.enabled()

Syntax: command.enabled() -> bool

Description: Returns master-enabled state.

command.update(dt)

Syntax: command.update(dt: number) -> void

Example:

function update(ctx, dt)
    command.update(dt)
end

Description: Per-frame execution: for each active command, computes direction-vector + normalized step, applies set_pos_fn(...). When step >= remaining distance, snaps to target and clears the command.

Conventions

  • World-coords + pixel-units throughout (per ADR-0031).
  • Move-only in v0.1.0; context-sensitive dispatch (attack/use/etc.) deferred.
  • Issuing a new move on an active handle replaces the old target (no queueing).
  • register / unregister are O(1) amortized; handles are opaque integers.

Consumer pattern

local input     = require("lib-core.input")
local selection = require("lib-core.selection")
local command   = require("lib-core.command")

input.bind("rmb", { "mouse_right" })
command.bind_move_action("rmb")
command.bind_target_provider(function() return selection.list() end)

local handle = command.register(
    function() return { x = unit.x, y = unit.y } end,
    function(nx, ny) unit.x = nx; unit.y = ny end,
    100
)

function update(ctx, dt)
    command.update(dt)
end

CHANGELOG

v0.1.0 (P.3.7)

  • Initial release: move-only commands + handle-registry + auto-wire (action + target-provider) + per-frame execution.

References

  • Spec v0.1.0 (P.3.7): meta/docs/superpowers/specs/2026-05-14-p3-7-lib-command-design.md
  • ADR-0001 (engine knows verbs, libs bring nouns)
  • ADR-0031 (pixel-convention: Y-down-positive)
  • ADR-0038 (API-Doc-Convention)
Description
P.3.7 lib-core.command v0.1.0 � Move-Commands + Per-Frame-Execution
Readme 33 KiB
Languages
Lua 94.2%
Shell 5.8%