增加不可变源码检出、两阶段 finalize/activate、Runtime 同源对象读取与 iframe 安全边界,并用 fail-closed CI 门固定契约。Git 仅提交平台实现、契约、迁移和 SoT,不包含具体游戏源码、素材、bundle 或验收证据。
88 lines
7.1 KiB
JavaScript
88 lines
7.1 KiB
JavaScript
/**
|
||
* entry-bundle.template.js —— W-G1 通用 bundle 入口模板(逐字拷进每个生成 game 目录为 entry-bundle.js)
|
||
* owner:W-G1 lane | 消费方:esbuild --global-name=__GameBundle → P1 宿主 bootGameHost 真玩
|
||
*
|
||
* ════════════════════════════════════════════════════════════════════════════
|
||
* 【职责】把「生成的游戏工厂 + 通用宿主 + 标准 7 插件 wiring + 引擎」汇成一个 iife 全局 __GameBundle。
|
||
* 产出靶契约(冻结·逐字对齐 entry-bundle.js / game-package.schema.json engineBundle):
|
||
* iife 顶层全局名固定 **__GameBundle**;宿主从 window.__GameBundle 取 GameHostFactory 与 bootGameHost。
|
||
*
|
||
* 【最大化复用·最小新代码】
|
||
* - 宿主:复用 src/host/boot-game-host.js 的通用 bootGameHost(不改)。
|
||
* - 插件 wiring:用官方 L0 通用装载壳 src/host/generic-host-config.js 的 buildGenericHostConfig(标准 7 插件 + 偏序 + 视口 + 工厂 wiring,与官方 entry-generic.js 同一份),
|
||
* override factory 为本目录生成的工厂 → 生成游戏跑在【官方 generic 标准装配】上。
|
||
* - 注:本入口 = 官方 entry-generic.js 的「harness 可取证」超集——多透传 recHook/onReady 供 CDP 八门(F门真接线);
|
||
* studio 渠道调 bootGameHost({canvas,seed}) 时 recHook 为空=no-op,feed 照常(一份 bundle 同时服务 feed + 取证门)。
|
||
* - 引擎:Option C 动态 import(node import 本入口不触引擎,保 import-safe;esbuild 把引擎内联进单文件 iife)。
|
||
*
|
||
* 【Q4 铁律】本入口是「集成段 host」唯一引擎 import 落点(动态 import 后经 opts.engine 注入);
|
||
* ./factory.js 游戏工厂零引擎 import,能力一律经 boot.ctx.getEngine()。
|
||
* ════════════════════════════════════════════════════════════════════════════
|
||
*/
|
||
|
||
'use strict';
|
||
|
||
// 通用宿主(引擎骨架参数化;本身零引擎 import,引擎经 opts.engine 注入)。
|
||
import { bootGameHost as bootGameHostCore } from '../../../src/host/boot-game-host.js';
|
||
// 标准插件装配(官方 L0 通用装载壳 buildGenericHostConfig:collision/physics/gamefeel/juice/palettePost/audioMusic/save + 偏序 + 390×844 视口;零 wanglanmei 专属)。
|
||
import { buildGenericHostConfig } from '../../../src/host/generic-host-config.js';
|
||
// 本目录生成的游戏工厂(默认导出 GameHostFactory,零引擎 import,A3 硬独立文件;官方靶名 generated-factory.js)。
|
||
import gameFactory from './generated-factory.js';
|
||
|
||
/** 【契约导出】GameHostFactory:宿主从 window.__GameBundle.GameHostFactory 取它(契约冻结)。= 本目录生成的工厂。 */
|
||
export const GameHostFactory = gameFactory;
|
||
// 默认导出同为 GameHostFactory(便于 import default 取用;与具名导出同一引用)。
|
||
export default gameFactory;
|
||
|
||
/**
|
||
* 【P2/W-G1 boot 入口】供 host 页在浏览器内启动本 bundle(引擎由本 bundle 注入后驱动)。
|
||
* - 动态 import 引擎(Option C):调用时才求值,esbuild 已把引擎内联进本 bundle(无外部请求)。
|
||
* - engineMode 强制 'real'(W-G1 真玩取证一律引擎掌帧)。
|
||
* - 插件/视口/工厂 wiring 取自 buildRefHostConfig(与 ref 同一标准集),factory override 为生成工厂。
|
||
* - recHook / onReady 透传:供取证 harness 注入「引擎 call-ID 探针」与「internals(uncaught) 收集」(假绿守卫)。
|
||
*
|
||
* @param {Object} opts host 页传入入参。
|
||
* @param {HTMLCanvasElement} opts.canvas 页面 #game 画布(real 通道引擎自建 mainCanvas#game-engine,本 canvas 作占位/输入兜底)。
|
||
* @param {HTMLElement} [opts.statusEl] 状态行(可空)。
|
||
* @param {number} [opts.seed] 主随机种子(缺省固定值,保确定性)。
|
||
* @param {Function} [opts.recHook] 引擎 call-ID 取证钩子 id=>void(取证路径注入 window.__engineCalls.push;渠道产物不注)。
|
||
* @param {Function} [opts.onReady] (host, internals)=>void 就绪回调(取证收集 internals.uncaught 等)。
|
||
* @param {Iterable<string>} [opts.allowedGameEventTypes] 当前可信 profile 的业务事件 type 白名单。
|
||
* @param {Array<object>} [opts.assets] Studio 已完成字节校验的素材描述。
|
||
* @param {any} [opts.engine] 覆盖引擎名字空间(缺省动态 import littlejsengine)。
|
||
* @returns {Promise<object>} bootGameHost 的 host 句柄(frameCount/stepFrames/tap/do/state 等)。
|
||
*/
|
||
export async function bootGameHost(opts) {
|
||
const o = opts || {};
|
||
// 动态 import 引擎:求值时机延后到本函数被调用(浏览器运行期)。esbuild 内联,无外部请求。
|
||
const engine = o.engine || (await import('littlejsengine'));
|
||
// 主随机种子(缺省固定值,与 ref 取证同口径,保确定性可复现)。
|
||
const seed = (o.seed != null ? o.seed : 0x1234abcd) >>> 0;
|
||
// 官方 generic 标准装配(7 插件 + 偏序 + 视口 + 工厂 wiring;与 entry-generic.js 同一 buildGenericHostConfig)。
|
||
const cfg = buildGenericHostConfig({ seed });
|
||
// playtest/3 seed 握手:入口是实际 seed 的唯一裁决点,先公开实际采用值,再把同一值传给宿主与插件装配。
|
||
// 渠道正常启动同样会得到缺省 seed 的只读观测值,不改变既有运行行为。
|
||
if (typeof window !== 'undefined') window.__playtestActualSeed = seed;
|
||
// 调通用宿主:real 通道引擎掌帧;factory override 为本目录生成工厂;其余 wiring 取标准集。
|
||
return bootGameHostCore({
|
||
canvas: o.canvas,
|
||
statusEl: o.statusEl || null,
|
||
engine,
|
||
seed,
|
||
mode: o.mode || 'play', // W-G1 真玩=play
|
||
engineMode: 'real', // 一律引擎掌帧(real 通道)
|
||
viewport: cfg.viewport, // 390×844(与 ref 同,移动竖屏基准)
|
||
factory: gameFactory, // ★ override:本目录【生成的游戏】(其余 wiring 全复用 ref)
|
||
plugins: cfg.plugins, // 标准 7 插件实例集(经 opts.runtime.plugins 注入给工厂)
|
||
registerOrder: cfg.registerOrder, // 注册偏序(保六锚)
|
||
producerCapability: cfg.producerCapability, // 品类装配若声明受保护生产能力,必须原样交给可信宿主
|
||
buildFactoryOpts: cfg.buildFactoryOpts, // 注入 runtime:{plugins,bundle,getRealAudioCtx}
|
||
// 生产 runner 可按已解析 profile 收窄;普通渠道仅接受 generic config 明确声明,否则空集 fail-closed。
|
||
allowedGameEventTypes: o.allowedGameEventTypes != null
|
||
? o.allowedGameEventTypes : (cfg.allowedGameEventTypes || []),
|
||
recHook: o.recHook || null, // 取证:引擎 call-ID 探针(默认 no-op)
|
||
onReady: o.onReady || null, // 取证:收集 internals(uncaught)
|
||
assets: o.assets || [], // studio 已逐字节校验后注入的内存素材描述
|
||
});
|
||
}
|