uloggdDesenvolvedores
Portal do desenvolvedoruloggd
ComeçarRecursosArcade
Portal do desenvolvedoruloggdArcadeHospedagemO frameSDKIdentidadeVerificação em outras linguagensEventos de dadosTestesPolítica de revisãoDeveres de privacidadeEngines

SDK

@uloggd/arcade-sdk: o cliente, cada comando, evento, erro e código de fechamento, e o simulador.

npm install @uloggd/arcade-sdk
  • Licença MIT, sem dependências em tempo de execução. Mira ES2020 e pode ser importado durante a renderização no servidor.
  • Vem como módulos ES e como CommonJS, ambos com declarações de tipos, e como um build para uma tag script comum (abaixo).
  • @uloggd/arcade-sdk é o cliente, @uloggd/arcade-sdk/mock o simulador, e @uloggd/arcade-sdk/server a verificação de tokens para Node 20.19 ou mais novo, Deno, Bun e Workers (veja Identidade; para servidores em outras linguagens, veja Verificação em outras linguagens).
  • O uloggd nunca serve o SDK aos jogos: você o empacota, ou hospeda junto com o jogo.
VersãoO que traz
0.1.0Só módulos ES.
0.2.0Acrescenta CommonJS, carregado por require, e o build para tag script, dist/uloggd-arcade.min.js. A API e o protocolo não mudam.

Sem um bundler

O pacote inclui dist/uloggd-arcade.min.js, um build para uma tag <script> comum que define uma única variável global, UloggdArcade. Copie-o de node_modules/@uloggd/arcade-sdk/dist/ para o seu jogo, junto com uloggd-arcade.min.js.map se quiser pilhas de erro legíveis, e sirva-o da própria origem do jogo.

<script src="./uloggd-arcade.min.js"></script>
<script>
  const arcade = UloggdArcade.createArcadeSDK({
    appId: "ID_DO_SEU_APLICATIVO",
    mockWhenStandalone: true,
  });
  arcade.ready().then(({ context }) => startGame(context));
</script>
  • UloggdArcade traz createArcadeSDK, ArcadeSDKError, ArcadeSDKMock e as constantes (SDK_VERSION, ERROR_CODES, HostCloseCode, GuestCloseCode, PROTOCOL_VERSION, SUBSCRIBABLE_EVENTS e DEFAULT_HOST_ORIGIN). A verificação de tokens não está nele: ela é do seu servidor.
  • Sirva-o você mesmo. O uloggd não o serve, e uma cópia numa CDN pública é um terceiro que o seu lançamento precisa declarar, e que pode mudar o que o jogo roda sem uma nova revisão.
  • Sem o npm, o mesmo arquivo está em https://registry.npmjs.org/@uloggd/arcade-sdk/-/arcade-sdk-0.2.0.tgz, em package/dist/.
  • Carregue-o como script clássico, antes dos scripts que o usam. Como script de módulo (type="module"), ele não define nenhuma variável global.
  • Os módulos ES de dist também funcionam num script de módulo, que importa dist/client.js com a pasta chunks ao lado.

Criar o cliente

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

const arcade = createArcadeSDK({
  appId: "ID_DO_SEU_APLICATIVO",
  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("Jogue este jogo no uloggd.com");
  }
}
Opção
appIdO id do seu aplicativo, como o portal mostra: um uuid em minúsculas.
hostOriginOnde o uloggd roda. https://uloggd.com por padrão; uma origem http:// só é aceita quando o próprio jogo roda numa origem de loopback.
mockWhenStandaloneAberto direto numa origem de loopback (localhost), fora de qualquer frame, o cliente é o simulador. Em qualquer outro lugar fora do uloggd, ready() rejeita com not_embedded, então um jogo publicado no lugar errado falha de forma visível.

createArcadeSDK lança invalid_args na hora para um appId ou um hostOrigin malformado.

Membro
ready()Resolve uma vez, depois do handshake, com { protocol, commands, context }. Rejeita com not_embedded, com timeout quando o uloggd não responde ao handshake em 10 segundos, ou com closed.
contextO mesmo contexto, ou null antes de ready() resolver.
commandsOs comandos abaixo.
subscribe(event, listener, onError?)Escuta um evento e devolve a função que para de escutar.
supports(command)Se o uloggd anunciou o comando em READY. Confira antes de usar um comando mais novo que o SDK que você publicou.
close({ code, message? })Encerra a sessão, com um dos códigos de fechamento abaixo.
destroy()Encerra a sessão normalmente, com o código 1000, como close faria, e rejeita tudo o que está pendente. Para a limpeza de um efeito ou um hot reload.

Comandos

Todo comando devolve uma promise e tem prazo: 10 segundos, ou 5 minutos para authorize, que espera pelo jogador.

ComandoArgumentosResultadoExige
authorize{ scopes: ["identify"] }{ scopes }
getPlayernenhum{ id, nickname }identify
getIdentityToken{ nonce }{ token, expiresAt }identify
getGamenenhum{ appId, slug, name }
requestFullscreennenhum{ fullscreen }um gesto
exitFullscreennenhum{ fullscreen }
  • authorize abre o diálogo de consentimento do próprio uloggd, fora do frame, onde o jogador escolhe o apelido que o seu jogo vai ver (um gerado, por padrão). Sem a capacidade pointer-lock, o diálogo abre direto, ou assim que a aba voltar a aparecer, se estiver oculta. Com ela, o diálogo não abre sozinho, porque o uloggd não enxerga uma trava que o seu jogo segura: a barra do jogador mostra o pedido com um botão Responder, e o diálogo abre a partir desse clique. Peça só escopos que o lançamento declarou, senão ele falha com invalid_args. Se o jogador cancela, ele falha com user_cancelled, e pedir de novo continua falhando até o jogador abrir o jogo outra vez. Peça depois de um clique seu, como "Salvar meu progresso", e não ao carregar. Um jogador que já aceitou o seu jogo não é perguntado de novo.
  • getPlayer devolve o id por jogo e o apelido do jogador, sem verificação. Mostre-os; nunca confie neles no seu servidor.
  • getIdentityToken devolve um token assinado pelo uloggd, para o seu servidor verificar. O nonce vem do seu servidor: de 16 a 128 caracteres entre letras, dígitos, _ e -. Um token a cada 3 segundos, e 30 por jogador por hora.
  • getGame devolve o nome aprovado e o slug, o endereço reservado quando o Arcade foi ativado. Hoje o slug nunca é null; o tipo admite null para versões futuras.
  • requestFullscreen e exitFullscreen agem no contêiner do uloggd, com a barra dele visível. Chame requestFullscreen a partir de um clique ou de uma tecla, senão ele falha com requires_gesture.
document.querySelector("#salvar")!.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);
});
// depois
off();
EventoDados
READY{ protocol: 1, commands, context }. Enviado uma vez, sem inscrição; ready() resolve com ele.
VISIBILITY_UPDATE{ visible }
LAYOUT_UPDATE{ width, height, fullscreen, safeArea: { top, right, bottom, left } }
LOCALE_UPDATE{ locale }
CLOSING{ reason, deadlineMs }, em que reason é user, hidden ou suspended.
GRANT_UPDATE{ scopes }
  • O primeiro ouvinte de um evento faz a inscrição, e o último off() a desfaz. Uma inscrição que o uloggd recusa remove os ouvintes dela e chama onError.
  • O SDK também escreve a área segura em :root, como --uloggd-safe-area-inset-top, -right, -bottom e -left.
  • CLOSING dá até deadlineMs para salvar.
  • GRANT_UPDATE chega quando o jogador revoga o acesso do seu jogo nas Configurações. Pare de chamar getPlayer e getIdentityToken, e trate o jogador como desconectado do seu servidor.

Erros

Toda rejeição é um ArcadeSDKError, com um code:

CódigoSignifica
not_embeddedFora do uloggd, e fora do simulador.
unknown_commandO uloggd não conhece o comando; confira supports() antes.
invalid_argsOs argumentos foram recusados: um escopo que o lançamento não declarou, um nonce malformado, uma chave a mais.
missing_scopeO jogador não concedeu o escopo de que o comando precisa.
user_cancelledO jogador fechou o diálogo do uloggd.
requires_gestureO comando precisa antes de um clique ou de uma tecla no jogo.
rate_limitedComandos demais, ou tokens demais.
timeoutSem resposta a tempo.
closedA sessão fechou antes da resposta. Quando um código de fechamento a encerrou, o erro o traz em closeCode.
unavailableO uloggd não consegue fazer isso agora, como emitir tokens de identidade sem uma chave de assinatura disponível.
internalAlgo falhou do lado do uloggd.

Códigos de fechamento

O uloggd encerra a sessão com um destes, e tira o frame:

CódigoSignifica
4000Frame ou aplicativo inválido.
4001Origem inválida.
4002Mensagens demais.
4003O jogador revogou o acesso do jogo.
4004Versão de protocolo não suportada.
4010O jogo foi suspenso ou desligado.

O jogo pode fechar com 1000 (normal) ou com um código próprio de 4500 a 4599. A message, de até 200 caracteres, chega ao console do navegador só no modo de teste: os jogadores só veem as palavras do próprio uloggd.

Limites

O SDK mantém você dentro deles, mas eles importam se você manda muitos comandos de uma vez: cada mensagem tem até 64 KiB, no máximo 32 comandos esperam resposta ao mesmo tempo, e os comandos ficam limitados a 20 por segundo, com picos de 50. Passando disso, o uloggd encerra a sessão com 4002.

O simulador

Em localhost, com mockWhenStandalone: true, o cliente é um ArcadeSDKMock, que tem a mesma interface:

  • todo comando responde com dados fixos. authorize concede na hora, como um jogador que aceita, e até lá getPlayer e getIdentityToken falham com missing_scope, como dentro do uloggd;
  • ?mock_player=2 no endereço da página dá um segundo jogador, então duas abas podem ser dois jogadores;
  • os tokens de identidade são assinados com uma chave descartável e iss: "mock", que os verificadores do servidor recusam a não ser que você passe allowMock: true.

No build para tag script, o simulador é UloggdArcade.ArcadeSDKMock.

Nos testes, crie o simulador você mesmo e conduza-o. Além de appId, ele aceita mode, locale, platform, player e scopes, para um jogador que já aceitou:

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

const arcade = new ArcadeSDKMock({
  appId: "ID_DO_SEU_APLICATIVO",
  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 });

O frame

O que um jogo pode e não pode fazer dentro do player do uloggd, como ele começa e termina, e os parâmetros com que é aberto.

Identidade

Saiba quem está jogando, por um token de cinco minutos assinado pelo uloggd e verificado pelo seu servidor, offline.

Nesta página

Sem um bundlerCriar o clienteComandosEventosErrosCódigos de fechamentoLimitesO simulador