Simple implementation for cvar queries
This commit is contained in:
		@@ -59,6 +59,10 @@ void CPlayer::Disconnect() {
 | 
			
		||||
  ingame = false;
 | 
			
		||||
  initialized = false;
 | 
			
		||||
  authorized = false;
 | 
			
		||||
 | 
			
		||||
  while (!cvarQueryQueue.empty())
 | 
			
		||||
	  cvarQueryQueue.pop();
 | 
			
		||||
 | 
			
		||||
  bot = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -62,9 +62,15 @@ public:
 | 
			
		||||
// class CPlayer
 | 
			
		||||
// *****************************************************
 | 
			
		||||
 | 
			
		||||
struct ClientCvarQuery_Info
 | 
			
		||||
{
 | 
			
		||||
	bool querying;			// Are we actually waiting for a response at the moment?
 | 
			
		||||
	String cvarName;
 | 
			
		||||
	int resultFwd;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class CPlayer 
 | 
			
		||||
{
 | 
			
		||||
	
 | 
			
		||||
public:
 | 
			
		||||
	edict_t* pEdict;
 | 
			
		||||
	
 | 
			
		||||
@@ -106,6 +112,8 @@ public:
 | 
			
		||||
	Vector thisTrace;
 | 
			
		||||
	Vector lastHit;
 | 
			
		||||
	
 | 
			
		||||
	CQueue<ClientCvarQuery_Info*> cvarQueryQueue;
 | 
			
		||||
 | 
			
		||||
	void Init( edict_t* e , int i );
 | 
			
		||||
	void Disconnect();
 | 
			
		||||
	void PutInServer();
 | 
			
		||||
 
 | 
			
		||||
@@ -2921,6 +2921,56 @@ static cell AMX_NATIVE_CALL int3(AMX *amx, cell *params)
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*********************************************************************/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// native query_client_cvar(id, const cvar[], const resultfunc[])
 | 
			
		||||
static cell AMX_NATIVE_CALL query_client_cvar(AMX *amx, cell *params)
 | 
			
		||||
{
 | 
			
		||||
	if (!g_NewDLL_Available)
 | 
			
		||||
	{
 | 
			
		||||
		LogError(amx, AMX_ERR_NATIVE, "NewDLL functions are not available. Blame (your) metamod (version)");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	int id = params[1];
 | 
			
		||||
	if (id < 1 || id > gpGlobals->maxClients)
 | 
			
		||||
	{
 | 
			
		||||
		LogError(amx, AMX_ERR_NATIVE, "Invalid player id %d", id);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	CPlayer *pPlayer = GET_PLAYER_POINTER_I(id);
 | 
			
		||||
 | 
			
		||||
	if (!pPlayer->initialized || pPlayer->bot)
 | 
			
		||||
	{
 | 
			
		||||
		LogError(amx, AMX_ERR_NATIVE, "Player %d is either not connected or a bot", id);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	int dummy;
 | 
			
		||||
	const char *cvarname = get_amxstring(amx, params[2], 0, dummy);
 | 
			
		||||
	const char *resultfuncname = get_amxstring(amx, params[3], 1, dummy);
 | 
			
		||||
 | 
			
		||||
	// public clientcvarquery_result(id, const cvar[], const result[])
 | 
			
		||||
	int iFunc = registerSPForwardByName(amx, resultfuncname, FP_CELL, FP_STRING, FP_STRING, FP_DONE);
 | 
			
		||||
	if (iFunc == -1)
 | 
			
		||||
	{
 | 
			
		||||
		LogError(amx, AMX_ERR_NATIVE, "Function \"%s\" is not present", resultfuncname);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ClientCvarQuery_Info *queryObject = new ClientCvarQuery_Info;
 | 
			
		||||
	queryObject->querying = false;
 | 
			
		||||
	queryObject->cvarName.assign(cvarname);
 | 
			
		||||
	queryObject->resultFwd = iFunc;
 | 
			
		||||
 | 
			
		||||
	pPlayer->cvarQueryQueue.push(queryObject);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AMX_NATIVE_INFO amxmod_Natives[] = {
 | 
			
		||||
  { "client_cmd",       client_cmd },
 | 
			
		||||
  { "client_print",     client_print },
 | 
			
		||||
@@ -3089,5 +3139,6 @@ AMX_NATIVE_INFO amxmod_Natives[] = {
 | 
			
		||||
  { "lang_phrase",		lang_phrase},
 | 
			
		||||
  { "mkdir",			amx_mkdir},
 | 
			
		||||
  { "int3",				int3},
 | 
			
		||||
  { "query_client_cvar", query_client_cvar },
 | 
			
		||||
  { NULL, NULL }
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -176,6 +176,7 @@ extern float g_game_restarting;
 | 
			
		||||
extern float g_game_timeleft;
 | 
			
		||||
extern float g_task_time;
 | 
			
		||||
extern float g_auth_time;
 | 
			
		||||
extern bool g_NewDLL_Available;
 | 
			
		||||
extern hudtextparms_t g_hudset;
 | 
			
		||||
//extern int g_edict_point;
 | 
			
		||||
extern int g_players_num;
 | 
			
		||||
 
 | 
			
		||||
@@ -97,6 +97,7 @@ bool g_IsNewMM = false;
 | 
			
		||||
bool g_NeedsP = false;
 | 
			
		||||
bool g_coloredmenus;
 | 
			
		||||
bool g_activated = false;
 | 
			
		||||
bool g_NewDLL_Available=false;
 | 
			
		||||
 | 
			
		||||
#ifdef MEMORY_TEST
 | 
			
		||||
float g_next_memreport_time;
 | 
			
		||||
@@ -818,6 +819,22 @@ void C_StartFrame_Post( void )
 | 
			
		||||
 | 
			
		||||
  g_tasksMngr.startFrame();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  // Dispatch client cvar queries
 | 
			
		||||
  for(int i = 1; i <= gpGlobals->maxClients; ++i)
 | 
			
		||||
  {
 | 
			
		||||
	  CPlayer* pPlayer = GET_PLAYER_POINTER_I(i);
 | 
			
		||||
	  if (pPlayer->pEdict && pPlayer->initialized && !pPlayer->cvarQueryQueue.empty())
 | 
			
		||||
	  {
 | 
			
		||||
		  if (!IS_QUERYING_CLIENT_CVAR(PLID, pPlayer->pEdict))
 | 
			
		||||
		  {
 | 
			
		||||
			  QUERY_CLIENT_CVAR_VALUE(pPlayer->pEdict, pPlayer->cvarQueryQueue.front()->cvarName.c_str());
 | 
			
		||||
			  pPlayer->cvarQueryQueue.front()->querying = true;
 | 
			
		||||
		  }
 | 
			
		||||
	  }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  RETURN_META(MRES_IGNORED);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1004,6 +1021,26 @@ void C_AlertMessage_Post(ALERT_TYPE atype, char *szFmt, ...)
 | 
			
		||||
	RETURN_META(MRES_IGNORED);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void C_CvarValue(const edict_t *pEdict, const char *value)
 | 
			
		||||
{
 | 
			
		||||
	CPlayer *pPlayer = GET_PLAYER_POINTER(pEdict);
 | 
			
		||||
	if (pPlayer->cvarQueryQueue.empty())
 | 
			
		||||
		RETURN_META(MRES_IGNORED);
 | 
			
		||||
 | 
			
		||||
	ClientCvarQuery_Info *pQuery = pPlayer->cvarQueryQueue.front();
 | 
			
		||||
 | 
			
		||||
	if (pPlayer->cvarQueryQueue.front()->querying)
 | 
			
		||||
	{
 | 
			
		||||
		executeForwards(pQuery->resultFwd, ENTINDEX(pEdict), pQuery->cvarName.c_str(), value);
 | 
			
		||||
		unregisterSPForward(pQuery->resultFwd);
 | 
			
		||||
		delete pQuery;
 | 
			
		||||
		pPlayer->cvarQueryQueue.pop();
 | 
			
		||||
		RETURN_META(MRES_HANDLED);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	RETURN_META(MRES_IGNORED);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool m_NeedsP = false;
 | 
			
		||||
 | 
			
		||||
C_DLLEXPORT	int	Meta_Query(char	*ifvers, plugin_info_t **pPlugInfo,	mutil_funcs_t *pMetaUtilFuncs)
 | 
			
		||||
@@ -1091,8 +1128,8 @@ C_DLLEXPORT	int	Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS *pFunctionTable, m
 | 
			
		||||
  gMetaFunctionTable.pfnGetEntityAPI2_Post = GetEntityAPI2_Post;
 | 
			
		||||
  gMetaFunctionTable.pfnGetEngineFunctions = GetEngineFunctions;
 | 
			
		||||
  gMetaFunctionTable.pfnGetEngineFunctions_Post	= GetEngineFunctions_Post;
 | 
			
		||||
#ifdef FAKEMETA
 | 
			
		||||
  gMetaFunctionTable.pfnGetNewDLLFunctions = GetNewDLLFunctions;
 | 
			
		||||
#ifdef FAKEMETA
 | 
			
		||||
  gMetaFunctionTable.pfnGetNewDLLFunctions_Post = GetNewDLLFunctions_Post;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@@ -1354,17 +1391,30 @@ C_DLLEXPORT	int	GetEngineFunctions_Post(enginefuncs_t *pengfuncsFromEngine,	int
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef FAKEMETA
 | 
			
		||||
NEW_DLL_FUNCTIONS gNewDLLFunctionTable;
 | 
			
		||||
C_DLLEXPORT int GetNewDLLFunctions(NEW_DLL_FUNCTIONS *pNewFunctionTable, int *interfaceVersion)
 | 
			
		||||
{
 | 
			
		||||
	// default metamod does not call this if the gamedll doesn't provide it
 | 
			
		||||
	g_NewDLL_Available = true;
 | 
			
		||||
 | 
			
		||||
	gNewDLLFunctionTable.pfnCvarValue = C_CvarValue;
 | 
			
		||||
#ifdef FAKEMETA
 | 
			
		||||
	return g_FakeMeta.GetNewDLLFunctions(pNewFunctionTable, interfaceVersion, &gNewDLLFunctionTable);
 | 
			
		||||
#else
 | 
			
		||||
	memcpy(pNewFunctionTable, &gNewDLLFunctionTable, sizeof(NEW_DLL_FUNCTIONS));
 | 
			
		||||
	return 1;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef FAKEMETA
 | 
			
		||||
 | 
			
		||||
NEW_DLL_FUNCTIONS gNewDLLFunctionTable_Post;
 | 
			
		||||
C_DLLEXPORT int GetNewDLLFunctions_Post(NEW_DLL_FUNCTIONS *pNewFunctionTable, int *interfaceVersion)
 | 
			
		||||
{
 | 
			
		||||
	return g_FakeMeta.GetNewDLLFunctions_Post(pNewFunctionTable, interfaceVersion, &gNewDLLFunctionTable_Post);
 | 
			
		||||
	memcpy(pNewFunctionTable, &gNewDLLFunctionTable_Post, sizeof(NEW_DLL_FUNCTIONS));
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
		Reference in New Issue
	
	Block a user