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

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $Workfile: $
  6. // $Date: $
  7. //
  8. //-----------------------------------------------------------------------------
  9. // $Log: $
  10. //
  11. // $NoKeywords: $
  12. //=============================================================================//
  13. #if !defined( CLIENT_CLASS_H )
  14. #define CLIENT_CLASS_H
  15. #ifdef _WIN32
  16. #pragma once
  17. #endif
  18. #include "interface.h"
  19. #include "dt_recv.h"
  20. //-----------------------------------------------------------------------------
  21. // forward declarations
  22. //-----------------------------------------------------------------------------
  23. class Vector;
  24. class CMouthInfo;
  25. //-----------------------------------------------------------------------------
  26. // represents a handle used only by the client DLL
  27. //-----------------------------------------------------------------------------
  28. #include "iclientrenderable.h"
  29. #include "iclientnetworkable.h"
  30. class ClientClass;
  31. // Linked list of all known client classes
  32. extern ClientClass *g_pClientClassHead;
  33. // The serial number that gets passed in is used for ehandles.
  34. typedef IClientNetworkable* (*CreateClientClassFn)( int entnum, int serialNum );
  35. typedef IClientNetworkable* (*CreateEventFn)();
  36. //-----------------------------------------------------------------------------
  37. // Purpose: Client side class definition
  38. //-----------------------------------------------------------------------------
  39. class ClientClass
  40. {
  41. public:
  42. ClientClass( const char *pNetworkName, CreateClientClassFn createFn, CreateEventFn createEventFn, RecvTable *pRecvTable )
  43. {
  44. m_pNetworkName = pNetworkName;
  45. m_pCreateFn = createFn;
  46. m_pCreateEventFn= createEventFn;
  47. m_pRecvTable = pRecvTable;
  48. // Link it in
  49. m_pNext = g_pClientClassHead;
  50. g_pClientClassHead = this;
  51. }
  52. const char* GetName()
  53. {
  54. return m_pNetworkName;
  55. }
  56. public:
  57. CreateClientClassFn m_pCreateFn;
  58. CreateEventFn m_pCreateEventFn; // Only called for event objects.
  59. const char *m_pNetworkName;
  60. RecvTable *m_pRecvTable;
  61. ClientClass *m_pNext;
  62. int m_ClassID; // Managed by the engine.
  63. };
  64. #define DECLARE_CLIENTCLASS() \
  65. virtual int YouForgotToImplementOrDeclareClientClass();\
  66. virtual ClientClass* GetClientClass();\
  67. static RecvTable *m_pClassRecvTable; \
  68. DECLARE_CLIENTCLASS_NOBASE()
  69. // This can be used to give all datatables access to protected and private members of the class.
  70. #define ALLOW_DATATABLES_PRIVATE_ACCESS() \
  71. template <typename T> friend int ClientClassInit(T *);
  72. #define DECLARE_CLIENTCLASS_NOBASE ALLOW_DATATABLES_PRIVATE_ACCESS
  73. // This macro adds a ClientClass to the linked list in g_pClientClassHead (so
  74. // the list can be given to the engine).
  75. // Use this macro to expose your client class to the engine.
  76. // networkName must match the network name of a class registered on the server.
  77. #define IMPLEMENT_CLIENTCLASS(clientClassName, dataTable, serverClassName) \
  78. INTERNAL_IMPLEMENT_CLIENTCLASS_PROLOGUE(clientClassName, dataTable, serverClassName) \
  79. static IClientNetworkable* _##clientClassName##_CreateObject( int entnum, int serialNum ) \
  80. { \
  81. clientClassName *pRet = new clientClassName; \
  82. if ( !pRet ) \
  83. return 0; \
  84. pRet->Init( entnum, serialNum ); \
  85. return pRet; \
  86. } \
  87. ClientClass __g_##clientClassName##ClientClass(#serverClassName, \
  88. _##clientClassName##_CreateObject, \
  89. NULL,\
  90. &dataTable::g_RecvTable);
  91. // Implement a client class and provide a factory so you can allocate and delete it yourself
  92. // (or make it a singleton).
  93. #define IMPLEMENT_CLIENTCLASS_FACTORY(clientClassName, dataTable, serverClassName, factory) \
  94. INTERNAL_IMPLEMENT_CLIENTCLASS_PROLOGUE(clientClassName, dataTable, serverClassName) \
  95. ClientClass __g_##clientClassName##ClientClass(#serverClassName, \
  96. factory, \
  97. NULL,\
  98. &dataTable::g_RecvTable);
  99. // The IMPLEMENT_CLIENTCLASS_DT macros do IMPLEMENT_CLIENT_CLASS and also do BEGIN_RECV_TABLE.
  100. #define IMPLEMENT_CLIENTCLASS_DT(clientClassName, dataTable, serverClassName)\
  101. IMPLEMENT_CLIENTCLASS(clientClassName, dataTable, serverClassName)\
  102. BEGIN_RECV_TABLE(clientClassName, dataTable)
  103. #define IMPLEMENT_CLIENTCLASS_DT_NOBASE(clientClassName, dataTable, serverClassName)\
  104. IMPLEMENT_CLIENTCLASS(clientClassName, dataTable, serverClassName)\
  105. BEGIN_RECV_TABLE_NOBASE(clientClassName, dataTable)
  106. // Using IMPLEMENT_CLIENTCLASS_EVENT means the engine thinks the entity is an event so the entity
  107. // is responsible for freeing itself.
  108. #define IMPLEMENT_CLIENTCLASS_EVENT(clientClassName, dataTable, serverClassName)\
  109. INTERNAL_IMPLEMENT_CLIENTCLASS_PROLOGUE(clientClassName, dataTable, serverClassName)\
  110. static clientClassName __g_##clientClassName; \
  111. static IClientNetworkable* _##clientClassName##_CreateObject() {return &__g_##clientClassName;}\
  112. ClientClass __g_##clientClassName##ClientClass(#serverClassName, \
  113. NULL,\
  114. _##clientClassName##_CreateObject, \
  115. &dataTable::g_RecvTable);
  116. #define IMPLEMENT_CLIENTCLASS_EVENT_DT(clientClassName, dataTable, serverClassName)\
  117. namespace dataTable {extern RecvTable g_RecvTable;}\
  118. IMPLEMENT_CLIENTCLASS_EVENT(clientClassName, dataTable, serverClassName)\
  119. BEGIN_RECV_TABLE(clientClassName, dataTable)
  120. // Register a client event singleton but specify a pointer to give to the engine rather than
  121. // have a global instance. This is useful if you're using Initializers and your object's constructor
  122. // uses some other global object (so you must use Initializers so you're constructed afterwards).
  123. #define IMPLEMENT_CLIENTCLASS_EVENT_POINTER(clientClassName, dataTable, serverClassName, ptr)\
  124. INTERNAL_IMPLEMENT_CLIENTCLASS_PROLOGUE(clientClassName, dataTable, serverClassName)\
  125. static IClientNetworkable* _##clientClassName##_CreateObject() {return ptr;}\
  126. ClientClass __g_##clientClassName##ClientClass(#serverClassName, \
  127. NULL,\
  128. _##clientClassName##_CreateObject, \
  129. &dataTable::g_RecvTable);
  130. #define IMPLEMENT_CLIENTCLASS_EVENT_NONSINGLETON(clientClassName, dataTable, serverClassName)\
  131. static IClientNetworkable* _##clientClassName##_CreateObject() \
  132. { \
  133. clientClassName *p = new clientClassName; \
  134. if ( p ) \
  135. p->Init( -1, 0 ); \
  136. return p; \
  137. } \
  138. ClientClass __g_##clientClassName##ClientClass(#serverClassName, \
  139. NULL,\
  140. _##clientClassName##_CreateObject, \
  141. &dataTable::g_RecvTable);
  142. // Used internally..
  143. #define INTERNAL_IMPLEMENT_CLIENTCLASS_PROLOGUE(clientClassName, dataTable, serverClassName) \
  144. namespace dataTable {extern RecvTable g_RecvTable;}\
  145. extern ClientClass __g_##clientClassName##ClientClass;\
  146. RecvTable* clientClassName::m_pClassRecvTable = &dataTable::g_RecvTable;\
  147. int clientClassName::YouForgotToImplementOrDeclareClientClass() {return 0;}\
  148. ClientClass* clientClassName::GetClientClass() {return &__g_##clientClassName##ClientClass;}
  149. #endif // CLIENT_CLASS_H