Torque3D Documentation / _generateds / stdGameProcess.cpp

stdGameProcess.cpp

Engine/source/T3D/gameBase/std/stdGameProcess.cpp

More...

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