This repository has been archived on 2024-06-13. You can view files and clone it, but cannot push or open issues or pull requests.
2020-08-04 13:13:01 -04:00

156 lines
8.0 KiB
C++

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#if !defined(CLIENT_CLASS_H)
#define CLIENT_CLASS_H
#if defined(_WIN32) && !defined(__GNUG__)
#pragma once
#endif
#include "dt_recv.h"
#include "tier1/interface.h"
//-----------------------------------------------------------------------------
// forward declarations
//-----------------------------------------------------------------------------
class Vector;
class CMouthInfo;
//-----------------------------------------------------------------------------
// represents a handle used only by the client DLL
//-----------------------------------------------------------------------------
#include "iclientnetworkable.h"
#include "iclientrenderable.h"
class ClientClass;
// Linked list of all known client classes
extern ClientClass* g_pClientClassHead;
#define DECLARE_CLIENTCLASS() \
virtual int YouForgotToImplementOrDeclareClientClass(); \
virtual ClientClass* GetClientClass(); \
static RecvTable* m_pClassRecvTable; \
DECLARE_CLIENTCLASS_NOBASE()
// This can be used to give all datatables access to protected and private
// members of the class.
#define ALLOW_DATATABLES_PRIVATE_ACCESS() \
template <typename T> \
friend int ClientClassInit(T*);
#define DECLARE_CLIENTCLASS_NOBASE ALLOW_DATATABLES_PRIVATE_ACCESS
// This macro adds a ClientClass to the linked list in g_pClientClassHead (so
// the list can be given to the engine).
// Use this macro to expose your client class to the engine.
// networkName must match the network name of a class registered on the server.
#define IMPLEMENT_CLIENTCLASS(clientClassName, dataTable, serverClassName) \
INTERNAL_IMPLEMENT_CLIENTCLASS_PROLOGUE(clientClassName, dataTable, \
serverClassName) \
static IClientNetworkable* _##clientClassName##_CreateObject( \
int entnum, int serialNum) { \
clientClassName* pRet = new clientClassName; \
if (!pRet) return 0; \
pRet->Init(entnum, serialNum); \
return pRet; \
} \
ClientClass __g_##clientClassName##ClientClass( \
#serverClassName, _##clientClassName##_CreateObject, NULL, \
&dataTable::g_RecvTable);
// Implement a client class and provide a factory so you can allocate and delete
// it yourself (or make it a singleton).
#define IMPLEMENT_CLIENTCLASS_FACTORY(clientClassName, dataTable, \
serverClassName, factory) \
INTERNAL_IMPLEMENT_CLIENTCLASS_PROLOGUE(clientClassName, dataTable, \
serverClassName) \
ClientClass __g_##clientClassName##ClientClass( \
#serverClassName, factory, NULL, &dataTable::g_RecvTable);
// The IMPLEMENT_CLIENTCLASS_DT macros do IMPLEMENT_CLIENT_CLASS and also do
// BEGIN_RECV_TABLE.
#define IMPLEMENT_CLIENTCLASS_DT(clientClassName, dataTable, serverClassName) \
IMPLEMENT_CLIENTCLASS(clientClassName, dataTable, serverClassName) \
BEGIN_RECV_TABLE(clientClassName, dataTable)
#define IMPLEMENT_CLIENTCLASS_DT_NOBASE(clientClassName, dataTable, \
serverClassName) \
IMPLEMENT_CLIENTCLASS(clientClassName, dataTable, serverClassName) \
BEGIN_RECV_TABLE_NOBASE(clientClassName, dataTable)
// Using IMPLEMENT_CLIENTCLASS_EVENT means the engine thinks the entity is an
// event so the entity is responsible for freeing itself.
#define IMPLEMENT_CLIENTCLASS_EVENT(clientClassName, dataTable, \
serverClassName) \
INTERNAL_IMPLEMENT_CLIENTCLASS_PROLOGUE(clientClassName, dataTable, \
serverClassName) \
static clientClassName __g_##clientClassName; \
static IClientNetworkable* _##clientClassName##_CreateObject() { \
return &__g_##clientClassName; \
} \
ClientClass __g_##clientClassName##ClientClass( \
#serverClassName, NULL, _##clientClassName##_CreateObject, \
&dataTable::g_RecvTable);
#define IMPLEMENT_CLIENTCLASS_EVENT_DT(clientClassName, dataTable, \
serverClassName) \
namespace dataTable { \
extern RecvTable g_RecvTable; \
} \
IMPLEMENT_CLIENTCLASS_EVENT(clientClassName, dataTable, serverClassName) \
BEGIN_RECV_TABLE(clientClassName, dataTable)
// Register a client event singleton but specify a pointer to give to the engine
// rather than have a global instance. This is useful if you're using
// Initializers and your object's constructor uses some other global object (so
// you must use Initializers so you're constructed afterwards).
#define IMPLEMENT_CLIENTCLASS_EVENT_POINTER(clientClassName, dataTable, \
serverClassName, ptr) \
INTERNAL_IMPLEMENT_CLIENTCLASS_PROLOGUE(clientClassName, dataTable, \
serverClassName) \
static IClientNetworkable* _##clientClassName##_CreateObject() { \
return ptr; \
} \
ClientClass __g_##clientClassName##ClientClass( \
#serverClassName, NULL, _##clientClassName##_CreateObject, \
&dataTable::g_RecvTable);
#define IMPLEMENT_CLIENTCLASS_EVENT_NONSINGLETON(clientClassName, dataTable, \
serverClassName) \
static IClientNetworkable* _##clientClassName##_CreateObject() { \
clientClassName* p = new clientClassName; \
if (p) p->Init(-1, 0); \
return p; \
} \
ClientClass __g_##clientClassName##ClientClass( \
#serverClassName, NULL, _##clientClassName##_CreateObject, \
&dataTable::g_RecvTable);
// Used internally..
#define INTERNAL_IMPLEMENT_CLIENTCLASS_PROLOGUE(clientClassName, dataTable, \
serverClassName) \
namespace dataTable { \
extern RecvTable g_RecvTable; \
} \
extern ClientClass __g_##clientClassName##ClientClass; \
RecvTable* clientClassName::m_pClassRecvTable = &dataTable::g_RecvTable; \
int clientClassName::YouForgotToImplementOrDeclareClientClass() { \
return 0; \
} \
ClientClass* clientClassName::GetClientClass() { \
return &__g_##clientClassName##ClientClass; \
}
#endif // CLIENT_CLASS_H