Geliştirici Günlükleri

MKA Engine'i geliştirirken tuttuğumuz günlükler: neyi neden böyle kurduğumuz ve ne ölçtüğümüz.

MKA Engine'i geliştirirken tuttuğumuz günlükler. Her günlükte bir kararı, nedenini ve ölçtüğümüz sonucu yazıyoruz. Motorun kendisi için MKA Engine sayfasına bakın.

Geliştirici Günlükleri

Geliştirici Günlüğü #2: Kilit adım ve senkron kaybı

· Ayrı sayfada aç

Yan yana iki bilgisayar aynı strateji haritasını gösteriyor; soldaki düzenli, sağdaki haritada sınırlar kaymış, ortada ince bir ışık çatlağı var.

Kısaca: MKA Engine'de çok oyunculu oyun kilit adımla (deterministic lockstep) çalışır: ağdan dünya değil yalnız oyuncuların komutları gider ve her bilgisayar aynı simülasyonu kendisi hesaplar. Bunun için motor her yerde aynı sonucu üretir; dünyanın 64 bitlik parmak izi bilgisayarlar arasında karşılaştırılır, fark varsa senkron kaybı çıktığı anda yakalanır.

Çok oyunculu strateji oynayanlar bu ekranı bilir: oyun "senkron kaybı" der ve oturum kopar. MKA Engine'de çok oyunculu oyunla ve tutarlılıkla ilgili her şeyi bu günlükte topladık: iki bilgisayarın aynı dünyayı nasıl hesapladığı, bunun için hangi kurallara uyduğumuz, bir fark çıkarsa nasıl yakalandığı ve biri oyundan düşerse ne olduğu. Yazının sonunda bunları 15 Ekim 2026'da yeniden koşturduğumuz testlerin sonuçları var.

Önce dürüst bir not: aşağıdakilerin hepsi motorun ekransız testlerinde ve ekransız sunucusunda çalışıyor. Ekranı çizen ön yüz henüz yazılmadı; yani bugün oynanabilir bir çok oyunculu oyun yok.

İki yol: dünyayı göndermek, hamleyi göndermek

Çok oyunculu bir oyunu kurmanın iki temel yolu var.

Birincisinde bir sunucu dünyayı hesaplar ve oyunculara dünyanın değişen kısmını sürekli gönderir. Nişancı ve aksiyon oyunlarının çoğu böyle çalışır (Unreal ağ yapısı (yeni sekmede açılır)). Ekranda birkaç düzine nesne olduğunda bu iyi bir yoldur.

İkincisi mektupla satranç oynamaya benzer: iki oyuncunun da önünde kendi tahtası vardır ve birbirlerine yalnız hamlelerini yazarlar. Tahtalar aynı başlar ve aynı hamleler aynı kuralla oynanırsa, iki tahta hep aynı kalır. Buna kilit adımlı oyun denir. Age of Empires yüzlerce birimi yavaş modem bağlantılarında bu yöntemle eşitliyordu (1500 Archers on a 28.8 (yeni sekmede açılır)).

ÖlçütDünyayı göndermekHamleyi göndermek (kilit adım)
Ağdan ne geçerDeğişen nesnelerin durumuYalnız oyuncu komutları
Kim hesaplarSunucuHer oyuncunun bilgisayarı
Dünya büyüdükçe ağ yüküBüyürDeğişmez
En büyük şartıHızlı ve güçlü bir sunucuHer bilgisayarın bit bit aynı sonucu üretmesi
İki yolun karşılaştırması

Bir büyük strateji oyununda 30.000 konum, 250 ülke ve 2 milyon nüfus birimi her gün değişir; bunu her gün her oyuncuya göndermek mümkün değildir. Oysa oyuncuların verdiği komutlar ("bu orduyu oraya yürüt", "vergiyi artır") birkaç bayttır. MKA Engine bu yüzden kilit adımlıdır. Bedeli tablonun son satırında: her bilgisayar aynı komutlardan bit bit aynı dünyayı çıkarmak zorundadır.

Kilit adım nasıl işler?

Ortada bir ana makine, çevresinde aynı haritayı gösteren dört bilgisayar; küçük zarflar yalnız ana makineye giden çizgiler üzerinde gidip geliyor.

Oyunu bir grup yürüyüşü gibi düşünün: grup en yavaş yürüyeni bekler. Motorda her adım (bir gün ya da bir tur) şöyle ilerler:

  1. Bir oyuncu bir komut verdiğinde komut hemen uygulanmaz; iki adım sonrası için bir pakete konur ve diğer oyunculara gönderilir. Bu iki adımlık pay, komutun ağdan herkese ulaşması için zaman kazandırır.
  2. Bir adım, ancak her oyuncunun o adım için paketi geldiğinde koşulur. Paketi gelmeyen oyuncu varsa herkes onu bekler.
  3. Paketler herkeste aynı sırayla (oyuncu ve sıra numarasıyla) birleştirilir; böylece herkes aynı komutları aynı sırada uygular.

Oyunu duraklatmak bile bir komuttur: duraklatma kararı komut günlüğünden geçer, yani her bilgisayar aynı adımda durur.

Bağlantılar yıldız biçimindedir: bir oyuncu başka bir oyuncuya mesaj gönderdiğinde mesaj ana makineden geçer. Telden geçenler sınırlıdır:

GeçerGeçmez
Bir adımın komut paketiDünyanın durumu
Belirli aralıklarla dünyanın parmak iziNüfus, para, ordu gibi tek tek değerler
Katılma, ayrılma ve koltuk mesajlarıEkran görüntüsü, kare bilgisi
Oyuna sonradan girene kayıt dosyasıZar sonuçları
Telden ne geçer, ne geçmez

Zar sonuçları da geçmez; çünkü zar, Günlük #1'de anlattığımız gibi tohum ve adresle her bilgisayarda aynı çıkar.

Aynı sonuç için hangi kurallara uyuyoruz?

"Bit bit aynı" hedefi tek bir önlemle tutmaz; motorun çekirdeğinde bir dizi kurala uyuyoruz. Her biri, farklı bilgisayarlarda farklı sonuç çıkaran bilinen bir sebebi kapatıyor:

KuralNeyi önler
Ondalıklı sayı yok, yalnız sabit noktalı sayıDerleyici ve işlemci farkından gelen küçük sapmalar
Zar yalnız tohum ve adresleZarların hangi sırayla atıldığının sonucu değiştirmesi
Zaman yalnız oyun adımı; saat, dosya ve ağ çekirdeğe giremezBilgisayarın hızının ya da saatinin oyuna sızması
Karma tablosu yok; veri hep aynı sırayla dolaşılırAynı verinin farklı bilgisayarda farklı sırayla işlenmesi
İş parçacıklarını yalnız zamanlayıcı açar; sonuçlar parça sırasıyla birleşirHangi çekirdeğin önce bittiğinin sonucu değiştirmesi
Varlık ekleme ve silme yalnız adım sınırındaBir adımın ortasında dünyanın değişmesi
Çekirdeğin kuralları

İlk üç kuralı Günlük #1 ayrıntısıyla anlatıyor. Diğer üçü motorun veri deposunun ve zamanlayıcısının işi; onları kendi günlüklerinde anlatacağız.

Parmak izi: farkı yakalamak

Küçük harita parçalarından oluşan iki parmak izi ve aralarında bir büyüteç; sağdaki izde tek bir parça turuncu renkle farklı.

Kurallara uysak bile bir hata çıkabilir: bir modun beklenmedik bir davranışı ya da motorda bir yanlış. Önemli olan, farkın çıktığı anda yakalanması. Bunun için dünyanın parmak izini alıyoruz: bütün durumdan hesaplanan 64 bitlik kısa bir sayı. Dünyada tek bir değer değişse parmak izi de değişir.

Parmak izi bir ağaç gibi kurulur: her tablonun satırları 16.384'lük parçalara bölünür, her parçanın kendi izi, her tablonun bir kök izi, bütün dünyanın da tek bir kök izi vardır. Ekransız sunucuda bilgisayarlar her 30 adımda bir dünya kök izini birbirine gönderir. İz tutmazsa motor bir "ayrışma" olayı üretir.

Sonra farkın yerini bulur. Bunu kütüphanede kaybolan bir kitabı aramaya benzetebilirsiniz: önce hangi salonda olduğuna, sonra hangi rafta, en son hangi sırada olduğuna bakarsınız. Motor da iki bilgisayarın izlerini önce tablo tablo, sonra parça parça, en son satır satır karşılaştırır ve ilk farkı "şu tablo, şu satır, şu varlık" diye bildirir. Bu arama sırasında da ağdan yalnız izler geçer; dünyanın kendisi gönderilmez.

Parmak izi bir değişikliği yakalamak içindir, şifreleme amaçlı değildir. İzin hesap yöntemi dondurulmuştur: kayıtlar, tekrar oynatmalar ve ağ denetimi aynı izleri karşılaştırdığı için bu yöntem değişirse hepsi bozulur.

Kanıt: 15 Ekim'de yeniden koşturduk

Bu günlüğü yazarken dört sınamayı yeniden koşturduk. Hepsi geliştirme bilgisayarımızda ve ekransız; süreler başka işlerle yüklü bir bilgisayarda alındığı için burada süre değil sonuç önemli.

  • 10 yıl ölçek dünyası; günlük parmak izleri 1, 8 ve 16 iş parçacığında birebir aynı
  • 5. yıl sonu kaydedilen oyun, yüklenince kesintisiz oyunla aynı
  • 4 eş, 100 yıl ağ üzerinden hep aynı izlerle koşan oyun
15 Ekim 2026 sınamaları

Çekirdek sayısı fark etmiyor. Ölçek dünyasını (30.000 konum, 250 ülke, 2 milyon nüfus birimi) 10 oyun yılı boyunca üç kez koşturduk: tek iş parçacığında, 8 iş parçacığında ve 16 iş parçacığında. Her gün alınan parmak izlerinin üçü de birebir aynı çıktı. Yani 4 çekirdekli bir bilgisayarla 16 çekirdekli bir bilgisayar aynı oyunda buluşabilir.

Kaydet ve yükle aynı oyunu sürdürüyor. Aynı dünyada oyunu 5. yılın sonunda kaydettik, kaydı yükledik ve 5 yıl daha koşturduk. Sonuç, hiç durmadan koşan oyunla aynıydı. Oyuna sonradan katılan oyuncu da bu yolla girer.

Dört bilgisayar, yüz yıl. Ağ testinde dört eş 100 oyun yılı koşturuyor: bir kez dört ayrı program olarak gerçek ağ bağlantısı (TCP) üzerinden, bir kez tek program içinde. Eşlerden birine yapay gecikme veriliyor. Her eş her denetimde aynı parmak izinde buluşuyor ve hiçbiri diğerlerinden girdi gecikmesinden (iki adım) fazla öne geçmiyor. İki koşu da geçti.

Farklı işlemciler aynı sonucu veriyor. Motorun çekirdek paketlerinin testlerini üç ayrı ortamda koşturduk: geliştirme bilgisayarımızın işlemcisi (x86_64), ARM işlemci (aarch64; Docker içinde öykünmeyle) ve WebAssembly (wasmtime ile). Üçü de aynı sonuçları verdi. Yani üç ortam aynı sayıları, zarları ve tarihleri üretti.

Aynı oyunu başlatmak: lobi

Bit bit aynı dünya, aynı başlangıçla başlar. Bir oyuncu lobiye katılırken ana makine şunları karşılaştırır: ağ protokolünün sürümü, motorun sürümü, yüklü modların özeti ve modların yükleme sırası. Biri tutmazsa katılma reddedilir ve iki taraf da kendi değerini görür; "bende şu mod var, sende yok" türünden bir sorun oyun başlamadan ortaya çıkar. Kayıt dosyası da mod özetini taşır, yani bir kayıt farklı bir mod setiyle açılamaz.

Oyun başlarken her bilgisayar aynı paketi alır: tohum, başlangıç adımı, koltuklar (hangi oyuncu hangi ülke) ve oyun kuralları. Aynı ülkeyi iki oyuncu isterse önce katılan alır.

Biri düşerse

İnternet bağlantısı kopar, bilgisayar donar. Motorun bunlara verdiği cevaplar:

DurumNe olur
Bir oyuncu düşerOyun duraklar; belirlenen süre (0, 30, 60 ya da 120 saniye) dolunca o ülkeyi yapay zekâ devralır
Düşen oyuncu geri gelirKendi koltuğunun jetonuyla yeniden bağlanır; ülkesi ona geri verilir
Yeni biri oyuna katılırAna makine ona son kaydı ve sonraki komutları gönderir; kayıt 64 KB'lık parçalarla gider ve izi doğrulanır
Ana makine ayrılırHerkes son adımda durur; kalanlar arasında en küçük oyuncu numarası kendi kaydından oyunu sürdürür
DuraklatmaÜç kural seçeneği: herkes duraklatır, yalnız ana makine duraklatır, ya da ana makinenin duraklatmasını yalnız o kaldırır
İki insan oyuncu savaştaAna makine oyunun hızına bir tavan koyabilir
Olağan dışı durumlar

Ayrıca ekransız bir sunucu programımız var: hiçbir ülkeyi oynamayan, yalnız oyunu barındıran bir ana makine. Gözlemciler de katılabilir; gözlemcinin komutları reddedilir.

Sınırlar

  • Oynanabilir oyun yok: Bunların hepsi ekransız testlerde ve sunucuda çalışıyor; ekran ve arayüz henüz yok.
  • En yavaş belirler: Kilit adımda oyun en yavaş bilgisayarın ve en yavaş bağlantının hızında ilerler.
  • İki adımlık gecikme: Bir komut, verildiği adımdan iki adım sonra uygulanır.
  • Ana makine değişimi kesintisiz değil: Ana makine ayrılınca oyun kısa bir süre durur ve kayıttan devam eder.
  • Her şey ana makineden geçer: Yıldız düzeninde ana makinenin bağlantısı herkesin bağlantısını etkiler.
  • Hile önleme değil: Her bilgisayar dünyanın tamamını hesapladığı için, değiştirilmiş bir istemci normalde görmemesi gereken bilgiyi okuyabilir. Kilit adım bunu kendi başına önlemez.
  • Oyuncu bulma yok: İnternet üzerinden oyuncu bulma ve bağlantı kurma, oyunun yayımlanacağı platformun işidir; henüz yazılmadı.

Sık sorulanlar

Kilit adım (lockstep) nedir?

Her bilgisayarın aynı simülasyonu koştuğu, ağdan yalnız oyuncu komutlarının gittiği çok oyunculu yöntem. Büyük dünyalı strateji oyunlarında ağ trafiğini dünya büyüklüğünden bağımsız tutar.

Senkron kaybı (desync) neden olur?

İki bilgisayar aynı komutlardan farklı bir dünya hesapladığında. Tipik sebepler ondalıklı sayı farkları, sıralaması belirsiz tablolar, saate ya da ortama bağlı kod ve iş parçacıklarının yarışmasıdır.

MKA Engine senkron kaybını nasıl yakalıyor?

Dünyanın bütün durumundan 64 bitlik bir parmak izi hesaplanır ve oyuncular arasında karşılaştırılır. Fark çıkarsa oyun hemen bunu bildirir.

Oyundan düşen oyuncu geri dönebilir mi?

Evet. Düşen oyuncu kendi koltuğunun jetonuyla yeniden bağlanır ve ülkesi ona geri verilir. Yeni katılan birine ana makine son kaydı ve sonraki komutları gönderir. Bugün bu, motorun ekransız sunucusunda çalışıyor.

Kaynaklar ve kayıtlar

Dış kaynaklar:

İç kayıtlarımız (motorun deposu kapalı olduğu için bağlantı veremiyoruz):

  • Belirlenimcilik kararı ve lobi/el değiştirme kararı.
  • Çok oyunculu katman belgesi: tel protokolü, lobi, duraklatma, kayıtla el değiştirme, ayrışma yerelleştirme ve ekransız sunucu.
  • 15 Ekim 2026 sınamaları: ölçek dünyası 10 yıl, 1/8/16 iş parçacığı ve günlük parmak izleri; 5. yıl sonunda kaydet-yükle karşılaştırması; dört eşle 100 yıllık ağ testi (iki koşu); çapraz test (x86_64, aarch64, WebAssembly).

Bir sonraki günlükte motorun içine iniyoruz: 2 milyon nüfus birimi bellekte nasıl tutulur?

Bu günlük hakkında sorularınız ya da önerileriniz varsa bize iletişim sayfasından yazabilirsiniz. Motorun genel tanıtımı için MKA Engine sayfasına, bütün günlükler için Geliştirici Günlükleri listesine bakabilirsiniz.