207 lines
4.2 KiB
C++
207 lines
4.2 KiB
C++
//================= Copyright kotofyt, All rights reserved ==================//
|
|
//
|
|
// Purpose:
|
|
//
|
|
//===========================================================================//
|
|
|
|
#include "entitysystem.h"
|
|
#include "baseentity.h"
|
|
#include "stddef.h"
|
|
#include "string.h"
|
|
#include "stdlib.h"
|
|
#include "engine.h"
|
|
#include "netprotocol.h"
|
|
|
|
|
|
CEntitySystem *EntitySystem()
|
|
{
|
|
static CEntitySystem s_entitySystem;
|
|
return &s_entitySystem;
|
|
}
|
|
|
|
static struct EntityRegistry_t
|
|
{
|
|
IEntityFactory *m_pFactory;
|
|
const char *m_szClassName;
|
|
struct EntityRegistry_t *m_pNext;
|
|
} *s_pEntitiesRegistry = NULL;
|
|
|
|
CEntitySystem::CEntitySystem()
|
|
{
|
|
int i = 0;
|
|
for ( i = 0; i < MAX_EDICTS; i++ )
|
|
{
|
|
m_pEntities[i] = NULL;
|
|
}
|
|
m_nEntityCount = 0;
|
|
}
|
|
|
|
void CEntitySystem::RegisterEntityClass( IEntityFactory *pEntityFactory, const char *szClassName )
|
|
{
|
|
IEntityFactory *pFactory;
|
|
EntityRegistry_t *pRegistry;
|
|
|
|
pFactory = GetFactoryByClassname(szClassName);
|
|
|
|
if ( pFactory != NULL )
|
|
{
|
|
// Already registered
|
|
return;
|
|
}
|
|
|
|
pRegistry = new EntityRegistry_t;
|
|
pRegistry->m_pFactory = pEntityFactory;
|
|
pRegistry->m_pNext = s_pEntitiesRegistry;
|
|
pRegistry->m_szClassName = szClassName;
|
|
s_pEntitiesRegistry = pRegistry;
|
|
}
|
|
|
|
CBaseEntity *CEntitySystem::CreateByClassname( const char *szName )
|
|
{
|
|
IEntityFactory *pFactory;
|
|
CBaseEntity *pEntity;
|
|
int i;
|
|
int iSelectedSlot;
|
|
|
|
pFactory = GetFactoryByClassname(szName);
|
|
if ( !pFactory )
|
|
return NULL;
|
|
|
|
// We do not want to have more than MAX_EDICT entities
|
|
if ( m_nEntityCount >= MAX_EDICTS-1 )
|
|
return NULL;
|
|
|
|
// Search for space
|
|
// Could be more efficient but nobody cares
|
|
for ( i = 0; i < MAX_EDICTS; i++ )
|
|
{
|
|
if ( m_pEntities[i] == NULL )
|
|
{
|
|
iSelectedSlot = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
pEntity = pFactory->Create();
|
|
pEntity->m_szClassName = szName;
|
|
m_pEntities[iSelectedSlot] = pEntity;
|
|
m_nEntityCount++;
|
|
|
|
EntityClass_t stClassSync = {
|
|
MESSAGE_ENTITY_CLASS_SYNC,
|
|
iSelectedSlot,
|
|
};
|
|
V_strncpy((char*)stClassSync.m_szEntityName, szName, 256);
|
|
if (g_pCurrentConnection)
|
|
g_pCurrentConnection->SendPacket({&stClassSync, sizeof(stClassSync)});
|
|
return pEntity;
|
|
}
|
|
IEntityFactory *CEntitySystem::GetFactoryByClassname( const char *szName )
|
|
{
|
|
EntityRegistry_t *pEntity;
|
|
|
|
for ( pEntity = s_pEntitiesRegistry; pEntity; pEntity = pEntity->m_pNext )
|
|
{
|
|
if (!strcmp(szName, pEntity->m_szClassName))
|
|
{
|
|
return pEntity->m_pFactory;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
void CEntitySystem::Think()
|
|
{
|
|
CBaseEntity *pEntity;
|
|
int i;
|
|
|
|
for ( i = 0; i < MAX_EDICTS; i++ )
|
|
{
|
|
|
|
pEntity = m_pEntities[i];
|
|
if ( pEntity == NULL )
|
|
continue;
|
|
|
|
if ( !pEntity->m_pfnThink )
|
|
continue;
|
|
|
|
(pEntity->*pEntity->m_pfnThink)(0);
|
|
}
|
|
}
|
|
|
|
void CEntitySystem::NetThink( INetworkBase *pBase )
|
|
{
|
|
|
|
CBaseEntity *pEntity;
|
|
int i;
|
|
uint32_t u;
|
|
uint32_t x;
|
|
uint32_t uSize;
|
|
netmap_t *pNetMap;
|
|
void *pData;
|
|
union {
|
|
void *pCurrentData;
|
|
char *pcCurrentData;
|
|
EntityDataSync_t *pSync;
|
|
EntityDataSyncValue_t *pValue;
|
|
};
|
|
|
|
for ( i = 0; i < MAX_EDICTS; i++ )
|
|
{
|
|
pEntity = m_pEntities[i];
|
|
if ( pEntity == NULL )
|
|
continue;
|
|
|
|
if ( !pEntity->m_pfnThink )
|
|
continue;
|
|
|
|
pNetMap = pEntity->GetSendMap();
|
|
uSize = sizeof(EntityDataSyncValue_t);
|
|
x = 0;
|
|
while ( pNetMap )
|
|
{
|
|
for ( u = 0; u < pNetMap->m_uFieldCount; u++ )
|
|
{
|
|
x++;
|
|
uSize += (pNetMap->m_pFields[u].m_uSize+7) & ~7;
|
|
uSize += sizeof(EntityDataSyncValue_t);
|
|
}
|
|
pNetMap = pNetMap->m_pBase;
|
|
}
|
|
pData = V_malloc(uSize);
|
|
V_memset(pData, 0, uSize);
|
|
pCurrentData = pData;
|
|
pSync->m_eType = MESSAGE_ENTITY_DATA_SYNC;
|
|
pSync->m_uIndex = i;
|
|
pSync->m_uCount = x;
|
|
|
|
pcCurrentData += sizeof(EntityDataSync_t);
|
|
pNetMap = pEntity->GetSendMap();
|
|
x = 0;
|
|
while ( pNetMap )
|
|
{
|
|
for ( u = 0; u < pNetMap->m_uFieldCount; u++ )
|
|
{
|
|
pValue->m_uVariableSize = pNetMap->m_pFields[u].m_uSize;
|
|
pValue->m_uVariableIndex = x;
|
|
uint32_t uVariableSize;
|
|
pcCurrentData += sizeof(EntityDataSyncValue_t);
|
|
V_memcpy(pcCurrentData,
|
|
pNetMap->m_pFields[u].m_uOffset+(char*)pEntity,
|
|
pNetMap->m_pFields[u].m_uSize);
|
|
pcCurrentData += (pNetMap->m_pFields[u].m_uSize+7) & ~7;
|
|
x++;
|
|
}
|
|
pNetMap = pNetMap->m_pBase;
|
|
}
|
|
if (g_pCurrentConnection)
|
|
g_pCurrentConnection->SendPacket({pData, uSize});
|
|
V_free(pData);
|
|
|
|
}
|
|
}
|
|
|
|
CBaseEntity **CEntitySystem::GetEntities()
|
|
{
|
|
return m_pEntities;
|
|
}
|