@gnsx/genesys.sdk 4.2.9
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 -0
- package/dist/src/asset-pack/eslint.config.js +58 -0
- package/dist/src/asset-pack/scripts/post-install.js +64 -0
- package/dist/src/asset-pack/src/index.js +1 -0
- package/dist/src/core/cli.js +303 -0
- package/dist/src/core/common.js +325 -0
- package/dist/src/core/index.js +6 -0
- package/dist/src/core/tools/build-project.js +456 -0
- package/dist/src/core/tools/index.js +2 -0
- package/dist/src/core/tools/new-asset-pack.js +153 -0
- package/dist/src/core/tools/new-project.js +293 -0
- package/dist/src/core/types.js +1 -0
- package/dist/src/dependencies.js +84 -0
- package/dist/src/electron/IpcSerializableError.js +38 -0
- package/dist/src/electron/api.js +7 -0
- package/dist/src/electron/backend/actions.js +56 -0
- package/dist/src/electron/backend/handler.js +452 -0
- package/dist/src/electron/backend/logging.js +41 -0
- package/dist/src/electron/backend/main.js +369 -0
- package/dist/src/electron/backend/menu.js +196 -0
- package/dist/src/electron/backend/state.js +201 -0
- package/dist/src/electron/backend/telemetry.js +9 -0
- package/dist/src/electron/backend/tools/const.js +9 -0
- package/dist/src/electron/backend/tools/file-server.js +383 -0
- package/dist/src/electron/backend/tools/open-project.js +249 -0
- package/dist/src/electron/backend/window.js +161 -0
- package/dist/src/templates/eslint.config.js +58 -0
- package/dist/src/templates/scripts/genesys/build-project.js +42 -0
- package/dist/src/templates/scripts/genesys/calc-bounding-box.js +205 -0
- package/dist/src/templates/scripts/genesys/common.js +36 -0
- package/dist/src/templates/scripts/genesys/const.js +9 -0
- package/dist/src/templates/scripts/genesys/dev/dump-default-scene.js +8 -0
- package/dist/src/templates/scripts/genesys/dev/generate-manifest.js +116 -0
- package/dist/src/templates/scripts/genesys/dev/launcher.js +39 -0
- package/dist/src/templates/scripts/genesys/dev/storage-provider.js +188 -0
- package/dist/src/templates/scripts/genesys/dev/update-template-scenes.js +67 -0
- package/dist/src/templates/scripts/genesys/doc-server.js +12 -0
- package/dist/src/templates/scripts/genesys/genesys-mcp.js +413 -0
- package/dist/src/templates/scripts/genesys/mcp/doc-tools.js +70 -0
- package/dist/src/templates/scripts/genesys/mcp/editor-functions.js +123 -0
- package/dist/src/templates/scripts/genesys/mcp/editor-tools.js +51 -0
- package/dist/src/templates/scripts/genesys/mcp/get-scene-state.js +26 -0
- package/dist/src/templates/scripts/genesys/mcp/run-subprocess.js +23 -0
- package/dist/src/templates/scripts/genesys/mcp/search-actors.js +703 -0
- package/dist/src/templates/scripts/genesys/mcp/search-assets.js +296 -0
- package/dist/src/templates/scripts/genesys/mcp/utils.js +234 -0
- package/dist/src/templates/scripts/genesys/migrate-scenes-and-prefabs.js +252 -0
- package/dist/src/templates/scripts/genesys/misc.js +32 -0
- package/dist/src/templates/scripts/genesys/mock.js +5 -0
- package/dist/src/templates/scripts/genesys/place-actors.js +112 -0
- package/dist/src/templates/scripts/genesys/post-install.js +33 -0
- package/dist/src/templates/scripts/genesys/remove-engine-comments.js +113 -0
- package/dist/src/templates/scripts/genesys/storageProvider.js +146 -0
- package/dist/src/templates/scripts/genesys/validate-prefabs.js +115 -0
- package/dist/src/templates/src/index.js +20 -0
- package/dist/src/templates/src/templates/firstPerson/src/auto-imports.js +1 -0
- package/dist/src/templates/src/templates/firstPerson/src/game.js +30 -0
- package/dist/src/templates/src/templates/firstPerson/src/player.js +55 -0
- package/dist/src/templates/src/templates/fps/src/auto-imports.js +1 -0
- package/dist/src/templates/src/templates/fps/src/game.js +30 -0
- package/dist/src/templates/src/templates/fps/src/player.js +60 -0
- package/dist/src/templates/src/templates/fps/src/weapon.js +54 -0
- package/dist/src/templates/src/templates/freeCamera/src/auto-imports.js +1 -0
- package/dist/src/templates/src/templates/freeCamera/src/game.js +30 -0
- package/dist/src/templates/src/templates/freeCamera/src/player.js +38 -0
- package/dist/src/templates/src/templates/sideScroller/src/auto-imports.js +1 -0
- package/dist/src/templates/src/templates/sideScroller/src/const.js +43 -0
- package/dist/src/templates/src/templates/sideScroller/src/game.js +102 -0
- package/dist/src/templates/src/templates/sideScroller/src/level-generator.js +249 -0
- package/dist/src/templates/src/templates/sideScroller/src/player.js +100 -0
- package/dist/src/templates/src/templates/thirdPerson/src/auto-imports.js +1 -0
- package/dist/src/templates/src/templates/thirdPerson/src/game.js +30 -0
- package/dist/src/templates/src/templates/thirdPerson/src/player.js +58 -0
- package/dist/src/templates/src/templates/vehicle/src/auto-imports.js +1 -0
- package/dist/src/templates/src/templates/vehicle/src/base-vehicle.js +122 -0
- package/dist/src/templates/src/templates/vehicle/src/game.js +33 -0
- package/dist/src/templates/src/templates/vehicle/src/mesh-vehicle.js +188 -0
- package/dist/src/templates/src/templates/vehicle/src/player.js +97 -0
- package/dist/src/templates/src/templates/vehicle/src/primitive-vehicle.js +258 -0
- package/dist/src/templates/src/templates/vehicle/src/ui-hints.js +100 -0
- package/dist/src/templates/src/templates/vr-game/src/auto-imports.js +1 -0
- package/dist/src/templates/src/templates/vr-game/src/game.js +55 -0
- package/dist/src/templates/src/templates/vr-game/src/sample-vr-actor.js +29 -0
- package/dist/src/templates/vite.config.js +46 -0
- package/package.json +181 -0
- package/scripts/post-install.ts +143 -0
- package/src/asset-pack/.gitattributes +89 -0
- package/src/asset-pack/.github/workflows/publish.yml +90 -0
- package/src/asset-pack/eslint.config.js +59 -0
- package/src/asset-pack/gitignore +11 -0
- package/src/asset-pack/scripts/post-install.ts +81 -0
- package/src/asset-pack/src/index.ts +0 -0
- package/src/asset-pack/tsconfig.json +34 -0
- package/src/templates/.cursor/mcp.json +20 -0
- package/src/templates/.cursorignore +2 -0
- package/src/templates/.gitattributes +89 -0
- package/src/templates/.vscode/settings.json +6 -0
- package/src/templates/AGENTS.md +104 -0
- package/src/templates/CLAUDE.md +1 -0
- package/src/templates/README.md +24 -0
- package/src/templates/eslint.config.js +60 -0
- package/src/templates/gitignore +11 -0
- package/src/templates/index.html +34 -0
- package/src/templates/pnpm-lock.yaml +3676 -0
- package/src/templates/scripts/genesys/build-project.ts +51 -0
- package/src/templates/scripts/genesys/calc-bounding-box.ts +272 -0
- package/src/templates/scripts/genesys/common.ts +46 -0
- package/src/templates/scripts/genesys/const.ts +9 -0
- package/src/templates/scripts/genesys/dev/dump-default-scene.ts +11 -0
- package/src/templates/scripts/genesys/dev/generate-manifest.ts +146 -0
- package/src/templates/scripts/genesys/dev/launcher.ts +46 -0
- package/src/templates/scripts/genesys/dev/storage-provider.ts +229 -0
- package/src/templates/scripts/genesys/dev/update-template-scenes.ts +84 -0
- package/src/templates/scripts/genesys/doc-server.ts +16 -0
- package/src/templates/scripts/genesys/genesys-mcp.ts +526 -0
- package/src/templates/scripts/genesys/mcp/doc-tools.ts +86 -0
- package/src/templates/scripts/genesys/mcp/editor-functions.ts +151 -0
- package/src/templates/scripts/genesys/mcp/editor-tools.ts +73 -0
- package/src/templates/scripts/genesys/mcp/get-scene-state.ts +35 -0
- package/src/templates/scripts/genesys/mcp/run-subprocess.ts +30 -0
- package/src/templates/scripts/genesys/mcp/search-actors.ts +858 -0
- package/src/templates/scripts/genesys/mcp/search-assets.ts +380 -0
- package/src/templates/scripts/genesys/mcp/utils.ts +281 -0
- package/src/templates/scripts/genesys/migrate-scenes-and-prefabs.ts +301 -0
- package/src/templates/scripts/genesys/misc.ts +42 -0
- package/src/templates/scripts/genesys/mock.ts +6 -0
- package/src/templates/scripts/genesys/place-actors.ts +179 -0
- package/src/templates/scripts/genesys/post-install.ts +39 -0
- package/src/templates/scripts/genesys/prefab.schema.json +85 -0
- package/src/templates/scripts/genesys/remove-engine-comments.ts +135 -0
- package/src/templates/scripts/genesys/run-mcp-inspector.bat +5 -0
- package/src/templates/scripts/genesys/storageProvider.ts +182 -0
- package/src/templates/scripts/genesys/validate-prefabs.ts +138 -0
- package/src/templates/src/index.ts +22 -0
- package/src/templates/src/templates/firstPerson/assets/default.genesys-scene +166 -0
- package/src/templates/src/templates/firstPerson/src/auto-imports.ts +0 -0
- package/src/templates/src/templates/firstPerson/src/game.ts +39 -0
- package/src/templates/src/templates/firstPerson/src/player.ts +59 -0
- package/src/templates/src/templates/fps/assets/default.genesys-scene +9460 -0
- package/src/templates/src/templates/fps/assets/models/SM_Beam_400.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_ChamferCube.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Floor_Thick_400x400.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Floor_Thick_400x400_Orange.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Floor_Thin_400x400.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Floor_Thin_400x400_Orange.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Ramp_400x400.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Rifle.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Wall_Thin_400x200.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Wall_Thin_400x200_Orange.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Wall_Thin_400x400.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Wall_Thin_400x400_Orange.glb +0 -0
- package/src/templates/src/templates/fps/src/auto-imports.ts +0 -0
- package/src/templates/src/templates/fps/src/game.ts +39 -0
- package/src/templates/src/templates/fps/src/player.ts +66 -0
- package/src/templates/src/templates/fps/src/weapon.ts +47 -0
- package/src/templates/src/templates/freeCamera/assets/default.genesys-scene +166 -0
- package/src/templates/src/templates/freeCamera/src/auto-imports.ts +0 -0
- package/src/templates/src/templates/freeCamera/src/game.ts +39 -0
- package/src/templates/src/templates/freeCamera/src/player.ts +40 -0
- package/src/templates/src/templates/sideScroller/assets/default.genesys-scene +122 -0
- package/src/templates/src/templates/sideScroller/src/auto-imports.ts +0 -0
- package/src/templates/src/templates/sideScroller/src/const.ts +46 -0
- package/src/templates/src/templates/sideScroller/src/game.ts +121 -0
- package/src/templates/src/templates/sideScroller/src/level-generator.ts +361 -0
- package/src/templates/src/templates/sideScroller/src/player.ts +123 -0
- package/src/templates/src/templates/thirdPerson/assets/default.genesys-scene +166 -0
- package/src/templates/src/templates/thirdPerson/src/auto-imports.ts +0 -0
- package/src/templates/src/templates/thirdPerson/src/game.ts +39 -0
- package/src/templates/src/templates/thirdPerson/src/player.ts +58 -0
- package/src/templates/src/templates/vehicle/assets/default.genesys-scene +226 -0
- package/src/templates/src/templates/vehicle/assets/models/cyberTruck/chassis.glb +0 -0
- package/src/templates/src/templates/vehicle/assets/models/cyberTruck/wheel.glb +0 -0
- package/src/templates/src/templates/vehicle/src/auto-imports.ts +0 -0
- package/src/templates/src/templates/vehicle/src/base-vehicle.ts +145 -0
- package/src/templates/src/templates/vehicle/src/game.ts +43 -0
- package/src/templates/src/templates/vehicle/src/mesh-vehicle.ts +189 -0
- package/src/templates/src/templates/vehicle/src/player.ts +106 -0
- package/src/templates/src/templates/vehicle/src/primitive-vehicle.ts +264 -0
- package/src/templates/src/templates/vehicle/src/ui-hints.ts +101 -0
- package/src/templates/src/templates/vr-game/assets/default.genesys-scene +247 -0
- package/src/templates/src/templates/vr-game/src/auto-imports.ts +1 -0
- package/src/templates/src/templates/vr-game/src/game.ts +66 -0
- package/src/templates/src/templates/vr-game/src/sample-vr-actor.ts +26 -0
- package/src/templates/tsconfig.json +35 -0
- package/src/templates/vite.config.ts +52 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import * as ENGINE from '@gnsx/genesys.js';
|
|
4
|
+
import { AssetPath, AssetPathEncodeState } from '@gnsx/genesys.js';
|
|
5
|
+
import { getProjectRoot } from './common.js';
|
|
6
|
+
export class StorageProvider {
|
|
7
|
+
async resolvePath(assetPath, expiry) {
|
|
8
|
+
if (assetPath.isResolved()) {
|
|
9
|
+
return assetPath;
|
|
10
|
+
}
|
|
11
|
+
assetPath.resolvePath(this.getFullPath(assetPath.initialPath), AssetPathEncodeState.Decoded);
|
|
12
|
+
return assetPath;
|
|
13
|
+
}
|
|
14
|
+
getFullPath(filePath) {
|
|
15
|
+
let fullPath = filePath;
|
|
16
|
+
let rootPath = undefined;
|
|
17
|
+
if (filePath.startsWith(ENGINE.PROJECT_PATH_PREFIX)) {
|
|
18
|
+
filePath = filePath.slice(ENGINE.PROJECT_PATH_PREFIX.length);
|
|
19
|
+
rootPath = getProjectRoot();
|
|
20
|
+
}
|
|
21
|
+
else if (filePath.startsWith(ENGINE.ENGINE_PATH_PREFIX)) {
|
|
22
|
+
filePath = filePath.slice(ENGINE.ENGINE_PATH_PREFIX.length);
|
|
23
|
+
rootPath = path.join(getProjectRoot(), 'node_modules', 'genesys.js');
|
|
24
|
+
}
|
|
25
|
+
if (rootPath !== undefined) {
|
|
26
|
+
fullPath = AssetPath.join(rootPath, filePath);
|
|
27
|
+
}
|
|
28
|
+
return fullPath;
|
|
29
|
+
}
|
|
30
|
+
async downloadFileAsBuffer(assetPath) {
|
|
31
|
+
assetPath = await this.resolvePath(assetPath);
|
|
32
|
+
const fullPath = getResolvedPath(assetPath);
|
|
33
|
+
if (!fs.existsSync(fullPath)) {
|
|
34
|
+
return new ArrayBuffer(0);
|
|
35
|
+
}
|
|
36
|
+
const data = fs.readFileSync(fullPath);
|
|
37
|
+
const arrayBuffer = data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
|
|
38
|
+
return arrayBuffer;
|
|
39
|
+
}
|
|
40
|
+
async downloadFileAsJson(assetPath) {
|
|
41
|
+
assetPath = await this.resolvePath(assetPath);
|
|
42
|
+
const fullPath = getResolvedPath(assetPath);
|
|
43
|
+
if (!fs.existsSync(fullPath)) {
|
|
44
|
+
return {};
|
|
45
|
+
}
|
|
46
|
+
return JSON.parse(fs.readFileSync(fullPath, 'utf8'));
|
|
47
|
+
}
|
|
48
|
+
async downloadFileAsText(assetPath) {
|
|
49
|
+
assetPath = await this.resolvePath(assetPath);
|
|
50
|
+
const fullPath = getResolvedPath(assetPath);
|
|
51
|
+
if (!fs.existsSync(fullPath)) {
|
|
52
|
+
return '';
|
|
53
|
+
}
|
|
54
|
+
return fs.readFileSync(fullPath, 'utf8');
|
|
55
|
+
}
|
|
56
|
+
async exists(assetPath) {
|
|
57
|
+
assetPath = await this.resolvePath(assetPath);
|
|
58
|
+
const fullPath = getResolvedPath(assetPath);
|
|
59
|
+
return fs.existsSync(fullPath);
|
|
60
|
+
}
|
|
61
|
+
async buildCurrentProject(runTsc) {
|
|
62
|
+
throw new Error('Not implemented');
|
|
63
|
+
}
|
|
64
|
+
async uploadFile(assetPath, content, options) {
|
|
65
|
+
assetPath = await this.resolvePath(assetPath);
|
|
66
|
+
const fullPath = getResolvedPath(assetPath);
|
|
67
|
+
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
|
|
68
|
+
if (typeof content === 'string') {
|
|
69
|
+
fs.writeFileSync(fullPath, content);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
throw new Error(`Unsupported content type: ${typeof content}`);
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
path: fullPath,
|
|
76
|
+
name: path.basename(fullPath)
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
async deleteFile(assetPath) {
|
|
80
|
+
assetPath = await this.resolvePath(assetPath);
|
|
81
|
+
const fullPath = getResolvedPath(assetPath);
|
|
82
|
+
if (fs.existsSync(fullPath)) {
|
|
83
|
+
fs.unlinkSync(fullPath);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async listFiles(assetPath, recursive, includeHiddenFiles) {
|
|
87
|
+
assetPath = await this.resolvePath(assetPath);
|
|
88
|
+
const fullPath = getResolvedPath(assetPath);
|
|
89
|
+
if (!fs.existsSync(fullPath)) {
|
|
90
|
+
return { files: [], directories: [] };
|
|
91
|
+
}
|
|
92
|
+
const files = [];
|
|
93
|
+
const directories = [];
|
|
94
|
+
const processDirectory = (dirPath, basePath = '') => {
|
|
95
|
+
const entries = fs.readdirSync(dirPath, { withFileTypes: true });
|
|
96
|
+
for (const entry of entries) {
|
|
97
|
+
// Skip hidden files if not requested
|
|
98
|
+
if (!includeHiddenFiles && entry.name.startsWith('.')) {
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
const fullEntryPath = path.join(dirPath, entry.name);
|
|
102
|
+
const relativePath = basePath ? path.join(basePath, entry.name) : entry.name;
|
|
103
|
+
const stats = fs.statSync(fullEntryPath);
|
|
104
|
+
const fileItem = {
|
|
105
|
+
name: entry.name,
|
|
106
|
+
path: relativePath,
|
|
107
|
+
absolutePath: fullEntryPath,
|
|
108
|
+
size: stats.size,
|
|
109
|
+
modifiedTime: stats.mtime,
|
|
110
|
+
isDirectory: entry.isDirectory()
|
|
111
|
+
};
|
|
112
|
+
if (entry.isDirectory()) {
|
|
113
|
+
directories.push(fileItem);
|
|
114
|
+
// Recursively process subdirectories if requested
|
|
115
|
+
if (recursive) {
|
|
116
|
+
processDirectory(fullEntryPath, relativePath);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
files.push(fileItem);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
// Check if the path is a directory
|
|
125
|
+
const stats = fs.statSync(fullPath);
|
|
126
|
+
if (stats.isDirectory()) {
|
|
127
|
+
processDirectory(fullPath);
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
// If it's a file, return just that file
|
|
131
|
+
const fileItem = {
|
|
132
|
+
name: path.basename(fullPath),
|
|
133
|
+
path: path.basename(fullPath),
|
|
134
|
+
absolutePath: fullPath,
|
|
135
|
+
size: stats.size,
|
|
136
|
+
modifiedTime: stats.mtime,
|
|
137
|
+
isDirectory: false
|
|
138
|
+
};
|
|
139
|
+
files.push(fileItem);
|
|
140
|
+
}
|
|
141
|
+
return { files, directories };
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
export function getResolvedPath(assetPath) {
|
|
145
|
+
return assetPath.getResolvedPath(false);
|
|
146
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import Ajv from 'ajv';
|
|
4
|
+
import { getProjectRoot } from './common.js';
|
|
5
|
+
function findPrefabFiles(dir, prefabFiles = []) {
|
|
6
|
+
const files = fs.readdirSync(dir);
|
|
7
|
+
for (const file of files) {
|
|
8
|
+
const filePath = path.join(dir, file);
|
|
9
|
+
const stat = fs.statSync(filePath);
|
|
10
|
+
if (stat.isDirectory()) {
|
|
11
|
+
// Skip node_modules and other common directories that shouldn't contain prefabs
|
|
12
|
+
if (file === 'node_modules' || file === 'dist' || file === '.git') {
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
findPrefabFiles(filePath, prefabFiles);
|
|
16
|
+
}
|
|
17
|
+
else if (file.endsWith('.prefab.json')) {
|
|
18
|
+
prefabFiles.push(filePath);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return prefabFiles;
|
|
22
|
+
}
|
|
23
|
+
function validatePrefabs() {
|
|
24
|
+
const projectRoot = getProjectRoot();
|
|
25
|
+
const schemaPath = path.join(__dirname, 'prefab.schema.json');
|
|
26
|
+
// Load the schema
|
|
27
|
+
let schema;
|
|
28
|
+
try {
|
|
29
|
+
const schemaContent = fs.readFileSync(schemaPath, 'utf-8');
|
|
30
|
+
schema = JSON.parse(schemaContent);
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
console.error(`❌ Failed to load schema from ${schemaPath}`);
|
|
34
|
+
console.error(error);
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
// Initialize Ajv
|
|
38
|
+
const ajv = new Ajv({
|
|
39
|
+
allErrors: true,
|
|
40
|
+
validateSchema: false // Don't validate the schema itself
|
|
41
|
+
});
|
|
42
|
+
// Process $ref in the schema to use proper format
|
|
43
|
+
const processedSchema = JSON.parse(JSON.stringify(schema), (key, value) => {
|
|
44
|
+
if (key === '$ref' && typeof value === 'string' && !value.startsWith('#')) {
|
|
45
|
+
return `#/definitions/${value}`;
|
|
46
|
+
}
|
|
47
|
+
return value;
|
|
48
|
+
});
|
|
49
|
+
const validate = ajv.compile(processedSchema);
|
|
50
|
+
// Find all prefab files
|
|
51
|
+
const prefabFiles = findPrefabFiles(projectRoot);
|
|
52
|
+
if (prefabFiles.length === 0) {
|
|
53
|
+
console.log('⚠️ No prefab files found in the project.');
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
console.log(`Found ${prefabFiles.length} prefab file(s) to validate:\n`);
|
|
57
|
+
const validationErrors = [];
|
|
58
|
+
let validCount = 0;
|
|
59
|
+
// Validate each prefab file
|
|
60
|
+
for (const prefabPath of prefabFiles) {
|
|
61
|
+
const relativePath = path.relative(projectRoot, prefabPath);
|
|
62
|
+
try {
|
|
63
|
+
const prefabContent = fs.readFileSync(prefabPath, 'utf-8');
|
|
64
|
+
const prefabData = JSON.parse(prefabContent);
|
|
65
|
+
const valid = validate(prefabData);
|
|
66
|
+
if (valid) {
|
|
67
|
+
console.log(`✅ ${relativePath}`);
|
|
68
|
+
validCount++;
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
console.log(`❌ ${relativePath}`);
|
|
72
|
+
const errors = validate.errors?.map((err) => {
|
|
73
|
+
const path = err.instancePath ?? '/';
|
|
74
|
+
const message = err.message ?? 'unknown error';
|
|
75
|
+
return ` - ${path}: ${message}`;
|
|
76
|
+
}) ?? [];
|
|
77
|
+
validationErrors.push({
|
|
78
|
+
file: relativePath,
|
|
79
|
+
errors
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
console.log(`❌ ${relativePath} (parse error)`);
|
|
85
|
+
validationErrors.push({
|
|
86
|
+
file: relativePath,
|
|
87
|
+
errors: [`Failed to parse JSON: ${error instanceof Error ? error.message : String(error)}`]
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// Print summary
|
|
92
|
+
console.log(`\n${'='.repeat(60)}`);
|
|
93
|
+
console.log('Validation Summary:');
|
|
94
|
+
console.log(` Total files: ${prefabFiles.length}`);
|
|
95
|
+
console.log(` Valid: ${validCount}`);
|
|
96
|
+
console.log(` Invalid: ${validationErrors.length}`);
|
|
97
|
+
console.log(`${'='.repeat(60)}\n`);
|
|
98
|
+
// Print detailed errors if any
|
|
99
|
+
if (validationErrors.length > 0) {
|
|
100
|
+
console.log('Validation Errors:\n');
|
|
101
|
+
for (const { file, errors } of validationErrors) {
|
|
102
|
+
console.log(`${file}:`);
|
|
103
|
+
for (const error of errors) {
|
|
104
|
+
console.log(error);
|
|
105
|
+
}
|
|
106
|
+
console.log('');
|
|
107
|
+
}
|
|
108
|
+
process.exit(1);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
console.log('🎉 All prefab files are valid!');
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// Run validation
|
|
115
|
+
validatePrefabs();
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// which items will be copied to the new project, includes files and folders
|
|
2
|
+
export const sharedTemplateItems = [
|
|
3
|
+
'.cursor',
|
|
4
|
+
'.vscode',
|
|
5
|
+
'scripts/genesys',
|
|
6
|
+
'gitignore', // npm excludes .gitignore files from packages, so we rename it when copying
|
|
7
|
+
'.gitattributes',
|
|
8
|
+
'.cursorignore',
|
|
9
|
+
'eslint.config.js',
|
|
10
|
+
'tsconfig.json',
|
|
11
|
+
'AGENTS.md',
|
|
12
|
+
'CLAUDE.md',
|
|
13
|
+
'index.html',
|
|
14
|
+
'vite.config.ts',
|
|
15
|
+
];
|
|
16
|
+
// which items will be deleted from the project, if exists
|
|
17
|
+
export const deletedTemplateItems = [
|
|
18
|
+
'.cursorrules'
|
|
19
|
+
];
|
|
20
|
+
export * as ENGINE from '@gnsx/genesys.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as ENGINE from '@gnsx/genesys.js';
|
|
2
|
+
import * as THREE from 'three';
|
|
3
|
+
import { FirstPersonPlayer } from './player.js';
|
|
4
|
+
import './auto-imports.js';
|
|
5
|
+
class FirstPersonGame extends ENGINE.BaseGameLoop {
|
|
6
|
+
pawn = null;
|
|
7
|
+
controller = null;
|
|
8
|
+
createLoadingScreen() {
|
|
9
|
+
// enable the default loading screen
|
|
10
|
+
return new ENGINE.DefaultLoadingScreen();
|
|
11
|
+
}
|
|
12
|
+
async preStart() {
|
|
13
|
+
// default spawn location
|
|
14
|
+
const position = new THREE.Vector3(0, ENGINE.CHARACTER_HEIGHT / 2, 0);
|
|
15
|
+
// now create the pawn
|
|
16
|
+
this.pawn = FirstPersonPlayer.create({ position });
|
|
17
|
+
// create the controller and possess the pawn
|
|
18
|
+
this.controller = ENGINE.PlayerController.create();
|
|
19
|
+
this.controller.possess(this.pawn);
|
|
20
|
+
// add both to the world
|
|
21
|
+
this.world.addActors(this.pawn, this.controller);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export function main(container, gameId) {
|
|
25
|
+
const game = new FirstPersonGame(container, {
|
|
26
|
+
...ENGINE.BaseGameLoop.DEFAULT_OPTIONS,
|
|
27
|
+
gameId
|
|
28
|
+
});
|
|
29
|
+
return game;
|
|
30
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import * as ENGINE from '@gnsx/genesys.js';
|
|
8
|
+
import * as THREE from 'three';
|
|
9
|
+
/**
|
|
10
|
+
* A first person player class.
|
|
11
|
+
*
|
|
12
|
+
* Key points:
|
|
13
|
+
* - No need to provide movementComponent and camera, they are created internally
|
|
14
|
+
* - The pawn is set to be transient so it's never saved in the level
|
|
15
|
+
* - The directional light follows the player for consistent shadows
|
|
16
|
+
*
|
|
17
|
+
*/
|
|
18
|
+
let FirstPersonPlayer = class FirstPersonPlayer extends ENGINE.Pawn {
|
|
19
|
+
// No need to provide rootComponent, movementComponent and camera, they are created internally
|
|
20
|
+
constructor() {
|
|
21
|
+
super();
|
|
22
|
+
// simple camera component - contains a perspective camera by default
|
|
23
|
+
const camera = new THREE.PerspectiveCamera(ENGINE.CAMERA_FOV, 1, ENGINE.CAMERA_NEAR, ENGINE.CAMERA_FAR);
|
|
24
|
+
// set proper camera height for first person view
|
|
25
|
+
camera.position.set(0, ENGINE.CHARACTER_HEIGHT * 0.4, 0);
|
|
26
|
+
// use a simple capsule geometry as the root component
|
|
27
|
+
const rootComponent = ENGINE.MeshComponent.create({
|
|
28
|
+
geometry: ENGINE.GameBuilder.createDefaultPawnCapsuleGeometry(),
|
|
29
|
+
material: new THREE.MeshStandardMaterial({ color: ENGINE.Color.YELLOW }),
|
|
30
|
+
physicsOptions: {
|
|
31
|
+
enabled: true,
|
|
32
|
+
// KinematicVelocityBased is required to use the physics character controller
|
|
33
|
+
motionType: ENGINE.PhysicsMotionType.KinematicVelocityBased,
|
|
34
|
+
collisionProfile: ENGINE.DefaultCollisionProfile.Pawn,
|
|
35
|
+
generateCollisionEvents: true,
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
// hide the mesh in first person view
|
|
39
|
+
rootComponent.getMesh().visible = false;
|
|
40
|
+
this.setRootComponent(rootComponent, true);
|
|
41
|
+
this.rootComponent.add(camera);
|
|
42
|
+
// create the movement component
|
|
43
|
+
const movementComponent = ENGINE.CharacterMovementComponent.create({
|
|
44
|
+
movementType: ENGINE.CharacterMovementType.FirstPerson,
|
|
45
|
+
});
|
|
46
|
+
this.movementComponent = movementComponent;
|
|
47
|
+
this.enableDirectionalLightFollowing = true;
|
|
48
|
+
// set the pawn to be transient so it's never saved in the level
|
|
49
|
+
this.setTransient(true);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
FirstPersonPlayer = __decorate([
|
|
53
|
+
ENGINE.GameClass()
|
|
54
|
+
], FirstPersonPlayer);
|
|
55
|
+
export { FirstPersonPlayer };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as ENGINE from '@gnsx/genesys.js';
|
|
2
|
+
import * as THREE from 'three';
|
|
3
|
+
import { FPSPlayer } from './player.js';
|
|
4
|
+
import './auto-imports.js';
|
|
5
|
+
class MyGame extends ENGINE.BaseGameLoop {
|
|
6
|
+
pawn = null;
|
|
7
|
+
controller = null;
|
|
8
|
+
createLoadingScreen() {
|
|
9
|
+
// enable the default loading screen
|
|
10
|
+
return new ENGINE.DefaultLoadingScreen();
|
|
11
|
+
}
|
|
12
|
+
async preStart() {
|
|
13
|
+
// default spawn location
|
|
14
|
+
const position = new THREE.Vector3(0, ENGINE.CHARACTER_HEIGHT / 2, 0);
|
|
15
|
+
// now create the pawn
|
|
16
|
+
this.pawn = FPSPlayer.create({ position });
|
|
17
|
+
// create the controller and possess the pawn
|
|
18
|
+
this.controller = ENGINE.PlayerController.create();
|
|
19
|
+
this.controller.possess(this.pawn);
|
|
20
|
+
// add both to the world
|
|
21
|
+
this.world.addActors(this.pawn, this.controller);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export function main(container, gameId) {
|
|
25
|
+
const game = new MyGame(container, {
|
|
26
|
+
...ENGINE.BaseGameLoop.DEFAULT_OPTIONS,
|
|
27
|
+
gameId
|
|
28
|
+
});
|
|
29
|
+
return game;
|
|
30
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import * as ENGINE from '@gnsx/genesys.js';
|
|
8
|
+
import * as THREE from 'three';
|
|
9
|
+
import { DefaultWeapon } from './weapon.js';
|
|
10
|
+
/**
|
|
11
|
+
* A FPS player class.
|
|
12
|
+
*
|
|
13
|
+
* Key points:
|
|
14
|
+
* - No need to provide rootComponent, movementComponent and camera, they are created internally
|
|
15
|
+
* - The pawn is set to be transient so it's never saved in the level
|
|
16
|
+
* - The directional light follows the player for consistent shadows
|
|
17
|
+
* - The weapon is created and attached to the camera
|
|
18
|
+
*
|
|
19
|
+
*/
|
|
20
|
+
let FPSPlayer = class FPSPlayer extends ENGINE.Pawn {
|
|
21
|
+
// No need to provide rootComponent, movementComponent and camera, they are created internally
|
|
22
|
+
constructor() {
|
|
23
|
+
super();
|
|
24
|
+
// simple camera component - contains a perspective camera by default
|
|
25
|
+
const camera = new THREE.PerspectiveCamera(ENGINE.CAMERA_FOV, 1, ENGINE.CAMERA_NEAR, ENGINE.CAMERA_FAR);
|
|
26
|
+
// set proper camera height for first person view
|
|
27
|
+
camera.position.set(0, ENGINE.CHARACTER_HEIGHT * 0.4, 0);
|
|
28
|
+
// create the weapon and attach it to the camera
|
|
29
|
+
const weapon = DefaultWeapon.create();
|
|
30
|
+
camera.add(weapon);
|
|
31
|
+
// use a simple capsule geometry as the root component
|
|
32
|
+
const rootComponent = ENGINE.MeshComponent.create({
|
|
33
|
+
geometry: ENGINE.GameBuilder.createDefaultPawnCapsuleGeometry(),
|
|
34
|
+
material: new THREE.MeshStandardMaterial({ color: ENGINE.Color.YELLOW }),
|
|
35
|
+
physicsOptions: {
|
|
36
|
+
enabled: true,
|
|
37
|
+
// KinematicVelocityBased is required to use the physics character controller
|
|
38
|
+
motionType: ENGINE.PhysicsMotionType.KinematicVelocityBased,
|
|
39
|
+
collisionProfile: ENGINE.DefaultCollisionProfile.Pawn,
|
|
40
|
+
generateCollisionEvents: true,
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
// hide the mesh in first person view
|
|
44
|
+
rootComponent.getMesh().visible = false;
|
|
45
|
+
this.setRootComponent(rootComponent, true);
|
|
46
|
+
this.rootComponent.add(camera);
|
|
47
|
+
// create the movement component
|
|
48
|
+
const movementComponent = ENGINE.CharacterMovementComponent.create({
|
|
49
|
+
movementType: ENGINE.CharacterMovementType.FirstPerson,
|
|
50
|
+
});
|
|
51
|
+
this.movementComponent = movementComponent;
|
|
52
|
+
this.enableDirectionalLightFollowing = true;
|
|
53
|
+
// set the pawn to be transient so it's never saved in the level
|
|
54
|
+
this.setTransient(true);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
FPSPlayer = __decorate([
|
|
58
|
+
ENGINE.GameClass()
|
|
59
|
+
], FPSPlayer);
|
|
60
|
+
export { FPSPlayer };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import * as ENGINE from '@gnsx/genesys.js';
|
|
8
|
+
import * as THREE from 'three';
|
|
9
|
+
/**
|
|
10
|
+
* A default weapon class.
|
|
11
|
+
*
|
|
12
|
+
* Key points:
|
|
13
|
+
* - Inherits from the ProjectileWeaponComponent class
|
|
14
|
+
* - All the weapon options are configured in the constructor so no need to configure by the user
|
|
15
|
+
*/
|
|
16
|
+
let DefaultWeapon = class DefaultWeapon extends ENGINE.ProjectileWeaponComponent {
|
|
17
|
+
constructor() {
|
|
18
|
+
super();
|
|
19
|
+
this.fireInterval = 0.1;
|
|
20
|
+
this.isSingleFire = false;
|
|
21
|
+
this.modelPath = '@project/assets/models/SM_Rifle.glb';
|
|
22
|
+
this.modelTransform = {
|
|
23
|
+
position: new THREE.Vector3(0.1, -0.1, -0.25),
|
|
24
|
+
rotation: new THREE.Euler(0, THREE.MathUtils.degToRad(-90), 0),
|
|
25
|
+
};
|
|
26
|
+
this.projectileSpawnOffset = new THREE.Vector3(0.8, -0.6, -2);
|
|
27
|
+
this.crosshairOptions = {
|
|
28
|
+
size: 10,
|
|
29
|
+
color: 'white',
|
|
30
|
+
style: 'dot'
|
|
31
|
+
};
|
|
32
|
+
this.fireSoundUrl = '@engine/assets/sounds/game-gun-short.mp3';
|
|
33
|
+
this.recoilOptions = {
|
|
34
|
+
weaponRecoilDistance: 0.05,
|
|
35
|
+
weaponRecoilDuration: 0.05,
|
|
36
|
+
weaponRecoilRotation: 0,
|
|
37
|
+
};
|
|
38
|
+
this.projectileOptions = {
|
|
39
|
+
velocity: 100,
|
|
40
|
+
range: 500,
|
|
41
|
+
projectileLifespan: 3,
|
|
42
|
+
useOverlapCheck: false,
|
|
43
|
+
destroyOnHit: false,
|
|
44
|
+
gravityScale: 0,
|
|
45
|
+
geometry: new THREE.SphereGeometry(0.1),
|
|
46
|
+
material: new THREE.MeshStandardMaterial({ color: ENGINE.Color.YELLOW })
|
|
47
|
+
};
|
|
48
|
+
this.setTransient(true);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
DefaultWeapon = __decorate([
|
|
52
|
+
ENGINE.GameClass()
|
|
53
|
+
], DefaultWeapon);
|
|
54
|
+
export { DefaultWeapon };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as ENGINE from '@gnsx/genesys.js';
|
|
2
|
+
import * as THREE from 'three';
|
|
3
|
+
import { FreeCameraPlayer } from './player.js';
|
|
4
|
+
import './auto-imports.js';
|
|
5
|
+
class MyGame extends ENGINE.BaseGameLoop {
|
|
6
|
+
pawn = null;
|
|
7
|
+
controller = null;
|
|
8
|
+
createLoadingScreen() {
|
|
9
|
+
// enable the default loading screen
|
|
10
|
+
return new ENGINE.DefaultLoadingScreen();
|
|
11
|
+
}
|
|
12
|
+
async preStart() {
|
|
13
|
+
// default spawn location
|
|
14
|
+
const position = new THREE.Vector3(0, ENGINE.CHARACTER_HEIGHT, 0);
|
|
15
|
+
// create the pawn with simple movement mechanics
|
|
16
|
+
this.pawn = FreeCameraPlayer.create({ position });
|
|
17
|
+
// create the controller and possess the pawn
|
|
18
|
+
this.controller = ENGINE.PlayerController.create();
|
|
19
|
+
this.controller.possess(this.pawn);
|
|
20
|
+
// add both to the world
|
|
21
|
+
this.world.addActors(this.pawn, this.controller);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export function main(container, gameId) {
|
|
25
|
+
const game = new MyGame(container, {
|
|
26
|
+
...ENGINE.BaseGameLoop.DEFAULT_OPTIONS,
|
|
27
|
+
gameId
|
|
28
|
+
});
|
|
29
|
+
return game;
|
|
30
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import * as ENGINE from '@gnsx/genesys.js';
|
|
8
|
+
import * as THREE from 'three';
|
|
9
|
+
/**
|
|
10
|
+
* A free camera player class.
|
|
11
|
+
*
|
|
12
|
+
* Key points:
|
|
13
|
+
* - No need to provide movementComponent and camera, they are created internally
|
|
14
|
+
* - The pawn is set to be transient so it's never saved in the level
|
|
15
|
+
* - The directional light follows the player for consistent shadows
|
|
16
|
+
*
|
|
17
|
+
*/
|
|
18
|
+
let FreeCameraPlayer = class FreeCameraPlayer extends ENGINE.Pawn {
|
|
19
|
+
constructor() {
|
|
20
|
+
super();
|
|
21
|
+
// simple perspective camera
|
|
22
|
+
const camera = new THREE.PerspectiveCamera(ENGINE.CAMERA_FOV, 1, ENGINE.CAMERA_NEAR, ENGINE.CAMERA_FAR);
|
|
23
|
+
this.rootComponent.add(camera);
|
|
24
|
+
// simple movement component, do not use the character controller
|
|
25
|
+
const movementComponent = ENGINE.CharacterMovementComponent.create({
|
|
26
|
+
// disable the character controller
|
|
27
|
+
characterControllerOptions: null,
|
|
28
|
+
});
|
|
29
|
+
this.movementComponent = movementComponent;
|
|
30
|
+
this.enableDirectionalLightFollowing = true;
|
|
31
|
+
// set the pawn to be transient so it's never saved in the level
|
|
32
|
+
this.setTransient(true);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
FreeCameraPlayer = __decorate([
|
|
36
|
+
ENGINE.GameClass()
|
|
37
|
+
], FreeCameraPlayer);
|
|
38
|
+
export { FreeCameraPlayer };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// Player Movement Configuration
|
|
2
|
+
export const PLAYER_MOVEMENT = {
|
|
3
|
+
JUMP_SPEED: 20,
|
|
4
|
+
MAX_SPEED: 8,
|
|
5
|
+
MAX_MID_AIR_JUMPS: 1,
|
|
6
|
+
ACCELERATION_LAMBDA: 15,
|
|
7
|
+
DECELERATION_LAMBDA: 10,
|
|
8
|
+
MID_AIR_ACCELERATION_LAMBDA: 8,
|
|
9
|
+
MID_AIR_DECELERATION_LAMBDA: 2,
|
|
10
|
+
};
|
|
11
|
+
// Camera Settings
|
|
12
|
+
export const CAMERA_SETTINGS = {
|
|
13
|
+
FOV: 60,
|
|
14
|
+
NEAR: 0.1,
|
|
15
|
+
FAR: 1000,
|
|
16
|
+
DAMP_FACTOR: 10,
|
|
17
|
+
POSITION: { x: 0, y: 1, z: 8 },
|
|
18
|
+
LOOK_AT: { x: 0, y: 0, z: 0 },
|
|
19
|
+
};
|
|
20
|
+
// Level Generation Configuration
|
|
21
|
+
export const LEVEL_CONFIG = {
|
|
22
|
+
DEPTH: 3,
|
|
23
|
+
CHUNK_SIZE: 50,
|
|
24
|
+
CHUNKS_AHEAD: 2,
|
|
25
|
+
CHUNKS_BEHIND: 2,
|
|
26
|
+
PLATFORM_HEIGHT_RANGE: { min: 1, max: 2 },
|
|
27
|
+
PLATFORM_WIDTH_RANGE: { min: 3, max: 6 },
|
|
28
|
+
OBSTACLE_HEIGHT_RANGE: { min: 3, max: 6 },
|
|
29
|
+
OBSTACLE_WIDTH_RANGE: { min: 1.5, max: 3.0 },
|
|
30
|
+
CHUNK_MARGIN: 0,
|
|
31
|
+
MIN_SPACING: 4,
|
|
32
|
+
DEBUG_VISUALIZATION_HEIGHT: 6,
|
|
33
|
+
DEBUG_VISUALIZATION_OPACITY: 0.3,
|
|
34
|
+
DEBUG_VISUALIZATION_COLOR: 0x00ff00,
|
|
35
|
+
GROUND_HEIGHT: 0.1,
|
|
36
|
+
GROUND_Y_POSITION: -0.05,
|
|
37
|
+
};
|
|
38
|
+
// Material colors
|
|
39
|
+
export const COLORS = {
|
|
40
|
+
PLATFORM: 0x90ee90, // Light green
|
|
41
|
+
OBSTACLE: 0xff4444, // Red
|
|
42
|
+
GROUND: 0x8b4513, // Brown
|
|
43
|
+
};
|