@akashic/headless-driver 2.17.10 → 2.18.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.
@@ -92,6 +92,12 @@ export declare abstract class Runner {
92
92
  * @param ms 進行するミリ秒。
93
93
  */
94
94
  abstract advance(ms: number): Promise<void>;
95
+ /**
96
+ * Runner を呼び出し時点で得られる最新状態まで進める。
97
+ * passive かつリアルタイムでのみ利用可能。
98
+ * @param timeout タイムアウトまでのミリ時間。省略時は `5000` 。ゲーム内時間ではなく実時間である点に注意。
99
+ */
100
+ abstract advanceLatest(timeout?: number): Promise<void>;
95
101
  /**
96
102
  * Runner を一フレーム進行する。
97
103
  */
@@ -18,6 +18,7 @@ export declare class RunnerV1 extends Runner {
18
18
  step(): Promise<void>;
19
19
  protected _stepMinimal(): void;
20
20
  advance(ms: number): Promise<void>;
21
+ advanceLatest(_timeout?: number): Promise<void>;
21
22
  changeGameDriverState(param: gdr.GameDriverInitializeParameterObject): Promise<void>;
22
23
  firePointEvent(event: RunnerPointEvent): void;
23
24
  getPrimarySurface(): never;
@@ -125,6 +125,11 @@ class RunnerV1 extends Runner_1.Runner {
125
125
  yield (0, promises_1.setImmediate)();
126
126
  });
127
127
  }
128
+ advanceLatest(_timeout) {
129
+ return __awaiter(this, void 0, void 0, function* () {
130
+ this.errorTrigger.fire(new Error("Runner#advanceLatest() is not supported in RunnerV1"));
131
+ });
132
+ }
128
133
  changeGameDriverState(param) {
129
134
  return new Promise((resolve, reject) => {
130
135
  if (!this.driver) {
@@ -17,6 +17,7 @@ export declare class RunnerV2 extends Runner {
17
17
  resume(): void;
18
18
  step(): Promise<void>;
19
19
  advance(ms: number): Promise<void>;
20
+ advanceLatest(timeout?: number): Promise<void>;
20
21
  changeGameDriverState(param: gdr.GameDriverInitializeParameterObject): Promise<void>;
21
22
  firePointEvent(event: RunnerPointEvent): void;
22
23
  getPrimarySurface(): never;
@@ -12,6 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.RunnerV2 = void 0;
13
13
  const promises_1 = require("node:timers/promises");
14
14
  const engine_files_v2_1 = require("engine-files-v2");
15
+ const Logger_1 = require("../../Logger");
15
16
  const Runner_1 = require("../Runner");
16
17
  const PlatformV2_1 = require("./platform/PlatformV2");
17
18
  class RunnerV2 extends Runner_1.Runner {
@@ -113,6 +114,65 @@ class RunnerV2 extends Runner_1.Runner {
113
114
  yield (0, promises_1.setImmediate)();
114
115
  });
115
116
  }
117
+ advanceLatest() {
118
+ return __awaiter(this, arguments, void 0, function* (timeout = 5000) {
119
+ var _a, _b;
120
+ if (this.driver == null) {
121
+ this.errorTrigger.fire(new Error("Cannot call Runner#advanceLatest() before initialization"));
122
+ return;
123
+ }
124
+ if (this.running) {
125
+ this.errorTrigger.fire(new Error("Cannot call Runner#advanceLatest() while running"));
126
+ return;
127
+ }
128
+ if (this.executionMode !== "passive" || this.loopMode !== "realtime") {
129
+ (0, Logger_1.getSystemLogger)().warn("RunnerV2#advanceLatest() is only available when executionMode is 'passive' and loopMode is 'realtime'");
130
+ return;
131
+ }
132
+ const tickBuffer = (_b = (_a = this.driver) === null || _a === void 0 ? void 0 : _a._gameLoop) === null || _b === void 0 ? void 0 : _b._tickBuffer;
133
+ if (!tickBuffer) {
134
+ this.errorTrigger.fire(new Error("RunnerV2#advanceLatest() aborted because tickBuffer does not exist"));
135
+ return;
136
+ }
137
+ const startTime = performance.now();
138
+ // 最新の Tick をリクエストして、トリガーを待機する Promise を準備
139
+ const gotTickPromise = new Promise((resolve, reject) => {
140
+ const timeoutId = setTimeout(() => {
141
+ reject(new Error("RunnerV2#advanceLatest() timeout: no tick response"));
142
+ }, Math.max(0, timeout - (performance.now() - startTime)));
143
+ // 新しい Tick が存在した場合
144
+ tickBuffer.gotNextTickTrigger.addOnce(() => {
145
+ clearTimeout(timeoutId);
146
+ resolve();
147
+ });
148
+ // Tick がない場合
149
+ tickBuffer.gotNoTickTrigger.addOnce(() => {
150
+ clearTimeout(timeoutId);
151
+ resolve();
152
+ });
153
+ });
154
+ // 先に requestTicks を呼び出して、並行して Tick の取得を開始
155
+ tickBuffer.requestTicks();
156
+ // gotNoTickTrigger または gotNextTickTrigger が fire するまで待機
157
+ yield gotTickPromise;
158
+ // TickBuffer#currentAge === TickBuffer#knownLatestAge になるまで進める
159
+ while (tickBuffer.currentAge < tickBuffer.knownLatestAge) {
160
+ if (performance.now() - startTime > timeout) {
161
+ this.errorTrigger.fire(new Error("RunnerV2#advanceLatest() timeout: failed to catch up to knownLatestAge"));
162
+ return;
163
+ }
164
+ // 一度に最大 100 ステップ実行
165
+ const batchSize = Math.min(100, tickBuffer.knownLatestAge - tickBuffer.currentAge);
166
+ for (let i = 0; i < batchSize; i++) {
167
+ if (tickBuffer.currentAge >= tickBuffer.knownLatestAge) {
168
+ break;
169
+ }
170
+ this._stepMinimal();
171
+ }
172
+ yield (0, promises_1.setImmediate)();
173
+ }
174
+ });
175
+ }
116
176
  changeGameDriverState(param) {
117
177
  return new Promise((resolve, reject) => {
118
178
  if (!this.driver) {
@@ -20,6 +20,7 @@ export declare class RunnerV3 extends Runner {
20
20
  resume(): void;
21
21
  step(): Promise<void>;
22
22
  advance(ms: number): Promise<void>;
23
+ advanceLatest(timeout?: number): Promise<void>;
23
24
  changeGameDriverState(param: gdr.GameDriverInitializeParameterObject): Promise<void>;
24
25
  firePointEvent(event: RunnerPointEvent): void;
25
26
  /**
@@ -11,6 +11,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.RunnerV3 = void 0;
13
13
  const promises_1 = require("node:timers/promises");
14
+ const Logger_1 = require("../../Logger");
14
15
  const Runner_1 = require("../Runner");
15
16
  const engineFiles_1 = require("./engineFiles");
16
17
  const PlatformV3_1 = require("./platform/PlatformV3");
@@ -122,6 +123,65 @@ class RunnerV3 extends Runner_1.Runner {
122
123
  yield (0, promises_1.setImmediate)();
123
124
  });
124
125
  }
126
+ advanceLatest() {
127
+ return __awaiter(this, arguments, void 0, function* (timeout = 5000) {
128
+ var _a, _b;
129
+ if (this.driver == null) {
130
+ this.errorTrigger.fire(new Error("Cannot call Runner#advanceLatest() before initialization"));
131
+ return;
132
+ }
133
+ if (this.running) {
134
+ this.errorTrigger.fire(new Error("Cannot call Runner#advanceLatest() while running"));
135
+ return;
136
+ }
137
+ if (this.executionMode !== "passive" || this.loopMode !== "realtime") {
138
+ (0, Logger_1.getSystemLogger)().warn("RunnerV3#advanceLatest() is only available when executionMode is 'passive' and loopMode is 'realtime'");
139
+ return;
140
+ }
141
+ const tickBuffer = (_b = (_a = this.driver) === null || _a === void 0 ? void 0 : _a._gameLoop) === null || _b === void 0 ? void 0 : _b._tickBuffer;
142
+ if (!tickBuffer) {
143
+ this.errorTrigger.fire(new Error("RunnerV3#advanceLatest() aborted because tickBuffer does not exist"));
144
+ return;
145
+ }
146
+ const startTime = performance.now();
147
+ // 最新の Tick をリクエストして、トリガーを待機する Promise を準備
148
+ const gotTickPromise = new Promise((resolve, reject) => {
149
+ const timeoutId = setTimeout(() => {
150
+ reject(new Error("RunnerV3#advanceLatest() timeout: no tick response"));
151
+ }, Math.max(0, timeout - (performance.now() - startTime)));
152
+ // 新しい Tick が存在した場合
153
+ tickBuffer.gotNextTickTrigger.addOnce(() => {
154
+ clearTimeout(timeoutId);
155
+ resolve();
156
+ });
157
+ // Tick がない場合
158
+ tickBuffer.gotNoTickTrigger.addOnce(() => {
159
+ clearTimeout(timeoutId);
160
+ resolve();
161
+ });
162
+ });
163
+ // 先に requestTicks を呼び出して、並行して Tick の取得を開始
164
+ tickBuffer.requestTicks();
165
+ // gotNoTickTrigger または gotNextTickTrigger が fire するまで待機
166
+ yield gotTickPromise;
167
+ // TickBuffer#currentAge === TickBuffer#knownLatestAge になるまで進める
168
+ while (tickBuffer.currentAge < tickBuffer.knownLatestAge) {
169
+ if (performance.now() - startTime > timeout) {
170
+ this.errorTrigger.fire(new Error("RunnerV3#advanceLatest() timeout: failed to catch up to knownLatestAge"));
171
+ return;
172
+ }
173
+ // 一度に最大 100 ステップ実行
174
+ const batchSize = Math.min(100, tickBuffer.knownLatestAge - tickBuffer.currentAge);
175
+ for (let i = 0; i < batchSize; i++) {
176
+ if (tickBuffer.currentAge >= tickBuffer.knownLatestAge) {
177
+ break;
178
+ }
179
+ this._stepMinimal();
180
+ }
181
+ yield (0, promises_1.setImmediate)();
182
+ }
183
+ });
184
+ }
125
185
  changeGameDriverState(param) {
126
186
  return new Promise((resolve, reject) => {
127
187
  if (!this.driver) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akashic/headless-driver",
3
- "version": "2.17.10",
3
+ "version": "2.18.0",
4
4
  "description": "A library to execute contents using Akashic Engine headlessly",
5
5
  "main": "lib/index.js",
6
6
  "author": "DWANGO Co., Ltd.",
@@ -33,7 +33,7 @@
33
33
  "@akashic/trigger": "^2.0.0",
34
34
  "engine-files-v1": "npm:@akashic/engine-files@1.4.0",
35
35
  "engine-files-v2": "npm:@akashic/engine-files@2.4.0",
36
- "engine-files-v3": "npm:@akashic/engine-files@3.13.2",
36
+ "engine-files-v3": "npm:@akashic/engine-files@3.13.3",
37
37
  "js-sha256": "^0.11.0",
38
38
  "lodash.clonedeep": "^4.5.0",
39
39
  "node-fetch": "^2.6.7"
@@ -42,7 +42,7 @@
42
42
  "@akashic/eslint-config": "^3.0.2",
43
43
  "@akashic/remark-preset-lint": "^0.1.2",
44
44
  "@napi-rs/canvas": "^0.1.66",
45
- "@types/jest": "^29.1.1",
45
+ "@types/jest": "^30.0.0",
46
46
  "@types/lodash.clonedeep": "^4.5.7",
47
47
  "@types/node": "^24.0.0",
48
48
  "@types/node-fetch": "^2.6.2",
@@ -52,7 +52,7 @@
52
52
  "eslint-config-prettier": "^10.0.0",
53
53
  "get-port": "^5.1.1",
54
54
  "image-size": "^1.0.2",
55
- "jest": "^29.1.2",
55
+ "jest": "^30.0.0",
56
56
  "npm-run-all": "^4.1.5",
57
57
  "pixelmatch": "^5.3.0",
58
58
  "pngjs": "^7.0.0",
@@ -60,7 +60,7 @@
60
60
  "remark-cli": "^12.0.0",
61
61
  "rimraf": "^6.0.0",
62
62
  "serve-handler": "^6.1.3",
63
- "ts-jest": "^29.2.5",
63
+ "ts-jest": "^29.4.6",
64
64
  "typescript": "^5.7.3"
65
65
  },
66
66
  "jest": {