@directivegames/genesys.sdk 3.2.2 → 3.2.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.
- package/README.md +60 -60
- package/dist/src/core/cli.js +22 -22
- package/dist/src/templates/scripts/genesys/genesys-mcp.js +25 -25
- package/dist/src/templates/scripts/genesys/mcp/editor-functions.js +4 -4
- package/dist/src/templates/src/templates/vehicle/src/ui-hints.js +30 -30
- package/package.json +176 -176
- package/scripts/post-install.ts +143 -143
- package/src/asset-pack/.gitattributes +88 -88
- package/src/asset-pack/eslint.config.js +45 -45
- package/src/asset-pack/gitignore +11 -11
- package/src/asset-pack/scripts/postinstall.ts +81 -81
- package/src/asset-pack/tsconfig.json +33 -33
- package/src/templates/.cursor/mcp.json +20 -20
- package/src/templates/.cursorignore +2 -2
- package/src/templates/.gitattributes +88 -88
- package/src/templates/.vscode/settings.json +6 -6
- package/src/templates/AGENTS.md +86 -86
- package/src/templates/README.md +24 -24
- package/src/templates/eslint.config.js +45 -45
- package/src/templates/gitignore +11 -11
- package/src/templates/index.html +34 -34
- package/src/templates/pnpm-lock.yaml +3676 -3676
- package/src/templates/scripts/genesys/build-project.ts +51 -51
- package/src/templates/scripts/genesys/calc-bounding-box.ts +272 -272
- package/src/templates/scripts/genesys/common.ts +46 -46
- package/src/templates/scripts/genesys/const.ts +9 -9
- package/src/templates/scripts/genesys/dev/dump-default-scene.ts +11 -11
- package/src/templates/scripts/genesys/dev/generate-manifest.ts +146 -146
- package/src/templates/scripts/genesys/dev/launcher.ts +46 -46
- package/src/templates/scripts/genesys/dev/storage-provider.ts +229 -229
- package/src/templates/scripts/genesys/dev/update-template-scenes.ts +84 -84
- package/src/templates/scripts/genesys/doc-server.ts +16 -16
- package/src/templates/scripts/genesys/genesys-mcp.ts +526 -526
- package/src/templates/scripts/genesys/mcp/doc-tools.ts +86 -86
- package/src/templates/scripts/genesys/mcp/editor-functions.ts +151 -151
- package/src/templates/scripts/genesys/mcp/editor-tools.ts +73 -73
- package/src/templates/scripts/genesys/mcp/get-scene-state.ts +35 -35
- package/src/templates/scripts/genesys/mcp/run-subprocess.ts +30 -30
- package/src/templates/scripts/genesys/mcp/search-actors.ts +858 -858
- package/src/templates/scripts/genesys/mcp/search-assets.ts +380 -380
- package/src/templates/scripts/genesys/mcp/utils.ts +281 -281
- package/src/templates/scripts/genesys/misc.ts +42 -42
- package/src/templates/scripts/genesys/mock.ts +6 -6
- package/src/templates/scripts/genesys/place-actors.ts +179 -179
- package/src/templates/scripts/genesys/post-install.ts +30 -30
- package/src/templates/scripts/genesys/prefab.schema.json +84 -84
- package/src/templates/scripts/genesys/remove-engine-comments.ts +134 -134
- package/src/templates/scripts/genesys/run-mcp-inspector.bat +4 -4
- package/src/templates/scripts/genesys/storageProvider.ts +182 -182
- package/src/templates/scripts/genesys/validate-prefabs.ts +138 -138
- package/src/templates/src/index.ts +22 -22
- package/src/templates/src/templates/firstPerson/assets/default.genesys-scene +165 -165
- package/src/templates/src/templates/firstPerson/src/game.ts +39 -39
- package/src/templates/src/templates/firstPerson/src/player.ts +63 -63
- package/src/templates/src/templates/fps/assets/default.genesys-scene +9459 -9459
- package/src/templates/src/templates/fps/src/game.ts +39 -39
- package/src/templates/src/templates/fps/src/player.ts +69 -69
- package/src/templates/src/templates/fps/src/weapon.ts +54 -54
- package/src/templates/src/templates/freeCamera/assets/default.genesys-scene +165 -165
- package/src/templates/src/templates/freeCamera/src/game.ts +39 -39
- package/src/templates/src/templates/freeCamera/src/player.ts +45 -45
- package/src/templates/src/templates/sideScroller/assets/default.genesys-scene +121 -121
- package/src/templates/src/templates/sideScroller/src/const.ts +45 -45
- package/src/templates/src/templates/sideScroller/src/game.ts +122 -122
- package/src/templates/src/templates/sideScroller/src/level-generator.ts +361 -361
- package/src/templates/src/templates/sideScroller/src/player.ts +125 -125
- package/src/templates/src/templates/thirdPerson/assets/default.genesys-scene +165 -165
- package/src/templates/src/templates/thirdPerson/src/game.ts +39 -39
- package/src/templates/src/templates/thirdPerson/src/player.ts +61 -61
- package/src/templates/src/templates/vehicle/assets/default.genesys-scene +225 -225
- package/src/templates/src/templates/vehicle/src/base-vehicle.ts +145 -145
- package/src/templates/src/templates/vehicle/src/game.ts +43 -43
- package/src/templates/src/templates/vehicle/src/mesh-vehicle.ts +191 -191
- package/src/templates/src/templates/vehicle/src/player.ts +109 -109
- package/src/templates/src/templates/vehicle/src/primitive-vehicle.ts +266 -266
- package/src/templates/src/templates/vehicle/src/ui-hints.ts +101 -101
- package/src/templates/src/templates/vr-game/assets/default.genesys-scene +246 -246
- package/src/templates/src/templates/vr-game/src/auto-imports.ts +1 -1
- package/src/templates/src/templates/vr-game/src/game.ts +66 -66
- package/src/templates/src/templates/vr-game/src/sample-vr-actor.ts +26 -26
- package/src/templates/tsconfig.json +34 -34
- package/src/templates/vite.config.ts +52 -52
|
@@ -1,229 +1,229 @@
|
|
|
1
|
-
import * as ENGINE from 'genesys.js';
|
|
2
|
-
|
|
3
|
-
export type FileManifestItem = Omit<ENGINE.FileItem, 'absolutePath'>;
|
|
4
|
-
|
|
5
|
-
export const ManifestPath = 'dist/file-manifest.json';
|
|
6
|
-
|
|
7
|
-
export interface FileManifest {
|
|
8
|
-
generated: string;
|
|
9
|
-
projectFiles: Record<string, FileManifestItem[]>;
|
|
10
|
-
engineFiles: Record<string, FileManifestItem[]>;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export class DevStorageProvider implements ENGINE.IStorageProvider {
|
|
14
|
-
private manifestCache: FileManifest | null = null;
|
|
15
|
-
private manifestPromise: Promise<FileManifest> | null = null;
|
|
16
|
-
|
|
17
|
-
private async loadManifest(): Promise<FileManifest> {
|
|
18
|
-
if (this.manifestCache) {
|
|
19
|
-
return this.manifestCache;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
if (this.manifestPromise) {
|
|
23
|
-
return this.manifestPromise;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
this.manifestPromise = this.fetchManifest();
|
|
27
|
-
this.manifestCache = await this.manifestPromise;
|
|
28
|
-
this.manifestPromise = null;
|
|
29
|
-
|
|
30
|
-
return this.manifestCache;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
private async fetchManifest(): Promise<FileManifest> {
|
|
34
|
-
try {
|
|
35
|
-
const response = await fetch(`/${ManifestPath}`);
|
|
36
|
-
if (!response.ok) {
|
|
37
|
-
throw new Error(`Failed to load manifest: ${response.status} ${response.statusText}`);
|
|
38
|
-
}
|
|
39
|
-
return await response.json();
|
|
40
|
-
} catch (error) {
|
|
41
|
-
console.warn('Failed to load file manifest, falling back to empty manifest:', error);
|
|
42
|
-
return {
|
|
43
|
-
generated: new Date().toISOString(),
|
|
44
|
-
projectFiles: {},
|
|
45
|
-
engineFiles: {}
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
async resolvePath(path: ENGINE.AssetPath, expiry?: number): Promise<ENGINE.AssetPath> {
|
|
51
|
-
if (path.isResolved()) {
|
|
52
|
-
return path;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
let resolvedUrl: string;
|
|
56
|
-
|
|
57
|
-
if (path.initialPath.startsWith(ENGINE.PROJECT_PATH_PREFIX)) {
|
|
58
|
-
resolvedUrl = path.initialPath.replace(ENGINE.PROJECT_PATH_PREFIX, ENGINE.BUILT_PROJECT_FOLDER);
|
|
59
|
-
} else if (path.initialPath.startsWith(ENGINE.ENGINE_PATH_PREFIX)) {
|
|
60
|
-
resolvedUrl = path.initialPath.replace(ENGINE.ENGINE_PATH_PREFIX, '/node_modules/genesys.js');
|
|
61
|
-
} else if (path.initialPath.startsWith('/')) {
|
|
62
|
-
resolvedUrl = `/node_modules/genesys.js${path.initialPath}`;
|
|
63
|
-
} else if (path.initialPath.startsWith('http') || path.initialPath.startsWith('https')) {
|
|
64
|
-
resolvedUrl = path.initialPath;
|
|
65
|
-
} else {
|
|
66
|
-
// Paths without prefix are treated as engine paths
|
|
67
|
-
resolvedUrl = `/node_modules/genesys.js/${path.initialPath}`;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
path.resolvePath(resolvedUrl, ENGINE.AssetPathEncodeState.Unknown);
|
|
71
|
-
return path;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
async downloadFileAsBuffer(path: ENGINE.AssetPath): Promise<ArrayBuffer> {
|
|
75
|
-
const resolvedPath = await this.resolvePath(path);
|
|
76
|
-
const response = await fetch(resolvedPath.getResolvedPath());
|
|
77
|
-
this.checkResponse(path, response);
|
|
78
|
-
return response.arrayBuffer();
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
async downloadFileAsJson<T>(path: ENGINE.AssetPath): Promise<T> {
|
|
82
|
-
const resolvedPath = await this.resolvePath(path);
|
|
83
|
-
const response = await fetch(resolvedPath.getResolvedPath());
|
|
84
|
-
this.checkResponse(path, response);
|
|
85
|
-
return response.json();
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
async downloadFileAsText(path: ENGINE.AssetPath): Promise<string> {
|
|
89
|
-
const resolvedPath = await this.resolvePath(path);
|
|
90
|
-
const response = await fetch(resolvedPath.getResolvedPath());
|
|
91
|
-
this.checkResponse(path, response);
|
|
92
|
-
return response.text();
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
async uploadFile(
|
|
96
|
-
path: ENGINE.AssetPath,
|
|
97
|
-
content: Blob | File | string | ArrayBuffer,
|
|
98
|
-
options?: ENGINE.FileUploadOptions
|
|
99
|
-
): Promise<{ path: string; name: string }> {
|
|
100
|
-
throw new Error('ViteDevStorageProvider does not support uploading files.');
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
async listFiles(
|
|
104
|
-
path: ENGINE.AssetPath,
|
|
105
|
-
recursive?: boolean,
|
|
106
|
-
includeHiddenFiles?: boolean
|
|
107
|
-
): Promise<ENGINE.FileListResult> {
|
|
108
|
-
try {
|
|
109
|
-
const manifest = await this.loadManifest();
|
|
110
|
-
const initialPath = path.initialPath;
|
|
111
|
-
const targetPath = this.normalizePathForManifest(initialPath);
|
|
112
|
-
|
|
113
|
-
// Determine which file collection to use
|
|
114
|
-
// Paths without prefix are treated as engine assets
|
|
115
|
-
const isEngineAsset = initialPath.startsWith(ENGINE.ENGINE_PATH_PREFIX);
|
|
116
|
-
const isProjectAsset = initialPath.startsWith(ENGINE.PROJECT_PATH_PREFIX);
|
|
117
|
-
if (!isEngineAsset && !isProjectAsset) {
|
|
118
|
-
throw new Error(`Invalid path: ${path}`);
|
|
119
|
-
}
|
|
120
|
-
const fileCollection = isEngineAsset ? manifest.engineFiles : manifest.projectFiles;
|
|
121
|
-
|
|
122
|
-
const files: ENGINE.FileItem[] = [];
|
|
123
|
-
const directories: ENGINE.FileItem[] = [];
|
|
124
|
-
|
|
125
|
-
if (recursive) {
|
|
126
|
-
// For recursive listing, include all files that start with the target path
|
|
127
|
-
for (const [dirPath, items] of Object.entries(fileCollection)) {
|
|
128
|
-
if (dirPath === targetPath || dirPath.startsWith(targetPath + '/') || (targetPath === '' && !dirPath.includes('/'))) {
|
|
129
|
-
for (const item of items) {
|
|
130
|
-
const engineFileItem = this.convertToEngineFileItem(item, isEngineAsset);
|
|
131
|
-
|
|
132
|
-
if (!includeHiddenFiles && item.name.startsWith('.')) {
|
|
133
|
-
continue;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
if (item.isDirectory) {
|
|
137
|
-
directories.push(engineFileItem);
|
|
138
|
-
} else {
|
|
139
|
-
files.push(engineFileItem);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
} else {
|
|
145
|
-
// For non-recursive listing, only include direct children
|
|
146
|
-
const directItems = fileCollection[targetPath] || [];
|
|
147
|
-
|
|
148
|
-
for (const item of directItems) {
|
|
149
|
-
const engineFileItem = this.convertToEngineFileItem(item, isEngineAsset);
|
|
150
|
-
|
|
151
|
-
if (!includeHiddenFiles && item.name.startsWith('.')) {
|
|
152
|
-
continue;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// Only include direct children (not nested)
|
|
156
|
-
const itemDirPath = item.path.substring(0, item.path.lastIndexOf('/'));
|
|
157
|
-
const normalizedItemDirPath = itemDirPath === '.' || itemDirPath === '' ? '' : itemDirPath;
|
|
158
|
-
|
|
159
|
-
if (normalizedItemDirPath === targetPath) {
|
|
160
|
-
if (item.isDirectory) {
|
|
161
|
-
directories.push(engineFileItem);
|
|
162
|
-
} else {
|
|
163
|
-
files.push(engineFileItem);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
return { files, directories };
|
|
170
|
-
} catch (error) {
|
|
171
|
-
console.warn(`Failed to list files for path ${path.initialPath}:`, error);
|
|
172
|
-
return { files: [], directories: [] };
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
async exists(path: ENGINE.AssetPath): Promise<boolean> {
|
|
177
|
-
try {
|
|
178
|
-
const resolvedPath = await this.resolvePath(path);
|
|
179
|
-
const response = await fetch(resolvedPath.getResolvedPath(), { method: 'HEAD' });
|
|
180
|
-
return response.ok;
|
|
181
|
-
} catch {
|
|
182
|
-
return false;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
async buildCurrentProject(runTsc: boolean): Promise<boolean> {
|
|
187
|
-
// For development, we don't need to build the project
|
|
188
|
-
// Vite handles the compilation
|
|
189
|
-
return true;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
private normalizePathForManifest(pathStr: string): string {
|
|
193
|
-
// Remove @project/ or @engine/ prefix
|
|
194
|
-
let normalized = pathStr.replace(ENGINE.PROJECT_PATH_PREFIX, '').replace(ENGINE.ENGINE_PATH_PREFIX, '');
|
|
195
|
-
|
|
196
|
-
// Remove leading slash if present
|
|
197
|
-
if (normalized.startsWith('/')) {
|
|
198
|
-
normalized = normalized.substring(1);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// Remove trailing slash if present
|
|
202
|
-
if (normalized.endsWith('/')) {
|
|
203
|
-
normalized = normalized.substring(0, normalized.length - 1);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
return normalized;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
private convertToEngineFileItem(manifestItem: FileManifestItem, isEngineAsset: boolean): ENGINE.FileItem {
|
|
210
|
-
const prefix = isEngineAsset ? ENGINE.ENGINE_PATH_PREFIX : ENGINE.PROJECT_PATH_PREFIX;
|
|
211
|
-
const path = `${prefix}/${manifestItem.path}`;
|
|
212
|
-
return {
|
|
213
|
-
name: manifestItem.name,
|
|
214
|
-
path: path,
|
|
215
|
-
absolutePath: path,
|
|
216
|
-
size: manifestItem.size,
|
|
217
|
-
modifiedTime: new Date(manifestItem.modifiedTime),
|
|
218
|
-
isDirectory: manifestItem.isDirectory,
|
|
219
|
-
contentType: manifestItem.contentType
|
|
220
|
-
};
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
private checkResponse(path: ENGINE.AssetPath, response: Response): void {
|
|
225
|
-
if (!response.ok) {
|
|
226
|
-
throw new Error(`Failed to fetch ${path.initialPath}: ${response.status} ${response.statusText}`);
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
}
|
|
1
|
+
import * as ENGINE from 'genesys.js';
|
|
2
|
+
|
|
3
|
+
export type FileManifestItem = Omit<ENGINE.FileItem, 'absolutePath'>;
|
|
4
|
+
|
|
5
|
+
export const ManifestPath = 'dist/file-manifest.json';
|
|
6
|
+
|
|
7
|
+
export interface FileManifest {
|
|
8
|
+
generated: string;
|
|
9
|
+
projectFiles: Record<string, FileManifestItem[]>;
|
|
10
|
+
engineFiles: Record<string, FileManifestItem[]>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export class DevStorageProvider implements ENGINE.IStorageProvider {
|
|
14
|
+
private manifestCache: FileManifest | null = null;
|
|
15
|
+
private manifestPromise: Promise<FileManifest> | null = null;
|
|
16
|
+
|
|
17
|
+
private async loadManifest(): Promise<FileManifest> {
|
|
18
|
+
if (this.manifestCache) {
|
|
19
|
+
return this.manifestCache;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (this.manifestPromise) {
|
|
23
|
+
return this.manifestPromise;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
this.manifestPromise = this.fetchManifest();
|
|
27
|
+
this.manifestCache = await this.manifestPromise;
|
|
28
|
+
this.manifestPromise = null;
|
|
29
|
+
|
|
30
|
+
return this.manifestCache;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
private async fetchManifest(): Promise<FileManifest> {
|
|
34
|
+
try {
|
|
35
|
+
const response = await fetch(`/${ManifestPath}`);
|
|
36
|
+
if (!response.ok) {
|
|
37
|
+
throw new Error(`Failed to load manifest: ${response.status} ${response.statusText}`);
|
|
38
|
+
}
|
|
39
|
+
return await response.json();
|
|
40
|
+
} catch (error) {
|
|
41
|
+
console.warn('Failed to load file manifest, falling back to empty manifest:', error);
|
|
42
|
+
return {
|
|
43
|
+
generated: new Date().toISOString(),
|
|
44
|
+
projectFiles: {},
|
|
45
|
+
engineFiles: {}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async resolvePath(path: ENGINE.AssetPath, expiry?: number): Promise<ENGINE.AssetPath> {
|
|
51
|
+
if (path.isResolved()) {
|
|
52
|
+
return path;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
let resolvedUrl: string;
|
|
56
|
+
|
|
57
|
+
if (path.initialPath.startsWith(ENGINE.PROJECT_PATH_PREFIX)) {
|
|
58
|
+
resolvedUrl = path.initialPath.replace(ENGINE.PROJECT_PATH_PREFIX, ENGINE.BUILT_PROJECT_FOLDER);
|
|
59
|
+
} else if (path.initialPath.startsWith(ENGINE.ENGINE_PATH_PREFIX)) {
|
|
60
|
+
resolvedUrl = path.initialPath.replace(ENGINE.ENGINE_PATH_PREFIX, '/node_modules/genesys.js');
|
|
61
|
+
} else if (path.initialPath.startsWith('/')) {
|
|
62
|
+
resolvedUrl = `/node_modules/genesys.js${path.initialPath}`;
|
|
63
|
+
} else if (path.initialPath.startsWith('http') || path.initialPath.startsWith('https')) {
|
|
64
|
+
resolvedUrl = path.initialPath;
|
|
65
|
+
} else {
|
|
66
|
+
// Paths without prefix are treated as engine paths
|
|
67
|
+
resolvedUrl = `/node_modules/genesys.js/${path.initialPath}`;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
path.resolvePath(resolvedUrl, ENGINE.AssetPathEncodeState.Unknown);
|
|
71
|
+
return path;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async downloadFileAsBuffer(path: ENGINE.AssetPath): Promise<ArrayBuffer> {
|
|
75
|
+
const resolvedPath = await this.resolvePath(path);
|
|
76
|
+
const response = await fetch(resolvedPath.getResolvedPath());
|
|
77
|
+
this.checkResponse(path, response);
|
|
78
|
+
return response.arrayBuffer();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async downloadFileAsJson<T>(path: ENGINE.AssetPath): Promise<T> {
|
|
82
|
+
const resolvedPath = await this.resolvePath(path);
|
|
83
|
+
const response = await fetch(resolvedPath.getResolvedPath());
|
|
84
|
+
this.checkResponse(path, response);
|
|
85
|
+
return response.json();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async downloadFileAsText(path: ENGINE.AssetPath): Promise<string> {
|
|
89
|
+
const resolvedPath = await this.resolvePath(path);
|
|
90
|
+
const response = await fetch(resolvedPath.getResolvedPath());
|
|
91
|
+
this.checkResponse(path, response);
|
|
92
|
+
return response.text();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async uploadFile(
|
|
96
|
+
path: ENGINE.AssetPath,
|
|
97
|
+
content: Blob | File | string | ArrayBuffer,
|
|
98
|
+
options?: ENGINE.FileUploadOptions
|
|
99
|
+
): Promise<{ path: string; name: string }> {
|
|
100
|
+
throw new Error('ViteDevStorageProvider does not support uploading files.');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async listFiles(
|
|
104
|
+
path: ENGINE.AssetPath,
|
|
105
|
+
recursive?: boolean,
|
|
106
|
+
includeHiddenFiles?: boolean
|
|
107
|
+
): Promise<ENGINE.FileListResult> {
|
|
108
|
+
try {
|
|
109
|
+
const manifest = await this.loadManifest();
|
|
110
|
+
const initialPath = path.initialPath;
|
|
111
|
+
const targetPath = this.normalizePathForManifest(initialPath);
|
|
112
|
+
|
|
113
|
+
// Determine which file collection to use
|
|
114
|
+
// Paths without prefix are treated as engine assets
|
|
115
|
+
const isEngineAsset = initialPath.startsWith(ENGINE.ENGINE_PATH_PREFIX);
|
|
116
|
+
const isProjectAsset = initialPath.startsWith(ENGINE.PROJECT_PATH_PREFIX);
|
|
117
|
+
if (!isEngineAsset && !isProjectAsset) {
|
|
118
|
+
throw new Error(`Invalid path: ${path}`);
|
|
119
|
+
}
|
|
120
|
+
const fileCollection = isEngineAsset ? manifest.engineFiles : manifest.projectFiles;
|
|
121
|
+
|
|
122
|
+
const files: ENGINE.FileItem[] = [];
|
|
123
|
+
const directories: ENGINE.FileItem[] = [];
|
|
124
|
+
|
|
125
|
+
if (recursive) {
|
|
126
|
+
// For recursive listing, include all files that start with the target path
|
|
127
|
+
for (const [dirPath, items] of Object.entries(fileCollection)) {
|
|
128
|
+
if (dirPath === targetPath || dirPath.startsWith(targetPath + '/') || (targetPath === '' && !dirPath.includes('/'))) {
|
|
129
|
+
for (const item of items) {
|
|
130
|
+
const engineFileItem = this.convertToEngineFileItem(item, isEngineAsset);
|
|
131
|
+
|
|
132
|
+
if (!includeHiddenFiles && item.name.startsWith('.')) {
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (item.isDirectory) {
|
|
137
|
+
directories.push(engineFileItem);
|
|
138
|
+
} else {
|
|
139
|
+
files.push(engineFileItem);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
} else {
|
|
145
|
+
// For non-recursive listing, only include direct children
|
|
146
|
+
const directItems = fileCollection[targetPath] || [];
|
|
147
|
+
|
|
148
|
+
for (const item of directItems) {
|
|
149
|
+
const engineFileItem = this.convertToEngineFileItem(item, isEngineAsset);
|
|
150
|
+
|
|
151
|
+
if (!includeHiddenFiles && item.name.startsWith('.')) {
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Only include direct children (not nested)
|
|
156
|
+
const itemDirPath = item.path.substring(0, item.path.lastIndexOf('/'));
|
|
157
|
+
const normalizedItemDirPath = itemDirPath === '.' || itemDirPath === '' ? '' : itemDirPath;
|
|
158
|
+
|
|
159
|
+
if (normalizedItemDirPath === targetPath) {
|
|
160
|
+
if (item.isDirectory) {
|
|
161
|
+
directories.push(engineFileItem);
|
|
162
|
+
} else {
|
|
163
|
+
files.push(engineFileItem);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return { files, directories };
|
|
170
|
+
} catch (error) {
|
|
171
|
+
console.warn(`Failed to list files for path ${path.initialPath}:`, error);
|
|
172
|
+
return { files: [], directories: [] };
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
async exists(path: ENGINE.AssetPath): Promise<boolean> {
|
|
177
|
+
try {
|
|
178
|
+
const resolvedPath = await this.resolvePath(path);
|
|
179
|
+
const response = await fetch(resolvedPath.getResolvedPath(), { method: 'HEAD' });
|
|
180
|
+
return response.ok;
|
|
181
|
+
} catch {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
async buildCurrentProject(runTsc: boolean): Promise<boolean> {
|
|
187
|
+
// For development, we don't need to build the project
|
|
188
|
+
// Vite handles the compilation
|
|
189
|
+
return true;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
private normalizePathForManifest(pathStr: string): string {
|
|
193
|
+
// Remove @project/ or @engine/ prefix
|
|
194
|
+
let normalized = pathStr.replace(ENGINE.PROJECT_PATH_PREFIX, '').replace(ENGINE.ENGINE_PATH_PREFIX, '');
|
|
195
|
+
|
|
196
|
+
// Remove leading slash if present
|
|
197
|
+
if (normalized.startsWith('/')) {
|
|
198
|
+
normalized = normalized.substring(1);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Remove trailing slash if present
|
|
202
|
+
if (normalized.endsWith('/')) {
|
|
203
|
+
normalized = normalized.substring(0, normalized.length - 1);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return normalized;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
private convertToEngineFileItem(manifestItem: FileManifestItem, isEngineAsset: boolean): ENGINE.FileItem {
|
|
210
|
+
const prefix = isEngineAsset ? ENGINE.ENGINE_PATH_PREFIX : ENGINE.PROJECT_PATH_PREFIX;
|
|
211
|
+
const path = `${prefix}/${manifestItem.path}`;
|
|
212
|
+
return {
|
|
213
|
+
name: manifestItem.name,
|
|
214
|
+
path: path,
|
|
215
|
+
absolutePath: path,
|
|
216
|
+
size: manifestItem.size,
|
|
217
|
+
modifiedTime: new Date(manifestItem.modifiedTime),
|
|
218
|
+
isDirectory: manifestItem.isDirectory,
|
|
219
|
+
contentType: manifestItem.contentType
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
private checkResponse(path: ENGINE.AssetPath, response: Response): void {
|
|
225
|
+
if (!response.ok) {
|
|
226
|
+
throw new Error(`Failed to fetch ${path.initialPath}: ${response.status} ${response.statusText}`);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
@@ -1,84 +1,84 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
|
|
4
|
-
import { SCENE_EXTENSION } from '../const.js';
|
|
5
|
-
import { loadWorld } from '../mcp/utils.js';
|
|
6
|
-
import { mockBrowserEnvironment } from '../mock.js';
|
|
7
|
-
|
|
8
|
-
// Mock browser environment as required by the engine
|
|
9
|
-
mockBrowserEnvironment();
|
|
10
|
-
|
|
11
|
-
async function findGenesysSceneFiles(dir: string): Promise<string[]> {
|
|
12
|
-
const sceneFiles: string[] = [];
|
|
13
|
-
|
|
14
|
-
try {
|
|
15
|
-
const items = fs.readdirSync(dir, { withFileTypes: true });
|
|
16
|
-
|
|
17
|
-
for (const item of items) {
|
|
18
|
-
const fullPath = path.join(dir, item.name);
|
|
19
|
-
|
|
20
|
-
if (item.isDirectory()) {
|
|
21
|
-
// Recursively search subdirectories
|
|
22
|
-
const subFiles = await findGenesysSceneFiles(fullPath);
|
|
23
|
-
sceneFiles.push(...subFiles);
|
|
24
|
-
} else if (item.isFile() && item.name.endsWith(SCENE_EXTENSION)) {
|
|
25
|
-
sceneFiles.push(fullPath);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
} catch (error) {
|
|
29
|
-
console.error(`Error reading directory ${dir}:`, error);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return sceneFiles;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
async function updateSceneFile(sceneFilePath: string): Promise<void> {
|
|
36
|
-
console.log(`Processing: ${sceneFilePath}`);
|
|
37
|
-
|
|
38
|
-
try {
|
|
39
|
-
// Use the loadWorld utility with proper disposal using 'using' keyword
|
|
40
|
-
using worldResource = await loadWorld(sceneFilePath, {
|
|
41
|
-
readonly: false, // Allow saving changes
|
|
42
|
-
skipLoadingGLTF: true // Skip GLTF loading for faster processing
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
console.log(`✓ Successfully updated: ${sceneFilePath}`);
|
|
46
|
-
} catch (error) {
|
|
47
|
-
console.error(`✗ Failed to update ${sceneFilePath}:`, error);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
async function main() {
|
|
52
|
-
console.log('Searching for .genesys-scene files in src folder...');
|
|
53
|
-
|
|
54
|
-
const srcDir = path.join(process.cwd(), 'src');
|
|
55
|
-
|
|
56
|
-
if (!fs.existsSync(srcDir)) {
|
|
57
|
-
console.error('src directory not found');
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const sceneFiles = await findGenesysSceneFiles(srcDir);
|
|
62
|
-
|
|
63
|
-
if (sceneFiles.length === 0) {
|
|
64
|
-
console.log('No .genesys-scene files found in src folder');
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
console.log(`Found ${sceneFiles.length} .genesys-scene files:`);
|
|
69
|
-
sceneFiles.forEach(file => console.log(` - ${path.relative(process.cwd(), file)}`));
|
|
70
|
-
|
|
71
|
-
console.log('\nUpdating scene files...');
|
|
72
|
-
|
|
73
|
-
// Process each scene file
|
|
74
|
-
for (const sceneFile of sceneFiles) {
|
|
75
|
-
await updateSceneFile(sceneFile);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
console.log('\nScene update process completed!');
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
main().catch(error => {
|
|
82
|
-
console.error('Script failed:', error);
|
|
83
|
-
process.exit(1);
|
|
84
|
-
});
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
import { SCENE_EXTENSION } from '../const.js';
|
|
5
|
+
import { loadWorld } from '../mcp/utils.js';
|
|
6
|
+
import { mockBrowserEnvironment } from '../mock.js';
|
|
7
|
+
|
|
8
|
+
// Mock browser environment as required by the engine
|
|
9
|
+
mockBrowserEnvironment();
|
|
10
|
+
|
|
11
|
+
async function findGenesysSceneFiles(dir: string): Promise<string[]> {
|
|
12
|
+
const sceneFiles: string[] = [];
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
const items = fs.readdirSync(dir, { withFileTypes: true });
|
|
16
|
+
|
|
17
|
+
for (const item of items) {
|
|
18
|
+
const fullPath = path.join(dir, item.name);
|
|
19
|
+
|
|
20
|
+
if (item.isDirectory()) {
|
|
21
|
+
// Recursively search subdirectories
|
|
22
|
+
const subFiles = await findGenesysSceneFiles(fullPath);
|
|
23
|
+
sceneFiles.push(...subFiles);
|
|
24
|
+
} else if (item.isFile() && item.name.endsWith(SCENE_EXTENSION)) {
|
|
25
|
+
sceneFiles.push(fullPath);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
} catch (error) {
|
|
29
|
+
console.error(`Error reading directory ${dir}:`, error);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return sceneFiles;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function updateSceneFile(sceneFilePath: string): Promise<void> {
|
|
36
|
+
console.log(`Processing: ${sceneFilePath}`);
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
// Use the loadWorld utility with proper disposal using 'using' keyword
|
|
40
|
+
using worldResource = await loadWorld(sceneFilePath, {
|
|
41
|
+
readonly: false, // Allow saving changes
|
|
42
|
+
skipLoadingGLTF: true // Skip GLTF loading for faster processing
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
console.log(`✓ Successfully updated: ${sceneFilePath}`);
|
|
46
|
+
} catch (error) {
|
|
47
|
+
console.error(`✗ Failed to update ${sceneFilePath}:`, error);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async function main() {
|
|
52
|
+
console.log('Searching for .genesys-scene files in src folder...');
|
|
53
|
+
|
|
54
|
+
const srcDir = path.join(process.cwd(), 'src');
|
|
55
|
+
|
|
56
|
+
if (!fs.existsSync(srcDir)) {
|
|
57
|
+
console.error('src directory not found');
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const sceneFiles = await findGenesysSceneFiles(srcDir);
|
|
62
|
+
|
|
63
|
+
if (sceneFiles.length === 0) {
|
|
64
|
+
console.log('No .genesys-scene files found in src folder');
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
console.log(`Found ${sceneFiles.length} .genesys-scene files:`);
|
|
69
|
+
sceneFiles.forEach(file => console.log(` - ${path.relative(process.cwd(), file)}`));
|
|
70
|
+
|
|
71
|
+
console.log('\nUpdating scene files...');
|
|
72
|
+
|
|
73
|
+
// Process each scene file
|
|
74
|
+
for (const sceneFile of sceneFiles) {
|
|
75
|
+
await updateSceneFile(sceneFile);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
console.log('\nScene update process completed!');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
main().catch(error => {
|
|
82
|
+
console.error('Script failed:', error);
|
|
83
|
+
process.exit(1);
|
|
84
|
+
});
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
-
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
|
-
|
|
4
|
-
import { addDocTools } from './mcp/doc-tools.js';
|
|
5
|
-
|
|
6
|
-
// Create an MCP server
|
|
7
|
-
const server = new McpServer({
|
|
8
|
-
name: 'Genesys-Doc-Server',
|
|
9
|
-
version: '0.0.1'
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
addDocTools(server);
|
|
13
|
-
|
|
14
|
-
// Start receiving messages on stdin and sending messages on stdout
|
|
15
|
-
const transport = new StdioServerTransport();
|
|
16
|
-
await server.connect(transport);
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
|
+
|
|
4
|
+
import { addDocTools } from './mcp/doc-tools.js';
|
|
5
|
+
|
|
6
|
+
// Create an MCP server
|
|
7
|
+
const server = new McpServer({
|
|
8
|
+
name: 'Genesys-Doc-Server',
|
|
9
|
+
version: '0.0.1'
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
addDocTools(server);
|
|
13
|
+
|
|
14
|
+
// Start receiving messages on stdin and sending messages on stdout
|
|
15
|
+
const transport = new StdioServerTransport();
|
|
16
|
+
await server.connect(transport);
|