From 38ea0b2b7093ec09abcb2028aa6b5abea7502171 Mon Sep 17 00:00:00 2001 From: yu-ogi Date: Wed, 13 Nov 2024 09:17:19 +0900 Subject: [PATCH 1/9] feat: support assetBundle --- src/AssetManager.ts | 56 +++++++++++++++++++++----- src/Game.ts | 9 +++-- src/InitialScene.ts | 45 +++++++++++++++++++++ src/__tests__/GameSpec.ts | 6 +-- src/__tests__/InitialSceneSpec.ts | 62 +++++++++++++++++++++++++++++ src/auxiliary/BundledScriptAsset.ts | 53 ++++++++++++++++++++++++ src/index.common.ts | 1 + 7 files changed, 215 insertions(+), 17 deletions(-) create mode 100644 src/InitialScene.ts create mode 100644 src/__tests__/InitialSceneSpec.ts create mode 100644 src/auxiliary/BundledScriptAsset.ts diff --git a/src/AssetManager.ts b/src/AssetManager.ts index 5e79f4996..dc9c911fd 100644 --- a/src/AssetManager.ts +++ b/src/AssetManager.ts @@ -12,7 +12,9 @@ import type { VideoAssetConfigurationBase, VectorImageAssetConfigurationBase, BinaryAssetConfigurationBase, - ModuleMainPathsMap + ModuleMainPathsMap, + AssetBundleConfiguration, + BundledAssetConfiguration } from "@akashic/game-configuration"; import type { Asset, @@ -32,6 +34,7 @@ import type { AssetGenerationConfiguration } from "./AssetGenerationConfiguratio import type { AssetManagerLoadHandler } from "./AssetManagerLoadHandler"; import type { AudioSystem } from "./AudioSystem"; import type { AudioSystemManager } from "./AudioSystemManager"; +import { BundledScriptAsset } from "./auxiliary/BundledScriptAsset"; import { EmptyBinaryAsset } from "./auxiliary/EmptyBinaryAsset"; import { EmptyGeneratedVectorImageAsset } from "./auxiliary/EmptyGeneratedVectorImageAsset"; import { EmptyVectorImageAsset } from "./auxiliary/EmptyVectorImageAsset"; @@ -261,6 +264,11 @@ export class AssetManager implements AssetLoadHandler { */ private _generatedAssetCount: number; + /** + * アセットバンドル。 + */ + private _assetBundle: AssetBundleConfiguration | null; + /** * `AssetManager` のインスタンスを生成する。 * @@ -290,6 +298,7 @@ export class AssetManager implements AssetLoadHandler { this._refCounts = {}; this._loadings = {}; this._generatedAssetCount = 0; + this._assetBundle = null; const assetIds = Object.keys(this.configuration); for (let i = 0; i < assetIds.length; ++i) { @@ -313,6 +322,7 @@ export class AssetManager implements AssetLoadHandler { this._liveAssetPathTable = undefined!; this._refCounts = undefined!; this._loadings = undefined!; + this._assetBundle = undefined!; } /** @@ -563,6 +573,10 @@ export class AssetManager implements AssetLoadHandler { return "/" + virtualPath; } + setAssetBundle(assetBundle: AssetBundleConfiguration): void { + this._assetBundle = assetBundle; + } + /** * @ignore */ @@ -648,7 +662,23 @@ export class AssetManager implements AssetLoadHandler { let id: string; let uri: string; let conf: AssetConfiguration | DynamicAssetConfiguration; - if (typeof idOrConf === "string") { + if (this._assetBundle && typeof idOrConf === "string") { + const id = idOrConf; + const conf = this._assetBundle.assets[id] as BundledAssetConfiguration; + const type = conf.type; + switch (type) { + case "script": + const asset = new BundledScriptAsset({ + id, + ...conf + }); + return asset; + default: + throw ExceptionFactory.createAssertionError( + `AssertionError#_createAssetFor: unknown asset type ${type} for asset ID: ${id}` + ); + } + } else if (typeof idOrConf === "string") { id = idOrConf; conf = this.configuration[id]; uri = this.configuration[id].path; @@ -849,17 +879,23 @@ export class AssetManager implements AssetLoadHandler { */ _addAssetToTables(asset: OneOfAsset): void { this._assets[asset.id] = asset; + let path: string | undefined; // DynamicAsset の場合は configuration に書かれていないので以下の判定が偽になる if (this.configuration[asset.id]) { - const virtualPath = this.configuration[asset.id].virtualPath!; // virtualPath の存在は _normalize() で確認済みのため 非 null アサーションとする - if (!this._liveAssetVirtualPathTable.hasOwnProperty(virtualPath)) { - this._liveAssetVirtualPathTable[virtualPath] = asset; - } else { - if (this._liveAssetVirtualPathTable[virtualPath].path !== asset.path) - throw ExceptionFactory.createAssertionError("AssetManager#_onAssetLoad(): duplicated asset path"); - } - if (!this._liveAssetPathTable.hasOwnProperty(asset.path)) this._liveAssetPathTable[asset.path] = virtualPath; + path = this.configuration[asset.id].virtualPath!; // virtualPath の存在は _normalize() で確認済みのため 非 null アサーションとする + } else if (this._assetBundle && this._assetBundle.assets[asset.id]) { + path = this._assetBundle.assets[asset.id].path; + } + + if (!path) return; + + if (!this._liveAssetVirtualPathTable.hasOwnProperty(path)) { + this._liveAssetVirtualPathTable[path] = asset; + } else { + if (this._liveAssetVirtualPathTable[path].path !== asset.path) + throw ExceptionFactory.createAssertionError("AssetManager#_onAssetLoad(): duplicated asset path"); } + if (!this._liveAssetPathTable.hasOwnProperty(asset.path)) this._liveAssetPathTable[asset.path] = path; } } diff --git a/src/Game.ts b/src/Game.ts index d7194931d..22a3ae3f0 100644 --- a/src/Game.ts +++ b/src/Game.ts @@ -25,6 +25,7 @@ import type { EventFilter } from "./EventFilter"; import { ExceptionFactory } from "./ExceptionFactory"; import type { GameHandlerSet } from "./GameHandlerSet"; import type { GameMainParameterObject } from "./GameMainParameterObject"; +import { InitialScene } from "./InitialScene"; import { LoadingScene } from "./LoadingScene"; import type { LocalTickModeString } from "./LocalTickModeString"; import { ModuleManager } from "./ModuleManager"; @@ -33,7 +34,7 @@ import { OperationPluginManager } from "./OperationPluginManager"; import type { InternalOperationPluginOperation } from "./OperationPluginOperation"; import { PointEventResolver } from "./PointEventResolver"; import type { RandomGenerator } from "./RandomGenerator"; -import { Scene } from "./Scene"; +import type { Scene } from "./Scene"; import type { SnapshotSaveRequest } from "./SnapshotSaveRequest"; import { SurfaceAtlasSet } from "./SurfaceAtlasSet"; import type { TickGenerationModeString } from "./TickGenerationModeString"; @@ -640,7 +641,7 @@ export class Game { * グローバルアセットを読み込むための初期シーン。必ずシーンスタックの一番下に存在する。これをpopScene()することはできない。 * @private */ - _initialScene: Scene; + _initialScene: InitialScene; /** * デフォルトローディングシーン。 @@ -1009,13 +1010,13 @@ export class Game { this.onUpdate = new Trigger(); - this._initialScene = new Scene({ + this._initialScene = new InitialScene({ game: this, assetIds: this._assetManager.globalAssetIds(), local: true, name: "akashic:initial-scene" }); - this._initialScene.onLoad.add(this._handleInitialSceneLoad, this); + this._initialScene.onAllAssetsLoad.add(this._handleInitialSceneLoad, this); this._reset({ age: 0 }); } diff --git a/src/InitialScene.ts b/src/InitialScene.ts new file mode 100644 index 000000000..3b0dec581 --- /dev/null +++ b/src/InitialScene.ts @@ -0,0 +1,45 @@ +import type { AssetBundleConfiguration } from "@akashic/game-configuration"; +import { Trigger } from "@akashic/trigger"; +import type { SceneParameterObject } from "./Scene"; +import { Scene } from "./Scene"; + +/** + * グローバルアセットを読み込むための初期シーン。 + */ +export class InitialScene extends Scene { + /** + * ゲームの実行に必要なグローバルアセットがすべて読み込まれた際に発火される Trigger。 + * `gameConfiguration` に `assetBundle` が指定されている場合は、そのアセットもすべて読み込み完了後に発火される。 + * 一方、`this.onLoad` は `gameConfiguration` の `assetBundle` 指定を無視して発火する点に注意が必要。 + */ + onAllAssetsLoad: Trigger; + + constructor(param: SceneParameterObject) { + super(param); + this.onAllAssetsLoad = new Trigger(); + this.onLoad.add(this._handleLoad, this); + } + + override destroy(): void { + super.destroy(); + if (!this.onAllAssetsLoad.destroyed()) { + this.onAllAssetsLoad.destroy(); + } + this.onAllAssetsLoad = undefined!; + } + + _handleLoad(): void { + if (this.game._configuration.assetBundle) { + const assetBundle: AssetBundleConfiguration = this.game._moduleManager._internalRequire(this.game._configuration.assetBundle); + this.game._assetManager.setAssetBundle(assetBundle); + const assetIds = Object.keys(assetBundle.assets); + this.requestAssets(assetIds, this._handleRequestAssets.bind(this)); + } else { + this.onAllAssetsLoad.fire(); + } + } + + _handleRequestAssets(): void { + this.onAllAssetsLoad.fire(); + } +} diff --git a/src/__tests__/GameSpec.ts b/src/__tests__/GameSpec.ts index 01750f377..56cc7f0ba 100644 --- a/src/__tests__/GameSpec.ts +++ b/src/__tests__/GameSpec.ts @@ -1398,12 +1398,12 @@ describe("test Game", () => { }); const loadScene = game._defaultLoadingScene; - expect(game._initialScene.onLoad.contains(game._handleInitialSceneLoad, game)).toBe(true); + expect(game._initialScene.onAllAssetsLoad.contains(game._handleInitialSceneLoad, game)).toBe(true); expect(loadScene.onLoad.contains(loadScene._doReset, loadScene)).toBe(false); game._loadAndStart(); expect(game.isLoaded).toBe(false); // _loadAndStartしたがまだ読み込みは終わっていない - expect(game._initialScene.onLoad.contains(game._handleInitialSceneLoad, game)).toBe(true); + expect(game._initialScene.onAllAssetsLoad.contains(game._handleInitialSceneLoad, game)).toBe(true); expect(game.scenes.length).toBe(2); expect(game.scenes[0]).toBe(game._initialScene); expect(game.scenes[1]).toBe(loadScene); @@ -1413,7 +1413,7 @@ describe("test Game", () => { expect(loadScene2).not.toBe(loadScene); expect(loadScene.destroyed()).toBe(true); expect(game.isLoaded).toBe(false); - expect(game._initialScene.onLoad.contains(game._handleInitialSceneLoad, game)).toBe(true); + expect(game._initialScene.onAllAssetsLoad.contains(game._handleInitialSceneLoad, game)).toBe(true); expect(loadScene2.onLoad.contains(loadScene2._doReset, loadScene2)).toBe(false); expect(game.scenes.length).toBe(0); diff --git a/src/__tests__/InitialSceneSpec.ts b/src/__tests__/InitialSceneSpec.ts new file mode 100644 index 000000000..88f5f769a --- /dev/null +++ b/src/__tests__/InitialSceneSpec.ts @@ -0,0 +1,62 @@ +import type { GameConfiguration } from ".."; +import { Game } from "./helpers"; + +describe("test InitialScene", () => { + const configuration: GameConfiguration = { + width: 320, + height: 320, + main: "./main.js", + assetBundle: "./asset.bundle.js", + assets: { + main: { + type: "script", + path: "./main.js", + virtualPath: "main.js", + global: true + }, + "asset.bundle": { + type: "script", + path: "./asset.bundle.js", + virtualPath: "asset.bundle.js", + global: true + } + } + }; + const assetBundle = `{ + assets: { + "/script/module.js": { + type: "script", + path: "script/module.js", + execute: (runtimeValue) => { + const { module } = runtimeValue; + const exports = module.exports; + + exports.multiply = (a, b) => { + return a * b; + } + + return module.exports; + } + } + }, + }`; + + it("should load from asset.bundle.js instead of the defined asset", done => { + const game = new Game(configuration); + game.resourceFactory.scriptContents["./main.js"] = "module.exports = () => g.game.__entry_point__();"; + game.resourceFactory.scriptContents["./asset.bundle.js"] = `module.exports = ${assetBundle}`; + (game as any).__entry_point__ = () => { + const assetBundle = game._moduleManager._internalRequire(configuration.assetBundle!); + expect(assetBundle.assets["/script/module.js"]).toBeDefined(); + expect(assetBundle.assets["/script/module.js"].type).toBe("script"); + expect(assetBundle.assets["/script/module.js"].path).toBe("script/module.js"); + expect(assetBundle.assets["/script/module.js"].execute).toBeInstanceOf(Function); + + const module = game._moduleManager._internalRequire("./script/module.js"); + expect(module.multiply).toBeInstanceOf(Function); + expect(module.multiply(2, 10)).toBe(20); + done(); + }; + game._loadAndStart(); + }); +}); diff --git a/src/auxiliary/BundledScriptAsset.ts b/src/auxiliary/BundledScriptAsset.ts new file mode 100644 index 000000000..fada0b54e --- /dev/null +++ b/src/auxiliary/BundledScriptAsset.ts @@ -0,0 +1,53 @@ +import type { Asset, AssetLoadHandler, ScriptAsset, ScriptAssetRuntimeValue } from "@akashic/pdi-types"; +import { Trigger } from "@akashic/trigger"; + +export interface BundledScriptAssetParameterObject { + id: string; + type: string; + path: string; + execute: (execEnv: ScriptAssetRuntimeValue) => any; +} + +export class BundledScriptAsset implements ScriptAsset { + type: "script"; + script: string; + exports?: string[] | undefined; + id: string; + path: string; + originalPath: string; + onDestroyed: Trigger; + execute: (execEnv: ScriptAssetRuntimeValue) => any; + + constructor(param: BundledScriptAssetParameterObject) { + this.type = "script"; + this.id = param.id; + this.script = ""; + this.path = param.path; + this.originalPath = param.path; + this.onDestroyed = new Trigger(); + this.execute = param.execute.bind(this); + } + + inUse(): boolean { + return true; + } + + destroy(): void { + if (!this.onDestroyed.destroyed()) { + this.onDestroyed.destroy(); + } + this.execute = undefined!; + } + + destroyed(): boolean { + return !this.execute; + } + + _load(loader: AssetLoadHandler): void { + loader._onAssetLoad(this); + } + + _assetPathFilter(path: string): string { + return path; + } +} diff --git a/src/index.common.ts b/src/index.common.ts index 322f6debd..a47eebf6d 100644 --- a/src/index.common.ts +++ b/src/index.common.ts @@ -51,6 +51,7 @@ export * from "./EventPriority"; export * from "./ExceptionFactory"; export * from "./Font"; export * from "./GameMainParameterObject"; +export * from "./InitialScene"; export * from "./InternalOperationPluginInfo"; export * from "./LoadingScene"; export * from "./LocalTickModeString"; From ae344e7fc7dad767ed69706ebc931abff6cf6486 Mon Sep 17 00:00:00 2001 From: yu-ogi Date: Thu, 14 Nov 2024 09:21:35 +0900 Subject: [PATCH 2/9] fix: support preload --- src/AssetManager.ts | 20 +++++++++++++++++--- src/ModuleManager.ts | 10 ++++------ 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/AssetManager.ts b/src/AssetManager.ts index dc9c911fd..3a210de98 100644 --- a/src/AssetManager.ts +++ b/src/AssetManager.ts @@ -372,9 +372,23 @@ export class AssetManager implements AssetLoadHandler { * プリロードすべきスクリプトアセットのIDを全て返す。 */ preloadScriptAssetIds(): string[] { - return Object.entries(this.configuration) - .filter(([, conf]) => conf.type === "script" && conf.global && conf.preload) - .map(([assetId]) => assetId); + const assetIds: string[] = []; + + if (this._assetBundle) { + assetIds.push( + ...Object.entries(this._assetBundle.assets) + .filter(([, conf]) => conf.type === "script" && conf.preload) + .map(([assetId]) => assetId) + ); + } + + assetIds.push( + ...Object.entries(this.configuration) + .filter(([, conf]) => conf.type === "script" && conf.global && conf.preload) + .map(([assetId]) => assetId) + ); + + return assetIds; } /** diff --git a/src/ModuleManager.ts b/src/ModuleManager.ts index ae862c681..d3a30448a 100644 --- a/src/ModuleManager.ts +++ b/src/ModuleManager.ts @@ -76,12 +76,10 @@ export class ModuleManager { const liveAssetVirtualPathTable = this._assetManager._liveAssetVirtualPathTable; const moduleMainScripts = this._assetManager._moduleMainScripts; - // 0. アセットIDらしい場合はまず当該アセットを探す - if (path.indexOf("/") === -1) { - if (this._assetManager._assets.hasOwnProperty(path)) { - targetScriptAsset = this._assetManager._assets[path]; - resolvedPath = this._assetManager._liveAssetPathTable[targetScriptAsset.path]; - } + // 0. アセットIDと一致した場合は当該アセットを返す + if (this._assetManager._assets.hasOwnProperty(path)) { + targetScriptAsset = this._assetManager._assets[path]; + resolvedPath = this._assetManager._liveAssetPathTable[targetScriptAsset.path]; } if (!resolvedPath) { From 18a2d2ad80dbbd24e2be6dfa0467d303d0091caa Mon Sep 17 00:00:00 2001 From: yu-ogi Date: Thu, 14 Nov 2024 09:22:30 +0900 Subject: [PATCH 3/9] chore: add comment --- src/AssetManager.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/AssetManager.ts b/src/AssetManager.ts index 3a210de98..030d0864e 100644 --- a/src/AssetManager.ts +++ b/src/AssetManager.ts @@ -587,7 +587,12 @@ export class AssetManager implements AssetLoadHandler { return "/" + virtualPath; } - setAssetBundle(assetBundle: AssetBundleConfiguration): void { + /** + * アセットバンドルを設定する。 + * + * @param assetBundle アセットバンドル + */ + setAssetBundle(assetBundle: AssetBundleConfiguration | null): void { this._assetBundle = assetBundle; } From cbddfe9eeed347d934d06fe381e94c1df9b17ec4 Mon Sep 17 00:00:00 2001 From: yu-ogi Date: Thu, 14 Nov 2024 09:38:38 +0900 Subject: [PATCH 4/9] chore: add a test to verify that the preload script runs --- src/__tests__/InitialSceneSpec.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/__tests__/InitialSceneSpec.ts b/src/__tests__/InitialSceneSpec.ts index 88f5f769a..53375dd41 100644 --- a/src/__tests__/InitialSceneSpec.ts +++ b/src/__tests__/InitialSceneSpec.ts @@ -24,6 +24,21 @@ describe("test InitialScene", () => { }; const assetBundle = `{ assets: { + "/script/preload.js": { + type: "script", + path: "script/preload.js", + preload: true, + execute: (runtimeValue) => { + const { module } = runtimeValue; + const exports = module.exports; + + module.exports = () => { + g.game.vars.preloaded = true; + } + + return module.exports; + } + }, "/script/module.js": { type: "script", path: "script/module.js", @@ -37,7 +52,7 @@ describe("test InitialScene", () => { return module.exports; } - } + }, }, }`; @@ -46,6 +61,8 @@ describe("test InitialScene", () => { game.resourceFactory.scriptContents["./main.js"] = "module.exports = () => g.game.__entry_point__();"; game.resourceFactory.scriptContents["./asset.bundle.js"] = `module.exports = ${assetBundle}`; (game as any).__entry_point__ = () => { + expect(game.vars.preloaded).toBe(true); // エントリポイントに先行して /script/preload.js が実行されていることを確認 + const assetBundle = game._moduleManager._internalRequire(configuration.assetBundle!); expect(assetBundle.assets["/script/module.js"]).toBeDefined(); expect(assetBundle.assets["/script/module.js"].type).toBe("script"); From 4dd00c0bb2539c615d5ac928f1392df0a0001ce6 Mon Sep 17 00:00:00 2001 From: yu-ogi Date: Mon, 18 Nov 2024 15:19:50 +0900 Subject: [PATCH 5/9] fix: fix the behavior to require paths that start with `../` or `/`. --- src/AssetManager.ts | 18 ++++++++++-------- src/Game.ts | 8 ++++---- src/ModuleManager.ts | 19 ++++++++++++------- src/__tests__/AssetManagerSpec.ts | 22 +++++++++++----------- 4 files changed, 37 insertions(+), 30 deletions(-) diff --git a/src/AssetManager.ts b/src/AssetManager.ts index 030d0864e..ec22d2c78 100644 --- a/src/AssetManager.ts +++ b/src/AssetManager.ts @@ -369,26 +369,28 @@ export class AssetManager implements AssetLoadHandler { } /** - * プリロードすべきスクリプトアセットのIDを全て返す。 + * プリロードすべきスクリプトアセットの path を全て返す。 */ - preloadScriptAssetIds(): string[] { - const assetIds: string[] = []; + preloadScriptAssetPaths(): string[] { + let assetPaths: string[] = []; if (this._assetBundle) { - assetIds.push( + assetPaths.push( ...Object.entries(this._assetBundle.assets) .filter(([, conf]) => conf.type === "script" && conf.preload) - .map(([assetId]) => assetId) + .map(([, conf]) => conf.path) ); } - assetIds.push( + assetPaths.push( ...Object.entries(this.configuration) .filter(([, conf]) => conf.type === "script" && conf.global && conf.preload) - .map(([assetId]) => assetId) + .map(([, conf]) => conf.virtualPath!) // この箇所ではすでに virtualPath が補完されていることが前提 ); - return assetIds; + assetPaths = assetPaths.map(path => (path.startsWith("./") ? path : `./${path}`)); + + return assetPaths; } /** diff --git a/src/Game.ts b/src/Game.ts index 22a3ae3f0..6773423ec 100644 --- a/src/Game.ts +++ b/src/Game.ts @@ -2014,11 +2014,11 @@ export class Game { } this.operationPlugins = this.operationPluginManager.plugins; - const preloadAssetIds = this._assetManager.preloadScriptAssetIds(); - for (const preloadAssetId of preloadAssetIds) { - const fun = this._moduleManager._internalRequire(preloadAssetId); + const preloadAssetPaths = this._assetManager.preloadScriptAssetPaths(); + for (const preloadAssetPath of preloadAssetPaths) { + const fun = this._moduleManager._internalRequire(preloadAssetPath); if (!fun || typeof fun !== "function") - throw ExceptionFactory.createAssertionError(`Game#_handleLoad: ${preloadAssetId} has no-exported function.`); + throw ExceptionFactory.createAssertionError(`Game#_handleLoad: ${preloadAssetPath} has no-exported function.`); fun(); } diff --git a/src/ModuleManager.ts b/src/ModuleManager.ts index d3a30448a..76c30c6d3 100644 --- a/src/ModuleManager.ts +++ b/src/ModuleManager.ts @@ -76,10 +76,12 @@ export class ModuleManager { const liveAssetVirtualPathTable = this._assetManager._liveAssetVirtualPathTable; const moduleMainScripts = this._assetManager._moduleMainScripts; - // 0. アセットIDと一致した場合は当該アセットを返す - if (this._assetManager._assets.hasOwnProperty(path)) { - targetScriptAsset = this._assetManager._assets[path]; - resolvedPath = this._assetManager._liveAssetPathTable[targetScriptAsset.path]; + // 0. アセットIDらしい場合はまず当該アセットを探す + if (path.indexOf("/") === -1) { + if (this._assetManager._assets.hasOwnProperty(path)) { + targetScriptAsset = this._assetManager._assets[path]; + resolvedPath = this._assetManager._liveAssetPathTable[targetScriptAsset.path]; + } } if (!resolvedPath) { @@ -154,14 +156,17 @@ export class ModuleManager { if (currentModule) { if (!currentModule._virtualDirname) { - throw ExceptionFactory.createAssertionError("g._require.resolve: couldn't resolve the moudle path without virtualPath"); + throw ExceptionFactory.createAssertionError("g._require.resolve: couldn't resolve the module path without virtualPath"); } resolvedPath = PathUtil.resolvePath(currentModule._virtualDirname, path); } else { - if (!/^\.\//.test(path)) { + if (/^\.\//.test(path)) { + resolvedPath = path.substring(2); + } else if (/^\//.test(path)) { + resolvedPath = path.substring(1); + } else { throw ExceptionFactory.createAssertionError("g._require.resolve: entry point path must start with './'"); } - resolvedPath = path.substring(2); } // 2.a. LOAD_AS_FILE(Y + X) diff --git a/src/__tests__/AssetManagerSpec.ts b/src/__tests__/AssetManagerSpec.ts index 4f3fc973b..e106c57f3 100644 --- a/src/__tests__/AssetManagerSpec.ts +++ b/src/__tests__/AssetManagerSpec.ts @@ -739,35 +739,35 @@ describe("test AssetManager", () => { assets: { asset1: { type: "script", - path: "/path/to/real/file", - virtualPath: "path/to/virtual/file", + path: "/path/to/real/file1", + virtualPath: "path/to/virtual/file1", global: true }, asset2: { type: "script", - path: "/path/to/real/file", - virtualPath: "path/to/virtual/file", + path: "/path/to/real/file2", + virtualPath: "path/to/virtual/file2", global: true, preload: false }, asset3: { type: "script", - path: "/path/to/real/file", - virtualPath: "path/to/virtual/file", + path: "/path/to/real/file3", + virtualPath: "path/to/virtual/file3", global: true, preload: true }, asset4: { type: "script", - path: "/path/to/real/file", - virtualPath: "path/to/virtual/file", + path: "/path/to/real/file4", + virtualPath: "path/to/virtual/file4", global: true, preload: 0 as any }, asset5: { type: "script", - path: "/path/to/real/file", - virtualPath: "path/to/virtual/file", + path: "/path/to/real/file5", + virtualPath: "path/to/virtual/file5", global: true, preload: true } @@ -778,7 +778,7 @@ describe("test AssetManager", () => { const manager = game._assetManager; // NOTE: 配列の順序は実装依存であることに注意 - expect(manager.preloadScriptAssetIds()).toEqual(["asset3", "asset5"]); + expect(manager.preloadScriptAssetPaths()).toEqual(["./path/to/virtual/file3", "./path/to/virtual/file5"]); }); it("can get accessorPath from assetId", async () => { From 69f3a1ee2f22a9567f19f626f8081227745d6a8a Mon Sep 17 00:00:00 2001 From: yu-ogi Date: Wed, 20 Nov 2024 08:38:31 +0900 Subject: [PATCH 6/9] chore: use `Object.values()` instead of `Object.entries()` --- src/AssetManager.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/AssetManager.ts b/src/AssetManager.ts index ec22d2c78..d387a144f 100644 --- a/src/AssetManager.ts +++ b/src/AssetManager.ts @@ -376,16 +376,16 @@ export class AssetManager implements AssetLoadHandler { if (this._assetBundle) { assetPaths.push( - ...Object.entries(this._assetBundle.assets) - .filter(([, conf]) => conf.type === "script" && conf.preload) - .map(([, conf]) => conf.path) + ...Object.values(this._assetBundle.assets) + .filter(conf => conf.type === "script" && conf.preload) + .map(conf => conf.path) ); } assetPaths.push( - ...Object.entries(this.configuration) - .filter(([, conf]) => conf.type === "script" && conf.global && conf.preload) - .map(([, conf]) => conf.virtualPath!) // この箇所ではすでに virtualPath が補完されていることが前提 + ...Object.values(this.configuration) + .filter(conf => conf.type === "script" && conf.global && conf.preload) + .map(conf => conf.virtualPath!) // この箇所ではすでに virtualPath が補完されていることが前提 ); assetPaths = assetPaths.map(path => (path.startsWith("./") ? path : `./${path}`)); From a6c96be3d39d62359bf9197e58a8dd00bf26d7a6 Mon Sep 17 00:00:00 2001 From: yu-ogi Date: Wed, 20 Nov 2024 08:38:45 +0900 Subject: [PATCH 7/9] chore: update CHANGELOG.md --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 734409784..bd4fb570b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # ChangeLog +## unreleased changes +* @akashic/game-configuration@2.4.0 に追従 + * `assetBundle` に対応 + * `BundledScriptAsset` を追加 + ## 3.18.3 * `g.E#destroy()` で破棄済みチェックを行うように修正 From 2ec763c4e538c9339fe0fc73bce6a4b4e1efe40d Mon Sep 17 00:00:00 2001 From: yu-ogi Date: Wed, 20 Nov 2024 09:01:12 +0900 Subject: [PATCH 8/9] chore(deps): update game-configuration to 2.4.0 --- package-lock.json | 9 +++++---- package.json | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index f7a274a37..c550768f5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "3.18.3", "license": "MIT", "dependencies": { - "@akashic/game-configuration": "~2.3.0", + "@akashic/game-configuration": "~2.4.0", "@akashic/pdi-types": "^1.13.0", "@akashic/playlog": "~3.3.0", "@akashic/trigger": "~2.1.0" @@ -76,9 +76,10 @@ } }, "node_modules/@akashic/game-configuration": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@akashic/game-configuration/-/game-configuration-2.3.0.tgz", - "integrity": "sha512-JQrUcg8RXNN7sE/CoeonLicTzgwNYscT60w4fgyaD4S+R0kKb0+QEukVMdB6hydWKMoK+pyAQbPKRZ6bEv8qww==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@akashic/game-configuration/-/game-configuration-2.4.0.tgz", + "integrity": "sha512-uClL7F82uBM0KpkqXSMORd7ocShpGjH0HptZGH0GjFL8EtbGrY0rj1sSi2AZKOKXD8mscDOE07LWXFlHswfi/A==", + "license": "MIT", "dependencies": { "@akashic/pdi-types": "^1.14.0" } diff --git a/package.json b/package.json index 744ef0136..36ce31043 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "The core library of Akashic Engine", "main": "index.js", "dependencies": { - "@akashic/game-configuration": "~2.3.0", + "@akashic/game-configuration": "~2.4.0", "@akashic/pdi-types": "^1.13.0", "@akashic/playlog": "~3.3.0", "@akashic/trigger": "~2.1.0" From ec9cdddc497aaad21211f0075611d47df090b3f3 Mon Sep 17 00:00:00 2001 From: yu-ogi Date: Thu, 21 Nov 2024 14:16:12 +0900 Subject: [PATCH 9/9] chore: v3.19.0 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bd4fb570b..9a20e8587 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # ChangeLog -## unreleased changes +## 3.19.0 * @akashic/game-configuration@2.4.0 に追従 * `assetBundle` に対応 * `BundledScriptAsset` を追加 diff --git a/package-lock.json b/package-lock.json index c550768f5..8fee15785 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@akashic/akashic-engine", - "version": "3.18.3", + "version": "3.19.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@akashic/akashic-engine", - "version": "3.18.3", + "version": "3.19.0", "license": "MIT", "dependencies": { "@akashic/game-configuration": "~2.4.0", diff --git a/package.json b/package.json index 36ce31043..7c42c958d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@akashic/akashic-engine", - "version": "3.18.3", + "version": "3.19.0", "description": "The core library of Akashic Engine", "main": "index.js", "dependencies": {