Game_network.cpp 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #include "../idlib/precompiled.h"
  21. #pragma hdrstop
  22. #include "Game_local.h"
  23. #include "..\framework\Common_local.h"
  24. static const int SNAP_GAMESTATE = 0;
  25. static const int SNAP_SHADERPARMS = 1;
  26. static const int SNAP_PORTALS = 2;
  27. static const int SNAP_PLAYERSTATE = SNAP_PORTALS + 1;
  28. static const int SNAP_PLAYERSTATE_END = SNAP_PLAYERSTATE + MAX_PLAYERS;
  29. static const int SNAP_ENTITIES = SNAP_PLAYERSTATE_END;
  30. static const int SNAP_ENTITIES_END = SNAP_ENTITIES + MAX_GENTITIES;
  31. static const int SNAP_LAST_CLIENT_FRAME = SNAP_ENTITIES_END;
  32. static const int SNAP_LAST_CLIENT_FRAME_END = SNAP_LAST_CLIENT_FRAME + MAX_PLAYERS;
  33. /*
  34. ===============================================================================
  35. Client running game code:
  36. - entity events don't work and should not be issued
  37. - entities should never be spawned outside idGameLocal::ClientReadSnapshot
  38. ===============================================================================
  39. */
  40. idCVar net_clientSmoothing( "net_clientSmoothing", "0.8", CVAR_GAME | CVAR_FLOAT, "smooth other clients angles and position.", 0.0f, 0.95f );
  41. idCVar net_clientSelfSmoothing( "net_clientSelfSmoothing", "0.6", CVAR_GAME | CVAR_FLOAT, "smooth self position if network causes prediction error.", 0.0f, 0.95f );
  42. extern idCVar net_clientMaxPrediction;
  43. idCVar cg_predictedSpawn_debug( "cg_predictedSpawn_debug", "0", CVAR_BOOL, "Debug predictive spawning of presentables" );
  44. idCVar g_clientFire_checkLineOfSightDebug( "g_clientFire_checkLineOfSightDebug", "0", CVAR_BOOL, "" );
  45. /*
  46. ================
  47. idGameLocal::InitAsyncNetwork
  48. ================
  49. */
  50. void idGameLocal::InitAsyncNetwork() {
  51. eventQueue.Init();
  52. savedEventQueue.Init();
  53. entityDefBits = -( idMath::BitsForInteger( declManager->GetNumDecls( DECL_ENTITYDEF ) ) + 1 );
  54. realClientTime = 0;
  55. fast.Set( 0, 0, 0 );
  56. slow.Set( 0, 0, 0 );
  57. isNewFrame = true;
  58. clientSmoothing = net_clientSmoothing.GetFloat();
  59. lastCmdRunTimeOnClient.Zero();
  60. lastCmdRunTimeOnServer.Zero();
  61. usercmdLastClientMilliseconds.Zero();
  62. }
  63. /*
  64. ================
  65. idGameLocal::ShutdownAsyncNetwork
  66. ================
  67. */
  68. void idGameLocal::ShutdownAsyncNetwork() {
  69. eventQueue.Shutdown();
  70. savedEventQueue.Shutdown();
  71. }
  72. /*
  73. ================
  74. idGameLocal::ServerRemapDecl
  75. ================
  76. */
  77. int idGameLocal::ServerRemapDecl( int clientNum, declType_t type, int index ) {
  78. return index;
  79. }
  80. /*
  81. ================
  82. idGameLocal::ClientRemapDecl
  83. ================
  84. */
  85. int idGameLocal::ClientRemapDecl( declType_t type, int index ) {
  86. return index;
  87. }
  88. /*
  89. ================
  90. idGameLocal::SyncPlayersWithLobbyUsers
  91. ================
  92. */
  93. void idGameLocal::SyncPlayersWithLobbyUsers( bool initial ) {
  94. idLobbyBase & lobby = session->GetActingGameStateLobbyBase();
  95. if ( !lobby.IsHost() ) {
  96. return;
  97. }
  98. idStaticList< lobbyUserID_t, MAX_CLIENTS > newLobbyUsers;
  99. // First, loop over lobby users, and see if we find a lobby user that we haven't registered
  100. for ( int i = 0; i < lobby.GetNumLobbyUsers(); i++ ) {
  101. lobbyUserID_t lobbyUserID1 = lobby.GetLobbyUserIdByOrdinal( i );
  102. if ( !lobbyUserID1.IsValid() ) {
  103. continue;
  104. }
  105. if ( !initial && !lobby.IsLobbyUserLoaded( lobbyUserID1 ) ) {
  106. continue;
  107. }
  108. // Now, see if we find this lobby user in our list
  109. bool found = false;
  110. for ( int j = 0; j < MAX_PLAYERS; j++ ) {
  111. idPlayer * player = static_cast<idPlayer *>( entities[ j ] );
  112. if ( player == NULL ) {
  113. continue;
  114. }
  115. lobbyUserID_t lobbyUserID2 = lobbyUserIDs[j];
  116. if ( lobbyUserID1 == lobbyUserID2 ) {
  117. found = true;
  118. break;
  119. }
  120. }
  121. if ( !found ) {
  122. // If we didn't find it, we need to create a player and assign it to this new lobby user
  123. newLobbyUsers.Append( lobbyUserID1 );
  124. }
  125. }
  126. // Validate connected players
  127. for ( int i = 0; i < MAX_PLAYERS; i++ ) {
  128. idPlayer * player = static_cast<idPlayer *>( entities[ i ] );
  129. if ( player == NULL ) {
  130. continue;
  131. }
  132. lobbyUserID_t lobbyUserID = lobbyUserIDs[i];
  133. if ( !lobby.IsLobbyUserValid( lobbyUserID ) ) {
  134. delete entities[ i ];
  135. mpGame.DisconnectClient( i );
  136. lobbyUserIDs[i] = lobbyUserID_t();
  137. continue;
  138. }
  139. lobby.EnableSnapshotsForLobbyUser( lobbyUserID );
  140. }
  141. while ( newLobbyUsers.Num() > 0 ) {
  142. // Find a free player data slot to use for this new player
  143. int freePlayerDataIndex = -1;
  144. for ( int i = 0; i < MAX_PLAYERS; ++i ) {
  145. idPlayer * player = static_cast<idPlayer *>( entities[ i ] );
  146. if ( player == NULL ) {
  147. freePlayerDataIndex = i;
  148. break;
  149. }
  150. }
  151. if ( freePlayerDataIndex == -1 ) {
  152. break; // No player data slots (this shouldn't happen)
  153. }
  154. lobbyUserID_t lobbyUserID = newLobbyUsers[0];
  155. newLobbyUsers.RemoveIndex( 0 );
  156. mpGame.ServerClientConnect( freePlayerDataIndex );
  157. Printf( "client %d connected.\n", freePlayerDataIndex );
  158. lobbyUserIDs[ freePlayerDataIndex ] = lobbyUserID;
  159. // Clear this player's old usercmds.
  160. common->ResetPlayerInput( freePlayerDataIndex );
  161. common->UpdateLevelLoadPacifier();
  162. // spawn the player
  163. SpawnPlayer( freePlayerDataIndex );
  164. common->UpdateLevelLoadPacifier();
  165. ServerWriteInitialReliableMessages( freePlayerDataIndex, lobbyUserID );
  166. }
  167. }
  168. /*
  169. ================
  170. idGameLocal::ServerSendNetworkSyncCvars
  171. ================
  172. */
  173. void idGameLocal::ServerSendNetworkSyncCvars() {
  174. if ( ( cvarSystem->GetModifiedFlags() & CVAR_NETWORKSYNC ) == 0 ) {
  175. return;
  176. }
  177. cvarSystem->ClearModifiedFlags( CVAR_NETWORKSYNC );
  178. idBitMsg outMsg;
  179. byte msgBuf[MAX_GAME_MESSAGE_SIZE];
  180. idLobbyBase & lobby = session->GetActingGameStateLobbyBase();
  181. outMsg.InitWrite( msgBuf, sizeof( msgBuf ) );
  182. outMsg.BeginWriting();
  183. idDict syncedCvars;
  184. cvarSystem->MoveCVarsToDict( CVAR_NETWORKSYNC, syncedCvars, true );
  185. outMsg.WriteDeltaDict( syncedCvars, NULL );
  186. lobby.SendReliable( GAME_RELIABLE_MESSAGE_SYNCEDCVARS, outMsg, false );
  187. idLib::Printf( "Sending networkSync cvars:\n" );
  188. syncedCvars.Print();
  189. }
  190. /*
  191. ================
  192. idGameLocal::ServerWriteInitialReliableMessages
  193. Send reliable messages to initialize the client game up to a certain initial state.
  194. ================
  195. */
  196. void idGameLocal::ServerWriteInitialReliableMessages( int clientNum, lobbyUserID_t lobbyUserID ) {
  197. if ( clientNum == GetLocalClientNum() ) {
  198. // We don't need to send messages to ourself
  199. return;
  200. }
  201. idBitMsg outMsg;
  202. byte msgBuf[MAX_GAME_MESSAGE_SIZE];
  203. idLobbyBase & lobby = session->GetActingGameStateLobbyBase();
  204. outMsg.InitWrite( msgBuf, sizeof( msgBuf ) );
  205. outMsg.BeginWriting();
  206. idDict syncedCvars;
  207. cvarSystem->MoveCVarsToDict( CVAR_NETWORKSYNC, syncedCvars, true );
  208. outMsg.WriteDeltaDict( syncedCvars, NULL );
  209. lobby.SendReliableToLobbyUser( lobbyUserID, GAME_RELIABLE_MESSAGE_SYNCEDCVARS, outMsg );
  210. idLib::Printf( "Sending initial networkSync cvars:\n" );
  211. syncedCvars.Print();
  212. // send all saved events
  213. for ( entityNetEvent_t * event = savedEventQueue.Start(); event; event = event->next ) {
  214. outMsg.InitWrite( msgBuf, sizeof( msgBuf ) );
  215. outMsg.BeginWriting();
  216. outMsg.WriteBits( event->spawnId, 32 );
  217. outMsg.WriteByte( event->event );
  218. outMsg.WriteLong( event->time );
  219. outMsg.WriteBits( event->paramsSize, idMath::BitsForInteger( MAX_EVENT_PARAM_SIZE ) );
  220. if ( event->paramsSize ) {
  221. outMsg.WriteData( event->paramsBuf, event->paramsSize );
  222. }
  223. lobby.SendReliableToLobbyUser( lobbyUserID, GAME_RELIABLE_MESSAGE_EVENT, outMsg );
  224. }
  225. mpGame.ServerWriteInitialReliableMessages( clientNum, lobbyUserID );
  226. }
  227. /*
  228. ================
  229. idGameLocal::SaveEntityNetworkEvent
  230. ================
  231. */
  232. void idGameLocal::SaveEntityNetworkEvent( const idEntity *ent, int eventId, const idBitMsg *msg ) {
  233. entityNetEvent_t * event = savedEventQueue.Alloc();
  234. event->spawnId = GetSpawnId( ent );
  235. event->event = eventId;
  236. event->time = time;
  237. if ( msg ) {
  238. event->paramsSize = msg->GetSize();
  239. memcpy( event->paramsBuf, msg->GetReadData(), msg->GetSize() );
  240. } else {
  241. event->paramsSize = 0;
  242. }
  243. savedEventQueue.Enqueue( event, idEventQueue::OUTOFORDER_IGNORE );
  244. }
  245. /*
  246. ================
  247. idGameLocal::ServerWriteSnapshot
  248. Write a snapshot of the current game state
  249. ================
  250. */
  251. void idGameLocal::ServerWriteSnapshot( idSnapShot & ss ) {
  252. ss.SetTime( fast.time );
  253. byte buffer[ MAX_ENTITY_STATE_SIZE ];
  254. idBitMsg msg;
  255. // First write the generic game state to the snapshot
  256. msg.InitWrite( buffer, sizeof( buffer ) );
  257. mpGame.WriteToSnapshot( msg );
  258. ss.S_AddObject( SNAP_GAMESTATE, ~0U, msg, "Game State" );
  259. // Update global shader parameters
  260. msg.InitWrite( buffer, sizeof( buffer ) );
  261. for ( int i = 0; i < MAX_GLOBAL_SHADER_PARMS; i++ ) {
  262. msg.WriteFloat( globalShaderParms[i] );
  263. }
  264. ss.S_AddObject( SNAP_SHADERPARMS, ~0U, msg, "Shader Parms" );
  265. // update portals for opened doors
  266. msg.InitWrite( buffer, sizeof( buffer ) );
  267. int numPortals = gameRenderWorld->NumPortals();
  268. msg.WriteLong( numPortals );
  269. for ( int i = 0; i < numPortals; i++ ) {
  270. msg.WriteBits( gameRenderWorld->GetPortalState( (qhandle_t) (i+1) ) , NUM_RENDER_PORTAL_BITS );
  271. }
  272. ss.S_AddObject( SNAP_PORTALS, ~0U, msg, "Portal State" );
  273. idEntity * skyEnt = portalSkyEnt.GetEntity();
  274. pvsHandle_t portalSkyPVS;
  275. portalSkyPVS.i = -1;
  276. if ( skyEnt != NULL ) {
  277. portalSkyPVS = pvs.SetupCurrentPVS( skyEnt->GetPVSAreas(), skyEnt->GetNumPVSAreas() );
  278. }
  279. // Build PVS data for each player and write their player state to the snapshot as well
  280. pvsHandle_t pvsHandles[ MAX_PLAYERS ];
  281. for ( int i = 0; i < MAX_PLAYERS; i++ ) {
  282. idPlayer * player = static_cast<idPlayer *>( entities[ i ] );
  283. if ( player == NULL ) {
  284. pvsHandles[i].i = -1;
  285. continue;
  286. }
  287. idPlayer * spectated = player;
  288. if ( player->spectating && player->spectator != i && entities[ player->spectator ] ) {
  289. spectated = static_cast< idPlayer * >( entities[ player->spectator ] );
  290. }
  291. msg.InitWrite( buffer, sizeof( buffer ) );
  292. spectated->WritePlayerStateToSnapshot( msg );
  293. ss.S_AddObject( SNAP_PLAYERSTATE + i, ~0U, msg, "Player State" );
  294. int sourceAreas[ idEntity::MAX_PVS_AREAS ];
  295. int numSourceAreas = gameRenderWorld->BoundsInAreas( spectated->GetPlayerPhysics()->GetAbsBounds(), sourceAreas, idEntity::MAX_PVS_AREAS );
  296. pvsHandles[i] = pvs.SetupCurrentPVS( sourceAreas, numSourceAreas, PVS_NORMAL );
  297. if ( portalSkyPVS.i >= 0 ) {
  298. pvsHandle_t tempPVS = pvs.MergeCurrentPVS( pvsHandles[i], portalSkyPVS );
  299. pvs.FreeCurrentPVS( pvsHandles[i] );
  300. pvsHandles[i] = tempPVS;
  301. }
  302. // Write the last usercmd processed by the server so that clients know
  303. // when to stop predicting.
  304. msg.BeginWriting();
  305. msg.WriteLong( usercmdLastClientMilliseconds[i] );
  306. ss.S_AddObject( SNAP_LAST_CLIENT_FRAME + i, ~0U, msg, "Last client frame" );
  307. }
  308. if ( portalSkyPVS.i >= 0 ) {
  309. pvs.FreeCurrentPVS( portalSkyPVS );
  310. }
  311. // Add all entities to the snapshot
  312. for ( idEntity * ent = spawnedEntities.Next(); ent != NULL; ent = ent->spawnNode.Next() ) {
  313. if ( ent->GetSkipReplication() ) {
  314. continue;
  315. }
  316. msg.InitWrite( buffer, sizeof( buffer ) );
  317. msg.WriteBits( spawnIds[ ent->entityNumber ], 32 - GENTITYNUM_BITS );
  318. msg.WriteBits( ent->GetType()->typeNum, idClass::GetTypeNumBits() );
  319. msg.WriteBits( ServerRemapDecl( -1, DECL_ENTITYDEF, ent->entityDefNumber ), entityDefBits );
  320. msg.WriteBits( ent->GetPredictedKey(), 32 );
  321. if ( ent->fl.networkSync ) {
  322. // write the class specific data to the snapshot
  323. ent->WriteToSnapshot( msg );
  324. }
  325. ss.S_AddObject( SNAP_ENTITIES + ent->entityNumber, ~0U, msg, ent->GetName() );
  326. }
  327. // Free PVS handles for all the players
  328. for ( int i = 0; i < MAX_PLAYERS; i++ ) {
  329. if ( pvsHandles[i].i < 0 ) {
  330. continue;
  331. }
  332. pvs.FreeCurrentPVS( pvsHandles[i] );
  333. }
  334. }
  335. /*
  336. ================
  337. idGameLocal::NetworkEventWarning
  338. ================
  339. */
  340. void idGameLocal::NetworkEventWarning( const entityNetEvent_t *event, const char *fmt, ... ) {
  341. char buf[1024];
  342. int length = 0;
  343. va_list argptr;
  344. int entityNum = event->spawnId & ( ( 1 << GENTITYNUM_BITS ) - 1 );
  345. int id = event->spawnId >> GENTITYNUM_BITS;
  346. length += idStr::snPrintf( buf+length, sizeof(buf)-1-length, "event %d for entity %d %d: ", event->event, entityNum, id );
  347. va_start( argptr, fmt );
  348. length = idStr::vsnPrintf( buf+length, sizeof(buf)-1-length, fmt, argptr );
  349. va_end( argptr );
  350. idStr::Append( buf, sizeof(buf), "\n" );
  351. common->DWarning( buf );
  352. }
  353. /*
  354. ================
  355. idGameLocal::ServerProcessEntityNetworkEventQueue
  356. ================
  357. */
  358. void idGameLocal::ServerProcessEntityNetworkEventQueue() {
  359. while ( eventQueue.Start() ) {
  360. entityNetEvent_t * event = eventQueue.Start();
  361. if ( event->time > time ) {
  362. break;
  363. }
  364. idEntityPtr< idEntity > entPtr;
  365. if( !entPtr.SetSpawnId( event->spawnId ) ) {
  366. NetworkEventWarning( event, "Entity does not exist any longer, or has not been spawned yet." );
  367. } else {
  368. idEntity * ent = entPtr.GetEntity();
  369. assert( ent );
  370. idBitMsg eventMsg;
  371. eventMsg.InitRead( event->paramsBuf, sizeof( event->paramsBuf ) );
  372. eventMsg.SetSize( event->paramsSize );
  373. eventMsg.BeginReading();
  374. if ( !ent->ServerReceiveEvent( event->event, event->time, eventMsg ) ) {
  375. NetworkEventWarning( event, "unknown event" );
  376. }
  377. }
  378. entityNetEvent_t* freedEvent = eventQueue.Dequeue();
  379. verify( freedEvent == event );
  380. eventQueue.Free( event );
  381. }
  382. }
  383. /*
  384. ================
  385. idGameLocal::ProcessReliableMessage
  386. ================
  387. */
  388. void idGameLocal::ProcessReliableMessage( int clientNum, int type, const idBitMsg &msg ) {
  389. if ( session->GetActingGameStateLobbyBase().IsPeer() ) {
  390. ClientProcessReliableMessage( type, msg );
  391. } else {
  392. ServerProcessReliableMessage( clientNum, type, msg );
  393. }
  394. }
  395. /*
  396. ================
  397. idGameLocal::ServerProcessReliableMessage
  398. ================
  399. */
  400. void idGameLocal::ServerProcessReliableMessage( int clientNum, int type, const idBitMsg &msg ) {
  401. if ( clientNum < 0 ) {
  402. return;
  403. }
  404. switch( type ) {
  405. case GAME_RELIABLE_MESSAGE_CHAT:
  406. case GAME_RELIABLE_MESSAGE_TCHAT: {
  407. char name[128];
  408. char text[128];
  409. msg.ReadString( name, sizeof( name ) );
  410. msg.ReadString( text, sizeof( text ) );
  411. mpGame.ProcessChatMessage( clientNum, type == GAME_RELIABLE_MESSAGE_TCHAT, name, text, NULL );
  412. break;
  413. }
  414. case GAME_RELIABLE_MESSAGE_VCHAT: {
  415. int index = msg.ReadLong();
  416. bool team = msg.ReadBits( 1 ) != 0;
  417. mpGame.ProcessVoiceChat( clientNum, team, index );
  418. break;
  419. }
  420. case GAME_RELIABLE_MESSAGE_DROPWEAPON: {
  421. mpGame.DropWeapon( clientNum );
  422. break;
  423. }
  424. case GAME_RELIABLE_MESSAGE_EVENT: {
  425. // allocate new event
  426. entityNetEvent_t * event = eventQueue.Alloc();
  427. eventQueue.Enqueue( event, idEventQueue::OUTOFORDER_DROP );
  428. event->spawnId = msg.ReadBits( 32 );
  429. event->event = msg.ReadByte();
  430. event->time = msg.ReadLong();
  431. event->paramsSize = msg.ReadBits( idMath::BitsForInteger( MAX_EVENT_PARAM_SIZE ) );
  432. if ( event->paramsSize ) {
  433. if ( event->paramsSize > MAX_EVENT_PARAM_SIZE ) {
  434. NetworkEventWarning( event, "invalid param size" );
  435. return;
  436. }
  437. msg.ReadByteAlign();
  438. msg.ReadData( event->paramsBuf, event->paramsSize );
  439. }
  440. break;
  441. }
  442. case GAME_RELIABLE_MESSAGE_SPECTATE: {
  443. bool spec = msg.ReadBool();
  444. idPlayer * player = GetClientByNum( clientNum );
  445. if ( serverInfo.GetBool( "si_spectators" ) ) {
  446. // never let spectators go back to game while sudden death is on
  447. if ( mpGame.GetGameState() == idMultiplayerGame::SUDDENDEATH && !spec && player->wantSpectate ) {
  448. // Don't allow the change
  449. } else {
  450. if ( player->wantSpectate && !spec ) {
  451. player->forceRespawn = true;
  452. }
  453. player->wantSpectate = spec;
  454. }
  455. } else {
  456. // If the server turned off si_spectators while a player is spectating, then any spectate message forces the player out of spectate mode
  457. if ( player->wantSpectate ) {
  458. player->forceRespawn = true;
  459. }
  460. player->wantSpectate = false;
  461. }
  462. break;
  463. }
  464. case GAME_RELIABLE_MESSAGE_CLIENT_HITSCAN_HIT: {
  465. const int attackerNum = msg.ReadShort();
  466. const int victimNum = msg.ReadShort();
  467. idVec3 dir;
  468. msg.ReadVectorFloat( dir );
  469. const int damageDefIndex = msg.ReadLong();
  470. const float damageScale = msg.ReadFloat();
  471. const int location = msg.ReadLong();
  472. if ( gameLocal.entities[victimNum] == NULL ) {
  473. break;
  474. }
  475. if ( gameLocal.entities[attackerNum] == NULL ) {
  476. break;
  477. }
  478. idPlayer & victim = static_cast< idPlayer & >( *gameLocal.entities[victimNum] );
  479. idPlayer & attacker = static_cast< idPlayer & >( *gameLocal.entities[attackerNum] );
  480. if ( victim.GetPhysics() == NULL ) {
  481. break;
  482. }
  483. if ( attacker.weapon.GetEntity() == NULL ) {
  484. break;
  485. }
  486. if ( location == INVALID_JOINT ) {
  487. break;
  488. }
  489. // Line of sight check. As a basic precaution against cheating,
  490. // the server performs a ray intersection from the client's position
  491. // to the joint he hit on the target.
  492. idVec3 muzzleOrigin;
  493. idMat3 muzzleAxis;
  494. attacker.weapon.GetEntity()->GetProjectileLaunchOriginAndAxis( muzzleOrigin, muzzleAxis );
  495. idVec3 targetLocation = victim.GetRenderEntity()->origin + victim.GetRenderEntity()->joints[location].ToVec3() * victim.GetRenderEntity()->axis;
  496. trace_t tr;
  497. gameLocal.clip.Translation( tr, muzzleOrigin, targetLocation, NULL, mat3_identity, MASK_SHOT_RENDERMODEL, &attacker );
  498. idEntity * hitEnt = gameLocal.entities[ tr.c.entityNum ];
  499. if ( hitEnt != &victim ) {
  500. break;
  501. }
  502. const idDeclEntityDef *damageDef = static_cast<const idDeclEntityDef *>( declManager->DeclByIndex( DECL_ENTITYDEF, damageDefIndex, false ) );
  503. if ( damageDef != NULL ) {
  504. victim.Damage( NULL, gameLocal.entities[attackerNum], dir, damageDef->GetName(), damageScale, location );
  505. }
  506. break;
  507. }
  508. default: {
  509. Warning( "Unknown reliable message (%d) from client %d", type, clientNum );
  510. break;
  511. }
  512. }
  513. }
  514. /*
  515. ================
  516. idGameLocal::ClientReadSnapshot
  517. ================
  518. */
  519. void idGameLocal::ClientReadSnapshot( const idSnapShot & ss ) {
  520. if ( GetLocalClientNum() < 0 ) {
  521. return;
  522. }
  523. // if prediction is off, enable local client smoothing
  524. //localPlayer->SetSelfSmooth( dupeUsercmds > 2 );
  525. // clear any debug lines from a previous frame
  526. gameRenderWorld->DebugClearLines( time );
  527. // clear any debug polygons from a previous frame
  528. gameRenderWorld->DebugClearPolygons( time );
  529. SelectTimeGroup( false );
  530. // so that StartSound/StopSound doesn't risk skipping
  531. isNewFrame = true;
  532. // clear the snapshot entity list
  533. snapshotEntities.Clear();
  534. // read all entities from the snapshot
  535. for ( int o = 0; o < ss.NumObjects(); o++ ) {
  536. idBitMsg msg;
  537. int snapObjectNum = ss.GetObjectMsgByIndex( o, msg );
  538. if ( snapObjectNum < 0 ) {
  539. assert( false );
  540. continue;
  541. }
  542. if ( snapObjectNum == SNAP_GAMESTATE ) {
  543. mpGame.ReadFromSnapshot( msg );
  544. continue;
  545. }
  546. if ( snapObjectNum == SNAP_SHADERPARMS ) {
  547. for ( int i = 0; i < MAX_GLOBAL_SHADER_PARMS; i++ ) {
  548. globalShaderParms[i] = msg.ReadFloat();
  549. }
  550. continue;
  551. }
  552. if ( snapObjectNum == SNAP_PORTALS ) {
  553. // update portals for opened doors
  554. int numPortals = msg.ReadLong();
  555. assert( numPortals == gameRenderWorld->NumPortals() );
  556. for ( int i = 0; i < numPortals; i++ ) {
  557. gameRenderWorld->SetPortalState( (qhandle_t) (i+1), msg.ReadBits( NUM_RENDER_PORTAL_BITS ) );
  558. }
  559. continue;
  560. }
  561. if ( snapObjectNum >= SNAP_PLAYERSTATE && snapObjectNum < SNAP_PLAYERSTATE_END ) {
  562. int playerNumber = snapObjectNum - SNAP_PLAYERSTATE;
  563. idPlayer * otherPlayer = static_cast< idPlayer * >( entities[ playerNumber ] );
  564. // Don't process Player Snapshots that are disconnected.
  565. const int lobbyIndex = session->GetActingGameStateLobbyBase().GetLobbyUserIndexFromLobbyUserID( lobbyUserIDs[ playerNumber ] );
  566. if( lobbyIndex < 0 || session->GetActingGameStateLobbyBase().IsLobbyUserConnected( lobbyIndex ) == false ) {
  567. continue;
  568. }
  569. if ( otherPlayer != NULL ) {
  570. otherPlayer->ReadPlayerStateFromSnapshot( msg );
  571. if ( otherPlayer != entities[ GetLocalClientNum() ] ) { // This happens when we spectate another player
  572. idWeapon * weap = otherPlayer->weapon.GetEntity();
  573. if ( weap && ( weap->GetRenderEntity()->bounds[0] == weap->GetRenderEntity()->bounds[1] ) ) {
  574. // update the weapon's viewmodel bounds so that the model doesn't flicker in the spectator's view
  575. weap->GetAnimator()->GetBounds( gameLocal.time, weap->GetRenderEntity()->bounds );
  576. weap->UpdateVisuals();
  577. }
  578. }
  579. }
  580. continue;
  581. }
  582. if ( snapObjectNum >= SNAP_LAST_CLIENT_FRAME && snapObjectNum < SNAP_LAST_CLIENT_FRAME_END ) {
  583. int playerNumber = snapObjectNum - SNAP_LAST_CLIENT_FRAME;
  584. // Don't process Player Snapshots that are disconnected.
  585. const int lobbyIndex = session->GetActingGameStateLobbyBase().GetLobbyUserIndexFromLobbyUserID( lobbyUserIDs[ playerNumber ] );
  586. if( lobbyIndex < 0 || session->GetActingGameStateLobbyBase().IsLobbyUserConnected( lobbyIndex ) == false ) {
  587. continue;
  588. }
  589. usercmdLastClientMilliseconds[playerNumber] = msg.ReadLong();
  590. continue;
  591. }
  592. if ( snapObjectNum < SNAP_ENTITIES || snapObjectNum >= SNAP_ENTITIES_END ) {
  593. continue;
  594. }
  595. int entityNumber = snapObjectNum - SNAP_ENTITIES;
  596. if ( msg.GetSize() == 0 ) {
  597. delete entities[entityNumber];
  598. continue;
  599. }
  600. bool debug = false;
  601. int spawnId = msg.ReadBits( 32 - GENTITYNUM_BITS );
  602. int typeNum = msg.ReadBits( idClass::GetTypeNumBits() );
  603. int entityDefNumber = ClientRemapDecl( DECL_ENTITYDEF, msg.ReadBits( entityDefBits ) );
  604. const int predictedKey = msg.ReadBits( 32 );
  605. idTypeInfo * typeInfo = idClass::GetType( typeNum );
  606. if ( !typeInfo ) {
  607. idLib::Error( "Unknown type number %d for entity %d with class number %d", typeNum, entityNumber, entityDefNumber );
  608. }
  609. // If there is no entity on this client, but the server's entity matches a predictionKey, move the client's
  610. // predicted entity to the normal, replicated area in the entity list.
  611. if ( entities[entityNumber] == NULL ) {
  612. if ( predictedKey != idEntity::INVALID_PREDICTION_KEY ) {
  613. idLib::PrintfIf( debug, "Looking for predicted key %d.\n", predictedKey );
  614. idEntity * predictedEntity = FindPredictedEntity( predictedKey, typeInfo );
  615. if ( predictedEntity != NULL ) {
  616. // This presentable better be in the proper place in the list or bad things will happen if we move this presentable around
  617. assert( predictedEntity->GetEntityNumber() >= ENTITYNUM_FIRST_NON_REPLICATED );
  618. continue;
  619. #if 0
  620. idProjectile * predictedProjectile = idProjectile::CastTo( predictedEntity );
  621. if ( predictedProjectile != NULL ) {
  622. for ( int i = 0; i < MAX_PLAYERS; i++ ) {
  623. if ( entities[i] == NULL ) {
  624. continue;
  625. }
  626. idPlayer * player = idPlayer::CastTo( entities[i] );
  627. if ( player != NULL ) {
  628. if ( player->GetUniqueProjectile() == predictedProjectile ) {
  629. // Set new spawn id
  630. player->TrackUniqueProjectile( predictedProjectile );
  631. }
  632. }
  633. }
  634. }
  635. idLib::PrintfIf( debug, "Found predicted EntNum old:%i new:%i spawnID:%i\n", predictedEntity->GetEntityNumber(), entityNumber, spawnId >> GENTITYNUM_BITS );
  636. // move the entity
  637. RemoveEntityFromHash( predictedEntity->name.c_str(), predictedEntity );
  638. UnregisterEntity( predictedEntity );
  639. assert( entities[predictedEntity->GetEntityNumber()] == NULL );
  640. predictedEntity->spawnArgs.SetInt( "spawn_entnum", entityNumber );
  641. RegisterEntity( predictedEntity, spawnId, predictedEntity->spawnArgs );
  642. predictedEntity->SetName( "" );
  643. // now mark us as no longer predicted
  644. predictedEntity->BecomeReplicated();
  645. #endif
  646. }
  647. //TODO make this work with non-client preditced entities
  648. /* else {
  649. idLib::Warning( "Could not find predicted entity - key: %d. EntityIndex: %d", predictedKey, entityNum );
  650. } */
  651. }
  652. }
  653. idEntity * ent = entities[entityNumber];
  654. // if there is no entity or an entity of the wrong type
  655. if ( !ent || ent->GetType()->typeNum != typeNum || ent->entityDefNumber != entityDefNumber || spawnId != spawnIds[ entityNumber ] ) {
  656. delete ent;
  657. spawnCount = spawnId;
  658. if ( entityNumber < MAX_CLIENTS ) {
  659. commonLocal.GetUCmdMgr().ResetPlayer( entityNumber );
  660. SpawnPlayer( entityNumber );
  661. ent = entities[ entityNumber ];
  662. ent->FreeModelDef();
  663. } else {
  664. idDict args;
  665. args.SetInt( "spawn_entnum", entityNumber );
  666. args.Set( "name", va( "entity%d", entityNumber ) );
  667. if ( entityDefNumber >= 0 ) {
  668. if ( entityDefNumber >= declManager->GetNumDecls( DECL_ENTITYDEF ) ) {
  669. Error( "server has %d entityDefs instead of %d", entityDefNumber, declManager->GetNumDecls( DECL_ENTITYDEF ) );
  670. }
  671. const char * classname = declManager->DeclByIndex( DECL_ENTITYDEF, entityDefNumber, false )->GetName();
  672. args.Set( "classname", classname );
  673. if ( !SpawnEntityDef( args, &ent ) || !entities[entityNumber] || entities[entityNumber]->GetType()->typeNum != typeNum ) {
  674. Error( "Failed to spawn entity with classname '%s' of type '%s'", classname, typeInfo->classname );
  675. }
  676. } else {
  677. ent = SpawnEntityType( *typeInfo, &args, true );
  678. if ( !entities[entityNumber] || entities[entityNumber]->GetType()->typeNum != typeNum ) {
  679. Error( "Failed to spawn entity of type '%s'", typeInfo->classname );
  680. }
  681. }
  682. if ( ent != NULL ) {
  683. // Fixme: for now, force all think flags on. We'll need to figure out how we want dormancy to work on clients
  684. // (but for now since clientThink is so light weight, this is ok)
  685. ent->BecomeActive( TH_ANIMATE );
  686. ent->BecomeActive( TH_THINK );
  687. ent->BecomeActive( TH_PHYSICS );
  688. }
  689. if ( entityNumber < MAX_CLIENTS && entityNumber >= numClients ) {
  690. numClients = entityNumber + 1;
  691. }
  692. }
  693. }
  694. if ( ss.ObjectIsStaleByIndex( o ) ) {
  695. if ( ent->entityNumber >= MAX_CLIENTS && ent->entityNumber < mapSpawnCount && !ent->spawnArgs.GetBool("net_dynamic", "0")) { //_D3XP
  696. // server says it's not in PVS
  697. // if that happens on map entities, most likely something is wrong
  698. // I can see that moving pieces along several PVS could be a legit situation though
  699. // this is a band aid, which means something is not done right elsewhere
  700. common->DWarning( "map entity 0x%x (%s) is stale", ent->entityNumber, ent->name.c_str() );
  701. } else {
  702. ent->snapshotStale = true;
  703. ent->FreeModelDef();
  704. // possible fix for left over lights on CTF flag
  705. ent->FreeLightDef();
  706. ent->UpdateVisuals();
  707. ent->GetPhysics()->UnlinkClip();
  708. }
  709. } else {
  710. // add the entity to the snapshot list
  711. ent->snapshotNode.AddToEnd( snapshotEntities );
  712. int snapshotChanged = ss.ObjectChangedCountByIndex( o );
  713. msg.SetHasChanged( ent->snapshotChanged != snapshotChanged );
  714. ent->snapshotChanged = snapshotChanged;
  715. ent->FlagNewSnapshot();
  716. // read the class specific data from the snapshot
  717. if ( msg.GetRemainingReadBits() > 0 ) {
  718. ent->ReadFromSnapshot_Ex( msg );
  719. ent->snapshotBits = msg.GetSize();
  720. }
  721. // Set after ReadFromSnapshot so we can detect coming unstale
  722. ent->snapshotStale = false;
  723. }
  724. }
  725. // process entity events
  726. ClientProcessEntityNetworkEventQueue();
  727. }
  728. /*
  729. ================
  730. idGameLocal::ClientProcessEntityNetworkEventQueue
  731. ================
  732. */
  733. void idGameLocal::ClientProcessEntityNetworkEventQueue() {
  734. while( eventQueue.Start() ) {
  735. entityNetEvent_t * event = eventQueue.Start();
  736. // only process forward, in order
  737. if ( event->time > this->serverTime ) {
  738. break;
  739. }
  740. idEntityPtr< idEntity > entPtr;
  741. if( !entPtr.SetSpawnId( event->spawnId ) ) {
  742. if( !gameLocal.entities[ event->spawnId & ( ( 1 << GENTITYNUM_BITS ) - 1 ) ] ) {
  743. // if new entity exists in this position, silently ignore
  744. NetworkEventWarning( event, "Entity does not exist any longer, or has not been spawned yet." );
  745. }
  746. } else {
  747. idEntity * ent = entPtr.GetEntity();
  748. assert( ent );
  749. idBitMsg eventMsg;
  750. eventMsg.InitRead( event->paramsBuf, sizeof( event->paramsBuf ) );
  751. eventMsg.SetSize( event->paramsSize );
  752. eventMsg.BeginReading();
  753. if ( !ent->ClientReceiveEvent( event->event, event->time, eventMsg ) ) {
  754. NetworkEventWarning( event, "unknown event" );
  755. }
  756. }
  757. verify( eventQueue.Dequeue() == event );
  758. eventQueue.Free( event );
  759. }
  760. }
  761. /*
  762. ================
  763. idGameLocal::ClientProcessReliableMessage
  764. ================
  765. */
  766. void idGameLocal::ClientProcessReliableMessage( int type, const idBitMsg &msg ) {
  767. switch( type ) {
  768. case GAME_RELIABLE_MESSAGE_SYNCEDCVARS: {
  769. idDict syncedCvars;
  770. msg.ReadDeltaDict( syncedCvars, NULL );
  771. idLib::Printf( "Got networkSync cvars:\n" );
  772. syncedCvars.Print();
  773. cvarSystem->ResetFlaggedVariables( CVAR_NETWORKSYNC );
  774. cvarSystem->SetCVarsFromDict( syncedCvars );
  775. break;
  776. }
  777. case GAME_RELIABLE_MESSAGE_CHAT:
  778. case GAME_RELIABLE_MESSAGE_TCHAT: { // (client should never get a TCHAT though)
  779. char name[128];
  780. char text[128];
  781. msg.ReadString( name, sizeof( name ) );
  782. msg.ReadString( text, sizeof( text ) );
  783. mpGame.AddChatLine( "%s^0: %s\n", name, text );
  784. break;
  785. }
  786. case GAME_RELIABLE_MESSAGE_SOUND_EVENT: {
  787. snd_evt_t snd_evt = (snd_evt_t)msg.ReadByte();
  788. mpGame.PlayGlobalSound( -1, snd_evt );
  789. break;
  790. }
  791. case GAME_RELIABLE_MESSAGE_SOUND_INDEX: {
  792. int index = gameLocal.ClientRemapDecl( DECL_SOUND, msg.ReadLong() );
  793. if ( index >= 0 && index < declManager->GetNumDecls( DECL_SOUND ) ) {
  794. const idSoundShader *shader = declManager->SoundByIndex( index );
  795. mpGame.PlayGlobalSound( -1, SND_COUNT, shader->GetName() );
  796. }
  797. break;
  798. }
  799. case GAME_RELIABLE_MESSAGE_DB: {
  800. idMultiplayerGame::msg_evt_t msg_evt = (idMultiplayerGame::msg_evt_t)msg.ReadByte();
  801. int parm1, parm2;
  802. parm1 = msg.ReadByte( );
  803. parm2 = msg.ReadByte( );
  804. mpGame.PrintMessageEvent( msg_evt, parm1, parm2 );
  805. break;
  806. }
  807. case GAME_RELIABLE_MESSAGE_EVENT: {
  808. // allocate new event
  809. entityNetEvent_t * event = eventQueue.Alloc();
  810. eventQueue.Enqueue( event, idEventQueue::OUTOFORDER_IGNORE );
  811. event->spawnId = msg.ReadBits( 32 );
  812. event->event = msg.ReadByte();
  813. event->time = msg.ReadLong();
  814. event->paramsSize = msg.ReadBits( idMath::BitsForInteger( MAX_EVENT_PARAM_SIZE ) );
  815. if ( event->paramsSize ) {
  816. if ( event->paramsSize > MAX_EVENT_PARAM_SIZE ) {
  817. NetworkEventWarning( event, "invalid param size" );
  818. return;
  819. }
  820. msg.ReadByteAlign();
  821. msg.ReadData( event->paramsBuf, event->paramsSize );
  822. }
  823. break;
  824. }
  825. case GAME_RELIABLE_MESSAGE_RESTART: {
  826. MapRestart();
  827. break;
  828. }
  829. case GAME_RELIABLE_MESSAGE_TOURNEYLINE: {
  830. int line = msg.ReadByte( );
  831. idPlayer * p = static_cast< idPlayer * >( entities[ GetLocalClientNum() ] );
  832. if ( !p ) {
  833. break;
  834. }
  835. p->tourneyLine = line;
  836. break;
  837. }
  838. case GAME_RELIABLE_MESSAGE_STARTSTATE: {
  839. mpGame.ClientReadStartState( msg );
  840. break;
  841. }
  842. case GAME_RELIABLE_MESSAGE_WARMUPTIME: {
  843. mpGame.ClientReadWarmupTime( msg );
  844. break;
  845. }
  846. case GAME_RELIABLE_MESSAGE_LOBBY_COUNTDOWN: {
  847. int timeRemaining = msg.ReadLong();
  848. Shell_UpdateClientCountdown( timeRemaining );
  849. break;
  850. }
  851. case GAME_RELIABLE_MESSAGE_RESPAWN_AVAILABLE: {
  852. idPlayer * p = static_cast< idPlayer * >( entities[ GetLocalClientNum() ] );
  853. if ( p ) {
  854. p->ShowRespawnHudMessage();
  855. }
  856. break;
  857. }
  858. case GAME_RELIABLE_MESSAGE_MATCH_STARTED_TIME: {
  859. mpGame.ClientReadMatchStartedTime( msg );
  860. break;
  861. }
  862. case GAME_RELIABLE_MESSAGE_ACHIEVEMENT_UNLOCK: {
  863. mpGame.ClientReadAchievementUnlock( msg );
  864. break;
  865. }
  866. default: {
  867. Error( "Unknown reliable message (%d) from host", type );
  868. break;
  869. }
  870. }
  871. }
  872. /*
  873. ================
  874. idGameLocal::ClientRunFrame
  875. ================
  876. */
  877. void idGameLocal::ClientRunFrame( idUserCmdMgr & cmdMgr, bool lastPredictFrame, gameReturn_t & ret ) {
  878. idEntity *ent;
  879. // update the game time
  880. previousTime = FRAME_TO_MSEC( framenum );
  881. framenum++;
  882. time = FRAME_TO_MSEC( framenum );
  883. idPlayer * player = static_cast<idPlayer *>( entities[GetLocalClientNum()] );
  884. if ( !player ) {
  885. // service any pending events
  886. idEvent::ServiceEvents();
  887. return;
  888. }
  889. // check for local client lag
  890. idLobbyBase & lobby = session->GetActingGameStateLobbyBase();
  891. if ( lobby.GetPeerTimeSinceLastPacket( lobby.PeerIndexForHost() ) >= net_clientMaxPrediction.GetInteger() ) {
  892. player->isLagged = true;
  893. } else {
  894. player->isLagged = false;
  895. }
  896. // update the real client time and the new frame flag
  897. if ( time > realClientTime ) {
  898. realClientTime = time;
  899. isNewFrame = true;
  900. } else {
  901. isNewFrame = false;
  902. }
  903. slow.Set( time, previousTime, realClientTime );
  904. fast.Set( time, previousTime, realClientTime );
  905. // run prediction on all active entities
  906. for( ent = activeEntities.Next(); ent != NULL; ent = ent->activeNode.Next() ) {
  907. ent->thinkFlags |= TH_PHYSICS;
  908. if ( ent->entityNumber != GetLocalClientNum() ) {
  909. ent->ClientThink( netInterpolationInfo.serverGameMs, netInterpolationInfo.pct, true );
  910. } else {
  911. RunAllUserCmdsForPlayer( cmdMgr, ent->entityNumber );
  912. }
  913. }
  914. // service any pending events
  915. idEvent::ServiceEvents();
  916. // show any debug info for this frame
  917. if ( isNewFrame ) {
  918. RunDebugInfo();
  919. D_DrawDebugLines();
  920. }
  921. BuildReturnValue( ret );
  922. }
  923. /*
  924. ===============
  925. idGameLocal::Tokenize
  926. ===============
  927. */
  928. void idGameLocal::Tokenize( idStrList &out, const char *in ) {
  929. char buf[ MAX_STRING_CHARS ];
  930. char *token, *next;
  931. idStr::Copynz( buf, in, MAX_STRING_CHARS );
  932. token = buf;
  933. next = strchr( token, ';' );
  934. while ( token ) {
  935. if ( next ) {
  936. *next = '\0';
  937. }
  938. idStr::ToLower( token );
  939. out.Append( token );
  940. if ( next ) {
  941. token = next + 1;
  942. next = strchr( token, ';' );
  943. } else {
  944. token = NULL;
  945. }
  946. }
  947. }
  948. /*
  949. ========================
  950. idGameLocal::FindPredictedEntity
  951. ========================
  952. */
  953. idEntity * idGameLocal::FindPredictedEntity( uint32 predictedKey, idTypeInfo * type ) {
  954. for ( idEntity * predictedEntity = activeEntities.Next(); predictedEntity != NULL; predictedEntity = predictedEntity->activeNode.Next() ) {
  955. if ( !verify( predictedEntity != NULL ) ) {
  956. continue;
  957. }
  958. if ( !predictedEntity->IsReplicated() && predictedEntity->GetPredictedKey() == predictedKey ) {
  959. if ( predictedEntity->GetType() != type ) {
  960. idLib::Warning("Mismatched presentable type. Predicted: %s Actual: %s", predictedEntity->GetType()->classname, type->classname );
  961. }
  962. return predictedEntity;
  963. }
  964. }
  965. return NULL;
  966. }
  967. /*
  968. ========================
  969. idGameLocal::GeneratePredictionKey
  970. ========================
  971. */
  972. uint32 idGameLocal::GeneratePredictionKey( idWeapon * weapon, idPlayer * playerAttacker, int overrideKey ) {
  973. if ( overrideKey != -1 ) {
  974. uint32 predictedKey = overrideKey;
  975. int peerIndex = -1;
  976. if ( common->IsServer() ) {
  977. peerIndex = session->GetActingGameStateLobbyBase().PeerIndexFromLobbyUser( lobbyUserIDs[ playerAttacker->entityNumber ] );
  978. } else {
  979. peerIndex = session->GetActingGameStateLobbyBase().PeerIndexOnHost();
  980. }
  981. predictedKey |= ( peerIndex << 28 );
  982. return predictedKey;
  983. }
  984. uint32 predictedKey = idEntity::INVALID_PREDICTION_KEY;
  985. int peerIndex = -1;
  986. // Get key - fireCount or throwCount
  987. //if ( weapon != NULL ) {
  988. if ( common->IsClient() ) {
  989. predictedKey = playerAttacker->GetClientFireCount();
  990. } else {
  991. predictedKey = playerAttacker->usercmd.fireCount;
  992. }
  993. //} else {
  994. // predictedKey = ( playerAttacker->GetThrowCount() );
  995. //}
  996. // Get peer index
  997. if ( common->IsServer() ) {
  998. peerIndex = session->GetActingGameStateLobbyBase().PeerIndexFromLobbyUser( lobbyUserIDs[ playerAttacker->entityNumber ] );
  999. } else {
  1000. peerIndex = session->GetActingGameStateLobbyBase().PeerIndexOnHost();
  1001. }
  1002. if ( cg_predictedSpawn_debug.GetBool() ) {
  1003. idLib::Printf("GeneratePredictionKey. predictedKey: %d peedIndex: %d\n", predictedKey, peerIndex );
  1004. }
  1005. predictedKey |= ( peerIndex << 28 );
  1006. return predictedKey;
  1007. }
  1008. /*
  1009. ===============
  1010. idEventQueue::Alloc
  1011. ===============
  1012. */
  1013. entityNetEvent_t* idEventQueue::Alloc() {
  1014. entityNetEvent_t* event = eventAllocator.Alloc();
  1015. event->prev = NULL;
  1016. event->next = NULL;
  1017. return event;
  1018. }
  1019. /*
  1020. ===============
  1021. idEventQueue::Free
  1022. ===============
  1023. */
  1024. void idEventQueue::Free( entityNetEvent_t *event ) {
  1025. // should only be called on an unlinked event!
  1026. assert( !event->next && !event->prev );
  1027. eventAllocator.Free( event );
  1028. }
  1029. /*
  1030. ===============
  1031. idEventQueue::Shutdown
  1032. ===============
  1033. */
  1034. void idEventQueue::Shutdown() {
  1035. eventAllocator.Shutdown();
  1036. this->Init();
  1037. }
  1038. /*
  1039. ===============
  1040. idEventQueue::Init
  1041. ===============
  1042. */
  1043. void idEventQueue::Init() {
  1044. start = NULL;
  1045. end = NULL;
  1046. }
  1047. /*
  1048. ===============
  1049. idEventQueue::Dequeue
  1050. ===============
  1051. */
  1052. entityNetEvent_t* idEventQueue::Dequeue() {
  1053. entityNetEvent_t* event = start;
  1054. if ( !event ) {
  1055. return NULL;
  1056. }
  1057. start = start->next;
  1058. if ( !start ) {
  1059. end = NULL;
  1060. } else {
  1061. start->prev = NULL;
  1062. }
  1063. event->next = NULL;
  1064. event->prev = NULL;
  1065. return event;
  1066. }
  1067. /*
  1068. ===============
  1069. idEventQueue::RemoveLast
  1070. ===============
  1071. */
  1072. entityNetEvent_t* idEventQueue::RemoveLast() {
  1073. entityNetEvent_t *event = end;
  1074. if ( !event ) {
  1075. return NULL;
  1076. }
  1077. end = event->prev;
  1078. if ( !end ) {
  1079. start = NULL;
  1080. } else {
  1081. end->next = NULL;
  1082. }
  1083. event->next = NULL;
  1084. event->prev = NULL;
  1085. return event;
  1086. }
  1087. /*
  1088. ===============
  1089. idEventQueue::Enqueue
  1090. ===============
  1091. */
  1092. void idEventQueue::Enqueue( entityNetEvent_t *event, outOfOrderBehaviour_t behaviour ) {
  1093. if ( behaviour == OUTOFORDER_DROP ) {
  1094. // go backwards through the queue and determine if there are
  1095. // any out-of-order events
  1096. while ( end && end->time > event->time ) {
  1097. entityNetEvent_t *outOfOrder = RemoveLast();
  1098. common->DPrintf( "WARNING: new event with id %d ( time %d ) caused removal of event with id %d ( time %d ), game time = %d.\n", event->event, event->time, outOfOrder->event, outOfOrder->time, gameLocal.time );
  1099. Free( outOfOrder );
  1100. }
  1101. } else if ( behaviour == OUTOFORDER_SORT && end ) {
  1102. // NOT TESTED -- sorting out of order packets hasn't been
  1103. // tested yet... wasn't strictly necessary for
  1104. // the patch fix.
  1105. entityNetEvent_t *cur = end;
  1106. // iterate until we find a time < the new event's
  1107. while ( cur && cur->time > event->time ) {
  1108. cur = cur->prev;
  1109. }
  1110. if ( !cur ) {
  1111. // add to start
  1112. event->next = start;
  1113. event->prev = NULL;
  1114. start = event;
  1115. } else {
  1116. // insert
  1117. event->prev = cur;
  1118. event->next = cur->next;
  1119. cur->next = event;
  1120. }
  1121. return;
  1122. }
  1123. // add the new event
  1124. event->next = NULL;
  1125. event->prev = NULL;
  1126. if ( end ) {
  1127. end->next = event;
  1128. event->prev = end;
  1129. } else {
  1130. start = event;
  1131. }
  1132. end = event;
  1133. }