Contas e tradução
Comece pela disponibilidade e pelos erros do SDK. Os exemplos usam o objeto global injetado; o jogo nunca solicita credenciais da conta.
Login após uma ação do jogador
Chame checkSession() imediatamente antes de uma ação que exige conta. Se retornar false, chame login() a partir de uma ação explícita do jogador. O host controla a interface. cancelled é uma decisão normal; falhas de transporte, popup ou sincronização da conta rejeitam a Promise.
Após success, prossiga diretamente com a ação. Não recarregue, faça polling ou verifique a sessão novamente para essa mesma ação. Verifique de novo em uma ação independente posterior. Desative o botão enquanto a solicitação estiver pendente.
<button id="player-button">Show player</button>
<output id="player-info" aria-live="polite"></output>async function readPlayerAfterClick() {
const sdk = window.combos;
if (!sdk) return null;
const { methods } = await sdk.init();
if (!methods.includes("getUserInfo")) return null;
if (!(await sdk.checkSession())) {
const result = await sdk.login();
if (result.status !== "success") return null;
}
return sdk.getUserInfo();
}
const button = document.querySelector<HTMLButtonElement>("#player-button");
const output = document.querySelector<HTMLOutputElement>("#player-info");
button?.addEventListener("click", async () => {
if (!output) return;
button.disabled = true;
try {
const player = await readPlayerAfterClick();
output.textContent = player
? player.nickName || "Player"
: "Player information is unavailable.";
} catch {
output.textContent = "Unable to read player information. Please try again.";
} finally {
button.disabled = false;
}
});Botões e mensagens são exemplos de interface: adapte-os aos idiomas do jogo. A função retorna null quando falta o recurso ou o login é cancelado; o manipulador de clique captura as falhas reais.
Leia as informações do jogador
getUserInfo() não recebe argumentos. Use após verificar a sessão ou concluir o login. Sem login, a chamada é rejeitada com session_required.
| Campo | Significado |
|---|---|
appId | Identidade do aplicativo do jogo atual |
openId | Identidade do jogador dentro desse aplicativo |
nickName | Nome de exibição; pode estar vazio |
avatarUrl | URL do avatar; pode estar vazia |
locale | Idioma público salvo do jogador, como en ou zh-CN; o idioma atual do produto se nenhum estiver salvo |
Ofereça alternativas para informações de exibição ausentes. Respeite o escopo do aplicativo; não use essa resposta de exibição como credencial ou prova de autorização para seu backend. Ela não contém ID de usuário da plataforma, e-mail ou sessão de Cloud Ability.
Traduza textos já exibidos
Mostre primeiro o texto original e depois solicite a tradução. sourceLocale indica o idioma de origem, não o destino desejado. O host escolhe seu idioma atual do produto. sourceTexts contém as strings ou modelos originais exatos, também usados como chaves do resultado.
<button data-source-text="Play"></button>
<button data-source-text="Pause"></button>async function localizeLabels() {
const nodes = [...document.querySelectorAll<HTMLElement>("[data-source-text]")];
const sourceTexts = nodes.map(node => node.dataset.sourceText ?? "");
nodes.forEach((node, index) => { node.textContent = sourceTexts[index]; });
const sdk = window.combos;
if (!sdk) return;
try {
const { methods } = await sdk.init();
if (!methods.includes("requestI18n")) return;
const result = await sdk.requestI18n({ sourceLocale: "en", sourceTexts });
if (!result.needed) return;
nodes.forEach((node, index) => {
const source = sourceTexts[index];
node.textContent = result.translations[source] || source;
});
} catch {
// Keep the source copy on screen.
}
}
void localizeLabels();O resultado é { needed: false } ou { needed: true, locale, translations }. Mantenha o original quando a tradução não for necessária, faltarem chaves, o host não oferecer suporte ou houver falha. Resultados SDK inválidos também viram needed: false. Insira traduções como texto, nunca como HTML bruto. Traduza modelos estáveis antes de inserir valores dinâmicos e atualize sourceLocale ao alterar os textos ingleses do exemplo.
Referência opcional de Cloud Ability
O host Web atual não anuncia estes quatro métodos. Use somente quando init().methods incluir explicitamente o método correspondente. Esse contrato não habilita IA apenas por publicar um jogo.
type Authorization = {
decision: "AUTHORIZATION_DECISION_GRANTED" | "AUTHORIZATION_DECISION_DENIED";
decidedAtMs: number;
};
type AuthSetting = Partial<Record<"ai_model", Authorization>>;
type CloudAbilitySession = { session: string; expiresAtMs: number };| Método | Parâmetros e resultado |
|---|---|
getSetting() | Sem argumentos; retorna AuthSetting. Um escopo ausente nunca foi solicitado |
authorize({ scope: "ai_model" }) | O host controla a solicitação de permissão e retorna Authorization |
openSetting() | Sem argumentos; abre configurações do host e retorna AuthSetting |
getCloudAbilitySession() | Sem argumentos; retorna uma CloudAbilitySession de curta duração |
AUTHORIZATION_DECISION_DENIED é uma decisão normal, não uma falha de transporte. Não grave o valor zero UNSPECIFIED. Os tempos são em milissegundos. Não envie IDs de usuário, dispositivo ou jogo. Mantenha a sessão apenas na memória, respeite expiresAtMs, descarte-a ao terminar a partida e nunca a coloque em armazenamento, logs ou URLs.