my way is to use the traditional metamod 1.19, list all game functions, not the dynamic way.
here we go.
prepare 3 files. "h_export.h"
Code:
#ifndef _H_EXPORT_H_
#define _H_EXPORT_H_
#include <enginecallback.h>
#include <util.h>
#define C_DLLEXPORT extern "C" __declspec(dllexport)
#define GET_INFOKEYBUFFER (*g_engfuncs.pfnGetInfoKeyBuffer)
#define INFOKEY_VALUE (*g_engfuncs.pfnInfoKeyValue)
#define SET_CLIENT_KEYVALUE (*g_engfuncs.pfnSetClientKeyValue)
#define REG_SVR_COMMAND (*g_engfuncs.pfnAddServerCommand)
#define SERVER_PRINT (*g_engfuncs.pfnServerPrint)
#define SET_SERVER_KEYVALUE (*g_engfuncs.pfnSetKeyValue)
extern HMODULE hGameDll;
extern enginefuncs_t g_engfuncs;
extern globalvars_t *gpGlobals;
extern DLL_FUNCTIONS g_dllfuncs;
// dll funcs callback
#define MDLL_GameDLLInit (*g_dllfuncs.pfnGameInit)
#define MDLL_Spawn (*g_dllfuncs.pfnSpawn)
#define MDLL_Think (*g_dllfuncs.pfnThink)
#define MDLL_Use (*g_dllfuncs.pfnUse)
#define MDLL_Touch (*g_dllfuncs.pfnTouch)
#define MDLL_Blocked (*g_dllfuncs.pfnBlocked)
#define MDLL_KeyValue (*g_dllfuncs.pfnKeyValue)
#define MDLL_Save (*g_dllfuncs.pfnSave)
#define MDLL_Restore (*g_dllfuncs.pfnRestore)
#define MDLL_ObjectCollsionBox (*g_dllfuncs.pfnAbsBox)
#define MDLL_SaveWriteFields (*g_dllfuncs.pfnSaveWriteFields)
#define MDLL_SaveReadFields (*g_dllfuncs.pfnSaveReadFields)
#define MDLL_SaveGlobalState (*g_dllfuncs.pfnSaveGlobalState)
#define MDLL_RestoreGlobalState (*g_dllfuncs.pfnRestoreGlobalState)
#define MDLL_ResetGlobalState (*g_dllfuncs.pfnResetGlobalState)
#define MDLL_ClientConnect (*g_dllfuncs.pfnClientConnect)
#define MDLL_ClientDisconnect (*g_dllfuncs.pfnClientDisconnect)
#define MDLL_ClientKill (*g_dllfuncs.pfnClientKill)
#define MDLL_ClientPutInServer (*g_dllfuncs.pfnClientPutInServer)
#define MDLL_ClientCommand (*g_dllfuncs.pfnClientCommand)
#define MDLL_ClientUserInfoChanged (*g_dllfuncs.pfnClientUserInfoChanged)
#define MDLL_ServerActivate (*g_dllfuncs.pfnServerActivate)
#define MDLL_ServerDeactivate (*g_dllfuncs.pfnServerDeactivate)
#define MDLL_PlayerPreThink (*g_dllfuncs.pfnPlayerPreThink)
#define MDLL_PlayerPostThink (*g_dllfuncs.pfnPlayerPostThink)
#define MDLL_StartFrame (*g_dllfuncs.pfnStartFrame)
#define MDLL_ParmsNewLevel (*g_dllfuncs.pfnParmsNewLevel)
#define MDLL_ParmsChangeLevel (*g_dllfuncs.pfnParmsChangeLevel)
#define MDLL_GetGameDescription (*g_dllfuncs.pfnGetGameDescription)
#define MDLL_PlayerCustomization (*g_dllfuncs.pfnPlayerCustomization)
#define MDLL_SpectatorConnect (*g_dllfuncs.pfnSpectatorConnect)
#define MDLL_SpectatorDisconnect (*g_dllfuncs.pfnSpectatorDisconnect)
#define MDLL_SpectatorThink (*g_dllfuncs.pfnSpectatorThink)
#define MDLL_Sys_Error (*g_dllfuncs.pfnSys_Error)
#define MDLL_PM_Move (*g_dllfuncs.pfnPM_Move)
#define MDLL_PM_Init (*g_dllfuncs.pfnPM_Init)
#define MDLL_PM_FindTextureType (*g_dllfuncs.pfnPM_FindTextureType)
#define MDLL_SetupVisibility (*g_dllfuncs.pfnSetupVisibility)
#define MDLL_UpdateClientData (*g_dllfuncs.pfnUpdateClientData)
#define MDLL_AddToFullPack (*g_dllfuncs.pfnAddToFullPack)
#define MDLL_CreateBaseline (*g_dllfuncs.pfnCreateBaseline)
#define MDLL_RegisterEncoders (*g_dllfuncs.pfnRegisterEncoders)
#define MDLL_GetWeaponData (*g_dllfuncs.pfnGetWeaponData)
#define MDLL_CmdStart (*g_dllfuncs.pfnCmdStart)
#define MDLL_CmdEnd (*g_dllfuncs.pfnCmdEnd)
#define MDLL_ConnectionlessPacket (*g_dllfuncs.pfnConnectionlessPacket)
#define MDLL_GetHullBounds (*g_dllfuncs.pfnGetHullBounds)
#define MDLL_CreateInstancedBaselines (*g_dllfuncs.pfnCreateInstancedBaselines)
#define MDLL_InconsistentFile (*g_dllfuncs.pfnInconsistentFile)
#define MDLL_AllowLagCompensation (*g_dllfuncs.pfnAllowLagCompensation)
typedef void (FAR *ENTITY_FN)(entvars_t *);
inline void ENTITY_SET_KEYVALUE(edict_t *entity, char *key, char *value)
{
char *ifbuf = GET_INFOKEYBUFFER(entity);
SET_CLIENT_KEYVALUE(ENTINDEX(entity), ifbuf, key, value);
}
#endif//_H_EXPORT_H_
"h_export.cpp"
Code:
#include <extdll.h>
#include "h_export.h"
#include "csdm.h"
HMODULE hGameDll = NULL; //the address of mp.dll's entry
enginefuncs_t g_engfuncs; //the address of hl engine function table
globalvars_t *gpGlobals; //the address of hl engine's global variables
DLL_FUNCTIONS g_dllfuncs; //the address of dll functions
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
if(fdwReason == DLL_PROCESS_ATTACH)
{}
else if(fdwReason == DLL_PROCESS_DETACH)
{
if(hGameDll)
FreeLibrary(hGameDll);
}
return TRUE;
}
//the first function engine calls, all stuff begins from here.
#pragma comment(linker, "/EXPORT:GiveFnptrsToDll=_GiveFnptrsToDll@8,@1")
#pragma comment(linker, "/SECTION:.data,RW")
typedef void (WINAPI *GIVE_ENGINE_FUNCTIONS_FN)(enginefuncs_t *pengfuncsFromEngine, globalvars_t *pGlobals);
C_DLLEXPORT void WINAPI GiveFnptrsToDll(enginefuncs_t *pengfuncsFromEngine, globalvars_t *pGlobals)
{
//get the engine functions table address
memcpy(&g_engfuncs, pengfuncsFromEngine, 144 * sizeof(uint32));
//get the global variables address
gpGlobals = pGlobals;
//load the game dll
hGameDll = LoadLibrary("cstrike/dlls/mp.dll");
if(hGameDll == NULL)
{
LOG_ERROR("[CSDM] can't load mp.dll !\n");
Sleep(1000);
exit(1);
return;
}
//get the address of the function "GiveFnptrsToDll" in game dll
GIVE_ENGINE_FUNCTIONS_FN give_fnptrs_to_dll;
give_fnptrs_to_dll = (GIVE_ENGINE_FUNCTIONS_FN)GetProcAddress(hGameDll, "GiveFnptrsToDll");
if(!give_fnptrs_to_dll)
return;
//call that "GiveFnptrsToDll", pass the engine functions and global variables
give_fnptrs_to_dll(pengfuncsFromEngine, pGlobals);
//BEGIN YOUR MODULE HERE! <---
if(FALSE == CSDM_StartUp())
{
Sleep(1000);
exit(1);
return;
}
}
typedef int (*GETENTITYAPI_FN)(DLL_FUNCTIONS *pFunctionTable, int interfaceVersion);
C_DLLEXPORT int GetEntityAPI(DLL_FUNCTIONS *pFunctionTable, int interfaceVersion)
{
if(pFunctionTable == NULL || interfaceVersion != INTERFACE_VERSION)
return FALSE;
GETENTITYAPI_FN get_entity_api;
get_entity_api = (GETENTITYAPI_FN)GetProcAddress(hGameDll, "GetEntityAPI");
if(!get_entity_api)
return FALSE;
//get dll functions
get_entity_api(&g_dllfuncs, interfaceVersion);
//
get_entity_api(pFunctionTable, interfaceVersion);
//functions you want to hook, overwrite the address in function table
pFunctionTable->pfnSpawn = C_Spawn;
pFunctionTable->pfnServerActivate = C_ServerActivate_Post;
pFunctionTable->pfnStartFrame = C_StartFrame_Post;
pFunctionTable->pfnClientConnect = C_ClientConnect_Post;
pFunctionTable->pfnServerDeactivate = C_ServerDeactivate;
pFunctionTable->pfnClientPutInServer = C_ClientPutInServer_Post;
pFunctionTable->pfnClientDisconnect = C_ClientDisconnect;
pFunctionTable->pfnClientCommand = C_ClientCommand;
return TRUE;
}
typedef int (*GETNEWDLLFUNCTIONS_FN)(NEW_DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion);
C_DLLEXPORT int GetNewDLLFunctions(NEW_DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion)
{
if(pFunctionTable == NULL)
return FALSE;
else if(*interfaceVersion != NEW_DLL_FUNCTIONS_VERSION)
{
*interfaceVersion = NEW_DLL_FUNCTIONS_VERSION;
return FALSE;
}
GETNEWDLLFUNCTIONS_FN get_new_dll_functions;
get_new_dll_functions = (GETNEWDLLFUNCTIONS_FN)GetProcAddress(hGameDll, "GetNewDLLFunctions");
if(!get_new_dll_functions)
return FALSE;
get_new_dll_functions(pFunctionTable, interfaceVersion);
return TRUE;
}
"linkgame.cpp"
Code:
#include <extdll.h>
#include "h_export.h"
#define LINK_ENTITY_TO_GAME(EntityClassName)\
C_DLLEXPORT void EntityClassName(entvars_t *pev) {\
static ENTITY_FN pfnEntity = NULL;\
if(pfnEntity == NULL) pfnEntity = (ENTITY_FN)GetProcAddress(hGameDll, #EntityClassName);\
if(pfnEntity == NULL) return;\
(*pfnEntity)(pev);\
}
// Entities in Counter-Strike
LINK_ENTITY_TO_GAME(DelayedUse);
LINK_ENTITY_TO_GAME(ambient_generic);
LINK_ENTITY_TO_GAME(ammo_338magnum);
LINK_ENTITY_TO_GAME(ammo_357sig);
LINK_ENTITY_TO_GAME(ammo_45acp);
LINK_ENTITY_TO_GAME(ammo_50ae);
LINK_ENTITY_TO_GAME(ammo_556nato);
LINK_ENTITY_TO_GAME(ammo_556natobox);
LINK_ENTITY_TO_GAME(ammo_57mm);
LINK_ENTITY_TO_GAME(ammo_762nato);
LINK_ENTITY_TO_GAME(ammo_9mm);
LINK_ENTITY_TO_GAME(ammo_buckshot);
LINK_ENTITY_TO_GAME(armoury_entity);
LINK_ENTITY_TO_GAME(beam);
LINK_ENTITY_TO_GAME(bodyque);
LINK_ENTITY_TO_GAME(button_target);
LINK_ENTITY_TO_GAME(cycler);
LINK_ENTITY_TO_GAME(cycler_prdroid);
LINK_ENTITY_TO_GAME(cycler_sprite);
LINK_ENTITY_TO_GAME(cycler_weapon);
LINK_ENTITY_TO_GAME(cycler_wreckage);
LINK_ENTITY_TO_GAME(env_beam);
LINK_ENTITY_TO_GAME(env_beverage);
LINK_ENTITY_TO_GAME(env_blood);
LINK_ENTITY_TO_GAME(env_bombglow);
LINK_ENTITY_TO_GAME(env_bubbles);
LINK_ENTITY_TO_GAME(env_debris);
LINK_ENTITY_TO_GAME(env_explosion);
LINK_ENTITY_TO_GAME(env_fade);
LINK_ENTITY_TO_GAME(env_funnel);
LINK_ENTITY_TO_GAME(env_global);
LINK_ENTITY_TO_GAME(env_glow);
LINK_ENTITY_TO_GAME(env_laser);
LINK_ENTITY_TO_GAME(env_lightning);
LINK_ENTITY_TO_GAME(env_message);
LINK_ENTITY_TO_GAME(env_rain);
LINK_ENTITY_TO_GAME(env_render);
LINK_ENTITY_TO_GAME(env_shake);
LINK_ENTITY_TO_GAME(env_shooter);
LINK_ENTITY_TO_GAME(env_snow);
LINK_ENTITY_TO_GAME(env_sound);
LINK_ENTITY_TO_GAME(env_spark);
LINK_ENTITY_TO_GAME(env_sprite);
LINK_ENTITY_TO_GAME(fireanddie);
LINK_ENTITY_TO_GAME(func_bomb_target);
LINK_ENTITY_TO_GAME(func_breakable);
LINK_ENTITY_TO_GAME(func_button);
LINK_ENTITY_TO_GAME(func_buyzone);
LINK_ENTITY_TO_GAME(func_conveyor);
LINK_ENTITY_TO_GAME(func_door);
LINK_ENTITY_TO_GAME(func_door_rotating);
LINK_ENTITY_TO_GAME(func_escapezone);
LINK_ENTITY_TO_GAME(func_friction);
LINK_ENTITY_TO_GAME(func_grencatch);
LINK_ENTITY_TO_GAME(func_guntarget);
LINK_ENTITY_TO_GAME(func_healthcharger);
LINK_ENTITY_TO_GAME(func_hostage_rescue);
LINK_ENTITY_TO_GAME(func_illusionary);
LINK_ENTITY_TO_GAME(func_ladder);
LINK_ENTITY_TO_GAME(func_monsterclip);
LINK_ENTITY_TO_GAME(func_mortar_field);
LINK_ENTITY_TO_GAME(func_pendulum);
LINK_ENTITY_TO_GAME(func_plat);
LINK_ENTITY_TO_GAME(func_platrot);
LINK_ENTITY_TO_GAME(func_pushable);
LINK_ENTITY_TO_GAME(func_rain);
LINK_ENTITY_TO_GAME(func_recharge);
LINK_ENTITY_TO_GAME(func_rot_button);
LINK_ENTITY_TO_GAME(func_rotating);
LINK_ENTITY_TO_GAME(func_snow);
LINK_ENTITY_TO_GAME(func_tank);
LINK_ENTITY_TO_GAME(func_tankcontrols);
LINK_ENTITY_TO_GAME(func_tanklaser);
LINK_ENTITY_TO_GAME(func_tankmortar);
LINK_ENTITY_TO_GAME(func_tankrocket);
LINK_ENTITY_TO_GAME(func_trackautochange);
LINK_ENTITY_TO_GAME(func_trackchange);
LINK_ENTITY_TO_GAME(func_tracktrain);
LINK_ENTITY_TO_GAME(func_train);
LINK_ENTITY_TO_GAME(func_traincontrols);
LINK_ENTITY_TO_GAME(func_vehicle);
LINK_ENTITY_TO_GAME(func_vehiclecontrols);
LINK_ENTITY_TO_GAME(func_vip_safetyzone);
LINK_ENTITY_TO_GAME(func_wall);
LINK_ENTITY_TO_GAME(func_wall_toggle);
LINK_ENTITY_TO_GAME(func_water);
LINK_ENTITY_TO_GAME(func_weaponcheck);
LINK_ENTITY_TO_GAME(game_counter);
LINK_ENTITY_TO_GAME(game_counter_set);
LINK_ENTITY_TO_GAME(game_end);
LINK_ENTITY_TO_GAME(game_player_equip);
LINK_ENTITY_TO_GAME(game_player_hurt);
LINK_ENTITY_TO_GAME(game_player_team);
LINK_ENTITY_TO_GAME(game_score);
LINK_ENTITY_TO_GAME(game_team_master);
LINK_ENTITY_TO_GAME(game_team_set);
LINK_ENTITY_TO_GAME(game_text);
LINK_ENTITY_TO_GAME(game_zone_player);
LINK_ENTITY_TO_GAME(gibshooter);
LINK_ENTITY_TO_GAME(grenade);
LINK_ENTITY_TO_GAME(hostage_entity);
LINK_ENTITY_TO_GAME(info_bomb_target);
LINK_ENTITY_TO_GAME(info_hostage_rescue);
LINK_ENTITY_TO_GAME(info_intermission);
LINK_ENTITY_TO_GAME(info_landmark);
LINK_ENTITY_TO_GAME(info_map_parameters);
LINK_ENTITY_TO_GAME(info_null);
LINK_ENTITY_TO_GAME(info_player_deathmatch);
LINK_ENTITY_TO_GAME(info_player_start);
LINK_ENTITY_TO_GAME(info_target);
LINK_ENTITY_TO_GAME(info_teleport_destination);
LINK_ENTITY_TO_GAME(info_vip_start);
LINK_ENTITY_TO_GAME(infodecal);
LINK_ENTITY_TO_GAME(item_airtank);
LINK_ENTITY_TO_GAME(item_antidote);
LINK_ENTITY_TO_GAME(item_assaultsuit);
LINK_ENTITY_TO_GAME(item_battery);
LINK_ENTITY_TO_GAME(item_healthkit);
LINK_ENTITY_TO_GAME(item_kevlar);
LINK_ENTITY_TO_GAME(item_longjump);
LINK_ENTITY_TO_GAME(item_security);
LINK_ENTITY_TO_GAME(item_sodacan);
LINK_ENTITY_TO_GAME(item_suit);
LINK_ENTITY_TO_GAME(item_thighpack);
LINK_ENTITY_TO_GAME(light);
LINK_ENTITY_TO_GAME(light_environment);
LINK_ENTITY_TO_GAME(light_spot);
LINK_ENTITY_TO_GAME(momentary_door);
LINK_ENTITY_TO_GAME(momentary_rot_button);
LINK_ENTITY_TO_GAME(monster_hevsuit_dead);
LINK_ENTITY_TO_GAME(monster_mortar);
LINK_ENTITY_TO_GAME(monster_scientist);
LINK_ENTITY_TO_GAME(multi_manager);
LINK_ENTITY_TO_GAME(multisource);
LINK_ENTITY_TO_GAME(path_corner);
LINK_ENTITY_TO_GAME(path_track);
LINK_ENTITY_TO_GAME(player);
LINK_ENTITY_TO_GAME(player_loadsaved);
LINK_ENTITY_TO_GAME(player_weaponstrip);
LINK_ENTITY_TO_GAME(soundent);
LINK_ENTITY_TO_GAME(spark_shower);
LINK_ENTITY_TO_GAME(speaker);
LINK_ENTITY_TO_GAME(target_cdaudio);
LINK_ENTITY_TO_GAME(test_effect);
LINK_ENTITY_TO_GAME(trigger);
LINK_ENTITY_TO_GAME(trigger_auto);
LINK_ENTITY_TO_GAME(trigger_autosave);
LINK_ENTITY_TO_GAME(trigger_camera);
LINK_ENTITY_TO_GAME(trigger_cdaudio);
LINK_ENTITY_TO_GAME(trigger_changelevel);
LINK_ENTITY_TO_GAME(trigger_changetarget);
LINK_ENTITY_TO_GAME(trigger_counter);
LINK_ENTITY_TO_GAME(trigger_endsection);
LINK_ENTITY_TO_GAME(trigger_gravity);
LINK_ENTITY_TO_GAME(trigger_hurt);
LINK_ENTITY_TO_GAME(trigger_monsterjump);
LINK_ENTITY_TO_GAME(trigger_multiple);
LINK_ENTITY_TO_GAME(trigger_once);
LINK_ENTITY_TO_GAME(trigger_push);
LINK_ENTITY_TO_GAME(trigger_relay);
LINK_ENTITY_TO_GAME(trigger_teleport);
LINK_ENTITY_TO_GAME(trigger_transition);
LINK_ENTITY_TO_GAME(weapon_ak47);
LINK_ENTITY_TO_GAME(weapon_aug);
LINK_ENTITY_TO_GAME(weapon_awp);
LINK_ENTITY_TO_GAME(weapon_c4);
LINK_ENTITY_TO_GAME(weapon_deagle);
LINK_ENTITY_TO_GAME(weapon_elite);
LINK_ENTITY_TO_GAME(weapon_famas);
LINK_ENTITY_TO_GAME(weapon_fiveseven);
LINK_ENTITY_TO_GAME(weapon_flashbang);
LINK_ENTITY_TO_GAME(weapon_g3sg1);
LINK_ENTITY_TO_GAME(weapon_galil);
LINK_ENTITY_TO_GAME(weapon_glock18);
LINK_ENTITY_TO_GAME(weapon_hegrenade);
LINK_ENTITY_TO_GAME(weapon_knife);
LINK_ENTITY_TO_GAME(weapon_m249);
LINK_ENTITY_TO_GAME(weapon_m3);
LINK_ENTITY_TO_GAME(weapon_m4a1);
LINK_ENTITY_TO_GAME(weapon_mac10);
LINK_ENTITY_TO_GAME(weapon_mp5navy);
LINK_ENTITY_TO_GAME(weapon_p228);
LINK_ENTITY_TO_GAME(weapon_p90);
LINK_ENTITY_TO_GAME(weapon_scout);
LINK_ENTITY_TO_GAME(weapon_sg550);
LINK_ENTITY_TO_GAME(weapon_sg552);
LINK_ENTITY_TO_GAME(weapon_shield);
LINK_ENTITY_TO_GAME(weapon_smokegrenade);
LINK_ENTITY_TO_GAME(weapon_tmp);
LINK_ENTITY_TO_GAME(weapon_ump45);
LINK_ENTITY_TO_GAME(weapon_usp);
LINK_ENTITY_TO_GAME(weapon_xm1014);
LINK_ENTITY_TO_GAME(weaponbox);
LINK_ENTITY_TO_GAME(world_items);
LINK_ENTITY_TO_GAME(worldspawn);
I use memory hack way to hook engine functions, so the example above only show the way of hooking game dll functions. You can do that yourself, same way. And you can try to dynamicly llink entity to game. first read the functions(entity functions) from game dll, then call it in your module.
example of hooked dll function
Code:
void C_ClientPutInServer_Post(edict_t *pEntity)
{
MDLL_ClientPutInServer(pEntity); // here is the post hook, just call the game function before your own code. if you don't call, that's the effect of blocking. or you can do pre hook, just call the dll function after your code.
CPlayer *pPlayer = GET_PLAYER_POINTER(pEntity);
if(!pPlayer->IsBot())
{
pPlayer->PutInServer();
++g_players_num;
}
return;
}
__________________