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
- The game turns invites on and sets a join code (when the player creates or enters a room, for example).
- 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.
- 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.
- 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.
- The game reads the invite (
GET /hyperfocus/inviteor the Scratch hat block), connects to the room from the code, and clears the invite.
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 game in their Hyperfocus library. Community games (
c-IDs) are added automatically; an official game has to be in their library. - The game installed and up to date. If it is not, they see a message saying what it needs first, and the invite waits for 30 minutes.
- To be a friend of the player who invited them on Velora, since invites travel as messages between friends.
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 } }
- Joins work when
joinableis on and a code is set. That is independent ofenabled:enabledonly controls the invite buttons, so a game can allow joins without showing any invite buttons, or the other way round. - The join code is only shown to the player's friends, never on public profiles.
- Like the rest of the invite settings,
joinableis forgotten when the game closes. Turn it off with"joinable": falsewhen the player is not in a room that can be joined, and update the code when the room changes. - The joining player's game reads it from the same
GET /hyperfocus/invitecall, with"kind": "join"andfromset to the friend they joined:
{ "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 [on/off] turns the invite buttons on or off. set join code to sets the code.
- when joining a friend's game is an edge-activated hat: it fires once when an invite arrives, also when the game was just launched by the invite. Use invite join code and invited by inside it.
- joined from an invite? is true from the moment an invite arrives until you use forget the invite, the game closes, or 30 minutes pass. It is true for joins as well as invites.
- allow friends to join [on/off] lets friends join from the player's profile and Friends tab. It works together with set join code to: friends can only join while a code is set.
- joined a friend themselves? is true when the current invite is a join, not an invite. The hat, invite join code and invited by work the same for both, so most games only need the one flow.
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.