diff options
Diffstat (limited to 'src/libparsec/e_relist.cpp')
| -rw-r--r-- | src/libparsec/e_relist.cpp | 1027 |
1 files changed, 1027 insertions, 0 deletions
diff --git a/src/libparsec/e_relist.cpp b/src/libparsec/e_relist.cpp new file mode 100644 index 0000000..14c0f37 --- /dev/null +++ b/src/libparsec/e_relist.cpp @@ -0,0 +1,1027 @@ +/* + * PARSEC - Remote Events handler + * + * $Author: uberlinuxguy $ - $Date: 2004/09/26 03:43:43 $ + * + * Orginally written by: + * Copyright (c) Clemens Beer <cbx@parsec.org> 2001-2002 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// C library +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +// compilation flags/debug support +#include "config.h" +#include "debug.h" + +// general definitions +#include "general.h" +#include "objstruc.h" + +// global externals +#include "globals.h" + +// subsystem headers +#include "net_defs.h" + +// mathematics header +#include "utl_math.h" + +#ifdef PARSEC_SERVER + + // server defs + #include "e_defs.h" + + // net game header + #include "net_game_sv.h" + + // proprietary module headers + #include "con_aux_sv.h" + #include "g_main_sv.h" + #include "obj_creg.h" + #include "e_simplayerinfo.h" + #include "e_simulator.h" + #include "e_gameserver.h" + #include "e_connmanager.h" + +#else + + #include "net_game.h" + +#endif // PARSEC_SERVER + +// local module header +#include "e_relist.h" + + +// table of remote event sizes ------------------------------------------------ +// +static size_t re_sizes[] = { + sizeof( RE_Header ), + sizeof( RE_Header ), + sizeof( RE_CreateObject ), + sizeof( RE_CreateLaser ), + sizeof( RE_CreateMissile ), + sizeof( RE_CreateExtra ), + sizeof( RE_KillObject ), + sizeof( RE_SendText ), + sizeof( RE_PlayerName ), + sizeof( RE_ParticleObject ), + sizeof( RE_PlayerList ), + sizeof( RE_ConnectQueue ), + sizeof( RE_WeaponState ), + sizeof( RE_StateSync ), + sizeof( RE_CreateSwarm ), + sizeof( RE_CreateEmp ), + sizeof( RE_OwnerSection ), + sizeof( RE_PlayerStatus ), + sizeof( RE_PlayerAndShipStatus ), + sizeof( RE_KillStats ), + sizeof( RE_GameState ), + sizeof( RE_CommandInfo ), + sizeof( RE_ClientInfo ), + sizeof( RE_CreateExtra2 ), + sizeof( RE_IPv4ServerInfo ), + sizeof( RE_ServerLinkInfo ), + sizeof( RE_MapObject ), + sizeof( RE_Stargate ), + sizeof( RE_CreateMine), +}; + +// table of remote event sizes ------------------------------------------------ +// +static const char* re_names[] = { + "RE_EMPTY", + "RE_DELETED", + "RE_CREATEOBJECT", + "RE_CREATELASER", + "RE_CREATEMISSILE", + "RE_CREATEEXTRA", + "RE_KILLOBJECT", + "RE_SENDTEXT", + "RE_PLAYERNAME", + "RE_PARTICLEOBJECT", + "RE_PLAYERLIST", + "RE_CONNECTQUEUE", + "RE_WEAPONSTATE", + "RE_STATESYNC", + "RE_CREATESWARM", + "RE_CREATEEMP", + "RE_OWNERSECTION", + "RE_PLAYERSTATUS", + "RE_PLAYERANDSHIPSTATUS", + "RE_KILLSTATS", + "RE_GAMESTATE", + "RE_COMMANDINFO", + "RE_CLIENTINFO", + "RE_CREATEEXTRA2", + "RE_IPV4SERVERINFO", + "RE_SERVERLINKINFO", + "RE_MAPOBJECT", + "RE_STARGATE", + "RE_CREATEMINE", + //FIXME: use NET_UTIL::PrInf_* functions and E_REList::Dump +}; + +// default ctor --------------------------------------------------------------- +// +E_REList::E_REList() +{ + m_data = NULL; + m_nMaxSize = 0; + m_nRefCount = 0; +} + +// ctor with init ------------------------------------------------------------- +// +E_REList::E_REList( size_t size ) +{ + m_data = NULL; + m_nMaxSize = 0; + m_nRefCount = 0; + + Init( size ); +} + +// standard dtor -------------------------------------------------------------- +// +E_REList::~E_REList() +{ + if ( m_data != NULL ) + delete []m_data; +} + +// init the remote event list ------------------------------------------------- +// +void E_REList::Init( size_t nMaxSize ) +{ + ASSERT( nMaxSize > 0 ); + + if ( m_data != NULL ) + delete []m_data; + + m_nMaxSize = nMaxSize; + + // allocate max. size of remote event list + m_data = new char[ nMaxSize ]; + + // initialize the list to empty + ( (RE_Header*) m_data)->RE_Type = RE_EMPTY; + + m_CurPos = m_data; + m_Avail = nMaxSize; + + ASSERT( m_Avail >= 0 ); +} + +// clear remote event list ---------------------------------------------------- +// +int E_REList::Clear() +{ + ASSERT( m_data != NULL ); + ASSERT( m_nMaxSize > 0 ); + + // initialize the list to empty + ( (RE_Header*) m_data)->RE_Type = RE_EMPTY; + + m_CurPos = m_data; + m_Avail = m_nMaxSize; + + ASSERT( m_Avail >= 0 ); + + return TRUE; +} + +// append a E_REList -------------------------------------------------------- +// +int E_REList::AppendList( E_REList* relist ) +{ + ASSERT( relist != NULL ); + return AppendList( (RE_Header*) relist->m_data ); +} + + +// append a remote event list ------------------------------------------------- +// +int E_REList::AppendList( RE_Header* relist ) +{ + ASSERT( m_data != NULL ); + + // do not append an empty list + if ( relist->RE_Type == RE_EMPTY ) + return TRUE; + + // determine the size of the list to append + size_t lsize = DetermineListSize( relist ); + + ASSERT( lsize <= m_Avail ); + if ( lsize <= m_Avail ) { + // append the list + memcpy( (void*)m_CurPos, (void*)relist, lsize ); + + m_CurPos += lsize; + m_Avail -= lsize; + + ASSERT( m_Avail >= 0 ); + + // ensure proper end for remote event list + ((RE_Header*) m_CurPos)->RE_Type = RE_EMPTY; + + return TRUE; + } else { + return FALSE; + } +} + +// append a remote event ------------------------------------------------------ +// +size_t E_REList::AppendEvent( RE_Header* re, size_t size ) +{ + ASSERT( re != NULL ); + ASSERT( RmEvGetSize( re ) == size ); + + // check whether enough space is left ( account for the trailing RE_EMPTY ) + if ( m_Avail >= ( size + sizeof( RE_Header ) ) ) { + + // copy over the event + memcpy( (void*)m_CurPos, (void*)re, size ); + + m_CurPos += size; + m_Avail -= size; + + ((RE_Header*)m_CurPos)->RE_Type = RE_EMPTY; + + return size; + + } else { + return 0; + } +} + + + + +// fill an external remote event list ----------------------------------------- +// +size_t E_REList::WriteTo( RE_Header* dst, size_t maxsize, int allow_truncate ) +{ + // determine size of remote event list ( include RE_EMPTY byte at end ) + size_t datasize = (size_t)( m_CurPos - m_data ); + + if ( datasize == 0 ) + return 0; + + // ensure we have enough space + if ( datasize > maxsize ) { + + if ( !allow_truncate ) { + ASSERT( FALSE ); + return 0; + } + + RE_Header* relist = (RE_Header*)m_data; + unsigned int filledsize = 0; + + // process remote event list + while ( ( relist->RE_Type != RE_EMPTY ) && ( filledsize < maxsize ) ) { + + size_t resize = RmEvGetSize( relist ); + + if ( ( resize + filledsize ) < maxsize ) { + memcpy( (void*)dst, (void*)relist, resize * sizeof( char ) ); + dst += resize; + + filledsize += resize; + } + + // advance to next event + ASSERT( ( relist->RE_BlockSize == RE_BLOCKSIZE_INVALID ) || + ( relist->RE_BlockSize == resize ) ); + relist = (RE_Header *) ( (char *) relist + resize ); + } + + return filledsize; + + + } else { + memcpy( (void*)dst, m_data, datasize * sizeof( char ) ); + return datasize; + } +} + +// determine size of remote event --------------------------------------------- +// +size_t E_REList::RmEvGetSize( RE_Header *relist ) +{ + ASSERT( relist != NULL ); + byte retype = relist->RE_Type; + + // use stored size for remote-events of variable size + if ( ( retype == RE_DELETED ) || ( retype == RE_SENDTEXT ) || ( retype == RE_COMMANDINFO ) ) { + ASSERT( relist->RE_BlockSize != RE_BLOCKSIZE_INVALID ); + return (size_t)relist->RE_BlockSize; + } + + ASSERT( retype > RE_DELETED ); + ASSERT( retype < RE_NUMEVENTS ); + + return re_sizes[ retype ]; +} + +// determine size of remote event --------------------------------------------- +// +size_t E_REList::RmEvGetSizeFromType( byte retype ) +{ + // use stored size for remote-events of variable size + if ( ( retype == RE_DELETED ) || ( retype == RE_SENDTEXT ) || ( retype == RE_COMMANDINFO ) ) { + return -1; + } + + ASSERT( retype > RE_DELETED ); + ASSERT( retype < RE_NUMEVENTS ); + + return re_sizes[ retype ]; +} + + +// check whether the remote event list is well formed ------------------------- +// +int E_REList::IsWellFormed( RE_Header *relist ) +{ + ASSERT( relist != NULL ); + + //FIXME: [1/30/2002] implement + //FIXME: check NET_RMEV::NET_RmEvList_IsWellFormed + + //RE_LIST_MAXAVAIL + + //ASSERT( FALSE ); + return TRUE; +} + +// return the max. size of the RE list that can fit in one external packet ---- +// +size_t E_REList::GetMaxSizeInPacket() +{ + return ( NET_UDP_DATA_LENGTH - sizeof( NetPacketExternal_GMSV ) ); +} + +// dump contents of RE list --------------------------------------------------- +// +void E_REList::Dump() +{ +#ifndef PARSEC_MASTER + + RE_Header* relist = (RE_Header*)m_data; + int nNumEvents = 0; + + // process remote event list + while ( relist->RE_Type != RE_EMPTY ) { + + size_t resize = RmEvGetSize( relist ); + + if ( relist->RE_Type == RE_COMMANDINFO ) { + LOGOUT(( "%02d: %s size: %d command: %s", nNumEvents, re_names[ relist->RE_Type ], resize, ((RE_CommandInfo*)relist)->command )); + } else { + LOGOUT(( "%02d: %s size: %d", nNumEvents, re_names[ relist->RE_Type ], resize )); + } + + // advance to next event + ASSERT( ( relist->RE_BlockSize == RE_BLOCKSIZE_INVALID ) || + ( relist->RE_BlockSize == resize ) ); + relist = (RE_Header *) ( (char *) relist + resize ); + + nNumEvents++; + } + + LOGOUT(( "# of events: %d", nNumEvents )); + +#endif // !PARSEC_MASTER +} + +// validate the RE according to all bounds ------------------------------------ +// +int E_REList::ValidateRE( RE_Header* relist, size_t size ) +{ + switch( relist->RE_Type ) { + case RE_CLIENTINFO: + { + RE_ClientInfo* re_clientinfo = (RE_ClientInfo*)relist; + re_clientinfo->client_sendfreq = max( re_clientinfo->client_sendfreq, (byte) CLIENT_SEND_FREQUENCY_MIN ); + re_clientinfo->client_sendfreq = min( re_clientinfo->client_sendfreq, (byte) CLIENT_SEND_FREQUENCY_MAX ); + re_clientinfo->server_sendrate = max( re_clientinfo->server_sendrate, PACK_SERVERRATE( CLIENT_RECV_RATE_MIN ) ); + re_clientinfo->server_sendrate = min( re_clientinfo->server_sendrate, PACK_SERVERRATE( CLIENT_RECV_RATE_MAX ) ); + return TRUE; + } + default: + return TRUE; + } +} + + +// check if enough space in RE_List for specified remote event ---------------- +// +int E_REList::RmEvAllowed( int re_type ) +{ + ASSERT( re_type > RE_DELETED ); + ASSERT( re_type < RE_NUMEVENTS ); + ASSERT( re_type != RE_SENDTEXT ); + ASSERT( re_type != RE_PLAYERLIST ); + ASSERT( re_type != RE_CONNECTQUEUE ); + ASSERT( re_type != RE_OWNERSECTION ); + + return ( m_Avail < re_sizes[ re_type ] ); +} + +// insert state sync into RE_List --------------------------------------------- +// +int E_REList::RmEvStateSync( byte statekey, byte stateval ) +{ + //NOTE: + // calling E_REList::RmEvAllowed() is mandatory before calling this function. + + if ( m_Avail < sizeof( RE_StateSync ) ) { + ASSERT( 0 ); + return 0; + } + + RE_StateSync *re_statesync = (RE_StateSync *) m_CurPos; + re_statesync->RE_Type = RE_STATESYNC; + re_statesync->RE_BlockSize = sizeof( RE_StateSync ); + re_statesync->StateKey = statekey; + re_statesync->StateValue = stateval; + + re_statesync++; + re_statesync->RE_Type = RE_EMPTY; + + m_CurPos = (char *) re_statesync; + m_Avail -= sizeof( RE_StateSync ); + + return 1; +} + +// insert command info into remote event list --------------------------------- +// +int E_REList::NET_Append_RE_CommandInfo( const char* commandstring ) +{ + ASSERT( m_data != NULL ); + ASSERT( commandstring != NULL ); + + if ( m_Avail < sizeof( RE_CommandInfo ) ) { + return FALSE; + } + + size_t len = strlen( commandstring ); + if ( len > MAX_RE_COMMANDINFO_COMMAND_LEN ) { + len = MAX_RE_COMMANDINFO_COMMAND_LEN; + } + + RE_CommandInfo* re_commandinfo = (RE_CommandInfo*) m_CurPos; + re_commandinfo->RE_Type = RE_COMMANDINFO; + re_commandinfo->RE_BlockSize = len + 1/*string terminator '\0'*/ + 2/*header*/ + 1/*code*/; + strncpy( re_commandinfo->command , commandstring, MAX_RE_COMMANDINFO_COMMAND_LEN ); + re_commandinfo->command[ MAX_RE_COMMANDINFO_COMMAND_LEN ] = 0; + + m_CurPos += re_commandinfo->RE_BlockSize; + ((RE_Header*)m_CurPos)->RE_Type = RE_EMPTY; + + m_Avail -= sizeof( RE_CommandInfo ); + + ASSERT( m_Avail >= 0 ); + + return TRUE; +} + + +// insert owner section into remote event list -------------------------------- +// +int E_REList::NET_Append_RE_OwnerSection( int ownerid ) +{ + ASSERT( m_data != NULL ); + + if ( m_Avail < sizeof( RE_OwnerSection ) ) { + return FALSE; + } + + RE_OwnerSection* re_ownersection = (RE_OwnerSection*) m_CurPos; + re_ownersection->RE_Type = RE_OWNERSECTION; + re_ownersection->RE_BlockSize = sizeof( RE_OwnerSection ); + re_ownersection->owner = (byte) ownerid; + + re_ownersection++; + re_ownersection->RE_Type = RE_EMPTY; + + m_CurPos = (char *) re_ownersection; + m_Avail -= sizeof( RE_OwnerSection ); + + ASSERT( m_Avail >= 0 ); + + return TRUE; +} + +// append a RE_PlayerAndShipStatus event -------------------------------------- +// +int E_REList::NET_Append_RE_PlayerAndShipStatus( int nClientID, E_SimPlayerInfo* pSimPlayerInfo, E_SimShipState* pSimShipState, refframe_t CurRefFrame, bool_t bUpdatePropsOnly ) +{ +#ifdef PARSEC_SERVER + //FIXME: + //FIXME: + //FIXME: + //FIXME: this is GAMECODE !!! + //FIXME: + //FIXME: + //FIXME: + + ASSERT( nClientID >= 0 && nClientID < MAX_NUM_CLIENTS ); + ASSERT( pSimShipState != NULL ); + + if ( m_Avail < sizeof( RE_PlayerAndShipStatus ) ) { + return FALSE; + } + + RE_PlayerAndShipStatus* re_pas_status = (RE_PlayerAndShipStatus*) m_CurPos; + ASSERT( re_pas_status->RE_Type == RE_EMPTY ); + + re_pas_status->RE_Type = RE_PLAYERANDSHIPSTATUS; + re_pas_status->RE_BlockSize = sizeof( RE_PlayerAndShipStatus ); + + // update all fields + re_pas_status->UpdateFlags = bUpdatePropsOnly ? UF_PROPERTIES : UF_ALL; + + //FIXME: redesign this !! + //FIXME: we should have flags indicating which fields are transmitted in this event + re_pas_status->player_status = pSimPlayerInfo->GetStatus(); + re_pas_status->params[ 0 ] = pSimPlayerInfo->IsPlayerConnected() ? TheGame->GetPlayerLastUnjoinFlag( nClientID ) : 0; + re_pas_status->params[ 1 ] = 0; + re_pas_status->params[ 2 ] = pSimPlayerInfo->IsPlayerConnected() ? ( TheGame->GetPlayerLastKiller( nClientID ) + KILLERID_BIAS ) : 0; + re_pas_status->params[ 3 ] = 0; + re_pas_status->senderid = nClientID; + //FIXME: is this the global object class id ? + re_pas_status->objectindex = ObjClassShipIndex[ pSimPlayerInfo->GetShipObjectClass() ]; + + // fill position and speed from sim-state + memcpy( &re_pas_status->ObjPosition, &pSimShipState->m_ObjPosition, sizeof( Xmatrx ) ); + re_pas_status->CurSpeed = pSimShipState->m_CurSpeed; + re_pas_status->CurYaw = pSimShipState->m_CurYaw; + re_pas_status->CurPitch = pSimShipState->m_CurPitch; + re_pas_status->CurRoll = pSimShipState->m_CurRoll; + re_pas_status->CurSlideHorz = pSimShipState->m_CurSlideHorz; + re_pas_status->CurSlideVert = pSimShipState->m_CurSlideVert; + + // get the properties directly from the ship object + ShipObject* pShipObject = pSimPlayerInfo->GetShipObject(); + if ( pShipObject != NULL ) { + re_pas_status->CurDamage = pShipObject->CurDamage; + re_pas_status->CurShield = pShipObject->CurShield; + re_pas_status->CurEnergy = pShipObject->CurEnergy; + re_pas_status->NumMissls = pShipObject->NumMissls; + re_pas_status->NumHomMissls = pShipObject->NumHomMissls; + re_pas_status->NumMines = pShipObject->NumMines; + re_pas_status->NumPartMissls = pShipObject->NumPartMissls; + } + + DBGTXT( MSGOUT( "sending RE_PlayerAndShipStatus: senderid: %d, status: %d, updateflags: %d", nClientID, pSimPlayerInfo->GetStatus(), re_pas_status->UpdateFlags ); ); + + re_pas_status->RefFrame = CurRefFrame; + + re_pas_status++; + re_pas_status->RE_Type = RE_EMPTY; + + m_CurPos = (char *) re_pas_status; + m_Avail -= sizeof( RE_PlayerAndShipStatus ); + + ASSERT( m_Avail >= 0 ); +#endif // PARSEC_SERVER + + return TRUE; +} + +// append a RE_GameState event ------------------------------------------------ +// +int E_REList::NET_Append_RE_GameState() +{ +#ifdef PARSEC_SERVER + + //FIXME: + //FIXME: + //FIXME: + //FIXME: this is GAMECODE !!! + //FIXME: + //FIXME: + //FIXME: + + if ( m_Avail < sizeof( RE_GameState ) ) { + return FALSE; + } + + RE_GameState* re_gamestate = (RE_GameState*) m_CurPos; + re_gamestate->RE_Type = RE_GAMESTATE; + re_gamestate->RE_BlockSize = sizeof( RE_GameState ); + + // fill in the server gametime + re_gamestate->GameTime = TheGame->GetCurGameTime(); + + re_gamestate++; + re_gamestate->RE_Type = RE_EMPTY; + + m_CurPos = (char *) re_gamestate; + m_Avail -= sizeof( RE_GameState ); + + return TRUE; +#else + ASSERT( FALSE ); + return FALSE; +#endif // PARSEC_SERVER +} + +// insert particle object into RE_List ---------------------------------------- +// +int E_REList::NET_Append_RE_ParticleObject( int type, const Vertex3& origin ) +{ + if ( m_Avail < sizeof( RE_ParticleObject ) ) { + return FALSE; + } + + RE_ParticleObject *re_particleobject = (RE_ParticleObject *) m_CurPos; + re_particleobject->RE_Type = RE_PARTICLEOBJECT; + re_particleobject->RE_BlockSize = sizeof( RE_ParticleObject ); + re_particleobject->ObjectType = type; + re_particleobject->Origin = origin; + + re_particleobject++; + re_particleobject->RE_Type = RE_EMPTY; + + m_CurPos = (char *) re_particleobject; + m_Avail -= sizeof( RE_ParticleObject ); + + return TRUE; +} + + +// append a RE_CreateExtra2 event ---------------------------------------------- +// +int E_REList::NET_Append_RE_CreateExtra2( const ExtraObject *extrapo ) +{ +#ifdef PARSEC_SERVER + + //FIXME: + //FIXME: + //FIXME: + //FIXME: this is GAMECODE !!! + //FIXME: + //FIXME: + //FIXME: + + //NOTE: + // calling NET_RmEvAllowed() is mandatory + // before calling this function. + + ASSERT( extrapo != NULL ); + + if ( m_Avail < sizeof( RE_CreateExtra2 ) ) { + return FALSE; + } + + // translate from objectclass to extra index + int extraindex = ObjClassExtraIndex[ extrapo->ObjectClass ]; + ASSERT( extraindex != EXTRAINDEX_NO_EXTRA ); + + RE_CreateExtra2 *re_ce2 = (RE_CreateExtra2 *) m_CurPos; + re_ce2->RE_Type = RE_CREATEEXTRA2; + re_ce2->RE_BlockSize = sizeof( RE_CreateExtra2 ); + re_ce2->ExtraIndex = extraindex; + re_ce2->HostObjId = extrapo->HostObjNumber; + memcpy( &re_ce2->ObjPosition, &extrapo->ObjPosition, sizeof( Xmatrx ) ); + re_ce2->DriftVec.X = extrapo->DriftVec.X; + re_ce2->DriftVec.Y = extrapo->DriftVec.Y; + re_ce2->DriftVec.Z = extrapo->DriftVec.Z; + re_ce2->DriftTimeout = extrapo->DriftTimeout; + + re_ce2++; + re_ce2->RE_Type = RE_EMPTY; + + m_CurPos = (char *) re_ce2; + m_Avail -= sizeof( RE_CreateExtra2 ); + + return TRUE; +#else + ASSERT( FALSE ); + return FALSE; +#endif // PARSEC_SERVER +} + + +// append a RE_CreateLaser event ---------------------------------------------- +// +int E_REList::NET_Append_RE_CreateLaser( const LaserObject* laserpo ) +{ +#ifdef PARSEC_SERVER + + //FIXME: + //FIXME: + //FIXME: + //FIXME: this is GAMECODE !!! + //FIXME: + //FIXME: + //FIXME: + + + //NOTE: + // calling NET_RmEvAllowed() is mandatory before calling this function. + + ASSERT( laserpo != NULL ); + + if ( m_Avail < sizeof( RE_CreateLaser ) ) { + return FALSE; + } + + RE_CreateLaser *re_createlaser = (RE_CreateLaser *) m_CurPos; + re_createlaser->RE_Type = RE_CREATELASER; + re_createlaser->RE_BlockSize = sizeof( RE_CreateLaser ); + //FIXME: objectclass is not synced between client and server + re_createlaser->ObjectClass = laserpo->ObjectClass; + re_createlaser->HostObjId = laserpo->HostObjNumber; + memcpy( &re_createlaser->ObjPosition, &laserpo->ObjPosition, sizeof( Xmatrx ) ); + re_createlaser->DirectionVec = laserpo->DirectionVec; + + re_createlaser++; + re_createlaser->RE_Type = RE_EMPTY; + + m_CurPos = (char *) re_createlaser; + m_Avail -= sizeof( RE_CreateLaser ); + + return TRUE; +#else + ASSERT( FALSE ); + return FALSE; +#endif // PARSEC_SERVER +} + +// insert missile into RE_List ------------------------------------------------ +// +int E_REList::NET_Append_RE_CreateMissile( const MissileObject *missilepo, dword targetobjid ) +{ +#ifdef PARSEC_SERVER + + //FIXME: + //FIXME: + //FIXME: + //FIXME: this is GAMECODE !!! + //FIXME: + //FIXME: + //FIXME: + + //NOTE: + // calling NET_RmEvAllowed() is mandatory + // before calling this function. + + ASSERT( missilepo != NULL ); + + + if ( m_Avail < sizeof( RE_CreateMissile ) ) { + return FALSE; + } + + RE_CreateMissile *re_createmissl = (RE_CreateMissile *) m_CurPos;; + re_createmissl->RE_Type = RE_CREATEMISSILE; + re_createmissl->RE_BlockSize = sizeof( RE_CreateMissile ); + re_createmissl->ObjectClass = missilepo->ObjectClass; + re_createmissl->HostObjId = missilepo->HostObjNumber; + re_createmissl->TargetHostObjId = targetobjid; + memcpy( &re_createmissl->ObjPosition, &missilepo->ObjPosition, sizeof( Xmatrx ) ); + re_createmissl->DirectionVec = missilepo->DirectionVec; + + re_createmissl++; + re_createmissl->RE_Type = RE_EMPTY; + + m_CurPos = (char *) re_createmissl; + m_Avail -= sizeof( RE_CreateMissile ); + + + return TRUE; +#else + return FALSE; +#endif //Parsec Server +} + +// append a RE_KillOjbect event ----------------------------------------------- +// +int E_REList::NET_Append_RE_KillObject( dword objectid, byte listno ) +{ +#ifdef PARSEC_SERVER + + //FIXME: + //FIXME: + //FIXME: + //FIXME: this is GAMECODE !!! + //FIXME: + //FIXME: + //FIXME: + +#ifdef NO_PROJECTILE_KILL_MESSAGES + + // for projectiles depend on local client lifetime expiration + if ( ( listno == LASER_LIST ) || ( listno == MISSL_LIST ) ) { + return 1; + } + ASSERT( listno == EXTRA_LIST ); + +#endif + + if ( m_Avail < sizeof( RE_KillObject ) ) { + return FALSE; + } + + RE_KillObject *re_killobject = (RE_KillObject *) m_CurPos; + re_killobject->RE_Type = RE_KILLOBJECT; + re_killobject->RE_BlockSize = sizeof( RE_KillObject ); + re_killobject->HostObjId = objectid; + re_killobject->ListId = listno; + + re_killobject++; + re_killobject->RE_Type = RE_EMPTY; + + m_CurPos = (char *) re_killobject; + m_Avail -= sizeof( RE_KillObject ); + + return TRUE; +#else + ASSERT( FALSE ); + return FALSE; +#endif // PARSEC_SERVER +} + + +// append a RE_KillStats event ------------------------------------------------ +// +int E_REList::NET_Append_RE_KillStats() +{ +#ifdef PARSEC_SERVER + + //FIXME: + //FIXME: + //FIXME: + //FIXME: this is GAMECODE !!! + //FIXME: + //FIXME: + //FIXME: + + if ( m_Avail < sizeof( RE_KillStats ) ) { + return FALSE; + } + + RE_KillStats* re_killstats = (RE_KillStats*) m_CurPos; + re_killstats->RE_Type = RE_KILLSTATS; + re_killstats->RE_BlockSize = sizeof( RE_KillStats ); + + // fill in the server gametime + for( int nClientID = 0; nClientID < MAX_NUM_CLIENTS; nClientID++ ) { + re_killstats->PlayerKills[ nClientID ] = TheGame->GetPlayerKills( nClientID ); + } + + re_killstats++; + re_killstats->RE_Type = RE_EMPTY; + + m_CurPos = (char*) re_killstats; + m_Avail -= sizeof( RE_KillStats ); + + return TRUE; +#else + ASSERT( FALSE ); + return FALSE; +#endif // PARSEC_SERVER +} + +// append a RE_IPv4ServerInfo event ------------------------------------------- +// +int E_REList::NET_Append_RE_IPv4ServerInfo( node_t* node, word nServerID, int xpos, int ypos, word flags ) +{ + + + ASSERT( node != NULL ); + + if ( m_Avail < sizeof( RE_IPv4ServerInfo ) ) { + return FALSE; + } + + RE_IPv4ServerInfo* re_ipv4serverinfo = (RE_IPv4ServerInfo*) m_CurPos; + re_ipv4serverinfo->RE_Type = RE_IPV4SERVERINFO; + re_ipv4serverinfo->RE_BlockSize = sizeof( RE_IPv4ServerInfo ); + + memcpy( re_ipv4serverinfo->node, node, NODE_ADR_LENGTH ); + + re_ipv4serverinfo->flags = flags; + re_ipv4serverinfo->serverid = nServerID; + re_ipv4serverinfo->xpos = xpos; + re_ipv4serverinfo->ypos = ypos; + + re_ipv4serverinfo++; + re_ipv4serverinfo->RE_Type = RE_EMPTY; + + m_CurPos = (char *) re_ipv4serverinfo; + m_Avail -= sizeof( RE_IPv4ServerInfo ); + + return TRUE; +} + +// append a RE_ServerLinkInfo event ------------------------------------------- +// +int E_REList::NET_Append_RE_ServerLinkInfo( word nServerID_1, word nServerID_2, word flags ) +{ + if ( m_Avail < sizeof( RE_ServerLinkInfo ) ) { + return FALSE; + } + + RE_ServerLinkInfo* re_sli = (RE_ServerLinkInfo*) m_CurPos; + re_sli->RE_Type = RE_SERVERLINKINFO; + re_sli->RE_BlockSize = sizeof( RE_ServerLinkInfo ); + + re_sli->flags = flags; + re_sli->serverid1 = nServerID_1; + re_sli->serverid2 = nServerID_2; + + re_sli++; + re_sli->RE_Type = RE_EMPTY; + + m_CurPos = (char *) re_sli; + m_Avail -= sizeof( RE_ServerLinkInfo ); + + return TRUE; +} + +// append a RE_MapObject ------------------------------------------------------ +// +int E_REList::NET_Append_RE_MapObject( int map_objectid, char* name, int xpos, int ypos, int w, int h, char* texname ) +{ + ASSERT( ( map_objectid >= 0 ) && ( map_objectid < MAX_MAP_OBJECTS ) ); + ASSERT( name != NULL ); + ASSERT( texname != NULL ); + + if ( m_Avail < sizeof( RE_MapObject ) ) { + return FALSE; + } + + RE_MapObject* re_mo = (RE_MapObject*) m_CurPos; + re_mo->RE_Type = RE_MAPOBJECT; + re_mo->RE_BlockSize = sizeof( RE_MapObject ); + + re_mo->map_objectid = map_objectid; + strncpy( re_mo->name, name, MAX_MAP_OBJ_NAME ); + re_mo->name[ MAX_MAP_OBJ_NAME ] = 0; + re_mo->xpos = xpos; + re_mo->ypos = ypos; + re_mo->w = w; + re_mo->h = h; + strncpy( re_mo->texname, texname, MAX_TEXNAME); + re_mo->texname[ MAX_TEXNAME ] = 0; + + re_mo++; + re_mo->RE_Type = RE_EMPTY; + + m_CurPos = (char *) re_mo; + m_Avail -= sizeof( RE_MapObject ); + + return TRUE; +} + +// allocate space for a specific RE ------------------------------------------- +// +RE_Header* E_REList::NET_Allocate( int retype ) +{ + ASSERT( ( retype >= RE_EMPTY ) && ( retype < RE_NUMEVENTS ) ); + ASSERT( ( retype != RE_DELETED ) && ( retype != RE_SENDTEXT ) && ( retype != RE_COMMANDINFO ) ); + + ssize_t size = RmEvGetSizeFromType( retype ); + ASSERT( size != -1 ); + + if( m_Avail < (size_t)size ) { + return NULL; + } + + RE_Header* pBegin = (RE_Header*)m_CurPos; + pBegin->RE_Type = retype; + pBegin->RE_BlockSize = size; + + m_CurPos += size; + m_Avail -= size; + + ((RE_Header*)m_CurPos)->RE_Type = RE_EMPTY; + + return pBegin; +} |
