@directivegames/genesys.sdk 3.2.2

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 (181) hide show
  1. package/README.md +60 -0
  2. package/dist/src/asset-pack/eslint.config.js +43 -0
  3. package/dist/src/asset-pack/scripts/postinstall.js +64 -0
  4. package/dist/src/asset-pack/src/index.js +1 -0
  5. package/dist/src/core/cli.js +306 -0
  6. package/dist/src/core/common.js +324 -0
  7. package/dist/src/core/index.js +6 -0
  8. package/dist/src/core/tools/build-project.js +450 -0
  9. package/dist/src/core/tools/index.js +2 -0
  10. package/dist/src/core/tools/new-asset-pack.js +150 -0
  11. package/dist/src/core/tools/new-project.js +292 -0
  12. package/dist/src/core/types.js +1 -0
  13. package/dist/src/dependencies.js +82 -0
  14. package/dist/src/electron/IpcSerializableError.js +38 -0
  15. package/dist/src/electron/api.js +7 -0
  16. package/dist/src/electron/backend/actions.js +56 -0
  17. package/dist/src/electron/backend/handler.js +441 -0
  18. package/dist/src/electron/backend/logging.js +41 -0
  19. package/dist/src/electron/backend/main.js +315 -0
  20. package/dist/src/electron/backend/menu.js +208 -0
  21. package/dist/src/electron/backend/state.js +201 -0
  22. package/dist/src/electron/backend/tools/const.js +9 -0
  23. package/dist/src/electron/backend/tools/file-server.js +383 -0
  24. package/dist/src/electron/backend/tools/open-project.js +261 -0
  25. package/dist/src/electron/backend/window.js +161 -0
  26. package/dist/src/templates/eslint.config.js +43 -0
  27. package/dist/src/templates/scripts/genesys/build-project.js +42 -0
  28. package/dist/src/templates/scripts/genesys/calc-bounding-box.js +205 -0
  29. package/dist/src/templates/scripts/genesys/common.js +36 -0
  30. package/dist/src/templates/scripts/genesys/const.js +9 -0
  31. package/dist/src/templates/scripts/genesys/dev/dump-default-scene.js +8 -0
  32. package/dist/src/templates/scripts/genesys/dev/generate-manifest.js +116 -0
  33. package/dist/src/templates/scripts/genesys/dev/launcher.js +39 -0
  34. package/dist/src/templates/scripts/genesys/dev/storage-provider.js +188 -0
  35. package/dist/src/templates/scripts/genesys/dev/update-template-scenes.js +67 -0
  36. package/dist/src/templates/scripts/genesys/doc-server.js +12 -0
  37. package/dist/src/templates/scripts/genesys/genesys-mcp.js +413 -0
  38. package/dist/src/templates/scripts/genesys/mcp/doc-tools.js +70 -0
  39. package/dist/src/templates/scripts/genesys/mcp/editor-functions.js +123 -0
  40. package/dist/src/templates/scripts/genesys/mcp/editor-tools.js +51 -0
  41. package/dist/src/templates/scripts/genesys/mcp/get-scene-state.js +26 -0
  42. package/dist/src/templates/scripts/genesys/mcp/run-subprocess.js +23 -0
  43. package/dist/src/templates/scripts/genesys/mcp/search-actors.js +703 -0
  44. package/dist/src/templates/scripts/genesys/mcp/search-assets.js +296 -0
  45. package/dist/src/templates/scripts/genesys/mcp/utils.js +234 -0
  46. package/dist/src/templates/scripts/genesys/misc.js +32 -0
  47. package/dist/src/templates/scripts/genesys/mock.js +5 -0
  48. package/dist/src/templates/scripts/genesys/place-actors.js +112 -0
  49. package/dist/src/templates/scripts/genesys/post-install.js +25 -0
  50. package/dist/src/templates/scripts/genesys/remove-engine-comments.js +113 -0
  51. package/dist/src/templates/scripts/genesys/storageProvider.js +146 -0
  52. package/dist/src/templates/scripts/genesys/validate-prefabs.js +115 -0
  53. package/dist/src/templates/src/index.js +20 -0
  54. package/dist/src/templates/src/templates/firstPerson/src/auto-imports.js +1 -0
  55. package/dist/src/templates/src/templates/firstPerson/src/game.js +30 -0
  56. package/dist/src/templates/src/templates/firstPerson/src/player.js +60 -0
  57. package/dist/src/templates/src/templates/fps/src/auto-imports.js +1 -0
  58. package/dist/src/templates/src/templates/fps/src/game.js +30 -0
  59. package/dist/src/templates/src/templates/fps/src/player.js +64 -0
  60. package/dist/src/templates/src/templates/fps/src/weapon.js +62 -0
  61. package/dist/src/templates/src/templates/freeCamera/src/auto-imports.js +1 -0
  62. package/dist/src/templates/src/templates/freeCamera/src/game.js +30 -0
  63. package/dist/src/templates/src/templates/freeCamera/src/player.js +43 -0
  64. package/dist/src/templates/src/templates/sideScroller/src/auto-imports.js +1 -0
  65. package/dist/src/templates/src/templates/sideScroller/src/const.js +43 -0
  66. package/dist/src/templates/src/templates/sideScroller/src/game.js +103 -0
  67. package/dist/src/templates/src/templates/sideScroller/src/level-generator.js +249 -0
  68. package/dist/src/templates/src/templates/sideScroller/src/player.js +105 -0
  69. package/dist/src/templates/src/templates/thirdPerson/src/auto-imports.js +1 -0
  70. package/dist/src/templates/src/templates/thirdPerson/src/game.js +30 -0
  71. package/dist/src/templates/src/templates/thirdPerson/src/player.js +63 -0
  72. package/dist/src/templates/src/templates/vehicle/src/auto-imports.js +1 -0
  73. package/dist/src/templates/src/templates/vehicle/src/base-vehicle.js +122 -0
  74. package/dist/src/templates/src/templates/vehicle/src/game.js +33 -0
  75. package/dist/src/templates/src/templates/vehicle/src/mesh-vehicle.js +189 -0
  76. package/dist/src/templates/src/templates/vehicle/src/player.js +102 -0
  77. package/dist/src/templates/src/templates/vehicle/src/primitive-vehicle.js +259 -0
  78. package/dist/src/templates/src/templates/vehicle/src/ui-hints.js +100 -0
  79. package/dist/src/templates/src/templates/vr-game/src/auto-imports.js +1 -0
  80. package/dist/src/templates/src/templates/vr-game/src/game.js +55 -0
  81. package/dist/src/templates/src/templates/vr-game/src/sample-vr-actor.js +29 -0
  82. package/dist/src/templates/vite.config.js +46 -0
  83. package/package.json +176 -0
  84. package/scripts/post-install.ts +143 -0
  85. package/src/asset-pack/.gitattributes +89 -0
  86. package/src/asset-pack/eslint.config.js +45 -0
  87. package/src/asset-pack/gitignore +11 -0
  88. package/src/asset-pack/scripts/postinstall.ts +81 -0
  89. package/src/asset-pack/src/index.ts +0 -0
  90. package/src/asset-pack/tsconfig.json +34 -0
  91. package/src/templates/.cursor/mcp.json +20 -0
  92. package/src/templates/.cursorignore +2 -0
  93. package/src/templates/.gitattributes +89 -0
  94. package/src/templates/.vscode/settings.json +6 -0
  95. package/src/templates/AGENTS.md +86 -0
  96. package/src/templates/CLAUDE.md +1 -0
  97. package/src/templates/README.md +24 -0
  98. package/src/templates/eslint.config.js +45 -0
  99. package/src/templates/gitignore +11 -0
  100. package/src/templates/index.html +34 -0
  101. package/src/templates/pnpm-lock.yaml +3676 -0
  102. package/src/templates/scripts/genesys/build-project.ts +51 -0
  103. package/src/templates/scripts/genesys/calc-bounding-box.ts +272 -0
  104. package/src/templates/scripts/genesys/common.ts +46 -0
  105. package/src/templates/scripts/genesys/const.ts +9 -0
  106. package/src/templates/scripts/genesys/dev/dump-default-scene.ts +11 -0
  107. package/src/templates/scripts/genesys/dev/generate-manifest.ts +146 -0
  108. package/src/templates/scripts/genesys/dev/launcher.ts +46 -0
  109. package/src/templates/scripts/genesys/dev/storage-provider.ts +229 -0
  110. package/src/templates/scripts/genesys/dev/update-template-scenes.ts +84 -0
  111. package/src/templates/scripts/genesys/doc-server.ts +16 -0
  112. package/src/templates/scripts/genesys/genesys-mcp.ts +526 -0
  113. package/src/templates/scripts/genesys/mcp/doc-tools.ts +86 -0
  114. package/src/templates/scripts/genesys/mcp/editor-functions.ts +151 -0
  115. package/src/templates/scripts/genesys/mcp/editor-tools.ts +73 -0
  116. package/src/templates/scripts/genesys/mcp/get-scene-state.ts +35 -0
  117. package/src/templates/scripts/genesys/mcp/run-subprocess.ts +30 -0
  118. package/src/templates/scripts/genesys/mcp/search-actors.ts +858 -0
  119. package/src/templates/scripts/genesys/mcp/search-assets.ts +380 -0
  120. package/src/templates/scripts/genesys/mcp/utils.ts +281 -0
  121. package/src/templates/scripts/genesys/misc.ts +42 -0
  122. package/src/templates/scripts/genesys/mock.ts +6 -0
  123. package/src/templates/scripts/genesys/place-actors.ts +179 -0
  124. package/src/templates/scripts/genesys/post-install.ts +30 -0
  125. package/src/templates/scripts/genesys/prefab.schema.json +85 -0
  126. package/src/templates/scripts/genesys/remove-engine-comments.ts +135 -0
  127. package/src/templates/scripts/genesys/run-mcp-inspector.bat +5 -0
  128. package/src/templates/scripts/genesys/storageProvider.ts +182 -0
  129. package/src/templates/scripts/genesys/validate-prefabs.ts +138 -0
  130. package/src/templates/src/index.ts +22 -0
  131. package/src/templates/src/templates/firstPerson/assets/default.genesys-scene +166 -0
  132. package/src/templates/src/templates/firstPerson/src/auto-imports.ts +0 -0
  133. package/src/templates/src/templates/firstPerson/src/game.ts +39 -0
  134. package/src/templates/src/templates/firstPerson/src/player.ts +63 -0
  135. package/src/templates/src/templates/fps/assets/default.genesys-scene +9460 -0
  136. package/src/templates/src/templates/fps/assets/models/SM_Beam_400.glb +0 -0
  137. package/src/templates/src/templates/fps/assets/models/SM_ChamferCube.glb +0 -0
  138. package/src/templates/src/templates/fps/assets/models/SM_Floor_Thick_400x400.glb +0 -0
  139. package/src/templates/src/templates/fps/assets/models/SM_Floor_Thick_400x400_Orange.glb +0 -0
  140. package/src/templates/src/templates/fps/assets/models/SM_Floor_Thin_400x400.glb +0 -0
  141. package/src/templates/src/templates/fps/assets/models/SM_Floor_Thin_400x400_Orange.glb +0 -0
  142. package/src/templates/src/templates/fps/assets/models/SM_Ramp_400x400.glb +0 -0
  143. package/src/templates/src/templates/fps/assets/models/SM_Rifle.glb +0 -0
  144. package/src/templates/src/templates/fps/assets/models/SM_Wall_Thin_400x200.glb +0 -0
  145. package/src/templates/src/templates/fps/assets/models/SM_Wall_Thin_400x200_Orange.glb +0 -0
  146. package/src/templates/src/templates/fps/assets/models/SM_Wall_Thin_400x400.glb +0 -0
  147. package/src/templates/src/templates/fps/assets/models/SM_Wall_Thin_400x400_Orange.glb +0 -0
  148. package/src/templates/src/templates/fps/src/auto-imports.ts +0 -0
  149. package/src/templates/src/templates/fps/src/game.ts +39 -0
  150. package/src/templates/src/templates/fps/src/player.ts +69 -0
  151. package/src/templates/src/templates/fps/src/weapon.ts +54 -0
  152. package/src/templates/src/templates/freeCamera/assets/default.genesys-scene +166 -0
  153. package/src/templates/src/templates/freeCamera/src/auto-imports.ts +0 -0
  154. package/src/templates/src/templates/freeCamera/src/game.ts +39 -0
  155. package/src/templates/src/templates/freeCamera/src/player.ts +45 -0
  156. package/src/templates/src/templates/sideScroller/assets/default.genesys-scene +122 -0
  157. package/src/templates/src/templates/sideScroller/src/auto-imports.ts +0 -0
  158. package/src/templates/src/templates/sideScroller/src/const.ts +46 -0
  159. package/src/templates/src/templates/sideScroller/src/game.ts +122 -0
  160. package/src/templates/src/templates/sideScroller/src/level-generator.ts +361 -0
  161. package/src/templates/src/templates/sideScroller/src/player.ts +125 -0
  162. package/src/templates/src/templates/thirdPerson/assets/default.genesys-scene +166 -0
  163. package/src/templates/src/templates/thirdPerson/src/auto-imports.ts +0 -0
  164. package/src/templates/src/templates/thirdPerson/src/game.ts +39 -0
  165. package/src/templates/src/templates/thirdPerson/src/player.ts +61 -0
  166. package/src/templates/src/templates/vehicle/assets/default.genesys-scene +226 -0
  167. package/src/templates/src/templates/vehicle/assets/models/cyberTruck/chassis.glb +0 -0
  168. package/src/templates/src/templates/vehicle/assets/models/cyberTruck/wheel.glb +0 -0
  169. package/src/templates/src/templates/vehicle/src/auto-imports.ts +0 -0
  170. package/src/templates/src/templates/vehicle/src/base-vehicle.ts +145 -0
  171. package/src/templates/src/templates/vehicle/src/game.ts +43 -0
  172. package/src/templates/src/templates/vehicle/src/mesh-vehicle.ts +191 -0
  173. package/src/templates/src/templates/vehicle/src/player.ts +109 -0
  174. package/src/templates/src/templates/vehicle/src/primitive-vehicle.ts +266 -0
  175. package/src/templates/src/templates/vehicle/src/ui-hints.ts +101 -0
  176. package/src/templates/src/templates/vr-game/assets/default.genesys-scene +247 -0
  177. package/src/templates/src/templates/vr-game/src/auto-imports.ts +1 -0
  178. package/src/templates/src/templates/vr-game/src/game.ts +66 -0
  179. package/src/templates/src/templates/vr-game/src/sample-vr-actor.ts +26 -0
  180. package/src/templates/tsconfig.json +35 -0
  181. package/src/templates/vite.config.ts +52 -0
@@ -0,0 +1,51 @@
1
+ import { getProjectRoot, isDev } from './common.js';
2
+
3
+ const fileServerPort = !isDev ? 4000 : 4001;
4
+
5
+ async function main() {
6
+ try {
7
+ const rootResponse = await fetch(`http://localhost:${fileServerPort}/`);
8
+
9
+ if (!rootResponse.ok) {
10
+ console.log('❌ Failed to talk to the Genesys SDK App, please make sure it is running and open the project in it!');
11
+ return;
12
+ }
13
+
14
+ const projectPath = getProjectRoot();
15
+
16
+ console.log(`🔨 Building project: ${projectPath} ...`);
17
+
18
+ const buildResponse = await fetch(`http://localhost:${fileServerPort}/api/build-project`, {
19
+ method: 'POST',
20
+ headers: {
21
+ 'Content-Type': 'application/json',
22
+ },
23
+ body: JSON.stringify({
24
+ projectPath,
25
+ }),
26
+ });
27
+ const responseJson = await buildResponse.json();
28
+ if (!buildResponse.ok) {
29
+ console.log('❌ Failed to build project, please check the console for errors!');
30
+ console.log(responseJson);
31
+ return;
32
+ }
33
+
34
+ /*
35
+ success: result.success,
36
+ message: result.message,
37
+ error: result.error
38
+ */
39
+ if (!responseJson.success) {
40
+ console.log(`❌ Failed to build project:\n - ${responseJson.error ?? responseJson.message}`);
41
+ return;
42
+ }
43
+
44
+ console.log(`✅ ${responseJson.message}`);
45
+
46
+ } catch (error) {
47
+ console.log('❌ Failed to talk to the Genesys SDK App, please make sure it is running and open the project in it!');
48
+ }
49
+ }
50
+
51
+ main();
@@ -0,0 +1,272 @@
1
+ import fs, { readFileSync } from 'fs';
2
+ import path, { resolve } from 'path';
3
+
4
+ import * as ENGINE from 'genesys.js';
5
+ import * as THREE from 'three';
6
+ import { MeshoptDecoder } from 'three/examples/jsm/libs/meshopt_decoder.module.js';
7
+ import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
8
+ import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
9
+
10
+ import { mockBrowserEnvironment } from './mock.js';
11
+
12
+ import type { Transform } from './common.js';
13
+
14
+ mockBrowserEnvironment();
15
+
16
+ // Custom error types for better error handling
17
+ class GLBLoadError extends Error {
18
+ constructor(message: string, public readonly filePath: string) {
19
+ super(message);
20
+ this.name = 'GLBLoadError';
21
+ }
22
+ }
23
+
24
+ class BoundingBoxCalculationError extends Error {
25
+ constructor(message: string) {
26
+ super(message);
27
+ this.name = 'BoundingBoxCalculationError';
28
+ }
29
+ }
30
+
31
+ // Interface for manifest entry
32
+ interface ManifestEntry {
33
+ readonly bounding_box: ENGINE.TBoundingBox;
34
+ readonly timestamp: string;
35
+ }
36
+
37
+ // Interface for the entire manifest
38
+ interface BoundingBoxManifest {
39
+ [filePath: string]: ManifestEntry;
40
+ }
41
+
42
+ function verifyPath(path: string) {
43
+ if (path.startsWith(ENGINE.PROJECT_PATH_PREFIX) || path.startsWith(ENGINE.ENGINE_PATH_PREFIX)) {
44
+ throw new Error(`Expecting a valid path, not a project or engine path: ${path}`);
45
+ }
46
+ }
47
+
48
+ /**
49
+ * Helper function to load and parse a GLB file
50
+ * @param glbFilePath - Path to the GLB file
51
+ * @returns Promise resolving to the loaded GLTF scene
52
+ */
53
+ async function loadGLBFile(glbFilePath: string): Promise<any> {
54
+ verifyPath(glbFilePath);
55
+
56
+ // Resolve the absolute path
57
+ const absolutePath = resolve(glbFilePath);
58
+ try {
59
+ // Read the GLB file
60
+ const glbData = readFileSync(absolutePath);
61
+ const arrayBuffer = glbData.buffer.slice(
62
+ glbData.byteOffset,
63
+ glbData.byteOffset + glbData.byteLength
64
+ );
65
+
66
+ // Load the GLB using GLTFLoader
67
+ const loader = new GLTFLoader();
68
+ loader.setMeshoptDecoder(MeshoptDecoder);
69
+ const dracoLoader = new DRACOLoader();
70
+ dracoLoader.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.5.6/');
71
+ loader.setDRACOLoader(dracoLoader);
72
+ const gltf = await loader.parseAsync(arrayBuffer, '');
73
+
74
+ if (!gltf.scene) {
75
+ throw new BoundingBoxCalculationError('No scene found in GLB file');
76
+ }
77
+
78
+ return gltf;
79
+ } catch (error) {
80
+ if (error instanceof Error) {
81
+ if (error.name === 'GLBLoadError' || error.name === 'BoundingBoxCalculationError') {
82
+ throw error;
83
+ }
84
+ throw new GLBLoadError(`Failed to load GLB file: ${error.message}`, glbFilePath);
85
+ }
86
+ throw new GLBLoadError('Unknown error loading GLB file', glbFilePath);
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Helper function to extract bounding box data from a Three.js Box3
92
+ * @param boundingBox - Three.js Box3 object
93
+ * @returns BoundingBox interface object
94
+ */
95
+ function extractBoundingBoxData(boundingBox: THREE.Box3): ENGINE.TBoundingBox {
96
+ return ENGINE.DescriptionHelper.dumpBoundingBox(boundingBox);
97
+ }
98
+
99
+ /**
100
+ * Calculates the bounding box of a GLB mesh with applied transformations
101
+ * @param glbFilePath - Path to the GLB file
102
+ * @param transform - Transformation to apply (position, rotation, scale)
103
+ * @returns Promise resolving to the calculated bounding box
104
+ */
105
+ async function calculateGLBBoundingBox(
106
+ glbFilePath: string,
107
+ transform: Transform
108
+ ): Promise<ENGINE.TBoundingBox> {
109
+ const gltf = await loadGLBFile(glbFilePath);
110
+
111
+ // Create a new object to apply transformations
112
+ const transformedObject = new THREE.Object3D();
113
+ transformedObject.add(gltf.scene);
114
+
115
+ // Apply transformations
116
+ transform.position && transformedObject.position.set(...transform.position as [number, number, number]);
117
+ transform.rotation && transformedObject.rotation.set(...transform.rotation as [number, number, number]);
118
+ transform.scale && transformedObject.scale.set(...transform.scale as [number, number, number]);
119
+
120
+ // Update world matrix to ensure transformations are applied
121
+ transformedObject.updateMatrixWorld(true);
122
+
123
+ const boundingBox = ENGINE.GLTFMeshComponent.calcBoundingBoxFromGLTF(gltf);
124
+ return extractBoundingBoxData(boundingBox);
125
+ }
126
+
127
+ /**
128
+ * Calculates the original bounding box of a GLB mesh without any transformations
129
+ * @param glbFilePath - Path to the GLB file
130
+ * @returns Promise resolving to the original mesh bounding box
131
+ */
132
+ async function calculateGLBOriginalBoundingBox(glbFilePath: string): Promise<ENGINE.TBoundingBox> {
133
+ const gltf = await loadGLBFile(glbFilePath);
134
+
135
+ const boundingBox = ENGINE.GLTFMeshComponent.calcBoundingBoxFromGLTF(gltf);
136
+ return extractBoundingBoxData(boundingBox);
137
+ }
138
+
139
+ /**
140
+ * Helper function to create a default transform
141
+ */
142
+ function createTransform(
143
+ position: [number, number, number] = [0, 0, 0],
144
+ rotation: [number, number, number] = [0, 0, 0],
145
+ scale: [number, number, number] = [1, 1, 1]
146
+ ): Transform {
147
+ return { position, rotation, scale };
148
+ }
149
+
150
+ /**
151
+ * Utility function to convert degrees to radians
152
+ */
153
+ function degreesToRadians(degrees: number): number {
154
+ return degrees * (Math.PI / 180);
155
+ }
156
+
157
+
158
+ /**
159
+ * Fetches the bounding box data from the manifest file, and returns the bounding box data
160
+ * It internally keeps a bounding box manifest as a cache, and only recalculates the bounding box data if the file has been modified since last calculation
161
+ * @param manifestFile - Path to the manifest JSON file, must be a valid path, not `@project` or `@engine` path
162
+ * @param gltfPaths - Dictionary of gltf key to GLTF file paths, key in theory can be any ID of a gltf mesh.
163
+ */
164
+ async function fetchBoundingBoxData(manifestFile: string, gltfPaths: {[key: string]: string}): Promise<{[filePath: string]: ENGINE.TBoundingBox}> {
165
+ verifyPath(manifestFile);
166
+ manifestFile = resolve(manifestFile);
167
+ try {
168
+ // Read existing manifest or create empty one
169
+ let manifest: BoundingBoxManifest = {};
170
+
171
+ try {
172
+ if (fs.existsSync(manifestFile)) {
173
+ const manifestContent = fs.readFileSync(manifestFile, 'utf-8');
174
+ manifest = JSON.parse(manifestContent) as BoundingBoxManifest;
175
+ console.log(`Loaded existing manifest with ${Object.keys(manifest).length} entries`);
176
+ } else {
177
+ console.log('Creating new manifest file');
178
+ }
179
+ } catch (error) {
180
+ console.warn(`Failed to read existing manifest, starting fresh: ${error instanceof Error ? error.message : String(error)}`);
181
+ manifest = {};
182
+ }
183
+
184
+ // Process each GLTF file
185
+ const updatedManifest: BoundingBoxManifest = { ...manifest };
186
+ let processedCount = 0;
187
+ let skippedCount = 0;
188
+
189
+ for (const [key, gltfPath] of Object.entries(gltfPaths)) {
190
+ try {
191
+ // Resolve absolute path for consistent comparison
192
+ const absolutePath = resolve(gltfPath);
193
+
194
+ // Check if file exists
195
+ if (!fs.existsSync(absolutePath)) {
196
+ console.warn(`Warning: File not found: ${gltfPath}`);
197
+ continue;
198
+ }
199
+
200
+ // Get file stats to check modification time
201
+ const stats = fs.statSync(absolutePath);
202
+ const currentTimestamp = stats.mtime.toISOString();
203
+
204
+ // Check if we need to update this file
205
+ const existingEntry = manifest[key];
206
+ if (existingEntry && existingEntry.timestamp === currentTimestamp) {
207
+ console.log(`Skipping ${gltfPath} (unchanged)`);
208
+ skippedCount++;
209
+ continue;
210
+ }
211
+
212
+ // Calculate bounding box for new/modified file
213
+ console.log(`Processing ${gltfPath}...`);
214
+ const boundingBox = await calculateGLBOriginalBoundingBox(absolutePath);
215
+
216
+ // Update manifest entry
217
+ updatedManifest[key] = {
218
+ bounding_box: boundingBox,
219
+ timestamp: currentTimestamp
220
+ };
221
+
222
+ processedCount++;
223
+ console.log(`✓ Updated bounding box for ${gltfPath}`);
224
+
225
+ } catch (error) {
226
+ const errorMessage = error instanceof Error ? error.message : String(error);
227
+ console.error(`Failed to process ${gltfPath}: ${errorMessage}`);
228
+ // Continue processing other files even if one fails
229
+ }
230
+ }
231
+
232
+ // Save updated manifest if any changes were made
233
+ if (processedCount > 0) {
234
+ // Ensure directory exists
235
+ const manifestDir = path.dirname(manifestFile);
236
+ if (!fs.existsSync(manifestDir)) {
237
+ fs.mkdirSync(manifestDir, { recursive: true });
238
+ }
239
+
240
+ // Write manifest with pretty formatting
241
+ fs.writeFileSync(manifestFile, JSON.stringify(updatedManifest, null, 2), 'utf-8');
242
+ console.log(`\n✓ Manifest updated: ${processedCount} files processed, ${skippedCount} files skipped`);
243
+ console.log(`Manifest saved to: ${manifestFile}`);
244
+ } else {
245
+ console.log(`\n✓ No updates needed: ${skippedCount} files already up to date`);
246
+ }
247
+
248
+ return Object.fromEntries(
249
+ Object.entries(gltfPaths).map(([key, absPath]) => [key, updatedManifest[key].bounding_box])
250
+ );
251
+ } catch (error) {
252
+ const errorMessage = error instanceof Error ? error.message : String(error);
253
+ throw new Error(`Failed to update bounding box manifest: ${errorMessage}`);
254
+ }
255
+ }
256
+
257
+ // Export the main functions for use as a module
258
+ export {
259
+ calculateGLBBoundingBox,
260
+ calculateGLBOriginalBoundingBox,
261
+ createTransform,
262
+ degreesToRadians,
263
+ fetchBoundingBoxData,
264
+ extractBoundingBoxData,
265
+ GLBLoadError,
266
+ BoundingBoxCalculationError
267
+ };
268
+
269
+ export type { Transform, ManifestEntry, BoundingBoxManifest };
270
+ export { BoundingBoxSchema } from 'genesys.js';
271
+
272
+
@@ -0,0 +1,46 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { fileURLToPath } from 'url';
4
+
5
+ import { z } from 'zod';
6
+
7
+ export const isDev = process.env.NODE_ENV === 'development' ||
8
+ process.env.NODE_ENV === 'dev' ||
9
+ process.argv.includes('--dev');
10
+
11
+ export function mockEsModule() {
12
+ const __filename = fileURLToPath(import.meta.url);
13
+ const __dirname = path.dirname(__filename);
14
+ (global as any).__filename = __filename;
15
+ (global as any).__dirname = __dirname;
16
+ }
17
+
18
+ mockEsModule();
19
+
20
+ export function getProjectRoot() {
21
+ let currentDir = __dirname;
22
+ while (true) {
23
+ if (fs.existsSync(path.join(currentDir, 'package.json'))) {
24
+ return currentDir;
25
+ }
26
+ const parentDir = path.dirname(currentDir);
27
+ if (parentDir === currentDir) {
28
+ throw new Error('Project root not found');
29
+ }
30
+ currentDir = parentDir;
31
+ }
32
+ }
33
+
34
+ export const TransformSchema = z.object({
35
+ position: z.array(z.number()).length(3).optional().describe('Position as [x, y, z]'),
36
+ rotation: z.array(z.number()).length(3).optional().describe('Rotation in radians as [x, y, z]'),
37
+ scale: z.array(z.number()).length(3).optional().describe('Scale as [x, y, z], use this to scale the actor up or down'),
38
+ });
39
+
40
+ export type Transform = z.infer<typeof TransformSchema>;
41
+
42
+ export const ActorInfoSchema = z.object({
43
+ displayName: z.string().describe('Display name of the actor'),
44
+ description: z.string().optional().describe('Description of the actor, including its purpose, how to use it, etc.'),
45
+ });
46
+
@@ -0,0 +1,9 @@
1
+ // MUST be kept in sync with https://github.com/directivegames/genesys.ai/blob/develop/src/const.ts
2
+ export const SCENE_EXTENSION: string = '.genesys-scene';
3
+ export const PUBLIC_FOLDER: string = 'public';
4
+ export const PROJECT_PREFIX: string = '@project';
5
+ export const ENGINE_PREFIX: string = '@engine';
6
+ export const DEFAULT_GAME_NAME: string = 'game.ts';
7
+ export const DEFAULT_GAME_BUNDLE_NAME: string = 'game.js';
8
+ export const BUILT_PROJECT_FOLDER: string = '.dist';
9
+ export const JS_CLASSES_DIR_NAME: string = '@js-classes';
@@ -0,0 +1,11 @@
1
+ import * as ENGINE from 'genesys.js';
2
+
3
+ import { defaultWorldOptions } from '../mcp/utils.js';
4
+
5
+ function main() {
6
+ const world = new ENGINE.World(defaultWorldOptions);
7
+ ENGINE.GameBuilder.createDefaultEditorScene(world);
8
+ console.log(JSON.stringify(world.asExportedObject(), null, 2));
9
+ }
10
+
11
+ main();
@@ -0,0 +1,146 @@
1
+ // pnpm exec tsx ./scripts/genesys/dev/generate-manifest.ts
2
+ import * as fs from 'fs';
3
+ import * as path from 'path';
4
+
5
+ import * as ENGINE from 'genesys.js';
6
+
7
+ import { ManifestPath } from './storage-provider.js';
8
+
9
+ import type { FileManifest, FileManifestItem} from './storage-provider.js';
10
+
11
+ /**
12
+ * Recursively scans a directory and returns file information
13
+ */
14
+ function scanDirectory(
15
+ dirPath: string,
16
+ basePath: string = '',
17
+ ): FileManifestItem[] {
18
+
19
+ const items: FileManifestItem[] = [];
20
+
21
+ if (!fs.existsSync(dirPath)) {
22
+ return items;
23
+ }
24
+
25
+ try {
26
+ const entries = fs.readdirSync(dirPath, { withFileTypes: true });
27
+
28
+ for (const entry of entries) {
29
+ const fullPath = path.join(dirPath, entry.name);
30
+ const relativePath = basePath ? path.join(basePath, entry.name) : entry.name;
31
+ const stats = fs.statSync(fullPath);
32
+
33
+ const item: FileManifestItem = {
34
+ name: entry.name,
35
+ path: relativePath.replace(/\\/g, '/'), // Normalize to forward slashes
36
+ size: stats.size,
37
+ modifiedTime: stats.mtime,
38
+ isDirectory: entry.isDirectory(),
39
+ contentType: getContentType(entry.name)
40
+ };
41
+
42
+ items.push(item);
43
+
44
+ // Recursively scan subdirectories
45
+ if (entry.isDirectory()) {
46
+ const subItems = scanDirectory(fullPath, relativePath);
47
+ items.push(...subItems);
48
+ }
49
+ }
50
+ } catch (error) {
51
+ console.warn(`Failed to scan directory ${dirPath}:`, error);
52
+ }
53
+
54
+ return items;
55
+ }
56
+
57
+ /**
58
+ * Gets content type based on file extension
59
+ */
60
+ function getContentType(fileName: string): string | undefined {
61
+ const ext = path.extname(fileName).toLowerCase();
62
+ const contentTypes: Record<string, string> = {
63
+ '.json': 'application/json',
64
+ '.js': 'application/javascript',
65
+ '.ts': 'application/typescript',
66
+ '.html': 'text/html',
67
+ '.css': 'text/css',
68
+ '.png': 'image/png',
69
+ '.jpg': 'image/jpeg',
70
+ '.jpeg': 'image/jpeg',
71
+ '.gif': 'image/gif',
72
+ '.webp': 'image/webp',
73
+ '.svg': 'image/svg+xml',
74
+ '.glb': 'model/gltf-binary',
75
+ '.gltf': 'model/gltf+json',
76
+ '.wav': 'audio/wav',
77
+ '.mp3': 'audio/mpeg',
78
+ '.ogg': 'audio/ogg',
79
+ '.genesys-scene': 'application/json',
80
+ '.genesys-project': 'application/json'
81
+ };
82
+
83
+ return contentTypes[ext];
84
+ }
85
+
86
+ /**
87
+ * Groups files by directory path for efficient lookup
88
+ */
89
+ function groupFilesByDirectory(files: FileManifestItem[]): Record<string, FileManifestItem[]> {
90
+ const grouped: Record<string, FileManifestItem[]> = {};
91
+
92
+ // Add root directory
93
+ grouped[''] = [];
94
+
95
+ for (const file of files) {
96
+ const dir = path.dirname(file.path).replace(/\\/g, '/');
97
+ const normalizedDir = dir === '.' ? '' : dir;
98
+
99
+ if (!grouped[normalizedDir]) {
100
+ grouped[normalizedDir] = [];
101
+ }
102
+
103
+ grouped[normalizedDir].push(file);
104
+ }
105
+
106
+ return grouped;
107
+ }
108
+
109
+ /**
110
+ * Generates the file manifest
111
+ */
112
+ export async function generateManifest(): Promise<void> {
113
+ console.log('Generating file manifest...');
114
+
115
+ const manifest: FileManifest = {
116
+ generated: new Date().toISOString(),
117
+ projectFiles: {},
118
+ engineFiles: {}
119
+ };
120
+
121
+ // Scan project files
122
+ console.log('Scanning project files...');
123
+ const projectRoot = process.cwd();
124
+ const builtProjectRoot = path.join(projectRoot, ENGINE.BUILT_PROJECT_FOLDER);
125
+ const projectFiles = scanDirectory(builtProjectRoot);
126
+ manifest.projectFiles = groupFilesByDirectory(projectFiles);
127
+
128
+ // Scan engine files
129
+ console.log('Scanning engine files...');
130
+ const engineAssetsRoot = path.join(projectRoot, 'node_modules', 'genesys.js', 'assets');
131
+ if (fs.existsSync(engineAssetsRoot)) {
132
+ const engineFiles = scanDirectory(engineAssetsRoot, 'assets');
133
+ manifest.engineFiles = groupFilesByDirectory(engineFiles);
134
+ console.log(`Engine files: ${Object.values(manifest.engineFiles).flat().length}`);
135
+ }
136
+
137
+ // Write manifest to public directory so it's accessible to the dev server
138
+ const manifestPath = path.join(projectRoot, ManifestPath);
139
+ fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
140
+
141
+ console.log(`File manifest generated: ${manifestPath}`);
142
+ console.log(`Project files: ${Object.values(manifest.projectFiles).flat().length}`);
143
+ console.log(`Engine files: ${Object.values(manifest.engineFiles).flat().length}`);
144
+ }
145
+
146
+ generateManifest().catch(console.error);
@@ -0,0 +1,46 @@
1
+ import * as ENGINE from 'genesys.js';
2
+
3
+ import { DevStorageProvider } from './storage-provider.js';
4
+
5
+ // Ensure process is available globally with minimal implementation
6
+ if (typeof globalThis.process === 'undefined') {
7
+ (globalThis as any).process = {
8
+ cwd: () => '/',
9
+ env: {},
10
+ };
11
+ }
12
+
13
+ // Initialize the game - can be called manually
14
+ export async function launchGame() {
15
+ const container = document.getElementById('game-container');
16
+ if (!container) {
17
+ console.error('Game container not found!');
18
+ return;
19
+ }
20
+
21
+ try {
22
+ // Create the storage provider for Vite dev environment
23
+ const storageProvider = new DevStorageProvider();
24
+
25
+ ENGINE.projectContext({
26
+ project: 'dev-game',
27
+ storageProvider,
28
+ });
29
+
30
+ // Create the game runtime
31
+ const gameRuntime = new ENGINE.GameRuntime({
32
+ provider: storageProvider,
33
+ container: container,
34
+ gameId: 'dev-game',
35
+ buildProject: false,
36
+ skipClearGameClasses: false
37
+ });
38
+
39
+ console.log('Starting game runtime...');
40
+
41
+ // Start the game with the default scene
42
+ await gameRuntime.startGame();
43
+ } catch (error) {
44
+ console.error('Failed to initialize game:', error);
45
+ }
46
+ }