create-siltrun 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +54 -0
- package/package.json +8 -4
- package/templates/mass-grid/AGENTS.md +1 -1
- package/templates/mass-grid/skills/genre-lane-mapping.md +1 -1
- package/templates/turn-based-grid/room.ts +1 -1
- package/templates/turn-based-grid/src/brains.ts +1 -1
- package/templates/turn-based-grid/src/stubAgent.ts +1 -1
- package/templates/turn-based-grid/src/substrate/map.ts +1 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Joel Brubaker
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# create-siltrun
|
|
2
|
+
|
|
3
|
+
Scaffold a [Silt](https://silt.run) multiplayer project: an authoritative room
|
|
4
|
+
contract and a client, in one directory, wired together and ready to run.
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
npm create siltrun@latest my-game
|
|
8
|
+
cd my-game
|
|
9
|
+
npm install
|
|
10
|
+
npm run dev
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
`npm run dev` boots both halves at once. Your room runs through the `siltrun` CLI,
|
|
14
|
+
which serves room info on <http://localhost:4000>, and the Vite client runs on
|
|
15
|
+
<http://localhost:5173>. Open the client in two windows and you have a multiplayer
|
|
16
|
+
room. Edit `room.ts` and both sides reload.
|
|
17
|
+
|
|
18
|
+
The project directory is required. Running the command with no directory prints
|
|
19
|
+
usage and exits.
|
|
20
|
+
|
|
21
|
+
## Templates
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm create siltrun@latest my-game -- --template tower-defense
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
| Template | What you get |
|
|
28
|
+
|---|---|
|
|
29
|
+
| `minimal` | The default. The smallest real room: each player moves a ship by tapping a target, the server clamps that intent and eases the ship toward it, and every client renders the same authoritative state. |
|
|
30
|
+
| `tower-defense` | Co-op tower defense. Two players share one always-warm room, ready up, and defend a path against waves together. |
|
|
31
|
+
| `mass-grid` | Territory capture in the Paper.io style. Leave your land to draw a trail, loop back to claim what you enclosed, cut a rival by crossing their trail. |
|
|
32
|
+
| `turn-based-grid` | A starter for agent-first games: a deterministic world that agents play and humans watch, with an action API, an ASCII view alongside the graphics view, an emote channel, and scripted stub agents to prove it. |
|
|
33
|
+
|
|
34
|
+
An unknown template name fails immediately and lists the ones that exist.
|
|
35
|
+
|
|
36
|
+
## What you get
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
my-game/
|
|
40
|
+
room.ts your contract: tick(state, inputs), runs server-side at 60Hz
|
|
41
|
+
src/ the client, built on @siltrun/react and @siltrun/stage
|
|
42
|
+
package.json a dev script that runs the room and Vite together
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
`room.ts` is the whole server. It default-exports a `tick(state, inputs)` function
|
|
46
|
+
that runs 60 times a second and owns the truth. Clients send intent; the tick
|
|
47
|
+
decides what actually happens.
|
|
48
|
+
|
|
49
|
+
This is a plain Node initializer with no dependencies of its own, so it runs
|
|
50
|
+
anywhere `npm create` does.
|
|
51
|
+
|
|
52
|
+
## Docs
|
|
53
|
+
|
|
54
|
+
Full guides and API reference: <https://silt.run/docs/>
|
package/package.json
CHANGED
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-siltrun",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"license": "MIT",
|
|
4
5
|
"description": "Scaffold a Silt multiplayer project — `npm create siltrun my-game`.",
|
|
5
6
|
"type": "module",
|
|
6
7
|
"bin": {
|
|
7
8
|
"create-siltrun": "index.mjs"
|
|
8
9
|
},
|
|
9
|
-
"files": [
|
|
10
|
-
|
|
10
|
+
"files": [
|
|
11
|
+
"index.mjs",
|
|
12
|
+
"templates"
|
|
13
|
+
],
|
|
11
14
|
"engines": {
|
|
12
15
|
"node": ">=18"
|
|
13
16
|
},
|
|
14
17
|
"scripts": {
|
|
15
18
|
"test": "node --test",
|
|
16
19
|
"typecheck": "true"
|
|
17
|
-
}
|
|
20
|
+
},
|
|
21
|
+
"homepage": "https://silt.run"
|
|
18
22
|
}
|
|
@@ -50,7 +50,7 @@ server sends and send intent back. This is why cheating is hard: a client asking
|
|
|
50
50
|
understand before you touch `State`.** → `skills/compact-snapshots.md`.
|
|
51
51
|
- **The genre picks the lane.** Moves ride the *reliable* lane, not the presence datagram lane,
|
|
52
52
|
because a slow discrete grid game wants ordered, no-drop turns (a dropped turn is a death).
|
|
53
|
-
**
|
|
53
|
+
**Amendment: a room that opts into client-side prediction moves its
|
|
54
54
|
steering to the INPUT lane as held intent** — only input-envelope seqs are acked, so only
|
|
55
55
|
they can reconcile. → `skills/genre-lane-mapping.md` (incl. the prediction amendment).
|
|
56
56
|
|
|
@@ -55,7 +55,7 @@ ack map would be pure dead weight on a datagram budget this genre already pushes
|
|
|
55
55
|
empty and is dropped from the wire entirely. The lane choice that is *correct for the genre* is
|
|
56
56
|
also the one that *reclaims budget*. That is not a coincidence you should fight.
|
|
57
57
|
|
|
58
|
-
## The prediction amendment
|
|
58
|
+
## The prediction amendment
|
|
59
59
|
|
|
60
60
|
The rule above has one ratified exception: **a room that opts into client-side prediction
|
|
61
61
|
puts its steering on the INPUT (datagram) lane — even discrete steering.** Prediction's
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// intent on the reliable lane; this tick() decides what actually happens; every peer
|
|
4
4
|
// (playing agents + spectating humans) receives the resulting State each tick.
|
|
5
5
|
//
|
|
6
|
-
// THE TICK / BEAT MODEL (
|
|
6
|
+
// THE TICK / BEAT MODEL (the load-bearing decision) ─────────────────────────
|
|
7
7
|
//
|
|
8
8
|
// • The relay clock is a constant 60Hz and never pauses while ≥1 peer is present.
|
|
9
9
|
// We do NOT fight it. On top of it we quantize turns into BEATS of BEAT_TICKS ticks.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// brains.ts — scripted stub agents. Each brain is a pure decision function over the
|
|
2
2
|
// AGENT PERCEPTION (the rendered ASCII string) — it never sees State. That constraint
|
|
3
3
|
// is the whole point: if these can play from text alone, the substrate is sufficient,
|
|
4
|
-
// and the same brain lifts behind a real MCP agent later
|
|
4
|
+
// and the same brain lifts behind a real MCP agent later unchanged.
|
|
5
5
|
//
|
|
6
6
|
// The four brains double as the substrate's live demonstrators:
|
|
7
7
|
// greedy — competent play (walks to the nearest pellet)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// stubAgent.ts — a scripted agent as a REAL Silt client. It opens its own joinRoom
|
|
2
2
|
// connection (exactly like the drift diag two-connection pattern), so from the room's
|
|
3
3
|
// point of view it is indistinguishable from any other peer — and from a real MCP-driven
|
|
4
|
-
// agent later
|
|
4
|
+
// agent later. The only difference is the brain: scripted here, an LLM there.
|
|
5
5
|
//
|
|
6
6
|
// The read→think→act loop is deliberately faithful to real agent latency:
|
|
7
7
|
// 1. snapshot the latest received State,
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import type { Dir, Pos } from "./types.ts";
|
|
8
8
|
|
|
9
|
-
// ── The tick / beat model constants (the load-bearing design
|
|
9
|
+
// ── The tick / beat model constants (the load-bearing design) ──
|
|
10
10
|
//
|
|
11
11
|
// The relay's world clock runs at a fixed 60 ticks/sec and never pauses while ≥1 peer
|
|
12
12
|
// is present. On top of that constant clock we quantize turns into BEATS.
|