> For the complete documentation index, see [llms.txt](https://docs.decentraland.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.decentraland.org/creator/content-creator-pt/scenes-sdk7/comecar/coding-scenes.md).

# Essenciais de codificação

## As ferramentas de desenvolvimento

A um nível muito alto, o Decentraland **Software Development Kit** (SDK) permite fazer o seguinte:

* Gerar um *projeto* padrão contendo uma scene do Decentraland, incluindo todos os assets necessários para renderizar e executar o teu conteúdo.
* Construir, testar e pré-visualizar o conteúdo da tua scene localmente no teu navegador web — completamente offline, e sem ter de fazer quaisquer transações Ethereum ou possuir LAND.
* Escrever código TypeScript usando a API do Decentraland para adicionar comportamento interativo e dinâmico à scene.
* Fazer upload do conteúdo da tua scene para o content server.
* Associar os teus tokens LAND ao URL do conteúdo que carregaste.

O nosso SDK inclui o seguinte:

* **O Creator Hub**: Uma aplicação autónoma que, entre outras coisas, te permite criar scenes com uma interface fácil de drag-and-drop. Podes executar previews, debug, editar código e publicar. [Ler mais](/creator/content-creator-pt/scene-editor/comecar/about-editor.md)
* **O Decentraland ECS**: Um pacote TypeScript que contém a framework de methods auxiliares que te permite criar experiências interativas. Usa-o para criar e manipular objects na scene e também para facilitar transações in-world entre players ou outras applications. ( [referência mais recente do ECS](https://github.com/decentraland/ecs-reference/blob/master/docs-latest/decentraland-ecs.md))
* **Exemplos de scenes**: Inspira-te e obtém boas práticas de código a partir dos [exemplos de scenes](https://studios.decentraland.org/resources?sdk_version=SDK7).

Outras ferramentas legacy:

* **O Web Editor**: Uma ferramenta baseada na web para criar scenes simples e publicá-las.

## Requirements

Para desenvolver uma scene localmente, não precisas de possuir tokens LAND. Desenvolver e testar uma scene pode ser feito completamente offline, sem necessidade de deployar uma scene para a rede Ethereum (o sistema que o Decentraland usa para estabelecer a propriedade de LAND, de um Decentraland Name), ou para o content server.

Deves ter:

* **O Creator Hub**: Uma aplicação autónoma que, entre outras coisas, te permite criar scenes com uma interface fácil de drag-and-drop. Podes executar previews, debug, editar código e publicar. [Ler mais](/creator/content-creator-pt/scene-editor/comecar/about-editor.md).

Se planeias editar o código da scene, também vais precisar de instalar um dos seguintes:

* <img src="/files/a305eec4daaf6c2c958d5c992d5a1dddf1e5a8c7" alt="VS Code" data-size="line"> **Visual Studio Code**: Faz download [aqui](https://code.visualstudio.com/). Ajuda-te a escrever código muito mais depressa e com menos errors. Um editor de source code assinala erros de sintaxe, faz autocomplete enquanto escreves e até mostra sugestões inteligentes que dependem do contexto em que te encontras. Também podes clicar num object no código para ver a definição completa da sua class e quais attributes ela suporta.
* <img src="/files/d7ef8798423b1db77d0089e922fcc89f1d600c49" alt="Cursor" data-size="line"> **Cursor AI**: Faz download [aqui](https://www.cursor.com/). Um poderoso code editor integrado com IA. Permite-te escolher diferentes modelos de IA para te ajudar a escrever código, todos eles gratuitos. O assistente de IA não faz apenas autocomplete enquanto escreves; também lhe podes pedir para refatorar uma grande code base, escrever documentação e muito mais.

{% hint style="info" %}
**💡 Dica**: Podes usar assistentes de IA como Cursor, OpenDCL ou Claude Code para construir scenes inteiras a partir de descrições em linguagem natural — não é necessária experiência em TypeScript. Vê [Vibe Coding com IA](/creator/content-creator-pt/scenes-sdk7/comecar/vibe-coding.md) para começares.
{% endhint %}

## Linguagens e sintaxe suportadas

O Decentraland utiliza [TypeScript (.ts)](https://www.typescriptlang.org/docs/handbook/jsx.html) como language padrão para escrever scenes.

TypeScript é um superset de JavaScript, por isso, se estiveres familiarizado com JavaScript, vais achar que é quase o mesmo, mas TypeScript inclui type declarations. Graças às type declarations, é possível ter features como autocomplete e melhores dicas de debugging; isto acelera os tempos de desenvolvimento e permite a criação de uma codebase mais sólida. Estas features são componentes essenciais para uma boa developer experience.

Quando uma scene é construída, o código Typescript que escreveste é compiled para Javascript minificado, para o tornar mais leve. O source code original em Typescript nunca é uploaded para os servers, apenas a versão compilada em Javascript.

### Outras languages

Podes usar outra ferramenta ou language em vez de TypeScript e compiled para JavaScript, desde que os teus scripts compilados estejam contidos num único ficheiro JavaScript chamado *game.js*. Todas as type declarations fornecidas são feitas em TypeScript, e outras languages e transpilers não são oficialmente supported.

## Scenes

O conteúdo que fazes deploy para o teu LAND chama-se uma **scene**. Uma scene é um programa interativo que renderiza conteúdo 3D; isto pode ser um jogo, uma experiência interativa, uma galeria de arte, o que quiseres!

As scenes são deployadas para LAND virtual no Decentraland. LAND é um asset escasso e non-fungible mantido num Ethereum smart contract. Faz deploy para um único **parcel**, um terreno de LAND de 16 metros por 16 metros, ou para múltiplos parcels adjacentes.

Quando os players visitam Decentraland, fazem download e renderizam o conteúdo de cada scene à medida que percorrem o mapa. As scenes são descarregadas quando se afastam delas.

Também podes correr uma scene localmente na tua máquina executando um preview a partir da CLI.

## Entities e Components

As scenes tridimensionais no Decentraland baseiam-se numa [Entity-Component-System](https://en.wikipedia.org/wiki/Entity%E2%80%93component%E2%80%93system) architecture, onde tudo numa scene é uma *entity*entity. As entities têm *components*; cada component dá à entity a que pertence propriedades específicas. É provável que uma entity de uma door tenha, pelo menos, um component Transform (que define position, rotation e scale) e outro para lhe fornecer uma shape. Os components são apenas um lugar para armazenar data; não executam quaisquer actions por si próprios.

![](/files/202178095a284867e3bcb546d0085d41bde3f20d)

```ts
export function main() {
	// Criar uma entity
	const door = engine.addEntity()

	// Dar uma posição à entity via um component Transform
	Transform.create(door, {
		position: Vector3.create(5, 1, 5),
	})

	// Dar à entity uma forma visível via um component GltfContainer
	GltfContainer.create(door)
}
```

As entities podem estar aninhadas dentro de outras entities para formar uma estrutura em árvore. Se estiveres familiarizado com web development, pode ser útil pensar nas entities como elements numa DOM tree e nos components como os attributes de cada um desses elements.

![](/files/565ff9ca2e8c99fe6a21d4bc6d8fd49f51d64b26)

As entities são um conceito abstracto. Uma entity é apenas um id, usado como referência para agrupar diferentes components.

Veja [Entities e components](/creator/content-creator-pt/scenes-sdk7/arquitetura/entities-components.md) para uma análise aprofundada destes dois conceitos e de como são usados pelas scenes do Decentraland.

### Custom components

O conjunto padrão de components (como `Transform`, `GltfContainer`, `Material`, etc) é interpretado pelo engine e tem consequências diretas em como a entity vai parecer, qual é a sua position, se emite sounds, etc.

Também podes definir *custom components* para armazenar data que possa ser útil para a mecânica da tua scene. O engine não saberá como interpretar o que os values destes components significam; eles não terão quaisquer consequências diretas na forma como a scene é rendered. No entanto, podes escrever lógica no código da tua scene para monitorizar esses values e responder a eles. Por exemplo, podes definir um component custom "doorState" para acompanhar o estado aberto/fechado da door. Neste caso, o component não é mais do que um lugar para armazenar um value que acompanha este estado. Para veres a door abrir e fechar na tua scene, tens então de implementar separadamente a lógica que usa estes values para afetar a rotation da door, um value do `Transform` component que o engine sabe interpretar.

Veja [Custom Components](/creator/content-creator-pt/scenes-sdk7/arquitetura/custom-components.md) para mais informações.

### Obter entities pelo nome

As entities adicionadas por drag-and-drop no Scene Editor no Creator Hub também podem ser acedidas via código para as editares mais e adicionares comportamento.

Use `engine.getEntityOrNullByName()` para obter uma entity, passando o nome atribuído à entity na UI do Scene Editor. Cada uma deve ter um nome único.

```ts
function main() {
	const door = engine.getEntityOrNullByName('door3')
}
```

Depois podes fazer o que quiseres com essa entity, como adicionar novos components, modificar os seus components existentes, duplicá-la ou apagá-la.

Veja [Obter entity pelo nome](/creator/content-creator-pt/scenes-sdk7/arquitetura/entities-components.md#get-an-entity-by-name) para mais informações.

Se a entity for um [Smart item](/creator/content-creator-pt/scene-editor/interatividade/smart-items.md), também podes chamar o seu **Actions** ou subscrever o seu **Triggers** via código. Vê [Reference Items](/creator/content-creator-pt/scene-editor/expandir-com-codigo/reference-items.md).

## Systems

Entities e components são lugares para armazenar information sobre os objects numa scene. *Systems* contêm functions que mudam a information armazenada nos components ao longo do tempo.

Os Systems são o local onde implementamos a game logic; eles executam as actions que precisam de ser updated ou verificadas periodicamente a cada tick do game loop.

Um system é uma função pura e simples que é chamada uma vez em cada tick (até 30 vezes por segundo), seguindo o [*update pattern*](http://gameprogrammingpatterns.com/update-method.html).

```ts
// Sistema básico
function mySystem() {
	console.log('my system is running')
}

engine.addSystem(mySystem)

// System com dt
function mySystemDT(dt: number) {
	console.log('tempo desde o último frame:  ', dt)
}

engine.addSystem(mySystemDT)
```

Uma única scene pode ter 0 ou muitos systems a correr ao mesmo tempo. Os systems podem ser ligados ou desligados em diferentes momentos durante a duração da scene. Geralmente, é uma boa prática manter comportamentos independentes em systems separados.

Veja [Systems](/creator/content-creator-pt/scenes-sdk7/arquitetura/systems.md) para mais detalhes sobre como os systems são usados numa scene.

### O game loop

O [game loop](http://gameprogrammingpatterns.com/game-loop.html) é a espinha dorsal do código de uma scene do Decentraland. Ele percorre parte do código num intervalo regular e faz o seguinte:

* Ouvir input do player
* Update a scene
* Re-render a scene

Na maioria dos programas de software tradicionais, todos os events são acionados diretamente pelas actions do player. Nada no estado do programa mudará até o player clicar num button, abrir um menu, etc.

Mas os ambientes interativos e os jogos são diferentes disso. Nem todas as alterações na scene são necessariamente causadas pelas actions de um player. A tua scene pode ter objects animados que se movem por si próprios ou até non-player characters que têm a sua própria IA. Algumas actions do player também podem levar vários ticks a ser concluídas; por exemplo, se a abertura de uma door precisar de um segundo inteiro, a rotation da door tem de ser updated incrementalmente cerca de 30 vezes à medida que se move.

Chamamos a cada iteração do loop um *tick*. As scenes do Decentraland são rendered a 30 ticks por segundo, sempre que possível. Se a máquina estiver com dificuldade em renderizar cada tick, isso pode resultar em updates menos frequentes.

Em cada tick, a scene é updated; depois a scene é re-rendered, com base nos values updated.

Nas scenes do Decentraland, não existe um game loop explicitamente declarado, mas sim os [Systems](/creator/content-creator-pt/scenes-sdk7/arquitetura/systems.md) da scene que compõem o game loop.

O compiling e o rendering da scene são realizados no backend; não precisas de lidar com isso enquanto desenvolves a tua scene.

## Consultar components

Podes [consultar components](/creator/content-creator-pt/scenes-sdk7/arquitetura/querying-components.md) com o método `engine.getEntitiesWith(...components)` para acompanhar todas as entities na scene que têm certos components.

Muitas vezes faz sentido consultar components dentro de um [system](/creator/content-creator-pt/scenes-sdk7/arquitetura/systems.md), para depois iterar sobre cada uma das entities devolvidas e executar o mesmo conjunto de actions em cada uma.

Se tentares iterar sobre todas as entities na scene em cada tick do game loop, isso pode ter um custo significativo de performance. Ao referires apenas as entities devolvidas por uma query, garantes que estás apenas a lidar com aquelas que são relevantes.

```ts
// Define um System
function boxHeightSystem(dt: number) {
	// query para entities que incluam tanto components MeshRenderer como Transform
	for (const [entity] of engine.getEntitiesWith(MeshRenderer, Transform)) {
		const transform = Transform.get(entity)
		console.log('uma box está à altura:  ', transform.position.y)
	}
}

// Adiciona o system ao engine
engine.addSystem(rotationSystem)
```

## Ciclo de vida da scene

Se começares a escrever linhas soltas de código diretamente em `index.ts`, o teu código pode estar a faltar algum contexto importante. Por exemplo, vai faltar informação sobre o player entity, ou sobre entities que foram adicionadas via drag and drop no Creator Hub. No momento em que as tuas linhas de código são lidas, essas coisas ainda não estão carregadas.

Para evitar esse cenário, é sempre recomendado escrever o código de carregamento inicial da tua scene usando a `main()` function (no `index.ts` ficheiro) como entrypoint. Esta function só é executada depois de todo o contexto inicial da scene já estar carregado, incluindo tudo o que foi adicionado via a UI do Scene Editor.

Podes escrever o teu código fora da `main()` function quando:

* O código é chamado indiretamente por `main()`
* O código define um system, ou adiciona um system ao engine
* O código está dentro de um [async function](/creator/content-creator-pt/scenes-sdk7/padroes-de-programacao/async-functions.md)

{% hint style="warning" %}
**📔 Nota**: Quando o código dentro de uma async function ou de um system é executado pela primeira vez, tudo na scene já está devidamente inicializado.

[As definições de Custom Component](/creator/content-creator-pt/scenes-sdk7/arquitetura/custom-components.md) são uma exceção; estas devem ser sempre escritas fora da `main()` function, num ficheiro separado. Precisam de ser interpretadas antes de `main()` ser executado.
{% endhint %}

## Mutabilidade

Podes escolher lidar com versões mutáveis ou imutáveis (read-only) de um component. A `.get()` function num component devolve uma versão imutável do component. Só podes ler os seus values, mas não podes alterar nenhuma das suas properties.

O `.getMutable()` function devolve uma representação do component que te permite alterar os seus values. Usa versões mutáveis apenas quando pretendes fazer changes a um component. Lidar com versões imutáveis de components resulta num enorme ganho de performance.

```ts
// obter uma versão imutável (read-only)
const immutableTransform = Transform.get(myEntity)

// o seguinte NÃO funciona:
// 	immutableTransform.position.y = 2

const mutableTransform = Transform.getMutable(myEntity)

// o seguinte ALTERA a position da entity
mutableTransform.position.y = 2
```

Veja [dados mutáveis](/creator/content-creator-pt/scenes-sdk7/padroes-de-programacao/mutable-data.md) para mais detalhes.

## Juntando tudo

O *engine* é o que fica entre *entities*e *components* por um lado e *systems* por outro.

![](/files/3a762409ce1248c88733ded658462ffb0195993f)

Todos os values armazenados nos components da scene representam o estado da scene naquele ponto no tempo. A cada tick do game loop, o engine executa as functions de cada um dos systems para update os values armazenados nos components.

Depois de todos os systems serem executados, os components de cada entity terão novos values. Quando o engine renderiza a scene, usará estes novos values updated e os players verão as entities mudar para corresponder aos seus novos states.

```ts
export function main() {
	// Criar uma entity
	const cube = engine.addEntity()

	// Dar uma posição à entity via um component Transform
	Transform.create(cube, {
		position: Vector3.create(5, 1, 5),
	})

	// Dá à entity uma shape visível através de um component MeshRenderer
	MeshRenderer.setBox(cube)
}

// Define um System
function rotationSystem(dt: number) {
	// query para entities que incluam tanto components MeshRenderer como Transform
	for (const [entity] of engine.getEntitiesWith(MeshRenderer, Transform)) {
		const transform = Transform.getMutable(entity)
		transform.rotation = Quaternion.multiply(
			transform.rotation,
			Quaternion.fromAngleAxis(dt * 10, Vector3.Up())
		)
	}
}

// Adiciona o system ao engine
engine.addSystem(rotationSystem)
```

No exemplo acima, uma `cube` entity e um `rotationSystem` system são adicionados ao engine. A `cube` entity tem um `Transform`, e um `MeshRenderer` component. Em cada tick do game loop, o `rotationSystem` system é chamado, e altera os values de rotation no `Transform` component da `cube` entity.

Nota que a maior parte do código acima é executada apenas uma vez, ao carregar a scene. A exceção é o `rotationSystem` system, que é chamado a cada tick do game loop.

## Desacoplamento da Scene

As tuas scenes não correm no mesmo context que o engine (também conhecido como a main thread). Criámos o SDK de uma forma totalmente desacoplada do rendering engine. Desenhámo-lo assim tanto por razões de segurança como de performance.

Devido a este desacoplamento, o código da tua scene não tem access ao DOM nem ao `window` object, por isso não podes aceder a data como o browser do player ou a localização geográfica.

O desacoplamento funciona através do uso do protocolo RPC; este protocolo atribui uma pequena parte do client apenas para renderizar a scene e controlar events.

Também abstraímos o communication protocol. Isto permite-nos correr as scenes localmente num WebWorker.

Não queremos que os developers intervenham com os internals do engine, nem sequer que precisem de saber o que existe dentro do engine. Precisamos de garantir uma experiência consistente para os players em todo o mapa do Decentraland, e os errors são mais prováveis de acontecer a esse nível "baixo".

Este desacoplamento também é importante para impedir que scenes vizinhas interfiram com a experiência dos players enquanto estão na scene de outra pessoa. Um player pode ter várias scenes próximas carregadas ao mesmo tempo, cada uma a correr o seu próprio código. Algumas actions (como abrir links externos, ou mover o player) só são permitidas quando o player está em cima dessa scene específica, e não se a scene estiver carregada mas o player estiver fora.

## Tree Shaking

Ao converter o source code em TypeScript para o compiled code em JavaScript minificado, o processo realiza [tree shaking](https://en.wikipedia.org/wiki/Tree_shaking) para garantir que apenas as partes do código que estão realmente a ser used são convertidas. Isto ajuda a manter o código final da scene o mais leve possível. É especialmente útil quando se usam external libraries, já que muitas vezes essas libraries incluem muita functionality que não é usada e que, de outra forma, aumentaria o tamanho da scene.

Como consequência do tree shaking, qualquer código que queiras que a tua scene execute precisa de ser referenced de alguma forma pelos entry points do teu código: a `main()` function no `index.ts`. Os systems também podem, em alternativa, ser added ao engine no `index.ts` ficheiro, sem referencing `main()`. Qualquer código que não seja explicitamente ou indiretamente referenced por estes ficheiros não fará parte da scene.

Por exemplo, suponhamos que tens um ficheiro chamado `extraContent.ts` com o seguinte conteúdo; a entity não será rendered e o system não começará a correr:

```ts
// extraContent.ts

const myEntity = engine.addEntity()
Transform.create(myEntity, {
	position: { x: 8, y: 0, z: 8 },
})
MeshRenderer.setBox(myEntity)

function mySystem(dt: number) {
	console.log('system running')
}

engine.addSystem(mySystem)
```

Para o fazer correr como parte da tua scene, podes reference a partir de `index.ts` da seguinte forma:

```ts
// em extraContent.ts

export function addEntities() {
	const myEntity = engine.addEntity()
	Transform.create(myEntity, {
		position: { x: 8, y: 0, z: 8 },
	})
	MeshRenderer.setBox(myEntity)
}

export function mySystem(dt: number) {
	console.log('system running')
}

/////////////////////////////

// em index.ts

import { addEntities, mySystem } from '/extraContent'

export function main() {
	addEntities()
}

engine.addSystem(mySystem)
```

A exceção a esta regra são as definições de custom components. Estas não devem ser acedidas através do `main()` function entry point, pois precisam de ser interpretadas antes de tudo o resto.

## Imports

Todas as functions, objects, components e outros elements usados pela scene devem ser imported para cada ficheiro para poder usá-los. Isto é uma consequência de [tree-shaking](#tree-shaking), pois evita empacotar o SDK inteiro e, em vez disso, inclui apenas as partes que a scene usa.

Os snippets ao longo da documentação omitem as linhas de import no início de cada ficheiro para os manter limpos, mas para funcionarem tens de adicioná-las à scene.

Quando usas o VS Studio Code para escrever as tuas scenes, as opções inteligentes de autocomplete devem tratar dos imports por ti enquanto escreves, sem precisares de estar consciente disso.

No entanto, quando colas um snippet na tua scene, provavelmente vais ver alguns elements assinalados a vermelho, que não estão imported para esse ficheiro. Para corrigir isto:

* Clica em cada palavra sublinhada
* Clica no ícone da lâmpada à esquerda da linha
* Selecione **Add Import From**
* Uma linha de import aparece no início do ficheiro.

![](/files/0dc6f98b5c0a5751420e7bcacd490d6711f2d6ba)

Se houver muitas coisas diferentes para importar, também podes selecionar **Add all missing imports** no mesmo dropdown.

Nota que os imports têm de ser feitos em cada ficheiro onde um element é used.

O VS Studio Code deve conseguir resolver por si próprio os paths corretos para os teus imports. Se, por qualquer razão, estiver com dificuldades em fazê-lo, uma dica é colar as seguintes empty import statements no início do teu ficheiro. O VS Studio deverá conseguir tratar do resto.

```ts
import {} from '@dcl/sdk/ecs'
import {} from '@dcl/sdk/math'
```

## Versões do SDK

Ao desenvolver uma nova scene, usas a release estável `@latest` do SDK por padrão.

Podes instalar a release `@next` do SDK se quiseres aproveitar ou pré-visualizar features futuras que ainda não chegaram à latest stable release.

Para o fazer, abre o `package.json` ficheiro da tua scene e altera as seguintes linhas:

```json
  "devDependencies": {
    "@dcl/js-runtime": "next",
    "@dcl/sdk": "next"
  },
```

Depois executa o seguinte command na pasta do projeto da tua scene:

```
npm i
```

Veja [gerir dependências](/creator/content-creator-pt/scenes-sdk7/libraries/manage-dependencies.md) para mais detalhes.

{% hint style="warning" %}
**📔 Nota**: Tem em atenção que a versão @next pode sofrer issues de tempos a tempos. A syntax e o nome de novas features podem mudar antes de ser lançada numa versão estável.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.decentraland.org/creator/content-creator-pt/scenes-sdk7/comecar/coding-scenes.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
