Python fonksiyonlarıyla oluşturulmuş aslında olmayan bir eşyayı ya da olan ama yine python fonksiyonlarıyla efsun ve taşları değiştirilmiş eşyaları yansıtmanın önüne geçmek için bir düzenleme paylaşıyorum.
Hile:
Fix:
içerisinden aşağıdaki satırı bul
yukarıdaki satırdan itibaren son return satırına kadar değiştir
* common/stl.h
Ekle:
* common/utils.h
Ekle:
* game/input_main.cpp
Arat:
Üstüne ekle:
Arat:
Değiştir:
Arat:
Altına ekle:
Arat: (CInputMain::Whisper)
Değiştir:
Arat: (CInputMain::Whisper)
Değiştir:
Arat: (CInputMain::Chat)
Değiştir:
Arat: (CInputMain::Chat)
Değiştir:
* root/uitooltip.py
Arat:
İçini değiştir:
Sahte Item Yansıtma Fixi Nedir?
Metin2 özel sunucularında karşılaşılan yaygın hatalardan birisi sahte item yansıtmasıdır. Bu durum, oyuncuların ekranda bir iteme sahipmiş gibi görünmelerine rağmen gerçek itemin sunucuda bulunmaması sonucunda ortaya çıkar. Bu yazımızda sahte item yansıtma hatasının neden oluştuğunu ve nasıl düzeltileceğini detaylıca ele alacağız.
Neden Sahte Item Yansıtması Oluşur?
Bu problem genellikle C++ tabanlı sunucu kaynak kodlarında hata meydana geldiğinde veya istemci ile sunucu arasında senkronizasyon eksikliği olduğunda ortaya çıkar. Özellikle PvP sistemlerinde, item drop sistemlerinde ya da trade işlemlerinde bu tür sorunlar sıkça rastlanabilir. Örneğin, bir oyuncu bir item satın alır ama sunucu bu işlemi doğru şekilde işleyemediğinde, istemcide item gözükürken, sunucuda item yoktur.
Fix İçin Gerekli Adımlar
Sahte item yansıtma fixi uygulamak için öncelikle sunucu tarafında item kontrol mekanizmaları güçlendirilmelidir. Bunun için game server üzerindeki item handling fonksiyonları gözden geçirilmelidir. Özellikle DB core ile bağlantılı işlemlerde hata kontrolü yapılmalıdır. Eğer bir item silinirken DB’ye yazma işlemi başarısız olursa, istemciye tekrar kontrol mesajı gönderilmelidir.
Python ve C++ Arası Senkronizasyon
Metin2 özel sunucularında hem C++ hem de Python dilleri aktif olarak kullanılır. Bu iki sistem arasında veri alışverişi sırasında hata olabilir. Py root ve client src arasındaki iletişimde, item verileri doğru şekilde eşleştirilmelidir. Python GUI üzerinden yapılan işlemlerde, sunucuya gönderilen item ID’leri doğrulanmalı ve sunucu tarafından kabul edildiğinden emin olunmalıdır.
Martysama ve Diğer Kaynak Kodlar
Bazı özel sunucular Martysama gibi modifiye kaynak kodlar kullanır. Bu tür sistemlerde item handling işlemleri değişiklik görebilir. Bu yüzden kullanılan core'a özel sahte item fixleri uygulanmalıdır. Game core kısmında item creation ve deletion süreçleri kontrol edilmeli, gerekirse loglama yapılarak hata takibi yapılmalıdır.
Sunucu Taraflı Kontroller
Oyun sunucusunda item transferleri sırasında, her işlem için checksum veya hash kontrolü yapılabilir. Bu sayede istemcide görünen item ile sunucudaki itemin birebir aynı olup olmadığı kontrol edilir. Auth ve game sunucuları arasındaki veri akışı da izlenmelidir. Özellikle trade, drop, buy/sell gibi işlemlerde sahte item oluşumu engellenmelidir.
Sonuç
Sahte item yansıtma hatası, Metin2 özel sunucularında kullanıcı deneyimini ciddi anlamda bozabilir. Bu tür hataların önlenmesi için hem sunucu hem de istemci tarafında dikkatli kontroller yapılmalıdır. C++ kaynak kod, DB core ve Python scriptlerindeki item sistemleri düzenli olarak test edilmeli ve gerekli düzeltmeler yapılmalıdır.
What Is Fake Item Rendering Fix?
One of the common errors encountered in Metin2 private servers is fake item rendering. This issue occurs when players appear to have an item on their screen, but the actual item does not exist on the server. In this article, we will examine in detail why fake item rendering happens and how to fix it.
Why Does Fake Item Rendering Occur?
This issue generally arises when there is an error in the C++ based server source code or a synchronization failure between the client and server. Such problems frequently occur in PvP systems, item drop systems, or trading operations. For example, a player might purchase an item, but if the server fails to process the transaction correctly, the item may appear on the client while it doesn't actually exist on the server.
Steps Required for the Fix
To implement a fake item rendering fix, item control mechanisms on the server side must first be strengthened. For this purpose, item handling functions on the game server should be reviewed. Error checks must be performed especially in operations connected with the DB core. If an item deletion fails to write to the database, a verification message should be sent back to the client.
Synchronization Between Python and C++
In Metin2 private servers, both C++ and Python languages are actively used. Errors may occur during data exchange between these two systems. The item data exchanged between the py root and client src must be matched correctly. When items are handled via Python GUI, the item IDs sent to the server must be validated and confirmed by the server.
Martysama and Other Source Codes
Some private servers use modified source codes like Martysama. In such systems, item handling processes can differ. Therefore, fake item fixes specific to the core being used must be applied. Item creation and deletion processes within the game core must be checked, and logging may be implemented for error tracking if necessary.
Server-Side Checks
During item transfers on the game server, checksum or hash validation can be performed for each operation. This ensures that the item visible on the client matches exactly with the one on the server. Data flow between the auth and game servers must also be monitored. Fake item generation should be prevented particularly during trading, dropping, or buying/selling operations.
Conclusion
Fake item rendering errors can significantly impact user experience in Metin2 private servers. To prevent such issues, careful checks must be conducted on both the server and client sides. Item systems in C++ source code, DB core, and Python scripts should be tested regularly and corrected as needed.
Hile:
Ziyaretçiler için gizlenmiş link,görmek için üye olmalısınız!
Giriş yap veya üye ol.
Fix:
Kod:
PyObject * playerGetItemLink(PyObject * poSelf, PyObject * poArgs)
içerisinden aşağıdaki satırı bul
Kod:
const TItemData * pPlayerItem = CPythonPlayer::Instance().GetItemData(Cell);
yukarıdaki satırdan itibaren son return satırına kadar değiştir
Kod:
CItemData* pItemData = nullptr; const auto pPlayerItem = CPythonPlayer::Instance().GetItemData(Cell); if (pPlayerItem && CItemManager::Instance().GetItemDataPointer(pPlayerItem->vnum, &pItemData)) { char szItemName[32]{ '\0' }; #ifdef ENABLE_NEW_NAME_ITEM if (!strstr(pPlayerItem->name, "^")) snprintf(szItemName, sizeof(szItemName), "%s", pPlayerItem->name); else #endif snprintf(szItemName, sizeof(szItemName), "%s", pItemData->GetName()); char szBuffer[256]{ '\0' }; snprintf(szBuffer, sizeof(szBuffer), "|cffffc700|Hnew_item:%x:%x|h[%s]|h|r", Cell.window_type, Cell.cell, szItemName); return Py_BuildValue("s", szBuffer); } return Py_BuildValue("s", "");
* common/stl.h
Ekle:
Kod:
inline std::vector <std::string> string_split_with_tokens(const std::string& str, const std::string& start_token, const std::string& end_token) { auto out = std::vector<std::string>(); std::size_t start_pos = 0; std::size_t start = str.find(start_token, start_pos); std::size_t end = str.find(end_token, start + start_token.size()); while (start != std::string::npos && end != std::string::npos) { out.emplace_back(str.substr(start, end - start + end_token.size())); start_pos = end + end_token.size(); start = str.find(start_token, start_pos); end = str.find(end_token, start + start_token.size()); } return out; }
* common/utils.h
Ekle:
Kod:
static bool is_number_hex(const char* s) { if (!s) return false; for (size_t i = 0; s[i] != '\0'; ++i) { if (!std::isxdigit(s[i])) return false; } return true; } static bool is_number_hex(const std::string& s) { return is_number_hex(s.c_str()); } inline bool str_to_hex(uint32_t& out, const char* in) { if (0 == in || 0 == in[0]) return false; out = static_cast<uint32_t>(strtoul(in, nullptr, 16)); return true; }
* game/input_main.cpp
Arat:
Kod:
int ProcessTextTag(LPCHARACTER ch, const char * c_pszText, size_t len)
Üstüne ekle:
Kod:
struct SHyperlink { uint8_t nMessagePos; std::string stOldHyperlink; std::string stNewHyperlink; }; std::vector <SHyperlink> ValidateItemHyperlinks(LPCHARACTER ch, const std::string& c_stBuffer, const uint8_t c_byHyperlinkCount, uint8_t& byrfFailStep) { if (c_stBuffer.empty() || c_byHyperlinkCount == 0) { byrfFailStep = 1; return {}; } auto vecArgs = string_split_with_tokens(c_stBuffer, "|c", "|h|r"); if (vecArgs.size() != c_byHyperlinkCount) { byrfFailStep = 2; return {}; } uint8_t nMessagePos = 0; std::vector <SHyperlink> vecHyperlinks; for (const auto& s : vecArgs) { // Sample: // "|cffffc700|Hnew_item:1:54|h[Kral Ku�a�� (ki�iye �ze)]|h|r SATILIR |cffffc700|Hnew_item:7:23|h[Ekipman Plan�]|h|r SATILIR �NCE KUMA� ALINIRRRRRRRRRRRRRR" // "|cffffc700|Hnew_item:10:20|h[Zehir Kýlýcý+9]|h|r" // Format: // |c > color start tag // ffffc700 > color code (constant value) // |H > hyperlink start tag // new_item > hyperlink type (constant value) // 10 > item window id (hex) // 20 > item slot id (hex) // |h > hyperlink end tag // [%s] > item name // |h > hyperlink end tag // |r > color end tag // Sanity checks if (s.empty()) { sys_err("Hyperlink string is empty. Full string: %s From: %s", c_stBuffer.c_str(), ch->GetName()); byrfFailStep = 3; return {}; } else if (s.front() != '|') { sys_err("Hyperlink string does not start with '|'. Full string: %s From: %s", c_stBuffer.c_str(), ch->GetName()); byrfFailStep = 4; return {}; } else if (s.substr(1, 1) != "c") { sys_err("Hyperlink string does not contain a color tag ('|c'). Full string: %s From: %s", c_stBuffer.c_str(), ch->GetName()); byrfFailStep = 5; return {}; } else if (s.find("|H") == std::string::npos) { sys_err("Hyperlink string does not contain a hyperlink start tag ('|H'). Full string: %s From: %s", c_stBuffer.c_str(), ch->GetName()); byrfFailStep = 6; return {}; } else if (s.find(":") == std::string::npos) { sys_err("Hyperlink string does not contain a colon separator (':'). Full string: %s From: %s", c_stBuffer.c_str(), ch->GetName()); byrfFailStep = 7; return {}; } else if (s.find("|h|r") == std::string::npos || s.find("|h|r") != s.size() - 4) { sys_err("Hyperlink string does not contain a hyperlink end tag ('|h'). Full string: %s From: %s", c_stBuffer.c_str(), ch->GetName()); byrfFailStep = 8; return {}; } // Validating values const auto color_code = s.substr(2, 8); if (color_code != "ffffc700") { sys_err("Color code is not 'ffffc700'. String: %s From: %s", color_code.c_str(), ch->GetName()); byrfFailStep = 9; return {}; } const auto hyperlink_type = s.substr(s.find("|H") + 2, s.find(":") - s.find("|H") - 2); if (hyperlink_type != "new_item") { sys_err("Hyperlink type is not 'new_item'. String: %s From: %s", hyperlink_type.c_str(), ch->GetName()); byrfFailStep = 10; return {}; } auto item_name = s.substr(s.find("|h") + 3, s.find("|r") - s.find("|h") - 6); if (item_name.empty()) { sys_err("Item name is empty. String: %s From: %s", s.c_str(), ch->GetName()); byrfFailStep = 11; return {}; } const auto window_id_str = s.substr(s.find(":") + 1, s.find_last_of(":") - s.find(":") - 1); const auto slot_id_str = s.substr(s.find_last_of(":") + 1, s.find("|h") - s.find_last_of(":") - 1); if (window_id_str.empty() || slot_id_str.empty()) { sys_err("Item window id or slot id is empty. String: %s From: %s", s.c_str(), ch->GetName()); byrfFailStep = 12; return {}; } else if (!is_number_hex(window_id_str) || !is_number_hex(slot_id_str)) { sys_err("Item window id or slot id is not a number. String: %s From: %s", s.c_str(), ch->GetName()); byrfFailStep = 13; return {}; } // Extracting item info uint32_t windows_id = 0, slot_id = 0; str_to_hex(windows_id, window_id_str.c_str()); str_to_hex(slot_id, slot_id_str.c_str()); SItemPos pos(windows_id, slot_id); auto item = ch->GetItem(pos); if (!item) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Item does not exist.")); // sys_err("Item does not exist. String: %s From: %s", s.c_str(), ch->GetName()); byrfFailStep = 14; return {}; } char szBuffer[1024]{ '\0' }; std::string stSockets, stAttrs; for (int i = 0; i < ITEM_SOCKET_MAX_NUM; ++i) { const auto socket = item->GetSocket(i); snprintf(szBuffer, sizeof(szBuffer), ":%x", socket); stSockets += szBuffer; } for (int i = 0; i < ITEM_ATTRIBUTE_MAX_NUM; ++i) { const auto attr = item->GetAttribute(i); snprintf(szBuffer, sizeof(szBuffer), ":%x:%d", attr.bType, attr.sValue); stAttrs += szBuffer; } char szHyperlinkBuffer[2048]{ '\0' }; snprintf(szHyperlinkBuffer, sizeof(szHyperlinkBuffer), "|c%s|Hitem:%x:%x:%s%s%s|h[%s]|h|r", color_code.c_str(), item->GetVnum(), item->GetFlag(), item_name.c_str(), stSockets.c_str(), stAttrs.c_str(), item->GetName() ); // Creating hyperlink auto link = SHyperlink(); link.nMessagePos = nMessagePos; link.stOldHyperlink = szHyperlinkBuffer; link.stNewHyperlink = s; // Adding hyperlink to the list vecHyperlinks.push_back(link); nMessagePos++; } return vecHyperlinks; }
Arat:
Kod:
int ProcessTextTag(LPCHARACTER ch, const char * c_pszText, size_t len) { int hyperlinks; bool colored; GetTextTagInfo(c_pszText, len, hyperlinks, colored);
Değiştir:
Kod:
int ProcessTextTag(LPCHARACTER ch, std::string& strfText) { int hyperlinks = 0; bool colored = false; GetTextTagInfo(strfText.c_str(), strfText.length(), hyperlinks, colored);
Arat:
Kod:
if (colored == true && hyperlinks == 0) return 4;
Altına ekle:
Kod:
if (hyperlinks > 0) { uint8_t byFailStep = 0; const auto vecHyperlinks = ValidateItemHyperlinks(ch, strfText, hyperlinks, byFailStep); if (!vecHyperlinks.empty()) { for (const auto& link : vecHyperlinks) { const auto old_link = link.stOldHyperlink; const auto new_link = link.stNewHyperlink; const auto pos = strfText.find(new_link); if (pos == std::string::npos) { sys_err("#d Old hyperlink not found in message. Old: %s New: %s From: %s", link.nMessagePos, old_link.c_str(), new_link.c_str(), ch->GetName()); return 4; } strfText.replace(pos, new_link.length(), old_link); } } else if (byFailStep && byFailStep != 14) // 14 is a special case for non-existing items, just ignore it { sys_err("Hyperlink validation failed. Step: %d String: %s From: %s", byFailStep, strfText.c_str(), ch->GetName()); return 4; } }
Arat: (CInputMain::Whisper)
Kod:
int processReturn = ProcessTextTag(ch, buf, buflen);
Değiştir:
Kod:
std::string stBuf = buf; int processReturn = ProcessTextTag(ch, stBuf);
Arat: (CInputMain::Whisper)
Kod:
tmpbuf.write(&pack, sizeof(pack)); tmpbuf.write(buf, buflen);
Değiştir:
Kod:
tmpbuf.write(&pack, sizeof(pack)); tmpbuf.write(stBuf.c_str(), stBuf.length());
Arat: (CInputMain::Chat)
Kod:
int processReturn = ProcessTextTag(ch, buf, buflen);
Değiştir:
Kod:
std::string stBuf = buf; int processReturn = ProcessTextTag(ch, stBuf);
Arat: (CInputMain::Chat)
Kod:
int len = snprintf(chatbuf, sizeof(chatbuf), "%s %s : %s", (ch->IsGM()?colorbuf[0]:colorbuf[MINMAX(0, ch->GetEmpire(), 3)]), ch->GetName(), buf); #else int len = snprintf(chatbuf, sizeof(chatbuf), "%s : %s", ch->GetName(), buf);
Değiştir:
Kod:
int len = snprintf(chatbuf, sizeof(chatbuf), "%s %s : %s", (ch->IsGM()?colorbuf[0]:colorbuf[MINMAX(0, ch->GetEmpire(), 3)]), ch->GetName(), stBuf.c_str()); #else int len = snprintf(chatbuf, sizeof(chatbuf), "%s : %s", ch->GetName(), stBuf.c_str());
* root/uitooltip.py
Arat:
Kod:
def SetHyperlinkItem(self, tokens):
İçini değiştir:
Kod:
def SetHyperlinkItem(self, tokens): defaultTokenCount = 4 #head, vnum, flag, newname minTokenCount = defaultTokenCount + player.METIN_SOCKET_MAX_NUM maxTokenCount = minTokenCount + 2 * player.ATTRIBUTE_SLOT_MAX_NUM if tokens and len(tokens) >= minTokenCount and len(tokens) <= maxTokenCount: head, vnum, flag, newname = tokens[:defaultTokenCount] newname = str(newname) itemVnum = int(vnum, 16) metinSlot = [int(metin, 16) for metin in tokens[defaultTokenCount:defaultTokenCount+player.METIN_SOCKET_MAX_NUM]] rests = tokens[defaultTokenCount+player.METIN_SOCKET_MAX_NUM:] if rests: attrSlot = [*] rests.reverse() while rests: key = int(rests.pop(), 16) if rests: val = int(rests.pop()) attrSlot.append((key, val)) attrSlot += [(0, 0)] * (player.ATTRIBUTE_SLOT_MAX_NUM - len(attrSlot)) else: attrSlot = [(0, 0)] * player.ATTRIBUTE_SLOT_MAX_NUM self.ClearToolTip() self.AddItemData(itemVnum, metinSlot, attrSlot) ItemToolTip.OnUpdate(self)
Sahte Item Yansıtma Fixi Nedir?
Metin2 özel sunucularında karşılaşılan yaygın hatalardan birisi sahte item yansıtmasıdır. Bu durum, oyuncuların ekranda bir iteme sahipmiş gibi görünmelerine rağmen gerçek itemin sunucuda bulunmaması sonucunda ortaya çıkar. Bu yazımızda sahte item yansıtma hatasının neden oluştuğunu ve nasıl düzeltileceğini detaylıca ele alacağız.
Neden Sahte Item Yansıtması Oluşur?
Bu problem genellikle C++ tabanlı sunucu kaynak kodlarında hata meydana geldiğinde veya istemci ile sunucu arasında senkronizasyon eksikliği olduğunda ortaya çıkar. Özellikle PvP sistemlerinde, item drop sistemlerinde ya da trade işlemlerinde bu tür sorunlar sıkça rastlanabilir. Örneğin, bir oyuncu bir item satın alır ama sunucu bu işlemi doğru şekilde işleyemediğinde, istemcide item gözükürken, sunucuda item yoktur.
Fix İçin Gerekli Adımlar
Sahte item yansıtma fixi uygulamak için öncelikle sunucu tarafında item kontrol mekanizmaları güçlendirilmelidir. Bunun için game server üzerindeki item handling fonksiyonları gözden geçirilmelidir. Özellikle DB core ile bağlantılı işlemlerde hata kontrolü yapılmalıdır. Eğer bir item silinirken DB’ye yazma işlemi başarısız olursa, istemciye tekrar kontrol mesajı gönderilmelidir.
Python ve C++ Arası Senkronizasyon
Metin2 özel sunucularında hem C++ hem de Python dilleri aktif olarak kullanılır. Bu iki sistem arasında veri alışverişi sırasında hata olabilir. Py root ve client src arasındaki iletişimde, item verileri doğru şekilde eşleştirilmelidir. Python GUI üzerinden yapılan işlemlerde, sunucuya gönderilen item ID’leri doğrulanmalı ve sunucu tarafından kabul edildiğinden emin olunmalıdır.
Martysama ve Diğer Kaynak Kodlar
Bazı özel sunucular Martysama gibi modifiye kaynak kodlar kullanır. Bu tür sistemlerde item handling işlemleri değişiklik görebilir. Bu yüzden kullanılan core'a özel sahte item fixleri uygulanmalıdır. Game core kısmında item creation ve deletion süreçleri kontrol edilmeli, gerekirse loglama yapılarak hata takibi yapılmalıdır.
Sunucu Taraflı Kontroller
Oyun sunucusunda item transferleri sırasında, her işlem için checksum veya hash kontrolü yapılabilir. Bu sayede istemcide görünen item ile sunucudaki itemin birebir aynı olup olmadığı kontrol edilir. Auth ve game sunucuları arasındaki veri akışı da izlenmelidir. Özellikle trade, drop, buy/sell gibi işlemlerde sahte item oluşumu engellenmelidir.
Sonuç
Sahte item yansıtma hatası, Metin2 özel sunucularında kullanıcı deneyimini ciddi anlamda bozabilir. Bu tür hataların önlenmesi için hem sunucu hem de istemci tarafında dikkatli kontroller yapılmalıdır. C++ kaynak kod, DB core ve Python scriptlerindeki item sistemleri düzenli olarak test edilmeli ve gerekli düzeltmeler yapılmalıdır.
What Is Fake Item Rendering Fix?
One of the common errors encountered in Metin2 private servers is fake item rendering. This issue occurs when players appear to have an item on their screen, but the actual item does not exist on the server. In this article, we will examine in detail why fake item rendering happens and how to fix it.
Why Does Fake Item Rendering Occur?
This issue generally arises when there is an error in the C++ based server source code or a synchronization failure between the client and server. Such problems frequently occur in PvP systems, item drop systems, or trading operations. For example, a player might purchase an item, but if the server fails to process the transaction correctly, the item may appear on the client while it doesn't actually exist on the server.
Steps Required for the Fix
To implement a fake item rendering fix, item control mechanisms on the server side must first be strengthened. For this purpose, item handling functions on the game server should be reviewed. Error checks must be performed especially in operations connected with the DB core. If an item deletion fails to write to the database, a verification message should be sent back to the client.
Synchronization Between Python and C++
In Metin2 private servers, both C++ and Python languages are actively used. Errors may occur during data exchange between these two systems. The item data exchanged between the py root and client src must be matched correctly. When items are handled via Python GUI, the item IDs sent to the server must be validated and confirmed by the server.
Martysama and Other Source Codes
Some private servers use modified source codes like Martysama. In such systems, item handling processes can differ. Therefore, fake item fixes specific to the core being used must be applied. Item creation and deletion processes within the game core must be checked, and logging may be implemented for error tracking if necessary.
Server-Side Checks
During item transfers on the game server, checksum or hash validation can be performed for each operation. This ensures that the item visible on the client matches exactly with the one on the server. Data flow between the auth and game servers must also be monitored. Fake item generation should be prevented particularly during trading, dropping, or buying/selling operations.
Conclusion
Fake item rendering errors can significantly impact user experience in Metin2 private servers. To prevent such issues, careful checks must be conducted on both the server and client sides. Item systems in C++ source code, DB core, and Python scripts should be tested regularly and corrected as needed.
