Gå til hovedindhold
Udviklere Game SDK

Vis, hvad nogen spiller

Lad dit spil fortælle mssgs, hvad en spiller laver. Venner ser "Spiller" under navnet, åbner detaljerne og trykker på Deltag nu for at hoppe ind i det samme spil. Dit spil kan også tjekke, om en spiller er med i dit fællesskab.

Det kan du

  • Udgiv en spillestatusSpillet, hvad spilleren laver, spillerens rolle, og hvor fuld gruppen er.
  • Tilføj en Deltag nu-knapVenner kommer ind i det samme spil, på den samme server eller i den samme lobby med ét tryk.
  • Tjek medlemskabSpørg, om en spiller er med i dit fællesskab, og med hvilke roller.
  • Desktop, browser eller telefonNative spil bruger den lokale bridge; browser- og mobilspil går gennem din backend.

I appen

daniSpiller Space Raiders
Space RaidersSpilles af dani
Sector 7
I et raid
3 af 4 i gruppen · i 12 min
Skytte

Statussen under et navn og de detaljer, den åbner. Spillet udgav én JSON-blok; resten er appen.

Overblik

mssgs' desktop-app kører en lille lokal HTTP-bridge, som et spil på den samme maskine taler med. Dit spil taler aldrig med vores servere, ser aldrig en kontoadgangskode eller et token og kan aldrig poste som spilleren. Det taler med den kopi af mssgs, som spilleren allerede er logget ind på, og den kopi bestemmer, hvad der svares.

Det kan du bruge den til:

  • Registrere, at mssgs er installeret, og at nogen er logget ind.
  • Læse, hvem spilleren er: user_guid, brugernavn, avatar.
  • Spørge "er denne spiller med i fællesskab X?", og hvilken rolle spilleren har dér.
  • Udgive en "Spiller …"-status med en Deltag nu-knap til andre.
  • Modtage en deltagelsesoverdragelse, når nogen trykker på den knap.

To veje ind

Et native desktopspil taler med den lokale bridge; det er det, de næste afsnit beskriver. Et spil i en browser eller på en telefon kan ikke nå den bridge. For dem udgiver din egen backend status for spillere, der har forbundet deres mssgs-konto via en QR-kode eller en kode på otte tegn: se Browser- og mobilspil, med CozyCity som det første eksempel. Selve spillestatussen er den samme blok i begge tilfælde.

Minimal deling som standard

Scopes er bevidst ulige. Har du kun brug for at vide, "er denne person med i vores fællesskab", beder du om membership.query og angiver selv server_guid: du får ja/nej plus spillerens roller dér og lærer intet om resten af spillerens fællesskaber. Den fulde liste ligger bag et separat, højere scope, som spilleren skal godkende for sig.

Find klienten

Bridgen lytter kun på 127.0.0.1, på den første ledige port i et lille interval. Prøv dem i rækkefølge, indtil en svarer: 7440, 7441, 7442, 7443. Udviklingsbuilds af mssgs lytter i stedet på 7540–7543, så et testbuild aldrig svarer på et rigtigt spils kald.

GET http://127.0.0.1:7440/mssgs/v1/hello

Der kræves intet token, og svaret siger intet om spilleren, kun at mssgs er her, og om nogen er logget ind.

Svar
{
  "product": "mssgs",
  "api": 1,
  "client": "desktop",
  "version": "14.2.20015",
  "platform": "darwin",
  "signed_in": true,
  "scopes": ["identity", "staff", "membership.query", "servers.list", "presence.write"]
}

Tjek product === "mssgs" og api, før du går videre. Svarer ingen af de fire porte, kører mssgs ikke. Tilbyd så bare din normale oplevelse i stedet for at lade spilleren vente.

Bed om tilladelse

Alt undtagen /hello kræver et token, og et token findes først, når spilleren har godkendt dit spil i en dialog i appen. Bed kun om de scopes, du rent faktisk bruger: spilleren ser hvert enkelt for sig med en forklaring og kan fjerne fluebenet ved dem enkeltvis.

1. Bed om tilladelse
curl -X POST http://127.0.0.1:7440/mssgs/v1/authorize \
  -H "Content-Type: application/json" \
  -d '{
    "game_id": "com.acme.spacegame",
    "name": "Space Raiders",
    "scopes": ["identity", "membership.query", "presence.write"]
  }'

Du får {"status":"pending","request_id":"…","poll_after_ms":1000} tilbage, og spilleren ser dialogen. Poll derefter, indtil spilleren svarer (anmodningen udløber efter 3 minutter):

2. Poll efter svaret
curl http://127.0.0.1:7440/mssgs/v1/authorize/<request_id>

# {"status":"approved","token":"…","scopes":["identity","presence.write"],"game_id":"com.acme.spacegame"}

Tjek altid, hvad du faktisk fik

scopes i svaret kan være kortere end det, du bad om: spilleren kan frit fjerne fluebenet ved enkelte af dem. I eksemplet ovenfor blev membership.query afvist. Forgren på det, svaret siger, ikke på det, du bad om, ellers møder du en 403 MISSING_SCOPE, du ikke havde planlagt.

Gem tokenet, og send det som Authorization: Bearer <token>. Det overlever genstarter, så en spiller godkender dit spil én gang og ikke hver session. Genautoriserer du senere med scopes, der allerede er givet, får du det samme token tilbage med det samme uden nogen dialog.

Scopes og privatliv

De fem scopes giver meget forskellige mængder væk. Det er ikke tilfældigt; det er hele designet. Bed om så lidt som muligt, og arbejd dig ned gennem tabellen.

Scope Hvad det tillader Hvad spilleren giver fra sig
presence.write Vis, hvad spilleren spiller Intet. Dette scope skriver kun; det læser slet ingen kontodata.
identity Hvem spilleren er user_guid, brugernavn, visningsnavn, avatar-URL.
staff Staff-/moderatorflag To booleans oven i identity. Separat, fordi et spil, der viser et navn, ikke har noget at gøre med, om spilleren modererer fællesskaber.
membership.query Tjek et fællesskab, du allerede kender For et server_guid, du angiver: ja/nej, dets navn og de roller, spilleren har dér. Intet om noget andet fællesskab.
servers.list Alle fællesskaber, spilleren er med i Hele listen: guids, navne, ikoner og roller. Det er det dyre: bed kun om det, hvis du virkelig har brug for det.

De fleste spil har brug for to af dem

identity og presence.write dækker "hvem er du" og "vis, hvad du spiller", og det er næsten alle integrationer. Tilføj membership.query, hvis du vil knytte en belønning til medlemskab af dit fællesskab. Du har næsten aldrig brug for servers.list, og spilleren ser det fremhævet med rødt.

Tjek medlemskab

Dette er alternativet til "giv mig hele listen". Du angiver server_guid for dit eget fællesskab (som du allerede kender) og får et svar om netop det og intet andet.

Ét fællesskab
curl -H "Authorization: Bearer $TOKEN" \
  "http://127.0.0.1:7440/mssgs/v1/membership?server_guid=ca94ecc…f4g02"

# et medlem:
# {"server_guid":"ca94ecc…","member":true,"name":"Acme Fans","is_owner":false,
#  "roles":[{"guid":"0aa32…","name":"Pro"}]}

# ikke et medlem, og intet andet:
# {"server_guid":"…","member":false}

Et "nej" er præcis det og intet mere. Du må sende op til 10 guids per kald (gentag server_guid eller adskil dem med komma), hvilket returnerer et results-array. Gruppen @everyone er aldrig med i roles: den gælder for alle medlemmer, så den fortæller dig intet.

Udgiv en spillestatus

Ét PUT sætter "Spiller …"-linjen under spillerens navn, overalt hvor spillerens fællesskaber ser spilleren.

PUT /mssgs/v1/activity
{
  "name":    "Space Raiders",
  "details": "Sector 7",
  "state":   "In a raid",
  "role":    "Gunner",
  "started_at": 1755859200000,
  "party":   { "size": 3, "max": 4, "kind": "party" },
  "join":    { "secret": "raid-42" }
}

Kun name er påkrævet. Svaret fortæller dig, hvor længe statussen lever, og hvor tit du skal sende et heartbeat:

Svar
{ "ok": true, "expires_in_ms": 90000, "heartbeat_every_ms": 30000 }

Heartbeat, ellers forsvinder statussen

En status uden livstegn i 90 sekunder ryddes automatisk. Det er bevidst: hvis dit spil crasher, står spilleren ikke som "spiller" i timevis. Send et POST /mssgs/v1/activity/heartbeat hvert 30. sekund og DELETE /mssgs/v1/activity ved en ren nedlukning.

Antal spillere og rolle

party.kind bestemmer, hvilken sætning der vises, for de samme to tal betyder ikke det samme. Et hold på fire er ikke en server med fire spillere på.

kind Vises som Til
party (standard)3 af 4 i gruppenet hold, en crew eller en gruppe
server4/100 spillereen spilserver (FiveM, en fællesskabsserver)
lobby4/100 spillereen lobby, før kampen starter
match4/100 spillereen kamp eller runde, der er i gang

role (op til 48 tegn) er det, spilleren spiller som: et job, en klasse eller en figur. Den får sit eget felt i stedet for endnu en sætning i state, fordi den vises som en etiket ved siden af antallet af spillere.

details og state er begrænset til 128 tegn hver, name til 64. Linjeskift og kontroltegn fjernes. En ikon-URL understøttes bevidst ikke: den ville blive hentet af hver klient, der viser linjen, og det gør en status til et fyrtårn, der melder hvert medlem af hvert fællesskab, spilleren er med i, tilbage til din server.

Deltag nu-knappen

Læg en join-blok i din aktivitet, så får andre medlemmer en Deltag nu-knap ved siden af statussen. Der er to måder, og du kan kombinere dem.

1. En hemmelighed (til native spil)

Sæt {"join":{"secret":"raid-42"}}. Når nogen trykker på Deltag nu, leveres den hemmelighed til deres egen kopi af dit spil på deres egen maskine, matchet på det samme game_id. Der åbnes ingen URL, og ingen scheme-handler kaldes. Dit spil henter den med:

GET /mssgs/v1/events
{
  "events": [
    { "seq": 1, "type": "join", "secret": "raid-42",
      "from": { "user_guid": "62e377…", "username": "mssgs-test-1" } }
  ],
  "cursor": 1
}

Poll med ?since=<cursor>, så du ser hver hændelse én gang. Kører spillet hos den, der trykkede, ikke, leveres der intet, og det er en god grund til også at tilbyde en URL.

2. En https-URL (til webspil og lobbylinks)

Sæt {"join":{"url":"https://play.example.com/s/abc"}}, så åbner knappen det link. Kun https accepteres. Et brugerdefineret scheme (steam://, mygame://, file://) afvises: den blok lander på hvert medlems skærm, og sådan en URL er en måde at få en andens maskine til at kalde en lokal handler med argumenter, du har valgt.

Alt i join er offentligt

join-blokken sendes ud til alle, der kan se spillerens status; det er hele pointen med en Deltag nu-knap. Behandl den derfor som en lobbykode, ikke som et login. Læg aldrig noget i den, der skal forblive hemmeligt, og lad dine koder udløbe.

FiveM

FiveM har ingen HTTP i sin Lua-runtime på klientsiden, så en resource taler med bridgen gennem NUI, en CEF-visning, som sender en Origin. Bridgen accepterer eksplicit de origins: https://cfx-nui-<resource> og den ældre nui://<resource>. Almindelige websider afvises stadig, og en side på det åbne web kan ikke udgive sig for at have den origin; browseren sætter den selv.

client.lua: bed NUI om at udgive
-- NUI-siden står for HTTP; Lua sender den kun dataene.
CreateThread(function()
  while true do
    SendNUIMessage({
      action  = 'mssgs:publish',
      players = GetActivePlayers and #GetActivePlayers() or 0,
      maxPlayers = GetConvarInt('sv_maxclients', 100),
      job     = exports['qb-core'] and 'Police' or nil
    })
    Wait(30000) -- heartbeat: statussen udløber efter 90 s
  end
end)
nui.js
const BASE = 'http://127.0.0.1:7440/mssgs/v1';   // prøv 7440-7443
let token = null;

async function authorize () {
  const res = await fetch(`${BASE}/authorize`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      game_id: 'fivem.lossantos.rp',
      name: 'Los Santos Roleplay',
      scopes: ['presence.write']          // mere er ikke nødvendigt her
    })
  });
  const started = await res.json();
  if (started.status === 'approved') { return started.token; }

  // Spilleren ser nu tilladelsesdialogen i mssgs.
  for (let i = 0; i < 180; i += 1) {
    await new Promise((r) => { setTimeout(r, 1000); });
    const poll = await (await fetch(`${BASE}/authorize/${started.request_id}`)).json();
    if (poll.status === 'approved') { return poll.token; }
    if (poll.status !== 'pending') { return null; }
  }
  return null;
}

window.addEventListener('message', async (event) => {
  if (event.data.action !== 'mssgs:publish') { return; }
  if (!token) { token = await authorize(); }
  if (!token) { return; }

  await fetch(`${BASE}/activity`, {
    method: 'PUT',
    headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` },
    body: JSON.stringify({
      name: 'FiveM',
      details: 'Los Santos Roleplay',
      role: event.data.job,                       // "Police"
      party: { size: event.data.players, max: event.data.maxPlayers, kind: 'server' },
      join: { url: 'https://cfx.re/join/abc123' } // dit cfx.re-link
    })
  });
});

Resultatet: Spiller FiveM · Los Santos Roleplay · 4/100 spillere · Police, med en Deltag nu-knap, der åbner dit cfx.re-link.

Bed kun om presence.write

En spillestatus har ikke brug for andet: det scope læser slet ingenting. Vil du knytte en belønning i spillet til medlemskab af dit mssgs-fællesskab, så tilføj membership.query og angiv dit eget server_guid; du lærer stadig intet om spillerens andre fællesskaber.

En server, du spiller på, er ikke automatisk betroet

Enhver FiveM-server kan køre klient-resources, så enhver server, nogen går ind på, kan bede om tilladelse. Det er netop derfor, der sidder en dialog imellem, som navngiver resourcen: det er spilleren, der bestemmer, ikke serveren.

Browser- og mobilspil: forbind gennem din backend

Et spil i en browserfane eller på en telefon kan ikke nå bridgen ovenfor. Den kører på spillerens desktop, og tre mure står i vejen: bridgen afviser enhver anmodning med en browser-Origin, Chrome sætter en tilladelsesprompt foran en offentlig side, der henter 127.0.0.1, og Safari afviser helt, og en telefon har overhovedet ingen vej til en desktops loopback.

Så retningen vendes om. Din egen backend ved allerede, hvem der spiller, og den fortæller det til mssgs, for spillere, der har forbundet deres mssgs-konto med dit spil. Forbindelsen godkendes i mssgs-appen, aldrig i dit spil, og den opretter en forbindelse, aldrig en session: intet nedenfor kan logge nogen ind eller handle som spilleren. Din spilklient ser aldrig en nøgle og taler aldrig med mss.gs. Det første spil på denne vej er CozyCity, et bybyggerspil, der udkommer som en WebGL-side og en iPhone-app uden desktopbuild; eksemplerne nedenfor er dets egne.

1. Registrér dit spil

Registrér spillet på Game SDK’ets registreringsside: dit game_id (for eksempel com.deverence.cozycity), det navn og ikon, spilleren ser på godkendelsesarket, og dine backend-hostnavne. Vi gennemgår det dér, og når det er godkendt, venter din backend-nøgle på samme side, vist én gang; vi gemmer kun et digest. Nøglen hører til på din server og ingen andre steder. Du kan rotere den dér når som helst, og den gamle forbliver gyldig i 24 timer, så et deploy kan rulle ud.

Registrér dit spil

Navnet og ikonet på arket kommer altid fra registreringen, aldrig fra anmodningen. Ellers kunne et phishinglink klæde en forbindelsesanmodning ud som et hvilket som helst spil. Hostnavnene afgrænser, hvor en join.url må pege hen, se nedenfor.

2. Forbind en spiller

Spilleren vælger Forbind mssgs i dit spil. Dit spil spørger din backend, og din backend spørger os:

POST /game-sdk/v1/link/start
curl -X POST https://ams1-gateway.mss.gs/game-sdk/v1/link/start \
  -H "Authorization: Bearer $BACKEND_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "player_ref": "player-8812", "player_name": "René\u2019s city" }'

# {"link_code":"K7PQ2XM4","device_code":"…","qr_url":"https://mss.gs/gl/K7PQ2XM4",
#  "deep_link":"mssgs://link-game/K7PQ2XM4","expires_in":600,"interval":5}

player_ref er dit eget stabile id for spilleren (op til 128 tegn), ikke for en session eller en kamp; player_name (op til 64) er det, arket viser som "Spiller: …". Giv kun din spilklient link_code, qr_url og deep_link. device_code er dit polling-håndtag og bliver på serveren.

Dit spil viser så tre ting på én gang, for spilleren kan være hvor som helst:

  • QR-koden for qr_url. En telefon med mssgs åbner den direkte i appens godkendelsesark. Uden appen lander den på en side på mss.gs, der viser koden og tilbyder download.
  • En "Åbn i mssgs"-knap med deep_link, til en desktopbrowser ved siden af desktop-appen. Det er den eneste eksterne URL, dit spil nogensinde behøver at åbne.
  • Selve koden, i to grupper af fire, til at skrive under Indstillinger → Spilaktivitet → Forbind et spil. Alfabetet har ingen 0/O eller 1/I, så det går sjældent galt, når den skrives.

Det, spilleren ser i mssgs, tegnet af appen ud fra registreringen:

Forbind CozyCity til din mssgs-konto?

CozyCity vil kunne vise, hvad du spiller, som din mssgs-status. Spillet ser ikke dine beskeder, dine venner eller dine servere, og det kan ikke skrive som dig.
Spiller: Renés by · Forbind / Ikke nu

Imens poller din backend hvert interval sekund (hurtigere svarer 429 SLOW_DOWN), indtil statussen skifter. En kode virker én gang og udløber efter ti minutter:

POST /game-sdk/v1/link/poll
curl -X POST https://ams1-gateway.mss.gs/game-sdk/v1/link/poll \
  -H "Authorization: Bearer $BACKEND_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "device_code": "…" }'

# {"status":"pending"}
# {"status":"denied"}      # spilleren valgte Ikke nu
# {"status":"expired"}
# {"status":"linked","link_guid":"…","user":{"user_guid":"62e377…"}}

Gem link_guid ved din spiller; fra nu af er det den adresse, du udgiver for. Svaret indeholder kun user_guid; et username tilføjes kun, når din registrering har scopet identity.link, og mere end det er der ikke. En ny godkendelse for det samme player_ref erstatter den tidligere forbindelse, så én spiller i dit spil er én mssgs-konto. Den samme mssgs-konto kan forbindes med flere spil og med flere player_refs i ét spil (en familie-iPad).

3. Udgiv spillestatussen

Den samme blok som på bridgen, med de samme regler og de samme grænser, blot nu per forbindelse og med din backend-nøgle:

PUT /game-sdk/v1/links/{link_guid}/activity
{
  "activity": {
    "name":       "CozyCity",
    "details":    "Lantern Hollow",
    "state":      "Day 12 · 34 residents",
    "started_at": 1788901000000,
    "party":      { "size": 6, "max": 40, "kind": "server" },
    "join":       { "url": "https://cozycity.net/game/?share=…" }
  }
}
Svar
200 {"published":true,"changed":true}     # blokken blev ændret og sendt ud
200 {"published":true,"changed":false}    # identisk med det gemte; kun TTL blev fornyet
204                                        # gemt, men spilleren er ikke online i mssgs lige nu
410 {"error":"LINK_REVOKED"}               # spilleren afbrød forbindelsen: slip den

Behandl 200 og 204 ens: gemt. { "activity": null } rydder blokken, send det, når spilleren går. Én forskel fra bridgen: værten i join.url skal være en af dine registrerede backends (eller et subdomæne af en), ellers får du 400 INVALID_PAYLOAD. Så en backend kan ikke sætte en Deltag nu-knap på en spillers status, der fører et sted hen, hvor spilleren aldrig har spillet.

Heartbeat hvert 60. sekund, TTL 120

En udgivet status lever 120 sekunder uden en ny besked og forsvinder så af sig selv. Send derfor den samme blok igen hvert 60. sekund; en uændret blok koster intet og fornyer kun TTL. Stopper dit heartbeat, stopper "Spiller …"-linjen, og det er netop pointen.

Med hundredvis af spillere online sender du heartbeat i ét kald, op til 100 elementer ad gangen. Hvert element får sin egen status, så én spiller, der har afbrudt forbindelsen i mssgs, aldrig stopper de andre nioghalvfems:

POST /game-sdk/v1/activity/batch
{ "items": [ { "link_guid": "…", "activity": { "name": "CozyCity", "details": "Lantern Hollow" } },
             { "link_guid": "…", "activity": null } ] }

// → 200 { "results": [ { "link_guid": "…", "status": 200, "changed": false },
//                      { "link_guid": "…", "status": 410 } ] }

Sådan vises statussen

  • Identisk med en bridge-status: Spiller CozyCity · Lantern Hollow · 6/40 spillere, med Deltag nu, når der er en join.url. Blokken stemples via: "backend" på serversiden, så en klient kan tilføje "Delt af spillets server".
  • Kun mens spilleren er online i mssgs. Uden en åben mssgs-klient er kontoen offline og forbliver offline; din backend kan ikke få nogen til at se til stede ud. Det forhindrer også, at denne vej bliver et "sidder René ved sin computer"-fyrtårn.
  • Forrang: et spil i appen > et spil på bridgen > din backend. Sætter spilleren sig til et parti skak inde i mssgs, mens din backend bliver ved med at sende heartbeat, vinder skakken, ikke den, der skrev sidst.

Afbryd forbindelsen

Spilleren ser hver forbindelse under Indstillinger → Spilaktivitet → Forbundne spil med dit ikon og navn, spillernavnet fra dit spil, hvornår forbindelsen blev oprettet, og hvornår der sidst blev udgivet, samt en Afbryd-knap. Derefter svarer din næste udgivelse 410 LINK_REVOKED; sådan finder dit spil ud af det. Slip link_guid, og tilbyd "Forbind mssgs" igen. Fra din side afslutter du en forbindelse med DELETE /game-sdk/v1/links/{link_guid}.

Grænser

Per forbindelse tæller en ændring højst hvert 2. sekund; et uændret heartbeat er gratis. Per nøgle er der 600 anmodninger i minuttet, hvor batch-elementer tælles enkeltvis: heartbeat for 300 spillere hvert 60. sekund bruger 5 af de 600.

Endpoint-reference: bridgen

Basis-URL http://127.0.0.1:<port>. Alt undtagen de tre første kræver Authorization: Bearer <token>.

Metode Sti Scope Hvad den gør
GET /mssgs/v1/hello intet Er mssgs her, hvad taler det, og er nogen logget ind? Den eneste route, der ikke kræver et token, og den siger intet om spilleren.
POST /mssgs/v1/authorize intet Bed spilleren om tilladelse. Viser en dialog i appen og returnerer et request_id, der skal polles.
GET /mssgs/v1/authorize/:request_id intet pending, approved (med tokenet), denied eller expired.
GET /mssgs/v1/me identity Den indloggede spiller. Tilføjer kun is_staff / is_moderator med staff-scopet.
GET /mssgs/v1/membership membership.query Medlemskab af de server_guid-værdier, du sender (op til 10, gentaget eller kommasepareret).
GET /mssgs/v1/servers servers.list Alle fællesskaber, spilleren er med i, med spillerens roller. Direkte beskeder er aldrig med.
PUT /mssgs/v1/activity presence.write Udgiv "Spiller …"-blokken. Returnerer TTL, og hvor tit der skal sendes heartbeat.
POST /mssgs/v1/activity/heartbeat presence.write Hold den udgivne aktivitet i live uden at sende den igen.
DELETE /mssgs/v1/activity presence.write Ryd den med det samme, ved en ren nedlukning.
GET /mssgs/v1/events presence.write Deltagelsesoverdragelser rettet mod dit spil. Poll med ?since=<cursor>.
GET /mssgs/v1/session intet Hvad dette token har: game_id, givne scopes, og om nogen er logget ind.
DELETE /mssgs/v1/session intet Giv tilladelsen tilbage. Samme virkning, som når spilleren tilbagekalder den i Indstillinger.

Endpoint-reference: forbundne backends

Basis-URL https://ams1-gateway.mss.gs. Hver route kræver Authorization: Bearer <backend key> og scopet activity.write på din registrering; svar sendes med Cache-Control: no-store. Kald dem fra din server, aldrig fra spilklienten.

Metode Sti Hvad den gør
POST /game-sdk/v1/link/start Start en forbindelse for en af dine spillere ({ player_ref, player_name? }). Returnerer link_code, device_code, qr_url, deep_link, expires_in og interval.
POST /game-sdk/v1/link/poll { device_code } → pending, denied, expired eller linked med link_guid og user.
DELETE /game-sdk/v1/links/{link_guid} Afslut en forbindelse fra din side. Spilleren kan gøre det samme fra Indstillinger.
PUT /game-sdk/v1/links/{link_guid}/activity Udgiv "Spiller …"-blokken for én spiller; { "activity": null } rydder den.
POST /game-sdk/v1/activity/batch Det samme for op til 100 spillere i ét kald. Hvert element svarer for sig.

Fejlkoder

Fejl kommer tilbage som {"error":"CODE","message":"…"} med en tilsvarende HTTP-status.

Kode Betydning
401 UNAUTHORIZEDManglende eller ukendt token; autorisér først.
403 MISSING_SCOPESpilleren gav ikke den tilladelse. Spilleren kan have fjernet fluebenet ved den.
403 ORIGIN_NOT_ALLOWEDAnmodningen havde en browser-Origin. Se "Kun native spil" nedenfor.
409 NOT_SIGNED_INmssgs kører, men ingen er logget ind.
429 RATE_LIMITEDMere end 120 anmodninger i minuttet fra ét spil.
400 INVALID_GAME_IDgame_id må kun bestå af bogstaver, tal, punktum, bindestreg eller understregning.
400 TOO_MANY_GUIDSHøjst 10 server_guid-værdier per medlemskabskald.

Forbundne backends

Backend-routes bruger samme form. I en batch kommer statussen tilbage per element i results, så én afsluttet forbindelse aldrig får hele kaldet til at fejle.

Kode Betydning
401 INVALID_BACKEND_KEYUkendt nøgle, eller en nøgle, der blev roteret ud for mere end 24 timer siden.
403 SCOPE_NOT_GRANTEDDin registrering har ikke det scope, som routen kræver.
400 INVALID_PAYLOADUgyldig body, mere end 100 batch-elementer eller en join.url, hvis vært ikke er en af dine registrerede backends.
400 INVALID_ACTIVITYIntet brugbart navn tilbage efter normalisering.
410 LINK_REVOKEDForbindelsen er afsluttet, fra en af siderne. Slip den, og tilbyd "Forbind mssgs" igen.
429 SLOW_DOWNDu pollede link/poll hurtigere end interval.
429 RATE_LIMITEDEn ændring af én forbindelse inden for 2 sekunder af den forrige, eller mere end 600 anmodninger i minuttet på din nøgle.
503 LINK_STORE_UNAVAILABLEMidlertidigt på vores side. Prøv igen ved dit næste heartbeat.

Sikkerhed

Kun native spil

Anmodninger med en websides Origin afvises med 403 ORIGIN_NOT_ALLOWED. At enhver webside kan registrere, at du kører mssgs, og fremkalde en tilladelsesdialog, er en flade for fingerprinting og phishing, ikke en funktion. Et native spil sender slet ingen Origin, så det påvirkes ikke, og et spils egen indlejrede browser tillades ved navn, se FiveM. Bygger du et browser- eller mobilspil, taler du ikke med bridgen: din egen backend udgiver for forbundne spillere, se Browser- og mobilspil.

Det, spilleren beholder kontrollen over

  • Spilleren kan slå bridgen fra under Indstillinger → Spilaktivitet, og derefter kan intet spil overhovedet se mssgs.
  • Hvert godkendt spil står dér med præcis de tilladelser, det har, hvornår det sidst var aktivt, og en Fjern-knap. Fjernelse sker med det samme: tokenet dør øjeblikkeligt.
  • Et forbundet browser- eller mobilspil står under Forbundne spil med en Afbryd-knap. Også det sker med det samme: den backends næste udgivelse får en 410.
  • Bridgen lytter kun på 127.0.0.1, aldrig på netværket.
  • Direkte beskeder afsløres aldrig, heller ikke med servers.list.
  • Der er et budget på 120 anmodninger i minuttet per spil.

Vær en god borger

  • Bed om scopes, når du har brug for dem, ikke alle på én gang ved første opstart.
  • Fungér uden mssgs: spilleren behøver ikke at have det.
  • Ryd din status, når spillet stopper, i stedet for at vente på TTL.
  • Behandl et afvist scope som et normalt udfald, ikke som en fejl.

Byg videre