GMS083 拆分椅子img为多个小img的例子
原帖地址这个例子是将原本的椅子数据从0301.img拆分为0301x.img 并让客户端正确加载,可以尽情的举一反三推导出其他的使用场景,我就不举例了。
客户端部分
//#include "Global.h"
#include <shlwapi.h>
#pragma comment(lib, "shlwapi.lib")
bool Hook_LoadLayer() {
typedef int(__fastcall* _LoadLayer)(void* ecx, void* edx, wchar_t** bsUOL, int bLeft, void* l, int* pnRepeatStartIndex);
static auto LoadLayer = reinterpret_cast<_LoadLayer>(0x00941417);
_LoadLayer Hook = [](void* ecx, void* edx, wchar_t** bsUOL, int bLeft, void* l, int* pnRepeatStartIndex) -> int {
if (StrStrW(*bsUOL, L"0301.img")) {
wchar_t* wsUOL = StrStrW(*bsUOL, L".img/") + 5;
wchar_t* wsEffect = StrStrW(wsUOL, L"/");
unsigned int uLen = lstrlenW(wsUOL) - lstrlenW(wsEffect) + 1;
wchar_t wsNewUOL;
StrCpyNW(wsNewUOL, wsUOL, uLen);
int nItemID = _wtoi(wsNewUOL);
int nItemType = nItemID / 1000;
wchar_t wsPath;
wsprintfW(wsPath, L"Item/Install/%05d.img/%08d%ws", nItemType, nItemID, wsEffect);
StrCpyW(*bsUOL, wsPath);
}
return LoadLayer(ecx, edx, bsUOL, bLeft, l, pnRepeatStartIndex);
};
return SetHook(true, reinterpret_cast<void**>(&LoadLayer), Hook);
}
bool Hook_GetObjectA() {
typedef void* (__fastcall* _GetObjectA)(void* ecx, void* edx, void* result, wchar_t** bsUOL, void* vParam, void* vAux);
static auto GetObjectA = reinterpret_cast<_GetObjectA>(0x00403A93);
_GetObjectA Hook = [](void* ecx, void* edx, void* result, wchar_t** bsUOL, void* vParam, void* vAux) -> void* {
if (StrStrW(*bsUOL, L"Item/")) {
wchar_t* wsCategory = StrStrW(*bsUOL, L"/00");
if (wsCategory) {
wsCategory += 2;
unsigned int uLen = lstrlenW(*bsUOL) - lstrlenW(wsCategory);
wchar_t wsUOL;
StrCpyNW(wsUOL, *bsUOL, uLen);
StrCatW(wsUOL, wsCategory);
StrCpyW(*bsUOL, wsUOL);
}
}
return GetObjectA(ecx, edx, result, bsUOL, vParam, vAux);
};
return SetHook(true, reinterpret_cast<void**>(&GetObjectA), Hook);
}
DWORD dwGetItemProp = 0x005D371F;
void __declspec(naked) Hook_GetItemProp()
{
__asm
{
cmp esi, 3
jne _RET
cmp edi, 399
je _RET
push eax
push ecx
push edx
xor edx, edx
mov eax, ebx
mov ecx, 1000
div ecx
mov edi, eax
pop edx
pop ecx
pop eax
_RET :
jmp dword ptr
}
}
void Hook_Install() {
Hook_LoadLayer();
Hook_GetObjectA();
Hook(&dwGetItemProp, Hook_GetItemProp);
}
另外要修改 StringPool 中ID为2352的值
由
Item/%s/%04d.img
改为
Item/%s/%05d.img
因为img的文件名多了一个
然后你就可以把0301.img里的内容拆分到0301x.img中去了
服务端要修改的部分,应该是HeavenMS的端
修改src\server\MapleItemInformationProvider.java里的两个方法
private MapleData getItemData(int itemId) {
MapleData ret = null;
String idStr = String.format("%08d", itemId); // e.g. 03010001
String baseImgName = idStr.substring(0, 4); // e.g. 0301
String splitImgPrefix = idStr.substring(0, 5); // e.g. 03010
MapleDataDirectoryEntry root = itemData.getRoot();
for (MapleDataDirectoryEntry topDir : root.getSubdirectories()) {
for (MapleDataFileEntry iFile : topDir.getFiles()) {
// First: Try original format (e.g. 0301.img)
if (iFile.getName().equals(baseImgName + ".img")) {
ret = itemData.getData(topDir.getName() + "/" + iFile.getName());
if (ret != null) {
MapleData child = ret.getChildByPath(idStr);
if (child != null) {
return child;
}
}
}
// Second: Try split format (e.g. 03010.img, 03011.img, etc.)
else if (iFile.getName().startsWith(splitImgPrefix)) {
ret = itemData.getData(topDir.getName() + "/" + iFile.getName());
if (ret != null) {
MapleData child = ret.getChildByPath(idStr);
if (child != null) {
return child;
}
System.out.println(" Tried to load item " + itemId + " from " + iFile.getName());
}
}
}
}
// Fallback: try equipData
root = equipData.getRoot();
for (MapleDataDirectoryEntry topDir : root.getSubdirectories()) {
for (MapleDataFileEntry iFile : topDir.getFiles()) {
if (iFile.getName().equals(idStr + ".img")) {
return equipData.getData(topDir.getName() + "/" + iFile.getName());
}
}
}
return null;
}
public List<Integer> getItemIdsInRange(int minId, int maxId, boolean ignoreCashItem) {
List<Integer> list = new ArrayList<>();
for (int i = minId; i <= maxId; i++) {
if (getItemData(i) != null && (!ignoreCashItem || !isCash(i))) {
list.add(i);
}
}
return list;
}
沙发!顶起来支持!
页:
[1]