Source Temizliği: Proto "LocaleName" Karmaşasına Son Verin
Korece isim sütununu kaldırın, encoding hatalarından ve kod kirliliğinden kurtulun.
Korece isim sütununu kaldırın, encoding hatalarından ve kod kirliliğinden kurtulun.
Nedir ve Neden Yapıyoruz?
Orijinal Ymir altyapısında "Name" sütunu Korece isimler, "LocaleName" sütunu ise yerel dildeki (İngilizce/Türkçe) isimler için ayrılmıştır. Ancak Korece konuşmayan geliştiriciler için bu durum:
- <li data-xf-list-type="ul">
Gereksiz Kod Kalabalığı: Her yerde çift kontrol yapılır. <li data-xf-list-type="ul">
Encoding Sorunları: Visual Studio veya veritabanı encoding'i bozulduğunda Korece karakterler (gb2312) sunucunun açılmamasına veya mob isimlerinin bozuk görünmesine neden olur. <li data-xf-list-type="ul">
Veri Tekrarı: Proto dosyalarında gereksiz yere iki isim tutulur.
Bu rehber ile "LocaleName" yapısını kaldırıp, her şeyi tek bir "Name" (szName) yapısı altında birleştiriyoruz.
İşlemlere başlamadan önce Client Source, Server Source ve Tools yedeğinizi alınız!
DumpProto düzenlemesi içerir, kapatıcı (packer) güncellemeniz gerekebilir.
BÖLÜM 1: Client Source (İstemci)
Dosya: Client\Source\GameLib\ItemData.cpp
Bul:
Kod:
return m_ItemTable.szLocaleName;
Kod:
return m_ItemTable.szName;
Dosya: Client\Source\GameLib\ItemData.h
Bul ve Sil:
Kod:
char szLocaleName[ITEM_NAME_MAX_LEN + 1];
Dosya: Client\Source\UserInterface\PythonNetworkStreamCommand.cpp
Bul:
Kod:
strMonsterList += c_pMobTable->szLocaleName;
Kod:
strMonsterList += c_pMobTable->szName;
Dosya: Client\Source\UserInterface\PythonNonPlayer.cpp
İşlem: Aşağıdaki tüm
Kod:
szLocaleName
Kod:
szName
Kod:
// 1. Değişiklik pNonPlayerData->szLocaleName -> pNonPlayerData->szName // 2. Değişiklik (GetName içinde) *c_pszName = p->szLocaleName; -> *c_pszName = p->szName; // 3. Değişiklik (GetMonsterName içinde) return c_pTable->szLocaleName; -> return c_pTable->szName;
Dosya: Client\Source\UserInterface\PythonNonPlayer.h
Bul ve Sil:
Kod:
char szLocaleName[CHARACTER_NAME_MAX_LEN + 1];
BÖLÜM 2: Server Source - DB & Common
Dosya: Server\Source\common\tables.h
Bul ve Sil (SEntityTable içinde):
Kod:
char szLocaleName[CHARACTER_NAME_MAX_LEN + 1];
Kod:
char szLocaleName[ITEM_NAME_MAX_LEN + 1];
Dosya: Server\Source\db\ClientManager.cpp
Bul ve Sil:
Kod:
extern int g_iItemCacheFlushSeconds; extern std::string g_stLocaleNameColumn; // SİL
Bul ve Sil (InitializeLocalization içinde):
Kod:
g_stLocaleNameColumn = "xxx"; // ... ve ... else if (strcmp(locale.szKey, "DB_NAME_COLUMN") == 0) { // ... g_stLocaleNameColumn = locale.szValue; }
Dosya: Server\Source\db\ClientManagerBoot.cpp
Bul ve Sil:
Kod:
extern std::string g_stLocaleNameColumn;
InitializeMobTable Fonksiyonu Düzenlemeleri:
- <li data-xf-list-type="ul">Sil:
<li data-xf-list-type="ul">Loglardaki `szLocaleName` alanlarını kaldırın.Kod:
strlcpy(mob_table->szLocaleName, tempTable->szLocaleName, sizeof(tempTable->szName));
InitializeItemTable Fonksiyonu Düzenlemeleri:
- <li data-xf-list-type="ul">Sil:
<li data-xf-list-type="ul">Loglardaki `szLocaleName` alanlarını kaldırın.Kod:
strlcpy(item_table->szLocaleName, tempTable->szLocaleName, sizeof(item_table->szLocaleName));
MirrorMobTableIntoDB Fonksiyonu (Query Yapısı):
Buradaki sorguyu `szLocaleName` olmadan sadeleştiriyoruz.
Bununla Değiştirin:
Kod:
snprintf(query, sizeof(query), "replace into mob_proto%s " "(" "vnum, name, type, rank, battle_type, level, size, ai_flag, setRaceFlag, setImmuneFlag, " "on_click, empire, drop_item, resurrection_vnum, folder, " "st, dx, ht, iq, damage_min, damage_max, max_hp, regen_cycle, regen_percent, exp, " "gold_min, gold_max, def, attack_speed, move_speed, aggressive_hp_pct, aggressive_sight, attack_range, polymorph_item, " "enchant_curse, enchant_slow, enchant_poison, enchant_stun, enchant_critical, enchant_penetrate, " "resist_sword, resist_twohand, resist_dagger, resist_bell, resist_fan, resist_bow, " "resist_fire, resist_elect, resist_magic, resist_wind, resist_poison, " "dam_multiply, summon, drain_sp, " "skill_vnum0, skill_level0, skill_vnum1, skill_level1, skill_vnum2, skill_level2, " "skill_vnum3, skill_level3, skill_vnum4, skill_level4, " "sp_berserk, sp_stoneskin, sp_godspeed, sp_deathblow, sp_revive" ") " "values (" "%d, \"%s\", %d, %d, %d, %d, %d, %u, %u, %u, " "%d, %d, %d, %d, '%s', " "%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, " "%d, %d, %d, %d, %d, %d, %d, %d, %d, " "%d, %d, %d, %d, %d, %d, " "%d, %d, %d, %d, %d, %d, " "%d, %d, %d, %d, %d, " "%f, %d, %d, " "%d, %d, %d, %d, %d, %d, " "%d, %d, %d, %d, " "%d, %d, %d, %d, %d" ")", GetTablePostfix(), t.dwVnum, t.szName, t.bType, t.bRank, t.bBattleType, t.bLevel, t.bSize, t.dwAIFlag, t.dwRaceFlag, t.dwImmuneFlag, t.bOnClickType, t.bEmpire, t.dwDropItemVnum, t.dwResurrectionVnum, t.szFolder, t.bStr, t.bDex, t.bCon, t.bInt, t.dwDamageRange[0], t.dwDamageRange[1], t.dwMaxHP, t.bRegenCycle, t.bRegenPercent, t.dwExp, t.dwGoldMin, t.dwGoldMax, t.wDef, t.sAttackSpeed, t.sMovingSpeed, t.bAggresiveHPPct, t.wAggressiveSight, t.wAttackRange, t.dwPolymorphItemVnum, t.cEnchants[0], t.cEnchants[1], t.cEnchants[2], t.cEnchants[3], t.cEnchants[4], t.cEnchants[5], t.cResists[0], t.cResists[1], t.cResists[2], t.cResists[3], t.cResists[4], t.cResists[5], t.cResists[6], t.cResists[7], t.cResists[8], t.cResists[9], t.cResists[10], t.fDamMultiply, t.dwSummonVnum, t.dwDrainSP, t.Skills[0].dwVnum, t.Skills[0].bLevel, t.Skills[1].dwVnum, t.Skills[1].bLevel, t.Skills[2].dwVnum, t.Skills[2].bLevel, t.Skills[3].dwVnum, t.Skills[3].bLevel, t.Skills[4].dwVnum, t.Skills[4].bLevel, t.bBerserkPoint, t.bStoneSkinPoint, t.bGodSpeedPoint, t.bDeathBlowPoint, t.bRevivePoint );
MirrorItemTableIntoDB Fonksiyonu:
Burada `g_stLocaleNameColumn` kontrolünü kaldırıp tek bir sorgu bırakıyoruz.
Bununla Değiştirin:
Kod:
const TItemTable& t = *it; char query[4096]; snprintf(query, sizeof(query), "replace into item_proto%s (" "vnum, type, subtype, name, gold, shop_buy_price, weight, size, " "flag, wearflag, antiflag, immuneflag, " "refined_vnum, refine_set, magic_pct, socket_pct, addon_type, " "limittype0, limitvalue0, limittype1, limitvalue1, " "applytype0, applyvalue0, applytype1, applyvalue1, applytype2, applyvalue2, " "value0, value1, value2, value3, value4, value5 ) " "values (" "%d, %d, %d, \"%s\", %d, %d, %d, %d, " "%d, %d, %d, %d, " "%d, %d, %d, %d, %d, " "%d, %d, %d, %d, " "%d, %d, %d, %d, %d, %d, " "%d, %d, %d, %d, %d, %d )", GetTablePostfix(), t.dwVnum, t.bType, t.bSubType, t.szName, t.dwGold, t.dwShopBuyPrice, t.bWeight, t.bSize, t.dwFlags, t.dwWearFlags, t.dwAntiFlags, t.dwImmuneFlag, t.dwRefinedVnum, t.wRefineSet, t.bAlterToMagicItemPct, t.bGainSocketPct, t.sAddonType, t.aLimits[0].bType, t.aLimits[0].lValue, t.aLimits[1].bType, t.aLimits[1].lValue, t.aApplies[0].bType, t.aApplies[0].lValue, t.aApplies[1].bType, t.aApplies[1].lValue, t.aApplies[2].bType, t.aApplies[2].lValue, t.alValues[0], t.alValues[1], t.alValues[2], t.alValues[3], t.alValues[4], t.alValues[5]); CDBManager::instance().AsyncQuery(query);
Dosya: Server\Source\db\Main.cpp
Bul ve Sil:
Kod:
std::string g_stLocaleNameColumn = "name";
Dosya: Server\Source\db\ProtoReader.cpp
TXT okuyucuda artık localeName aramak yerine doğrudan name'i güncelleyeceğiz.
Mob Table İçin Değiştir:
Kod:
/*======== NAME =======*/ strlcpy(mobTable->szName, csvTable.AsStringByIndex(col++), sizeof(mobTable->szName)); // Overwrite name with localized name if found if (auto it = nameMap.find(mobTable->dwVnum); it != nameMap.end()) { strlcpy(mobTable->szName, it->second, sizeof(mobTable->szName)); }
Item Table İçin Değiştir:
Kod:
// Overwrite name with localized name if found if (auto it = nameMap.find(itemTable->dwVnum); it != nameMap.end()) { strlcpy(itemTable->szName, it->second, sizeof(itemTable->szName)); }
BÖLÜM 3: Server Source - Game
Aşağıdaki dosyalarda `szLocaleName` gördüğünüz her yeri `szName` olarak değiştirmeniz gerekmektedir. Bazı yerlerde `GetTable(xxx)->szLocaleName` şeklinde geçer, bunları da `szName` yapın.
Dosya Listesi:
- <li data-xf-list-type="ul">game/char.cpp <li data-xf-list-type="ul">game/char_manager.cpp <li data-xf-list-type="ul">game/cmd_general.cpp (At besleme ve item gereksinimi logları) <li data-xf-list-type="ul">game/input_main.cpp (Fısıltı ve Ticaret logları) <li data-xf-list-type="ul">game/item.cpp (GetRefineFromVnum ve GetBaseName fonksiyonları) <li data-xf-list-type="ul">game/item.h (`GetName` fonksiyonu artık `szName` döndürmeli) <li data-xf-list-type="ul">game/item_manager.cpp <li data-xf-list-type="ul">game/mob_manager.cpp <li data-xf-list-type="ul">game/questlua_global.cpp <li data-xf-list-type="ul">game/regen.cpp <li data-xf-list-type="ul">game/shop_manager.cpp
BÖLÜM 4: Tools (DumpProto)
Kapatıcınızın proto oluştururken hata vermemesi için bunu yapmalısınız.
Dosya: Tools\DumpProto\dump_proto\dump_proto.cpp
- <li data-xf-list-type="ul">Struct'lardan `szLocaleName` değişkenlerini silin. <li data-xf-list-type="ul">TXT'den veri okurken (Set_Proto_Mob_Table ve Set_Proto_Item_Table) `szLocaleName` atamalarını kaldırın, `nameMap` (mob_names.txt / item_names.txt) verisini doğrudan `szName` üzerine yazın. <li data-xf-list-type="ul">Build fonksiyonlarındaki (BuildMobTable / BuildItemTable) `szLocaleName` loglarını `szName` ile değiştirin veya silin.
Tüm işlemleri bitirdikten sonra tüm projeyi (Client, Server, DumpProto) "Rebuild" yapın.
Artık protos'larınızda sadece tek bir isim sütunu var!
İyi forumlar!
DB_NAME_COLUMN Sistemi Detaylı Kaldırma Rehberi
Metin2 özel sunucularında geliştirme yaparken, bazı eski sistemlerin kaldırılması veya değiştirilmesi gerekebilir. Bu rehberde, DB_NAME_COLUMN sisteminin ne olduğu, neden kaldırılması gerektiği ve bu işlemin nasıl yapıldığı detaylı olarak ele alınacaktır. Bu işlem, genellikle server-side değişikliklerle yapılır ve DB (veritabanı) üzerinde çalışmayı içerir.
DB_NAME_COLUMN Nedir?
DB_NAME_COLUMN, Metin2 sunucu yapılarında oyuncu adlarını doğrudan veritabanında belirli bir sütunda tutan eski bir yapıdır. Bu sütun genellikle 'name' olarak tanımlanır ve oyuncu kimliğiyle eşleştirilerek saklanır. Ancak bu yapı, güvenlik açısından zayıflıklar barındırabilir ve modern sistemlerde tercih edilmez.
Neden Kaldırılır?
Güvenlik endişeleri, performans optimizasyonu ve C++[/COORD] tabanlı kod düzeninin yeniden yapılandırılması gibi sebeplerle bu sütun kaldırılır. Özellikle Martysama gibi gelişmiş sistemlerde bu sütunun kullanılması önerilmez. Ayrıca, client tarafında da isim doğrulamaları farklı yöntemlerle yapılabilir hale getirilir.
Kaldırma Adımları
Adım 1: Veritabanı Yedeği Alın
Herhangi bir DB değişikliğinden önce mutlaka yedek alınmalıdır. Bu işlem, olası veri kayıplarına karşı koruma sağlar.
Adım 2: Sunucu Kodlarında DB_NAME_COLUMN Kullanımı Araştırılır
Sunucu source kodları incelenerek DB_NAME_COLUMN’a erişen tüm fonksiyonlar bulunur. Bunlar genellikle auth ve game sunucularında yer alır. Bu fonksiyonlar, yeni bir isim doğrulama mekanizmasına göre yeniden yazılmalıdır.
Adım 3: SQL Sorgusuyla Sütun Silinir
Aşağıdaki gibi bir SQL komutu ile sütun silinir:
ALTER TABLE player DROP COLUMN name;
Adım 4: Client ve Game Sunucusu Güncellenir
Oyuncu adı doğrulaması artık doğrudan veritabanında tutulan sütuna değil, packet ile gönderilen isme göre yapılır. Bu, uiscript ve py root dosyalarında da bazı değişiklikler yapılmasını gerektirebilir.
Yeni Sistemde Oyuncu Adı Doğrulaması
Client tarafından gönderilen isim, game server tarafından doğrulanır. Bu işlem, Python tabanlı sistemlerde py gui yardımıyla da desteklenebilir. Bu sayede, DB_NAME_COLUMN gibi sabit bir sütuna ihtiyaç kalmaz.
Sonuç
DB_NAME_COLUMN sistemini kaldırmak, Metin2 özel sunucularında daha modern ve güvenli bir yapıya geçiş sağlar. Bu işlem, doğru şekilde uygulandığında hem performans artışı sağlar hem de source kodların okunabilirliğini artırır. Geliştiricilerin dikkat etmesi gereken konular ise, tüm modül ve sistemlerin uyumlu çalıştığından emin olmaktır.
Detailed Guide for Removing DB_NAME_COLUMN System
In Metin2 private server development, removing or replacing certain legacy systems may become necessary. In this guide, we will detail what the DB_NAME_COLUMN system is, why it should be removed, and how to properly remove it. This process involves server-side modifications and requires working with the DB (database).
What is DB_NAME_COLUMN?
DB_NAME_COLUMN refers to an older structure in Metin2 server configurations where player names are stored directly in a specific column within the database. This column is usually named 'name', and it is associated with the player's ID. However, this structure can present security vulnerabilities and is not preferred in modern systems.
Why Should It Be Removed?
Reasons such as security concerns, performance optimization, and restructuring of C++-based codebases lead to the removal of this column. Especially in advanced systems like Martysama, using this column is not recommended. Additionally, player name validations on the client side can be handled via different methods.
Removal Steps
Step 1: Backup Database
Before making any changes to the DB, always take a backup to prevent potential data loss.
Step 2: Locate DB_NAME_COLUMN Usage in Server Code
Examine the server source code to find all functions accessing the DB_NAME_COLUMN. These are typically located in the auth and game servers and need to be rewritten according to a new name validation mechanism.
Step 3: Remove Column Using SQL Query
Remove the column using an SQL command like the following:
ALTER TABLE player DROP COLUMN name;
Step 4: Update Client and Game Servers
Player name validation now relies on the name sent via packet rather than a fixed database column. This might require changes in uiscript and py root files as well.
New Player Name Validation System
The name sent by the client is validated by the game server. This process can also be supported in Python-based systems using py gui. This eliminates the need for a fixed column like DB_NAME_COLUMN.
Conclusion
Removing the DB_NAME_COLUMN system enables more modern and secure structures in Metin2 private servers. When applied correctly, this process improves performance and enhances readability of the source code. Developers must ensure compatibility across all modules and systems.
