Torque3D Documentation / _generateds / extendedMoveList.cpp

extendedMoveList.cpp

Engine/source/T3D/gameBase/extended/extendedMoveList.cpp

More...

Public Defines

Detailed Description

Public Defines

MAX_MOVE_PACKET_SENDS() 4
  1
  2#include "platform/platform.h"
  3#include "T3D/gameBase/extended/extendedMoveList.h"
  4#include "T3D/gameBase/gameConnection.h"
  5#include "core/stream/bitStream.h"
  6
  7#define MAX_MOVE_PACKET_SENDS 4
  8
  9ExtendedMoveList::ExtendedMoveList()
 10{
 11   mMoveCredit = MaxMoveCount;
 12   mControlMismatch = false;
 13   reset();
 14}
 15
 16void ExtendedMoveList::reset()
 17{
 18   mLastMoveAck = 0;
 19   mLastClientMove = 0;
 20   mFirstMoveIndex = 0;
 21
 22   mExtMoveVec.clear();
 23}
 24
 25bool ExtendedMoveList::getNextExtMove( ExtendedMove &curMove )
 26{
 27   if ( mExtMoveVec.size() > MaxMoveQueueSize )
 28      return false;
 29
 30   // From MoveList
 31   F32 pitchAdd = MoveManager::mPitchUpSpeed - MoveManager::mPitchDownSpeed;
 32   F32 yawAdd = MoveManager::mYawLeftSpeed - MoveManager::mYawRightSpeed;
 33   F32 rollAdd = MoveManager::mRollRightSpeed - MoveManager::mRollLeftSpeed;
 34
 35   curMove.pitch = MoveManager::mPitch + pitchAdd;
 36   curMove.yaw = MoveManager::mYaw + yawAdd;
 37   curMove.roll = MoveManager::mRoll + rollAdd;
 38
 39   MoveManager::mPitch = 0;
 40   MoveManager::mYaw = 0;
 41   MoveManager::mRoll = 0;
 42
 43   curMove.x = MoveManager::mRightAction - MoveManager::mLeftAction + MoveManager::mXAxis_L;
 44   curMove.y = MoveManager::mForwardAction - MoveManager::mBackwardAction + MoveManager::mYAxis_L;
 45   curMove.z = MoveManager::mUpAction - MoveManager::mDownAction;
 46
 47   curMove.freeLook = MoveManager::mFreeLook;
 48   curMove.deviceIsKeyboardMouse = MoveManager::mDeviceIsKeyboardMouse;
 49
 50   for(U32 i = 0; i < MaxTriggerKeys; i++)
 51   {
 52      curMove.trigger[i] = false;
 53      if(MoveManager::mTriggerCount[i] & 1)
 54         curMove.trigger[i] = true;
 55      else if(!(MoveManager::mPrevTriggerCount[i] & 1) && MoveManager::mPrevTriggerCount[i] != MoveManager::mTriggerCount[i])
 56         curMove.trigger[i] = true;
 57      MoveManager::mPrevTriggerCount[i] = MoveManager::mTriggerCount[i];
 58   }
 59
 60   for(U32 i=0; i<ExtendedMove::MaxPositionsRotations; ++i)
 61   {
 62      // Process position
 63      curMove.posX[i] = ExtendedMoveManager::mPosX[i];
 64      curMove.posY[i] = ExtendedMoveManager::mPosY[i];
 65      curMove.posZ[i] = ExtendedMoveManager::mPosZ[i];
 66
 67      // Process rotation.  There are two possible forms of rotation: Angle Axis and Euler angles.
 68      curMove.EulerBasedRotation[i] = ExtendedMoveManager::mRotIsEuler[i];
 69      if(curMove.EulerBasedRotation[i])
 70      {
 71         // Euler angle based rotation passed in as degrees.  We only need to work with three components.
 72         curMove.rotX[i] = mDegToRad(ExtendedMoveManager::mRotAX[i]);
 73         curMove.rotY[i] = mDegToRad(ExtendedMoveManager::mRotAY[i]);
 74         curMove.rotZ[i] = mDegToRad(ExtendedMoveManager::mRotAZ[i]);
 75      }
 76      else
 77      {
 78         //Rotation is passed in as an Angle Axis in degrees.  We need to convert this into a Quat.
 79         AngAxisF q(Point3F(ExtendedMoveManager::mRotAX[i], ExtendedMoveManager::mRotAY[i], ExtendedMoveManager::mRotAZ[i]), mDegToRad(ExtendedMoveManager::mRotAA[i]));
 80         curMove.rotX[i] = q.axis.x;
 81         curMove.rotY[i] = q.axis.y;
 82         curMove.rotZ[i] = q.axis.z;
 83         curMove.rotW[i] = q.angle;
 84      }
 85   }
 86
 87   if (mConnection->getControlObject())
 88      mConnection->getControlObject()->preprocessMove(&curMove);
 89
 90   curMove.clamp();  // clamp for net traffic
 91   return true;
 92}
 93
 94U32 ExtendedMoveList::getMoves(Move** movePtr,U32* numMoves)
 95{
 96   // We don't want to be here
 97   AssertFatal(0, "getMoves() called");
 98
 99   numMoves = 0;
100
101   return 0;
102}
103
104U32 ExtendedMoveList::getExtMoves( ExtendedMove** movePtr, U32 *numMoves )
105{
106   if (!mConnection->isConnectionToServer())
107   {
108      if (mExtMoveVec.size() > mMoveCredit)
109         mExtMoveVec.setSize(mMoveCredit);
110   }
111
112   // From MoveList but converted to use mExtMoveVec
113   if (mConnection->isConnectionToServer())
114   {
115      // give back moves starting at the last client move...
116
117      AssertFatal(mLastClientMove >= mFirstMoveIndex, "Bad move request");
118      AssertFatal(mLastClientMove - mFirstMoveIndex <= mExtMoveVec.size(), "Desynched first and last move.");
119      *numMoves = mExtMoveVec.size() - mLastClientMove + mFirstMoveIndex;
120      *movePtr = mExtMoveVec.address() + mLastClientMove - mFirstMoveIndex;
121   }
122   else
123   {
124      // return the full list
125      *numMoves = mExtMoveVec.size();
126      *movePtr = mExtMoveVec.begin();
127   }
128
129   return *numMoves;
130}
131
132void ExtendedMoveList::collectMove()
133{
134   ExtendedMove mv;   
135   if (mConnection)
136   {
137      if(!mConnection->isPlayingBack() && getNextExtMove(mv))
138      {
139         mv.checksum=<a href="/coding/class/structmove/#structmove_1a7c9c5270e5adc67cfbacc428c88a865ca576cec207777350a664848a92ad8b99b">Move::ChecksumMismatch</a>;
140         pushMove(mv);
141         mConnection->recordBlock(GameConnection::BlockTypeMove, sizeof(ExtendedMove), &mv);
142      }
143   }
144   else
145   {
146      if(getNextExtMove(mv))
147      {
148         mv.checksum=<a href="/coding/class/structmove/#structmove_1a7c9c5270e5adc67cfbacc428c88a865ca576cec207777350a664848a92ad8b99b">Move::ChecksumMismatch</a>;
149         pushMove(mv);
150      }
151   }
152}
153
154void ExtendedMoveList::pushMove(const Move &mv)
155{
156   const ExtendedMove* extMove = dynamic_cast<const ExtendedMove*>(&mv);
157   AssertFatal(extMove, "Regular Move struct passed to pushMove()");
158
159   pushExtMove(*extMove);
160}
161
162void ExtendedMoveList::pushExtMove( const ExtendedMove &mv )
163{
164   U32 id = mFirstMoveIndex + mExtMoveVec.size();
165   U32 sz = mExtMoveVec.size();
166   mExtMoveVec.push_back(mv);
167   mExtMoveVec[sz].id = id;
168   mExtMoveVec[sz].sendCount = 0;
169}
170
171void ExtendedMoveList::clearMoves(U32 count)
172{
173   if (!mConnection->isConnectionToServer())
174   {
175      count = mClamp(count,0,mMoveCredit);
176      mMoveCredit -= count;
177   }
178
179   // From MoveList but converted to use mExtMoveVec
180   if (mConnection->isConnectionToServer())
181   {
182      mLastClientMove += count;
183      AssertFatal(mLastClientMove >= mFirstMoveIndex, "Bad move request");
184      AssertFatal(mLastClientMove - mFirstMoveIndex <= mExtMoveVec.size(), "Desynched first and last move.");
185      if (!mConnection)
186         // drop right away if no connection
187         ackMoves(count);
188   }
189   else 
190   {
191      AssertFatal(count <= mExtMoveVec.size(),"GameConnection: Clearing too many moves");
192      for (S32 i=0; i<count; i++)
193         if (mExtMoveVec[i].checksum == Move::ChecksumMismatch)
194            mControlMismatch = true;
195         else 
196            mControlMismatch = false;
197      if (count == mExtMoveVec.size())
198         mExtMoveVec.clear();
199      else
200         while (count--)
201            mExtMoveVec.pop_front();
202   }
203}
204
205void ExtendedMoveList::advanceMove()
206{
207   AssertFatal(!mConnection->isConnectionToServer(), "Cannot inc move credit on the client.");
208
209   // Game tick increment
210   mMoveCredit++;
211   if (mMoveCredit > MaxMoveCount)
212      mMoveCredit = MaxMoveCount;
213
214   // Clear pending moves for the elapsed time if there
215   // is no control object.
216   if ( mConnection->getControlObject() == NULL )
217      mExtMoveVec.clear();
218}
219
220void ExtendedMoveList::clientWriteMovePacket(BitStream *bstream)
221{
222   AssertFatal(mLastMoveAck == mFirstMoveIndex, "Invalid move index.");
223   U32 count = mExtMoveVec.size();
224
225   ExtendedMove* extMove = mExtMoveVec.address();
226   U32 start = mLastMoveAck;
227   U32 offset;
228   for(offset = 0; offset < count; offset++)
229      if(extMove[offset].sendCount < MAX_MOVE_PACKET_SENDS)
230         break;
231   if(offset == count && count != 0)
232      offset--;
233
234   start += offset;
235   count -= offset;
236
237   if (count > MaxMoveCount)
238      count = MaxMoveCount;
239   bstream->writeInt(start,32);
240   bstream->writeInt(count,MoveCountBits);
241   ExtendedMove* prevExtMove = NULL;
242   for (int i = 0; i < count; i++)
243   {
244      extMove[offset + i].sendCount++;
245      extMove[offset + i].pack(bstream,prevExtMove);
246      bstream->writeInt(extMove[offset + i].checksum & (~(0xFFFFFFFF << Move::ChecksumBits)),Move::ChecksumBits);
247      prevExtMove = &extMove[offset+i];
248   }
249}
250
251void ExtendedMoveList::serverReadMovePacket(BitStream *bstream)
252{
253   // Server side packet read.
254   U32 start = bstream->readInt(32);
255   U32 count = bstream->readInt(MoveCountBits);
256
257   ExtendedMove* prevExtMove = NULL;
258   ExtendedMove prevExtMoveHolder;
259
260   // Skip forward (must be starting up), or over the moves
261   // we already have.
262   int skip = mLastMoveAck - start;
263   if (skip < 0) 
264   {
265      mLastMoveAck = start;
266   }
267   else 
268   {
269      if (skip > count)
270         skip = count;
271      for (int i = 0; i < skip; i++)
272      {
273         prevExtMoveHolder.unpack(bstream,prevExtMove);
274         prevExtMoveHolder.checksum = bstream->readInt(Move::ChecksumBits);
275         prevExtMove = &prevExtMoveHolder;
276         S32 idx = mExtMoveVec.size()-skip+i;
277         if (idx>=0)
278         {
279#ifdef TORQUE_DEBUG_NET_MOVES
280            if (mExtMoveVec[idx].checksum != prevExtMoveHolder.checksum)
281               Con::printf("updated checksum on move %i from %i to %i",mExtMoveVec[idx].id,mExtMoveVec[idx].checksum,prevExtMoveHolder.checksum);
282#endif
283            mExtMoveVec[idx].checksum = prevExtMoveHolder.checksum;
284         }
285      }
286      start += skip;
287      count = count - skip;
288   }
289
290   // Put the rest on the move list.
291   int index = mExtMoveVec.size();
292   mExtMoveVec.increment(count);
293   while (index < mExtMoveVec.size())
294   {
295      mExtMoveVec[index].unpack(bstream,prevExtMove);
296      mExtMoveVec[index].checksum = bstream->readInt(Move::ChecksumBits);
297      prevExtMove = &mExtMoveVec[index];
298      mExtMoveVec[index].id = start++;
299      index ++;
300   }
301
302   mLastMoveAck += count;
303}
304
305void ExtendedMoveList::serverWriteMovePacket(BitStream * bstream)
306{
307#ifdef TORQUE_DEBUG_NET_MOVES
308   Con::printf("ack %i minus %i",mLastMoveAck,mExtMoveVec.size());
309#endif
310
311   // acknowledge only those moves that have been ticked
312   bstream->writeInt(mLastMoveAck - mExtMoveVec.size(),32);
313}
314
315void ExtendedMoveList::clientReadMovePacket(BitStream * bstream)
316{
317#ifdef TORQUE_DEBUG_NET_MOVES
318   Con::printf("pre move ack: %i", mLastMoveAck);
319#endif
320
321   mLastMoveAck = bstream->readInt(32);
322
323#ifdef TORQUE_DEBUG_NET_MOVES
324   Con::printf("post move ack %i, first move %i, last move %i", mLastMoveAck, mFirstMoveIndex, mLastClientMove);
325#endif
326
327   if (mLastMoveAck < mFirstMoveIndex)
328      mLastMoveAck = mFirstMoveIndex;
329
330   if(mLastMoveAck > mLastClientMove)
331      mLastClientMove = mLastMoveAck;
332   while(mFirstMoveIndex < mLastMoveAck)
333   {
334      if (mExtMoveVec.size())
335      {
336         mExtMoveVec.pop_front();
337         mFirstMoveIndex++;
338      }
339      else
340      {
341         AssertWarn(1, "Popping off too many moves!");
342         mFirstMoveIndex = mLastMoveAck;
343      }
344   }
345}
346
347bool ExtendedMoveList::isBacklogged()
348{
349   if ( !mConnection->isConnectionToServer() )
350      return false;
351
352   return mLastClientMove - mFirstMoveIndex == mExtMoveVec.size() && 
353          mExtMoveVec.size() >= MaxMoveCount;
354}
355
356bool ExtendedMoveList::areMovesPending()
357{
358   return mConnection->isConnectionToServer() ?
359          mExtMoveVec.size() - mLastClientMove + mFirstMoveIndex :
360          mExtMoveVec.size();
361}
362
363void ExtendedMoveList::ackMoves(U32 count)
364{
365   mLastMoveAck += count;
366   if(mLastMoveAck > mLastClientMove)
367      mLastClientMove = mLastMoveAck;
368   while(mFirstMoveIndex < mLastMoveAck)
369   {
370      if (mExtMoveVec.size())
371      {
372         mExtMoveVec.pop_front();
373         mFirstMoveIndex++;
374      }
375      else
376      {
377         AssertWarn(1, "Popping off too many moves!");
378         mFirstMoveIndex = mLastMoveAck;
379      }
380   }
381}
382