diff --git a/dep/rehlsdk/common/BaseSystemModule.cpp b/dep/rehlsdk/common/BaseSystemModule.cpp new file mode 100644 index 0000000..3233b54 --- /dev/null +++ b/dep/rehlsdk/common/BaseSystemModule.cpp @@ -0,0 +1,164 @@ +/* +* +* 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" + +BaseSystemModule::BaseSystemModule() +{ + m_System = nullptr; + m_Serial = 0; + m_SystemTime = 0; + m_State = MODULE_UNDEFINED; + + Q_memset(m_Name, 0, sizeof(m_Name)); +} + +char *BaseSystemModule::GetName() +{ + return m_Name; +} + +char *BaseSystemModule::GetType() +{ + return "GenericModule"; +} + +char *BaseSystemModule::GetStatusLine() +{ + return "No status available.\n"; +} + +void BaseSystemModule::ExecuteCommand(int commandID, char *commandLine) +{ + m_System->DPrintf("WARNING! Undeclared ExecuteCommand().\n"); +} + +extern int COM_BuildNumber(); + +int BaseSystemModule::GetVersion() +{ + return COM_BuildNumber(); +} + +int BaseSystemModule::GetSerial() +{ + return m_Serial; +} + +IBaseSystem *BaseSystemModule::GetSystem() +{ + return m_System; +} + +bool BaseSystemModule::Init(IBaseSystem *system, int serial, char *name) +{ + if (!system) + return false; + + m_State = MODULE_INITIALIZING; + m_System = system; + m_Serial = serial; + m_SystemTime = 0; + + if (name) { + Q_strlcpy(m_Name, name); + } + + return true; +} + +void BaseSystemModule::RunFrame(double time) +{ + m_SystemTime = time; +} + +void BaseSystemModule::ShutDown() +{ + if (m_State == MODULE_DISCONNECTED) + return; + + m_Listener.Clear(); + m_State = MODULE_DISCONNECTED; + + if (!m_System->RemoveModule(this)) + { + m_System->DPrintf("ERROR! BaseSystemModule::ShutDown: faild to remove module %s.\n", m_Name); + } +} + +void BaseSystemModule::RegisterListener(ISystemModule *module) +{ + ISystemModule *listener = (ISystemModule *)m_Listener.GetFirst(); + while (listener) + { + if (listener->GetSerial() == module->GetSerial()) + { + m_System->DPrintf("WARNING! BaseSystemModule::RegisterListener: module %s already added.\n", module->GetName()); + return; + } + + listener = (ISystemModule *)m_Listener.GetNext(); + } + + m_Listener.Add(module); +} + +void BaseSystemModule::RemoveListener(ISystemModule *module) +{ + ISystemModule *listener = (ISystemModule *)m_Listener.GetFirst(); + while (listener) + { + if (listener->GetSerial() == module->GetSerial()) + { + m_Listener.Remove(module); + return; + } + + listener = (ISystemModule *)m_Listener.GetNext(); + } +} + +void BaseSystemModule::FireSignal(unsigned int signal, void *data) +{ + ISystemModule *listener = (ISystemModule *)m_Listener.GetFirst(); + while (listener) + { + listener->ReceiveSignal(this, signal, data); + listener = (ISystemModule *)m_Listener.GetNext(); + } +} + +void BaseSystemModule::ReceiveSignal(ISystemModule *module, unsigned int signal, void *data) +{ + m_System->DPrintf("WARNING! Unhandled signal (%i) from module %s.\n", signal, module->GetName()); +} + +int BaseSystemModule::GetState() +{ + return m_State; +} diff --git a/dep/rehlsdk/common/BaseSystemModule.h b/dep/rehlsdk/common/BaseSystemModule.h new file mode 100644 index 0000000..f4998b4 --- /dev/null +++ b/dep/rehlsdk/common/BaseSystemModule.h @@ -0,0 +1,75 @@ +/* +* +* 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. +* +*/ + +#pragma once + +#include "ObjectList.h" +#include "IBaseSystem.h" + +// C4250 - 'class1' : inherits 'BaseSystemModule::member' via dominance +#pragma warning(disable:4250) + +class BaseSystemModule: virtual public ISystemModule { +public: + BaseSystemModule(); + virtual ~BaseSystemModule() {} + + EXT_FUNC virtual bool Init(IBaseSystem *system, int serial, char *name); + EXT_FUNC virtual void RunFrame(double time); + EXT_FUNC virtual void ReceiveSignal(ISystemModule *module, unsigned int signal, void *data); + EXT_FUNC virtual void ExecuteCommand(int commandID, char *commandLine); + EXT_FUNC virtual void RegisterListener(ISystemModule *module); + EXT_FUNC virtual void RemoveListener(ISystemModule *module); + EXT_FUNC virtual IBaseSystem *GetSystem(); + EXT_FUNC virtual int GetSerial(); + EXT_FUNC virtual char *GetStatusLine(); + EXT_FUNC virtual char *GetType(); + EXT_FUNC virtual char *GetName(); + + enum ModuleState { + MODULE_UNDEFINED = 0, + MODULE_INITIALIZING, + MODULE_CONNECTING, + MODULE_RUNNING, + MODULE_DISCONNECTED + }; + + EXT_FUNC virtual int GetState(); + EXT_FUNC virtual int GetVersion(); + EXT_FUNC virtual void ShutDown(); + EXT_FUNC virtual char *GetBaseDir() { return ""; } + void FireSignal(unsigned int signal, void *data = nullptr); + +protected: + IBaseSystem *m_System; + ObjectList m_Listener; + char m_Name[255]; + unsigned int m_State; + unsigned int m_Serial; + double m_SystemTime; +}; diff --git a/dep/rehlsdk/common/IAdminServer.h b/dep/rehlsdk/common/IAdminServer.h new file mode 100644 index 0000000..ab367ce --- /dev/null +++ b/dep/rehlsdk/common/IAdminServer.h @@ -0,0 +1,54 @@ +/* +* +* 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. +* +*/ + +#pragma once + +#include "interface.h" + +// handle to a game window +typedef unsigned int ManageServerUIHandle_t; +class IManageServer; + +// Purpose: Interface to server administration functions +class IAdminServer: public IBaseInterface +{ +public: + // opens a manage server dialog for a local server + virtual ManageServerUIHandle_t OpenManageServerDialog(const char *serverName, const char *gameDir) = 0; + + // opens a manage server dialog to a remote server + virtual ManageServerUIHandle_t OpenManageServerDialog(unsigned int gameIP, unsigned int gamePort, const char *password) = 0; + + // forces the game info dialog closed + virtual void CloseManageServerDialog(ManageServerUIHandle_t gameDialog) = 0; + + // Gets a handle to the interface + virtual IManageServer *GetManageServerInterface(ManageServerUIHandle_t handle) = 0; +}; + +#define ADMINSERVER_INTERFACE_VERSION "AdminServer002" diff --git a/dep/rehlsdk/common/IBaseSystem.h b/dep/rehlsdk/common/IBaseSystem.h new file mode 100644 index 0000000..9f50fe3 --- /dev/null +++ b/dep/rehlsdk/common/IBaseSystem.h @@ -0,0 +1,91 @@ +/* +* +* 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. +* +*/ + +#pragma once + +#if defined(_WIN32) + #define LIBRARY_PREFIX "dll" +#elif defined(OSX) + #define LIBRARY_PREFIX "dylib" +#else + #define LIBRARY_PREFIX "so" +#endif + +#include "ISystemModule.h" +#include "IVGuiModule.h" + +class Panel; +class ObjectList; +class IFileSystem; + +class IBaseSystem: virtual public ISystemModule { +public: + virtual ~IBaseSystem() {} + + virtual double GetTime() = 0; + virtual unsigned int GetTick() = 0; + virtual void SetFPS(float fps) = 0; + + virtual void Printf(char *fmt, ...) = 0; + virtual void DPrintf(char *fmt, ...) = 0; + + virtual void RedirectOutput(char *buffer = nullptr, int maxSize = 0) = 0; + + virtual IFileSystem *GetFileSystem() = 0; + virtual unsigned char *LoadFile(const char *name, int *length = nullptr) = 0; + virtual void FreeFile(unsigned char *fileHandle) = 0; + + virtual void SetTitle(char *text) = 0; + virtual void SetStatusLine(char *text) = 0; + + virtual void ShowConsole(bool visible) = 0; + virtual void LogConsole(char *filename) = 0; + + virtual bool InitVGUI(IVGuiModule *module) = 0; + +#ifdef _WIN32 + virtual Panel *GetPanel() = 0; +#endif // _WIN32 + + virtual bool RegisterCommand(char *name, ISystemModule *module, int commandID) = 0; + virtual void GetCommandMatches(char *string, ObjectList *pMatchList) = 0; + virtual void ExecuteString(char *commands) = 0; + virtual void ExecuteFile(char *filename) = 0; + virtual void Errorf(char *fmt, ...) = 0; + + virtual char *CheckParam(char *param) = 0; + + virtual bool AddModule(ISystemModule *module, char *name) = 0; + virtual ISystemModule *GetModule(char *interfacename, char *library, char *instancename = nullptr) = 0; + virtual bool RemoveModule(ISystemModule *module) = 0; + + virtual void Stop() = 0; + virtual char *GetBaseDir() = 0; +}; + +#define BASESYSTEM_INTERFACE_VERSION "basesystem002" diff --git a/dep/rehlsdk/common/IDemoPlayer.h b/dep/rehlsdk/common/IDemoPlayer.h new file mode 100644 index 0000000..2431b54 --- /dev/null +++ b/dep/rehlsdk/common/IDemoPlayer.h @@ -0,0 +1,93 @@ +/* +* +* 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. +* +*/ + +#pragma once + +#include "ref_params.h" + +class IWorld; +class IProxy; +class DirectorCmd; +class IBaseSystem; +class ISystemModule; +class IObjectContainer; + +class IDemoPlayer { +public: + virtual ~IDemoPlayer() {} + + virtual bool Init(IBaseSystem *system, int serial, char *name) = 0; + virtual void RunFrame(double time) = 0; + virtual void ReceiveSignal(ISystemModule *module, unsigned int signal, void *data) = 0; + virtual void ExecuteCommand(int commandID, char *commandLine) = 0; + virtual void RegisterListener(ISystemModule *module) = 0; + virtual void RemoveListener(ISystemModule *module) = 0; + virtual IBaseSystem *GetSystem() = 0; + virtual int GetSerial() = 0; + virtual char *GetStatusLine() = 0; + virtual char *GetType() = 0; + virtual char *GetName() = 0; + virtual int GetState() = 0; + virtual int GetVersion() = 0; + virtual void ShutDown() = 0; + + virtual void NewGame(IWorld *world, IProxy *proxy = nullptr) = 0; + virtual char *GetModName() = 0; + virtual void WriteCommands(BitBuffer *stream, float startTime, float endTime) = 0; + virtual int AddCommand(DirectorCmd *cmd) = 0; + virtual bool RemoveCommand(int index) = 0; + virtual DirectorCmd *GetLastCommand() = 0; + virtual IObjectContainer *GetCommands() = 0; + virtual void SetWorldTime(double time, bool relative) = 0; + virtual void SetTimeScale(float scale) = 0; + virtual void SetPaused(bool state) = 0; + virtual void SetEditMode(bool state) = 0; + virtual void SetMasterMode(bool state) = 0; + virtual bool IsPaused() = 0; + virtual bool IsLoading() = 0; + virtual bool IsActive() = 0; + virtual bool IsEditMode() = 0; + virtual bool IsMasterMode() = 0; + virtual void RemoveFrames(double starttime, double endtime) = 0; + virtual void ExecuteDirectorCmd(DirectorCmd *cmd) = 0; + virtual double GetWorldTime() = 0; + virtual double GetStartTime() = 0; + virtual double GetEndTime() = 0; + virtual float GetTimeScale() = 0; + virtual IWorld *GetWorld() = 0; + virtual char *GetFileName() = 0; + virtual bool SaveGame(char *filename) = 0; + virtual bool LoadGame(char *filename) = 0; + virtual void Stop() = 0; + virtual void ForceHLTV(bool state) = 0; + virtual void GetDemoViewInfo(ref_params_t *rp, float *view, int *viewmodel) = 0; + virtual int ReadDemoMessage(unsigned char *buffer, int size) = 0; + virtual void ReadNetchanState(int *incoming_sequence, int *incoming_acknowledged, int *incoming_reliable_acknowledged, int *incoming_reliable_sequence, int *outgoing_sequence, int *reliable_sequence, int *last_reliable_sequence) = 0; +}; + +#define DEMOPLAYER_INTERFACE_VERSION "demoplayer001" diff --git a/dep/rehlsdk/common/IEngineWrapper.h b/dep/rehlsdk/common/IEngineWrapper.h new file mode 100644 index 0000000..0a58d4c --- /dev/null +++ b/dep/rehlsdk/common/IEngineWrapper.h @@ -0,0 +1,56 @@ +/* +* +* 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. +* +*/ + +#pragma once + +#include "event_args.h" +#include "vmodes.h" +#include "cdll_int.h" + +class IBaseSystem; +class ISystemModule; + +class IEngineWrapper: virtual public ISystemModule { +public: + virtual ~IEngineWrapper() {} + + virtual bool GetViewOrigin(float *origin) = 0; + virtual bool GetViewAngles(float *angles) = 0; + virtual int GetTraceEntity() = 0; + virtual float GetCvarFloat(char *szName) = 0; + virtual char *GetCvarString(char *szName) = 0; + virtual void SetCvar(char *szName, char *szValue) = 0; + virtual void Cbuf_AddText(char *text) = 0; + virtual void DemoUpdateClientData(client_data_t *cdat) = 0; + virtual void CL_QueueEvent(int flags, int index, float delay, event_args_t *pargs) = 0; + virtual void HudWeaponAnim(int iAnim, int body) = 0; + virtual void CL_DemoPlaySound(int channel, char *sample, float attenuation, float volume, int flags, int pitch) = 0; + virtual void ClientDLL_ReadDemoBuffer(int size, unsigned char *buffer) = 0; +}; + +#define ENGINEWRAPPER_INTERFACE_VERSION "enginewrapper001" diff --git a/dep/rehlsdk/common/IObjectContainer.h b/dep/rehlsdk/common/IObjectContainer.h new file mode 100644 index 0000000..333e9d0 --- /dev/null +++ b/dep/rehlsdk/common/IObjectContainer.h @@ -0,0 +1,47 @@ +/* +* +* 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. +* +*/ + +#pragma once + +class IObjectContainer { +public: + virtual ~IObjectContainer() {} + + virtual void Init() = 0; + + virtual bool Add(void *newObject) = 0; + virtual bool Remove(void *object) = 0; + virtual void Clear(bool freeElementsMemory) = 0; + + virtual void *GetFirst() = 0; + virtual void *GetNext() = 0; + + virtual int CountElements() = 0; + virtual bool Contains(void *object) = 0; + virtual bool IsEmpty() = 0; +}; diff --git a/dep/rehlsdk/common/ISystemModule.h b/dep/rehlsdk/common/ISystemModule.h new file mode 100644 index 0000000..9004a95 --- /dev/null +++ b/dep/rehlsdk/common/ISystemModule.h @@ -0,0 +1,57 @@ +/* +* +* 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. +* +*/ + +#pragma once + +#include "interface.h" + +class IBaseSystem; +class ISystemModule; + +class ISystemModule: public IBaseInterface { +public: + virtual ~ISystemModule() {} + virtual bool Init(IBaseSystem *system, int serial, char *name) = 0; + + virtual void RunFrame(double time) = 0; + virtual void ReceiveSignal(ISystemModule *module, unsigned int signal, void *data = nullptr) = 0; + virtual void ExecuteCommand(int commandID, char *commandLine) = 0; + virtual void RegisterListener(ISystemModule *module) = 0; + virtual void RemoveListener(ISystemModule *module) = 0; + + virtual IBaseSystem *GetSystem() = 0; + + virtual int GetSerial() = 0; + virtual char *GetStatusLine() = 0; + virtual char *GetType() = 0; + virtual char *GetName() = 0; + + virtual int GetState() = 0; + virtual int GetVersion() = 0; + virtual void ShutDown() = 0; +}; diff --git a/dep/rehlsdk/common/IVGuiModule.h b/dep/rehlsdk/common/IVGuiModule.h new file mode 100644 index 0000000..e6864c8 --- /dev/null +++ b/dep/rehlsdk/common/IVGuiModule.h @@ -0,0 +1,76 @@ +/* +* +* 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. +* +*/ + +#pragma once + +#include +#include "interface.h" + +// Purpose: Standard interface to loading vgui modules +class IVGuiModule: public IBaseInterface +{ +public: + // called first to setup the module with the vgui + // returns true on success, false on failure + virtual bool Initialize(CreateInterfaceFn *vguiFactories, int factoryCount) = 0; + + // called after all the modules have been initialized + // modules should use this time to link to all the other module interfaces + virtual bool PostInitialize(CreateInterfaceFn *modules = nullptr, int factoryCount = 0) = 0; + + // called when the module is selected from the menu or otherwise activated + virtual bool Activate() = 0; + + // returns true if the module is successfully initialized and available + virtual bool IsValid() = 0; + + // requests that the UI is temporarily disabled and all data files saved + virtual void Deactivate() = 0; + + // restart from a Deactivate() + virtual void Reactivate() = 0; + + // called when the module is about to be shutdown + virtual void Shutdown() = 0; + + // returns a handle to the main module panel + virtual vgui2::VPANEL GetPanel() = 0; + + // sets the parent of the main module panel + virtual void SetParent(vgui2::VPANEL parent) = 0; + + // messages sent through through the panel returned by GetPanel(): + // + // "ConnectedToGame" "ip" "port" "gamedir" + // "DisconnectedFromGame" + // "ActiveGameName" "name" + // "LoadingStarted" "type" "name" + // "LoadingFinished" "type" "name" +}; + +#define VGUIMODULE_INTERFACE_VERSION "VGuiModuleAdminServer001" diff --git a/dep/rehlsdk/common/ObjectDictionary.cpp b/dep/rehlsdk/common/ObjectDictionary.cpp new file mode 100644 index 0000000..84a0f88 --- /dev/null +++ b/dep/rehlsdk/common/ObjectDictionary.cpp @@ -0,0 +1,515 @@ +/* +* +* 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" + +ObjectDictionary::ObjectDictionary() +{ + m_currentEntry = 0; + m_findKey = 0; + m_entries = nullptr; + + Q_memset(m_cache, 0, sizeof(m_cache)); + + m_cacheIndex = 0; + m_size = 0; + m_maxSize = 0; +} + +ObjectDictionary::~ObjectDictionary() +{ + if (m_entries) { + Mem_Free(m_entries); + } +} + +void ObjectDictionary::Clear(bool freeObjectssMemory) +{ + if (freeObjectssMemory) + { + for (int i = 0; i < m_size; i++) + { + void *obj = m_entries[i].object; + if (obj) { + Mem_Free(obj); + } + } + } + + m_size = 0; + CheckSize(); + ClearCache(); +} + +bool ObjectDictionary::Add(void *object, float key) +{ + if (m_size == m_maxSize && !CheckSize()) + return false; + + entry_t *p; + if (m_size && key < m_entries[m_size - 1].key) + { + p = &m_entries[FindClosestAsIndex(key)]; + + entry_t *e1 = &m_entries[m_size]; + entry_t *e2 = &m_entries[m_size - 1]; + + while (p->key <= key) { p++; } + while (p != e1) + { + e1->object = e2->object; + e1->key = e2->key; + + e1--; + e2--; + } + } + else + p = &m_entries[m_size]; + + p->key = key; + p->object = object; + m_size++; + + ClearCache(); + AddToCache(p); + + return true; +} + +int ObjectDictionary::FindClosestAsIndex(float key) +{ + if (m_size <= 0) + return -1; + + if (key <= m_entries->key) + return 0; + + int index = FindKeyInCache(key); + if (index >= 0) { + return index; + } + + int middle; + int first = 0; + int last = m_size - 1; + float keyMiddle, keyNext; + + if (key < m_entries[last].key) + { + while (true) + { + middle = (last + first) >> 1; + keyMiddle = m_entries[middle].key; + + if (keyMiddle == key) + break; + + if (keyMiddle < key) + { + if (m_entries[middle + 1].key >= key) + { + if (m_entries[middle + 1].key - key < key - keyMiddle) + ++middle; + break; + } + + first = (last + first) >> 1; + } + else + { + last = (last + first) >> 1; + } + } + } + else + { + middle = last; + } + + keyNext = m_entries[middle - 1].key; + while (keyNext == key) { + keyNext = m_entries[middle--].key; + } + + AddToCache(&m_entries[middle], key); + return middle; +} + +void ObjectDictionary::ClearCache() +{ + Q_memset(m_cache, 0, sizeof(m_cache)); + m_cacheIndex = 0; +} + +bool ObjectDictionary::RemoveIndex(int index, bool freeObjectMemory) +{ + if (index < 0 || index >= m_size) + return false; + + entry_t *p = &m_entries[m_size - 1]; + entry_t *e1 = &m_entries[index]; + entry_t *e2 = &m_entries[index + 1]; + + if (freeObjectMemory && e1->object) + Mem_Free(e1->object); + + while (p != e1) + { + e1->object = e2->object; + e1->key = e2->key; + + e1++; + e2++; + } + + p->object = nullptr; + p->key = 0; + m_size--; + + CheckSize(); + ClearCache(); + + return false; +} + +bool ObjectDictionary::RemoveIndexRange(int minIndex, int maxIndex) +{ + if (minIndex > maxIndex) + { + if (maxIndex < 0) + maxIndex = 0; + + if (minIndex >= m_size) + minIndex = m_size - 1; + } + else + { + if (minIndex < 0) + minIndex = 0; + + if (maxIndex >= m_size) + maxIndex = m_size - 1; + } + + int offset = minIndex + maxIndex - 1; + m_size -= offset; + CheckSize(); + return true; +} + +bool ObjectDictionary::Remove(void *object) +{ + bool found = false; + for (int i = 0; i < m_size; i++) + { + if (m_entries[i].object == object) { + RemoveIndex(i); + found = true; + } + } + + return found ? true : false; +} + +bool ObjectDictionary::RemoveSingle(void *object) +{ + for (int i = 0; i < m_size; i++) + { + if (m_entries[i].object == object) { + RemoveIndex(i); + return true; + } + } + + return false; +} + +bool ObjectDictionary::RemoveKey(float key) +{ + int i = FindClosestAsIndex(key); + if (m_entries[i].key == key) + { + int j = i; + do { + ++j; + } + while (key == m_entries[j + 1].key); + + return RemoveIndexRange(i, j); + } + + return false; +} + +bool ObjectDictionary::CheckSize() +{ + int newSize = m_maxSize; + if (m_size == m_maxSize) + { + newSize = 1 - (int)(m_maxSize * -1.25f); + } + else if (m_maxSize * 0.5f > m_size) + { + newSize = (int)(m_maxSize * 0.75f); + } + + if (newSize != m_maxSize) + { + entry_t *newEntries = (entry_t *)Mem_Malloc(sizeof(entry_t) * newSize); + if (!newEntries) + return false; + + Q_memset(&newEntries[m_size], 0, sizeof(entry_t) * (newSize - m_size)); + + if (m_entries && m_size) + { + Q_memcpy(newEntries, m_entries, sizeof(entry_t) * m_size); + Mem_Free(m_entries); + } + + m_entries = newEntries; + m_maxSize = newSize; + } + + return true; +} + +void ObjectDictionary::Init() +{ + m_size = 0; + m_maxSize = 0; + m_entries = nullptr; + + CheckSize(); + ClearCache(); +} + +void ObjectDictionary::Init(int baseSize) +{ + m_size = 0; + m_maxSize = 0; + m_entries = (entry_t *)Mem_ZeroMalloc(sizeof(entry_t) * baseSize); + + if (m_entries) { + m_maxSize = baseSize; + } +} + +bool ObjectDictionary::Add(void *object) +{ + return Add(object, 0); +} + +int ObjectDictionary::CountElements() +{ + return m_size; +} + +bool ObjectDictionary::IsEmpty() +{ + return (m_size == 0) ? true : false; +} + +bool ObjectDictionary::Contains(void *object) +{ + if (FindObjectInCache(object) >= 0) + return true; + + for (int i = 0; i < m_size; i++) + { + entry_t *e = &m_entries[i]; + if (e->object == object) { + AddToCache(e); + return true; + } + } + + return false; +} + +void *ObjectDictionary::GetFirst() +{ + m_currentEntry = 0; + return GetNext(); +} + +void *ObjectDictionary::GetLast() +{ + return (m_size > 0) ? m_entries[m_size - 1].object : nullptr; +} + +bool ObjectDictionary::ChangeKey(void *object, float newKey) +{ + int pos = FindObjectInCache(object); + if (pos < 0) + { + for (pos = 0; pos < m_size; pos++) + { + if (m_entries[pos].object == object) { + AddToCache(&m_entries[pos]); + break; + } + } + + if (pos == m_size) { + return false; + } + } + + entry_t *p, *e; + + p = &m_entries[pos]; + if (p->key == newKey) + return false; + + int newpos = FindClosestAsIndex(newKey); + e = &m_entries[newpos]; + if (pos < newpos) + { + if (e->key > newKey) + e--; + + entry_t *e2 = &m_entries[pos + 1]; + while (p < e) + { + p->object = e2->object; + p->key = e2->key; + + p++; + e2++; + } + } + else if (pos > newpos) + { + if (e->key > newKey) + e++; + + entry_t *e2 = &m_entries[pos - 1]; + while (p > e) + { + p->object = e2->object; + p->key = e2->key; + + p--; + e2--; + } + } + + p->object = object; + p->key = newKey; + ClearCache(); + + return true; +} + +bool ObjectDictionary::UnsafeChangeKey(void *object, float newKey) +{ + int pos = FindObjectInCache(object); + if (pos < 0) + { + for (pos = 0; pos < m_size; pos++) + { + if (m_entries[pos].object == object) { + break; + } + } + + if (pos == m_size) { + return false; + } + } + + m_entries[pos].key = newKey; + ClearCache(); + return true; +} + +void ObjectDictionary::AddToCache(entry_t *entry) +{ + int i = (m_cacheIndex % MAX_OBJECT_CACHE); + + m_cache[i].object = entry; + m_cache[i].key = entry->key; + m_cacheIndex++; +} + +void ObjectDictionary::AddToCache(entry_t *entry, float key) +{ + int i = (m_cacheIndex % MAX_OBJECT_CACHE); + + m_cache[i].object = entry; + m_cache[i].key = key; + m_cacheIndex++; +} + +int ObjectDictionary::FindKeyInCache(float key) +{ + for (auto& ch : m_cache) + { + if (ch.object && ch.key == key) { + return (entry_t *)ch.object - m_entries; + } + } + + return -1; +} + +int ObjectDictionary::FindObjectInCache(void *object) +{ + for (auto& ch : m_cache) + { + if (ch.object && ch.object == object) { + return (entry_t *)ch.object - m_entries; + } + } + + return -1; +} + +void *ObjectDictionary::FindClosestKey(float key) +{ + m_currentEntry = FindClosestAsIndex(key); + return GetNext(); +} + +void *ObjectDictionary::GetNext() +{ + if (m_currentEntry < 0 || m_currentEntry >= m_size) + return nullptr; + + return m_entries[m_currentEntry++].object; +} + +void *ObjectDictionary::FindExactKey(float key) +{ + if ((m_currentEntry = FindClosestAsIndex(key)) < 0) + return nullptr; + + return (m_entries[m_currentEntry].key == key) ? GetNext() : nullptr; +} diff --git a/dep/rehlsdk/common/ObjectDictionary.h b/dep/rehlsdk/common/ObjectDictionary.h new file mode 100644 index 0000000..bf1b77f --- /dev/null +++ b/dep/rehlsdk/common/ObjectDictionary.h @@ -0,0 +1,94 @@ +/* +* +* 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. +* +*/ + +#pragma once + +#include "IObjectContainer.h" + +class ObjectDictionary: public IObjectContainer { +public: + ObjectDictionary(); + virtual ~ObjectDictionary(); + + void Init(); + void Init(int baseSize); + + bool Add(void *object); + bool Contains(void *object); + bool IsEmpty(); + int CountElements(); + + void Clear(bool freeObjectssMemory = false); + + bool Add(void *object, float key); + bool ChangeKey(void *object, float newKey); + bool UnsafeChangeKey(void *object, float newKey); + + bool Remove(void *object); + bool RemoveSingle(void *object); + bool RemoveKey(float key); + bool RemoveRange(float startKey, float endKey); + + void *FindClosestKey(float key); + void *FindExactKey(float key); + + void *GetFirst(); + void *GetLast(); + void *GetNext(); + + int FindKeyInCache(float key); + int FindObjectInCache(void *object); + + void ClearCache(); + bool CheckSize(); + + typedef struct entry_s { + void *object; + float key; + } entry_t; + + void AddToCache(entry_t *entry); + void AddToCache(entry_t *entry, float key); + + bool RemoveIndex(int index, bool freeObjectMemory = false); + bool RemoveIndexRange(int minIndex, int maxIndex); + int FindClosestAsIndex(float key); + +protected: + int m_currentEntry; + float m_findKey; + + enum { MAX_OBJECT_CACHE = 32 }; + + entry_t *m_entries; + entry_t m_cache[MAX_OBJECT_CACHE]; + + int m_cacheIndex; + int m_size; + int m_maxSize; +}; diff --git a/dep/rehlsdk/common/ObjectList.cpp b/dep/rehlsdk/common/ObjectList.cpp new file mode 100644 index 0000000..4518090 --- /dev/null +++ b/dep/rehlsdk/common/ObjectList.cpp @@ -0,0 +1,259 @@ +/* +* +* 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" + +ObjectList::ObjectList() +{ + m_head = m_tail = m_current = nullptr; + m_number = 0; +} + +ObjectList::~ObjectList() +{ + Clear(false); +} + +bool ObjectList::AddHead(void *newObject) +{ + // create new element + element_t *newElement = (element_t *)Mem_ZeroMalloc(sizeof(element_t)); + + // out of memory + if (!newElement) + return false; + + // insert element + newElement->object = newObject; + + if (m_head) + { + newElement->next = m_head; + m_head->prev = newElement; + } + + m_head = newElement; + + // if list was empty set new m_tail + if (!m_tail) + m_tail = m_head; + + m_number++; + return true; +} + +void *ObjectList::RemoveHead() +{ + void *retObj; + + // check m_head is present + if (m_head) + { + retObj = m_head->object; + element_t *newHead = m_head->next; + if (newHead) + newHead->prev = nullptr; + + // if only one element is in list also update m_tail + // if we remove this prev element + if (m_tail == m_head) + m_tail = nullptr; + + Mem_Free(m_head); + m_head = newHead; + + m_number--; + } + else + retObj = nullptr; + + return retObj; +} + +bool ObjectList::AddTail(void *newObject) +{ + // create new element + element_t *newElement = (element_t *)Mem_ZeroMalloc(sizeof(element_t)); + + // out of memory + if (!newElement) + return false; + + // insert element + newElement->object = newObject; + + if (m_tail) + { + newElement->prev = m_tail; + m_tail->next = newElement; + } + + m_tail = newElement; + + // if list was empty set new m_tail + if (!m_head) + m_head = m_tail; + + m_number++; + return true; +} + +void *ObjectList::RemoveTail() +{ + void *retObj; + + // check m_tail is present + if (m_tail) + { + retObj = m_tail->object; + element_t *newTail = m_tail->prev; + if (newTail) + newTail->next = nullptr; + + // if only one element is in list also update m_tail + // if we remove this prev element + if (m_head == m_tail) + m_head = nullptr; + + Mem_Free(m_tail); + m_tail = newTail; + + m_number--; + + } + else + retObj = nullptr; + + return retObj; +} + +bool ObjectList::IsEmpty() +{ + return (m_head == nullptr); +} + +int ObjectList::CountElements() +{ + return m_number; +} + +bool ObjectList::Contains(void *object) +{ + element_t *e = m_head; + + while (e && e->object != object) { e = e->next; } + + if (e) + { + m_current = e; + return true; + } + else + { + return false; + } +} + +void ObjectList::Clear(bool freeElementsMemory) +{ + element_t *ne; + element_t *e = m_head; + + while (e) + { + ne = e->next; + + if (freeElementsMemory && e->object) + Mem_Free(e->object); + + Mem_Free(e); + e = ne; + } + + m_head = m_tail = m_current = nullptr; + m_number = 0; +} + +bool ObjectList::Remove(void *object) +{ + element_t *e = m_head; + + while (e && e->object != object) { e = e->next; } + + if (e) + { + if (e->prev) e->prev->next = e->next; + if (e->next) e->next->prev = e->prev; + + if (m_head == e) m_head = e->next; + if (m_tail == e) m_tail = e->prev; + if (m_current == e) m_current= e->next; + + Mem_Free(e); + m_number--; + } + + return (e != nullptr); +} + +void ObjectList::Init() +{ + m_head = m_tail = m_current = nullptr; + m_number = 0; +} + +void *ObjectList::GetFirst() +{ + if (m_head) + { + m_current = m_head->next; + return m_head->object; + } + else + { + m_current = nullptr; + return nullptr; + } +} + +void *ObjectList::GetNext() +{ + void *retObj = nullptr; + if (m_current) + { + retObj = m_current->object; + m_current = m_current->next; + } + + return retObj; +} + +bool ObjectList::Add(void *newObject) +{ + return AddTail(newObject); +} diff --git a/dep/rehlsdk/common/ObjectList.h b/dep/rehlsdk/common/ObjectList.h new file mode 100644 index 0000000..aa023f8 --- /dev/null +++ b/dep/rehlsdk/common/ObjectList.h @@ -0,0 +1,65 @@ +/* +* +* 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. +* +*/ + +#pragma once + +#include "IObjectContainer.h" + +class ObjectList: public IObjectContainer { +public: + EXT_FUNC void Init(); + EXT_FUNC bool Add(void *newObject); + EXT_FUNC void *GetFirst(); + EXT_FUNC void *GetNext(); + + ObjectList(); + virtual ~ObjectList(); + + EXT_FUNC void Clear(bool freeElementsMemory = false); + EXT_FUNC int CountElements(); + void *RemoveTail(); + void *RemoveHead(); + + bool AddTail(void *newObject); + bool AddHead(void *newObject); + EXT_FUNC bool Remove(void *object); + EXT_FUNC bool Contains(void *object); + EXT_FUNC bool IsEmpty(); + + typedef struct element_s { + struct element_s *prev; // pointer to the last element or NULL + struct element_s *next; // pointer to the next elemnet or NULL + void *object; // the element's object + } element_t; + +protected: + element_t *m_head; // first element in list + element_t *m_tail; // last element in list + element_t *m_current; // current element in list + int m_number; +}; diff --git a/dep/rehlsdk/common/SteamAppStartUp.cpp b/dep/rehlsdk/common/SteamAppStartUp.cpp new file mode 100644 index 0000000..7f13f4b --- /dev/null +++ b/dep/rehlsdk/common/SteamAppStartUp.cpp @@ -0,0 +1,211 @@ +/* +* +* 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" + +#ifdef _WIN32 +#include "SteamAppStartup.h" + +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include +#include + +#define STEAM_PARM "-steam" + +bool FileExists(const char *fileName) +{ + struct _stat statbuf; + return (_stat(fileName, &statbuf) == 0); +} + +// Handles launching the game indirectly via steam +void LaunchSelfViaSteam(const char *params) +{ + // calculate the details of our launch + char appPath[MAX_PATH]; + ::GetModuleFileName((HINSTANCE)GetModuleHandle(NULL), appPath, sizeof(appPath)); + + // strip out the exe name + char *slash = Q_strrchr(appPath, '\\'); + if (slash) + { + *slash = '\0'; + } + + // save out our details to the registry + HKEY hKey; + if (ERROR_SUCCESS == RegOpenKey(HKEY_CURRENT_USER, "Software\\Valve\\Steam", &hKey)) + { + DWORD dwType = REG_SZ; + DWORD dwSize = static_cast(Q_strlen(appPath) + 1); + RegSetValueEx(hKey, "TempAppPath", NULL, dwType, (LPBYTE)appPath, dwSize); + dwSize = static_cast(Q_strlen(params) + 1); + RegSetValueEx(hKey, "TempAppCmdLine", NULL, dwType, (LPBYTE)params, dwSize); + // clear out the appID (since we don't know it yet) + dwType = REG_DWORD; + int appID = -1; + RegSetValueEx(hKey, "TempAppID", NULL, dwType, (LPBYTE)&appID, sizeof(appID)); + RegCloseKey(hKey); + } + + // search for an active steam instance + HWND hwnd = ::FindWindow("Valve_SteamIPC_Class", "Hidden Window"); + if (hwnd) + { + ::PostMessage(hwnd, WM_USER + 3, 0, 0); + } + else + { + // couldn't find steam, find and launch it + + // first, search backwards through our current set of directories + char steamExe[MAX_PATH] = ""; + char dir[MAX_PATH]; + + if (::GetCurrentDirectoryA(sizeof(dir), dir)) + { + char *slash = Q_strrchr(dir, '\\'); + while (slash) + { + // see if steam_dev.exe is in the directory first + slash[1] = '\0'; + Q_strcat(slash, "steam_dev.exe"); + FILE *f = fopen(dir, "rb"); + if (f) + { + // found it + fclose(f); + Q_strcpy(steamExe, dir); + break; + } + + // see if steam.exe is in the directory + slash[1] = '\0'; + Q_strcat(slash, "steam.exe"); + f = fopen(dir, "rb"); + if (f) + { + // found it + fclose(f); + Q_strcpy(steamExe, dir); + break; + } + + // kill the string at the slash + slash[0] = '\0'; + + // move to the previous slash + slash = Q_strrchr(dir, '\\'); + } + } + + if (!steamExe[0]) + { + // still not found, use the one in the registry + HKEY hKey; + if (ERROR_SUCCESS == RegOpenKey(HKEY_CURRENT_USER, "Software\\Valve\\Steam", &hKey)) + { + DWORD dwType; + DWORD dwSize = sizeof(steamExe); + RegQueryValueEx(hKey, "SteamExe", NULL, &dwType, (LPBYTE)steamExe, &dwSize); + RegCloseKey(hKey); + } + } + + if (!steamExe[0]) + { + // still no path, error + ::MessageBox(NULL, "Error running game: could not find steam.exe to launch", "Fatal Error", MB_OK | MB_ICONERROR); + return; + } + + // fix any slashes + for (char *slash = steamExe; *slash; slash++) + { + if (*slash == '/') + { + *slash = '\\'; + } + } + + // change to the steam directory + Q_strcpy(dir, steamExe); + char *delimiter = Q_strrchr(dir, '\\'); + if (delimiter) + { + *delimiter = '\0'; + _chdir(dir); + } + + // exec steam.exe, in silent mode, with the launch app param + char *args[4] = { steamExe, "-silent", "-applaunch", '\0' }; + _spawnv(_P_NOWAIT, steamExe, args); + } +} + +// Launches steam if necessary +bool ShouldLaunchAppViaSteam(const char *lpCmdLine, const char *steamFilesystemDllName, const char *stdioFilesystemDllName) +{ + // see if steam is on the command line + const char *steamStr = Q_strstr(lpCmdLine, STEAM_PARM); + + // check the character following it is a whitespace or null + if (steamStr) + { + const char *postChar = steamStr + Q_strlen(STEAM_PARM); + if (*postChar == 0 || isspace(*postChar)) + { + // we're running under steam already, let the app continue + return false; + } + } + + // we're not running under steam, see which filesystems are available + if (FileExists(stdioFilesystemDllName)) + { + // we're being run with a stdio filesystem, so we can continue without steam + return false; + } + + // make sure we have a steam filesystem available + if (!FileExists(steamFilesystemDllName)) + { + return false; + } + + // we have the steam filesystem, and no stdio filesystem, so we must need to be run under steam + // launch steam + LaunchSelfViaSteam(lpCmdLine); + return true; +} + +#endif // _WIN32 diff --git a/dep/rehlsdk/common/SteamAppStartUp.h b/dep/rehlsdk/common/SteamAppStartUp.h new file mode 100644 index 0000000..2b9fbe7 --- /dev/null +++ b/dep/rehlsdk/common/SteamAppStartUp.h @@ -0,0 +1,37 @@ +/* +* +* 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. +* +*/ + +#pragma once + +// Call this first thing at startup +// Works out if the app is a steam app that is being ran outside of steam, +// and if so, launches steam and tells it to run us as a steam app +// +// if it returns true, then exit +// if it ruturns false, then continue with normal startup +bool ShouldLaunchAppViaSteam(const char *cmdLine, const char *steamFilesystemDllName, const char *stdioFilesystemDllName); diff --git a/dep/rehlsdk/common/SteamCommon.h b/dep/rehlsdk/common/SteamCommon.h index 4d5eb40..6645099 100644 --- a/dep/rehlsdk/common/SteamCommon.h +++ b/dep/rehlsdk/common/SteamCommon.h @@ -36,7 +36,7 @@ extern "C" #if defined ( _WIN32 ) #ifdef STEAM_EXPORTS -#define STEAM_API __declspec(dllexport) +#define STEAM_API __declspec(dllexport) EXT_FUNC #else #define STEAM_API __declspec(dllimport) #endif @@ -45,7 +45,11 @@ extern "C" #else +#ifdef STEAM_EXPORTS +#define STEAM_API EXT_FUNC +#else #define STEAM_API /* */ +#endif #define STEAM_CALL /* */ #endif diff --git a/dep/rehlsdk/common/TextConsoleUnix.cpp b/dep/rehlsdk/common/TextConsoleUnix.cpp new file mode 100644 index 0000000..32671ae --- /dev/null +++ b/dep/rehlsdk/common/TextConsoleUnix.cpp @@ -0,0 +1,324 @@ +/* +* +* 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" + +#if !defined(_WIN32) + +#include "TextConsoleUnix.h" +#include "icommandline.h" + +#include +#include +#include +#include +#include +#include +#include + +CTextConsoleUnix console; + +CTextConsoleUnix::~CTextConsoleUnix() +{ + CTextConsoleUnix::ShutDown(); +} + +bool CTextConsoleUnix::Init(IBaseSystem *system) +{ + static struct termios termNew; + sigset_t block_ttou; + + sigemptyset(&block_ttou); + sigaddset(&block_ttou, SIGTTOU); + sigprocmask(SIG_BLOCK, &block_ttou, NULL); + + tty = stdout; + + // this code is for echo-ing key presses to the connected tty + // (which is != STDOUT) + if (isatty(STDIN_FILENO)) + { + tty = fopen(ctermid(NULL), "w+"); + if (!tty) + { + printf("Unable to open tty(%s) for output\n", ctermid(NULL)); + tty = stdout; + } + else + { + // turn buffering off + setbuf(tty, NULL); + } + } + else + { + tty = fopen("/dev/null", "w+"); + if (!tty) + { + tty = stdout; + } + } + + tcgetattr(STDIN_FILENO, &termStored); + + Q_memcpy(&termNew, &termStored, sizeof(struct termios)); + + // Disable canonical mode, and set buffer size to 1 byte + termNew.c_lflag &= (~ICANON); + termNew.c_cc[ VMIN ] = 1; + termNew.c_cc[ VTIME ] = 0; + + // disable echo + termNew.c_lflag &= (~ECHO); + + tcsetattr(STDIN_FILENO, TCSANOW, &termNew); + sigprocmask(SIG_UNBLOCK, &block_ttou, NULL); + + return CTextConsole::Init(system); +} + +void CTextConsoleUnix::ShutDown() +{ + sigset_t block_ttou; + + sigemptyset(&block_ttou); + sigaddset(&block_ttou, SIGTTOU); + sigprocmask(SIG_BLOCK, &block_ttou, NULL); + tcsetattr(STDIN_FILENO, TCSANOW, &termStored); + sigprocmask(SIG_UNBLOCK, &block_ttou, NULL); + + CTextConsole::ShutDown(); +} + +// return 0 if the kb isn't hit +int CTextConsoleUnix::kbhit() +{ + fd_set rfds; + struct timeval tv; + + // Watch stdin (fd 0) to see when it has input. + FD_ZERO(&rfds); + FD_SET(STDIN_FILENO, &rfds); + + // Return immediately. + tv.tv_sec = 0; + tv.tv_usec = 0; + + // Must be in raw or cbreak mode for this to work correctly. + return select(STDIN_FILENO + 1, &rfds, NULL, NULL, &tv) != -1 && FD_ISSET(STDIN_FILENO, &rfds); +} + +char *CTextConsoleUnix::GetLine() +{ + // early return for 99.999% case :) + if (!kbhit()) + return NULL; + + escape_sequence_t es; + + es = ESCAPE_CLEAR; + sigset_t block_ttou; + + sigemptyset(&block_ttou); + sigaddset(&block_ttou, SIGTTOU); + sigaddset(&block_ttou, SIGTTIN); + sigprocmask(SIG_BLOCK, &block_ttou, NULL); + + while (true) + { + if (!kbhit()) + break; + + int nLen; + char ch = 0; + int numRead = read(STDIN_FILENO, &ch, 1); + if (!numRead) + break; + + switch (ch) + { + case '\n': // Enter + es = ESCAPE_CLEAR; + + nLen = ReceiveNewline(); + if (nLen) + { + sigprocmask(SIG_UNBLOCK, &block_ttou, NULL); + return m_szConsoleText; + } + break; + + case 127: // Backspace + case '\b': // Backspace + es = ESCAPE_CLEAR; + ReceiveBackspace(); + break; + + case '\t': // TAB + es = ESCAPE_CLEAR; + ReceiveTab(); + break; + + case 27: // Escape character + es = ESCAPE_RECEIVED; + break; + + case '[': // 2nd part of escape sequence + case 'O': + case 'o': + switch (es) + { + case ESCAPE_CLEAR: + case ESCAPE_BRACKET_RECEIVED: + es = ESCAPE_CLEAR; + ReceiveStandardChar(ch); + break; + + case ESCAPE_RECEIVED: + es = ESCAPE_BRACKET_RECEIVED; + break; + } + break; + case 'A': + if (es == ESCAPE_BRACKET_RECEIVED) + { + es = ESCAPE_CLEAR; + ReceiveUpArrow(); + } + else + { + es = ESCAPE_CLEAR; + ReceiveStandardChar(ch); + } + break; + case 'B': + if (es == ESCAPE_BRACKET_RECEIVED) + { + es = ESCAPE_CLEAR; + ReceiveDownArrow(); + } + else + { + es = ESCAPE_CLEAR; + ReceiveStandardChar(ch); + } + break; + case 'C': + if (es == ESCAPE_BRACKET_RECEIVED) + { + es = ESCAPE_CLEAR; + ReceiveRightArrow(); + } + else + { + es = ESCAPE_CLEAR; + ReceiveStandardChar(ch); + } + break; + case 'D': + if (es == ESCAPE_BRACKET_RECEIVED) + { + es = ESCAPE_CLEAR; + ReceiveLeftArrow(); + } + else + { + es = ESCAPE_CLEAR; + ReceiveStandardChar(ch); + } + break; + default: + // Just eat this char if it's an unsupported escape + if (es != ESCAPE_BRACKET_RECEIVED) + { + // dont' accept nonprintable chars + if ((ch >= ' ') && (ch <= '~')) + { + es = ESCAPE_CLEAR; + ReceiveStandardChar(ch); + } + } + break; + } + + fflush(stdout); + } + + sigprocmask(SIG_UNBLOCK, &block_ttou, NULL); + return NULL; +} + +void CTextConsoleUnix::PrintRaw(char *pszMsg, int nChars) +{ + if (nChars == 0) + { + printf("%s", pszMsg); + } + else + { + for (int nCount = 0; nCount < nChars; nCount++) + { + putchar(pszMsg[ nCount ]); + } + } +} + +void CTextConsoleUnix::Echo(char *pszMsg, int nChars) +{ + if (nChars == 0) + { + fputs(pszMsg, tty); + } + else + { + for (int nCount = 0; nCount < nChars; nCount++) + { + fputc(pszMsg[ nCount ], tty); + } + } +} + +int CTextConsoleUnix::GetWidth() +{ + struct winsize ws; + int nWidth = 0; + + if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0) + { + nWidth = (int)ws.ws_col; + } + + if (nWidth <= 1) + { + nWidth = 80; + } + + return nWidth; +} + +#endif // !defined(_WIN32) diff --git a/dep/rehlsdk/common/TextConsoleUnix.h b/dep/rehlsdk/common/TextConsoleUnix.h new file mode 100644 index 0000000..b40cbc4 --- /dev/null +++ b/dep/rehlsdk/common/TextConsoleUnix.h @@ -0,0 +1,59 @@ +/* +* +* 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. +* +*/ + +#pragma once + +#include +#include "textconsole.h" + +enum escape_sequence_t +{ + ESCAPE_CLEAR, + ESCAPE_RECEIVED, + ESCAPE_BRACKET_RECEIVED +}; + +class CTextConsoleUnix: public CTextConsole { +public: + virtual ~CTextConsoleUnix(); + + bool Init(IBaseSystem *system = nullptr); + void ShutDown(); + void PrintRaw(char *pszMsg, int nChars = 0); + void Echo(char *pszMsg, int nChars = 0); + char *GetLine(); + int GetWidth(); + +private: + int kbhit(); + + struct termios termStored; + FILE *tty; +}; + +extern CTextConsoleUnix console; diff --git a/dep/rehlsdk/common/TextConsoleWin32.cpp b/dep/rehlsdk/common/TextConsoleWin32.cpp new file mode 100644 index 0000000..aeaefb3 --- /dev/null +++ b/dep/rehlsdk/common/TextConsoleWin32.cpp @@ -0,0 +1,282 @@ +/* +* +* 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" + +#if defined(_WIN32) + +CTextConsoleWin32 console; +#pragma comment(lib, "user32.lib") + +BOOL WINAPI ConsoleHandlerRoutine(DWORD CtrlType) +{ + // TODO ? + /*if (CtrlType != CTRL_C_EVENT && CtrlType != CTRL_BREAK_EVENT) + { + // don't quit on break or ctrl+c + m_System->Stop(); + }*/ + + return TRUE; +} + +// GetConsoleHwnd() helper function from MSDN Knowledge Base Article Q124103 +// needed, because HWND GetConsoleWindow(VOID) is not avaliable under Win95/98/ME +HWND GetConsoleHwnd() +{ + HWND hwndFound; // This is what is returned to the caller. + char pszNewWindowTitle[1024]; // Contains fabricated WindowTitle + char pszOldWindowTitle[1024]; // Contains original WindowTitle + + // Fetch current window title. + GetConsoleTitle(pszOldWindowTitle, sizeof(pszOldWindowTitle)); + + // Format a "unique" NewWindowTitle. + wsprintf(pszNewWindowTitle, "%d/%d", GetTickCount(), GetCurrentProcessId()); + + // Change current window title. + SetConsoleTitle(pszNewWindowTitle); + + // Ensure window title has been updated. + Sleep(40); + + // Look for NewWindowTitle. + hwndFound = FindWindow(nullptr, pszNewWindowTitle); + + // Restore original window title. + SetConsoleTitle(pszOldWindowTitle); + + return hwndFound; +} + +CTextConsoleWin32::~CTextConsoleWin32() +{ + CTextConsoleWin32::ShutDown(); +} + +bool CTextConsoleWin32::Init(IBaseSystem *system) +{ + if (!AllocConsole()) + m_System = system; + + SetTitle(m_System ? m_System->GetName() : "Console"); + + hinput = GetStdHandle(STD_INPUT_HANDLE); + houtput = GetStdHandle(STD_OUTPUT_HANDLE); + + if (!SetConsoleCtrlHandler(&ConsoleHandlerRoutine, TRUE)) { + Print("WARNING! TextConsole::Init: Could not attach console hook.\n"); + } + + Attrib = FOREGROUND_GREEN | FOREGROUND_INTENSITY | BACKGROUND_INTENSITY; + SetWindowPos(GetConsoleHwnd(), HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOREPOSITION | SWP_SHOWWINDOW); + + return CTextConsole::Init(system); +} + +void CTextConsoleWin32::ShutDown() +{ + FreeConsole(); + CTextConsole::ShutDown(); +} + +void CTextConsoleWin32::SetVisible(bool visible) +{ + ShowWindow(GetConsoleHwnd(), visible ? SW_SHOW : SW_HIDE); + m_ConsoleVisible = visible; +} + +char *CTextConsoleWin32::GetLine() +{ + while (true) + { + INPUT_RECORD recs[1024]; + unsigned long numread; + unsigned long numevents; + + if (!GetNumberOfConsoleInputEvents(hinput, &numevents)) + { + if (m_System) { + m_System->Errorf("CTextConsoleWin32::GetLine: !GetNumberOfConsoleInputEvents\n"); + } + + return nullptr; + } + + if (numevents <= 0) + break; + + if (!ReadConsoleInput(hinput, recs, ARRAYSIZE(recs), &numread)) + { + if (m_System) { + m_System->Errorf("CTextConsoleWin32::GetLine: !ReadConsoleInput\n"); + } + + return nullptr; + } + + if (numread == 0) + return nullptr; + + for (int i = 0; i < (int)numread; i++) + { + INPUT_RECORD *pRec = &recs[i]; + if (pRec->EventType != KEY_EVENT) + continue; + + if (pRec->Event.KeyEvent.bKeyDown) + { + // check for cursor keys + if (pRec->Event.KeyEvent.wVirtualKeyCode == VK_UP) + { + ReceiveUpArrow(); + } + else if (pRec->Event.KeyEvent.wVirtualKeyCode == VK_DOWN) + { + ReceiveDownArrow(); + } + else if (pRec->Event.KeyEvent.wVirtualKeyCode == VK_LEFT) + { + ReceiveLeftArrow(); + } + else if (pRec->Event.KeyEvent.wVirtualKeyCode == VK_RIGHT) + { + ReceiveRightArrow(); + } + else + { + int nLen; + char ch = pRec->Event.KeyEvent.uChar.AsciiChar; + switch (ch) + { + case '\r': // Enter + nLen = ReceiveNewline(); + if (nLen) + { + return m_szConsoleText; + } + break; + case '\b': // Backspace + ReceiveBackspace(); + break; + case '\t': // TAB + ReceiveTab(); + break; + default: + // dont' accept nonprintable chars + if ((ch >= ' ') && (ch <= '~')) + { + ReceiveStandardChar(ch); + } + break; + } + } + } + } + } + + return nullptr; +} + +void CTextConsoleWin32::PrintRaw(char *pszMsg, int nChars) +{ +#ifdef LAUNCHER_FIXES + char outputStr[2048]; + WCHAR unicodeStr[1024]; + + DWORD nSize = MultiByteToWideChar(CP_UTF8, 0, pszMsg, -1, NULL, 0); + if (nSize > sizeof(unicodeStr)) + return; + + MultiByteToWideChar(CP_UTF8, 0, pszMsg, -1, unicodeStr, nSize); + DWORD nLength = WideCharToMultiByte(CP_OEMCP, 0, unicodeStr, -1, 0, 0, NULL, NULL); + if (nLength > sizeof(outputStr)) + return; + + WideCharToMultiByte(CP_OEMCP, 0, unicodeStr, -1, outputStr, nLength, NULL, NULL); + WriteFile(houtput, outputStr, nChars ? nChars : Q_strlen(outputStr), NULL, NULL); +#else + WriteFile(houtput, pszMsg, nChars ? nChars : Q_strlen(pszMsg), NULL, NULL); +#endif +} + +void CTextConsoleWin32::Echo(char *pszMsg, int nChars) +{ + PrintRaw(pszMsg, nChars); +} + +int CTextConsoleWin32::GetWidth() +{ + CONSOLE_SCREEN_BUFFER_INFO csbi; + int nWidth = 0; + + if (GetConsoleScreenBufferInfo(houtput, &csbi)) { + nWidth = csbi.dwSize.X; + } + + if (nWidth <= 1) + nWidth = 80; + + return nWidth; +} + +void CTextConsoleWin32::SetStatusLine(char *pszStatus) +{ + Q_strncpy(statusline, pszStatus, sizeof(statusline) - 1); + statusline[sizeof(statusline) - 2] = '\0'; + UpdateStatus(); +} + +void CTextConsoleWin32::UpdateStatus() +{ + COORD coord; + DWORD dwWritten = 0; + WORD wAttrib[ 80 ]; + + for (int i = 0; i < 80; i++) + { + wAttrib[i] = Attrib; // FOREGROUND_GREEN | FOREGROUND_INTENSITY | BACKGROUND_INTENSITY; + } + + coord.X = coord.Y = 0; + + WriteConsoleOutputAttribute(houtput, wAttrib, 80, coord, &dwWritten); + WriteConsoleOutputCharacter(houtput, statusline, 80, coord, &dwWritten); +} + +void CTextConsoleWin32::SetTitle(char *pszTitle) +{ + SetConsoleTitle(pszTitle); +} + +void CTextConsoleWin32::SetColor(WORD attrib) +{ + Attrib = attrib; +} + +#endif // defined(_WIN32) diff --git a/dep/rehlsdk/common/TextConsoleWin32.h b/dep/rehlsdk/common/TextConsoleWin32.h new file mode 100644 index 0000000..656110e --- /dev/null +++ b/dep/rehlsdk/common/TextConsoleWin32.h @@ -0,0 +1,62 @@ +/* +* +* 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. +* +*/ + +#pragma once + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#include +#include "TextConsole.h" + +class CTextConsoleWin32: public CTextConsole { +public: + virtual ~CTextConsoleWin32(); + + bool Init(IBaseSystem *system = nullptr); + void ShutDown(); + + void SetTitle(char *pszTitle); + void SetStatusLine(char *pszStatus); + void UpdateStatus(); + + void PrintRaw(char * pszMsz, int nChars = 0); + void Echo(char * pszMsz, int nChars = 0); + char *GetLine(); + int GetWidth(); + + void SetVisible(bool visible); + void SetColor(WORD); + +private: + HANDLE hinput; // standard input handle + HANDLE houtput; // standard output handle + WORD Attrib; // attrib colours for status bar + + char statusline[81]; // first line in console is status line +}; + +extern CTextConsoleWin32 console; diff --git a/dep/rehlsdk/common/TokenLine.cpp b/dep/rehlsdk/common/TokenLine.cpp new file mode 100644 index 0000000..7f88555 --- /dev/null +++ b/dep/rehlsdk/common/TokenLine.cpp @@ -0,0 +1,132 @@ +#include "precompiled.h" + +TokenLine::TokenLine() +{ + Q_memset(m_token, 0, sizeof(m_token)); + Q_memset(m_fullLine, 0, sizeof(m_fullLine)); + Q_memset(m_tokenBuffer, 0, sizeof(m_tokenBuffer)); + + m_tokenNumber = 0; +} + +TokenLine::TokenLine(char *string) +{ + SetLine(string); +} + +TokenLine::~TokenLine() +{ + +} + +bool TokenLine::SetLine(const char *newLine) +{ + m_tokenNumber = 0; + + if (!newLine || (Q_strlen(newLine) >= (MAX_LINE_CHARS - 1))) + { + Q_memset(m_fullLine, 0, sizeof(m_fullLine)); + Q_memset(m_tokenBuffer, 0, sizeof(m_tokenBuffer)); + return false; + } + + Q_strlcpy(m_fullLine, newLine); + Q_strlcpy(m_tokenBuffer, newLine); + + // parse tokens + char *charPointer = m_tokenBuffer; + while (*charPointer && (m_tokenNumber < MAX_LINE_TOKENS)) + { + // skip nonprintable chars + while (*charPointer && ((*charPointer <= ' ') || (*charPointer > '~'))) + charPointer++; + + if (*charPointer) + { + m_token[m_tokenNumber] = charPointer; + + // special treatment for quotes + if (*charPointer == '\"') + { + charPointer++; + m_token[m_tokenNumber] = charPointer; + while (*charPointer && (*charPointer != '\"')) + charPointer++; + } + else + { + m_token[m_tokenNumber] = charPointer; + while (*charPointer && ((*charPointer > 32) && (*charPointer <= 126))) + charPointer++; + } + + m_tokenNumber++; + + if (*charPointer) + { + *charPointer = '\0'; + charPointer++; + } + } + } + + return (m_tokenNumber != MAX_LINE_TOKENS); +} + +char *TokenLine::GetLine() +{ + return m_fullLine; +} + +char *TokenLine::GetToken(int i) +{ + if (i >= m_tokenNumber) + return NULL; + + return m_token[i]; +} + +// if the given parm is not present return NULL +// otherwise return the address of the following token, or an empty string +char *TokenLine::CheckToken(char *parm) +{ + for (int i = 0; i < m_tokenNumber; i++) + { + if (!m_token[i]) + continue; + + if (!Q_strcmp(parm, m_token[i])) + { + char *ret = m_token[i + 1]; + + // if this token doesn't exist, since index i was the last + // return an empty string + if (m_tokenNumber == (i + 1)) + ret = ""; + + return ret; + } + } + + return NULL; +} + +int TokenLine::CountToken() +{ + int c = 0; + for (int i = 0; i < m_tokenNumber; i++) + { + if (m_token[i]) + c++; + } + + return c; +} + +char *TokenLine::GetRestOfLine(int i) +{ + if (i >= m_tokenNumber) + return NULL; + + return m_fullLine + (m_token[i] - m_tokenBuffer); +} diff --git a/dep/rehlsdk/common/TokenLine.h b/dep/rehlsdk/common/TokenLine.h new file mode 100644 index 0000000..0d16fb6 --- /dev/null +++ b/dep/rehlsdk/common/TokenLine.h @@ -0,0 +1,51 @@ +/* +* +* 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. +* +*/ + +#pragma once + +class TokenLine { +public: + TokenLine(); + TokenLine(char *string); + virtual ~TokenLine(); + + char *GetRestOfLine(int i); // returns all chars after token i + int CountToken(); // returns number of token + char *CheckToken(char *parm); // returns token after token parm or "" + char *GetToken(int i); // returns token i + char *GetLine(); // returns full line + bool SetLine(const char *newLine); // set new token line and parses it + +private: + enum { MAX_LINE_CHARS = 2048, MAX_LINE_TOKENS = 128 }; + + char m_tokenBuffer[MAX_LINE_CHARS]; + char m_fullLine[MAX_LINE_CHARS]; + char *m_token[MAX_LINE_TOKENS]; + int m_tokenNumber; +}; diff --git a/dep/rehlsdk/common/commandline.cpp b/dep/rehlsdk/common/commandline.cpp new file mode 100644 index 0000000..9be292c --- /dev/null +++ b/dep/rehlsdk/common/commandline.cpp @@ -0,0 +1,356 @@ +#include "precompiled.h" + +class CCommandLine: public ICommandLine { +public: + CCommandLine(); + virtual ~CCommandLine(); + + void CreateCmdLine(const char *commandline); + void CreateCmdLine(int argc, const char *argv[]); + const char *GetCmdLine() const; + + // Check whether a particular parameter exists + const char *CheckParm(const char *psz, char **ppszValue = nullptr) const; + void RemoveParm(const char *pszParm); + void AppendParm(const char *pszParm, const char *pszValues); + + void SetParm(const char *pszParm, const char *pszValues); + void SetParm(const char *pszParm, int iValue); + + // When the commandline contains @name, it reads the parameters from that file + void LoadParametersFromFile(const char *&pSrc, char *&pDst, int maxDestLen); + +private: + // Copy of actual command line + char *m_pszCmdLine; +}; + +CCommandLine g_CmdLine; +ICommandLine *cmdline = &g_CmdLine; + +ICommandLine *CommandLine() +{ + return &g_CmdLine; +} + +CCommandLine::CCommandLine() +{ + m_pszCmdLine = nullptr; +} + +CCommandLine::~CCommandLine() +{ + if (m_pszCmdLine) + { + delete [] m_pszCmdLine; + m_pszCmdLine = nullptr; + } +} + +char *CopyString(const char *src) +{ + if (!src) + return nullptr; + + char *out = (char *)new char[Q_strlen(src) + 1]; + Q_strcpy(out, src); + return out; +} + +// Creates a command line from the arguments passed in +void CCommandLine::CreateCmdLine(int argc, const char *argv[]) +{ + char cmdline[4096] = ""; + const int MAX_CHARS = sizeof(cmdline) - 1; + + for (int i = 0; i < argc; ++i) + { + if (Q_strchr(argv[i], ' ')) + { + Q_strlcat(cmdline, "\""); + Q_strlcat(cmdline, argv[i]); + Q_strlcat(cmdline, "\""); + } + else + { + Q_strlcat(cmdline, argv[i]); + } + + Q_strlcat(cmdline, " "); + } + + cmdline[Q_strlen(cmdline)] = '\0'; + CreateCmdLine(cmdline); +} + +void CCommandLine::LoadParametersFromFile(const char *&pSrc, char *&pDst, int maxDestLen) +{ + // Suck out the file name + char szFileName[ MAX_PATH ]; + char *pOut; + char *pDestStart = pDst; + + // Skip the @ sign + pSrc++; + pOut = szFileName; + + while (*pSrc && *pSrc != ' ') + { + *pOut++ = *pSrc++; +#if 0 + if ((pOut - szFileName) >= (MAX_PATH - 1)) + break; +#endif + } + + *pOut = '\0'; + + // Skip the space after the file name + if (*pSrc) + pSrc++; + + // Now read in parameters from file + FILE *fp = fopen(szFileName, "r"); + if (fp) + { + char c; + c = (char)fgetc(fp); + while (c != EOF) + { + // Turn return characters into spaces + if (c == '\n') + c = ' '; + + *pDst++ = c; + +#if 0 + // Don't go past the end, and allow for our terminating space character AND a terminating null character. + if ((pDst - pDestStart) >= (maxDestLen - 2)) + break; +#endif + + // Get the next character, if there are more + c = (char)fgetc(fp); + } + + // Add a terminating space character + *pDst++ = ' '; + + fclose(fp); + } + else + { + printf("Parameter file '%s' not found, skipping...", szFileName); + } +} + +// Purpose: Create a command line from the passed in string +// Note that if you pass in a @filename, then the routine will read settings from a file instead of the command line +void CCommandLine::CreateCmdLine(const char *commandline) +{ + if (m_pszCmdLine) + { + delete[] m_pszCmdLine; + m_pszCmdLine = nullptr; + } + + char szFull[4096]; + + char *pDst = szFull; + const char *pSrc = commandline; + + bool allowAtSign = true; + + while (*pSrc) + { + if (*pSrc == '@') + { + if (allowAtSign) + { + LoadParametersFromFile(pSrc, pDst, sizeof(szFull) - (pDst - szFull)); + continue; + } + } + + allowAtSign = isspace(*pSrc) != 0; + +#if 0 + // Don't go past the end. + if ((pDst - szFull) >= (sizeof(szFull) - 1)) + break; +#endif + *pDst++ = *pSrc++; + } + + *pDst = '\0'; + + int len = Q_strlen(szFull) + 1; + m_pszCmdLine = new char[len]; + Q_memcpy(m_pszCmdLine, szFull, len); +} + +// Purpose: Remove specified string ( and any args attached to it ) from command line +void CCommandLine::RemoveParm(const char *pszParm) +{ + if (!m_pszCmdLine) + return; + + if (!pszParm || *pszParm == '\0') + return; + + // Search for first occurrence of pszParm + char *p, *found; + char *pnextparam; + int n; + int curlen; + + p = m_pszCmdLine; + while (*p) + { + curlen = Q_strlen(p); + found = Q_strstr(p, pszParm); + + if (!found) + break; + + pnextparam = found + 1; + while (pnextparam && *pnextparam && (*pnextparam != '-') && (*pnextparam != '+')) + pnextparam++; + + if (pnextparam && *pnextparam) + { + // We are either at the end of the string, or at the next param. Just chop out the current param. + // # of characters after this param. + n = curlen - (pnextparam - p); + + Q_memcpy(found, pnextparam, n); + found[n] = '\0'; + } + else + { + // Clear out rest of string. + n = pnextparam - found; + Q_memset(found, 0, n); + } + } + + // Strip and trailing ' ' characters left over. + while (1) + { + int curpos = Q_strlen(m_pszCmdLine); + if (curpos == 0 || m_pszCmdLine[ curpos - 1 ] != ' ') + break; + + m_pszCmdLine[curpos - 1] = '\0'; + } +} + +// Purpose: Append parameter and argument values to command line +void CCommandLine::AppendParm(const char *pszParm, const char *pszValues) +{ + int nNewLength = 0; + char *pCmdString; + + // Parameter. + nNewLength = Q_strlen(pszParm); + + // Values + leading space character. + if (pszValues) + nNewLength += Q_strlen(pszValues) + 1; + + // Terminal 0; + nNewLength++; + + if (!m_pszCmdLine) + { + m_pszCmdLine = new char[ nNewLength ]; + Q_strcpy(m_pszCmdLine, pszParm); + if (pszValues) + { + Q_strcat(m_pszCmdLine, " "); + Q_strcat(m_pszCmdLine, pszValues); + } + + return; + } + + // Remove any remnants from the current Cmd Line. + RemoveParm(pszParm); + + nNewLength += Q_strlen(m_pszCmdLine) + 1 + 1; + + pCmdString = new char[ nNewLength ]; + Q_memset(pCmdString, 0, nNewLength); + + Q_strcpy(pCmdString, m_pszCmdLine); // Copy old command line. + Q_strcat(pCmdString, " "); // Put in a space + Q_strcat(pCmdString, pszParm); + + if (pszValues) + { + Q_strcat(pCmdString, " "); + Q_strcat(pCmdString, pszValues); + } + + // Kill off the old one + delete[] m_pszCmdLine; + + // Point at the new command line. + m_pszCmdLine = pCmdString; +} + +void CCommandLine::SetParm(const char *pszParm, const char *pszValues) +{ + RemoveParm(pszParm); + AppendParm(pszParm, pszValues); +} + +void CCommandLine::SetParm(const char *pszParm, int iValue) +{ + char buf[64]; + Q_snprintf(buf, sizeof(buf), "%d", iValue); + SetParm(pszParm, buf); +} + +// Purpose: Search for the parameter in the current commandline +const char *CCommandLine::CheckParm(const char *psz, char **ppszValue) const +{ + static char sz[128] = ""; + + if (!m_pszCmdLine) + return nullptr; + + if (ppszValue) + *ppszValue = nullptr; + + char *pret = Q_strstr(m_pszCmdLine, psz); + if (!pret || !ppszValue) + return pret; + + // find the next whitespace + char *p1 = pret; + do { + ++p1; + } while (*p1 != ' ' && *p1); + + int i = 0; + char *p2 = p1 + 1; + + do { + if (p2[i] == '\0' || p2[i] == ' ') + break; + + sz[i] = p2[i]; + i++; + } while (i < sizeof(sz)); + + sz[i] = '\0'; + *ppszValue = sz; + + return pret; +} + +const char *CCommandLine::GetCmdLine() const +{ + return m_pszCmdLine; +} diff --git a/dep/rehlsdk/common/crc.h b/dep/rehlsdk/common/crc.h index 69343aa..4e0cfb6 100644 --- a/dep/rehlsdk/common/crc.h +++ b/dep/rehlsdk/common/crc.h @@ -17,17 +17,8 @@ #include "quakedef.h" -// MD5 Hash -typedef struct -{ - unsigned int buf[4]; - unsigned int bits[2]; - unsigned char in[64]; -} MD5Context_t; - typedef unsigned int CRC32_t; - #ifdef __cplusplus extern "C" { @@ -45,11 +36,3 @@ BOOL CRC_File(CRC32_t *crcvalue, char *pszFileName); byte COM_BlockSequenceCRCByte(byte *base, int length, int sequence); int CRC_MapFile(CRC32_t *crcvalue, char *pszFileName); - -void MD5Init(MD5Context_t *ctx); -void MD5Update(MD5Context_t *ctx, const unsigned char *buf, unsigned int len); -void MD5Final(unsigned char digest[16], MD5Context_t *ctx); -void MD5Transform(unsigned int buf[4], const unsigned int in[16]); - -BOOL MD5_Hash_File(unsigned char digest[16], char *pszFileName, BOOL bUsefopen, BOOL bSeed, unsigned int seed[4]); -char *MD5_Print(unsigned char hash[16]); diff --git a/dep/rehlsdk/common/cvardef.h b/dep/rehlsdk/common/cvardef.h index d1bf88b..aea0f9e 100644 --- a/dep/rehlsdk/common/cvardef.h +++ b/dep/rehlsdk/common/cvardef.h @@ -1,9 +1,9 @@ /*** * * Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * All Rights Reserved. * * Use, distribution, and modification of this source code and/or resulting @@ -36,4 +36,15 @@ typedef struct cvar_s struct cvar_s *next; } cvar_t; +using cvar_callback_t = void (*)(const char *pszNewValue); + +struct cvar_listener_t +{ + cvar_listener_t(const char *var_name, cvar_callback_t handler) : + func(handler), name(var_name) {} + + cvar_callback_t func; + const char *name; +}; + #endif // CVARDEF_H diff --git a/dep/rehlsdk/common/entity_state.h b/dep/rehlsdk/common/entity_state.h index 4bd381e..91fe2ed 100644 --- a/dep/rehlsdk/common/entity_state.h +++ b/dep/rehlsdk/common/entity_state.h @@ -23,8 +23,9 @@ // For entityType below -#define ENTITY_NORMAL (1<<0) -#define ENTITY_BEAM (1<<1) +#define ENTITY_NORMAL (1<<0) +#define ENTITY_BEAM (1<<1) +#define ENTITY_UNINITIALIZED (1<<30) // Entity state is used for the baseline and for delta compression of a packet of // entities that is sent to a client. diff --git a/dep/rehlsdk/common/enums.h b/dep/rehlsdk/common/enums.h index 4f6021d..72f525c 100644 --- a/dep/rehlsdk/common/enums.h +++ b/dep/rehlsdk/common/enums.h @@ -16,12 +16,13 @@ #ifndef ENUMS_H #define ENUMS_H +// Used as array indexer typedef enum netsrc_s { - NS_CLIENT, + NS_CLIENT = 0, NS_SERVER, - NS_MULTICAST // xxxMO + NS_MULTICAST, // xxxMO + NS_MAX } netsrc_t; #endif - diff --git a/dep/rehlsdk/common/hltv.h b/dep/rehlsdk/common/hltv.h index 136183d..635c8c3 100644 --- a/dep/rehlsdk/common/hltv.h +++ b/dep/rehlsdk/common/hltv.h @@ -1,6 +1,6 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ // -// Purpose: +// Purpose: // // $NoKeywords: $ //============================================================================= @@ -13,12 +13,13 @@ #define TYPE_CLIENT 0 // client is a normal HL client (default) #define TYPE_PROXY 1 // client is another proxy +#define TYPE_DIRECTOR 2 #define TYPE_COMMENTATOR 3 // client is a commentator #define TYPE_DEMO 4 // client is a demo file // sub commands of svc_hltv: #define HLTV_ACTIVE 0 // tells client that he's an spectator and will get director commands -#define HLTV_STATUS 1 // send status infos about proxy +#define HLTV_STATUS 1 // send status infos about proxy #define HLTV_LISTEN 2 // tell client to listen to a multicast stream // director command types: @@ -41,10 +42,9 @@ #define DRC_CMD_LAST 15 - // DRC_CMD_EVENT event flags #define DRC_FLAG_PRIO_MASK 0x0F // priorities between 0 and 15 (15 most important) -#define DRC_FLAG_SIDE (1<<4) // +#define DRC_FLAG_SIDE (1<<4) // #define DRC_FLAG_DRAMATIC (1<<5) // is a dramatic scene #define DRC_FLAG_SLOWMOTION (1<<6) // would look good in SloMo #define DRC_FLAG_FACEPLAYER (1<<7) // player is doning something (reload/defuse bomb etc) @@ -52,7 +52,6 @@ #define DRC_FLAG_FINAL (1<<9) // is a final scene #define DRC_FLAG_NO_RANDOM (1<<10) // don't randomize event data - // DRC_CMD_WAYPOINT flags #define DRC_FLAG_STARTPATH 1 // end with speed 0.0 #define DRC_FLAG_SLOWSTART 2 // start with speed 0.0 diff --git a/dep/rehlsdk/common/mathlib.h b/dep/rehlsdk/common/mathlib.h index 6d19b3f..83affe8 100644 --- a/dep/rehlsdk/common/mathlib.h +++ b/dep/rehlsdk/common/mathlib.h @@ -65,32 +65,31 @@ typedef union DLONG_u #endif template -inline T min(T a, T b) { +inline T min(T a, T b) +{ return (a < b) ? a : b; } template -inline T max(T a, T b) { +inline T max(T a, T b) +{ return (a < b) ? b : a; } template -inline T clamp(T a, T min, T max) { +inline T clamp(T a, T min, T max) +{ return (a > max) ? max : (a < min) ? min : a; } template -inline T bswap(T s) { - switch (sizeof(T)) { -#ifdef _WIN32 - case 2: {auto res = _byteswap_ushort(*(uint16 *)&s); return *(T *)&res;} - case 4: {auto res = _byteswap_ulong(*(uint32 *)(&s)); return *(T *)&res;} - case 8: {auto res = _byteswap_uint64(*(uint64 *)&s); return *(T *)&res;} -#else - case 2: {auto res = _bswap16(*(uint16 *)&s); return *(T *)&res;} - case 4: {auto res = _bswap(*(uint32 *)&s); return *(T *)&res;} - case 8: {auto res = _bswap64(*(uint64 *)&s); return *(T *)&res;} -#endif +inline T bswap(T s) +{ + switch (sizeof(T)) + { + case 2: {auto res = __builtin_bswap16(*(uint16 *)&s); return *(T *)&res; } + case 4: {auto res = __builtin_bswap32(*(uint32 *)&s); return *(T *)&res; } + case 8: {auto res = __builtin_bswap64(*(uint64 *)&s); return *(T *)&res; } default: return s; } } diff --git a/dep/rehlsdk/common/md5.h b/dep/rehlsdk/common/md5.h new file mode 100644 index 0000000..637ba0f --- /dev/null +++ b/dep/rehlsdk/common/md5.h @@ -0,0 +1,34 @@ +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ + +#pragma once + +#include + +// MD5 Hash +typedef struct +{ + unsigned int buf[4]; + unsigned int bits[2]; + unsigned char in[64]; +} MD5Context_t; + +void MD5Init(MD5Context_t *ctx); +void MD5Update(MD5Context_t *ctx, const unsigned char *buf, unsigned int len); +void MD5Final(unsigned char digest[16], MD5Context_t *ctx); +void MD5Transform(unsigned int buf[4], const unsigned int in[16]); + +BOOL MD5_Hash_File(unsigned char digest[16], char *pszFileName, BOOL bUsefopen, BOOL bSeed, unsigned int seed[4]); +char *MD5_Print(unsigned char hash[16]); diff --git a/dep/rehlsdk/common/netapi.cpp b/dep/rehlsdk/common/netapi.cpp new file mode 100644 index 0000000..7c69449 --- /dev/null +++ b/dep/rehlsdk/common/netapi.cpp @@ -0,0 +1,208 @@ +#include +#include + +#ifdef _WIN32 + #include "winsock.h" +#else + #include + #include + #include + #include + #include + #include +#endif // _WIN32 + +#include "netapi.h" + +class CNetAPI: public INetAPI { +public: + virtual void NetAdrToSockAddr(netadr_t *a, struct sockaddr *s); + virtual void SockAddrToNetAdr(struct sockaddr *s, netadr_t *a); + + virtual char *AdrToString(netadr_t *a); + virtual bool StringToAdr(const char *s, netadr_t *a); + + virtual void GetSocketAddress(int socket, netadr_t *a); + virtual bool CompareAdr(netadr_t *a, netadr_t *b); + virtual void GetLocalIP(netadr_t *a); +}; + +// Expose interface +CNetAPI g_NetAPI; +INetAPI *net = (INetAPI *)&g_NetAPI; + +void CNetAPI::NetAdrToSockAddr(netadr_t *a, struct sockaddr *s) +{ + memset(s, 0, sizeof(*s)); + + if (a->type == NA_BROADCAST) + { + ((struct sockaddr_in *)s)->sin_family = AF_INET; + ((struct sockaddr_in *)s)->sin_port = a->port; + ((struct sockaddr_in *)s)->sin_addr.s_addr = INADDR_BROADCAST; + } + else if (a->type == NA_IP) + { + ((struct sockaddr_in *)s)->sin_family = AF_INET; + ((struct sockaddr_in *)s)->sin_addr.s_addr = *(int *)&a->ip; + ((struct sockaddr_in *)s)->sin_port = a->port; + } +} + +void CNetAPI::SockAddrToNetAdr(struct sockaddr *s, netadr_t *a) +{ + if (s->sa_family == AF_INET) + { + a->type = NA_IP; + *(int *)&a->ip = ((struct sockaddr_in *)s)->sin_addr.s_addr; + a->port = ((struct sockaddr_in *)s)->sin_port; + } +} + +char *CNetAPI::AdrToString(netadr_t *a) +{ + static char s[64]; + memset(s, 0, sizeof(s)); + + if (a) + { + if (a->type == NA_LOOPBACK) + { + sprintf(s, "loopback"); + } + else if (a->type == NA_IP) + { + sprintf(s, "%i.%i.%i.%i:%i", a->ip[0], a->ip[1], a->ip[2], a->ip[3], ntohs(a->port)); + } + } + + return s; +} + +bool StringToSockaddr(const char *s, struct sockaddr *sadr) +{ + struct hostent *h; + char *colon; + char copy[128]; + struct sockaddr_in *p; + + memset(sadr, 0, sizeof(*sadr)); + + p = (struct sockaddr_in *)sadr; + p->sin_family = AF_INET; + p->sin_port = 0; + + strcpy(copy, s); + + // strip off a trailing :port if present + for (colon = copy ; *colon ; colon++) + { + if (*colon == ':') + { + // terminate + *colon = '\0'; + + // Start at next character + p->sin_port = htons((short)atoi(colon + 1)); + } + } + + // Numeric IP, no DNS + if (copy[0] >= '0' && copy[0] <= '9' && strstr(copy, ".")) + { + *(int *)&p->sin_addr = inet_addr(copy); + } + else + { + // DNS it + if (!(h = gethostbyname(copy))) + { + return false; + } + + // Use first result + *(int *)&p->sin_addr = *(int *)h->h_addr_list[0]; + } + + return true; +} + +bool CNetAPI::StringToAdr(const char *s, netadr_t *a) +{ + struct sockaddr sadr; + if (!strcmp(s, "localhost")) + { + memset(a, 0, sizeof(*a)); + a->type = NA_LOOPBACK; + return true; + } + + if (!StringToSockaddr(s, &sadr)) + { + return false; + } + + SockAddrToNetAdr(&sadr, a); + return true; +} + +// Lookup the IP address for the specified IP socket +void CNetAPI::GetSocketAddress(int socket, netadr_t *a) +{ + char buff[512]; + struct sockaddr_in address; + int namelen; + + memset(a, 0, sizeof(*a)); + gethostname(buff, sizeof(buff)); + + // Ensure that it doesn't overrun the buffer + buff[sizeof buff - 1] = '\0'; + StringToAdr(buff, a); + + namelen = sizeof(address); + if (getsockname(socket, (struct sockaddr *)&address, (int *)&namelen) == 0) + { + a->port = address.sin_port; + } +} + +bool CNetAPI::CompareAdr(netadr_t *a, netadr_t *b) +{ + if (a->type != b->type) + { + return false; + } + + if (a->type == NA_LOOPBACK) + { + return true; + } + + if (a->type == NA_IP && + a->ip[0] == b->ip[0] && + a->ip[1] == b->ip[1] && + a->ip[2] == b->ip[2] && + a->ip[3] == b->ip[3] && + a->port == b->port) + { + return true; + } + + return false; +} + +void CNetAPI::GetLocalIP(netadr_t *a) +{ + char s[64]; + if(!::gethostname(s, 64)) + { + struct hostent *localip = ::gethostbyname(s); + if(localip) + { + a->type = NA_IP; + a->port = 0; + memcpy(a->ip, localip->h_addr_list[0], 4); + } + } +} diff --git a/dep/rehlsdk/common/netapi.h b/dep/rehlsdk/common/netapi.h new file mode 100644 index 0000000..8401c92 --- /dev/null +++ b/dep/rehlsdk/common/netapi.h @@ -0,0 +1,25 @@ +#ifndef NETAPI_H +#define NETAPI_H +#ifdef _WIN32 +#pragma once +#endif + +#include "netadr.h" + +class INetAPI { +public: + virtual void NetAdrToSockAddr(netadr_t *a, struct sockaddr *s) = 0; // Convert a netadr_t to sockaddr + virtual void SockAddrToNetAdr(struct sockaddr *s, netadr_t *a) = 0; // Convert a sockaddr to netadr_t + + virtual char *AdrToString(netadr_t *a) = 0; // Convert a netadr_t to a string + virtual bool StringToAdr(const char *s, netadr_t *a) = 0; // Convert a string address to a netadr_t, doing DNS if needed + virtual void GetSocketAddress(int socket, netadr_t *a) = 0; // Look up IP address for socket + virtual bool CompareAdr(netadr_t *a, netadr_t *b) = 0; + + // return the IP of the local host + virtual void GetLocalIP(netadr_t *a) = 0; +}; + +extern INetAPI *net; + +#endif // NETAPI_H diff --git a/dep/rehlsdk/common/qlimits.h b/dep/rehlsdk/common/qlimits.h index c19e670..1a67bd5 100644 --- a/dep/rehlsdk/common/qlimits.h +++ b/dep/rehlsdk/common/qlimits.h @@ -24,6 +24,7 @@ #define MAX_LIGHTSTYLE_INDEX_BITS 6 #define MAX_LIGHTSTYLES (1< + +#if !defined(_WIN32) +void NORETURN Sys_Error(const char *error, ...); + +// This file adds the necessary compatibility tricks to avoid symbols with +// version GLIBCXX_3.4.16 and bigger, keeping binary compatibility with libstdc++ 4.6.1. +namespace std +{ + // We shouldn't be throwing exceptions at all, but it sadly turns out we call STL (inline) functions that do. + void __throw_out_of_range_fmt(const char *fmt, ...) + { + va_list ap; + char buf[1024]; // That should be big enough. + + va_start(ap, fmt); + vsnprintf(buf, sizeof(buf), fmt, ap); + buf[sizeof(buf) - 1] = '\0'; + va_end(ap); + + Sys_Error(buf); + } +}; // namespace std + +// Technically, this symbol is not in GLIBCXX_3.4.20, but in CXXABI_1.3.8, +// but that's equivalent, version-wise. Those calls are added by the compiler +// itself on `new Class[n]` calls. +extern "C" +void __cxa_throw_bad_array_new_length() +{ + Sys_Error("Bad array new length."); +} +#endif // !defined(_WIN32) diff --git a/dep/rehlsdk/common/textconsole.cpp b/dep/rehlsdk/common/textconsole.cpp new file mode 100644 index 0000000..45d13d7 --- /dev/null +++ b/dep/rehlsdk/common/textconsole.cpp @@ -0,0 +1,392 @@ +/* +* +* 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" + +bool CTextConsole::Init(IBaseSystem *system) +{ + // NULL or a valid base system interface + m_System = system; + + Q_memset(m_szConsoleText, 0, sizeof(m_szConsoleText)); + m_nConsoleTextLen = 0; + m_nCursorPosition = 0; + + Q_memset(m_szSavedConsoleText, 0, sizeof(m_szSavedConsoleText)); + m_nSavedConsoleTextLen = 0; + + Q_memset(m_aszLineBuffer, 0, sizeof(m_aszLineBuffer)); + m_nTotalLines = 0; + m_nInputLine = 0; + m_nBrowseLine = 0; + + // these are log messages, not related to console + Sys_Printf("\n"); + Sys_Printf("Console initialized.\n"); + + m_ConsoleVisible = true; + + return true; +} + +void CTextConsole::InitSystem(IBaseSystem *system) +{ + m_System = system; +} + +void CTextConsole::SetVisible(bool visible) +{ + m_ConsoleVisible = visible; +} + +bool CTextConsole::IsVisible() +{ + return m_ConsoleVisible; +} + +void CTextConsole::ShutDown() +{ + ; +} + +void CTextConsole::Print(char *pszMsg) +{ + if (m_nConsoleTextLen) + { + int nLen = m_nConsoleTextLen; + while (nLen--) + { + PrintRaw("\b \b"); + } + } + + PrintRaw(pszMsg); + + if (m_nConsoleTextLen) + { + PrintRaw(m_szConsoleText, m_nConsoleTextLen); + } + + UpdateStatus(); +} + +int CTextConsole::ReceiveNewline() +{ + int nLen = 0; + + Echo("\n"); + + if (m_nConsoleTextLen) + { + nLen = m_nConsoleTextLen; + + m_szConsoleText[ m_nConsoleTextLen ] = '\0'; + m_nConsoleTextLen = 0; + m_nCursorPosition = 0; + + // cache line in buffer, but only if it's not a duplicate of the previous line + if ((m_nInputLine == 0) || (Q_strcmp(m_aszLineBuffer[ m_nInputLine - 1 ], m_szConsoleText))) + { + Q_strncpy(m_aszLineBuffer[ m_nInputLine ], m_szConsoleText, MAX_CONSOLE_TEXTLEN); + m_nInputLine++; + + if (m_nInputLine > m_nTotalLines) + m_nTotalLines = m_nInputLine; + + if (m_nInputLine >= MAX_BUFFER_LINES) + m_nInputLine = 0; + + } + + m_nBrowseLine = m_nInputLine; + } + + return nLen; +} + +void CTextConsole::ReceiveBackspace() +{ + int nCount; + + if (m_nCursorPosition == 0) + { + return; + } + + m_nConsoleTextLen--; + m_nCursorPosition--; + + Echo("\b"); + + for (nCount = m_nCursorPosition; nCount < m_nConsoleTextLen; ++nCount) + { + m_szConsoleText[ nCount ] = m_szConsoleText[ nCount + 1 ]; + Echo(m_szConsoleText + nCount, 1); + } + + Echo(" "); + + nCount = m_nConsoleTextLen; + while (nCount >= m_nCursorPosition) + { + Echo("\b"); + nCount--; + } + + m_nBrowseLine = m_nInputLine; +} + +void CTextConsole::ReceiveTab() +{ + if (!m_System) + return; + + ObjectList matches; + m_szConsoleText[ m_nConsoleTextLen ] = '\0'; + m_System->GetCommandMatches(m_szConsoleText, &matches); + + if (matches.IsEmpty()) + return; + + if (matches.CountElements() == 1) + { + char *pszCmdName = (char *)matches.GetFirst(); + char *pszRest = pszCmdName + Q_strlen(m_szConsoleText); + + if (pszRest) + { + Echo(pszRest); + Q_strlcat(m_szConsoleText, pszRest); + m_nConsoleTextLen += Q_strlen(pszRest); + + Echo(" "); + Q_strlcat(m_szConsoleText, " "); + m_nConsoleTextLen++; + } + } + else + { + int nLongestCmd = 0; + int nSmallestCmd = 0; + int nCurrentColumn; + int nTotalColumns; + char szCommonCmd[256]; // Should be enough. + char szFormatCmd[256]; + char *pszSmallestCmd; + char *pszCurrentCmd = (char *)matches.GetFirst(); + nSmallestCmd = Q_strlen(pszCurrentCmd); + pszSmallestCmd = pszCurrentCmd; + while (pszCurrentCmd) + { + if ((int)Q_strlen(pszCurrentCmd) > nLongestCmd) + { + nLongestCmd = Q_strlen(pszCurrentCmd); + } + if ((int)Q_strlen(pszCurrentCmd) < nSmallestCmd) + { + nSmallestCmd = Q_strlen(pszCurrentCmd); + pszSmallestCmd = pszCurrentCmd; + } + pszCurrentCmd = (char *)matches.GetNext(); + } + + nTotalColumns = (GetWidth() - 1) / (nLongestCmd + 1); + nCurrentColumn = 0; + + Echo("\n"); + Q_strcpy(szCommonCmd, pszSmallestCmd); + + // Would be nice if these were sorted, but not that big a deal + pszCurrentCmd = (char *)matches.GetFirst(); + while (pszCurrentCmd) + { + if (++nCurrentColumn > nTotalColumns) + { + Echo("\n"); + nCurrentColumn = 1; + } + + Q_snprintf(szFormatCmd, sizeof(szFormatCmd), "%-*s ", nLongestCmd, pszCurrentCmd); + Echo(szFormatCmd); + for (char *pCur = pszCurrentCmd, *pCommon = szCommonCmd; (*pCur && *pCommon); pCur++, pCommon++) + { + if (*pCur != *pCommon) + { + *pCommon = 0; + break; + } + } + + pszCurrentCmd = (char *)matches.GetNext(); + } + + Echo("\n"); + if (Q_strcmp(szCommonCmd, m_szConsoleText)) + { + Q_strcpy(m_szConsoleText, szCommonCmd); + m_nConsoleTextLen = Q_strlen(szCommonCmd); + } + + Echo(m_szConsoleText); + } + + m_nCursorPosition = m_nConsoleTextLen; + m_nBrowseLine = m_nInputLine; +} + +void CTextConsole::ReceiveStandardChar(const char ch) +{ + int nCount; + + // If the line buffer is maxed out, ignore this char + if (m_nConsoleTextLen >= (sizeof(m_szConsoleText) - 2)) + { + return; + } + + nCount = m_nConsoleTextLen; + while (nCount > m_nCursorPosition) + { + m_szConsoleText[ nCount ] = m_szConsoleText[ nCount - 1 ]; + nCount--; + } + + m_szConsoleText[ m_nCursorPosition ] = ch; + + Echo(m_szConsoleText + m_nCursorPosition, m_nConsoleTextLen - m_nCursorPosition + 1); + + m_nConsoleTextLen++; + m_nCursorPosition++; + + nCount = m_nConsoleTextLen; + while (nCount > m_nCursorPosition) + { + Echo("\b"); + nCount--; + } + + m_nBrowseLine = m_nInputLine; +} + +void CTextConsole::ReceiveUpArrow() +{ + int nLastCommandInHistory = m_nInputLine + 1; + if (nLastCommandInHistory > m_nTotalLines) + nLastCommandInHistory = 0; + + if (m_nBrowseLine == nLastCommandInHistory) + return; + + if (m_nBrowseLine == m_nInputLine) + { + if (m_nConsoleTextLen > 0) + { + // Save off current text + Q_strncpy(m_szSavedConsoleText, m_szConsoleText, m_nConsoleTextLen); + // No terminator, it's a raw buffer we always know the length of + } + + m_nSavedConsoleTextLen = m_nConsoleTextLen; + } + + m_nBrowseLine--; + if (m_nBrowseLine < 0) + { + m_nBrowseLine = m_nTotalLines - 1; + } + + // delete old line + while (m_nConsoleTextLen--) + { + Echo("\b \b"); + } + + // copy buffered line + Echo(m_aszLineBuffer[ m_nBrowseLine ]); + + Q_strncpy(m_szConsoleText, m_aszLineBuffer[ m_nBrowseLine ], MAX_CONSOLE_TEXTLEN); + + m_nConsoleTextLen = Q_strlen(m_aszLineBuffer[ m_nBrowseLine ]); + m_nCursorPosition = m_nConsoleTextLen; +} + +void CTextConsole::ReceiveDownArrow() +{ + if (m_nBrowseLine == m_nInputLine) + return; + + if (++m_nBrowseLine > m_nTotalLines) + m_nBrowseLine = 0; + + // delete old line + while (m_nConsoleTextLen--) + { + Echo("\b \b"); + } + + if (m_nBrowseLine == m_nInputLine) + { + if (m_nSavedConsoleTextLen > 0) + { + // Restore current text + Q_strncpy(m_szConsoleText, m_szSavedConsoleText, m_nSavedConsoleTextLen); + // No terminator, it's a raw buffer we always know the length of + + Echo(m_szConsoleText, m_nSavedConsoleTextLen); + } + + m_nConsoleTextLen = m_nSavedConsoleTextLen; + } + else + { + // copy buffered line + Echo(m_aszLineBuffer[ m_nBrowseLine ]); + Q_strncpy(m_szConsoleText, m_aszLineBuffer[ m_nBrowseLine ], MAX_CONSOLE_TEXTLEN); + m_nConsoleTextLen = Q_strlen(m_aszLineBuffer[ m_nBrowseLine ]); + } + + m_nCursorPosition = m_nConsoleTextLen; +} + +void CTextConsole::ReceiveLeftArrow() +{ + if (m_nCursorPosition == 0) + return; + + Echo("\b"); + m_nCursorPosition--; +} + +void CTextConsole::ReceiveRightArrow() +{ + if (m_nCursorPosition == m_nConsoleTextLen) + return; + + Echo(m_szConsoleText + m_nCursorPosition, 1); + m_nCursorPosition++; +} diff --git a/dep/rehlsdk/common/textconsole.h b/dep/rehlsdk/common/textconsole.h new file mode 100644 index 0000000..9d1b67e --- /dev/null +++ b/dep/rehlsdk/common/textconsole.h @@ -0,0 +1,95 @@ +/* +* +* 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. +* +*/ + +#pragma once + +#include "IBaseSystem.h" + +#define MAX_CONSOLE_TEXTLEN 256 +#define MAX_BUFFER_LINES 30 + +class CTextConsole { +public: + virtual ~CTextConsole() {} + + virtual bool Init(IBaseSystem *system = nullptr); + virtual void ShutDown(); + virtual void Print(char *pszMsg); + + virtual void SetTitle(char *pszTitle) {} + virtual void SetStatusLine(char *pszStatus) {} + virtual void UpdateStatus() {} + + // Must be provided by children + virtual void PrintRaw(char *pszMsg, int nChars = 0) = 0; + virtual void Echo(char *pszMsg, int nChars = 0) = 0; + virtual char *GetLine() = 0; + virtual int GetWidth() = 0; + + virtual void SetVisible(bool visible); + virtual bool IsVisible(); + + void InitSystem(IBaseSystem *system); + +protected: + char m_szConsoleText[MAX_CONSOLE_TEXTLEN]; // console text buffer + int m_nConsoleTextLen; // console textbuffer length + int m_nCursorPosition; // position in the current input line + + // Saved input data when scrolling back through command history + char m_szSavedConsoleText[MAX_CONSOLE_TEXTLEN]; // console text buffer + int m_nSavedConsoleTextLen; // console textbuffer length + + char m_aszLineBuffer[MAX_BUFFER_LINES][MAX_CONSOLE_TEXTLEN]; // command buffer last MAX_BUFFER_LINES commands + int m_nInputLine; // Current line being entered + int m_nBrowseLine; // current buffer line for up/down arrow + int m_nTotalLines; // # of nonempty lines in the buffer + + bool m_ConsoleVisible; + + IBaseSystem *m_System; + + int ReceiveNewline(); + void ReceiveBackspace(); + void ReceiveTab(); + void ReceiveStandardChar(const char ch); + void ReceiveUpArrow(); + void ReceiveDownArrow(); + void ReceiveLeftArrow(); + void ReceiveRightArrow(); +}; + +#include "SteamAppStartUp.h" + +#if defined(_WIN32) + #include "TextConsoleWin32.h" +#else + #include "TextConsoleUnix.h" +#endif // defined(_WIN32) + +void Sys_Printf(char *fmt, ...); diff --git a/dep/rehlsdk/dlls/cbase.h b/dep/rehlsdk/dlls/cbase.h index 6bc9669..df3b8ee 100644 --- a/dep/rehlsdk/dlls/cbase.h +++ b/dep/rehlsdk/dlls/cbase.h @@ -54,9 +54,9 @@ CBaseEntity #ifndef CBASE_DLLEXPORT #ifdef _WIN32 -#define CBASE_DLLEXPORT _declspec( dllexport ) +#define CBASE_DLLEXPORT _declspec( dllexport ) EXT_FUNC #else -#define CBASE_DLLEXPORT __attribute__ ((visibility("default"))) +#define CBASE_DLLEXPORT __attribute__ ((visibility("default"))) EXT_FUNC #endif #endif diff --git a/dep/rehlsdk/dlls/nodes.h b/dep/rehlsdk/dlls/nodes.h index 7447768..8778366 100644 --- a/dep/rehlsdk/dlls/nodes.h +++ b/dep/rehlsdk/dlls/nodes.h @@ -376,4 +376,4 @@ enum extern CGraph WorldGraph; -#endif // NODES_H \ No newline at end of file +#endif // NODES_H diff --git a/dep/rehlsdk/dlls/util.h b/dep/rehlsdk/dlls/util.h index 2f7b8c8..951b52d 100644 --- a/dep/rehlsdk/dlls/util.h +++ b/dep/rehlsdk/dlls/util.h @@ -85,9 +85,9 @@ typedef int BOOL; #ifndef UTIL_DLLEXPORT #ifdef _WIN32 -#define UTIL_DLLEXPORT _declspec( dllexport ) +#define UTIL_DLLEXPORT _declspec( dllexport ) EXT_FUNC #else -#define UTIL_DLLEXPORT __attribute__ ((visibility("default"))) +#define UTIL_DLLEXPORT __attribute__ ((visibility("default"))) EXT_FUNC #endif #endif diff --git a/dep/rehlsdk/engine/cmd_rehlds.h b/dep/rehlsdk/engine/cmd_rehlds.h index 0f5de26..9337575 100644 --- a/dep/rehlsdk/engine/cmd_rehlds.h +++ b/dep/rehlsdk/engine/cmd_rehlds.h @@ -33,7 +33,7 @@ typedef void(*xcommand_t)(void); typedef struct cmd_function_s { struct cmd_function_s *next; - char *name; + const char *name; xcommand_t function; int flags; } cmd_function_t; diff --git a/dep/rehlsdk/engine/crc32c.cpp b/dep/rehlsdk/engine/crc32c.cpp index ac33355..669fc81 100644 --- a/dep/rehlsdk/engine/crc32c.cpp +++ b/dep/rehlsdk/engine/crc32c.cpp @@ -115,10 +115,12 @@ uint32 crc32c_t_nosse(uint32 iCRC, const uint8 *buf, int len) { return crc; } +FUNC_TARGET("sse4.2") uint32 crc32c_t8_sse(uint32 iCRC, uint8 u8) { return _mm_crc32_u8(iCRC, u8); } +FUNC_TARGET("sse4.2") uint32 crc32c_t_sse(uint32 iCRC, const uint8 *buf, unsigned int len) { uint32 crc32cval = iCRC; unsigned int i = 0; diff --git a/dep/rehlsdk/engine/custom.h b/dep/rehlsdk/engine/custom.h index 190d769..d2ebd48 100644 --- a/dep/rehlsdk/engine/custom.h +++ b/dep/rehlsdk/engine/custom.h @@ -1,9 +1,9 @@ /*** * * Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * All Rights Reserved. * * Use, distribution, and modification of this source code and/or resulting @@ -63,7 +63,14 @@ typedef struct resourceinfo_s typedef struct resource_s { +#ifdef HOOK_HLTV + // NOTE HLTV: array szFileName declared on 260 cell, + // this changes necessary for compatibility hookers. + char szFileName[MAX_PATH]; +#else char szFileName[MAX_QPATH]; // File name to download/precache. +#endif // HOOK_HLTV + resourcetype_t type; // t_sound, t_skin, t_model, t_decal. int nIndex; // For t_decals int nDownloadSize; // Size in Bytes if this must be downloaded. @@ -75,14 +82,19 @@ typedef struct resource_s unsigned char rguc_reserved[ 32 ]; // For future expansion struct resource_s *pNext; // Next in chain. + +#if !defined(HLTV) struct resource_s *pPrev; +#else + unsigned char *data; +#endif // !defined(HLTV) } resource_t; typedef struct customization_s { qboolean bInUse; // Is this customization in use; resource_t resource; // The resource_t for this customization - qboolean bTranslated; // Has the raw data been translated into a useable format? + qboolean bTranslated; // Has the raw data been translated into a useable format? // (e.g., raw decal .wad make into texture_t *) int nUserData1; // Customization specific data int nUserData2; // Customization specific data diff --git a/dep/rehlsdk/engine/eiface.h b/dep/rehlsdk/engine/eiface.h index 8081743..59680bc 100644 --- a/dep/rehlsdk/engine/eiface.h +++ b/dep/rehlsdk/engine/eiface.h @@ -37,9 +37,9 @@ /* #ifdef _WIN32 -#define DLLEXPORT __stdcall +#define DLLEXPORT __stdcall EXT_FUNC #else -#define DLLEXPORT __attribute__ ((visibility("default"))) +#define DLLEXPORT __attribute__ ((visibility("default"))) EXT_FUNC #endif */ @@ -144,11 +144,11 @@ typedef struct enginefuncs_s const char *(*pfnTraceTexture) (edict_t *pTextureEntity, const float *v1, const float *v2 ); void (*pfnTraceSphere) (const float *v1, const float *v2, int fNoMonsters, float radius, edict_t *pentToSkip, TraceResult *ptr); void (*pfnGetAimVector) (edict_t* ent, float speed, float *rgflReturn); - void (*pfnServerCommand) (char* str); + void (*pfnServerCommand) (const char* str); void (*pfnServerExecute) (void); - void (*pfnClientCommand) (edict_t* pEdict, char* szFmt, ...); + void (*pfnClientCommand) (edict_t* pEdict, const char* szFmt, ...); void (*pfnParticleEffect) (const float *org, const float *dir, float color, float count); - void (*pfnLightStyle) (int style, char* val); + void (*pfnLightStyle) (int style, const char* val); int (*pfnDecalIndex) (const char *name); int (*pfnPointContents) (const float *rgflVector); void (*pfnMessageBegin) (int msg_dest, int msg_type, const float *pOrigin, edict_t *ed); @@ -200,7 +200,7 @@ typedef struct enginefuncs_s void (*pfnSetView) (const edict_t *pClient, const edict_t *pViewent ); float (*pfnTime) ( void ); void (*pfnCrosshairAngle) (const edict_t *pClient, float pitch, float yaw); - byte * (*pfnLoadFileForMe) (char *filename, int *pLength); + byte * (*pfnLoadFileForMe) (const char *filename, int *pLength); void (*pfnFreeFile) (void *buffer); void (*pfnEndSection) (const char *pszSectionName); // trigger_endsection int (*pfnCompareFileTime) (char *filename1, char *filename2, int *iCompare); @@ -215,9 +215,9 @@ typedef struct enginefuncs_s char* (*pfnInfoKeyValue) (char *infobuffer, const char *key); void (*pfnSetKeyValue) (char *infobuffer, const char *key, const char *value); void (*pfnSetClientKeyValue) (int clientIndex, char *infobuffer, const char *key, const char *value); - int (*pfnIsMapValid) (char *filename); + int (*pfnIsMapValid) (const char *filename); void (*pfnStaticDecal) ( const float *origin, int decalIndex, int entityIndex, int modelIndex ); - int (*pfnPrecacheGeneric) (char* s); + int (*pfnPrecacheGeneric) (const char* s); int (*pfnGetPlayerUserId) (edict_t *e ); // returns the server assigned userid for this player. useful for logging frags, etc. returns -1 if the edict couldn't be found in the list of clients void (*pfnBuildSoundMsg) (edict_t *entity, int channel, const char *sample, /*int*/float volume, float attenuation, int fFlags, int pitch, int msg_dest, int msg_type, const float *pOrigin, edict_t *ed); int (*pfnIsDedicatedServer) (void);// is this a dedicated server? @@ -239,7 +239,7 @@ typedef struct enginefuncs_s void (*pfnDeltaSetField) ( struct delta_s *pFields, const char *fieldname ); void (*pfnDeltaUnsetField) ( struct delta_s *pFields, const char *fieldname ); - void (*pfnDeltaAddEncoder) ( char *name, void (*conditionalencode)( struct delta_s *pFields, const unsigned char *from, const unsigned char *to ) ); + void (*pfnDeltaAddEncoder) ( const char *name, void (*conditionalencode)( struct delta_s *pFields, const unsigned char *from, const unsigned char *to ) ); int (*pfnGetCurrentPlayer) ( void ); int (*pfnCanSkipPlayer) ( const edict_t *player ); int (*pfnDeltaFindField) ( struct delta_s *pFields, const char *fieldname ); @@ -258,7 +258,7 @@ typedef struct enginefuncs_s void (*pfnGetPlayerStats) ( const edict_t *pClient, int *ping, int *packet_loss ); - void (*pfnAddServerCommand) ( char *cmd_name, void (*function) (void) ); + void (*pfnAddServerCommand) ( const char *cmd_name, void (*function) (void) ); // For voice communications, set which clients hear eachother. // NOTE: these functions take player entity indices (starting at 1). @@ -274,7 +274,7 @@ typedef struct enginefuncs_s sentenceEntry_s* (*pfnSequencePickSentence) ( const char* groupName, int pickMethod, int *picked ); // LH: Give access to filesize via filesystem - int (*pfnGetFileSize) ( char *filename ); + int (*pfnGetFileSize) ( const char *filename ); unsigned int (*pfnGetApproxWavePlayLen) (const char *filepath); // MDC: Added for CZ career-mode diff --git a/dep/rehlsdk/engine/maintypes.h b/dep/rehlsdk/engine/maintypes.h index 131a18c..b211e2d 100644 --- a/dep/rehlsdk/engine/maintypes.h +++ b/dep/rehlsdk/engine/maintypes.h @@ -32,11 +32,9 @@ #pragma once #endif - #include "osconfig.h" #include "mathlib.h" - // Has no references on server side. #define NOXREF // Function body is not implemented. @@ -44,9 +42,29 @@ // Function is not tested at all. #define UNTESTED +#define CONST_INTEGER_AS_STRING(x) #x //Wraps the integer in quotes, allowing us to form constant strings with it +#define __HACK_LINE_AS_STRING__(x) CONST_INTEGER_AS_STRING(x) //__LINE__ can only be converted to an actual number by going through this, otherwise the output is literally "__LINE__" +#define __LINE__AS_STRING __HACK_LINE_AS_STRING__(__LINE__) //Gives you the line number in constant string form + +#if defined _MSC_VER || defined __INTEL_COMPILER +#define NOXREFCHECK int __retAddr; __asm { __asm mov eax, [ebp + 4] __asm mov __retAddr, eax }; Sys_Error("[NOXREFCHECK]: %s: (" __FILE__ ":" __LINE__AS_STRING ") NOXREF, but called from 0x%.08x", __func__, __retAddr) +#else +// For EBP based stack (older gcc) (uncomment version apropriate for your compiler) +//#define NOXREFCHECK int __retAddr; __asm__ __volatile__("movl 4(%%ebp), %%eax;" "movl %%eax, %0":"=r"(__retAddr)::"%eax"); Sys_Error("[NOXREFCHECK]: %s: (" __FILE__ ":" __LINE__AS_STRING ") NOXREF, but called from 0x%.08x", __func__, __retAddr); +// For ESP based stack (newer gcc) (uncomment version apropriate for your compiler) +#define NOXREFCHECK int __retAddr; __asm__ __volatile__("movl 16(%%esp), %%eax;" "movl %%eax, %0":"=r"(__retAddr)::"%eax"); Sys_Error("[NOXREFCHECK]: %s: (" __FILE__ ":" __LINE__AS_STRING ") NOXREF, but called from 0x%.08x", __func__, __retAddr); +#endif + #define BIT(n) (1<<(n)) +// From engine/pr_comp.h; +typedef unsigned int string_t; -typedef unsigned int string_t; // from engine's pr_comp.h; +// From engine/server.h +typedef enum sv_delta_s +{ + sv_packet_nodelta, + sv_packet_delta, +} sv_delta_t; #endif // MAINTYPES_H diff --git a/dep/rehlsdk/engine/model.h b/dep/rehlsdk/engine/model.h index 7837482..bcb952a 100644 --- a/dep/rehlsdk/engine/model.h +++ b/dep/rehlsdk/engine/model.h @@ -74,7 +74,7 @@ typedef struct texture_s char name[16]; unsigned width, height; -#ifndef SWDS +#if !defined(SWDS) && !defined(HLTV) int gl_texturenum; struct msurface_s * texturechain; #endif @@ -85,7 +85,7 @@ typedef struct texture_s struct texture_s *alternate_anims; // bmodels in frame 1 use these unsigned offsets[MIPLEVELS]; // four mip maps stored -#ifdef SWDS +#if defined(SWDS) || defined(HLTV) unsigned paloffset; #else byte *pPal; diff --git a/dep/rehlsdk/engine/osconfig.h b/dep/rehlsdk/engine/osconfig.h index cf6a551..0e31743 100644 --- a/dep/rehlsdk/engine/osconfig.h +++ b/dep/rehlsdk/engine/osconfig.h @@ -48,6 +48,7 @@ #include #ifdef _WIN32 // WINDOWS + #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #include #include #include // for support IPX @@ -79,9 +80,6 @@ #include #include #include - - // Deail with stupid macro in kernel.h - #undef __FUNCTION__ #endif // _WIN32 #include @@ -92,19 +90,32 @@ #include #include + #ifdef _WIN32 // WINDOWS + // Define __func__ on VS less than 2015 + #if _MSC_VER < 1900 + #define __func__ __FUNCTION__ + #endif + #define _CRT_SECURE_NO_WARNINGS #define WIN32_LEAN_AND_MEAN #ifndef CDECL #define CDECL __cdecl #endif + #define FASTCALL __fastcall #define STDCALL __stdcall #define HIDDEN + #define FORCEINLINE __forceinline #define NOINLINE __declspec(noinline) #define ALIGN16 __declspec(align(16)) #define NORETURN __declspec(noreturn) #define FORCE_STACK_ALIGN + #define FUNC_TARGET(x) + + #define __builtin_bswap16 _byteswap_ushort + #define __builtin_bswap32 _byteswap_ulong + #define __builtin_bswap64 _byteswap_uint64 //inline bool SOCKET_FIONBIO(SOCKET s, int m) { return (ioctlsocket(s, FIONBIO, (u_long*)&m) == 0); } //inline int SOCKET_MSGLEN(SOCKET s, u_long& r) { return ioctlsocket(s, FIONREAD, (u_long*)&r); } @@ -124,11 +135,6 @@ VirtualFree(ptr, 0, MEM_RELEASE); } #else // _WIN32 - #ifdef __FUNCTION__ - #undef __FUNCTION__ - #endif - #define __FUNCTION__ __func__ - #ifndef PAGESIZE #define PAGESIZE 4096 #endif @@ -144,14 +150,26 @@ typedef unsigned short WORD; typedef unsigned int UNINT32; + #define FASTCALL #define CDECL __attribute__ ((cdecl)) #define STDCALL __attribute__ ((stdcall)) #define HIDDEN __attribute__((visibility("hidden"))) + #define FORCEINLINE inline #define NOINLINE __attribute__((noinline)) #define ALIGN16 __attribute__((aligned(16))) #define NORETURN __attribute__((noreturn)) #define FORCE_STACK_ALIGN __attribute__((force_align_arg_pointer)) +#if defined __INTEL_COMPILER + #define FUNC_TARGET(x) + + #define __builtin_bswap16 _bswap16 + #define __builtin_bswap32 _bswap + #define __builtin_bswap64 _bswap64 +#else + #define FUNC_TARGET(x) __attribute__((target(x))) +#endif // __INTEL_COMPILER + //inline bool SOCKET_FIONBIO(SOCKET s, int m) { return (ioctl(s, FIONBIO, (int*)&m) == 0); } //inline int SOCKET_MSGLEN(SOCKET s, u_long& r) { return ioctl(s, FIONREAD, (int*)&r); } typedef int SOCKET; @@ -164,6 +182,10 @@ #define SOCKET_AGAIN() (errno == EAGAIN) #define SOCKET_ERROR -1 + inline int ioctlsocket(int fd, int cmd, unsigned int *argp) { return ioctl(fd, cmd, argp); } + inline int closesocket(int fd) { return close(fd); } + inline int WSAGetLastError() { return errno; } + inline void* sys_allocmem(unsigned int size) { return mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); } @@ -191,4 +213,8 @@ #define EXT_FUNC FORCE_STACK_ALIGN +// Used to obtain the string name of a variable. +#define nameof_variable(name) template_nameof_variable(name, #name) +template const char* template_nameof_variable(const T& /*validate_type*/, const char* name) { return name; } + #endif // _OSCONFIG_H diff --git a/dep/rehlsdk/engine/pr_dlls.h b/dep/rehlsdk/engine/pr_dlls.h new file mode 100644 index 0000000..d7b72c1 --- /dev/null +++ b/dep/rehlsdk/engine/pr_dlls.h @@ -0,0 +1,51 @@ +/* +* +* 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. +* +*/ + +#pragma once + +#include "maintypes.h" +#include "eiface.h" + +const int MAX_EXTENSION_DLL = 50; + +typedef struct functiontable_s +{ + uint32 pFunction; + char *pFunctionName; +} functiontable_t; + +typedef struct extensiondll_s +{ + void *lDLLHandle; + functiontable_t *functionTable; + int functionCount; +} extensiondll_t; + +typedef void(*ENTITYINIT)(struct entvars_s *); +typedef void(*DISPATCHFUNCTION)(struct entvars_s *, void *); +typedef void(*FIELDIOFUNCTION)(SAVERESTOREDATA *, const char *, void *, TYPEDESCRIPTION *, int); diff --git a/dep/rehlsdk/engine/rehlds_api.h b/dep/rehlsdk/engine/rehlds_api.h index 0b0a588..938bd0c 100644 --- a/dep/rehlsdk/engine/rehlds_api.h +++ b/dep/rehlsdk/engine/rehlds_api.h @@ -33,9 +33,11 @@ #include "FlightRecorder.h" #include "interface.h" #include "model.h" +#include "ObjectList.h" +#include "pr_dlls.h" #define REHLDS_API_VERSION_MAJOR 3 -#define REHLDS_API_VERSION_MINOR 0 +#define REHLDS_API_VERSION_MINOR 3 //Steam_NotifyClientConnect hook typedef IHookChain IRehldsHook_Steam_NotifyClientConnect; @@ -189,6 +191,10 @@ typedef IHookChainRegistry IRehldsHook_SV_EmitSound2; typedef IHookChainRegistry IRehldsHookRegistry_SV_EmitSound2; +//CreateFakeClient hook +typedef IHookChain IRehldsHook_CreateFakeClient; +typedef IHookChainRegistry IRehldsHookRegistry_CreateFakeClient; + class IRehldsHookchains { public: virtual ~IRehldsHookchains() { } @@ -231,6 +237,7 @@ public: virtual IRehldsHookRegistry_SV_Spawn_f* SV_Spawn_f() = 0; virtual IRehldsHookRegistry_SV_CreatePacketEntities* SV_CreatePacketEntities() = 0; virtual IRehldsHookRegistry_SV_EmitSound2* SV_EmitSound2() = 0; + virtual IRehldsHookRegistry_CreateFakeClient* CreateFakeClient() = 0; }; struct RehldsFuncs_t { @@ -267,7 +274,7 @@ struct RehldsFuncs_t { cvar_t*(*GetCvarVars)(); int (*SV_GetChallenge)(const netadr_t& adr); void (*SV_AddResource)(resourcetype_t type, const char *name, int size, unsigned char flags, int index); - int(*MSG_ReadShort)(void); + int(*MSG_ReadShort)(); int(*MSG_ReadBuf)(int iSize, void *pbuf); void(*MSG_WriteBuf)(sizebuf_t *sb, int iSize, void *buf); void(*MSG_WriteByte)(sizebuf_t *sb, int c); @@ -282,6 +289,13 @@ struct RehldsFuncs_t { bool(*SV_EmitSound2)(edict_t *entity, IGameClient *receiver, int channel, const char *sample, float volume, float attenuation, int flags, int pitch, int emitFlags, const float *pOrigin); void(*SV_UpdateUserInfo)(IGameClient *pGameClient); bool(*StripUnprintableAndSpace)(char *pch); + void(*Cmd_RemoveCmd)(const char *cmd_name); + void(*GetCommandMatches)(const char *string, ObjectList *pMatchList); + bool(*AddExtDll)(void *hModule); + void(*AddCvarListener)(const char *var_name, cvar_callback_t func); + void(*RemoveExtDll)(void *hModule); + void(*RemoveCvarListener)(const char *var_name, cvar_callback_t func); + ENTITYINIT(*GetEntityInit)(char *pszClassName); }; class IRehldsApi { @@ -297,4 +311,4 @@ public: virtual IRehldsFlightRecorder* GetFlightRecorder() = 0; }; -#define VREHLDS_HLDS_API_VERSION "VREHLDS_HLDS_API_VERSION001" \ No newline at end of file +#define VREHLDS_HLDS_API_VERSION "VREHLDS_HLDS_API_VERSION001" diff --git a/dep/rehlsdk/engine/static_map.h b/dep/rehlsdk/engine/static_map.h index 0a6de4d..11235d7 100644 --- a/dep/rehlsdk/engine/static_map.h +++ b/dep/rehlsdk/engine/static_map.h @@ -44,7 +44,7 @@ private: // this was a root node unsigned int rootId = GetRoodNodeId(node->key); if (m_RootNodes[rootId] != node) { - Sys_Error(__FUNCTION__ ": invalid root node"); + Sys_Error("%s: invalid root node", __func__); return; } diff --git a/dep/rehlsdk/engine/sys_shared.cpp b/dep/rehlsdk/engine/sys_shared.cpp index 385b778..c9d0893 100644 --- a/dep/rehlsdk/engine/sys_shared.cpp +++ b/dep/rehlsdk/engine/sys_shared.cpp @@ -29,6 +29,8 @@ #if defined(__GNUC__) #include +#elif _MSC_VER >= 1400 && !defined(ASMLIB_H) +#include // __cpuidex #endif #define SSE3_FLAG (1<<0) @@ -69,4 +71,4 @@ void Sys_CheckCpuInstructionsSupport(void) #endif cpuinfo.avx2 = (cpuid_data[1] & AVX2_FLAG) ? 1 : 0; // ebx -} \ No newline at end of file +} diff --git a/dep/rehlsdk/pm_shared/pm_defs.h b/dep/rehlsdk/pm_shared/pm_defs.h index 1a5f01d..7350c1a 100644 --- a/dep/rehlsdk/pm_shared/pm_defs.h +++ b/dep/rehlsdk/pm_shared/pm_defs.h @@ -208,7 +208,7 @@ typedef struct playermove_s void (*PM_GetModelBounds)( struct model_s *mod, float *mins, float *maxs ); void *(*PM_HullForBsp)( physent_t *pe, float *offset ); float (*PM_TraceModel)( physent_t *pEnt, float *start, float *end, trace_t *trace ); - int (*COM_FileSize)(char *filename); + int (*COM_FileSize)(const char *filename); byte *(*COM_LoadFile) (const char *path, int usehunk, int *pLength); void (*COM_FreeFile) ( void *buffer ); char *(*memfgets)( byte *pMemFile, int fileSize, int *pFilePos, char *pBuffer, int bufferSize ); diff --git a/revoice/src/revoice_cfg.cpp b/revoice/src/revoice_cfg.cpp index 42cc151..12d8286 100644 --- a/revoice/src/revoice_cfg.cpp +++ b/revoice/src/revoice_cfg.cpp @@ -51,10 +51,20 @@ void Revoice_Init_Cvars() g_pcv_sv_voiceenable = g_engfuncs.pfnCVarGetPointer("sv_voiceenable"); g_pcv_rev_hltv_codec = g_engfuncs.pfnCVarGetPointer(g_cv_rev_hltv_codec.name); g_pcv_rev_default_codec = g_engfuncs.pfnCVarGetPointer(g_cv_rev_default_codec.name); + + g_RehldsFuncs->AddCvarListener(g_cv_rev_hltv_codec.name, Revoice_Update_Hltv); + g_RehldsFuncs->AddCvarListener(g_cv_rev_default_codec.name, Revoice_Update_Players); +} + +void Revoice_DeInit_Cvars() +{ + g_RehldsFuncs->RemoveCvarListener(g_cv_rev_hltv_codec.name, Revoice_Update_Hltv); + g_RehldsFuncs->RemoveCvarListener(g_cv_rev_default_codec.name, Revoice_Update_Players); } REVCmds g_revoice_cmds[] = { - { "version", Cmd_REV_Version } + { "version", Cmd_REV_Version }, + { "status", Cmd_REV_Status } }; void Revoice_Cmds_Handler() @@ -75,3 +85,23 @@ void Cmd_REV_Version() g_engfuncs.pfnServerPrint("Build date: " APP_COMMIT_TIME " " APP_COMMIT_DATE "\n"); g_engfuncs.pfnServerPrint("Build from: " APP_COMMIT_URL APP_COMMIT_SHA "\n"); } + +void Cmd_REV_Status() +{ + int nUsers = 0; + UTIL_ServerPrintf("\n%-5s %-32s %-6s %-4s %5s", "#", "name", "codec", "rate", "proto"); + + for (int i = 0; i < g_RehldsSvs->GetMaxClients(); i++) { + auto plr = &g_Players[i]; + if (plr->IsConnected()) { + printf("#%-4i %-32s %-6s %-4i %-2i %-3s", i + 1, UTIL_VarArgs("\"%s\"", plr->GetClient()->GetName()), plr->GetCodecTypeToString(), plr->GetVoiceRate(), plr->GetProtocol(), plr->IsHLTV() ? " (HLTV)" : ""); + nUsers++; + } + } + + if (!nUsers) { + UTIL_ServerPrintf("0 users"); + } + + UTIL_ServerPrintf("\n"); +} diff --git a/revoice/src/revoice_cfg.h b/revoice/src/revoice_cfg.h index 5ce4893..8f415aa 100644 --- a/revoice/src/revoice_cfg.h +++ b/revoice/src/revoice_cfg.h @@ -10,8 +10,11 @@ struct REVCmds { void Revoice_Exec_Config(); bool Revoice_Init_Config(); void Revoice_Init_Cvars(); +void Revoice_DeInit_Cvars(); void Revoice_Cmds_Handler(); + +void Cmd_REV_Status(); void Cmd_REV_Version(); extern cvar_t *g_pcv_sv_voiceenable; diff --git a/revoice/src/revoice_main.cpp b/revoice/src/revoice_main.cpp index ac36a98..c1530ba 100644 --- a/revoice/src/revoice_main.cpp +++ b/revoice/src/revoice_main.cpp @@ -216,16 +216,6 @@ void SV_WriteVoiceCodec_hooked(IRehldsHook_SV_WriteVoiceCodec *chain, sizebuf_t } } -void Cvar_DirectSet_hooked(IRehldsHook_Cvar_DirectSet *chain, cvar_t *var, const char *value) -{ - chain->callNext(var, value); - - if (g_pcv_rev_hltv_codec == var - || g_pcv_rev_default_codec == var) { - Revoice_Update_Players(); - } -} - bool Revoice_Load() { if (!Revoice_Utils_Init()) @@ -256,7 +246,6 @@ bool Revoice_Main_Init() g_RehldsHookchains->SV_DropClient()->registerHook(&SV_DropClient_hook, HC_PRIORITY_DEFAULT + 1); g_RehldsHookchains->HandleNetCommand()->registerHook(&Rehlds_HandleNetCommand, HC_PRIORITY_DEFAULT + 1); g_RehldsHookchains->SV_WriteVoiceCodec()->registerHook(&SV_WriteVoiceCodec_hooked, HC_PRIORITY_DEFAULT + 1); - g_RehldsHookchains->Cvar_DirectSet()->registerHook(&Cvar_DirectSet_hooked, HC_PRIORITY_DEFAULT + 1); return true; } @@ -266,5 +255,6 @@ void Revoice_Main_DeInit() g_RehldsHookchains->SV_DropClient()->unregisterHook(&SV_DropClient_hook); g_RehldsHookchains->HandleNetCommand()->unregisterHook(&Rehlds_HandleNetCommand); g_RehldsHookchains->SV_WriteVoiceCodec()->unregisterHook(&SV_WriteVoiceCodec_hooked); - g_RehldsHookchains->Cvar_DirectSet()->unregisterHook(&Cvar_DirectSet_hooked); + + Revoice_DeInit_Cvars(); } diff --git a/revoice/src/revoice_player.cpp b/revoice/src/revoice_player.cpp index d625445..92bb503 100644 --- a/revoice/src/revoice_player.cpp +++ b/revoice/src/revoice_player.cpp @@ -81,9 +81,12 @@ void CRevoicePlayer::OnDisconnected() void CRevoicePlayer::Update() { - m_CodecType = GetCodecTypeByString(((m_HLTV) ? - g_pcv_rev_hltv_codec : g_pcv_rev_default_codec)->string); + if (m_HLTV) { + m_CodecType = GetCodecTypeByString(g_pcv_rev_hltv_codec->string); + return; + } + m_CodecType = GetCodecTypeByString(g_pcv_rev_default_codec->string); m_RequestId = MAKE_REQUESTID(PLID); if (m_Protocol == 48) { @@ -91,16 +94,6 @@ void CRevoicePlayer::Update() } } -void Revoice_Update_Players() -{ - int maxclients = g_RehldsSvs->GetMaxClients(); - for (int i = 0; i < maxclients; i++) { - if (g_Players[i].IsConnected()) { - g_Players[i].Update(); - } - } -} - void Revoice_Init_Players() { int maxclients = g_RehldsSvs->GetMaxClients(); @@ -109,6 +102,27 @@ void Revoice_Init_Players() } } +void Revoice_Update_Players(const char *pszNewValue) +{ + for (int i = 0; i < g_RehldsSvs->GetMaxClients(); i++) { + auto plr = &g_Players[i]; + if (plr->IsConnected()) { + plr->Update(); + } + } +} + +void Revoice_Update_Hltv(const char *pszNewValue) +{ + int maxclients = g_RehldsSvs->GetMaxClients(); + for (int i = 0; i < g_RehldsSvs->GetMaxClients(); i++) { + auto plr = &g_Players[i]; + if (plr->IsConnected() && plr->IsHLTV()) { + plr->Update(); + } + } +} + CRevoicePlayer *GetPlayerByClientPtr(IGameClient *cl) { return &g_Players[ cl->GetId() ]; diff --git a/revoice/src/revoice_player.h b/revoice/src/revoice_player.h index 51d7181..dc0fc4f 100644 --- a/revoice/src/revoice_player.h +++ b/revoice/src/revoice_player.h @@ -32,6 +32,7 @@ public: CodecType GetCodecTypeByString(const char *codec); const char *GetCodecTypeToString(); + int GetProtocol() const { return m_Protocol; } int GetVoiceRate() const { return m_VoiceRate; } int GetRequestId() const { return m_RequestId; } bool IsConnected() const { return m_Connected; } @@ -53,4 +54,5 @@ CRevoicePlayer *GetPlayerByClientPtr(IGameClient *cl); CRevoicePlayer *GetPlayerByEdict(const edict_t *ed); void Revoice_Init_Players(); -void Revoice_Update_Players(); +void Revoice_Update_Players(const char *pszNewValue); +void Revoice_Update_Hltv(const char *pszNewValue); diff --git a/revoice/src/revoice_shared.h b/revoice/src/revoice_shared.h index 351dc78..0ce756c 100644 --- a/revoice/src/revoice_shared.h +++ b/revoice/src/revoice_shared.h @@ -36,21 +36,6 @@ enum svc_messages { svc_voicedata = 53 }; -template -T _min(T a, T b) { - return (a < b) ? a : b; -} - -template -T _max(T a, T b) { - return (a < b) ? b : a; -} - -template -T clamp(T a, T min, T max) { - return (a > max) ? max : (a < min) ? min : a; -} - extern char* trimbuf(char *str); extern void NormalizePath(char *path); extern bool IsFileExists(const char *path); diff --git a/revoice/src/sdk_util.cpp b/revoice/src/sdk_util.cpp index 115951f..2edd79c 100644 --- a/revoice/src/sdk_util.cpp +++ b/revoice/src/sdk_util.cpp @@ -43,3 +43,35 @@ void UTIL_LogPrintf(char *fmt, ...) // Print to server console ALERT(at_logged, "%s", string); } + +char *UTIL_VarArgs(char *format, ...) +{ + va_list argptr; + static char string[1024]; + + va_start(argptr, format); + vsprintf(string, format, argptr); + va_end(argptr); + + return string; +} + +void UTIL_ServerPrintf(const char *fmt, ...) +{ + // Check is null, test the demo started before than searches pointer to refs + if (&g_engfuncs == nullptr || g_engfuncs.pfnServerPrint == nullptr) + return; + + static char string[1024]; + va_list ap; + va_start(ap, fmt); + vsnprintf(string, sizeof(string), fmt, ap); + va_end(ap); + + if (strlen(string) < sizeof(string) - 2) + strcat(string, "\n"); + else + string[strlen(string) - 1] = '\n'; + + SERVER_PRINT(string); +} diff --git a/revoice/src/voice_codec_frame.cpp b/revoice/src/voice_codec_frame.cpp index b77000e..29a8fa8 100644 --- a/revoice/src/voice_codec_frame.cpp +++ b/revoice/src/voice_codec_frame.cpp @@ -59,7 +59,7 @@ int VoiceCodec_Frame::Compress(const char *pUncompressedBytes, int nSamples, cha } // Store the remaining samples. - int nNewSamples = _min(nSamples, _min(m_nRawSamples - m_nEncodeBufferSamples, m_nRawSamples)); + int nNewSamples = min(nSamples, min(m_nRawSamples - m_nEncodeBufferSamples, m_nRawSamples)); if (nNewSamples) { memcpy(&m_EncodeBuffer[m_nEncodeBufferSamples], &pUncompressed[nSamples - nNewSamples], nNewSamples * BYTES_PER_SAMPLE); m_nEncodeBufferSamples += nNewSamples;