Çok Oyunculu Mimari
En Parlant~ çok oyunculu modu, iki oyuncuyu gerçek zamanlı olarak bağlamak için bir WebSocket aktarım sunucusu kullanır. Eşler arası (peer-to-peer) bağlantı yoktur — tüm iletişim aktarım sunucusu üzerinden gerçekleşir. Bu, ağ yapısını basit tutar ve güvenlik duvarları ile NAT’lar arkasında güvenilir şekilde çalışır.
Mimariye Genel Bakış
Section titled “Mimariye Genel Bakış”Player A (host) Relay Server Player B (joiner) | | | |--- create_game(name) ----------->| | |<-- game_created(code) -----------| | | |<--- join_game(code, name) -----| |<-- game_joined(name) ------------|--- game_joined(name) -------->| | | | |--- game_move(uci, times) ------->|--- game_move(uci, times) --->| |<-- game_move(uci, times) --------|<-- game_move(uci, times) ----| | | | |--- heartbeat ------------------>|--- peer_heartbeat ----------->|Aktarım sunucusu ince bir yönlendirme katmanıdır. Odaları bellekte tutar, her odadaki iki oyuncu arasında olayları yönlendirir ve temizlik işlemlerini yönetir. Sunucuda oyun mantığı veya hamle doğrulaması yoktur — istemciler yetkilidir.
Teknoloji Yığını
Section titled “Teknoloji Yığını”- Ön yüz (istemci): socket.io-client — standart Socket.IO JavaScript istemcisi
- Arka yüz (aktarım): socketioxide — Axum üzerine inşa edilmiş bir Rust Socket.IO sunucusu
- Protokol: WebSocket üzerinden Socket.IO (gerektiğinde otomatik olarak HTTP long-polling’e geri dönüş ile)
Socket.IO, ham WebSocket yerine tercih edilmiştir çünkü otomatik yeniden bağlanma, oda/ad alanı yönetimi ve yapılandırılmış olay işleme özelliklerini kutudan çıktığı gibi sunar.
Oyun Akışı
Section titled “Oyun Akışı”1. Oyun Oluşturma
Section titled “1. Oyun Oluşturma”Ev sahibi Multiplayer seçeneğine tıklar ve görünen adını girer. İstemci, adla birlikte bir create_game olayı gönderir. Sunucu:
- Benzersiz 6 karakterlik bir oda kodu oluşturur
- Bir oda oluşturur ve ev sahibini ilk oyuncu olarak ekler
- Ev sahibinin kodu paylaşabilmesi için
game_created(code)ile yanıt verir
2. Oyuna Katılma
Section titled “2. Oyuna Katılma”Katılımcı oda kodunu ve görünen adını girer. İstemci join_game(code, name) olayını gönderir. Sunucu:
- Koda göre odayı bulur
- Katılımcıyı ikinci oyuncu olarak ekler
- Her iki oyuncuya da
game_joined(name)gönderir — her biri diğerinin görünen adını alır
3. Oynama
Section titled “3. Oynama”Her iki oyuncu da odada olduğunda:
- Ev sahibi her zaman Beyaz, katılımcı her zaman Siyah oynar. Bu, müzakere ile değil katılım sırasına göre belirlenir.
- Hamleler UCI formatında (örn.
e2e4) gönderilir ve her iki oyuncunun saat süreleri de birlikte iletilir. - Aktarım sunucusu her
game_moveolayını rakibe iletir. Her iki oyuncu da onay olarak kendi hamlelerini geri alır.
4. Oyun Sonu Olayları
Section titled “4. Oyun Sonu Olayları”Oyun sonu senaryolarını birkaç olay yönetir:
- İstifa — terk etme diyalogunu tetiklemek için rakibe iletilir
- Beraberlik teklifi — rakibe iletilir; rakip kabul edebilir veya görmezden gelebilir
- Beraberlik kabulü — oyunu beraberlik olarak sonlandırmak için her iki oyuncuya iletilir
5. Rövanş
Section titled “5. Rövanş”Bir oyun sona erdikten sonra, herhangi bir oyuncu rövanş isteğini bildirmek için ready olayı gönderebilir. Her iki oyuncu da ready gönderdiğinde, istemciler tahtayı sıfırlar ve renkleri değiştirir (veya aynı tutar — istemci tarafında belirlenir).
Oda Kodları
Section titled “Oda Kodları”Oda kodları 6 karakterdir ve sözlü paylaşımda okunabilirlik için XX-XX-XX biçiminde formatlanır. Karakter seti görsel olarak karıştırılabilecek karakterleri hariç tutar:
0veyaOyok (sıfır ile O harfi karışıklığı)1,IveyaLyok (bir ile büyük I ve büyük L karışıklığı)
Bu, birisi sesli sohbet üzerinden bir kodu okurken veya arkadaşının mesajından yazarken yaşanabilecek “bu sıfır mı yoksa O mu?” sorununu önler.
Kalp Atışı Sistemi
Section titled “Kalp Atışı Sistemi”Çok oyunculu bağlantılarda bir oyuncunun bağlantısının kesildiğini tespit etmek gerekir — ister ağ kesintisinden, ister uygulamanın kapatılmasından, isterse dizüstü bilgisayarın uyku moduna geçmesinden kaynaklansın. En Parlant~ bunun için bir kalp atışı sistemi kullanır:
- Her istemci, sunucuya her 5 saniyede bir
heartbeatolayı gönderir - Sunucu kalp atışını onaylar ve
peer_heartbeatolarak rakibe iletir - İstemci, rakipten en son ne zaman
peer_heartbeataldığını takip eder isPeerAlive(timeoutMs)fonksiyonu, rakibin son kalp atışının kabul edilebilir eşik dahilinde olup olmadığını kontrol eder
Bu, kullanıcı arayüzündeki bağlantı durumu göstergesini yönlendirir. Kalp atışları gelmeyi bırakırsa, oyuncu rakibinin bağlantısının kopmuş olabileceğini görür ve beklemeyi veya oyundan ayrılmayı seçebilir.
Oda Temizliği
Section titled “Oda Temizliği”Aktarım sunucusu, bellek sızıntılarını önlemek için boşta kalan odaları otomatik olarak kaldırır:
- Bir oda, 30 dakika boyunca herhangi bir etkinlik olmadığında boşta kabul edilir
- Her 60 saniyede bir temizlik görevi çalışır ve boşta kalma eşiğini aşmış odaları temizler
- Bir oda temizlendiğinde, kalan tüm bağlantılar düşürülür
Kalıcı depolama yoktur. Sunucu yeniden başlarsa tüm odalar kaybolur. Bu kasıtlıdır — aktarım sunucusu durumsuz ve geçicidir. Devam eden oyunların yeniden başlatılması gerekir, ancak pratikte bu nadiren yaşanır.
Dağıtım
Section titled “Dağıtım”Varsayılan aktarım sunucusu Fly.io üzerinde çalışır ve otomatik TLS ile düşük gecikmeli WebSocket bağlantıları sağlar. Kendi aktarım sunucunuzu çalıştırmak için talimatları Çok Oyunculu Sunucu kurulum kılavuzunda bulabilirsiniz.
Yerel Ortamda Test Etme
Section titled “Yerel Ortamda Test Etme”Geliştirme sırasında çok oyunculu modu test etmek için:
-
Aktarım sunucusunu klonlayın ve çalıştırın:
Terminal window git clone https://github.com/DarrellThomas/en-parlant-relay.gitcd en-parlant-relaycargo runSunucu 3210 portunda başlar.
-
En Parlant~ uygulamasında aktarım sunucusu URL’sini
ws://localhost:3210olarak değiştirin. -
Her iki oyuncuyu simüle etmek için uygulamanın iki örneğini açın (veya bir uygulama ve bir geliştirme modunda).
Hamleler, kalp atışları ve tüm olaylar üretim aktarım sunucusuyla aynı şekilde çalışır — tek fark bağlantı URL’sidir.