계정과 다국어
먼저 SDK 지원 기능과 오류를 확인하세요. 아래 예제는 주입된 전역 객체를 사용하며 게임에서 계정 자격 증명을 요구하지 않습니다.
플레이어 행동 이후 로그인
계정이 필요한 작업 직전에 checkSession()을 호출하세요. false이면 플레이어의 명시적인 행동으로 login()을 호출합니다. 로그인 UI는 호스트가 관리합니다. 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;
}
});버튼과 메시지는 게임 UI 예시이므로 게임 언어에 맞게 바꾸세요. 헬퍼는 기능이 없거나 로그인이 취소되면 null을 반환하며 실제 오류는 클릭 핸들러에서 처리합니다.
플레이어 정보 읽기
getUserInfo()는 인수가 없으며 세션 확인 또는 로그인 성공 후 호출합니다. 로그아웃 상태에서는 session_required로 거부됩니다.
| 필드 | 의미 |
|---|---|
appId | 현재 게임의 앱 식별자 |
openId | 해당 앱 안에서의 플레이어 식별자 |
nickName | 표시 이름. 빈 문자열일 수 있음 |
avatarUrl | 아바타 URL. 빈 문자열일 수 있음 |
locale | 플레이어가 저장한 공개 언어(예: en, zh-CN). 저장값이 없으면 현재 제품 언어 |
표시 정보가 없을 때 사용할 기본값을 준비하세요. 앱 내부 신원은 해당 앱 범위로 유지하고 이 표시용 응답을 자체 백엔드의 자격 증명이나 권한 증명으로 사용하지 마세요. 플랫폼 사용자 ID, 이메일 또는 Cloud Ability 세션은 포함되지 않습니다.
표시된 게임 문구 번역
원문을 먼저 표시한 뒤 번역을 요청하세요. sourceLocale은 원하는 번역 대상이 아니라 원문의 언어입니다. 대상 언어는 호스트의 현재 제품 언어로 결정됩니다. sourceTexts에는 정확한 원문 문자열이나 템플릿을 넣으며 결과도 같은 원문을 키로 사용합니다.
<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 }입니다. 번역 불필요, 키 누락, 미지원 또는 실패 시 원문을 유지하세요. 잘못된 SDK 결과도 needed: false로 처리됩니다. 번역문은 HTML이 아닌 텍스트로 표시하세요. 고정 템플릿을 번역한 뒤 동적 값을 채우고 예제의 영어 원문을 바꾸면 sourceLocale도 수정하세요.
선택적 Cloud Ability API
현재 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 반환. scope가 없으면 아직 묻지 않음 |
authorize({ scope: "ai_model" }) | 호스트가 권한 UI를 관리하고 Authorization 반환 |
openSetting() | 인수 없음. 호스트 설정을 열고 AuthSetting 반환 |
getCloudAbilitySession() | 인수 없음. 단기 CloudAbilitySession 반환 |
AUTHORIZATION_DECISION_DENIED는 정상 권한 결과이며 전송 실패가 아닙니다. 0값인 UNSPECIFIED를 쓰지 마세요. 시간 단위는 밀리초입니다. 사용자·기기·게임 ID를 이 메서드에 전달하지 마세요. 반환된 세션은 메모리에만 보관하고 expiresAtMs를 지키며 플레이 종료 시 폐기하세요. 저장소, 로그 또는 URL에 넣지 마세요.