ravensight-playtest 0.5.2 → 0.7.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.
Files changed (99) hide show
  1. package/README.md +319 -14
  2. package/addons/ravensight_driver/driver.gd +406 -8
  3. package/addons/ravensight_simulate/simulate.gd +360 -0
  4. package/docs/godot-driver.md +70 -8
  5. package/package.json +4 -3
  6. package/src/api/README.md +4 -1
  7. package/src/api/client.js +120 -3
  8. package/src/api/errors.js +17 -1
  9. package/src/api/http.js +43 -17
  10. package/src/assets/formats.js +267 -0
  11. package/src/assets/index.js +260 -0
  12. package/src/assets/integration.js +429 -0
  13. package/src/assets/inventory.js +337 -0
  14. package/src/assets/measure.js +392 -0
  15. package/src/cli.js +233 -0
  16. package/src/commands/assets.js +62 -0
  17. package/src/commands/check.js +4 -1
  18. package/src/commands/create.js +734 -0
  19. package/src/commands/fakeCore.js +16 -1
  20. package/src/commands/feature.js +845 -0
  21. package/src/commands/fix.js +647 -70
  22. package/src/commands/init.js +19 -3
  23. package/src/commands/lists.js +206 -0
  24. package/src/commands/profile.js +25 -6
  25. package/src/commands/punch.js +116 -0
  26. package/src/commands/replay.js +204 -0
  27. package/src/commands/resume.js +7 -0
  28. package/src/commands/run.js +200 -24
  29. package/src/commands/tape.js +74 -0
  30. package/src/commands/template.js +70 -0
  31. package/src/commands/validate.js +414 -0
  32. package/src/commands/validateHosted.js +292 -0
  33. package/src/create/scaffold.js +192 -0
  34. package/src/run/acceptance.js +212 -0
  35. package/src/run/args.js +18 -1
  36. package/src/run/checks.js +705 -0
  37. package/src/run/dimension.js +95 -0
  38. package/src/run/drivers/godot-observation.js +59 -11
  39. package/src/run/drivers/godot-project.js +201 -31
  40. package/src/run/drivers/godot.js +532 -45
  41. package/src/run/drivers/web.js +18 -0
  42. package/src/run/evidence.js +170 -0
  43. package/src/run/featureLoop.js +288 -0
  44. package/src/run/fixLoop.js +82 -12
  45. package/src/run/git.js +110 -20
  46. package/src/run/json.js +65 -9
  47. package/src/run/labsOutcome.js +136 -0
  48. package/src/run/liveWork.js +103 -0
  49. package/src/run/model.js +105 -5
  50. package/src/run/openPr.js +107 -0
  51. package/src/run/paths.js +4 -1
  52. package/src/run/pendingRegister.js +81 -0
  53. package/src/run/personaLoop.js +111 -4
  54. package/src/run/profile.js +68 -7
  55. package/src/run/replay.js +236 -0
  56. package/src/run/repoTools.js +227 -27
  57. package/src/run/report.js +7 -1
  58. package/src/run/resume.js +19 -1
  59. package/src/run/secretScan.js +35 -0
  60. package/src/run/settle.js +41 -0
  61. package/src/run/tools.js +33 -4
  62. package/src/run/trace.js +124 -0
  63. package/src/simulation/godotPack.js +112 -0
  64. package/src/ui/index.js +61 -9
  65. package/src/upload/allowlist.js +6 -2
  66. package/src/upload/index.js +5 -4
  67. package/templates/godot-2d/README.md +36 -0
  68. package/templates/godot-2d/addons/ravensight/LICENSE +21 -0
  69. package/templates/godot-2d/addons/ravensight/Ravensight.gd +1823 -0
  70. package/templates/godot-2d/export_presets.cfg +27 -0
  71. package/templates/godot-2d/gitignore +10 -0
  72. package/templates/godot-2d/project.godot +58 -0
  73. package/templates/godot-2d/scenes/main.tscn +67 -0
  74. package/templates/godot-2d/scripts/autoload/game_config.gd +83 -0
  75. package/templates/godot-2d/scripts/autoload/game_state.gd +44 -0
  76. package/templates/godot-2d/scripts/autoload/telemetry.gd +37 -0
  77. package/templates/godot-2d/scripts/main.gd +32 -0
  78. package/templates/godot-2d/scripts/player.gd +10 -0
  79. package/templates/godot-2d/scripts/state_hook.gd +16 -0
  80. package/templates/godot-2d/template.json +14 -0
  81. package/templates/godot-2d/tools/inject_release_key.sh +19 -0
  82. package/templates/godot-2d/tools/selftest.gd +70 -0
  83. package/templates/godot-3d/README.md +49 -0
  84. package/templates/godot-3d/addons/ravensight/LICENSE +21 -0
  85. package/templates/godot-3d/addons/ravensight/Ravensight.gd +1823 -0
  86. package/templates/godot-3d/export_presets.cfg +27 -0
  87. package/templates/godot-3d/gitignore +10 -0
  88. package/templates/godot-3d/project.godot +56 -0
  89. package/templates/godot-3d/scenes/main.tscn +154 -0
  90. package/templates/godot-3d/scripts/autoload/game_config.gd +83 -0
  91. package/templates/godot-3d/scripts/autoload/game_state.gd +44 -0
  92. package/templates/godot-3d/scripts/autoload/telemetry.gd +37 -0
  93. package/templates/godot-3d/scripts/beacon.gd +20 -0
  94. package/templates/godot-3d/scripts/main.gd +49 -0
  95. package/templates/godot-3d/scripts/player.gd +19 -0
  96. package/templates/godot-3d/scripts/state_hook.gd +25 -0
  97. package/templates/godot-3d/template.json +16 -0
  98. package/templates/godot-3d/tools/inject_release_key.sh +19 -0
  99. package/templates/godot-3d/tools/selftest.gd +77 -0
@@ -0,0 +1,62 @@
1
+ import path from 'node:path';
2
+
3
+ import { loadConfig } from '../config.js';
4
+ import EXIT from '../run/exit.js';
5
+ import { scanUsage } from '../assets/integration.js';
6
+ import { buildInventory, countsLine, DEFAULT_ASSETS_DIR, describeFile, formatBytes, warningKinds } from '../assets/inventory.js';
7
+
8
+ /**
9
+ * `ravensight-playtest assets`: what a project's art and audio folder holds, as
10
+ * measured on this machine. It needs no login, sends nothing anywhere and costs
11
+ * nothing, so it can be run as often as a studio likes before a feature job.
12
+ *
13
+ * @param {Object} flags
14
+ * @param {Object} [injected] test seam
15
+ * @returns {Promise<number>} an exit code
16
+ */
17
+ export async function assetsCommand(flags = {}, injected = {}) {
18
+ const log = injected.log || (line => console.log(line));
19
+ const repoRoot = path.resolve(flags.repoRoot || process.cwd());
20
+ const config = await loadConfig({ repoRoot }).catch(() => null);
21
+ const projectDir = path.resolve(repoRoot, flags.godotProject || config?.godot_project || '.');
22
+ const folder = flags.assetsDir || config?.assets_dir || DEFAULT_ASSETS_DIR;
23
+ const grid = Number.isInteger(flags.grid) && flags.grid > 0 ? flags.grid : null;
24
+ if (flags.grid !== undefined && !grid) {
25
+ log('--grid has to be a whole number of art pixels across, such as 32.');
26
+ return EXIT.ENVIRONMENT;
27
+ }
28
+ let inventory;
29
+ try {
30
+ inventory = await buildInventory({ projectDir, folder, grid });
31
+ } catch (error) {
32
+ log(`The project could not be read: ${String(error && error.message)}`);
33
+ return EXIT.ENVIRONMENT;
34
+ }
35
+ if (!inventory.ok) {
36
+ log(inventory.reason);
37
+ return EXIT.ENVIRONMENT;
38
+ }
39
+ if (!inventory.exists) {
40
+ log(`There is no folder ${folder} in this project. Put your art and audio there, or name the folder with --assets-dir. A feature uses placeholders for anything it cannot find.`);
41
+ return flags.assetsDir ? EXIT.ENVIRONMENT : EXIT.OK;
42
+ }
43
+ const usage = await scanUsage({ projectDir, inventory });
44
+ if (flags.json) {
45
+ (injected.json || (value => console.log(JSON.stringify(value, null, 2))))({ ...inventory, usage: { used: usage.used, unused: usage.unused, built_in_code: usage.built_in_code } });
46
+ return EXIT.OK;
47
+ }
48
+ const used = new Set(usage.used);
49
+ log(`${inventory.folder}: ${countsLine(inventory.counts)}. ${usage.used.length} used by the project, ${usage.unused.length} unused.`);
50
+ for (const file of inventory.files) {
51
+ log(`${file.path} ${[file.format, formatBytes(file.bytes), describeFile(file)].filter(Boolean).join(', ')}${used.has(file.path) ? '' : ' (unused)'}`);
52
+ for (const item of file.warnings) log(` warning: ${item.text}`);
53
+ }
54
+ for (const item of inventory.warnings) log(`warning: ${item.text}`);
55
+ if (inventory.truncated) log(`Only the first ${inventory.counts.files} files are listed.`);
56
+ const kinds = warningKinds(inventory);
57
+ log(kinds.length === 0 ? 'No warnings.' : `${kinds.reduce((sum, item) => sum + item.count, 0)} warning(s).`);
58
+ log('This read your files on this machine and sent nothing.');
59
+ return EXIT.OK;
60
+ }
61
+
62
+ export default assetsCommand;
@@ -425,7 +425,7 @@ export async function runChecks(flags = {}, deps = {}) {
425
425
  'login',
426
426
  games.length > 0 ? 'pass' : 'warn',
427
427
  games.length > 0
428
- ? `${who}, valid, scoped to ${plural(games.length, 'game')}: ${games.map(gameLabel).join(', ')}`
428
+ ? `${who}, valid, scoped to ${plural(games.length, 'game')}: ${games.slice(0, MAX_GAMES_LISTED).map(gameLabel).join(', ')}${games.length > MAX_GAMES_LISTED ? `, and ${games.length - MAX_GAMES_LISTED} more (check --json lists them all)` : ''}`
429
429
  : `${who}, valid, but scoped to no games`,
430
430
  games.length > 0 ? null : 'run ravensight-playtest login again and approve the game for this token'
431
431
  ));
@@ -742,6 +742,9 @@ export async function firstScreenRow(measure, url, { authed, gameId, priced }) {
742
742
  * @param {Object} [deps]
743
743
  * @returns {Promise<number>} exit code, 3 when anything failed
744
744
  */
745
+ /** Games named on check's login row; the rest are counted, and --json has them all. */
746
+ export const MAX_GAMES_LISTED = 5;
747
+
745
748
  export async function check(flags = {}, deps = {}) {
746
749
  const progress = flags.json ? {} : { onProgress: line => ui.info(line) };
747
750
  const { rows, ok, cli, login, project, brief, build, automation } = await runChecks(flags, { ...progress, ...deps });