-
Notifications
You must be signed in to change notification settings - Fork 14
How to implement new SDK Components
This is the high-level steps that must be followed:
- Create the protobuf definition in Decentraland's SDK protocol
- Generate the new protobuf TypeScript code in the js-sdk-toolchain (serialization test + (optional) sdk helpers)
- Generate the new protobuf C# code in unity-explorer + implement the systems that handle the functionalities, cleanup, etc. for the component
- (Ideally) Create an example test-scene to show how the component is used from the SDK side
IMPORTANT This is the order in which PRs must be merged:
- Merge Protocol repo PR (if the change was on
main, thenexperimentalmust sync the new changes before step 2) - Update both
js-sdk-toolchainrepo PR andunity-explorerrepo PR to use the updated@dcl/protocol@experimentalpackage - Merge
js-sdk-toolchainandunity-explorerin any order
1. Create the protobuf definition in Decentraland's SDK protocol
- Create the protobuf definition inside https://github.com/decentraland/protocol/tree/main/proto/decentraland/sdk/components
- Create a PR with the new changes
NOTE: After creating the PR, a GitHub Bot will comment with the package link to test the PR. You can use that link for testing in the following steps
Things to take into account
- We are using proto 3, so all the definition of the proto must compile with their syntax
- Be VERY mindful of the fields and types you create in the Protobuf Message, due to retro-compatibility standards we can never rename or modify any field of an already released Protobuf message (AKA if you are still working on your PRs then you can keep changing stuff, although you will be forced to change the other 2 repo PRs as well fo course), as that will break scenes that are already deployed and create conflicts in the SDK and Explorer... if at some point we really need to "update" an already released component field, we should create a new field and somehow flag the old one as deprecated...
- We have some common types that cannot be recreated
- The proto should have the basic definition
- You must add the following code to enumerate the component with a unique ID
import "common/id.proto";
option (ecs_component_id) = 1100;
NOTE: With the repo cloned locally you can run
make list-components-idsandmake check-component-id ID=xxxto make sure your component is using a unique id.
Example of .proto:
syntax = "proto3";
import "common/id.proto";
option (ecs_component_id) = 1020;
message PBAudioSource {
optional bool playing = 1;
optional float volume = 2; // default=1.0f
optional bool loop = 3;
optional float pitch = 4; // default=1.0f
string audio_clip_url = 5;
}
2. Generate the new protobuf TypeScript code in the js-sdk-toolchain
Clone the sdk repo: https://github.com/decentraland/js-sdk-toolchain
Run the following command at the root of the js-sdk-toolchain project (use @experimental instead if you are working on an experimental feature):
npm install @dcl/protocol@next
Or the command generated by the GitHub Bot in your @dcl/protocol PR (this must be temporal for testing the PRs).
Then run the following commands at the root of the js-sdk-toolchain project:
make install
make build
And push the generated code to your branch.
For the branch PR to be approved and functional you will also need to:
- [Mandatory] Implement the new component serialization test (check the existent ones at https://github.com/decentraland/js-sdk-toolchain/tree/main/test/ecs/components)
- Afterwards you will have to run
make update-snapshotsto incorporate the new test into the test memory snapshots.
- Afterwards you will have to run
- [Optional] If it was defined that there would be SDK helpers, those also have to be implemented in the PR (Wiki page for helpers)
After that is done, the GitHub Bot comment in the PR will expose a test package so that you install that in your test scene and be able to use the new component from the SDK in the scene (see this wiki page on setting up a local scene and running it)
To generate the C# code from the protobuf files that come from the protocol, go to the scripts path in the root of the unity-explorer repository. And execute the following commands:
npm install
npm run build-protocol
To upgrade to the latest version of the @dcl/protocol, we should update using
npm install @dcl/protocol@experimental
npm run build-protocol
NOTE: unity-explorer needs to always use the
@experimentalprotocol package to support all the experimental features, otherwise the Unity project won't even compile due to missing component files, etc.
To test a PR, we can use a URL generated by the GitHub Bot in the @dcl/protocol PR:
Example:
npm install "https://sdk-team-cdn.decentraland.org/@dcl/protocol/branch//dcl-protocol-1.0.0-3143233696.commit-45f1290.tgz"
npm run build-protocol
IMPORTANT: After merging a @dcl/protocol PR, we must make unity-explorer point to the updated @dcl/protocol@experimental package (and NOT the PR test package) before merging the unity-explorer PR.
- If the protocol update happened at
mainthen theexperimentalbranch must sync those new changes first, and then update the unity-explorer PR with the latest@experimentalpackage. - If the protocol update happened at
experimentalthen the unity-explorer PR can just use the updated@experimentalpackage.
After the C# code for the protobuf component was generated, one or more systems have to be implemented to handle its functionality, following the Arch ECS architecture.
- Add the
partialclass corresponding to the new PB component at IDirtyMarker - Register the component at the ComponentsContainer, otherwise no system will recognize the component on the ECS entities
NOTE: You'll see that some special components registered as "result components". Those are some components designed mainly to be PUT by the Explorer and only READ by the scene (e.g. input result component, raycast result component).
- Create a folder dedicated to the new component at https://github.com/decentraland/unity-explorer/tree/dev/Explorer/Assets/DCL/SDKComponents and implement the handling systems, components, etc. in there.
- Create a PLUGIN file at https://github.com/decentraland/unity-explorer/tree/dev/Explorer/Assets/DCL/PluginSystem/World to INJECT your Systems in that code
- Your Plugin has to be instantiated at https://github.com/decentraland/unity-explorer/blob/dev/Explorer/Assets/DCL/Infrastructure/Global/StaticContainer.cs#L254~L280 along with the other Scene Plugins (not GLOBAL)
As a general guideline this must be implemented:
- Relevant functionalities for the new component
- Custom non-sdk
structcomponents (can be empty) are normally used to change the state of the entity - If
IsDirtyneeds to be relied upon, for the case of the scene modifying the component values in runtime and reacting to that: then theIsDirtyreset handling can either be manual in your systems OR by injectingResetDirtyFlagSystem<PBYourComponent>.InjectToWorld(ref builder)in your Plugin.
- Custom non-sdk
- Cleanup of the component
- SDK component removal
- Scene unloading (
IFinalizeWorldSystemimplementation)
This step is important because it allows creators (like the Content Team itself) to easily test the new component and know how it should be used, when the official documentation may still be pending.
- Clone the sdk7-test-scenes repo
- Create your test scene base
- Duplicate one of the existent test scenes that exist in
/scenes - Change the new folder name to your new test scene coordinates AND name (same format as the rest)
- Update the
README.mdfile - Update the
package.jsonfile ->"name"property - Update the
scene.jsonfile ->"name"property +"title"property +"base"and"parcels"coordinate properties
- Duplicate one of the existent test scenes that exist in
- Go to the root of the repo and run
npm iand thennpm run check-parcelsto confirm there is no coordinates conflict between your new test scene and a previously existent one (that also updates thedcl-workspace.jsonfile) - Return to the root of your test scene and install an SDK version that contains the new component, for example if you are still working on an SDK branch with the component, the package is the one exposed in the js-sdl-toolchain PR, like
npm install "https://sdk-team-cdn.decentraland.org/@dcl/js-sdk-toolchain/branch/feat/trigger-area-components/dcl-sdk-7.10.1-17412673762.commit-72cc7b1.tgz"- After that, your IDE should recognize the new component when imported from
'@dcl/sdk/ecs'and you should be able to use it in your code without compilation errors
- After that, your IDE should recognize the new component when imported from
- run your scene to confirm there are no compilation errors (
npm run start -- --explorer-alpha) - Code your test scene making use of the new component (
index.tsand whatever extra scripts you need) - Make sure to remove unneeded files like
/models, etc. if your scene doesn't use them (/images/scene-thumbnail.pngmust be kept) - create a branch in the test scenes repo and push your new scene to create the corresponding PR in that repo, you are responsible for merging it