@directivegames/genesys.sdk 4.0.2 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/src/core/tools/new-project.js +1 -0
  2. package/dist/src/dependencies.js +1 -1
  3. package/dist/src/templates/scripts/genesys/migrate-scenes-and-prefabs.js +179 -0
  4. package/dist/src/templates/scripts/genesys/post-install.js +10 -2
  5. package/dist/src/templates/src/templates/firstPerson/src/game.js +1 -1
  6. package/dist/src/templates/src/templates/firstPerson/src/player.js +8 -13
  7. package/dist/src/templates/src/templates/fps/src/game.js +1 -1
  8. package/dist/src/templates/src/templates/fps/src/player.js +8 -12
  9. package/dist/src/templates/src/templates/fps/src/weapon.js +30 -38
  10. package/dist/src/templates/src/templates/freeCamera/src/game.js +1 -1
  11. package/dist/src/templates/src/templates/freeCamera/src/player.js +6 -11
  12. package/dist/src/templates/src/templates/sideScroller/src/game.js +2 -3
  13. package/dist/src/templates/src/templates/sideScroller/src/level-generator.js +17 -17
  14. package/dist/src/templates/src/templates/sideScroller/src/player.js +12 -17
  15. package/dist/src/templates/src/templates/thirdPerson/src/game.js +1 -1
  16. package/dist/src/templates/src/templates/thirdPerson/src/player.js +13 -18
  17. package/dist/src/templates/src/templates/vehicle/src/base-vehicle.js +1 -1
  18. package/dist/src/templates/src/templates/vehicle/src/game.js +2 -2
  19. package/dist/src/templates/src/templates/vehicle/src/mesh-vehicle.js +8 -9
  20. package/dist/src/templates/src/templates/vehicle/src/player.js +13 -18
  21. package/dist/src/templates/src/templates/vehicle/src/primitive-vehicle.js +11 -12
  22. package/dist/src/templates/src/templates/vehicle/src/ui-hints.js +2 -2
  23. package/dist/src/templates/src/templates/vr-game/src/game.js +5 -5
  24. package/package.json +2 -2
  25. package/src/templates/scripts/genesys/migrate-scenes-and-prefabs.ts +212 -0
  26. package/src/templates/scripts/genesys/post-install.ts +11 -2
  27. package/src/templates/src/templates/firstPerson/src/game.ts +1 -1
  28. package/src/templates/src/templates/firstPerson/src/player.ts +10 -14
  29. package/src/templates/src/templates/fps/src/game.ts +1 -1
  30. package/src/templates/src/templates/fps/src/player.ts +10 -13
  31. package/src/templates/src/templates/fps/src/weapon.ts +31 -38
  32. package/src/templates/src/templates/freeCamera/src/game.ts +1 -1
  33. package/src/templates/src/templates/freeCamera/src/player.ts +7 -12
  34. package/src/templates/src/templates/sideScroller/src/game.ts +2 -3
  35. package/src/templates/src/templates/sideScroller/src/level-generator.ts +21 -21
  36. package/src/templates/src/templates/sideScroller/src/player.ts +15 -17
  37. package/src/templates/src/templates/thirdPerson/src/game.ts +1 -1
  38. package/src/templates/src/templates/thirdPerson/src/player.ts +16 -19
  39. package/src/templates/src/templates/vehicle/src/base-vehicle.ts +1 -1
  40. package/src/templates/src/templates/vehicle/src/game.ts +2 -2
  41. package/src/templates/src/templates/vehicle/src/mesh-vehicle.ts +8 -10
  42. package/src/templates/src/templates/vehicle/src/player.ts +16 -19
  43. package/src/templates/src/templates/vehicle/src/primitive-vehicle.ts +11 -13
  44. package/src/templates/src/templates/vehicle/src/ui-hints.ts +2 -2
  45. package/src/templates/src/templates/vr-game/src/game.ts +5 -5
@@ -24,7 +24,7 @@ export class BaseVehicle extends ENGINE.Pawn {
24
24
  }
25
25
  setupCamera() {
26
26
  // create a follow component for smooth camera movement
27
- const followComponent = new ENGINE.FollowComponent({
27
+ const followComponent = ENGINE.FollowComponent.create({
28
28
  positionOffset: new THREE.Vector3(0, 4, 10),
29
29
  positionDamping: 0.02,
30
30
  lookAtOffset: new THREE.Vector3(0, 0, 0),
@@ -14,12 +14,12 @@ class MyGame extends ENGINE.BaseGameLoop {
14
14
  // default spawn location
15
15
  const position = new THREE.Vector3(0, ENGINE.CHARACTER_HEIGHT / 2, 0);
16
16
  // create the pawn
17
- this.pawn = new VehiclePlayer({ position });
17
+ this.pawn = VehiclePlayer.create({ position });
18
18
  // create the controller and possess the pawn
19
19
  this.controller = new ENGINE.PlayerController();
20
20
  this.controller.possess(this.pawn);
21
21
  // create UI hints
22
- const uiHints = new UIHints();
22
+ const uiHints = UIHints.create();
23
23
  // add all actors to the world
24
24
  this.world.addActors(this.pawn, this.controller, uiHints);
25
25
  }
@@ -22,9 +22,10 @@ import { BaseVehicle } from './base-vehicle.js';
22
22
  *
23
23
  */
24
24
  let MeshVehicle = MeshVehicle_1 = class MeshVehicle extends BaseVehicle {
25
- constructor(options) {
25
+ constructor() {
26
+ super();
26
27
  // the root component is only used for collision and physics simulation
27
- const rootComponent = new ENGINE.MeshComponent({
28
+ const rootComponent = ENGINE.MeshComponent.create({
28
29
  geometry: new THREE.BoxGeometry(2.77, 1.79, 5.75),
29
30
  material: new THREE.MeshStandardMaterial({
30
31
  color: 0x4444FF,
@@ -41,10 +42,10 @@ let MeshVehicle = MeshVehicle_1 = class MeshVehicle extends BaseVehicle {
41
42
  },
42
43
  });
43
44
  rootComponent.name = 'root';
44
- options.rootComponent = rootComponent;
45
+ this.setRootComponent(rootComponent, true);
45
46
  // mark the component as transient, this prevents all the components from being saved since we're recreating them in code
46
47
  rootComponent.setTransient(true);
47
- const chassisComponent = new ENGINE.GLTFMeshComponent({
48
+ const chassisComponent = ENGINE.GLTFMeshComponent.create({
48
49
  modelUrl: '@project/assets/models/cyberTruck/chassis.glb',
49
50
  position: new THREE.Vector3(0, 0, -0.75),
50
51
  material: new THREE.MeshStandardMaterial({
@@ -61,7 +62,7 @@ let MeshVehicle = MeshVehicle_1 = class MeshVehicle extends BaseVehicle {
61
62
  rootComponent.add(chassisComponent);
62
63
  const wheelMeshes = [];
63
64
  for (let i = 0; i < 4; i++) {
64
- const wheelComponent = new ENGINE.GLTFMeshComponent({
65
+ const wheelComponent = ENGINE.GLTFMeshComponent.create({
65
66
  modelUrl: '@project/assets/models/cyberTruck/wheel.glb',
66
67
  material: new THREE.MeshStandardMaterial({
67
68
  color: 0x44FF44,
@@ -78,8 +79,7 @@ let MeshVehicle = MeshVehicle_1 = class MeshVehicle extends BaseVehicle {
78
79
  }
79
80
  rootComponent.add(...wheelMeshes);
80
81
  const vehicleMovementComponent = MeshVehicle_1.createVehicleMovementComponent();
81
- options.movementComponent = vehicleMovementComponent;
82
- super(options);
82
+ this.movementComponent = vehicleMovementComponent;
83
83
  const wheelComponents = this.getComponents(ENGINE.GLTFMeshComponent).filter(component => component.name.startsWith('wheel_'));
84
84
  vehicleMovementComponent.onWheelUpdated.add((component, wheelIndex, wheelState) => {
85
85
  // The first mesh component is the chassis component, so we need to skip it
@@ -108,8 +108,7 @@ let MeshVehicle = MeshVehicle_1 = class MeshVehicle extends BaseVehicle {
108
108
  const sideFrictionStiffness = 2;
109
109
  const frictionSlip = 50;
110
110
  // Create vehicle movement component
111
- const vehicleMovement = new ENGINE.VehicleMovementComponent({
112
- ...ENGINE.BasePawnMovementComponent.DEFAULT_OPTIONS,
111
+ const vehicleMovement = ENGINE.VehicleMovementComponent.create({
113
112
  createWheelMeshes: false,
114
113
  maxEnginePower: 100,
115
114
  maxBrakeForce: 1.5,
@@ -18,14 +18,15 @@ import { BaseVehicle } from './base-vehicle.js';
18
18
  */
19
19
  let VehiclePlayer = class VehiclePlayer extends ENGINE.ThirdPersonCharacterPawn {
20
20
  // Omit all the options that are created internally
21
- constructor(options) {
21
+ constructor() {
22
+ super();
22
23
  // simple camera component - contains a perspective camera by default
23
24
  const camera = new THREE.PerspectiveCamera(ENGINE.CAMERA_FOV, 1, 0.1, 1000);
24
25
  // set camera position for third person view
25
26
  camera.position.set(0, ENGINE.CHARACTER_HEIGHT * 1.3, ENGINE.CHARACTER_HEIGHT * 2);
26
27
  camera.lookAt(0, 0, 0);
27
28
  // use capsule root component for collision
28
- const rootComponent = new ENGINE.MeshComponent({
29
+ const rootComponent = ENGINE.MeshComponent.create({
29
30
  geometry: ENGINE.GameBuilder.createDefaultPawnCapsuleGeometry(),
30
31
  material: new THREE.MeshStandardMaterial({ color: ENGINE.Color.YELLOW, visible: false, transparent: true, opacity: 0.5 }),
31
32
  physicsOptions: {
@@ -35,25 +36,19 @@ let VehiclePlayer = class VehiclePlayer extends ENGINE.ThirdPersonCharacterPawn
35
36
  collisionProfile: ENGINE.DefaultCollisionProfile.Character,
36
37
  },
37
38
  });
39
+ this.setRootComponent(rootComponent, true);
40
+ this.rootComponent.add(camera);
38
41
  // use third person movement mechanics
39
- const movementComponent = new ENGINE.CharacterMovementComponent({
40
- ...ENGINE.CharacterMovementComponent.DEFAULT_OPTIONS,
42
+ const movementComponent = ENGINE.CharacterMovementComponent.create({
41
43
  movementType: ENGINE.CharacterMovementType.ThirdPerson,
42
44
  });
43
- // construct the pawn
44
- super({
45
- ...options,
46
- rootComponent,
47
- movementComponent,
48
- camera,
49
- // make sure the directional light follows the player for consistent shadows
50
- enableDirectionalLightFollowing: true,
51
- modelUrl: '@engine/assets/character/mannequinG.glb',
52
- configUrl: '@engine/assets/character/config/mannequin-anim.json',
53
- meshPosition: new THREE.Vector3(0, -ENGINE.CHARACTER_HEIGHT / 2, 0),
54
- meshRotation: new THREE.Euler(0, Math.PI, 0),
55
- meshScale: new THREE.Vector3(1, 1, 1),
56
- });
45
+ this.movementComponent = movementComponent;
46
+ // Character model settings
47
+ this.enableDirectionalLightFollowing = true;
48
+ this.configUrl = '@engine/assets/character/config/mannequin-anim.json';
49
+ this.meshComponent.position.copy(new THREE.Vector3(0, -ENGINE.CHARACTER_HEIGHT / 2, 0));
50
+ this.meshComponent.rotation.copy(new THREE.Euler(0, Math.PI, 0));
51
+ rootComponent.add(this.meshComponent);
57
52
  // set the pawn to be transient so it's never saved in the level
58
53
  this.setTransient(true);
59
54
  }
@@ -21,9 +21,10 @@ import { BaseVehicle } from './base-vehicle.js';
21
21
  */
22
22
  let PrimitiveVehicle = PrimitiveVehicle_1 = class PrimitiveVehicle extends BaseVehicle {
23
23
  tailLightComponents = [];
24
- constructor(options) {
24
+ constructor() {
25
+ super();
25
26
  // Create chassis mesh
26
- const rootComponent = new ENGINE.MeshComponent({
27
+ const rootComponent = ENGINE.MeshComponent.create({
27
28
  geometry: new THREE.BoxGeometry(2, 1, 4),
28
29
  material: new THREE.MeshStandardMaterial({
29
30
  color: 0x4444FF,
@@ -40,11 +41,10 @@ let PrimitiveVehicle = PrimitiveVehicle_1 = class PrimitiveVehicle extends BaseV
40
41
  rootComponent.name = 'chassis';
41
42
  // mark the component as transient, this prevents all the components from being saved since we're recreating them in code
42
43
  rootComponent.setTransient(true);
43
- options.rootComponent = rootComponent;
44
+ this.setRootComponent(rootComponent, true);
44
45
  // create decorative meshes
45
46
  PrimitiveVehicle_1.createDecorativeMeshes(rootComponent);
46
- options.movementComponent = PrimitiveVehicle_1.createVehicleMovementComponent();
47
- super(options);
47
+ this.movementComponent = PrimitiveVehicle_1.createVehicleMovementComponent();
48
48
  this.tailLightComponents = this.getComponents(ENGINE.MeshComponent)
49
49
  .filter((component) => component.name.includes('_taillight'));
50
50
  }
@@ -72,7 +72,7 @@ let PrimitiveVehicle = PrimitiveVehicle_1 = class PrimitiveVehicle extends BaseV
72
72
  }
73
73
  static createDecorativeMeshes(rootComponent) {
74
74
  // Add windshield
75
- const windshieldComponent = new ENGINE.MeshComponent({
75
+ const windshieldComponent = ENGINE.MeshComponent.create({
76
76
  geometry: new THREE.BoxGeometry(1.8, 1.8, 0.1),
77
77
  material: new THREE.MeshStandardMaterial({
78
78
  color: 0x87CEEB,
@@ -90,7 +90,7 @@ let PrimitiveVehicle = PrimitiveVehicle_1 = class PrimitiveVehicle extends BaseV
90
90
  windshieldComponent.name = 'windshield';
91
91
  rootComponent.add(windshieldComponent);
92
92
  // Add left headlight
93
- const leftHeadlightComponent = new ENGINE.MeshComponent({
93
+ const leftHeadlightComponent = ENGINE.MeshComponent.create({
94
94
  geometry: new THREE.CylinderGeometry(0.15, 0.15, 0.1, 8),
95
95
  material: new THREE.MeshStandardMaterial({
96
96
  color: 0xFFFFFF,
@@ -106,7 +106,7 @@ let PrimitiveVehicle = PrimitiveVehicle_1 = class PrimitiveVehicle extends BaseV
106
106
  leftHeadlightComponent.name = 'left_headlight';
107
107
  rootComponent.add(leftHeadlightComponent);
108
108
  // Add right headlight
109
- const rightHeadlightComponent = new ENGINE.MeshComponent({
109
+ const rightHeadlightComponent = ENGINE.MeshComponent.create({
110
110
  geometry: new THREE.CylinderGeometry(0.15, 0.15, 0.1, 8),
111
111
  material: new THREE.MeshStandardMaterial({
112
112
  color: 0xFFFFFF,
@@ -127,7 +127,7 @@ let PrimitiveVehicle = PrimitiveVehicle_1 = class PrimitiveVehicle extends BaseV
127
127
  emissive: 0x440000,
128
128
  emissiveIntensity: 0.2,
129
129
  });
130
- const leftTaillightComponent = new ENGINE.MeshComponent({
130
+ const leftTaillightComponent = ENGINE.MeshComponent.create({
131
131
  geometry: new THREE.CylinderGeometry(0.1, 0.1, 0.1, 8),
132
132
  material: leftTaillightMaterial,
133
133
  physicsOptions: {
@@ -144,7 +144,7 @@ let PrimitiveVehicle = PrimitiveVehicle_1 = class PrimitiveVehicle extends BaseV
144
144
  emissive: 0x440000,
145
145
  emissiveIntensity: 0.2,
146
146
  });
147
- const rightTaillightComponent = new ENGINE.MeshComponent({
147
+ const rightTaillightComponent = ENGINE.MeshComponent.create({
148
148
  geometry: new THREE.CylinderGeometry(0.1, 0.1, 0.1, 8),
149
149
  material: rightTaillightMaterial,
150
150
  physicsOptions: {
@@ -171,7 +171,6 @@ let PrimitiveVehicle = PrimitiveVehicle_1 = class PrimitiveVehicle extends BaseV
171
171
  const sideFrictionStiffness = 2;
172
172
  const frictionSlip = 8;
173
173
  const options = {
174
- ...ENGINE.BasePawnMovementComponent.DEFAULT_OPTIONS,
175
174
  maxEnginePower: 35,
176
175
  maxSteeringAngle: Math.PI / 6, // 30 degrees
177
176
  maxBrakeForce: 1,
@@ -250,7 +249,7 @@ let PrimitiveVehicle = PrimitiveVehicle_1 = class PrimitiveVehicle extends BaseV
250
249
  },
251
250
  ],
252
251
  };
253
- return new ENGINE.VehicleMovementComponent(options);
252
+ return ENGINE.VehicleMovementComponent.create(options);
254
253
  }
255
254
  };
256
255
  PrimitiveVehicle = PrimitiveVehicle_1 = __decorate([
@@ -10,8 +10,8 @@ import * as ENGINE from '@directivegames/genesys.js';
10
10
  */
11
11
  let UIHints = class UIHints extends ENGINE.Actor {
12
12
  uiElement = null;
13
- constructor(options = {}) {
14
- super(options);
13
+ constructor() {
14
+ super();
15
15
  this.setTransient(true); // Don't save this UI element to the level
16
16
  }
17
17
  async doBeginPlay() {
@@ -22,7 +22,7 @@ class MyGame extends ENGINE.BaseGameLoop {
22
22
  // Disable tone mapping for VR because it breaks VR
23
23
  this.world.postProcessManager.disablePasses(ENGINE.PostProcessPass.ToneMapping);
24
24
  // create the vr pawn
25
- this.pawn = new ENGINE.VRPawn({
25
+ this.pawn = ENGINE.VRPawn.create({
26
26
  position: new THREE.Vector3(0, 0, 0),
27
27
  movementComponent: null,
28
28
  camera: new THREE.PerspectiveCamera(ENGINE.CAMERA_FOV, 1, ENGINE.CAMERA_NEAR, ENGINE.CAMERA_FAR),
@@ -38,10 +38,10 @@ class MyGame extends ENGINE.BaseGameLoop {
38
38
  // create the controller and possess the pawn
39
39
  this.controller = new ENGINE.PlayerController();
40
40
  this.controller.possess(this.pawn);
41
- this.pawn.addComponent(new ENGINE.VRGrabComponent({}));
42
- this.pawn.addComponent(new ENGINE.VRSnapTurnComponent({ angleDeg: this.pawn.getSnapTurnAngleDegrees() }));
43
- this.pawn.addComponent(new ENGINE.VRInteractComponent({ button: ENGINE.XRButton.Trigger }));
44
- this.pawn.addComponent(new ENGINE.VRTeleportComponent({ maxDistance: 15 }));
41
+ this.pawn.addComponent(ENGINE.VRGrabComponent.create());
42
+ this.pawn.addComponent(ENGINE.VRSnapTurnComponent.create({ angleDeg: this.pawn.getSnapTurnAngleDegrees() }));
43
+ this.pawn.addComponent(ENGINE.VRInteractComponent.create({ button: ENGINE.XRButton.Trigger }));
44
+ this.pawn.addComponent(ENGINE.VRTeleportComponent.create({ maxDistance: 15 }));
45
45
  // add both to the world
46
46
  this.world.addActors(this.pawn, this.controller);
47
47
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@directivegames/genesys.sdk",
3
- "version": "4.0.2",
3
+ "version": "4.1.0",
4
4
  "description": "Genesys SDK - A development toolkit for game development",
5
5
  "author": "Directive Games",
6
6
  "main": "index.js",
@@ -109,7 +109,7 @@
109
109
  }
110
110
  },
111
111
  "dependencies": {
112
- "@directivegames/genesys.js": "^4.0.2",
112
+ "@directivegames/genesys.js": "^4.0.3",
113
113
  "@electron/rebuild": "^4.0.1",
114
114
  "@emotion/react": "^11.14.0",
115
115
  "@emotion/styled": "^11.14.0",
@@ -0,0 +1,212 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+
4
+ import * as ENGINE from '@directivegames/genesys.js';
5
+
6
+ import { getProjectRoot } from './common.js';
7
+ import { mockBrowserEnvironment } from './mock.js';
8
+ import { StorageProvider } from './storageProvider.js';
9
+
10
+ // Import game module to register game classes (tsx compiles TypeScript on the fly)
11
+ import '../../src/game.js';
12
+
13
+ // Set up browser environment for Node.js (provides document, window, etc.)
14
+ mockBrowserEnvironment();
15
+
16
+ // Set up storage provider for file operations
17
+ const storageProvider = new StorageProvider();
18
+ ENGINE.projectContext({ project: 'local-project', storageProvider: storageProvider });
19
+
20
+
21
+ interface FileInfo {
22
+ path: string;
23
+ type: 'scene' | 'prefab';
24
+ }
25
+
26
+ const defaultWorldOptions = {
27
+ rendererDomElement: document.createElement('div'),
28
+ gameContainer: document.createElement('div'),
29
+ backgroundColor: 0x2E2E2E,
30
+ physicsOptions: {
31
+ engine: ENGINE.PhysicsEngine.Rapier,
32
+ gravity: ENGINE.MathHelpers.makeVector({ up: -9.81 }),
33
+ },
34
+ navigationOptions: {
35
+ engine: ENGINE.NavigationEngine.RecastNavigation,
36
+ },
37
+ useManifold: true
38
+ };
39
+
40
+ function findScenesAndPrefabs(dir: string, files: FileInfo[] = []): FileInfo[] {
41
+ const entries = fs.readdirSync(dir);
42
+
43
+ for (const entry of entries) {
44
+ const fullPath = path.join(dir, entry);
45
+ const stat = fs.statSync(fullPath);
46
+
47
+ if (stat.isDirectory()) {
48
+ // Skip common directories that shouldn't be processed
49
+ if (entry === 'node_modules' || entry === 'dist' || entry === '.git' || entry === '.engine') {
50
+ continue;
51
+ }
52
+ findScenesAndPrefabs(fullPath, files);
53
+ } else if (entry.endsWith('.genesys-scene')) {
54
+ files.push({ path: fullPath, type: 'scene' });
55
+ } else if (entry.endsWith('.prefab.json')) {
56
+ files.push({ path: fullPath, type: 'prefab' });
57
+ }
58
+ }
59
+
60
+ return files;
61
+ }
62
+
63
+ async function migrateSceneFile(filePath: string, relativePath: string): Promise<boolean> {
64
+ // Read the file content
65
+ const content = fs.readFileSync(filePath, 'utf-8');
66
+ const data = JSON.parse(content);
67
+
68
+ // Create a world and load into it
69
+ const world = new ENGINE.World(defaultWorldOptions);
70
+
71
+ if (ENGINE.isLegacyData(data)) {
72
+ // Use WorldSerializer for legacy data
73
+ await ENGINE.WorldSerializer.loadWorld(world, data);
74
+ } else {
75
+ // Use Loader for new format
76
+ const loader = new ENGINE.Loader();
77
+ await loader.loadToInstanceAsync(data, world);
78
+ }
79
+
80
+ // Dump the world
81
+ const dumper = new ENGINE.Dumper();
82
+ const newData = dumper.dump(world);
83
+
84
+ // Write back to file
85
+ const newContent = JSON.stringify(newData, null, 2);
86
+ fs.writeFileSync(filePath, newContent, 'utf-8');
87
+
88
+ console.log(`✅ ${relativePath}`);
89
+ return true;
90
+ }
91
+
92
+ async function migratePrefabFile(filePath: string, relativePath: string): Promise<boolean> {
93
+ // Read the file content
94
+ const content = fs.readFileSync(filePath, 'utf-8');
95
+ const data = JSON.parse(content);
96
+
97
+ let instance: any;
98
+
99
+ if (ENGINE.isLegacyData(data)) {
100
+ // Use WorldSerializer for legacy data
101
+ console.log(`🔍 Migrating legacy prefab: ${relativePath}`);
102
+ instance = await ENGINE.WorldSerializer.loadActor(data);
103
+ console.log(`✅ ${relativePath}`);
104
+ } else {
105
+ // Use Loader for new format
106
+ const loader = new ENGINE.Loader();
107
+ instance = await loader.loadAsync(data);
108
+ }
109
+
110
+ if (!instance) {
111
+ console.log(`⚠️ ${relativePath}: Loaded instance is null, skipping`);
112
+ return false;
113
+ }
114
+
115
+ // Dump using Dumper
116
+ const dumper = new ENGINE.Dumper();
117
+ const newData = dumper.dump(instance);
118
+
119
+ // Write back to file
120
+ const newContent = JSON.stringify(newData, null, 2);
121
+ fs.writeFileSync(filePath, newContent, 'utf-8');
122
+
123
+ console.log(`✅ ${relativePath}`);
124
+ return true;
125
+ }
126
+
127
+ async function migrateFile(fileInfo: FileInfo): Promise<boolean> {
128
+ const { path: filePath, type } = fileInfo;
129
+ const relativePath = path.relative(getProjectRoot(), filePath);
130
+
131
+ try {
132
+ if (type === 'scene') {
133
+ return await migrateSceneFile(filePath, relativePath);
134
+ } else {
135
+ return await migratePrefabFile(filePath, relativePath);
136
+ }
137
+ } catch (error) {
138
+ console.error(`❌ ${relativePath}: ${error instanceof Error ? error.message : String(error)}`);
139
+ return false;
140
+ } finally {
141
+ console.log('');
142
+ }
143
+ }
144
+
145
+ async function main() {
146
+ // Game classes are registered via the top-level import of dist/src/game.js
147
+ // Make sure to run `pnpm build` first!
148
+
149
+ const projectRoot = getProjectRoot();
150
+ const assetsFolder = path.join(projectRoot, 'assets');
151
+ console.log(`📁 Scanning for scene and prefab files in: ${assetsFolder}\n`);
152
+
153
+ // Find all scene and prefab files in the assets folder
154
+ const files = findScenesAndPrefabs(assetsFolder);
155
+
156
+ if (files.length === 0) {
157
+ console.log('⚠️ No scene or prefab files found.');
158
+ return;
159
+ }
160
+
161
+ const prefabFiles = files.filter(f => f.type === 'prefab');
162
+ const sceneFiles = files.filter(f => f.type === 'scene');
163
+ console.log(`Found ${files.length} files to migrate:`);
164
+ console.log(` - ${prefabFiles.length} prefab file(s)`);
165
+ console.log(` - ${sceneFiles.length} scene file(s)\n`);
166
+
167
+ let successCount = 0;
168
+ let failCount = 0;
169
+
170
+ // Migrate prefabs first
171
+ if (prefabFiles.length > 0) {
172
+ console.log('📦 Migrating prefabs...\n');
173
+ for (const fileInfo of prefabFiles) {
174
+ const success = await migrateFile(fileInfo);
175
+ if (success) {
176
+ successCount++;
177
+ } else {
178
+ failCount++;
179
+ }
180
+ }
181
+ }
182
+
183
+ // Then migrate scenes
184
+ if (sceneFiles.length > 0) {
185
+ console.log('\n🌍 Migrating scenes...\n');
186
+ for (const fileInfo of sceneFiles) {
187
+ const success = await migrateFile(fileInfo);
188
+ if (success) {
189
+ successCount++;
190
+ } else {
191
+ failCount++;
192
+ }
193
+ }
194
+ }
195
+
196
+ console.log(`\n${'='.repeat(60)}`);
197
+ console.log('Migration Summary:');
198
+ console.log(` Total files: ${files.length}`);
199
+ console.log(` Successful: ${successCount}`);
200
+ console.log(` Failed: ${failCount}`);
201
+ console.log(`${'='.repeat(60)}`);
202
+
203
+ if (failCount > 0) {
204
+ process.exit(1);
205
+ }
206
+ }
207
+
208
+ main().catch((error) => {
209
+ console.error('Unexpected error:', error);
210
+ console.error('Stack trace:', error.stack);
211
+ process.exit(1);
212
+ });
@@ -17,14 +17,23 @@ async function main() {
17
17
 
18
18
  const foldersToCopy: string[] = [
19
19
  'games/examples',
20
- 'src',
21
- 'docs',
20
+ 'src'
22
21
  ];
23
22
  for (const folder of foldersToCopy) {
24
23
  const engineFolderPath = path.join(engineInstallFolder, folder);
25
24
  const localFolderPath = path.join(copiedEngineFolder, folder);
26
25
  fs.cpSync(engineFolderPath, localFolderPath, { recursive: true });
27
26
  }
27
+
28
+ // copy all *.md files
29
+ const files = fs.readdirSync(engineInstallFolder);
30
+ for (const file of files) {
31
+ if (file.endsWith('.md')) {
32
+ const engineFilePath = path.join(engineInstallFolder, file);
33
+ const localFilePath = path.join(copiedEngineFolder, file);
34
+ fs.copyFileSync(engineFilePath, localFilePath);
35
+ }
36
+ }
28
37
  }
29
38
 
30
39
  main();
@@ -19,7 +19,7 @@ class FirstPersonGame extends ENGINE.BaseGameLoop {
19
19
  const position = new THREE.Vector3(0, ENGINE.CHARACTER_HEIGHT / 2, 0);
20
20
 
21
21
  // now create the pawn
22
- this.pawn = new FirstPersonPlayer({ position });
22
+ this.pawn = FirstPersonPlayer.create({ position });
23
23
 
24
24
  // create the controller and possess the pawn
25
25
  this.controller = new ENGINE.PlayerController();
@@ -18,16 +18,17 @@ export interface FirstPersonPlayerOptions extends ENGINE.PawnOptions {
18
18
  *
19
19
  */
20
20
  @ENGINE.GameClass()
21
- export class FirstPersonPlayer extends ENGINE.Pawn<FirstPersonPlayerOptions> {
21
+ export class FirstPersonPlayer extends ENGINE.Pawn {
22
22
  // No need to provide rootComponent, movementComponent and camera, they are created internally
23
- constructor(options: Omit<FirstPersonPlayerOptions, 'rootComponent' | 'movementComponent' | 'camera'>) {
23
+ constructor() {
24
+ super();
24
25
  // simple camera component - contains a perspective camera by default
25
26
  const camera = new THREE.PerspectiveCamera(ENGINE.CAMERA_FOV, 1, ENGINE.CAMERA_NEAR, ENGINE.CAMERA_FAR);
26
27
  // set proper camera height for first person view
27
28
  camera.position.set(0, ENGINE.CHARACTER_HEIGHT * 0.4, 0);
28
29
 
29
30
  // use a simple capsule geometry as the root component
30
- const rootComponent = new ENGINE.MeshComponent({
31
+ const rootComponent = ENGINE.MeshComponent.create({
31
32
  geometry: ENGINE.GameBuilder.createDefaultPawnCapsuleGeometry(),
32
33
  material: new THREE.MeshStandardMaterial({ color: ENGINE.Color.YELLOW }),
33
34
  physicsOptions: {
@@ -40,22 +41,17 @@ export class FirstPersonPlayer extends ENGINE.Pawn<FirstPersonPlayerOptions> {
40
41
  });
41
42
  // hide the mesh in first person view
42
43
  rootComponent.getMesh().visible = false;
44
+ this.setRootComponent(rootComponent, true);
45
+
46
+ this.rootComponent.add(camera);
43
47
 
44
48
  // create the movement component
45
- const movementComponent = new ENGINE.CharacterMovementComponent({
46
- ...ENGINE.CharacterMovementComponent.DEFAULT_OPTIONS,
49
+ const movementComponent = ENGINE.CharacterMovementComponent.create({
47
50
  movementType: ENGINE.CharacterMovementType.FirstPerson,
48
51
  });
52
+ this.movementComponent = movementComponent;
49
53
 
50
- // construct the pawn
51
- super({
52
- ...options,
53
- rootComponent,
54
- movementComponent,
55
- // make sure the directional light follows the player for consistent shadows
56
- enableDirectionalLightFollowing: true,
57
- camera,
58
- });
54
+ this.enableDirectionalLightFollowing = true;
59
55
 
60
56
  // set the pawn to be transient so it's never saved in the level
61
57
  this.setTransient(true);
@@ -19,7 +19,7 @@ class MyGame extends ENGINE.BaseGameLoop {
19
19
  const position = new THREE.Vector3(0, ENGINE.CHARACTER_HEIGHT / 2, 0);
20
20
 
21
21
  // now create the pawn
22
- this.pawn = new FPSPlayer({ position });
22
+ this.pawn = FPSPlayer.create({ position });
23
23
 
24
24
  // create the controller and possess the pawn
25
25
  this.controller = new ENGINE.PlayerController();
@@ -21,9 +21,10 @@ export interface FPSPlayerOptions extends ENGINE.PawnOptions {
21
21
  *
22
22
  */
23
23
  @ENGINE.GameClass()
24
- export class FPSPlayer extends ENGINE.Pawn<FPSPlayerOptions> {
24
+ export class FPSPlayer extends ENGINE.Pawn {
25
25
  // No need to provide rootComponent, movementComponent and camera, they are created internally
26
- constructor(options: Omit<FPSPlayerOptions, 'rootComponent' | 'movementComponent' | 'camera'>) {
26
+ constructor() {
27
+ super();
27
28
  // simple camera component - contains a perspective camera by default
28
29
  const camera = new THREE.PerspectiveCamera(ENGINE.CAMERA_FOV, 1, ENGINE.CAMERA_NEAR, ENGINE.CAMERA_FAR);
29
30
  // set proper camera height for first person view
@@ -34,7 +35,7 @@ export class FPSPlayer extends ENGINE.Pawn<FPSPlayerOptions> {
34
35
  camera.add(weapon);
35
36
 
36
37
  // use a simple capsule geometry as the root component
37
- const rootComponent = new ENGINE.MeshComponent({
38
+ const rootComponent = ENGINE.MeshComponent.create({
38
39
  geometry: ENGINE.GameBuilder.createDefaultPawnCapsuleGeometry(),
39
40
  material: new THREE.MeshStandardMaterial({ color: ENGINE.Color.YELLOW }),
40
41
  physicsOptions: {
@@ -47,21 +48,17 @@ export class FPSPlayer extends ENGINE.Pawn<FPSPlayerOptions> {
47
48
  });
48
49
  // hide the mesh in first person view
49
50
  rootComponent.getMesh().visible = false;
51
+ this.setRootComponent(rootComponent, true);
52
+ this.rootComponent.add(camera);
50
53
 
51
54
  // create the movement component
52
- const movementComponent = new ENGINE.CharacterMovementComponent({
53
- ...ENGINE.CharacterMovementComponent.DEFAULT_OPTIONS,
55
+ const movementComponent = ENGINE.CharacterMovementComponent.create({
54
56
  movementType: ENGINE.CharacterMovementType.FirstPerson,
55
57
  });
56
58
 
57
- super({
58
- ...options,
59
- rootComponent,
60
- movementComponent,
61
- // make sure the directional light follows the player for consistent shadows
62
- enableDirectionalLightFollowing: true,
63
- camera
64
- });
59
+ this.movementComponent = movementComponent;
60
+
61
+ this.enableDirectionalLightFollowing = true;
65
62
 
66
63
  // set the pawn to be transient so it's never saved in the level
67
64
  this.setTransient(true);