İçeriğe geç

Metin2 Source Yapısı: game, db ve Client Modülleri

Hazırlayan: Metin2VIP Editörleri Yayın: 9 dk okuma

Kısaca: Metin2 server kaynağı iki programdan oluşur: oyunu yürüten game (auth da aynı programdır) ve oyuncu verisini önbellekte tutup MySQL'e yazan db. İkisi common klasöründeki ortak başlıkları ve libthecore, libsql, libgame, libpoly, liblua kütüphanelerini kullanır. Client kaynağında exe'yi UserInterface projesi üretir; grafik EterLib'de, harita ve karakterler GameLib'de, paketler EterPack'te, Python bağlantısı ScriptLib ve EterPythonLib'de durur, toplam 15 kütüphane vardır.
İçindekiler
  1. Sunucu süreçleri birbiriyle nasıl konuşur?
  2. Sunucu klasörleri: hangi modül ne yapar?
  3. game/src içinde ne nerede?
  4. Bir paket sunucuda nasıl işlenir?
    1. Örnek: bir sohbet mesajının yolu
  5. Ana döngü: saniyede 25 nabız
  6. db/src içinde ne nerede?
  7. İstemci tarafı: UserInterface ve 15 kütüphane
  8. İstemcide C++ ile Python nasıl konuşur?
  9. Bir özelliği kaynakta nerede ararsın?

Metin2 server kaynağı iki programdan oluşur: oyunun kendisini yürüten game ve oyuncu verisini önbellekte tutup MySQL'e yazan db. Giriş sunucusu (auth) ayrı bir program değildir; CONFIG dosyasında AUTH_SERVER satırı bulunan bir game sürecidir. İki program common klasöründeki ortak başlıkları ve beş küçük kütüphaneyi (libthecore, libsql, libgame, libpoly, liblua) paylaşır. Client tarafında exe'yi UserInterface projesi üretir; grafik, harita, ses, paket ve Python bağlantısı 15 ayrı kütüphanededir.

Aşağıdaki harita, kaynak paketindeki Source/Serversrc/Server ve Source/Clientsrc/Client klasörlerine dayanır. Bu kaynak, Ymir'in orijinal kodu üzerine topluluk düzeltmeleri eklenmiş bir sürümdür; isteğe bağlı sistemler service.h ve Locale_inc.h bayraklarıyla açılıp kapanır. Derleme adımları Metin2 source derleme yazısında.

Sunucu süreçleri birbiriyle nasıl konuşur?

Bağlantıların hepsi TCP'dir; bu kaynakta __UDP_BLOCK__ bayrağı yüzünden çekirdeğin UDP soketi hiç açılmaz. Her paketin ilk baytı türünü söyleyen bir başlıktır ve başlıkların adı kimin kime konuştuğunu gösterir:

Bağlantı Başlık öneki Ne taşır
İstemci → oyun çekirdeği ya da auth HEADER_CG_ Oyuncunun istekleri: hareket, saldırı, sohbet, eşya kullanma (78 tür)
Oyun çekirdeği → istemci HEADER_GC_ Görünen karakterler, eşyalar, puanlar, mesajlar (125 tür)
Oyun çekirdeği ↔ oyun çekirdeği HEADER_GG_ P2P: oyuncunun hangi çekirdekte olduğu, fısıltı aktarımı, duyuru, bağırma, lonca, ışınlanma (29 tür)
Oyun çekirdeği ↔ db HEADER_GD_, HEADER_DG_ Karakter yükleme ve kaydetme, protolar, lonca, evlilik gibi ortak veriler (105 ve 102 tür)

db, oyuncu ve eşya kayıtlarının yüklendiği ve kaydedildiği yerdir. Açılışta item_proto, mob_proto, skill_proto, refine_proto, shop, item_attr, banword, land ve object tablolarını okur; bir oyun çekirdeği bağlandığında hepsini ona tek pakette gönderir. Karakter kaydı da db'ye gider ve önbellekte bekler; MySQL'e varsayılan olarak oyuncu verisi 7, eşya verisi 5 dakikada bir yazılır (conf.txt'deki PLAYER_CACHE_FLUSH_SECONDS ve ITEM_CACHE_FLUSH_SECONDS).

Oyun çekirdekleri MySQL'e tamamen db üzerinden bağlanmaz. CONFIG'deki COMMON_SQL bağlantısı locale tablosu gibi ortak ayarları okur, PLAYER_SQL lonca, arkadaş listesi ve quest fonksiyonları gibi yerlerde doğrudan sorgu çalıştırır, LOG_SQL günlük kayıtlarını yazar. auth'un PLAYER_SQL satırı ise account veritabanını gösterir; kullanıcı adı ve parola orada doğrulanır. Veritabanlarının içeriği Metin2 veritabanları, portların dağılımı Metin2 kanal ve portlar yazısında.

Sunucu klasörleri: hangi modül ne yapar?

Klasör Görevi
common/ game ile db'nin ortak dili: sabitler ve sınırlar (length.h), eşya türleri ve yuvaları (item_length.h), game ile db arasındaki paket ve tablo yapıları (tables.h), özellik bayrakları (service.h)
game/src/ Oyun çekirdeği. Klasördeki 173 .cpp dosyasının 169'u derlenir; test ile başlayan dördü derlemeye girmez
db/src/ Veritabanı çekirdeği, 31 .cpp dosyası
libthecore/ Çalışma zamanı: soketler, olay izleyici (FreeBSD'de kqueue, başka sistemlerde select), tamponlar, sinyaller, syslog ve syserr günlükleri, nabız döngüsü, TEA, DES ve GOST şifreleri, Korece metin yardımcıları
libsql/ MySQL sorgularını ayrı bir iş parçacığında çalıştıran asenkron katman
libgame/ Harita hücre nitelikleri (CAttribute), depo, ticaret penceresi ve market ızgarası (CGrid), TGA okuyucu
libpoly/ Formül çözücü: skill_proto'daki atk, k, lv gibi değişkenli formülleri hesaplar
liblua/ Lua 5.0.3; quest motoru bunun üstünde çalışır. 5.2 klasörü varsayılan derlemede kullanılmaz

common başlıkları iki programın arasındaki sözleşmedir. Buradaki bir yapıyı ya da bayrağı değiştirmek game ile db'nin birlikte yeniden derlenmesini, değişiklik istemciye giden bir paketi etkiliyorsa istemcinin de güncellenmesini gerektirir.

game/src içinde ne nerede?

Konu Dosyalar
Ağ ve oturum desc*.cpp (bağlantılar), input*.cpp (paket işleyicileri), packet.h, packet_info.cpp, p2p.cpp
Karakter char.cpp, char_*.cpp (eşya, etki, at, durum), char_manager.cpp
Savaş battle.cpp, char_battle.cpp, pvp.cpp
Beceri char_skill.cpp, skill.cpp, skill_power.cpp
Eşya item.cpp, item_attribute.cpp, item_manager*.cpp, refine.cpp, cube.cpp, blend_item.cpp, DragonSoul.cpp
Harita ve canavarlar sectree*.cpp, regen.cpp, mob_manager.cpp, dungeon.cpp, map_location.cpp
Quest questmanager.cpp, questlua*.cpp, questnpc.cpp, questpc.cpp
Sistemler guild*.cpp, party.cpp, marriage.cpp, exchange.cpp, shop*.cpp, safebox.cpp, fishing.cpp, mining.cpp, horse_rider.cpp, PetSystem.cpp, OXEvent.cpp, monarch.cpp, threeway_war.cpp, DragonLair.cpp
Komutlar cmd.cpp (komut tablosu ve yetki seviyeleri), cmd_general.cpp, cmd_gm.cpp, cmd_emotion.cpp
Ayar ve dil config.cpp, locale_service.cpp, locale.cpp, constants.cpp
Veritabanı ve günlük db.cpp, log.cpp, input_db.cpp
Ana döngü main.cpp, event.cpp, event_queue.cpp

Ülkeye göre değişen davranışlar LC_IsEurope(), LC_IsYMIR() gibi fonksiyonlarla seçilir. Hangisinin geçerli olduğunu common veritabanındaki LOCALE değeri belirler; bu pakette turkey'dir ve LC_IsEurope() doğru döner. Kaynak koddaki yorumlar ve oyuncuya giden metinlerin aslı Korecedir (cp949), düzenleyicide başka bir kod sayfasıyla açılınca bozuk görünür.

Bir paket sunucuda nasıl işlenir?

  1. libthecore'un olay izleyicisi soketi okunabilir bildirir, gelen baytlar bağlantının (DESC) tamponuna alınır.
  2. CInputProcessor::Process (input.cpp) ilk bayttaki başlığa bakar ve paketin boyunu packet_info.cpp'deki tablodan bulur. Tanınmayan başlıkta syserr'e "UNKNOWN HEADER" yazılır ve bağlantı kapatılır.
  3. Paketi bağlantının bulunduğu aşamanın işleyicisi alır: el sıkışmada CInputHandshake, giriş, karakter seçimi ve yüklemede CInputLogin, oyunda ve ölüyken CInputMain, auth'ta CInputAuth.
  4. CInputMain::Analyze (input_main.cpp) başlığa göre ilgili fonksiyonu çağırır; oyun mantığı karakter nesnesinin (CHARACTER) yöntemlerinde yürür.
  5. Sonuç istemciye GC paketi olarak gider. Kaydedilmesi gereken veri (karakter, eşya, lonca) db'ye GD paketleriyle gider; db'nin cevaplarını CInputDB::Analyze (input_db.cpp) işler.

Örnek: bir sohbet mesajının yolu

  1. Oyuncu mesajı yazıp Enter'a basar; uichat.py mesajı net.SendChatPacket ile gönderir ve istemci HEADER_CG_CHAT paketini kurar.
  2. Çekirdekte paket CInputMain::Analyze üzerinden CInputMain::Chat'e gelir.
  3. Chat, yasaklı kelimeleri banword listesiyle * yapar; bağırmada seviye ve bekleme süresi sınırlarını denetler.
  4. Normal mesaj görüş alanındaki karakterlere HEADER_GC_CHAT olarak gider. Bağırma ayrıca HEADER_GG_SHOUT ile diğer çekirdeklere aktarılır.
  5. Alan istemci paketi oyun aşamasının başlık listesinde tanır, kendi küfür süzgecinden geçirir ve sohbet penceresine yazar.

Ana döngü: saniyede 25 nabız

Oyun çekirdeği tek bir döngüde çalışır. libthecore döngüyü saniyede 25 nabızla kurar. Her nabızda zamanlanmış olaylar (event.cpp) işlenir; her saniye db'ye çekirdekteki oyuncu sayısı bildirilir, belli aralıklarla bekleyen karakter kayıtları ve eşya güncellemeleri yapılır. Nabızların arasında karakterler güncellenir, soketler okunup yazılır.

Oyun mantığının tamamı bu tek iş parçacığında döner; yalnız MySQL sorguları libsql'in ayrı iş parçacığında, döngüyü bekletmeden yürür. Kodda süreler bu yüzden saniye değil nabız cinsinden yazılır: PASSES_PER_SEC(5) 5 saniye, yani 125 nabız demektir. CONFIG'deki PASSES_PER_SEC satırının neden 25 kalması gerektiği CONFIG ayarları yazısında. db çekirdeğinin nabız sayısı ise conf.txt'deki CLIENT_HEART_FPS ile verilir.

db/src içinde ne nerede?

Dosya Görevi
Main.cpp, Config.cpp Açılış, conf.txt okuma, MySQL bağlantıları
ClientManager*.cpp Oyun çekirdeklerinden gelen isteklerin merkezi. ClientManagerBoot protoları ve tabloları yükler; Login, Player, Guild, Party, EventFlag, HorseName dosyaları kendi konularını işler
Cache.cpp Oyuncu ve eşya önbelleği, MySQL'e gecikmeli yazma
ProtoReader.cpp, CsvReader.cpp item_proto.txt ve mob_proto.txt okuyucuları
GuildManager.cpp Lonca savaşları ve puanları
PrivManager.cpp Krallık, lonca ve karakter bonusları (EXP, drop, Yang oranı)
ItemAwardManager.cpp item_award tablosundan eşya verme
Marriage.cpp, Monarch.cpp Evlilik ve kral sistemi verisi
ItemIDRangeManager.cpp Her oyun çekirdeğine çakışmayan bir eşya numarası aralığı dağıtma
HB.cpp hotbackup veritabanına yedek

İstemci tarafı: UserInterface ve 15 kütüphane

Modül .cpp Görevi
UserInterface 95 Exe: açılış (UserInterface.cpp), ana döngü (PythonApplication.cpp), ağ aşamaları (PythonNetworkStream*.cpp, AccountConnector.cpp), karakter görünümü (InstanceBase*.cpp), oyuncunun durumu (PythonPlayer*.cpp), Python'a açılan modüller (Python*Module.cpp)
EterLib 71 Direct3D 8 aygıtı, doku ve yazı tipi, metin çizimi, IME, klavye ve fare girdisi, kamera, soket akışı, kaynak yöneticisi
GameLib 59 Harita ve arazi yükleme (MapOutdoor*.cpp), aktörler ve hareketleri (ActorInstance*.cpp), ırk verisi (.msm), eşya verisi (ItemData, ItemManager), oklar ve büyüler gibi uçan nesneler, harita nesneleri (Property)
EffectLib 18 .mse efektleri, parçacıklar, efekt modelleri
EterBase 17 Temel araçlar: CRC32, dosya eşleme, LZO, TEA, paket şifrelemesi, zamanlayıcı, syserr.txt günlüğü, çökme dökümü
EterGrnLib 15 Granny .gr2 modelleri, hareketleri ve ayrıntı düzeyi (LOD)
MilesLib 11 2B ve 3B sesler, müzik akışı
EterPythonLib 11 Pencere sistemi (wndMgr), yuva pencereleri, çizim modülleri (grp)
SpeedTreeLib 7 .spt ağaçları ve çimen
EterPack 6 Paket dosyaları (.eix, .epk)
ScriptLib 6 Python yorumlayıcısını gömme (PythonLauncher), uzantıya göre kaynak türü (gr2, dds, tga, sub, mse...), hata ayıklama modülü
EterLocale 5 Kod sayfası dönüşümleri; Arapça, Japonca ve Vietnamca metin desteği
SphereLib 4 Görünürlük hesabı için küre ağacı ve görüş konisi
EterImageLib 4 DDS (DXT) ve TGA görüntü okuma
PRTerrainLib 3 Arazi ve doku setleri (TextureSet)
CWebBrowser 1 Oyun içi web penceresi (Windows'un tarayıcı bileşeni)

UserInterface dışındaki projelerin hepsi statik kütüphanedir ve exe'ye gömülür. İstemcinin özellik bayrakları UserInterface/Locale_inc.h dosyasındadır; kütüphanelerin hemen hepsi bu dosyayı ön derlenmiş başlığına aldığı için bir bayrak bütün çözümü etkiler.

İstemcide C++ ile Python nasıl konuşur?

Exe açılırken Python 2.7 yorumlayıcısını başlatır ve ona 38 modül tanıtır: net (ağ), player (oyuncunun kendi durumu), chr ve chrmgr (karakterler), item, skill, nonplayer (canavar verisi), app (pencere ve uygulama), wndMgr ve grp (arayüz ve çizim), pack, snd, background, miniMap, quest, guild, shop, safebox, exchange, messenger, systemSetting ve diğerleri. root paketindeki .py dosyaları arayüzü bu modüllerle kurar; hangi pencerenin açılacağına, bir tuşun ne yapacağına Python tarafı karar verir.

Bilgi iki yönde akar. Bir betik net.SendChatPacket(metin, tür) gibi bir fonksiyon çağırdığında C++ paketi kurup gönderir. Sunucudan gelen paketi ise C++ çözer (PythonNetworkStreamPhaseGame.cpp içindeki başlık listesi), kendi durumunu günceller ve gerekirse oyun penceresindeki bir Python fonksiyonunu çağırır. Bu fonksiyonların adları BINARY_ ile başlar; game.py'de 38 tane vardır.

İstemcinin ağ tarafı sunucudaki aşamaların aynısını izler: çevrimdışı, el sıkışma, giriş, karakter seçimi, yükleme ve oyun. Her aşamanın işleyicisi ayrı bir dosyadadır (PythonNetworkStreamPhaseLogin.cpp, PythonNetworkStreamPhaseSelect.cpp, PythonNetworkStreamPhaseLoading.cpp, PythonNetworkStreamPhaseGame.cpp). Dosyalar paketlerden EterPack üzerinden okunur, her uzantı ScriptLib'deki tabloya göre doğru sınıfa (model, görüntü, efekt) verilir; paket biçimi Metin2 pack dosyaları, açılış sırası Metin2 client klasör yapısı yazısında.

Bir özelliği kaynakta nerede ararsın?

Konu Sunucu İstemci
Hasar hesabı battle.cpp, char_battle.cpp Hesaplamaz, sunucunun sayısını gösterir
Puanlar ve efsunların etkisi char.cpp (ComputePoints, ApplyPoint), constants.cpp uitooltip.py (gösterim)
Beceriler char_skill.cpp, skill.cpp PythonSkill.cpp, skilldesc.txt, skilltable.txt
Artı basma char_item.cpp (DoRefine), refine.cpp uirefine.py
Efsun ekleme ve değiştirme item_attribute.cpp uitooltip.py
Drop item_manager.cpp, item_manager_read_tables.cpp Yok
Canavarların doğması regen.cpp, sectree_manager.cpp Yok
Quest fonksiyonları questlua_*.cpp (her dosya bir Lua tablosu: pc, item, npc, game...) uiquest.py (pencere)
GM komutları cmd.cpp, cmd_gm.cpp, cmd_general.cpp Yok
CONFIG anahtarları config.cpp Yok
item_proto okuma db: ClientManagerBoot.cpp, ProtoReader.cpp ItemManager.cpp (istemci kopyası)
Giriş input_auth.cpp, input_login.cpp AccountConnector.cpp, intrologin.py
Paket listesi packet.h, packet_info.cpp Packet.h, PythonNetworkStream.cpp

Hasarın oyuncu açısından nasıl hesaplandığı Metin2 hasar hesaplama, quest tablolarındaki fonksiyonların listesi Metin2 quest fonksiyonları yazısında. Komut tablosundaki yetki seviyeleriyle birlikte bütün komutlar GM komutları sayfasında toplanıyor.

Sık sorulan sorular

Metin2 source'da hasar hesabı hangi dosyada?
Sunucunun game/src klasöründe: saldırı ve savunma hesabı battle.cpp'de, hasarın hedefe uygulanması ve kritik ile delici vuruş char_battle.cpp'de. İstemci hasarı hesaplamaz, sunucunun bildirdiği sayıyı gösterir.
auth ayrı bir program mı?
Hayır. auth, CONFIG dosyasında AUTH_SERVER satırı bulunan bir game sürecidir. Aynı ikili dosya çalışır, yalnız giriş paketlerini işler ve kullanıcı adıyla parolayı account veritabanında doğrular.
Quest fonksiyonları kaynakta nerede?
game/src altındaki questlua_*.cpp dosyalarında. Her dosya bir Lua tablosunu kaydeder: questlua_pc.cpp pc.*, questlua_item.cpp item.*, questlua_npc.cpp npc.* fonksiyonlarını tanımlar.
Client'taki Python dosyaları C++ koduna nasıl ulaşır?
Exe, Python'a net, player, item, chr, app, wndMgr gibi 38 modül açar. root paketindeki betikler bu modüllerin fonksiyonlarını çağırır; sunucudan gelen paketler C++ tarafında çözülüp game.py'deki BINARY_ ile başlayan fonksiyonlara iletilir.

İlgili sayfalar

Kategori: Server Kurma Kaynak Kod kaynak kod geliştirici db source game

Bu sayfadaki bilgiler Metin2'nin sunucu yazılımındaki hesaplamalara ve standart oyun dosyalarına dayanır. Oyun dosyalarını değiştiren sunucularda değerler farklı olabilir. İçerikleri nasıl hazırlıyoruz?

Bu sayfa işine yaradı mı?

Giriş yap, oy ver ya da sayfayı kaydet. Okumak için üyelik gerekmez. WhatsApp X'te paylaş
Yanlış ya da eksik bir bilgi mi gördün? Bildir
Neyin yanlış olduğunu, doğrusunun ne olduğunu ve bunu nereden bildiğini yaz. Mesajın editörlere gider; yazı, kontrol edildikten sonra düzeltilir.
Yalnız editör görür.

Tartışma

Kurallar

Henüz yorum yok. Bu konuda bir deneyimin ya da sorun varsa ilk yorumu sen yaz.

Giriş yap ya da kayıt ol, sonra yorum yaz. Metin2VIP üyeliği hiçbir oyun sunucusunun hesabı değildir.