uloggdDesarrolladores
Portal de desarrolladoresuloggd
EmpezarRecursosArcade
Portal de desarrolladoresuloggdArcadeAlojamientoEl frameSDKIdentidadVerificación en otros lenguajesEventos de datosPruebasPolítica de revisiónDeberes de privacidadMotores

SDK

@uloggd/arcade-sdk: el cliente, cada comando, evento, error y código de cierre, y el simulador.

npm install @uloggd/arcade-sdk
  • Licencia MIT, sin dependencias en tiempo de ejecución. Apunta a ES2020 y se puede importar durante el renderizado en el servidor.
  • Viene como módulos ES y como CommonJS, ambos con declaraciones de tipos, y como un build para una etiqueta script común (abajo).
  • @uloggd/arcade-sdk es el cliente, @uloggd/arcade-sdk/mock el simulador, y @uloggd/arcade-sdk/server la verificación de tokens para Node 20.19 o posterior, Deno, Bun y Workers (consulta Identidad; para servidores en otros lenguajes, consulta Verificación en otros lenguajes).
  • uloggd nunca sirve el SDK a los juegos: lo empaquetas tú, o lo alojas junto al juego.
VersiónQué trae
0.1.0Solo módulos ES.
0.2.0Añade CommonJS, cargado con require, y el build para etiqueta script, dist/uloggd-arcade.min.js. La API y el protocolo no cambian.

Sin un bundler

El paquete incluye dist/uloggd-arcade.min.js, un build para una etiqueta <script> común que define una sola variable global, UloggdArcade. Cópialo de node_modules/@uloggd/arcade-sdk/dist/ a tu juego, junto con uloggd-arcade.min.js.map si quieres trazas de error legibles, y sírvelo desde el propio origen del juego.

<script src="./uloggd-arcade.min.js"></script>
<script>
  const arcade = UloggdArcade.createArcadeSDK({
    appId: "ID_DE_TU_APLICACION",
    mockWhenStandalone: true,
  });
  arcade.ready().then(({ context }) => startGame(context));
</script>
  • UloggdArcade contiene createArcadeSDK, ArcadeSDKError, ArcadeSDKMock y las constantes (SDK_VERSION, ERROR_CODES, HostCloseCode, GuestCloseCode, PROTOCOL_VERSION, SUBSCRIBABLE_EVENTS y DEFAULT_HOST_ORIGIN). La verificación de tokens no está en él: le corresponde a tu servidor.
  • Sírvelo tú mismo. uloggd no lo sirve, y una copia en una CDN pública es un tercero que tu lanzamiento debe declarar, y que puede cambiar lo que ejecuta el juego sin una nueva revisión.
  • Sin npm, el mismo archivo está en https://registry.npmjs.org/@uloggd/arcade-sdk/-/arcade-sdk-0.2.0.tgz, dentro de package/dist/.
  • Cárgalo como script clásico, antes de los scripts que lo usan. Como script de módulo (type="module"), no define ninguna variable global.
  • Los módulos ES de dist también funcionan desde un script de módulo, que importa dist/client.js con la carpeta chunks al lado.

Crear el cliente

import { createArcadeSDK, ArcadeSDKError } from "@uloggd/arcade-sdk";

const arcade = createArcadeSDK({
  appId: "ID_DE_TU_APLICACION",
  mockWhenStandalone: true,
});

try {
  const { context } = await arcade.ready();
  // context: { appId, instanceId, mode, locale, platform, layout, game }
  startGame(context);
} catch (error) {
  if (error instanceof ArcadeSDKError && error.code === "not_embedded") {
    showMessage("Juega a este juego en uloggd.com");
  }
}
Opción
appIdEl id de tu aplicación, tal como lo muestra el portal: un uuid en minúsculas.
hostOriginDónde se ejecuta uloggd. https://uloggd.com por defecto; un origen http:// solo se acepta cuando el propio juego se ejecuta en un origen de loopback.
mockWhenStandaloneAbierto directamente en un origen de loopback (localhost), fuera de cualquier frame, el cliente es el simulador. En cualquier otro sitio fuera de uloggd, ready() se rechaza con not_embedded, así que un juego desplegado donde no toca falla a la vista.

createArcadeSDK lanza invalid_args al instante para un appId o un hostOrigin mal formado.

Miembro
ready()Se resuelve una vez, tras el handshake, con { protocol, commands, context }. Se rechaza con not_embedded, con timeout cuando uloggd no responde al handshake en 10 segundos, o con closed.
contextEl mismo contexto, o null antes de que ready() se resuelva.
commandsLos comandos de abajo.
subscribe(event, listener, onError?)Escucha un evento y devuelve la función que deja de escucharlo.
supports(command)Si uloggd anunció el comando en READY. Compruébalo antes de usar un comando más nuevo que el SDK que publicaste.
close({ code, message? })Termina la sesión, con uno de los códigos de cierre de abajo.
destroy()Termina la sesión normalmente, con el código 1000, como haría close, y rechaza todo lo pendiente. Para la limpieza de un efecto o un hot reload.

Comandos

Todo comando devuelve una promesa y tiene un plazo: 10 segundos, o 5 minutos para authorize, que espera al jugador.

ComandoArgumentosResultadoExige
authorize{ scopes: ["identify"] }{ scopes }
getPlayerninguno{ id, nickname }identify
getIdentityToken{ nonce }{ token, expiresAt }identify
getGameninguno{ appId, slug, name }
requestFullscreenninguno{ fullscreen }un gesto
exitFullscreenninguno{ fullscreen }
  • authorize abre el diálogo de consentimiento del propio uloggd, fuera del frame, donde el jugador elige el apodo que verá tu juego (uno generado, por defecto). Sin la capacidad pointer-lock, el diálogo se abre directamente, o en cuanto la pestaña vuelva a mostrarse, si está oculta. Con ella, el diálogo no se abre solo, porque uloggd no ve un bloqueo que tu juego mantiene: la barra del jugador muestra la petición con un botón Responder, y el diálogo se abre desde ese clic. Pide solo permisos que el lanzamiento declaró, o falla con invalid_args. Si el jugador cancela, falla con user_cancelled, y pedirlo de nuevo sigue fallando hasta que el jugador vuelva a abrir el juego. Pídelo tras un clic tuyo, como "Guardar mi progreso", y no al cargar. A un jugador que ya aceptó tu juego no se le vuelve a preguntar.
  • getPlayer devuelve el id por juego y el apodo del jugador, sin verificar. Muéstralos; nunca confíes en ellos en tu servidor.
  • getIdentityToken devuelve un token firmado por uloggd, para que lo verifique tu servidor. El nonce viene de tu servidor: de 16 a 128 caracteres entre letras, dígitos, _ y -. Un token cada 3 segundos, y 30 por jugador por hora.
  • getGame devuelve el nombre aprobado y el slug, la dirección reservada al activar Arcade. Hoy el slug nunca es null; el tipo admite null para versiones futuras.
  • requestFullscreen y exitFullscreen actúan sobre el contenedor de uloggd, con su barra visible. Llama a requestFullscreen desde un clic o una tecla, o falla con requires_gesture.
document.querySelector("#guardar")!.addEventListener("click", async () => {
  await arcade.commands.authorize({ scopes: ["identify"] });
  const { nonce } = await fetch("/session/nonce", { method: "POST" }).then(
    (r) => r.json(),
  );
  const { token } = await arcade.commands.getIdentityToken({ nonce });
  await fetch("/session", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ token }),
  });
});

Eventos

const off = arcade.subscribe("LAYOUT_UPDATE", (layout) => {
  resize(layout.width, layout.height);
});
// más tarde
off();
EventoDatos
READY{ protocol: 1, commands, context }. Se envía una vez, sin suscribirse; ready() se resuelve con él.
VISIBILITY_UPDATE{ visible }
LAYOUT_UPDATE{ width, height, fullscreen, safeArea: { top, right, bottom, left } }
LOCALE_UPDATE{ locale }
CLOSING{ reason, deadlineMs }, donde reason es user, hidden o suspended.
GRANT_UPDATE{ scopes }
  • El primer oyente de un evento hace la suscripción, y el último off() la deshace. Una suscripción que uloggd rechaza quita sus oyentes y llama a onError.
  • El SDK también escribe el área segura en :root, como --uloggd-safe-area-inset-top, -right, -bottom y -left.
  • CLOSING te deja hasta deadlineMs para guardar.
  • GRANT_UPDATE llega cuando el jugador revoca el acceso de tu juego en Ajustes. Deja de llamar a getPlayer y getIdentityToken, y trata al jugador como desconectado de tu servidor.

Errores

Todo rechazo es un ArcadeSDKError, con un code:

CódigoSignifica
not_embeddedFuera de uloggd, y fuera del simulador.
unknown_commanduloggd no conoce el comando; comprueba supports() antes.
invalid_argsSe rechazaron los argumentos: un permiso que el lanzamiento no declaró, un nonce mal formado, una clave de más.
missing_scopeEl jugador no concedió el permiso que necesita el comando.
user_cancelledEl jugador cerró el diálogo de uloggd.
requires_gestureEl comando necesita antes un clic o una tecla en el juego.
rate_limitedDemasiados comandos, o demasiados tokens.
timeoutSin respuesta a tiempo.
closedLa sesión se cerró antes de la respuesta. Cuando la terminó un código de cierre, el error lo lleva en closeCode.
unavailableuloggd no puede hacerlo ahora, como emitir tokens de identidad sin una llave de firma disponible.
internalAlgo falló del lado de uloggd.

Códigos de cierre

uloggd termina la sesión con uno de estos, y quita el frame:

CódigoSignifica
4000Frame o aplicación no válidos.
4001Origen no válido.
4002Demasiados mensajes.
4003El jugador revocó el acceso del juego.
4004Versión de protocolo no admitida.
4010El juego fue suspendido o desactivado.

El juego puede cerrar con 1000 (normal) o con un código propio de 4500 a 4599. El message, de hasta 200 caracteres, llega a la consola del navegador solo en modo de prueba: los jugadores solo ven las palabras del propio uloggd.

Límites

El SDK te mantiene dentro de ellos, pero importan si envías muchos comandos a la vez: cada mensaje tiene hasta 64 KiB, como mucho 32 comandos esperan respuesta al mismo tiempo, y los comandos se limitan a 20 por segundo, con picos de 50. Pasado eso, uloggd termina la sesión con 4002.

El simulador

En localhost, con mockWhenStandalone: true, el cliente es un ArcadeSDKMock, que tiene la misma interfaz:

  • todos los comandos responden con datos fijos. authorize concede al instante, como un jugador que acepta, y hasta entonces getPlayer y getIdentityToken fallan con missing_scope, como dentro de uloggd;
  • ?mock_player=2 en la dirección de la página da un segundo jugador, así que dos pestañas pueden ser dos jugadores;
  • los tokens de identidad se firman con una llave desechable e iss: "mock", que los verificadores del servidor rechazan salvo que pases allowMock: true.

En el build para etiqueta script, el simulador es UloggdArcade.ArcadeSDKMock.

En las pruebas, crea tú el simulador y dirígelo. Además de appId, acepta mode, locale, platform, player y scopes, para un jugador que ya aceptó:

import { ArcadeSDKError } from "@uloggd/arcade-sdk";
import { ArcadeSDKMock } from "@uloggd/arcade-sdk/mock";

const arcade = new ArcadeSDKMock({
  appId: "ID_DE_TU_APLICACION",
  scopes: ["identify"],
});
arcade.setPlayer({
  id: "6d0c0d6e-3f7a-4d4b-9d61-2f1f5b0a8c11",
  nickname: "Ada",
});
arcade.overrideCommand("authorize", async () => {
  throw new ArcadeSDKError("user_cancelled");
});
arcade.emit("VISIBILITY_UPDATE", { visible: false });

El frame

Lo que un juego puede y no puede hacer dentro del reproductor de uloggd, cómo empieza y termina, y los parámetros con que se abre.

Identidad

Sabe quién está jugando, con un token de cinco minutos firmado por uloggd y verificado por tu servidor, sin conexión.

En esta página

Sin un bundlerCrear el clienteComandosEventosErroresCódigos de cierreLímitesEl simulador