extendedGameProcess.cpp
Engine/source/T3D/gameBase/extended/extendedGameProcess.cpp
Public Variables
Detailed Description
Public Variables
MODULE_END
MODULE_INIT
MODULE_SHUTDOWN
1 2#include "platform/platform.h" 3#include "T3D/gameBase/extended/extendedGameProcess.h" 4#include "T3D/gameBase/extended/extendedMoveList.h" 5 6#include "platform/profiler.h" 7#include "console/consoleTypes.h" 8#include "core/dnet.h" 9#include "core/stream/bitStream.h" 10#include "core/frameAllocator.h" 11#include "core/util/refBase.h" 12#include "math/mPoint3.h" 13#include "math/mMatrix.h" 14#include "math/mathUtils.h" 15#include "T3D/gameBase/gameBase.h" 16#include "T3D/gameBase/gameConnection.h" 17#include "T3D/fx/cameraFXMgr.h" 18 19MODULE_BEGIN( ProcessList ) 20 21 MODULE_INIT 22 { 23 ExtendedServerProcessList::init(); 24 ExtendedClientProcessList::init(); 25 } 26 27 MODULE_SHUTDOWN 28 { 29 ExtendedServerProcessList::shutdown(); 30 ExtendedClientProcessList::shutdown(); 31 } 32 33MODULE_END; 34 35void ExtendedServerProcessList::init() 36{ 37 smServerProcessList = new ExtendedServerProcessList(); 38} 39 40void ExtendedServerProcessList::shutdown() 41{ 42 delete smServerProcessList; 43} 44 45void ExtendedClientProcessList::init() 46{ 47 smClientProcessList = new ExtendedClientProcessList(); 48} 49 50void ExtendedClientProcessList::shutdown() 51{ 52 delete smClientProcessList; 53} 54 55//---------------------------------------------------------------------------- 56 57 58namespace 59{ 60 // local work class 61 struct GameBaseListNode 62 { 63 GameBaseListNode() 64 { 65 mPrev=this; 66 mNext=this; 67 mObject=<a href="/coding/file/types_8lint_8h/#types_8lint_8h_1a070d2ce7b6bb7e5c05602aa8c308d0c4">NULL</a>; 68 } 69 70 GameBaseListNode * mPrev; 71 GameBaseListNode * mNext; 72 GameBase * mObject; 73 74 void linkBefore(GameBaseListNode * obj) 75 { 76 // Link this before obj 77 mNext = obj; 78 mPrev = obj->mPrev; 79 obj->mPrev = this; 80 mPrev->mNext = this; 81 } 82 }; 83} // namespace 84 85//-------------------------------------------------------------------------- 86// ExtendedClientProcessList 87//-------------------------------------------------------------------------- 88 89ExtendedClientProcessList::ExtendedClientProcessList() 90{ 91} 92 93bool ExtendedClientProcessList::advanceTime( SimTime timeDelta ) 94{ 95 PROFILE_SCOPE( ExtendedClientProcessList_AdvanceTime ); 96 97 if ( doBacklogged( timeDelta ) ) 98 return false; 99 100 bool ret = Parent::advanceTime( timeDelta ); 101 ProcessObject *obj = NULL; 102 103 AssertFatal( mLastDelta >= 0.0f && mLastDelta <= 1.0f, "mLastDelta is not zero to one."); 104 105 obj = mHead.mProcessLink.next; 106 while ( obj != &mHead ) 107 { 108 if ( obj->isTicking() ) 109 obj->interpolateTick( mLastDelta ); 110 111 obj = obj->mProcessLink.next; 112 } 113 114 // Inform objects of total elapsed delta so they can advance 115 // client side animations. 116 F32 dt = F32(timeDelta) / 1000; 117 118 // Update camera FX. 119 gCamFXMgr.update( dt ); 120 121 obj = mHead.mProcessLink.next; 122 while ( obj != &mHead ) 123 { 124 obj->advanceTime( dt ); 125 obj = obj->mProcessLink.next; 126 } 127 128 return ret; 129} 130 131//---------------------------------------------------------------------------- 132void ExtendedClientProcessList::onAdvanceObjects() 133{ 134 PROFILE_SCOPE( ExtendedClientProcessList_OnAdvanceObjects ); 135 136 GameConnection* connection = GameConnection::getConnectionToServer(); 137 if ( connection ) 138 { 139 // process any demo blocks that are NOT moves, and exactly one move 140 // we advance time in the demo stream by a move inserted on 141 // each tick. So before doing the tick processing we advance 142 // the demo stream until a move is ready 143 if ( connection->isPlayingBack() ) 144 { 145 U32 blockType; 146 do 147 { 148 blockType = connection->getNextBlockType(); 149 bool res = connection->processNextBlock(); 150 // if there are no more blocks, exit out of this function, 151 // as no more client time needs to process right now - we'll 152 // get it all on the next advanceClientTime() 153 if(!res) 154 return; 155 } 156 while ( blockType != GameConnection::BlockTypeMove ); 157 } 158 159 connection->mMoveList->collectMove(); 160 advanceObjects(); 161 } 162 else 163 advanceObjects(); 164} 165 166void ExtendedClientProcessList::onTickObject( ProcessObject *obj ) 167{ 168 PROFILE_SCOPE( ExtendedClientProcessList_OnTickObject ); 169 170 // In case the object deletes itself during its processTick. 171 SimObjectPtr<SceneObject> safePtr = static_cast<SceneObject*>( obj ); 172 173 // Each object is either advanced a single tick, or if it's 174 // being controlled by a client, ticked once for each pending move. 175 ExtendedMove* extMovePtr; 176 U32 numMoves; 177 GameConnection* con = obj->getControllingClient(); 178 if ( con && con->getControlObject() == obj ) 179 { 180 ExtendedMoveList* extMoveList = static_cast<ExtendedMoveList*>(con->mMoveList); 181 extMoveList->getExtMoves( &extMovePtr, &numMoves ); 182 if ( numMoves ) 183 { 184 // Note: should only have a single move at this point 185 AssertFatal(numMoves==1,"ClientProccessList::onTickObject: more than one move in queue"); 186 187 #ifdef TORQUE_DEBUG_NET_MOVES 188 U32 sum = Move::ChecksumMask & obj->getPacketDataChecksum(obj->getControllingClient()); 189 #endif 190 191 if ( obj->isTicking() ) 192 obj->processTick( extMovePtr ); 193 194 if ( bool(safePtr) && obj->getControllingClient() ) 195 { 196 U32 newsum = Move::ChecksumMask & obj->getPacketDataChecksum( obj->getControllingClient() ); 197 198 // set checksum if not set or check against stored value if set 199 extMovePtr->checksum = newsum; 200 201 #ifdef TORQUE_DEBUG_NET_MOVES 202 Con::printf("move checksum: %i, (start %i), (move %f %f %f)", 203 movePtr->checksum,sum,movePtr->yaw,movePtr->y,movePtr->z); 204 #endif 205 } 206 con->mMoveList->clearMoves( 1 ); 207 } 208 } 209 else if ( obj->isTicking() ) 210 obj->processTick( 0 ); 211} 212 213void ExtendedClientProcessList::advanceObjects() 214{ 215 PROFILE_SCOPE( ExtendedClientProcessList_AdvanceObjects ); 216 217 #ifdef TORQUE_DEBUG_NET_MOVES 218 Con::printf("Advance client time..."); 219 #endif 220 221 Parent::advanceObjects(); 222 223 #ifdef TORQUE_DEBUG_NET_MOVES 224 Con::printf("---------"); 225 #endif 226} 227 228void ExtendedClientProcessList::clientCatchup( GameConnection * connection ) 229{ 230 SimObjectPtr<GameBase> control = connection->getControlObject(); 231 if ( control ) 232 { 233 ExtendedMove * extMovePtr; 234 U32 numMoves; 235 U32 m = 0; 236 ExtendedMoveList* extMoveList = static_cast<ExtendedMoveList*>(connection->mMoveList); 237 extMoveList->getExtMoves( &extMovePtr, &numMoves ); 238 239 #ifdef TORQUE_DEBUG_NET_MOVES 240 Con::printf("client catching up... (%i)", numMoves); 241 #endif 242 243 preTickSignal().trigger(); 244 245 if ( control->isTicking() ) 246 for ( m = 0; m < numMoves; m++ ) 247 control->processTick( extMovePtr++ ); 248 249 extMoveList->clearMoves( m ); 250 } 251 252 #ifdef TORQUE_DEBUG_NET_MOVES 253 Con::printf("---------"); 254 #endif 255} 256 257//-------------------------------------------------------------------------- 258// ServerProcessList 259//-------------------------------------------------------------------------- 260 261ExtendedServerProcessList::ExtendedServerProcessList() 262{ 263} 264 265void ExtendedServerProcessList::onPreTickObject( ProcessObject *pobj ) 266{ 267 if ( pobj->mIsGameBase ) 268 { 269 SimObjectPtr<GameBase> obj = getGameBase( pobj ); 270 271 // Each object is either advanced a single tick, or if it's 272 // being controlled by a client, ticked once for each pending move. 273 GameConnection *con = obj->getControllingClient(); 274 275 if ( con && con->getControlObject() == obj ) 276 { 277 ExtendedMove* extMovePtr; 278 U32 numMoves; 279 ExtendedMoveList* extMoveList = static_cast<ExtendedMoveList*>(con->mMoveList); 280 extMoveList->getExtMoves( &extMovePtr, &numMoves ); 281 282 if ( numMoves == 0 ) 283 { 284 #ifdef TORQUE_DEBUG_NET_MOVES 285 Con::printf("no moves on object %i, skip tick",obj->getId()); 286 #endif 287 return; 288 } 289 } 290 } 291 292 Parent::onPreTickObject (pobj ); 293} 294 295void ExtendedServerProcessList::onTickObject( ProcessObject *pobj ) 296{ 297 PROFILE_SCOPE( ExtendedServerProcessList_OnTickObject ); 298 299 // Each object is either advanced a single tick, or if it's 300 // being controlled by a client, ticked once for each pending move. 301 302 GameConnection *con = pobj->getControllingClient(); 303 304 if ( pobj->mIsGameBase && con && con->getControlObject() == pobj ) 305 { 306 // In case the object is deleted during its own tick. 307 SimObjectPtr<GameBase> obj = getGameBase( pobj ); 308 309 ExtendedMove* extMovePtr; 310 U32 m, numMoves; 311 ExtendedMoveList* extMoveList = static_cast<ExtendedMoveList*>(con->mMoveList); 312 extMoveList->getExtMoves( &extMovePtr, &numMoves ); 313 314 // For debugging it can be useful to know when this happens. 315 //if ( numMoves > 1 ) 316 // Con::printf( "numMoves: %i", numMoves ); 317 318 // Do we really need to test the control object each iteration? Does it change? 319 for ( m = 0; m < numMoves && con && con->getControlObject() == obj; m++, extMovePtr++ ) 320 { 321 #ifdef TORQUE_DEBUG_NET_MOVES 322 U32 sum = Move::ChecksumMask & obj->getPacketDataChecksum(obj->getControllingClient()); 323 #endif 324 325 if ( obj->isTicking() ) 326 obj->processTick( extMovePtr ); 327 328 if ( con && con->getControlObject() == obj ) 329 { 330 U32 newsum = Move::ChecksumMask & obj->getPacketDataChecksum( obj->getControllingClient() ); 331 332 // check move checksum 333 if ( extMovePtr->checksum != newsum ) 334 { 335 #ifdef TORQUE_DEBUG_NET_MOVES 336 if( !obj->isAIControlled() ) 337 Con::printf("move %i checksum disagree: %i != %i, (start %i), (move %f %f %f)", 338 extMovePtr->id, extMovePtr->checksum,newsum,sum,extMovePtr->yaw,extMovePtr->y,extMovePtr->z); 339 #endif 340 341 extMovePtr->checksum = Move::ChecksumMismatch; 342 } 343 else 344 { 345 #ifdef TORQUE_DEBUG_NET_MOVES 346 Con::printf("move %i checksum agree: %i == %i, (start %i), (move %f %f %f)", 347 extMovePtr->id, extMovePtr->checksum,newsum,sum,extMovePtr->yaw,extMovePtr->y,extMovePtr->z); 348 #endif 349 } 350 } 351 } 352 353 extMoveList->clearMoves( m ); 354 } 355 else if ( pobj->isTicking() ) 356 pobj->processTick( 0 ); 357} 358 359void ExtendedServerProcessList::advanceObjects() 360{ 361 #ifdef TORQUE_DEBUG_NET_MOVES 362 Con::printf("Advance server time..."); 363 #endif 364 365 Parent::advanceObjects(); 366 367 // Credit all connections with the elapsed tick 368 SimGroup *clientGroup = Sim::getClientGroup(); 369 for(SimGroup::iterator i = clientGroup->begin(); i != clientGroup->end(); i++) 370 { 371 if (GameConnection *con = dynamic_cast<GameConnection *>(*i)) 372 { 373 con->mMoveList->advanceMove(); 374 } 375 } 376 377 #ifdef TORQUE_DEBUG_NET_MOVES 378 Con::printf("---------"); 379 #endif 380} 381