帳號與多語言
先閱讀 SDK 可用性與錯誤處理。以下範例使用宿主注入的全域物件,遊戲不需要索取帳號憑證。
玩家主動操作後登入
在需要帳號的操作前呼叫 checkSession()。若回傳 false,由玩家主動操作觸發 login(),登入介面由宿主管理。cancelled 是正常的使用者選擇;訊息傳輸、彈出視窗或帳號資料同步失敗則會拒絕 Promise。
收到 success 後直接繼續目前操作,不需要重新整理、輪詢或再次檢查這次操作的登入狀態。下一次獨立操作再重新檢查。請求進行中應停用發起按鈕。
<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;
}
});範例按鈕與提示是遊戲內的示範文字,可依遊戲語言調整。輔助函式在能力缺少或登入取消時回傳 null,真正的失敗交由點擊處理函式捕捉。
讀取玩家資訊
getUserInfo() 不接收參數,在登入狀態檢查通過或登入成功後呼叫。未登入時以 session_required 拒絕請求。
| 欄位 | 含義 |
|---|---|
appId | 目前遊戲的應用程式識別碼 |
openId | 玩家在該應用程式內的身分識別碼 |
nickName | 顯示暱稱,可能為空字串 |
avatarUrl | 頭像網址,可能為空字串 |
locale | 玩家已儲存的公開產品語言,如 en、zh-CN;未儲存時為目前產品語言 |
為缺少的顯示資訊提供預設值。應用程式內身分應維持其應用範圍,不要把這份顯示資料當作自有後端的憑證或授權證明。結果不包含平台使用者 ID、電子郵件或雲端能力工作階段。
翻譯已顯示的遊戲文字
先顯示原文,再請求翻譯。sourceLocale 代表原文語言,而非想要的目標語言;目標語言由宿主目前的產品語言決定。sourceTexts 傳入完整原文字串或範本,翻譯結果也以相同原文作為 key。
<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();結果為 { needed: false } 或 { needed: true, locale, translations }。不需翻譯、缺少 key、宿主不支援或請求失敗時都保留原文。SDK 收到無效結果時也會退回 needed: false。以純文字方式顯示譯文,不要插入原始 HTML。動態數值應在固定範本翻譯完成後再填入;修改範例的英文原文時,也要更新 sourceLocale。
選用雲端能力介面參考
目前 Web 宿主不宣告以下四個方法。 只有 init().methods 明確包含對應方法時才能使用。這份介面契約不代表發布遊戲後就自動取得 AI 能力。
type Authorization = {
decision: "AUTHORIZATION_DECISION_GRANTED" | "AUTHORIZATION_DECISION_DENIED";
decidedAtMs: number;
};
type AuthSetting = Partial<Record<"ai_model", Authorization>>;
type CloudAbilitySession = { session: string; expiresAtMs: number };| 方法 | 參數與結果 |
|---|---|
getSetting() | 無參數,回傳 AuthSetting;缺少某項代表尚未詢問過 |
authorize({ scope: "ai_model" }) | 宿主管理授權視窗,回傳 Authorization |
openSetting() | 無參數,開啟宿主設定並回傳 AuthSetting |
getCloudAbilitySession() | 無參數,回傳短期 CloudAbilitySession |
AUTHORIZATION_DECISION_DENIED 是正常授權結果,不是傳輸失敗。不要寫入 UNSPECIFIED 零值。時間單位為毫秒,不要向這些方法傳送使用者、裝置或遊戲 ID。回傳的工作階段僅保留在記憶體,遵守 expiresAtMs,遊玩結束即捨棄,不放入持久化儲存、日誌或 URL。