Events

Every host event the SDK exposes, when it fires, and what to do in the handler.

The SDK exposes typed listener methods. Register them early, before ready(), so no host message is missed. The top-level sdk.on methods return nothing; sdk.achievements.onUnlocked, sdk.realtime.onRoom and sdk.realtime.onRoomError return a function that removes the listener.

Lifecycle

sdk.onPlay(callback)

The host starts play: a replay after game over, or a host-directed level start in level games. callback(data?) receives { levelIndex?: number } (1-based); a plain restart omits it. Reset the run in place.

sdk.onPlayAgain is an alias.

sdk.onToggleMute(callback)

The player toggled sound in the host chrome. callback({ isMuted }). Games must not draw their own mute button.

sdk.audio.attach(adapter)

Connects one audio adapter that covers every sound in the game. With one attached, the speaker in the host chrome opens a Sound menu: Everything, plus Game Sounds and Music for the channels you list, and Mute. The player's levels follow them to every game that attaches an adapter. Without one, the speaker stays a plain mute toggle.

const detach = sdk.audio?.attach({
  channels: ['music', 'sfx'], // only the channels your engine routes separately
  apply({ master, muted, music, sfx }) {
    masterGain.gain.value = muted ? 0 : master
    musicGain.gain.value = music
    sfxGain.gain.value = sfx
  },
})

apply runs at once with the saved levels, then on every change. Each gain is 0 to 1. Multiply it into your own mix on a separate gain node, so a player's level never undoes a fade you authored. Call detach() when you dispose the engine. Build no volume settings of your own. Games on @remix-gg/three are already attached; do not attach a second adapter. sdk.audio is missing on older SDK copies, so keep onToggleMute as the fallback.

sdk.onGameInfo(callback)

A fresh GameInfo arrived. ready() already resolves with the first one, so most games never need this. It is where a changed safe area or content layout, or an updated player record, would show up.

Multiplayer

sdk.onGameStateUpdated(callback)

Another player pushed shared state in a turn-based challenge. callback({ id, gameState }), or callback(null) when state is cleared. Validate it and call sdk.multiplayer.actions.refuteGameState({ gameStateId: id }) if it is invalid. See Multiplayer.

sdk.realtime.onRoom(callback) and sdk.realtime.onRoomError(callback)

A realtime room became live, including one the platform joined for the player from an invite, or such a join failed. See Multiplayer.

Purchases

sdk.onPurchaseComplete(callback)

A purchase finished, whether your game started it or the player bought from the host chrome. callback({ success, item? }). Re-check ownership with sdk.hasItem. See Purchases.

Progression

sdk.achievements.onUnlocked(callback)

One or more achievements were earned, from an unlock() call or a refreshed snapshot. callback(keys), each key once. The host already shows the popup; use this for in-game celebration.

A Complete Registration

const sdk = window.RemixSDK

sdk.onPlay((data) => startRun(data?.levelIndex))
sdk.onToggleMute(({ isMuted }) => (audio.muted = isMuted))
sdk.onPurchaseComplete(() => refreshUnlocks())
sdk.achievements.onUnlocked((keys) => celebrate(keys))

await sdk.ready()