Birinin ne oynadığını göster
Oyunun, bir oyuncunun ne yaptığını mssgs’e bildirsin. Arkadaşları adının altında “Playing” görür, ayrıntıları açar ve Join now’a basarak aynı oyuna atlar. Oyunun ayrıca bir oyuncunun topluluğunda olup olmadığını da kontrol edebilir.
Neler yapabilirsin
- Oynama durumu yayınlaOyun, oyuncunun ne yaptığı, rolü ve grubun ne kadar dolu olduğu.
- Join now düğmesi ekleArkadaşlar tek basışta aynı oyuna, sunucuya ya da lobiye katılır.
- Üyeliği kontrol etBir oyuncunun topluluğunda olup olmadığını ve hangi rollere sahip olduğunu sor.
- Masaüstü, tarayıcı ya da telefonNative oyunlar yerel köprüyü kullanır; tarayıcı ve telefon oyunları senin backend’inden geçer.
Uygulamada
Bir adın altındaki durum ve açtığı ayrıntılar. Oyun tek bir JSON bloğu yayınladı; gerisini uygulama yapar.
Genel bakış
mssgs masaüstü uygulaması, aynı makinedeki bir oyunun konuştuğu küçük bir yerel HTTP köprüsü çalıştırır. Oyunun sunucularımızla hiç konuşmaz, bir hesap parolasını ya da token’ını hiç görmez ve oyuncu adına asla mesaj gönderemez. Oyuncunun zaten giriş yapmış olduğu mssgs kopyasıyla konuşur ve ne yanıt verileceğine o kopya karar verir.
Onunla neler yapabilirsin:
- mssgs’in kurulu olduğunu ve birinin giriş yapmış olduğunu algıla.
- Oyuncunun kim olduğunu oku: user_guid, username, avatar.
- “Bu oyuncu X topluluğunda mı?” diye ve orada hangi role sahip olduğunu sor.
- Başkaları için Join now düğmeli bir “Playing …” durumu yayınla.
- Biri o düğmeye bastığında katılma bilgisini al.
İki giriş yolu
Native bir masaüstü oyunu yerel köprüyle konuşur; sonraki bölümler bunu anlatır. Tarayıcıdaki ya da telefondaki bir oyun o köprüye ulaşamaz. Bu oyunlarda, mssgs hesaplarını bir QR ya da sekiz karakterlik bir kodla bağlamış oyuncular adına kendi backend’in yayın yapar: bkz. Tarayıcı ve telefon oyunları, ilk örnek olarak CozyCity ile. Oynama durumunun kendisi her iki yolda da aynı bloktur.
Varsayılan olarak en az bilgi
Kapsamlar bilerek eşit değil. Tek ihtiyacın “bu kişi topluluğumuzda mı” ise membership.query istersin ve server_guid’i kendin belirtirsin: evet/hayır ile oradaki rollerini alırsın ve diğer toplulukları hakkında hiçbir şey öğrenmezsin. Tam liste, oyuncunun ayrıca onaylaması gereken ayrı ve daha yüksek bir kapsamın arkasındadır.
İstemciyi bulmak
Köprü yalnızca 127.0.0.1 üzerinde, küçük bir aralıktaki ilk boş portta dinler. Biri yanıt verene kadar sırayla dene: 7440, 7441, 7442, 7443. mssgs’in geliştirme sürümleri bunun yerine 7540–7543 üzerinde dinler, böylece bir test sürümü gerçek bir oyunun çağrılarına asla yanıt vermez.
http://127.0.0.1:7440/mssgs/v1/hello
Token gerekmez ve yanıt oyuncu hakkında hiçbir şey söylemez; yalnızca mssgs’in burada olduğunu ve birinin giriş yapıp yapmadığını söyler.
{
"product": "mssgs",
"api": 1,
"client": "desktop",
"version": "14.2.20015",
"platform": "darwin",
"signed_in": true,
"scopes": ["identity", "staff", "membership.query", "servers.list", "presence.write"]
}
Devam etmeden önce product === "mssgs" ve api değerlerini kontrol et. Dört porttan hiçbiri yanıt vermezse mssgs çalışmıyordur. Oyuncuyu bekletmek yerine normal deneyimini sun.
Kapsamlar ve gizlilik
Beş kapsam çok farklı miktarlarda bilgi verir. Bu tesadüf değil; tasarımın ta kendisi. Bu tabloda yukarıdan aşağı inerek olabildiğince az şey iste.
| Kapsam | Neye izin verir | Oyuncunun verdiği |
|---|---|---|
presence.write |
Ne oynadığını göstermek | Hiçbir şey. Bu kapsam yalnızca yazar; hiçbir hesap verisi okumaz. |
identity |
Oyuncunun kim olduğu | user_guid, username, görünen ad, avatar URL’si. |
staff |
Personel / moderatör işaretleri | identity’ye ek olarak iki boolean değer. Ayrıdır, çünkü bir ad gösteren oyunun, oyuncunun toplulukları moderatör olarak yönettiğini bilmesine gerek yoktur. |
membership.query |
Zaten bildiğin bir topluluğu kontrol etmek | Belirttiğin bir server_guid için: evet/hayır, topluluğun adı ve oyuncunun oradaki rolleri. Başka hiçbir topluluk hakkında hiçbir şey. |
servers.list |
Bulunduğu tüm topluluklar | Tam liste: guid’ler, adlar, simgeler ve roller. Pahalı olan bu: yalnızca gerçekten ihtiyacın varsa iste. |
Çoğu oyuna ikisi yeter
identity ve presence.write, “sen kimsin” ve “ne oynadığını göster” işlerini karşılar; bu da neredeyse her entegrasyon demek. Bir ödülü topluluğuna üyeliğe bağlamak istersen membership.query ekle. servers.list’e neredeyse hiç ihtiyacın olmaz ve oyuncu onu kırmızıyla vurgulanmış görür.
Üyeliği kontrol etmek
Bu, “bana tüm listeyi ver”in alternatifi. Kendi topluluğunun server_guid’ini (onu zaten biliyorsun) belirtirsin ve yalnızca o topluluk hakkında bir yanıt alırsın.
curl -H "Authorization: Bearer $TOKEN" \
"http://127.0.0.1:7440/mssgs/v1/membership?server_guid=ca94ecc…f4g02"
# bir üye:
# {"server_guid":"ca94ecc…","member":true,"name":"Acme Fans","is_owner":false,
# "roles":[{"guid":"0aa32…","name":"Pro"}]}
# üye değil, başka hiçbir bilgi yok:
# {"server_guid":"…","member":false}
“Hayır” tam olarak bu demektir, fazlası değil. Tek çağrıda en fazla 10 guid gönderebilirsin (server_guid’i tekrarla ya da virgülle ayır); bu durumda bir results dizisi döner. @everyone grubu roles içinde asla yer almaz: her üye için geçerlidir, yani sana hiçbir şey söylemez.
Oynama durumu yayınlamak
Tek bir PUT, oyuncunun adının altına, topluluklarının onu gördüğü her yerde “Playing …” satırını koyar.
{
"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" }
}
Yalnızca name zorunludur. Yanıt, durumun ne kadar yaşadığını ve ne sıklıkla heartbeat göndermen gerektiğini söyler:
{ "ok": true, "expires_in_ms": 90000, "heartbeat_every_ms": 30000 }
Heartbeat gönder, yoksa durum kaybolur
90 saniye boyunca yaşam belirtisi göstermeyen bir durum otomatik olarak temizlenir. Bu bilerek böyle: oyunun çökerse oyuncu saatlerce “oynuyor” görünmez. Her 30 saniyede bir POST /mssgs/v1/activity/heartbeat, düzgün bir kapanışta da DELETE /mssgs/v1/activity gönder.
Oyuncu sayısı ve rol
Hangi cümlenin gösterileceğine party.kind karar verir, çünkü aynı iki sayı aynı anlama gelmez. Dört kişilik bir ekip, üzerinde dört oyuncu olan bir sunucu değildir.
kind |
Görünümü | Şunun için |
|---|---|---|
party (varsayılan) | 3 of 4 in the party | bir ekip, tayfa ya da grup |
server | 4/100 players | bir oyun sunucusu (FiveM, bir topluluk sunucusu) |
lobby | 4/100 players | maç başlamadan önceki bir lobi |
match | 4/100 players | devam eden bir maç ya da tur |
role (en fazla 48 karakter), oyuncunun ne olarak oynadığıdır: bir meslek, sınıf ya da karakter. state içinde bir cümle daha olmak yerine kendi alanına sahiptir, çünkü oyuncu sayısının yanında bir etiket olarak gösterilir.
details ve state en fazla 128’er karakter, name en fazla 64 karakter olabilir. Satır sonları ve kontrol karakterleri çıkarılır. Simge URL’si bilerek desteklenmez: satırı gösteren her istemci onu indirirdi; bu da durumu, oyuncunun bulunduğu her topluluğun her üyesini senin sunucuna bildiren bir işarete dönüştürürdü.
Join now düğmesi
Etkinliğine bir join bloğu koy, diğer üyeler durumun yanında bir Join now düğmesi görsün. İki yolu var ve ikisini birleştirebilirsin.
1. Gizli bir değer (native oyunlar için)
{"join":{"secret":"raid-42"}} ayarla. Biri Join now’a bastığında bu değer, aynı game_id ile eşleşen ve onun kendi makinesinde çalışan oyun kopyasına iletilir. Hiçbir URL açılmaz ve hiçbir şema işleyicisi çağrılmaz. Oyunun onu şöyle alır:
{
"events": [
{ "seq": 1, "type": "join", "secret": "raid-42",
"from": { "user_guid": "62e377…", "username": "mssgs-test-1" } }
],
"cursor": 1
}
Her olayı bir kez görmek için ?since=<cursor> ile yokla. Düğmeye basan kişinin oyunu çalışmıyorsa hiçbir şey iletilmez; bu da ayrıca bir URL sunmak için iyi bir neden.
2. Bir https URL’si (web oyunları ve lobi bağlantıları için)
{"join":{"url":"https://play.example.com/s/abc"}} ayarla, düğme o bağlantıyı açar. Yalnızca https kabul edilir. Özel bir şema (steam://, mygame://, file://) reddedilir: o blok her üyenin ekranına düşer ve böyle bir URL, başka birinin makinesine senin seçtiğin argümanlarla yerel bir işleyici çağırtmanın bir yoludur.
join içindeki her şey herkese açıktır
join bloğu, oyuncunun durumunu görebilen herkese yayınlanır; bir Join now düğmesinin bütün amacı da bu. Bu yüzden onu bir kimlik bilgisi gibi değil, bir lobi kodu gibi düşün. İçine gizli kalması gereken hiçbir şey koyma ve kodlarının süresinin dolmasını sağla.
FiveM
FiveM’in istemci tarafındaki Lua çalışma ortamında HTTP yoktur, bu yüzden bir kaynak köprüyle, Origin gönderen bir CEF görünümü olan NUI üzerinden konuşur. Köprü bu origin’leri açıkça kabul eder: https://cfx-nui-<resource> ve eski nui://<resource>. Sıradan web sayfaları reddedilmeye devam eder ve açık web’deki bir sayfa bu origin’i sahiplenemez; onu tarayıcının kendisi belirler.
-- HTTP’yi NUI sayfası yapar; Lua ona yalnızca veriyi gönderir.
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: durum 90 sn sonra sona erer
end
end)
const BASE = 'http://127.0.0.1:7440/mssgs/v1'; // 7440-7443’ü dene
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'] // burada başka bir şey gerekmez
})
});
const started = await res.json();
if (started.status === 'approved') { return started.token; }
// Oyuncu şimdi mssgs’te izin iletişim kutusunu görür.
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' } // cfx.re bağlantın
})
});
});
Sonuç: cfx.re bağlantını açan bir Join now düğmesiyle Playing FiveM · Los Santos Roleplay · 4/100 players · Police.
Yalnızca presence.write iste
Oynama durumu başka hiçbir şeye ihtiyaç duymaz: bu kapsam hiçbir şey okumaz. Oyun içi bir ödülü mssgs topluluğuna üyeliğe bağlamak istersen membership.query ekle ve kendi server_guid’ini belirt; oyuncunun diğer toplulukları hakkında yine hiçbir şey öğrenmezsin.
Oynadığın bir sunucu otomatik olarak güvenilir değildir
Her FiveM sunucusu istemci kaynakları çalıştırabilir, yani birinin katıldığı her sunucu izin isteyebilir. Tam da bu yüzden arada, kaynağın adını gösteren bir iletişim kutusu vardır: karar sunucunun değil, oyuncunundur.
Tarayıcı ve telefon oyunları: backend’in üzerinden bağlamak
Bir tarayıcı sekmesindeki ya da telefondaki bir oyun yukarıdaki köprüye ulaşamaz. Köprü oyuncunun masaüstünde çalışır ve arada üç engel vardır: köprü, tarayıcı Origin’i taşıyan her isteği reddeder; Chrome, herkese açık bir sayfanın 127.0.0.1 adresine istek atmasının önüne bir izin istemi koyar, Safari ise doğrudan reddeder; bir telefonun da masaüstünün loopback adresine ulaşmasının hiçbir yolu yoktur.
Bu yüzden yön tersine döner. Kendi backend’in kimin oynadığını zaten bilir ve bunu mssgs’e o söyler; mssgs hesaplarını oyununa bağlamış oyuncular için. Bağlantı oyununda değil, her zaman mssgs uygulamasında onaylanır ve bir oturum değil, yalnızca bir bağlantı oluşturur: aşağıdaki hiçbir şey kimsenin oturumunu açamaz ya da oyuncu adına hareket edemez. Oyun istemcin hiçbir anahtar görmez ve mss.gs ile hiç konuşmaz. Bu yoldaki ilk oyun, masaüstü sürümü olmadan bir WebGL sayfası ve bir iPhone uygulaması olarak yayımlanan şehir kurma oyunu CozyCity; aşağıdaki örnekler de ondan.
1. Oyununu kaydet
Oyunu Game SDK kayıt sayfasında kaydet: game_id değerin (örneğin com.deverence.cozycity), oyuncunun onay ekranında göreceği ad ve simge ve backend’inin ana bilgisayar adları. Başvuruyu orada inceleriz; onaylandığında backend anahtarın aynı sayfada seni bekler ve yalnızca bir kez gösterilir; biz yalnızca özetini saklarız. Anahtarın yeri senin sunucundur, başka hiçbir yer değil. Anahtarı orada istediğin zaman yenileyebilirsin; eski anahtar 24 saat geçerli kalır, böylece bir dağıtım sorunsuz tamamlanabilir.
Ekrandaki ad ve simge her zaman kayıttan gelir, asla istekten değil. Aksi halde bir oltalama bağlantısı, bir bağlantı isteğini istediği oyunun kılığına sokabilirdi. Ana bilgisayar adları, bir join.url’nin nereye gidebileceğini sınırlar, aşağıya bak.
2. Bir oyuncuyu bağla
Oyuncu oyununda Connect mssgs seçeneğini seçer. Oyunun backend’ine sorar, backend’in de bize sorar:
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, o oyuncu için senin kendi kalıcı kimliğindir (en fazla 128 karakter); bir oturumun ya da maçın kimliği değil. player_name (en fazla 64) ekranın “Player: …” olarak gösterdiği addır. Oyun istemcine yalnızca link_code, qr_url ve deep_link ver. device_code senin yoklama tutamacındır ve sunucuda kalır.
Ardından oyunun aynı anda üç şey gösterir, çünkü oyuncu herhangi bir yerde olabilir:
qr_urldeğerinin QR kodu. mssgs yüklü bir telefon onu doğrudan uygulamanın onay ekranında açar. Uygulama yoksa, kodu gösteren ve indirmeyi öneren mss.gs’teki bir sayfaya gider.deep_linkile bir “Open in mssgs” düğmesi, masaüstü uygulamasının çalıştığı bilgisayardaki bir tarayıcı için. Oyununun açması gereken tek harici URL budur.- Kodun kendisi, dörder karakterlik iki grup halinde, Settings → Game Activity → Link a game altına yazılmak üzere. Alfabede 0/O ya da 1/I yoktur, bu yüzden yazarken nadiren hata olur.
Oyuncunun mssgs’te gördüğü, uygulamanın kayda göre çizdiği ekran:
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
Bu arada backend’in, durum değişene kadar her interval saniyede bir yoklar (daha sık yoklarsan yanıt 429 SLOW_DOWN olur). Bir kod bir kez çalışır ve on dakika sonra geçersiz olur:
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"} # oyuncu Not now seçeneğini seçti
# {"status":"expired"}
# {"status":"linked","link_guid":"…","user":{"user_guid":"62e377…"}}
link_guid’i oyuncunla birlikte sakla; artık yayın yaptığın adres budur. Yanıt yalnızca user_guid’i taşır; kaydın identity.link kapsamına sahipse yalnızca bir username eklenir, bunun ötesinde hiçbir şey yoktur. Aynı player_ref için ikinci bir onay önceki bağlantının yerini alır, yani oyununun bir oyuncusu tek bir mssgs hesabıdır. Aynı mssgs hesabı birkaç oyuna ve bir oyunun birkaç player_ref’ine bağlanabilir (bir aile iPad’i).
3. Oynama durumunu yayınla
Köprüdekiyle aynı blok, aynı kurallar ve aynı sınırlarla; yalnızca artık bağlantı başına ve backend anahtarınla:
{
"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 değişti ve yayınlandı
200 {"published":true,"changed":false} # saklananla aynı; yalnızca TTL yenilendi
204 # saklandı, ama oyuncu şu anda mssgs’te çevrimiçi değil
410 {"error":"LINK_REVOKED"} # oyuncu bağlantıyı kesti: bağlantıyı bırak
200 ve 204’ü aynı şekilde ele al: saklandı. { "activity": null } bloğu temizler; oyuncu ayrıldığında bunu gönder. Köprüden bir farkı var: join.url’nin ana bilgisayarı, kayıtlı backend’lerinden biri (ya da onun bir alt alan adı) olmalıdır, yoksa 400 INVALID_PAYLOAD alırsın. Böylece bir backend, bir oyuncunun durumuna o oyuncunun hiç oynamadığı bir yere götüren bir Join now düğmesi koyamaz.
Her 60 saniyede heartbeat, TTL 120
Yayınlanan bir durum, yeni bir mesaj gelmezse 120 saniye yaşar ve sonra kendiliğinden düşer. Bu yüzden aynı bloğu her 60 saniyede bir yeniden gönder; değişmemiş bir blok hiçbir şeye mal olmaz ve yalnızca TTL’yi yeniler. Heartbeat’in durursa “Playing …” satırı da kaybolur; amaç da tam olarak bu.
Yüzlerce oyuncu çevrimiçiyken heartbeat’i tek çağrıda, bir seferde en fazla 100 öğeyle gönder. Her öğe kendi durumunu alır, böylece mssgs’te bağlantısını kesmiş bir oyuncu diğer doksan dokuzunu asla durdurmaz:
{ "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 } ] }
Durum nasıl gösterilir
- Köprü durumuyla aynı: Playing CozyCity · Lantern Hollow · 6/40 players, bir
join.urlvarsa Join now ile. Blok sunucu tarafındavia: "backend"olarak işaretlenir, böylece bir istemci “Shared by the game's server” ekleyebilir. - Yalnızca oyuncu mssgs’te çevrimiçiyken. Açık bir mssgs istemcisi yoksa hesap çevrimdışıdır ve öyle kalır; backend’in birini oradaymış gibi gösteremez. Bu, bu yolun bir “René bilgisayarının başında mı” işaretine dönüşmesini de engeller.
- Öncelik: uygulama içi bir oyun > köprüdeki bir oyun > senin backend’in. Oyuncu mssgs’in içinde satranca otururken backend’in heartbeat göndermeye devam ederse, en son yazan değil, satranç kazanır.
Bağlantıyı kesmek
Oyuncu her bağlantıyı Settings → Game Activity → Linked games altında görür: simgen ve adın, oyunundaki oyuncu adı, ne zaman bağlandığı, en son ne zaman yayın yaptığı ve bir Disconnect düğmesiyle. Bundan sonra bir sonraki yayının 410 LINK_REVOKED yanıtını alır; oyunun bunu böyle öğrenir. link_guid’i bırak ve yeniden “Connect mssgs” sun. Kendi tarafından bir bağlantıyı DELETE /game-sdk/v1/links/{link_guid} ile sonlandırırsın.
Sınırlar
Bağlantı başına bir değişiklik en fazla 2 saniyede bir sayılır; değişmemiş bir heartbeat ücretsizdir. Anahtar başına dakikada 600 istek hakkın vardır ve toplu çağrıdaki öğeler tek tek sayılır: 300 oyuncu için her 60 saniyede bir heartbeat göndermek 600’ün 5’ini harcar.
Uç nokta referansı: köprü
Temel URL http://127.0.0.1:<port>. İlk üçü dışındaki her şey Authorization: Bearer <token> gerektirir.
| Yöntem | Yol | Scope | Ne yapar |
|---|---|---|---|
| GET | /mssgs/v1/hello |
yok | mssgs burada mı, hangi API’yi konuşuyor ve giriş yapmış biri var mı. Token gerektirmeyen tek rota; oyuncu hakkında hiçbir şey söylemez. |
| POST | /mssgs/v1/authorize |
yok | Oyuncudan izin iste. Uygulamada bir iletişim kutusu açar ve yoklaman için bir request_id döndürür. |
| GET | /mssgs/v1/authorize/:request_id |
yok | pending, approved (token ile), denied ya da expired. |
| GET | /mssgs/v1/me |
identity |
Giriş yapmış oyuncu. is_staff / is_moderator yalnızca staff kapsamıyla eklenir. |
| GET | /mssgs/v1/membership |
membership.query |
Gönderdiğin server_guid değerlerindeki üyelik (en fazla 10, tekrarlanmış ya da virgülle ayrılmış). |
| GET | /mssgs/v1/servers |
servers.list |
Oyuncunun bulunduğu tüm topluluklar, rolleriyle birlikte. Özel mesajlar asla dahil edilmez. |
| PUT | /mssgs/v1/activity |
presence.write |
“Playing …” bloğunu yayınla. TTL’yi ve ne sıklıkla heartbeat gönderileceğini döndürür. |
| POST | /mssgs/v1/activity/heartbeat |
presence.write |
Yayınlanan etkinliği yeniden göndermeden canlı tut. |
| DELETE | /mssgs/v1/activity |
presence.write |
Düzgün bir kapanış için hemen temizle. |
| GET | /mssgs/v1/events |
presence.write |
Oyununa yönelik katılma olayları. ?since=<cursor> ile yokla. |
| GET | /mssgs/v1/session |
yok | Bu token’da neler olduğu: game_id, verilen kapsamlar, giriş yapmış biri olup olmadığı. |
| DELETE | /mssgs/v1/session |
yok | İzni geri ver. Oyuncunun izni Settings’ten geri almasıyla aynı etkiye sahiptir. |
Uç nokta referansı: bağlı backend’ler
Temel URL https://ams1-gateway.mss.gs. Her rota Authorization: Bearer <backend key> ve kaydında activity.write kapsamını gerektirir; yanıtlar Cache-Control: no-store ile gönderilir. Bunları oyun istemcisinden değil, her zaman kendi sunucundan çağır.
| Yöntem | Yol | Ne yapar |
|---|---|---|
| POST | /game-sdk/v1/link/start |
Oyuncularından biri için bir bağlantı başlat ({ player_ref, player_name? }). link_code, device_code, qr_url, deep_link, expires_in ve interval döndürür. |
| POST | /game-sdk/v1/link/poll |
{ device_code } → pending, denied, expired ya da link_guid ve user ile linked. |
| DELETE | /game-sdk/v1/links/{link_guid} |
Bir bağlantıyı kendi tarafından sonlandır. Oyuncu da aynısını Settings’ten yapabilir. |
| PUT | /game-sdk/v1/links/{link_guid}/activity |
Bir oyuncu için “Playing …” bloğunu yayınla; { "activity": null } bloğu temizler. |
| POST | /game-sdk/v1/activity/batch |
Aynısı, tek çağrıda en fazla 100 oyuncu için. Her öğe ayrı yanıtlanır. |
Hata kodları
Hatalar, eşleşen bir HTTP durum koduyla {"error":"CODE","message":"…"} olarak döner.
| Kod | Anlamı |
|---|---|
401 UNAUTHORIZED | Token eksik ya da bilinmiyor; önce yetkilendir. |
403 MISSING_SCOPE | Oyuncu bu izni vermedi. İşaretini kaldırmış olabilir. |
403 ORIGIN_NOT_ALLOWED | İstek bir tarayıcı Origin’i taşıyordu. Aşağıdaki “Yalnızca native oyunlar” bölümüne bak. |
409 NOT_SIGNED_IN | mssgs çalışıyor ama kimse giriş yapmamış. |
429 RATE_LIMITED | Bir oyundan bir dakikada 120’den fazla istek. |
400 INVALID_GAME_ID | game_id yalnızca harf, rakam, nokta, tire ya da alt çizgiden oluşabilir. |
400 TOO_MANY_GUIDS | Üyelik çağrısı başına en fazla 10 server_guid değeri. |
Bağlı backend’ler
Backend rotaları aynı yapıyı kullanır. Toplu bir çağrıda durum, results içinde her öğe için ayrı döner; böylece sona ermiş tek bir bağlantı tüm çağrıyı asla başarısız kılmaz.
| Kod | Anlamı |
|---|---|
401 INVALID_BACKEND_KEY | Bilinmeyen bir anahtar ya da 24 saatten daha önce yenilenerek devreden çıkmış bir anahtar. |
403 SCOPE_NOT_GRANTED | Kaydın, o rotanın gerektirdiği kapsama sahip değil. |
400 INVALID_PAYLOAD | Hatalı biçimlendirilmiş gövde, 100’den fazla toplu öğe ya da ana bilgisayarı kayıtlı backend’lerinden biri olmayan bir join.url. |
400 INVALID_ACTIVITY | Normalleştirmeden sonra kullanılabilir bir ad kalmadı. |
410 LINK_REVOKED | Bağlantı, taraflardan biri tarafından sonlandırıldı. Bağlantıyı bırak ve yeniden “Connect mssgs” sun. |
429 SLOW_DOWN | link/poll çağrısını interval değerinden daha sık yaptın. |
429 RATE_LIMITED | Bir bağlantıda bir öncekinden sonraki 2 saniye içinde bir değişiklik ya da anahtarında dakikada 600’den fazla istek. |
503 LINK_STORE_UNAVAILABLE | Bizim tarafımızda geçici bir sorun. Bir sonraki heartbeat’inde yeniden dene. |
Güvenlik
Yalnızca native oyunlar
Bir web sayfası Origin’i taşıyan istekler 403 ORIGIN_NOT_ALLOWED ile reddedilir. Herhangi bir web sayfasının mssgs kullandığını algılayıp bir izin iletişim kutusu açabilmesi bir özellik değil, parmak izi çıkarma ve oltalama için bir saldırı yüzeyi olurdu. Native bir oyun hiç Origin göndermez, bu yüzden etkilenmez; bir oyunun kendi gömülü tarayıcısına da adıyla izin verilir, bkz. FiveM. Bir tarayıcı ya da telefon oyunu geliştiriyorsan köprüyle konuşmazsın: bağlı oyuncular adına kendi backend’in yayın yapar, bkz. Tarayıcı ve telefon oyunları.
Oyuncunun elinde kalanlar
- Oyuncu köprüyü Settings → Game Activity altında kapatabilir; bundan sonra hiçbir oyun mssgs’i göremez.
- Onaylanan her oyun orada, sahip olduğu izinlerin tam listesi, en son ne zaman etkin olduğu ve bir Remove düğmesiyle listelenir. Kaldırma anında gerçekleşir: token hemen geçersiz olur.
- Bağlı bir tarayıcı ya da telefon oyunu Linked games altında bir Disconnect düğmesiyle listelenir. Bağlantıyı kesmek de anında gerçekleşir: o backend’in bir sonraki yayını
410alır. - Köprü yalnızca 127.0.0.1 üzerinde dinler, asla ağda değil.
- Özel mesajlar, servers.list ile bile asla paylaşılmaz.
- Oyun başına dakikada 120 isteklik bir bütçe vardır.
İyi uygulamalar
- Kapsamları ilk açılışta hepsini birden değil, ihtiyacın olduğunda iste.
- mssgs olmadan da çalış: oyuncunun mssgs kullanması şart değil.
- Oyun bittiğinde TTL’yi beklemek yerine durumunu temizle.
- Reddedilen bir kapsamı hata değil, olağan bir sonuç olarak ele al.