mirror of
https://github.com/rehlds/rehlds.git
synced 2025-01-28 06:28:06 +03:00
Add project Dedicated (hlds launcher without VGUI)
This commit is contained in:
parent
713eb77e9e
commit
3bf374d298
2
.gitignore
vendored
2
.gitignore
vendored
@ -15,11 +15,11 @@
|
||||
**/msvc/*.suo
|
||||
**/msvc/*.db
|
||||
**/msvc/*.opendb
|
||||
**/msvc/PublishPath*.txt
|
||||
**/msvc/ipch
|
||||
**/msvc/.vs
|
||||
|
||||
rehlds/version/appversion.h
|
||||
rehlds/msvc/PublishPath*.txt
|
||||
rehlds/_rehldsTestImg
|
||||
rehlds/_dev
|
||||
publish
|
||||
|
@ -2,11 +2,25 @@ import org.doomedsociety.gradlecpp.GradleCppUtils
|
||||
import org.apache.commons.io.FilenameUtils
|
||||
|
||||
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))
|
||||
GradleCppUtils.copyFile(project.file(from), dst, false)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
@ -22,19 +36,21 @@ task publishPrepareFiles {
|
||||
|
||||
pubRootDir.mkdirs()
|
||||
|
||||
//bugfixed binaries
|
||||
project.file('publish/publishRoot/bin/bugfixed').mkdirs()
|
||||
// bugfixed binaries
|
||||
_copyFileToDir('publish/releaseRehldsFixes/swds.dll', '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')
|
||||
|
||||
//pure binaries
|
||||
project.file('publish/publishRoot/bin/pure').mkdirs()
|
||||
// pure binaries
|
||||
_copyFileToDir('publish/releaseRehldsNofixes/swds.dll', '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')
|
||||
|
||||
//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()
|
||||
copy {
|
||||
from 'rehlds/common'
|
||||
@ -58,8 +74,7 @@ task publishPrepareFiles {
|
||||
into 'publish/publishRoot/hlsdk/engine'
|
||||
}
|
||||
|
||||
//flightrecorder
|
||||
|
||||
// flightrecorder
|
||||
def flightRecJarTask = project(':flightrec/decoder').tasks.getByName('uberjar')
|
||||
println flightRecJarTask
|
||||
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)
|
||||
{
|
||||
g_pFileSystemModule = Sys_LoadModule(FILESYSTEM_DLL_NAME);
|
||||
g_pFileSystemModule = Sys_LoadModule(STDIO_FILESYSTEM_LIB);
|
||||
|
||||
if (g_pFileSystemModule)
|
||||
{
|
||||
|
@ -36,12 +36,6 @@
|
||||
#include "iregistry.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
|
||||
#define g_fallbackLocalizationFiles (*pg_fallbackLocalizationFiles)
|
||||
#define s_pBaseDir (*ps_pBaseDir)
|
||||
|
@ -1,6 +1,6 @@
|
||||
//========= Copyright <20> 1996-2001, Valve LLC, All rights reserved. ============
|
||||
//
|
||||
// Purpose:
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================
|
||||
@ -15,6 +15,13 @@
|
||||
#include <stdio.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
|
||||
@ -77,7 +84,7 @@ public:
|
||||
// Add paths in priority order (mod dir, game dir, ....)
|
||||
// If one or more .pak files are in the specified directory, then they are
|
||||
// added after the file system path
|
||||
// If the path is the relative path to a .bsp file, then any previous .bsp file
|
||||
// If the path is the relative path to a .bsp file, then any previous .bsp file
|
||||
// override is cleared and the current .bsp is searched for an embedded PAK file
|
||||
// and this file becomes the highest priority search path ( i.e., it's looked at first
|
||||
// even before the mod's file system path ).
|
||||
@ -121,7 +128,7 @@ public:
|
||||
|
||||
// direct filesystem buffer access
|
||||
// returns a handle to a buffer containing the file data
|
||||
// this is the optimal way to access the complete data for a file,
|
||||
// this is the optimal way to access the complete data for a file,
|
||||
// since the file preloader has probably already got it in memory
|
||||
virtual void *GetReadBuffer( FileHandle_t file, int *outBufferSize, bool failIfNotInCache ) = 0;
|
||||
virtual void ReleaseReadBuffer( FileHandle_t file, void *readBuffer ) = 0;
|
||||
@ -174,7 +181,7 @@ public:
|
||||
|
||||
// interface for custom pack files > 4Gb
|
||||
virtual bool AddPackFile( const char *fullpath, const char *pathID ) = 0;
|
||||
|
||||
|
||||
// open a file but force the data to come from the steam cache, NOT from disk
|
||||
virtual FileHandle_t OpenFromCacheForRead( const char *pFileName, const char *pOptions, const char *pathID = 0L ) = 0;
|
||||
|
||||
|
@ -31,6 +31,12 @@
|
||||
#include "maintypes.h"
|
||||
#include "interface.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define ENGINE_LIB "swds.dll"
|
||||
#else
|
||||
#define ENGINE_LIB "engine_i486.so"
|
||||
#endif // _WIN32
|
||||
|
||||
class IDedicatedServerAPI : public IBaseInterface
|
||||
{
|
||||
public:
|
||||
|
@ -1,6 +1,6 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
@ -28,35 +28,34 @@
|
||||
#include "steamps3params.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// Steam API export macro
|
||||
#if defined( _WIN32 ) && !defined( _X360 )
|
||||
#if defined( STEAM_API_EXPORTS )
|
||||
#define S_API extern "C" __declspec( dllexport )
|
||||
#define S_API extern "C" __declspec( dllexport )
|
||||
#elif defined( STEAM_API_NODLL )
|
||||
#define S_API extern "C"
|
||||
#else
|
||||
#define S_API extern "C" __declspec( dllimport )
|
||||
#define S_API extern "C" __declspec( dllimport )
|
||||
#endif // STEAM_API_EXPORTS
|
||||
#elif defined( GNUC )
|
||||
#if defined( STEAM_API_EXPORTS )
|
||||
#define S_API extern "C" __attribute__ ((visibility("default")))
|
||||
#define S_API extern "C" __attribute__ ((visibility("default")))
|
||||
#else
|
||||
#define S_API extern "C"
|
||||
#define S_API extern "C"
|
||||
#endif // STEAM_API_EXPORTS
|
||||
#else // !WIN32
|
||||
#if defined( STEAM_API_EXPORTS )
|
||||
#define S_API extern "C"
|
||||
#define S_API extern "C"
|
||||
#else
|
||||
#define S_API extern "C"
|
||||
#define S_API extern "C"
|
||||
#endif // STEAM_API_EXPORTS
|
||||
#endif
|
||||
|
||||
class CCallbackBase;
|
||||
|
||||
#ifdef REHLDS_SELF
|
||||
#include "rehlds/platform.h"
|
||||
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------------------------------------------//
|
||||
// Steam API setup & shutdown
|
||||
@ -68,10 +67,10 @@ class CCallbackBase;
|
||||
// S_API void SteamAPI_Init(); (see below)
|
||||
S_API void SteamAPI_Shutdown();
|
||||
|
||||
// checks if a local Steam client is running
|
||||
// checks if a local Steam client is running
|
||||
S_API bool SteamAPI_IsSteamRunning();
|
||||
|
||||
// Detects if your executable was launched through the Steam client, and restarts your game through
|
||||
// Detects if your executable was launched through the Steam client, and restarts your game through
|
||||
// the client if necessary. The Steam client will be started if it is not running.
|
||||
//
|
||||
// Returns: true if your executable was NOT launched through the Steam client. This function will
|
||||
@ -96,10 +95,10 @@ S_API ISteamClient *SteamClient();
|
||||
// VERSION_SAFE_STEAM_API_INTERFACES is usually not necessary, but it provides safety against releasing
|
||||
// new steam_api.dll's without recompiling/rereleasing modules that use it.
|
||||
//
|
||||
// If you use VERSION_SAFE_STEAM_API_INTERFACES, then you should call SteamAPI_InitSafe(). Also, to get the
|
||||
// If you use VERSION_SAFE_STEAM_API_INTERFACES, then you should call SteamAPI_InitSafe(). Also, to get the
|
||||
// Steam interfaces, you must create and Init() a CSteamAPIContext (below) and use the interfaces in there.
|
||||
//
|
||||
// If you don't use VERSION_SAFE_STEAM_API_INTERFACES, then you can use SteamAPI_Init() and the SteamXXXX()
|
||||
// If you don't use VERSION_SAFE_STEAM_API_INTERFACES, then you can use SteamAPI_Init() and the SteamXXXX()
|
||||
// functions below to get at the Steam interfaces.
|
||||
//
|
||||
#ifdef VERSION_SAFE_STEAM_API_INTERFACES
|
||||
@ -132,7 +131,7 @@ S_API ISteamPS3OverlayRender * SteamPS3OverlayRender();
|
||||
//----------------------------------------------------------------------------------------------------------------------------------------------------------//
|
||||
// steam callback helper functions
|
||||
//
|
||||
// The following classes/macros are used to be able to easily multiplex callbacks
|
||||
// The following classes/macros are used to be able to easily multiplex callbacks
|
||||
// from the Steam API into various objects in the app in a thread-safe manner
|
||||
//
|
||||
// These functors are triggered via the SteamAPI_RunCallbacks() function, mapping the callback
|
||||
@ -152,7 +151,7 @@ S_API void SteamAPI_UnregisterCallResult( class CCallbackBase *pCallback, SteamA
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: base for callbacks,
|
||||
// Purpose: base for callbacks,
|
||||
// used only by CCallback, shouldn't be used directly
|
||||
//-----------------------------------------------------------------------------
|
||||
class CCallbackBase
|
||||
@ -221,7 +220,7 @@ public:
|
||||
SteamAPI_UnregisterCallResult( this, m_hAPICall );
|
||||
m_hAPICall = k_uAPICallInvalid;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
~CCallResult()
|
||||
@ -234,14 +233,14 @@ private:
|
||||
virtual void Run( void *pvParam )
|
||||
{
|
||||
m_hAPICall = k_uAPICallInvalid; // caller unregisters for us
|
||||
(m_pObj->*m_Func)( (P *)pvParam, false );
|
||||
(m_pObj->*m_Func)( (P *)pvParam, false );
|
||||
}
|
||||
void Run( void *pvParam, bool bIOFailure, SteamAPICall_t hSteamAPICall )
|
||||
{
|
||||
if ( hSteamAPICall == m_hAPICall )
|
||||
{
|
||||
m_hAPICall = k_uAPICallInvalid; // caller unregisters for us
|
||||
(m_pObj->*m_Func)( (P *)pvParam, bIOFailure );
|
||||
(m_pObj->*m_Func)( (P *)pvParam, bIOFailure );
|
||||
}
|
||||
}
|
||||
int GetCallbackSizeBytes()
|
||||
@ -271,7 +270,7 @@ public:
|
||||
// ::Register() for your object
|
||||
// Or, just call the regular constructor with (NULL, NULL)
|
||||
// CCallback() {}
|
||||
|
||||
|
||||
// constructor for initializing this object in owner's constructor
|
||||
CCallback( T *pObj, func_t func ) : m_pObj( pObj ), m_Func( func )
|
||||
{
|
||||
@ -301,13 +300,23 @@ public:
|
||||
m_pObj = pObj;
|
||||
m_Func = func;
|
||||
// SteamAPI_RegisterCallback sets k_ECallbackFlagsRegistered
|
||||
|
||||
#ifdef REHLDS_SELF
|
||||
CRehldsPlatformHolder::get()->SteamAPI_RegisterCallback(this, P::k_iCallback);
|
||||
#else
|
||||
SteamAPI_RegisterCallback(this, P::k_iCallback);
|
||||
#endif // REHLDS_SELF
|
||||
}
|
||||
|
||||
void Unregister()
|
||||
{
|
||||
// SteamAPI_UnregisterCallback removes k_ECallbackFlagsRegistered
|
||||
|
||||
#ifdef REHLDS_SELF
|
||||
CRehldsPlatformHolder::get()->SteamAPI_UnregisterCallback(this);
|
||||
#else
|
||||
SteamAPI_UnregisterCallback(this);
|
||||
#endif // REHLDS_SELF
|
||||
}
|
||||
|
||||
void SetGameserverFlag() { m_nCallbackFlags |= k_ECallbackFlagsGameServer; }
|
||||
@ -380,7 +389,7 @@ S_API HSteamUser GetHSteamUser();
|
||||
|
||||
#ifdef VERSION_SAFE_STEAM_API_INTERFACES
|
||||
//----------------------------------------------------------------------------------------------------------------------------------------------------------//
|
||||
// VERSION_SAFE_STEAM_API_INTERFACES uses CSteamAPIContext to provide interfaces to each module in a way that
|
||||
// VERSION_SAFE_STEAM_API_INTERFACES uses CSteamAPIContext to provide interfaces to each module in a way that
|
||||
// lets them each specify the interface versions they are compiled with.
|
||||
//
|
||||
// It's important that these stay inlined in the header so the calling module specifies the interface versions
|
||||
@ -488,7 +497,7 @@ inline bool CSteamAPIContext::Init()
|
||||
m_pSteamUserStats = SteamClient()->GetISteamUserStats( hSteamUser, hSteamPipe, STEAMUSERSTATS_INTERFACE_VERSION );
|
||||
if ( !m_pSteamUserStats )
|
||||
return false;
|
||||
|
||||
|
||||
m_pSteamApps = SteamClient()->GetISteamApps( hSteamUser, hSteamPipe, STEAMAPPS_INTERFACE_VERSION );
|
||||
if ( !m_pSteamApps )
|
||||
return false;
|
||||
|
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/bzip2'
|
||||
include 'rehlds'
|
||||
include 'rehlds/dedicated'
|
||||
include 'flightrec/decoder_api', 'flightrec/decoder'
|
||||
|
Loading…
x
Reference in New Issue
Block a user