# Datos del usuario

## Posición y rotación del jugador

Usa la `PlayerEntity` como las `CameraEntity` para conocer la posición y rotación del jugador, comprobando su `Transform` componentes.

```ts
function getPlayerPosition() {
	if (!Transform.has(engine.PlayerEntity)) return
	if (!Transform.has(engine.CameraEntity)) return

	//posición del jugador
	const playerPos = Transform.get(engine.PlayerEntity).position

	//rotación del jugador
	const playerRot = Transform.get(engine.PlayerEntity).rotation

	//posición de la cámara
	const CameraPos = Transform.get(engine.CameraEntity).position

	//rotación de la cámara
	const CameraRot = Transform.get(engine.CameraEntity).rotation

	console.log('playerPos: ', playerPos)
	console.log('playerRot: ', playerRot)
	console.log('cameraPos: ', CameraPos)
	console.log('cameraRot: ', CameraRot)
}

engine.addSystem(getPlayerPosition)
```

* **Posición de PlayerEntity**: La posición del avatar, a la altura del pecho. Aproximadamente a 0.88 cm sobre el suelo.
* **Rotación de PlayerEntity**: La dirección en la que el avatar está mirando, expresada como un quaternion.
* **Posición de CameraEntity**:
  * En primera persona: Igual a la posición del avatar, pero a la altura de los ojos. Aproximadamente a 1.75 cm sobre el suelo.
  * En tercera persona: Puede variar dependiendo de los movimientos de la cámara.
* **Rotación de PlayerEntity**:
  * En primera persona: Similar a la dirección en la que el avatar está mirando, expresada como un quaternion. Puede redondearse ligeramente diferente a la rotación del jugador.
  * En tercera persona: Puede variar dependiendo de los movimientos de la cámara.

{% hint style="warning" %}
**📔 Nota**: Evita referirte al `engine.PlayerEntity` o el `engine.CameraEntity` en la carga inicial de la escena, porque eso puede resultar en errores si las entidades aún no están inicializadas. Para evitar este problema, usa estos dentro del `main()` function, or on a function indirectly called by `main()`. You can also encapsulate the behavior in an async [`executeTask` block](https://docs.decentraland.org/creator/content-creator-es/patrones-de-programacion/async-functions#the-executetask-function).

Otra opción es referirse a estas entidades dentro de un sistema. Allí siempre estarán disponibles, porque la primera ejecución del sistema se llama una vez que la escena ya está correctamente inicializada.
{% endhint %}

## Obtener todos los jugadores

Todos los jugadores en la escena tienen un `Transform` componente. Este componente es de solo lectura en avatares. Para obtener las posiciones de todos los jugadores, [itera sobre todas las entidades con](https://docs.decentraland.org/creator/content-creator-es/scenes-sdk7/interactividad/user-data) a `PlayerIdentityData` component.

```ts
import { PlayerIdentityData } from '@dcl/sdk/ecs'

for (const [entity, data, transform] of engine.getEntitiesWith(
	PlayerIdentityData,
	Transform
)) {
	console.log('Player data: ', { entity, data, transform })
}
```

El código anterior itera sobre todas las entidades con un `Transform` y un `PlayerIdentityData` componente, y registra sus datos. Puedes usar este mismo método para obtener cualquiera de los datos disponibles de todos los jugadores.

Ver [Listeners de eventos](https://docs.decentraland.org/creator/content-creator-es/scenes-sdk7/event-listeners#player-locks-or-unlocks-cursor) para aprender cómo detectar y reaccionar cuando nuevos jugadores se unen a la escena.

## Obtener datos del jugador

Usa `getPlayer()` para obtener datos sobre el jugador actual, o cualquier otro jugador en la escena.

```ts
import { getPlayer } from '@dcl/sdk/src/players'

export function main() {
	createCube(5, 1, 5)

	let myPlayer = getPlayer()

	if (myPlayer) {
		console.log('Name : ', myPlayer.name)
		console.log('UserId : ', myPlayer.userId)
	}
}
```

`getPlayer()` devuelve lo siguiente:

* `name`: *(string)* El nombre de usuario del jugador, tal como otros lo ven en el mundo
* `userId`: *(string)* Una cadena UUID que identifica al jugador. Si el jugador tiene una clave pública, este campo tendrá el mismo valor que la clave pública.
* `isGuest`: *(boolean)* Indica si el jugador tiene una clave pública. *True* si el jugador es una cuenta invitada sin clave pública.
* `position`: *(Vector3)* La posición del avatar en la escena.
* `avatar`: Un objeto anidado con datos sobre el avatar base y la apariencia del jugador.
* `wearables`: Un arreglo de identificadores para cada una de las wearables que el jugador lleva puestas actualmente. Por ejemplo `urn:decentraland:off-chain:base-avatars:green_hoodie`. Todas las wearables tienen un identificador similar, incluso si son NFTs.
* `emotes`: Un arreglo de identificadores para cada uno de los emotes que el jugador tiene equipados actualmente en la rueda de acceso rápido.
* `entity`: Una referencia a la entidad del jugador. Esto puede ser útil para pasar a otras funciones, o para añadir componentes personalizados a la misma.

El `avatar` el objeto tiene la siguiente información anidada:

* `bodyShapeUrn`: Un identificador para la forma corporal general del avatar. Ya sea `urn:decentraland:off-chain:base-avatars:BaseFemale` para femenina o `urn:decentraland:off-chain:base-avatars:BaseMale` para masculina.
* `skinColor`: Color de piel del jugador como un `Color4`
* `eyesColor`: Color de ojos del jugador como un `Color4`
* `hairColor`: Color de cabello del jugador como un `Color4`
* `name`: El nombre del jugador.

{% hint style="warning" %}
**📔 Nota**: Los datos del jugador pueden no estar disponibles en el primer fotograma de la escena, dependiendo de los tiempos de carga. Deberías verificar que los datos fueron retornados y, de lo contrario, intentar de nuevo unos milisegundos más tarde.
{% endhint %}

```ts
import { getPlayer } from '@dcl/sdk/src/players'

export function main() {
	createCube(5, 1, 5)

	let myPlayer = getPlayer()

	if (myPlayer) {
		console.log('Is Guest: ', myPlayer.isGuest)
		console.log('Name : ', myPlayer.name)
		console.log('UserId : ', myPlayer.userId)
		console.log('Avatar shape : ', myPlayer.position)
		console.log('Avatar shape : ', myPlayer.avatar?.bodyShapeUrn)
		console.log('Avatar eyes color : ', myPlayer.avatar?.eyesColor)
		console.log('Avatar hair color : ', myPlayer.avatar?.hairColor)
		console.log('Wearables on : ', myPlayer.wearables)
		console.log('Emotes available : ', myPlayer.emotes)
	}
}
```

{% hint style="info" %}
**💡 Tip**: Al probar en preview con el editor web heredado, para evitar usar un avatar aleatorio, ejecuta la escena en el navegador conectado con tu billetera Metamask.
{% endhint %}

Para obtener los datos de un jugador específico en la escena, distinto del jugador actual, ejecuta `getPlayer()` con un objeto con un `userId` propiedad.

```ts
import { getPlayer } from '@dcl/sdk/src/players'

for (const [entity, data, transform] of engine.getEntitiesWith(
	PlayerIdentityData,
	Transform
)) {
	let player = getPlayer({ userId: data.address })
	console.log('PLAYER : ', player?.name)
}
```

El fragmento anterior itera sobre todas las entidades con un `PlayerIdentityData` componente, es decir todas las entidades de avatar en la escena. Luego ejecuta el `getPlayer()` para esa entidad.

`getPlayer()` solo puede obtener datos de jugadores que actualmente se encuentran en la misma escena, no tienen que estar necesariamente en rango visual, pero deben estar conectados a la misma isla de comunicaciones. Para probar esto en preview, abre una segunda pestaña e inicia sesión con una cuenta diferente, y que ambos jugadores estén dentro de la escena.

{% hint style="warning" %}
**📔 Nota**: Los IDs de usuario deben estar siempre en minúsculas. Si copias una dirección de wallet, asegúrate de que todos los caracteres estén en minúsculas.
{% endhint %}

## Datos de cualquier jugador

Para obtener información de cualquier jugador, haz una [REST API call](https://docs.decentraland.org/creator/content-creator-es/redes/network-connections#call-a-rest-api) a los servidores de contenido.

Esta información se expone en la siguiente URL, agregando el id de usuario del jugador al parámetro de la URL.

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

{% hint style="info" %}
**💡 Tip**: Prueba la URL en un navegador para ver cómo está estructurada la respuesta.
{% endhint %}

La siguiente información está disponible a partir de esta API:

* `displayName`: *(string)* El nombre de usuario del jugador, tal como otros lo ven en el mundo
* `userId`: *(string)* Una cadena UUID que identifica al jugador. Si el jugador tiene una clave pública, este campo tendrá el mismo valor que la clave pública.
* `hasConnectedWeb3`: *(boolean)* Indica si el jugador tiene una clave pública. *True* si el jugador tiene una.
* `publicKey`: *(string)* La clave pública de la billetera Ethereum del jugador. Si el jugador inicia sesión como invitado, sin billetera vinculada, este campo será `null`.
* `avatar`: Un objeto anidado con datos sobre la apariencia del jugador.
* `version`: *(number)* Un número de versión que incrementa en uno cada vez que el jugador cambia cualquiera de sus configuraciones. Usa esto si encuentras datos en conflicto, para saber qué versión es más reciente.

{% hint style="warning" %}
**📔 Nota**: Para cualquier transacción de Ethereum con el jugador, siempre usa el `publicKey` campo, en lugar del `userId`, para evitar lidiar con billeteras inexistentes.
{% endhint %}

El `avatar` el objeto tiene la siguiente información anidada:

* `wearables`: `WearableId[]` Un arreglo de identificadores para cada una de las wearables que el jugador lleva puestas actualmente. Por ejemplo `urn:decentraland:off-chain:base-avatars:green_hoodie`. Todas las wearables tienen un identificador similar, incluso si son NFTs.
* `bodyShape`: Un identificador para la forma corporal general del avatar. Ya sea `urn:decentraland:off-chain:base-avatars:BaseFemale` para femenina o `urn:decentraland:off-chain:base-avatars:BaseMale` para masculina.
* `skinColor`: *ColorString* Un valor hex para el color de piel del jugador.
* `hairColor`: *ColorString* Un valor hex para el color de cabello del jugador.
* `eyeColor`: *ColorString* Un valor hex para el color de ojos del jugador.
* `snapshots`: Un objeto anidado con representaciones base64 de imágenes .jpg del jugador en varias resoluciones.
  * `face256`: *string* La cara del jugador como una imagen de 256x256 píxeles.
  * `body`: *string* La imagen en resolución completa del jugador de pie, con 512x1024 píxeles.

{% hint style="danger" %}
**❗Advertencia** Las snapshots del avatar serán desaprobadas en el futuro y ya no se devolverán como parte de los datos de un avatar. El enfoque recomendado es usar `AvatarTexture` en su lugar, ver [Retratos de avatar](https://docs.decentraland.org/creator/content-creator-es/conceptos-esenciales-de-contenido-3d/materials#avatar-portraits).
{% endhint %}

A diferencia de `getPlayer()`, esta opción no está limitada solo a los jugadores que actualmente están en la misma escena, o incluso en el mismo servidor. Con este enfoque puedes obtener datos de cualquier jugador que haya iniciado sesión en los servidores en el pasado.

Si sabes a qué servidor está conectado el jugador que deseas consultar, puedes obtener datos más actualizados enviando tus peticiones a ese servidor específico. Por ejemplo, si el jugador cambia de ropa, esta información estará disponible instantáneamente en el servidor del jugador, pero probablemente tardará un par de minutos en propagarse al `peer.decentraland.org` servidor.

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

{% hint style="info" %}
**💡 Tip**: Puedes obtener el servidor actual del jugador obteniendo `getRealm().domain`.
{% endhint %}

Este ejemplo combina `myProfile.userId` y `getRealm()` para obtener los datos del jugador directamente desde el servidor en el que está el jugador:

```ts
import { getRealm } from '~system/Runtime'
import { myProfile } from '@dcl/sdk/network'

async function fetchPlayerData() {
	const { realmInfo } = await getRealm({})

	const url = `${realmInfo.baseUrl}/lambdas/profile/${myProfile.userId}`
	console.log('using URL: ', url)

	try {
		const json = (await fetch(url)).json()

		console.log('full response: ', json)
		console.log(
			'player is wearing :',
			json[0].metadata.avatars[0].avatar.wearables
		)
		console.log('player owns :', json[0].metadata.avatars[0].inventory)
	} catch {
		console.log('an error occurred while reaching for player data')
	}
}

fetchPlayerData()
```

## Componentes de datos del jugador

En lugar de usar `getPlayer()`, puedes leer datos directamente desde una serie de componentes que almacenan los datos en cada entidad de jugador. Existen los siguientes componentes:

* `PlayerIdentityData`: Almacena la dirección del jugador y una `isGuest` propiedad para marcar cuentas invitadas.
* `AvatarBase`: Almacena datos sobre el avatar base, incluyendo:
  * `name`: El nombre del jugador.
  * `bodyShapeUrn`: Los ids correspondientes al tipo de cuerpo masculino o femenino.
  * `skinColor`: Color de piel del jugador como un `Color4`
  * `eyeColor`: Color de ojos del jugador como un `Color4`
  * `hairColor`: Color de cabello del jugador como un `Color4`
* `AvatarEquippedData`: La lista de wearables y emotes equipados.
  * `wearableUrns`: La lista de wearables que el jugador tiene equipadas actualmente.
  * `emoteUrns`: La lista de emotes que el jugador tiene equipados actualmente en la rueda de acceso rápido.
* `AvatarEmoteCommand`: Información sobre los emotes que el jugador está reproduciendo actualmente. Incluye:
  * `emoteUrn`: El URN del último emote reproducido por el jugador, desde que entró en la escena
  * `loop`: True si el emote está en loop
  * `timestamp`: El momento en que este emote fue activado

```ts
for (const [entity, data, base, attach, transform] of engine.getEntitiesWith(
	PlayerIdentityData,
	AvatarBase,
	AvatarEquippedData,
	Transform
)) {
	console.log('PLAYER DATA: ', { entity, data, transform, base, attach })
}
```

{% hint style="warning" %}
**📔 Nota**: Todos estos componentes son de solo lectura. No puedes cambiar sus valores desde la escena.
{% endhint %}

## Obtener Portable Experiences

Las portable experiences son esencialmente escenas que no están restringidas a parcelas de tierra. Los jugadores pueden llevarlas consigo a cualquier lugar al que vayan en Decentraland, añadiendo una nueva capa de contenido sobre el mundo. Smart Wearables son ejemplos de portable experiences. Puede que quieras saber si un jugador lleva una de estas, ya que un smart wearable puede habilitar habilidades que podrían considerarse trampa en un juego competitivo. Por ejemplo, en un juego de plataformas, un jugador que lleva un jetpack tiene una ventaja muy injusta sobre otros.

Como creador de escenas, puede que quieras limitar lo que los jugadores que llevan portable experiences pueden hacer en tu escena. Usa `getPortableExperiencesLoaded()` para comprobar si el jugador tiene alguna portable experience actualmente activada.

```ts
import { getPortableExperiencesLoaded } from '~system/PortableExperiences'

executeTask(async () => {
	let portableExperiences = await getPortableExperiencesLoaded({})
	console.log(portableExperiences.loaded)
})
```

`getPortableExperiencesLoaded()` devuelve un arreglo de objetos, cada uno de estos objetos incluye un `id` atributo. En el caso de wearables, el id es el URN del wearable.

## Obtener información detallada sobre las wearables de un jugador

El `getPlayer()` function devuelve solo una lista de ids de wearables, sin información sobre cada wearable. Quizá quieras comprobar cualquier wearable de una categoría específica (p. ej.: sombreros), o cualquier wearable de una rareza específica (p. ej.: Mythic), para eso necesitarás obtener información más detallada sobre las wearables del jugador.

Haz un [REST API call](https://docs.decentraland.org/creator/content-creator-es/redes/network-connections#call-a-rest-api) a la siguiente URL, para obtener una lista completa y actualizada de todas las wearables que son actualmente utilizables, con detalles sobre cada una.

`${playerRealm.realmInfo.baseUrl}/lambdas/collections/wearables-by-owner/${userData.userId}?includeDefinitions`

{% hint style="warning" %}
**📔 Nota**: Para construir esta URL, debes obtener el realm (probablemente con `getRealm()`) y el id del jugador (probablemente con `getPlayer()`)
{% endhint %}

Esta característica podría usarse junto con obtener info sobre el jugador, por ejemplo para permitir que los jugadores entren en un lugar solo si llevan cualquier wearable de la colección de halloween, o cualquier wearable que sea de *legendary* rareza.

{% hint style="info" %}
**💡 Tip**: Prueba la URL en un navegador para ver cómo está estructurada la respuesta.
{% endhint %}

```ts
import { getPlayer } from '@dcl/sdk/src/players'
import { getRealm } from '~system/Runtime'

async function fetchWearablesData() {
	try {
		let userData = getPlayer({})
		const realm = await getRealm({})

		const url =
			`${realm.realmInfo?.baseUrl}/lambdas/collections/wearables-by-owner/${userData.userId}?includeDefinitions`.toString()
		console.log('using URL: ', url)

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

		console.log('full response: ', json)
	} catch {
		console.log('an error occurred while reaching for wearables data')
	}
}

executeTask(fetchWearablesData)
```

{% hint style="info" %}
**💡 Tip**: Incluso puedes obtener más información sobre wearables específicos desde la [siguiente API](https://decentraland.github.io/catalyst-api-specs/#tag/Lambdas/operation/searchWearables).
{% endhint %}

## Comprobar el modo de cámara del jugador

Los jugadores pueden usar ya sea una cámara en primera o tercera persona al explorar Decentraland. Comprueba cuál de estas está usando el jugador verificando el valor `CameraMode` componente del `engine.CameraEntity` entity.

```ts
function checkCameraMode() {
	if (!Transform.has(engine.CameraEntity)) return

	let cameraEntity = CameraMode.get(engine.CameraEntity)

	if (cameraEntity.mode == CameraType.CT_THIRD_PERSON) {
		console.log('The player is using the 3rd person camera')
	} else {
		console.log('The player is using the 1st person camera')
	}
}

engine.addSystem(checkCameraMode)
```

{% hint style="warning" %}
**📔 Nota**: La información de la cámara solo está disponible para el jugador actual que ejecuta la escena. No puedes solicitar los datos de cámara de ningún otro jugador.
{% endhint %}

El modo de cámara usa un valor del `CameraType` enum. Los siguientes valores son posibles:

* `CameraType.CT_FIRST_PERSON`
* `CameraType.CT_THIRD_PERSON`

El `CameraMode` componente del `engine.CameraEntity` es de solo lectura, no puedes forzar al jugador a cambiar el modo de cámara mediante esto.

{% hint style="info" %}
**💡 Tip**: Para cambiar el modo de cámara del jugador, usa un [Camera modifier area](https://docs.decentraland.org/creator/content-creator-es/conceptos-esenciales-de-contenido-3d/camera#1st-and-3rd-person-camera-modes).
{% endhint %}

Saber el modo de cámara puede ser muy útil para ajustar fino las mecánicas de tu escena para adaptarlas mejor a lo que es más cómodo usando este modo. Por ejemplo, los objetivos pequeños son más difíciles de clicar cuando se está en 3rd person.

{% hint style="warning" %}
**📔 Nota**: Evita referirte al `engine.CameraEntity` en la carga inicial de la escena, porque eso puede resultar en errores si las entidades aún no están inicializadas. Para evitar este problema, usa estos dentro del `main()` function, or on a function indirectly called by `main()`. You can also encapsulate the behavior in an async [`executeTask` block](https://docs.decentraland.org/creator/content-creator-es/patrones-de-programacion/async-functions#the-executetask-function).

Otra opción es referirse a esta entidad dentro de un sistema. Siempre estará disponible, porque la primera ejecución del sistema se llama una vez que la escena ya está correctamente inicializada.
{% endhint %}

## Comprobar si el jugador tiene el cursor bloqueado

Los jugadores pueden cambiar entre dos modos de cursor: *modo de cursor bloqueado* para controlar la cámara o *modo de cursor desbloqueado* para mover el cursor libremente sobre la UI.

Los jugadores desbloquean el cursor haciendo clic el *Botón derecho del ratón* o presionando la *Esc* tecla, y bloquean de nuevo el cursor haciendo clic en cualquier parte de la pantalla.

Marca la casilla `PointerLock` componente de la [entidad de la cámara](https://docs.decentraland.org/creator/content-creator-es/arquitectura/entities-components#reserved-entities) para averiguar cuál es el modo actual del cursor.

```ts
export function main() {
	const isLocked = PointerLock.get(engine.CameraEntity).isPointerLocked
	console.log(isLocked)
}
```

Ver [Listeners de eventos](https://docs.decentraland.org/creator/content-creator-es/scenes-sdk7/event-listeners#player-locks-or-unlocks-cursor) para ver cómo reaccionar fácilmente a los cambios en el estado del cursor.

El `PointerLock` componente del `engine.CameraEntity` es de solo lectura, no puedes forzar al jugador a bloquear o desbloquear el cursor.

{% hint style="warning" %}
**📔 Nota**: Evita referirte al `engine.CameraEntity` en la carga inicial de la escena, porque eso puede resultar en errores si las entidades aún no están inicializadas. Para evitar este problema, usa estos dentro del `main()` function, or on a function indirectly called by `main()`. You can also encapsulate the behavior in an async [`executeTask` block](https://docs.decentraland.org/creator/content-creator-es/patrones-de-programacion/async-functions#the-executetask-function).

Otra opción es referirse a la entidad dentro de un sistema. Siempre estará disponible, porque la primera ejecución del sistema se llama una vez que la escena ya está correctamente inicializada.
{% endhint %}

## Comprobar la posición del cursor del jugador

Usa la `primaryPointerInfo` componente en el `engine.RootEntity` para obtener la posición del cursor del jugador. Esto puede usarse para mecánicas como interacciones de arrastrar y soltar, gestos de deslizamiento, etc.

```ts
import { PrimaryPointerInfo } from '@dcl/sdk/ecs'

function CursorSystem() {
	const pointerInfo = PrimaryPointerInfo.get(engine.RootEntity)
	console.log(pointerInfo)
}

engine.addSystem(CursorSystem)
```

{% hint style="warning" %}
**📔 Nota**: Evita referirte al `engine.RootEntity` en la carga inicial de la escena, porque eso puede resultar en errores si las entidades aún no están inicializadas. Para evitar este problema, siempre refiérete a la entidad dentro de un sistema. Siempre estará disponible, porque la primera ejecución del sistema se llama una vez que la escena ya está correctamente inicializada.
{% endhint %}

El `primaryPointerInfo` el componente devuelve un objeto con las siguientes propiedades:

* `screenCoordinates`: *(Vector2)* La posición del cursor en la escena, expresada en píxeles. El origen es la esquina superior izquierda de la pantalla.
* `screenDelta`: *(Vector2)* El cambio delta en la posición del cursor desde el último fotograma, expresado en píxeles.
* `worldRayDirection`: *(Vector3)* Un vector que representa la dirección del rayo desde la cámara hasta el cursor. El origen es la posición de la cámara. Usa esto para calcular la posición del cursor en el mundo.
* `pointerType`: 0 para `none`, 1 para `mouse`

{% hint style="info" %}
**💡 Tip**: Para reaccionar a eventos simples de hover en elementos UI, puede resultarte más fácil usar los `onMouseEnter` y `onMouseLeave` events, ver [UI Button Events](https://docs.decentraland.org/creator/content-creator-es/ui-2d/ui_button_events#hover-feedback).
{% endhint %}

El `primaryPointerInfo` el componente es de solo lectura, no puedes forzar al jugador a cambiar la posición del cursor.

El siguiente ejemplo muestra cómo mostrar la posición del cursor en un elemento UI.

***archivo ui.tsx:***

```tsx
import { UiEntity, ReactEcs } from '@dcl/sdk/react-ecs'
import { Color4 } from '@dcl/sdk/math'
import {cursorXpos, cursorYpos} from './index'

export const uiMenu = () => (
  <UiEntity
    uiTransform={{
			width: '100%',
			height: '100px',
			justifyContent: 'center',
			alignItems: 'center',
    }}
    uiText={{ value: `Cursor pos: `+  cursorXpos + `,` + cursorYpos, fontSize: 40 }}
    uiBackground={{ color: Color4.create(0.5, 0.8, 0.1, 0.6) }}
  />
)
```

***archivo index.ts:***

```ts
import { engine } from '@dcl/sdk/ecs'
import { ReactEcsRenderer } from '@dcl/sdk/react-ecs'
import { uiMenu } from './ui'

export function main() {
  ReactEcsRenderer.setUiRenderer(uiMenu)
}

export let cursorXpos: number | undefined = undefined
export let cursorYpos: number | undefined = undefined

function CursorSystem() {
  const pointerInfo = PrimaryPointerInfo.get(engine.RootEntity)
  console.log(pointerInfo)

  cursorXpos = pointerInfo.screenCoordinates?.x
  cursorYpos = pointerInfo.screenCoordinates?.y
}

engine.addSystem(CursorSystem)
```

Puedes usar el `worldRayDirection` para establecer el `dirección` campo de un raycast para saber si una entidad está en la línea de visión del cursor. Ver [Raycasting](https://docs.decentraland.org/creator/content-creator-es/scenes-sdk7/interactividad/raycasting) para más detalles.
