forked from metin-server/m2dev-client-src
ML-Client: Item Names client sided
This commit is contained in:
@@ -298,6 +298,8 @@ enum
|
|||||||
HEADER_GC_DRAGON_SOUL_REFINE = 209,
|
HEADER_GC_DRAGON_SOUL_REFINE = 209,
|
||||||
HEADER_GC_RESPOND_CHANNELSTATUS = 210,
|
HEADER_GC_RESPOND_CHANNELSTATUS = 210,
|
||||||
|
|
||||||
|
HEADER_GC_ITEM_GET = 211,
|
||||||
|
|
||||||
HEADER_GC_KEY_AGREEMENT_COMPLETED = 0xfa, // _IMPROVED_PACKET_ENCRYPTION_
|
HEADER_GC_KEY_AGREEMENT_COMPLETED = 0xfa, // _IMPROVED_PACKET_ENCRYPTION_
|
||||||
HEADER_GC_KEY_AGREEMENT = 0xfb, // _IMPROVED_PACKET_ENCRYPTION_
|
HEADER_GC_KEY_AGREEMENT = 0xfb, // _IMPROVED_PACKET_ENCRYPTION_
|
||||||
HEADER_GC_HANDSHAKE_OK = 0xfc, // 252
|
HEADER_GC_HANDSHAKE_OK = 0xfc, // 252
|
||||||
@@ -1630,6 +1632,15 @@ typedef struct packet_set_item
|
|||||||
TPlayerItemAttribute aAttr[ITEM_ATTRIBUTE_SLOT_MAX_NUM];
|
TPlayerItemAttribute aAttr[ITEM_ATTRIBUTE_SLOT_MAX_NUM];
|
||||||
} TPacketGCItemSet;
|
} TPacketGCItemSet;
|
||||||
|
|
||||||
|
typedef struct packet_item_get
|
||||||
|
{
|
||||||
|
uint8_t header;
|
||||||
|
uint32_t dwItemVnum;
|
||||||
|
uint8_t bCount;
|
||||||
|
uint8_t bArg; // 0: normal, 1: from party member
|
||||||
|
char szFromName[CHARACTER_NAME_MAX_LEN + 1];
|
||||||
|
} TPacketGCItemGet;
|
||||||
|
|
||||||
typedef struct packet_use_item
|
typedef struct packet_use_item
|
||||||
{
|
{
|
||||||
uint8_t header;
|
uint8_t header;
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ class CMainPacketHeaderMap : public CNetworkPacketHeaderMap
|
|||||||
|
|
||||||
Set(HEADER_GC_ITEM_DEL, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketGCItemDel), STATIC_SIZE_PACKET));
|
Set(HEADER_GC_ITEM_DEL, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketGCItemDel), STATIC_SIZE_PACKET));
|
||||||
Set(HEADER_GC_ITEM_SET, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketGCItemSet), STATIC_SIZE_PACKET));
|
Set(HEADER_GC_ITEM_SET, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketGCItemSet), STATIC_SIZE_PACKET));
|
||||||
|
Set(HEADER_GC_ITEM_GET, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketGCItemGet), STATIC_SIZE_PACKET));
|
||||||
|
|
||||||
Set(HEADER_GC_ITEM_USE, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketGCItemUse), STATIC_SIZE_PACKET));
|
Set(HEADER_GC_ITEM_USE, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketGCItemUse), STATIC_SIZE_PACKET));
|
||||||
Set(HEADER_GC_ITEM_UPDATE, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketGCItemUpdate), STATIC_SIZE_PACKET));
|
Set(HEADER_GC_ITEM_UPDATE, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketGCItemUpdate), STATIC_SIZE_PACKET));
|
||||||
|
|||||||
@@ -447,6 +447,7 @@ class CPythonNetworkStream : public CNetworkStream, public CSingleton<CPythonNet
|
|||||||
|
|
||||||
bool RecvItemDelPacket(); // Alarm to python
|
bool RecvItemDelPacket(); // Alarm to python
|
||||||
bool RecvItemSetPacket(); // Alarm to python
|
bool RecvItemSetPacket(); // Alarm to python
|
||||||
|
bool RecvItemGetPacket(); // Alarm to python
|
||||||
bool RecvItemUsePacket(); // Alarm to python
|
bool RecvItemUsePacket(); // Alarm to python
|
||||||
bool RecvItemUpdatePacket(); // Alarm to python
|
bool RecvItemUpdatePacket(); // Alarm to python
|
||||||
bool RecvItemGroundAddPacket();
|
bool RecvItemGroundAddPacket();
|
||||||
@@ -604,6 +605,7 @@ class CPythonNetworkStream : public CNetworkStream, public CSingleton<CPythonNet
|
|||||||
void __RecvCharacterUpdatePacket(SNetworkUpdateActorData * pkNetUpdateActorData);
|
void __RecvCharacterUpdatePacket(SNetworkUpdateActorData * pkNetUpdateActorData);
|
||||||
|
|
||||||
void __FilterInsult(char* szLine, UINT uLineLen);
|
void __FilterInsult(char* szLine, UINT uLineLen);
|
||||||
|
void __LocalizeItemLinks(char* buf, size_t bufSize);
|
||||||
|
|
||||||
void __SetGuildID(DWORD id);
|
void __SetGuildID(DWORD id);
|
||||||
|
|
||||||
|
|||||||
@@ -320,6 +320,10 @@ void CPythonNetworkStream::GamePhase()
|
|||||||
ret = RecvItemSetPacket();
|
ret = RecvItemSetPacket();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case HEADER_GC_ITEM_GET:
|
||||||
|
ret = RecvItemGetPacket();
|
||||||
|
break;
|
||||||
|
|
||||||
case HEADER_GC_ITEM_USE:
|
case HEADER_GC_ITEM_USE:
|
||||||
ret = RecvItemUsePacket();
|
ret = RecvItemUsePacket();
|
||||||
break;
|
break;
|
||||||
@@ -1293,6 +1297,111 @@ void CPythonNetworkStream::__ConvertEmpireText(DWORD dwEmpireID, char* szText)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CPythonNetworkStream::__LocalizeItemLinks(char* buf, size_t bufSize)
|
||||||
|
{
|
||||||
|
// Replace item names in hyperlinks with client-side localized names
|
||||||
|
// Format: |Hitem:VNUM:flags:socket0:socket1:socket2...|h[ItemName]|h
|
||||||
|
|
||||||
|
// Early exit: skip processing if no item links exist
|
||||||
|
if (!strstr(buf, "|Hitem:"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
char* pSearch = buf;
|
||||||
|
char result[2048];
|
||||||
|
char* pResult = result;
|
||||||
|
char* pResultEnd = result + sizeof(result) - 1;
|
||||||
|
|
||||||
|
while (*pSearch && pResult < pResultEnd)
|
||||||
|
{
|
||||||
|
// Look for |Hitem:
|
||||||
|
if (strncmp(pSearch, "|Hitem:", 7) == 0)
|
||||||
|
{
|
||||||
|
char* pLinkStart = pSearch;
|
||||||
|
pSearch += 7;
|
||||||
|
|
||||||
|
// Extract vnum (first hex value after "item:")
|
||||||
|
DWORD dwVnum = 0;
|
||||||
|
while (*pSearch && *pSearch != ':' && *pSearch != '|')
|
||||||
|
{
|
||||||
|
if (*pSearch >= '0' && *pSearch <= '9')
|
||||||
|
dwVnum = dwVnum * 16 + (*pSearch - '0');
|
||||||
|
else if (*pSearch >= 'a' && *pSearch <= 'f')
|
||||||
|
dwVnum = dwVnum * 16 + (*pSearch - 'a' + 10);
|
||||||
|
else if (*pSearch >= 'A' && *pSearch <= 'F')
|
||||||
|
dwVnum = dwVnum * 16 + (*pSearch - 'A' + 10);
|
||||||
|
pSearch++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find |h[ which marks the start of the item name
|
||||||
|
char* pNameStart = strstr(pSearch, "|h[");
|
||||||
|
if (pNameStart)
|
||||||
|
{
|
||||||
|
pNameStart += 3; // Skip "|h["
|
||||||
|
|
||||||
|
// Find ]|h which marks the end of the item name
|
||||||
|
char* pNameEnd = strstr(pNameStart, "]|h");
|
||||||
|
if (pNameEnd)
|
||||||
|
{
|
||||||
|
// Get the client-side item name
|
||||||
|
CItemData* pItemData;
|
||||||
|
const char* szLocalName = NULL;
|
||||||
|
if (CItemManager::Instance().GetItemDataPointer(dwVnum, &pItemData))
|
||||||
|
szLocalName = pItemData->GetName();
|
||||||
|
|
||||||
|
// Copy everything from link start to |h[
|
||||||
|
size_t copyLen = pNameStart - pLinkStart;
|
||||||
|
if (pResult + copyLen < pResultEnd)
|
||||||
|
{
|
||||||
|
memcpy(pResult, pLinkStart, copyLen);
|
||||||
|
pResult += copyLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert the localized name (or original if not found)
|
||||||
|
const char* szName = szLocalName ? szLocalName : pNameStart;
|
||||||
|
size_t nameLen = szLocalName ? strlen(szLocalName) : (pNameEnd - pNameStart);
|
||||||
|
if (pResult + nameLen < pResultEnd)
|
||||||
|
{
|
||||||
|
if (szLocalName)
|
||||||
|
{
|
||||||
|
memcpy(pResult, szLocalName, nameLen);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy(pResult, pNameStart, nameLen);
|
||||||
|
}
|
||||||
|
pResult += nameLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy ]|h
|
||||||
|
if (pResult + 3 < pResultEnd)
|
||||||
|
{
|
||||||
|
memcpy(pResult, "]|h", 3);
|
||||||
|
pResult += 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
pSearch = pNameEnd + 3; // Skip past ]|h
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we couldn't parse properly, just copy the character and continue
|
||||||
|
if (pResult < pResultEnd)
|
||||||
|
*pResult++ = *pLinkStart;
|
||||||
|
pSearch = pLinkStart + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (pResult < pResultEnd)
|
||||||
|
*pResult++ = *pSearch;
|
||||||
|
pSearch++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*pResult = '\0';
|
||||||
|
|
||||||
|
strncpy(buf, result, bufSize - 1);
|
||||||
|
buf[bufSize - 1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
bool CPythonNetworkStream::RecvChatPacket()
|
bool CPythonNetworkStream::RecvChatPacket()
|
||||||
{
|
{
|
||||||
TPacketGCChat kChat;
|
TPacketGCChat kChat;
|
||||||
@@ -1309,6 +1418,9 @@ bool CPythonNetworkStream::RecvChatPacket()
|
|||||||
|
|
||||||
buf[uChatSize]='\0';
|
buf[uChatSize]='\0';
|
||||||
|
|
||||||
|
// Localize item names in hyperlinks for multi-language support
|
||||||
|
__LocalizeItemLinks(buf, sizeof(buf));
|
||||||
|
|
||||||
if (kChat.type >= CHAT_TYPE_MAX_NUM)
|
if (kChat.type >= CHAT_TYPE_MAX_NUM)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "PythonCharacterManager.h"
|
#include "PythonCharacterManager.h"
|
||||||
|
|
||||||
#include "AbstractPlayer.h"
|
#include "AbstractPlayer.h"
|
||||||
|
#include "GameLib/ItemManager.h"
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
// SafeBox
|
// SafeBox
|
||||||
@@ -254,6 +255,40 @@ bool CPythonNetworkStream::RecvItemSetPacket()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CPythonNetworkStream::RecvItemGetPacket()
|
||||||
|
{
|
||||||
|
TPacketGCItemGet packet;
|
||||||
|
if (!Recv(sizeof(TPacketGCItemGet), &packet))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
CItemData* pItemData;
|
||||||
|
if (!CItemManager::Instance().GetItemDataPointer(packet.dwItemVnum, &pItemData))
|
||||||
|
{
|
||||||
|
TraceError("CPythonNetworkStream::RecvItemGetPacket - Unknown item vnum %u", packet.dwItemVnum);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packet.bArg == 0)
|
||||||
|
{
|
||||||
|
// Normal pickup
|
||||||
|
PyCallClassMemberFunc(m_apoPhaseWnd[PHASE_WINDOW_GAME], "BINARY_ItemGet",
|
||||||
|
Py_BuildValue("(si)", pItemData->GetName(), packet.bCount));
|
||||||
|
}
|
||||||
|
else if (packet.bArg == 1)
|
||||||
|
{
|
||||||
|
// Received from party member
|
||||||
|
PyCallClassMemberFunc(m_apoPhaseWnd[PHASE_WINDOW_GAME], "BINARY_ItemGetFromParty",
|
||||||
|
Py_BuildValue("(ssi)", pItemData->GetName(), packet.szFromName, packet.bCount));
|
||||||
|
}
|
||||||
|
else if (packet.bArg == 2)
|
||||||
|
{
|
||||||
|
// Delivered to party member
|
||||||
|
PyCallClassMemberFunc(m_apoPhaseWnd[PHASE_WINDOW_GAME], "BINARY_ItemDeliverToParty",
|
||||||
|
Py_BuildValue("(ssi)", pItemData->GetName(), packet.szFromName, packet.bCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool CPythonNetworkStream::RecvItemUsePacket()
|
bool CPythonNetworkStream::RecvItemUsePacket()
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user