Event listeners
There are several events that the scene can subscribe to, to know the actions of the player while in or near the scene.
For button and click events performed by the player, see Button events .
Player enters or leaves scene #
Whenever an avatar steps inside or out of the parcels of land that make up your scene, or teleports in or out, this creates an event you can listen to.
This event is triggered by all avatars, including the player’s.
import { onEnterScene, onLeaveScene } from '@dcl/sdk/src/players'
export function main() {
onEnterScene((player) => {
if (!player) return
console.log('ENTERED SCENE', player)
})
onLeaveScene((userId) => {
if (!userId) return
console.log('LEFT SCENE', userId)
})
}
On the onEnterScene
event, the function can access all of the data returned by
get player data
via the player
property.
On the onLeaveScene
event, the function only has access to the player’s ID.
Only current player #
You can filter out the triggered events to only react to the player’s avatar, rather than other avatars that may be around.
import { getPlayer, onEnterScene, onLeaveScene } from '@dcl/sdk/src/players'
export function main() {
let myPlayer = getPlayer()
onEnterScene((player) => {
if (!player) return
console.log('ENTERED SCENE', player)
if (myPlayer && player.userId == myPlayer.userId) {
console.log('I CAME IN')
}
})
onLeaveScene((userId) => {
if (!userId) return
console.log('LEFT SCENE', userId)
if (myPlayer && userId == myPlayer.userId) {
console.log('I LEFT')
}
})
}
This example first obtains the player’s id, then subscribes to the events and compares the userId
returned by the event to that of the player.
Query all players in scene #
Go over the full list of players who are currently on your scene by iterating over all entities with a PlayerIdentityData
component.
import { PlayerIdentityData, Transform } from '@dcl/sdk/ecs'
export function main() {
for (const [entity, data, transform] of engine.getEntitiesWith(
PlayerIdentityData,
Transform
)) {
console.log('PLAYER: ', { entity, data, transform })
}
}
Player changes camera mode #
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.
The following snippet uses the onChange
function to fire an event each time the camera changes. It also fires an event when the scene loads, with the player’s initial camera mode.
export function main() {
CameraMode.onChange(engine.CameraEntity, (cameraComponent) => {
if (!cameraComponent) return
console.log('Camera mode changed', cameraComponent?.mode)
// 0 = first person
// 1 = third person
})
}
See Check player’s camera mode .
Player plays animation #
Use the onChange
function on the AvatarEmoteCommand
component to fire an event each time the player plays an emote. This includes both base emotes (dance, clap, wave, etc) and emotes from tokens.
import { AvatarEmoteCommand } from '@dcl/sdk/ecs'
export function main() {
AvatarEmoteCommand.onChange(engine.PlayerEntity, (emote) => {
if (!emote) return
console.log('Emote played: ', emote.emoteUrn)
})
}
The event includes the following information:
emoteUrn
: Name of the emote performed (ie: wave, clap, kiss)loop
: If the emote is looping or playing oncetimestamp
: When the emote was triggered.
You can also detect emotes form other players in the scene, simply pass a reference to the other player instead of engine.PlayerEntity
.
Player changes profile #
Use the onChange
function on the AvatarEquippedData
component to fire an event each time the player changes one of their wearables, or their listed emotes on the quick access wheel. Similarly, use the onChange
function on the AvatarBase
to fire an event each time the player changes their base avatar properties, like hair color, skin color, avatar shape, or name.
import { AvatarEquippedData, AvatarBase } from '@dcl/sdk/ecs'
export function main() {
AvatarEquippedData.onChange(engine.PlayerEntity, (equipped) => {
if (!equipped) return
console.log('New wearables list: ', equipped.wearableUrns)
console.log('New emotes list : ', equipped.emoteUrns)
})
AvatarBase.onChange(engine.PlayerEntity, (body) => {
if (!body) return
console.log('New eyes color: ', body.eyesColor)
console.log('New skin color: ', body.skinColor)
console.log('New hair color: ', body.hairColor)
console.log('New body URN: ', body.bodyShapeUrn)
})
}
The event on AvatarEquippedData
includes the following information:
wearableUrns
: The list of wearables that the player currently has equipped.emoteUrns
: The list of emotes that the player currently has equipped in the quick access wheel.
The event on AvatarBase
includes the following information:
name
: The player’s name.bodyShapeUrn
: The ids corresponding to male or female body type.skinColor
: Player skin color as aColor4
eyeColor
: Player eye color as aColor4
hairColor
: Player hair color as aColor4
You can also detect changes in wearables or avatars form other players in the scene, simply pass a reference to the other player instead of engine.PlayerEntity
.
💡 Tip: When testing in preview with the legacy web editor, to avoid using a random avatar, run the scene in the browser connected with your Metamask wallet. In the Decentraland VS Code Extension, open the Decentraland tab and hover your mouse over it to display the three dots icon on the top-right. Click this icon and select Open in browser with Web3.
You can also detect changes on the profiles of other players in the scene, simply pass a reference to the other player instead of engine.PlayerEntity
.
Player locks or unlocks cursor #
Players can switch between two cursor modes: locked cursor mode to control the camera or unlocked cursor mode for moving the cursor freely over the UI.
Players unlock the cursor by clicking the Right mouse button or pressing the Esc key, and lock the cursor back by clicking anywhere in the screen.
Use the onChange
function on the PointerLock
component to fire an event each time the player changes between the two cursor modes.
export function main() {
PointerLock.onChange(engine.CameraEntity, (pointerLock) => {
if (!pointerLock) return
console.log('Pointer lock changed', pointerLock.isPointerLocked)
})
}
Checking for this component is useful if the player needs to change cursor modes and may need a hint for how to lock/unlock the cursor. This can also be used in scenes where the player is expected to react fast, but the action can take a break while the player has the cursor unlocked.