stdGameProcess.cpp
Engine/source/T3D/gameBase/std/stdGameProcess.cpp
Public Variables
Detailed Description
Public Variables
MODULE_END
MODULE_INIT
MODULE_SHUTDOWN
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "platform/platform.h" 25#include "T3D/gameBase/std/stdGameProcess.h" 26 27#include "platform/profiler.h" 28#include "console/consoleTypes.h" 29#include "core/dnet.h" 30#include "core/stream/bitStream.h" 31#include "core/frameAllocator.h" 32#include "core/util/refBase.h" 33#include "math/mPoint3.h" 34#include "math/mMatrix.h" 35#include "math/mathUtils.h" 36#include "T3D/gameBase/gameBase.h" 37#include "T3D/gameBase/gameConnection.h" 38#include "T3D/gameBase/std/stdMoveList.h" 39#include "T3D/fx/cameraFXMgr.h" 40 41#ifdef TORQUE_EXPERIMENTAL_EC 42#include "T3D/components/coreInterfaces.h" 43#include "T3D/components/component.h" 44#endif 45 46MODULE_BEGIN( ProcessList ) 47 48 MODULE_INIT 49 { 50 StdServerProcessList::init(); 51 StdClientProcessList::init(); 52 } 53 54 MODULE_SHUTDOWN 55 { 56 StdServerProcessList::shutdown(); 57 StdClientProcessList::shutdown(); 58 } 59 60MODULE_END; 61 62void StdServerProcessList::init() 63{ 64 smServerProcessList = new StdServerProcessList(); 65} 66 67void StdServerProcessList::shutdown() 68{ 69 delete smServerProcessList; 70} 71 72void StdClientProcessList::init() 73{ 74 smClientProcessList = new StdClientProcessList(); 75} 76 77void StdClientProcessList::shutdown() 78{ 79 delete smClientProcessList; 80} 81 82//---------------------------------------------------------------------------- 83 84 85namespace 86{ 87 // local work class 88 struct GameBaseListNode 89 { 90 GameBaseListNode() 91 { 92 mPrev=this; 93 mNext=this; 94 mObject=<a href="/coding/file/types_8lint_8h/#types_8lint_8h_1a070d2ce7b6bb7e5c05602aa8c308d0c4">NULL</a>; 95 } 96 97 GameBaseListNode * mPrev; 98 GameBaseListNode * mNext; 99 GameBase * mObject; 100 101 void linkBefore(GameBaseListNode * obj) 102 { 103 // Link this before obj 104 mNext = obj; 105 mPrev = obj->mPrev; 106 obj->mPrev = this; 107 mPrev->mNext = this; 108 } 109 }; 110} // namespace 111 112//-------------------------------------------------------------------------- 113// ClientProcessList 114//-------------------------------------------------------------------------- 115 116StdClientProcessList::StdClientProcessList() 117{ 118} 119 120bool StdClientProcessList::advanceTime( SimTime timeDelta ) 121{ 122 PROFILE_SCOPE( StdClientProcessList_AdvanceTime ); 123 124 if ( doBacklogged( timeDelta ) ) 125 return false; 126 127 bool ret = Parent::advanceTime( timeDelta ); 128 ProcessObject *obj = NULL; 129 130 AssertFatal( mLastDelta >= 0.0f && mLastDelta <= 1.0f, "mLastDelta is not zero to one."); 131 132 obj = mHead.mProcessLink.next; 133 while ( obj != &mHead ) 134 { 135 if ( obj->isTicking() ) 136 obj->interpolateTick( mLastDelta ); 137 138 obj = obj->mProcessLink.next; 139 } 140 141#ifdef TORQUE_EXPERIMENTAL_EC 142 for (U32 i = 0; i < UpdateInterface::all.size(); i++) 143 { 144 Component *comp = dynamic_cast<Component*>(UpdateInterface::all[i]); 145 146 if (!comp->isClientObject() || !comp->isActive()) 147 continue; 148 149 UpdateInterface::all[i]->interpolateTick(mLastDelta); 150 } 151#endif 152 153 // Inform objects of total elapsed delta so they can advance 154 // client side animations. 155 F32 dt = F32(timeDelta) / 1000; 156 157 // Update camera FX. 158 gCamFXMgr.update( dt ); 159 160 obj = mHead.mProcessLink.next; 161 while ( obj != &mHead ) 162 { 163 obj->advanceTime( dt ); 164 obj = obj->mProcessLink.next; 165 } 166 167#ifdef TORQUE_EXPERIMENTAL_EC 168 for (U32 i = 0; i < UpdateInterface::all.size(); i++) 169 { 170 Component *comp = dynamic_cast<Component*>(UpdateInterface::all[i]); 171 172 if (comp) 173 { 174 if (!comp->isClientObject() || !comp->isActive()) 175 continue; 176 } 177 178 UpdateInterface::all[i]->advanceTime(dt); 179 } 180#endif 181 182 return ret; 183} 184 185//---------------------------------------------------------------------------- 186void StdClientProcessList::onAdvanceObjects() 187{ 188 PROFILE_SCOPE( StdClientProcessList_OnAdvanceObjects ); 189 190 GameConnection* connection = GameConnection::getConnectionToServer(); 191 if ( connection ) 192 { 193 // process any demo blocks that are NOT moves, and exactly one move 194 // we advance time in the demo stream by a move inserted on 195 // each tick. So before doing the tick processing we advance 196 // the demo stream until a move is ready 197 if ( connection->isPlayingBack() ) 198 { 199 U32 blockType; 200 do 201 { 202 blockType = connection->getNextBlockType(); 203 bool res = connection->processNextBlock(); 204 // if there are no more blocks, exit out of this function, 205 // as no more client time needs to process right now - we'll 206 // get it all on the next advanceClientTime() 207 if(!res) 208 return; 209 } 210 while ( blockType != GameConnection::BlockTypeMove ); 211 } 212 213 connection->mMoveList->collectMove(); 214 advanceObjects(); 215 } 216 else 217 advanceObjects(); 218} 219 220void StdClientProcessList::onTickObject( ProcessObject *obj ) 221{ 222 PROFILE_SCOPE( StdClientProcessList_OnTickObject ); 223 224 // In case the object deletes itself during its processTick. 225 SimObjectPtr<SceneObject> safePtr = static_cast<SceneObject*>( obj ); 226 227 // Each object is either advanced a single tick, or if it's 228 // being controlled by a client, ticked once for each pending move. 229 Move* movePtr; 230 U32 numMoves; 231 GameConnection* con = obj->getControllingClient(); 232 if ( con && con->getControlObject() == obj ) 233 { 234 con->mMoveList->getMoves( &movePtr, &numMoves ); 235 if ( numMoves ) 236 { 237 // Note: should only have a single move at this point 238 AssertFatal(numMoves==1,"ClientProccessList::onTickObject: more than one move in queue"); 239 240 #ifdef TORQUE_DEBUG_NET_MOVES 241 U32 sum = Move::ChecksumMask & obj->getPacketDataChecksum(obj->getControllingClient()); 242 #endif 243 244 if ( obj->isTicking() ) 245 obj->processTick( movePtr ); 246 247 if ( bool(safePtr) && obj->getControllingClient() ) 248 { 249 U32 newsum = Move::ChecksumMask & obj->getPacketDataChecksum( obj->getControllingClient() ); 250 251 // set checksum if not set or check against stored value if set 252 movePtr->checksum = newsum; 253 254 #ifdef TORQUE_DEBUG_NET_MOVES 255 Con::printf("move checksum: %i, (start %i), (move %f %f %f)", 256 movePtr->checksum,sum,movePtr->yaw,movePtr->y,movePtr->z); 257 #endif 258 } 259 con->mMoveList->clearMoves( 1 ); 260 } 261 } 262 else if ( obj->isTicking() ) 263 obj->processTick( 0 ); 264} 265 266void StdClientProcessList::advanceObjects() 267{ 268 PROFILE_SCOPE( StdClientProcessList_AdvanceObjects ); 269 270 #ifdef TORQUE_DEBUG_NET_MOVES 271 Con::printf("Advance client time..."); 272 #endif 273 274 Parent::advanceObjects(); 275 276 #ifdef TORQUE_DEBUG_NET_MOVES 277 Con::printf("---------"); 278 #endif 279} 280 281void StdClientProcessList::clientCatchup( GameConnection * connection ) 282{ 283 SimObjectPtr<GameBase> control = connection->getControlObject(); 284 if ( control ) 285 { 286 Move * movePtr; 287 U32 numMoves; 288 U32 m = 0; 289 connection->mMoveList->getMoves( &movePtr, &numMoves ); 290 291 #ifdef TORQUE_DEBUG_NET_MOVES 292 Con::printf("client catching up... (%i)", numMoves); 293 #endif 294 295 preTickSignal().trigger(); 296 297 if ( control->isTicking() ) 298 for ( m = 0; m < numMoves; m++ ) 299 control->processTick( movePtr++ ); 300 301 connection->mMoveList->clearMoves( m ); 302 } 303 304 #ifdef TORQUE_DEBUG_NET_MOVES 305 Con::printf("---------"); 306 #endif 307} 308 309//-------------------------------------------------------------------------- 310// ServerProcessList 311//-------------------------------------------------------------------------- 312 313StdServerProcessList::StdServerProcessList() 314{ 315} 316 317void StdServerProcessList::onPreTickObject( ProcessObject *pobj ) 318{ 319 if ( pobj->mIsGameBase ) 320 { 321 SimObjectPtr<GameBase> obj = getGameBase( pobj ); 322 323 // Each object is either advanced a single tick, or if it's 324 // being controlled by a client, ticked once for each pending move. 325 GameConnection *con = obj->getControllingClient(); 326 327 if ( con && con->getControlObject() == obj ) 328 { 329 Move* movePtr; 330 U32 numMoves; 331 con->mMoveList->getMoves( &movePtr, &numMoves ); 332 333 if ( numMoves == 0 ) 334 { 335 #ifdef TORQUE_DEBUG_NET_MOVES 336 Con::printf("no moves on object %i, skip tick",obj->getId()); 337 #endif 338 return; 339 } 340 } 341 } 342 343 Parent::onPreTickObject (pobj ); 344} 345 346void StdServerProcessList::onTickObject( ProcessObject *pobj ) 347{ 348 PROFILE_SCOPE( StdServerProcessList_OnTickObject ); 349 350 // Each object is either advanced a single tick, or if it's 351 // being controlled by a client, ticked once for each pending move. 352 353 GameConnection *con = pobj->getControllingClient(); 354 355 if ( pobj->mIsGameBase && con && con->getControlObject() == pobj ) 356 { 357 // In case the object is deleted during its own tick. 358 SimObjectPtr<GameBase> obj = getGameBase( pobj ); 359 360 Move* movePtr; 361 U32 m, numMoves; 362 con->mMoveList->getMoves( &movePtr, &numMoves ); 363 364 // For debugging it can be useful to know when this happens. 365 //if ( numMoves > 1 ) 366 // Con::printf( "numMoves: %i", numMoves ); 367 368 // Do we really need to test the control object each iteration? Does it change? 369 for ( m = 0; m < numMoves && con && con->getControlObject() == obj; m++, movePtr++ ) 370 { 371 #ifdef TORQUE_DEBUG_NET_MOVES 372 U32 sum = Move::ChecksumMask & obj->getPacketDataChecksum(obj->getControllingClient()); 373 #endif 374 375 if ( obj->isTicking() ) 376 obj->processTick( movePtr ); 377 378 if ( con && con->getControlObject() == obj ) 379 { 380 U32 newsum = Move::ChecksumMask & obj->getPacketDataChecksum( obj->getControllingClient() ); 381 382 // check move checksum 383 if ( movePtr->checksum != newsum ) 384 { 385 #ifdef TORQUE_DEBUG_NET_MOVES 386 if( !obj->isAIControlled() ) 387 Con::printf("move %i checksum disagree: %i != %i, (start %i), (move %f %f %f)", 388 movePtr->id, movePtr->checksum,newsum,sum,movePtr->yaw,movePtr->y,movePtr->z); 389 #endif 390 391 movePtr->checksum = Move::ChecksumMismatch; 392 } 393 else 394 { 395 #ifdef TORQUE_DEBUG_NET_MOVES 396 Con::printf("move %i checksum agree: %i == %i, (start %i), (move %f %f %f)", 397 movePtr->id, movePtr->checksum,newsum,sum,movePtr->yaw,movePtr->y,movePtr->z); 398 #endif 399 } 400 } 401 } 402 403 con->mMoveList->clearMoves( m ); 404 } 405 else if ( pobj->isTicking() ) 406 pobj->processTick( 0 ); 407} 408 409void StdServerProcessList::advanceObjects() 410{ 411 #ifdef TORQUE_DEBUG_NET_MOVES 412 Con::printf("Advance server time..."); 413 #endif 414 415 Parent::advanceObjects(); 416 417 // Credit all connections with the elapsed tick 418 SimGroup *clientGroup = Sim::getClientGroup(); 419 for(SimGroup::iterator i = clientGroup->begin(); i != clientGroup->end(); i++) 420 { 421 if (GameConnection *con = dynamic_cast<GameConnection *>(*i)) 422 { 423 con->mMoveList->advanceMove(); 424 } 425 } 426 427 #ifdef TORQUE_DEBUG_NET_MOVES 428 Con::printf("---------"); 429 #endif 430} 431 432 433 434
