@dcl-regenesislabs/opendcl 0.1.0-22234509684.commit-63dfd19

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 (54) hide show
  1. package/README.md +234 -0
  2. package/context/components-reference.md +113 -0
  3. package/context/open-source-3d-assets.md +705 -0
  4. package/context/sdk7-complete-reference.md +3684 -0
  5. package/context/sdk7-examples.md +1709 -0
  6. package/dist/index.d.ts +8 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +76 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/scene-context.d.ts +97 -0
  11. package/dist/scene-context.d.ts.map +1 -0
  12. package/dist/scene-context.js +203 -0
  13. package/dist/scene-context.js.map +1 -0
  14. package/dist/utils.d.ts +2 -0
  15. package/dist/utils.d.ts.map +1 -0
  16. package/dist/utils.js +4 -0
  17. package/dist/utils.js.map +1 -0
  18. package/extensions/dcl-context.ts +123 -0
  19. package/extensions/dcl-deploy.ts +89 -0
  20. package/extensions/dcl-header.ts +162 -0
  21. package/extensions/dcl-init.ts +62 -0
  22. package/extensions/dcl-preview.ts +144 -0
  23. package/extensions/dcl-setup-ollama.ts +312 -0
  24. package/extensions/dcl-setup.ts +96 -0
  25. package/extensions/dcl-status.ts +88 -0
  26. package/extensions/dcl-tasks.ts +102 -0
  27. package/extensions/dcl-update-check.ts +79 -0
  28. package/extensions/dcl-validate.ts +80 -0
  29. package/extensions/plan-mode/index.ts +340 -0
  30. package/extensions/plan-mode/utils.ts +168 -0
  31. package/extensions/process-registry.ts +25 -0
  32. package/extensions/scene-utils.ts +31 -0
  33. package/package.json +65 -0
  34. package/prompts/explain.md +16 -0
  35. package/prompts/review.md +19 -0
  36. package/prompts/system.md +126 -0
  37. package/skills/add-3d-models/SKILL.md +115 -0
  38. package/skills/add-interactivity/SKILL.md +176 -0
  39. package/skills/advanced-input/SKILL.md +238 -0
  40. package/skills/advanced-rendering/SKILL.md +235 -0
  41. package/skills/animations-tweens/SKILL.md +173 -0
  42. package/skills/audio-video/SKILL.md +167 -0
  43. package/skills/authoritative-server/SKILL.md +329 -0
  44. package/skills/build-ui/SKILL.md +231 -0
  45. package/skills/camera-control/SKILL.md +199 -0
  46. package/skills/create-scene/SKILL.md +67 -0
  47. package/skills/deploy-scene/SKILL.md +106 -0
  48. package/skills/deploy-worlds/SKILL.md +107 -0
  49. package/skills/lighting-environment/SKILL.md +216 -0
  50. package/skills/multiplayer-sync/SKILL.md +132 -0
  51. package/skills/nft-blockchain/SKILL.md +246 -0
  52. package/skills/optimize-scene/SKILL.md +160 -0
  53. package/skills/player-avatar/SKILL.md +239 -0
  54. package/skills/smart-items/SKILL.md +181 -0
@@ -0,0 +1,199 @@
1
+ ---
2
+ name: camera-control
3
+ description: Control camera behavior in Decentraland scenes. Switch between first-person and third-person with CameraMode, force camera in regions with CameraModeArea, create cinematic scripted cameras with VirtualCamera, and read camera position/rotation via MainCamera. Use when user wants camera control, cinematic views, cutscenes, or camera mode switching.
4
+ ---
5
+
6
+ # Camera Control in Decentraland
7
+
8
+ ## Reading Camera State
9
+
10
+ Access the camera's current position and rotation via the reserved `engine.CameraEntity`:
11
+
12
+ ```typescript
13
+ import { engine, Transform, CameraMode, CameraType } from '@dcl/sdk/ecs'
14
+
15
+ function trackCamera() {
16
+ if (!Transform.has(engine.CameraEntity)) return
17
+
18
+ const cameraTransform = Transform.get(engine.CameraEntity)
19
+ console.log('Camera position:', cameraTransform.position)
20
+ console.log('Camera rotation:', cameraTransform.rotation)
21
+ }
22
+
23
+ engine.addSystem(trackCamera)
24
+ ```
25
+
26
+ ## Camera Mode Detection
27
+
28
+ Check whether the player is in first-person or third-person:
29
+
30
+ ```typescript
31
+ function checkCameraMode() {
32
+ if (!CameraMode.has(engine.CameraEntity)) return
33
+
34
+ const cameraMode = CameraMode.get(engine.CameraEntity)
35
+ if (cameraMode.mode === CameraType.CT_FIRST_PERSON) {
36
+ console.log('First person camera')
37
+ } else if (cameraMode.mode === CameraType.CT_THIRD_PERSON) {
38
+ console.log('Third person camera')
39
+ }
40
+ }
41
+
42
+ engine.addSystem(checkCameraMode)
43
+ ```
44
+
45
+ ### Camera Mode Values
46
+
47
+ ```typescript
48
+ CameraType.CT_FIRST_PERSON // First-person view
49
+ CameraType.CT_THIRD_PERSON // Third-person view (default)
50
+ ```
51
+
52
+ ## CameraModeArea (Force Camera in a Region)
53
+
54
+ Force a specific camera mode when the player enters an area:
55
+
56
+ ```typescript
57
+ import { engine, Transform, CameraModeArea, CameraType } from '@dcl/sdk/ecs'
58
+ import { Vector3 } from '@dcl/sdk/math'
59
+
60
+ const fpArea = engine.addEntity()
61
+ Transform.create(fpArea, { position: Vector3.create(8, 1.5, 8) })
62
+
63
+ CameraModeArea.create(fpArea, {
64
+ area: Vector3.create(6, 4, 6), // 6x4x6 meter box
65
+ mode: CameraType.CT_FIRST_PERSON // Force first-person inside
66
+ })
67
+ ```
68
+
69
+ When the player leaves the area, the camera reverts to their preferred mode.
70
+
71
+ ## VirtualCamera (Cinematic Cameras)
72
+
73
+ Create scripted camera positions for cutscenes or special views:
74
+
75
+ ```typescript
76
+ import { engine, Transform, VirtualCamera, CameraTransition } from '@dcl/sdk/ecs'
77
+ import { Vector3, Quaternion } from '@dcl/sdk/math'
78
+
79
+ const cinematicCam = engine.addEntity()
80
+ Transform.create(cinematicCam, {
81
+ position: Vector3.create(8, 5, 2),
82
+ rotation: Quaternion.fromEulerDegrees(-20, 0, 0)
83
+ })
84
+
85
+ VirtualCamera.create(cinematicCam, {
86
+ defaultTransition: {
87
+ transitionMode: CameraTransition.CT_SPEED,
88
+ speed: 1.0
89
+ }
90
+ })
91
+ ```
92
+
93
+ ### Transition Modes
94
+
95
+ - `CameraTransition.CT_SPEED` — smooth transition at a fixed speed
96
+ - Higher `speed` values = faster camera movement to the virtual camera position
97
+
98
+ ### Look-At Target
99
+
100
+ Make the virtual camera track an entity:
101
+
102
+ ```typescript
103
+ const target = engine.addEntity()
104
+ Transform.create(target, { position: Vector3.create(8, 1, 8) })
105
+
106
+ VirtualCamera.create(cinematicCam, {
107
+ lookAtEntity: target,
108
+ defaultTransition: {
109
+ transitionMode: CameraTransition.CT_SPEED,
110
+ speed: 2.0
111
+ }
112
+ })
113
+ ```
114
+
115
+ ## Tracking Camera Position
116
+
117
+ Poll camera position each frame for camera-triggered events:
118
+
119
+ ```typescript
120
+ import { engine, Transform, CameraMode, CameraType } from '@dcl/sdk/ecs'
121
+ import { Vector3 } from '@dcl/sdk/math'
122
+
123
+ let lastNotifiedZone = ''
124
+
125
+ function cameraZoneSystem() {
126
+ if (!Transform.has(engine.CameraEntity)) return
127
+
128
+ const camPos = Transform.get(engine.CameraEntity).position
129
+ let currentZone = ''
130
+
131
+ if (camPos.y > 10) {
132
+ currentZone = 'sky'
133
+ } else if (camPos.x < 4) {
134
+ currentZone = 'west'
135
+ } else {
136
+ currentZone = 'center'
137
+ }
138
+
139
+ if (currentZone !== lastNotifiedZone) {
140
+ lastNotifiedZone = currentZone
141
+ console.log('Camera entered zone:', currentZone)
142
+ }
143
+ }
144
+
145
+ engine.addSystem(cameraZoneSystem)
146
+ ```
147
+
148
+ ## Common Patterns
149
+
150
+ ### Camera-Triggered Events
151
+
152
+ Use the camera position to trigger actions when the player looks at a specific area:
153
+
154
+ ```typescript
155
+ function cameraLookTrigger() {
156
+ const camTransform = Transform.get(engine.CameraEntity)
157
+ const targetPos = Vector3.create(8, 2, 8)
158
+ const distance = Vector3.distance(camTransform.position, targetPos)
159
+
160
+ if (distance < 5) {
161
+ // Player is close — check if camera is pointing at target
162
+ // Use raycasting for precise look detection (see add-interactivity skill)
163
+ }
164
+ }
165
+
166
+ engine.addSystem(cameraLookTrigger)
167
+ ```
168
+
169
+ ### Following an NPC
170
+
171
+ Move camera to track an NPC by updating a VirtualCamera's Transform:
172
+
173
+ ```typescript
174
+ function followNpcCamera(dt: number) {
175
+ const npcPos = Transform.get(npcEntity).position
176
+ const camTransform = Transform.getMutable(cinematicCam)
177
+
178
+ // Position camera behind and above the NPC
179
+ camTransform.position = Vector3.create(
180
+ npcPos.x - 2,
181
+ npcPos.y + 3,
182
+ npcPos.z - 2
183
+ )
184
+ }
185
+
186
+ engine.addSystem(followNpcCamera)
187
+ ```
188
+
189
+ ## Best Practices
190
+
191
+ - Only one VirtualCamera should be active at a time
192
+ - Use `CameraModeArea` to force first-person in tight indoor spaces
193
+ - Keep transition speeds between 0.5 and 3.0 for comfortable camera movement
194
+ - Always provide a way for the player to exit forced camera modes (e.g., leave the area)
195
+ - Read camera state via `engine.CameraEntity` — never try to write to it directly
196
+ - For look-at detection, combine camera position with raycasting (see `add-interactivity` skill)
197
+ - Camera control is read-only outside of VirtualCamera and CameraModeArea — you cannot directly move the player's camera
198
+
199
+ For component field details, see `context/components-reference.md`.
@@ -0,0 +1,67 @@
1
+ ---
2
+ name: create-scene
3
+ description: Scaffold a new Decentraland SDK7 scene project from scratch. Creates scene.json, package.json, tsconfig.json, and src/index.ts with a basic scene setup. Use when user wants to start a new scene, initialize a project, or set up from an empty folder.
4
+ ---
5
+
6
+ # Create a New Decentraland SDK7 Scene
7
+
8
+ When the user wants to create a new scene, follow these steps:
9
+
10
+ ## 1. Ask What They Want to Build
11
+
12
+ If the user hasn't described their scene, ask them:
13
+ - What kind of scene? (gallery, game, social space, interactive art, etc.)
14
+ - How many parcels? (default: 1 parcel = 16x16m)
15
+ - Any specific features? (3D models, interactivity, UI, multiplayer)
16
+
17
+ ## 2. Scaffold the Project with `/init`
18
+
19
+ **Always run `/init` first.** This uses the official `@dcl/sdk-commands init` to create scene.json, package.json, tsconfig.json, and src/index.ts with the correct, up-to-date configuration.
20
+
21
+ Never manually create scene.json, package.json, or tsconfig.json — the SDK templates may change between versions and hand-written copies will diverge.
22
+
23
+ ## 3. Customize the Generated Files
24
+
25
+ After `/init` completes, customize the generated files based on what the user wants:
26
+
27
+ ### scene.json
28
+ Update the `display` fields and parcels:
29
+ - `display.title` — set to the scene name
30
+ - `display.description` — set to a short description
31
+ - `scene.parcels` — for multi-parcel scenes, list all parcels (e.g., `["0,0", "0,1", "1,0", "1,1"]` for 2x2)
32
+ - `scene.base` — set to the southwest corner parcel
33
+
34
+ ### src/index.ts
35
+ Replace the generated code with the user's scene. Example:
36
+
37
+ ```typescript
38
+ import { engine, Transform, MeshRenderer, Material } from '@dcl/sdk/ecs'
39
+ import { Vector3, Color4 } from '@dcl/sdk/math'
40
+
41
+ export function main() {
42
+ // Create a cube at the center of the scene
43
+ const cube = engine.addEntity()
44
+ Transform.create(cube, {
45
+ position: Vector3.create(8, 1, 8)
46
+ })
47
+ MeshRenderer.setBox(cube)
48
+ Material.setPbrMaterial(cube, {
49
+ albedoColor: Color4.create(0.2, 0.5, 1, 1)
50
+ })
51
+ }
52
+ ```
53
+
54
+ ## 4. Post-Creation Steps
55
+
56
+ After creating the files, tell the user:
57
+ 1. Run `npm install` to install dependencies
58
+ 2. Use the `preview` tool to start the preview server (or run `npx @dcl/sdk-commands start --bevy-web` manually)
59
+ 3. The scene will open in a browser at http://localhost:8000
60
+
61
+ ## Important Notes
62
+
63
+ - Always place objects within the scene boundaries (0 to 16*parcelsX for X, 0 to 16*parcelsZ for Z)
64
+ - Center of a single-parcel scene is (8, 0, 8) at ground level
65
+ - Y axis is up, minimum Y=0 (ground)
66
+ - The `main` field in scene.json MUST be `"bin/index.js"` — this is the compiled output path
67
+ - The `jsx` and `jsxImportSource` in tsconfig are required for React-ECS UI support
@@ -0,0 +1,106 @@
1
+ ---
2
+ name: deploy-scene
3
+ description: Deploy and publish a Decentraland scene to Genesis City (LAND-based). Use when user wants to deploy, publish, upload, go live, or make their scene accessible on parcels they own.
4
+ ---
5
+
6
+ # Deploying to Genesis City
7
+
8
+ Deploy to specific parcels you own or have permission to deploy to.
9
+
10
+ **Use the `/deploy` command** to deploy. It runs `npx @dcl/sdk-commands deploy` and handles the full process:
11
+ 1. Build the scene
12
+ 2. Upload assets to IPFS
13
+ 3. Deploy to the specified parcels
14
+ 4. Requires a wallet with LAND or deployment permissions
15
+
16
+ > **Deploying to a World instead?** See the `deploy-worlds` skill for Worlds deployment (personal spaces using DCL NAMEs or ENS domains).
17
+
18
+ ## Pre-Deployment Checklist
19
+
20
+ Before deploying, verify:
21
+
22
+ 1. **scene.json is valid**:
23
+ - `ecs7: true` and `runtimeVersion: "7"`
24
+ - Correct `parcels` matching your LAND (for Genesis City)
25
+ - Valid `base` parcel
26
+ - `main: "bin/index.js"`
27
+
28
+ 2. **Code compiles**:
29
+ ```bash
30
+ npx tsc --noEmit
31
+ ```
32
+
33
+ 3. **Scene previews correctly**:
34
+ Use the `preview` tool to verify the scene works (or `npx @dcl/sdk-commands start --bevy-web` manually)
35
+
36
+ 4. **Dependencies installed**:
37
+ ```bash
38
+ npm install
39
+ ```
40
+
41
+ 5. **Assets are within limits** (check parcel count):
42
+ | Parcels | Entities | Triangles | Textures |
43
+ |---------|----------|-----------|----------|
44
+ | 1 | 512 | 10,000 | 10 MB |
45
+ | 2 | 1,024 | 20,000 | 20 MB |
46
+ | 4 | 2,048 | 40,000 | 40 MB |
47
+ | 8+ | Scales linearly | | |
48
+
49
+ ## Deployment Process
50
+
51
+ ### Using CLI
52
+ ```bash
53
+ # Build first
54
+ npx @dcl/sdk-commands build
55
+
56
+ # Deploy (will open browser for wallet connection)
57
+ npx @dcl/sdk-commands deploy
58
+ ```
59
+
60
+ ### Using Creator Hub
61
+ 1. Open Creator Hub
62
+ 2. Select your scene
63
+ 3. Click "Publish"
64
+ 4. Connect wallet
65
+ 5. Confirm transaction
66
+
67
+ ## scene.json for Deployment
68
+
69
+ ```json
70
+ {
71
+ "ecs7": true,
72
+ "runtimeVersion": "7",
73
+ "display": {
74
+ "title": "My Awesome Scene",
75
+ "description": "A description for the marketplace",
76
+ "navmapThumbnail": "images/thumbnail.png"
77
+ },
78
+ "scene": {
79
+ "parcels": ["0,0", "0,1"],
80
+ "base": "0,0"
81
+ },
82
+ "main": "bin/index.js",
83
+ "requiredPermissions": []
84
+ }
85
+ ```
86
+
87
+ ## Permissions
88
+
89
+ Some features require permissions in scene.json:
90
+ ```json
91
+ {
92
+ "requiredPermissions": [
93
+ "ALLOW_TO_MOVE_PLAYER_INSIDE_SCENE",
94
+ "ALLOW_TO_TRIGGER_AVATAR_EMOTE",
95
+ "ALLOW_MEDIA_HOSTNAMES"
96
+ ]
97
+ }
98
+ ```
99
+
100
+ ## Best Practices
101
+
102
+ - Always preview locally before deploying
103
+ - Use a thumbnail image (`navmapThumbnail`) for the Genesis City map
104
+ - Write a clear description for discovery
105
+ - Test with multiple browser tabs to verify multiplayer behavior
106
+ - Keep scene load time under 15 seconds (optimize assets)
@@ -0,0 +1,107 @@
1
+ ---
2
+ name: deploy-worlds
3
+ description: Deploy and publish a Decentraland scene to a World (personal 3D space). Use when user wants to deploy to a World, publish to a World, set up worldConfiguration, use a DCL NAME or ENS domain for deployment, or opt out of Places listing.
4
+ ---
5
+
6
+ # Deploying to Decentraland Worlds
7
+
8
+ Worlds are personal 3D spaces not tied to LAND. They have no parcel limitations and are automatically listed on the Places page.
9
+
10
+ ## Requirements
11
+
12
+ To publish to a World, the user must own either:
13
+ - A **Decentraland NAME** (e.g., `my-name.dcl.eth`)
14
+ - An **ENS domain** (e.g., `my-name.eth`)
15
+
16
+ The wallet signing the deployment must own the NAME, or have been granted permission via Access Control Lists (ACL).
17
+
18
+ ## 1. Configure scene.json
19
+
20
+ Add a `worldConfiguration` section to `scene.json`:
21
+
22
+ ```json
23
+ {
24
+ "worldConfiguration": {
25
+ "name": "my-name.dcl.eth"
26
+ }
27
+ }
28
+ ```
29
+
30
+ The `name` field must match a Decentraland NAME or ENS domain owned by the deploying wallet.
31
+
32
+ ### Opt out of Places listing
33
+
34
+ All Worlds are automatically listed on the [Places page](https://places.decentraland.org). To opt out:
35
+
36
+ ```json
37
+ {
38
+ "worldConfiguration": {
39
+ "name": "my-name.dcl.eth",
40
+ "placesConfig": {
41
+ "optOut": true
42
+ }
43
+ }
44
+ }
45
+ ```
46
+
47
+ ## 2. Deploy
48
+
49
+ **Use the `/deploy` command** — it auto-detects the `worldConfiguration` in scene.json and deploys to the Worlds content server automatically.
50
+
51
+ Alternatively, deploy manually via CLI:
52
+
53
+ ```bash
54
+ npx @dcl/sdk-commands deploy --target-content https://worlds-content-server.decentraland.org
55
+ ```
56
+
57
+ This will prompt the user to sign the deployment with their wallet. Validations run automatically to allow or reject the scene.
58
+
59
+ ### Via Creator Hub
60
+
61
+ 1. Open the scene project in Creator Hub
62
+ 2. Click the **Publish** button (top-right corner)
63
+ 3. Select **PUBLISH TO WORLD**
64
+ 4. Choose which NAME or ENS domain to publish to
65
+
66
+ ## 3. Access the World
67
+
68
+ Once deployed, the World is accessible at:
69
+
70
+ ```
71
+ decentraland://?realm=NAME.dcl.eth
72
+ ```
73
+
74
+ Replace `NAME` with the Decentraland NAME or ENS domain used for deployment.
75
+
76
+ From inside Decentraland, use the chatbox command:
77
+ ```
78
+ /goto NAME.dcl.eth
79
+ ```
80
+
81
+ ## Full scene.json Example
82
+
83
+ ```json
84
+ {
85
+ "ecs7": true,
86
+ "runtimeVersion": "7",
87
+ "display": {
88
+ "title": "My World",
89
+ "description": "A personal 3D space"
90
+ },
91
+ "scene": {
92
+ "parcels": ["0,0"],
93
+ "base": "0,0"
94
+ },
95
+ "main": "bin/index.js",
96
+ "worldConfiguration": {
97
+ "name": "my-name.dcl.eth"
98
+ }
99
+ }
100
+ ```
101
+
102
+ ## Key Differences from Genesis City
103
+
104
+ - **No parcel limitations** — Worlds are not constrained by LAND ownership
105
+ - **NAME/ENS required** — must own a Decentraland NAME or ENS domain instead of LAND
106
+ - **Different deploy target** — uses `--target-content https://worlds-content-server.decentraland.org`
107
+ - **Auto-listed on Places** — unless opted out via `placesConfig.optOut`
@@ -0,0 +1,216 @@
1
+ ---
2
+ name: lighting-environment
3
+ description: Add dynamic lighting and control environment settings in Decentraland scenes. Create point, spot, and directional lights with LightSource, configure shadows, control day/night cycle with SkyboxTime, detect realm info, and use emissive materials for glow effects. Use when user wants lights, shadows, skybox, day-night cycle, or glowing materials.
4
+ ---
5
+
6
+ # Lighting and Environment in Decentraland
7
+
8
+ ## Point Lights
9
+
10
+ Emit light in all directions from a position:
11
+
12
+ ```typescript
13
+ import { engine, Transform, LightSource } from '@dcl/sdk/ecs'
14
+ import { Vector3, Color3 } from '@dcl/sdk/math'
15
+
16
+ const light = engine.addEntity()
17
+ Transform.create(light, { position: Vector3.create(8, 3, 8) })
18
+
19
+ LightSource.create(light, {
20
+ type: LightSource.Type.Point({}),
21
+ color: Color3.White(),
22
+ intensity: 300 // candela
23
+ })
24
+ ```
25
+
26
+ ### Colored Point Light
27
+
28
+ ```typescript
29
+ LightSource.create(light, {
30
+ type: LightSource.Type.Point({}),
31
+ color: Color3.create(1, 0.5, 0), // Warm orange
32
+ intensity: 200,
33
+ range: 15 // Maximum distance in meters
34
+ })
35
+ ```
36
+
37
+ ## Spot Lights
38
+
39
+ Emit a cone of light in a direction:
40
+
41
+ ```typescript
42
+ const spotlight = engine.addEntity()
43
+ Transform.create(spotlight, {
44
+ position: Vector3.create(8, 4, 8),
45
+ rotation: Quaternion.fromEulerDegrees(-90, 0, 0) // Point downward
46
+ })
47
+
48
+ LightSource.create(spotlight, {
49
+ type: LightSource.Type.Spot({ innerAngle: 25, outerAngle: 45 }),
50
+ color: Color3.White(),
51
+ intensity: 800
52
+ })
53
+ ```
54
+
55
+ - `innerAngle` — full-brightness cone angle (degrees)
56
+ - `outerAngle` — outer fade angle (degrees)
57
+ - The light direction follows the entity's forward vector (set via Transform rotation)
58
+
59
+ ## Shadows
60
+
61
+ Enable shadows on point or spot lights:
62
+
63
+ ```typescript
64
+ LightSource.create(spotlight, {
65
+ type: LightSource.Type.Spot({ innerAngle: 25, outerAngle: 45 }),
66
+ shadow: true,
67
+ intensity: 800
68
+ })
69
+ ```
70
+
71
+ ### Shadow Mask Textures (Gobos)
72
+
73
+ Project a pattern through the light:
74
+
75
+ ```typescript
76
+ const maskedLight = LightSource.getMutable(spotlight)
77
+ maskedLight.shadowMaskTexture = Material.Texture.Common({
78
+ src: 'assets/scene/images/lightmask1.png'
79
+ })
80
+ ```
81
+
82
+ ## Toggling Lights
83
+
84
+ ```typescript
85
+ // Toggle on/off
86
+ const lightData = LightSource.getMutable(light)
87
+ lightData.active = !lightData.active
88
+ ```
89
+
90
+ ## Light Limits
91
+
92
+ - Maximum **one active light per parcel** (16m x 16m)
93
+ - The renderer auto-culls lights based on quality settings and proximity
94
+ - Up to ~3 shadowed lights visible at once
95
+ - Intensity is in candela — visible distance grows roughly with `sqrt(intensity)`
96
+
97
+ ## SkyboxTime (Day/Night Cycle)
98
+
99
+ ### Fixed Time in scene.json
100
+
101
+ Set a permanent time of day without code:
102
+
103
+ ```json
104
+ {
105
+ "skyboxConfig": {
106
+ "fixedTime": 36000
107
+ }
108
+ }
109
+ ```
110
+
111
+ Time values: 0 = midnight, 36000 = noon, 54000 = dusk, 72000 = midnight again.
112
+
113
+ ### Read Current World Time
114
+
115
+ ```typescript
116
+ import { getWorldTime } from '~system/Runtime'
117
+
118
+ executeTask(async () => {
119
+ const time = await getWorldTime({})
120
+ console.log('Seconds since midnight:', time.seconds)
121
+ })
122
+ ```
123
+
124
+ ### Change Time Dynamically
125
+
126
+ ```typescript
127
+ import { SkyboxTime, TransitionMode } from '~system/Runtime'
128
+
129
+ // Set time of day (must target root entity)
130
+ SkyboxTime.create(engine.RootEntity, { fixed_time: 36000 }) // Noon
131
+
132
+ // Change with transition direction
133
+ SkyboxTime.createOrReplace(engine.RootEntity, {
134
+ fixed_time: 54000, // Dusk
135
+ direction: TransitionMode.TM_BACKWARD
136
+ })
137
+ ```
138
+
139
+ ### Day/Night Cycle System
140
+
141
+ ```typescript
142
+ let currentTime = 36000
143
+ const CYCLE_SPEED = 100 // Time units per second
144
+
145
+ function dayNightCycle(dt: number) {
146
+ currentTime = (currentTime + CYCLE_SPEED * dt) % 72000
147
+ SkyboxTime.createOrReplace(engine.RootEntity, {
148
+ fixed_time: currentTime
149
+ })
150
+ }
151
+
152
+ engine.addSystem(dayNightCycle)
153
+ ```
154
+
155
+ ## Realm Info
156
+
157
+ Detect which realm (server) the player is connected to:
158
+
159
+ ```typescript
160
+ import { getRealm } from '~system/Runtime'
161
+
162
+ executeTask(async () => {
163
+ const realm = await getRealm({})
164
+ console.log('Realm:', realm.realmInfo?.realmName)
165
+ console.log('Network:', realm.realmInfo?.networkId)
166
+ console.log('Base URL:', realm.realmInfo?.baseUrl)
167
+ })
168
+ ```
169
+
170
+ ## Emissive Materials (Glow Effects)
171
+
172
+ For a visual glow without casting light on surroundings:
173
+
174
+ ```typescript
175
+ import { engine, Material } from '@dcl/sdk/ecs'
176
+ import { Color4, Color3 } from '@dcl/sdk/math'
177
+
178
+ // Self-illuminated material
179
+ Material.setPbrMaterial(entity, {
180
+ albedoColor: Color4.create(0, 0, 0, 1),
181
+ emissiveColor: Color4.create(0, 1, 0, 1), // Green glow
182
+ emissiveIntensity: 2.0
183
+ })
184
+ ```
185
+
186
+ ### Combining Emissive + LightSource
187
+
188
+ For an object that both glows visually and casts light:
189
+
190
+ ```typescript
191
+ // Visual glow on the mesh
192
+ Material.setPbrMaterial(bulb, {
193
+ emissiveColor: Color4.create(1, 0.9, 0.7, 1),
194
+ emissiveIntensity: 1.5
195
+ })
196
+
197
+ // Actual light emission
198
+ LightSource.create(bulb, {
199
+ type: LightSource.Type.Point({}),
200
+ color: Color3.create(1, 0.9, 0.7),
201
+ intensity: 200,
202
+ range: 10
203
+ })
204
+ ```
205
+
206
+ ## Best Practices
207
+
208
+ - Stay within the **one light per parcel** budget — plan light placement around scene parcels
209
+ - Use emissive materials for decorative glow that doesn't need to illuminate surroundings
210
+ - Combine emissive materials with LightSource for realistic light fixtures (lamp = emissive mesh + point light)
211
+ - Use spot lights with shadows for dramatic effects (stage lighting, flashlights)
212
+ - Keep shadow count low (max ~3 visible) — disable `shadow` on lights that don't need it
213
+ - Set `range` on lights to limit their influence and save performance
214
+ - Use `SkyboxTime` for atmosphere — nighttime scenes with point lights create dramatic environments
215
+
216
+ For component field details, see `context/components-reference.md`.