2
0
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:
s1lent 2017-02-14 00:45:46 +07:00
parent 713eb77e9e
commit 3bf374d298
58 changed files with 5390 additions and 41 deletions

2
.gitignore vendored
View File

@ -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

View File

@ -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

View 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;
}

View 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

View 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

View 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

View 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

View 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

View 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

View 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;
}

View 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

View 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);
}

View 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

View 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

View 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

View 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)

View 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

View 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)

View 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
View 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
View 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
View 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
View 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

View 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++;
}

View 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

View 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'
}
}

View 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

Binary file not shown.

View 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

View 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>

View 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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

View 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;
}

View 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);
}

View 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

View 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;
// }
//}
}

View 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

View 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

View 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);
}

View 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

View 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

View File

@ -0,0 +1 @@
#include "precompiled.h"

View 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

View 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"

View 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;
}

View 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

View 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;
}

View 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;
}

View 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);
}*/
}

View 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);

View File

@ -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)
{

View File

@ -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)

View File

@ -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;

View File

@ -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:

View File

@ -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
View 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

View File

@ -2,4 +2,5 @@ rootProject.name = 'rehlds'
include 'dep/cppunitlite'
include 'dep/bzip2'
include 'rehlds'
include 'rehlds/dedicated'
include 'flightrec/decoder_api', 'flightrec/decoder'