Здравствуйте!
Я никогда не понимал, почему Repi большую часть функционала ReGame просто "дублирует". Сегодня ночью столкнувшись с необходимостью выдать Defkit игроку, я полез смотреть реализацию натива rg_give_defusekit. Вспоминаю, что совсем недавно в регейме видел в
Сравнивая обе реализации, написанные одними и теми же разработчиками, я решительно не понимал, ПААЧЕМУУУУ? этот натив нельзя было сократить и написать в виде:
Прикинув, что если я скопирую реализацию функции регейма
Полез к себе в модуль и написав для объекта типа
Для своего модуля я использую "обертку" от ReAPI, в которой есть файлик
Лезем в
Там же, чуть ниже, в описание класса CBasePlayer в public секции добавляем:
После чего для объекта типа CBasePlayer в списке доступных элементов появляется новая функция GiveDefuser():
Компилируем, проверяем... УРААА!! Все работает 
Продолжаем искать и добавлять функции, берем бинарник регейма (
Берем mangled имя функции "_ZN11CBasePlayer13RemoveDefuserEv" и повторяем процесс...
Я никогда не понимал, почему Repi большую часть функционала ReGame просто "дублирует". Сегодня ночью столкнувшись с необходимостью выдать Defkit игроку, я полез смотреть реализацию натива rg_give_defusekit. Вспоминаю, что совсем недавно в регейме видел в
player.h функцию GiveDefuser.Сравнивая обе реализации, написанные одними и теми же разработчиками, я решительно не понимал, ПААЧЕМУУУУ? этот натив нельзя было сократить и написать в виде:
Код:
cell AMX_NATIVE_CALL rg_give_defusekit(AMX *amx, cell *params)
{
enum args_e { arg_count, arg_index, arg_def, arg_color, arg_icon, arg_flash };
CHECK_GAMERULES();
CHECK_ISPLAYER(arg_index);
CBasePlayer *pPlayer = UTIL_PlayerByIndex(params[arg_index]);
CHECK_CONNECTED(pPlayer, arg_index);
// on the map there is not bomb places
if (CSGameRules() != nullptr && !CSGameRules()->m_bMapHasBombTarget && !CSGameRules()->m_bMapHasBombZone) {
return FALSE;
}
if (pPlayer->m_iTeam != CT) {
return FALSE;
}
pPlayer->GiveDefuser();
return TRUE;
}
Прикинув, что если я скопирую реализацию функции регейма
GiveDefuser, суммарно в памяти получится 3 копии одного и того же кода... БредПолез к себе в модуль и написав для объекта типа
CBasePlayer "pl_to->" в списке доступных функций GiveDefuser не было... Прошерстив cssdk я понял, что это древнее говно мамонта, которое 9 лет никто не обновлял и оно кочует из проекта в проект без изменений. Но мне точно нужно pl_to->GiveDefuser() и еще много функций из player.h регейма... Перепробовав наверно десяток разных вариантов (включая изменение ячеек памяти vtable и т.п.), рабочих оказалось 3... Самый красивый и удобный ниже.Для своего модуля я использую "обертку" от ReAPI, в которой есть файлик
ex_regamedll_api.cpp, добавляем туда строки (+):
Diff:
+CBasePlayer_GiveDefuser_t func_CBasePlayer_GiveDefuser;
bool RegamedllApi_Init()
{
const char *szGameDLLModule = GET_GAME_INFO(PLID, GINFO_DLL_FULLPATH);
if (!szGameDLLModule)
return false;
CSysModule *gameModule = Sys_GetModuleHandle(szGameDLLModule);
if (!gameModule)
return false;
CreateInterfaceFn ifaceFactory = Sys_GetFactory(gameModule);
if (!ifaceFactory)
return false;
int retCode = 0;
g_ReGameApi = (IReGameApi *)ifaceFactory(VRE_GAMEDLL_API_VERSION, &retCode);
if (!g_ReGameApi)
{
return false;
}
int majorVersion = g_ReGameApi->GetMajorVersion();
int minorVersion = g_ReGameApi->GetMinorVersion();
if (majorVersion != REGAMEDLL_API_VERSION_MAJOR)
{
UTIL_ServerPrint("[%s]: ReGameDLL API major version mismatch; expected %d, real %d\n", Plugin_info.logtag, REGAMEDLL_API_VERSION_MAJOR, majorVersion);
// need to notify that it is necessary to update the ReGameDLL.
if (majorVersion < REGAMEDLL_API_VERSION_MAJOR)
{
UTIL_ServerPrint("[%s]: Please update the ReGameDLL up to a major version API >= %d\n", Plugin_info.logtag, REGAMEDLL_API_VERSION_MAJOR);
}
// need to notify that it is necessary to update the module.
else if (majorVersion > REGAMEDLL_API_VERSION_MAJOR)
{
UTIL_ServerPrint("[%s]: Please update the %s up to a major version API >= %d\n", Plugin_info.logtag, Plugin_info.logtag, majorVersion);
}
return false;
}
if (minorVersion < REGAMEDLL_API_VERSION_MINOR)
{
UTIL_ServerPrint("[%s]: ReGameDLL API minor version mismatch; expected at least %d, real %d\n", Plugin_info.logtag, REGAMEDLL_API_VERSION_MINOR, minorVersion);
UTIL_ServerPrint("[%s]: Please update the ReGameDLL up to a minor version API >= %d\n", Plugin_info.logtag, REGAMEDLL_API_VERSION_MINOR);
return false;
}
g_ReGameFuncs = g_ReGameApi->GetFuncs();
g_ReGameHookchains = g_ReGameApi->GetHookchains();
// Safe check CCSEntity API interface version
if (!g_ReGameApi->BGetICSEntity(CSENTITY_API_INTERFACE_VERSION))
{
UTIL_ServerPrint("[%s]: Interface CCSEntity API version '%s' not found.\n", Plugin_info.logtag, CSENTITY_API_INTERFACE_VERSION);
if (g_ReGameApi->BGetICSEntity("CSENTITY_API_INTERFACE_VERSION002"))
UTIL_ServerPrint("[%s]: Please update ReGameDLL to the latest version.\n", Plugin_info.logtag);
else
UTIL_ServerPrint("[%s]: Please update ReAPI to the latest version.\n", Plugin_info.logtag);
return false;
}
+ // Hack ReGame
+ func_CBasePlayer_GiveDefuser = (CBasePlayer_GiveDefuser_t)Sys_GetProcAddress(gameModule, "_ZN11CBasePlayer11GiveDefuserEv");
+ if (!func_CBasePlayer_GiveDefuser)
+ {
+ UTIL_ServerPrint("[%s]: ReGame function %s not found.\n", Plugin_info.logtag, "_ZN11CBasePlayer11GiveDefuserEv");
+ return false;
+ }
+
return true;
}
Лезем в
player.h из cssdk и добавляем строчки наверх:
Код:
// Hack ReGame
typedef void (*CBasePlayer_GiveDefuser_t)(CBasePlayer*);
extern CBasePlayer_GiveDefuser_t func_CBasePlayer_GiveDefuser;
Там же, чуть ниже, в описание класса CBasePlayer в public секции добавляем:
Код:
// RefsAPI
void GiveDefuser() { if (func_CBasePlayer_GiveDefuser) func_CBasePlayer_GiveDefuser(this); };
После чего для объекта типа CBasePlayer в списке доступных элементов появляется новая функция GiveDefuser():
Код:
pl_to->GiveDefuser();
Продолжаем искать и добавлять функции, берем бинарник регейма (
cs.so) и ищем теперь следующую функцию без модификатора EXT_FUNC:
Код:
ubuntu@ubuntu1604:~/dev/Release$ strings cs.so | grep RemoveDefuser
_ZN11CBasePlayer13RemoveDefuserEv
Берем mangled имя функции "_ZN11CBasePlayer13RemoveDefuserEv" и повторяем процесс...
Последнее редактирование: