@nanotoolkit/game-sdk 0.1.10 → 0.1.11

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.
@@ -1,7 +1,7 @@
1
1
  import { parseWireJSON, stringifyWireJSON } from './WireJSON.js';
2
2
  import { GameState } from './GameState.js';
3
3
 
4
- export const SDK_VERSION = '0.1.10';
4
+ export const SDK_VERSION = '0.1.11';
5
5
 
6
6
  const REQUEST_TIMEOUT_MS = 10000;
7
7
 
@@ -123,6 +123,7 @@ export function ready(bundleId, onInit) {
123
123
  });
124
124
  subscribe('game:ping', (msg) => send({ type: 'game:pong', echo: msg.ts }));
125
125
  ensureBackListener();
126
+ ensureExitListener();
126
127
  ensureStateListeners();
127
128
  subscribe('game:init', (msg) => {
128
129
  if (initState) return;
@@ -132,7 +133,7 @@ export function ready(bundleId, onInit) {
132
133
  settleInit(publicInit(msg));
133
134
  for (const run of initWaiters.splice(0)) run();
134
135
  });
135
- send({ type: 'game:ready', game: bundleId, sdk: SDK_VERSION });
136
+ send({ type: 'game:ready', game: bundleId, sdk: SDK_VERSION, exitLifecycle: 1 });
136
137
  }
137
138
  if (typeof onInit === 'function') initPromise.then(onInit);
138
139
  return initPromise;
@@ -155,6 +156,22 @@ export function serverNow() {
155
156
  }
156
157
 
157
158
  const backHandlers = new Set();
159
+ const exitHandlers = new Set();
160
+
161
+ function ensureExitListener() {
162
+ if (ensureExitListener.done) return;
163
+ ensureExitListener.done = true;
164
+ let lastSequence = null;
165
+ subscribe('game:will_exit', (msg) => {
166
+ if (msg.seq !== lastSequence) {
167
+ lastSequence = msg.seq;
168
+ for (const handler of [...exitHandlers]) {
169
+ try { handler(); } catch (error) { console.error('[game-sdk] handler error', error); }
170
+ }
171
+ }
172
+ send({ type: 'game:exit_ready', seq: msg.seq });
173
+ });
174
+ }
158
175
 
159
176
  function ensureBackListener() {
160
177
  if (ensureBackListener.done) return;
@@ -205,6 +222,11 @@ function emitLocal(event, payload) {
205
222
 
206
223
  export function on(event, handler) {
207
224
  if (typeof handler !== 'function') throw new TypeError('invalid handler');
225
+ if (event === 'willExit') {
226
+ ensureExitListener();
227
+ exitHandlers.add(handler);
228
+ return () => exitHandlers.delete(handler);
229
+ }
208
230
  if (event === 'back') {
209
231
  ensureBackListener();
210
232
  backHandlers.add(handler);
@@ -225,7 +247,7 @@ export function on(event, handler) {
225
247
  const spec = EVENTS[event];
226
248
  if (!spec)
227
249
  throw new TypeError(
228
- `invalid event: ${event} / ${[...Object.keys(EVENTS), 'back', ...Object.keys(localHandlers)].join(
250
+ `invalid event: ${event} / ${[...Object.keys(EVENTS), 'back', 'willExit', ...Object.keys(localHandlers)].join(
229
251
  ' / ',
230
252
  )}`,
231
253
  );
package/index.d.ts CHANGED
@@ -295,6 +295,7 @@ export function watchIssues(): () => void;
295
295
  export interface EventPayloads {
296
296
  pause: undefined;
297
297
  resume: undefined;
298
+ willExit: undefined;
298
299
  theme: { dark: boolean };
299
300
  lang: { lang: string };
300
301
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nanotoolkit/game-sdk",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "private": false,
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",