@netforge/tabletop 0.1.0 → 0.2.0
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/README.md +53 -5
- package/package.json +24 -9
- package/src/boot.ts +1 -1
package/README.md
CHANGED
|
@@ -1,7 +1,55 @@
|
|
|
1
1
|
# @netforge/tabletop
|
|
2
2
|
|
|
3
|
-
The client kit the board-style
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
The shared client kit for the Net Forge board-style game templates (tower defense, idle, card battler and monster collector): the room connection and input clock for rules genres, the styled 3D stage, the store, stake and gear wiring, and the HUD shell.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm install @netforge/tabletop
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Node 20 or later. The package ships TypeScript source (ES modules) for a bundler such as Vite. It is used by template clients (`@netforge/template-tower`, `template-idle`, `template-cards`, `template-collector`). Game code in `src/game.ts` never imports it.
|
|
12
|
+
|
|
13
|
+
## Example
|
|
14
|
+
|
|
15
|
+
A board template's client boots with one call. This is the shape the tower defense client uses:
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { bootBoard } from "@netforge/tabletop";
|
|
19
|
+
import { GAME_VERSION, PLACE, TEMPLATE, towerAdapter, towerManifest } from "@netforge/template-tower";
|
|
20
|
+
|
|
21
|
+
const app = await bootBoard({
|
|
22
|
+
adapter: towerAdapter(),
|
|
23
|
+
manifest: towerManifest(),
|
|
24
|
+
template: TEMPLATE,
|
|
25
|
+
place: PLACE,
|
|
26
|
+
version: GAME_VERSION,
|
|
27
|
+
labels: { title: "COGSPIRE", rules: {}, skus: {}, upgrades: {}, loading: "Winding the spire", help: "Click a tile to build" },
|
|
28
|
+
theme, // HudTheme: accent, gold, ink, dim, panel, bg, font, display, radius
|
|
29
|
+
coin: { name: "Cog", symbol: "COG", logo: null },
|
|
30
|
+
cosmetics: {},
|
|
31
|
+
swatch: () => "#c9a15a",
|
|
32
|
+
ground: { w: 20, h: 12 },
|
|
33
|
+
// plus the template's own draw, input and autopilot hooks (see BoardBootOptions)
|
|
34
|
+
});
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Key API
|
|
38
|
+
|
|
39
|
+
- `bootBoard(options)`: connects to the room, builds the stage and the HUD, and wires the store, stake and gear for a rules genre.
|
|
40
|
+
- `joinBoard(adapter, join)` and `InputClock`: the room connection and the input clock for rules genres; `roomsEndpoint(params)` picks the room server from the page URL.
|
|
41
|
+
- `BoardStage` and `fallbackShape`: the styled 3D stage and placeholder shapes.
|
|
42
|
+
- `Hud`, `wireStore`, `$` and `cssColor`: the HUD shell and store panel.
|
|
43
|
+
- `wireStake`, `wireGear`, `gearOf` and `wirePot`: the buy-in run, losable gear and pots.
|
|
44
|
+
- `mockKit`: the in-page store backend used for local play.
|
|
45
|
+
- `hostFlags`, `namedPlayer`, `onHostPlayer`, `postReady`, `storeNote`: how a page talks to the Net Forge studio or to kit play when it is embedded.
|
|
46
|
+
|
|
47
|
+
To run a board game locally, use `@netforge/kit-play`.
|
|
48
|
+
|
|
49
|
+
## Docs
|
|
50
|
+
|
|
51
|
+
- https://forge.netnet.capital/docs/packages/tabletop
|
|
52
|
+
|
|
53
|
+
## License
|
|
54
|
+
|
|
55
|
+
MIT. See `LICENSE` and `NOTICE`.
|
package/package.json
CHANGED
|
@@ -1,11 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@netforge/tabletop",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Shared client kit for Net Forge board-style game templates (tower defense, idle, card battler, monster collector): room connection, input clock, 3D stage, store and HUD.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"game-engine",
|
|
7
|
+
"multiplayer",
|
|
8
|
+
"browser-game",
|
|
9
|
+
"threejs",
|
|
10
|
+
"tower-defense",
|
|
11
|
+
"card-game",
|
|
12
|
+
"idle-game",
|
|
13
|
+
"monster-collector",
|
|
14
|
+
"typescript",
|
|
15
|
+
"gamedev",
|
|
16
|
+
"net-forge"
|
|
17
|
+
],
|
|
5
18
|
"license": "MIT",
|
|
6
19
|
"type": "module",
|
|
7
20
|
"exports": {
|
|
8
|
-
".": "./src/index.ts"
|
|
21
|
+
".": "./src/index.ts",
|
|
22
|
+
"./package.json": "./package.json"
|
|
9
23
|
},
|
|
10
24
|
"files": [
|
|
11
25
|
"src",
|
|
@@ -14,22 +28,26 @@
|
|
|
14
28
|
"NOTICE",
|
|
15
29
|
"LICENSE"
|
|
16
30
|
],
|
|
31
|
+
"sideEffects": false,
|
|
17
32
|
"publishConfig": {
|
|
18
33
|
"access": "public"
|
|
19
34
|
},
|
|
35
|
+
"homepage": "https://forge.netnet.capital/docs/packages/tabletop",
|
|
36
|
+
"bugs": {
|
|
37
|
+
"url": "https://github.com/netnetdev/net-forge/issues"
|
|
38
|
+
},
|
|
20
39
|
"repository": {
|
|
21
40
|
"type": "git",
|
|
22
41
|
"url": "git+https://github.com/netnetdev/net-forge.git",
|
|
23
42
|
"directory": "packages/tabletop"
|
|
24
43
|
},
|
|
25
|
-
"homepage": "https://github.com/netnetdev/net-forge/tree/main/packages/tabletop#readme",
|
|
26
44
|
"engines": {
|
|
27
45
|
"node": ">=20"
|
|
28
46
|
},
|
|
29
47
|
"dependencies": {
|
|
30
48
|
"three": "0.186.1",
|
|
31
|
-
"@netforge/asset-library": "0.
|
|
32
|
-
"@netforge/engine": "0.
|
|
49
|
+
"@netforge/asset-library": "0.2.0",
|
|
50
|
+
"@netforge/engine": "0.2.0"
|
|
33
51
|
},
|
|
34
52
|
"devDependencies": {
|
|
35
53
|
"@types/node": "22.20.1",
|
|
@@ -37,9 +55,6 @@
|
|
|
37
55
|
"typescript": "5.8.3",
|
|
38
56
|
"vitest": "3.2.7"
|
|
39
57
|
},
|
|
40
|
-
"bugs": {
|
|
41
|
-
"url": "https://github.com/netnetdev/net-forge/issues"
|
|
42
|
-
},
|
|
43
58
|
"scripts": {
|
|
44
59
|
"typecheck": "tsc -p tsconfig.json",
|
|
45
60
|
"test": "vitest run --passWithNoTests"
|
package/src/boot.ts
CHANGED
|
@@ -167,7 +167,7 @@ export async function bootBoard<S>(o: BoardBootOptions<S>): Promise<BoardApp<S>>
|
|
|
167
167
|
if (friendRoomId && conn.roomId !== friendRoomId) setTimeout(() => hud.toast("Room full, new room"), 500);
|
|
168
168
|
if (conn.welcome.version !== o.version) setTimeout(() => hud.toast("Update ready. Reload."), 800);
|
|
169
169
|
const autopilot = params.get("autopilot") === "1";
|
|
170
|
-
const linkFor = (base: string) => `${base}?room=${conn.roomId}${place !== o.place ? `&place=${encodeURIComponent(place)}` : ""}${params.has("server") ? `&server=${encodeURIComponent(endpoint)}` : ""}`;
|
|
170
|
+
const linkFor = (base: string) => `${base}?room=${conn.roomId}${place !== o.place ? `&place=${encodeURIComponent(place)}` : ""}${params.has("server") ? `&server=${encodeURIComponent(endpoint)}` : ""}${params.has("game") ? `&game=${encodeURIComponent(params.get("game") ?? "")}` : ""}`;
|
|
171
171
|
const keep = ["autopilot", "webgl", "stats", "style", "preview", "shapes", "host", "coin", "title", "player", "library"].filter((k) => params.has(k)).map((k) => `&${k}=${encodeURIComponent(params.get(k) ?? "")}`).join("");
|
|
172
172
|
history.replaceState(null, "", `${linkFor(location.pathname)}${keep}`);
|
|
173
173
|
|