Player data

Track player position and rotation

The Camera object exposes information about the player’s point of view in your scene.

  • Camera.instance.position returns a 3D vector with the coordinates of the player’s center, relative to the scene. When the player is on the ground, the height of this point is aproximately 1.177 m.
  • Camera.instance.feetPosition returns a 3D vector with the coordinates of the player’s feet, relative to the scene.
  • Camera.instance.worldPosition returns a 3D vector with the coordinates of the player’s center, relative to the whole of Genesis City. For example, if the scene is in coordinates 100,-100, and the player is standing on the bottom-left corner of that scene, the player’s world position will be about 1600, 1.177, -1600
  • Camera.instance.rotation returns a quaternion with the player’s rotation.
  • Camera.instance.eulerAngles returns a Vector3 with the player’s rotation.
log(Camera.instance.feetPosition)
log(Camera.instance.rotation.eulerAngles)

The example above logs the player’s position and rotation.

class CubeRotateSystem implements ISystem {
  entity: Entity
  constructor(entity: Entity) {
    this.entity = entity
  }

  update() {
    const transform = this.entity.getComponent(Transform)
    transform.rotation = Camera.instance.rotation
  }
}

const cube = new Entity()
cube.addComponent(new BoxShape())
cube.addComponent(new Transform({ position: new Vector3(5, 1, 5) }))
engine.addEntity(cube)

engine.addSystem(new CubeRotateSystem(cube))

The example above uses the player’s rotation to set that of a cube in the scene.

Note: The Camera.instance.position data is updated at a throttled rate of 10 times per second. Due to this, positions may lag slightly in relation to the scene that runs at 30 FPS under ideal conditions.

Check the player’s camera mode

Players can either be using a 1st or 3rd person camera when exploring Decentraland. Check which of these the player is using by checking the value Camera.instance.cameraMode.

The value of this property can either be CameraMode.FirstPerson or CameraMode.ThirdPerson.

if (Camera.instance.cameraMode == CameraMode.FirstPerson) {
  log("The player is using the 1st person camera")
} else {
  log("The player is using the 3rd person camera")
}

The Camera.instance.cameraMode property is read only, you can’t force the player to change camera mode.

Tip: To encourage players to use a particular camera mode in your scene, display a UI message advising them to switch modes whenever they use the wrong one.

Knowing the camera mode can be very useful to fine-tune the mechanics of your scene to better adjust to what’s more comfortable using this mode. For example, small targets are harder to click when on 3rd person.

Tip: Whenever the player changes camera mode while in or near your scene, this creates an event that you can listen to. See Event Listeners

Get player’s public Ethereum key

You can obtain a player’s public Ethereum key by using getUserPublicKey(). You can then use this information to send payments to the player, or as a way to recognize players.

The example below imports the Identity library and runs getUserPublicKey() to get the public key of the player’s Ethereum account and log it to console. The player must be logged into their Metamask account on their browser for this to work.

import { getUserPublicKey } from "@decentraland/Identity"

const publicKeyRequest = executeTask(async () => {
  const publicKey = await getUserPublicKey()
  log(publicKey)
  return publicKey
})

Note that we’re using an async function to run the getUserPublicKey() function, as it might take some time to retrieve this data. We’re then handling the data in a system, to be able to use it whenever it’s ready.

Get the essential player data

You can obtain a player’s display name and public Ethereum key by using getUserData().

The example below imports the Identity library and runs getUserData().

import { getUserData } from "@decentraland/Identity"

const userData = executeTask(async () => {
  const data = await getUserData()
  log(data.displayName)
  return data.displayName
})

NOTE: This won’t work when running a local preview, since you’re not authenticated while running a preview. But once the scene is deployed to Decentraland, the player’s data will be readable by this code.

Here we’re using an async function to run the getUserData() function, as it might take some time to retrieve this data. We’re then handling the data in a system, to be able to use it whenever it’s ready.

The getUserData() function returns the following information:

  • displayName: (string) The player’s user name, as others see in-world
  • userId: (string) A UUID string that identifies the player. If the player has a public key, this field will have the same value as the public key.
  • publicKey: (string) The public key of the player’s Ethereum wallet. If the player has no linked wallet, this field will be null.
  • hasConnectedWeb3: (boolean) Indicates if the player has a public key. True if the player has one.

Note: For any Ethereum transactions with the player, always use the publicKey field, instead of the userId.

Get player realm data

Players in decentraland exist in many separate realms. Players in different relms cant see each other, interact or chat with each other, even if they’re standing on the same parcels. Dividing players like this allows Decentraland to handle an unlimited ammount of players without running into any limitations. It also pairs players that are in close regions, to ensure that ping times between players that interact are acceptable.

If your scene sends data to a 3rd party server to sync changes between players in real time, then it’s important that changes are only synced between players that are on the same realm. You should handle all changes that belong to one realm as separate from those on a different realm. Otherwise, players will see things change in a spooky way, without anyone making the change.

import { getCurrentRealm } from "@decentraland/EnvironmentAPI"

const playerRealm = executeTask(async () => {
  let realm = await getCurrentRealm()
  log(`You are in the realm: ${JSON.stringify(realm.displayName)}`)
  return realm
})

Decentraland handles its communications between players (including player positions, chat, messageBus messages and smart item state changes) through a decentralized network of communication servers. Each one of these servers can support multiple separate layers, each with a different set of players. Each one of these layers in a server is a separate realm.

The getCurrentRealm() function returns the following information:

  • displayName: (string) The full address of the relm, composed of the server + the layer
  • domain: (string) The URL of the server
  • serverName: (string) The name of the server
  • layer: (string) The name of the layer

Fetch more player data

Make a REST API call to the following URL, to obtain info about the player from the content server. Besides obtaining the player name, and wallet (which you can also obtain through userData) you can also find a full list of all the wearables that the player owns and all the wearables that the player is currently wearing. You can also find the player’s base body shape (male of female avatar), and snapshots of the avatar’s face and body in .jpg format.

This feature could be used, for example, to only allow players that are wearing a special wearable item into a place.

This information is exposed in the following URL, appending the player’s user id to the url parameter.

https://peer.decentraland.org/lambdas/profile/<player user id>

Tip: Try the URL out in a browser to see how the response is structured.

To get more real time data about the player, you can query that same information but directly from the same server that the player is currently on. For example, if the player changes clothes, this information will be available instantly in the player’s server, but will take a couple of minutes to propagate to the peer.decentraland.org server.

https://<player server>/lambdas/profile/<player user id>

Tip: You can obtain the player’s server by doing getCurrentRealm().domain.

This example combines getUserData() and getCurrentRealm() to obtain the player’s data directly from the server that the player is on:

import { getUserData } from "@decentraland/Identity"
import { getCurrentRealm } from "@decentraland/EnvironmentAPI"

async fetchPlayerData() {
    const userData = await getUserData()
    const playerRealm = await getCurrentRealm()

    let url = `{playerRealm.domain}/lambdas/profile/{userData.userId}`.toString()
	log('using URL: ', url)

      try {
		let response = await fetch(url)
		let json = await response.json()

		log('full response: ', json)
		log('player is wearing :', json[0].metadata.avatars[0].avatar.wearables )
		log('player owns :', json[0].metadata.avatars[0].inventory)

	  }
	  catch {
		log("an error occurred while reaching for player data")
	  }
}

fetchPlayerData()

Get detailed info about all wearables

Make a REST API call to the following URL, to obtain a full updated list of all wearables that are currently usable, with details about each.

https://dcl-wearables-dev.now.sh/expected.json

This feature could be used together with fetching info about the player, to for example only allow players to enter a place if they are wearing any wearable from the halloween collection, or any wearable that is of legendary rarity.

Tip: Try the URL out in a browser to see how the response is structured.

fetchWearablesData() {
    let url = `https://dcl-wearables-dev.now.sh/expected.json`

    executeTask(async () => {
      try {
        let response = await fetch(url)
        let json = await response.json()
        log('full response: ', json)
	  }
	  catch {
		log("an error occurred while reaching for wearables data")
	  }
	})

fetchPlayerData()