Hyperfocus

Game invites and join codes in Hyperfocus

Hyperfocus can carry a friend into your multiplayer game. While your game runs, it tells the launcher that invites are on and gives it a join code (a room ID, a lobby name, anything). The player picks a friend in Hyperfocus, the friend accepts, Hyperfocus launches their copy of the game and hands it the code. Your game decides what the code means. There is nothing to host: the invite is a normal Velora message. Friends can also join on their own, without an invite, when the game allows it (see Letting friends join).

How the flow works

  1. The game turns invites on and sets a join code (when the player creates or enters a room, for example).
  2. The player invites a friend. The Hyperfocus friends window (open it with the overlay hotkey, Shift + Tab by default, or let the game open it) shows an invite bar and an invite button next to every friend while invites are on. The game can also open the friends list itself.
  3. The friend gets a popup, "invited you to play <game> - click to join!", and the same invite as a join button in the chat. Clicking either one joins.
  4. Hyperfocus joins: it launches the game if it is not running (installing or updating comes first if needed), and remembers the code, the sender's name and an invite number for that game.
  5. The game reads the invite (GET /hyperfocus/invite or the Scratch hat block), connects to the room from the code, and clears the invite.
What the invite looks like.It is a message from the player with a link in it: hyperfocus://join/<game id>/<join code>. The code part is left out when the game has not set one. Opening such a link (from a browser, for example) does the same as accepting the invite, so you can also put join links on a website or in a Discord server.

What the invited player needs

The bridge calls

These are on the game bridge. They only work for a game Hyperfocus started (409 not_running otherwise) and, from a website, need the one-time Allow popup.

Turn invites on and set the code

POST /hyperfocus/invites
{ "enabled": true, "code": "room123" }

-> { "ok": true, "invites": { "enabled": true, "code": "room123", "joinable": false } }

All fields are optional (joinable is covered under Letting friends join); send only what changed. code may contain letters, numbers, - and _, up to 64 characters (400 bad_code otherwise). Send an empty code to remove it. Update the code whenever the room changes: the invite carries whatever the code is at the moment the player presses invite. Turn invites off with "enabled": false when the player is not in a room that can be joined.

Read an accepted invite

GET /hyperfocus/invite

-> { "ok": true,
     "invite": { "code": "room123", "from": "Ikelene", "seq": 3, "kind": "invite" },
     "invites": { "enabled": true, "code": "room123", "joinable": false } }

kind is "invite" for an accepted invite and "join" when the player joined a friend themselves (an older launcher leaves it out: treat a missing kind as an invite). invite is null when there is none. seq goes up with every accepted invite, so poll every second or two and act when seq is new. An invite is forgotten when the game closes, when you clear it, or after 30 minutes.

Clear it, open the friends list

POST /hyperfocus/invite/clear      -> { "ok": true }
POST /hyperfocus/friends/open      -> { "ok": true }

The friends list opens over the game until the player clicks away.

A complete example

const HF = 'http://127.0.0.1:47833/hyperfocus';
const post = (path, body) => fetch(HF + path, { method: 'POST', headers: { 'Content-Type': 'text/plain' }, body: JSON.stringify(body) }).then(r => r.json());

// when the player opens a lobby
post('/invites', { enabled: true, code: lobby.id });

// when the lobby closes
post('/invites', { enabled: false, code: '' });

// poll for an accepted invite
let seen = 0;
setInterval(async () => {
  const { invite } = await fetch(HF + '/invite').then(r => r.json()).catch(() => ({}));
  if (invite && invite.seq !== seen) {
    seen = invite.seq;
    joinLobby(invite.code, invite.from);
    post('/invite/clear', {});
  }
}, 1500);

Letting friends join

Invites need the player to press a button. Joins work the other way round: while your game allows them, a friend sees In joinable game as the player's status and a Join game button on the player's profile and in the Friends tab of the launcher, and can jump in on their own. Hyperfocus starts the game for them (installing or updating first if needed) and hands their copy the join code, exactly like an accepted invite. If they do not have the game yet, Hyperfocus opens its library or store page instead.

POST /hyperfocus/invites
{ "joinable": true, "code": "room123" }

-> { "ok": true, "invites": { "enabled": false, "code": "room123", "joinable": true } }
{ "ok": true,
  "invite": { "code": "room123", "from": "Ikelene", "seq": 4, "kind": "join" },
  "invites": { "enabled": false, "code": "", "joinable": false } }

Your game can treat both kinds the same (connect to the room from the code) or tell them apart with kind, for example to skip a "you were invited" message when the player chose to join.

The Scratch extension

The Hyperfocus extension (https://ikelene.net/launcher/hyperfocus_extension.js) has blocks for all of it. It checks for an accepted invite every 1.5 seconds while the game is launched.

allow inviting friends STATEset join code to CODEallow friends to join STATEopen friends listwhen joining a friend's gamejoined from an invite?joined a friend themselves?invite join codeinvited byforget the invite

The extension remembers what the project set (invites on, joins on, the code) and sends it again if the launcher restarts.

Setting it up for testing

Invites need a running game. To test from an editor in the browser, turn on Developer Mode in the Hyperfocus settings and allow game extension connections with no game open, then name the game with the block this game's Hyperfocus ID is (or game in the call). Two accounts help: the invite is sent to another Velora account that has you as a friend.

Questions

Does the friend need the game installed?

They need the game in their Hyperfocus library. Community games are added to the library automatically when they accept; if the game still needs installing or an update, Hyperfocus tells them and keeps the invite for 30 minutes.

What can a join code contain?

Letters, numbers, hyphens and underscores, up to 64 characters. Typical codes are room IDs or lobby names.

What if the friend already has the game open?

Hyperfocus stores the invite and your game picks it up the next time it asks for it (the Scratch extension asks every 1.5 seconds).

Can an invite be sent when the game is not running?

No. Invites need a game that Hyperfocus started, unless you are testing with the developer settings.

Can friends join without an invite?

Yes. Allow joins (POST /hyperfocus/invites with joinable true, or the allow friends to join block) and set a join code. Friends then see In joinable game and a Join game button on your profile and in the Friends tab, and their copy of the game receives the code with kind set to join.

More Hyperfocus guides