Essenciais de programação
Este conjunto ajudará você a entender como as coisas funcionam no cliente e no SDK do Decentraland.
As ferramentas de desenvolvimento
Em um nível muito alto, o Decentraland Software Development Kit (SDK) permite que você faça o seguinte:
Gerar um projeto padrão contendo uma cena do Decentraland, incluindo todos os assets necessários para renderizar e executar seu conteúdo.
Construir, testar e pré-visualizar o conteúdo da sua cena localmente no seu navegador - completamente offline, sem precisar fazer qualquer transação no Ethereum ou possuir LAND.
Escrever código TypeScript usando a API do Decentraland para adicionar comportamento interativo e dinâmico à cena.
Enviar o conteúdo da sua cena para o servidor de conteúdo.
Vincular seus tokens LAND à URL do conteúdo que você enviou.
Nosso SDK inclui o seguinte:
The Creator Hub: Um aplicativo independente que, entre outras coisas, permite criar cenas com uma interface fácil de arrastar e soltar. Você pode executar pré-visualizações, depurar, editar código e publicar. Leia mais
O ECS do Decentraland: Um pacote TypeScript que contém o framework de métodos auxiliares que permite criar experiências interativas. Use-o para criar e manipular objetos na cena e também para facilitar transações in-world entre jogadores ou outras aplicações. ( referência ECS mais recente)
Exemplos de cenas: Inspire-se e obtenha boas práticas de codificação a partir dos exemplos de cena.
Outras ferramentas legadas:
O Web Editor: Uma ferramenta baseada na web para criar cenas simples e publicá-las.
Requisitos
Para desenvolver uma cena localmente, você não precisa possuir tokens LAND. Desenvolver e testar uma cena pode ser feito completamente offline, sem a necessidade de implantar a cena na rede Ethereum (o sistema que o Decentraland usa para estabelecer a propriedade do LAND, de um Decentraland Name), ou no servidor de conteúdo.
Você deve ter:
The Creator Hub: Um aplicativo independente que, entre outras coisas, permite criar cenas com uma interface fácil de arrastar e soltar. Você pode executar pré-visualizações, depurar, editar código e publicar. Leia mais.
Se você planeja editar o código da cena, também precisará instalar uma das seguintes:
Visual Studio Code: Faça o download aqui. Ele ajuda você a escrever código muito mais rápido e com menos erros. Um editor de código fonte marca erros de sintaxe, conclui automaticamente enquanto você escreve e até mostra sugestões inteligentes que dependem do contexto em que você está. Você também pode clicar em um objeto no código para ver a definição completa de sua classe e quais atributos ela suporta.
Cursor AI: Faça o download aqui. Um editor de código poderoso que é integrado com IA. Ele permite escolher diferentes modelos de IA para ajudar a escrever código, todos gratuitos. O assistente de IA não apenas completa automaticamente enquanto você escreve, você também pode solicitar que ele refatore uma grande base de código, escreva documentação e mais.
Linguagens e sintaxe suportadas
O Decentraland utiliza TypeScript (.ts) como a linguagem padrão para escrever cenas.
TypeScript é um superset de JavaScript, então se você está familiarizado com JavaScript achará que é quase o mesmo, mas o TypeScript inclui declarações de tipo. Graças às declarações de tipo, é possível ter recursos como autocomplete e dicas de depuração melhores; isso acelera o tempo de desenvolvimento e permite a criação de uma base de código mais sólida. Esses recursos são componentes-chave para uma experiência positiva do desenvolvedor.
Quando uma cena é compilada, o código TypeScript que você escreveu é convertido em JavaScript minificado, para torná-lo mais leve. O código fonte original em TypeScript nunca é enviado aos servidores, somente a versão compilada em JavaScript.
Outras linguagens
Você pode usar outra ferramenta ou linguagem em vez de TypeScript e compilá-la para JavaScript, contanto que seus scripts compilados estejam contidos em um único arquivo JavaScript chamado game.js. Todas as declarações de tipo fornecidas são feitas em TypeScript, e outras linguagens e transpilers não são oficialmente suportados.
Scenes
O conteúdo que você implanta no seu LAND é chamado de scene. Uma cena é um programa interativo que renderiza conteúdo 3D; isso pode ser um jogo, uma experiência interativa, uma galeria de arte, o que você quiser!
Cenas são implantadas em LAND virtual no Decentraland. LAND é um asset escasso e não-fungível mantido em um smart contract do Ethereum. Faça o deploy em um único parcel, um lote de LAND de 16 metros por 16 metros, ou em múltiplos parcels adjacentes.
Quando os jogadores visitam o Decentraland, eles baixam e renderizam o conteúdo de cada cena enquanto caminham pelo mapa. Eles descarregam cenas quando se afastam delas.
Você também pode executar uma cena localmente na sua máquina executando uma pré-visualização a partir do CLI.
Entidades e Componentes
Cenas tridimensionais no Decentraland são baseadas em uma arquitetura Entity-Component-System , onde tudo em uma cena é uma entity. Entidades têm componentes, cada componente dá à entidade a que pertence propriedades específicas. Uma entidade porta provavelmente terá pelo menos um componente Transform (que define posição, rotação e escala) e outro para fornecer sua forma. Componentes são apenas um local para armazenar dados; eles não executam ações por si mesmos.

Entidades podem ser aninhadas dentro de outras entidades para formar uma estrutura em árvore. Se você está familiarizado com desenvolvimento web, pode achar útil pensar nas entidades como elementos em uma árvore DOM e nos componentes como os atributos de cada um desses elementos.

Entidades são um conceito abstrato. Uma entidade é apenas um id, que é usado como referência para agrupar diferentes componentes.
Veja Entities e components para um olhar aprofundado sobre ambos os conceitos e como eles são usados pelas cenas do Decentraland.
Custom components
O conjunto padrão de componentes (como Transform, GltfContainer, Material, etc) é interpretado pelo engine e tem consequências diretas sobre como a entidade vai aparecer, sua posição, se emite sons, etc.
Você também pode definir customizados específicos para armazenar dados que possam ser úteis para as mecânicas da sua cena. O engine não saberá como interpretar o que os valores nesses componentes significam; eles não terão consequências diretas sobre como a cena é renderizada. No entanto, você pode escrever lógica no código da sua cena para monitorar esses valores e responder a eles. Por exemplo, você pode definir um componente personalizado "doorState" para rastrear o estado aberto/fechado da porta. Nesse caso, o componente nada mais é do que um local para armazenar um valor que acompanha esse estado. Para ver a porta abrir e fechar na sua cena, você então precisa implementar separadamente a lógica que usa esses valores para afetar a rotação da porta, um valor do componente Transform que o engine sabe como interpretar.
Veja Componentes Personalizados para mais informações.
Buscar entidades por nome
As entidades adicionadas arrastando e soltando no Scene Editor do Creator Hub também podem ser acessadas via código para editá-las e adicionar comportamento.
Use engine.getEntityOrNullByName() para buscar uma entidade, passando o nome atribuído à entidade na UI do Scene Editor. Cada uma deve ter um nome único.
Você então pode fazer qualquer coisa que quiser com essa entidade, como adicionar novos componentes, modificar seus componentes existentes, duplicá-la ou excluí-la.
Veja Obter entidade por nome para mais informações.
Se a entidade for um Smart item, você também pode chamar seu Actions ou se inscrever em seu Triggers via código. Veja Itens de Referência.
Sistemas
Entidades e componentes são locais para armazenar informações sobre os objetos em uma cena. Sistemas seguram funções que alteram a informação que está armazenada nos componentes ao longo do tempo.
Sistemas são onde implementamos a lógica do jogo; eles executam as ações que precisam ser atualizadas ou verificadas periodicamente em cada tick do loop do jogo.
Um sistema é uma função pura e simples que é chamada uma vez em cada tick (até 30 vezes por segundo), seguindo o padrão de update.
Uma única cena pode ter 0 ou muitos sistemas executando ao mesmo tempo. Sistemas podem ser ativados ou desativados em diferentes momentos durante a duração da cena. Geralmente é uma boa prática manter comportamentos independentes em sistemas separados.
Veja Sistemas para mais detalhes sobre como sistemas são usados em uma cena.
O loop do jogo
O game loop é a espinha dorsal do código de uma cena do Decentraland. Ele percorre parte do código em intervalos regulares e faz o seguinte:
Ouvir a entrada do jogador
Atualizar a cena
Re-renderizar a cena
Na maioria dos programas tradicionais, todos os eventos são disparados diretamente por ações do jogador. Nada no estado do programa mudará até que o jogador clique em um botão, abra um menu, etc.
Mas ambientes interativos e jogos são diferentes. Nem todas as mudanças na cena são necessariamente causadas por ações do jogador. Sua cena pode ter objetos animados que se movem sozinhos ou até personagens não-jogadores com sua própria IA. Algumas ações do jogador também podem levar múltiplos ticks para serem concluídas; por exemplo, se a abertura de uma porta precisa levar um segundo inteiro, a rotação da porta deve ser atualizada incrementalmente cerca de 30 vezes enquanto ela se move.
Chamamos cada iteração do loop de um tick. Cenas do Decentraland são renderizadas a 30 ticks por segundo, sempre que possível. Se a máquina estiver com dificuldades para renderizar cada tick, isso pode resultar em atualizações menos frequentes.
Em cada tick, a cena é atualizada; então a cena é re-renderizada, com base nos valores atualizados.
Em cenas do Decentraland, não existe um loop do jogo explicitamente declarado, mas sim as Sistemas funções da cena que compõem o loop do jogo.
A compilação e renderização da cena é realizada no backend; você não precisa lidar com isso enquanto desenvolve sua cena.
Consultando componentes
Você pode consultar componentes com o método engine.getEntitiesWith(...components) para acompanhar todas as entidades na cena que possuem certos componentes.
Frequentemente faz sentido consultar componentes dentro de uma sistema, para então iterar sobre cada uma das entidades retornadas e executar o mesmo conjunto de ações em cada uma.
Se você tentar iterar sobre todas as entidades na cena em cada tick do loop do jogo, isso pode ter um custo significativo em desempenho. Referindo-se apenas às entidades retornadas por uma query, você garante que está lidando apenas com as relevantes.
Ciclo de vida da cena
Se você começar a escrever linhas soltas de código diretamente em index.ts, seu código pode estar sem algum contexto importante. Por exemplo, faltará informação sobre a entidade do jogador, ou sobre entidades que foram adicionadas via drag and drop no Creator Hub. No momento em que suas linhas de código são lidas, essas coisas ainda não estarão carregadas.
Para evitar esse cenário, é sempre recomendado escrever o código de carregamento inicial da sua cena usando a main() função (no arquivo index.ts ) como ponto de entrada. Essa função roda apenas após todo o contexto inicial da cena já estar carregado, incluindo qualquer coisa adicionada via UI do Scene Editor.
Você pode escrever seu código fora da função main() quando:
O código é chamado indiretamente por
main()O código define um sistema, ou adiciona um sistema ao engine
O código está dentro de um async function
📔 Nota: No momento em que o código dentro de uma função async ou de um sistema é executado pela primeira vez, tudo na cena já está devidamente inicializado.
Componente Personalizado defs são uma exceção; estes devem sempre ser escritos fora da função main() , em um arquivo separado. Eles precisam ser interpretados antes que main() seja executado.
Mutabilidade
Você pode optar por lidar com versões mutáveis ou imutáveis (somente leitura) de um componente. A função .get() da entity em um componente retorna uma versão imutável do componente. Você só pode ler seus valores, mas não pode alterar nenhuma das propriedades nele.
O .getMutable() A função retorna uma representação do componente que permite que você altere seus valores. Use versões mutáveis somente quando planejar fazer mudanças em um componente. Lidar com versões imutáveis de componentes resulta em um grande ganho de desempenho.
Veja dados mutáveis para mais detalhes.
Juntando tudo
O engine é o que fica entre entities, e componentes por um lado e systems por outro.

Todos os valores armazenados nos componentes da cena representam o estado da cena naquele ponto no tempo. A cada tick do loop do jogo, o engine executa as funções de cada um dos sistemas para atualizar os valores armazenados nos componentes.
Após todos os sistemas serem executados, os componentes em cada entidade terão novos valores. Quando o engine renderiza a cena, ele usará esses novos valores atualizados e os jogadores verão as entidades mudarem para corresponder aos seus novos estados.
No exemplo acima, uma entidade cube e um rotationSystem sistema são adicionados ao engine. A entidade cube entidade tem um Transform, e um MeshRenderer componente. A cada tick do loop do jogo, o rotationSystem sistema é chamado, e ele muda os valores de rotação no Transform componente da entidade cube entidade.
Note que a maior parte do código acima é executada apenas uma vez, ao carregar a cena. A exceção é o rotationSystem sistema, que é chamado em cada tick do loop do jogo.
Desacoplamento da Cena
Suas cenas não rodam no mesmo contexto que o engine (também conhecido como thread principal). Criamos o SDK de uma forma que é totalmente desacoplada do engine de renderização. Projetamos assim por motivos de segurança e desempenho.
Por causa desse desacoplamento, o código da sua cena não tem acesso ao DOM ou ao objeto window , portanto você não pode acessar dados como o navegador do jogador ou localização geográfica.
O desacoplamento funciona usando protocolo RPC; esse protocolo atribui uma pequena parte do cliente apenas para renderizar a cena e controlar eventos.
Também abstraímos o protocolo de comunicação. Isso nos permite executar as cenas localmente em um WebWorker.
Não queremos que desenvolvedores intervenham nos internos do engine ou mesmo precisem saber o que há dentro do engine. Precisamos garantir uma experiência consistente para os jogadores por todo o mapa do Decentraland, e erros são mais propensos a acontecer nesse nível "baixo".
Esse desacoplamento também é importante para evitar que cenas vizinhas interfiram na experiência dos jogadores enquanto eles estão na cena de outra pessoa. Um jogador pode ter múltiplas cenas próximas carregadas ao mesmo tempo, cada uma executando seu próprio código. Algumas ações (como abrir links externos, ou mover o jogador) são permitidas apenas quando o jogador está em cima daquela cena específica, não se a cena estiver carregada mas o jogador estiver fora dela.
Tree Shaking
Ao converter o código fonte em TypeScript para o código compilado em JavaScript minificado, o processo realiza tree shaking para garantir que somente as partes do código que estão sendo realmente usadas sejam convertidas. Isso ajuda a manter o código final da cena o mais leve possível. É especialmente útil ao usar bibliotecas externas, já que frequentemente essas bibliotecas incluem muita funcionalidade que não é usada e que aumentaria o tamanho da cena.
Como consequência do tree shaking, qualquer código que você queira que sua cena execute precisa ser referenciado de alguma forma pelos pontos de entrada do seu código: a função main() no arquivo index.ts. Sistemas também podem, alternativamente, ser adicionados ao engine no arquivo index.ts , sem referenciar main(). Qualquer código que não seja explicitamente ou indiretamente referenciado por esses arquivos não fará parte da cena.
Por exemplo, suponha que você tenha um arquivo chamado extraContent.ts com o seguinte conteúdo, a entidade não será renderizada e o sistema não começará a rodar:
Para fazê-lo rodar como parte da sua cena, você pode referenciar a partir de index.ts da seguinte forma:
A exceção a essa regra são as definições de componentes personalizados. Estes não devem ser acessados via o ponto de entrada da função, pois precisam ser interpretados antes de todo o resto. main() Todas as funções, objetos, componentes e outros elementos usados pela cena devem ser importados em cada arquivo que os use. Isso é uma consequência do
Imports
tree-shaking , pois evita empacotar todo o SDK e em vez disso inclui somente as partes que a cena usa.Trechos ao longo da documentação omitem as linhas de import no início de cada arquivo para mantê-los limpos, mas para que funcionem você deve adicioná-las à cena.
Ao usar o VS Studio Code para escrever suas cenas, as opções inteligentes de autocompletar devem cuidar de gerenciar as importações para você enquanto escreve, sem que você precise se preocupar com isso.
Quando você cola um snippet na sua cena, no entanto, provavelmente verá alguns elementos sublinhados em vermelho, que não estão importados naquele arquivo. Para corrigir isso:
Clique em cada palavra sublinhada
Clique no ícone de lâmpada à esquerda da linha
Adicionar Import From
Selecionar Uma linha de import aparece no início do arquivo.
Se houver muitas coisas diferentes para importar, você também pode selecionar

Adicionar todas as importações ausentes no mesmo menu suspenso. Observe que importações devem ser feitas em cada arquivo onde um elemento é usado.
O VS Studio Code deve ser capaz de resolver os caminhos corretos para suas importações por conta própria. Se por algum motivo ele estiver com dificuldade, um truque é colar as seguintes instruções de import vazias no início do seu arquivo. O VS Studio deve conseguir se virar a partir daí.
import {} from '@dcl/sdk/ecs'
Ao desenvolver uma nova cena, você usa a versão estável do SDK por padrão.
Você pode instalar a @latest release estável do SDK por padrão.
Você pode instalar a @next release do SDK se quiser aproveitar ou pré-visualizar recursos futuros que ainda não chegaram à última versão estável.
Para fazer isso, abra o arquivo package.json da sua cena, e altere as seguintes linhas:
Então execute o seguinte comando na pasta do projeto da sua cena:
Veja gerenciar dependências para mais detalhes.
📔 Nota: Tenha em mente que a versão @next pode apresentar problemas de vez em quando. A sintaxe e o nome de novos recursos podem mudar antes de serem lançados em uma versão estável.
Atualizado