@netforge/template-tower 0.0.0-stage → 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/AGENTS.md +66 -0
- package/CLAUDE.md +11 -0
- package/LICENSE +21 -0
- package/NOTICE +28 -0
- package/README.md +80 -2
- package/client/decor.ts +11 -0
- package/client/index.html +11 -0
- package/client/main.ts +746 -0
- package/client/names.ts +50 -0
- package/llms-full.txt +292 -0
- package/llms.txt +129 -0
- package/package.json +79 -3
- package/src/game.ts +148 -0
- package/src/manifest.ts +44 -0
- package/src/store.ts +25 -0
package/AGENTS.md
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Extending COGSPIRE
|
|
2
|
+
|
|
3
|
+
COGSPIRE is the tower defense template of the Net Forge game engine. This file tells a coding agent how to change the game safely. `llms.txt` in this package has the full recipe book for this genre, and `llms-full.txt` adds the whole `src/game.ts` as a worked example.
|
|
4
|
+
|
|
5
|
+
## The one file to edit
|
|
6
|
+
|
|
7
|
+
Change the game by editing `src/game.ts` only. It holds declarations, not engine code. src/names.json holds the title and every label players read. Towers go in "weapons" ({ name, line }), creeps in "enemies", plus upgrades, earn rules and store items. Everything else (the client, the manifest, the store hooks, the simulation, the netcode) is template machinery.
|
|
8
|
+
|
|
9
|
+
## Import only @netforge/engine
|
|
10
|
+
|
|
11
|
+
`src/game.ts` imports from `@netforge/engine` and nothing else. The template's game imports:
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { earn, game, prefab, store, tower, towerBoard, upgrade, waves } from "@netforge/engine";
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Also available for this genre: `economy`. `earn` has `earn.rule(...)` and `earn.stake(...)`; `store` has `store.sku(...)`. `system(id, ctx => ...)` gets the systems API described in `llms.txt`. The renderer, input, netcode and physics live elsewhere and are not reachable from game code.
|
|
18
|
+
|
|
19
|
+
## Rules the build enforces
|
|
20
|
+
|
|
21
|
+
- Ids are lower_snake_case.
|
|
22
|
+
- Every game declares at least one `earn.rule(...)` (mandatory earn) and one `earn.stake(...)` (the buy-in run), on one top-level line. A game without either does not build.
|
|
23
|
+
- Asset ids are library ids such as `style.lowpoly.turret`, never URLs or file paths, and must exist in the asset library.
|
|
24
|
+
- `game({ template: "tower-defense", style, places, players: { prefab, max } })` with `players.max` at most 4.
|
|
25
|
+
- Exactly one `towerBoard(...)` and one `waves(...)`; 1 to 8 `tower(...)`s.
|
|
26
|
+
- The road is tile waypoints in `towerBoard({ path })`: each step changes x or y, never both, and it starts and ends on the board's edge. `blocked` tiles are rocks nobody builds on.
|
|
27
|
+
- Every waves group names a declared creep prefab, not a pickup.
|
|
28
|
+
- Tower kinds are "bolt", "splash", "frost" or "chain". Upgrades read four stats only: might, haste, area and maxHealth.
|
|
29
|
+
- No `weapon(...)`: a tower defense game declares `tower(...)`.
|
|
30
|
+
- `game({ style })` is the art style the creator picked (lowpoly, toon, ps1, pixel, voxel or handdrawn). Keep it.
|
|
31
|
+
- Keep the store SKUs the client is wired to, at their prices: overclock, tempered_brass, spyglass, spare_bell, skin_verdigris, skin_gilt and the brass_gear gear. "stake" is reserved and is never a SKU id.
|
|
32
|
+
|
|
33
|
+
## Validate
|
|
34
|
+
|
|
35
|
+
- With the MCP server (`npx -y @netforge/mcp`, bin `netforge-mcp`): call `netforge_validate_game` on the game. It returns one line per problem.
|
|
36
|
+
- In this package: `npx vitest run` runs `test/harness.test.ts`, `test/store.test.ts`. A bad declaration throws `GameDefinitionError` with a line you can act on.
|
|
37
|
+
|
|
38
|
+
## Playtest
|
|
39
|
+
|
|
40
|
+
- With the MCP server: call `netforge_run_playtest`.
|
|
41
|
+
- In code: `import { engine } from "@netforge/engine"` and run `engine.test.run({ ticks: 30 * 240, bots: 4 })`. It reports kills, wave reached, runs won and lost, leaks (as deaths), earned by rule, softlock, ms per tick, and the genre's own checks under rules.checks.
|
|
42
|
+
|
|
43
|
+
## Play locally
|
|
44
|
+
|
|
45
|
+
```sh
|
|
46
|
+
mkdir -p my-game/src && cd my-game
|
|
47
|
+
npm init -y && npm install @netforge/kit-play @netforge/engine @netforge/template-tower
|
|
48
|
+
cp node_modules/@netforge/template-tower/src/game.ts src/
|
|
49
|
+
echo '{"template":"tower-defense"}' > netnet.json
|
|
50
|
+
npx kit-play # opens http://127.0.0.1:4663
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The MCP tool `netforge_play_locally` does the same. Coins are play money; nothing pays out and no chain or wallet is involved. Edit `src/game.ts` and run it again to try a change.
|
|
54
|
+
|
|
55
|
+
## What not to do
|
|
56
|
+
|
|
57
|
+
- Do not write renderers, netcode, physics or bot AI. The template already has them.
|
|
58
|
+
- Do not use asset URLs or file paths. Use library ids.
|
|
59
|
+
- Do not import anything other than `@netforge/engine` in `src/game.ts`.
|
|
60
|
+
- Do not edit `client/`, `src/manifest.ts` or `src/store.ts`.
|
|
61
|
+
- Do not rename or reprice the store SKUs the client is wired to.
|
|
62
|
+
- Do not write targeting or pathing code; towers and creeps are declared and the rules module runs them.
|
|
63
|
+
|
|
64
|
+
## Docs
|
|
65
|
+
|
|
66
|
+
https://forge.netnet.capital/docs/templates/tower
|
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
Read AGENTS.md before changing this game.
|
|
4
|
+
|
|
5
|
+
The five hard rules:
|
|
6
|
+
|
|
7
|
+
1. Edit only `src/game.ts`.
|
|
8
|
+
2. Import only `@netforge/engine`.
|
|
9
|
+
3. Ids are lower_snake_case.
|
|
10
|
+
4. Declare at least one `earn.rule(...)` and exactly one `earn.stake(...)`.
|
|
11
|
+
5. No renderers, netcode, physics or asset URLs.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 NetNet Capital Management
|
|
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/NOTICE
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
@netforge/template-tower (COGSPIRE)
|
|
2
|
+
Copyright (c) 2026 NetNet Capital Management
|
|
3
|
+
|
|
4
|
+
An original game. No names, characters, maps, models, sounds or code from
|
|
5
|
+
any other game or franchise.
|
|
6
|
+
|
|
7
|
+
Art and sound
|
|
8
|
+
- Models come from the per-style asset library
|
|
9
|
+
(@netforge/asset-library): CC0 1.0 models by Kenney and
|
|
10
|
+
Quaternius (Space Kit turrets, Nature Kit, monsters, robots), each pack listed with its
|
|
11
|
+
source URL and licence verification in that package's NOTICE and
|
|
12
|
+
manifest/packs.json. The files are fetched and built, never committed
|
|
13
|
+
here; the build copies only the models this game uses.
|
|
14
|
+
- Fallback shapes (@netforge/tabletop stage.ts) are generated from three.js
|
|
15
|
+
primitives; all textures are drawn on a canvas at load; sounds are the
|
|
16
|
+
library's CC0 samples with WebAudio synth fallbacks.
|
|
17
|
+
|
|
18
|
+
Dependencies (unmodified, via npm)
|
|
19
|
+
- three.js 0.186.1 (https://github.com/mrdoob/three.js), MIT.
|
|
20
|
+
- @netforge/engine and @netforge/engine-sim (this repository);
|
|
21
|
+
see their NOTICE files (bitECS MPL-2.0, Rapier Apache-2.0, Colyseus MIT,
|
|
22
|
+
zod MIT).
|
|
23
|
+
|
|
24
|
+
Patterns (ideas only)
|
|
25
|
+
- The tower defense genre's general mechanics (a fixed road, waves, towers
|
|
26
|
+
that target and upgrade, a bounty economy, lives). Mechanics, not
|
|
27
|
+
expression; no map, tower, creep, character or text was copied from any
|
|
28
|
+
game.
|
package/README.md
CHANGED
|
@@ -1,3 +1,81 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @netforge/template-tower
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A co-op tower defense game template for Net Forge: up to 4 players on one shared board (COGSPIRE).
|
|
4
|
+
|
|
5
|
+
Rust swarms crawl an old rail road toward a brass clockwork spire in waves. Each tinker builds and upgrades towers with their own gold, every kill pays its builder a bounty and a share to the rest, and the team shares the spire's bells. Hold twenty waves to keep the spire.
|
|
6
|
+
|
|
7
|
+
It is a board genre: a deterministic rules module runs on the room host at 30 Hz behind the same adapter seam as the action templates. Your tinker (the cursor) is predicted; builds, upgrades, sells and the ready vote are actions the room validates (gold, tile, ownership). The client kit is `@netforge/tabletop`.
|
|
8
|
+
|
|
9
|
+
Towers aim at the creep furthest along the road in range. Splash hits a radius, frost slows, chain jumps. A leak costs the creep's damage in bells, and zero bells loses the run.
|
|
10
|
+
|
|
11
|
+
Earn: three waves, ten waves, the first boss and sixty kills. A player who joins mid-run is not paid for waves cleared before their run started.
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
npm install @netforge/template-tower
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
You normally do not import this package yourself. `kit play` runs it on your own computer, and the Net Forge MCP server and studio copy its `src/game.ts` as the starting point for a new game.
|
|
20
|
+
|
|
21
|
+
## Play it locally
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
mkdir -p my-game/src && cd my-game
|
|
25
|
+
npm init -y && npm install @netforge/kit-play @netforge/engine @netforge/template-tower
|
|
26
|
+
cp node_modules/@netforge/template-tower/src/game.ts src/
|
|
27
|
+
echo '{"template":"tower-defense"}' > netnet.json
|
|
28
|
+
npx kit-play # opens http://127.0.0.1:4663
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Coins are play money and nothing pays out. Real-token earning, stakes and claims run only on the hosted Net Forge server.
|
|
32
|
+
|
|
33
|
+
## Change the game
|
|
34
|
+
|
|
35
|
+
The bolt post is the cheap first tower. Make it cheaper and give it more reach:
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
tower("bolt_post", {
|
|
39
|
+
model: "style.lowpoly.turret",
|
|
40
|
+
kind: "bolt",
|
|
41
|
+
cost: 35,
|
|
42
|
+
damage: 8,
|
|
43
|
+
rate: 1.5,
|
|
44
|
+
range: 3.5,
|
|
45
|
+
// levels stay as they are
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Save `src/game.ts` and run `npx kit-play` again.
|
|
50
|
+
|
|
51
|
+
## Files
|
|
52
|
+
|
|
53
|
+
| Path | What |
|
|
54
|
+
|---|---|
|
|
55
|
+
| `src/game.ts` | The game, declarations only: the board and road, towers, creeps, waves, upgrades, earn, store. |
|
|
56
|
+
| `src/manifest.ts` | Loads the game; `towerAdapter()` and `towerManifest()` for the room host and the client. |
|
|
57
|
+
| `src/store.ts` | The coin prices the client is wired to. |
|
|
58
|
+
| `client/` | The browser client: the board, towers, creeps, tracers, the build bar and the tower panel. |
|
|
59
|
+
| `test/` | Playtest bots through `engine.test.run`, and the store. |
|
|
60
|
+
| `llms.txt` | How to change the game, for agents. |
|
|
61
|
+
|
|
62
|
+
## Controls
|
|
63
|
+
|
|
64
|
+
Click a tile to build the tower picked in the bar (keys 1 to 4), click a tower to upgrade or sell it, Space calls the next wave. Touch: tap a tile to aim, tap again to build. The backquote key shows stats.
|
|
65
|
+
|
|
66
|
+
## For AI agents
|
|
67
|
+
|
|
68
|
+
Read `AGENTS.md` and `llms.txt` in this package before changing the game. `llms-full.txt` adds the whole `src/game.ts` as a worked example.
|
|
69
|
+
|
|
70
|
+
Agents can also drive this template through the Net Forge MCP server: run `npx -y @netforge/mcp` (package `@netforge/mcp`, bin `netforge-mcp`). Its tools are `netforge_list_templates`, `netforge_create_game`, `netforge_explain_api`, `netforge_search_docs`, `netforge_validate_game`, `netforge_run_playtest` and `netforge_play_locally`.
|
|
71
|
+
|
|
72
|
+
To set up a coding agent in a game project, run `npx netforge setup agent`. It writes AGENTS.md, CLAUDE.md, Cursor rules and `.mcp.json` into the project. In Claude Code you can also add the server directly with `claude mcp add netforge -- npx -y @netforge/mcp`.
|
|
73
|
+
|
|
74
|
+
## Docs
|
|
75
|
+
|
|
76
|
+
- https://forge.netnet.capital/docs/templates/tower
|
|
77
|
+
- `llms.txt` and `llms-full.txt` in this package (also exported as `@netforge/template-tower/llms.txt` and `@netforge/template-tower/llms-full.txt`)
|
|
78
|
+
|
|
79
|
+
## License
|
|
80
|
+
|
|
81
|
+
MIT. See `LICENSE` and `NOTICE`.
|
package/client/decor.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Library models the scene draws on its own (not named in game.ts): the
|
|
3
|
+
* spire, the gate, the moor's trees and rocks. The build copies these into
|
|
4
|
+
* ./library next to the page, in every art style (?style= may draw any).
|
|
5
|
+
*/
|
|
6
|
+
export const SPIRE_MODEL = "style.lowpoly.obelisk";
|
|
7
|
+
export const GATE_MODEL = "style.lowpoly.column_broken";
|
|
8
|
+
export const ROCK_MODEL = "style.lowpoly.rock_large";
|
|
9
|
+
export const TREE_MODELS = ["style.lowpoly.tree_pine", "style.lowpoly.tree_autumn", "style.lowpoly.tree_fat", "style.lowpoly.bush"] as const;
|
|
10
|
+
export const SMALL_DECOR = ["style.lowpoly.rock_small", "style.lowpoly.mushroom_red", "style.lowpoly.stump", "style.lowpoly.flower_red"] as const;
|
|
11
|
+
export const SCENE_MODELS: readonly string[] = [SPIRE_MODEL, GATE_MODEL, ROCK_MODEL, ...TREE_MODELS, ...SMALL_DECOR];
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover, user-scalable=no" />
|
|
6
|
+
<title>Cogspire</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<script type="module" src="./main.ts"></script>
|
|
10
|
+
</body>
|
|
11
|
+
</html>
|