mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-20 12:44:46 +00:00
380 lines
11 KiB
C++
380 lines
11 KiB
C++
|
|
#include "platform/platform.h"
|
||
|
|
#include "T3D/gameBase/extended/extendedGameProcess.h"
|
||
|
|
#include "T3D/gameBase/extended/extendedMoveList.h"
|
||
|
|
|
||
|
|
#include "platform/profiler.h"
|
||
|
|
#include "console/consoleTypes.h"
|
||
|
|
#include "core/dnet.h"
|
||
|
|
#include "core/stream/bitStream.h"
|
||
|
|
#include "core/frameAllocator.h"
|
||
|
|
#include "core/util/refBase.h"
|
||
|
|
#include "math/mPoint3.h"
|
||
|
|
#include "math/mMatrix.h"
|
||
|
|
#include "math/mathUtils.h"
|
||
|
|
#include "T3D/gameBase/gameBase.h"
|
||
|
|
#include "T3D/gameBase/gameConnection.h"
|
||
|
|
#include "T3D/fx/cameraFXMgr.h"
|
||
|
|
|
||
|
|
MODULE_BEGIN( ProcessList )
|
||
|
|
|
||
|
|
MODULE_INIT
|
||
|
|
{
|
||
|
|
ExtendedServerProcessList::init();
|
||
|
|
ExtendedClientProcessList::init();
|
||
|
|
}
|
||
|
|
|
||
|
|
MODULE_SHUTDOWN
|
||
|
|
{
|
||
|
|
ExtendedServerProcessList::shutdown();
|
||
|
|
ExtendedClientProcessList::shutdown();
|
||
|
|
}
|
||
|
|
|
||
|
|
MODULE_END;
|
||
|
|
|
||
|
|
void ExtendedServerProcessList::init()
|
||
|
|
{
|
||
|
|
smServerProcessList = new ExtendedServerProcessList();
|
||
|
|
}
|
||
|
|
|
||
|
|
void ExtendedServerProcessList::shutdown()
|
||
|
|
{
|
||
|
|
delete smServerProcessList;
|
||
|
|
}
|
||
|
|
|
||
|
|
void ExtendedClientProcessList::init()
|
||
|
|
{
|
||
|
|
smClientProcessList = new ExtendedClientProcessList();
|
||
|
|
}
|
||
|
|
|
||
|
|
void ExtendedClientProcessList::shutdown()
|
||
|
|
{
|
||
|
|
delete smClientProcessList;
|
||
|
|
}
|
||
|
|
|
||
|
|
//----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
|
||
|
|
namespace
|
||
|
|
{
|
||
|
|
// local work class
|
||
|
|
struct GameBaseListNode
|
||
|
|
{
|
||
|
|
GameBaseListNode()
|
||
|
|
{
|
||
|
|
mPrev=this;
|
||
|
|
mNext=this;
|
||
|
|
mObject=NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
GameBaseListNode * mPrev;
|
||
|
|
GameBaseListNode * mNext;
|
||
|
|
GameBase * mObject;
|
||
|
|
|
||
|
|
void linkBefore(GameBaseListNode * obj)
|
||
|
|
{
|
||
|
|
// Link this before obj
|
||
|
|
mNext = obj;
|
||
|
|
mPrev = obj->mPrev;
|
||
|
|
obj->mPrev = this;
|
||
|
|
mPrev->mNext = this;
|
||
|
|
}
|
||
|
|
};
|
||
|
|
} // namespace
|
||
|
|
|
||
|
|
//--------------------------------------------------------------------------
|
||
|
|
// ExtendedClientProcessList
|
||
|
|
//--------------------------------------------------------------------------
|
||
|
|
|
||
|
|
ExtendedClientProcessList::ExtendedClientProcessList()
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
bool ExtendedClientProcessList::advanceTime( SimTime timeDelta )
|
||
|
|
{
|
||
|
|
PROFILE_SCOPE( ExtendedClientProcessList_AdvanceTime );
|
||
|
|
|
||
|
|
if ( doBacklogged( timeDelta ) )
|
||
|
|
return false;
|
||
|
|
|
||
|
|
bool ret = Parent::advanceTime( timeDelta );
|
||
|
|
ProcessObject *obj = NULL;
|
||
|
|
|
||
|
|
AssertFatal( mLastDelta >= 0.0f && mLastDelta <= 1.0f, "mLastDelta is not zero to one.");
|
||
|
|
|
||
|
|
obj = mHead.mProcessLink.next;
|
||
|
|
while ( obj != &mHead )
|
||
|
|
{
|
||
|
|
if ( obj->isTicking() )
|
||
|
|
obj->interpolateTick( mLastDelta );
|
||
|
|
|
||
|
|
obj = obj->mProcessLink.next;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Inform objects of total elapsed delta so they can advance
|
||
|
|
// client side animations.
|
||
|
|
F32 dt = F32(timeDelta) / 1000;
|
||
|
|
|
||
|
|
// Update camera FX.
|
||
|
|
gCamFXMgr.update( dt );
|
||
|
|
|
||
|
|
obj = mHead.mProcessLink.next;
|
||
|
|
while ( obj != &mHead )
|
||
|
|
{
|
||
|
|
obj->advanceTime( dt );
|
||
|
|
obj = obj->mProcessLink.next;
|
||
|
|
}
|
||
|
|
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
//----------------------------------------------------------------------------
|
||
|
|
void ExtendedClientProcessList::onAdvanceObjects()
|
||
|
|
{
|
||
|
|
PROFILE_SCOPE( ExtendedClientProcessList_OnAdvanceObjects );
|
||
|
|
|
||
|
|
GameConnection* connection = GameConnection::getConnectionToServer();
|
||
|
|
if ( connection )
|
||
|
|
{
|
||
|
|
// process any demo blocks that are NOT moves, and exactly one move
|
||
|
|
// we advance time in the demo stream by a move inserted on
|
||
|
|
// each tick. So before doing the tick processing we advance
|
||
|
|
// the demo stream until a move is ready
|
||
|
|
if ( connection->isPlayingBack() )
|
||
|
|
{
|
||
|
|
U32 blockType;
|
||
|
|
do
|
||
|
|
{
|
||
|
|
blockType = connection->getNextBlockType();
|
||
|
|
bool res = connection->processNextBlock();
|
||
|
|
// if there are no more blocks, exit out of this function,
|
||
|
|
// as no more client time needs to process right now - we'll
|
||
|
|
// get it all on the next advanceClientTime()
|
||
|
|
if(!res)
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
while ( blockType != GameConnection::BlockTypeMove );
|
||
|
|
}
|
||
|
|
|
||
|
|
connection->mMoveList->collectMove();
|
||
|
|
advanceObjects();
|
||
|
|
}
|
||
|
|
else
|
||
|
|
advanceObjects();
|
||
|
|
}
|
||
|
|
|
||
|
|
void ExtendedClientProcessList::onTickObject( ProcessObject *obj )
|
||
|
|
{
|
||
|
|
PROFILE_SCOPE( ExtendedClientProcessList_OnTickObject );
|
||
|
|
|
||
|
|
// In case the object deletes itself during its processTick.
|
||
|
|
SimObjectPtr<SceneObject> safePtr = static_cast<SceneObject*>( obj );
|
||
|
|
|
||
|
|
// Each object is either advanced a single tick, or if it's
|
||
|
|
// being controlled by a client, ticked once for each pending move.
|
||
|
|
ExtendedMove* extMovePtr;
|
||
|
|
U32 numMoves;
|
||
|
|
GameConnection* con = obj->getControllingClient();
|
||
|
|
if ( con && con->getControlObject() == obj )
|
||
|
|
{
|
||
|
|
ExtendedMoveList* extMoveList = static_cast<ExtendedMoveList*>(con->mMoveList);
|
||
|
|
extMoveList->getExtMoves( &extMovePtr, &numMoves );
|
||
|
|
if ( numMoves )
|
||
|
|
{
|
||
|
|
// Note: should only have a single move at this point
|
||
|
|
AssertFatal(numMoves==1,"ClientProccessList::onTickObject: more than one move in queue");
|
||
|
|
|
||
|
|
#ifdef TORQUE_DEBUG_NET_MOVES
|
||
|
|
U32 sum = Move::ChecksumMask & obj->getPacketDataChecksum(obj->getControllingClient());
|
||
|
|
#endif
|
||
|
|
|
||
|
|
if ( obj->isTicking() )
|
||
|
|
obj->processTick( extMovePtr );
|
||
|
|
|
||
|
|
if ( bool(safePtr) && obj->getControllingClient() )
|
||
|
|
{
|
||
|
|
U32 newsum = Move::ChecksumMask & obj->getPacketDataChecksum( obj->getControllingClient() );
|
||
|
|
|
||
|
|
// set checksum if not set or check against stored value if set
|
||
|
|
extMovePtr->checksum = newsum;
|
||
|
|
|
||
|
|
#ifdef TORQUE_DEBUG_NET_MOVES
|
||
|
|
Con::printf("move checksum: %i, (start %i), (move %f %f %f)",
|
||
|
|
movePtr->checksum,sum,movePtr->yaw,movePtr->y,movePtr->z);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
con->mMoveList->clearMoves( 1 );
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if ( obj->isTicking() )
|
||
|
|
obj->processTick( 0 );
|
||
|
|
}
|
||
|
|
|
||
|
|
void ExtendedClientProcessList::advanceObjects()
|
||
|
|
{
|
||
|
|
PROFILE_SCOPE( ExtendedClientProcessList_AdvanceObjects );
|
||
|
|
|
||
|
|
#ifdef TORQUE_DEBUG_NET_MOVES
|
||
|
|
Con::printf("Advance client time...");
|
||
|
|
#endif
|
||
|
|
|
||
|
|
Parent::advanceObjects();
|
||
|
|
|
||
|
|
#ifdef TORQUE_DEBUG_NET_MOVES
|
||
|
|
Con::printf("---------");
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
void ExtendedClientProcessList::clientCatchup( GameConnection * connection )
|
||
|
|
{
|
||
|
|
SimObjectPtr<GameBase> control = connection->getControlObject();
|
||
|
|
if ( control )
|
||
|
|
{
|
||
|
|
ExtendedMove * extMovePtr;
|
||
|
|
U32 numMoves;
|
||
|
|
U32 m = 0;
|
||
|
|
ExtendedMoveList* extMoveList = static_cast<ExtendedMoveList*>(connection->mMoveList);
|
||
|
|
extMoveList->getExtMoves( &extMovePtr, &numMoves );
|
||
|
|
|
||
|
|
#ifdef TORQUE_DEBUG_NET_MOVES
|
||
|
|
Con::printf("client catching up... (%i)", numMoves);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
preTickSignal().trigger();
|
||
|
|
|
||
|
|
if ( control->isTicking() )
|
||
|
|
for ( m = 0; m < numMoves; m++ )
|
||
|
|
control->processTick( extMovePtr++ );
|
||
|
|
|
||
|
|
extMoveList->clearMoves( m );
|
||
|
|
}
|
||
|
|
|
||
|
|
#ifdef TORQUE_DEBUG_NET_MOVES
|
||
|
|
Con::printf("---------");
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
//--------------------------------------------------------------------------
|
||
|
|
// ServerProcessList
|
||
|
|
//--------------------------------------------------------------------------
|
||
|
|
|
||
|
|
ExtendedServerProcessList::ExtendedServerProcessList()
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
void ExtendedServerProcessList::onPreTickObject( ProcessObject *pobj )
|
||
|
|
{
|
||
|
|
if ( pobj->mIsGameBase )
|
||
|
|
{
|
||
|
|
SimObjectPtr<GameBase> obj = getGameBase( pobj );
|
||
|
|
|
||
|
|
// Each object is either advanced a single tick, or if it's
|
||
|
|
// being controlled by a client, ticked once for each pending move.
|
||
|
|
GameConnection *con = obj->getControllingClient();
|
||
|
|
|
||
|
|
if ( con && con->getControlObject() == obj )
|
||
|
|
{
|
||
|
|
ExtendedMove* extMovePtr;
|
||
|
|
U32 numMoves;
|
||
|
|
ExtendedMoveList* extMoveList = static_cast<ExtendedMoveList*>(con->mMoveList);
|
||
|
|
extMoveList->getExtMoves( &extMovePtr, &numMoves );
|
||
|
|
|
||
|
|
if ( numMoves == 0 )
|
||
|
|
{
|
||
|
|
#ifdef TORQUE_DEBUG_NET_MOVES
|
||
|
|
Con::printf("no moves on object %i, skip tick",obj->getId());
|
||
|
|
#endif
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
Parent::onPreTickObject (pobj );
|
||
|
|
}
|
||
|
|
|
||
|
|
void ExtendedServerProcessList::onTickObject( ProcessObject *pobj )
|
||
|
|
{
|
||
|
|
PROFILE_SCOPE( ExtendedServerProcessList_OnTickObject );
|
||
|
|
|
||
|
|
// Each object is either advanced a single tick, or if it's
|
||
|
|
// being controlled by a client, ticked once for each pending move.
|
||
|
|
|
||
|
|
GameConnection *con = pobj->getControllingClient();
|
||
|
|
|
||
|
|
if ( pobj->mIsGameBase && con && con->getControlObject() == pobj )
|
||
|
|
{
|
||
|
|
// In case the object is deleted during its own tick.
|
||
|
|
SimObjectPtr<GameBase> obj = getGameBase( pobj );
|
||
|
|
|
||
|
|
ExtendedMove* extMovePtr;
|
||
|
|
U32 m, numMoves;
|
||
|
|
ExtendedMoveList* extMoveList = static_cast<ExtendedMoveList*>(con->mMoveList);
|
||
|
|
extMoveList->getExtMoves( &extMovePtr, &numMoves );
|
||
|
|
|
||
|
|
// For debugging it can be useful to know when this happens.
|
||
|
|
//if ( numMoves > 1 )
|
||
|
|
// Con::printf( "numMoves: %i", numMoves );
|
||
|
|
|
||
|
|
// Do we really need to test the control object each iteration? Does it change?
|
||
|
|
for ( m = 0; m < numMoves && con && con->getControlObject() == obj; m++, extMovePtr++ )
|
||
|
|
{
|
||
|
|
#ifdef TORQUE_DEBUG_NET_MOVES
|
||
|
|
U32 sum = Move::ChecksumMask & obj->getPacketDataChecksum(obj->getControllingClient());
|
||
|
|
#endif
|
||
|
|
|
||
|
|
if ( obj->isTicking() )
|
||
|
|
obj->processTick( extMovePtr );
|
||
|
|
|
||
|
|
if ( con && con->getControlObject() == obj )
|
||
|
|
{
|
||
|
|
U32 newsum = Move::ChecksumMask & obj->getPacketDataChecksum( obj->getControllingClient() );
|
||
|
|
|
||
|
|
// check move checksum
|
||
|
|
if ( extMovePtr->checksum != newsum )
|
||
|
|
{
|
||
|
|
#ifdef TORQUE_DEBUG_NET_MOVES
|
||
|
|
if( !obj->isAIControlled() )
|
||
|
|
Con::printf("move %i checksum disagree: %i != %i, (start %i), (move %f %f %f)",
|
||
|
|
extMovePtr->id, extMovePtr->checksum,newsum,sum,extMovePtr->yaw,extMovePtr->y,extMovePtr->z);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
extMovePtr->checksum = Move::ChecksumMismatch;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
#ifdef TORQUE_DEBUG_NET_MOVES
|
||
|
|
Con::printf("move %i checksum agree: %i == %i, (start %i), (move %f %f %f)",
|
||
|
|
extMovePtr->id, extMovePtr->checksum,newsum,sum,extMovePtr->yaw,extMovePtr->y,extMovePtr->z);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
extMoveList->clearMoves( m );
|
||
|
|
}
|
||
|
|
else if ( pobj->isTicking() )
|
||
|
|
pobj->processTick( 0 );
|
||
|
|
}
|
||
|
|
|
||
|
|
void ExtendedServerProcessList::advanceObjects()
|
||
|
|
{
|
||
|
|
#ifdef TORQUE_DEBUG_NET_MOVES
|
||
|
|
Con::printf("Advance server time...");
|
||
|
|
#endif
|
||
|
|
|
||
|
|
Parent::advanceObjects();
|
||
|
|
|
||
|
|
// Credit all connections with the elapsed tick
|
||
|
|
SimGroup *clientGroup = Sim::getClientGroup();
|
||
|
|
for(SimGroup::iterator i = clientGroup->begin(); i != clientGroup->end(); i++)
|
||
|
|
{
|
||
|
|
if (GameConnection *con = dynamic_cast<GameConnection *>(*i))
|
||
|
|
{
|
||
|
|
con->mMoveList->advanceMove();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#ifdef TORQUE_DEBUG_NET_MOVES
|
||
|
|
Con::printf("---------");
|
||
|
|
#endif
|
||
|
|
}
|