@dcl-regenesislabs/opendcl 0.1.0-22239132687.commit-eccf1dd → 0.1.0-22312642473.commit-ea3ce8c
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 +3 -2
- package/context/asset-packs-catalog.md +2854 -0
- package/dist/compact-tool-renderers.d.ts +34 -0
- package/dist/compact-tool-renderers.d.ts.map +1 -0
- package/dist/compact-tool-renderers.js +102 -0
- package/dist/compact-tool-renderers.js.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -1
- package/extensions/dcl-init.ts +3 -3
- package/package.json +2 -2
- package/prompts/system.md +16 -14
- package/skills/add-3d-models/SKILL.md +32 -8
- package/skills/add-interactivity/SKILL.md +32 -12
- package/skills/advanced-rendering/SKILL.md +10 -19
- package/skills/audio-video/SKILL.md +52 -8
- package/skills/build-ui/SKILL.md +76 -70
- package/skills/camera-control/SKILL.md +20 -9
- package/skills/create-scene/SKILL.md +21 -7
- package/skills/lighting-environment/SKILL.md +5 -3
- package/skills/multiplayer-sync/SKILL.md +15 -8
- package/skills/player-avatar/SKILL.md +27 -6
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compact tool output renderers for built-in tools (write, read).
|
|
3
|
+
*
|
|
4
|
+
* Pi-coding-agent's built-in renderer shows verbose output: write shows 10 lines
|
|
5
|
+
* of file content, read shows 10 lines of preview. This module provides compact
|
|
6
|
+
* alternatives that reduce terminal noise when the agent writes/reads many files.
|
|
7
|
+
*
|
|
8
|
+
* These are wired in via a monkey-patch on InteractiveMode.getRegisteredToolDefinition
|
|
9
|
+
* in src/index.ts — they provide renderCall/renderResult without replacing execution logic.
|
|
10
|
+
*/
|
|
11
|
+
import { Text } from "@mariozechner/pi-tui";
|
|
12
|
+
import type { Theme } from "@mariozechner/pi-coding-agent";
|
|
13
|
+
/** Partial tool definition — only the fields ToolExecutionComponent checks */
|
|
14
|
+
interface CompactToolDef {
|
|
15
|
+
name: string;
|
|
16
|
+
renderCall?: (args: Record<string, unknown>, theme: Theme) => Text;
|
|
17
|
+
renderResult?: (result: {
|
|
18
|
+
content: Array<{
|
|
19
|
+
type: string;
|
|
20
|
+
text?: string;
|
|
21
|
+
}>;
|
|
22
|
+
details?: unknown;
|
|
23
|
+
}, options: {
|
|
24
|
+
expanded: boolean;
|
|
25
|
+
isPartial: boolean;
|
|
26
|
+
}, theme: Theme) => Text;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Returns a partial tool definition with compact renderCall/renderResult
|
|
30
|
+
* for supported built-in tools, or undefined for tools we don't override.
|
|
31
|
+
*/
|
|
32
|
+
export declare function getCompactToolDefinition(toolName: string): CompactToolDef | undefined;
|
|
33
|
+
export {};
|
|
34
|
+
//# sourceMappingURL=compact-tool-renderers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compact-tool-renderers.d.ts","sourceRoot":"","sources":["../src/compact-tool-renderers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAC5C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,+BAA+B,CAAC;AAiB3D,8EAA8E;AAC9E,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACnE,YAAY,CAAC,EAAE,CACb,MAAM,EAAE;QAAE,OAAO,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,EAC9E,OAAO,EAAE;QAAE,QAAQ,EAAE,OAAO,CAAC;QAAC,SAAS,EAAE,OAAO,CAAA;KAAE,EAClD,KAAK,EAAE,KAAK,KACT,IAAI,CAAC;CACX;AA0FD;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAErF"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compact tool output renderers for built-in tools (write, read).
|
|
3
|
+
*
|
|
4
|
+
* Pi-coding-agent's built-in renderer shows verbose output: write shows 10 lines
|
|
5
|
+
* of file content, read shows 10 lines of preview. This module provides compact
|
|
6
|
+
* alternatives that reduce terminal noise when the agent writes/reads many files.
|
|
7
|
+
*
|
|
8
|
+
* These are wired in via a monkey-patch on InteractiveMode.getRegisteredToolDefinition
|
|
9
|
+
* in src/index.ts — they provide renderCall/renderResult without replacing execution logic.
|
|
10
|
+
*/
|
|
11
|
+
import { Text } from "@mariozechner/pi-tui";
|
|
12
|
+
import { homedir } from "node:os";
|
|
13
|
+
/** Shorten absolute paths to tilde notation (mirrors pi's internal shortenPath) */
|
|
14
|
+
function shortenPath(path) {
|
|
15
|
+
const home = homedir();
|
|
16
|
+
if (path.startsWith(home)) {
|
|
17
|
+
return `~${path.slice(home.length)}`;
|
|
18
|
+
}
|
|
19
|
+
return path;
|
|
20
|
+
}
|
|
21
|
+
/** Replace tabs with spaces for consistent rendering */
|
|
22
|
+
function replaceTabs(text) {
|
|
23
|
+
return text.replace(/\t/g, " ");
|
|
24
|
+
}
|
|
25
|
+
const READ_PREVIEW_LINES = 5;
|
|
26
|
+
const writeRenderer = {
|
|
27
|
+
name: "write",
|
|
28
|
+
renderCall(args, theme) {
|
|
29
|
+
const rawPath = typeof args.path === "string" ? args.path : null;
|
|
30
|
+
const content = typeof args.content === "string" ? args.content : null;
|
|
31
|
+
const path = rawPath !== null ? shortenPath(rawPath) : null;
|
|
32
|
+
const invalidArg = theme.fg("error", "[invalid arg]");
|
|
33
|
+
let text = theme.fg("toolTitle", theme.bold("write")) +
|
|
34
|
+
" " +
|
|
35
|
+
(path === null ? invalidArg : path ? theme.fg("accent", path) : theme.fg("toolOutput", "..."));
|
|
36
|
+
if (content !== null) {
|
|
37
|
+
const lines = content.split("\n").length;
|
|
38
|
+
const chars = content.length;
|
|
39
|
+
text += theme.fg("muted", ` (${chars} chars, ${lines} lines)`);
|
|
40
|
+
}
|
|
41
|
+
return new Text(text, 0, 0);
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
const readRenderer = {
|
|
45
|
+
name: "read",
|
|
46
|
+
renderCall(args, theme) {
|
|
47
|
+
const rawPath = typeof args.path === "string" ? args.path : null;
|
|
48
|
+
const path = rawPath !== null ? shortenPath(rawPath) : null;
|
|
49
|
+
const offset = args.offset;
|
|
50
|
+
const limit = args.limit;
|
|
51
|
+
const invalidArg = theme.fg("error", "[invalid arg]");
|
|
52
|
+
let pathDisplay = path === null ? invalidArg : path ? theme.fg("accent", path) : theme.fg("toolOutput", "...");
|
|
53
|
+
if (offset !== undefined || limit !== undefined) {
|
|
54
|
+
const startLine = offset ?? 1;
|
|
55
|
+
const endLine = limit !== undefined ? startLine + limit - 1 : "";
|
|
56
|
+
pathDisplay += theme.fg("warning", `:${startLine}${endLine ? `-${endLine}` : ""}`);
|
|
57
|
+
}
|
|
58
|
+
return new Text(theme.fg("toolTitle", theme.bold("read")) + " " + pathDisplay, 0, 0);
|
|
59
|
+
},
|
|
60
|
+
renderResult(result, { expanded }, theme) {
|
|
61
|
+
const textBlocks = result.content?.filter((c) => c.type === "text") || [];
|
|
62
|
+
const output = textBlocks.map((c) => c.text || "").join("\n");
|
|
63
|
+
if (!output)
|
|
64
|
+
return new Text("", 0, 0);
|
|
65
|
+
const lines = output.split("\n");
|
|
66
|
+
const maxLines = expanded ? lines.length : READ_PREVIEW_LINES;
|
|
67
|
+
const displayLines = lines.slice(0, maxLines);
|
|
68
|
+
const remaining = lines.length - maxLines;
|
|
69
|
+
let text = displayLines.map((line) => theme.fg("toolOutput", replaceTabs(line))).join("\n");
|
|
70
|
+
if (remaining > 0) {
|
|
71
|
+
text += theme.fg("muted", `\n... (${remaining} more lines, ctrl+o to expand)`);
|
|
72
|
+
}
|
|
73
|
+
const details = result.details;
|
|
74
|
+
const truncation = details?.truncation;
|
|
75
|
+
if (truncation?.truncated) {
|
|
76
|
+
if (truncation.firstLineExceedsLimit) {
|
|
77
|
+
text += "\n" + theme.fg("warning", "[First line exceeds size limit]");
|
|
78
|
+
}
|
|
79
|
+
else if (truncation.truncatedBy === "lines") {
|
|
80
|
+
text +=
|
|
81
|
+
"\n" +
|
|
82
|
+
theme.fg("warning", `[Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines]`);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
text += "\n" + theme.fg("warning", `[Truncated: ${truncation.outputLines} lines shown]`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return new Text(text, 0, 0);
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
const renderers = new Map([
|
|
92
|
+
["write", writeRenderer],
|
|
93
|
+
["read", readRenderer],
|
|
94
|
+
]);
|
|
95
|
+
/**
|
|
96
|
+
* Returns a partial tool definition with compact renderCall/renderResult
|
|
97
|
+
* for supported built-in tools, or undefined for tools we don't override.
|
|
98
|
+
*/
|
|
99
|
+
export function getCompactToolDefinition(toolName) {
|
|
100
|
+
return renderers.get(toolName);
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=compact-tool-renderers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compact-tool-renderers.js","sourceRoot":"","sources":["../src/compact-tool-renderers.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { main, InteractiveMode } from "@mariozechner/pi-coding-agent";
|
|
8
8
|
import { isDev } from "./utils.js";
|
|
9
|
+
import { getCompactToolDefinition } from "./compact-tool-renderers.js";
|
|
9
10
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
10
11
|
import { homedir } from "node:os";
|
|
11
12
|
import { fileURLToPath } from "node:url";
|
|
@@ -70,6 +71,17 @@ InteractiveMode.prototype.showWarning = function (msg) {
|
|
|
70
71
|
return;
|
|
71
72
|
_showWarning.call(this, msg);
|
|
72
73
|
};
|
|
74
|
+
// Compact tool output — override built-in write/read renderers to reduce terminal noise.
|
|
75
|
+
// When a built-in tool has no custom renderCall/renderResult, pi shows verbose output.
|
|
76
|
+
// By returning compact renderers from getRegisteredToolDefinition, the ToolExecutionComponent
|
|
77
|
+
// uses them instead (see shouldUseBuiltInRenderer() in tool-execution.js).
|
|
78
|
+
const _getToolDef = InteractiveMode.prototype.getRegisteredToolDefinition;
|
|
79
|
+
InteractiveMode.prototype.getRegisteredToolDefinition = function (toolName) {
|
|
80
|
+
const original = _getToolDef.call(this, toolName);
|
|
81
|
+
if (original)
|
|
82
|
+
return original;
|
|
83
|
+
return getCompactToolDefinition(toolName);
|
|
84
|
+
};
|
|
73
85
|
main(args).catch((err) => {
|
|
74
86
|
console.error("OpenDCL fatal error:", err);
|
|
75
87
|
process.exit(1);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;GAIG;AAEH,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AACtC,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAEzC,uFAAuF;AACvF,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;AACtD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,CAAC;IACrC,OAAO,CAAC,GAAG,CAAC,mBAAmB,GAAG,QAAQ,CAAC;AAC7C,CAAC;AAED,wEAAwE;AACxE,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;AACrD,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;IAC9B,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,aAAa,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,iBAAiB,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;AAC3F,CAAC;AAED,yCAAyC;AACzC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAEnC,iFAAiF;AACjF,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC;IACtC,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,UAAU,EAAE,mBAAmB,CAAC,EAAE,OAAO,CAAC,CAAC;IACzE,MAAM,YAAY,GAAG,GAAG,CAAC,OAAO,CAAC,uBAAuB,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACrE,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,YAAY,CAAC,CAAC;AAC7C,CAAC;AAED,sBAAsB;AACtB,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;AAC9C,MAAM,UAAU,GAAG;IACjB,gBAAgB;IAChB,gBAAgB;IAChB,aAAa;IACb,eAAe;IACf,cAAc;IACd,qBAAqB;IACrB,iBAAiB;IACjB,eAAe;IACf,qBAAqB;IACrB,eAAe;IACf,cAAc;CACf,CAAC;AACF,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;IAC7B,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;AACrC,CAAC;AACD,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC,CAAC;AACpD,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC,CAAC;AAEtD,6BAA6B;AAC7B,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC;AAEjD,yFAAyF;AACzF,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,IAAI,CAAC,UAAU,EAAE,mBAAmB,CAAC,CAAC,CAAC;AACtE,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,IAAI,CAAC,UAAU,EAAE,oBAAoB,CAAC,CAAC,CAAC;AAEvE,gFAAgF;AAChF,mEAAmE;AACnE,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;IACb,OAAO,CAAC,GAAG,CAAC,qBAAqB,GAAG,GAAG,CAAC;AAC1C,CAAC;AAED,6EAA6E;AAC7E,sEAAsE;AACtE,MAAM,YAAY,GAAG,eAAe,CAAC,SAAS,CAAC,WAAW,CAAC;AAC3D,eAAe,CAAC,SAAS,CAAC,WAAW,GAAG,UAAU,GAAW;IAC3D,IAAI,GAAG,CAAC,UAAU,CAAC,qBAAqB,CAAC;QAAE,OAAO;IAClD,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC/B,CAAC,CAAC;AAEF,yFAAyF;AACzF,uFAAuF;AACvF,8FAA8F;AAC9F,2EAA2E;AAC3E,MAAM,WAAW,GAAI,eAAe,CAAC,SAAiB,CAAC,2BAA2B,CAAC;AAClF,eAAe,CAAC,SAAiB,CAAC,2BAA2B,GAAG,UAAU,QAAgB;IACzF,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAClD,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,OAAO,wBAAwB,CAAC,QAAQ,CAAC,CAAC;AAC5C,CAAC,CAAC;AAEF,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACvB,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,GAAG,CAAC,CAAC;IAC3C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
package/extensions/dcl-init.ts
CHANGED
|
@@ -19,13 +19,13 @@ async function initScene(
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
try {
|
|
22
|
-
const result = await pi.exec("npx", ["@dcl/sdk-commands", "init"
|
|
22
|
+
const result = await pi.exec("npx", ["@dcl/sdk-commands", "init"], {
|
|
23
23
|
cwd,
|
|
24
|
-
timeout:
|
|
24
|
+
timeout: 180000,
|
|
25
25
|
});
|
|
26
26
|
|
|
27
27
|
if (result.code === 0) {
|
|
28
|
-
return { message: "Scene initialized
|
|
28
|
+
return { message: "Scene initialized and dependencies installed! Use the preview tool to start." };
|
|
29
29
|
} else {
|
|
30
30
|
return { message: `Init failed (exit code ${result.code}): ${result.stderr || result.stdout}`, isError: true };
|
|
31
31
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dcl-regenesislabs/opendcl",
|
|
3
|
-
"version": "0.1.0-
|
|
3
|
+
"version": "0.1.0-22312642473.commit-ea3ce8c",
|
|
4
4
|
"description": "AI coding assistant for Decentraland SDK7 scene development",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -61,5 +61,5 @@
|
|
|
61
61
|
"prompts/",
|
|
62
62
|
"context/"
|
|
63
63
|
],
|
|
64
|
-
"commit": "
|
|
64
|
+
"commit": "ea3ce8ca6234b519b29fc8e807ce51402ff3033f"
|
|
65
65
|
}
|
package/prompts/system.md
CHANGED
|
@@ -16,7 +16,7 @@ You are **OpenDCL**, an AI coding assistant specialized in Decentraland SDK7 sce
|
|
|
16
16
|
### Architecture
|
|
17
17
|
- **Entity-Component System (ECS)**: Scenes are built with entities (IDs), components (data), and systems (logic).
|
|
18
18
|
- **Runtime**: Sandboxed QuickJS — **no** Node.js APIs (`fs`, `http`, `path`, `process` are unavailable).
|
|
19
|
-
- **Imports**: Use `@dcl/sdk/ecs`, `@dcl/sdk/math`, `@dcl/sdk/react-ecs`
|
|
19
|
+
- **Imports**: Use `@dcl/sdk/ecs`, `@dcl/sdk/math`, `@dcl/sdk/react-ecs` for most APIs. Use `~system/RestrictedActions` for player actions (emotes, teleport, external URLs) and `~system/Runtime` for world time, realm info, and scene info.
|
|
20
20
|
- **Entry point**: `export function main() {}` in `src/index.ts` — the engine calls this on scene load.
|
|
21
21
|
|
|
22
22
|
### Scene Constraints
|
|
@@ -56,18 +56,16 @@ engine.addSystem((dt: number) => {
|
|
|
56
56
|
|
|
57
57
|
**UI with React-ECS:**
|
|
58
58
|
```tsx
|
|
59
|
-
import ReactEcs, { UiEntity, Label, Button } from '@dcl/sdk/react-ecs'
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
<
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
)
|
|
67
|
-
}
|
|
59
|
+
import ReactEcs, { ReactEcsRenderer, UiEntity, Label, Button } from '@dcl/sdk/react-ecs'
|
|
60
|
+
|
|
61
|
+
const MyUI = () => (
|
|
62
|
+
<UiEntity uiTransform={{ width: 200, height: 50, positionType: 'absolute' }}>
|
|
63
|
+
<Label value="Hello" fontSize={18} />
|
|
64
|
+
</UiEntity>
|
|
65
|
+
)
|
|
68
66
|
|
|
69
67
|
export function setupUi() {
|
|
70
|
-
|
|
68
|
+
ReactEcsRenderer.setUiRenderer(MyUI)
|
|
71
69
|
}
|
|
72
70
|
```
|
|
73
71
|
|
|
@@ -97,9 +95,9 @@ scene-project/
|
|
|
97
95
|
|
|
98
96
|
### Empty Folder (No scene.json)
|
|
99
97
|
1. Ask the user what they want to build.
|
|
100
|
-
2. **Use the `init` tool first** — this uses the official SDK scaffolding to create scene.json, package.json, tsconfig.json, and src/index.ts with the correct, up-to-date configuration. Never create these files manually.
|
|
98
|
+
2. **Use the `init` tool first** — this uses the official SDK scaffolding to create scene.json, package.json, tsconfig.json, and src/index.ts with the correct, up-to-date configuration, and installs dependencies. Never create these files manually.
|
|
101
99
|
3. After init completes, customize `scene.json` (title, description, parcels) and `src/index.ts` (scene code) based on what the user wants.
|
|
102
|
-
4.
|
|
100
|
+
4. Use the `preview` tool to start the preview server.
|
|
103
101
|
|
|
104
102
|
### Existing Scene
|
|
105
103
|
1. Read scene.json and src/index.ts to understand the project.
|
|
@@ -110,9 +108,13 @@ scene-project/
|
|
|
110
108
|
- Always position objects within the scene boundaries (based on parcels).
|
|
111
109
|
- Use `Vector3.create()` and `Quaternion.fromEulerDegrees()` for transforms.
|
|
112
110
|
- For 3D models, use `GltfContainer.create(entity, { src: 'models/myModel.glb' })`.
|
|
111
|
+
- `GltfContainer` only works with **local files** — never use external URLs for the `src` field. Always download models into the scene's `models/` directory first.
|
|
113
112
|
- Place `.glb` files in a `models/` directory, textures in `images/`.
|
|
114
113
|
- After writing TypeScript, use the `preview` tool to start the preview server.
|
|
115
|
-
-
|
|
114
|
+
- **Proactively suggest 3D assets**: When building a scene, always check both asset catalogs for free models that match the user's theme:
|
|
115
|
+
- `context/open-source-3d-assets.md` — 991 CC0 models from Polygonal Mind (nature, medieval, cyberpunk, sci-fi, etc.)
|
|
116
|
+
- `context/asset-packs-catalog.md` — 2,700+ models from the official Decentraland Creator Hub (furniture, structures, decorations, etc.)
|
|
117
|
+
- Download matching models with `curl -o models/filename.glb "URL"` before referencing them in code.
|
|
116
118
|
|
|
117
119
|
## Tools & Commands
|
|
118
120
|
|
|
@@ -93,16 +93,40 @@ GltfContainer.create(child, { src: 'models/hat.glb' })
|
|
|
93
93
|
|
|
94
94
|
## Free 3D Models
|
|
95
95
|
|
|
96
|
-
|
|
97
|
-
`context/open-source-3d-assets.md` (in the opendcl repo root). If unavailable locally, fetch from:
|
|
98
|
-
https://raw.githubusercontent.com/dcl-regenesislabs/opendcl/main/context/open-source-3d-assets.md
|
|
96
|
+
Always check both asset catalogs before suggesting the user create or find their own models.
|
|
99
97
|
|
|
100
|
-
|
|
98
|
+
### Creator Hub Asset Packs (2,700+ models)
|
|
101
99
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
100
|
+
Read `context/asset-packs-catalog.md` for official Decentraland models across 12 themed packs (Cyberpunk, Fantasy, Gallery, Sci-fi, Western, Pirates, etc.) with furniture, structures, decorations, nature, and more.
|
|
101
|
+
|
|
102
|
+
To use a Creator Hub model:
|
|
103
|
+
```bash
|
|
104
|
+
# Download from catalog
|
|
105
|
+
mkdir -p models
|
|
106
|
+
curl -o models/arcade_machine.glb "https://builder-items.decentraland.org/contents/bafybei..."
|
|
107
|
+
```
|
|
108
|
+
```typescript
|
|
109
|
+
// Reference in code — must be a local file path
|
|
110
|
+
GltfContainer.create(entity, { src: 'models/arcade_machine.glb' })
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Open Source CC0 Models (991 models)
|
|
114
|
+
|
|
115
|
+
Read `context/open-source-3d-assets.md` for free CC0-licensed models from Polygonal Mind, organized by 18 themed collections (MomusPark, Medieval Fair, Cyberpunk, Sci-fi, etc.) with direct GitHub download URLs.
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
curl -o models/tree.glb "https://raw.githubusercontent.com/ToxSam/cc0-models-Polygonal-Mind/main/projects/momuspark/Tree_01_Art.glb"
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### How to suggest models
|
|
122
|
+
|
|
123
|
+
1. Read both catalog files
|
|
124
|
+
2. Search for models matching the user's description/theme
|
|
125
|
+
3. Suggest specific models with download commands
|
|
126
|
+
4. Download selected models into the scene's `models/` directory
|
|
127
|
+
5. Reference them in code with local paths
|
|
128
|
+
|
|
129
|
+
> **Important**: `GltfContainer` only works with **local files**. Never use external URLs for the model `src` field. Always download models into `models/` first.
|
|
106
130
|
|
|
107
131
|
## Model Best Practices
|
|
108
132
|
|
|
@@ -79,26 +79,46 @@ GltfContainer.create(entity, {
|
|
|
79
79
|
|
|
80
80
|
## Trigger Areas (Proximity Detection)
|
|
81
81
|
|
|
82
|
-
Detect when the player enters or
|
|
82
|
+
Detect when the player enters, exits, or stays inside an area:
|
|
83
83
|
|
|
84
84
|
```typescript
|
|
85
|
-
import { engine, Transform, TriggerArea
|
|
85
|
+
import { engine, Transform, TriggerArea } from '@dcl/sdk/ecs'
|
|
86
|
+
import { triggerAreaEventsSystem } from '@dcl/sdk/ecs'
|
|
86
87
|
import { Vector3 } from '@dcl/sdk/math'
|
|
87
88
|
|
|
88
|
-
const
|
|
89
|
-
|
|
89
|
+
const area = engine.addEntity()
|
|
90
|
+
TriggerArea.setBox(area) // or TriggerArea.setSphere(area)
|
|
91
|
+
Transform.create(area, {
|
|
92
|
+
position: Vector3.create(8, 0, 8),
|
|
93
|
+
scale: Vector3.create(4, 4, 4) // Size the area via Transform.scale
|
|
94
|
+
})
|
|
90
95
|
|
|
91
|
-
|
|
92
|
-
|
|
96
|
+
// Register enter/exit/stay events
|
|
97
|
+
triggerAreaEventsSystem.onTriggerEnter(area, (event) => {
|
|
98
|
+
console.log('Entity entered trigger:', event.trigger.entity)
|
|
93
99
|
})
|
|
94
100
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
const result = TriggerAreaResult.getOrNull(trigger)
|
|
98
|
-
if (result && result.isTriggered) {
|
|
99
|
-
// Player is inside the trigger area
|
|
100
|
-
}
|
|
101
|
+
triggerAreaEventsSystem.onTriggerExit(area, () => {
|
|
102
|
+
console.log('Entity exited trigger')
|
|
101
103
|
})
|
|
104
|
+
|
|
105
|
+
triggerAreaEventsSystem.onTriggerStay(area, () => {
|
|
106
|
+
// Called every frame while an entity is inside
|
|
107
|
+
})
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
By default, trigger areas react to the player layer. Use `ColliderLayer` to restrict which entities activate the area:
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
import { ColliderLayer, MeshCollider } from '@dcl/sdk/ecs'
|
|
114
|
+
|
|
115
|
+
// Area that only reacts to custom layers
|
|
116
|
+
TriggerArea.setBox(area, ColliderLayer.CL_CUSTOM1 | ColliderLayer.CL_CUSTOM2)
|
|
117
|
+
|
|
118
|
+
// Mark a moving entity to activate the area
|
|
119
|
+
const mover = engine.addEntity()
|
|
120
|
+
Transform.create(mover, { position: Vector3.create(8, 0, 8) })
|
|
121
|
+
MeshCollider.setBox(mover, ColliderLayer.CL_CUSTOM1)
|
|
102
122
|
```
|
|
103
123
|
|
|
104
124
|
## Raycasting
|
|
@@ -137,10 +137,10 @@ Material.setPbrMaterial(entity, {
|
|
|
137
137
|
### Emissive (Glow Effects)
|
|
138
138
|
|
|
139
139
|
```typescript
|
|
140
|
-
// Glowing material
|
|
140
|
+
// Glowing material (emissiveColor uses Color3, not Color4)
|
|
141
141
|
Material.setPbrMaterial(entity, {
|
|
142
142
|
albedoColor: Color4.create(0, 0, 0, 1),
|
|
143
|
-
emissiveColor:
|
|
143
|
+
emissiveColor: Color3.create(0, 1, 0), // Green glow
|
|
144
144
|
emissiveIntensity: 2.0
|
|
145
145
|
})
|
|
146
146
|
|
|
@@ -163,33 +163,24 @@ Material.setPbrMaterial(entity, {
|
|
|
163
163
|
})
|
|
164
164
|
```
|
|
165
165
|
|
|
166
|
-
##
|
|
166
|
+
## GltfContainer Visibility Masks
|
|
167
167
|
|
|
168
|
-
|
|
168
|
+
Control visibility and collision of specific mesh layers within a GLTF model using collision masks:
|
|
169
169
|
|
|
170
170
|
```typescript
|
|
171
|
-
import { engine, Transform, GltfContainer,
|
|
172
|
-
import { Vector3
|
|
171
|
+
import { engine, Transform, GltfContainer, ColliderLayer } from '@dcl/sdk/ecs'
|
|
172
|
+
import { Vector3 } from '@dcl/sdk/math'
|
|
173
173
|
|
|
174
174
|
const model = engine.addEntity()
|
|
175
|
-
GltfContainer.create(model, { src: 'models/myModel.glb' })
|
|
176
175
|
Transform.create(model, { position: Vector3.create(4, 0, 4) })
|
|
177
176
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
path: '', // empty string = all nodes
|
|
183
|
-
materialOverride: Material.setPbrMaterial(model, {
|
|
184
|
-
albedoColor: Color4.Red()
|
|
185
|
-
})
|
|
186
|
-
}
|
|
187
|
-
]
|
|
177
|
+
GltfContainer.create(model, {
|
|
178
|
+
src: 'models/myModel.glb',
|
|
179
|
+
visibleMeshesCollisionMask: ColliderLayer.CL_PHYSICS | ColliderLayer.CL_POINTER,
|
|
180
|
+
invisibleMeshesCollisionMask: ColliderLayer.CL_PHYSICS
|
|
188
181
|
})
|
|
189
182
|
```
|
|
190
183
|
|
|
191
|
-
Use node paths to target specific parts of a model for visibility or material changes.
|
|
192
|
-
|
|
193
184
|
## VisibilityComponent
|
|
194
185
|
|
|
195
186
|
Show or hide entities without removing them:
|
|
@@ -122,16 +122,16 @@ VideoPlayer.create(screen, {
|
|
|
122
122
|
playing: true,
|
|
123
123
|
loop: true,
|
|
124
124
|
volume: 0.5,
|
|
125
|
-
playbackRate: 1.0
|
|
125
|
+
playbackRate: 1.0,
|
|
126
|
+
position: 0 // Start time in seconds
|
|
126
127
|
})
|
|
127
128
|
|
|
128
|
-
//
|
|
129
|
-
Material.
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
emissiveTexture: Material.Texture.Video({ videoPlayerEntity: screen })
|
|
129
|
+
// Create video texture
|
|
130
|
+
const videoTexture = Material.Texture.Video({ videoPlayerEntity: screen })
|
|
131
|
+
|
|
132
|
+
// Basic material (recommended — better performance)
|
|
133
|
+
Material.setBasicMaterial(screen, {
|
|
134
|
+
texture: videoTexture
|
|
135
135
|
})
|
|
136
136
|
```
|
|
137
137
|
|
|
@@ -150,6 +150,50 @@ VideoPlayer.getMutable(screen).volume = 0.8
|
|
|
150
150
|
VideoPlayer.getMutable(screen).src = 'https://example.com/other.mp4'
|
|
151
151
|
```
|
|
152
152
|
|
|
153
|
+
### Enhanced Video Material (PBR)
|
|
154
|
+
|
|
155
|
+
For a brighter, emissive video screen:
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
import { Color3 } from '@dcl/sdk/math'
|
|
159
|
+
|
|
160
|
+
const videoTexture = Material.Texture.Video({ videoPlayerEntity: screen })
|
|
161
|
+
Material.setPbrMaterial(screen, {
|
|
162
|
+
texture: videoTexture,
|
|
163
|
+
roughness: 1.0,
|
|
164
|
+
specularIntensity: 0,
|
|
165
|
+
metallic: 0,
|
|
166
|
+
emissiveTexture: videoTexture,
|
|
167
|
+
emissiveIntensity: 0.6,
|
|
168
|
+
emissiveColor: Color3.White()
|
|
169
|
+
})
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Video Events
|
|
173
|
+
|
|
174
|
+
Monitor video playback state:
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
import { videoEventsSystem, VideoState } from '@dcl/sdk/ecs'
|
|
178
|
+
|
|
179
|
+
videoEventsSystem.registerVideoEventsEntity(screen, (videoEvent) => {
|
|
180
|
+
switch (videoEvent.state) {
|
|
181
|
+
case VideoState.VS_PLAYING:
|
|
182
|
+
console.log('Video started playing')
|
|
183
|
+
break
|
|
184
|
+
case VideoState.VS_PAUSED:
|
|
185
|
+
console.log('Video paused')
|
|
186
|
+
break
|
|
187
|
+
case VideoState.VS_READY:
|
|
188
|
+
console.log('Video ready to play')
|
|
189
|
+
break
|
|
190
|
+
case VideoState.VS_ERROR:
|
|
191
|
+
console.log('Video error occurred')
|
|
192
|
+
break
|
|
193
|
+
}
|
|
194
|
+
})
|
|
195
|
+
```
|
|
196
|
+
|
|
153
197
|
## Spatial Audio
|
|
154
198
|
|
|
155
199
|
Audio in Decentraland is **spatial by default** — it gets louder as the player approaches the audio source entity and quieter as they move away. The position is determined by the entity's `Transform`.
|