Metin2 patcher yapımı, kendi sunucunu işletirken karşılaşacağın en kritik altyapı işlerinden biridir: oyuncular istemcilerini elle indirip dosya kopyalamak yerine, açtıkları launcher'ın güncellemeleri sessizce halletmesini bekler. İyi tasarlanmış bir launcher; sunucudaki sürümle oyuncunun diskindeki sürümü karşılaştırır, yalnızca değişen dosyaları indirir ve oyunu doğru parametrelerle başlatır. Bu rehberde, sade ama sağlam bir otomatik güncelleme mimarisini baştan sona kuruyoruz.
Launcher nasıl çalışır? Mimarinin özeti
Patcher mantığı aslında basit bir senkronizasyon problemidir. Üç parça vardır:
- Sunucu tarafı manifest: yayınlanan istemcideki her dosyanın yolu, boyutu ve
hashdeğerini (örneğin SHA-256) listeleyen bir dosya. - Dosya deposu: güncel istemci dosyalarının indirilebileceği bir HTTP(S) sunucusu veya CDN.
- İstemci uygulaması (launcher): manifesti indirir, yereldeki dosyalarla karşılaştırır, eksik/değişen dosyaları çeker ve oyunu çalıştırır.
Buradaki anahtar fikir, içerik tabanlı karşılaştırmadır. Tarih veya sürüm numarasına güvenmek yerine her dosyanın hash'ini doğrularsın; böylece yarım inen ya da bozulan dosyalar bir sonraki açılışta otomatik onarılır.
Manifest dosyasını üretmek
Önce yayınlanacak istemci klasörünü tarayıp bir manifest üreten küçük bir script hazırla. Aşağıda PowerShell ile basit bir örnek var; aynı mantığı Python veya bir CI adımıyla da kurabilirsin:
$root = "C:\dist\metin2-client"
$items = Get-ChildItem $root -Recurse -File | ForEach-Object {
$rel = $_.FullName.Substring($root.Length + 1).Replace('\','/')
[pscustomobject]@{
path = $rel
size = $_.Length
hash = (Get-FileHash $_.FullName -Algorithm SHA256).Hash.ToLower()
}
}
$items | ConvertTo-Json -Depth 3 | Out-File "$root\manifest.json" -Encoding utf8
Üretilen manifest.json şuna benzer:
[
{ "path": "metin2client.exe", "size": 5242880, "hash": "9f2c..." },
{ "path": "pack/root.eix", "size": 184320, "hash": "ab17..." },
{ "path": "pack/root.epk", "size": 9437184, "hash": "5e0d..." }
]
Manifesti istemci dosyalarıyla aynı dizine, sabit bir URL altına koy (örneğin https://cdn.sunucum.com/client/manifest.json). Her yeni yamada bu script'i tekrar çalıştırıp manifesti yeniden yayınlaman yeterli.
İstemci tarafı: karşılaştırma ve indirme
Launcher'ı Windows için yazacağın için C# (.NET) pratik bir seçimdir; HttpClient, SHA256 ve WPF/WinForms hazır gelir. Çekirdek akış şudur: manifesti indir, her giriş için yereldeki dosyanın hash'ini hesapla, eşleşmeyenleri indir.
using System.Security.Cryptography;
string Sha256(string file)
{
using var stream = File.OpenRead(file);
using var sha = SHA256.Create();
return Convert.ToHexString(sha.ComputeHash(stream)).ToLowerInvariant();
}
async Task SyncAsync(string baseUrl, string localRoot, List<Entry> manifest)
{
using var http = new HttpClient();
foreach (var entry in manifest)
{
var local = Path.Combine(localRoot, entry.path);
bool needs = !File.Exists(local) || Sha256(local) != entry.hash;
if (!needs) continue;
Directory.CreateDirectory(Path.GetDirectoryName(local)!);
var bytes = await http.GetByteArrayAsync($"{baseUrl}/{entry.path}");
await File.WriteAllBytesAsync(local, bytes);
}
}
Büyük .epk/.eix paketleri için GetByteArrayAsync yerine akışla (stream) yazmayı tercih et; bellek dolmasın ve ilerleme çubuğunu besleyebilesin. Her dosya için indirilen baytları toplam boyuta oranlayarak yüzde gösterirsin.
Oyunu doğru başlatmak
Senkronizasyon bittikten sonra launcher istemciyi çalıştırır. Çalışma dizinini istemci klasörüne ayarlamak önemlidir, aksi halde oyun paketlerini bulamaz:
var psi = new ProcessStartInfo
{
FileName = Path.Combine(localRoot, "metin2client.exe"),
WorkingDirectory = localRoot,
UseShellExecute = false
};
Process.Start(psi);
İstersen launcher'ın oturum/token bilgisini istemciye iletmesi için argüman da geçebilirsin; ancak hassas verileri komut satırında açık göndermekten kaçın, bunun yerine geçici bir dosya ya da named pipe kullan.
Güncelleme ve güvenlik notları
- HTTPS kullan. Manifesti ve dosyaları düz HTTP üzerinden sunmak, araya girip dosya değiştirme (MITM) riskini doğurur.
- Manifesti imzala. Daha sağlam bir kurulum için manifesti özel anahtarla imzalayıp launcher'a gömülü açık anahtarla doğrula; böylece sahte manifest enjekte edilemez.
- Self-update. Launcher'ın kendisi de güncellenmeli. Yaygın yöntem: yeni sürümü
launcher.exe.newolarak indir, küçük bir yardımcı script ile kapanışta dosyayı değiştir. - Yeniden deneme ve onarım. İndirme yarıda kesilirse bir sonraki açılışta hash uyuşmadığı için dosya zaten tekrar çekilir; bu mimarinin doğal getirdiği bir onarım mekanizmasıdır.
metin2 patcher yapımında sık yapılan hatalar
Çoğu sorun mimariden değil, ayrıntılardan çıkar. En sık görülenler: göreli dosya yollarında ters/eğik bölü karışıklığı (Windows \ vs URL /), hash'leri büyük/küçük harf tutarsız karşılaştırmak, ve büyük paketleri belleğe komple yükleyip launcher'ı şişirmek. Manifesti her zaman dağıtımın son adımında üret; aksi halde yeni eklediğin dosya manifestte yer almaz ve oyunculara hiç inmez.
Sık Sorulan Sorular
Hangi dili/teknolojiyi seçmeliyim?
Windows hedefliyorsan C# (.NET) en az sürtünmeli yoldur; tek dosyalık bir publish ile dağıtırsın. Çapraz platform veya daha ince bir arayüz istiyorsan C++/Qt ya da Electron de çalışır, ama Electron'un boyut maliyeti vardır.
MD5 yerine neden SHA-256?
MD5 çakışmalara açık olduğu için güvenlik açısından önerilmez. Yalnızca bütünlük kontrolü için MD5 hızlı olsa da, manifest imzalama gibi güvenlik katmanı eklediğinde SHA-256 ile tutarlı kalmak daha doğrudur.
Tüm istemciyi mi yoksa sadece farkı mı dağıtmalıyım?
Bu mimaride yalnızca hash'i değişen dosyalar iner, yani fiilen artımlı (incremental) güncelleme yaparsın. İlk kurulum için ayrıca tam istemciyi bir kez indirten bir bağlantı sunman oyuncuların işini kolaylaştırır.
Kendi sunucun için sağlam bir patcher mi istiyorsun? Manifest üretiminden self-update'e kadar tüm launcher altyapısını kurar, marka kimliğine uygun bir arayüzle teslim ederim. Projeni konuşalım: benimle iletişime geç.