extendedMoveList.cpp
Engine/source/T3D/gameBase/extended/extendedMoveList.cpp
Public Defines
define
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