Giter VIP home page Giter VIP logo

adr's Introduction

Marketplace

Decentraland's Marketplace

Frontend

Coverage Status

The Marketplace is a React static site. Its code can be found under the /webapp directory.

Backend

It can be found under /indexer.

How to contribute

Contributing to the Marketplace is easy, you just need to go through the following process:

  1. Look for issues in the Issues tab or create a new one with the proposed changes. We classify issues with the “Enhancement”, “Bug” or “Good first issue” tags. Feel free to check one of those first.
  2. Contact team members via the GitHub issue or use the Code Contribution Discord channel. It’s important to at least check on the issue status before starting.
  3. Set up your GPG key and sign all commits in your branch.
  4. Read the testing standards and the coding standards to produce code that fits the project standards.
  5. Create a PR with the changes, linking the PR to the created issue. If there are visual changes in the PR, attach images.

Copyright & License

This repository is protected with a standard Apache 2 license. See the terms and conditions in the LICENSE file.

adr's People

Contributors

2fd avatar agusaldasoro avatar ajimenezdcl avatar aleortega avatar braianj avatar brianamadori avatar cazala avatar davidejensen avatar fzavalia avatar gonpombo8 avatar guidota avatar hugoarregui avatar jmoguilevsky avatar kevinszuchet avatar kuruk-mm avatar lautaropetaccio avatar leanmendoza avatar lorux0 avatar manumena avatar marianogoldman avatar menduz avatar nachomazzara avatar nchamo avatar nearnshaw avatar nicosantangelo avatar pedrotambo avatar pentreathm avatar pravusjif avatar sandrade-dcl avatar slezica avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

adr's Issues

feat: Voting Power tracking for Saved Items in the Marketplace


layout: adr
adr: 231
title: Voting Power Tracking for Marketplace Saved Items
date: 2023-05-09
status: Idea
type: Standards Track
spdx-license: CC0-1.0
authors:

  • kevinszuchet

Abstract

This document outlines the guidelines for counting the number of users who have saved an item in the Marketplace. The approach adopted is similar to the one used in Places for determining the highest-rated percentage of upvotes and downvotes from users with specific Voting Power. However, it has been adapted to meet the needs of the recently launched Marketplace Lists feature.

Context, Reach & Prioritization

Previously, users of the Decentraland Marketplace needed an option to save items for future reference, leading to missed opportunities for creators and potential customers. The Marketplace Lists feature was introduced to tackle this problem, enabling users to easily create and manage lists of items they plan to save for later and offering a gamified experience.

To improve accuracy and empower community members, a Voting Power criterion has been introduced for calculating the number of users who have saved an item in a list, ensuring a more precise count of saved items.

Solution Space Exploration

The strategy employed in Places has been adapted to the new feature requirements. When a new item is added to the list, the user's Voting Power (VP) is retrieved from the Snapshot platform and stored for future use. Then, the number of times an item has been added to a list only considers users with a specific VP.

One potential drawback of this method is that users may transfer their assets to a new account and re-add an item to the list with the same Voting Power, as it is only recorded once an item is added. As a result, this could cause the count for that item to be artificially inflated, as the same assets would be counted twice when retrieving the VP, resulting in an inaccurate count.

Specification

The guidelines mentioned above were introduced on May 4, 2023.

RFC 2119 and RFC 8174

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.

Ubiquitous authentication mechanism for HTTP requests

Abstract

This ADR describes the mechanisms used to authenticate and validate HTTP requests. It presents different alternatives and decides to use the AuthChain mechanism since it is compatible with with digital signature algorithm used in EVM compatible schemas and it inherits the same capabilities as other mechanisms with the addition of signed headers and payloads.

Create ADR for favorite places

layout: adr
adr:
title: Add favorite places
date: 2023-01-31
status: Idea
type: ADR
spdx-license: CC0-1.0
authors:

@davidejensen

Abstract

This document describes an approach on how to integrate the new Favorite Places functionality in Decentraland.

Problem

To enhance the discoverability of the different Decentraland places, there is the need of adding a favorite mechanism. This will allow user to store and retrieve easily a set of their best loved places.
To integrate this changes at multiple levels are required, from the visual representation in the explorer, to the backend structure that will allow the saving and retrieving of a user favorites.

Following a list of the expected functionalities:

  • Users can add a place to their favorite from the explore menu
  • Users can navigate to a new tab listing all the places they added to favorites

In a future iteration it will be possible to favorite places from the minimap HUD and also from the map parcel info pop-up, currently not possible due to technical limitations of the renderer map handling and Places API restriction to curated places.
More in the limitations section.

Solution

Data storing

After an initial discussion about whether to store favorites in the user profile or in Places, we are more incline to store everything in Places, more informations about the decision journey at the end.

Favorite retrieval

The Places API will need to add three new endpoints:

  • An endpoint to obtain the (paginated if we decide for a big maximum amount) list of favorites.
  • An endpoint to add a new favorite for the current user
  • An endpoint to remove a favorite for the current user

In additon a change will be required in the current place data structure in order to show the favorite information in the explore places list with a boolean.

Data structure

To facilitate the addition of the feature when handling favorites we should use the same data structure currently used for Places, with the boolean addition previously mentioned:

public class Realm
{
	public string serverName;
	public string layer;
	public int usersCount;
	public int maxUsers;
	public Vector2Int[] userParcels;
}

public string id;
public string name;
public string creator;
public string description;
public string thumbnail;
public Vector2Int baseCoords;
public Vector2Int[] parcels;
public int usersTotalCount;
public bool isPOI;
public Realm[] realms;

Current limitations

With the current functionalities provided by the Places website it is not possible to favorite all the Decentraland areas due to a restriction that allows only curated Places to be displayed. This together with a legacy code integration of the map in the unity renderer will allow the favorite functionality to be applied only in the places section in the explore menu.

Decision journey

In the initial iteration it has been discussed where to store the favorite list, the two options were storing them in the user profile or storing them in Places, the following PROs and CONs made us lean towards the Places option:

  • Storing favorite in the user profile:
    • PROs
      • Easily readable in unity renderer
      • Simple to obtain favorites of other players
      • Decentralised approach
      • Favorites can be imported in places without user interaction
    • CONs
      • requires updates on the profile schema
      • requires to implement the profile update on web
      • requires to track every catalyst update to calculate stats and trends
      • explorer can’t suggest places based on the favorites of your friends
      • scenes can read it but not update it
      • an update request from different apps can erase a favorites accidentally
      • limited by the max size of a profile
      • not paginated
  • Storing favorites in places
    • PROs
      • no limit on the amount of favorites
      • api already paginated
      • can be accessed and updated with code in the scene
      • can calculate stats just looking at the database (place with the most favorites, last favorites, favorites trends)
      • can suggest favorites places of your friends
      • can eventually move all favorites from one position to other in case the scene move to another parcel
    • CONs
      • is a single point of failure
      • requires a new integration in the unity side to request this data (it just a signed fetch)
      • favorites can’t be imported into the profile, it requires user interaction to do it

In addition, because currently unity-renderer doesn't communicate directly with the Places API, it has been thought that the missing endpoints will be contacted with the old kernel request system, in order to avoid blocking the development of this new functionality until the authentication system and request handling is transferred to the unity renderer.

Write ADR for Scene Bounds Checking

Write a Standard Track ADR documenting the architecture deccisions implemented in the reference client to check entities and meshes against their scene bounds and how the client reacts to that (preview and production).

Tackled at #193

Rendering order for UI entities


layout: adr
adr: 151
title: Rendering order for UI entities
date: 2022-12-14
status: Review
type: Standards Track
spdx-license: CC0-1.0
authors:

  • menduz

Abstract

This document describes the requirements to render the UI entities for the Decentraland Protocol. TL;DR; Pre-order using the entity tree defined by the UiTransform (ADR-124).

Specification

The UI entities are derived from a synthetic tree of entities defined by the UiTransformComponent (ADR-124). That entity should be rendered from the root to the leafs recursively using a pre-order sequencing.

That means the children will overwrite the pixels of the parent. This is a common practice, HTML, ReactNative and Unity's UiToolkit behave this way OOTB.

It MUST be possible to configure entities to act as stencil to only render what it is between the borders of the parent entity. The default behavior SHALL always be that children will be rendered in full even though are bigger than the borders of the parent.

TODO: create ADR for UiOverflowMode component

RFC 2119 and RFC 8174

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.

StaticEntities

Context

In order to facilitate communication between the renderer and the scenes, a special number of reserved entities are needed. These entities hold no special logic compared to other entities, but they have static IDs that systems can use to share information about the renderer, player, camera, etc.
Decision

We will reserve 512 static entities numbers, starting at 0. The "0" entity will be the root entity of the scenes, and all other entities will be parented to it by default.
List of static entities per scene

  • RootEntity = 0: It is the root of the scene.

    • The SceneInformation component (READ ONLY) of the root entity has the scene metadata (scene.json), the content mappings, and the scene id.
    • TBD: The ForeignEntitiesFrom { names: string[] } component is set from the scene itself and is used to signal the renderer about Foreign entity replication policies.
    • TBD: The ForeignEntitiesReservation { name: string, from: Entity, to: Entity } component is used to signal the renderer (or other actors) that this scene CAN share its entities as ForeignEntities.
    • The LoadingState { status = LOADING/RUNNING/PAUSED } component is set by the renderer.
    • TBD: The CommsState component is set by the kernel and used to query information about the current Comms connection (including realm).
  • PlayerEntity = 1: Represents the current player avatar.

    • The Transform component is READ/WRITE from the scene.
    • TBD: The PlayerPortableExperiences component (READ ONLY) contains information about the current portable experiences run by the user.
    • TBD: The PlayerIdentity component (READ ONLY) contains information about the Ethereum address, guest mode, and names of the player.
    • TBD: The (internal) AvatarShape component (READ ONLY) contains information about the wearables, hair, eyes and skin colors, and the equipped wearables.
  • CameraEntity = 2:

    • The Transform component is READ ONLY from the scene.
    • The PointerLocked component (READ ONLY) presence signals the status of the pointer-locking of the renderer.
    • The `WindowIdle`` component (READ ONLY) presence signals if the renderer is in background-mode or it is actively rendering.
    • The CameraMode { mode = ThirdPerson/FirstPerson } component is used to get the current camera mode; it is only set from the Renderer.

Consequences

By reserving a fixed number of static entities and assigning specific roles to them, we simplify the renderer-scene communication. This decision will make it easier for systems to share information about the renderer, player, camera, etc.

However, it is important to note that some of the components mentioned above are still TBD and may be subject to future revisions.

AMD Build & Global variables SDK7


adr: 130
title: Scene Compiler & Global variables SDK7
date: 2022-11-15
status: Idea
type: Standards Track
spdx-license: CC0-1.0
authors:

  • gonpombo8
  • menduz
  • leanmendoza

Abstract

This document describes the approach used to define which global variables are exposed in the SDK7, and how the scenes should be compiled in order to optimize the bundle of the scene.

Context, Reach & Prioritization

In the previous SDK, we had exposed a lot of global variables and they were bundled inside the ECS.
This is a problem for the final bundle size because even if you don't use any of that vars, they will be compiled inside the scene.
An example of this is the ecs-math library. We should import the vars that we want to use, and compile them only if we are using it (Tree Shaking).

Also we need to remove the AMD loader when we compile the scene, and use esbuild so we can enable tree shaking.
Tree shaking is a term to describe the removal of dead code.
Right now if you import a library inside your scene but you don't use a single line of that library, your scene will be bundled with the entire library code. Meaning a lot of extra kb that are not necessary.

Specification

Esbuild

Our current build tools for the web are 10-100x slower than they could be. The main goal of the esbuild bundler project is to bring about a new era of build tool performance, and create an easy-to-use modern bundler along the way.

Use esbuild to compile the scenes in order to optimize the final bundle size with tree shaking, and deprecate the current amd loader we have.
This was really useful but we reach a point were we need to improve the way the scenes are bundled. We are going to deliver a lot of new features, and systems inside our sdk-library and we need that the bundle size of the scenes contains only the code that is being used, instead of the entire library.

https://esbuild.github.io/

Global Variables

Remove unnecessary global vars that are exposed and bundled inside the SDK7.
We should export only the engine and the baseComponents as global variables of the scene.

Currently in the SDK7 we are importing the @dcl/ecs-math library and exporting all the vars as global variables.
This means that your scene will have all the @dcl/ecs-math code even if you don't use a single line of code.
We should remove all the ecs-math library and expose it as an external library, just like we do with @dcl/react-ecs

// game.ts
import { Vector3, Color3 } from '@dcl/ecs-math'
Transform.create(someEntity, { position: Vector3.create(0, 0, 0) } )

RFC 2119 and RFC 8174

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.

CRDT semantics to prevent cycles in Transforms


layout: adr
adr: 0 # replace this number for the PR or ISSUE number
title: Title of the ADR
date: 2020-02-20
status: Idea, Draft # pick one of these
type: Standards Track | Meta | RFC # pick one of these
spdx-license: CC0-1.0
authors:

  • menduz # this is your github username

remove the following line! it exists to render the template nicely

slug: /adr/TEMPLATE

Abstract

This document presents the problem of cyclic entities in an entity tree. Cycles are not compatible with how the rendering engines work since it is an unrepresentable and invalid state.

Context, Reach & Prioritization

Assuming the following valid messages:

  • Timestamp:0 EntityC.parent = EntityA
  • Timestamp:1 EntityA.parent = EntityB
  • Timestamp:2 EntityB.parent = EntityC
  • Timestamp:4 EntityC.parent = ROOT

The rules of CRDT allow us to derive a final state

0 ROOT
└──C
   └──B
      └──A

The problem

Assuming these messages will arrive in any order (thanks to the commutative property of CRDT), every implementation of Decentraland should reach the same final state without conflict. But partially or sequentially processing the shuffled messages, may render invalid intermediate states with cycles.

Most engines will fail and crash with such situation. And adding safeguards to the PUT messages will add way more complexity than anticipated to the renderer.

Solution Space Exploration

  1. Store all cycles and conflicting "PUT" operations, do not apply conflicting "PUT" operations and wait for the next update of any of the entities of the cycle to try to converge the state.
  2. Reject the CRDT operation if introduces cycles.

RFC 2119 and RFC 8174

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.

Semantics of entity parenting with ECS-compatible semantics


layout: adr
adr: 153
title: Semantics of entity parenting with ECS-compatible semantics
date: 2022-12-14
status: Living
type: Standards Track
spdx-license: CC0-1.0
authors:

  • menduz

Abstract

This document describes the semantics of changing parenting of entities and what happens when an entity in the middle of a branch of the tree is removed. The problem is complex because in an ECS approach, entities are stored in a flat structure, and trees are a synthetic construct for positioning purposes only. The decision is that when an entity in the middle of a branch is removed, all its children will be re-parented to the root entity.

Assumptions

  • When a Transform component doesn't exist in an entity, it is assumed that the entity has a scale={1,1,1}
  • Thus, it is safe to assume that a missing Transform component has the same rendering semantics than an entity with a Transform.Identity
  • And since entities are defined by the set of components and don't exist by themselves. It is safe to assume that all entities have an Transform.Identity by default.
  • Thus we can deduct that parenting an entity A with a parent B (which doesn't exist, because it doesn't have any components) should have the same semantics as parenting an entity A with a valid parent entity B with a Transform.Identity component

When an entity A is added to an entity B but the engine do not know about entity B

  • The engine MUST assume that the entity B is valid, even though "it doesn't exist" because no component is registered to it.
  • The assumption for the Transform component of the entity B is that the entity have a Transform.Identity component

When the engine is made aware about the real Transform component of entity B

  • It MUST change the default Transform.Identity and the change of the matrix calculation of all its children should take it into account.

Complex scenario

After creating and emparenting entities with explicit transform in the form:

ROOT_ENTITY
  └── A
      └── B
          └── C
              └── D
                  └── E
                      └── F
  • After removing the Transform component from entity D, the engine should assume entity D has a Transform.Identity component.
  • Since the Transform.Identity component has parent=ROOT_ENTITY, the rendering tree now looks like:
ROOT_ENTITY
  ├── A
  │   └── B
  │       └── C
  └── D
      └── E
          └── F

Appendix

Transform.Identity = {
  scale = {1,1,1}
  position = {0,0,0}
  rotation = {0,0,0,1}
  parent = ROOT_ENTITY
}

RFC 2119 and RFC 8174

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.

Back-end dependencies for the new Backpack V2


layout: adr
adr: 206
title: Back-end dependencies for the new Backpack V2
date: 2023-04-04
status: Review
type: ADR
spdx-license: CC0-1.0
authors:

  • sandrade-dcl
  • lorux0
  • davidejensen

Need

This is a technical proposal for the needs described here: PRD: Backpack V2

image

The intention of this document is:

  • Identifying which teams will be involved and what responsibilities they’ll cover.
  • Dividing the new functionality in smaller tasks that will be estimated accordingly in order to create a development roadmap.
  • Finding possible corner cases in order to preemptively identify and solve them.
  • Reaching a consensus between different affected teams in terms of defining the different functionalities and flows.

Involved teams

This initiative will require a cross team effort that will include the following teams:

  • Explorer: for the UI, UI functionalities and integration with the back-end side.
  • Platform: for the modification of the already existing lambdas endpoints in order to make them compatible with the new requirements (sorting wearables by different criteria, filtering them by different criteria, etc.) and/or the creation of new ones required.

Back-end dependencies

We currently have several lambdas endpoints (some of them compatible with pagination) that are already being used by the current version of the Backpack to retrieve the information about the wearables. These endpoints are:

  • Base Wearables: /lambdas/collections/wearables?collectionId=urn:decentraland:off-chain:base-avatars
  • Owned Wearables: /lambdas/users/:userId/wearables?includeDefinitions=true
  • Owned Emotes: /lambdas/users/:userId/emotes?includeDefinitions=true
  • Third Party Wearables by collection: /lambdas/users/:userId/third-party-wearables/:collectionId&includeDefinitions=true

We need to support the features in the lambdas. It is recommended to create new ones, to keep retro-compatibility, but we leave the decision to the @platform team.

Filter WEARABLES by collection

In order to give the user the possibility of seeing and managing any type of wearables (BASE, OWNED and THIRD PARTY) together in the backpack, we would need to receive all the information from a single endpoint instead of having to request them separately.

These will be the filters available in the UI to filter the wearables:

Show BASE WEARABLES ON/OFF

image

Select 1 or more COLLECTIONS ("decentraland" would be the owned wearables and any other would belong to TPW)

image

In order to be able to manage these filters, we will need an endpoint where we can specify a list of collection ids (either "Decentraland", "urn:decentraland:off-chain:base-avatars" or any third party collection) and return the list of wearables that match with those collections.

Examples:

Only owned collection
/lambdas/users/:userId/wearables?includeDefinitions=true&collectionIds=decentraland
Only base collection
/lambdas/users/:userId/wearables?includeDefinitions=true&collectionIds=urn:decentraland:off-chain:base-avatars
Several third party collections
/lambdas/users/:userId/wearables?includeDefinitions=true&collectionIds=urn:decentraland:matic:collections-thirdparty:cryptoavatars,urn:decentraland:matic:collections-thirdparty:kollectiff,...
Any combination
/lambdas/users/:userId/wearables?includeDefinitions=true&collectionIds=decentraland,urn:decentraland:off-chain:base-avatars,urn:decentraland:matic:collections-thirdparty:cryptoavatars,urn:decentraland:matic:collections-thirdparty:kollectiff,...

Filter EMOTES by collection

In order to give the user the possibility of seeing and managing any type of emotes (BASE or OWNED) together in the backpack, we would need to receive all the information from a single endpoint instead of having to request them separately.

This will be the filter available in the UI to filter the emotes:

Show BASE EMOTES ON/OFF

image

In order to be able to manage these filters, we will need an endpoint where we can specify a list of collection ids (either "decentraland" or "base") and return the list of emotes that match with those collections.

Examples:

Only owned collection
/lambdas/users/:userId/emotes?includeDefinitions=true&collectionIds=decentraland
Only base collection
/lambdas/users/:userId/emotes?includeDefinitions=true&collectionIds=base
Any combination
/lambdas/users/:userId/emotes?includeDefinitions=true&collectionIds=decentraland,base

Filter WEARABLES/EMOTES by text

The user will be able to filter the wearables/emotes by text.

image

In order to be able to do it, we will need to add a new parameter to the existing endpoints that will be used to specify a text and return the list of wearables that match with that text. The new parameter will be called textFilter and will be a string that will accept any value.

In order to be able to manage this filter, we will need an endpoint (the same described in the previous sections) where we can specify a text and return the list of wearables that match with that text.

Examples:

Filter any combination of wearables by text
/lambdas/users/:userId/wearables?includeDefinitions=true&collectionIds=decentraland,urn:decentraland:off-chain:base-avatars,urn:decentraland:matic:collections-thirdparty:cryptoavatars,urn:decentraland:matic:collections-thirdparty:kollectiff&textFilter=aviator
Filter any combination of emotes by text
/lambdas/users/:userId/wearables?includeDefinitions=true&collectionIds=decentraland,base&textFilter=chic

Filter WEARABLES by category

The user will be able to filter the wearables by category.

image

In order to be able to manage this filter, we will need an endpoint (the same described in the previous sections) where we can specify the category and return the list of wearables that match with that category.

Examples:

Filter any combination of wearables by category
/lambdas/users/:userId/wearables?includeDefinitions=true&collectionIds=decentraland,urn:decentraland:off-chain:base-avatars,urn:decentraland:matic:collections-thirdparty:cryptoavatars,urn:decentraland:matic:collections-thirdparty:kollectiff&category=hat

Sort WEARABLES/EMOTES

The user will be able to sort the wearables/emotes by different criteria: newest/oldest, rarest/less rare or name A-Z/name Z-A.

image

In order to be able to manage this sorting, we will need an endpoint (the same described in the previous sections) where we can specify the sorting criteria and return the list of wearables sorted by that criteria. The sorting parameter will be a string that will accept the following values:

  • newest
  • oldest
  • rarest
  • less_rare
  • name_a_z
  • name_z_a

In cases where wearables or emotes dont have minted timestamps, they should be added at the bottom of the list.

Examples:

Sort any combination of wearables by rarest
/lambdas/users/:userId/wearables?includeDefinitions=true&collectionIds=decentraland,urn:decentraland:off-chain:base-avatars,urn:decentraland:matic:collections-thirdparty:cryptoavatars,urn:decentraland:matic:collections-thirdparty:kollectiff&sort=rarest
Filter any combination of emotes by name A-Z
/lambdas/users/:userId/wearables?includeDefinitions=true&collectionIds=decentraland,base&sort=name_a_z

Get wearable market details (NEW ENDPOINT)

The user will be able to click on a wearable and open a modal with some details as:

  • Creator (optional): Name and image of the creator of the wearable.
  • Collection (optional): Name and image of the collection where the wearable belongs to.
  • Network: Network where the wearable is deployed.
  • Contract address: Address of the contract where the wearable is deployed.
  • Latest sales: List of the latest sales of the wearable. It would be a list of the following information:
    • From: Name and image of the seller.
    • To: Name and image of the buyer.
    • Type: Type of the transaction (Transfered or Minted).
    • When: Date of the transaction.
    • Price: Price of the transaction.
  • Minting number and total scarcity (optional): Minted number + total amount of NFTs of this wearable.

image

To be able to request this information, the client will have to use the minted id instead of the generic id. This information is available when querying the wearables.
In order to be able to get this info, we will need to create a new endpoint that will return the details of a specific wearable:

Example:

Get market details of a specific wearable
/lambdas/wearables/:wearableId/market-details

Get a random list of equipped wearables (NEW ENDPOINT)

The user will be able to click on a [RANDOMIZE] button and equip a random list of wearables on his avatar.

image

In order to be able to do it, we will need to create a new endpoint that will return a random list of wearable ids from the owned wearables of the user.
The wearables must be from each category, avoiding conflicts with hides and replaces whenever possible.

Example:

Get random wearables of a specific user
/lambdas/users/:userId/random-wearables

Outfits

image

The outfit information should be stored in the catalyst because we need to support multi-platform.

On the other hand, we should avoid storing it in profiles since it is information that only each individual user needs and does not need to be shared with other users.
Adding it to the profiles would add an additional data transfer for each request unnecessarily.

Update: The outfit information will be stored in the user profile.

Regarding to the outfit image previews, they can be generated in the client when saving the outfit.
There is no need to store the images in the catalysts.

We may encounter the need of checking that the wearables in the outfit are valid for the current user. (What happens if the user does not have the wearable anymore?)

Equip/save wearables

image

We though about several alternatives to avoid performance issues by saving the profile every time you equip an item:

  1. Equip all the items and only when the backpack is closed, make the request to save the profile.
  2. The profile will be updated/saved in intervals of 20 seconds (to be defined) or whenever the user closes the backpack.
  3. Save the profile when the user equips a wearable.

Saving the profile would mean that the nearby users will be able to see the changes as soon as possible.

Update: we will go for option 1, taking in consideration that we cant save the profile during the quitting of the application. It will only be saved when closing the backpack, just like the "save" button worked before.

Emotes pagination

image

We will need to refactor the current emotes catalog, the same way on how we did on wearables catalog, so its supports pagination.
We will also reduce kernel responsibilities, moving all (or most) of the emote handling in the renderer.
No need backend support.
Open ticket: #4429

BackpackEditorV2

In Unity we are going to implement a new UI for the backpack v2 requirements, including all the components needed.

We will keep retro-compatibility with the old one, including the UI, service calls and dependencies.

Open questions

  1. We need to define an approach on how to request/store the outfits information for every user (ref: outfits). Its going to be stored in the user profile.
  2. We need to discuss and define an approach on when we should save the profile (ref: equip/save wearables). Option 1.
  3. Is the preview image generation for outfits going to be a suitable approach? (ref: outfits). Yes, it will be done in the client.
  4. In order to query market details for every wearable, we need to solve the specific minted wearableId (now the client uses the generic one). In case the user has many wearables of the same generic id, how are we going to display the information?
  5. The randomizer will need a bounded scope because querying the whole wearables that the user may have would be too expensive. Is it ok that the randomized result is smaller?
  6. Is it necessary that the nearby users see the avatar changes as soon as you equip a wearable in the backpack? Taking in consideration that we will go for option 1, the nearby users will only see the avatar changes when closing the backpack, very similar on how it works today.

Document visual UI components for new SDK


adr: 125
title: User interface components for SDK 7
date: 2022-11-14
status: Idea
type: Standards Track
spdx-license: CC0-1.0
authors:

  • menduz

Abstract

This specification covers an initial set of components of the SDK to create flexbox-based user interfaces. The components only describe behavior and configuration skipping position and sizing, that is considered layouting and is given by the UiTransform component from ADR-124.

Context, Reach & Prioritization

... initial elements required for feature parity ...

Specification

PointerEvents component

We are going to reuse the existing PointerHoverFeedback component, but with another name (HoverFeedback is not the most accurate name IMO).
We are going to use this component to tell the renderer which entities are going to be clickable/hover, etc.

enum PointerEventType {
  PET_UP = 0;
  PET_DOWN = 1;
  PET_HOVER_ENTER = 2;
  PET_HOVER_LEAVE = 3;
}

// We can talk about this name 
message PBPointerEvents {
  message Info {
    optional common.InputAction button = 1; // default=InputAction.ANY
    optional string hover_text = 2; // default='Interact'
    optional float max_distance = 3; // default=10
    optional bool show_feedback = 4; // default=true
  }

  message Entry {
    PointerEventType event_type = 1;
    Info event_info = 2;
  }

  repeated Entry pointer_events = 1;
}

PointerEventsResult component

We are going to use the same component that we are currently using for 3D objects, so we can reuse the same logic and we dont to manage multiple messages that does the same.

This pointerEventResult message has a lot of props that we are not going to use inside the Hit prop, but since they can all be undefined, we can only send the entity and it'll be ok.

message PBPointerEventsResult {
  // a list of the last N pointer commands (from the engine)
  repeated PointerCommand commands = 1;

  // this message represents a pointer event, used both for UP and DOWN actions
  message PointerCommand {
    common.InputAction button = 1; // identifier of the input
    RaycastHit hit = 2;
    PointerEventType state = 4;
    int32 timestamp = 5; // could be a Lamport timestamp
    optional float analog = 6; // if the input is analog then we store it here
  }
}

UiText component

To all extents, it is a reusable label for the UI.

message PBUiText {
  string value = 1;
  optional decentraland.common.Color4 color = 2; // default=(1.0,1.0,1.0,1.0)
  TextAlignMode text_align = 3;
  Font font = 4; // default=0 - SansSerif
  optional int32 font_size = 5; // default=10
}

UiBackground component

Sets the background of a UI element. By default it has a transparent color. It can specify a 9-slices texture. When a texture and a color are specified, the color multiplies the texture to enable easy customization of UI elements in different states i.e. active, focused, highlighted.

message PBUiBackground {
  // default=(0.0, 0.0, 0.0, 0.0)
  optional decentraland.common.Color4 color = 1;

  // texture for the background
  optional Texture texture = 2;

  // texture mode
  BackgroundTextureMode texture_mode = 3;

  // texture_slices, represents the top | right | bottom | left sizes of the
  // slices for the borders. values are percentages of the texture.
  // default=(1/3,1/3,1/3,1/3)
  optional Rect texture_slices = 4;

  // when STRETCH is selected, the uvs are configurable
  // default=default plane uvs
  optional repeated float uvs = 5;
}

enum BackgroundTextureMode {
  // https://docs.unity3d.com/Manual/9SliceSprites.html
  // https://developer.mozilla.org/en-US/docs/Web/CSS/border-image-slice
  // https://forum.unity.com/threads/how-does-slicing-in-ui-tookkit-works.1235863/
  NINE_SLICES = 0; (default)

  // CENTER enables the texture to be rendered centered in relation to the
  // element. If the element is smaller than the texture then the background
  // should use the element as stencil to cut off the out-of-bounds area
  CENTER = 1;

  // STRETCH enables the texture to cover all the area of the container,
  // adopting its aspect ratio. It takes the UVs from the uvs field 
  STRETCH = 2;
}

UiButton component

UiButton can be implemented with a UiText+UiTransform+UiBackground to start.

UiInput

UiInput adds an editable behavior to the UiEntity. By default it can render a placeholder label.

message UiInput {
  // placeholder text
  optional string placeholder = 1;

  // color of the text
  // default=(0.0,0.0,0.0,1.0)
  optional decentraland.common.Color4 color = 2;

  // color of the placeholder text
  // default=(0.3,0.3,0.3,1.0)
  optional decentraland.common.Color4 placeholder_color = 3;

  // makes it non-interactable
  bool disabled = 4;

  // text align
  TextAlignMode text_align = 10;
  // font family default=0 - SansSerif
  Font font = 11;
  // font size default=10
  optional int32 font_size = 12;
}

message UiInputResult {
  string value = 1
  // Maybe we can add some state info of the input here such as Focused/Selected etc ?
}

UiDropdown

message UiDropdown {
  // does this accept an empty selection?
  // a.k.a "null" state
  bool accept_empty = 1;

  // placeholder for "null" state
  optional string empty_label = 2;

  // list of strings
  repeated string options = 3;

  // default=-1 when accept_empty==true
  // default=0 when accept_empty==false
  int32 selected_index = 4;

  // makes it non-interactable
  bool disabled = 4;

  // text align
  TextAlignMode text_align = 10;
  // font family default=0 - SansSerif
  Font font = 11;
  // font size default=10
  optional int32 font_size = 12;
}

message UiDropdownResult {
  int32 value = 1
}

RFC 2119 and RFC 8174

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.

Realm resolution from connection string


layout: adr
adr: 144
title: Realm resolution from connection string
date: 2022-12-13
status: Review
type: Standards Track
spdx-license: CC0-1.0
authors:

  • menduz

Abstract

This document describes the Realm resolution algorithms to consistently resolve servers based on a realm connection string. It resembles DNS, and uses the DAO catalysts, ENS and URLs to resolve the realms as described in ADR-110.

Context, Reach & Prioritization

Realms (ADR-110) are the configurations that define what and how is executed and rendered in a Decentraland Explorer ADR-102. If we reason by analogy and consider an Explorer like a Web Browser, and the Scenes like WebSites. Then the Realm is the URL of that site.

Specification

Realm are represented as strings. Those strings need to be resolved to a /about endpoint to fetch the configuration.

The mechanism to resolve that endpoint is:

  1. If the string is an URL, then it uses the URL
  2. If the string equals to the name of a DAO catalyst, then it picks the URL of the Catalyst like https://peer.decentraland.org/about
  3. If the string is an ENS, then it resolves using ENS dcl.realm TXT values
    1. If no values are defined for the ENS-DNS and it is a .dcl.eth subdomain, then it falls back to the Worlds resolver
  4. If this point is reached, then the realm is invalid.

ENS resolver

NAME and ENS holders can decide where their worlds are hosted. For that purpose, a special record dcl.realm can be added both to ENS and NAME tokens and it should resolve to a base URL that is compliant with the Realm specification (ADR-110)

Worlds resolver

Worlds is a configuration of services that enable deploying Decentraland scenes using NAME, as described in ADR-111. To resolve Worlds, an URL in the shape of https://worlds-content-server.decentraland.org/world/<NAME>.dcl.eth is used, the /about response is compliant with the Realm specification (ADR-110)

RFC 2119 and RFC 8174

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.

Remove assets from Renderer's build


layout: adr
adr: 175
title: Remove assets from Renderer's build
date: 2023-01-16
status: Idea
type: ADR
spdx-license: CC0-1.0
authors:

  • ajimenezDCL

Abstract

This document describes an approach on how to make the reference's client lightweight by streaming the currently embedded assets.

Glossary

  • Asset Bundle : Unity's proprietary system to pack assets that can be consumed in runtime (without going through importing).
  • Addressables : Unity's new abstraction layer to deal with remote assets.

Problem

Every nice UI, sound effect, particle or material we add to the renderer increases its size. This directly impact loading times or caching since the client's size will go above the max allowed for it. The idea is to pack textures and audio files and stream them in runtime.

Solution

Pack the Assets

Similar to what we are doing with scene assets, we can pack everything into one or multiple (to always be under the cache size limit) asset packs to be consumed by the client. This solution should be part of a different system than the one used for scene assets; therefore we can evaluate using an alternative like Addressables for consuming the assets.

  • Asset bundle: We have lot of built in tools to deal with ABs, we can make use of them to get all the packages when loading the experience.
  • Addressable: Unity's new API to consume streamed resources theoretically provides a seamless layer of abstraction that would allow the client to work with assets and textures as if they were local.

Regardless of the bundling approach, a CI job (within the same pipeline) can be developed as a part of the building process. It would take the assets, pack them and upload them to the server.

Retrocompatibility and Versioning

Currently the renderer is a self-contained experience; to run any renderer you just need a compatible kernel and catalyst; it should be the same for the assets packs.

Getting your compatible Asset Pack

A handful of solutions can be implemented to ensure that a version of the Renderer consumes its asset packs counterpart. All of them would require versioning the packs so the client can distinguish them by name/endpoint/path. At building time a manifest with this information can be placed in StreamingAssets to be consulted in runtime.

Open Questions:

  • Addressables or Asset Bundles?
  • CI's tasks breakdown to deliver the feature?
  • How to make the renderer aware of what version to consume.

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.

[WIP] Avatar Assembly Changes ADR

layout: adr
adr: 239
title: Avatar Assembly Changes
date: 2023-05-23
status: Draft
type: Standards Track
spdx-license: CC0-1.0
authors:
@davidejensen @olavra

Abstract

Context, Reach & Prioritization

Previously, the avatar system has been unreliable and limited over different aspects.
To increase users freedom, create a reliable, flexible and scalable system the following changes will be applied:

  • Wearable Visualization Priority: A prioritization order will be defined for wearable visualization to resolve issues of mutual exclusion.
  • Hiding and Replacing: The replacement system will be modified so that a wearable cannot replace another.
  • Body Fallback: From now on, some categories will show parts of the base body when no wearable is equipped or hiding it.
  • Force Render: Users will be given more ability to show a wearable that is hidden by another.

The different decisions will become the standard base for Decentraland Avatar Assembly System, initially applied in the unity reference client, but then proposed to any external platform that uses the Decentraland avatars.

Solution Space Exploration

Wearable Visualization Priority

Previously the hiding and replacing functionality was following a rule of "Last equipped", meaning that replaces and hides were applied based on the last wearable equipped, creating discrepancy and an inconsistent behaviour. Additionally it was not solving situations of mutual hiding (wearable A hiding B and B hiding A)
To standardize this an ordered list of categories will be followed to calculate which wearables are hiding which.
The proposed priority list is (from most important to least):

  • Skins
  • Top Body
  • Bottom Body
  • Shoes
  • Helmets
  • Masks
  • Hats
  • Top Head
  • Hair
  • Tiaras
  • Eyewear
  • Earrings

All elements associated with the face, such as the mouth, eyes, and eyebrows, directly depend on the visualization of the head. The head is not a wearable itself, so it cannot create circular references, and it is hidden as soon as one or more wearables determine it.

The following example illustrates the expected behavior: If a wearable of type "Mask" hides another wearable of type "Hat", and this in turn hides wearables of type "Mask", the wearable of type "Mask" will have visualization priority, hiding the Mask.

Hiding and replacing

The current result of equipping an item that replaces or hides other wearables is unexpected and inconsistent. When a player navigates through their inventory items, as they equip, unequip, or hide other wearables from other categories without notice, they cannot reverse this behavior when equipping a different wearable.
When a wearable unequips another wearable, the latter could be running a portable experience. By deactivating it, any progress or data in memory could be lost, ruining its expected behavior.
The decision-making capacity of creators is overlapping with the freedom of choice of players. When a player purchases a wearable, thinking it will combine well with what they already have in their inventory, they may be unpleasantly surprised that these are not compatible. Information about which other wearables are replaced or hidden is not clearly indicated in the marketplace or backpack.
There is no real weighty reason for a wearable to unequip another wearable, instead of hiding it to prevent clipping problems.

On the base of that the replacing functionality for new wearables will be removed, pre-existing wearables will see the replacing list being merged with the hiding list.

Body fallback

Previously, by unequipping the upper_body, the lower_body, the feet or the eyebrows, caused the system to fallback to default wearables (t-shirt, pants and shoes).
This prevents, for example, players from going barefoot or without t-shirt.

The system will extent the concept of Body by removing the default fallback wearables.
These pieces, which can be called "Bare feet", "Naked Top" and "Naked Bottom", are not considered wearables, but rather parts of the base body geometry that are exclusively displayed when no wearables are equipped and there are no other wearables hiding the relevant category.

The base body geometry and textures will change to make them more suitable for an environment for all audiences.

Force Render

To extend further players ability to use the wearables they have in all their glory. If an equipped wearable is hidden by the effect of another wearable, players can unhide them and override this instruction.
This forced render effect is removed as soon as another wearable that re-hides that category is equipped, forcing the user to show it again.

In order to store the force render categories, it is proposed to add a new field to the player profile holding a list of overridden hide categories.
This list of string will hold the current overridden categories so that each player can render other players (and itself) according to the new rules.
As an example:

"forceRender": ["mask","top_head","feet"]

This example means that when the avatar is going to be assembled the "mask", "top_head" and "feet" categories will be shown even if other wearables are hiding them.

Here's the avatar definition with the additional forceRender field that will be provided:

{
   "timestamp":1684839566179,
   "avatars":[
      {
         "hasClaimedName":true,
         "description":"",
         "tutorialStep":256,
         "name":"Username",
         "avatar":{
            "bodyShape":"urn:decentraland:off-chain:base-avatars:BaseMale",
            "wearables":[
               "urn:decentraland:off-chain:base-avatars:eyebrows_00",
               "urn:decentraland:off-chain:base-avatars:mouth_00",
               "urn:decentraland:off-chain:base-avatars:casual_hair_01",
               "urn:decentraland:off-chain:base-avatars:beard",
               "urn:decentraland:matic:collections-v2:0xc11b9d892e12cfaca551551345266d60e9abff6e:1",
               "urn:decentraland:matic:collections-v2:0x84a1d84f183fa0fd9b6b9cb1ed0ff1b7f5409ebb:5",
               "urn:decentraland:ethereum:collections-v1:halloween_2020:hwn_2020_ghostblaster_tiara",
               "urn:decentraland:ethereum:collections-v1:halloween_2020:hwn_2020_cat_eyes",
               "urn:decentraland:off-chain:base-avatars:piratepatch",
               "urn:decentraland:matic:collections-v2:0xca7c347ffdeee480092f3b1268550b60ea031077:4",
               "urn:decentraland:matic:collections-v2:0x2a3a6d0c92b18102ed189233976c974473a59c87:0"
            ],
            "forceRender":["mask","top_head","feet"]
            "emotes":[
               {
                  "slot":0,
                  "urn":"raiseHand"
               },
               {
                  "slot":1,
                  "urn":"urn:decentraland:matic:collections-v2:0x167d6b63511a7b5062d1f7b07722fccbbffb5105:0"
               },
               {
                  "slot":2,
                  "urn":"urn:decentraland:matic:collections-v2:0x875146d1d26e91c80f25f5966a84b098d3db1fc8:1"
               },
               {
                  "slot":3,
                  "urn":"urn:decentraland:matic:collections-v2:0x875146d1d26e91c80f25f5966a84b098d3db1fc8:2"
               },
               {
                  "slot":4,
                  "urn":"urn:decentraland:matic:collections-v2:0x875146d1d26e91c80f25f5966a84b098d3db1fc8:0"
               },
               {
                  "slot":5,
                  "urn":"headexplode"
               },
               {
                  "slot":6,
                  "urn":"tektonik"
               },
               {
                  "slot":7,
                  "urn":"clap"
               },
               {
                  "slot":8,
                  "urn":"handsair"
               },
               {
                  "slot":9,
                  "urn":"dance"
               }
            ],
            "snapshots":{
               "body":"https://interconnected.online/content/contents/bafkreihhwboio77zsl6evt6i3f5iun5ek65w7dyuvl44xwk33zts4qx2v4",
               "face256":"https://interconnected.online/content/contents/bafkreiddnf2ixknlhio4hk7ao47agiwkqs43cg3nkoyibckgmhz5iqn3he"
            },
            "eyes":{
               "color":{
                  "r":0.529411792755127,
                  "g":0.501960813999176,
                  "b":0.47058823704719543,
                  "a":1
               }
            },
            "hair":{
               "color":{
                  "r":0.10980392247438431,
                  "g":0.10980392247438431,
                  "b":0.10980392247438431,
                  "a":1
               }
            },
            "skin":{
               "color":{
                  "r":0.800000011920929,
                  "g":0.6078431606292725,
                  "b":0.46666666865348816,
                  "a":1
               }
            }
         },
         "ethAddress":"0x1hd7fl09yivcn7z6asc0a8af9c3b1ba28hdy65sd",
         "userId":"0x1hd7fl09yivcn7z6asc0a8af9c3b1ba28hdy65sd",
         "version":12,
         "hasConnectedWeb3":true
      }
   ]
}

Avatar assembly suggested flow

With the points previously discovered, the suggested procedure to visualize an avatar is the following:

  • Request a user profile ( https://catalyst/lambdas/profile/address )
  • Request the wearables listed in the profile wearables field, all wearables listed are the equipped ones, no matter their visibility. ( https://catalyst/lambdas/collections/wearables?wearableId=urnId )
  • Process the hide list provided in each wearable following the visualization priority ( the field is the array data.hides in each wearable definition )
  • Apply any force render category listed in the forceRender array in the profile definition ( obtained in the profile response called forceRender )

CRDTs: State synchronization and renderer

Abstract

This document intention is to describe the current problem with the synchronization of state of scenes and renderer and therefore, the evaluated alternatives and options to deal with these specific issues through different CRDT algorithms in order to optimize performance by preserving and reproducing 'user intention' in a more consistent and reasonable way.

Finding the right problem ADR-114 solves (fka RFC-14)

This is a follow up issue to discuss and continue adding comments to the RFC-14.

It describes:

  • A mechanism to direct messages in a mesh mocking BGP
  • A fallback mechanism to ensure messages arrive in case of failure of the former

Although the first may be sound in the void, RFC-4 describes that all communications inside a room/island/adapter are designed to be broadcasted. Rendering the routing logic pointless. And adding a fallback to begin with seems like starting with the wrong foot.

This issue is to challenge to get to a problem to fix, before proposing a solution.

A proposal to frame the problem would be:

Decentraland communication adapters are varied in capabilities and costs (from WebSockets, to Livekit to name a few.) but a low-cost solution that works everywhere is still needed. The current version of "comms" uses an P2P incomplete mesh with gossip replication of messages to achieve pseudo full-mesh capabilities. One of the identified problems with this incomplete mesh is that the organization of the connections may lead to local clusters which play against the intended design. That is so, because connections are created at random and refreshed at high intervals (within the 10s seconds).

Statement of the problem:
Find a P2P adapter that enables lightweight (cheap) communications in incomplete meshes, to work as fallback when all other adapters are not available.

  • It must require no extra fallback services (besides STUN, TURN and signaling, which are needed to fully support WebRTC)
  • It must ensure that the connections don't form local clusters
  • It must ensure that there are bi-directional communication paths between any A and B peers in the mesh
  • It should prioritize to always have short paths (fewer than X hops) between any A and B peers in meshes of 100 peers
  • The overhead traffic of the protocols (signaling, message metadata, synchronization messages) should be minimum

Metrics for success:

  • Ping responses. In any given mesh of N known peers, a Ping message should receive N responses before the 10second mark (this interval should lower with the evolution of the protocol). Store this number in a histogram to track progress.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.