2
0
mirror of https://github.com/rehlds/rehlds.git synced 2025-03-29 05:39:08 +03:00
rehlds/rehlds/rehlds/rehlds_api_impl.cpp
2018-09-27 01:04:19 +03:00

612 lines
16 KiB
C++

/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#include "precompiled.h"
struct plugin_api_t
{
char name[32];
void *impl;
};
std::vector<plugin_api_t *> g_PluginApis;
std::vector<cvar_listener_t *> g_CvarsListeners;
plugin_api_t* FindPluginApiByName(const char *name) {
for (auto pl : g_PluginApis) {
if (!strcmp(pl->name, name)) {
return pl;
}
}
return NULL;
}
char* EXT_FUNC GetClientFallback_api() {
return com_clientfallback;
}
int* EXT_FUNC GetAllowCheats_api() {
return &allow_cheats;
}
bool EXT_FUNC GSBSecure_api() {
return Steam_GSBSecure() != 0;
}
int EXT_FUNC GetBuildNumber_api() {
return build_number();
}
double EXT_FUNC GetRealTime_api() {
return realtime;
}
int* EXT_FUNC GetMsgBadRead_api() {
return &msg_badread;
}
cmd_source_t* EXT_FUNC GetCmdSource_api() {
return &cmd_source;
}
void EXT_FUNC Log_api(const char* prefix, const char* msg) {
#ifdef REHLDS_FLIGHT_REC
FR_Log(prefix, msg);
#endif
}
DLL_FUNCTIONS* EXT_FUNC GetEntityInterface_api() {
return &gEntityInterface;
}
void EXT_FUNC MSG_StartBitWriting_api(sizebuf_t *buf) {
MSG_StartBitWriting(buf);
}
void EXT_FUNC MSG_WriteBits_api(uint32 data, int numbits) {
MSG_WriteBits(data, numbits);
}
int EXT_FUNC MSG_ReadShort_api() {
return MSG_ReadShort();
}
int EXT_FUNC MSG_ReadBuf_api(int iSize, void *pbuf) {
return MSG_ReadBuf(iSize, pbuf);
}
void EXT_FUNC MSG_WriteBuf_api(sizebuf_t *sb, int iSize, void *buf) {
MSG_WriteBuf(sb, iSize, buf);
}
void EXT_FUNC MSG_WriteByte_api(sizebuf_t *sb, int c) {
MSG_WriteByte(sb, c);
}
void EXT_FUNC MSG_WriteShort_api(sizebuf_t *sb, int c) {
MSG_WriteShort(sb, c);
}
void EXT_FUNC MSG_WriteString_api(sizebuf_t *sb, const char *s) {
MSG_WriteString(sb, s);
}
void EXT_FUNC MSG_WriteBitVec3Coord_api(const vec3_t fa) {
MSG_WriteBitVec3Coord(fa);
}
void EXT_FUNC MSG_EndBitWriting_api(sizebuf_t *buf) {
MSG_EndBitWriting(buf);
}
cvar_t* EXT_FUNC GetCvarVars_api() {
return cvar_vars;
}
void EXT_FUNC SV_StartSound_api(int recipients, edict_t *entity, int channel, const char *sample, int volume, float attenuation, int flags, int pitch) {
SV_StartSound(recipients, entity, channel, sample, volume, attenuation, flags, pitch);
}
void EXT_FUNC SV_UpdateUserInfo_api(IGameClient *pGameClient) {
SV_UpdateUserInfo(pGameClient->GetClient());
}
void* EXT_FUNC Rehlds_GetPluginApi(const char *name) {
auto api = FindPluginApiByName(name);
return api ? api->impl : NULL;
}
bool EXT_FUNC StripUnprintableAndSpace_api(char *pch) {
return Q_StripUnprintableAndSpace(pch) != FALSE;
}
void EXT_FUNC Rehlds_RegisterPluginApi(const char *name, void *impl) {
auto api = FindPluginApiByName(name);
if (!api) {
api = new plugin_api_t;
Q_strncpy(api->name, name, sizeof api->name - 1);
api->name[sizeof api->name - 1] = '\0';
g_PluginApis.push_back(api);
}
api->impl = impl;
}
void EXT_FUNC GetCommandMatches_api(const char *string, ObjectList *pMatchList)
{
if (!string || !string[0])
{
return;
}
auto TextLen = Q_strlen(string);
for (auto EngCmd = Cmd_GetFirstCmd(); EngCmd; EngCmd = EngCmd->next)
{
if (!Q_strnicmp(EngCmd->name, string, TextLen))
{
pMatchList->Add((void*)(EngCmd->name));
}
}
for (auto EngCvar = GetCvarVars_api(); EngCvar; EngCvar = EngCvar->next)
{
if (!Q_strnicmp(EngCvar->name, string, TextLen))
{
pMatchList->Add((void*)(EngCvar->name));
}
}
}
bool EXT_FUNC AddExtDll_api(void *hModule)
{
if (!hModule) {
return false;
}
if (g_iextdllMac >= MAX_EXTENSION_DLL) {
Con_Printf("Too many DLLs, ignoring remainder\n");
return false;
}
auto pextdll = &g_rgextdll[g_iextdllMac++];
Q_memset(pextdll, 0, sizeof(*pextdll));
pextdll->lDLLHandle = hModule;
return true;
}
void EXT_FUNC RemoveExtDll_api(void *hModule)
{
if (!hModule) {
return;
}
for (auto i = 0; i < g_iextdllMac; i++)
{
if (g_rgextdll[i].lDLLHandle == hModule)
{
g_iextdllMac--;
if (g_iextdllMac != i)
{
Q_memmove(&g_rgextdll[i], &g_rgextdll[i + 1], (g_iextdllMac - i) * sizeof(g_rgextdll[0]));
i = g_iextdllMac;
}
Q_memset(&g_rgextdll[i], 0, sizeof(g_rgextdll[0]));
break;
}
}
}
void EXT_FUNC AddCvarListener_api(const char *var_name, cvar_callback_t func)
{
cvar_t *var = Cvar_FindVar(var_name);
if (!var) {
return;
}
for (auto cvars : g_CvarsListeners) {
if (!Q_strcmp(cvars->name, var_name)) {
if (cvars->func == func) {
return;
}
}
}
cvar_listener_t *list = new cvar_listener_t(var_name, func);
g_CvarsListeners.push_back(list);
}
void EXT_FUNC RemoveCvarListener_api(const char *var_name, cvar_callback_t func)
{
auto iter = g_CvarsListeners.begin();
while (iter != g_CvarsListeners.end())
{
if (Q_strcmp((*iter)->name, var_name) != 0 || (*iter)->func != func) {
iter++;
continue;
}
delete (*iter);
iter = g_CvarsListeners.erase(iter);
}
}
CRehldsServerStatic g_RehldsServerStatic;
CRehldsServerData g_RehldsServerData;
CRehldsHookchains g_RehldsHookchains;
RehldsFuncs_t g_RehldsApiFuncs =
{
&SV_DropClient_api,
&SV_RejectConnection,
&Steam_NotifyBotConnect_api,
&GetNetMessage_api,
&GetHostClient_api,
&GetMsgReadCount_api,
&SV_FilterUser,
&NET_SendPacket_api,
&Cmd_TokenizeString,
&SV_CheckChallenge_api,
&SV_SendUserReg,
&SV_WriteDeltaDescriptionsToClient,
&SV_SetMoveVars,
&SV_WriteMovevarsToClient,
&GetClientFallback_api,
&GetAllowCheats_api,
&GSBSecure_api,
&GetBuildNumber_api,
&GetRealTime_api,
&GetMsgBadRead_api,
&GetCmdSource_api,
&Log_api,
&GetEntityInterface_api,
&EV_PlayReliableEvent_api,
&SV_LookupSoundIndex,
&MSG_StartBitWriting_api,
&MSG_WriteBits_api,
&MSG_WriteBitVec3Coord_api,
&MSG_EndBitWriting_api,
&SZ_GetSpace,
&GetCvarVars_api,
&SV_GetChallenge,
&SV_AddResource,
&MSG_ReadShort_api,
&MSG_ReadBuf_api,
&MSG_WriteBuf_api,
&MSG_WriteByte_api,
&MSG_WriteShort_api,
&MSG_WriteString_api,
&Rehlds_GetPluginApi,
&Rehlds_RegisterPluginApi,
&SV_FileInConsistencyList,
&Steam_NotifyClientConnect_api,
&Steam_NotifyClientDisconnect_api,
&SV_StartSound_api,
&SV_EmitSound2_api,
&SV_UpdateUserInfo_api,
&StripUnprintableAndSpace_api,
&Cmd_RemoveCmd,
&GetCommandMatches_api,
&AddExtDll_api,
&AddCvarListener_api,
&RemoveExtDll_api,
&RemoveCvarListener_api,
&GetEntityInit
};
bool EXT_FUNC SV_EmitSound2_internal(edict_t *entity, IGameClient *pReceiver, int channel, const char *sample, float volume, float attenuation, int flags, int pitch, int emitFlags, const float *pOrigin)
{
bool bSendPAS = (channel != CHAN_STATIC && !(flags & SND_FL_STOP) && !(emitFlags & SND_EMIT2_NOPAS));
vec3_t origin = {0, 0, 0};
if (entity && entity != g_psv.edicts)
{
for (int i = 0; i < 3; ++i)
origin[i] = (entity->v.maxs[i] + entity->v.mins[i]) * 0.5f + entity->v.origin[i];
}
// only worldspawn
else if (pOrigin != nullptr)
{
for (int i = 0; i < 3; ++i)
origin[i] = pOrigin[i];
}
// spawn sound of the entity for everyone clients
if (!pReceiver)
{
if (!SV_BuildSoundMsg(entity, channel, sample, (int)(volume * 255.0f), attenuation, flags, pitch, origin, &g_psv.multicast))
return false;
int msg_destination = MSG_FL_NONE;
if (emitFlags & SND_EMIT2_INVOKER) {
msg_destination = MSG_FL_ONE;
}
if (bSendPAS)
{
SV_Multicast(entity, origin, msg_destination | MSG_FL_PAS, FALSE);
}
else
{
SV_Multicast(entity, origin, msg_destination | MSG_FL_BROADCAST, TRUE);
}
return true;
}
sizebuf_t *pBuffer;
client_t *receiver = pReceiver->GetClient();
if (bSendPAS && receiver->edict != entity) // if the sound for myself, then do not check PAS.
{
int leafnum = SV_PointLeafnum(origin);
if (!SV_ValidClientMulticast(receiver, leafnum, MSG_FL_PAS))
return false;
pBuffer = &receiver->datagram;
}
else
{
// reliable
pBuffer = &receiver->netchan.message;
}
// send to one client
return SV_BuildSoundMsg(entity, channel, sample, (int)(volume * 255.0f), attenuation, flags, pitch, origin, pBuffer) != FALSE;
}
bool EXT_FUNC SV_EmitSound2_api(edict_t *entity, IGameClient *receiver, int channel, const char *sample, float volume, float attenuation, int flags, int pitch, int emitFlags, const float *pOrigin)
{
return g_RehldsHookchains.m_SV_EmitSound2.callChain(SV_EmitSound2_internal, entity, receiver, channel, sample, volume, attenuation, flags, pitch, emitFlags, pOrigin);
}
sizebuf_t* EXT_FUNC GetNetMessage_api()
{
return &net_message;
}
IGameClient* EXT_FUNC GetHostClient_api()
{
if (host_client == NULL)
return NULL;
return GetRehldsApiClient(host_client);
}
extern int* EXT_FUNC GetMsgReadCount_api()
{
return &msg_readcount;
}
IRehldsHookRegistry_Steam_NotifyClientConnect* CRehldsHookchains::Steam_NotifyClientConnect()
{
return &m_Steam_NotifyClientConnect;
}
IRehldsHookRegistry_SV_ConnectClient* CRehldsHookchains::SV_ConnectClient()
{
return &m_SV_ConnectClient;
}
IRehldsHookRegistry_SV_GetIDString* CRehldsHookchains::SV_GetIDString()
{
return &m_SV_GetIDString;
}
IRehldsHookRegistry_SV_SendServerinfo* CRehldsHookchains::SV_SendServerinfo()
{
return &m_SV_SendServerinfo;
}
IRehldsHookRegistry_SV_CheckProtocol* CRehldsHookchains::SV_CheckProtocol()
{
return &m_SV_CheckProtocol;
}
IRehldsHookRegistry_SVC_GetChallenge_mod* CRehldsHookchains::SVC_GetChallenge_mod()
{
return &m_SVC_GetChallenge_mod;
}
IRehldsHookRegistry_SV_CheckKeyInfo* CRehldsHookchains::SV_CheckKeyInfo()
{
return &m_SV_CheckKeyInfo;
}
IRehldsHookRegistry_SV_CheckIPRestrictions* CRehldsHookchains::SV_CheckIPRestrictions()
{
return &m_SV_CheckIPRestrictions;
}
IRehldsHookRegistry_SV_FinishCertificateCheck* CRehldsHookchains::SV_FinishCertificateCheck()
{
return &m_SV_FinishCertificateCheck;
}
IRehldsHookRegistry_Steam_NotifyBotConnect* CRehldsHookchains::Steam_NotifyBotConnect()
{
return &m_Steam_NotifyBotConnect;
}
IRehldsHookRegistry_SerializeSteamId* CRehldsHookchains::SerializeSteamId()
{
return &m_SerializeSteamId;
}
IRehldsHookRegistry_SV_CompareUserID* CRehldsHookchains::SV_CompareUserID()
{
return &m_SV_CompareUserID;
}
IRehldsHookRegistry_Steam_NotifyClientDisconnect* CRehldsHookchains::Steam_NotifyClientDisconnect()
{
return &m_Steam_NotifyClientDisconnect;
}
IRehldsHookRegistry_PreprocessPacket* CRehldsHookchains::PreprocessPacket() {
return &m_PreprocessPacket;
}
IRehldsHookRegistry_ValidateCommand* CRehldsHookchains::ValidateCommand() {
return &m_ValidateCommand;
}
IRehldsHookRegistry_ClientConnected* CRehldsHookchains::ClientConnected() {
return &m_ClientConnected;
}
IRehldsHookRegistry_HandleNetCommand* CRehldsHookchains::HandleNetCommand() {
return &m_HandleNetCommand;
}
IRehldsHookRegistry_Mod_LoadBrushModel* CRehldsHookchains::Mod_LoadBrushModel() {
return &m_Mod_LoadBrushModel;
}
IRehldsHookRegistry_Mod_LoadStudioModel* CRehldsHookchains::Mod_LoadStudioModel() {
return &m_Mod_LoadStudioModel;
}
IRehldsHookRegistry_ExecuteServerStringCmd* CRehldsHookchains::ExecuteServerStringCmd() {
return &m_ExecuteServerStringCmd;
}
IRehldsHookRegistry_SV_EmitEvents* CRehldsHookchains::SV_EmitEvents() {
return &m_SV_EmitEvents;
}
IRehldsHookRegistry_EV_PlayReliableEvent* CRehldsHookchains::EV_PlayReliableEvent() {
return &m_EV_PlayReliableEvent;
}
IRehldsHookRegistry_SV_StartSound* CRehldsHookchains::SV_StartSound() {
return &m_SV_StartSound;
}
IRehldsHookRegistry_PF_Remove_I* CRehldsHookchains::PF_Remove_I() {
return &m_PF_Remove_I;
}
IRehldsHookRegistry_PF_BuildSoundMsg_I* CRehldsHookchains::PF_BuildSoundMsg_I() {
return &m_PF_BuildSoundMsg_I;
}
IRehldsHookRegistry_SV_WriteFullClientUpdate* CRehldsHookchains::SV_WriteFullClientUpdate() {
return &m_SV_WriteFullClientUpdate;
}
IRehldsHookRegistry_SV_CheckConsistencyResponse* CRehldsHookchains::SV_CheckConsistencyResponse() {
return &m_SV_CheckConsistencyResponse;
}
IRehldsHookRegistry_SV_DropClient* CRehldsHookchains::SV_DropClient() {
return &m_SV_DropClient;
}
IRehldsHookRegistry_SV_ActivateServer* CRehldsHookchains::SV_ActivateServer() {
return &m_SV_ActivateServer;
}
IRehldsHookRegistry_SV_WriteVoiceCodec* CRehldsHookchains::SV_WriteVoiceCodec() {
return &m_SV_WriteVoiceCodec;
}
IRehldsHookRegistry_Steam_GSGetSteamID* CRehldsHookchains::Steam_GSGetSteamID() {
return &m_Steam_GSGetSteamID;
}
IRehldsHookRegistry_SV_TransferConsistencyInfo* CRehldsHookchains::SV_TransferConsistencyInfo() {
return &m_SV_TransferConsistencyInfo;
}
IRehldsHookRegistry_Steam_GSBUpdateUserData* CRehldsHookchains::Steam_GSBUpdateUserData() {
return &m_Steam_GSBUpdateUserData;
}
IRehldsHookRegistry_Cvar_DirectSet* CRehldsHookchains::Cvar_DirectSet() {
return &m_Cvar_DirectSet;
}
IRehldsHookRegistry_SV_EstablishTimeBase* CRehldsHookchains::SV_EstablishTimeBase() {
return &m_SV_EstablishTimeBase;
}
IRehldsHookRegistry_SV_Spawn_f* CRehldsHookchains::SV_Spawn_f() {
return &m_SV_Spawn_f;
}
IRehldsHookRegistry_SV_CreatePacketEntities* CRehldsHookchains::SV_CreatePacketEntities() {
return &m_SV_CreatePacketEntities;
}
IRehldsHookRegistry_SV_EmitSound2* CRehldsHookchains::SV_EmitSound2() {
return &m_SV_EmitSound2;
}
IRehldsHookRegistry_CreateFakeClient* CRehldsHookchains::CreateFakeClient() {
return &m_CreateFakeClient;
}
IRehldsHookRegistry_SV_CheckConnectionLessRateLimits* CRehldsHookchains::SV_CheckConnectionLessRateLimits()
{
return &m_SV_CheckConnectionLessRateLimits;
}
int EXT_FUNC CRehldsApi::GetMajorVersion()
{
return REHLDS_API_VERSION_MAJOR;
}
int EXT_FUNC CRehldsApi::GetMinorVersion()
{
return REHLDS_API_VERSION_MINOR;
}
const RehldsFuncs_t* EXT_FUNC CRehldsApi::GetFuncs()
{
return &g_RehldsApiFuncs;
}
IRehldsHookchains* EXT_FUNC CRehldsApi::GetHookchains()
{
return &g_RehldsHookchains;
}
IRehldsServerStatic* EXT_FUNC CRehldsApi::GetServerStatic() {
return &g_RehldsServerStatic;
}
IRehldsServerData* EXT_FUNC CRehldsApi::GetServerData() {
return &g_RehldsServerData;
}
IRehldsFlightRecorder* EXT_FUNC CRehldsApi::GetFlightRecorder() {
return g_FlightRecorder;
}
EXPOSE_SINGLE_INTERFACE(CRehldsApi, IRehldsApi, VREHLDS_HLDS_API_VERSION);