PacketEntitiesFix
16-04-2014, 04:34
Описание:
Данный метамод плагин фиксит баг с частично неправильной в некоторых случаях отсылкой полей в Svc_PacketEntities.
Например, это могло повлечь к "подскакиванию" игроков при записи демо.
Представлена только linux версия.
Авторы: [WPMG]PRoSToTeM@, Lev
Версия: 0.0.1
Установка:
Распаковать в папку с модом, добавить в plugins.ini из metamod:
linux addons/PacketEntitiesFix/PacketEntitiesFix.so
Также имеется возможность подгрузки в режиме "онлайн":
meta load addons/PacketEntitiesFix/PacketEntitiesFix.so
C++ код
#include <extdll.h>
#include <meta_api.h>
#include <sys/mman.h>
#ifndef PAGE_SIZE
#define PAGE_SIZE 4096
#endif
#define BIT(n) (1<<(n))
#define DT_BYTE BIT(0)
#define DT_SHORT BIT(1)
#define DT_SIGNED BIT(31)
#define DT_SEND BIT(0)
struct delta_t
{
int m_iFieldType;
byte dontneed[32];
int m_iOffset;
byte dontneed0[16];
byte m_iFlags;
byte dontneed1[8];
};
struct delta_info_t
{
byte dontneed[4];
int m_iFieldsCount;
byte dontneed0[36];
delta_t *m_pFields;
};
#define OPCODE_JMPNEAR 0xE9
#pragma pack(push, 1)
struct jmpnear_t {
byte m_bOpcode;
void *m_pAddr;
};
#pragma pack(pop)
struct hook_t {
void *m_pfnOriginal;
byte m_rgbOriginalBytes[sizeof(jmpnear_t)];
jmpnear_t m_jmpnearBytes;
};
meta_globals_t *gpMetaGlobals;
gamedll_funcs_t *gpGamedllFuncs;
mutil_funcs_t *gpMetaUtilFuncs;
enginefuncs_t g_engfuncs;
globalvars_t *gpGlobals;
typedef void (DELTA_MARKSENDFIELDS)(void *, void *, delta_info_t *);
typedef void (SV_CREATEPACKETENTITIES)(int, void *, void *, void *);
hook_t *g_phookDeltaMarkSendFields;
hook_t *g_phookSvCreatePacketEntities;
void *g_pEngineHandle;
plugin_info_t Plugin_info = {
META_INTERFACE_VERSION,
"PacketEntitiesFix",
"0.0.1",
"Apr 6 2014",
"[WPMG]PRoSToTeM@ / Lev",
"",
"PEF",
PT_ANYTIME,
PT_ANYTIME,
};
extern void SV_CreatePacketEntities(int fDelta, void *dontneed, void *dontneed0, void *dontneed1);
extern void DELTA_MarkSendFields(void *pFrom, void *pTo, delta_info_t *pDeltaInfo);
extern void OpenEngine(void);
extern void CloseEngine(void);
extern void *FindSymbol(const char *pszSymbolName);
extern hook_t *CreateHook(void *pfnOriginal, void *pfnCallback, bool fDoHook = true);
extern void DeleteHook(hook_t *pHook);
extern void DoHook(hook_t *pHook);
extern void UndoHook(hook_t *pHook);
C_DLLEXPORT void GiveFnptrsToDll(enginefuncs_t* pengfuncsFromEngine, globalvars_t *pGlobals) {
memcpy(&g_engfuncs, pengfuncsFromEngine, sizeof(enginefuncs_t));
gpGlobals = pGlobals;
}
C_DLLEXPORT int Meta_Query(char *, plugin_info_t **pPlugInfo, mutil_funcs_t *pMetaUtilFuncs) {
*pPlugInfo = &Plugin_info;
gpMetaUtilFuncs = pMetaUtilFuncs;
return TRUE;
}
C_DLLEXPORT int Meta_Attach(PLUG_LOADTIME , META_FUNCTIONS *pFunctionTable, meta_globals_t *pMGlobals, gamedll_funcs_t *pGamedllFuncs) {
gpMetaGlobals = pMGlobals;
gpGamedllFuncs = pGamedllFuncs;
OpenEngine();
g_phookDeltaMarkSendFields = CreateHook(FindSymbol("DELTA_MarkSendFields"), &DELTA_MarkSendFields, false);
g_phookSvCreatePacketEntities = CreateHook(FindSymbol("SV_CreatePacketEntities"), &SV_CreatePacketEntities);
CloseEngine();
return TRUE;
}
C_DLLEXPORT int Meta_Detach(PLUG_LOADTIME , PL_UNLOAD_REASON) {
DeleteHook(g_phookSvCreatePacketEntities);
DeleteHook(g_phookDeltaMarkSendFields);
return TRUE;
}
void SV_CreatePacketEntities(int fDelta, void *dontneed, void *dontneed0, void *dontneed1) {
if (!fDelta) {
DoHook(g_phookDeltaMarkSendFields);
}
UndoHook(g_phookSvCreatePacketEntities);
(*(SV_CREATEPACKETENTITIES *)g_phookSvCreatePacketEntities->m_pfnOriginal)(fDelta, dontneed, dontneed0, dontneed1);
DoHook(g_phookSvCreatePacketEntities);
if (!fDelta) {
UndoHook(g_phookDeltaMarkSendFields);
}
}
void DELTA_MarkSendFields(void *pFrom, void *pTo, delta_info_t *pDeltaInfo) {
delta_t *pField;
int nFieldCount;
int i;
void *pFromChange;
void *pToChange;
UndoHook(g_phookDeltaMarkSendFields);
(*(DELTA_MARKSENDFIELDS *)g_phookDeltaMarkSendFields->m_pfnOriginal)(pFrom, pTo, pDeltaInfo);
DoHook(g_phookDeltaMarkSendFields);
pField = &(pDeltaInfo->m_pFields[0]);
nFieldCount = pDeltaInfo->m_iFieldsCount;
for (i = 0; i < nFieldCount; i++, pField++) {
if (pField->m_iFlags & DT_SEND) {
continue;
}
pFromChange = (byte *)pFrom + pField->m_iOffset;
pToChange = (byte *)pTo + pField->m_iOffset;
switch (pField->m_iFieldType & ~DT_SIGNED) {
case DT_BYTE:
*(byte *)pToChange = *(byte *)pFromChange;
break;
case DT_SHORT:
*(word *)pToChange = *(word *)pFromChange;
break;
// Don't care about strings, cause entity_state_t haven't it
default:
*(unsigned int *)pToChange = *(unsigned int *)pFromChange;
break;
}
}
}
void OpenEngine(void) {
Dl_info Info;
dladdr(g_engfuncs.pfnPrecacheModel, &Info);
g_pEngineHandle = dlopen(Info.dli_fname, RTLD_NOW);
}
void CloseEngine(void) {
dlclose(g_pEngineHandle);
}
void *FindSymbol(const char *pszSymbolName) {
return dlsym(g_pEngineHandle, pszSymbolName);
}
hook_t *CreateHook(void *pfnOriginal, void *pfnCallback, bool fDoHook = true) {
hook_t *pHook = new hook_t;
pHook->m_pfnOriginal = pfnOriginal;
memcpy(pHook->m_rgbOriginalBytes, pfnOriginal, sizeof(jmpnear_t));
pHook->m_jmpnearBytes.m_bOpcode = OPCODE_JMPNEAR;
pHook->m_jmpnearBytes.m_pAddr = (void *)((size_t)pfnCallback - (size_t)pfnOriginal - sizeof(jmpnear_t));
mprotect((void *)((size_t)pfnOriginal & ~(PAGE_SIZE-1)), PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC);
if (fDoHook) {
DoHook(pHook);
}
return pHook;
}
void DeleteHook(hook_t *pHook) {
UndoHook(pHook);
delete pHook;
}
void DoHook(hook_t *pHook) {
memcpy(pHook->m_pfnOriginal, &(pHook->m_jmpnearBytes), sizeof(jmpnear_t));
}
void UndoHook(hook_t *pHook) {
memcpy(pHook->m_pfnOriginal, pHook->m_rgbOriginalBytes, sizeof(jmpnear_t));
}Скачать PacketEntitiesFix:

Комментариев 0