ball2d 0.0.1 → 0.1.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.
Files changed (56) hide show
  1. package/README.md +154 -5
  2. package/dist/browser.js +4051 -0
  3. package/dist/core.wasm +0 -0
  4. package/dist/licenses/fflate.txt +21 -0
  5. package/dist/licenses/json5.txt +23 -0
  6. package/dist/licenses/native.json +236 -0
  7. package/dist/licenses/werift.txt +21 -0
  8. package/dist/node.js +43399 -0
  9. package/dist/stadiums/big.hbs +85 -0
  10. package/dist/stadiums/big_easy.hbs +85 -0
  11. package/dist/stadiums/big_hockey.hbs +87 -0
  12. package/dist/stadiums/big_rounded.hbs +100 -0
  13. package/dist/stadiums/classic.hbs +85 -0
  14. package/dist/stadiums/easy.hbs +85 -0
  15. package/dist/stadiums/hockey.hbs +87 -0
  16. package/dist/stadiums/huge.hbs +85 -0
  17. package/dist/stadiums/provenance.json +46 -0
  18. package/dist/stadiums/rounded.hbs +100 -0
  19. package/dist/stadiums/small.hbs +85 -0
  20. package/dist/types/client/announcement.d.ts +10 -0
  21. package/dist/types/client/connection-stats.d.ts +11 -0
  22. package/dist/types/client/headless.d.ts +130 -0
  23. package/dist/types/client/host-config.d.ts +11 -0
  24. package/dist/types/client/host-runtime.d.ts +10 -0
  25. package/dist/types/client/network-runtime.d.ts +8 -0
  26. package/dist/types/client/network.d.ts +91 -0
  27. package/dist/types/client/stadium-library.d.ts +4 -0
  28. package/dist/types/client/startup-scope.d.ts +6 -0
  29. package/dist/types/client/traffic.d.ts +9 -0
  30. package/dist/types/core/avatar.d.ts +2 -0
  31. package/dist/types/core/build-id.d.ts +2 -0
  32. package/dist/types/core/control.d.ts +5 -0
  33. package/dist/types/core/disc-properties.d.ts +7 -0
  34. package/dist/types/core/engine.d.ts +68 -0
  35. package/dist/types/core/host-types.d.ts +21 -0
  36. package/dist/types/core/match-state.d.ts +17 -0
  37. package/dist/types/core/protocol.d.ts +24 -0
  38. package/dist/types/core/replay-codec.d.ts +6 -0
  39. package/dist/types/core/replay-types.d.ts +41 -0
  40. package/dist/types/core/replay-wire.d.ts +5 -0
  41. package/dist/types/core/replay.d.ts +48 -0
  42. package/dist/types/core/stadium.d.ts +91 -0
  43. package/dist/types/core/team-colors.d.ts +8 -0
  44. package/dist/types/sdk/browser.d.ts +11 -0
  45. package/dist/types/sdk/command-queue.d.ts +11 -0
  46. package/dist/types/sdk/config.d.ts +6 -0
  47. package/dist/types/sdk/create-options.d.ts +4 -0
  48. package/dist/types/sdk/node-transport.d.ts +4 -0
  49. package/dist/types/sdk/node.d.ts +18 -0
  50. package/dist/types/sdk/replay.d.ts +4 -0
  51. package/dist/types/sdk/room.d.ts +7 -0
  52. package/dist/types/sdk/stadium.d.ts +9 -0
  53. package/dist/types/sdk/types.d.ts +78 -0
  54. package/dist/types/shared/room-link.d.ts +6 -0
  55. package/package.json +21 -19
  56. package/index.js +0 -3
package/README.md CHANGED
@@ -1,7 +1,156 @@
1
- # Ball 2D
1
+ # Ball2D SDK
2
2
 
3
- Ball 2D by Fillbyte.
3
+ ```ts
4
+ import { createRoom, type RoomConfig } from 'ball2d';
4
5
 
5
- - Website: https://ball2d.com
6
- - Source: https://github.com/fillbyte-com/ball2d
7
- - Issues and wiki: https://github.com/fillbyte-com/ball2d-issues
6
+ const config: RoomConfig = { roomName: 'My room', noPlayer: true };
7
+ const room = await createRoom(config);
8
+ room.onPlayerJoin = (player) => room.setPlayerTeam(player.id, 1);
9
+ await room.startGame();
10
+ // When the host is finished:
11
+ // room.close();
12
+ ```
13
+
14
+ This initial entry runs in a browser on an origin serving the matching Ball2D
15
+ Worker API, WASM and stadium assets. The separate experimental `ball2d/node` entry provides native Node hosting. The
16
+ browser entry does not provide remote-origin hosting or an isolated plugin runtime.
17
+ Importing it does not register a window global or allocate a room. Creating a
18
+ room explicitly starts the existing browser host and its network lifecycle.
19
+
20
+ `RoomConfig`, `Room`, `HostPlayer`, `HostScores` and `HostDiscProperties` are exported
21
+ types. `readReplay` reads Ball2D recordings. This is not a complete HaxBall
22
+ compatibility shim.
23
+
24
+ State-changing SDK commands return Promises and run in call order. A synchronous
25
+ getter immediately after a command still observes the earlier state; await the
26
+ command before reading its result. Inputs are copied at call time. Up to 256
27
+ commands may wait; overflow rejects without dropping accepted work. Live command
28
+ errors also reach `onError`; cancellation and calls after closure only reject their
29
+ Promises. `close()` immediately rejects pending SDK work and closes the
30
+ host; it does not undo operations already applied remotely. Getters and recording
31
+ start/stop remain synchronous. Chat filters must synchronously return false.
32
+ Callbacks receive the SDK facade as `this`; engine/network internals are not
33
+ part of that facade. This is an API boundary, not a sandbox for untrusted code.
34
+
35
+ `createRoom()` accepts omitted options. Defaults are a private room named
36
+ `Headless Room`, capacity 12, and an admin host player named `Host`. Set
37
+ `noPlayer: true` for an unattended playerless room and `public: true` to list it.
38
+ Integer capacity is clamped to 2–30; malformed numeric or privacy values reject
39
+ before engine/network allocation. Omitted/null optional default fields resolve
40
+ to defaults. The standalone `/headless` and `/headless.html` pages have been
41
+ retired; import the SDK instead. No `window.Ball2D` global is registered.
42
+
43
+ Version 0.1.0 is the first functional SDK release. For native hosting use Node.js
44
+ 24 and the `ball2d/node` entry below. This is an early API; the native transport
45
+ remains experimental and the acceptance limits below still apply.
46
+
47
+ Validate a stadium before allocating a room:
48
+
49
+ ```ts
50
+ import { validateStadium } from 'ball2d';
51
+
52
+ const report = validateStadium('{name:"Training", canBeStored:false}');
53
+ console.log(report.name, report.canBeStored, report.warnings);
54
+ ```
55
+
56
+ `validateStadium(source)` is synchronous and works without browser globals,
57
+ network requests or a WASM instance. It uses the same parser and limits as room
58
+ creation. Malformed/unsupported input throws; ignored field names become bounded
59
+ warnings. The returned `StadiumValidation` and warning array are readonly and
60
+ frozen. No geometry or internal engine objects are exposed. Passing validation
61
+ means Ball2D can parse the source, not that its physics are identical to HaxBall.
62
+ Use the separate `ball2d/node` entry for native room hosting.
63
+
64
+ `room.signal` is a readonly `AbortSignal` that aborts once when host closure
65
+ begins, including a fatal transport closure. Use it to cancel your own room-bound
66
+ work. It signals cancellation, not completion of every cleanup operation. Pending
67
+ SDK commands are cancelled from the same signal; cancellation never reenters the
68
+ room's error callback. A terminal transport error can still be reported once.
69
+
70
+ SDK `setScoreLimit` and `setTimeLimit` clamp integer arguments to 0–99 (goals
71
+ and minutes respectively); zero disables that limit. Await them before reading
72
+ updated state. Active-match calls remain no-ops. Non-integer or non-numeric
73
+ values reject when settings are editable. These commands use the same queued
74
+ contract in browser and native SDK hosts.
75
+
76
+ ## Experimental native Node host
77
+
78
+ ```ts
79
+ import { createRoom, type NodeRoom } from 'ball2d/node';
80
+
81
+ const room: NodeRoom = await createRoom({
82
+ serviceOrigin: 'http://127.0.0.1:8787', // A matching Ball2D deployment
83
+ roomName: 'Native room',
84
+ noPlayer: true,
85
+ });
86
+ room.onPlayerJoin = (player) => room.setPlayerTeam(player.id, 1);
87
+ await room.setDefaultStadium('Classic');
88
+ await room.startGame();
89
+ // Later:
90
+ room.close();
91
+ await room.closed; // Native peer cleanup finished; rejects on cleanup failure.
92
+ ```
93
+
94
+ Verified on Node 24.19.0 and Bun 1.4.2 on macOS arm64 with local Worker signaling
95
+ and real Chrome guests. Both use the same `ball2d/node` entry, runtime WebSocket
96
+ and bundled, patched werift 0.24.4; no
97
+ browser host, postinstall patching or external transport dependency is required.
98
+ WASM and default stadium files are included and the engine identity is checked.
99
+ `serviceOrigin` defaults to `https://ball2d.com`; the deployment's client/protocol
100
+ and engine must match this SDK version. Importing the package does not
101
+ open a room. Browser consumers continue to import from `ball2d`.
102
+
103
+ On a deployment with accounts and SDK keys configured, supply an account-owned
104
+ key from an environment variable:
105
+
106
+ ```ts
107
+ const apiKey = process.env.BALL2D_API_KEY;
108
+ if (!apiKey) throw new Error('Set BALL2D_API_KEY from your Ball2D account.');
109
+ const room = await createRoom({ roomName: 'My room host', noPlayer: true, apiKey });
110
+ ```
111
+
112
+ `apiKey` is optional for existing anonymous hosting. When supplied, it is sent
113
+ only in the authenticated room-creation request's Authorization header, never
114
+ in a URL or peer message. Keys currently authorize only `rooms:create`. New keys
115
+ expire after 90 days by default; the account page offers 7, 30, 90 or 365 days.
116
+ Expiry and revocation prevent new room creation without stopping an existing match. Never include this key in browser bundles or version control.
117
+ Account access depends on configured social providers and Worker bindings.
118
+ Anonymous room hosting is available without an API key.
119
+
120
+ The matching Worker limits room creation to 10 attempts per minute per
121
+ API key and 20 per minute across an account's keys, in addition to the IP gate.
122
+ HTTP rate-limit responses include `Retry-After: 60`; avoid immediate retry loops.
123
+ These are approximate, location-local abuse limits, not globally exact quotas.
124
+ Exhausting a creation budget does not interrupt an established match.
125
+ Node.js 24 is the primary supported development target; Bun uses the same entry
126
+ without a separate implementation.
127
+
128
+ Native room callbacks and commands use the same SDK facade. `signal` aborts when
129
+ close begins; `closed` settles after native cleanup. Neither is a confirmation
130
+ that every remote player has received a shutdown message. This is not yet WAN,
131
+ Linux, other Bun versions, automatic outage recovery, sustained churn or capacity acceptance.
132
+ Bundled dependency licenses are in
133
+ `dist/licenses`; the transport includes DCEP unordered-bit and ICE restart fixes.
134
+
135
+ TypeScript Node consumers can use `module: "NodeNext"`, `lib: ["ES2022"]` and
136
+ `types: ["node"]` with their Node type package. Public declarations do not require
137
+ DOM/WebRTC globals or `skipLibCheck`; browser runtime classes remain internal.
138
+ `Replay` is exported as a data type from both SDK entries.
139
+
140
+ Both SDK entries accept `createRoom(config, { signal })`. The optional
141
+ `AbortSignal` cancels startup only; aborting it after creation does not close the
142
+ room. Use `room.close()` for an active room. Startup has a 15-second overall
143
+ deadline for engine assets, HTTP admission/body and signaling, while the existing
144
+ 12-second signaling timeout can fail earlier. Rejection preserves the caller's
145
+ abort reason; the overall deadline rejects with `TimeoutError`. In-flight asset
146
+ and admission requests receive the startup signal, and late results cannot
147
+ continue admission after cancellation.
148
+
149
+ ## Install
150
+
151
+ ```sh
152
+ npm install ball2d@0.1.0
153
+ ```
154
+
155
+ The application source remains private. The package retains its existing
156
+ UNLICENSED designation; bundled third-party notices are included separately.