---
title: "Game SDK: pokaži, kaj igralci igrajo v mssgs"
description: "Iz svoje igre objavi status „Playing“ z gumbom Join now in preveri članstvo v skupnosti. mssgs Game SDK za izvorne igre, igre v brskalniku in na telefonu."
canonical: https://docs.mss.gs/sl/game-sdk
language: sl
---

# Pokaži, kaj nekdo igra

Naj tvoja igra sporoča mssgs, kaj počne igralec. Prijatelji pod njegovim imenom vidijo „Playing“, odprejo podrobnosti in z gumbom Join now skočijo v isto igro. Tvoja igra lahko preveri tudi, ali je igralec v tvoji skupnosti.

## Kaj lahko narediš

- **Objavi status igranja** Igra, kaj igralec ravno počne, njegova vloga in kako polna je ekipa.

- **Dodaj gumb Join now** Prijatelji se z enim pritiskom pridružijo isti igri, strežniku ali lobiju.

- **Preveri članstvo** Vprašaj, ali je igralec v tvoji skupnosti in s katerimi vlogami.

- **Namizje, brskalnik ali telefon** Izvorne igre uporabljajo lokalni most; igre v brskalniku in na telefonu gredo prek tvojega backenda.

V aplikaciji

Status pod imenom in podrobnosti, ki jih odpre. Igra je objavila en blok JSON; vse drugo naredi aplikacija.

- [Pregled](#overview)

- [Iskanje odjemalca](#discover)

- [Prošnja za dovoljenje](#authorize)

- [Status igranja](#activity)

- [Join now](#join)

- [Brskalnik in telefon](#linked)

- [Referenca](#reference)

## Pregled

Namizna aplikacija mssgs poganja majhen **lokalni HTTP-most**, s katerim se pogovarja igra na istem računalniku. Tvoja igra nikoli ne komunicira z našimi strežniki, nikoli ne vidi gesla ali žetona računa in nikoli ne more objavljati v imenu igralca. Pogovarja se s kopijo mssgs, v katero je igralec že prijavljen, in ta kopija odloči, kaj bo odgovorila.

Kaj lahko narediš z njim:

- Zaznaš, da je mssgs nameščen in da je nekdo prijavljen.

- Prebereš, kdo je igralec: user_guid, username, avatar.

- Vprašaš „ali je ta igralec v skupnosti X?“ in kakšno vlogo ima tam.

- Objaviš status „Playing …“ z gumbom **Join now** za druge.

- Prejmeš podatke za pridružitev, ko nekdo pritisne ta gumb.

### Dve poti

**Izvorna namizna igra** se pogovarja z lokalnim mostom; to opisujejo naslednji razdelki. Igra **v brskalniku ali na telefonu** do tega mostu ne more. Zanjo objavlja tvoj lastni backend, in sicer za igralce, ki so svoj račun mssgs povezali s kodo QR ali z osemznakovno kodo: glej [Igre v brskalniku in na telefonu](#linked), s [CozyCity](https://cozycity.net) kot prvim primerom. Sam status igranja je v obeh primerih isti blok.

### Privzeto čim manj razkritih podatkov

Obsegi so namenoma neenaki. Če potrebuješ samo odgovor na vprašanje „ali je ta oseba v naši skupnosti“, zaprosiš za membership.query in sam navedeš server_guid: dobiš da/ne in vloge te osebe tam, o njenih drugih skupnostih pa ne izveš ničesar. Celoten seznam je za ločenim, višjim obsegom, ki ga mora igralec odobriti posebej.

## Iskanje odjemalca

Most posluša samo na 127.0.0.1 , na prvem prostem portu iz majhnega razpona. Preizkušaj jih po vrsti, dokler se kateri ne odzove: **7440, 7441, 7442, 7443**. Razvojne različice mssgs namesto tega poslušajo na **7540–7543**, zato testna različica nikoli ne odgovori na klice prave igre.

Žeton ni potreben, odgovor pa o igralcu ne pove ničesar, le to, da je mssgs tu in ali je kdo prijavljen.

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

Preden nadaljuješ, preveri product === "mssgs" in api . Če se ne odzove nobeden od štirih portov, mssgs ne teče. Takrat preprosto ponudi običajno izkušnjo, namesto da igralca pustiš čakati.

## Prošnja za dovoljenje

Vse razen /hello zahteva žeton, žeton pa obstaja šele, ko igralec tvojo igro odobri v pogovornem oknu v aplikaciji. Prosi samo za obsege, ki jih res uporabljaš: igralec vidi vsakega posebej, z razlago, in lahko vsakega posebej odznači.

```bash
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"]
  }'
```

Nazaj dobiš {"status":"pending","request_id":"…","poll_after_ms":1000} , igralec pa vidi pogovorno okno. Nato poizveduj, dokler ne odgovori (zahteva poteče po 3 minutah):

```bash
curl http://127.0.0.1:7440/mssgs/v1/authorize/<request_id>

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

### Vedno preveri, kaj si dejansko dobil

Seznam scopes v odgovoru je lahko **krajši** od tistega, za katerega si prosil: igralec lahko posamezne obsege odznači. V zgornjem primeru je bil membership.query zavrnjen. Ravnaj se po tem, kar pove odgovor, ne po tem, kar si zahteval, sicer naletiš na 403 MISSING_SCOPE , ki ga nisi predvidel.

Shrani žeton in ga pošiljaj kot Authorization: Bearer <token> . Preživi ponovne zagone, zato igralec tvojo igro odobri enkrat in ne ob vsaki seji. Če pozneje znova avtoriziraš z obsegi, ki so bili že odobreni, takoj dobiš isti žeton, brez pogovornega okna.

## Obsegi in zasebnost

Pet obsegov razkrije zelo različne količine podatkov. To ni naključje, na tem temelji celotna zasnova. Prosi za čim manj in začni na vrhu te tabele.

| Obseg | Kaj omogoča | Kaj igralec preda |
| --- | --- | --- |
| presence.write | **Pokaži, kaj igra** | Nič. Ta obseg samo piše; ne bere nobenih podatkov računa. |
| identity | **Kdo je igralec** | user_guid, username, prikazno ime, URL avatarja. |
| staff | **Oznake osebja / moderatorja** | Dve logični vrednosti, poleg identity. Ločeno, ker igra, ki prikazuje ime, nima kaj vedeti, da igralec moderira skupnosti. |
| membership.query | **Preverjanje skupnosti, ki jo že poznaš** | Za server_guid, ki ga navedeš: da/ne, njeno ime in vloge, ki jih ima igralec tam. Nič o nobeni drugi skupnosti. |
| servers.list | **Vse skupnosti, v katerih je** | Celoten seznam: guidi, imena, ikone in vloge. To je drag obseg: zanj prosi le, če ga res potrebuješ. |

### Večina iger potrebuje dva

identity in presence.write pokrijeta „kdo si“ in „pokaži, kaj igraš“, kar zadošča skoraj vsaki integraciji. Dodaj membership.query , če želiš nagrado povezati s članstvom v svoji skupnosti. servers.list skoraj nikoli ne potrebuješ, igralec pa ga vidi označenega z rdečo.

## Preverjanje članstva

To je alternativa za „daj mi cel seznam“. Navedeš server_guid svoje skupnosti (ki ga že poznaš) in dobiš odgovor samo o njej.

```bash
curl -H "Authorization: Bearer $TOKEN" \
  "http://127.0.0.1:7440/mssgs/v1/membership?server_guid=ca94ecc…f4g02"

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

# ni član in nič drugega:
# {"server_guid":"…","member":false}
```

„Ne“ pomeni točno to in nič več. V enem klicu lahko podaš do 10 guidov (ponovi server_guid ali jih loči z vejicami), kar vrne seznam results . Skupine @everyone nikoli ni v roles : velja za vsakega člana, zato ti ne pove ničesar.

## Objava statusa igranja

En PUT postavi vrstico „Playing …“ pod igralčevo ime, povsod, kjer ga vidijo njegove skupnosti.

```json
{
  "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" }
}
```

Obvezen je samo name . Odgovor ti pove, kako dolgo status živi in kako pogosto pošiljati heartbeat:

```json
{ "ok": true, "expires_in_ms": 90000, "heartbeat_every_ms": 30000 }
```

### Heartbeat, sicer status izgine

Status, ki 90 sekund ne da znaka življenja, se samodejno počisti. To je namerno: če se tvoja igra sesuje, igralec ne ostane ure „v igri“. Vsakih 30 sekund pošlji POST /mssgs/v1/activity/heartbeat , ob urejenem izklopu pa DELETE /mssgs/v1/activity .

### Število igralcev in vloga

party.kind določa, kateri stavek se prikaže, ker isti dve števili ne pomenita vedno istega. Štiričlanska ekipa ni strežnik s štirimi igralci.

| kind | Prikaže se kot | Za |
| --- | --- | --- |
| party (privzeto) | 3 of 4 in the party | ekipa, posadka ali skupina |
| server | 4/100 players | strežnik igre (FiveM, strežnik skupnosti) |
| lobby | 4/100 players | lobi pred začetkom tekme |
| match | 4/100 players | tekma ali runda v teku |

role (do 48 znakov) pove, *kot kdo* igralec igra: poklic, razred ali lik. Ima svoje polje namesto še enega stavka v state , ker se prikaže kot oznaka poleg števila igralcev.

details in state sta omejena na 128 znakov vsak, name na 64. Prelomi vrstic in kontrolni znaki se odstranijo. **URL ikone namenoma ni podprt**: prenesel bi ga vsak odjemalec, ki prikaže to vrstico, s čimer bi status postal oddajnik, ki tvojemu strežniku javlja vsakega člana vsake skupnosti, v kateri je igralec.

## Gumb Join now

V svojo aktivnost dodaj blok join in drugi člani poleg statusa dobijo gumb **Join now**. Načina sta dva in lahko ju kombiniraš.

### 1. Skrivnost (za izvorne igre)

Nastavi {"join":{"secret":"raid-42"}} . Ko nekdo pritisne Join now, se ta skrivnost dostavi *njegovi lastni* kopiji tvoje igre, na njegovem lastnem računalniku, prepoznani po istem game_id . Noben URL se ne odpre in noben upravljalnik sheme se ne sproži. Tvoja igra jo prevzame takole:

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

Poizveduj s ?since=<cursor> , da vsak dogodek vidiš samo enkrat. Če igra osebe, ki je pritisnila gumb, ne teče, se ne dostavi nič, kar je dober razlog, da ponudiš tudi URL.

### 2. URL https (za spletne igre in povezave do lobija)

Nastavi {"join":{"url":"https://play.example.com/s/abc"}} in gumb odpre to povezavo. **Sprejet je samo https .** Shema po meri ( steam:// , mygame:// , file:// ) je zavrnjena: ta blok pristane na zaslonu vsakega člana, tak URL pa je način, da tuj računalnik prisiliš, da sproži lokalni upravljalnik z argumenti, ki si jih izbral ti.

### Vse v join je javno

Blok join se razpošlje vsem, ki vidijo igralčev status; v tem je ves smisel gumba Join now. Zato ga obravnavaj kot kodo lobija, ne kot poverilnico. Vanj nikoli ne daj ničesar, kar mora ostati skrivnost, in kodam nastavi rok veljavnosti.

## FiveM

FiveM v svojem odjemalskem okolju Lua nima HTTP-ja, zato vir z mostom komunicira prek **NUI**, pogleda CEF, ki pošilja Origin. Most te izvore izrecno sprejema: https://cfx-nui-<resource> in starejši nui://<resource> . Običajne spletne strani ostanejo zavrnjene, stran na odprtem spletu pa si tega izvora ne more prisvojiti; nastavi ga brskalnik sam.

```lua
-- HTTP opravi stran NUI; Lua ji samo pošlje podatke.
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: status poteče po 90 s
  end
end)
```

```javascript
const BASE = 'http://127.0.0.1:7440/mssgs/v1';   // poskusi 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']          // tukaj ni potrebno nič več
    })
  });
  const started = await res.json();
  if (started.status === 'approved') { return started.token; }

  // Igralec zdaj v mssgs vidi pogovorno okno za dovoljenje.
  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' } // tvoja povezava cfx.re
    })
  });
});
```

Rezultat: **Playing FiveM · Los Santos Roleplay · 4/100 players · Police**, z gumbom Join now, ki odpre tvojo povezavo cfx.re.

### Prosi samo za presence.write

Status igranja ne potrebuje ničesar drugega: ta obseg ne bere ničesar. Če želiš nagrado v igri povezati s članstvom v svoji skupnosti mssgs, dodaj membership.query in navedi server_guid svoje skupnosti; o igralčevih drugih skupnostih še vedno ne izveš ničesar.

### Strežnik, na katerem igraš, ni samodejno vreden zaupanja

Vsak strežnik FiveM lahko poganja odjemalske vire, zato lahko za dovoljenje zaprosi vsak strežnik, ki se mu nekdo pridruži. Prav zato je vmes pogovorno okno, ki navede vir: odloča igralec, ne strežnik.

## Igre v brskalniku in na telefonu: povezava prek tvojega backenda

Igra v zavihku brskalnika ali na telefonu ne more do zgoraj opisanega mostu. Most teče na igralčevem namiznem računalniku, vmes pa stojijo tri ovire: most zavrne vsako zahtevo z brskalniškim Origin , Chrome pred javno stran, ki dostopa do 127.0.0.1 , postavi poziv za dovoljenje, Safari jo zavrne kar takoj, telefon pa do loopbacka namiznega računalnika sploh nima poti.

Zato se smer obrne. **Tvoj lastni backend že ve, kdo igra, in to sporoči mssgs**, za igralce, ki so svoj račun mssgs povezali s tvojo igro. Povezavo igralec odobri *v aplikaciji mssgs*, nikoli v tvoji igri, in s tem nastane povezava, nikoli seja: nič od spodaj opisanega ne more nikogar prijaviti ali delovati v imenu igralca. Odjemalec tvoje igre nikoli ne vidi ključa in nikoli ne komunicira z mss.gs. Prva igra na tej poti je [CozyCity](https://cozycity.net), igra o gradnji mesta, ki izhaja kot stran WebGL in aplikacija za iPhone, brez namizne različice; spodnji primeri so iz nje.

### 1. Registriraj svojo igro

Igro registriraj na [strani za registracijo Game SDK](https://mss.gs/sl/docs/game-sdk/register): svoj game_id (na primer com.deverence.cozycity ), ime in ikono, ki ju igralec vidi v oknu za odobritev, ter imena gostiteljev svojega backenda. Tam jo pregledamo, in ko je odobrena, te na isti strani čaka tvoj **ključ backenda**, prikazan samo enkrat; mi hranimo le njegovo zgoščeno vrednost. Ključ sodi na tvoj strežnik in nikamor drugam. Tam ga lahko kadar koli zamenjaš, stari pa ostane veljaven še 24 ur, da lahko deploy poteka postopoma.

[Registriraj svojo igro](https://mss.gs/sl/docs/game-sdk/register)

Ime in ikona v tem oknu **vedno prihajata iz registracije**, nikoli iz zahteve. Sicer bi lahko phishing povezava prošnjo za povezavo preoblekla v katero koli igro. Imena gostiteljev omejujejo, kam lahko kaže join.url , glej spodaj.

### 2. Poveži igralca

Igralec v tvoji igri izbere **Connect mssgs**. Tvoja igra vpraša tvoj backend, tvoj backend pa vpraša nas:

```bash
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 je tvoj lastni stalni ID tega igralca (do 128 znakov), ne seje ali tekme; player_name (do 64) je tisto, kar okno pokaže kot „Player: …“. Odjemalcu igre izroči samo link_code , qr_url in deep_link . device_code je tvoj ročaj za poizvedovanje in ostane na strežniku.

Tvoja igra nato hkrati pokaže tri stvari, ker je igralec lahko kjer koli:

- **Kodo QR** iz qr_url . Telefon z mssgs jo odpre naravnost v oknu za odobritev v aplikaciji. Brez aplikacije pristane na strani na mss.gs, ki pokaže kodo in ponudi prenos.

- **Gumb „Open in mssgs“** z deep_link , za brskalnik na namiznem računalniku, kjer teče namizna aplikacija. To je edini zunanji URL, ki ga mora tvoja igra kdaj koli odpreti.

- **Kodo v obliki besedila**, v dveh skupinah po štiri znake, za vnos v **Settings → Game Activity → Link a game**. V abecedi ni 0/O ali 1/I, zato se pri tipkanju le redko kaj zalomi.

Kaj igralec vidi v mssgs, v oknu, ki ga aplikacija izriše iz registracije:

### Connect CozyCity to your mssgs account?

CozyCity will be able to show what you are playing as your mssgs status. It will not see your messages, your friends or your servers, and it cannot post as you. Player: *René's city* · **Connect** / **Not now**

Medtem tvoj backend poizveduje vsakih interval sekund (na pogostejše poizvedbe dobi odgovor 429 SLOW_DOWN ), dokler se status ne spremeni. Koda deluje enkrat in poteče po desetih minutah:

```bash
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"}      # igralec je izbral Not now
# {"status":"expired"}
# {"status":"linked","link_guid":"…","user":{"user_guid":"62e377…"}}
```

Shrani link_guid k svojemu igralcu; od zdaj je to naslov, za katerega objavljaš. Odgovor vsebuje samo user_guid ; username je dodan le, če ima tvoja registracija obseg identity.link , in nič več od tega. Druga odobritev za isti player_ref **nadomesti** prejšnjo povezavo, zato je en igralec tvoje igre en račun mssgs. Isti račun mssgs se lahko poveže z več igrami in z več player_ref ene igre (družinski iPad).

### 3. Objavi status igranja

Isti blok kot pri [mostu](#activity), z enakimi pravili in enakimi omejitvami, le da zdaj za vsako povezavo posebej in s tvojim ključem backenda:

```json
{
  "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=…" }
  }
}
```

```bash
200 {"published":true,"changed":true}     # blok se je spremenil in je bil razposlan
200 {"published":true,"changed":false}    # enak shranjenemu; osvežen je bil le TTL
204                                        # shranjeno, a igralec trenutno ni na spletu v mssgs
410 {"error":"LINK_REVOKED"}               # igralec je prekinil povezavo: zavrzi jo
```

200 in 204 obravnavaj enako: shranjeno. { "activity": null } počisti blok, pošlji ga, ko igralec odide. Ena razlika od mostu: gostitelj v join.url mora biti eden od tvojih registriranih backendov (ali njegova poddomena), sicer dobiš 400 INVALID_PAYLOAD . Tako backend na igralčev status ne more postaviti gumba Join now, ki vodi nekam, kjer ta igralec nikoli ni igral.

### Heartbeat vsakih 60 sekund, TTL 120

Objavljen status brez novega sporočila živi **120 sekund**, nato sam izgine. Zato isti blok pošlji znova vsakih 60 sekund; nespremenjen blok ne stane nič in le osveži TTL. Če se tvoj heartbeat ustavi, izgine tudi vrstica „Playing …“, in prav to je namen.

S stotinami igralcev na spletu pošlji heartbeat v enem klicu, do 100 elementov naenkrat. Vsak element dobi svoj status, zato en igralec, ki je v mssgs prekinil povezavo, nikoli ne ustavi drugih devetindevetdesetih:

```json
{ "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 } ] }
```

### Kako je status prikazan

- Enako kot status z mostu: **Playing CozyCity · Lantern Hollow · 6/40 players**, z Join now, kadar obstaja join.url . Strežnik blok označi z via: "backend" , zato lahko odjemalec doda „Shared by the game's server“.

- **Samo, ko je igralec na spletu v mssgs.** Brez odprtega odjemalca mssgs je račun brez povezave in tak tudi ostane; tvoj backend ne more doseči, da bi bil nekdo videti prisoten. To tudi prepreči, da bi ta pot postala signal „ali René sedi za računalnikom“.

- Prednost: **igra v aplikaciji > igra prek mostu > tvoj backend**. Če igralec v mssgs sede k šahu, medtem ko tvoj backend še naprej pošilja heartbeat, zmaga šah, ne tisti, ki je zadnji zapisal.

### Prekinitev povezave

Igralec vidi vsako povezavo v **Settings → Game Activity → Linked games**, s tvojo ikono in imenom, imenom igralca iz tvoje igre, časom povezave in zadnje objave ter gumbom **Disconnect**. Potem tvoja naslednja objava dobi odgovor 410 LINK_REVOKED ; tako tvoja igra izve za to. Zavrzi link_guid in znova ponudi „Connect mssgs“. S svoje strani povezavo končaš z DELETE /game-sdk/v1/links/{link_guid} .

### Omejitve

Na povezavo se *sprememba* šteje največ vsaki 2 sekundi; nespremenjen heartbeat je brezplačen. Na ključ je 600 zahtev na minuto, elementi paketne zahteve pa se štejejo posamično: heartbeat za 300 igralcev vsakih 60 sekund porabi 5 od 600.

## Referenca endpointov: most

Osnovni URL http://127.0.0.1:<port> . Vse razen prvih treh zahteva Authorization: Bearer <token> .

| Metoda | Pot | Scope | Kaj naredi |
| --- | --- | --- | --- |
| GET | /mssgs/v1/hello | brez | Ali je mssgs tu, kaj podpira in ali je kdo prijavljen. Edina pot, ki ne potrebuje žetona, o igralcu pa ne pove ničesar. |
| POST | /mssgs/v1/authorize | brez | Prosi igralca za dovoljenje. V aplikaciji odpre pogovorno okno in vrne request_id za poizvedovanje. |
| GET | /mssgs/v1/authorize/:request_id | brez | pending, approved (z žetonom), denied ali expired. |
| GET | /mssgs/v1/me | identity | Prijavljeni igralec. is_staff / is_moderator doda samo z obsegom staff. |
| GET | /mssgs/v1/membership | membership.query | Članstvo v vrednostih server_guid, ki jih podaš (do 10, ponovljene ali ločene z vejicami). |
| GET | /mssgs/v1/servers | servers.list | Vse skupnosti, v katerih je igralec, z njegovimi vlogami. Neposredna sporočila niso nikoli vključena. |
| PUT | /mssgs/v1/activity | presence.write | Objavi blok „Playing …“. Vrne TTL in kako pogosto pošiljati heartbeat. |
| POST | /mssgs/v1/activity/heartbeat | presence.write | Ohrani objavljeno aktivnost živo, ne da bi jo pošiljal znova. |
| DELETE | /mssgs/v1/activity | presence.write | Takoj jo počisti, za urejen izklop. |
| GET | /mssgs/v1/events | presence.write | Podatki za pridružitev, namenjeni tvoji igri. Poizveduj s ?since=<cursor>. |
| GET | /mssgs/v1/session | brez | Kaj ima ta žeton: game_id, odobreni obsegi, ali je kdo prijavljen. |
| DELETE | /mssgs/v1/session | brez | Vrni dovoljenje. Enak učinek, kot če ga igralec prekliče v Settings. |

## Referenca endpointov: povezani backendi

Osnovni URL https://ams1-gateway.mss.gs . Vsaka pot zahteva Authorization: Bearer <backend key> in obseg activity.write v tvoji registraciji; odgovori se pošljejo z Cache-Control: no-store . Kliči jih s svojega strežnika, nikoli iz odjemalca igre.

| Metoda | Pot | Kaj naredi |
| --- | --- | --- |
| POST | /game-sdk/v1/link/start | Začni povezavo za enega od svojih igralcev ({ player_ref, player_name? }). Vrne link_code, device_code, qr_url, deep_link, expires_in in interval. |
| POST | /game-sdk/v1/link/poll | { device_code } → pending, denied, expired ali linked z link_guid in user. |
| DELETE | /game-sdk/v1/links/{link_guid} | Končaj povezavo s svoje strani. Igralec lahko isto naredi v Settings. |
| PUT | /game-sdk/v1/links/{link_guid}/activity | Objavi blok „Playing …“ za enega igralca; { "activity": null } ga počisti. |
| POST | /game-sdk/v1/activity/batch | Isto, za do 100 igralcev v enem klicu. Vsak element odgovori zase. |

## Kode napak

Napake se vrnejo kot {"error":"CODE","message":"…"} z ustreznim statusom HTTP.

| Koda | Pomen |
| --- | --- |
| 401 UNAUTHORIZED | Žeton manjka ali je neznan; najprej avtoriziraj. |
| 403 MISSING_SCOPE | Igralec tega dovoljenja ni odobril. Morda ga je odznačil. |
| 403 ORIGIN_NOT_ALLOWED | Zahteva je vsebovala brskalniški Origin. Glej „Samo izvorne igre“ spodaj. |
| 409 NOT_SIGNED_IN | mssgs teče, a nihče ni prijavljen. |
| 429 RATE_LIMITED | Več kot 120 zahtev v minuti od ene igre. |
| 400 INVALID_GAME_ID | game_id lahko vsebuje le črke, števke, piko, vezaj ali podčrtaj. |
| 400 TOO_MANY_GUIDS | Največ 10 vrednosti server_guid na en klic membership. |

### Povezani backendi

Poti backenda uporabljajo isto obliko. V paketni zahtevi se status vrne za vsak element posebej v results , zato ena končana povezava nikoli ne podre celotnega klica.

| Koda | Pomen |
| --- | --- |
| 401 INVALID_BACKEND_KEY | Neznan ključ ali ključ, ki je bil zamenjan pred več kot 24 urami. |
| 403 SCOPE_NOT_GRANTED | Tvoja registracija nima obsega, ki ga ta pot potrebuje. |
| 400 INVALID_PAYLOAD | Napačno oblikovano telo zahteve, več kot 100 elementov v paketu ali join.url, katerega gostitelj ni eden od tvojih registriranih backendov. |
| 400 INVALID_ACTIVITY | Po normalizaciji ni ostalo nobeno uporabno ime. |
| 410 LINK_REVOKED | Povezava se je končala, na eni ali drugi strani. Zavrzi jo in znova ponudi „Connect mssgs“. |
| 429 SLOW_DOWN | link/poll si klical pogosteje, kot dovoljuje interval. |
| 429 RATE_LIMITED | Sprememba ene povezave v 2 sekundah od prejšnje ali več kot 600 zahtev v minuti na tvoj ključ. |
| 503 LINK_STORE_UNAVAILABLE | Začasna težava na naši strani. Poskusi znova ob naslednjem heartbeatu. |

## Varnost

### Samo izvorne igre

Zahteve z Origin spletne strani so zavrnjene z 403 ORIGIN_NOT_ALLOWED . Če bi lahko katera koli spletna stran zaznala, da uporabljaš mssgs, in odprla pogovorno okno za dovoljenje, bi bila to vrata za fingerprinting in phishing, ne funkcija. Izvorna igra Origin sploh ne pošlje, zato je to ne zadeva, vgrajeni brskalnik igre pa je dovoljen poimensko, glej [FiveM](#fivem). Če gradiš igro za brskalnik ali telefon, se ne pogovarjaš z mostom: tvoj lastni backend objavlja za povezane igralce, glej [Igre v brskalniku in na telefonu](#linked).

### Nad čim igralec ohrani nadzor

- Igralec lahko most izklopi v **Settings → Game Activity**, nato nobena igra sploh ne vidi mssgs.

- Vsaka odobrena igra je tam navedena s točno tistimi dovoljenji, ki jih ima, s časom zadnje dejavnosti in z gumbom **Remove**. Odstranitev učinkuje takoj: žeton v trenutku preneha veljati.

- Povezana igra v brskalniku ali na telefonu je navedena pod **Linked games** z gumbom **Disconnect**. Tudi prekinitev učinkuje takoj: naslednja objava tega backenda dobi 410 .

- Most posluša samo na 127.0.0.1, nikoli v omrežju.

- Neposredna sporočila niso nikoli razkrita, niti s servers.list.

- Vsaka igra ima na voljo 120 zahtev na minuto.

### Dobre prakse

- Za obsege prosi, ko jih potrebuješ, ne za vse hkrati ob prvem zagonu.

- Deluj tudi brez mssgs: igralcu ga ni treba imeti.

- Počisti svoj status, ko se igranje konča, namesto da čakaš na TTL.

- Zavrnjen obseg obravnavaj kot običajen izid, ne kot napako.

## Gradi naprej
