Pokaż, w co ktoś gra
Niech twoja gra przekazuje mssgs, co robi gracz. Znajomi widzą „Playing” pod nazwą gracza, otwierają szczegóły i przyciskiem Join now dołączają do tej samej gry. Twoja gra może też sprawdzić, czy gracz jest w twojej społeczności.
Co możesz z tym zrobić
- Publikuj status gryGra, co gracz właśnie robi, jego rola i jak zapełniona jest drużyna.
- Dodaj przycisk Join nowZnajomi jednym kliknięciem dołączają do tej samej gry, serwera albo lobby.
- Sprawdzaj członkostwoZapytaj, czy gracz jest w twojej społeczności i z jakimi rolami.
- Komputer, przeglądarka albo telefonGry natywne korzystają z lokalnego mostka; gry w przeglądarce i na telefonie przechodzą przez twój backend.
W aplikacji
Status pod nazwą i szczegóły, które otwiera. Gra opublikowała jeden blok JSON; resztą zajmuje się aplikacja.
Przegląd
Aplikacja desktopowa mssgs uruchamia mały lokalny mostek HTTP, z którym rozmawia gra na tym samym komputerze. Twoja gra nigdy nie łączy się z naszymi serwerami, nigdy nie widzi hasła ani tokenu konta i nigdy nie może publikować w imieniu gracza. Rozmawia z kopią mssgs, w której gracz jest już zalogowany, a ta kopia decyduje, co odpowiedzieć.
Co możesz z nim zrobić:
- Wykryć, że mssgs jest zainstalowany i ktoś jest zalogowany.
- Odczytać, kim jest gracz: user_guid, username, awatar.
- Zapytać „czy ten gracz jest w społeczności X?” i jaką rolę tam ma.
- Opublikować status „Playing …” z przyciskiem Join now dla innych.
- Odebrać dane do dołączenia, gdy ktoś naciśnie ten przycisk.
Dwie drogi
Natywna gra desktopowa rozmawia z lokalnym mostkiem; to opisują kolejne sekcje. Gra w przeglądarce albo na telefonie nie może połączyć się z tym mostkiem. W jej przypadku publikuje twój własny backend, dla graczy, którzy połączyli swoje konto mssgs kodem QR albo ośmioznakowym kodem: zobacz Gry w przeglądarce i na telefonie, z CozyCity jako pierwszym przykładem. Sam status gry to w obu przypadkach ten sam blok.
Domyślnie minimum ujawnianych danych
Zakresy celowo nie są równe. Jeśli potrzebujesz tylko wiedzieć, „czy ta osoba jest w naszej społeczności”, prosisz o membership.query i podajesz konkretny server_guid: dostajesz tak/nie oraz role tej osoby w tej społeczności i nie dowiadujesz się niczego o pozostałych jej społecznościach. Pełna lista jest za osobnym, wyższym zakresem, który gracz musi zatwierdzić oddzielnie.
Wyszukiwanie klienta
Mostek nasłuchuje tylko na 127.0.0.1, na pierwszym wolnym porcie z niewielkiego zakresu. Próbuj ich po kolei, aż któryś odpowie: 7440, 7441, 7442, 7443. Wersje deweloperskie mssgs nasłuchują zamiast tego na 7540–7543, więc wersja testowa nigdy nie odpowiada na wywołania prawdziwej gry.
http://127.0.0.1:7440/mssgs/v1/hello
Token nie jest potrzebny, a odpowiedź nie mówi nic o graczu, tylko to, że mssgs tu jest i czy ktoś jest zalogowany.
{
"product": "mssgs",
"api": 1,
"client": "desktop",
"version": "14.2.20015",
"platform": "darwin",
"signed_in": true,
"scopes": ["identity", "staff", "membership.query", "servers.list", "presence.write"]
}
Sprawdź product === "mssgs" i api, zanim pójdziesz dalej. Jeśli żaden z czterech portów nie odpowiada, mssgs nie działa. Wtedy po prostu działaj jak zwykle, zamiast kazać graczowi czekać.
Zakresy i prywatność
Pięć zakresów ujawnia bardzo różne ilości danych. To nie przypadek, na tym polega cały projekt. Proś o jak najmniej, zaczynając od góry tej tabeli.
| Zakres | Na co pozwala | Co oddaje gracz |
|---|---|---|
presence.write |
Pokazywanie, w co gra | Nic. Ten zakres tylko zapisuje; nie odczytuje żadnych danych konta. |
identity |
Kim jest gracz | user_guid, username, nazwa wyświetlana, URL awatara. |
staff |
Flagi personelu / moderatora | Dwie wartości logiczne, oprócz identity. Osobno, bo gra, która wyświetla nazwę, nie ma powodu wiedzieć, że gracz moderuje społeczności. |
membership.query |
Sprawdzenie znanej ci społeczności | Dla podanego przez ciebie server_guid: tak/nie, jej nazwa i role, które ma tam gracz. Nic o żadnej innej społeczności. |
servers.list |
Wszystkie społeczności gracza | Pełna lista: guidy, nazwy, ikony i role. To ten kosztowny zakres: proś o niego tylko wtedy, gdy naprawdę go potrzebujesz. |
Większości gier wystarczą dwa
identity i presence.write obejmują „kim jesteś” i „pokaż, w co grasz”, czyli prawie każdą integrację. Dodaj membership.query, jeśli chcesz powiązać nagrodę z członkostwem w twojej społeczności. servers.list prawie nigdy nie jest potrzebny, a gracz widzi go wyróżniony na czerwono.
Sprawdzanie członkostwa
To alternatywa dla „daj mi całą listę”. Podajesz server_guid własnej społeczności (który już znasz) i dostajesz odpowiedź wyłącznie o niej.
curl -H "Authorization: Bearer $TOKEN" \
"http://127.0.0.1:7440/mssgs/v1/membership?server_guid=ca94ecc…f4g02"
# członek:
# {"server_guid":"ca94ecc…","member":true,"name":"Acme Fans","is_owner":false,
# "roles":[{"guid":"0aa32…","name":"Pro"}]}
# nie jest członkiem i nic poza tym:
# {"server_guid":"…","member":false}
„Nie” znaczy dokładnie tyle i nic więcej. W jednym wywołaniu możesz podać do 10 guidów (powtórz server_guid albo rozdziel je przecinkami), a wtedy dostajesz tablicę results. Grupy @everyone nigdy nie ma w roles: dotyczy każdego członka, więc nic ci nie mówi.
Publikowanie statusu gry
Jedno żądanie PUT umieszcza linię „Playing …” pod nazwą gracza, wszędzie tam, gdzie widzą go jego społeczności.
{
"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" }
}
Wymagane jest tylko name. Odpowiedź mówi, jak długo status żyje i jak często wysyłać heartbeat:
{ "ok": true, "expires_in_ms": 90000, "heartbeat_every_ms": 30000 }
Heartbeat, inaczej status znika
Status bez oznak życia przez 90 sekund jest usuwany automatycznie. To celowe: jeśli gra się zawiesi, gracz nie wisi potem godzinami jako „grający”. Wysyłaj POST /mssgs/v1/activity/heartbeat co 30 sekund, a DELETE /mssgs/v1/activity przy czystym zamknięciu gry.
Liczba graczy i rola
party.kind decyduje, jakie zdanie się wyświetli, bo te same dwie liczby nie znaczą tego samego. Czteroosobowa drużyna to nie serwer z czterema graczami.
kind |
Wyświetla się jako | Dla |
|---|---|---|
party (domyślnie) | 3 of 4 in the party | drużyna, ekipa albo grupa |
server | 4/100 players | serwer gry (FiveM, serwer społeczności) |
lobby | 4/100 players | lobby przed rozpoczęciem meczu |
match | 4/100 players | trwający mecz albo runda |
role (do 48 znaków) to to, kim gra gracz: zawód, klasa albo postać. Ma własne pole zamiast kolejnego zdania w state, bo wyświetla się jako etykieta obok liczby graczy.
details i state mają limit 128 znaków każde, name 64. Podziały wiersza i znaki sterujące są usuwane. Adres URL ikony celowo nie jest obsługiwany: pobierałby go każdy klient, który wyświetla tę linię, a to zmieniłoby status w piksel śledzący, który zgłasza twojemu serwerowi każdego członka każdej społeczności, w której jest gracz.
Przycisk Join now
Umieść w aktywności blok join, a inni członkowie dostaną obok statusu przycisk Join now. Są dwa sposoby i można je łączyć.
1. Sekret (dla gier natywnych)
Ustaw {"join":{"secret":"raid-42"}}. Gdy ktoś naciśnie Join now, ten sekret trafia do jego własnej kopii twojej gry, na jego własnym komputerze, dopasowanej po tym samym game_id. Żaden URL nie jest otwierany i żaden handler schematu nie jest wywoływany. Twoja gra odbiera go tak:
{
"events": [
{ "seq": 1, "type": "join", "secret": "raid-42",
"from": { "user_guid": "62e377…", "username": "mssgs-test-1" } }
],
"cursor": 1
}
Odpytuj z ?since=<cursor>, żeby każde zdarzenie zobaczyć tylko raz. Jeśli gra osoby, która nacisnęła przycisk, nie jest uruchomiona, nic nie zostaje dostarczone, i to dobry powód, żeby podać też URL.
2. URL https (dla gier webowych i linków do lobby)
Ustaw {"join":{"url":"https://play.example.com/s/abc"}}, a przycisk otworzy ten link. Akceptowany jest tylko https. Własny schemat (steam://, mygame://, file://) jest odrzucany: ten blok trafia na ekran każdego członka, a taki URL to sposób, by zmusić cudzy komputer do wywołania lokalnego handlera z wybranymi przez ciebie argumentami.
Wszystko w join jest publiczne
Blok join jest rozsyłany do wszystkich, którzy widzą status gracza; na tym polega cały sens przycisku Join now. Traktuj go więc jak kod lobby, a nie jak dane uwierzytelniające. Nigdy nie umieszczaj w nim niczego, co musi pozostać tajne, i ustawiaj wygasanie kodów.
FiveM
FiveM nie ma HTTP w swoim środowisku Lua po stronie klienta, więc zasób rozmawia z mostkiem przez NUI, widok CEF, który wysyła nagłówek Origin. Mostek jawnie akceptuje te originy: https://cfx-nui-<resource> i starszy nui://<resource>. Zwykłe strony internetowe nadal są odrzucane, a strona w otwartym internecie nie może podszyć się pod ten origin; ustawia go sama przeglądarka.
-- Strona NUI wykonuje HTTP; Lua tylko przekazuje jej dane.
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 wygasa po 90 s
end
end)
const BASE = 'http://127.0.0.1:7440/mssgs/v1'; // próbuj 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'] // nic więcej nie jest tu potrzebne
})
});
const started = await res.json();
if (started.status === 'approved') { return started.token; }
// Gracz widzi teraz w mssgs okno z prośbą o zgodę.
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' } // twój link cfx.re
})
});
});
Efekt: Playing FiveM · Los Santos Roleplay · 4/100 players · Police, z przyciskiem Join now, który otwiera twój link cfx.re.
Proś tylko o presence.write
Status gry nie potrzebuje niczego więcej: ten zakres niczego nie odczytuje. Jeśli chcesz powiązać nagrodę w grze z członkostwem w twojej społeczności mssgs, dodaj membership.query i podaj server_guid swojej społeczności; nadal nie dowiadujesz się niczego o innych społecznościach gracza.
Serwer, na którym grasz, nie jest automatycznie zaufany
Każdy serwer FiveM może uruchamiać zasoby klienckie, więc każdy serwer, do którego ktoś dołączy, może poprosić o zgodę. Właśnie dlatego pośrodku stoi okno dialogowe z nazwą zasobu: decyduje gracz, nie serwer.
Gry w przeglądarce i na telefonie: połączenie przez twój backend
Gra w karcie przeglądarki albo na telefonie nie może połączyć się z opisanym wyżej mostkiem. Mostek działa na komputerze gracza, a po drodze stoją trzy przeszkody: mostek odrzuca każde żądanie z nagłówkiem Origin przeglądarki, Chrome pyta o zgodę, zanim publiczna strona pobierze coś z 127.0.0.1, a Safari od razu odmawia, telefon zaś w ogóle nie ma drogi do loopbacku komputera.
Dlatego kierunek się odwraca. Twój własny backend już wie, kto gra, i to on informuje mssgs, w przypadku graczy, którzy połączyli swoje konto mssgs z twoją grą. Zgodę na połączenie gracz daje w aplikacji mssgs, nigdy w twojej grze, i powstaje w ten sposób połączenie, nigdy sesja: nic poniżej nie może nikogo zalogować ani działać w imieniu gracza. Klient twojej gry nigdy nie widzi klucza i nigdy nie łączy się z mss.gs. Pierwszą grą na tej ścieżce jest CozyCity, gra o budowaniu miasta dostępna jako strona WebGL i aplikacja na iPhone’a, bez wersji desktopowej; poniższe przykłady pochodzą właśnie z niej.
1. Zarejestruj grę
Zarejestruj grę na stronie rejestracji Game SDK: podaj swój game_id (na przykład com.deverence.cozycity), nazwę i ikonę, które gracz zobaczy w oknie zatwierdzania, oraz nazwy hostów swojego backendu. Sprawdzamy ją na miejscu, a po zatwierdzeniu na tej samej stronie czeka twój klucz backendu, pokazany tylko raz; my przechowujemy wyłącznie jego skrót. Klucz powinien być na twoim serwerze i nigdzie indziej. Możesz go tam w każdej chwili zrotować, a stary pozostaje ważny przez 24 godziny, żeby wdrożenie mogło spokojnie przejść.
Nazwa i ikona w tym oknie zawsze pochodzą z rejestracji, nigdy z żądania. Inaczej link phishingowy mógłby przebrać prośbę o połączenie za dowolną grę. Nazwy hostów wyznaczają, dokąd może prowadzić join.url, zobacz niżej.
2. Połącz gracza
Gracz wybiera w twojej grze Connect mssgs. Gra pyta twój backend, a backend pyta nas:
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 to twój własny stały identyfikator tego gracza (do 128 znaków), a nie sesji czy meczu; player_name (do 64) to to, co okno pokazuje jako „Player: …”. Klientowi gry przekaż tylko link_code, qr_url i deep_link. device_code służy do odpytywania i zostaje na serwerze.
Następnie gra pokazuje jednocześnie trzy rzeczy, bo gracz może być gdziekolwiek:
- Kod QR z
qr_url. Telefon z mssgs otwiera go od razu w oknie zatwierdzania w aplikacji. Bez aplikacji trafia na stronę w mss.gs, która pokazuje kod i proponuje pobranie. - Przycisk „Open in mssgs” z
deep_link, dla przeglądarki na komputerze, na którym działa aplikacja desktopowa. To jedyny zewnętrzny URL, jaki twoja gra kiedykolwiek musi otworzyć. - Sam kod, w dwóch grupach po cztery znaki, do wpisania w Settings → Game Activity → Link a game. W alfabecie nie ma 0/O ani 1/I, więc przy przepisywaniu rzadko zdarzają się pomyłki.
Co gracz widzi w mssgs, w oknie, które aplikacja buduje na podstawie rejestracji:
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
W tym czasie twój backend odpytuje co interval sekund (na częstsze zapytania odpowiedzią jest 429 SLOW_DOWN), aż status się zmieni. Kod działa raz i wygasa po dziesięciu minutach:
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"} # gracz wybrał Not now
# {"status":"expired"}
# {"status":"linked","link_guid":"…","user":{"user_guid":"62e377…"}}
Zapisz link_guid przy swoim graczu; od teraz to adres, pod który publikujesz. Odpowiedź zawiera tylko user_guid; username dochodzi tylko wtedy, gdy twoja rejestracja ma zakres identity.link, i nic ponad to. Drugie zatwierdzenie dla tego samego player_ref zastępuje wcześniejsze połączenie, więc jeden gracz twojej gry to jedno konto mssgs. To samo konto mssgs może być połączone z kilkoma grami i z kilkoma player_ref jednej gry (rodzinny iPad).
3. Opublikuj status gry
Ten sam blok co przy mostku, z tymi samymi zasadami i limitami, tylko teraz dla każdego połączenia osobno i z twoim kluczem backendu:
{
"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=…" }
}
}
200 {"published":true,"changed":true} # blok się zmienił i został rozesłany
200 {"published":true,"changed":false} # identyczny z zapisanym; odświeżono tylko TTL
204 # zapisany, ale gracz nie jest teraz online w mssgs
410 {"error":"LINK_REVOKED"} # gracz się rozłączył: usuń połączenie
Traktuj 200 i 204 tak samo: zapisano. { "activity": null } czyści blok, wyślij to, gdy gracz wychodzi. Jedna różnica względem mostka: host w join.url musi być jednym z twoich zarejestrowanych backendów (albo jego subdomeną), inaczej dostajesz 400 INVALID_PAYLOAD. Dzięki temu backend nie może dodać do statusu gracza przycisku Join now, który prowadzi tam, gdzie ten gracz nigdy nie grał.
Heartbeat co 60 sekund, TTL 120
Opublikowany status żyje 120 sekund bez nowej wiadomości, a potem sam znika. Wysyłaj więc ten sam blok co 60 sekund; niezmieniony blok nic nie kosztuje i tylko odświeża TTL. Jeśli heartbeat ustanie, zniknie też linia „Playing …”, i właśnie o to chodzi.
Przy setkach graczy online wysyłaj heartbeat jednym wywołaniem, do 100 pozycji naraz. Każda pozycja dostaje własny status, więc jeden gracz, który rozłączył się w mssgs, nigdy nie zatrzyma pozostałych dziewięćdziesięciu dziewięciu:
{ "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 } ] }
Jak wyświetla się status
- Tak samo jak status z mostka: Playing CozyCity · Lantern Hollow · 6/40 players, z Join now, gdy jest
join.url. Serwer oznacza blok jakovia: "backend", więc klient może dopisać „Shared by the game's server”. - Tylko wtedy, gdy gracz jest online w mssgs. Bez otwartego klienta mssgs konto jest offline i takie pozostaje; twój backend nie może sprawić, że ktoś wygląda na obecnego. Dzięki temu ta droga nie staje się też sygnałem „czy René siedzi przy komputerze”.
- Pierwszeństwo: gra w aplikacji > gra przez mostek > twój backend. Jeśli gracz zasiądzie do szachów w mssgs, a twój backend dalej wysyła heartbeat, wygrywają szachy, a nie ten, kto zapisał ostatni.
Rozłączanie
Gracz widzi każde połączenie w Settings → Game Activity → Linked games, z twoją ikoną i nazwą, nazwą gracza z twojej gry, datą połączenia i ostatniej publikacji oraz przyciskiem Disconnect. Potem na twoją następną publikację odpowiedzią jest 410 LINK_REVOKED; tak twoja gra się o tym dowiaduje. Usuń link_guid i znów zaproponuj „Connect mssgs”. Ze swojej strony kończysz połączenie przez DELETE /game-sdk/v1/links/{link_guid}.
Limity
Na jedno połączenie zmiana liczy się najwyżej co 2 sekundy; niezmieniony heartbeat jest darmowy. Na klucz przypada 600 żądań na minutę, a pozycje żądania zbiorczego liczą się osobno: heartbeat dla 300 graczy co 60 sekund zużywa 5 z 600.
Referencja endpointów: mostek
Bazowy URL http://127.0.0.1:<port>. Wszystko poza pierwszymi trzema wymaga Authorization: Bearer <token>.
| Metoda | Ścieżka | Scope | Co robi |
|---|---|---|---|
| GET | /mssgs/v1/hello |
brak | Czy mssgs tu jest, co obsługuje i czy ktoś jest zalogowany. Jedyna trasa, która nie wymaga tokenu, i nie mówi nic o graczu. |
| POST | /mssgs/v1/authorize |
brak | Poproś gracza o zgodę. Wyświetla okno dialogowe w aplikacji i zwraca request_id do odpytywania. |
| GET | /mssgs/v1/authorize/:request_id |
brak | pending, approved (z tokenem), denied albo expired. |
| GET | /mssgs/v1/me |
identity |
Zalogowany gracz. Dodaje is_staff / is_moderator tylko z zakresem staff. |
| GET | /mssgs/v1/membership |
membership.query |
Członkostwo w podanych wartościach server_guid (do 10, powtórzonych albo rozdzielonych przecinkami). |
| GET | /mssgs/v1/servers |
servers.list |
Wszystkie społeczności gracza z jego rolami. Wiadomości prywatne nigdy nie są uwzględniane. |
| PUT | /mssgs/v1/activity |
presence.write |
Opublikuj blok „Playing …”. Zwraca TTL i to, jak często wysyłać heartbeat. |
| POST | /mssgs/v1/activity/heartbeat |
presence.write |
Utrzymaj opublikowaną aktywność bez ponownego wysyłania. |
| DELETE | /mssgs/v1/activity |
presence.write |
Wyczyść ją natychmiast, przy czystym zamknięciu. |
| GET | /mssgs/v1/events |
presence.write |
Zdarzenia dołączenia skierowane do twojej gry. Odpytuj z ?since=<cursor>. |
| GET | /mssgs/v1/session |
brak | Co ma ten token: game_id, przyznane zakresy, czy ktoś jest zalogowany. |
| DELETE | /mssgs/v1/session |
brak | Oddaj zgodę. Ten sam efekt, co cofnięcie jej przez gracza w Settings. |
Referencja endpointów: połączone backendy
Bazowy URL https://ams1-gateway.mss.gs. Każda trasa wymaga Authorization: Bearer <backend key> i zakresu activity.write w twojej rejestracji; odpowiedzi wychodzą z Cache-Control: no-store. Wywołuj je ze swojego serwera, nigdy z klienta gry.
| Metoda | Ścieżka | Co robi |
|---|---|---|
| POST | /game-sdk/v1/link/start |
Rozpocznij połączenie dla jednego z twoich graczy ({ player_ref, player_name? }). Zwraca link_code, device_code, qr_url, deep_link, expires_in i interval. |
| POST | /game-sdk/v1/link/poll |
{ device_code } → pending, denied, expired albo linked z link_guid i user. |
| DELETE | /game-sdk/v1/links/{link_guid} |
Zakończ połączenie ze swojej strony. Gracz może zrobić to samo w Settings. |
| PUT | /game-sdk/v1/links/{link_guid}/activity |
Opublikuj blok „Playing …” dla jednego gracza; { "activity": null } go czyści. |
| POST | /game-sdk/v1/activity/batch |
To samo dla maksymalnie 100 graczy w jednym wywołaniu. Każda pozycja dostaje własną odpowiedź. |
Kody błędów
Błędy wracają jako {"error":"CODE","message":"…"} z odpowiednim statusem HTTP.
| Kod | Znaczenie |
|---|---|
401 UNAUTHORIZED | Brak tokenu albo nieznany token; najpierw autoryzacja. |
403 MISSING_SCOPE | To uprawnienie nie zostało przyznane. Gracz mógł je odznaczyć. |
403 ORIGIN_NOT_ALLOWED | Żądanie miało nagłówek Origin przeglądarki. Zobacz „Tylko gry natywne” niżej. |
409 NOT_SIGNED_IN | mssgs działa, ale nikt nie jest zalogowany. |
429 RATE_LIMITED | Ponad 120 żądań na minutę od jednej gry. |
400 INVALID_GAME_ID | game_id może zawierać tylko litery, cyfry, kropkę, myślnik albo podkreślnik. |
400 TOO_MANY_GUIDS | Najwyżej 10 wartości server_guid na jedno wywołanie membership. |
Połączone backendy
Trasy backendu używają tego samego formatu. W żądaniu zbiorczym status wraca dla każdej pozycji osobno w results, więc jedno zakończone połączenie nigdy nie powoduje błędu całego wywołania.
| Kod | Znaczenie |
|---|---|
401 INVALID_BACKEND_KEY | Nieznany klucz albo klucz zrotowany ponad 24 godziny temu. |
403 SCOPE_NOT_GRANTED | Twoja rejestracja nie ma zakresu, którego wymaga ta trasa. |
400 INVALID_PAYLOAD | Nieprawidłowa treść żądania, ponad 100 pozycji w żądaniu zbiorczym albo join.url, którego host nie jest jednym z twoich zarejestrowanych backendów. |
400 INVALID_ACTIVITY | Po normalizacji nie została żadna użyteczna nazwa. |
410 LINK_REVOKED | Połączenie zostało zakończone, po jednej lub drugiej stronie. Usuń je i znów zaproponuj „Connect mssgs”. |
429 SLOW_DOWN | Odpytujesz link/poll częściej niż co interval. |
429 RATE_LIMITED | Zmiana jednego połączenia w ciągu 2 sekund od poprzedniej albo ponad 600 żądań na minutę na twój klucz. |
503 LINK_STORE_UNAVAILABLE | Chwilowy problem po naszej stronie. Spróbuj ponownie przy następnym heartbeacie. |
Bezpieczeństwo
Tylko gry natywne
Żądania z nagłówkiem Origin strony internetowej są odrzucane z 403 ORIGIN_NOT_ALLOWED. Gdyby dowolna strona mogła wykryć, że używasz mssgs, i wywołać okno z prośbą o zgodę, byłaby to furtka do fingerprintingu i phishingu, a nie funkcja. Gra natywna w ogóle nie wysyła Origin, więc to jej nie dotyczy, a wbudowana przeglądarka gry jest dopuszczona z nazwy, zobacz FiveM. Jeśli budujesz grę w przeglądarce albo na telefon, nie rozmawiasz z mostkiem: twój własny backend publikuje dla połączonych graczy, zobacz Gry w przeglądarce i na telefonie.
Nad czym gracz zachowuje kontrolę
- Gracz może wyłączyć mostek w Settings → Game Activity, a wtedy żadna gra w ogóle nie widzi mssgs.
- Każda zatwierdzona gra jest tam wymieniona dokładnie z uprawnieniami, które ma, datą ostatniej aktywności i przyciskiem Remove. Usunięcie działa natychmiast: token od razu przestaje działać.
- Połączona gra w przeglądarce albo na telefonie jest wymieniona w Linked games z przyciskiem Disconnect. Rozłączenie też działa natychmiast: następna publikacja tego backendu dostaje
410. - Mostek nasłuchuje tylko na 127.0.0.1, nigdy w sieci.
- Wiadomości prywatne nigdy nie są ujawniane, nawet przy servers.list.
- Każda gra ma limit 120 żądań na minutę.
Dobre praktyki
- Proś o zakresy wtedy, gdy ich potrzebujesz, a nie o wszystkie naraz przy pierwszym uruchomieniu.
- Działaj bez mssgs: gracz nie musi go mieć.
- Czyść status, gdy gra się kończy, zamiast czekać na TTL.
- Traktuj odrzucony zakres jako normalny wynik, a nie błąd.