@uzuhq/code-sdk 0.8.0 → 0.8.2
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 +10 -8
- package/dist/dev-globals.d.ts +1 -1
- package/dist/{dev-hooks-D6CbhPDP.d.ts → dev-hooks-DOtJHP55.d.ts} +31 -5
- package/dist/index.d.ts +2 -2
- package/dist/index.js +29 -9
- package/package.json +1 -1
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`
|
|
310
|
-
| `ctx.after(d)`
|
|
311
|
-
| `gameTime()`
|
|
312
|
-
| `plus(t, d)` / `
|
|
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` は
|
|
327
|
-
`Date.now()`
|
|
327
|
+
`GameTime` は brand 型なので実行時はただの数値で、state は素の JSON のまま。ただし型の上では
|
|
328
|
+
`number` と混ざらないので、`Date.now()` を書き込む式も `endsAt - Date.now()` と読む式も
|
|
329
|
+
コンパイルが通らない。
|
|
328
330
|
|
|
329
331
|
### 緊急一時停止
|
|
330
332
|
|
package/dist/dev-globals.d.ts
CHANGED
|
@@ -94,21 +94,47 @@ 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
|
-
/**
|
|
98
|
-
type
|
|
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
|
-
*
|
|
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;
|
|
128
|
+
/**
|
|
129
|
+
* ゲーム内時計の原点。ゲーム開始の瞬間で、`setup()` の `ctx.time` と同じ値。
|
|
130
|
+
*
|
|
131
|
+
* `minus(t, GAME_START)` がゲーム開始からの経過 ms になる。表示やログのために
|
|
132
|
+
* 素の数値が要る場面は、これを使えば cast を書かずに済む。
|
|
133
|
+
*
|
|
134
|
+
* `toMs` を公開しないのは `toMs(a) - toMs(b)` と書けて保護が丸ごと消えるためだが、
|
|
135
|
+
* `GAME_START` にその使い方は無い。差を取るには結局 `minus` を通る。
|
|
136
|
+
*/
|
|
137
|
+
declare const GAME_START: GameTime;
|
|
112
138
|
//#endregion
|
|
113
139
|
//#region ../engine-core/src/types.d.ts
|
|
114
140
|
/**
|
|
@@ -712,4 +738,4 @@ interface DevHooksCtx<S = unknown> {
|
|
|
712
738
|
declare function createDevHooks<S>(ctx: DevHooksCtx<S>): UzuDevHooks<S>;
|
|
713
739
|
declare function attachDevHooks<S>(ctx: DevHooksCtx<S>): void;
|
|
714
740
|
//#endregion
|
|
715
|
-
export {
|
|
741
|
+
export { GameTime 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, GAME_START 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, applyJsonMergePatch as at, PlayersChangedMessage as b, getPredictionWarnings as c, ConnectionCallbacks as d, minus as et, ConnectionState as f, PatchFn as g, GameConfig as h, UzuDevHooks as i, JsonPatchOp as it, Deadline as j, ActionMap as k, BridgeChannel as l, EventSubscription as m, RunHandle as n, sub as nt, createDevHooks as o, applyJsonPatch as ot, EventHandler as p, SetupArgs as q, SyncHandle as r, JsonMergePatch as rt, PredictionWarning as s, DevHooksCtx as t, plus 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
|
|
1
|
+
import { $ as GameTime, 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 GAME_START, 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 applyJsonMergePatch, b as PlayersChangedMessage, c as getPredictionWarnings, d as ConnectionCallbacks, et as minus, f as ConnectionState, g as PatchFn, h as GameConfig, i as UzuDevHooks, it as JsonPatchOp, j as Deadline, k as ActionMap, l as BridgeChannel, m as EventSubscription, n as RunHandle, nt as sub, o as createDevHooks, ot as applyJsonPatch, p as EventHandler, q as SetupArgs, r as SyncHandle, rt as JsonMergePatch, s as PredictionWarning, t as DevHooksCtx, tt as plus, u as BridgeMessage, v as PlayScreenMessage, w as SyncConfig, x as SeatKind, y as PlayerVoiceState, z as ServerActionArgs } from "./dev-hooks-DOtJHP55.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, GAME_START, 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,20 +10,39 @@ 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
|
-
*
|
|
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
|
*
|
|
24
33
|
* 時計の実装 (play-server の facet / dev-server / ソロ / SDK の補間) だけがここを通る。
|
|
25
34
|
*/
|
|
26
35
|
const asGameTime = (ms) => ms;
|
|
36
|
+
/**
|
|
37
|
+
* ゲーム内時計の原点。ゲーム開始の瞬間で、`setup()` の `ctx.time` と同じ値。
|
|
38
|
+
*
|
|
39
|
+
* `minus(t, GAME_START)` がゲーム開始からの経過 ms になる。表示やログのために
|
|
40
|
+
* 素の数値が要る場面は、これを使えば cast を書かずに済む。
|
|
41
|
+
*
|
|
42
|
+
* `toMs` を公開しないのは `toMs(a) - toMs(b)` と書けて保護が丸ごと消えるためだが、
|
|
43
|
+
* `GAME_START` にその使い方は無い。差を取るには結局 `minus` を通る。
|
|
44
|
+
*/
|
|
45
|
+
const GAME_START = asGameTime(0);
|
|
27
46
|
//#endregion
|
|
28
47
|
//#region ../engine-core/src/game-clock.ts
|
|
29
48
|
/**
|
|
@@ -74,7 +93,7 @@ var GameClock = class {
|
|
|
74
93
|
}
|
|
75
94
|
/** ゲーム内時刻を、alarm / setTimeout が使う実時刻へ直す。 */
|
|
76
95
|
toWall(at) {
|
|
77
|
-
return at + this.startedAtWall + this.pausedTotalMs;
|
|
96
|
+
return toMs(at) + this.startedAtWall + this.pausedTotalMs;
|
|
78
97
|
}
|
|
79
98
|
/** 実際に理由を足したら true。呼び出し側が永続化や tick 停止の要否に使う。 */
|
|
80
99
|
freeze(reason) {
|
|
@@ -139,8 +158,9 @@ var GameClock = class {
|
|
|
139
158
|
function withGameClock(time, fn) {
|
|
140
159
|
const realNow = Date.now;
|
|
141
160
|
const RealDate = Date;
|
|
142
|
-
|
|
143
|
-
|
|
161
|
+
const ms = toMs(time);
|
|
162
|
+
Date.now = () => ms;
|
|
163
|
+
globalThis.Date = new Proxy(RealDate, { construct: (target, args) => Reflect.construct(target, args.length === 0 ? [ms] : args) });
|
|
144
164
|
try {
|
|
145
165
|
return fn();
|
|
146
166
|
} finally {
|
|
@@ -303,7 +323,7 @@ function observeGameTime(t) {
|
|
|
303
323
|
* state の到着とは無関係にいつでも呼べる。
|
|
304
324
|
*/
|
|
305
325
|
function gameTime() {
|
|
306
|
-
return
|
|
326
|
+
return frozenAt ?? asGameTime(performance.now() + offset);
|
|
307
327
|
}
|
|
308
328
|
/**
|
|
309
329
|
* 時計を凍らせる。
|
|
@@ -2227,4 +2247,4 @@ function calcHudInsets(params) {
|
|
|
2227
2247
|
};
|
|
2228
2248
|
}
|
|
2229
2249
|
//#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 };
|
|
2250
|
+
export { DEFAULT_ICON_URLS, GAME_START, 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 };
|