İçeriğe geç / Skip to content / Zum Inhalt

Mobil Ağda Hile Kontrolü: Godot'da Sunucu Yetkili Yarış

Ahmet Balaman

6 dk okuma

Vibe CodingBOINGWARDGodotÇok OyunculuWebSocketOyun SunucusuClaude Code
Mobil Ağda Hile Kontrolü: Godot'da Sunucu Yetkili Yarış

BOINGWARD'ın oyuncuya henüz açılmamış bir parçası var: sekiz kişilik çevrimiçi yarış. Sunucusu, protokolü ve testleri yazıldı; menüdeki düğme ise sunucu herkese açılana kadar gizli. Bu yazı o sistemin nasıl kurulduğunu ve en öğretici kısmını anlatıyor: gerçek bir mobil ağda yapılan ilk testte sekiz dürüst botun hepsinin aynı anda hileci sayılması.

Oyunun genel hikâyesini serinin merkez yazısında, botların kullandığı pogo fiziğini fizik yazısında bulabilirsiniz.

Kim neye karar verir?

Yarış oyunlarında temel soru, kimin söylediğine güvenileceği. BOINGWARD'da cevap net: istemciye güvenilmez.

Sunucunun İstemcinin
Lobi, hazır olma, geri sayım, sunucu saati Kendi pogosunun simülasyonu
Kontrol noktası sırası ve süreleri Girdi, kamera, ekrana çizim
Bitiş sırası, süre, bitiremedi, diskalifiye Diğer yarışçıların yumuşatılmış görüntüsü
Yeniden doğmanın geçerliliği
Ödüller (yarış ve oyuncu başına bir kez)

İstemci hiçbir zaman "3. kontrol noktasına geldim" ya da "bitirdim" demiyor. Yalnızca pogosunun durumunu (konum, hız, durum) gönderiyor; kontrol noktasının ya da bitişin ne zaman geçildiğine, doğrulamadan geçmiş durumlara bakarak sunucu karar veriyor.

Bir karar daha baştan verildi: sıralamalı yarışta oyuncular birbirine çarpmıyor. Diğer yarışçılar yalnızca görsel düğümler; çarpışma gövdeleri yok. Farklı telefonlarda fiziğin bit bit aynı çalışması beklenemez, gecikme de herkese farklı yansır. Çarpışma olsaydı yarışı beceri değil ağ kalitesi belirlerdi.

WebSocket mi ENet mi?

Godot 4.7'de iki hazır seçenek var ve ikisi de ek eklenti istemiyor. Karşılaştırma kısaca şöyle:

WebSocket (TCP) ENet (UDP)
Operatör NAT'ı, kurumsal Wi-Fi HTTPS'in çalıştığı her yerde çalışır Çoğunlukla çalışır, bazen engellenir
Mevcut sunucuda nginx'e bir konum, mevcut TLS; yeni port yok Yeni bir UDP portu ve güvenlik duvarı kuralı
Paket kaybında Sırayla teslim; kayıp, arkasındakileri bekletir Kaybolan anlık görüntü atlanır

Karar WebSocket oldu, nginx arkasında ve TLS ile. Sebep, aynı sunucuda yeni bir port açmadan çalışması ve mobil ağlarda takılmaması. UDP'nin avantajı gerçek ama bu oyunda küçük: diğer yarışçılar zaten 0,3 ile 0,6 saniye geriden çiziliyor ve oyuncunun kendi pogosu ağı hiç beklemiyor. Yarış kodu yalnızca küçük bir aktarım arayüzü görüyor; ENet'e geçmek bir ayar değişikliği ve iki aktarım da aynı sekiz botlu testten geçiyor.

Hareket nasıl doğrulanıyor?

Sunucu her yeni durumu son kabul ettiği durumla karşılaştırıyor. Sınırlar pogonun kendi ayar dosyasından geliyor, üstüne bir tolerans ekleniyor:

  • Hız sınırları: yatay, yukarı ve düşüş hızı.
  • Mesafe ve süre: iki durum arasındaki yol, geçen sürede gidilebilecek yoldan uzun olamaz.
  • Hareket tutarlılığı: iki zıplama arasında hız yerçekimine ve hava kontrolüne uymalı. Dikey hata birikiyor; kendi içinde tutarlı hızlar bildiren bir "havada asılı kalma" hilesi bile yavaş yavaş sapıyor.
  • İtki bütçesi: Zıplama, sekme ve sıkışma gibi ani hız değişimleri küçük, dolan bir bütçeden harcanıyor: 4 hak, her 0,25 saniyede bir yenisi. Gerçek bir zıplama yaklaşık 2 hak harcıyor; her örnekte itki isteyen bir uçma hilesi yaklaşık bir saniyede bütçeyi bitiriyor.
  • Yeniden doğma: Işınlanma yalnızca başlangıca, onaylanmış kontrol noktasına ya da hemen yanındaki bir sonraki kontrol noktasına olabilir.

İhlal bir ihtar ve bir düzeltme demek: oyuncu onaylı kontrol noktasına geri alınıyor. İhtarlar 90 saniyede düşüyor; aynı anda üç geçerli ihtar diskalifiye. Diğer oyuncular her zaman son kabul edilen durumu görüyor, doğrulanmamış bir iddiayı asla.

Gerçek ağdaki ilk test: herkes hileci

Testler önce tek makinede, simüle edilmiş gecikme ve kayıpla yeşil geçti. Sonra gerçek bir ağ denendi: sunucu uzak bir VPS'te, bağlantı telefonun internet paylaşımı üzerinden, sekiz bot yarışıyor. Yarışın 34. saniyesinde sekiz botun hepsi aynı anda "ışınlanma" ihlali aldı: 0,18 saniyede 3,8 ile 5,2 metre. Bu, pogonun yatay hız sınırının iki katından fazla demek; oysa botların hepsi dürüst zıplıyordu.

Sebep zamandaydı. İlk protokolde her durumun üstüne, istemcinin sunucu saati tahminiyle bir zaman damgası basılıyordu. Hile yapan bir istemci geleceğe damga basmasın diye damga, "paketin geliş anı + 50 milisaniye" ile sınırlanıyordu. Gerçek ağda istemcilerin saat tahminleri yaklaşık 0,35 saniye ileri kaymıştı, bu yüzden her damga o sınıra takıldı. Hareket artık paketlerin geliş zamanına göre ölçülüyordu. TCP ağda takılıp birikmiş birkaç durumu aynı anda bırakınca aralarındaki süre sıkıştı ve dürüst zıplamalar ışınlanma gibi göründü.

Belgedeki cümle durumu iyi özetliyor: sınır yalancıları yakalamak içindi, saat tahmini kayan herkesi yakaladı. Tahminlerin neden 0,35 saniye kaydığı kanıtlanamadı; ama düzeltme bunu bilmeye ihtiyaç duymuyor.

Düzeltme: iki saat, iki iş

İkinci protokolde her durum iki ayrı damga taşıyor:

  • sim: Durumun simülasyon saati, yani istemcinin fizik zamanı. Hareket yalnızca bu farklarla doğrulanıyor. Ağ gecikmesi, biriken paketler, sunucu takılmaları ya da saat tahmini hatası bu farkları uzatıp kısaltamıyor.
  • time: İstemcinin sunucu saati tahmini. Yalnızca kontrol noktası ve bitiş anını zamanlamak için kullanılıyor ve sınırlı.

Simülasyon saatinin duvar saati değil fizik zamanı olması da ayrıca ölçüldü. Oyunda zorla 0,3 saniyelik takılmalar yaratıldı: duvar saati damgalarıyla 2 ihlal, fizik zamanıyla sıfır.

Peki istemci kendi saatini hızlandırırsa? O zaman hareket makul görünür. Bunu ayrı bir saat bekçisi yakalıyor: dürüst bir istemcide "geliş anı eksi simülasyon saati" farkı takılmalarla yükselip geri iner; hızlandırılmış saatte sürekli açılır. Ölçümler: 2,5 saniyeye varan takılmalar yaşayan dürüst bir istemci sıfır saniye kazanıyor; 1,8 kat hızlı bir saat 3,95 saniyede, 1,1 kat hızlı bir saat 20,8 saniyede yakalanıyor. Bir hilecinin hâlâ kazanabileceği de yazılı: bekçi devreye girmeden en fazla 1,5 saniyelik ek hareket ve bir kontrol noktası süresinde en fazla 0,35 saniye.

Sonuçlar

Aynı saha profili (TCP, istemci saati 0,35 saniye ileri, 150 ile 400 milisaniyelik takılmalar) simüle edilmiş saatte yeniden üretildi:

İhlal Düzeltme Bitiren
Protokol 1 24 16 8 bottan 0
Protokol 2 0 0 8 bottan 8

Aynı profilde hileci botlar da yarıştı: ışınlanma, 1,8 kat hız, havada asılı kalma ve 1,8 kat hızlı saat hileleri diskalifiye edildi, kontrol noktası atlayan bot "bitiremedi" sayıldı, ilk üç sırayı ihlalsiz dürüst botlar aldı.

Gerçek ağdaki ikinci test başka bir şey buldu: hiç ihlal almadan bitiremeyen botlar. Sebep, mesaj sınırı aşılınca birleştirilen durumlardı. Uzun bir kopukluktan sonra birikmiş durumlar tek bir duruma indirgenince, aradaki boşlukta geçilen kontrol noktası hiç sayılmıyordu. Sınır, yaklaşık 28 saniyelik birikmiş durumu tek tek doğrulayacak kadar büyütüldü; çok daha uzun kopukluklarda bir geçişin kaybolabileceği de belgeye yazıldı.

Aynı saatte dönen platformlar

Bir adalet sorunu daha vardı: her telefon parkuru farklı bir anda yüklüyor, bu yüzden pistonlar ve sarkaçlar herkeste farklı fazda dönüyordu. Diğer yarışçılar boşlukta duruyormuş gibi görünüyordu. Çözüm, yarışın başladığı anda bütün hareketli parçaların saatini sıfırlamak; sonra her istemcinin parçaları kendi fizik adımıyla ilerliyor.

Bazı platform türleri (düşük yerçekimi bölgeleri, rüzgâr koridorları, ışınlayıcılar) doğrulayıcının varsayımlarını bozuyor. Sunucu bunları sunucu tarafında modelleyene kadar bu parçaları içeren bir parkuru çevrimiçi yarışa açmayı reddediyor; tek kişilik modlarda hepsi var.

Sık Sorulan Sorular

Mobil oyun için WebSocket mi UDP mi?

Hızlı tepki gerektiren bir nişancı oyununda UDP daha iyi. BOINGWARD gibi her oyuncunun kendi karakterini yerelde sürdüğü ve diğerlerini zaten biraz geriden gördüğü bir oyunda, WebSocket'in operatör ağlarında takılmadan çalışması ve mevcut sunucuda yeni port gerektirmemesi daha ağır bastı. Aktarımı bir arayüzün arkasında tutmak, kararı sonra değiştirmeyi kolaylaştırıyor.

İstemci "bitirdim" diyebilmeli mi?

Hayır. İstemci yalnızca durumunu göndermeli; bitişi ve kontrol noktalarını, doğrulamadan geçmiş durumlara bakarak sunucu belirlemeli. Aksi hâlde tek bir sahte mesaj yarışı kazandırır.

Hız hilesi istilacı bir hile önleyici olmadan nasıl yakalanır?

Hareketi sunucuda fiziğin sınırlarıyla karşılaştırarak: hız sınırları, mesafe ve süre ilişkisi, yerçekimine uyum ve ani hız değişimleri için bir bütçe. Hareketi istemcinin simülasyon saatiyle ölçün, sonra o saatin kendisini ayrı bir kontrolle doğrulayın.

Yorumlar