moveList.cpp
Engine/source/T3D/gameBase/moveList.cpp
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