---
title: "Game SDK: parādi, ko spēlētāji spēlē mssgs"
description: "Publicē no savas spēles statusu „Playing“ ar pogu Join now un pārbaudi dalību kopienā. mssgs Game SDK datora, pārlūka un tālruņa spēlēm."
canonical: https://docs.mss.gs/lv/game-sdk
language: lv
---

# Parādi, ko kāds spēlē

Ļauj savai spēlei pastāstīt mssgs, ko dara spēlētājs. Draugi zem viņa vārda redz „Playing“, atver sīkāku informāciju un ar pogu Join now pievienojas tai pašai spēlei. Tava spēle var arī pārbaudīt, vai spēlētājs ir tavā kopienā.

## Ko tu vari darīt

- **Publicē spēles statusu** Spēle, ko spēlētājs dara, viņa loma un cik pilna ir grupa.

- **Pievieno pogu Join now** Draugi ar vienu klikšķi pievienojas tai pašai spēlei, serverim vai lobijam.

- **Pārbaudi dalību** Pajautā, vai spēlētājs ir tavā kopienā un ar kādām lomām.

- **Dators, pārlūks vai tālrunis** Natīvās spēles izmanto lokālo tiltu; pārlūka un tālruņa spēles iet caur tavu backend.

Lietotnē

Statuss zem vārda un sīkāka informācija, ko tas atver. Spēle publicēja vienu JSON bloku; pārējo paveic lietotne.

- [Pārskats](#overview)

- [Klienta atrašana](#discover)

- [Atļaujas pieprasīšana](#authorize)

- [Spēles statuss](#activity)

- [Join now](#join)

- [Pārlūks un tālrunis](#linked)

- [Uzziņas](#reference)

## Pārskats

mssgs datora lietotne darbina nelielu **lokālu HTTP tiltu**, ar kuru sazinās spēle tajā pašā datorā. Tava spēle nekad nesazinās ar mūsu serveriem, nekad neredz konta paroli vai tokenu un nekad nevar publicēt spēlētāja vārdā. Tā sazinās ar to mssgs kopiju, kurā spēlētājs jau ir pieslēdzies, un šī kopija izlemj, ko atbildēt.

Ko ar to var darīt:

- Noteikt, ka mssgs ir instalēts un kāds ir pieslēdzies.

- Nolasīt, kas ir spēlētājs: user_guid, username, avatārs.

- Pajautāt „vai šis spēlētājs ir kopienā X?“ un kāda loma viņam tur ir.

- Publicēt statusu „Playing …“ ar pogu **Join now** citiem.

- Saņemt pievienošanās datus, kad kāds nospiež šo pogu.

### Divi ceļi

**Natīva datora spēle** sazinās ar lokālo tiltu; to apraksta nākamās sadaļas. Spēle **pārlūkā vai tālrunī** šo tiltu nevar sasniegt. Tādām spēlēm statusu publicē tavs paša backend, tiem spēlētājiem, kuri sasaistījuši savu mssgs kontu ar QR kodu vai astoņu rakstzīmju kodu: skat. [Pārlūka un tālruņa spēles](#linked), ar [CozyCity](https://cozycity.net) kā pirmo piemēru. Pats spēles statuss abos gadījumos ir tas pats bloks.

### Pēc noklusējuma minimāla datu atklāšana

Tvērumi ir apzināti nevienlīdzīgi. Ja tev jāzina tikai „vai šis cilvēks ir mūsu kopienā“, tu prasi membership.query un pats norādi server_guid: saņem jā/nē un viņa lomas tur, bet neuzzini neko par pārējām viņa kopienām. Pilnais saraksts ir aiz atsevišķa, augstāka tvēruma, kas spēlētājam jāapstiprina atsevišķi.

## Klienta atrašana

Tilts klausās tikai uz 127.0.0.1 , pirmajā brīvajā portā no neliela diapazona. Mēģini tos pēc kārtas, līdz kāds atbild: **7440, 7441, 7442, 7443**. mssgs izstrādes versijas tā vietā klausās uz **7540–7543**, tāpēc testa versija nekad neatbild uz īstas spēles izsaukumiem.

Tokens nav vajadzīgs, un atbilde neko nepasaka par spēlētāju, tikai to, ka mssgs ir šeit un vai kāds ir pieslēdzies.

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

Pirms turpini, pārbaudi product === "mssgs" un api . Ja neviens no četriem portiem neatbild, mssgs nedarbojas. Tad vienkārši piedāvā ierasto pieredzi, nevis liec spēlētājam gaidīt.

## Atļaujas pieprasīšana

Visam, izņemot /hello , vajag tokenu, un tokens rodas tikai tad, kad spēlētājs ir apstiprinājis tavu spēli dialoglodziņā lietotnē. Prasi tikai tos tvērumus, kurus tiešām izmanto: spēlētājs redz katru atsevišķi, ar paskaidrojumu, un var noņemt atzīmi no katra atsevišķ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"]
  }'
```

Atpakaļ saņem {"status":"pending","request_id":"…","poll_after_ms":1000} , un spēlētājs redz dialoglodziņu. Tad periodiski vaicā, līdz viņš atbild (pieprasījums beidzas pēc 3 minūtēm):

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

### Vienmēr pārbaudi, ko tiešām saņēmi

Saraksts scopes atbildē var būt **īsāks** par to, ko prasīji: spēlētājs drīkst noņemt atzīmi no atsevišķiem tvērumiem. Iepriekšējā piemērā membership.query tika atteikts. Turpmāko loģiku balsti uz to, ko saka atbilde, nevis uz to, ko pieprasīji, citādi saskarsies ar 403 MISSING_SCOPE , ko nebiji paredzējis.

Saglabā tokenu un sūti to kā Authorization: Bearer <token> . Tas saglabājas arī pēc restartiem, tāpēc spēlētājs tavu spēli apstiprina vienreiz, nevis katrā sesijā. Ja vēlāk atkārtoti autorizējies ar jau piešķirtiem tvērumiem, uzreiz saņem atpakaļ to pašu tokenu bez dialoglodziņa.

## Tvērumi un privātums

Pieci tvērumi atklāj ļoti atšķirīgu datu apjomu. Tas nav nejauši, tajā ir visa iecere. Prasi pēc iespējas mazāk, virzoties pa šo tabulu no augšas uz leju.

| Tvērums | Ko tas atļauj | Ko spēlētājs atdod |
| --- | --- | --- |
| presence.write | **Parādīt, ko viņš spēlē** | Neko. Šis tvērums tikai raksta; tas nenolasa nekādus konta datus. |
| identity | **Kas ir spēlētājs** | user_guid, username, attēlojamais vārds, avatāra URL. |
| staff | **Personāla / moderatora karogi** | Divas Būla vērtības papildus identity. Atsevišķi, jo spēlei, kas rāda vārdu, nav nekāda pamata zināt, ka spēlētājs moderē kopienas. |
| membership.query | **Pārbaudīt kopienu, ko jau zini** | Tevis norādītam server_guid: jā/nē, tās nosaukums un lomas, kas spēlētājam tur ir. Neko par citām kopienām. |
| servers.list | **Visas kopienas, kurās viņš ir** | Pilns saraksts: guid, nosaukumi, ikonas un lomas. Šis ir dārgais: prasi to tikai tad, ja tiešām vajag. |

### Lielākajai daļai spēļu pietiek ar diviem

identity un presence.write nosedz „kas tu esi“ un „parādi, ko tu spēlē“, un ar to pietiek gandrīz jebkurai integrācijai. Pievieno membership.query , ja gribi atlīdzību sasaistīt ar dalību tavā kopienā. servers.list tev gandrīz nekad nav vajadzīgs, un spēlētājs to redz izceltu sarkanā krāsā.

## Dalības pārbaude

Šī ir alternatīva pieprasījumam „iedod man visu sarakstu“. Tu norādi savas kopienas server_guid (kuru jau zini) un saņem atbildi tikai par to.

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

# ir dalībnieks:
# {"server_guid":"ca94ecc…","member":true,"name":"Acme Fans","is_owner":false,
#  "roles":[{"guid":"0aa32…","name":"Pro"}]}

# nav dalībnieks, un nekas vairāk:
# {"server_guid":"…","member":false}
```

„Nē“ nozīmē tieši to un neko vairāk. Vienā izsaukumā vari padot līdz 10 guid (atkārto server_guid vai atdali tos ar komatiem), un tad atbildē saņem masīvu results . Grupa @everyone nekad neparādās laukā roles : tā attiecas uz katru dalībnieku, tāpēc neko neizsaka.

## Spēles statusa publicēšana

Viens PUT pieprasījums ievieto rindu „Playing …“ zem spēlētāja vārda visur, kur viņu redz viņa kopienas.

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

Obligāts ir tikai name . Atbilde pasaka, cik ilgi statuss dzīvo un cik bieži sūtīt heartbeat:

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

### Heartbeat, citādi statuss pazūd

Statuss, kas 90 sekundes nav devis dzīvības zīmes, tiek notīrīts automātiski. Tas ir apzināti: ja tava spēle avarē, spēlētājs nepaliek „spēlējam“ stundām ilgi. Sūti POST /mssgs/v1/activity/heartbeat ik pēc 30 sekundēm un DELETE /mssgs/v1/activity , kad spēle tiek korekti aizvērta.

### Spēlētāju skaits un loma

party.kind nosaka, kāds teikums tiek attēlots, jo tie paši divi skaitļi nenozīmē vienu un to pašu. Četru cilvēku vienība nav serveris ar četriem spēlētājiem.

| kind | Tiek attēlots kā | Kam |
| --- | --- | --- |
| party (noklusējums) | 3 of 4 in the party | vienība, komanda vai grupa |
| server | 4/100 players | spēles serveris (FiveM, kopienas serveris) |
| lobby | 4/100 players | lobijs pirms mača sākuma |
| match | 4/100 players | notiekošs mačs vai raunds |

role (līdz 48 rakstzīmēm) ir tas, *par ko* spēlētājs spēlē: profesija, klase vai tēls. Tai ir savs lauks, nevis vēl viens teikums laukā state , jo tā tiek parādīta kā etiķete blakus spēlētāju skaitam.

details un state katrs ir ierobežots līdz 128 rakstzīmēm, name līdz 64. Rindiņu pārtraukumi un vadības rakstzīmes tiek izņemti. **Ikonas URL apzināti netiek atbalstīts**: to ielādētu katrs klients, kas attēlo šo rindu, un statuss kļūtu par bāku, kas tavam serverim ziņo par katru dalībnieku katrā kopienā, kurā ir spēlētājs.

## Poga Join now

Ieliec savā aktivitātē bloku join , un citi dalībnieki blakus statusam redz pogu **Join now**. Ir divi veidi, un tos var apvienot.

### 1. Noslēpums (natīvām spēlēm)

Iestati {"join":{"secret":"raid-42"}} . Kad kāds nospiež Join now, šis noslēpums tiek nogādāts *viņa paša* tavas spēles kopijai, viņa paša datorā, atrodot to pēc tā paša game_id . Neviens URL netiek atvērts un neviens shēmas apstrādātājs netiek izsaukts. Tava spēle to saņem šādi:

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

Vaicā ar ?since=<cursor> , lai katru notikumu redzētu tikai vienreiz. Ja pogas nospiedēja spēle nedarbojas, nekas netiek nogādāts, un tas ir labs iemesls piedāvāt arī URL.

### 2. https URL (tīmekļa spēlēm un lobija saitēm)

Iestati {"join":{"url":"https://play.example.com/s/abc"}} , un poga atver šo saiti. **Tiek pieņemts tikai https .** Pielāgota shēma ( steam:// , mygame:// , file:// ) tiek atraidīta: šis bloks nonāk uz katra dalībnieka ekrāna, un šāds URL ir veids, kā likt kāda cita datoram izsaukt lokālu apstrādātāju ar tevis izvēlētiem argumentiem.

### Viss join blokā ir publisks

Bloks join tiek izsūtīts visiem, kas redz spēlētāja statusu; tieši tā ir visa pogas Join now jēga. Tāpēc izturies pret to kā pret lobija kodu, nevis kā pret piekļuves datiem. Nekad neliec tajā neko, kam jāpaliek slepenam, un nosaki saviem kodiem derīguma termiņu.

## FiveM

FiveM klienta puses Lua vidē nav HTTP, tāpēc resurss sazinās ar tiltu caur **NUI**, CEF skatu, kas sūta Origin. Tilts šos origin pieņem tieši: https://cfx-nui-<resource> un vecāko nui://<resource> . Parastas tīmekļa lapas joprojām tiek atraidītas, un lapa atvērtajā tīmeklī nevar uzdoties par šo origin; to iestata pats pārlūks.

```lua
-- NUI lapa veic HTTP; Lua tai tikai nodod datus.
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: statuss beidzas pēc 90 s
  end
end)
```

```javascript
const BASE = 'http://127.0.0.1:7440/mssgs/v1';   // mēģini 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']          // te vairāk nekas nav vajadzīgs
    })
  });
  const started = await res.json();
  if (started.status === 'approved') { return started.token; }

  // Spēlētājs tagad redz atļaujas dialoglodziņu 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' } // tava cfx.re saite
    })
  });
});
```

Rezultāts: **Playing FiveM · Los Santos Roleplay · 4/100 players · Police**, ar pogu Join now, kas atver tavu cfx.re saiti.

### Prasi tikai presence.write

Spēles statusam nekas cits nav vajadzīgs: šis tvērums neko nenolasa. Ja gribi spēles atlīdzību sasaistīt ar dalību savā mssgs kopienā, pievieno membership.query un norādi savas kopienas server_guid; tu joprojām neko neuzzini par spēlētāja citām kopienām.

### Serveris, kurā spēlē, nav automātiski uzticams

Jebkurš FiveM serveris var palaist klienta resursus, tāpēc jebkurš serveris, kuram kāds pievienojas, var prasīt atļauju. Tieši tāpēc pa vidu ir dialoglodziņš ar resursa nosaukumu: izlemj spēlētājs, nevis serveris.

## Pārlūka un tālruņa spēles: sasaiste caur tavu backend

Spēle pārlūka cilnē vai tālrunī nevar sasniegt iepriekš aprakstīto tiltu. Tas darbojas spēlētāja datorā, un pa vidu stāv trīs sienas: tilts atraida katru pieprasījumu ar pārlūka Origin , Chrome parāda atļaujas uzvedni, pirms publiska lapa vēršas pie 127.0.0.1 , bet Safari atsaka uzreiz, un tālrunim vispār nav ceļa uz datora loopback.

Tāpēc virziens apgriežas. **Tavs paša backend jau zina, kas spēlē, un tas pasaka mssgs**, par spēlētājiem, kuri sasaistījuši savu mssgs kontu ar tavu spēli. Sasaisti apstiprina *mssgs lietotnē*, nekad tavā spēlē, un tā izveido sasaisti, nekad sesiju: nekas no turpmāk aprakstītā nevar nevienu pieslēgt vai rīkoties spēlētāja vārdā. Tavas spēles klients nekad neredz atslēgu un nekad nesazinās ar mss.gs. Pirmā spēle šajā ceļā ir [CozyCity](https://cozycity.net), pilsētas būvēšanas spēle, kas pieejama kā WebGL lapa un iPhone lietotne bez datora versijas; tālāk sniegtie piemēri ir tieši no tās.

### 1. Reģistrē savu spēli

Reģistrē spēli [Game SDK reģistrācijas lapā](https://mss.gs/lv/docs/game-sdk/register): savu game_id (piemēram, com.deverence.cozycity ), nosaukumu un ikonu, ko spēlētājs redz apstiprināšanas logā, un sava backend resursdatoru nosaukumus. Mēs to tur pārskatām, un pēc apstiprināšanas tajā pašā lapā tevi gaida tava **backend atslēga**, parādīta vienreiz; mēs glabājam tikai tās jaucējvērtību. Atslēgai jāatrodas tavā serverī un nekur citur. Tur vari to jebkurā brīdī nomainīt, un vecā paliek derīga 24 stundas, lai izvietošana noritētu bez pārtraukuma.

[Reģistrē savu spēli](https://mss.gs/lv/docs/game-sdk/register)

Nosaukums un ikona logā **vienmēr nāk no reģistrācijas**, nekad no pieprasījuma. Citādi pikšķerēšanas saite varētu pārģērbt sasaistes pieprasījumu par jebkuru spēli. Resursdatoru nosaukumi nosaka, uz kurieni drīkst vest join.url , skat. tālāk.

### 2. Sasaisti spēlētāju

Spēlētājs tavā spēlē izvēlas **Connect mssgs**. Tava spēle vaicā tavam backend, un tavs backend vaicā mums:

```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 ir tavs paša stabilais šī spēlētāja identifikators (līdz 128 rakstzīmēm), nevis sesijas vai mača identifikators; player_name (līdz 64) ir tas, ko logs rāda kā „Player: …“. Savas spēles klientam nodod tikai link_code , qr_url un deep_link . device_code ir tavs vaicāšanas identifikators un paliek serverī.

Pēc tam tava spēle vienlaikus parāda trīs lietas, jo spēlētājs var būt jebkur:

- **QR kodu** no qr_url . Tālrunis ar mssgs to atver uzreiz lietotnes apstiprināšanas logā. Bez lietotnes tas nonāk lapā mss.gs, kas parāda kodu un piedāvā lejupielādi.

- **Pogu „Open in mssgs“** ar deep_link , pārlūkam datorā, kurā darbojas datora lietotne. Tas ir vienīgais ārējais URL, kas tavai spēlei jebkad jāatver.

- **Pašu kodu**, divās grupās pa četrām rakstzīmēm, ko ievadīt sadaļā **Settings → Game Activity → Link a game**. Alfabētā nav 0/O vai 1/I, tāpēc, to ierakstot, kļūdas gadās reti.

Ko spēlētājs redz mssgs, logā, ko lietotne veido no reģistrācijas datiem:

### 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**

Tikmēr tavs backend vaicā ik pēc interval sekundēm (uz biežākiem vaicājumiem atbilde ir 429 SLOW_DOWN ), līdz statuss mainās. Kods darbojas vienreiz un beidzas pēc desmit minūtēm:

```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"}      # spēlētājs izvēlējās Not now
# {"status":"expired"}
# {"status":"linked","link_guid":"…","user":{"user_guid":"62e377…"}}
```

Saglabā link_guid pie sava spēlētāja; no šī brīža tā ir adrese, kurai publicē. Atbildē ir tikai user_guid ; username tiek pievienots tikai tad, ja tavai reģistrācijai ir tvērums identity.link , un vairāk nekā nav. Otrs apstiprinājums tam pašam player_ref **aizstāj** iepriekšējo sasaisti, tāpēc viens tavas spēles spēlētājs ir viens mssgs konts. Tas pats mssgs konts var būt sasaistīts ar vairākām spēlēm un ar vairākiem vienas spēles player_ref (ģimenes iPad).

### 3. Publicē spēles statusu

Tas pats bloks kā [tiltā](#activity), ar tiem pašiem noteikumiem un ierobežojumiem, tikai tagad katrai sasaistei atsevišķi un ar tavu backend atslēgu:

```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}     # bloks mainījās un tika izsūtīts
200 {"published":true,"changed":false}    # identisks saglabātajam; atjaunots tikai TTL
204                                        # saglabāts, bet spēlētājs šobrīd nav tiešsaistē mssgs
410 {"error":"LINK_REVOKED"}               # spēlētājs atvienojās: dzēs sasaisti
```

Uztver 200 un 204 vienādi: saglabāts. { "activity": null } notīra bloku, sūti to, kad spēlētājs aiziet. Viena atšķirība no tilta: join.url resursdatoram jābūt vienam no taviem reģistrētajiem backend (vai tā apakšdomēnam), citādi saņem 400 INVALID_PAYLOAD . Tā backend nevar pievienot spēlētāja statusam pogu Join now, kas ved kaut kur, kur šis spēlētājs nekad nav spēlējis.

### Heartbeat ik pēc 60 sekundēm, TTL 120

Publicēts statuss dzīvo **120 sekundes** bez jauna ziņojuma un tad pazūd pats. Tāpēc sūti to pašu bloku ik pēc 60 sekundēm; nemainīts bloks neko nemaksā un tikai atjauno TTL. Ja tavs heartbeat apstājas, apstājas arī rinda „Playing …“, un tieši tā ir doma.

Ja tiešsaistē ir simtiem spēlētāju, sūti heartbeat vienā izsaukumā, līdz 100 vienībām reizē. Katra vienība saņem savu statusu, tāpēc viens spēlētājs, kurš atvienojies mssgs, nekad neaptur pārējos deviņdesmit deviņus:

```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 } ] }
```

### Kā statuss tiek parādīts

- Tieši tāpat kā tilta statuss: **Playing CozyCity · Lantern Hollow · 6/40 players**, ar Join now, ja ir join.url . Servera pusē bloks tiek atzīmēts ar via: "backend" , tāpēc klients var pievienot „Shared by the game's server“.

- **Tikai tad, kad spēlētājs ir tiešsaistē mssgs.** Ja neviens mssgs klients nav atvērts, konts ir bezsaistē un tāds paliek; tavs backend nevar likt kādam izskatīties klātesošam. Tas arī neļauj šim ceļam kļūt par bāku „vai René sēž pie datora“.

- Prioritāte: **spēle lietotnē > spēle caur tiltu > tavs backend**. Ja spēlētājs mssgs apsēžas spēlēt šahu, kamēr tavs backend turpina sūtīt heartbeat, uzvar šahs, nevis tas, kurš rakstīja pēdējais.

### Atvienošana

Spēlētājs redz katru sasaisti sadaļā **Settings → Game Activity → Linked games**, ar tavu ikonu un nosaukumu, spēlētāja vārdu no tavas spēles, sasaistes laiku un pēdējās publikācijas laiku, kā arī pogu **Disconnect**. Pēc tam tava nākamā publikācija saņem atbildi 410 LINK_REVOKED ; tā tava spēle to uzzina. Dzēs link_guid un atkal piedāvā „Connect mssgs“. No savas puses sasaisti beidz ar DELETE /game-sdk/v1/links/{link_guid} .

### Ierobežojumi

Katrai sasaistei *izmaiņa* tiek ņemta vērā ne biežāk kā reizi 2 sekundēs; nemainīts heartbeat ir bez maksas. Katrai atslēgai ir 600 pieprasījumu minūtē, un pakešpieprasījuma vienības tiek skaitītas atsevišķi: heartbeat 300 spēlētājiem ik pēc 60 sekundēm patērē 5 no 600.

## Galapunktu uzziņas: tilts

Bāzes URL http://127.0.0.1:<port> . Visam, izņemot pirmos trīs, vajag Authorization: Bearer <token> .

| Metode | Ceļš | Scope | Ko tas dara |
| --- | --- | --- | --- |
| GET | /mssgs/v1/hello | nav | Vai mssgs ir šeit, ko tas atbalsta un vai kāds ir pieslēdzies. Vienīgais maršruts, kam nav vajadzīgs tokens, un tas neko nepasaka par spēlētāju. |
| POST | /mssgs/v1/authorize | nav | Palūdz spēlētājam atļauju. Atver dialoglodziņu lietotnē un atgriež request_id, ko periodiski vaicāt. |
| GET | /mssgs/v1/authorize/:request_id | nav | pending, approved (ar tokenu), denied vai expired. |
| GET | /mssgs/v1/me | identity | Spēlētājs, kurš ir pieslēdzies. Pievieno is_staff / is_moderator tikai ar tvērumu staff. |
| GET | /mssgs/v1/membership | membership.query | Dalība kopienās ar padotajām server_guid vērtībām (līdz 10, atkārtotas vai atdalītas ar komatiem). |
| GET | /mssgs/v1/servers | servers.list | Visas kopienas, kurās ir spēlētājs, ar viņa lomām. Privātās ziņas nekad netiek iekļautas. |
| PUT | /mssgs/v1/activity | presence.write | Publicē bloku „Playing …“. Atgriež TTL un to, cik bieži sūtīt heartbeat. |
| POST | /mssgs/v1/activity/heartbeat | presence.write | Uztur publicēto aktivitāti dzīvu, nesūtot to atkārtoti. |
| DELETE | /mssgs/v1/activity | presence.write | Notīra to uzreiz, korektai aizvēršanai. |
| GET | /mssgs/v1/events | presence.write | Pievienošanās notikumi, kas adresēti tavai spēlei. Vaicā ar ?since=<cursor>. |
| GET | /mssgs/v1/session | nav | Kas ir šim tokenam: game_id, piešķirtie tvērumi, vai kāds ir pieslēdzies. |
| DELETE | /mssgs/v1/session | nav | Atdod atļauju atpakaļ. Tāds pats efekts, kā spēlētājam to atsaucot sadaļā Settings. |

## Galapunktu uzziņas: sasaistītie backend

Bāzes URL https://ams1-gateway.mss.gs . Katram maršrutam vajag Authorization: Bearer <backend key> un tvērumu activity.write tavā reģistrācijā; atbildes tiek sūtītas ar Cache-Control: no-store . Izsauc tos no sava servera, nekad no spēles klienta.

| Metode | Ceļš | Ko tas dara |
| --- | --- | --- |
| POST | /game-sdk/v1/link/start | Sāk sasaisti vienam no taviem spēlētājiem ({ player_ref, player_name? }). Atgriež link_code, device_code, qr_url, deep_link, expires_in un interval. |
| POST | /game-sdk/v1/link/poll | { device_code } → pending, denied, expired vai linked ar link_guid un user. |
| DELETE | /game-sdk/v1/links/{link_guid} | Beidz sasaisti no tavas puses. Spēlētājs to pašu var izdarīt sadaļā Settings. |
| PUT | /game-sdk/v1/links/{link_guid}/activity | Publicē bloku „Playing …“ vienam spēlētājam; { "activity": null } to notīra. |
| POST | /game-sdk/v1/activity/batch | Tas pats līdz 100 spēlētājiem vienā izsaukumā. Katra vienība saņem savu atbildi. |

## Kļūdu kodi

Kļūdas atgriežas kā {"error":"CODE","message":"…"} ar atbilstošu HTTP statusu.

| Kods | Nozīme |
| --- | --- |
| 401 UNAUTHORIZED | Tokena nav vai tas nav zināms; vispirms autorizējies. |
| 403 MISSING_SCOPE | Spēlētājs šo atļauju nepiešķīra. Iespējams, viņš noņēma atzīmi. |
| 403 ORIGIN_NOT_ALLOWED | Pieprasījumam bija pārlūka Origin. Skat. „Tikai natīvas spēles“ tālāk. |
| 409 NOT_SIGNED_IN | mssgs darbojas, bet neviens nav pieslēdzies. |
| 429 RATE_LIMITED | Vairāk nekā 120 pieprasījumu minūtē no vienas spēles. |
| 400 INVALID_GAME_ID | game_id drīkst saturēt tikai burtus, ciparus, punktu, defisi vai pasvītru. |
| 400 TOO_MANY_GUIDS | Ne vairāk kā 10 server_guid vērtības vienā membership izsaukumā. |

### Sasaistītie backend

Backend maršruti izmanto to pašu formu. Pakešpieprasījumā statuss atgriežas katrai vienībai atsevišķi laukā results , tāpēc viena beigusies sasaiste nekad neizgāž visu izsaukumu.

| Kods | Nozīme |
| --- | --- |
| 401 INVALID_BACKEND_KEY | Nezināma atslēga vai atslēga, kas nomainīta vairāk nekā pirms 24 stundām. |
| 403 SCOPE_NOT_GRANTED | Tavai reģistrācijai nav tvēruma, kas vajadzīgs šim maršrutam. |
| 400 INVALID_PAYLOAD | Nepareizi formēts pieprasījuma saturs, vairāk nekā 100 vienību pakešpieprasījumā vai join.url, kura resursdators nav neviens no taviem reģistrētajiem backend. |
| 400 INVALID_ACTIVITY | Pēc normalizēšanas nepaliek neviens izmantojams nosaukums. |
| 410 LINK_REVOKED | Sasaiste beidzās vienā vai otrā pusē. Dzēs to un atkal piedāvā „Connect mssgs“. |
| 429 SLOW_DOWN | Tu vaicāji link/poll biežāk nekā interval. |
| 429 RATE_LIMITED | Izmaiņa vienai sasaistei 2 sekunžu laikā kopš iepriekšējās vai vairāk nekā 600 pieprasījumu minūtē ar tavu atslēgu. |
| 503 LINK_STORE_UNAVAILABLE | Īslaicīga problēma mūsu pusē. Mēģini vēlreiz ar nākamo heartbeat. |

## Drošība

### Tikai natīvas spēles

Pieprasījumi ar tīmekļa lapas Origin tiek atraidīti ar 403 ORIGIN_NOT_ALLOWED . Ja jebkura tīmekļa lapa varētu noteikt, ka tu lieto mssgs, un atvērt atļaujas dialoglodziņu, tā būtu iespēja izsekošanai (fingerprinting) un pikšķerēšanai, nevis funkcija. Natīva spēle vispār nesūta Origin, tāpēc uz to tas neattiecas, un spēles iebūvētais pārlūks ir atļauts pēc nosaukuma, skat. [FiveM](#fivem). Ja veido pārlūka vai tālruņa spēli, tu nesazinies ar tiltu: tavs paša backend publicē statusu sasaistītajiem spēlētājiem, skat. [Pārlūka un tālruņa spēles](#linked).

### Kas paliek spēlētāja kontrolē

- Spēlētājs var izslēgt tiltu sadaļā **Settings → Game Activity**, un pēc tam neviena spēle mssgs vairs vispār neredz.

- Katra apstiprinātā spēle tur ir uzskaitīta ar tieši tām atļaujām, kas tai ir, pēdējās aktivitātes laiku un pogu **Remove**. Noņemšana darbojas uzreiz: tokens tūlīt zaudē derīgumu.

- Sasaistīta pārlūka vai tālruņa spēle ir uzskaitīta sadaļā **Linked games** ar pogu **Disconnect**. Arī atvienošana darbojas uzreiz: šī backend nākamā publikācija saņem 410 .

- Tilts klausās tikai uz 127.0.0.1, nekad tīklā.

- Privātās ziņas nekad netiek atklātas, pat ne ar servers.list.

- Katrai spēlei ir limits 120 pieprasījumi minūtē.

### Labā prakse

- Prasi tvērumus tad, kad tie ir vajadzīgi, nevis visus uzreiz pirmajā palaišanas reizē.

- Strādā arī bez mssgs: spēlētājam tas nav obligāti jābūt.

- Notīri statusu, kad spēle beidzas, nevis gaidi TTL.

- Uztver atteiktu tvērumu kā normālu iznākumu, nevis kļūdu.

## Veido tālāk
