@bitmagic/cli 0.1.83-dev.2 → 0.1.83-dev.4

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.
Files changed (160) hide show
  1. package/README.md +34 -3
  2. package/assets/metahuman/src/work/metahuman/MetaHumanMaterials.ts +4 -0
  3. package/assets/metahuman/src/work/metahuman/StudioEnvironment.ts +4 -0
  4. package/assets/optimizing-assets/SKILL.md +3 -2
  5. package/assets/optimizing-assets/references/tools.md +1 -1
  6. package/dist/assets/vxl-summary.js +1 -1
  7. package/dist/assets/vxl-summary.js.map +1 -1
  8. package/dist/cli.d.ts +9 -0
  9. package/dist/commands/steam-upload.js +6 -4
  10. package/dist/commands/steam-upload.js.map +1 -1
  11. package/dist/commands/steam.js +4 -2
  12. package/dist/commands/steam.js.map +1 -1
  13. package/dist/commands/upgrade.d.ts +18 -0
  14. package/dist/commands/upgrade.js +94 -1
  15. package/dist/commands/upgrade.js.map +1 -1
  16. package/dist/config/environments.d.ts +1 -1
  17. package/dist/editor/animation-preview-page.js +20 -0
  18. package/dist/editor/animation-preview-page.js.map +1 -1
  19. package/dist/editor/asset-viewer.js +4 -0
  20. package/dist/editor/asset-viewer.js.map +1 -1
  21. package/dist/editor/design.d.ts +2 -2
  22. package/dist/editor/design.js +2 -2
  23. package/dist/editor/design.js.map +1 -1
  24. package/dist/editor/hud-replay-page.js +5 -0
  25. package/dist/editor/hud-replay-page.js.map +1 -1
  26. package/dist/editor/recording-sink.js +1 -1
  27. package/dist/editor/runtime-token.d.ts +61 -0
  28. package/dist/editor/runtime-token.js +74 -0
  29. package/dist/editor/runtime-token.js.map +1 -0
  30. package/dist/editor/save.d.ts +2 -2
  31. package/dist/editor/server.js +39 -12
  32. package/dist/editor/server.js.map +1 -1
  33. package/dist/editor/shell-page.d.ts +12 -8
  34. package/dist/editor/shell-page.js +69 -10
  35. package/dist/editor/shell-page.js.map +1 -1
  36. package/dist/forge/browser-host.d.ts +1 -1
  37. package/dist/forge/browser-host.js +14 -11
  38. package/dist/forge/browser-host.js.map +1 -1
  39. package/dist/generate/model.js +4 -1
  40. package/dist/generate/model.js.map +1 -1
  41. package/dist/generate/prop.js +4 -1
  42. package/dist/generate/prop.js.map +1 -1
  43. package/dist/http/signed-upload.d.ts +6 -4
  44. package/dist/http/signed-upload.js +37 -14
  45. package/dist/http/signed-upload.js.map +1 -1
  46. package/dist/mobile/rewrite-shim.js +1 -1
  47. package/dist/project/published-three.js +4 -6
  48. package/dist/project/published-three.js.map +1 -1
  49. package/dist/publish/game-exchange.js +9 -3
  50. package/dist/publish/game-exchange.js.map +1 -1
  51. package/dist/scaffold/blender-level-skill-files.js +2 -2
  52. package/dist/scaffold/game-migration.d.ts +88 -0
  53. package/dist/scaffold/game-migration.js +492 -0
  54. package/dist/scaffold/game-migration.js.map +1 -0
  55. package/dist/scaffold/import-codemod.d.ts +51 -0
  56. package/dist/scaffold/import-codemod.js +117 -0
  57. package/dist/scaffold/import-codemod.js.map +1 -0
  58. package/dist/scaffold/legacy-game-baselines.d.ts +14 -0
  59. package/dist/scaffold/legacy-game-baselines.js +218 -0
  60. package/dist/scaffold/legacy-game-baselines.js.map +1 -0
  61. package/dist/scaffold/project-files.d.ts +1 -1
  62. package/dist/scaffold/project-files.js +13 -47
  63. package/dist/scaffold/project-files.js.map +1 -1
  64. package/dist/scaffold/project.js +8 -17
  65. package/dist/scaffold/project.js.map +1 -1
  66. package/dist/smoke/run.js +8 -1
  67. package/dist/smoke/run.js.map +1 -1
  68. package/dist/steam/art-generate.js +2 -1
  69. package/dist/steam/art-generate.js.map +1 -1
  70. package/dist/steam/art-render.js.map +1 -1
  71. package/dist/steam/art.js +1 -1
  72. package/dist/steam/art.js.map +1 -1
  73. package/dist/steam/check.js.map +1 -1
  74. package/dist/steam/electron-cache.d.ts +1 -1
  75. package/dist/steam/electron-cache.js +2 -2
  76. package/dist/steam/electron-cache.js.map +1 -1
  77. package/dist/steam/fuses.js +1 -1
  78. package/dist/steam/fuses.js.map +1 -1
  79. package/dist/steam/media.js +6 -2
  80. package/dist/steam/media.js.map +1 -1
  81. package/dist/steam/package-windows.d.ts +1 -2
  82. package/dist/steam/package-windows.js +1 -2
  83. package/dist/steam/package-windows.js.map +1 -1
  84. package/dist/steam/paths.d.ts +0 -2
  85. package/dist/steam/paths.js +0 -1
  86. package/dist/steam/paths.js.map +1 -1
  87. package/dist/steam/portal.js +1 -1
  88. package/dist/steam/portal.js.map +1 -1
  89. package/dist/steam/raster.d.ts +0 -1
  90. package/dist/steam/raster.js +1 -1
  91. package/dist/steam/raster.js.map +1 -1
  92. package/dist/steam/store-copy.d.ts +0 -1
  93. package/dist/steam/store-copy.js +3 -10
  94. package/dist/steam/store-copy.js.map +1 -1
  95. package/dist/steam/tags.js +6 -3
  96. package/dist/steam/tags.js.map +1 -1
  97. package/dist/theme/kernel.d.ts +14 -0
  98. package/dist/theme/kernel.js +15 -0
  99. package/dist/theme/kernel.js.map +1 -0
  100. package/dist/theme/theme-io.js +11 -16
  101. package/dist/theme/theme-io.js.map +1 -1
  102. package/dist/trailer/record-session.d.ts +1 -1
  103. package/dist/trailer/record-session.js +5 -8
  104. package/dist/trailer/record-session.js.map +1 -1
  105. package/dist/trailer/vendored-recorder.d.ts +8 -0
  106. package/dist/trailer/vendored-recorder.js +26 -0
  107. package/dist/trailer/vendored-recorder.js.map +1 -0
  108. package/dist/vendor/hud-theme/catalog.js +71 -0
  109. package/dist/vendor/hud-theme/engine/hud/ThemeTokens.js +115 -0
  110. package/dist/{theme/theme-color-math.js → vendor/hud-theme/engine/hud/colorMath.js} +13 -14
  111. package/dist/vendor/hud-theme/engine/hud/decorations.js +179 -0
  112. package/dist/vendor/hud-theme/engine/hud/fonts.js +147 -0
  113. package/dist/vendor/hud-theme/engine/hud/presets.js +80 -0
  114. package/dist/vendor/hud-theme/engine/hud/resolveWorldTheme.js +66 -0
  115. package/dist/vendor/hud-theme/engine/hud/themes/bitmagic.js +29 -0
  116. package/dist/vendor/hud-theme/engine/hud/themes/nexus.js +69 -0
  117. package/dist/vendor/hud-theme/engine/hud/themes/racing.js +57 -0
  118. package/dist/vendor/hud-theme/engine/hud/themes/rift-raider.js +63 -0
  119. package/dist/vendor/hud-theme/engine/hud/themes/simulator.js +55 -0
  120. package/dist/vendor/hud-theme/engine/hud/themes/village-keep.js +108 -0
  121. package/dist/vendor/hud-theme/engine/hud/validateTheme.js +535 -0
  122. package/dist/vendor/hud-theme/index.js +26 -0
  123. package/dist/{theme/theme-merge.js → vendor/hud-theme/merge.js} +0 -1
  124. package/dist/{theme/theme-report.js → vendor/hud-theme/report.js} +8 -9
  125. package/dist/{theme/theme-stored.js → vendor/hud-theme/stored.js} +6 -9
  126. package/dist/{theme/theme-validate.js → vendor/hud-theme/validate-strict.js} +102 -164
  127. package/dist/verify/browser.d.ts +6 -0
  128. package/dist/verify/browser.js +30 -3
  129. package/dist/verify/browser.js.map +1 -1
  130. package/dist/verify/categories.d.ts +1 -1
  131. package/dist/verify/categories.js +1 -0
  132. package/dist/verify/categories.js.map +1 -1
  133. package/dist/verify/classify.d.ts +7 -0
  134. package/dist/verify/classify.js +7 -0
  135. package/dist/verify/classify.js.map +1 -1
  136. package/dist/verify/hud-theme.d.ts +19 -14
  137. package/dist/verify/hud-theme.js +23 -17
  138. package/dist/verify/hud-theme.js.map +1 -1
  139. package/dist/verify/mobile-parity.d.ts +1 -1
  140. package/dist/verify/mobile-parity.js +1 -1
  141. package/dist/verify/model-downloads.d.ts +47 -0
  142. package/dist/verify/model-downloads.js +127 -0
  143. package/dist/verify/model-downloads.js.map +1 -0
  144. package/dist/verify/start.d.ts +3 -2
  145. package/dist/verify/start.js +1 -1
  146. package/dist/verify/start.js.map +1 -1
  147. package/package.json +11 -7
  148. package/dist/theme/hud-theme-catalog.d.ts +0 -235
  149. package/dist/theme/hud-theme-catalog.js +0 -389
  150. package/dist/theme/hud-theme-catalog.js.map +0 -1
  151. package/dist/theme/theme-color-math.d.ts +0 -21
  152. package/dist/theme/theme-color-math.js.map +0 -1
  153. package/dist/theme/theme-merge.d.ts +0 -36
  154. package/dist/theme/theme-merge.js.map +0 -1
  155. package/dist/theme/theme-report.d.ts +0 -28
  156. package/dist/theme/theme-report.js.map +0 -1
  157. package/dist/theme/theme-stored.d.ts +0 -21
  158. package/dist/theme/theme-stored.js.map +0 -1
  159. package/dist/theme/theme-validate.d.ts +0 -41
  160. package/dist/theme/theme-validate.js.map +0 -1
@@ -1,5 +1,6 @@
1
1
  import { type EventsObservation } from './events.js';
2
2
  import type { MobileParityGap } from './mobile-parity.js';
3
+ import type { ModelDownload } from './model-downloads.js';
3
4
  import type { VerifyPlatform } from './platform.js';
4
5
  export interface CanvasObservation {
5
6
  /** CSS pixel size from getBoundingClientRect() — whether the canvas is visible/laid out. */
@@ -120,6 +121,9 @@ export interface StartObservations {
120
121
  gameStartDetected: boolean;
121
122
  /** The start menu overlay was still displayed after settling. */
122
123
  menuVisibleAfterSettle: boolean;
124
+ /** Game code replaced the engine start screen (`engine.setUIComponent('start', …)`), so the
125
+ * engine's Play button never exists and verify can only press a `data-bitmagic-play` control. */
126
+ customStartScreen?: boolean;
123
127
  }
124
128
  export interface VerifyObservations {
125
129
  /** Console lines, each prefixed with its type, e.g. `error: …`. */
@@ -169,6 +173,9 @@ export interface VerifyObservations {
169
173
  /** The engine's mobile-parity verdict, read from the console it logs on every game start.
170
174
  * Null when it reported no gap — a clean game, or a genre without the check. */
171
175
  mobileParity?: MobileParityGap | null;
176
+ /** The GLBs the page downloaded. Only `publish`'s smoke check records them; `runSmokeCheck`
177
+ * turns them into warnings, so `classifyVerifyRun` never reads this. */
178
+ modelDownloads?: ModelDownload[];
172
179
  }
173
180
  /**
174
181
  * What the run was, as far as the classifier needs to know.
@@ -175,6 +175,13 @@ export function classifyVerifyRun(observations, context = {}) {
175
175
  + `${start.selectionsPicked === 1 ? '' : 's'} but the Play button never appeared and no `
176
176
  + 'game start was detected — the picked level or option most likely never finished loading.');
177
177
  }
178
+ else if (start.customStartScreen) {
179
+ // The commonest way a custom start screen fails verify: it renders its own Play control
180
+ // that verify has no way to recognise, so a healthy game reads as one that never started.
181
+ failures.push('The game installs its own start screen (setUIComponent(\'start\', …)) but never '
182
+ + 'started — no element marked data-bitmagic-play appeared to press, and no game start '
183
+ + 'was detected. Add the data-bitmagic-play attribute to the custom Play button.');
184
+ }
178
185
  else {
179
186
  failures.push('The game never started — no Play button appeared and no game start was detected.');
180
187
  }
@@ -1 +1 @@
1
- {"version":3,"file":"classify.js","sourceRoot":"","sources":["../../src/verify/classify.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"classify.js","sourceRoot":"","sources":["../../src/verify/classify.ts"],"names":[],"mappings":"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"}
@@ -9,25 +9,30 @@
9
9
  * it survives for as long as nobody diffs the intended look against the shipped one.
10
10
  *
11
11
  * The hosted agent is protected from this by `write-hud-theme`, which validates before it writes
12
- * and answers with a closest-match suggestion. `bitmagic theme set|patch` now gives the CLI lane the
13
- * same write-time guard over a gate-enforced mirror of that validator — but only for edits made
14
- * THROUGH it. A hand edit to world.json, a vendored engine older than the CLI's copy, or a theme
15
- * that validates yet still fails in the browser all land here, which is why this check stays: it is
16
- * the only one that reads what the engine itself said.
12
+ * and answers with a closest-match suggestion. `bitmagic theme set|patch` gives the CLI lane the
13
+ * same write-time guard with the same validator (the bundled `@bitmagic/hud-theme` kernel) — but
14
+ * only for edits made THROUGH it. A hand edit to world.json, a vendored engine older than the CLI's
15
+ * kernel, or a theme that validates yet still fails in the browser all land here, which is why this
16
+ * check stays: it is the only one that reads what the engine itself said.
17
17
  *
18
- * WHY PARSE THE CONSOLE rather than validate statically here. The obvious alternative is to read
19
- * world.json and check it against the engine's own validator, and it is not available: the vendored
20
- * engine emits with its path-mapped specifiers intact (`from 'engine/hud/ThemeTokens.js'`), which
21
- * resolve only through the browser import map, so `validateAndResolveTheme` cannot be imported from
22
- * Node. The remaining static option is a hand-mirrored preset list in the CLI, i.e. a third copy of
23
- * the same list to keep in sync. Parsing what the engine already said costs no mirror, cannot drift,
24
- * and inherits the engine's own error text — including the field paths from an invalid inline theme
25
- * and the live list of known presets, neither of which a mirror would have.
18
+ * WHY PARSE THE CONSOLE rather than validate statically here. The CLI's bundled kernel is the
19
+ * validator of the engine the CLI was BUILT with, while the project runs the engine it VENDORED —
20
+ * the project's own `engine/` cannot be imported from Node (its specifiers are path-mapped
21
+ * `engine/...` aliases that resolve only through the browser import map). Parsing what the
22
+ * project's engine actually said needs no assumption about which version that is, and inherits the
23
+ * engine's own error text — including the field paths from an invalid inline theme and the live
24
+ * list of known presets.
26
25
  *
27
26
  * The cost is honest and worth naming: this only sees a theme on a game that actually booted. A
28
27
  * project whose game fails to load has bigger findings in the same run.
29
28
  */
30
- /** The engine's marker on every theme-resolution warning. Also what a reader greps for. */
29
+ /**
30
+ * The engine's marker on every theme-resolution warning. Also what a reader greps for.
31
+ *
32
+ * The marker and the two phrases below are the engine's own constants (`resolveWorldTheme`),
33
+ * taken from the bundled theme kernel, so the parser and the emitter cannot drift. They are frozen
34
+ * engine-side because this parser reads warnings from engines of every vendored version.
35
+ */
31
36
  export declare const HUD_THEME_MARKER = "[HUD]";
32
37
  export interface HudThemeProblem {
33
38
  /**
@@ -9,30 +9,36 @@
9
9
  * it survives for as long as nobody diffs the intended look against the shipped one.
10
10
  *
11
11
  * The hosted agent is protected from this by `write-hud-theme`, which validates before it writes
12
- * and answers with a closest-match suggestion. `bitmagic theme set|patch` now gives the CLI lane the
13
- * same write-time guard over a gate-enforced mirror of that validator — but only for edits made
14
- * THROUGH it. A hand edit to world.json, a vendored engine older than the CLI's copy, or a theme
15
- * that validates yet still fails in the browser all land here, which is why this check stays: it is
16
- * the only one that reads what the engine itself said.
12
+ * and answers with a closest-match suggestion. `bitmagic theme set|patch` gives the CLI lane the
13
+ * same write-time guard with the same validator (the bundled `@bitmagic/hud-theme` kernel) — but
14
+ * only for edits made THROUGH it. A hand edit to world.json, a vendored engine older than the CLI's
15
+ * kernel, or a theme that validates yet still fails in the browser all land here, which is why this
16
+ * check stays: it is the only one that reads what the engine itself said.
17
17
  *
18
- * WHY PARSE THE CONSOLE rather than validate statically here. The obvious alternative is to read
19
- * world.json and check it against the engine's own validator, and it is not available: the vendored
20
- * engine emits with its path-mapped specifiers intact (`from 'engine/hud/ThemeTokens.js'`), which
21
- * resolve only through the browser import map, so `validateAndResolveTheme` cannot be imported from
22
- * Node. The remaining static option is a hand-mirrored preset list in the CLI, i.e. a third copy of
23
- * the same list to keep in sync. Parsing what the engine already said costs no mirror, cannot drift,
24
- * and inherits the engine's own error text — including the field paths from an invalid inline theme
25
- * and the live list of known presets, neither of which a mirror would have.
18
+ * WHY PARSE THE CONSOLE rather than validate statically here. The CLI's bundled kernel is the
19
+ * validator of the engine the CLI was BUILT with, while the project runs the engine it VENDORED —
20
+ * the project's own `engine/` cannot be imported from Node (its specifiers are path-mapped
21
+ * `engine/...` aliases that resolve only through the browser import map). Parsing what the
22
+ * project's engine actually said needs no assumption about which version that is, and inherits the
23
+ * engine's own error text — including the field paths from an invalid inline theme and the live
24
+ * list of known presets.
26
25
  *
27
26
  * The cost is honest and worth naming: this only sees a theme on a game that actually booted. A
28
27
  * project whose game fails to load has bigger findings in the same run.
29
28
  */
30
- /** The engine's marker on every theme-resolution warning. Also what a reader greps for. */
31
- export const HUD_THEME_MARKER = '[HUD]';
29
+ import { HUD_INVALID_THEME_PHRASE, HUD_THEME_LOG_MARKER, HUD_UNKNOWN_PRESET_PHRASE, } from '../theme/kernel.js';
30
+ /**
31
+ * The engine's marker on every theme-resolution warning. Also what a reader greps for.
32
+ *
33
+ * The marker and the two phrases below are the engine's own constants (`resolveWorldTheme`),
34
+ * taken from the bundled theme kernel, so the parser and the emitter cannot drift. They are frozen
35
+ * engine-side because this parser reads warnings from engines of every vendored version.
36
+ */
37
+ export const HUD_THEME_MARKER = HUD_THEME_LOG_MARKER;
32
38
  /** `resolveWorldTheme`'s wording when `hud.theme` is a string that names no preset. */
33
- const UNKNOWN_PRESET = 'Unknown theme preset';
39
+ const UNKNOWN_PRESET = HUD_UNKNOWN_PRESET_PHRASE;
34
40
  /** …and when it is an object the validator rejected. */
35
- const INVALID_THEME = 'Custom theme failed validation';
41
+ const INVALID_THEME = HUD_INVALID_THEME_PHRASE;
36
42
  /**
37
43
  * The theme problem the engine reported during this run, or null when it reported none.
38
44
  *
@@ -1 +1 @@
1
- {"version":3,"file":"hud-theme.js","sourceRoot":"","sources":["../../src/verify/hud-theme.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,2FAA2F;AAC3F,MAAM,CAAC,MAAM,gBAAgB,GAAG,OAAO,CAAC;AAExC,uFAAuF;AACvF,MAAM,cAAc,GAAG,sBAAsB,CAAC;AAE9C,wDAAwD;AACxD,MAAM,aAAa,GAAG,gCAAgC,CAAC;AAgBvD;;;;;;;;;GASG;AACH,MAAM,UAAU,oBAAoB,CAAC,YAAsB;IACzD,KAAK,IAAI,CAAC,GAAG,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAClD,MAAM,OAAO,GAAG,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3C,IAAI,OAAO,KAAK,IAAI;YAAE,OAAO,OAAO,CAAC;IACvC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,SAAS,CAAC,IAAY;IAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC9C,IAAI,MAAM,KAAK,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAE/B,mFAAmF;IACnF,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;IACnE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAErC,IAAI,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IACvE,IAAI,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IAEtE,6FAA6F;IAC7F,0FAA0F;IAC1F,OAAO,IAAI,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"hud-theme.js","sourceRoot":"","sources":["../../src/verify/hud-theme.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,EACL,wBAAwB,EACxB,oBAAoB,EACpB,yBAAyB,GAC1B,MAAM,oBAAoB,CAAC;AAE5B;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,oBAAoB,CAAC;AAErD,uFAAuF;AACvF,MAAM,cAAc,GAAG,yBAAyB,CAAC;AAEjD,wDAAwD;AACxD,MAAM,aAAa,GAAG,wBAAwB,CAAC;AAgB/C;;;;;;;;;GASG;AACH,MAAM,UAAU,oBAAoB,CAAC,YAAsB;IACzD,KAAK,IAAI,CAAC,GAAG,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAClD,MAAM,OAAO,GAAG,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3C,IAAI,OAAO,KAAK,IAAI;YAAE,OAAO,OAAO,CAAC;IACvC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,SAAS,CAAC,IAAY;IAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC9C,IAAI,MAAM,KAAK,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAE/B,mFAAmF;IACnF,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;IACnE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAErC,IAAI,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IACvE,IAAI,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IAEtE,6FAA6F;IAC7F,0FAA0F;IAC1F,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * `GameTemplate` calls `playerController.verifyMobileParity()` on every game start — desktop runs
5
5
  * included — and when it finds gaps the engine logs one `console.error` listing every one of
6
- * them (`game/src/engine/PlayerController.ts`, documented in
6
+ * them (`game/src/engine/player/PlayerController.ts`, documented in
7
7
  * `game/agent-docs/control-system.md`). Nothing consumed it, so a game with actions no phone can
8
8
  * reach passed verify silently.
9
9
  *
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * `GameTemplate` calls `playerController.verifyMobileParity()` on every game start — desktop runs
5
5
  * included — and when it finds gaps the engine logs one `console.error` listing every one of
6
- * them (`game/src/engine/PlayerController.ts`, documented in
6
+ * them (`game/src/engine/player/PlayerController.ts`, documented in
7
7
  * `game/agent-docs/control-system.md`). Nothing consumed it, so a game with actions no phone can
8
8
  * reach passed verify silently.
9
9
  *
@@ -0,0 +1,47 @@
1
+ /**
2
+ * The GLBs a published game actually downloads, and the two ways one can cost players far more
3
+ * than it needs to. `bitmagic publish`'s smoke check records them; this module turns the record
4
+ * into advice.
5
+ *
6
+ * - **Served without HTTP compression.** Most GLB bytes are vertex buffers, which brotli shrinks
7
+ * by 70-90%. Uploads store GLBs compressed now, but one uploaded before that, or hosted
8
+ * somewhere else, still crosses the wire raw. Re-uploading it is the whole fix.
9
+ * - **No mesh or texture compression inside the file.** meshopt, Draco and KTX2 are what the
10
+ * `optimizing-assets` skill applies per asset class, with an A/B check, because quantization
11
+ * has visible failure modes no upload can safely risk on its own (skinned characters
12
+ * mis-posing, named lamps moving). So the smoke check only points at it.
13
+ *
14
+ * Measured on a 58 MiB ship game (36 GLBs): raw 58.2 MiB, brotli 12.1 MiB, lossless meshopt plus
15
+ * brotli 10.8 MiB. The first warning is the big one; the second is for what is left.
16
+ *
17
+ * Advisory only: both become `warnings`, never failures. A game with heavy models still renders.
18
+ */
19
+ import type { Page } from 'playwright-core';
20
+ /** One GLB response the page received. */
21
+ export interface ModelDownload {
22
+ url: string;
23
+ /** The response's `Content-Encoding`, lower-cased; null when it had none (identity). */
24
+ contentEncoding: string | null;
25
+ /** Bytes after decoding — the GLB itself. */
26
+ decodedBytes: number;
27
+ /** `extensionsUsed` from the GLB's JSON chunk; null when the body was not a readable GLB. */
28
+ extensionsUsed: string[] | null;
29
+ }
30
+ /** Below this a raw download is not worth a line: headers and latency dominate. */
31
+ export declare const UNCOMPRESSED_WARN_MIN_BYTES: number;
32
+ /**
33
+ * Below this an unoptimized GLB is not worth the skill's A/B: a character at ~0.7 MiB gains a
34
+ * few hundred KB, and the creator's time is better spent on the files above it.
35
+ */
36
+ export declare const UNOPTIMIZED_WARN_MIN_BYTES: number;
37
+ /** `extensionsUsed` from a binary glTF, or null when `bytes` is not one. */
38
+ export declare function parseGlbExtensions(bytes: Uint8Array): string[] | null;
39
+ /**
40
+ * Start recording every GLB `page` (and its frames) receives. Call `collect()` once the run has
41
+ * settled: it waits for the bodies still being read and returns one entry per distinct URL.
42
+ */
43
+ export declare function recordModelDownloads(page: Page): {
44
+ collect: () => Promise<ModelDownload[]>;
45
+ };
46
+ /** The smoke check's advice about the GLBs it saw. Empty when there is nothing worth saying. */
47
+ export declare function modelDownloadWarnings(downloads: ModelDownload[], skillPath: string): string[];
@@ -0,0 +1,127 @@
1
+ /** Below this a raw download is not worth a line: headers and latency dominate. */
2
+ export const UNCOMPRESSED_WARN_MIN_BYTES = 256 * 1024;
3
+ /**
4
+ * Below this an unoptimized GLB is not worth the skill's A/B: a character at ~0.7 MiB gains a
5
+ * few hundred KB, and the creator's time is better spent on the files above it.
6
+ */
7
+ export const UNOPTIMIZED_WARN_MIN_BYTES = 2 * 1024 * 1024;
8
+ /** How many files a warning names before it summarises the rest as a count. */
9
+ const MAX_NAMED_FILES = 3;
10
+ /** Extensions that mean the geometry or textures were already compressed for download. */
11
+ const COMPRESSION_EXTENSIONS = new Set([
12
+ 'EXT_meshopt_compression',
13
+ 'KHR_meshopt_compression',
14
+ 'KHR_draco_mesh_compression',
15
+ 'KHR_mesh_quantization',
16
+ 'KHR_texture_basisu',
17
+ ]);
18
+ const GLB_MAGIC = 0x46546c67; // 'glTF'
19
+ const JSON_CHUNK_TYPE = 0x4e4f534a; // 'JSON'
20
+ /** `extensionsUsed` from a binary glTF, or null when `bytes` is not one. */
21
+ export function parseGlbExtensions(bytes) {
22
+ if (bytes.byteLength < 20)
23
+ return null;
24
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
25
+ if (view.getUint32(0, true) !== GLB_MAGIC)
26
+ return null;
27
+ const jsonLength = view.getUint32(12, true);
28
+ if (view.getUint32(16, true) !== JSON_CHUNK_TYPE || 20 + jsonLength > bytes.byteLength)
29
+ return null;
30
+ try {
31
+ const json = JSON.parse(new TextDecoder().decode(bytes.subarray(20, 20 + jsonLength)));
32
+ if (typeof json !== 'object' || json === null)
33
+ return null;
34
+ const used = json.extensionsUsed;
35
+ return Array.isArray(used) ? used.filter((e) => typeof e === 'string') : [];
36
+ }
37
+ catch {
38
+ return null;
39
+ }
40
+ }
41
+ function isGlbResponse(response) {
42
+ if (response.status() !== 200)
43
+ return false;
44
+ try {
45
+ return new URL(response.url()).pathname.toLowerCase().endsWith('.glb');
46
+ }
47
+ catch {
48
+ return false;
49
+ }
50
+ }
51
+ /**
52
+ * Start recording every GLB `page` (and its frames) receives. Call `collect()` once the run has
53
+ * settled: it waits for the bodies still being read and returns one entry per distinct URL.
54
+ */
55
+ export function recordModelDownloads(page) {
56
+ const pending = [];
57
+ page.on('response', (response) => {
58
+ if (!isGlbResponse(response))
59
+ return;
60
+ pending.push((async () => {
61
+ try {
62
+ const body = await response.body();
63
+ const encoding = (await response.headerValue('content-encoding'))?.trim().toLowerCase() ?? '';
64
+ return {
65
+ url: response.url(),
66
+ contentEncoding: encoding === '' || encoding === 'identity' ? null : encoding,
67
+ decodedBytes: body.byteLength,
68
+ extensionsUsed: parseGlbExtensions(new Uint8Array(body.buffer, body.byteOffset, body.byteLength)),
69
+ };
70
+ }
71
+ catch {
72
+ // The page navigated or closed before the body arrived — nothing to advise about.
73
+ return null;
74
+ }
75
+ })());
76
+ });
77
+ return {
78
+ collect: async () => {
79
+ const byUrl = new Map();
80
+ for (const download of await Promise.all(pending)) {
81
+ if (download !== null)
82
+ byUrl.set(download.url, download);
83
+ }
84
+ return [...byUrl.values()];
85
+ },
86
+ };
87
+ }
88
+ function mib(bytes) {
89
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MiB`;
90
+ }
91
+ function fileName(url) {
92
+ try {
93
+ return new URL(url).pathname.split('/').pop() ?? url;
94
+ }
95
+ catch {
96
+ return url;
97
+ }
98
+ }
99
+ function describeFiles(downloads) {
100
+ const sorted = [...downloads].sort((a, b) => b.decodedBytes - a.decodedBytes);
101
+ const named = sorted.slice(0, MAX_NAMED_FILES).map((d) => `${fileName(d.url)} (${mib(d.decodedBytes)})`);
102
+ const rest = sorted.length - named.length;
103
+ return rest > 0 ? `${named.join(', ')} and ${rest} more` : named.join(', ');
104
+ }
105
+ /** The smoke check's advice about the GLBs it saw. Empty when there is nothing worth saying. */
106
+ export function modelDownloadWarnings(downloads, skillPath) {
107
+ const warnings = [];
108
+ const raw = downloads.filter((d) => d.contentEncoding === null && d.decodedBytes >= UNCOMPRESSED_WARN_MIN_BYTES);
109
+ if (raw.length > 0) {
110
+ const total = raw.reduce((n, d) => n + d.decodedBytes, 0);
111
+ warnings.push(`${raw.length} GLB${raw.length === 1 ? ' was' : 's were'} served without HTTP compression, `
112
+ + `${mib(total)} that players download in full: ${describeFiles(raw)}. Uploads store GLBs `
113
+ + 'brotli-compressed now (typically 70-90% smaller, byte-identical once decoded), so these are '
114
+ + 'older uploads or hosted elsewhere: upload each again with `bitmagic assets add <file> '
115
+ + '--keep-glb` and point the game at the new URL.');
116
+ }
117
+ const unoptimized = downloads.filter((d) => d.extensionsUsed !== null
118
+ && d.decodedBytes >= UNOPTIMIZED_WARN_MIN_BYTES
119
+ && !d.extensionsUsed.some((e) => COMPRESSION_EXTENSIONS.has(e)));
120
+ if (unoptimized.length > 0) {
121
+ warnings.push(`${unoptimized.length} large GLB${unoptimized.length === 1 ? ' has' : 's have'} no meshopt, Draco or `
122
+ + `KTX2 compression: ${describeFiles(unoptimized)}. Shrinking them is usually a large further `
123
+ + `saving on top of HTTP compression; see ${skillPath} for the per-asset-class recipe and its A/B check.`);
124
+ }
125
+ return warnings;
126
+ }
127
+ //# sourceMappingURL=model-downloads.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-downloads.js","sourceRoot":"","sources":["../../src/verify/model-downloads.ts"],"names":[],"mappings":"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"}
@@ -16,8 +16,9 @@
16
16
  * not meaningfully begun; `loadingGraceMs` bounds how long that credit can last.
17
17
  */
18
18
  export interface StartInteractionOptions {
19
- /** Selector for the engine Play button. Its label is localizable and per-game overridable, so
20
- * never match by text. */
19
+ /** Selector for the Play button: the engine's own, or the control a custom start screen
20
+ * (`engine.setUIComponent('start', …)`) marks with `data-bitmagic-play`. Its label is
21
+ * localizable and per-game overridable, so never match by text. */
21
22
  playButtonSelector: string;
22
23
  /**
23
24
  * Selector for one option of a pre-play selection step (level chooser, difficulty, …), as
@@ -16,7 +16,7 @@
16
16
  * not meaningfully begun; `loadingGraceMs` bounds how long that credit can last.
17
17
  */
18
18
  export const DEFAULT_START_INTERACTION = {
19
- playButtonSelector: '#play-button, .hud-play-button',
19
+ playButtonSelector: '#play-button, .hud-play-button, [data-bitmagic-play]',
20
20
  selectionOptionSelector: '.start-screen-selection__option',
21
21
  startedConsoleMarker: '🎮 Starting game...',
22
22
  buttonTimeoutMs: 30_000,
@@ -1 +1 @@
1
- {"version":3,"file":"start.js","sourceRoot":"","sources":["../../src/verify/start.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAoCH,MAAM,CAAC,MAAM,yBAAyB,GAA4B;IAChE,kBAAkB,EAAE,gCAAgC;IACpD,uBAAuB,EAAE,iCAAiC;IAC1D,oBAAoB,EAAE,qBAAqB;IAC3C,eAAe,EAAE,MAAM;IACvB,cAAc,EAAE,OAAO;IACvB,uBAAuB,EAAE,MAAM;IAC/B,iBAAiB,EAAE,CAAC;CACrB,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,CAAC;AAEjC;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAEpC,MAAM,UAAU,cAAc,CAAC,YAAsB,EAAE,MAAc;IACnE,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;AAC5D,CAAC;AAwBD;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAC7B,MAAuB,EACvB,OAAgC;IAEhC,IAAI,MAAM,CAAC,eAAe;QAAE,OAAO,SAAS,CAAC;IAC7C,IAAI,MAAM,CAAC,sBAAsB,IAAI,MAAM,CAAC,SAAS,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;QAClF,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IACD,IAAI,MAAM,CAAC,iBAAiB,IAAI,MAAM,CAAC,gBAAgB,IAAI,kBAAkB,EAAE,CAAC;QAC9E,OAAO,YAAY,CAAC;IACtB,CAAC;IACD,IAAI,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,SAAS,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;QACpE,OAAO,cAAc,CAAC;IACxB,CAAC;IACD,OAAO,cAAc,CAAC;AACxB,CAAC"}
1
+ {"version":3,"file":"start.js","sourceRoot":"","sources":["../../src/verify/start.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAqCH,MAAM,CAAC,MAAM,yBAAyB,GAA4B;IAChE,kBAAkB,EAAE,sDAAsD;IAC1E,uBAAuB,EAAE,iCAAiC;IAC1D,oBAAoB,EAAE,qBAAqB;IAC3C,eAAe,EAAE,MAAM;IACvB,cAAc,EAAE,OAAO;IACvB,uBAAuB,EAAE,MAAM;IAC/B,iBAAiB,EAAE,CAAC;CACrB,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,CAAC;AAEjC;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAEpC,MAAM,UAAU,cAAc,CAAC,YAAsB,EAAE,MAAc;IACnE,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;AAC5D,CAAC;AAwBD;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAC7B,MAAuB,EACvB,OAAgC;IAEhC,IAAI,MAAM,CAAC,eAAe;QAAE,OAAO,SAAS,CAAC;IAC7C,IAAI,MAAM,CAAC,sBAAsB,IAAI,MAAM,CAAC,SAAS,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;QAClF,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IACD,IAAI,MAAM,CAAC,iBAAiB,IAAI,MAAM,CAAC,gBAAgB,IAAI,kBAAkB,EAAE,CAAC;QAC9E,OAAO,YAAY,CAAC;IACtB,CAAC;IACD,IAAI,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,SAAS,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;QACpE,OAAO,cAAc,CAAC;IACxB,CAAC;IACD,OAAO,cAAc,CAAC;AACxB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bitmagic/cli",
3
- "version": "0.1.83-dev.2",
3
+ "version": "0.1.83-dev.4",
4
4
  "description": "Build Bitmagic games from your own agent tool",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "author": "Bitmagic Oy",
@@ -26,9 +26,9 @@
26
26
  "resedit": "3.0.2",
27
27
  "tar": "^7.4.3",
28
28
  "ws": "^8.21.3",
29
- "@bitmagic/world-forger": "0.1.43-dev.2",
30
- "@bitmagic/animation-forger": "0.1.38-dev.2",
31
- "@bitmagic/asset-core": "0.2.38-dev.2"
29
+ "@bitmagic/animation-forger": "0.1.38-dev.4",
30
+ "@bitmagic/asset-core": "0.2.38-dev.4",
31
+ "@bitmagic/world-forger": "0.1.43-dev.4"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@eslint/js": "^9.38.0",
@@ -44,7 +44,9 @@
44
44
  "eslint-plugin-import": "^2.32.0",
45
45
  "jest": "^29.7.0",
46
46
  "ts-jest": "^29.4.12",
47
- "typescript": "^6.0.3"
47
+ "typescript": "^6.0.3",
48
+ "@bitmagic/engine-protocol": "0.1.0",
49
+ "@bitmagic/hud-theme": "0.1.0"
48
50
  },
49
51
  "jest": {
50
52
  "preset": "ts-jest/presets/default-esm",
@@ -77,11 +79,13 @@
77
79
  ]
78
80
  },
79
81
  "scripts": {
80
- "build": "tsc",
82
+ "build": "tsc && node scripts/bundle-hud-theme.mjs",
81
83
  "check": "pnpm run lint && pnpm run build && pnpm run check:lab",
82
84
  "check:lab": "tsc -p tsconfig.lab.json --noEmit",
83
85
  "lint": "eslint src lab",
84
86
  "lab": "tsx lab/cli.ts",
85
- "test": "NODE_OPTIONS=--experimental-vm-modules jest"
87
+ "test": "NODE_OPTIONS=--experimental-vm-modules jest",
88
+ "verify:upgrade-fixtures": "tsx scripts/verify-upgrade-fixtures.mjs",
89
+ "gen:legacy-game-baselines": "tsx scripts/gen-legacy-game-baselines.mjs"
86
90
  }
87
91
  }