@uzuhq/code-sdk 0.8.0 → 0.8.1

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 CHANGED
@@ -304,12 +304,13 @@ handler 側で弾く必要も無い。
304
304
  **時刻は Unix epoch ではない。** `ctx.time` はゲーム開始からの経過 ms (`GameTime`) で、
305
305
  [緊急一時停止](#緊急一時停止)中は進まない。`Date.now()` とは桁も意味も違う。
306
306
 
307
- | API | 意味 |
308
- | ---------------------------- | ----------------------------------------------------------------- |
309
- | `ctx.time` | そのハンドラが走っているゲーム内時刻。`setup` では必ず `0` |
310
- | `ctx.after(d)` | 今から `d` ms 後のゲーム内時刻。締切を state に置くときに使う |
311
- | `gameTime()` | 描画側で読む現在のゲーム内時刻 (推定値)。`performance.now()` 基準 |
312
- | `plus(t, d)` / `minus(a, b)` | 時刻に長さを足す / 2 つの時刻の差を取る |
307
+ | API | 意味 |
308
+ | -------------------------- | ----------------------------------------------------------------- |
309
+ | `ctx.time` | そのハンドラが走っているゲーム内時刻。`setup` では必ず `0` |
310
+ | `ctx.after(d)` | 今から `d` ms 後のゲーム内時刻。締切を state に置くときに使う |
311
+ | `gameTime()` | 描画側で読む現在のゲーム内時刻 (推定値)。`performance.now()` 基準 |
312
+ | `plus(t, d)` / `sub(t, d)` | 時刻に長さを足す / 引く |
313
+ | `minus(a, b)` | 2 つの時刻の差 (ms) |
313
314
 
314
315
  ```ts
315
316
  import { gameTime, minus } from '@uzuhq/code-sdk';
@@ -323,8 +324,9 @@ actions: {
323
324
  const remain = Math.ceil(minus(state.phaseEndsAt, gameTime()) / 1000);
324
325
  ```
325
326
 
326
- `GameTime` は `number` の brand 型なので、実行時はただの数値。state は素の JSON のまま。
327
- `Date.now()` `GameTime` の場所に入れると TypeScript が弾く。
327
+ `GameTime` は brand 型なので実行時はただの数値で、state は素の JSON のまま。ただし型の上では
328
+ `number` と混ざらないので、`Date.now()` を書き込む式も `endsAt - Date.now()` と読む式も
329
+ コンパイルが通らない。
328
330
 
329
331
  ### 緊急一時停止
330
332
 
@@ -1,4 +1,4 @@
1
- import { i as UzuDevHooks } from "./dev-hooks-D6CbhPDP.js";
1
+ import { i as UzuDevHooks } from "./dev-hooks-BYl_jrcy.js";
2
2
  //#region src/dev-globals.d.ts
3
3
  declare global {
4
4
  interface Window {
@@ -94,19 +94,35 @@ declare function applyJsonPatch(target: Record<string, unknown>, ops: JsonPatchO
94
94
  * 違うぶんは残る (`Date.now()` を混ぜれば締切が 56,000 日後になって初回で気付く)。
95
95
  */
96
96
  declare const gameTimeBrand: unique symbol;
97
- /** ゲーム内時刻 (ゲーム開始からの ms)。停止中は進まない。 */
98
- type GameTime = number & {
97
+ /** brand の印。`GameTime` を組み立てるためだけに使う。 */
98
+ type GameTimeTag = {
99
99
  readonly [gameTimeBrand]: 'GameTime';
100
100
  };
101
+ /**
102
+ * ゲーム内時刻 (ゲーム開始からの ms)。停止中は進まない。
103
+ *
104
+ * `number & Tag` ではなく `(number & Tag) | Tag` にしてあるのは、**読み側を守るため**。
105
+ * 交差だけだと `GameTime` が `number` へ代入できてしまい、
106
+ * `state.endsAt - Date.now()` が型検査を通る。これは `GameTime` を導入した動機
107
+ * そのもののバグで、しかも実行時に静かに壊れる (巨大な負数が
108
+ * `Math.max(0, ...)` に潰されてタイマーが 00:00 で固まる)。
109
+ *
110
+ * union にすると `number` への代入と算術が型で止まり、`GameTime` 同士の比較・`===`・
111
+ * テンプレート・`Number.isFinite`・JSON 往復・一段 cast はそのまま使える。
112
+ * TypeScript コンパイラ自身が `__String` (識別子の内部表現) で同じ形を採っている
113
+ * (microsoft/TypeScript#16915)。
114
+ */
115
+ type GameTime = (number & GameTimeTag) | GameTimeTag;
101
116
  /** 長さ (ms)。差や間隔はこちら。 */
102
117
  type Duration = number;
103
118
  /**
104
119
  * `GameTime` に長さを足す。
105
120
  *
106
- * 算術をすると brand が落ちる (`number + number = number`) ので、`GameTime`
107
- * 作り直す道はこの関数と `ctx.after` に限られる。
121
+ * 算術は型で止まるので、`GameTime` を作り直す道はこの関数と `ctx.after` に限られる。
108
122
  */
109
123
  declare const plus: (t: GameTime, d: Duration) => GameTime;
124
+ /** `GameTime` から長さを引く。`plus(t, -d)` と書かせないための対。 */
125
+ declare const sub: (t: GameTime, d: Duration) => GameTime;
110
126
  /** 2 つの `GameTime` の差 (ms)。 */
111
127
  declare const minus: (a: GameTime, b: GameTime) => Duration;
112
128
  //#endregion
@@ -712,4 +728,4 @@ interface DevHooksCtx<S = unknown> {
712
728
  declare function createDevHooks<S>(ctx: DevHooksCtx<S>): UzuDevHooks<S>;
713
729
  declare function attachDevHooks<S>(ctx: DevHooksCtx<S>): void;
714
730
  //#endregion
715
- export { minus as $, DEFAULT_ICON_URLS as A, ServerActionContext as B, SetFn as C, ActionContext as D, ActionArgs as E, GameLogic as F, ServerOnlyActionContext as G, ServerActionMap as H, SERVER_TIME as I, SetupContext as J, ServerOnlyActionHandlerFn as K, Seat as L, DeadlineArgs as M, DeadlineContext as N, ActionHandler as O, Emit as P, GameTime as Q, SeededRandom as R, SendAction as S, Operation as T, ServerEvent as U, ServerActionHandler as V, ServerOnlyAction as W, UpdateContext as X, UpdateArgs as Y, Duration as Z, PayloadMap as _, attachDevHooks as a, PlayersChangedMessage as b, getPredictionWarnings as c, ConnectionCallbacks as d, plus as et, ConnectionState as f, PatchFn as g, GameConfig as h, UzuDevHooks as i, applyJsonPatch as it, Deadline as j, ActionMap as k, BridgeChannel as l, EventSubscription as m, RunHandle as n, JsonPatchOp as nt, createDevHooks as o, EventHandler as p, SetupArgs as q, SyncHandle as r, applyJsonMergePatch as rt, PredictionWarning as s, DevHooksCtx as t, JsonMergePatch as tt, BridgeMessage as u, PlayScreenMessage as v, SyncConfig as w, SeatKind as x, PlayerVoiceState as y, ServerActionArgs as z };
731
+ export { minus as $, DEFAULT_ICON_URLS as A, ServerActionContext as B, SetFn as C, ActionContext as D, ActionArgs as E, GameLogic as F, ServerOnlyActionContext as G, ServerActionMap as H, SERVER_TIME as I, SetupContext as J, ServerOnlyActionHandlerFn as K, Seat as L, DeadlineArgs as M, DeadlineContext as N, ActionHandler as O, Emit as P, GameTime as Q, SeededRandom as R, SendAction as S, Operation as T, ServerEvent as U, ServerActionHandler as V, ServerOnlyAction as W, UpdateContext as X, UpdateArgs as Y, Duration as Z, PayloadMap as _, attachDevHooks as a, applyJsonPatch as at, PlayersChangedMessage as b, getPredictionWarnings as c, ConnectionCallbacks as d, plus as et, ConnectionState as f, PatchFn as g, GameConfig as h, UzuDevHooks as i, applyJsonMergePatch as it, Deadline as j, ActionMap as k, BridgeChannel as l, EventSubscription as m, RunHandle as n, JsonMergePatch as nt, createDevHooks as o, EventHandler as p, SetupArgs as q, SyncHandle as r, JsonPatchOp as rt, PredictionWarning as s, DevHooksCtx as t, sub as tt, BridgeMessage as u, PlayScreenMessage as v, SyncConfig as w, SeatKind as x, PlayerVoiceState as y, ServerActionArgs as z };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as minus, A as DEFAULT_ICON_URLS, B as ServerActionContext, C as SetFn, D as ActionContext, E as ActionArgs, F as GameLogic, G as ServerOnlyActionContext, H as ServerActionMap, I as SERVER_TIME, J as SetupContext, K as ServerOnlyActionHandlerFn, L as Seat, M as DeadlineArgs, N as DeadlineContext, O as ActionHandler, P as Emit, Q as GameTime, R as SeededRandom, S as SendAction, T as Operation, U as ServerEvent, V as ServerActionHandler, W as ServerOnlyAction, X as UpdateContext, Y as UpdateArgs, Z as Duration, _ as PayloadMap, a as attachDevHooks, b as PlayersChangedMessage, c as getPredictionWarnings, d as ConnectionCallbacks, et as plus, f as ConnectionState, g as PatchFn, h as GameConfig, i as UzuDevHooks, it as applyJsonPatch, j as Deadline, k as ActionMap, l as BridgeChannel, m as EventSubscription, n as RunHandle, nt as JsonPatchOp, o as createDevHooks, p as EventHandler, q as SetupArgs, r as SyncHandle, rt as applyJsonMergePatch, s as PredictionWarning, t as DevHooksCtx, tt as JsonMergePatch, u as BridgeMessage, v as PlayScreenMessage, w as SyncConfig, x as SeatKind, y as PlayerVoiceState, z as ServerActionArgs } from "./dev-hooks-D6CbhPDP.js";
1
+ import { $ as minus, A as DEFAULT_ICON_URLS, B as ServerActionContext, C as SetFn, D as ActionContext, E as ActionArgs, F as GameLogic, G as ServerOnlyActionContext, H as ServerActionMap, I as SERVER_TIME, J as SetupContext, K as ServerOnlyActionHandlerFn, L as Seat, M as DeadlineArgs, N as DeadlineContext, O as ActionHandler, P as Emit, Q as GameTime, R as SeededRandom, S as SendAction, T as Operation, U as ServerEvent, V as ServerActionHandler, W as ServerOnlyAction, X as UpdateContext, Y as UpdateArgs, Z as Duration, _ as PayloadMap, a as attachDevHooks, at as applyJsonPatch, b as PlayersChangedMessage, c as getPredictionWarnings, d as ConnectionCallbacks, et as plus, f as ConnectionState, g as PatchFn, h as GameConfig, i as UzuDevHooks, it as applyJsonMergePatch, j as Deadline, k as ActionMap, l as BridgeChannel, m as EventSubscription, n as RunHandle, nt as JsonMergePatch, o as createDevHooks, p as EventHandler, q as SetupArgs, r as SyncHandle, rt as JsonPatchOp, s as PredictionWarning, t as DevHooksCtx, tt as sub, u as BridgeMessage, v as PlayScreenMessage, w as SyncConfig, x as SeatKind, y as PlayerVoiceState, z as ServerActionArgs } from "./dev-hooks-BYl_jrcy.js";
2
2
  //#region ../engine-core/src/random.d.ts
3
3
  declare class SeededRandomImpl implements SeededRandom {
4
4
  private _state;
@@ -205,4 +205,4 @@ declare function onPlayersChanged(handler: PlayersChangedHandler): void;
205
205
  declare function run<S, A extends ActionMap<S> = ActionMap<S>, SA extends ServerActionMap<S> = Record<never, never>>(config: GameConfig<S, A, SA>): void;
206
206
  declare function sync<S>(config: SyncConfig<S>): void;
207
207
  //#endregion
208
- export { type ActionArgs, type ActionContext, type ActionHandler, type ActionMap, type BridgeChannel, type BridgeMessage, type ConnectionCallbacks, type ConnectionState, DEFAULT_ICON_URLS, type Deadline, type DeadlineArgs, type DeadlineContext, type DevHooksCtx, type Duration, type Emit, type EventHandler, type EventSubscription, type GameConfig, type GameLogic, type GameTime, type JsonMergePatch, type JsonPatchOp, type Operation, type PatchFn, type PayloadMap, type PlayScreenMessage, type PlayerVoiceState, type PlayersChangedMessage, type PredictionWarning, type ReconnectableWSOptions, ReconnectableWebSocket, Room, type RoomLike, type RunHandle, SERVER_TIME, type Seat, type SeatKind, type SeededRandom, SeededRandomImpl, type SendAction, type ServerActionArgs, type ServerActionContext, type ServerActionHandler, type ServerActionMap, type ServerEvent, type ServerOnlyAction, type ServerOnlyActionContext, type ServerOnlyActionHandlerFn, type SetFn, type SetupArgs, type SetupContext, type SyncConfig, type SyncHandle, type UpdateArgs, type UpdateContext, type UzuDevHooks, applyJsonMergePatch, applyJsonPatch, attachDevHooks, changeRoom, createDevHooks, firstFrameReady, gameReady, gameTime, getPredictionWarnings, getRoom, init, isHosted, isPaused, isServerOnlyAction, minus, on, onPauseChange, onPlayersChanged, onRoom, playBgm, playSound, plus, run, send, serverOnly, setMicEnabled, stopBgm, sync };
208
+ export { type ActionArgs, type ActionContext, type ActionHandler, type ActionMap, type BridgeChannel, type BridgeMessage, type ConnectionCallbacks, type ConnectionState, DEFAULT_ICON_URLS, type Deadline, type DeadlineArgs, type DeadlineContext, type DevHooksCtx, type Duration, type Emit, type EventHandler, type EventSubscription, type GameConfig, type GameLogic, type GameTime, type JsonMergePatch, type JsonPatchOp, type Operation, type PatchFn, type PayloadMap, type PlayScreenMessage, type PlayerVoiceState, type PlayersChangedMessage, type PredictionWarning, type ReconnectableWSOptions, ReconnectableWebSocket, Room, type RoomLike, type RunHandle, SERVER_TIME, type Seat, type SeatKind, type SeededRandom, SeededRandomImpl, type SendAction, type ServerActionArgs, type ServerActionContext, type ServerActionHandler, type ServerActionMap, type ServerEvent, type ServerOnlyAction, type ServerOnlyActionContext, type ServerOnlyActionHandlerFn, type SetFn, type SetupArgs, type SetupContext, type SyncConfig, type SyncHandle, type UpdateArgs, type UpdateContext, type UzuDevHooks, applyJsonMergePatch, applyJsonPatch, attachDevHooks, changeRoom, createDevHooks, firstFrameReady, gameReady, gameTime, getPredictionWarnings, getRoom, init, isHosted, isPaused, isServerOnlyAction, minus, on, onPauseChange, onPlayersChanged, onRoom, playBgm, playSound, plus, run, send, serverOnly, setMicEnabled, stopBgm, sub, sync };
package/dist/index.js CHANGED
@@ -10,14 +10,23 @@ const DEFAULT_ICON_URLS = [
10
10
  //#endregion
11
11
  //#region ../engine-core/src/game-time.ts
12
12
  /**
13
+ * エンジン内部で素の ms へ落とす。**パッケージの公開 API には出さない** (`index.ts` を見よ)。
14
+ *
15
+ * 公開すると `toMs(a) - toMs(b)` と書けてしまい brand の保護が丸ごと消える。
16
+ * 差を取る正当な用途は `minus` が既に埋めているので、外へ出す理由が無い。
17
+ * 外部 API へ素の数値を渡したいという実需が出たら、そのとき足す。
18
+ */
19
+ const toMs = (t) => t;
20
+ /**
13
21
  * `GameTime` に長さを足す。
14
22
  *
15
- * 算術をすると brand が落ちる (`number + number = number`) ので、`GameTime`
16
- * 作り直す道はこの関数と `ctx.after` に限られる。
23
+ * 算術は型で止まるので、`GameTime` を作り直す道はこの関数と `ctx.after` に限られる。
17
24
  */
18
- const plus = (t, d) => t + d;
25
+ const plus = (t, d) => toMs(t) + d;
26
+ /** `GameTime` から長さを引く。`plus(t, -d)` と書かせないための対。 */
27
+ const sub = (t, d) => toMs(t) - d;
19
28
  /** 2 つの `GameTime` の差 (ms)。 */
20
- const minus = (a, b) => a - b;
29
+ const minus = (a, b) => toMs(a) - toMs(b);
21
30
  /**
22
31
  * エンジン内部専用。作家コードから呼ばない。
23
32
  *
@@ -74,7 +83,7 @@ var GameClock = class {
74
83
  }
75
84
  /** ゲーム内時刻を、alarm / setTimeout が使う実時刻へ直す。 */
76
85
  toWall(at) {
77
- return at + this.startedAtWall + this.pausedTotalMs;
86
+ return toMs(at) + this.startedAtWall + this.pausedTotalMs;
78
87
  }
79
88
  /** 実際に理由を足したら true。呼び出し側が永続化や tick 停止の要否に使う。 */
80
89
  freeze(reason) {
@@ -139,8 +148,9 @@ var GameClock = class {
139
148
  function withGameClock(time, fn) {
140
149
  const realNow = Date.now;
141
150
  const RealDate = Date;
142
- Date.now = () => time;
143
- globalThis.Date = new Proxy(RealDate, { construct: (target, args) => Reflect.construct(target, args.length === 0 ? [time] : args) });
151
+ const ms = toMs(time);
152
+ Date.now = () => ms;
153
+ globalThis.Date = new Proxy(RealDate, { construct: (target, args) => Reflect.construct(target, args.length === 0 ? [ms] : args) });
144
154
  try {
145
155
  return fn();
146
156
  } finally {
@@ -303,7 +313,7 @@ function observeGameTime(t) {
303
313
  * state の到着とは無関係にいつでも呼べる。
304
314
  */
305
315
  function gameTime() {
306
- return asGameTime(frozenAt ?? performance.now() + offset);
316
+ return frozenAt ?? asGameTime(performance.now() + offset);
307
317
  }
308
318
  /**
309
319
  * 時計を凍らせる。
@@ -2227,4 +2237,4 @@ function calcHudInsets(params) {
2227
2237
  };
2228
2238
  }
2229
2239
  //#endregion
2230
- export { DEFAULT_ICON_URLS, ReconnectableWebSocket, Room, SERVER_TIME, SeededRandomImpl, applyJsonMergePatch, applyJsonPatch, attachDevHooks, changeRoom, createDevHooks, firstFrameReady, gameReady, gameTime, getPredictionWarnings, getRoom, init, isHosted, isPaused, isServerOnlyAction, minus, on, onPauseChange, onPlayersChanged, onRoom, playBgm, playSound, plus, run, send, serverOnly, setMicEnabled, stopBgm, sync };
2240
+ export { DEFAULT_ICON_URLS, ReconnectableWebSocket, Room, SERVER_TIME, SeededRandomImpl, applyJsonMergePatch, applyJsonPatch, attachDevHooks, changeRoom, createDevHooks, firstFrameReady, gameReady, gameTime, getPredictionWarnings, getRoom, init, isHosted, isPaused, isServerOnlyAction, minus, on, onPauseChange, onPlayersChanged, onRoom, playBgm, playSound, plus, run, send, serverOnly, setMicEnabled, stopBgm, sub, sync };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uzuhq/code-sdk",
3
- "version": "0.8.0",
3
+ "version": "0.8.1",
4
4
  "description": "UZU PlayScreen SDK - Flutter ↔ JS ゲーム通信ライブラリ",
5
5
  "type": "module",
6
6
  "exports": {