找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 88|回复: 1

[客户端] GMS083 拆分椅子img为多个小img的例子

[复制链接]

37

主题

14

回帖

170

积分

管理员

积分
170
发表于 2025-5-12 17:04:08 | 显示全部楼层 |阅读模式
原帖地址


这个例子是将原本的椅子数据从0301.img拆分为0301x.img 并让客户端正确加载,可以尽情的举一反三推导出其他的使用场景,我就不举例了。

客户端部分


  1. //#include "Global.h"
  2. #include <shlwapi.h>
  3. #pragma comment(lib, "shlwapi.lib")

  4. bool Hook_LoadLayer() {
  5.     typedef int(__fastcall* _LoadLayer)(void* ecx, void* edx, wchar_t** bsUOL, int bLeft, void* l, int* pnRepeatStartIndex);
  6.     static auto LoadLayer = reinterpret_cast<_LoadLayer>(0x00941417);

  7.     _LoadLayer Hook = [](void* ecx, void* edx, wchar_t** bsUOL, int bLeft, void* l, int* pnRepeatStartIndex) -> int {
  8.         if (StrStrW(*bsUOL, L"0301.img")) {
  9.             wchar_t* wsUOL = StrStrW(*bsUOL, L".img/") + 5;
  10.             wchar_t* wsEffect = StrStrW(wsUOL, L"/");

  11.             unsigned int uLen = lstrlenW(wsUOL) - lstrlenW(wsEffect) + 1;
  12.             wchar_t wsNewUOL[10];
  13.             StrCpyNW(wsNewUOL, wsUOL, uLen);

  14.             int nItemID = _wtoi(wsNewUOL);
  15.             int nItemType = nItemID / 1000;

  16.             wchar_t wsPath[64];
  17.             wsprintfW(wsPath, L"Item/Install/%05d.img/%08d%ws", nItemType, nItemID, wsEffect);

  18.             StrCpyW(*bsUOL, wsPath);
  19.         }

  20.         return LoadLayer(ecx, edx, bsUOL, bLeft, l, pnRepeatStartIndex);
  21.     };

  22.     return SetHook(true, reinterpret_cast<void**>(&LoadLayer), Hook);
  23. }

  24. bool Hook_GetObjectA() {
  25.     typedef void* (__fastcall* _GetObjectA)(void* ecx, void* edx, void* result, wchar_t** bsUOL, void* vParam, void* vAux);
  26.     static auto GetObjectA = reinterpret_cast<_GetObjectA>(0x00403A93);

  27.     _GetObjectA Hook = [](void* ecx, void* edx, void* result, wchar_t** bsUOL, void* vParam, void* vAux) -> void* {
  28.         if (StrStrW(*bsUOL, L"Item/")) {
  29.             wchar_t* wsCategory = StrStrW(*bsUOL, L"/00");
  30.             if (wsCategory) {
  31.                 wsCategory += 2;

  32.                 unsigned int uLen = lstrlenW(*bsUOL) - lstrlenW(wsCategory);
  33.                 wchar_t wsUOL[64];
  34.                 StrCpyNW(wsUOL, *bsUOL, uLen);
  35.                 StrCatW(wsUOL, wsCategory);
  36.                 StrCpyW(*bsUOL, wsUOL);
  37.             }
  38.         }
  39.         return GetObjectA(ecx, edx, result, bsUOL, vParam, vAux);
  40.         };

  41.     return SetHook(true, reinterpret_cast<void**>(&GetObjectA), Hook);
  42. }

  43. DWORD dwGetItemProp = 0x005D371F;
  44. void __declspec(naked) Hook_GetItemProp()
  45. {
  46.     __asm
  47.     {
  48.         cmp        esi, 3
  49.         jne        _RET
  50.         cmp        edi, 399
  51.         je        _RET

  52.         push    eax
  53.         push    ecx
  54.         push    edx

  55.         xor edx, edx
  56.         mov        eax, ebx
  57.         mov        ecx, 1000
  58.         div        ecx

  59.         mov        edi, eax

  60.         pop        edx
  61.         pop        ecx
  62.         pop        eax

  63.         _RET :
  64.         jmp    dword ptr[dwGetItemProp]
  65.     }
  66. }

  67. void Hook_Install() {
  68.     Hook_LoadLayer();
  69.     Hook_GetObjectA();
  70.     Hook(&dwGetItemProp, Hook_GetItemProp);
  71. }
复制代码


另外要修改 StringPool 中ID为2352的值

  1. Item/%s/%04d.img
复制代码

改为
  1. Item/%s/%05d.img
复制代码

因为img的文件名多了一个

然后你就可以把0301.img里的内容拆分到0301x.img中去了



服务端要修改的部分,应该是HeavenMS的端
修改src\server\MapleItemInformationProvider.java里的两个方法

  1. private MapleData getItemData(int itemId) {
  2.     MapleData ret = null;
  3.     String idStr = String.format("%08d", itemId); // e.g. 03010001
  4.     String baseImgName = idStr.substring(0, 4);   // e.g. 0301
  5.     String splitImgPrefix = idStr.substring(0, 5); // e.g. 03010

  6.     MapleDataDirectoryEntry root = itemData.getRoot();
  7.     for (MapleDataDirectoryEntry topDir : root.getSubdirectories()) {
  8.         for (MapleDataFileEntry iFile : topDir.getFiles()) {
  9.             // First: Try original format (e.g. 0301.img)
  10.             if (iFile.getName().equals(baseImgName + ".img")) {
  11.                 ret = itemData.getData(topDir.getName() + "/" + iFile.getName());
  12.                 if (ret != null) {
  13.                     MapleData child = ret.getChildByPath(idStr);
  14.                     if (child != null) {
  15.                         return child;
  16.                     }
  17.                 }
  18.             }
  19.             // Second: Try split format (e.g. 03010.img, 03011.img, etc.)
  20.             else if (iFile.getName().startsWith(splitImgPrefix)) {
  21.                 ret = itemData.getData(topDir.getName() + "/" + iFile.getName());
  22.                 if (ret != null) {
  23.                     MapleData child = ret.getChildByPath(idStr);
  24.                     if (child != null) {
  25.                         return child;
  26.                     }
  27.                     System.out.println("[WZ] Tried to load item " + itemId + " from " + iFile.getName());
  28.                 }
  29.             }
  30.         }
  31.     }

  32.     // Fallback: try equipData
  33.     root = equipData.getRoot();
  34.     for (MapleDataDirectoryEntry topDir : root.getSubdirectories()) {
  35.         for (MapleDataFileEntry iFile : topDir.getFiles()) {
  36.             if (iFile.getName().equals(idStr + ".img")) {
  37.                 return equipData.getData(topDir.getName() + "/" + iFile.getName());
  38.             }
  39.         }
  40.     }

  41.     return null;
  42. }

  43. public List<Integer> getItemIdsInRange(int minId, int maxId, boolean ignoreCashItem) {
  44.     List<Integer> list = new ArrayList<>();

  45.     for (int i = minId; i <= maxId; i++) {
  46.         if (getItemData(i) != null && (!ignoreCashItem || !isCash(i))) {
  47.             list.add(i);
  48.         }
  49.     }

  50.     return list;
  51. }
复制代码

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
有问题欢迎跟帖提问。

5

主题

15

回帖

176

积分

注册会员

积分
176
发表于 2025-5-13 22:08:23 | 显示全部楼层
沙发!顶起来支持!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|小黑屋|蘑菇物语

GMT+8, 2025-6-3 21:14 , Processed in 0.053055 second(s), 23 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表