mirror of
https://github.com/rehlds/rehlds.git
synced 2025-02-06 18:42:26 +03:00
Merge pull request #350 from s1lentq/hlds_launcher
Add project HLDS Launcher
This commit is contained in:
commit
69bdbc2575
2
.gitignore
vendored
2
.gitignore
vendored
@ -15,11 +15,11 @@
|
|||||||
**/msvc/*.suo
|
**/msvc/*.suo
|
||||||
**/msvc/*.db
|
**/msvc/*.db
|
||||||
**/msvc/*.opendb
|
**/msvc/*.opendb
|
||||||
|
**/msvc/PublishPath*.txt
|
||||||
**/msvc/ipch
|
**/msvc/ipch
|
||||||
**/msvc/.vs
|
**/msvc/.vs
|
||||||
|
|
||||||
rehlds/version/appversion.h
|
rehlds/version/appversion.h
|
||||||
rehlds/msvc/PublishPath*.txt
|
|
||||||
rehlds/_rehldsTestImg
|
rehlds/_rehldsTestImg
|
||||||
rehlds/_dev
|
rehlds/_dev
|
||||||
publish
|
publish
|
||||||
|
@ -2,11 +2,25 @@ import org.doomedsociety.gradlecpp.GradleCppUtils
|
|||||||
import org.apache.commons.io.FilenameUtils
|
import org.apache.commons.io.FilenameUtils
|
||||||
|
|
||||||
void _copyFileToDir(String from, String to) {
|
void _copyFileToDir(String from, String to) {
|
||||||
|
if (!project.file(from).exists()) {
|
||||||
|
println 'WARNING: Could not find: ' + from;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!project.file(to).exists()) {
|
||||||
|
project.file(to).mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
def dst = new File(project.file(to), FilenameUtils.getName(from))
|
def dst = new File(project.file(to), FilenameUtils.getName(from))
|
||||||
GradleCppUtils.copyFile(project.file(from), dst, false)
|
GradleCppUtils.copyFile(project.file(from), dst, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
void _copyFile(String from, String to) {
|
void _copyFile(String from, String to) {
|
||||||
|
if (!project.file(from).exists()) {
|
||||||
|
println 'WARNING: Could not find: ' + from;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
GradleCppUtils.copyFile(project.file(from), project.file(to), false)
|
GradleCppUtils.copyFile(project.file(from), project.file(to), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,19 +36,21 @@ task publishPrepareFiles {
|
|||||||
|
|
||||||
pubRootDir.mkdirs()
|
pubRootDir.mkdirs()
|
||||||
|
|
||||||
//bugfixed binaries
|
// bugfixed binaries
|
||||||
project.file('publish/publishRoot/bin/bugfixed').mkdirs()
|
|
||||||
_copyFileToDir('publish/releaseRehldsFixes/swds.dll', 'publish/publishRoot/bin/bugfixed/')
|
_copyFileToDir('publish/releaseRehldsFixes/swds.dll', 'publish/publishRoot/bin/bugfixed/')
|
||||||
_copyFileToDir('publish/releaseRehldsFixes/swds.pdb', 'publish/publishRoot/bin/bugfixed/')
|
_copyFileToDir('publish/releaseRehldsFixes/swds.pdb', 'publish/publishRoot/bin/bugfixed/')
|
||||||
_copyFile('publish/releaseRehldsFixes/libengine_i486.so', 'publish/publishRoot/bin/bugfixed/engine_i486.so')
|
_copyFile('publish/releaseRehldsFixes/libengine_i486.so', 'publish/publishRoot/bin/bugfixed/engine_i486.so')
|
||||||
|
|
||||||
//pure binaries
|
// pure binaries
|
||||||
project.file('publish/publishRoot/bin/pure').mkdirs()
|
|
||||||
_copyFileToDir('publish/releaseRehldsNofixes/swds.dll', 'publish/publishRoot/bin/pure/')
|
_copyFileToDir('publish/releaseRehldsNofixes/swds.dll', 'publish/publishRoot/bin/pure/')
|
||||||
_copyFileToDir('publish/releaseRehldsNofixes/swds.pdb', 'publish/publishRoot/bin/pure/')
|
_copyFileToDir('publish/releaseRehldsNofixes/swds.pdb', 'publish/publishRoot/bin/pure/')
|
||||||
_copyFile('publish/releaseRehldsNofixes/libengine_i486.so', 'publish/publishRoot/bin/pure/engine_i486.so')
|
_copyFile('publish/releaseRehldsNofixes/libengine_i486.so', 'publish/publishRoot/bin/pure/engine_i486.so')
|
||||||
|
|
||||||
//hlsdk
|
// dedicated binaries
|
||||||
|
_copyFile('publish/hlds.exe', 'publish/publishRoot/bin/hlds.exe')
|
||||||
|
_copyFile('publish/hlds_linux', 'publish/publishRoot/bin/hlds_linux')
|
||||||
|
|
||||||
|
// hlsdk
|
||||||
project.file('publish/publishRoot/hlsdk').mkdirs()
|
project.file('publish/publishRoot/hlsdk').mkdirs()
|
||||||
copy {
|
copy {
|
||||||
from 'rehlds/common'
|
from 'rehlds/common'
|
||||||
@ -58,8 +74,7 @@ task publishPrepareFiles {
|
|||||||
into 'publish/publishRoot/hlsdk/engine'
|
into 'publish/publishRoot/hlsdk/engine'
|
||||||
}
|
}
|
||||||
|
|
||||||
//flightrecorder
|
// flightrecorder
|
||||||
|
|
||||||
def flightRecJarTask = project(':flightrec/decoder').tasks.getByName('uberjar')
|
def flightRecJarTask = project(':flightrec/decoder').tasks.getByName('uberjar')
|
||||||
println flightRecJarTask
|
println flightRecJarTask
|
||||||
println flightRecJarTask.class.name
|
println flightRecJarTask.class.name
|
||||||
|
140
rehlds/common/BaseSystemModule.cpp
Normal file
140
rehlds/common/BaseSystemModule.cpp
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
#include "BaseSystemModule.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
BaseSystemModule::BaseSystemModule()
|
||||||
|
{
|
||||||
|
m_State = MODULE_INACTIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseSystemModule::~BaseSystemModule()
|
||||||
|
{
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
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_PENDING;
|
||||||
|
m_System = system;
|
||||||
|
m_Serial = serial;
|
||||||
|
m_SystemTime = 0;
|
||||||
|
|
||||||
|
if (name)
|
||||||
|
{
|
||||||
|
strncpy(m_Name, name, sizeof m_Name - 1);
|
||||||
|
m_Name[sizeof m_Name - 1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseSystemModule::RunFrame(double time)
|
||||||
|
{
|
||||||
|
m_SystemTime = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseSystemModule::ShutDown()
|
||||||
|
{
|
||||||
|
if (m_State == MODULE_UNLOAD)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_Listener.Clear();
|
||||||
|
m_State = MODULE_UNLOAD;
|
||||||
|
|
||||||
|
// TODO: Check me!
|
||||||
|
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;
|
||||||
|
}
|
55
rehlds/common/BaseSystemModule.h
Normal file
55
rehlds/common/BaseSystemModule.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#ifndef BASESYSTEMMODULE_H
|
||||||
|
#define BASESYSTEMMODULE_H
|
||||||
|
#ifdef _WIN32
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "ObjectList.h"
|
||||||
|
#include "IBaseSystem.h"
|
||||||
|
|
||||||
|
#define SIGNAL_MODULE_CLOSE 8 // closing down module
|
||||||
|
|
||||||
|
enum ModuleState
|
||||||
|
{
|
||||||
|
MODULE_INACTIVE,
|
||||||
|
MODULE_PENDING,
|
||||||
|
MODULE_RUNNING,
|
||||||
|
MODULE_LOAD,
|
||||||
|
MODULE_UNLOAD
|
||||||
|
};
|
||||||
|
|
||||||
|
// C4250 - 'class1' : inherits 'BaseSystemModule::member' via dominance
|
||||||
|
#pragma warning(disable:4250)
|
||||||
|
|
||||||
|
class BaseSystemModule: virtual public ISystemModule {
|
||||||
|
public:
|
||||||
|
BaseSystemModule();
|
||||||
|
virtual ~BaseSystemModule();
|
||||||
|
|
||||||
|
virtual bool Init(IBaseSystem *system, int serial, char *name);
|
||||||
|
virtual void RunFrame(double time);
|
||||||
|
virtual void ReceiveSignal(ISystemModule *module, unsigned int signal, void *data);
|
||||||
|
virtual void ExecuteCommand(int commandID, char *commandLine);
|
||||||
|
virtual void RegisterListener(ISystemModule *module);
|
||||||
|
virtual void RemoveListener(ISystemModule *module);
|
||||||
|
virtual IBaseSystem *GetSystem();
|
||||||
|
virtual int GetSerial();
|
||||||
|
virtual char *GetStatusLine();
|
||||||
|
virtual char *GetType();
|
||||||
|
virtual char *GetName();
|
||||||
|
virtual int GetState();
|
||||||
|
virtual int GetVersion();
|
||||||
|
virtual void ShutDown();
|
||||||
|
virtual char *COM_GetBaseDir() { return ""; }
|
||||||
|
void FireSignal(unsigned int signal, void *data);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
IBaseSystem *m_System;
|
||||||
|
ObjectList m_Listener;
|
||||||
|
char m_Name[255];
|
||||||
|
unsigned int m_State;
|
||||||
|
unsigned int m_Serial;
|
||||||
|
double m_SystemTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // BASESYSTEMMODULE_H
|
33
rehlds/common/IAdminServer.h
Normal file
33
rehlds/common/IAdminServer.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#ifndef IADMINSERVER_H
|
||||||
|
#define IADMINSERVER_H
|
||||||
|
#ifdef _WIN32
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#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"
|
||||||
|
|
||||||
|
|
||||||
|
#endif // IAdminServer_H
|
59
rehlds/common/IBaseSystem.h
Normal file
59
rehlds/common/IBaseSystem.h
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
#ifndef IBASESYSTEM_H
|
||||||
|
#define IBASESYSTEM_H
|
||||||
|
#ifdef _WIN32
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "ISystemModule.h"
|
||||||
|
|
||||||
|
class Panel;
|
||||||
|
class ObjectList;
|
||||||
|
class IFileSystem;
|
||||||
|
class IVGuiModule;
|
||||||
|
|
||||||
|
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, int maxSize) = 0;
|
||||||
|
|
||||||
|
virtual IFileSystem *GetFileSystem() = 0;
|
||||||
|
virtual unsigned char *LoadFile(const char *name, int *length) = 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 *COM_GetBaseDir() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // IBASESYSTEM_H
|
25
rehlds/common/IObjectContainer.h
Normal file
25
rehlds/common/IObjectContainer.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#ifndef IOBJECTCONTAINER_H
|
||||||
|
#define IOBJECTCONTAINER_H
|
||||||
|
#ifdef _WIN32
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // IOBJECTCONTAINER_H
|
35
rehlds/common/ISystemModule.h
Normal file
35
rehlds/common/ISystemModule.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#ifndef ISYSTEMMODULE_H
|
||||||
|
#define ISYSTEMMODULE_H
|
||||||
|
#ifdef _WIN32
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#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) = 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;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ISYSTEMMODULE_H
|
54
rehlds/common/IVGuiModule.h
Normal file
54
rehlds/common/IVGuiModule.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#ifndef IVGUIMODULE_H
|
||||||
|
#define IVGUIMODULE_H
|
||||||
|
#ifdef _WIN32
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <vgui/VGUI.h>
|
||||||
|
#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, int factoryCount) = 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"
|
||||||
|
|
||||||
|
#endif // IVGUIMODULE_H
|
483
rehlds/common/ObjectDictionary.cpp
Normal file
483
rehlds/common/ObjectDictionary.cpp
Normal file
@ -0,0 +1,483 @@
|
|||||||
|
#include "ObjectDictionary.h"
|
||||||
|
#include "maintypes.h"
|
||||||
|
|
||||||
|
ObjectDictionary::ObjectDictionary() :
|
||||||
|
maxSize(0),
|
||||||
|
size(0),
|
||||||
|
entries(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectDictionary::~ObjectDictionary()
|
||||||
|
{
|
||||||
|
if (entries) {
|
||||||
|
free(entries);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectDictionary::Clear(bool freeObjectssMemory)
|
||||||
|
{
|
||||||
|
if (freeObjectssMemory)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
void *obj = entries[i].object;
|
||||||
|
if (obj) {
|
||||||
|
free(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size = 0;
|
||||||
|
CheckSize();
|
||||||
|
ClearCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ObjectDictionary::Add(void *object, float key)
|
||||||
|
{
|
||||||
|
if (size == maxSize && !CheckSize())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
entry_t *p;
|
||||||
|
if (size && key < entries[size - 1].key)
|
||||||
|
{
|
||||||
|
p = &entries[FindClosestAsIndex(key)];
|
||||||
|
|
||||||
|
entry_t *e1 = &entries[size];
|
||||||
|
entry_t *e2 = &entries[size - 1];
|
||||||
|
|
||||||
|
while (p->key <= key) { p++; }
|
||||||
|
while (p != e1)
|
||||||
|
{
|
||||||
|
e1->object = e2->object;
|
||||||
|
e1->key = e2->key;
|
||||||
|
|
||||||
|
e1--;
|
||||||
|
e2--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
p = &entries[size];
|
||||||
|
|
||||||
|
p->key = key;
|
||||||
|
p->object = object;
|
||||||
|
size++;
|
||||||
|
|
||||||
|
ClearCache();
|
||||||
|
AddToCache(p);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ObjectDictionary::FindClosestAsIndex(float key)
|
||||||
|
{
|
||||||
|
UNTESTED
|
||||||
|
|
||||||
|
if (size <= 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (key <= entries->key)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int index = FindKeyInCache(key);
|
||||||
|
if (index >= 0)
|
||||||
|
return index;
|
||||||
|
|
||||||
|
int middle;
|
||||||
|
int first = 0;
|
||||||
|
int last = size - 1;
|
||||||
|
float keyMiddle, keyNext;
|
||||||
|
|
||||||
|
if (key == entries[last].key)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
middle = (last + first) >> 1;
|
||||||
|
keyMiddle = entries[middle].key;
|
||||||
|
|
||||||
|
if (keyMiddle == key)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (keyMiddle < key)
|
||||||
|
{
|
||||||
|
if (entries[middle + 1].key != key)
|
||||||
|
{
|
||||||
|
if (entries[middle + 1].key - key < key - keyMiddle)
|
||||||
|
++middle;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
first = (last + first) >> 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
last = (last + first) >> 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
middle = last;
|
||||||
|
}
|
||||||
|
|
||||||
|
keyNext = entries[middle - 1].key;
|
||||||
|
while (keyNext == key) {
|
||||||
|
keyNext = entries[middle--].key;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddToCache(&entries[middle], key);
|
||||||
|
return middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectDictionary::ClearCache()
|
||||||
|
{
|
||||||
|
memset(cache, 0, sizeof(cache));
|
||||||
|
cacheIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ObjectDictionary::RemoveIndex(int index, bool freeObjectMemory)
|
||||||
|
{
|
||||||
|
if (index < 0 || index >= size)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
entry_t *p = &entries[size - 1];
|
||||||
|
entry_t *e1 = &entries[size];
|
||||||
|
entry_t *e2 = &entries[size + 1];
|
||||||
|
|
||||||
|
if (freeObjectMemory && e1->object)
|
||||||
|
free(e1->object);
|
||||||
|
|
||||||
|
while (p != e1)
|
||||||
|
{
|
||||||
|
e1->object = e2->object;
|
||||||
|
e1->key = e2->key;
|
||||||
|
|
||||||
|
e1++;
|
||||||
|
e2++;
|
||||||
|
}
|
||||||
|
|
||||||
|
p->object = nullptr;
|
||||||
|
p->key = 0;
|
||||||
|
size--;
|
||||||
|
|
||||||
|
CheckSize();
|
||||||
|
ClearCache();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ObjectDictionary::RemoveIndexRange(int minIndex, int maxIndex)
|
||||||
|
{
|
||||||
|
if (minIndex > maxIndex)
|
||||||
|
{
|
||||||
|
if (maxIndex < 0)
|
||||||
|
maxIndex = 0;
|
||||||
|
|
||||||
|
if (minIndex >= size)
|
||||||
|
minIndex = size - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (minIndex < 0)
|
||||||
|
minIndex = 0;
|
||||||
|
|
||||||
|
if (maxIndex >= size)
|
||||||
|
maxIndex = size - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int offset = minIndex + maxIndex - 1;
|
||||||
|
size -= offset;
|
||||||
|
CheckSize();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ObjectDictionary::Remove(void *object)
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
for (int i = 0; i < size; ++i)
|
||||||
|
{
|
||||||
|
if (entries[i].object == object) {
|
||||||
|
RemoveIndex(i);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return found ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ObjectDictionary::RemoveSingle(void *object)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < size; ++i)
|
||||||
|
{
|
||||||
|
if (entries[i].object == object) {
|
||||||
|
RemoveIndex(i);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ObjectDictionary::RemoveKey(float key)
|
||||||
|
{
|
||||||
|
int i = FindClosestAsIndex(key);
|
||||||
|
if (entries[i].key == key)
|
||||||
|
{
|
||||||
|
int j = i;
|
||||||
|
do {
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
while (key == entries[j + 1].key);
|
||||||
|
|
||||||
|
return RemoveIndexRange(i, j);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ObjectDictionary::CheckSize()
|
||||||
|
{
|
||||||
|
int newSize = maxSize;
|
||||||
|
if (size == maxSize)
|
||||||
|
{
|
||||||
|
newSize = 1 - (int)(maxSize * -1.25f);
|
||||||
|
}
|
||||||
|
else if (maxSize * 0.5f >size)
|
||||||
|
{
|
||||||
|
newSize = (int)(maxSize * 0.75f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newSize != maxSize)
|
||||||
|
{
|
||||||
|
entry_t *newEntries = (entry_t *)malloc(sizeof(entry_t));
|
||||||
|
if (!newEntries)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
memset(&newEntries[size], 0, sizeof(entry_t) * (newSize - size));
|
||||||
|
|
||||||
|
if (entries && size)
|
||||||
|
{
|
||||||
|
memcpy(newEntries, entries, sizeof(entry_t) * size);
|
||||||
|
free(entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
entries = newEntries;
|
||||||
|
maxSize = newSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectDictionary::Init()
|
||||||
|
{
|
||||||
|
size = 0;
|
||||||
|
maxSize = 0;
|
||||||
|
entries = nullptr;
|
||||||
|
|
||||||
|
CheckSize();
|
||||||
|
ClearCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectDictionary::Init(int baseSize)
|
||||||
|
{
|
||||||
|
size = 0;
|
||||||
|
maxSize = 0;
|
||||||
|
entries = (entry_t *)Mem_ZeroMalloc(sizeof(entry_t) * baseSize);
|
||||||
|
|
||||||
|
if (entries) {
|
||||||
|
maxSize = baseSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ObjectDictionary::Add(void *object)
|
||||||
|
{
|
||||||
|
return Add(object, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ObjectDictionary::CountElements()
|
||||||
|
{
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ObjectDictionary::IsEmpty()
|
||||||
|
{
|
||||||
|
return (size == 0) ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ObjectDictionary::Contains(void *object)
|
||||||
|
{
|
||||||
|
if (FindObjectInCache(object) >= 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
for (int i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
entry_t *e = &entries[i];
|
||||||
|
if (e->object == object) {
|
||||||
|
AddToCache(e);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *ObjectDictionary::GetFirst()
|
||||||
|
{
|
||||||
|
currentEntry = 0;
|
||||||
|
return GetNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
void *ObjectDictionary::GetLast()
|
||||||
|
{
|
||||||
|
return (size > 0) ? entries[size - 1].object : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ObjectDictionary::ChangeKey(void *object, float newKey)
|
||||||
|
{
|
||||||
|
int pos = FindObjectInCache(object);
|
||||||
|
if (pos < 0)
|
||||||
|
{
|
||||||
|
for (pos = 0; pos < size; pos++)
|
||||||
|
{
|
||||||
|
if (entries[pos].object == object) {
|
||||||
|
AddToCache(&entries[pos]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pos == size) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
entry_t *p, *e;
|
||||||
|
|
||||||
|
p = &entries[pos];
|
||||||
|
if (p->key == newKey)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int newpos = FindClosestAsIndex(newKey);
|
||||||
|
e = &entries[newpos];
|
||||||
|
if (pos < newpos)
|
||||||
|
{
|
||||||
|
if (e->key > newKey)
|
||||||
|
e--;
|
||||||
|
|
||||||
|
entry_t *e2 = &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 = &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 < size; pos++)
|
||||||
|
{
|
||||||
|
if (entries[pos].object == object) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pos == size) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
entries[pos].key = newKey;
|
||||||
|
ClearCache();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectDictionary::AddToCache(entry_t *entry)
|
||||||
|
{
|
||||||
|
int i = (cacheIndex % 32);
|
||||||
|
|
||||||
|
cache[i].object = entry;
|
||||||
|
cache[i].key = entry->key;
|
||||||
|
cacheIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectDictionary::AddToCache(entry_t *entry, float key)
|
||||||
|
{
|
||||||
|
int i = (cacheIndex % 32);
|
||||||
|
|
||||||
|
cache[i].object = entry;
|
||||||
|
cache[i].key = key;
|
||||||
|
cacheIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ObjectDictionary::FindKeyInCache(float key)
|
||||||
|
{
|
||||||
|
for (auto& ch : cache)
|
||||||
|
{
|
||||||
|
if (ch.object && ch.key == key) {
|
||||||
|
return (entry_t *)ch.object - entries;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ObjectDictionary::FindObjectInCache(void *object)
|
||||||
|
{
|
||||||
|
for (auto& ch : cache)
|
||||||
|
{
|
||||||
|
if (ch.object && ch.object == object) {
|
||||||
|
return (entry_t *)ch.object - entries;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *ObjectDictionary::FindClosestKey(float key)
|
||||||
|
{
|
||||||
|
currentEntry = FindClosestAsIndex(key);
|
||||||
|
return GetNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
void *ObjectDictionary::GetNext()
|
||||||
|
{
|
||||||
|
if (currentEntry < 0 || currentEntry >= size)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return &entries[currentEntry++];
|
||||||
|
}
|
||||||
|
|
||||||
|
void *ObjectDictionary::FindExactKey(float key)
|
||||||
|
{
|
||||||
|
if ((currentEntry = FindClosestAsIndex(key)) < 0)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return (entries[currentEntry].key == key) ? GetNext() : nullptr;
|
||||||
|
}
|
73
rehlds/common/ObjectDictionary.h
Normal file
73
rehlds/common/ObjectDictionary.h
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
#ifndef OBJECTDICTIONARY_H
|
||||||
|
#define OBJECTDICTIONARY_H
|
||||||
|
#ifdef _WIN32
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "IObjectContainer.h"
|
||||||
|
|
||||||
|
typedef struct entry_s {
|
||||||
|
void *object;
|
||||||
|
float key;
|
||||||
|
} entry_t;
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
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 currentEntry;
|
||||||
|
float findKey;
|
||||||
|
|
||||||
|
enum { MAX_OBJECT_CACHE = 32 };
|
||||||
|
|
||||||
|
entry_t *entries;
|
||||||
|
entry_t cache[MAX_OBJECT_CACHE];
|
||||||
|
|
||||||
|
int cacheIndex;
|
||||||
|
int size;
|
||||||
|
int maxSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // OBJECTDICTIONARY_H
|
232
rehlds/common/ObjectList.cpp
Normal file
232
rehlds/common/ObjectList.cpp
Normal file
@ -0,0 +1,232 @@
|
|||||||
|
#include "ObjectList.h"
|
||||||
|
|
||||||
|
ObjectList::ObjectList()
|
||||||
|
{
|
||||||
|
head = tail = current = nullptr;
|
||||||
|
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 (head)
|
||||||
|
{
|
||||||
|
newElement->next = head;
|
||||||
|
head->prev = newElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
head = newElement;
|
||||||
|
|
||||||
|
// if list was empty set new tail
|
||||||
|
if (!tail)
|
||||||
|
tail = head;
|
||||||
|
|
||||||
|
number++;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *ObjectList::RemoveHead()
|
||||||
|
{
|
||||||
|
void *retObj;
|
||||||
|
|
||||||
|
// check head is present
|
||||||
|
if (head)
|
||||||
|
{
|
||||||
|
retObj = head->object;
|
||||||
|
element_t *newHead = head->next;
|
||||||
|
if (newHead)
|
||||||
|
newHead->prev = nullptr;
|
||||||
|
|
||||||
|
// if only one element is in list also update tail
|
||||||
|
// if we remove this prev element
|
||||||
|
if (tail == head)
|
||||||
|
tail = nullptr;
|
||||||
|
|
||||||
|
free(head);
|
||||||
|
head = newHead;
|
||||||
|
|
||||||
|
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 (tail)
|
||||||
|
{
|
||||||
|
newElement->prev = tail;
|
||||||
|
tail->next = newElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
tail = newElement;
|
||||||
|
|
||||||
|
// if list was empty set new tail
|
||||||
|
if (!head)
|
||||||
|
head = tail;
|
||||||
|
|
||||||
|
number++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *ObjectList::RemoveTail()
|
||||||
|
{
|
||||||
|
void *retObj;
|
||||||
|
|
||||||
|
// check tail is present
|
||||||
|
if (tail)
|
||||||
|
{
|
||||||
|
retObj = tail->object;
|
||||||
|
element_t *newTail = tail->prev;
|
||||||
|
if (newTail)
|
||||||
|
newTail->next = nullptr;
|
||||||
|
|
||||||
|
// if only one element is in list also update tail
|
||||||
|
// if we remove this prev element
|
||||||
|
if (head == tail)
|
||||||
|
head = nullptr;
|
||||||
|
|
||||||
|
free(tail);
|
||||||
|
tail = newTail;
|
||||||
|
|
||||||
|
number--;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
retObj = nullptr;
|
||||||
|
|
||||||
|
return retObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ObjectList::IsEmpty()
|
||||||
|
{
|
||||||
|
return (head == nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ObjectList::CountElements()
|
||||||
|
{
|
||||||
|
return number;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ObjectList::Contains(void *object)
|
||||||
|
{
|
||||||
|
element_t *e = head;
|
||||||
|
|
||||||
|
while (e && e->object != object) { e = e->next; }
|
||||||
|
|
||||||
|
if (e)
|
||||||
|
{
|
||||||
|
current = e;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectList::Clear(bool freeElementsMemory)
|
||||||
|
{
|
||||||
|
element_t *ne;
|
||||||
|
element_t *e = head;
|
||||||
|
|
||||||
|
while (e)
|
||||||
|
{
|
||||||
|
ne = e->next;
|
||||||
|
|
||||||
|
if (freeElementsMemory && e->object)
|
||||||
|
free(e->object);
|
||||||
|
|
||||||
|
free(e);
|
||||||
|
e = ne;
|
||||||
|
}
|
||||||
|
|
||||||
|
head = tail = current = nullptr;
|
||||||
|
number = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ObjectList::Remove(void *object)
|
||||||
|
{
|
||||||
|
element_t *e = 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 (head == e) head = e->next;
|
||||||
|
if (tail == e) tail = e->prev;
|
||||||
|
if (current == e) current= e->next;
|
||||||
|
|
||||||
|
free(e);
|
||||||
|
number--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (e != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectList::Init()
|
||||||
|
{
|
||||||
|
head = tail = current = nullptr;
|
||||||
|
number = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *ObjectList::GetFirst()
|
||||||
|
{
|
||||||
|
if (head)
|
||||||
|
{
|
||||||
|
current = head->next;
|
||||||
|
return head->object;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
current = nullptr;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *ObjectList::GetNext()
|
||||||
|
{
|
||||||
|
void *retObj = nullptr;
|
||||||
|
if (current)
|
||||||
|
{
|
||||||
|
retObj = current->object;
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return retObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ObjectList::Add(void *newObject)
|
||||||
|
{
|
||||||
|
return AddTail(newObject);
|
||||||
|
}
|
43
rehlds/common/ObjectList.h
Normal file
43
rehlds/common/ObjectList.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#ifndef OBJECTLIST_H
|
||||||
|
#define OBJECTLIST_H
|
||||||
|
#ifdef _WIN32
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "IObjectContainer.h"
|
||||||
|
|
||||||
|
class ObjectList: public IObjectContainer {
|
||||||
|
public:
|
||||||
|
void Init();
|
||||||
|
bool Add(void *newObject);
|
||||||
|
void *GetFirst();
|
||||||
|
void *GetNext();
|
||||||
|
|
||||||
|
ObjectList();
|
||||||
|
virtual ~ObjectList();
|
||||||
|
|
||||||
|
void Clear(bool freeElementsMemory = false);
|
||||||
|
int CountElements();
|
||||||
|
void *RemoveTail();
|
||||||
|
void *RemoveHead();
|
||||||
|
|
||||||
|
bool AddTail(void *newObject);
|
||||||
|
bool AddHead(void *newObject);
|
||||||
|
bool Remove(void *object);
|
||||||
|
bool Contains(void *object);
|
||||||
|
bool IsEmpty();
|
||||||
|
|
||||||
|
typedef struct element_s {
|
||||||
|
element_s *prev; // pointer to the last element or NULL
|
||||||
|
element_s *next; // pointer to the next elemnet or NULL
|
||||||
|
void *object; // the element's object
|
||||||
|
} element_t;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
element_t *head; // first element in list
|
||||||
|
element_t *tail; // last element in list
|
||||||
|
element_t *current; // current element in list
|
||||||
|
int number;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // OBJECTLIST_H
|
181
rehlds/common/SteamAppStartUp.cpp
Normal file
181
rehlds/common/SteamAppStartUp.cpp
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
#ifdef _WIN32
|
||||||
|
#include "SteamAppStartup.h"
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <assert.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#include <process.h>
|
||||||
|
#include <direct.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#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 = 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<DWORD>( strlen(appPath) + 1 );
|
||||||
|
RegSetValueEx(hKey, "TempAppPath", NULL, dwType, (LPBYTE)appPath, dwSize);
|
||||||
|
dwSize = static_cast<DWORD>( 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 = strrchr(dir, '\\');
|
||||||
|
while (slash)
|
||||||
|
{
|
||||||
|
// see if steam_dev.exe is in the directory first
|
||||||
|
slash[1] = 0;
|
||||||
|
strcat(slash, "steam_dev.exe");
|
||||||
|
FILE *f = fopen(dir, "rb");
|
||||||
|
if (f)
|
||||||
|
{
|
||||||
|
// found it
|
||||||
|
fclose(f);
|
||||||
|
strcpy(steamExe, dir);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see if steam.exe is in the directory
|
||||||
|
slash[1] = 0;
|
||||||
|
strcat(slash, "steam.exe");
|
||||||
|
f = fopen(dir, "rb");
|
||||||
|
if (f)
|
||||||
|
{
|
||||||
|
// found it
|
||||||
|
fclose(f);
|
||||||
|
strcpy(steamExe, dir);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// kill the string at the slash
|
||||||
|
slash[0] = 0;
|
||||||
|
|
||||||
|
// move to the previous slash
|
||||||
|
slash = 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
|
||||||
|
strcpy(dir, steamExe);
|
||||||
|
char *delimiter = 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 = strstr(lpCmdLine, STEAM_PARM);
|
||||||
|
|
||||||
|
// check the character following it is a whitespace or null
|
||||||
|
if (steamStr)
|
||||||
|
{
|
||||||
|
const char *postChar = steamStr + 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
|
15
rehlds/common/SteamAppStartUp.h
Normal file
15
rehlds/common/SteamAppStartUp.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#ifndef STEAMAPPSTARTUP_H
|
||||||
|
#define STEAMAPPSTARTUP_H
|
||||||
|
#ifdef _WIN32
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
#endif // STEAMAPPSTARTUP_H
|
294
rehlds/common/TextConsoleUnix.cpp
Normal file
294
rehlds/common/TextConsoleUnix.cpp
Normal file
@ -0,0 +1,294 @@
|
|||||||
|
#if !defined(_WIN32)
|
||||||
|
|
||||||
|
#include "TextConsoleUnix.h"
|
||||||
|
#include "icommandline.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
CTextConsoleUnix console;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
37
rehlds/common/TextConsoleUnix.h
Normal file
37
rehlds/common/TextConsoleUnix.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#ifndef TEXTCONSOLE_UNIX_H
|
||||||
|
#define TEXTCONSOLE_UNIX_H
|
||||||
|
#ifdef _WIN32
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <termios.h>
|
||||||
|
#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;
|
||||||
|
|
||||||
|
#endif // TEXTCONSOLE_UNIX_H
|
250
rehlds/common/TextConsoleWin32.cpp
Normal file
250
rehlds/common/TextConsoleWin32.cpp
Normal file
@ -0,0 +1,250 @@
|
|||||||
|
#if defined(_WIN32)
|
||||||
|
#include "TextConsoleWin32.h"
|
||||||
|
|
||||||
|
CTextConsoleWin32 console;
|
||||||
|
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
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");
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numevents <= 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!ReadConsoleInput(hinput, recs, ARRAYSIZE(recs), &numread))
|
||||||
|
{
|
||||||
|
if (m_System)
|
||||||
|
m_System->Errorf("CTextConsoleWin32::GetLine: !ReadConsoleInput");
|
||||||
|
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 : strlen(outputStr), NULL, NULL);
|
||||||
|
#else
|
||||||
|
WriteFile(houtput, pszMsg, nChars ? nChars : 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)
|
||||||
|
{
|
||||||
|
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)
|
39
rehlds/common/TextConsoleWin32.h
Normal file
39
rehlds/common/TextConsoleWin32.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#ifndef TEXTCONSOLE_WIN32_H
|
||||||
|
#define TEXTCONSOLE_WIN32_H
|
||||||
|
#ifdef _WIN32
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#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;
|
||||||
|
|
||||||
|
#endif // TEXTCONSOLE_WIN32_H
|
131
rehlds/common/TokenLine.cpp
Normal file
131
rehlds/common/TokenLine.cpp
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
#include "TokenLine.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
TokenLine::TokenLine()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TokenLine::TokenLine(char *string)
|
||||||
|
{
|
||||||
|
SetLine(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
TokenLine::~TokenLine()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TokenLine::SetLine(const char *newLine)
|
||||||
|
{
|
||||||
|
m_tokenNumber = 0;
|
||||||
|
|
||||||
|
if (!newLine || (strlen(newLine) >= (MAX_LINE_CHARS - 1)))
|
||||||
|
{
|
||||||
|
memset(m_fullLine, 0, MAX_LINE_CHARS);
|
||||||
|
memset(m_tokenBuffer, 0, MAX_LINE_CHARS);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(m_fullLine, newLine, MAX_LINE_CHARS - 1);
|
||||||
|
m_fullLine[MAX_LINE_CHARS - 1] = '\0';
|
||||||
|
|
||||||
|
strncpy(m_tokenBuffer, newLine, MAX_LINE_CHARS - 1);
|
||||||
|
m_tokenBuffer[MAX_LINE_CHARS - 1] = '\0';
|
||||||
|
|
||||||
|
// parse tokens
|
||||||
|
char *charPointer = m_tokenBuffer;
|
||||||
|
while (*charPointer && (m_tokenNumber < MAX_LINE_TOKENS))
|
||||||
|
{
|
||||||
|
while (*charPointer && ((*charPointer <= 32) || (*charPointer > 126)))
|
||||||
|
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 (!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);
|
||||||
|
}
|
29
rehlds/common/TokenLine.h
Normal file
29
rehlds/common/TokenLine.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#ifndef TOKENLINE_H
|
||||||
|
#define TOKENLINE_H
|
||||||
|
#ifdef _WIN32
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TOKENLINE_H
|
208
rehlds/common/netapi.cpp
Normal file
208
rehlds/common/netapi.cpp
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include "winsock.h"
|
||||||
|
#else
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
25
rehlds/common/netapi.h
Normal file
25
rehlds/common/netapi.h
Normal file
@ -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
|
344
rehlds/common/textconsole.cpp
Normal file
344
rehlds/common/textconsole.cpp
Normal file
@ -0,0 +1,344 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <port.h>
|
||||||
|
|
||||||
|
#include "textconsole.h"
|
||||||
|
#include "ObjectList.h"
|
||||||
|
|
||||||
|
bool CTextConsole::Init(IBaseSystem *system)
|
||||||
|
{
|
||||||
|
// NULL or a valid base system interface
|
||||||
|
m_System = system;
|
||||||
|
|
||||||
|
memset(m_szConsoleText, 0, sizeof(m_szConsoleText));
|
||||||
|
m_nConsoleTextLen = 0;
|
||||||
|
m_nCursorPosition = 0;
|
||||||
|
|
||||||
|
memset(m_szSavedConsoleText, 0, sizeof(m_szSavedConsoleText));
|
||||||
|
m_nSavedConsoleTextLen = 0;
|
||||||
|
|
||||||
|
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::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) || (strcmp(m_aszLineBuffer[ m_nInputLine - 1 ], m_szConsoleText)))
|
||||||
|
{
|
||||||
|
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 + strlen(m_szConsoleText);
|
||||||
|
|
||||||
|
if (pszRest)
|
||||||
|
{
|
||||||
|
Echo(pszRest);
|
||||||
|
strcat(m_szConsoleText, pszRest);
|
||||||
|
m_nConsoleTextLen += strlen(pszRest);
|
||||||
|
|
||||||
|
Echo(" ");
|
||||||
|
strcat(m_szConsoleText, " ");
|
||||||
|
m_nConsoleTextLen++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int nLongestCmd = 0;
|
||||||
|
int nCurrentColumn;
|
||||||
|
int nTotalColumns;
|
||||||
|
|
||||||
|
char *pszCurrentCmd = (char *)matches.GetFirst();
|
||||||
|
while (pszCurrentCmd)
|
||||||
|
{
|
||||||
|
if ((int)strlen(pszCurrentCmd) > nLongestCmd)
|
||||||
|
nLongestCmd = strlen(pszCurrentCmd);
|
||||||
|
|
||||||
|
pszCurrentCmd = (char *)matches.GetNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
nTotalColumns = (GetWidth() - 1) / (nLongestCmd + 1);
|
||||||
|
nCurrentColumn = 0;
|
||||||
|
|
||||||
|
Echo("\n");
|
||||||
|
|
||||||
|
// Would be nice if these were sorted, but not that big a deal
|
||||||
|
pszCurrentCmd = (char *)matches.GetFirst();
|
||||||
|
|
||||||
|
while (pszCurrentCmd)
|
||||||
|
{
|
||||||
|
char szFormatCmd[256];
|
||||||
|
if (++nCurrentColumn > nTotalColumns)
|
||||||
|
{
|
||||||
|
Echo("\n");
|
||||||
|
nCurrentColumn = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
_snprintf(szFormatCmd, sizeof(szFormatCmd), "%-*s ", nLongestCmd, pszCurrentCmd);
|
||||||
|
Echo(szFormatCmd);
|
||||||
|
|
||||||
|
pszCurrentCmd = (char *)matches.GetNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
Echo("\n");
|
||||||
|
Echo(m_szConsoleText);
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
// Tack on 'common' chars in all the matches, i.e. if I typed 'con' and all the
|
||||||
|
// matches begin with 'connect_' then print the matches but also complete the
|
||||||
|
// command up to that point at least.
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
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 ]);
|
||||||
|
|
||||||
|
strncpy(m_szConsoleText, m_aszLineBuffer[ m_nBrowseLine ], MAX_CONSOLE_TEXTLEN);
|
||||||
|
|
||||||
|
m_nConsoleTextLen = 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
|
||||||
|
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 ]);
|
||||||
|
strncpy(m_szConsoleText, m_aszLineBuffer[ m_nBrowseLine ], MAX_CONSOLE_TEXTLEN);
|
||||||
|
m_nConsoleTextLen = 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++;
|
||||||
|
}
|
71
rehlds/common/textconsole.h
Normal file
71
rehlds/common/textconsole.h
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#ifndef TEXTCONSOLE_H
|
||||||
|
#define TEXTCONSOLE_H
|
||||||
|
#ifdef _WIN32
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#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();
|
||||||
|
|
||||||
|
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, ...);
|
||||||
|
|
||||||
|
#endif // TEXTCONSOLE_H
|
137
rehlds/dedicated/build.gradle
Normal file
137
rehlds/dedicated/build.gradle
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
import org.doomedsociety.gradlecpp.cfg.ToolchainConfigUtils
|
||||||
|
import org.doomedsociety.gradlecpp.msvc.MsvcToolchainConfig
|
||||||
|
import org.doomedsociety.gradlecpp.gcc.GccToolchainConfig
|
||||||
|
import org.doomedsociety.gradlecpp.toolchain.icc.Icc
|
||||||
|
import org.doomedsociety.gradlecpp.toolchain.icc.IccCompilerPlugin
|
||||||
|
import org.doomedsociety.gradlecpp.GradleCppUtils
|
||||||
|
import org.gradle.nativeplatform.NativeExecutableSpec
|
||||||
|
import org.gradle.nativeplatform.NativeExecutableBinarySpec
|
||||||
|
|
||||||
|
apply plugin: 'cpp'
|
||||||
|
apply plugin: 'windows-resources'
|
||||||
|
apply plugin: IccCompilerPlugin
|
||||||
|
|
||||||
|
List<Task> getRcCompileTasks(NativeBinarySpec binary)
|
||||||
|
{
|
||||||
|
def linkTask = GradleCppUtils.getLinkTask(binary)
|
||||||
|
def res = linkTask.taskDependencies.getDependencies(linkTask).findAll { Task t -> t instanceof WindowsResourceCompile }
|
||||||
|
return res as List
|
||||||
|
}
|
||||||
|
|
||||||
|
void setupToolchain(NativeBinarySpec b) {
|
||||||
|
def cfg = rootProject.createToolchainConfig(b);
|
||||||
|
cfg.projectInclude(project, '/src', '/../engine', '/../common', '/../public', '/../public/rehlds');
|
||||||
|
|
||||||
|
cfg.singleDefines 'USE_BREAKPAD_HANDLER', 'DEDICATED', 'LAUNCHER_FIXES', '_CONSOLE'
|
||||||
|
|
||||||
|
if (cfg instanceof MsvcToolchainConfig) {
|
||||||
|
cfg.compilerOptions.pchConfig = new MsvcToolchainConfig.PrecompiledHeadersConfig(
|
||||||
|
enabled: true,
|
||||||
|
pchHeader: 'precompiled.h',
|
||||||
|
pchSourceSet: 'dedicated_pch'
|
||||||
|
);
|
||||||
|
|
||||||
|
cfg.singleDefines('_CRT_SECURE_NO_WARNINGS');
|
||||||
|
cfg.compilerOptions.args '/Ob2', '/Oi', '/GF', '/GR-';
|
||||||
|
cfg.extraLibs "ws2_32.lib", "winmm.lib", "user32.lib", "advapi32.lib", "shell32.lib"
|
||||||
|
}
|
||||||
|
else if (cfg instanceof GccToolchainConfig) {
|
||||||
|
cfg.compilerOptions.pchConfig = new GccToolchainConfig.PrecompilerHeaderOptions(
|
||||||
|
enabled: true,
|
||||||
|
pchSourceSet: 'dedicated_pch'
|
||||||
|
);
|
||||||
|
|
||||||
|
cfg.compilerOptions.languageStandard = 'c++0x'
|
||||||
|
cfg.defines([
|
||||||
|
'_strdup': 'strdup',
|
||||||
|
'_stricmp': 'strcasecmp',
|
||||||
|
'_strnicmp': 'strncasecmp',
|
||||||
|
'_vsnprintf': 'vsnprintf',
|
||||||
|
'_snprintf': 'snprintf',
|
||||||
|
]);
|
||||||
|
|
||||||
|
cfg.linkerOptions.stripSymbolTable = false;
|
||||||
|
cfg.linkerOptions.staticLibStdCpp = false;
|
||||||
|
cfg.compilerOptions.args '-Qoption,cpp,--treat_func_as_string_literal_cpp', '-fno-rtti', '-fno-exceptions'
|
||||||
|
}
|
||||||
|
|
||||||
|
ToolchainConfigUtils.apply(project, cfg, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
model {
|
||||||
|
buildTypes {
|
||||||
|
release
|
||||||
|
}
|
||||||
|
|
||||||
|
platforms {
|
||||||
|
x86 {
|
||||||
|
architecture "x86"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toolChains {
|
||||||
|
visualCpp(VisualCpp) {
|
||||||
|
}
|
||||||
|
icc(Icc) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
components {
|
||||||
|
dedicated(NativeExecutableSpec) {
|
||||||
|
targetPlatform 'x86'
|
||||||
|
baseName GradleCppUtils.windows ? 'hlds' : 'hlds_linux'
|
||||||
|
|
||||||
|
sources {
|
||||||
|
dedicated_main(CppSourceSet) {
|
||||||
|
source {
|
||||||
|
srcDir "src"
|
||||||
|
include "**/*.cpp"
|
||||||
|
exclude "precompiled.cpp"
|
||||||
|
|
||||||
|
if (GradleCppUtils.windows) {
|
||||||
|
exclude "sys_linux.cpp"
|
||||||
|
} else {
|
||||||
|
exclude "sys_window.cpp", "conproc.cpp"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exportedHeaders {
|
||||||
|
srcDirs "vgui"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dedicated_pch(CppSourceSet) {
|
||||||
|
source {
|
||||||
|
srcDir "src"
|
||||||
|
include "precompiled.cpp"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rc {
|
||||||
|
source {
|
||||||
|
srcDir "msvc"
|
||||||
|
include "dedicated.rc"
|
||||||
|
}
|
||||||
|
exportedHeaders {
|
||||||
|
srcDirs "msvc"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
binaries.all {
|
||||||
|
NativeExecutableBinarySpec b -> project.setupToolchain(b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task buildFixes {
|
||||||
|
dependsOn binaries.withType(NativeExecutableBinarySpec).matching { NativeExecutableBinarySpec blib ->
|
||||||
|
blib.buildable && blib.buildType.name == 'release'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task buildRelease {
|
||||||
|
dependsOn binaries.withType(NativeExecutableBinarySpec).matching { NativeExecutableBinarySpec blib ->
|
||||||
|
blib.buildable && blib.buildType.name == 'release'
|
||||||
|
}
|
||||||
|
}
|
39
rehlds/dedicated/msvc/PostBuild.bat
Normal file
39
rehlds/dedicated/msvc/PostBuild.bat
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
@echo OFF
|
||||||
|
::
|
||||||
|
:: Post-build auto-deploy script
|
||||||
|
:: Create and fill PublishPath.txt file with path to deployment folder
|
||||||
|
:: I.e. PublishPath.txt should contain one line with a folder path
|
||||||
|
:: Call it so:
|
||||||
|
:: IF EXIST "$(ProjectDir)PostBuild.bat" (CALL "$(ProjectDir)PostBuild.bat" "$(TargetDir)" "$(TargetName)" "$(TargetExt)" "$(ProjectDir)")
|
||||||
|
::
|
||||||
|
|
||||||
|
SET targetDir=%~1
|
||||||
|
SET targetName=%~2
|
||||||
|
SET targetExt=%~3
|
||||||
|
SET projectDir=%~4
|
||||||
|
SET destination=
|
||||||
|
|
||||||
|
IF NOT EXIST "%projectDir%\PublishPath.txt" (
|
||||||
|
ECHO No deployment path specified. Create PublishPath.txt near PostBuild.bat with paths on separate lines for auto deployment.
|
||||||
|
exit /B 0
|
||||||
|
)
|
||||||
|
|
||||||
|
FOR /f "tokens=* delims= usebackq" %%a IN ("%projectDir%\PublishPath.txt") DO (
|
||||||
|
ECHO Deploying to: %%a
|
||||||
|
IF NOT "%%a" == "" (
|
||||||
|
copy /Y "%targetDir%%targetName%%targetExt%" "%%a"
|
||||||
|
IF NOT ERRORLEVEL 1 (
|
||||||
|
IF EXIST "%targetDir%%targetName%.pdb" (
|
||||||
|
copy /Y "%targetDir%%targetName%.pdb" "%%a"
|
||||||
|
)
|
||||||
|
) ELSE (
|
||||||
|
ECHO PostBuild.bat ^(27^) : warning : Can't copy '%targetName%%targetExt%' to deploy path '%%a'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
IF "%%a" == "" (
|
||||||
|
ECHO No deployment path specified.
|
||||||
|
)
|
||||||
|
|
||||||
|
exit /B 0
|
BIN
rehlds/dedicated/msvc/dedicated.rc
Normal file
BIN
rehlds/dedicated/msvc/dedicated.rc
Normal file
Binary file not shown.
22
rehlds/dedicated/msvc/dedicated.sln
Normal file
22
rehlds/dedicated/msvc/dedicated.sln
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio 14
|
||||||
|
VisualStudioVersion = 14.0.25420.1
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dedicated", "dedicated.vcxproj", "{D49883F3-5C5C-4B9F-B9C7-B31518F228D4}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Win32 = Debug|Win32
|
||||||
|
Release|Win32 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{D49883F3-5C5C-4B9F-B9C7-B31518F228D4}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{D49883F3-5C5C-4B9F-B9C7-B31518F228D4}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{D49883F3-5C5C-4B9F-B9C7-B31518F228D4}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{D49883F3-5C5C-4B9F-B9C7-B31518F228D4}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
178
rehlds/dedicated/msvc/dedicated.vcxproj
Normal file
178
rehlds/dedicated/msvc/dedicated.vcxproj
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>{D49883F3-5C5C-4B9F-B9C7-B31518F228D4}</ProjectGuid>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<RootNamespace>HLDSLauncher</RootNamespace>
|
||||||
|
<ProjectName>dedicated</ProjectName>
|
||||||
|
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v140_xp</PlatformToolset>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v140_xp</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<TargetName>hlds</TargetName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<TargetName>hlds</TargetName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<PreprocessorDefinitions>WIN32;LAUNCHER_FIXES;_DEBUG;DEDICATED;_CRT_SECURE_NO_WARNINGS;USE_BREAKPAD_HANDLER;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<StringPooling>true</StringPooling>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
<AdditionalIncludeDirectories>$(ProjectDir)..\;$(ProjectDir)..\src\;$(ProjectDir)..\..\common;$(ProjectDir)..\..\engine;$(ProjectDir)..\..\public;$(ProjectDir)..\..\public\rehlds;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PrecompiledHeaderFile>precompiled.h</PrecompiledHeaderFile>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>ws2_32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
<PreBuildEvent>
|
||||||
|
<Command>IF EXIST "$(ProjectDir)PreBuild.bat" (CALL "$(ProjectDir)PreBuild.bat" "$(ProjectDir)..\version\" "$(ProjectDir)..\")</Command>
|
||||||
|
</PreBuildEvent>
|
||||||
|
<PreBuildEvent>
|
||||||
|
<Message>Setup version from Git revision</Message>
|
||||||
|
</PreBuildEvent>
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Command>IF EXIST "$(ProjectDir)PostBuild.bat" (CALL "$(ProjectDir)PostBuild.bat" "$(TargetDir)" "$(TargetName)" "$(TargetExt)" "$(ProjectDir)")</Command>
|
||||||
|
</PostBuildEvent>
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Message>Automatic deployment script</Message>
|
||||||
|
</PostBuildEvent>
|
||||||
|
<CustomBuildStep>
|
||||||
|
<Command>echo Empty Action</Command>
|
||||||
|
</CustomBuildStep>
|
||||||
|
<CustomBuildStep>
|
||||||
|
<Message>Force build to run Pre-Build event</Message>
|
||||||
|
</CustomBuildStep>
|
||||||
|
<CustomBuildStep>
|
||||||
|
<Outputs>git.always.run</Outputs>
|
||||||
|
</CustomBuildStep>
|
||||||
|
<CustomBuildStep>
|
||||||
|
<Inputs>git.always.run</Inputs>
|
||||||
|
</CustomBuildStep>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<Optimization>Full</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<PreprocessorDefinitions>WIN32;LAUNCHER_FIXES;NDEBUG;DEDICATED;_CRT_SECURE_NO_WARNINGS;USE_BREAKPAD_HANDLER;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<AdditionalIncludeDirectories>$(ProjectDir)..\;$(ProjectDir)..\..\common;$(ProjectDir)..\..\engine;$(ProjectDir)..\..\public;$(ProjectDir)..\..\public\rehlds;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
|
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
|
||||||
|
<FloatingPointModel>
|
||||||
|
</FloatingPointModel>
|
||||||
|
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
|
||||||
|
<OmitFramePointers>true</OmitFramePointers>
|
||||||
|
<StringPooling>true</StringPooling>
|
||||||
|
<PrecompiledHeaderFile>precompiled.h</PrecompiledHeaderFile>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<AdditionalDependencies>ws2_32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
<PreBuildEvent>
|
||||||
|
<Command>IF EXIST "$(ProjectDir)PreBuild.bat" (CALL "$(ProjectDir)PreBuild.bat" "$(ProjectDir)..\version\" "$(ProjectDir)..\")</Command>
|
||||||
|
</PreBuildEvent>
|
||||||
|
<PreBuildEvent>
|
||||||
|
<Message>Setup version from Git revision</Message>
|
||||||
|
</PreBuildEvent>
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Command>IF EXIST "$(ProjectDir)PostBuild.bat" (CALL "$(ProjectDir)PostBuild.bat" "$(TargetDir)" "$(TargetName)" "$(TargetExt)" "$(ProjectDir)")</Command>
|
||||||
|
</PostBuildEvent>
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Message>Automatic deployment script</Message>
|
||||||
|
</PostBuildEvent>
|
||||||
|
<CustomBuildStep>
|
||||||
|
<Command>echo Empty Action</Command>
|
||||||
|
</CustomBuildStep>
|
||||||
|
<CustomBuildStep>
|
||||||
|
<Outputs>subversion.always.run</Outputs>
|
||||||
|
</CustomBuildStep>
|
||||||
|
<CustomBuildStep>
|
||||||
|
<Inputs>subversion.always.run</Inputs>
|
||||||
|
<Message>Force build to run Pre-Build event</Message>
|
||||||
|
</CustomBuildStep>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\src\conproc.h" />
|
||||||
|
<ClInclude Include="..\src\dbg.h" />
|
||||||
|
<ClInclude Include="..\src\dedicated.h" />
|
||||||
|
<ClInclude Include="..\src\precompiled.h" />
|
||||||
|
<ClInclude Include="..\src\sys_ded.h" />
|
||||||
|
<ClInclude Include="..\src\vgui\vguihelpers.h" />
|
||||||
|
<ClInclude Include="resource.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="dedicated.rc" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\src\commandline.cpp" />
|
||||||
|
<ClCompile Include="..\src\conproc.cpp" />
|
||||||
|
<ClCompile Include="..\src\dbg.cpp" />
|
||||||
|
<ClCompile Include="..\src\dedicated_exports.cpp" />
|
||||||
|
<ClCompile Include="..\src\precompiled.cpp">
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\public_amalgamation.cpp" />
|
||||||
|
<ClCompile Include="..\src\sys_ded.cpp" />
|
||||||
|
<ClCompile Include="..\src\sys_linux.cpp">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\sys_window.cpp" />
|
||||||
|
<ClCompile Include="..\src\vgui\vguihelpers.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Image Include="icon.ico" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
71
rehlds/dedicated/msvc/dedicated.vcxproj.filters
Normal file
71
rehlds/dedicated/msvc/dedicated.vcxproj.filters
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="src">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="src\vgui">
|
||||||
|
<UniqueIdentifier>{711de26d-f116-48c0-96c0-5d4189574ad1}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="resource.h" />
|
||||||
|
<ClInclude Include="..\src\precompiled.h">
|
||||||
|
<Filter>src</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\src\dbg.h">
|
||||||
|
<Filter>src</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\src\sys_ded.h">
|
||||||
|
<Filter>src</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\src\dedicated.h">
|
||||||
|
<Filter>src</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\src\conproc.h">
|
||||||
|
<Filter>src</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\src\vgui\vguihelpers.h">
|
||||||
|
<Filter>src\vgui</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\src\commandline.cpp">
|
||||||
|
<Filter>src</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\dbg.cpp">
|
||||||
|
<Filter>src</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\sys_ded.cpp">
|
||||||
|
<Filter>src</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\precompiled.cpp">
|
||||||
|
<Filter>src</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\public_amalgamation.cpp">
|
||||||
|
<Filter>src</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\sys_linux.cpp">
|
||||||
|
<Filter>src</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\sys_window.cpp">
|
||||||
|
<Filter>src</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\conproc.cpp">
|
||||||
|
<Filter>src</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\vgui\vguihelpers.cpp">
|
||||||
|
<Filter>src\vgui</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\dedicated_exports.cpp">
|
||||||
|
<Filter>src</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Image Include="icon.ico" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="dedicated.rc" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
BIN
rehlds/dedicated/msvc/icon.ico
Normal file
BIN
rehlds/dedicated/msvc/icon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 114 KiB |
BIN
rehlds/dedicated/msvc/resource.h
Normal file
BIN
rehlds/dedicated/msvc/resource.h
Normal file
Binary file not shown.
354
rehlds/dedicated/src/commandline.cpp
Normal file
354
rehlds/dedicated/src/commandline.cpp
Normal file
@ -0,0 +1,354 @@
|
|||||||
|
#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[strlen(src) + 1];
|
||||||
|
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 (strchr(argv[i], ' '))
|
||||||
|
{
|
||||||
|
strncat(cmdline, "\"", MAX_CHARS);
|
||||||
|
strncat(cmdline, argv[i], MAX_CHARS);
|
||||||
|
strncat(cmdline, "\"", MAX_CHARS);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strncat(cmdline, argv[i], MAX_CHARS);
|
||||||
|
}
|
||||||
|
|
||||||
|
strncat(cmdline, " ", MAX_CHARS);
|
||||||
|
}
|
||||||
|
|
||||||
|
cmdline[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 = strlen(szFull) + 1;
|
||||||
|
m_pszCmdLine = new char[len];
|
||||||
|
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 = strlen(p);
|
||||||
|
found = 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);
|
||||||
|
|
||||||
|
memcpy(found, pnextparam, n);
|
||||||
|
found[n] = '\0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Clear out rest of string.
|
||||||
|
n = pnextparam - found;
|
||||||
|
memset(found, 0, n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strip and trailing ' ' characters left over.
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
int curpos = 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 = strlen(pszParm);
|
||||||
|
|
||||||
|
// Values + leading space character.
|
||||||
|
if (pszValues)
|
||||||
|
nNewLength += strlen(pszValues) + 1;
|
||||||
|
|
||||||
|
// Terminal 0;
|
||||||
|
nNewLength++;
|
||||||
|
|
||||||
|
if (!m_pszCmdLine)
|
||||||
|
{
|
||||||
|
m_pszCmdLine = new char[ nNewLength ];
|
||||||
|
strcpy(m_pszCmdLine, pszParm);
|
||||||
|
if (pszValues)
|
||||||
|
{
|
||||||
|
strcat(m_pszCmdLine, " ");
|
||||||
|
strcat(m_pszCmdLine, pszValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove any remnants from the current Cmd Line.
|
||||||
|
RemoveParm(pszParm);
|
||||||
|
|
||||||
|
nNewLength += strlen(m_pszCmdLine) + 1 + 1;
|
||||||
|
|
||||||
|
pCmdString = new char[ nNewLength ];
|
||||||
|
memset(pCmdString, 0, nNewLength);
|
||||||
|
|
||||||
|
strcpy(pCmdString, m_pszCmdLine); // Copy old command line.
|
||||||
|
strcat(pCmdString, " "); // Put in a space
|
||||||
|
strcat(pCmdString, pszParm);
|
||||||
|
|
||||||
|
if (pszValues)
|
||||||
|
{
|
||||||
|
strcat(pCmdString, " ");
|
||||||
|
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];
|
||||||
|
_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;
|
||||||
|
|
||||||
|
char *pret = strstr(m_pszCmdLine, psz);
|
||||||
|
if (!pret || !ppszValue)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
*ppszValue = nullptr;
|
||||||
|
|
||||||
|
// 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];
|
||||||
|
}
|
||||||
|
while (i < sizeof(sz));
|
||||||
|
|
||||||
|
sz[i] = '\0';
|
||||||
|
*ppszValue = sz;
|
||||||
|
return pret;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *CCommandLine::GetCmdLine() const
|
||||||
|
{
|
||||||
|
return m_pszCmdLine;
|
||||||
|
}
|
312
rehlds/dedicated/src/conproc.cpp
Normal file
312
rehlds/dedicated/src/conproc.cpp
Normal file
@ -0,0 +1,312 @@
|
|||||||
|
#include "precompiled.h"
|
||||||
|
|
||||||
|
static HANDLE heventDone;
|
||||||
|
static HANDLE hfileBuffer;
|
||||||
|
static HANDLE heventChildSend;
|
||||||
|
static HANDLE heventParentSend;
|
||||||
|
static HANDLE hStdout;
|
||||||
|
static HANDLE hStdin;
|
||||||
|
|
||||||
|
BOOL SetConsoleCXCY(HANDLE hStdout, int cx, int cy)
|
||||||
|
{
|
||||||
|
CONSOLE_SCREEN_BUFFER_INFO info;
|
||||||
|
COORD coordMax;
|
||||||
|
|
||||||
|
coordMax = GetLargestConsoleWindowSize(hStdout);
|
||||||
|
|
||||||
|
if (cy > coordMax.Y)
|
||||||
|
cy = coordMax.Y;
|
||||||
|
|
||||||
|
if (cx > coordMax.X)
|
||||||
|
cx = coordMax.X;
|
||||||
|
|
||||||
|
if (!GetConsoleScreenBufferInfo(hStdout, &info))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
// height
|
||||||
|
info.srWindow.Left = 0;
|
||||||
|
info.srWindow.Right = info.dwSize.X - 1;
|
||||||
|
info.srWindow.Top = 0;
|
||||||
|
info.srWindow.Bottom = cy - 1;
|
||||||
|
|
||||||
|
if (cy < info.dwSize.Y)
|
||||||
|
{
|
||||||
|
if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
info.dwSize.Y = cy;
|
||||||
|
|
||||||
|
if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else if (cy > info.dwSize.Y)
|
||||||
|
{
|
||||||
|
info.dwSize.Y = cy;
|
||||||
|
|
||||||
|
if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!GetConsoleScreenBufferInfo(hStdout, &info))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
// width
|
||||||
|
info.srWindow.Left = 0;
|
||||||
|
info.srWindow.Right = cx - 1;
|
||||||
|
info.srWindow.Top = 0;
|
||||||
|
info.srWindow.Bottom = info.dwSize.Y - 1;
|
||||||
|
|
||||||
|
if (cx < info.dwSize.X)
|
||||||
|
{
|
||||||
|
if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
info.dwSize.X = cx;
|
||||||
|
|
||||||
|
if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else if (cx > info.dwSize.X)
|
||||||
|
{
|
||||||
|
info.dwSize.X = cx;
|
||||||
|
|
||||||
|
if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LPVOID GetMappedBuffer(HANDLE hfileBuffer)
|
||||||
|
{
|
||||||
|
return MapViewOfFile(hfileBuffer, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReleaseMappedBuffer(LPVOID pBuffer)
|
||||||
|
{
|
||||||
|
UnmapViewOfFile(pBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL GetScreenBufferLines(int *piLines)
|
||||||
|
{
|
||||||
|
CONSOLE_SCREEN_BUFFER_INFO info;
|
||||||
|
|
||||||
|
BOOL bRet = GetConsoleScreenBufferInfo(hStdout, &info);
|
||||||
|
if (bRet)
|
||||||
|
*piLines = info.dwSize.Y;
|
||||||
|
|
||||||
|
return bRet;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL SetScreenBufferLines(int iLines)
|
||||||
|
{
|
||||||
|
return SetConsoleCXCY(hStdout, 80, iLines);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL ReadText(LPTSTR pszText, int iBeginLine, int iEndLine)
|
||||||
|
{
|
||||||
|
COORD coord;
|
||||||
|
DWORD dwRead;
|
||||||
|
BOOL bRet;
|
||||||
|
|
||||||
|
coord.X = 0;
|
||||||
|
coord.Y = iBeginLine;
|
||||||
|
|
||||||
|
bRet = ReadConsoleOutputCharacter(hStdout, pszText, 80 * (iEndLine - iBeginLine + 1), coord, &dwRead);
|
||||||
|
|
||||||
|
// Make sure it's null terminated.
|
||||||
|
if (bRet)
|
||||||
|
pszText[dwRead] = '\0';
|
||||||
|
|
||||||
|
return bRet;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CharToCode(char c)
|
||||||
|
{
|
||||||
|
char upper = toupper(c);
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case 13:
|
||||||
|
return 28;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isalpha(c))
|
||||||
|
return (30 + upper - 65);
|
||||||
|
|
||||||
|
if (isdigit(c))
|
||||||
|
return (1 + upper - 47);
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WriteText(LPCTSTR szText)
|
||||||
|
{
|
||||||
|
DWORD dwWritten;
|
||||||
|
INPUT_RECORD rec;
|
||||||
|
char upper, *sz;
|
||||||
|
|
||||||
|
sz = (LPTSTR)szText;
|
||||||
|
|
||||||
|
while (*sz)
|
||||||
|
{
|
||||||
|
// 13 is the code for a carriage return (\n) instead of 10.
|
||||||
|
if (*sz == '\n')
|
||||||
|
*sz = '\r';
|
||||||
|
|
||||||
|
upper = toupper(*sz);
|
||||||
|
|
||||||
|
rec.EventType = KEY_EVENT;
|
||||||
|
rec.Event.KeyEvent.bKeyDown = TRUE;
|
||||||
|
rec.Event.KeyEvent.wRepeatCount = 1;
|
||||||
|
rec.Event.KeyEvent.wVirtualKeyCode = upper;
|
||||||
|
rec.Event.KeyEvent.wVirtualScanCode = CharToCode(*sz);
|
||||||
|
rec.Event.KeyEvent.uChar.AsciiChar = *sz;
|
||||||
|
rec.Event.KeyEvent.uChar.UnicodeChar = *sz;
|
||||||
|
rec.Event.KeyEvent.dwControlKeyState = isupper(*sz) ? 0x80 : 0x0;
|
||||||
|
|
||||||
|
WriteConsoleInput(hStdin, &rec, 1, &dwWritten);
|
||||||
|
rec.Event.KeyEvent.bKeyDown = FALSE;
|
||||||
|
WriteConsoleInput(hStdin, &rec, 1, &dwWritten);
|
||||||
|
sz++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned _stdcall RequestProc(void *arg)
|
||||||
|
{
|
||||||
|
int *pBuffer;
|
||||||
|
DWORD dwRet;
|
||||||
|
HANDLE heventWait[2];
|
||||||
|
int iBeginLine, iEndLine;
|
||||||
|
|
||||||
|
heventWait[0] = heventParentSend;
|
||||||
|
heventWait[1] = heventDone;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
dwRet = WaitForMultipleObjects(2, heventWait, FALSE, INFINITE);
|
||||||
|
|
||||||
|
// heventDone fired, so we're exiting.
|
||||||
|
if (dwRet == WAIT_OBJECT_0 + 1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
pBuffer = (int *)GetMappedBuffer(hfileBuffer);
|
||||||
|
|
||||||
|
// hfileBuffer is invalid. Just leave.
|
||||||
|
if (!pBuffer)
|
||||||
|
{
|
||||||
|
sys->Printf("Request Proc: Invalid -HFILE handle\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (pBuffer[0])
|
||||||
|
{
|
||||||
|
case CCOM_WRITE_TEXT:
|
||||||
|
pBuffer[0] = WriteText((LPCTSTR)(pBuffer + 1));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CCOM_GET_TEXT:
|
||||||
|
iBeginLine = pBuffer[1];
|
||||||
|
iEndLine = pBuffer[2];
|
||||||
|
pBuffer[0] = ReadText((LPTSTR)(pBuffer + 1), iBeginLine, iEndLine);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CCOM_GET_SCR_LINES:
|
||||||
|
pBuffer[0] = GetScreenBufferLines(&pBuffer[1]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CCOM_SET_SCR_LINES:
|
||||||
|
pBuffer[0] = SetScreenBufferLines(pBuffer[1]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReleaseMappedBuffer(pBuffer);
|
||||||
|
SetEvent(heventChildSend);
|
||||||
|
}
|
||||||
|
|
||||||
|
_endthreadex(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeinitConProc()
|
||||||
|
{
|
||||||
|
if (heventDone)
|
||||||
|
{
|
||||||
|
SetEvent(heventDone);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitConProc()
|
||||||
|
{
|
||||||
|
unsigned threadAddr;
|
||||||
|
HANDLE hFile = (HANDLE)0;
|
||||||
|
HANDLE heventParent = (HANDLE)0;
|
||||||
|
HANDLE heventChild = (HANDLE)0;
|
||||||
|
int WantHeight = 50;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
// give external front ends a chance to hook into the console
|
||||||
|
if (CommandLine()->CheckParm("-HFILE", &p) && p)
|
||||||
|
{
|
||||||
|
hFile = (HANDLE)atoi(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CommandLine()->CheckParm("-HPARENT", &p) && p)
|
||||||
|
{
|
||||||
|
heventParent = (HANDLE)atoi(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CommandLine()->CheckParm("-HCHILD", &p) && p)
|
||||||
|
{
|
||||||
|
heventChild = (HANDLE)atoi(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore if we don't have all the events.
|
||||||
|
if (!hFile || !heventParent || !heventChild)
|
||||||
|
{
|
||||||
|
//sys->Printf ("\n\nNo external front end present.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sys->Printf("\n\nInitConProc: Setting up external control.\n");
|
||||||
|
|
||||||
|
hfileBuffer = hFile;
|
||||||
|
heventParentSend = heventParent;
|
||||||
|
heventChildSend = heventChild;
|
||||||
|
|
||||||
|
// So we'll know when to go away.
|
||||||
|
heventDone = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
|
if (!heventDone)
|
||||||
|
{
|
||||||
|
sys->Printf("InitConProc: Couldn't create heventDone\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_beginthreadex(NULL, 0, RequestProc, NULL, 0, &threadAddr))
|
||||||
|
{
|
||||||
|
CloseHandle(heventDone);
|
||||||
|
sys->Printf("InitConProc: Couldn't create third party thread\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// save off the input/output handles.
|
||||||
|
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
hStdin = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
|
|
||||||
|
if (CommandLine()->CheckParm("-conheight", &p) && p)
|
||||||
|
{
|
||||||
|
WantHeight = atoi(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force 80 character width, at least 25 character height
|
||||||
|
SetConsoleCXCY(hStdout, 80, WantHeight);
|
||||||
|
}
|
17
rehlds/dedicated/src/conproc.h
Normal file
17
rehlds/dedicated/src/conproc.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#ifndef CONPROC_H
|
||||||
|
#define CONPROC_H
|
||||||
|
#ifdef _WIN32
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <process.h>
|
||||||
|
|
||||||
|
#define CCOM_WRITE_TEXT 0x2 // Param1 : Text
|
||||||
|
#define CCOM_GET_TEXT 0x3 // Param1 : Begin line, Param2 : End line
|
||||||
|
#define CCOM_GET_SCR_LINES 0x4 // No params
|
||||||
|
#define CCOM_SET_SCR_LINES 0x5 // Param1 : Number of lines
|
||||||
|
|
||||||
|
void InitConProc();
|
||||||
|
void DeinitConProc();
|
||||||
|
|
||||||
|
#endif // CONPROC_H
|
171
rehlds/dedicated/src/dbg.cpp
Normal file
171
rehlds/dedicated/src/dbg.cpp
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
#include "precompiled.h"
|
||||||
|
|
||||||
|
class CPerformanceCounter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CPerformanceCounter();
|
||||||
|
|
||||||
|
void InitializePerformanceCounter();
|
||||||
|
double GetCurTime();
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_iLowShift;
|
||||||
|
double m_flPerfCounterFreq;
|
||||||
|
double m_flCurrentTime;
|
||||||
|
double m_flLastCurrentTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline CPerformanceCounter::CPerformanceCounter() :
|
||||||
|
m_iLowShift(0),
|
||||||
|
m_flPerfCounterFreq(0),
|
||||||
|
m_flCurrentTime(0),
|
||||||
|
m_flLastCurrentTime(0)
|
||||||
|
{
|
||||||
|
InitializePerformanceCounter();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void CPerformanceCounter::InitializePerformanceCounter()
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
LARGE_INTEGER performanceFreq;
|
||||||
|
QueryPerformanceFrequency(&performanceFreq);
|
||||||
|
|
||||||
|
// get 32 out of the 64 time bits such that we have around
|
||||||
|
// 1 microsecond resolution
|
||||||
|
unsigned int lowpart, highpart;
|
||||||
|
lowpart = (unsigned int)performanceFreq.LowPart;
|
||||||
|
highpart = (unsigned int)performanceFreq.HighPart;
|
||||||
|
m_iLowShift = 0;
|
||||||
|
|
||||||
|
while (highpart || (lowpart > 2000000.0))
|
||||||
|
{
|
||||||
|
m_iLowShift++;
|
||||||
|
lowpart >>= 1;
|
||||||
|
lowpart |= (highpart & 1) << 31;
|
||||||
|
highpart >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_flPerfCounterFreq = 1.0 / (double)lowpart;
|
||||||
|
|
||||||
|
#endif // _WIN32
|
||||||
|
}
|
||||||
|
|
||||||
|
inline double CPerformanceCounter::GetCurTime()
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
static int sametimecount;
|
||||||
|
static unsigned int oldtime;
|
||||||
|
static int first = 1;
|
||||||
|
LARGE_INTEGER PerformanceCount;
|
||||||
|
unsigned int temp, t2;
|
||||||
|
double time;
|
||||||
|
|
||||||
|
QueryPerformanceCounter(&PerformanceCount);
|
||||||
|
if (m_iLowShift == 0)
|
||||||
|
{
|
||||||
|
temp = (unsigned int)PerformanceCount.LowPart;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
temp = ((unsigned int)PerformanceCount.LowPart >> m_iLowShift) |
|
||||||
|
((unsigned int)PerformanceCount.HighPart << (32 - m_iLowShift));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first)
|
||||||
|
{
|
||||||
|
oldtime = temp;
|
||||||
|
first = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// check for turnover or backward time
|
||||||
|
if ((temp <= oldtime) && ((oldtime - temp) < 0x10000000))
|
||||||
|
{
|
||||||
|
// so we can't get stuck
|
||||||
|
oldtime = temp;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
t2 = temp - oldtime;
|
||||||
|
|
||||||
|
time = (double)t2 * m_flPerfCounterFreq;
|
||||||
|
oldtime = temp;
|
||||||
|
|
||||||
|
m_flCurrentTime += time;
|
||||||
|
|
||||||
|
if (m_flCurrentTime == m_flLastCurrentTime)
|
||||||
|
{
|
||||||
|
if (++sametimecount > 100000)
|
||||||
|
{
|
||||||
|
m_flCurrentTime += 1.0;
|
||||||
|
sametimecount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sametimecount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_flLastCurrentTime = m_flCurrentTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_flCurrentTime;
|
||||||
|
|
||||||
|
#else // _WIN32
|
||||||
|
|
||||||
|
struct timeval tp;
|
||||||
|
static int secbase = 0;
|
||||||
|
|
||||||
|
gettimeofday(&tp, NULL);
|
||||||
|
|
||||||
|
if (!secbase)
|
||||||
|
{
|
||||||
|
secbase = tp.tv_sec;
|
||||||
|
return (tp.tv_usec / 1000000.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((tp.tv_sec - secbase) + tp.tv_usec / 1000000.0);
|
||||||
|
|
||||||
|
#endif // _WIN32
|
||||||
|
}
|
||||||
|
|
||||||
|
void _LogFunctionTrace(const char *pFunctionName, const char *param)
|
||||||
|
{
|
||||||
|
//{
|
||||||
|
// char *entry;
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
double _StartFunctionTimer()
|
||||||
|
{
|
||||||
|
//CPerformanceCounter::GetCurTime();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _LogFunctionTraceMaxTime(const char *pFunctionName, double startTime, double maxTime)
|
||||||
|
{
|
||||||
|
//{
|
||||||
|
// double timeDiff;
|
||||||
|
// CPerformanceCounter::GetCurTime();
|
||||||
|
// _LogFunctionTrace(const char *pFunctionName, const char *param);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearErrorLogs()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Error(const char *pMsg, ...)
|
||||||
|
{
|
||||||
|
//{
|
||||||
|
// char logName;
|
||||||
|
// FILE *f;
|
||||||
|
// va_list args;
|
||||||
|
// {
|
||||||
|
// int i;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
}
|
13
rehlds/dedicated/src/dbg.h
Normal file
13
rehlds/dedicated/src/dbg.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#ifndef DBG_H
|
||||||
|
#define DBG_H
|
||||||
|
#ifdef _WIN32
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void _LogFunctionTrace(const char *pFunctionName, const char *param);
|
||||||
|
double _StartFunctionTimer();
|
||||||
|
void _LogFunctionTraceMaxTime(const char *pFunctionName, double startTime, double maxTime);
|
||||||
|
void ClearErrorLogs();
|
||||||
|
void Error(const char *pMsg, ...);
|
||||||
|
|
||||||
|
#endif // DBG_H
|
13
rehlds/dedicated/src/dedicated.h
Normal file
13
rehlds/dedicated/src/dedicated.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#ifndef DEDICATED_H
|
||||||
|
#define DEDICATED_H
|
||||||
|
#ifdef _WIN32
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef void (*NET_Sleep_t)();
|
||||||
|
typedef void (*SleepType)(int msec);
|
||||||
|
|
||||||
|
extern bool g_bVGui;
|
||||||
|
extern IDedicatedServerAPI *engineAPI;
|
||||||
|
|
||||||
|
#endif // DEDICATED_H
|
13
rehlds/dedicated/src/dedicated_exports.cpp
Normal file
13
rehlds/dedicated/src/dedicated_exports.cpp
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#include "precompiled.h"
|
||||||
|
|
||||||
|
class CDedicatedExports: IDedicatedExports {
|
||||||
|
public:
|
||||||
|
void Sys_Printf(char *text);
|
||||||
|
};
|
||||||
|
|
||||||
|
EXPOSE_SINGLE_INTERFACE(CDedicatedExports, IDedicatedExports, VENGINE_DEDICATEDEXPORTS_API_VERSION);
|
||||||
|
|
||||||
|
void CDedicatedExports::Sys_Printf(char *text)
|
||||||
|
{
|
||||||
|
::Sys_Printf_Safe(text);
|
||||||
|
}
|
25
rehlds/dedicated/src/icommandline.h
Normal file
25
rehlds/dedicated/src/icommandline.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#ifndef ICOMMANDLINE_H
|
||||||
|
#define ICOMMANDLINE_H
|
||||||
|
#ifdef _WIN32
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Interface to engine command line
|
||||||
|
class ICommandLine {
|
||||||
|
public:
|
||||||
|
virtual void CreateCmdLine(const char *commandline) = 0;
|
||||||
|
virtual void CreateCmdLine(int argc, const char **argv) = 0;
|
||||||
|
virtual const char *GetCmdLine() const = 0;
|
||||||
|
|
||||||
|
// Check whether a particular parameter exists
|
||||||
|
virtual const char *CheckParm(const char *psz, char **ppszValue = nullptr) const = 0;
|
||||||
|
virtual void RemoveParm(const char *pszParm) = 0;
|
||||||
|
virtual void AppendParm(const char *pszParm, const char *pszValues) = 0;
|
||||||
|
|
||||||
|
virtual void SetParm(const char *pszParm, const char *pszValues) = 0;
|
||||||
|
virtual void SetParm(const char *pszParm, int iValue) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
ICommandLine *CommandLine();
|
||||||
|
|
||||||
|
#endif // ICOMMANDLINE_H
|
31
rehlds/dedicated/src/isys.h
Normal file
31
rehlds/dedicated/src/isys.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef ISYS_H
|
||||||
|
#define ISYS_H
|
||||||
|
#ifdef _WIN32
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class ISys {
|
||||||
|
public:
|
||||||
|
virtual ~ISys() {}
|
||||||
|
|
||||||
|
virtual void Sleep(int msec) = 0;
|
||||||
|
virtual bool GetExecutableName(char *out) = 0;
|
||||||
|
virtual void ErrorMessage(int level, const char *msg) = 0;
|
||||||
|
|
||||||
|
virtual void WriteStatusText(char *szText) = 0;
|
||||||
|
virtual void UpdateStatus(int force) = 0;
|
||||||
|
|
||||||
|
virtual long LoadLibrary(char *lib) = 0;
|
||||||
|
virtual void FreeLibrary(long library) = 0;
|
||||||
|
|
||||||
|
virtual bool CreateConsoleWindow(void) = 0;
|
||||||
|
virtual void DestroyConsoleWindow(void) = 0;
|
||||||
|
|
||||||
|
virtual void ConsoleOutput(char *string) = 0;
|
||||||
|
virtual char *ConsoleInput(void) = 0;
|
||||||
|
virtual void Printf(char *fmt, ...) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern ISys *sys;
|
||||||
|
|
||||||
|
#endif // ISYS_H
|
1
rehlds/dedicated/src/precompiled.cpp
Normal file
1
rehlds/dedicated/src/precompiled.cpp
Normal file
@ -0,0 +1 @@
|
|||||||
|
#include "precompiled.h"
|
21
rehlds/dedicated/src/precompiled.h
Normal file
21
rehlds/dedicated/src/precompiled.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "osconfig.h"
|
||||||
|
#include "archtypes.h"
|
||||||
|
#include "mathlib.h"
|
||||||
|
#include "FileSystem.h"
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#include "engine_hlds_api.h"
|
||||||
|
#include "idedicatedexports.h"
|
||||||
|
#include "icommandline.h"
|
||||||
|
|
||||||
|
#include "sys_ded.h"
|
||||||
|
#include "icommandline.h"
|
||||||
|
#include "textconsole.h"
|
||||||
|
#include "vgui/vguihelpers.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include "conproc.h"
|
||||||
|
#endif // _WIN32
|
11
rehlds/dedicated/src/public_amalgamation.cpp
Normal file
11
rehlds/dedicated/src/public_amalgamation.cpp
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#include "precompiled.h"
|
||||||
|
|
||||||
|
#include "mem.cpp"
|
||||||
|
#include "interface.cpp"
|
||||||
|
#include "SteamAppStartUp.cpp"
|
||||||
|
|
||||||
|
#include "ObjectList.cpp"
|
||||||
|
|
||||||
|
#include "textconsole.cpp"
|
||||||
|
#include "TextConsoleUnix.cpp"
|
||||||
|
#include "TextConsoleWin32.cpp"
|
201
rehlds/dedicated/src/sys_ded.cpp
Normal file
201
rehlds/dedicated/src/sys_ded.cpp
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
#include "precompiled.h"
|
||||||
|
|
||||||
|
long hDLLThirdParty = 0L;
|
||||||
|
|
||||||
|
bool g_bVGui = false;
|
||||||
|
char *gpszCvars = nullptr;
|
||||||
|
bool gbAppHasBeenTerminated = false;
|
||||||
|
|
||||||
|
CSysModule *g_pEngineModule = nullptr;
|
||||||
|
IDedicatedServerAPI *engineAPI = nullptr;
|
||||||
|
|
||||||
|
IFileSystem *g_pFileSystemInterface = nullptr;
|
||||||
|
CSysModule *g_pFileSystemModule = nullptr;
|
||||||
|
|
||||||
|
CreateInterfaceFn g_FilesystemFactoryFn;
|
||||||
|
|
||||||
|
void Sys_Printf_Safe(char *text)
|
||||||
|
{
|
||||||
|
if (sys)
|
||||||
|
{
|
||||||
|
sys->Printf("%s", text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sys_Printf(char *fmt, ...)
|
||||||
|
{
|
||||||
|
// Dump text to debugging console.
|
||||||
|
va_list argptr;
|
||||||
|
char szText[1024];
|
||||||
|
|
||||||
|
va_start(argptr, fmt);
|
||||||
|
_vsnprintf(szText, sizeof(szText), fmt, argptr);
|
||||||
|
va_end(argptr);
|
||||||
|
|
||||||
|
// Get Current text and append it.
|
||||||
|
if (g_bVGui)
|
||||||
|
{
|
||||||
|
VGUIPrintf(szText);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
console.Print(szText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Load3rdParty()
|
||||||
|
{
|
||||||
|
// Only do this if the server operator wants the support.
|
||||||
|
// ( In case of malicious code, too )
|
||||||
|
if (CommandLine()->CheckParm("-usegh"))
|
||||||
|
{
|
||||||
|
hDLLThirdParty = sys->LoadLibrary("ghostinj.dll");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessConsoleInput()
|
||||||
|
{
|
||||||
|
if (!engineAPI)
|
||||||
|
return;
|
||||||
|
|
||||||
|
char *inputLine = console.GetLine();
|
||||||
|
if (inputLine)
|
||||||
|
{
|
||||||
|
char szBuf[256];
|
||||||
|
_snprintf(szBuf, sizeof(szBuf), "%s\n", inputLine);
|
||||||
|
engineAPI->AddConsoleText(szBuf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char *UTIL_GetBaseDir()
|
||||||
|
{
|
||||||
|
return ".";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Server Frame
|
||||||
|
int RunServer()
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
// TODO: finish me!
|
||||||
|
/*if (g_bVGui)
|
||||||
|
{
|
||||||
|
vgui::ivgui()->SetSleep(0);
|
||||||
|
}*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (gbAppHasBeenTerminated)
|
||||||
|
break;
|
||||||
|
|
||||||
|
CreateInterfaceFn engineFactory = Sys_GetFactory(g_pEngineModule);
|
||||||
|
RunVGUIFrame();
|
||||||
|
|
||||||
|
if (engineFactory)
|
||||||
|
engineAPI = (IDedicatedServerAPI *)engineFactory(VENGINE_HLDS_API_VERSION, NULL);
|
||||||
|
|
||||||
|
RunVGUIFrame();
|
||||||
|
if (!engineAPI)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!engineAPI->Init(UTIL_GetBaseDir(), (char *)CommandLine()->GetCmdLine(), Sys_GetFactoryThis(), g_FilesystemFactoryFn)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
RunVGUIFrame();
|
||||||
|
|
||||||
|
// TODO: finish me!
|
||||||
|
/*if (g_bVGui)
|
||||||
|
{
|
||||||
|
g_pFileSystemInterface->AddSearchPath("platform", "PLATFORM");
|
||||||
|
|
||||||
|
// find our configuration directory
|
||||||
|
char szConfigDir[512];
|
||||||
|
const char *steamPath = getenv("SteamInstallPath");
|
||||||
|
if (steamPath)
|
||||||
|
{
|
||||||
|
// put the config dir directly under steam
|
||||||
|
_snprintf(szConfigDir, sizeof(szConfigDir), "%s/config", steamPath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// we're not running steam, so just put the config dir under the platform
|
||||||
|
strncpy(szConfigDir, "platform/config", sizeof(szConfigDir));
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
RunVGUIFrame();
|
||||||
|
|
||||||
|
if (gpszCvars) {
|
||||||
|
engineAPI->AddConsoleText(gpszCvars);
|
||||||
|
}
|
||||||
|
|
||||||
|
VGUIFinishedConfig();
|
||||||
|
RunVGUIFrame();
|
||||||
|
|
||||||
|
bool bDone = false;
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
if (bDone)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Running really fast, yield some time to other apps
|
||||||
|
sys->Sleep(1);
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
MSG msg;
|
||||||
|
while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
|
||||||
|
{
|
||||||
|
if (!GetMessage(&msg, NULL, 0, 0))
|
||||||
|
{
|
||||||
|
bDone = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gbAppHasBeenTerminated)
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
if (g_bVGui)
|
||||||
|
{
|
||||||
|
RunVGUIFrame();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif // _WIN32
|
||||||
|
{
|
||||||
|
ProcessConsoleInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!engineAPI->RunFrame())
|
||||||
|
{
|
||||||
|
bDone = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
sys->UpdateStatus(0 /* don't force */);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_bVGui)
|
||||||
|
{
|
||||||
|
RunVGUIFrame();
|
||||||
|
StopVGUI();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sys->DestroyConsoleWindow();
|
||||||
|
console.ShutDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iret = engineAPI->Shutdown();
|
||||||
|
Sys_UnloadModule(g_pEngineModule);
|
||||||
|
VGUIFinishedConfig();
|
||||||
|
|
||||||
|
if (iret == DLL_CLOSE)
|
||||||
|
return iret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
33
rehlds/dedicated/src/sys_ded.h
Normal file
33
rehlds/dedicated/src/sys_ded.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#ifndef SYS_DED_H
|
||||||
|
#define SYS_DED_H
|
||||||
|
#ifdef _WIN32
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "isys.h"
|
||||||
|
#include "dedicated.h"
|
||||||
|
#include "dll_state.h"
|
||||||
|
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
#include <signal.h>
|
||||||
|
#endif // !defined(_WIN32)
|
||||||
|
|
||||||
|
int RunServer();
|
||||||
|
void Load3rdParty();
|
||||||
|
void Sys_Printf_Safe(char *text);
|
||||||
|
void Sys_Printf(char *fmt, ...);
|
||||||
|
void _log(const char *fmt, ...);
|
||||||
|
|
||||||
|
extern long hDLLThirdParty;
|
||||||
|
extern char *gpszCvars;
|
||||||
|
extern bool gbAppHasBeenTerminated;
|
||||||
|
extern IFileSystem *g_pFileSystemInterface;
|
||||||
|
extern CSysModule *g_pEngineModule;
|
||||||
|
extern CSysModule *g_pFileSystemModule;
|
||||||
|
extern CreateInterfaceFn g_FilesystemFactoryFn;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
BOOL WINAPI MyHandlerRoutine(DWORD CtrlType);
|
||||||
|
#endif // _WIN32
|
||||||
|
|
||||||
|
#endif // SYS_DED_H
|
334
rehlds/dedicated/src/sys_linux.cpp
Normal file
334
rehlds/dedicated/src/sys_linux.cpp
Normal file
@ -0,0 +1,334 @@
|
|||||||
|
#include "precompiled.h"
|
||||||
|
|
||||||
|
class CSys: public ISys {
|
||||||
|
public:
|
||||||
|
virtual ~CSys();
|
||||||
|
|
||||||
|
void Sleep(int msec);
|
||||||
|
bool GetExecutableName(char *out);
|
||||||
|
NORETURN void ErrorMessage(int level, const char *msg);
|
||||||
|
|
||||||
|
void WriteStatusText(char *szText);
|
||||||
|
void UpdateStatus(int force);
|
||||||
|
|
||||||
|
long LoadLibrary(char *lib);
|
||||||
|
void FreeLibrary(long library);
|
||||||
|
|
||||||
|
bool CreateConsoleWindow();
|
||||||
|
void DestroyConsoleWindow();
|
||||||
|
|
||||||
|
void ConsoleOutput(char *string);
|
||||||
|
char *ConsoleInput();
|
||||||
|
void Printf(char *fmt, ...);
|
||||||
|
};
|
||||||
|
|
||||||
|
CSys g_Sys;
|
||||||
|
ISys *sys = &g_Sys;
|
||||||
|
char g_szEXEName[MAX_PATH];
|
||||||
|
|
||||||
|
SleepType Sys_Sleep;
|
||||||
|
NET_Sleep_t NET_Sleep_Timeout = NULL;
|
||||||
|
|
||||||
|
CSys::~CSys()
|
||||||
|
{
|
||||||
|
sys = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this checks if pause has run yet,
|
||||||
|
// tell the compiler it can change at any time
|
||||||
|
volatile bool g_bPaused = false;
|
||||||
|
|
||||||
|
void CSys::Sleep(int msec)
|
||||||
|
{
|
||||||
|
usleep(msec * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sleep_Old(int msec)
|
||||||
|
{
|
||||||
|
usleep(msec * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sleep_Select(int msec)
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
// Assumes msec < 1000
|
||||||
|
tv.tv_sec = 0;
|
||||||
|
tv.tv_usec = 1000 * msec;
|
||||||
|
|
||||||
|
select(1, NULL, NULL, NULL, &tv);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sleep_Net(int msec)
|
||||||
|
{
|
||||||
|
if (NET_Sleep_Timeout)
|
||||||
|
{
|
||||||
|
NET_Sleep_Timeout();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NET_Sleep_Timeout isn't hooked yet, fallback to the old method
|
||||||
|
Sleep_Old(msec);
|
||||||
|
}
|
||||||
|
|
||||||
|
// linux runs on a 100Hz scheduling clock, so the minimum latency from
|
||||||
|
// usleep is 10msec. However, people want lower latency than this..
|
||||||
|
//
|
||||||
|
// There are a few solutions, one is to use the realtime scheduler in the
|
||||||
|
// kernel BUT this needs root privelleges to start. It also can play
|
||||||
|
// unfriendly with other programs.
|
||||||
|
//
|
||||||
|
// Another solution is to use software timers, they use the RTC of the
|
||||||
|
// system and are accurate to microseconds (or so).
|
||||||
|
//
|
||||||
|
// timers, via setitimer() are used here
|
||||||
|
void Sleep_Timer(int msec)
|
||||||
|
{
|
||||||
|
struct itimerval tm;
|
||||||
|
|
||||||
|
tm.it_value.tv_sec = msec / 1000; // convert msec to seconds
|
||||||
|
tm.it_value.tv_usec = (msec % 1000) * 1E3; // get the number of msecs and change to micros
|
||||||
|
tm.it_interval.tv_sec = 0;
|
||||||
|
tm.it_interval.tv_usec = 0;
|
||||||
|
|
||||||
|
g_bPaused = false;
|
||||||
|
|
||||||
|
// set the timer to trigger
|
||||||
|
if (setitimer(ITIMER_REAL, &tm, NULL)) {
|
||||||
|
// wait for the signal
|
||||||
|
pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
g_bPaused = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void alarmFunc(int num)
|
||||||
|
{
|
||||||
|
// reset the signal handler
|
||||||
|
signal(SIGALRM, alarmFunc);
|
||||||
|
|
||||||
|
// paused is 0, the timer has fired before the pause was called... Lets queue it again
|
||||||
|
if (!g_bPaused)
|
||||||
|
{
|
||||||
|
struct itimerval itim;
|
||||||
|
itim.it_interval.tv_sec = 0;
|
||||||
|
itim.it_interval.tv_usec = 0;
|
||||||
|
itim.it_value.tv_sec = 0;
|
||||||
|
itim.it_value.tv_usec = 1000; // get it to run again real soon
|
||||||
|
setitimer(ITIMER_REAL, &itim, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSys::GetExecutableName(char *out)
|
||||||
|
{
|
||||||
|
strcpy(out, g_szEXEName);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Engine is erroring out, display error in message box
|
||||||
|
void CSys::ErrorMessage(int level, const char *msg)
|
||||||
|
{
|
||||||
|
puts(msg);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSys::WriteStatusText(char *szText)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSys::UpdateStatus(int force)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
long CSys::LoadLibrary(char *lib)
|
||||||
|
{
|
||||||
|
char cwd[1024];
|
||||||
|
char absolute_lib[1024];
|
||||||
|
|
||||||
|
if (!getcwd(cwd, sizeof(cwd)))
|
||||||
|
ErrorMessage(1, "Sys_LoadLibrary: Couldn't determine current directory.");
|
||||||
|
|
||||||
|
if (cwd[strlen(cwd) - 1] == '/')
|
||||||
|
cwd[strlen(cwd) - 1] = '\0';
|
||||||
|
|
||||||
|
_snprintf(absolute_lib, sizeof(absolute_lib), "%s/%s", cwd, lib);
|
||||||
|
|
||||||
|
void *hDll = dlopen(absolute_lib, RTLD_NOW);
|
||||||
|
if (!hDll)
|
||||||
|
{
|
||||||
|
ErrorMessage(1, dlerror());
|
||||||
|
}
|
||||||
|
|
||||||
|
return (long)hDll;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSys::FreeLibrary(long library)
|
||||||
|
{
|
||||||
|
if (!library)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dlclose((void *)library);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSys::CreateConsoleWindow()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSys::DestroyConsoleWindow()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print text to the dedicated console
|
||||||
|
void CSys::ConsoleOutput(char *string)
|
||||||
|
{
|
||||||
|
printf("%s", string);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *CSys::ConsoleInput()
|
||||||
|
{
|
||||||
|
return console.GetLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSys::Printf(char *fmt, ...)
|
||||||
|
{
|
||||||
|
// Dump text to debugging console.
|
||||||
|
va_list argptr;
|
||||||
|
char szText[1024];
|
||||||
|
|
||||||
|
va_start(argptr, fmt);
|
||||||
|
_vsnprintf(szText, sizeof(szText), fmt, argptr);
|
||||||
|
va_end(argptr);
|
||||||
|
|
||||||
|
// Get Current text and append it.
|
||||||
|
ConsoleOutput(szText);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAX_LINUX_CMDLINE 2048
|
||||||
|
static char linuxCmdline[ MAX_LINUX_CMDLINE ];
|
||||||
|
|
||||||
|
void BuildCmdLine(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (len = 0, i = 1; i < argc; i++)
|
||||||
|
{
|
||||||
|
len += strlen(argv[i]) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len > MAX_LINUX_CMDLINE)
|
||||||
|
{
|
||||||
|
printf("command line too long, %i max\n", MAX_LINUX_CMDLINE);
|
||||||
|
exit(-1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
linuxCmdline[0] = '\0';
|
||||||
|
for (i = 1; i < argc; i++)
|
||||||
|
{
|
||||||
|
if (i > 1) {
|
||||||
|
strcat(linuxCmdline, " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
strcat(linuxCmdline, argv[ i ]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char *GetCommandLine()
|
||||||
|
{
|
||||||
|
return linuxCmdline;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
_snprintf(g_szEXEName, sizeof(g_szEXEName), "%s", argv[0]);
|
||||||
|
BuildCmdLine(argc, argv);
|
||||||
|
|
||||||
|
CommandLine()->CreateCmdLine(::GetCommandLine());
|
||||||
|
CommandLine()->AppendParm("-steam", NULL);
|
||||||
|
|
||||||
|
// Load engine
|
||||||
|
g_pEngineModule = Sys_LoadModule(ENGINE_LIB);
|
||||||
|
if (!g_pEngineModule)
|
||||||
|
{
|
||||||
|
sys->ErrorMessage(1, "Unable to load engine, image is corrupt.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Sys_Sleep = Sleep_Old;
|
||||||
|
|
||||||
|
char *pPingType;
|
||||||
|
int type;
|
||||||
|
if (CommandLine()->CheckParm("-pingboost", &pPingType) && pPingType)
|
||||||
|
{
|
||||||
|
type = atoi(pPingType);
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
signal(SIGALRM, alarmFunc);
|
||||||
|
Sys_Sleep = Sleep_Timer;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
Sys_Sleep = Sleep_Select;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
Sys_Sleep = Sleep_Net;
|
||||||
|
|
||||||
|
// we Sys_GetProcAddress NET_Sleep() from
|
||||||
|
//engine_i486.so later in this function
|
||||||
|
NET_Sleep_Timeout = (NET_Sleep_t)Sys_GetProcAddress(g_pEngineModule, "NET_Sleep_Timeout");
|
||||||
|
break;
|
||||||
|
// just in case
|
||||||
|
default:
|
||||||
|
Sys_Sleep = Sleep_Old;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char *fsmodule;
|
||||||
|
if (CommandLine()->CheckParm("-pidfile", &fsmodule) && fsmodule)
|
||||||
|
{
|
||||||
|
FILE *pidFile = fopen(fsmodule, "w");
|
||||||
|
if (pidFile) {
|
||||||
|
fprintf(pidFile, "%i\n", getpid());
|
||||||
|
fclose(pidFile);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
printf("Warning: unable to open pidfile (%s)\n", pPingType);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_pFileSystemModule = Sys_LoadModule(STDIO_FILESYSTEM_LIB);
|
||||||
|
|
||||||
|
// Get FileSystem interface
|
||||||
|
g_FilesystemFactoryFn = Sys_GetFactory(g_pFileSystemModule);
|
||||||
|
if (!g_FilesystemFactoryFn)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
IFileSystem *pFullFileSystem = (IFileSystem *)g_FilesystemFactoryFn(FILESYSTEM_INTERFACE_VERSION, NULL);
|
||||||
|
if (!pFullFileSystem)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
pFullFileSystem->Mount();
|
||||||
|
|
||||||
|
if (!console.Init()) {
|
||||||
|
puts("Failed to initilise console.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
gbAppHasBeenTerminated = false;
|
||||||
|
RunServer();
|
||||||
|
|
||||||
|
if (gpszCvars)
|
||||||
|
free(gpszCvars);
|
||||||
|
|
||||||
|
if (pFullFileSystem)
|
||||||
|
pFullFileSystem->Unmount();
|
||||||
|
|
||||||
|
Sys_UnloadModule(g_pFileSystemModule);
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
return 0;
|
||||||
|
}
|
266
rehlds/dedicated/src/sys_window.cpp
Normal file
266
rehlds/dedicated/src/sys_window.cpp
Normal file
@ -0,0 +1,266 @@
|
|||||||
|
#include "precompiled.h"
|
||||||
|
|
||||||
|
class CSys: public ISys {
|
||||||
|
public:
|
||||||
|
virtual ~CSys();
|
||||||
|
|
||||||
|
void Sleep(int msec);
|
||||||
|
bool GetExecutableName(char *out);
|
||||||
|
void ErrorMessage(int level, const char *msg);
|
||||||
|
|
||||||
|
void WriteStatusText(char *szText);
|
||||||
|
void UpdateStatus(int force);
|
||||||
|
|
||||||
|
long LoadLibrary(char *lib);
|
||||||
|
void FreeLibrary(long library);
|
||||||
|
|
||||||
|
bool CreateConsoleWindow();
|
||||||
|
void DestroyConsoleWindow();
|
||||||
|
|
||||||
|
void ConsoleOutput(char *string);
|
||||||
|
char *ConsoleInput();
|
||||||
|
void Printf(char *fmt, ...);
|
||||||
|
};
|
||||||
|
|
||||||
|
CSys g_Sys;
|
||||||
|
ISys *sys = &g_Sys;
|
||||||
|
|
||||||
|
CSys::~CSys()
|
||||||
|
{
|
||||||
|
sys = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSys::Sleep(int msec)
|
||||||
|
{
|
||||||
|
::Sleep(msec);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSys::GetExecutableName(char *out)
|
||||||
|
{
|
||||||
|
if (!::GetModuleFileName((HINSTANCE)GetModuleHandle(NULL), out, 256))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSys::ErrorMessage(int level, const char *msg)
|
||||||
|
{
|
||||||
|
MessageBox(NULL, msg, "Half-Life Dedicated Server Error", MB_OK);
|
||||||
|
PostQuitMessage(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSys::WriteStatusText(char *szText)
|
||||||
|
{
|
||||||
|
SetConsoleTitle(szText);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSys::UpdateStatus(int force)
|
||||||
|
{
|
||||||
|
static double tLast = 0.0;
|
||||||
|
double tCurrent;
|
||||||
|
char szStatus[256];
|
||||||
|
int n, nMax;
|
||||||
|
char szMap[32];
|
||||||
|
float fps;
|
||||||
|
|
||||||
|
if (!engineAPI)
|
||||||
|
return;
|
||||||
|
|
||||||
|
tCurrent = (double)timeGetTime() * 0.001;
|
||||||
|
engineAPI->UpdateStatus(&fps, &n, &nMax, szMap);
|
||||||
|
|
||||||
|
if (!force)
|
||||||
|
{
|
||||||
|
if ((tCurrent - tLast) < 0.5f)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tLast = tCurrent;
|
||||||
|
_snprintf(szStatus, sizeof(szStatus), "%.1f fps %2i/%2i on %16s", fps, n, nMax, szMap);
|
||||||
|
|
||||||
|
console.SetStatusLine(szStatus);
|
||||||
|
console.UpdateStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
long CSys::LoadLibrary(char *lib)
|
||||||
|
{
|
||||||
|
void *hDll = ::LoadLibrary(lib);
|
||||||
|
return (long)hDll;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSys::FreeLibrary(long library)
|
||||||
|
{
|
||||||
|
if (!library)
|
||||||
|
return;
|
||||||
|
|
||||||
|
::FreeLibrary((HMODULE)library);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSys::CreateConsoleWindow()
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
if (!AllocConsole())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
InitConProc();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSys::DestroyConsoleWindow()
|
||||||
|
{
|
||||||
|
FreeConsole();
|
||||||
|
|
||||||
|
// shut down QHOST hooks if necessary
|
||||||
|
DeinitConProc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSys::ConsoleOutput(char *string)
|
||||||
|
{
|
||||||
|
if (g_bVGui)
|
||||||
|
{
|
||||||
|
VGUIPrintf(string);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
console.Print(string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char *CSys::ConsoleInput()
|
||||||
|
{
|
||||||
|
return console.GetLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSys::Printf(char *fmt, ...)
|
||||||
|
{
|
||||||
|
// Dump text to debugging console.
|
||||||
|
va_list argptr;
|
||||||
|
char szText[1024];
|
||||||
|
|
||||||
|
va_start(argptr, fmt);
|
||||||
|
_vsnprintf(szText, sizeof(szText), fmt, argptr);
|
||||||
|
va_end(argptr);
|
||||||
|
|
||||||
|
// Get Current text and append it.
|
||||||
|
ConsoleOutput(szText);
|
||||||
|
}
|
||||||
|
|
||||||
|
int StartServer()
|
||||||
|
{
|
||||||
|
// Startup winock
|
||||||
|
WORD version = MAKEWORD(2, 0);
|
||||||
|
WSADATA wsaData;
|
||||||
|
WSAStartup(version, &wsaData);
|
||||||
|
|
||||||
|
CommandLine()->CreateCmdLine(GetCommandLine());
|
||||||
|
|
||||||
|
// Load engine
|
||||||
|
g_pEngineModule = Sys_LoadModule(ENGINE_LIB);
|
||||||
|
if (!g_pEngineModule)
|
||||||
|
{
|
||||||
|
MessageBox(NULL, "Unable to load engine, image is corrupt.", "Half-Life Dedicated Server Error", MB_OK);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_pFileSystemModule = Sys_LoadModule(STDIO_FILESYSTEM_LIB);
|
||||||
|
|
||||||
|
// Get FileSystem interface
|
||||||
|
g_FilesystemFactoryFn = Sys_GetFactory(g_pFileSystemModule);
|
||||||
|
if (!g_FilesystemFactoryFn)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
IFileSystem *pFullFileSystem = (IFileSystem *)g_FilesystemFactoryFn(FILESYSTEM_INTERFACE_VERSION, NULL);
|
||||||
|
if (!pFullFileSystem)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
pFullFileSystem->Mount();
|
||||||
|
|
||||||
|
char *pszValue = nullptr;
|
||||||
|
if (CommandLine()->CheckParm("-steam")
|
||||||
|
|| (CommandLine()->CheckParm("-console", &pszValue) && !pszValue)) {
|
||||||
|
g_bVGui = true;
|
||||||
|
StartVGUI();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!console.Init()) {
|
||||||
|
MessageBox(NULL, "Failed to initialize console.", "Half-Life Dedicated Server Error", MB_OK);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sys->CreateConsoleWindow()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.SetColor(FOREGROUND_RED | FOREGROUND_INTENSITY);
|
||||||
|
|
||||||
|
if (!SetConsoleCtrlHandler(MyHandlerRoutine, TRUE)) {
|
||||||
|
MessageBox(NULL, "Unable to set control handler", "Half-Life Dedicated Server Error", MB_OK);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gbAppHasBeenTerminated = false;
|
||||||
|
Load3rdParty();
|
||||||
|
|
||||||
|
// TODO: finish me!
|
||||||
|
/*// run vgui
|
||||||
|
if (g_bVGui)
|
||||||
|
{
|
||||||
|
while (VGUIIsInConfig() && VGUIIsRunning())
|
||||||
|
{
|
||||||
|
RunVGUIFrame();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else*/
|
||||||
|
{
|
||||||
|
RunServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gpszCvars)
|
||||||
|
free(gpszCvars);
|
||||||
|
|
||||||
|
if (pFullFileSystem)
|
||||||
|
pFullFileSystem->Unmount();
|
||||||
|
|
||||||
|
Sys_UnloadModule(g_pFileSystemModule);
|
||||||
|
|
||||||
|
if (hDLLThirdParty)
|
||||||
|
{
|
||||||
|
Sys_UnloadModule((CSysModule *)hDLLThirdParty);
|
||||||
|
hDLLThirdParty = 0L;
|
||||||
|
}
|
||||||
|
|
||||||
|
WSACleanup();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
|
||||||
|
{
|
||||||
|
if (ShouldLaunchAppViaSteam(lpCmdLine, STDIO_FILESYSTEM_LIB, STDIO_FILESYSTEM_LIB))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
auto command = CommandLineToArgvW(GetCommandLineW(), (int *)&lpCmdLine);
|
||||||
|
auto ret = StartServer();
|
||||||
|
LocalFree(command);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI MyHandlerRoutine(DWORD CtrlType)
|
||||||
|
{
|
||||||
|
switch (CtrlType)
|
||||||
|
{
|
||||||
|
case CTRL_C_EVENT:
|
||||||
|
case CTRL_BREAK_EVENT:
|
||||||
|
case CTRL_CLOSE_EVENT:
|
||||||
|
case CTRL_LOGOFF_EVENT:
|
||||||
|
case CTRL_SHUTDOWN_EVENT:
|
||||||
|
gbAppHasBeenTerminated = true;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
157
rehlds/dedicated/src/vgui/vguihelpers.cpp
Normal file
157
rehlds/dedicated/src/vgui/vguihelpers.cpp
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
#include "precompiled.h"
|
||||||
|
|
||||||
|
CSysModule *g_pVGUIModule = nullptr;
|
||||||
|
|
||||||
|
bool InitializeVGui(CreateInterfaceFn *factorylist, int factorycount)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
// TODO: finish me!
|
||||||
|
/*if (vgui::VGuiControls_Init("DEDICATED", factoryList, numFactories))
|
||||||
|
{
|
||||||
|
filesystem()->AddSearchPath(".", "MAIN");
|
||||||
|
return true;
|
||||||
|
}*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Starts up the VGUI system and loads the base panel
|
||||||
|
int StartVGUI()
|
||||||
|
{
|
||||||
|
// TODO: finish me!
|
||||||
|
/*g_pVGUIModule = Sys_LoadModule("vgui2.dll");
|
||||||
|
|
||||||
|
CreateInterfaceFn ifaceFactory = Sys_GetFactoryThis();
|
||||||
|
CreateInterfaceFn adminFactory = Sys_GetFactory(g_pVGUIModule);
|
||||||
|
CreateInterfaceFn filesystemFactory = Sys_GetFactory(g_pFileSystemModule);
|
||||||
|
CreateInterfaceFn dedicatedFactory = Sys_GetFactory(g_pEngineModule);
|
||||||
|
|
||||||
|
const int numFactories = 4;
|
||||||
|
if (!InitializeVGui(&ifaceFactory, numFactories))
|
||||||
|
{
|
||||||
|
MessageBox(NULL, "Fatal Error: Could not initialize vgui.", "Steam - Fatal Error", MB_OK | MB_ICONERROR);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
filesystem()->AddSearchPath("platform", "PLATFORM");
|
||||||
|
|
||||||
|
// find our configuration directory
|
||||||
|
char szConfigDir[512];
|
||||||
|
const char *steamPath = getenv("SteamInstallPath");
|
||||||
|
if (steamPath)
|
||||||
|
{
|
||||||
|
// put the config dir directly under steam
|
||||||
|
_snprintf(szConfigDir, sizeof(szConfigDir), "%s/config", steamPath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// we're not running steam, so just put the config dir under the platform
|
||||||
|
strncpy(szConfigDir, "platform/config", sizeof(szConfigDir));
|
||||||
|
}
|
||||||
|
|
||||||
|
mkdir(szConfigDir);
|
||||||
|
filesystem()->AddSearchPath(szConfigDir, "CONFIG");
|
||||||
|
|
||||||
|
vgui::system()->SetUserConfigFile("DialogConfig.vdf", "CONFIG");
|
||||||
|
|
||||||
|
// Init the surface
|
||||||
|
g_pMainPanel = new CMainPanel();
|
||||||
|
g_pMainPanel->SetVisible(true);
|
||||||
|
|
||||||
|
vgui::surface()->SetEmbeddedPanel(g_pMainPanel->GetVPanel());
|
||||||
|
|
||||||
|
// load the scheme
|
||||||
|
vgui::scheme()->LoadSchemeFromFile("Resource/TrackerScheme.res", NULL);
|
||||||
|
|
||||||
|
// localization
|
||||||
|
vgui::localize()->AddFile("Resource/platform_%language%.txt");
|
||||||
|
vgui::localize()->AddFile("Resource/vgui_%language%.txt");
|
||||||
|
vgui::localize()->AddFile("Admin/server_%language%.txt");
|
||||||
|
|
||||||
|
// Start vgui
|
||||||
|
vgui::ivgui()->Start();
|
||||||
|
|
||||||
|
// load the module
|
||||||
|
g_pFullFileSystem->GetLocalCopy("Platform/Admin/AdminServer.dll");
|
||||||
|
g_hAdminServerModule = Sys_LoadModule("Platform/Admin/AdminServer.dll");
|
||||||
|
Assert(g_hAdminServerModule != NULL);
|
||||||
|
CreateInterfaceFn adminFactory = NULL;
|
||||||
|
|
||||||
|
if (!g_hAdminServerModule)
|
||||||
|
{
|
||||||
|
vgui::ivgui()->DPrintf2("Admin Error: module version (Admin/AdminServer.dll, %s) invalid, not loading\n", IMANAGESERVER_INTERFACE_VERSION);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// make sure we get the right version
|
||||||
|
adminFactory = Sys_GetFactory(g_hAdminServerModule);
|
||||||
|
g_pAdminServer = (IAdminServer *)adminFactory(ADMINSERVER_INTERFACE_VERSION, NULL);
|
||||||
|
g_pAdminVGuiModule = (IVGuiModule *)adminFactory("VGuiModuleAdminServer001", NULL);
|
||||||
|
Assert(g_pAdminServer != NULL);
|
||||||
|
Assert(g_pAdminVGuiModule != NULL);
|
||||||
|
if (!g_pAdminServer || !g_pAdminVGuiModule)
|
||||||
|
{
|
||||||
|
vgui::ivgui()->DPrintf2("Admin Error: module version (Admin/AdminServer.dll, %s) invalid, not loading\n", IMANAGESERVER_INTERFACE_VERSION);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// finish initializing admin module
|
||||||
|
g_pAdminVGuiModule->Initialize(&dedicatedFactory, 1);
|
||||||
|
g_pAdminVGuiModule->PostInitialize(&adminFactory, 1);
|
||||||
|
g_pAdminVGuiModule->SetParent(g_pMainPanel->GetVPanel());
|
||||||
|
|
||||||
|
// finish setting up main panel
|
||||||
|
g_pMainPanel->Initialize();
|
||||||
|
g_pMainPanel->Open();
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run a single VGUI frame
|
||||||
|
void StopVGUI()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunVGUIFrame()
|
||||||
|
{
|
||||||
|
// TODO: finish me!
|
||||||
|
//vgui::ivgui()->RunFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VGUIIsRunning()
|
||||||
|
{
|
||||||
|
//return vgui::ivgui()->IsRunning();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VGUIIsStopping()
|
||||||
|
{
|
||||||
|
//return g_pMainPanel->Stopping();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VGUIIsInConfig()
|
||||||
|
{
|
||||||
|
//return g_pMainPanel->IsInConfig();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VGUIFinishedConfig()
|
||||||
|
{
|
||||||
|
/*Assert(g_pMainPanel);
|
||||||
|
|
||||||
|
// engine is loaded, pass the message on
|
||||||
|
if (g_pMainPanel)
|
||||||
|
{
|
||||||
|
SetEvent(g_pMainPanel->GetShutdownHandle());
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void VGUIPrintf(const char *msg)
|
||||||
|
{
|
||||||
|
/*if (g_pMainPanel)
|
||||||
|
{
|
||||||
|
g_pMainPanel->AddConsoleText(msg);
|
||||||
|
}*/
|
||||||
|
}
|
10
rehlds/dedicated/src/vgui/vguihelpers.h
Normal file
10
rehlds/dedicated/src/vgui/vguihelpers.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
int StartVGUI();
|
||||||
|
void StopVGUI();
|
||||||
|
void RunVGUIFrame();
|
||||||
|
bool VGUIIsRunning();
|
||||||
|
bool VGUIIsStopping();
|
||||||
|
bool VGUIIsInConfig();
|
||||||
|
void VGUIFinishedConfig();
|
||||||
|
void VGUIPrintf(const char *msg);
|
@ -51,7 +51,7 @@ bool FileSystem_LoadDLL(CreateInterfaceFn filesystemFactory)
|
|||||||
{
|
{
|
||||||
if (!filesystemFactory)
|
if (!filesystemFactory)
|
||||||
{
|
{
|
||||||
g_pFileSystemModule = Sys_LoadModule(FILESYSTEM_DLL_NAME);
|
g_pFileSystemModule = Sys_LoadModule(STDIO_FILESYSTEM_LIB);
|
||||||
|
|
||||||
if (g_pFileSystemModule)
|
if (g_pFileSystemModule)
|
||||||
{
|
{
|
||||||
|
@ -36,12 +36,6 @@
|
|||||||
#include "iregistry.h"
|
#include "iregistry.h"
|
||||||
#include "utlvector.h"
|
#include "utlvector.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#define FILESYSTEM_DLL_NAME "filesystem_stdio.dll"
|
|
||||||
#else
|
|
||||||
#define FILESYSTEM_DLL_NAME "filesystem_stdio.so"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HOOK_ENGINE
|
#ifdef HOOK_ENGINE
|
||||||
#define g_fallbackLocalizationFiles (*pg_fallbackLocalizationFiles)
|
#define g_fallbackLocalizationFiles (*pg_fallbackLocalizationFiles)
|
||||||
#define s_pBaseDir (*ps_pBaseDir)
|
#define s_pBaseDir (*ps_pBaseDir)
|
||||||
|
@ -15,6 +15,13 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define STDIO_FILESYSTEM_LIB "filesystem_stdio.dll"
|
||||||
|
#define STEAM_FILESYSTEM_LIB "filesystem_steam.dll"
|
||||||
|
#else
|
||||||
|
#define STDIO_FILESYSTEM_LIB "filesystem_stdio.so"
|
||||||
|
#define STEAM_FILESYSTEM_LIB "filesystem_steam.so"
|
||||||
|
#endif // _WIN32
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Forward declarations
|
// Forward declarations
|
||||||
|
@ -31,6 +31,12 @@
|
|||||||
#include "maintypes.h"
|
#include "maintypes.h"
|
||||||
#include "interface.h"
|
#include "interface.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define ENGINE_LIB "swds.dll"
|
||||||
|
#else
|
||||||
|
#define ENGINE_LIB "engine_i486.so"
|
||||||
|
#endif // _WIN32
|
||||||
|
|
||||||
class IDedicatedServerAPI : public IBaseInterface
|
class IDedicatedServerAPI : public IBaseInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -28,8 +28,6 @@
|
|||||||
#include "steamps3params.h"
|
#include "steamps3params.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Steam API export macro
|
// Steam API export macro
|
||||||
#if defined( _WIN32 ) && !defined( _X360 )
|
#if defined( _WIN32 ) && !defined( _X360 )
|
||||||
#if defined( STEAM_API_EXPORTS )
|
#if defined( STEAM_API_EXPORTS )
|
||||||
@ -55,8 +53,9 @@
|
|||||||
|
|
||||||
class CCallbackBase;
|
class CCallbackBase;
|
||||||
|
|
||||||
|
#ifdef REHLDS_SELF
|
||||||
#include "rehlds/platform.h"
|
#include "rehlds/platform.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------------------------------------------------------------//
|
//----------------------------------------------------------------------------------------------------------------------------------------------------------//
|
||||||
// Steam API setup & shutdown
|
// Steam API setup & shutdown
|
||||||
@ -301,13 +300,23 @@ public:
|
|||||||
m_pObj = pObj;
|
m_pObj = pObj;
|
||||||
m_Func = func;
|
m_Func = func;
|
||||||
// SteamAPI_RegisterCallback sets k_ECallbackFlagsRegistered
|
// SteamAPI_RegisterCallback sets k_ECallbackFlagsRegistered
|
||||||
|
|
||||||
|
#ifdef REHLDS_SELF
|
||||||
CRehldsPlatformHolder::get()->SteamAPI_RegisterCallback(this, P::k_iCallback);
|
CRehldsPlatformHolder::get()->SteamAPI_RegisterCallback(this, P::k_iCallback);
|
||||||
|
#else
|
||||||
|
SteamAPI_RegisterCallback(this, P::k_iCallback);
|
||||||
|
#endif // REHLDS_SELF
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unregister()
|
void Unregister()
|
||||||
{
|
{
|
||||||
// SteamAPI_UnregisterCallback removes k_ECallbackFlagsRegistered
|
// SteamAPI_UnregisterCallback removes k_ECallbackFlagsRegistered
|
||||||
|
|
||||||
|
#ifdef REHLDS_SELF
|
||||||
CRehldsPlatformHolder::get()->SteamAPI_UnregisterCallback(this);
|
CRehldsPlatformHolder::get()->SteamAPI_UnregisterCallback(this);
|
||||||
|
#else
|
||||||
|
SteamAPI_UnregisterCallback(this);
|
||||||
|
#endif // REHLDS_SELF
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetGameserverFlag() { m_nCallbackFlags |= k_ECallbackFlagsGameServer; }
|
void SetGameserverFlag() { m_nCallbackFlags |= k_ECallbackFlagsGameServer; }
|
||||||
|
31
rehlds/public/vgui/VGUI.h
Normal file
31
rehlds/public/vgui/VGUI.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef VGUI_H
|
||||||
|
#define VGUI_H
|
||||||
|
#ifdef _WIN32
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace vgui2
|
||||||
|
{
|
||||||
|
|
||||||
|
// handle to an internal vgui panel
|
||||||
|
// this is the only handle to a panel that is valid across dll boundaries
|
||||||
|
typedef unsigned int VPANEL;
|
||||||
|
|
||||||
|
// handles to vgui objects
|
||||||
|
// NULL values signify an invalid value
|
||||||
|
typedef unsigned long HScheme;
|
||||||
|
typedef unsigned long HTexture;
|
||||||
|
typedef unsigned long HCursor;
|
||||||
|
|
||||||
|
typedef int HContext;
|
||||||
|
typedef unsigned long HPanel;
|
||||||
|
typedef unsigned long HFont;
|
||||||
|
|
||||||
|
// the value of an invalid font handle
|
||||||
|
const VPANEL NULL_PANEL = 0;
|
||||||
|
const HFont INVALID_FONT = 0;
|
||||||
|
const HPanel INVALID_PANEL = 0xffffffff;
|
||||||
|
|
||||||
|
} // namespace vgui
|
||||||
|
|
||||||
|
#endif // VGUI_H
|
@ -2,4 +2,5 @@ rootProject.name = 'rehlds'
|
|||||||
include 'dep/cppunitlite'
|
include 'dep/cppunitlite'
|
||||||
include 'dep/bzip2'
|
include 'dep/bzip2'
|
||||||
include 'rehlds'
|
include 'rehlds'
|
||||||
|
include 'rehlds/dedicated'
|
||||||
include 'flightrec/decoder_api', 'flightrec/decoder'
|
include 'flightrec/decoder_api', 'flightrec/decoder'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user