@velo/battlefield (0.1.0)

Published 2026-10-15 19:17:10 +02:00 by r59q

Installation

@velo:registry=
npm install @velo/battlefield@0.1.0
"@velo/battlefield": "0.1.0"

About this package

@velo/battlefield

Game-neutral input and buffered authoritative movement, with no runtime dependencies. This ESM package publishes JavaScript, declarations and source maps from dist/. Node 22 or later is supported; input helpers run in a browser with DOM and pointer-lock support.

Install and imports

Configure the public Forgejo registry in the consuming project's .npmrc:

@velo:registry=https://git.amhk.dk/api/packages/velo/npm/

Install @velo/battlefield with npm and commit the consumer's lockfile. Import from the single public entry point; source files and deep imports are not part of the package contract:

import {
  UnitMotion,
  LockedCursor,
  bindMinimapInput,
  edgeDirection,
  CAMERA_NAVIGATION,
  clamp,
  type Point,
  type MovingEntity,
  type UnitPose,
} from '@velo/battlefield';

Units and lifecycle

  • Point is { x, z } in battlefield metres. MovingEntity adds numeric id and facing; UnitPose adds facing, in radians.
  • UnitMotion(bufferSeconds = 0.1) receives authoritative entities with receive(entities, serverSeconds, receivedMs, playing). Server time and the buffer use seconds; receive/frame clocks use monotonic milliseconds from the same clock. Call prepareFrame(nowMs) once per animation frame, then pose(id) for interpolation. It takes the shortest facing arc, rejects older playing snapshots, removes missing entities from retained history and never extrapolates past the latest snapshot. Use a buffer at least as long as sparse sample intervals. reset() clears history when switching battles; playing = false also resets it. It owns no listeners or animation loop.
  • bindMinimapInput(canvas, actions, signal) converts canvas pixels into map metres using actions.mapSize(). Left drag moves the camera; right press issues an order or cancels building placement. The caller owns the AbortController: abort on teardown to remove canvas/window listeners, release drag capture and clear drag styling. Supply a live signal when binding.
  • LockedCursor(canvas, hooks) creates a .locked-game-cursor marker and installs document/window listeners. Hooks receive cursor screen pixels, battlefield hover state, lock changes and errors. Call toggle() from user activation; release() exits lock. Call dispose() on teardown to release lock, remove listeners and remove the marker, including late pointer-lock acquisition. The consumer supplies marker styling and owns its canvas.
  • edgeDirection(positionPixels, extentPixels) returns signed edge-scroll strength. CAMERA_NAVIGATION documents its configuration through named pixel, viewport-per-second and second fields. clamp(value, minimum, maximum) bounds a number.

Package development

Run from this directory, independently of either game:

npm ci
npm run typecheck
npx tsx --test test/capabilities.test.mjs
npm run check:consumer
npm run build

npm test is the package-local source-test command. check:consumer compiles with the local TypeScript compiler, packs the artifact, installs it and TypeScript in a temporary project outside the repository, then type-checks and imports all public exports. It checks tarball contents and removes the fixture afterwards. No source aliases or sibling files are used by that consumer. The build writes only ignored dist/ output. npm pack includes dist/, this README and npm's required manifest; build before manually packing.

For optional unpublished integration testing, build here, then run npm install --no-save ../../packages/battlefield from a game directory (or use npm link). Keep registry dependencies and lockfiles committed; local links are temporary. Any game source alias must be explicitly opt-in and must stay disabled in CI and container builds.

Publication

.forgejo/workflows/publish-battlefield.yml checks, builds and publishes when main changes packages/battlefield/**, or on manual dispatch. It uses PACKAGE_REGISTRY_TOKEN to publish to https://git.amhk.dk/api/packages/velo/npm/. There are no inter-package dependencies to publish first. The workflow chooses the next available 0.x.0 release above the registry's matching versions; the committed version is the initial floor, not a fixed release version. Consumers update their version range and lockfile deliberately: ^0.N.0 accepts only 0.N.x.

Dependencies

Development dependencies

ID Version
jsdom ^26.1.0
tsx ^4.23.15
typescript ^5.9.3
Details
npm
2026-10-15 19:17:10 +02:00
956
UNLICENSED
latest
12 KiB
Assets (1)
Versions (1) View all
0.1.0 2026-10-15