@genex-ai/cli-demo 1.38.0 → 1.38.1-dev.1097
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/dist/{blender-mcp-QVEGHE5L.js → blender-mcp-WSURPZET.js} +2 -2
- package/dist/{blender-serve-66OHC4ML.js → blender-serve-EH2MOW3U.js} +1 -1
- package/dist/{chunk-4BBTPRJW.js → chunk-EABIVAGT.js} +2 -2
- package/dist/{chunk-QI7FIYBY.js → chunk-K4EHXOZK.js} +1 -1
- package/dist/index.js +1700 -811
- package/package.json +1 -1
- package/templates/skills/genex-authoritative-multiplayer/SKILL.md +208 -0
- package/templates/skills/genex-authoritative-multiplayer/references/module-api.md +172 -0
- package/templates/skills/genex-authoritative-multiplayer/references/physics.md +150 -0
- package/templates/skills/genex-authoritative-multiplayer/references/presets.md +394 -0
- package/templates/skills/genex-authoritative-multiplayer/references/projectiles.md +195 -0
- package/templates/skills/genex-authoritative-multiplayer/references/room-template.md +1189 -0
- package/templates/skills/genex-authoritative-multiplayer/references/settings.md +122 -0
- package/templates/skills/genex-authoritative-multiplayer/references/testing.md +118 -0
- package/templates/skills/genex-game-director/SKILL.md +2 -1
- package/templates/skills/genex-getting-started/SKILL.md +2 -2
- package/templates/skills/genex-llm-in-games/SKILL.md +209 -72
- package/templates/skills/genex-llm-in-games/references/pricing.md +126 -85
- package/templates/skills/genex-monetization/SKILL.md +2 -11
- package/templates/skills/genex-threejs-embed-auth/SKILL.md +4 -1
- package/templates/skills/genex-threejs-embed-auth/references/shells.md +104 -0
- package/templates/skills/genex-threejs-multiplayer/SKILL.md +4 -0
- package/templates/skills/genex-tool-llm/SKILL.md +11 -9
- package/templates/skills/genex-tool-publish/SKILL.md +7 -0
- package/templates/skills/genex-updates/SKILL.md +1 -1
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Room settings by genre
|
|
2
|
+
|
|
3
|
+
A room module says how its game feels as **data in `config`**, never as code that names the game.
|
|
4
|
+
Pick the genre preset closest to the game; every setting you leave out comes from its table, and
|
|
5
|
+
every engine runs the same table, so prediction matches on every client. All of it needs a
|
|
6
|
+
`firstperson` or `vehicle` movement preset ([presets.md](presets.md)); a bad value is refused when the
|
|
7
|
+
module loads, naming the first bad path (for example `$.config.contacts.top.speed`).
|
|
8
|
+
|
|
9
|
+
| The game | `contacts.preset` | Movement | Seats on each other | Input repeat |
|
|
10
|
+
|---|---|---|---|---|
|
|
11
|
+
| Shooter, arena brawler | `shooter` | `firstperson` | stand on a head, slide off if the foot is mostly over the edge; players are solid and never shoved | on |
|
|
12
|
+
| Platformer, co-op climber | `platformer` | `firstperson` | stand and ride; a stomp is opt-in | on |
|
|
13
|
+
| Party game, minigames | `party` | `firstperson` | stand and ride, shoved by each other | on |
|
|
14
|
+
| Sandbox with crates and props | `physics-sandbox` | `firstperson` or `vehicle` | stand and ride, props ride heads | on |
|
|
15
|
+
| Car arena, derby | `vehicle-arena` | `vehicle` | cars slide off roofs, shove each other, bounce (restitution 0.6) | off |
|
|
16
|
+
|
|
17
|
+
## Contacts
|
|
18
|
+
|
|
19
|
+
`config.contacts: { preset, ... }` is how two seats in contact are handled. The server runs it after
|
|
20
|
+
each tick's movement and before `step`; clients run it in their prediction. Write no contact code, and
|
|
21
|
+
never run a pass of your own beside it.
|
|
22
|
+
|
|
23
|
+
```js
|
|
24
|
+
// shooter: the seats' hull is the movement preset's; players walk on each other's heads
|
|
25
|
+
config: { tickHz: 60, maxPlayers: 10, preset: { name: "firstperson", params: {} }, contacts: { preset: "shooter" } },
|
|
26
|
+
// platformer with a stomp (the upper seat bounces off, a held jump adds a boost)
|
|
27
|
+
config: { tickHz: 60, maxPlayers: 8, preset: { name: "firstperson", params: {} }, contacts: { preset: "platformer", top: { policy: "bounce" } } },
|
|
28
|
+
// party: a shorter landing zone is one number
|
|
29
|
+
config: { tickHz: 30, maxPlayers: 12, preset: { name: "firstperson", params: {} }, contacts: { preset: "party", top: { policy: "stand", center: 0.5 } } },
|
|
30
|
+
// sandbox: players stand on each other and on the crates the room simulates
|
|
31
|
+
config: { tickHz: 60, maxPlayers: 8, preset: { name: "firstperson", params: {} }, physics: true, contacts: { preset: "physics-sandbox" } },
|
|
32
|
+
// car arena: cars on cars slide off, whatever the preset says about hulls
|
|
33
|
+
config: { tickHz: 60, maxPlayers: 6, preset: { name: "vehicle", params: {} }, contacts: { preset: "vehicle-arena" } },
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
- **What a seat does on another's top** is `top.policy`: `stand` (rest on the head; `center` is the share
|
|
37
|
+
of the lower seat's half width a landing may be off by, else it slides off; `ride: true` carries the
|
|
38
|
+
rider), `slide` (frictionless, slid off), `bounce` (a stomp: `stompMin`, `bounceSpeed`, `jumpBoost`)
|
|
39
|
+
or `ghost` (the pair never touches). **Head landing** is `stand` with a `center`: the shooter's is 0.25.
|
|
40
|
+
- **A pair rule** gives two kinds of seat their own top rule. A seat's tags are its entity's `tags`
|
|
41
|
+
and `flag:k` for each bit `k` of its `flags`: `pairs: [{ a: "flag:0", b: "flag:0", top: { policy: "ghost" } }]`
|
|
42
|
+
lets seats that both carry flag bit 0 (a team) pass through each other. At most 32 pairs.
|
|
43
|
+
- **Cells you can override**: `shape` (default: the movement preset's hull, a box over a `vehicle`),
|
|
44
|
+
`restitution`, `passes` (1 to 64), `offWall`, `drawing` (`predicted`, `separate`, `timeline`: how a
|
|
45
|
+
client draws other seats), `push` (`shared` or `mover`), `headFriction` (`slide` or `carry`, for props).
|
|
46
|
+
- A module that needs a rule the table cannot say keeps the contact functions of
|
|
47
|
+
[module-api.md](module-api.md); do not mix the two.
|
|
48
|
+
|
|
49
|
+
## Inputs
|
|
50
|
+
|
|
51
|
+
`config.inputs: { preset?, repeat? }`. A starved seat (its input is late) is either stepped again
|
|
52
|
+
under its last input (`repeat: "on"`, bounded to about 33 ms a starve and 100 ms in all) or held
|
|
53
|
+
(`"off"`). The default is the genre's column above (`inputs.preset`, else `contacts.preset`, else on).
|
|
54
|
+
Car arenas measured worse with repeats on, shooters and character games better. Override only with a
|
|
55
|
+
measurement: `inputs: { repeat: "off" }`. The client follows the room's setting by itself.
|
|
56
|
+
|
|
57
|
+
## Lifts
|
|
58
|
+
|
|
59
|
+
`config.lifts` declares moving platforms as data, each posed by an exact function of the tick: no
|
|
60
|
+
module code moves them. A rider is carried, and leaves with the lift's velocity unless `impart: "none"`.
|
|
61
|
+
|
|
62
|
+
```js
|
|
63
|
+
lifts: { platforms: [
|
|
64
|
+
{ id: "elevator", shape: { kind: "box", half: [96, 96, 8] }, path: { points: [[0, 0, 0], [0, 0, 240]], legs: [240], waits: [60, 60], ease: "smooth" } },
|
|
65
|
+
{ id: "turntable", shape: { kind: "disc", radius: 160, half: 8 }, at: [600, 0, 0], spin: { period: 600 } },
|
|
66
|
+
{ id: "belt", shape: { kind: "box", half: [200, 64, 8] }, at: [0, 600, 0], surface: [300, 0] },
|
|
67
|
+
] }
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
- A path has `points`, one leg length in **ticks** per leg (`legs`: one fewer than the points for the
|
|
71
|
+
default `pingpong`, one per point for `loop`), optional `waits` (one per point), `ease` (`linear` or
|
|
72
|
+
`smooth`) and `phase`. A `spin.period` is the ticks of a full turn (8 or more); `surface` is a
|
|
73
|
+
conveyor's speed in the platform's frame. 1 to 32 platforms, ids of a-z, 0-9 and `-`.
|
|
74
|
+
- A platform that moves more than the movement preset's `radius` in one tick is refused, naming the
|
|
75
|
+
leg and the most allowed. Lengths in ticks scale with `tickHz`: the same elevator at 120 Hz has doubled legs.
|
|
76
|
+
- The client draws a lift with `session.liftPose(id)` and, in a `firstperson` view, adds
|
|
77
|
+
`session.viewCarry()` to its yaw once a frame. The module reads `ctx.lifts.crushed()` for damage.
|
|
78
|
+
- The client must send the `lifts@1` capability; `connectAuthority` does. A client that does not (the
|
|
79
|
+
Godot SDK today) is refused when the room declares lifts, never allowed to fall through them.
|
|
80
|
+
With server physics, crates ride lifts and a conveyor moves them.
|
|
81
|
+
|
|
82
|
+
## Tick rate
|
|
83
|
+
|
|
84
|
+
`tickHz` is 20, 30, 60 or 120. Use 60 for character and car games, 30 for slow ones. **120 is for a
|
|
85
|
+
module that asks for physics** (`physics: true`): the world steps twice as often, the room counts twice
|
|
86
|
+
toward a server's capacity (12 units where 60 Hz counts 6), and each tick keeps a 60 Hz tick's budget
|
|
87
|
+
(8 ms, 1 ms on average), so the room gets twice the CPU a second. Check the REPORT line of
|
|
88
|
+
`genex-authority-dev start` against `tick.budgetMs` ([testing.md](testing.md)).
|
|
89
|
+
|
|
90
|
+
```js
|
|
91
|
+
config: { tickHz: 120, maxPlayers: 4, preset: { name: "vehicle", params: {} }, physics: true, contacts: { preset: "vehicle-arena" } },
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Regions
|
|
95
|
+
|
|
96
|
+
Pass the stand's regions beside its urls and the client joins the nearest one by measured ping:
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
const session = await connectAuthority({
|
|
100
|
+
urls: getAuthorityUrls(), regions: getAuthorityRegions(), room: GENEX.slug, auth: () => getColyseusAuth(),
|
|
101
|
+
});
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Each region is its own matchmaking pool: players meet others who entered through the same region. A
|
|
105
|
+
region that answers no probe is tried last. A full region (503) is retried, and moves on to the next-best
|
|
106
|
+
after a second refusal. Nothing to configure in the module.
|
|
107
|
+
|
|
108
|
+
## The fast channel (`fast@1`)
|
|
109
|
+
|
|
110
|
+
On a bad Wi-Fi link one lost TCP segment holds every input and snapshot behind it. With the fast
|
|
111
|
+
channel a seat's inputs and the room's motion go by unordered datagrams (each input is sent in several,
|
|
112
|
+
a lost snapshot is replaced by the next); join, game events, chat and everything else stay on the
|
|
113
|
+
WebSocket. It needs nothing in the room module.
|
|
114
|
+
|
|
115
|
+
- The seat asks for it (`fast@1`), the room offers it only when the server has it configured, and a seat
|
|
116
|
+
that is not offered it stays a WebSocket seat. If the datagrams stop, or the endpoint cannot be reached,
|
|
117
|
+
the seat falls back to the WebSocket by itself, mid-game, and prediction does not notice.
|
|
118
|
+
- **Status:** a UDP seat in Unreal (`bFastChannel`), Unity (`GenexAuthorityOptions.Fast`, not WebGL),
|
|
119
|
+
Rust (`AuthorityOptions::fast(true)`) and TypeScript in Node (the client's `fast` option, given
|
|
120
|
+
`openUdpFastSocket` from `@genex-ai/multiplayer/authority/fast-udp`). It is off until the game turns it on. **A browser game
|
|
121
|
+
is a WebSocket seat**: browsers have no raw UDP, and WebTransport is not shipped. Godot is a WebSocket seat.
|
|
122
|
+
Do not promise a browser player UDP-like play.
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# Testing a room module on this machine
|
|
2
|
+
|
|
3
|
+
`@genex-ai/authority-dev` runs the room module exactly as Genex's servers do — the same room core,
|
|
4
|
+
the same sandbox limits, the same bundler — on this machine, with no account and no network. It is
|
|
5
|
+
a dev dependency of the game (`npm i -D @genex-ai/authority-dev`); `npx genex preview` uses the same
|
|
6
|
+
package to check the module before it ships.
|
|
7
|
+
|
|
8
|
+
| Command | What it does |
|
|
9
|
+
|---|---|
|
|
10
|
+
| `npx genex-authority-dev validate --module server/room.ts --root .` | The publish gate: bundles the module, fuzzes it for 30 simulated seconds with random and adversarial players, checks every tick, holds its tick time to a CPU budget, and replays the run twice. Exit 0 = passed. `--out report.json` keeps the report. |
|
|
11
|
+
| `npx genex-authority-dev start --module server/room.ts --root . --bots 3 --latency 75 --report` | Serves the module on `127.0.0.1` with bots that join, wander, aim and fire, behind a 75 ms each-way link. |
|
|
12
|
+
| `npx genex-authority-dev replay --module server/room.ts --root .` | Replays the validation run twice and prints both state hashes. Equal means the module is deterministic. |
|
|
13
|
+
|
|
14
|
+
`--root .` lets the module import files outside its own folder (a movement step in `src/`); every
|
|
15
|
+
file the bundle reads must still be inside the game. `--port` picks the port (default: any free
|
|
16
|
+
one), `--jitter` adds random delay on top of `--latency`, `--duration` stops after that many seconds
|
|
17
|
+
and `--seed` changes the run. `start` only ever listens on `127.0.0.1`.
|
|
18
|
+
|
|
19
|
+
## Playing against the local server
|
|
20
|
+
|
|
21
|
+
`start` prints one line per event on stdout:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
LISTEN ws://127.0.0.1:<port>
|
|
25
|
+
REPORT {"rooms":1,"players":4,"tick":{"p50Ms":…,"p99Ms":…,"maxMs":…,"budgetMs":…},"strikes":0,"lastFault":null,…}
|
|
26
|
+
LOG {"room":"…","line":"what ctx.log wrote"}
|
|
27
|
+
ERROR {"reason":"…","detail":"…"}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Start the game's dev server and open it with the address from `LISTEN`:
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
http://localhost:5173/?genex_local_test=1&genex_authority_url=ws://127.0.0.1:<port>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
In local test mode `getAuthorityUrls()` returns that address and `getColyseusAuth()` a local
|
|
37
|
+
placeholder, so the game's own client joins without a change. Every join is a fresh local player
|
|
38
|
+
(whatever room name it sends, it meets the bots), so a second browser window is a second player.
|
|
39
|
+
Only a page served from this machine may join.
|
|
40
|
+
|
|
41
|
+
Read the REPORT line while you play: `strikes` above 0 or a `lastFault` means the module faulted
|
|
42
|
+
(the module's own bug, named by its close code); a `tick.p99Ms` near `tick.budgetMs` means the
|
|
43
|
+
module is too slow for Genex's servers; `corrections.visible` counts the bots' predictions the
|
|
44
|
+
server had to correct visibly — near zero is the goal, and your own client's count is
|
|
45
|
+
`session.telemetry.visibleCorrections`. Stop the server with Ctrl+C.
|
|
46
|
+
|
|
47
|
+
## A room with projectiles
|
|
48
|
+
|
|
49
|
+
The same commands test it; nothing extra to install. What to look for:
|
|
50
|
+
|
|
51
|
+
- **The fuzz and the bots fire button bit 1.** `validate` presses it most often and other bits now
|
|
52
|
+
and then; the bots that `start` runs press only bit 1, aimed at the nearest player. Bind the main shot
|
|
53
|
+
to bit 1, or neither ever launches one.
|
|
54
|
+
- **Removal is yours.** A module that never removes its projectiles fills the room's 1024 entities
|
|
55
|
+
and fails `module_ended`, with `too_many_entities` in the detail. `--out report.json` keeps the
|
|
56
|
+
report, whose `entitiesPeak` says how many entities the fuzz room held at its fullest: it should
|
|
57
|
+
stay far below 1024.
|
|
58
|
+
- **A launch that throws is a fault**: an `id` passed inside `onInput`, none passed in `step`, a
|
|
59
|
+
launch in `init` (`load_failed`), or a burst past the launch budget (`RangeError`).
|
|
60
|
+
- **In the browser**, at `--latency 75`: your shot leaves the frame you fire and flies on without a
|
|
61
|
+
jump when the server's arrives; another player's (a bot's) shots fly smoothly, not 100 ms behind;
|
|
62
|
+
`session.telemetry.projectilesRejected` stays near 0 while you fire steadily, and
|
|
63
|
+
`session.telemetry.projectilesConfirmed` grows with each shot.
|
|
64
|
+
|
|
65
|
+
## Why validation failed
|
|
66
|
+
|
|
67
|
+
`validate` (and `npx genex preview`, which runs it) names each failure by reason, with the close code
|
|
68
|
+
where the module itself ended or faulted:
|
|
69
|
+
|
|
70
|
+
| Reason | What happened | Fix |
|
|
71
|
+
|---|---|---|
|
|
72
|
+
| `build_failed` | The bundler could not build it: a syntax error, a missing file, a package import, a Node built-in. | Import only your own files; the module gets everything else through `ctx`. |
|
|
73
|
+
| `outside_root` | The bundle reads a file outside the game folder (or outside `--root`). | Keep every import inside the game; pass `--root .` for shared files in `src/`. |
|
|
74
|
+
| `too_large` | The bundle is over 1 MiB. | Move data out of the module; generate it in `init`. |
|
|
75
|
+
| `unavailable_global` | It uses something the sandbox does not have (`Date`, `setTimeout`, `fetch`, …). | Use `ctx.tick` and `ctx.dt` for time, `ctx.random()` for randomness. |
|
|
76
|
+
| `global_object` | It reaches `globalThis` instead of `ctx`. | Pass what it needs through `ctx` and `ctx.state`. |
|
|
77
|
+
| `load_failed` | Its top level or `init` failed (the code says how: an error, a timeout). | Keep the top level to constants and functions; make `init` small. |
|
|
78
|
+
| `module_ended` | The fuzz run ended the room: a timeout, too much memory, too many faults, a CPU budget broken. | Bound every loop by entities or players; never grow state without limit. |
|
|
79
|
+
| `module_fault` | It faulted at least once and survived: a hook threw, or its output broke a limit. | Fix the throw or the output; validation allows none. |
|
|
80
|
+
| `nondeterministic` | Two replays of the same run gave different states. | Remove every source of difference: a clock, unordered iteration, state outside `ctx.state`. |
|
|
81
|
+
| `tick_budget` | Its tick time p99 is over the local budget. | Do less per tick; move setup to `init` and `onJoin`. |
|
|
82
|
+
| `orphan_entity` | After a tick, an entity was owned by a player who had left. | Remove (or disown) a player's entities in `onLeave`. |
|
|
83
|
+
| `log_flood` | One tick logged more lines, or longer lines, than a room keeps. | Log on events, not every tick. |
|
|
84
|
+
| `short_run` | The fuzz ran fewer than 30 simulated seconds (`--duration`). | Run it with the default duration; a short run never passes. |
|
|
85
|
+
| `host_stall` | A busy machine cut a call off by wall clock while the module stayed under its CPU limit: no verdict on the module. | Change nothing in the module; run `validate` again on a quieter machine. |
|
|
86
|
+
| `physics_unavailable` | The module asks for `physics` and this validator has no physics core. | Update `@genex-ai/authority-dev`; see [physics.md](physics.md) for when servers run physics. |
|
|
87
|
+
| `physics_build` | The two replays ran on different physics core builds, so they were not compared. | Change nothing; run `validate` again. |
|
|
88
|
+
| `physics_backend_parity` | With `--physics-backend both`, the replay on the second physics core gave a different state from some tick on. | Report it with the tick the output names: the two cores must agree, so this is a core bug, not the module's. |
|
|
89
|
+
|
|
90
|
+
## When the deploy refuses the module
|
|
91
|
+
|
|
92
|
+
`npx genex preview` and `npx genex publish` print `Room module refused (<reason>)` and change
|
|
93
|
+
nothing:
|
|
94
|
+
|
|
95
|
+
| Reason | What to do |
|
|
96
|
+
|---|---|
|
|
97
|
+
| `manifest_invalid` | Fix `genex.authority` as the message says: a plain relative path to a `.js` or `.ts` file inside the game, and valid optional knobs. |
|
|
98
|
+
| `toolchain_missing` | `npm i -D @genex-ai/authority-dev`, then deploy again. |
|
|
99
|
+
| `toolchain_unusable` | `npm i -D @genex-ai/authority-dev@latest`, then deploy again. |
|
|
100
|
+
| `bundle_failed` | The bundler's reason is printed beside it (a reason from the table above). |
|
|
101
|
+
| `validate_failed` | Each validation failure is printed; the full report is at `.genex/authority/report.json`. Reproduce with `npx genex-authority-dev validate`. |
|
|
102
|
+
| `sha_disagrees` | The report passed a different bundle than the one to upload: update `@genex-ai/authority-dev` and deploy again. |
|
|
103
|
+
| `too_large` | The module is over 1 MiB, or its report over 64 KiB. |
|
|
104
|
+
| `config_out_of_range` | The tick rate or player count is one Genex does not run (20, 30, 60 or 120 Hz, 120 only with physics; 1 to 64 players). |
|
|
105
|
+
| `requires_pro` | The game's owner needs Genex Pro for Genex's servers. Testing on this machine stays free. |
|
|
106
|
+
| `upload_failed` | The module store refused the upload or could not be reached; try again. |
|
|
107
|
+
|
|
108
|
+
## Before calling it done
|
|
109
|
+
|
|
110
|
+
1. `validate` passes and `replay` says the hashes are equal.
|
|
111
|
+
2. At `--latency 75`, two players (two windows count) move, aim and fire, and see each other move
|
|
112
|
+
smoothly, about 100 ms behind.
|
|
113
|
+
3. A hit lands when it looked right on the shooter's screen; a respawn snaps instead of sliding.
|
|
114
|
+
With projectiles: a shot is judged where the target is on the server, so a dodged bolt misses.
|
|
115
|
+
4. Leaving and rejoining works, and the leaver's body is gone for everyone.
|
|
116
|
+
5. The REPORT line shows no strikes after a few minutes of play.
|
|
117
|
+
|
|
118
|
+
Say plainly what was not exercised (a full room, a slow connection, a reconnect).
|
|
@@ -158,11 +158,12 @@ vendored code from memory of another engine.
|
|
|
158
158
|
| requested UI/HUD/menu/interface work, a visible UI problem, or an interface you decided this game wants built with generated art | `$genex-threejs-game-ui` |
|
|
159
159
|
| selling anything for Nex (Genex's currency, bought with real money) or for real money with no currency named: a shop, an item catalog, boosts, cosmetics, "make it earn"; a fixed Nex price is a store item. Coins, gold or gems are the game's own earned currency, not this row. Also any request for a loot box, gacha, wager, casino mechanic or donation prompt, which that skill refuses and replaces | `$genex-monetization` |
|
|
160
160
|
| an item for the Genex store — sell a sword, a skin or a pet for Nex with its picture and description, "other games can use it too" — or another creator's shared item added to this game (`npx genex items add <id>`). Build the item first, list it with `npx genex shop add … --json` without asking; the person puts it on sale | `$genex-items` (with `$genex-monetization`) |
|
|
161
|
-
| the game calls a language model AT RUNTIME on the player's
|
|
161
|
+
| the game calls a language model AT RUNTIME on the player's credits, billed as used under a per-call ceiling the game benchmarks with `npx genex llm bench`: NPCs that answer in their own words, dialogue or quests written per save, a judge reading what the player typed — one-time calls, or a standing budget the player approves once. Check the lane with `npx genex llm models` before designing it in | `$genex-llm-in-games` |
|
|
162
162
|
| cinematic menu/title/pause/victory/defeat/lobby/credits video treatment | `$genex-ai-menu` |
|
|
163
163
|
| drawn HUD chrome the game's style wants—one element or a matched set of frames, masks, and icons | `$genex-ai-hud` |
|
|
164
164
|
| the game works but feels flat, floaty, or unresponsive: input response, camera, impacts, cooldowns, difficulty, fail/retry | `$genex-threejs-game-feel` |
|
|
165
165
|
| realtime multiplayer: movement sync, shared ball/NPC, host-run scores/enemies, shots/emotes, persistence | `$genex-threejs-multiplayer` |
|
|
166
|
+
| competitive multiplayer where cheating matters — ranked PvP, an arena or shooter with a winner worth faking, "so nobody can cheat", "server-authoritative": the game's room module runs on Genex's servers (`genex.authority`; the owner needs Genex Pro there, testing on this machine is free) | `$genex-authoritative-multiplayer` |
|
|
166
167
|
| players talking to each other by TEXT — chat, room chat, "let them type to each other" (`room.chat` + `npx genex controller chat`) | `$genex-threejs-multiplayer` |
|
|
167
168
|
| players TALKING — voice chat, mic, "hear each other", proximity/positional voice (`room.voice` + `npx genex controller voice`; party-sized, max 6 per room — say that number out loud before building the feature) | `$genex-threejs-multiplayer` |
|
|
168
169
|
| player identity, sign-in, guests, saves/progress, per-player state, shared persistent world, leaderboards—mandatory for every game | `$genex-threejs-embed-auth` |
|
|
@@ -161,7 +161,7 @@ downloads the game too, binary assets and all:
|
|
|
161
161
|
|
|
162
162
|
```bash
|
|
163
163
|
mkdir my-game && cd my-game
|
|
164
|
-
npx @genex-ai/cli-demo@
|
|
164
|
+
npx @genex-ai/cli-demo@dev link <slug> # slug = the name in the play URL
|
|
165
165
|
npm install
|
|
166
166
|
```
|
|
167
167
|
|
|
@@ -225,7 +225,7 @@ Safe to run any time — genex-owned skills are refreshed to the latest version,
|
|
|
225
225
|
and your own files are never touched:
|
|
226
226
|
|
|
227
227
|
```bash
|
|
228
|
-
npx @genex-ai/cli-demo@
|
|
228
|
+
npx @genex-ai/cli-demo@dev init
|
|
229
229
|
```
|
|
230
230
|
|
|
231
231
|
Use `--force` only if you intentionally want your own existing files overwritten
|