//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ // //=============================================================================// #ifndef SERVER_CLASS_H #define SERVER_CLASS_H #ifdef _WIN32 #pragma once #endif #include "dt_send.h" #include "networkstringtabledefs.h" #include "tier0/dbg.h" class ServerClass; class SendTable; extern ServerClass *g_pServerClassHead; class ServerClass { public: ServerClass(const char *pNetworkName, SendTable *pTable) { m_pNetworkName = pNetworkName; m_pTable = pTable; m_InstanceBaselineIndex = INVALID_STRING_INDEX; // g_pServerClassHead is sorted alphabetically, so find the correct // place to insert if (!g_pServerClassHead) { g_pServerClassHead = this; m_pNext = NULL; } else { ServerClass *p1 = g_pServerClassHead; ServerClass *p2 = p1->m_pNext; // use _stricmp because Q_stricmp isn't hooked up properly yet if (_stricmp(p1->GetName(), pNetworkName) > 0) { m_pNext = g_pServerClassHead; g_pServerClassHead = this; p1 = NULL; } while (p1) { if (p2 == NULL || _stricmp(p2->GetName(), pNetworkName) > 0) { m_pNext = p2; p1->m_pNext = this; break; } p1 = p2; p2 = p2->m_pNext; } } } const char *GetName() { return m_pNetworkName; } public: const char *m_pNetworkName; SendTable *m_pTable; ServerClass *m_pNext; int m_ClassID; // Managed by the engine. // This is an index into the network string table // (sv.GetInstanceBaselineTable()). int m_InstanceBaselineIndex; // INVALID_STRING_INDEX if not initialized // yet. }; class CBaseNetworkable; // If you do a DECLARE_SERVERCLASS, you need to do this inside the class // definition. #define DECLARE_SERVERCLASS() \ public: \ virtual ServerClass *GetServerClass(); \ static SendTable *m_pClassSendTable; \ template \ friend int ServerClassInit(T *); \ virtual int YouForgotToImplementOrDeclareServerClass(); #define DECLARE_SERVERCLASS_NOBASE() \ public: \ template \ friend int ServerClassInit(T *); // Use this macro to expose your class's data across the network. #define IMPLEMENT_SERVERCLASS(DLLClassName, sendTable) \ IMPLEMENT_SERVERCLASS_INTERNAL(DLLClassName, sendTable) // You can use this instead of BEGIN_SEND_TABLE and it will do a // DECLARE_SERVERCLASS automatically. #define IMPLEMENT_SERVERCLASS_ST(DLLClassName, sendTable) \ IMPLEMENT_SERVERCLASS_INTERNAL(DLLClassName, sendTable) \ BEGIN_SEND_TABLE(DLLClassName, sendTable) #define IMPLEMENT_SERVERCLASS_ST_NOBASE(DLLClassName, sendTable) \ IMPLEMENT_SERVERCLASS_INTERNAL(DLLClassName, sendTable) \ BEGIN_SEND_TABLE_NOBASE(DLLClassName, sendTable) #ifdef VALIDATE_DECLARE_CLASS #define CHECK_DECLARE_CLASS(DLLClassName, sendTable) \ template \ int CheckDeclareClass_Access(T *); \ template <> \ int CheckDeclareClass_Access(sendTable::ignored *, \ const char *pIgnored) { \ return DLLClassName::CheckDeclareClass(#DLLClassName); \ } \ namespace sendTable { \ int verifyDeclareClass = \ CheckDeclareClass_Access((sendTable::ignored *)0); \ } #else #define CHECK_DECLARE_CLASS(DLLClassName, sendTable) #endif #define IMPLEMENT_SERVERCLASS_INTERNAL(DLLClassName, sendTable) \ namespace sendTable { \ struct ignored; \ extern SendTable g_SendTable; \ } \ CHECK_DECLARE_CLASS(DLLClassName, sendTable) \ static ServerClass g_##DLLClassName##_ClassReg(#DLLClassName, \ &sendTable::g_SendTable); \ \ ServerClass *DLLClassName::GetServerClass() { \ return &g_##DLLClassName##_ClassReg; \ } \ SendTable *DLLClassName::m_pClassSendTable = &sendTable::g_SendTable; \ int DLLClassName::YouForgotToImplementOrDeclareServerClass() { return 0; } #endif