moveList.cpp

Engine/source/T3D/gameBase/moveList.cpp

More...

Detailed Description

  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 "T3D/gameBase/moveList.h"
 25#include "T3D/gameBase/gameConnection.h"
 26#include "core/stream/bitStream.h"
 27
 28MoveList::MoveList()
 29{
 30   mConnection = NULL;
 31   mControlMismatch = false;
 32   reset();
 33}
 34
 35void MoveList::reset()
 36{
 37   mLastMoveAck = 0;
 38   mLastClientMove = 0;
 39   mFirstMoveIndex = 0;
 40   mMoveVec.clear();
 41}
 42
 43bool MoveList::getNextMove(Move &curMove)
 44{
 45   if ( mMoveVec.size() > MaxMoveQueueSize )
 46      return false;
 47
 48   F32 pitchAdd = MoveManager::mPitchUpSpeed - MoveManager::mPitchDownSpeed;
 49   F32 yawAdd = MoveManager::mYawLeftSpeed - MoveManager::mYawRightSpeed;
 50   F32 rollAdd = MoveManager::mRollRightSpeed - MoveManager::mRollLeftSpeed;
 51
 52   curMove.pitch = MoveManager::mPitch + pitchAdd;
 53   curMove.yaw = MoveManager::mYaw + yawAdd;
 54   curMove.roll = MoveManager::mRoll + rollAdd;
 55
 56   MoveManager::mPitch = 0;
 57   MoveManager::mYaw = 0;
 58   MoveManager::mRoll = 0;
 59
 60   curMove.x = MoveManager::mRightAction - MoveManager::mLeftAction + MoveManager::mXAxis_L;
 61   curMove.y = MoveManager::mForwardAction - MoveManager::mBackwardAction + MoveManager::mYAxis_L;
 62   curMove.z = MoveManager::mUpAction - MoveManager::mDownAction;
 63
 64   curMove.freeLook = MoveManager::mFreeLook;
 65   curMove.deviceIsKeyboardMouse = MoveManager::mDeviceIsKeyboardMouse;
 66
 67   for(U32 i = 0; i < MaxTriggerKeys; i++)
 68   {
 69      curMove.trigger[i] = false;
 70      if(MoveManager::mTriggerCount[i] & 1)
 71         curMove.trigger[i] = true;
 72      else if(!(MoveManager::mPrevTriggerCount[i] & 1) && MoveManager::mPrevTriggerCount[i] != MoveManager::mTriggerCount[i])
 73         curMove.trigger[i] = true;
 74      MoveManager::mPrevTriggerCount[i] = MoveManager::mTriggerCount[i];
 75   }
 76
 77   if (mConnection->getControlObject())
 78      mConnection->getControlObject()->preprocessMove(&curMove);
 79
 80   curMove.clamp();  // clamp for net traffic
 81   return true;
 82}
 83
 84void MoveList::pushMove(const Move &mv)
 85{
 86   U32 id = mFirstMoveIndex + mMoveVec.size();
 87   U32 sz = mMoveVec.size();
 88   mMoveVec.push_back(mv);
 89   mMoveVec[sz].id = id;
 90   mMoveVec[sz].sendCount = 0;
 91}
 92
 93U32 MoveList::getMoves(Move** movePtr,U32* numMoves)
 94{
 95   if (mConnection->isConnectionToServer())
 96   {
 97      // give back moves starting at the last client move...
 98
 99      AssertFatal(mLastClientMove >= mFirstMoveIndex, "Bad move request");
100      AssertFatal(mLastClientMove - mFirstMoveIndex <= mMoveVec.size(), "Desynched first and last move.");
101      *numMoves = mMoveVec.size() - mLastClientMove + mFirstMoveIndex;
102      *movePtr = mMoveVec.address() + mLastClientMove - mFirstMoveIndex;
103   }
104   else
105   {
106      // return the full list
107      *numMoves = mMoveVec.size();
108      *movePtr = mMoveVec.begin();
109   }
110
111   return *numMoves;
112}
113
114void MoveList::collectMove()
115{
116   Move mv;   
117   if (mConnection)
118   {
119      if(!mConnection->isPlayingBack() && getNextMove(mv))
120      {
121         mv.checksum=<a href="/coding/class/structmove/#structmove_1a7c9c5270e5adc67cfbacc428c88a865ca576cec207777350a664848a92ad8b99b">Move::ChecksumMismatch</a>;
122         pushMove(mv);
123         mConnection->recordBlock(GameConnection::BlockTypeMove, sizeof(Move), &mv);
124      }
125   }
126   else
127   {
128      if(getNextMove(mv))
129      {
130         mv.checksum=<a href="/coding/class/structmove/#structmove_1a7c9c5270e5adc67cfbacc428c88a865ca576cec207777350a664848a92ad8b99b">Move::ChecksumMismatch</a>;
131         pushMove(mv);
132      }
133   }
134}
135
136void MoveList::clearMoves(U32 count)
137{
138   if (mConnection->isConnectionToServer())
139   {
140      mLastClientMove += count;
141      AssertFatal(mLastClientMove >= mFirstMoveIndex, "Bad move request");
142      AssertFatal(mLastClientMove - mFirstMoveIndex <= mMoveVec.size(), "Desynched first and last move.");
143      if (!mConnection)
144         // drop right away if no connection
145         ackMoves(count);
146   }
147   else 
148   {
149      AssertFatal(count <= mMoveVec.size(),"GameConnection: Clearing too many moves");
150      for (S32 i=0; i<count; i++)
151         if (mMoveVec[i].checksum == Move::ChecksumMismatch)
152            mControlMismatch = true;
153         else 
154            mControlMismatch = false;
155      if (count == mMoveVec.size())
156         mMoveVec.clear();
157      else
158         while (count--)
159            mMoveVec.pop_front();
160   }
161}
162
163bool MoveList::areMovesPending()
164{
165   return mConnection->isConnectionToServer() ?
166          mMoveVec.size() - mLastClientMove + mFirstMoveIndex :
167          mMoveVec.size();
168}
169
170bool MoveList::isBacklogged()
171{
172   if ( !mConnection->isConnectionToServer() )
173      return false;
174
175   return mLastClientMove - mFirstMoveIndex == mMoveVec.size() && 
176          mMoveVec.size() >= MaxMoveCount;
177}
178
179void MoveList::ackMoves(U32 count)
180{
181   mLastMoveAck += count;
182   if(mLastMoveAck > mLastClientMove)
183      mLastClientMove = mLastMoveAck;
184   while(mFirstMoveIndex < mLastMoveAck)
185   {
186      if (mMoveVec.size())
187      {
188         mMoveVec.pop_front();
189         mFirstMoveIndex++;
190      }
191      else
192      {
193         AssertWarn(1, "Popping off too many moves!");
194         mFirstMoveIndex = mLastMoveAck;
195      }
196   }
197}
198
199void MoveList::writeDemoStartBlock(ResizeBitStream *stream)
200{
201   stream->write(mLastMoveAck);
202   stream->write(mLastClientMove);
203   stream->write(mFirstMoveIndex);
204
205   stream->write(U32(mMoveVec.size()));
206   for(U32 j = 0; j < mMoveVec.size(); j++)
207      mMoveVec[j].pack(stream);
208}
209
210void MoveList::readDemoStartBlock(BitStream *stream)
211{
212   stream->read(&mLastMoveAck);
213   stream->read(&mLastClientMove);
214   stream->read(&mFirstMoveIndex);
215
216   U32 size;
217   Move mv;
218   stream->read(&size);
219   mMoveVec.clear();
220   while(size--)
221   {
222      mv.unpack(stream);
223      pushMove(mv);
224   }
225}
226