Files
funnygame/game/server/entitysystem.cpp
2026-03-16 15:35:31 +02:00

295 lines
6.4 KiB
C++

//================= Copyright kotofyt, All rights reserved ==================//
//
// Purpose:
//
//===========================================================================//
#include "entitysystem.h"
#include "baseentity.h"
#include "stddef.h"
#include "string.h"
#include "stdlib.h"
#include "game.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, int *pOutputIndex )
{
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++;
if (pOutputIndex)
*pOutputIndex = iSelectedSlot;
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), 0, PACKET_MUST_ARRIVE});
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( float fDelta )
{
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)(fDelta);
}
}
static void *UTIL_GetNetMapData( CBaseEntity *pEntity, netmap_t *pMap, uint32_t uIndex )
{
netmap_t *pCurrentMap = pMap;
uint32_t uCurrentIndex = uIndex;
searchIndex:
if ( pCurrentMap )
{
if (uCurrentIndex >= pCurrentMap->m_uFieldCount)
{
uCurrentIndex -= pCurrentMap->m_uFieldCount;
pCurrentMap = pCurrentMap->m_pBase;
goto searchIndex;
}
return (char*)pEntity+pCurrentMap->m_pFields[uCurrentIndex].m_uOffset;
}
return NULL;
}
void CEntitySystem::NetRecvPacket( NetPacket_t *pPacket )
{
PlayerPacket_t *pPlayerPacket = (PlayerPacket_t*)pPacket->pData;
CBaseEntity *pEntity;
switch (pPlayerPacket->m_eType)
{
case MESSAGE_ENTITY_DATA_SYNC:
if ( pPlayerPacket->m_entityData.m_uIndex >= MAX_EDICTS )
break;
pEntity = m_pEntities[pPlayerPacket->m_entityData.m_uIndex];
// check for owner being moron
if ( pEntity == NULL )
break;
if ( pEntity->m_ullOwner != pPacket->m_uOwner)
break;
union {
void *pData;
char *pcCurrentData;
EntityDataSyncValue_t *pcSyncValue;
};
pData = pPlayerPacket;
pcCurrentData += sizeof(EntityDataSync_t);
// too bad
// this shall be reworked
for ( uint32_t u = 0; u < pPlayerPacket->m_entityData.m_uCount; u++ )
{
uint32_t uVariableSize = pcSyncValue->m_uVariableSize;
void *pValueData = (float*)UTIL_GetNetMapData(
pEntity,
pEntity->GetRecvMap(),
pcSyncValue->m_uVariableIndex);
pcCurrentData += sizeof(EntityDataSyncValue_t);
if (pValueData)
V_memcpy(pValueData, pcCurrentData, uVariableSize);
pcCurrentData += (uVariableSize+7) & ~7;
}
break;
default:
break;
}
}
//-------------------------------------------------------------------------------
// Purpose: Sends packets to clients.
// Since we are running this on server we can't really accept any packet.
// We only allow packets from the entities sent by a client
//-------------------------------------------------------------------------------
void CEntitySystem::NetSendThink( 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;
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);
//if (pNetMap->m_pFields[u].m_eType == FIELD_STRING)
//V_printf("v: %s %u\n", pcCurrentData, pNetMap->m_pFields[u].m_uSize);
pcCurrentData += (pNetMap->m_pFields[u].m_uSize+7) & ~7;
x++;
}
pNetMap = pNetMap->m_pBase;
}
if (pBase)
pBase->SendPacket({pData, uSize});
V_free(pData);
}
}
CBaseEntity **CEntitySystem::GetEntities()
{
return m_pEntities;
}
void CEntitySystem::SetAllowedEntityForPlayer( uint64_t ullPlayer, CBaseEntity *pEntity )
{
if (pEntity)
{
}
else
{
}
}