# host extras

sdk.host.crazygames, sdk.host.poki and sdk.host.playgama expose what one portal has and the others do not; each is undefined elsewhere.

Everything a game needs on every host is in the main API. `sdk.host.<name>` is defined only while the game
runs on that host and is `undefined` everywhere else, so optional calls are safe. The object is the same
for the life of the SDK: `const { host } = sdk` stays valid.

## `host.crazygames`

| Member                             | What it does                                                                    |
| ---------------------------------- | ------------------------------------------------------------------------------- |
| `onMuteChange(fn): Off`            | The portal's mute setting changed; `fn(muted: boolean)`. Returns an unsubscribe |
| `muted(): boolean`                 | The current setting                                                             |
| `inviteLink(params): string`       | A link to the game with `params` as query, built by the portal                  |
| `inviteParam(key): string \| null` | A parameter of the link the player arrived with                                 |
| `setGameContext(data): void`       | Context for the portal's own features                                           |

<CodePanel title="CrazyGames extras">
  <Fragment slot="javascript">
    ```js
    audio.mute(sdk.host.crazygames?.muted() ?? false);
    sdk.host.crazygames?.onMuteChange((muted) => audio.mute(muted));
    const link = sdk.host.crazygames?.inviteLink({ seed: '42' });
    const seed = sdk.host.crazygames?.inviteParam('seed') ?? new URLSearchParams(location.search).get('seed');
    sdk.host.crazygames?.setGameContext({ level: 3 });
    ```

  </Fragment>
  <Fragment slot="typescript">
    ```ts
    import type { CrazygamesExtras } from '@filudi/game-sdk';

    const cg: CrazygamesExtras | undefined = sdk.host.crazygames;
    audio.mute(cg?.muted() ?? false);
    cg?.onMuteChange((muted: boolean) => audio.mute(muted));
    const link: string | undefined = cg?.inviteLink({ seed: '42' });
    const seed = cg?.inviteParam('seed') ?? new URLSearchParams(location.search).get('seed');
    cg?.setGameContext({ level: 3 });
    ```

  </Fragment>
</CodePanel>

## `host.poki`

| Member                                  | What it does                                    |
| --------------------------------------- | ----------------------------------------------- |
| `shareableURL(params): Promise<string>` | A poki.com link to the game with `params`       |
| `getURLParam(key): string \| null`      | A parameter of the link the player arrived with |

<CodePanel title="Poki extras">
  <Fragment slot="javascript">
    ```js
    const url = await sdk.host.poki?.shareableURL({ seed: '42' });
    const seed = sdk.host.poki?.getURLParam('seed');
    ```

  </Fragment>
  <Fragment slot="typescript">
    ```ts
    const url: string | undefined = await sdk.host.poki?.shareableURL({ seed: '42' });
    const seed: string | null | undefined = sdk.host.poki?.getURLParam('seed');
    ```

  </Fragment>
</CodePanel>

## `host.playgama`

| Member                   | What it does                                                                                                |
| ------------------------ | ----------------------------------------------------------------------------------------------------------- |
| `onAudioChange(fn): Off` | The platform's audio setting changed; `fn(enabled: boolean)`, the opposite of muted. Returns an unsubscribe |

<CodePanel title="Playgama extras">
  <Fragment slot="javascript">
    ```js
    sdk.host.playgama?.onAudioChange((enabled) => audio.mute(!enabled));
    ```

  </Fragment>
  <Fragment slot="typescript">
    ```ts
    sdk.host.playgama?.onAudioChange((enabled: boolean) => audio.mute(!enabled));
    ```

  </Fragment>
</CodePanel>

## A share link on every host

<CodePanel title="One function for every host">
  <Fragment slot="javascript">
    ```js
    async function shareLink(params) {
      if (sdk.host.crazygames) return sdk.host.crazygames.inviteLink(params);
      if (sdk.host.poki) return sdk.host.poki.shareableURL(params);
      const url = new URL(location.href);
      url.search = new URLSearchParams(params).toString();
      return url.toString();
    }
    ```

  </Fragment>
  <Fragment slot="typescript">
    ```ts
    async function shareLink(params: Record<string, string>): Promise<string> {
      if (sdk.host.crazygames) return sdk.host.crazygames.inviteLink(params);
      if (sdk.host.poki) return sdk.host.poki.shareableURL(params);
      const url = new URL(location.href);
      url.search = new URLSearchParams(params).toString();
      return url.toString();
    }
    ```

  </Fragment>
</CodePanel>

## Unavailable cases

The whole object is the unavailable case: on filudi.com all three names are `undefined`. Mute on
filudi.com is the page's own control; a game that wants a mute button draws one.
