Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

180 lines
6.8 KiB

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#if !defined( CLIENT_CLASS_H )
#define CLIENT_CLASS_H
#ifdef _WIN32
#pragma once
#endif
#include "interface.h"
#include "dt_recv.h"
//-----------------------------------------------------------------------------
// forward declarations
//-----------------------------------------------------------------------------
class Vector;
class CMouthInfo;
//-----------------------------------------------------------------------------
// represents a handle used only by the client DLL
//-----------------------------------------------------------------------------
#include "iclientrenderable.h"
#include "iclientnetworkable.h"
class ClientClass;
// Linked list of all known client classes
extern ClientClass *g_pClientClassHead;
// The serial number that gets passed in is used for ehandles.
typedef IClientNetworkable* (*CreateClientClassFn)( int entnum, int serialNum );
typedef IClientNetworkable* (*CreateEventFn)();
//-----------------------------------------------------------------------------
// Purpose: Client side class definition
//-----------------------------------------------------------------------------
class ClientClass
{
public:
ClientClass( const char *pNetworkName, CreateClientClassFn createFn, CreateEventFn createEventFn, RecvTable *pRecvTable )
{
m_pNetworkName = pNetworkName;
m_pCreateFn = createFn;
m_pCreateEventFn= createEventFn;
m_pRecvTable = pRecvTable;
// Link it in
m_pNext = g_pClientClassHead;
g_pClientClassHead = this;
}
const char* GetName()
{
return m_pNetworkName;
}
public:
CreateClientClassFn m_pCreateFn;
CreateEventFn m_pCreateEventFn; // Only called for event objects.
const char *m_pNetworkName;
RecvTable *m_pRecvTable;
ClientClass *m_pNext;
int m_ClassID; // Managed by the engine.
};
#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