GİRİŞ & PROBLEM
Merhaba, bugün GM komutlarının en sık kullanılanlarından birini, /set komutunu komple yenileyeceğiz. Hiçbir kontrol ve bilgilendirme içermeyen bu komuta gerekli tüm kontrolleri ekleyip, cinsiyet, karakter ve skill group değişimlerini aktif edip, kullanıcıların büyü hızını ayarlayabileceğiniz yeni bir field ekleyeceğiz.
NEDEN ?
Bunu nasıl olsa GM ekibi kullanacak, gerek yok diye düşünebilirsiniz ama oyun içindeki her yetkilinin oyun fonksiyonlarına hakim olma zorunluluğu yok, dolayısıyla amacımız işlerini mümkün olduğunca kolaylaştırmak ve yanlış bir şeyi tetikleme ihtimallerini ortadan kaldırmak.
ÇÖZÜM
Öncelikle "cmd_gm.cpp" dosyası açılır.
Merhaba, bugün GM komutlarının en sık kullanılanlarından birini, /set komutunu komple yenileyeceğiz. Hiçbir kontrol ve bilgilendirme içermeyen bu komuta gerekli tüm kontrolleri ekleyip, cinsiyet, karakter ve skill group değişimlerini aktif edip, kullanıcıların büyü hızını ayarlayabileceğiniz yeni bir field ekleyeceğiz.
NEDEN ?
Bunu nasıl olsa GM ekibi kullanacak, gerek yok diye düşünebilirsiniz ama oyun içindeki her yetkilinin oyun fonksiyonlarına hakim olma zorunluluğu yok, dolayısıyla amacımız işlerini mümkün olduğunca kolaylaştırmak ve yanlış bir şeyi tetikleme ihtimallerini ortadan kaldırmak.
ÇÖZÜM
Öncelikle "cmd_gm.cpp" dosyası açılır.
Kod:
// UYARI! ; Kodlar "Extended Max Yang" sistemine uyumludur, align bölümünde hard-coded bir kısım mevcut (maalesef) bu yüzden eğer 20.000 üstüne çıkan yeni bir alignment sistemi kullanıyorsanız lütfen o kısmı kendinize göre düzenleyin! // BULUNUR; #define MISC 0 #define BINARY 1 #define NUMBER 2 // BU DEFINE KODLARI KOMPLE SILINIR! // BULUNUR; const struct set_struct { const char* cmd; const char type; } set_fields[] = { { "gold", NUMBER }, { "race", BINARY }, { "sex", BINARY }, { "exp", NUMBER }, { "max_hp", NUMBER }, { "max_sp", NUMBER }, { "skill", NUMBER }, { "alignment", NUMBER }, { "align", NUMBER }, { "\n", MISC } }; // KOMPLE DEGISTIRILIR; const struct set_struct { const char* cmd; const char type; } set_fields[] = { { "gold", 1}, { "race", 1}, { "sex", 1}, { "exp", 1}, { "max_hp", 1}, { "max_sp", 1}, { "skill", 1}, { "castspeed", 1}, { "align", 1}, { "job", 1}, // DevFix 52 { "\n", 0} }; // BULUNUR; ACMD (do_set) // KOMPLE DEGISTIRILIR; ACMD (do_set) // DevFix 123 (Full Renewal - MT2Dev) { char arg1[256], arg2[256], arg3[256]; LPCHARACTER tch = NULL; int i, len; const char* line; line = two_arguments (argument, arg1, sizeof (arg1), arg2, sizeof (arg2)); one_argument (line, arg3, sizeof (arg3)); if (!*arg1 || !*arg2 || !*arg3) { ch->ChatPacket (CHAT_TYPE_INFO, "Usage: /set <player name> <field> <value>"); // Now it's correct.. - [MT2Dev Note] - 14/04/2024 ch->ChatPacket (CHAT_TYPE_INFO, "Fields: <gold> <race> <sex> <exp> <max_hp>"); // And some extra info about fields. - [MT2Dev Note] - 22/04/2024 ch->ChatPacket (CHAT_TYPE_INFO, " <max_sp> <skill> <castspeed> <align> <job>"); return; } tch = CHARACTER_MANAGER::instance().FindPC (arg1); if (!tch) { ch->ChatPacket (CHAT_TYPE_INFO, "<GM> %s not exist!", arg1); return; } len = strlen (arg2); for (i = 0; * (set_fields[i].cmd) != '\n'; i++) { if (!strncmp (arg2, set_fields[i].cmd, len)) { break; } } switch (i) { case 0: // Gold { long long int gold = 0; str_to_number (gold, arg3); gold = MINMAX (-GOLD_MAX, gold, GOLD_MAX); DBManager::instance().SendMoneyLog (MONEY_LOG_MISC, 3, gold); tch->PointChange (POINT_GOLD, gold, true); long long int after_gold = tch->GetGold(); if (after_gold < 0) { tch->PointChange (POINT_GOLD, -after_gold, true); after_gold = 0; tch->ChatPacket (CHAT_TYPE_INFO, "<GM> You're yang has been change with minimum value!"); } else if (after_gold > GOLD_MAX) { long long int difference = after_gold - GOLD_MAX; tch->PointChange (POINT_GOLD, -difference, true); after_gold = GOLD_MAX; tch->ChatPacket (CHAT_TYPE_INFO, "<GM> You're yang has been change with maximum value!"); } else { tch->ChatPacket (CHAT_TYPE_INFO, "<GM> You're yang has been change successfully!"); } } // Also useless log removed by me. - [MT2Dev Note] - 19/04/2024 break; case 1: // Race { // DevFix 52 unsigned char amount = 0; // DevFix 122 str_to_number (amount, arg3); amount = MINMAX (0, amount, JOB_MAX_NUM); ESex mySex = GET_SEX (tch); DWORD dwRace; switch (amount) { case JOB_WARRIOR: dwRace = (mySex == SEX_MALE) ? MAIN_RACE_WARRIOR_M : MAIN_RACE_WARRIOR_W; break; case JOB_ASSASSIN: dwRace = (mySex == SEX_MALE) ? MAIN_RACE_ASSASSIN_M : MAIN_RACE_ASSASSIN_W; break; case JOB_SURA: dwRace = (mySex == SEX_MALE) ? MAIN_RACE_SURA_M : MAIN_RACE_SURA_W; break; case JOB_SHAMAN: dwRace = (mySex == SEX_MALE) ? MAIN_RACE_SHAMAN_M : MAIN_RACE_SHAMAN_W; break; } if (dwRace != tch->GetRaceNum()) { tch->SetRace (dwRace); tch->ClearSkill(); tch->SetSkillGroup (0); tch->SetPolymorph (101); tch->SetPolymorph (0); tch->ChatPacket (CHAT_TYPE_INFO, "<GM> You're race has been change successfully!"); } } break; case 2: // Sex { // DevFix 52 unsigned char amount = 0; // DevFix 122 str_to_number (amount, arg3); amount = MINMAX (SEX_MALE, amount, SEX_FEMALE); if (amount != GET_SEX (tch)) { tch->ChangeSex(); tch->SetPolymorph (101); tch->SetPolymorph (0); tch->ChatPacket (CHAT_TYPE_INFO, "<GM> You're sex has been change successfully!"); } } break; case 3: // Exp { int amount = 0; str_to_number (amount, arg3); amount = MINMAX (-2050000000, amount, 2050000000); // It's hard-coded(i hate it for sure but we don't need to worry about this for now {because of the int limitations and 1-99 limit}) from exp_table_common.. - [MT2Dev Note] - 21/04/2024 int before_exp = tch->GetExp(); if (before_exp + amount >= 0) { tch->PointChange (POINT_EXP, amount, true); tch->ChatPacket (CHAT_TYPE_INFO, "<GM> You're EXP has been change successfully!"); } else { ch->ChatPacket (CHAT_TYPE_INFO, "<GM Control> Players minimum EXP cannot be under 0!"); } } break; case 4: // Max HP { int amount = 0; str_to_number (amount, arg3); amount = MINMAX (-10000000, amount, 10000000); // 10M is enough for the Max HP i guess, so it's hard-coded(and i hate it x2 -_-) .. - [MT2Dev Note] - 21/04/2024 int before_hp = tch->GetMaxHP(); if (before_hp + amount >= 1000) { tch->PointChange (POINT_MAX_HP, amount, true); tch->ChatPacket (CHAT_TYPE_INFO, "<GM> You're Max HP has been change successfully!"); } else { ch->ChatPacket (CHAT_TYPE_INFO, "<GM Control> Players Max HP cannot be under 1000!"); } } break; case 5: // Max SP { int amount = 0; str_to_number (amount, arg3); amount = MINMAX (-10000000, amount, 10000000); // 10M is enough for the Max SP i guess, so it's hard-coded(and i hate it x3 -_-) .. - [MT2Dev Note] - 21/04/2024 int before_sp = tch->GetMaxSP(); if (before_sp + amount >= 600) { tch->PointChange (POINT_MAX_SP, amount, true); tch->ChatPacket (CHAT_TYPE_INFO, "<GM> You're Max SP has been change successfully!"); } else { ch->ChatPacket (CHAT_TYPE_INFO, "<GM Control> Players Max SP cannot be under 600!"); } } break; case 6: // Active Skill Point { short int amount = 0; // DevFix 122 str_to_number (amount, arg3); amount = MINMAX (-180, amount, 180); // For possible 9 Skill (Yohara Extension) system, it's hard-coded with 180(and i hate it x4 -_-) .. - [MT2Dev Note] - 21/04/2024 short int before_skillpoint = tch->GetPoint (POINT_SKILL); if (before_skillpoint + amount >= 0) { tch->PointChange (POINT_SKILL, amount, true); tch->ChatPacket (CHAT_TYPE_INFO, "<GM> You're Skill Points has been change successfully!"); } else { ch->ChatPacket (CHAT_TYPE_INFO, "<GM Control> Players skill points cannot be under 0!"); } } break; case 7: // Casting Speed { short int amount = 0; str_to_number (amount, arg3); amount = MINMAX (-30000, amount, 30000); // It's also hard-coded but this one not give us any trouble in the future.. - [MT2Dev Note] - 22/04/2024 short int before_castspeed = tch->GetPoint (POINT_CASTING_SPEED); if (before_castspeed + amount >= 0) { tch->PointChange (POINT_CASTING_SPEED, amount, true); tch->ChatPacket (CHAT_TYPE_INFO, "<GM> You're Casting Speed has been change successfully!"); } else { ch->ChatPacket (CHAT_TYPE_INFO, "<GM Control> Players Casting Speed cannot be under 0!"); } } break; case 8: // Align { int amount = 0; str_to_number (amount, arg3); amount = MINMAX (-200000, amount, 200000); // I hate hard-code, did i tell u before ? *_* Change this if you have different system.. - [MT2Dev Note] - 23/04/2024 tch->UpdateAlignment (amount - ch->GetRealAlignment()); int after_align = tch->GetRealAlignment(); if (after_align < -200000) // If players final align < -20.000 (MAX value for original codes) - [MT2Dev Note] - 21/04/2024 { tch->UpdateAlignment (-200000); tch->ChatPacket (CHAT_TYPE_INFO, "<GM> You're alignment has been change with minimum value!"); } else if (after_align > 200000) // If players final align > 20.000 (MAX value for original codes) - [MT2Dev Note] - 21/04/2024 { tch->UpdateAlignment (200000); tch->ChatPacket (CHAT_TYPE_INFO, "<GM> You're alignment has been change with maximum value!"); } else { tch->ChatPacket (CHAT_TYPE_INFO, "<GM> You're alignment has been change successfully!"); } } break; case 9: // Job { unsigned char amount = 0; // DevFix 122 str_to_number (amount, arg3); amount = MINMAX (0, amount, 2); if (amount != tch->GetSkillGroup()) { tch->ClearSkill(); tch->SetSkillGroup (amount); tch->ChatPacket (CHAT_TYPE_INFO, "<GM> You're skill group has been change successfully!"); } } break; } if (set_fields[i].type == 1) { int amount = 0; str_to_number (amount, arg3); ch->ChatPacket (CHAT_TYPE_INFO, "<GM> %s's %s set to [%d]", tch->GetName(), set_fields[i].cmd, amount); } }
C++ ile Metin2 Sunucusunda GM Yetkililer İçin /set Komutu Yenileme Sistemi
Metin2 özel sunucularında yetkili oyuncuların (GM) belirli ayarlamaları hızlıca yapabilmesi için özel komutlar oldukça önemlidir. Bu yazıda, C++ tabanlı bir Metin2 sunucu yapısında GM yetkililerin kullanabileceği /set komutunu yenileme sistemini ele alacağız. Bu komut sayesinde yetkililer, oyuncuların bazı parametrelerini veya sunucudaki bazı sistem ayarlarını anlık olarak değiştirebilir. Bu tür sistemler, hem sunucu yönetimini kolaylaştırır hem de deneyimli geliştiriciler için harika bir öğrenme alanıdır.
Neden /set Komutu Gerekli?
Metin2 özel sunucularında, geliştiriciler genellikle oyuncuların seviye, stat, item gibi verilerini test etmek veya sunucu üzerinde hızlı müdahaleler yapabilmek için GM yetkisi olan hesaplar kullanırlar. /set komutu, bu yetkilere belirli değerleri doğrudan komutla atama imkanı sunar. Örneğin, bir GM belirli bir oyuncunun seviyesini veya can miktarını anında değiştirebilir. Ancak bu komut, güvenlik ve performans açısından doğru bir şekilde yapılandırılmalıdır.
Komutun Güvenlik Zafiyetlerine Dikkat
Yanlış yapılandırılmış bir /set komutu, sunucu güvenliği için ciddi riskler taşır. Oyuncular bu komutu kötüye kullanabilir veya yetkisiz erişimlerle sunucuya zarar verebilir. Bu nedenle, komutun sadece yetkili kullanıcılar tarafından kullanılması sağlanmalıdır. Ayrıca, komutun işlediği verilerin sınırlarını belirlemek de önemlidir. Örneğin, seviye 10000 gibi abartılı bir değerin atanmasını engellemek için kontrol mekanizmaları konulmalıdır.
C++ Kaynak Kodunda /set Komutu Nasıl Eklenir?
C++ tabanlı Metin2 sunucu kaynak kodlarında, komutlar genellikle input_main.cpp veya benzeri dosyalarda tanımlanır. /set komutu için bir fonksiyon oluşturulmalı ve bu fonksiyon, gelen argümanları analiz edip uygun değişiklikleri yapmalıdır. Örnek olarak, aşağıdaki gibi bir yapı kullanılabilir:
Kod:
[BR][/BR]void SetCommand(LPCHARACTER ch, const char* arg) { [BR][/BR] if (!ch->IsGM()) return; // Sadece GM'ler kullanabilir[BR][/BR] // Argümanları ayır ve işlem yap[BR][/BR]}
Bu yapı sayesinde, komutun yetki kontrolleri sağlanmış olur ve daha güvenli bir kullanım ortamı yaratılır.
Sistem Geliştirme ve Test Süreci
Komutun geliştirilmesi ardından, bu komutun test edilmesi gerekir. Geliştiriciler, farklı senaryolarda komutun nasıl davrandığını gözlemlemeli ve olası hataları düzeltmelidir. Özellikle veri sınırlarının kontrol edilmesi, sistem stabilitesi açısından kritik öneme sahiptir. Ayrıca, loglama sistemiyle komutun ne zaman hangi kullanıcı tarafından kullanıldığı da takip edilebilir.
Sonuç
/set komutu, Metin2 özel sunucularında GM yetkililer için oldukça faydalı bir özelliktir. Ancak dikkatli planlama ve güvenli kodlama ile uygulanmalıdır. C++ tabanlı sistemlerde bu komutun doğru şekilde entegrasyonu, hem geliştiricilerin hem de yetkililerin işini kolaylaştırır. Bu tarz sistemlerin geliştirilmesi, Metin2 geliştirme dünyasında önemli bir yer tutmaktadır.
Renewing the /set Command for GMs with C++ in Metin2 Servers
In private Metin2 servers, special commands are essential for administrators (GMs) to make quick adjustments. This article focuses on the renewal of the /set command for GMs within a C++-based Metin2 server structure. With this command, administrators can instantly change certain player attributes or server settings. Such systems simplify server management and provide an excellent learning platform for experienced developers.
Why Is the /set Command Necessary?
On Metin2 private servers, developers often use GM accounts to test player levels, stats, items, etc., or to quickly adjust server settings. The /set command allows these privileged users to directly assign specific values via commands. For example, a GM can instantly modify a player’s level or health amount. However, this command must be properly configured for security and performance reasons.
Security Risks of Improperly Configured Commands
An incorrectly structured /set command can pose serious security risks to the server. Players may misuse the command or gain unauthorized access, potentially harming the server. Therefore, it’s crucial to ensure that only authorized users can execute the command. Additionally, setting boundaries for processed data is important. For instance, control mechanisms should prevent assigning excessively high values like level 10000.
How to Add the /set Command in C++ Source Code?
In C++-based Metin2 server source codes, commands are typically defined in files such as input_main.cpp. A function must be created for the /set command that parses incoming arguments and applies the appropriate changes. An example structure might look like this:
Kod:
[BR][/BR]void SetCommand(LPCHARACTER ch, const char* arg) { [BR][/BR] if (!ch->IsGM()) return; // Only GMs can use it[BR][/BR] // Parse arguments and apply changes[BR][/BR]}
With this structure, authority checks for the command are ensured, creating a more secure environment.
System Development and Testing Process
After developing the command, thorough testing is required. Developers should observe how the command behaves under various scenarios and correct any potential errors. Particularly, verifying data limits is critical for system stability. Additionally, logging systems can track when and by whom the command was used.
Conclusion
The /set command is highly useful for GMs on Metin2 private servers. However, it must be implemented carefully with attention to planning and secure coding. Proper integration of this command in C++-based systems simplifies tasks for both developers and administrators. Developing such systems holds significant importance in the world of Metin2 development.
