Move docs/ package mirror into document-navigator plugin
Relocate the ~6k-file docs tree from the repo root into plugins/document-navigator/docs/ so the plugin is self-contained and portable. docs/superpowers/ (specs and plans) stays at the repo root. Moved via cp+rm rather than git mv because directory rename() fails with EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the identical-content files at commit time. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
# Pre-tuned Game Schemas
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## Purpose
|
||||
|
||||
A curated set of `BitPackerSchema` constants tuned for common game-state shapes — player position, rotation, stats, optional metadata, world updates, player input — plus the `createDeltaSchema` factory that mirrors any of those into its delta form. Constants here are the right choice when a game's data model fits the upstream conventions (1024 m bounded world, 0.01 m precision, 180° rotation, 0–100 health). Games with unusual ranges should use the `createGameSchema` factory in the `schema-factory` module instead.
|
||||
|
||||
The schemas are designed to compose: `PLAYER_STATE_SCHEMA` references `PLAYER_POSITION_SCHEMA`, `PLAYER_ROTATION_SCHEMA`, `PLAYER_STATS_SCHEMA`, and the optional bundle. `WORLD_UPDATE_SCHEMA` references the player schema array. Replacing one constant in a downstream consumer cascades automatically to the consumers of the composed schemas.
|
||||
|
||||
## Features
|
||||
|
||||
- `PLAYER_POSITION_SCHEMA` — fixed-point `{ x, y, z }` with 0.01 precision and ±1024 m / ±128 m ranges
|
||||
- `PLAYER_ROTATION_SCHEMA` — fixed-point `{ yaw, pitch }`, ±180° / ±90° respectively
|
||||
- `PLAYER_STATS_SCHEMA` — `{ health, shield, speed, isMoving, isSprinting }` tuned for a typical FPS
|
||||
- `PLAYER_OPTIONAL_SCHEMA` — animation name + effect-id array, both optional
|
||||
- `PLAYER_STATE_SCHEMA` — composes all of the above into one player snapshot
|
||||
- `WORLD_UPDATE_SCHEMA` — variable-length array of player states + a 16-bit tick
|
||||
- `PLAYER_INPUT_SCHEMA` — analog move + rotate axes + action-id array
|
||||
- `createDeltaSchema(base)` — wraps any base schema in a delta envelope (changed-mask + per-field optional)
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { GameBitPacker, PLAYER_STATE_SCHEMA } from "@suaveplan/bitpacker-game";
|
||||
|
||||
const bp = new GameBitPacker(PLAYER_STATE_SCHEMA);
|
||||
const bytes = bp.pack({
|
||||
position: { x: 100, y: 0, z: 50 },
|
||||
rotation: { yaw: 90, pitch: 0 },
|
||||
stats: { health: 95, shield: 50, speed: 5, isMoving: true, isSprinting: false },
|
||||
});
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import {
|
||||
GameBitPacker,
|
||||
PLAYER_INPUT_SCHEMA,
|
||||
WORLD_UPDATE_SCHEMA,
|
||||
createDeltaSchema,
|
||||
PLAYER_STATE_SCHEMA,
|
||||
} from "@suaveplan/bitpacker-game";
|
||||
|
||||
// Server emits world snapshots every tick:
|
||||
const worldBP = new GameBitPacker(WORLD_UPDATE_SCHEMA);
|
||||
|
||||
// Client emits inputs at frame rate:
|
||||
const inputBP = new GameBitPacker(PLAYER_INPUT_SCHEMA);
|
||||
|
||||
// Server transmits deltas instead of full snapshots:
|
||||
const playerDeltaSchema = createDeltaSchema(PLAYER_STATE_SCHEMA);
|
||||
const deltaBP = new GameBitPacker(playerDeltaSchema);
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `PLAYER_POSITION_SCHEMA: PositionSchema`
|
||||
|
||||
`{ x: "-1024.2", y: "-1024.2", z: "-128.2" }` — signed fixed-point with 0.01 precision. The `-` prefix marks the field as signed.
|
||||
|
||||
### `PLAYER_ROTATION_SCHEMA: RotationSchema`
|
||||
|
||||
`{ yaw: "-180.1", pitch: "-90.1" }` — signed fixed-point with 0.1 precision.
|
||||
|
||||
### `PLAYER_STATS_SCHEMA: PlayerStatsSchema`
|
||||
|
||||
`{ health: 100, shield: 100, speed: "8.2", isMoving: true, isSprinting: true }` — uint, uint, fixed-point, bool, bool.
|
||||
|
||||
### `PLAYER_OPTIONAL_SCHEMA: PlayerOptionalSchema`
|
||||
|
||||
Optional `{ animation, effects }` bundle. Animation is a variable-length string; effects is a variable-length array of compact ids.
|
||||
|
||||
### `PLAYER_STATE_SCHEMA: PlayerStateSchema`
|
||||
|
||||
Composes `position`, `rotation`, `stats`, `optional`. The canonical shape every game subsystem reads from.
|
||||
|
||||
### `WORLD_UPDATE_SCHEMA: WorldUpdateSchema`
|
||||
|
||||
`{ tick: 65535, players: [PLAYER_STATE_SCHEMA] }` — one tick + a variable-length array of player states.
|
||||
|
||||
### `PLAYER_INPUT_SCHEMA: PlayerInputSchema`
|
||||
|
||||
`{ moveX, moveY, rotateYaw, rotatePitch, actions }` — four signed fixed-point axes plus an action-id array.
|
||||
|
||||
### `createDeltaSchema<T>(base: T): DeltaSchema<T>`
|
||||
|
||||
Returns a schema that wraps `base` with a per-field changed-mask and optional fields. The wrapped schema is appropriate for incremental updates where most fields stay the same frame-to-frame.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- **Bit-widths are tuned for typical FPS games.** ±1024 m world with 0.01 m precision uses ~17 bits per axis after sign + integer + fractional. Smaller worlds save bits per field; the consumer should switch to `createGameSchema` if the defaults are wasteful.
|
||||
- **`isMoving` + `isSprinting` are independent.** The schema models them as two booleans because a player can be sprinting while not moving (e.g. holding sprint while stuck against a wall) — collapsing to a single tri-state would lose that distinction.
|
||||
- **`createDeltaSchema` is a factory, not a const.** It returns a fresh schema every call so the consumer can apply additional transformations (e.g. swapping in a custom `_optional` strategy) without mutating shared state.
|
||||
- **No timestamps in the player schema.** Timing is owned by the `tick` field on `WORLD_UPDATE_SCHEMA`. Consumers that want per-player timestamps must add a `_optional` field at their own layer.
|
||||
Reference in New Issue
Block a user