Game_network.cpp 51 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
  6. Doom 3 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 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 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 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 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. /*
  24. ===============================================================================
  25. Client running game code:
  26. - entity events don't work and should not be issued
  27. - entities should never be spawned outside idGameLocal::ClientReadSnapshot
  28. ===============================================================================
  29. */
  30. // adds tags to the network protocol to detect when things go bad ( internal consistency )
  31. // NOTE: this changes the network protocol
  32. #ifndef ASYNC_WRITE_TAGS
  33. #define ASYNC_WRITE_TAGS 0
  34. #endif
  35. idCVar net_clientShowSnapshot( "net_clientShowSnapshot", "0", CVAR_GAME | CVAR_INTEGER, "", 0, 3, idCmdSystem::ArgCompletion_Integer<0,3> );
  36. idCVar net_clientShowSnapshotRadius( "net_clientShowSnapshotRadius", "128", CVAR_GAME | CVAR_FLOAT, "" );
  37. idCVar net_clientSmoothing( "net_clientSmoothing", "0.8", CVAR_GAME | CVAR_FLOAT, "smooth other clients angles and position.", 0.0f, 0.95f );
  38. idCVar net_clientSelfSmoothing( "net_clientSelfSmoothing", "0.6", CVAR_GAME | CVAR_FLOAT, "smooth self position if network causes prediction error.", 0.0f, 0.95f );
  39. idCVar net_clientMaxPrediction( "net_clientMaxPrediction", "1000", CVAR_SYSTEM | CVAR_INTEGER | CVAR_NOCHEAT, "maximum number of milliseconds a client can predict ahead of server." );
  40. idCVar net_clientLagOMeter( "net_clientLagOMeter", "1", CVAR_GAME | CVAR_BOOL | CVAR_NOCHEAT | CVAR_ARCHIVE, "draw prediction graph" );
  41. /*
  42. ================
  43. idGameLocal::InitAsyncNetwork
  44. ================
  45. */
  46. void idGameLocal::InitAsyncNetwork( void ) {
  47. int i, type;
  48. for ( i = 0; i < MAX_CLIENTS; i++ ) {
  49. for ( type = 0; type < declManager->GetNumDeclTypes(); type++ ) {
  50. clientDeclRemap[i][type].Clear();
  51. }
  52. }
  53. memset( clientEntityStates, 0, sizeof( clientEntityStates ) );
  54. memset( clientPVS, 0, sizeof( clientPVS ) );
  55. memset( clientSnapshots, 0, sizeof( clientSnapshots ) );
  56. eventQueue.Init();
  57. savedEventQueue.Init();
  58. entityDefBits = -( idMath::BitsForInteger( declManager->GetNumDecls( DECL_ENTITYDEF ) ) + 1 );
  59. localClientNum = 0; // on a listen server SetLocalUser will set this right
  60. realClientTime = 0;
  61. isNewFrame = true;
  62. clientSmoothing = net_clientSmoothing.GetFloat();
  63. }
  64. /*
  65. ================
  66. idGameLocal::ShutdownAsyncNetwork
  67. ================
  68. */
  69. void idGameLocal::ShutdownAsyncNetwork( void ) {
  70. entityStateAllocator.Shutdown();
  71. snapshotAllocator.Shutdown();
  72. eventQueue.Shutdown();
  73. savedEventQueue.Shutdown();
  74. memset( clientEntityStates, 0, sizeof( clientEntityStates ) );
  75. memset( clientPVS, 0, sizeof( clientPVS ) );
  76. memset( clientSnapshots, 0, sizeof( clientSnapshots ) );
  77. }
  78. /*
  79. ================
  80. idGameLocal::InitLocalClient
  81. ================
  82. */
  83. void idGameLocal::InitLocalClient( int clientNum ) {
  84. isServer = false;
  85. isClient = true;
  86. localClientNum = clientNum;
  87. clientSmoothing = net_clientSmoothing.GetFloat();
  88. }
  89. /*
  90. ================
  91. idGameLocal::InitClientDeclRemap
  92. ================
  93. */
  94. void idGameLocal::InitClientDeclRemap( int clientNum ) {
  95. int type, i, num;
  96. for ( type = 0; type < declManager->GetNumDeclTypes(); type++ ) {
  97. // only implicit materials and sound shaders decls are used
  98. if ( type != DECL_MATERIAL && type != DECL_SOUND ) {
  99. continue;
  100. }
  101. num = declManager->GetNumDecls( (declType_t) type );
  102. clientDeclRemap[clientNum][type].Clear();
  103. clientDeclRemap[clientNum][type].AssureSize( num, -1 );
  104. // pre-initialize the remap with non-implicit decls, all non-implicit decls are always going
  105. // to be in order and in sync between server and client because of the decl manager checksum
  106. for ( i = 0; i < num; i++ ) {
  107. const idDecl *decl = declManager->DeclByIndex( (declType_t) type, i, false );
  108. if ( decl->IsImplicit() ) {
  109. // once the first implicit decl is found all remaining decls are considered implicit as well
  110. break;
  111. }
  112. clientDeclRemap[clientNum][type][i] = i;
  113. }
  114. }
  115. }
  116. /*
  117. ================
  118. idGameLocal::ServerSendDeclRemapToClient
  119. ================
  120. */
  121. void idGameLocal::ServerSendDeclRemapToClient( int clientNum, declType_t type, int index ) {
  122. idBitMsg outMsg;
  123. byte msgBuf[MAX_GAME_MESSAGE_SIZE];
  124. // if no client connected for this spot
  125. if ( entities[clientNum] == NULL ) {
  126. return;
  127. }
  128. // increase size of list if required
  129. if ( index >= clientDeclRemap[clientNum][type].Num() ) {
  130. clientDeclRemap[clientNum][(int)type].AssureSize( index + 1, -1 );
  131. }
  132. // if already remapped
  133. if ( clientDeclRemap[clientNum][(int)type][index] != -1 ) {
  134. return;
  135. }
  136. const idDecl *decl = declManager->DeclByIndex( type, index, false );
  137. if ( decl == NULL ) {
  138. gameLocal.Error( "server tried to remap bad %s decl index %d", declManager->GetDeclNameFromType( type ), index );
  139. return;
  140. }
  141. // set the index at the server
  142. clientDeclRemap[clientNum][(int)type][index] = index;
  143. // write update to client
  144. outMsg.Init( msgBuf, sizeof( msgBuf ) );
  145. outMsg.BeginWriting();
  146. outMsg.WriteByte( GAME_RELIABLE_MESSAGE_REMAP_DECL );
  147. outMsg.WriteByte( type );
  148. outMsg.WriteLong( index );
  149. outMsg.WriteString( decl->GetName() );
  150. networkSystem->ServerSendReliableMessage( clientNum, outMsg );
  151. }
  152. /*
  153. ================
  154. idGameLocal::ServerRemapDecl
  155. ================
  156. */
  157. int idGameLocal::ServerRemapDecl( int clientNum, declType_t type, int index ) {
  158. // only implicit materials and sound shaders decls are used
  159. if ( type != DECL_MATERIAL && type != DECL_SOUND ) {
  160. return index;
  161. }
  162. if ( clientNum == -1 ) {
  163. for ( int i = 0; i < MAX_CLIENTS; i++ ) {
  164. ServerSendDeclRemapToClient( i, type, index );
  165. }
  166. } else {
  167. ServerSendDeclRemapToClient( clientNum, type, index );
  168. }
  169. return index;
  170. }
  171. /*
  172. ================
  173. idGameLocal::ClientRemapDecl
  174. ================
  175. */
  176. int idGameLocal::ClientRemapDecl( declType_t type, int index ) {
  177. // only implicit materials and sound shaders decls are used
  178. if ( type != DECL_MATERIAL && type != DECL_SOUND ) {
  179. return index;
  180. }
  181. // negative indexes are sometimes used for NULL decls
  182. if ( index < 0 ) {
  183. return index;
  184. }
  185. // make sure the index is valid
  186. if ( clientDeclRemap[localClientNum][(int)type].Num() == 0 ) {
  187. gameLocal.Error( "client received decl index %d before %s decl remap was initialized", index, declManager->GetDeclNameFromType( type ) );
  188. return -1;
  189. }
  190. if ( index >= clientDeclRemap[localClientNum][(int)type].Num() ) {
  191. gameLocal.Error( "client received unmapped %s decl index %d from server", declManager->GetDeclNameFromType( type ), index );
  192. return -1;
  193. }
  194. if ( clientDeclRemap[localClientNum][(int)type][index] == -1 ) {
  195. gameLocal.Error( "client received unmapped %s decl index %d from server", declManager->GetDeclNameFromType( type ), index );
  196. return -1;
  197. }
  198. return clientDeclRemap[localClientNum][type][index];
  199. }
  200. /*
  201. ================
  202. idGameLocal::ServerAllowClient
  203. ================
  204. */
  205. allowReply_t idGameLocal::ServerAllowClient( int numClients, const char *IP, const char *guid, const char *password, char reason[ MAX_STRING_CHARS ] ) {
  206. reason[0] = '\0';
  207. if ( serverInfo.GetInt( "si_pure" ) && !mpGame.IsPureReady() ) {
  208. idStr::snPrintf( reason, MAX_STRING_CHARS, "#str_07139" );
  209. return ALLOW_NOTYET;
  210. }
  211. if ( !serverInfo.GetInt( "si_maxPlayers" ) ) {
  212. idStr::snPrintf( reason, MAX_STRING_CHARS, "#str_07140" );
  213. return ALLOW_NOTYET;
  214. }
  215. if ( numClients >= serverInfo.GetInt( "si_maxPlayers" ) ) {
  216. idStr::snPrintf( reason, MAX_STRING_CHARS, "#str_07141" );
  217. return ALLOW_NOTYET;
  218. }
  219. if ( !cvarSystem->GetCVarBool( "si_usepass" ) ) {
  220. return ALLOW_YES;
  221. }
  222. const char *pass = cvarSystem->GetCVarString( "g_password" );
  223. if ( pass[ 0 ] == '\0' ) {
  224. common->Warning( "si_usepass is set but g_password is empty" );
  225. cmdSystem->BufferCommandText( CMD_EXEC_NOW, "say si_usepass is set but g_password is empty" );
  226. // avoids silent misconfigured state
  227. idStr::snPrintf( reason, MAX_STRING_CHARS, "#str_07142" );
  228. return ALLOW_NOTYET;
  229. }
  230. if ( !idStr::Cmp( pass, password ) ) {
  231. return ALLOW_YES;
  232. }
  233. idStr::snPrintf( reason, MAX_STRING_CHARS, "#str_07143" );
  234. Printf( "Rejecting client %s from IP %s: invalid password\n", guid, IP );
  235. return ALLOW_BADPASS;
  236. }
  237. /*
  238. ================
  239. idGameLocal::ServerClientConnect
  240. ================
  241. */
  242. void idGameLocal::ServerClientConnect( int clientNum, const char *guid ) {
  243. // make sure no parasite entity is left
  244. if ( entities[ clientNum ] ) {
  245. common->DPrintf( "ServerClientConnect: remove old player entity\n" );
  246. delete entities[ clientNum ];
  247. }
  248. userInfo[ clientNum ].Clear();
  249. mpGame.ServerClientConnect( clientNum );
  250. Printf( "client %d connected.\n", clientNum );
  251. }
  252. /*
  253. ================
  254. idGameLocal::ServerClientBegin
  255. ================
  256. */
  257. void idGameLocal::ServerClientBegin( int clientNum ) {
  258. idBitMsg outMsg;
  259. byte msgBuf[MAX_GAME_MESSAGE_SIZE];
  260. // initialize the decl remap
  261. InitClientDeclRemap( clientNum );
  262. // send message to initialize decl remap at the client (this is always the very first reliable game message)
  263. outMsg.Init( msgBuf, sizeof( msgBuf ) );
  264. outMsg.BeginWriting();
  265. outMsg.WriteByte( GAME_RELIABLE_MESSAGE_INIT_DECL_REMAP );
  266. networkSystem->ServerSendReliableMessage( clientNum, outMsg );
  267. // spawn the player
  268. SpawnPlayer( clientNum );
  269. if ( clientNum == localClientNum ) {
  270. mpGame.EnterGame( clientNum );
  271. }
  272. // send message to spawn the player at the clients
  273. outMsg.Init( msgBuf, sizeof( msgBuf ) );
  274. outMsg.BeginWriting();
  275. outMsg.WriteByte( GAME_RELIABLE_MESSAGE_SPAWN_PLAYER );
  276. outMsg.WriteByte( clientNum );
  277. outMsg.WriteLong( spawnIds[ clientNum ] );
  278. networkSystem->ServerSendReliableMessage( -1, outMsg );
  279. }
  280. /*
  281. ================
  282. idGameLocal::ServerClientDisconnect
  283. ================
  284. */
  285. void idGameLocal::ServerClientDisconnect( int clientNum ) {
  286. int i;
  287. idBitMsg outMsg;
  288. byte msgBuf[MAX_GAME_MESSAGE_SIZE];
  289. outMsg.Init( msgBuf, sizeof( msgBuf ) );
  290. outMsg.BeginWriting();
  291. outMsg.WriteByte( GAME_RELIABLE_MESSAGE_DELETE_ENT );
  292. outMsg.WriteBits( ( spawnIds[ clientNum ] << GENTITYNUM_BITS ) | clientNum, 32 ); // see GetSpawnId
  293. networkSystem->ServerSendReliableMessage( -1, outMsg );
  294. // free snapshots stored for this client
  295. FreeSnapshotsOlderThanSequence( clientNum, 0x7FFFFFFF );
  296. // free entity states stored for this client
  297. for ( i = 0; i < MAX_GENTITIES; i++ ) {
  298. if ( clientEntityStates[ clientNum ][ i ] ) {
  299. entityStateAllocator.Free( clientEntityStates[ clientNum ][ i ] );
  300. clientEntityStates[ clientNum ][ i ] = NULL;
  301. }
  302. }
  303. // clear the client PVS
  304. memset( clientPVS[ clientNum ], 0, sizeof( clientPVS[ clientNum ] ) );
  305. // delete the player entity
  306. delete entities[ clientNum ];
  307. mpGame.DisconnectClient( clientNum );
  308. }
  309. /*
  310. ================
  311. idGameLocal::ServerWriteInitialReliableMessages
  312. Send reliable messages to initialize the client game up to a certain initial state.
  313. ================
  314. */
  315. void idGameLocal::ServerWriteInitialReliableMessages( int clientNum ) {
  316. int i;
  317. idBitMsg outMsg;
  318. byte msgBuf[MAX_GAME_MESSAGE_SIZE];
  319. entityNetEvent_t *event;
  320. // spawn players
  321. for ( i = 0; i < MAX_CLIENTS; i++ ) {
  322. if ( entities[i] == NULL || i == clientNum ) {
  323. continue;
  324. }
  325. outMsg.Init( msgBuf, sizeof( msgBuf ) );
  326. outMsg.BeginWriting( );
  327. outMsg.WriteByte( GAME_RELIABLE_MESSAGE_SPAWN_PLAYER );
  328. outMsg.WriteByte( i );
  329. outMsg.WriteLong( spawnIds[ i ] );
  330. networkSystem->ServerSendReliableMessage( clientNum, outMsg );
  331. }
  332. // send all saved events
  333. for ( event = savedEventQueue.Start(); event; event = event->next ) {
  334. outMsg.Init( msgBuf, sizeof( msgBuf ) );
  335. outMsg.BeginWriting();
  336. outMsg.WriteByte( GAME_RELIABLE_MESSAGE_EVENT );
  337. outMsg.WriteBits( event->spawnId, 32 );
  338. outMsg.WriteByte( event->event );
  339. outMsg.WriteLong( event->time );
  340. outMsg.WriteBits( event->paramsSize, idMath::BitsForInteger( MAX_EVENT_PARAM_SIZE ) );
  341. if ( event->paramsSize ) {
  342. outMsg.WriteData( event->paramsBuf, event->paramsSize );
  343. }
  344. networkSystem->ServerSendReliableMessage( clientNum, outMsg );
  345. }
  346. // update portals for opened doors
  347. int numPortals = gameRenderWorld->NumPortals();
  348. outMsg.Init( msgBuf, sizeof( msgBuf ) );
  349. outMsg.BeginWriting();
  350. outMsg.WriteByte( GAME_RELIABLE_MESSAGE_PORTALSTATES );
  351. outMsg.WriteLong( numPortals );
  352. for ( i = 0; i < numPortals; i++ ) {
  353. outMsg.WriteBits( gameRenderWorld->GetPortalState( (qhandle_t) (i+1) ) , NUM_RENDER_PORTAL_BITS );
  354. }
  355. networkSystem->ServerSendReliableMessage( clientNum, outMsg );
  356. mpGame.ServerWriteInitialReliableMessages( clientNum );
  357. }
  358. /*
  359. ================
  360. idGameLocal::SaveEntityNetworkEvent
  361. ================
  362. */
  363. void idGameLocal::SaveEntityNetworkEvent( const idEntity *ent, int eventId, const idBitMsg *msg ) {
  364. entityNetEvent_t *event;
  365. event = savedEventQueue.Alloc();
  366. event->spawnId = GetSpawnId( ent );
  367. event->event = eventId;
  368. event->time = time;
  369. if ( msg ) {
  370. event->paramsSize = msg->GetSize();
  371. memcpy( event->paramsBuf, msg->GetData(), msg->GetSize() );
  372. } else {
  373. event->paramsSize = 0;
  374. }
  375. savedEventQueue.Enqueue( event, idEventQueue::OUTOFORDER_IGNORE );
  376. }
  377. /*
  378. ================
  379. idGameLocal::FreeSnapshotsOlderThanSequence
  380. ================
  381. */
  382. void idGameLocal::FreeSnapshotsOlderThanSequence( int clientNum, int sequence ) {
  383. snapshot_t *snapshot, *lastSnapshot, *nextSnapshot;
  384. entityState_t *state;
  385. for ( lastSnapshot = NULL, snapshot = clientSnapshots[clientNum]; snapshot; snapshot = nextSnapshot ) {
  386. nextSnapshot = snapshot->next;
  387. if ( snapshot->sequence < sequence ) {
  388. for ( state = snapshot->firstEntityState; state; state = snapshot->firstEntityState ) {
  389. snapshot->firstEntityState = snapshot->firstEntityState->next;
  390. entityStateAllocator.Free( state );
  391. }
  392. if ( lastSnapshot ) {
  393. lastSnapshot->next = snapshot->next;
  394. } else {
  395. clientSnapshots[clientNum] = snapshot->next;
  396. }
  397. snapshotAllocator.Free( snapshot );
  398. } else {
  399. lastSnapshot = snapshot;
  400. }
  401. }
  402. }
  403. /*
  404. ================
  405. idGameLocal::ApplySnapshot
  406. ================
  407. */
  408. bool idGameLocal::ApplySnapshot( int clientNum, int sequence ) {
  409. snapshot_t *snapshot, *lastSnapshot, *nextSnapshot;
  410. entityState_t *state;
  411. FreeSnapshotsOlderThanSequence( clientNum, sequence );
  412. for ( lastSnapshot = NULL, snapshot = clientSnapshots[clientNum]; snapshot; snapshot = nextSnapshot ) {
  413. nextSnapshot = snapshot->next;
  414. if ( snapshot->sequence == sequence ) {
  415. for ( state = snapshot->firstEntityState; state; state = state->next ) {
  416. if ( clientEntityStates[clientNum][state->entityNumber] ) {
  417. entityStateAllocator.Free( clientEntityStates[clientNum][state->entityNumber] );
  418. }
  419. clientEntityStates[clientNum][state->entityNumber] = state;
  420. }
  421. memcpy( clientPVS[clientNum], snapshot->pvs, sizeof( snapshot->pvs ) );
  422. if ( lastSnapshot ) {
  423. lastSnapshot->next = nextSnapshot;
  424. } else {
  425. clientSnapshots[clientNum] = nextSnapshot;
  426. }
  427. snapshotAllocator.Free( snapshot );
  428. return true;
  429. } else {
  430. lastSnapshot = snapshot;
  431. }
  432. }
  433. return false;
  434. }
  435. /*
  436. ================
  437. idGameLocal::WriteGameStateToSnapshot
  438. ================
  439. */
  440. void idGameLocal::WriteGameStateToSnapshot( idBitMsgDelta &msg ) const {
  441. int i;
  442. for( i = 0; i < MAX_GLOBAL_SHADER_PARMS; i++ ) {
  443. msg.WriteFloat( globalShaderParms[i] );
  444. }
  445. mpGame.WriteToSnapshot( msg );
  446. }
  447. /*
  448. ================
  449. idGameLocal::ReadGameStateFromSnapshot
  450. ================
  451. */
  452. void idGameLocal::ReadGameStateFromSnapshot( const idBitMsgDelta &msg ) {
  453. int i;
  454. for( i = 0; i < MAX_GLOBAL_SHADER_PARMS; i++ ) {
  455. globalShaderParms[i] = msg.ReadFloat();
  456. }
  457. mpGame.ReadFromSnapshot( msg );
  458. }
  459. /*
  460. ================
  461. idGameLocal::ServerWriteSnapshot
  462. Write a snapshot of the current game state for the given client.
  463. ================
  464. */
  465. void idGameLocal::ServerWriteSnapshot( int clientNum, int sequence, idBitMsg &msg, byte *clientInPVS, int numPVSClients ) {
  466. int i, msgSize, msgWriteBit;
  467. idPlayer *player, *spectated = NULL;
  468. idEntity *ent;
  469. pvsHandle_t pvsHandle;
  470. idBitMsgDelta deltaMsg;
  471. snapshot_t *snapshot;
  472. entityState_t *base, *newBase;
  473. int numSourceAreas, sourceAreas[ idEntity::MAX_PVS_AREAS ];
  474. player = static_cast<idPlayer *>( entities[ clientNum ] );
  475. if ( !player ) {
  476. return;
  477. }
  478. if ( player->spectating && player->spectator != clientNum && entities[ player->spectator ] ) {
  479. spectated = static_cast< idPlayer * >( entities[ player->spectator ] );
  480. } else {
  481. spectated = player;
  482. }
  483. // free too old snapshots
  484. FreeSnapshotsOlderThanSequence( clientNum, sequence - 64 );
  485. // allocate new snapshot
  486. snapshot = snapshotAllocator.Alloc();
  487. snapshot->sequence = sequence;
  488. snapshot->firstEntityState = NULL;
  489. snapshot->next = clientSnapshots[clientNum];
  490. clientSnapshots[clientNum] = snapshot;
  491. memset( snapshot->pvs, 0, sizeof( snapshot->pvs ) );
  492. // get PVS for this player
  493. // don't use PVSAreas for networking - PVSAreas depends on animations (and md5 bounds), which are not synchronized
  494. numSourceAreas = gameRenderWorld->BoundsInAreas( spectated->GetPlayerPhysics()->GetAbsBounds(), sourceAreas, idEntity::MAX_PVS_AREAS );
  495. pvsHandle = gameLocal.pvs.SetupCurrentPVS( sourceAreas, numSourceAreas, PVS_NORMAL );
  496. #if ASYNC_WRITE_TAGS
  497. idRandom tagRandom;
  498. tagRandom.SetSeed( random.RandomInt() );
  499. msg.WriteLong( tagRandom.GetSeed() );
  500. #endif
  501. // create the snapshot
  502. for( ent = spawnedEntities.Next(); ent != NULL; ent = ent->spawnNode.Next() ) {
  503. // if the entity is not in the player PVS
  504. if ( !ent->PhysicsTeamInPVS( pvsHandle ) && ent->entityNumber != clientNum ) {
  505. continue;
  506. }
  507. // add the entity to the snapshot pvs
  508. snapshot->pvs[ ent->entityNumber >> 5 ] |= 1 << ( ent->entityNumber & 31 );
  509. // if that entity is not marked for network synchronization
  510. if ( !ent->fl.networkSync ) {
  511. continue;
  512. }
  513. // save the write state to which we can revert when the entity didn't change at all
  514. msg.SaveWriteState( msgSize, msgWriteBit );
  515. // write the entity to the snapshot
  516. msg.WriteBits( ent->entityNumber, GENTITYNUM_BITS );
  517. base = clientEntityStates[clientNum][ent->entityNumber];
  518. if ( base ) {
  519. base->state.BeginReading();
  520. }
  521. newBase = entityStateAllocator.Alloc();
  522. newBase->entityNumber = ent->entityNumber;
  523. newBase->state.Init( newBase->stateBuf, sizeof( newBase->stateBuf ) );
  524. newBase->state.BeginWriting();
  525. deltaMsg.Init( base ? &base->state : NULL, &newBase->state, &msg );
  526. deltaMsg.WriteBits( spawnIds[ ent->entityNumber ], 32 - GENTITYNUM_BITS );
  527. deltaMsg.WriteBits( ent->GetType()->typeNum, idClass::GetTypeNumBits() );
  528. deltaMsg.WriteBits( ServerRemapDecl( -1, DECL_ENTITYDEF, ent->entityDefNumber ), entityDefBits );
  529. // write the class specific data to the snapshot
  530. ent->WriteToSnapshot( deltaMsg );
  531. if ( !deltaMsg.HasChanged() ) {
  532. msg.RestoreWriteState( msgSize, msgWriteBit );
  533. entityStateAllocator.Free( newBase );
  534. } else {
  535. newBase->next = snapshot->firstEntityState;
  536. snapshot->firstEntityState = newBase;
  537. #if ASYNC_WRITE_TAGS
  538. msg.WriteLong( tagRandom.RandomInt() );
  539. #endif
  540. }
  541. }
  542. msg.WriteBits( ENTITYNUM_NONE, GENTITYNUM_BITS );
  543. // write the PVS to the snapshot
  544. #if ASYNC_WRITE_PVS
  545. for ( i = 0; i < idEntity::MAX_PVS_AREAS; i++ ) {
  546. if ( i < numSourceAreas ) {
  547. msg.WriteLong( sourceAreas[ i ] );
  548. } else {
  549. msg.WriteLong( 0 );
  550. }
  551. }
  552. gameLocal.pvs.WritePVS( pvsHandle, msg );
  553. #endif
  554. for ( i = 0; i < ENTITY_PVS_SIZE; i++ ) {
  555. msg.WriteDeltaLong( clientPVS[clientNum][i], snapshot->pvs[i] );
  556. }
  557. // free the PVS
  558. pvs.FreeCurrentPVS( pvsHandle );
  559. // write the game and player state to the snapshot
  560. base = clientEntityStates[clientNum][ENTITYNUM_NONE]; // ENTITYNUM_NONE is used for the game and player state
  561. if ( base ) {
  562. base->state.BeginReading();
  563. }
  564. newBase = entityStateAllocator.Alloc();
  565. newBase->entityNumber = ENTITYNUM_NONE;
  566. newBase->next = snapshot->firstEntityState;
  567. snapshot->firstEntityState = newBase;
  568. newBase->state.Init( newBase->stateBuf, sizeof( newBase->stateBuf ) );
  569. newBase->state.BeginWriting();
  570. deltaMsg.Init( base ? &base->state : NULL, &newBase->state, &msg );
  571. if ( player->spectating && player->spectator != player->entityNumber && gameLocal.entities[ player->spectator ] && gameLocal.entities[ player->spectator ]->IsType( idPlayer::Type ) ) {
  572. static_cast< idPlayer * >( gameLocal.entities[ player->spectator ] )->WritePlayerStateToSnapshot( deltaMsg );
  573. } else {
  574. player->WritePlayerStateToSnapshot( deltaMsg );
  575. }
  576. WriteGameStateToSnapshot( deltaMsg );
  577. // copy the client PVS string
  578. memcpy( clientInPVS, snapshot->pvs, ( numPVSClients + 7 ) >> 3 );
  579. LittleRevBytes( clientInPVS, sizeof( int ), sizeof( clientInPVS ) / sizeof ( int ) );
  580. }
  581. /*
  582. ================
  583. idGameLocal::ServerApplySnapshot
  584. ================
  585. */
  586. bool idGameLocal::ServerApplySnapshot( int clientNum, int sequence ) {
  587. return ApplySnapshot( clientNum, sequence );
  588. }
  589. /*
  590. ================
  591. idGameLocal::NetworkEventWarning
  592. ================
  593. */
  594. void idGameLocal::NetworkEventWarning( const entityNetEvent_t *event, const char *fmt, ... ) {
  595. char buf[1024];
  596. int length = 0;
  597. va_list argptr;
  598. int entityNum = event->spawnId & ( ( 1 << GENTITYNUM_BITS ) - 1 );
  599. int id = event->spawnId >> GENTITYNUM_BITS;
  600. length += idStr::snPrintf( buf+length, sizeof(buf)-1-length, "event %d for entity %d %d: ", event->event, entityNum, id );
  601. va_start( argptr, fmt );
  602. length = idStr::vsnPrintf( buf+length, sizeof(buf)-1-length, fmt, argptr );
  603. va_end( argptr );
  604. idStr::Append( buf, sizeof(buf), "\n" );
  605. common->DWarning( buf );
  606. }
  607. /*
  608. ================
  609. idGameLocal::ServerProcessEntityNetworkEventQueue
  610. ================
  611. */
  612. void idGameLocal::ServerProcessEntityNetworkEventQueue( void ) {
  613. idEntity *ent;
  614. entityNetEvent_t *event;
  615. idBitMsg eventMsg;
  616. while ( eventQueue.Start() ) {
  617. event = eventQueue.Start();
  618. if ( event->time > time ) {
  619. break;
  620. }
  621. idEntityPtr< idEntity > entPtr;
  622. if( !entPtr.SetSpawnId( event->spawnId ) ) {
  623. NetworkEventWarning( event, "Entity does not exist any longer, or has not been spawned yet." );
  624. } else {
  625. ent = entPtr.GetEntity();
  626. assert( ent );
  627. eventMsg.Init( event->paramsBuf, sizeof( event->paramsBuf ) );
  628. eventMsg.SetSize( event->paramsSize );
  629. eventMsg.BeginReading();
  630. if ( !ent->ServerReceiveEvent( event->event, event->time, eventMsg ) ) {
  631. NetworkEventWarning( event, "unknown event" );
  632. }
  633. }
  634. entityNetEvent_t* freedEvent = eventQueue.Dequeue();
  635. assert( freedEvent == event );
  636. eventQueue.Free( event );
  637. }
  638. }
  639. /*
  640. ================
  641. idGameLocal::ServerSendChatMessage
  642. ================
  643. */
  644. void idGameLocal::ServerSendChatMessage( int to, const char *name, const char *text ) {
  645. idBitMsg outMsg;
  646. byte msgBuf[ MAX_GAME_MESSAGE_SIZE ];
  647. outMsg.Init( msgBuf, sizeof( msgBuf ) );
  648. outMsg.BeginWriting();
  649. outMsg.WriteByte( GAME_RELIABLE_MESSAGE_CHAT );
  650. outMsg.WriteString( name );
  651. outMsg.WriteString( text, -1, false );
  652. networkSystem->ServerSendReliableMessage( to, outMsg );
  653. if ( to == -1 || to == localClientNum ) {
  654. mpGame.AddChatLine( "%s^0: %s\n", name, text );
  655. }
  656. }
  657. /*
  658. ================
  659. idGameLocal::ServerProcessReliableMessage
  660. ================
  661. */
  662. void idGameLocal::ServerProcessReliableMessage( int clientNum, const idBitMsg &msg ) {
  663. int id;
  664. id = msg.ReadByte();
  665. switch( id ) {
  666. case GAME_RELIABLE_MESSAGE_CHAT:
  667. case GAME_RELIABLE_MESSAGE_TCHAT: {
  668. char name[128];
  669. char text[128];
  670. msg.ReadString( name, sizeof( name ) );
  671. msg.ReadString( text, sizeof( text ) );
  672. mpGame.ProcessChatMessage( clientNum, id == GAME_RELIABLE_MESSAGE_TCHAT, name, text, NULL );
  673. break;
  674. }
  675. case GAME_RELIABLE_MESSAGE_VCHAT: {
  676. int index = msg.ReadLong();
  677. bool team = msg.ReadBits( 1 ) != 0;
  678. mpGame.ProcessVoiceChat( clientNum, team, index );
  679. break;
  680. }
  681. case GAME_RELIABLE_MESSAGE_KILL: {
  682. mpGame.WantKilled( clientNum );
  683. break;
  684. }
  685. case GAME_RELIABLE_MESSAGE_DROPWEAPON: {
  686. mpGame.DropWeapon( clientNum );
  687. break;
  688. }
  689. case GAME_RELIABLE_MESSAGE_CALLVOTE: {
  690. mpGame.ServerCallVote( clientNum, msg );
  691. break;
  692. }
  693. case GAME_RELIABLE_MESSAGE_CASTVOTE: {
  694. bool vote = ( msg.ReadByte() != 0 );
  695. mpGame.CastVote( clientNum, vote );
  696. break;
  697. }
  698. #if 0
  699. // uncomment this if you want to track when players are in a menu
  700. case GAME_RELIABLE_MESSAGE_MENU: {
  701. bool menuUp = ( msg.ReadBits( 1 ) != 0 );
  702. break;
  703. }
  704. #endif
  705. case GAME_RELIABLE_MESSAGE_EVENT: {
  706. entityNetEvent_t *event;
  707. // allocate new event
  708. event = eventQueue.Alloc();
  709. eventQueue.Enqueue( event, idEventQueue::OUTOFORDER_DROP );
  710. event->spawnId = msg.ReadBits( 32 );
  711. event->event = msg.ReadByte();
  712. event->time = msg.ReadLong();
  713. event->paramsSize = msg.ReadBits( idMath::BitsForInteger( MAX_EVENT_PARAM_SIZE ) );
  714. if ( event->paramsSize ) {
  715. if ( event->paramsSize > MAX_EVENT_PARAM_SIZE ) {
  716. NetworkEventWarning( event, "invalid param size" );
  717. return;
  718. }
  719. msg.ReadByteAlign();
  720. msg.ReadData( event->paramsBuf, event->paramsSize );
  721. }
  722. break;
  723. }
  724. default: {
  725. Warning( "Unknown client->server reliable message: %d", id );
  726. break;
  727. }
  728. }
  729. }
  730. /*
  731. ================
  732. idGameLocal::ClientShowSnapshot
  733. ================
  734. */
  735. void idGameLocal::ClientShowSnapshot( int clientNum ) const {
  736. int baseBits;
  737. idEntity *ent;
  738. idPlayer *player;
  739. idMat3 viewAxis;
  740. idBounds viewBounds;
  741. entityState_t *base;
  742. if ( !net_clientShowSnapshot.GetInteger() ) {
  743. return;
  744. }
  745. player = static_cast<idPlayer *>( entities[clientNum] );
  746. if ( !player ) {
  747. return;
  748. }
  749. viewAxis = player->viewAngles.ToMat3();
  750. viewBounds = player->GetPhysics()->GetAbsBounds().Expand( net_clientShowSnapshotRadius.GetFloat() );
  751. for( ent = snapshotEntities.Next(); ent != NULL; ent = ent->snapshotNode.Next() ) {
  752. if ( net_clientShowSnapshot.GetInteger() == 1 && ent->snapshotBits == 0 ) {
  753. continue;
  754. }
  755. const idBounds &entBounds = ent->GetPhysics()->GetAbsBounds();
  756. if ( !entBounds.IntersectsBounds( viewBounds ) ) {
  757. continue;
  758. }
  759. base = clientEntityStates[clientNum][ent->entityNumber];
  760. if ( base ) {
  761. baseBits = base->state.GetNumBitsWritten();
  762. } else {
  763. baseBits = 0;
  764. }
  765. if ( net_clientShowSnapshot.GetInteger() == 2 && baseBits == 0 ) {
  766. continue;
  767. }
  768. gameRenderWorld->DebugBounds( colorGreen, entBounds );
  769. gameRenderWorld->DrawText( va( "%d: %s (%d,%d bytes of %d,%d)\n", ent->entityNumber,
  770. ent->name.c_str(), ent->snapshotBits >> 3, ent->snapshotBits & 7, baseBits >> 3, baseBits & 7 ),
  771. entBounds.GetCenter(), 0.1f, colorWhite, viewAxis, 1 );
  772. }
  773. }
  774. /*
  775. ================
  776. idGameLocal::UpdateLagometer
  777. ================
  778. */
  779. void idGameLocal::UpdateLagometer( int aheadOfServer, int dupeUsercmds ) {
  780. int i, j, ahead;
  781. for ( i = 0; i < LAGO_HEIGHT; i++ ) {
  782. memmove( (byte *)lagometer + LAGO_WIDTH * 4 * i, (byte *)lagometer + LAGO_WIDTH * 4 * i + 4, ( LAGO_WIDTH - 1 ) * 4 );
  783. }
  784. j = LAGO_WIDTH - 1;
  785. for ( i = 0; i < LAGO_HEIGHT; i++ ) {
  786. lagometer[i][j][0] = lagometer[i][j][1] = lagometer[i][j][2] = lagometer[i][j][3] = 0;
  787. }
  788. ahead = idMath::Rint( (float)aheadOfServer / 16.0f );
  789. if ( ahead >= 0 ) {
  790. for ( i = 2 * Max( 0, 5 - ahead ); i < 2 * 5; i++ ) {
  791. lagometer[i][j][1] = 255;
  792. lagometer[i][j][3] = 255;
  793. }
  794. } else {
  795. for ( i = 2 * 5; i < 2 * ( 5 + Min( 10, -ahead ) ); i++ ) {
  796. lagometer[i][j][0] = 255;
  797. lagometer[i][j][1] = 255;
  798. lagometer[i][j][3] = 255;
  799. }
  800. }
  801. for ( i = LAGO_HEIGHT - 2 * Min( 6, dupeUsercmds ); i < LAGO_HEIGHT; i++ ) {
  802. lagometer[i][j][0] = 255;
  803. if ( dupeUsercmds <= 2 ) {
  804. lagometer[i][j][1] = 255;
  805. }
  806. lagometer[i][j][3] = 255;
  807. }
  808. }
  809. /*
  810. ================
  811. idGameLocal::ClientReadSnapshot
  812. ================
  813. */
  814. void idGameLocal::ClientReadSnapshot( int clientNum, int sequence, const int gameFrame, const int gameTime, const int dupeUsercmds, const int aheadOfServer, const idBitMsg &msg ) {
  815. int i, typeNum, entityDefNumber, numBitsRead;
  816. idTypeInfo *typeInfo;
  817. idEntity *ent;
  818. idPlayer *player, *spectated;
  819. pvsHandle_t pvsHandle;
  820. idDict args;
  821. const char *classname;
  822. idBitMsgDelta deltaMsg;
  823. snapshot_t *snapshot;
  824. entityState_t *base, *newBase;
  825. int spawnId;
  826. int numSourceAreas, sourceAreas[ idEntity::MAX_PVS_AREAS ];
  827. idWeapon *weap;
  828. if ( net_clientLagOMeter.GetBool() && renderSystem ) {
  829. UpdateLagometer( aheadOfServer, dupeUsercmds );
  830. if ( !renderSystem->UploadImage( LAGO_IMAGE, (byte *)lagometer, LAGO_IMG_WIDTH, LAGO_IMG_HEIGHT ) ) {
  831. common->Printf( "lagometer: UploadImage failed. turning off net_clientLagOMeter\n" );
  832. net_clientLagOMeter.SetBool( false );
  833. }
  834. }
  835. InitLocalClient( clientNum );
  836. // clear any debug lines from a previous frame
  837. gameRenderWorld->DebugClearLines( time );
  838. // clear any debug polygons from a previous frame
  839. gameRenderWorld->DebugClearPolygons( time );
  840. // update the game time
  841. framenum = gameFrame;
  842. time = gameTime;
  843. previousTime = time - msec;
  844. // so that StartSound/StopSound doesn't risk skipping
  845. isNewFrame = true;
  846. // clear the snapshot entity list
  847. snapshotEntities.Clear();
  848. // allocate new snapshot
  849. snapshot = snapshotAllocator.Alloc();
  850. snapshot->sequence = sequence;
  851. snapshot->firstEntityState = NULL;
  852. snapshot->next = clientSnapshots[clientNum];
  853. clientSnapshots[clientNum] = snapshot;
  854. #if ASYNC_WRITE_TAGS
  855. idRandom tagRandom;
  856. tagRandom.SetSeed( msg.ReadLong() );
  857. #endif
  858. // read all entities from the snapshot
  859. for ( i = msg.ReadBits( GENTITYNUM_BITS ); i != ENTITYNUM_NONE; i = msg.ReadBits( GENTITYNUM_BITS ) ) {
  860. base = clientEntityStates[clientNum][i];
  861. if ( base ) {
  862. base->state.BeginReading();
  863. }
  864. newBase = entityStateAllocator.Alloc();
  865. newBase->entityNumber = i;
  866. newBase->next = snapshot->firstEntityState;
  867. snapshot->firstEntityState = newBase;
  868. newBase->state.Init( newBase->stateBuf, sizeof( newBase->stateBuf ) );
  869. newBase->state.BeginWriting();
  870. numBitsRead = msg.GetNumBitsRead();
  871. deltaMsg.Init( base ? &base->state : NULL, &newBase->state, &msg );
  872. spawnId = deltaMsg.ReadBits( 32 - GENTITYNUM_BITS );
  873. typeNum = deltaMsg.ReadBits( idClass::GetTypeNumBits() );
  874. entityDefNumber = ClientRemapDecl( DECL_ENTITYDEF, deltaMsg.ReadBits( entityDefBits ) );
  875. typeInfo = idClass::GetType( typeNum );
  876. if ( !typeInfo ) {
  877. Error( "Unknown type number %d for entity %d with class number %d", typeNum, i, entityDefNumber );
  878. }
  879. ent = entities[i];
  880. // if there is no entity or an entity of the wrong type
  881. if ( !ent || ent->GetType()->typeNum != typeNum || ent->entityDefNumber != entityDefNumber || spawnId != spawnIds[ i ] ) {
  882. if ( i < MAX_CLIENTS && ent ) {
  883. // SPAWN_PLAYER should be taking care of spawning the entity with the right spawnId
  884. common->Warning( "ClientReadSnapshot: recycling client entity %d\n", i );
  885. }
  886. delete ent;
  887. spawnCount = spawnId;
  888. args.Clear();
  889. args.SetInt( "spawn_entnum", i );
  890. args.Set( "name", va( "entity%d", i ) );
  891. if ( entityDefNumber >= 0 ) {
  892. if ( entityDefNumber >= declManager->GetNumDecls( DECL_ENTITYDEF ) ) {
  893. Error( "server has %d entityDefs instead of %d", entityDefNumber, declManager->GetNumDecls( DECL_ENTITYDEF ) );
  894. }
  895. classname = declManager->DeclByIndex( DECL_ENTITYDEF, entityDefNumber, false )->GetName();
  896. args.Set( "classname", classname );
  897. if ( !SpawnEntityDef( args, &ent ) || !entities[i] || entities[i]->GetType()->typeNum != typeNum ) {
  898. Error( "Failed to spawn entity with classname '%s' of type '%s'", classname, typeInfo->classname );
  899. }
  900. } else {
  901. ent = SpawnEntityType( *typeInfo, &args, true );
  902. if ( !entities[i] || entities[i]->GetType()->typeNum != typeNum ) {
  903. Error( "Failed to spawn entity of type '%s'", typeInfo->classname );
  904. }
  905. }
  906. if ( i < MAX_CLIENTS && i >= numClients ) {
  907. numClients = i + 1;
  908. }
  909. }
  910. // add the entity to the snapshot list
  911. ent->snapshotNode.AddToEnd( snapshotEntities );
  912. ent->snapshotSequence = sequence;
  913. // read the class specific data from the snapshot
  914. ent->ReadFromSnapshot( deltaMsg );
  915. ent->snapshotBits = msg.GetNumBitsRead() - numBitsRead;
  916. #if ASYNC_WRITE_TAGS
  917. if ( msg.ReadLong() != tagRandom.RandomInt() ) {
  918. cmdSystem->BufferCommandText( CMD_EXEC_NOW, "writeGameState" );
  919. if ( entityDefNumber >= 0 && entityDefNumber < declManager->GetNumDecls( DECL_ENTITYDEF ) ) {
  920. classname = declManager->DeclByIndex( DECL_ENTITYDEF, entityDefNumber, false )->GetName();
  921. Error( "write to and read from snapshot out of sync for classname '%s' of type '%s'", classname, typeInfo->classname );
  922. } else {
  923. Error( "write to and read from snapshot out of sync for type '%s'", typeInfo->classname );
  924. }
  925. }
  926. #endif
  927. }
  928. player = static_cast<idPlayer *>( entities[clientNum] );
  929. if ( !player ) {
  930. return;
  931. }
  932. // if prediction is off, enable local client smoothing
  933. player->SetSelfSmooth( dupeUsercmds > 2 );
  934. if ( player->spectating && player->spectator != clientNum && entities[ player->spectator ] ) {
  935. spectated = static_cast< idPlayer * >( entities[ player->spectator ] );
  936. } else {
  937. spectated = player;
  938. }
  939. // get PVS for this player
  940. // don't use PVSAreas for networking - PVSAreas depends on animations (and md5 bounds), which are not synchronized
  941. numSourceAreas = gameRenderWorld->BoundsInAreas( spectated->GetPlayerPhysics()->GetAbsBounds(), sourceAreas, idEntity::MAX_PVS_AREAS );
  942. pvsHandle = gameLocal.pvs.SetupCurrentPVS( sourceAreas, numSourceAreas, PVS_NORMAL );
  943. // read the PVS from the snapshot
  944. #if ASYNC_WRITE_PVS
  945. int serverPVS[idEntity::MAX_PVS_AREAS];
  946. i = numSourceAreas;
  947. while ( i < idEntity::MAX_PVS_AREAS ) {
  948. sourceAreas[ i++ ] = 0;
  949. }
  950. for ( i = 0; i < idEntity::MAX_PVS_AREAS; i++ ) {
  951. serverPVS[ i ] = msg.ReadLong();
  952. }
  953. if ( memcmp( sourceAreas, serverPVS, idEntity::MAX_PVS_AREAS * sizeof( int ) ) ) {
  954. common->Warning( "client PVS areas != server PVS areas, sequence 0x%x", sequence );
  955. for ( i = 0; i < idEntity::MAX_PVS_AREAS; i++ ) {
  956. common->DPrintf( "%3d ", sourceAreas[ i ] );
  957. }
  958. common->DPrintf( "\n" );
  959. for ( i = 0; i < idEntity::MAX_PVS_AREAS; i++ ) {
  960. common->DPrintf( "%3d ", serverPVS[ i ] );
  961. }
  962. common->DPrintf( "\n" );
  963. }
  964. gameLocal.pvs.ReadPVS( pvsHandle, msg );
  965. #endif
  966. for ( i = 0; i < ENTITY_PVS_SIZE; i++ ) {
  967. snapshot->pvs[i] = msg.ReadDeltaLong( clientPVS[clientNum][i] );
  968. }
  969. // add entities in the PVS that haven't changed since the last applied snapshot
  970. for( ent = spawnedEntities.Next(); ent != NULL; ent = ent->spawnNode.Next() ) {
  971. // if the entity is already in the snapshot
  972. if ( ent->snapshotSequence == sequence ) {
  973. continue;
  974. }
  975. // if the entity is not in the snapshot PVS
  976. if ( !( snapshot->pvs[ent->entityNumber >> 5] & ( 1 << ( ent->entityNumber & 31 ) ) ) ) {
  977. if ( ent->PhysicsTeamInPVS( pvsHandle ) ) {
  978. if ( ent->entityNumber >= MAX_CLIENTS && ent->entityNumber < mapSpawnCount ) {
  979. // server says it's not in PVS, client says it's in PVS
  980. // if that happens on map entities, most likely something is wrong
  981. // I can see that moving pieces along several PVS could be a legit situation though
  982. // this is a band aid, which means something is not done right elsewhere
  983. common->DWarning( "client thinks map entity 0x%x (%s) is stale, sequence 0x%x", ent->entityNumber, ent->name.c_str(), sequence );
  984. } else {
  985. ent->FreeModelDef();
  986. ent->UpdateVisuals();
  987. ent->GetPhysics()->UnlinkClip();
  988. }
  989. }
  990. continue;
  991. }
  992. // add the entity to the snapshot list
  993. ent->snapshotNode.AddToEnd( snapshotEntities );
  994. ent->snapshotSequence = sequence;
  995. ent->snapshotBits = 0;
  996. base = clientEntityStates[clientNum][ent->entityNumber];
  997. if ( !base ) {
  998. // entity has probably fl.networkSync set to false
  999. continue;
  1000. }
  1001. base->state.BeginReading();
  1002. deltaMsg.Init( &base->state, NULL, (const idBitMsg *)NULL );
  1003. spawnId = deltaMsg.ReadBits( 32 - GENTITYNUM_BITS );
  1004. typeNum = deltaMsg.ReadBits( idClass::GetTypeNumBits() );
  1005. entityDefNumber = deltaMsg.ReadBits( entityDefBits );
  1006. typeInfo = idClass::GetType( typeNum );
  1007. // if the entity is not the right type
  1008. if ( !typeInfo || ent->GetType()->typeNum != typeNum || ent->entityDefNumber != entityDefNumber ) {
  1009. // should never happen - it does though. with != entityDefNumber only?
  1010. common->DWarning( "entity '%s' is not the right type %p 0x%d 0x%x 0x%x 0x%x", ent->GetName(), typeInfo, ent->GetType()->typeNum, typeNum, ent->entityDefNumber, entityDefNumber );
  1011. continue;
  1012. }
  1013. // read the class specific data from the base state
  1014. ent->ReadFromSnapshot( deltaMsg );
  1015. }
  1016. // free the PVS
  1017. pvs.FreeCurrentPVS( pvsHandle );
  1018. // read the game and player state from the snapshot
  1019. base = clientEntityStates[clientNum][ENTITYNUM_NONE]; // ENTITYNUM_NONE is used for the game and player state
  1020. if ( base ) {
  1021. base->state.BeginReading();
  1022. }
  1023. newBase = entityStateAllocator.Alloc();
  1024. newBase->entityNumber = ENTITYNUM_NONE;
  1025. newBase->next = snapshot->firstEntityState;
  1026. snapshot->firstEntityState = newBase;
  1027. newBase->state.Init( newBase->stateBuf, sizeof( newBase->stateBuf ) );
  1028. newBase->state.BeginWriting();
  1029. deltaMsg.Init( base ? &base->state : NULL, &newBase->state, &msg );
  1030. if ( player->spectating && player->spectator != player->entityNumber && gameLocal.entities[ player->spectator ] && gameLocal.entities[ player->spectator ]->IsType( idPlayer::Type ) ) {
  1031. static_cast< idPlayer * >( gameLocal.entities[ player->spectator ] )->ReadPlayerStateFromSnapshot( deltaMsg );
  1032. weap = static_cast< idPlayer * >( gameLocal.entities[ player->spectator ] )->weapon.GetEntity();
  1033. if ( weap && ( weap->GetRenderEntity()->bounds[0] == weap->GetRenderEntity()->bounds[1] ) ) {
  1034. // update the weapon's viewmodel bounds so that the model doesn't flicker in the spectator's view
  1035. weap->GetAnimator()->GetBounds( gameLocal.time, weap->GetRenderEntity()->bounds );
  1036. weap->UpdateVisuals();
  1037. }
  1038. } else {
  1039. player->ReadPlayerStateFromSnapshot( deltaMsg );
  1040. }
  1041. ReadGameStateFromSnapshot( deltaMsg );
  1042. // visualize the snapshot
  1043. ClientShowSnapshot( clientNum );
  1044. // process entity events
  1045. ClientProcessEntityNetworkEventQueue();
  1046. }
  1047. /*
  1048. ================
  1049. idGameLocal::ClientApplySnapshot
  1050. ================
  1051. */
  1052. bool idGameLocal::ClientApplySnapshot( int clientNum, int sequence ) {
  1053. return ApplySnapshot( clientNum, sequence );
  1054. }
  1055. /*
  1056. ================
  1057. idGameLocal::ClientProcessEntityNetworkEventQueue
  1058. ================
  1059. */
  1060. void idGameLocal::ClientProcessEntityNetworkEventQueue( void ) {
  1061. idEntity *ent;
  1062. entityNetEvent_t *event;
  1063. idBitMsg eventMsg;
  1064. while( eventQueue.Start() ) {
  1065. event = eventQueue.Start();
  1066. // only process forward, in order
  1067. if ( event->time > time ) {
  1068. break;
  1069. }
  1070. idEntityPtr< idEntity > entPtr;
  1071. if( !entPtr.SetSpawnId( event->spawnId ) ) {
  1072. if( !gameLocal.entities[ event->spawnId & ( ( 1 << GENTITYNUM_BITS ) - 1 ) ] ) {
  1073. // if new entity exists in this position, silently ignore
  1074. NetworkEventWarning( event, "Entity does not exist any longer, or has not been spawned yet." );
  1075. }
  1076. } else {
  1077. ent = entPtr.GetEntity();
  1078. assert( ent );
  1079. eventMsg.Init( event->paramsBuf, sizeof( event->paramsBuf ) );
  1080. eventMsg.SetSize( event->paramsSize );
  1081. eventMsg.BeginReading();
  1082. if ( !ent->ClientReceiveEvent( event->event, event->time, eventMsg ) ) {
  1083. NetworkEventWarning( event, "unknown event" );
  1084. }
  1085. }
  1086. entityNetEvent_t* freedEvent = eventQueue.Dequeue();
  1087. assert( freedEvent == event );
  1088. eventQueue.Free( event );
  1089. }
  1090. }
  1091. /*
  1092. ================
  1093. idGameLocal::ClientProcessReliableMessage
  1094. ================
  1095. */
  1096. void idGameLocal::ClientProcessReliableMessage( int clientNum, const idBitMsg &msg ) {
  1097. int id, line;
  1098. idPlayer *p;
  1099. idDict backupSI;
  1100. InitLocalClient( clientNum );
  1101. id = msg.ReadByte();
  1102. switch( id ) {
  1103. case GAME_RELIABLE_MESSAGE_INIT_DECL_REMAP: {
  1104. InitClientDeclRemap( clientNum );
  1105. break;
  1106. }
  1107. case GAME_RELIABLE_MESSAGE_REMAP_DECL: {
  1108. int type, index;
  1109. char name[MAX_STRING_CHARS];
  1110. type = msg.ReadByte();
  1111. index = msg.ReadLong();
  1112. msg.ReadString( name, sizeof( name ) );
  1113. const idDecl *decl = declManager->FindType( (declType_t)type, name, false );
  1114. if ( decl != NULL ) {
  1115. if ( index >= clientDeclRemap[clientNum][type].Num() ) {
  1116. clientDeclRemap[clientNum][type].AssureSize( index + 1, -1 );
  1117. }
  1118. clientDeclRemap[clientNum][type][index] = decl->Index();
  1119. }
  1120. break;
  1121. }
  1122. case GAME_RELIABLE_MESSAGE_SPAWN_PLAYER: {
  1123. int client = msg.ReadByte();
  1124. int spawnId = msg.ReadLong();
  1125. if ( !entities[ client ] ) {
  1126. SpawnPlayer( client );
  1127. entities[ client ]->FreeModelDef();
  1128. }
  1129. // fix up the spawnId to match what the server says
  1130. // otherwise there is going to be a bogus delete/new of the client entity in the first ClientReadFromSnapshot
  1131. spawnIds[ client ] = spawnId;
  1132. break;
  1133. }
  1134. case GAME_RELIABLE_MESSAGE_DELETE_ENT: {
  1135. int spawnId = msg.ReadBits( 32 );
  1136. idEntityPtr< idEntity > entPtr;
  1137. if( !entPtr.SetSpawnId( spawnId ) ) {
  1138. break;
  1139. }
  1140. delete entPtr.GetEntity();
  1141. break;
  1142. }
  1143. case GAME_RELIABLE_MESSAGE_CHAT:
  1144. case GAME_RELIABLE_MESSAGE_TCHAT: { // (client should never get a TCHAT though)
  1145. char name[128];
  1146. char text[128];
  1147. msg.ReadString( name, sizeof( name ) );
  1148. msg.ReadString( text, sizeof( text ) );
  1149. mpGame.AddChatLine( "%s^0: %s\n", name, text );
  1150. break;
  1151. }
  1152. case GAME_RELIABLE_MESSAGE_SOUND_EVENT: {
  1153. snd_evt_t snd_evt = (snd_evt_t)msg.ReadByte();
  1154. mpGame.PlayGlobalSound( -1, snd_evt );
  1155. break;
  1156. }
  1157. case GAME_RELIABLE_MESSAGE_SOUND_INDEX: {
  1158. int index = gameLocal.ClientRemapDecl( DECL_SOUND, msg.ReadLong() );
  1159. if ( index >= 0 && index < declManager->GetNumDecls( DECL_SOUND ) ) {
  1160. const idSoundShader *shader = declManager->SoundByIndex( index );
  1161. mpGame.PlayGlobalSound( -1, SND_COUNT, shader->GetName() );
  1162. }
  1163. break;
  1164. }
  1165. case GAME_RELIABLE_MESSAGE_DB: {
  1166. idMultiplayerGame::msg_evt_t msg_evt = (idMultiplayerGame::msg_evt_t)msg.ReadByte();
  1167. int parm1, parm2;
  1168. parm1 = msg.ReadByte( );
  1169. parm2 = msg.ReadByte( );
  1170. mpGame.PrintMessageEvent( -1, msg_evt, parm1, parm2 );
  1171. break;
  1172. }
  1173. case GAME_RELIABLE_MESSAGE_EVENT: {
  1174. entityNetEvent_t *event;
  1175. // allocate new event
  1176. event = eventQueue.Alloc();
  1177. eventQueue.Enqueue( event, idEventQueue::OUTOFORDER_IGNORE );
  1178. event->spawnId = msg.ReadBits( 32 );
  1179. event->event = msg.ReadByte();
  1180. event->time = msg.ReadLong();
  1181. event->paramsSize = msg.ReadBits( idMath::BitsForInteger( MAX_EVENT_PARAM_SIZE ) );
  1182. if ( event->paramsSize ) {
  1183. if ( event->paramsSize > MAX_EVENT_PARAM_SIZE ) {
  1184. NetworkEventWarning( event, "invalid param size" );
  1185. return;
  1186. }
  1187. msg.ReadByteAlign();
  1188. msg.ReadData( event->paramsBuf, event->paramsSize );
  1189. }
  1190. break;
  1191. }
  1192. case GAME_RELIABLE_MESSAGE_SERVERINFO: {
  1193. idDict info;
  1194. msg.ReadDeltaDict( info, NULL );
  1195. gameLocal.SetServerInfo( info );
  1196. break;
  1197. }
  1198. case GAME_RELIABLE_MESSAGE_RESTART: {
  1199. MapRestart();
  1200. break;
  1201. }
  1202. case GAME_RELIABLE_MESSAGE_TOURNEYLINE: {
  1203. line = msg.ReadByte( );
  1204. p = static_cast< idPlayer * >( entities[ clientNum ] );
  1205. if ( !p ) {
  1206. break;
  1207. }
  1208. p->tourneyLine = line;
  1209. break;
  1210. }
  1211. case GAME_RELIABLE_MESSAGE_STARTVOTE: {
  1212. char voteString[ MAX_STRING_CHARS ];
  1213. int clientNum = msg.ReadByte( );
  1214. msg.ReadString( voteString, sizeof( voteString ) );
  1215. mpGame.ClientStartVote( clientNum, voteString );
  1216. break;
  1217. }
  1218. case GAME_RELIABLE_MESSAGE_UPDATEVOTE: {
  1219. int result = msg.ReadByte( );
  1220. int yesCount = msg.ReadByte( );
  1221. int noCount = msg.ReadByte( );
  1222. mpGame.ClientUpdateVote( (idMultiplayerGame::vote_result_t)result, yesCount, noCount );
  1223. break;
  1224. }
  1225. case GAME_RELIABLE_MESSAGE_PORTALSTATES: {
  1226. int numPortals = msg.ReadLong();
  1227. assert( numPortals == gameRenderWorld->NumPortals() );
  1228. for ( int i = 0; i < numPortals; i++ ) {
  1229. gameRenderWorld->SetPortalState( (qhandle_t) (i+1), msg.ReadBits( NUM_RENDER_PORTAL_BITS ) );
  1230. }
  1231. break;
  1232. }
  1233. case GAME_RELIABLE_MESSAGE_PORTAL: {
  1234. qhandle_t portal = msg.ReadLong();
  1235. int blockingBits = msg.ReadBits( NUM_RENDER_PORTAL_BITS );
  1236. assert( portal > 0 && portal <= gameRenderWorld->NumPortals() );
  1237. gameRenderWorld->SetPortalState( portal, blockingBits );
  1238. break;
  1239. }
  1240. case GAME_RELIABLE_MESSAGE_STARTSTATE: {
  1241. mpGame.ClientReadStartState( msg );
  1242. break;
  1243. }
  1244. case GAME_RELIABLE_MESSAGE_WARMUPTIME: {
  1245. mpGame.ClientReadWarmupTime( msg );
  1246. break;
  1247. }
  1248. default: {
  1249. Error( "Unknown server->client reliable message: %d", id );
  1250. break;
  1251. }
  1252. }
  1253. }
  1254. /*
  1255. ================
  1256. idGameLocal::ClientPrediction
  1257. ================
  1258. */
  1259. gameReturn_t idGameLocal::ClientPrediction( int clientNum, const usercmd_t *clientCmds, bool lastPredictFrame ) {
  1260. idEntity *ent;
  1261. idPlayer *player;
  1262. gameReturn_t ret;
  1263. ret.sessionCommand[ 0 ] = '\0';
  1264. player = static_cast<idPlayer *>( entities[clientNum] );
  1265. if ( !player ) {
  1266. return ret;
  1267. }
  1268. // check for local client lag
  1269. if ( networkSystem->ClientGetTimeSinceLastPacket() >= net_clientMaxPrediction.GetInteger() ) {
  1270. player->isLagged = true;
  1271. } else {
  1272. player->isLagged = false;
  1273. }
  1274. InitLocalClient( clientNum );
  1275. // update the game time
  1276. framenum++;
  1277. previousTime = time;
  1278. time += msec;
  1279. // update the real client time and the new frame flag
  1280. if ( time > realClientTime ) {
  1281. realClientTime = time;
  1282. isNewFrame = true;
  1283. } else {
  1284. isNewFrame = false;
  1285. }
  1286. // set the user commands for this frame
  1287. memcpy( usercmds, clientCmds, numClients * sizeof( usercmds[ 0 ] ) );
  1288. // run prediction on all entities from the last snapshot
  1289. for( ent = snapshotEntities.Next(); ent != NULL; ent = ent->snapshotNode.Next() ) {
  1290. ent->thinkFlags |= TH_PHYSICS;
  1291. ent->ClientPredictionThink();
  1292. }
  1293. // service any pending events
  1294. idEvent::ServiceEvents();
  1295. // show any debug info for this frame
  1296. if ( isNewFrame ) {
  1297. RunDebugInfo();
  1298. D_DrawDebugLines();
  1299. }
  1300. if ( sessionCommand.Length() ) {
  1301. strncpy( ret.sessionCommand, sessionCommand, sizeof( ret.sessionCommand ) );
  1302. }
  1303. return ret;
  1304. }
  1305. /*
  1306. ===============
  1307. idGameLocal::Tokenize
  1308. ===============
  1309. */
  1310. void idGameLocal::Tokenize( idStrList &out, const char *in ) {
  1311. char buf[ MAX_STRING_CHARS ];
  1312. char *token, *next;
  1313. idStr::Copynz( buf, in, MAX_STRING_CHARS );
  1314. token = buf;
  1315. next = strchr( token, ';' );
  1316. while ( token ) {
  1317. if ( next ) {
  1318. *next = '\0';
  1319. }
  1320. idStr::ToLower( token );
  1321. out.Append( token );
  1322. if ( next ) {
  1323. token = next + 1;
  1324. next = strchr( token, ';' );
  1325. } else {
  1326. token = NULL;
  1327. }
  1328. }
  1329. }
  1330. /*
  1331. ===============
  1332. idGameLocal::DownloadRequest
  1333. ===============
  1334. */
  1335. bool idGameLocal::DownloadRequest( const char *IP, const char *guid, const char *paks, char urls[ MAX_STRING_CHARS ] ) {
  1336. if ( !cvarSystem->GetCVarInteger( "net_serverDownload" ) ) {
  1337. return false;
  1338. }
  1339. if ( cvarSystem->GetCVarInteger( "net_serverDownload" ) == 1 ) {
  1340. // 1: single URL redirect
  1341. if ( !strlen( cvarSystem->GetCVarString( "si_serverURL" ) ) ) {
  1342. common->Warning( "si_serverURL not set" );
  1343. return false;
  1344. }
  1345. idStr::snPrintf( urls, MAX_STRING_CHARS, "1;%s", cvarSystem->GetCVarString( "si_serverURL" ) );
  1346. return true;
  1347. } else {
  1348. // 2: table of pak URLs
  1349. // first token is the game pak if request, empty if not requested by the client
  1350. // there may be empty tokens for paks the server couldn't pinpoint - the order matters
  1351. idStr reply = "2;";
  1352. idStrList dlTable, pakList;
  1353. int i, j;
  1354. Tokenize( dlTable, cvarSystem->GetCVarString( "net_serverDlTable" ) );
  1355. Tokenize( pakList, paks );
  1356. for ( i = 0; i < pakList.Num(); i++ ) {
  1357. if ( i > 0 ) {
  1358. reply += ";";
  1359. }
  1360. if ( pakList[ i ][ 0 ] == '\0' ) {
  1361. if ( i == 0 ) {
  1362. // pak 0 will always miss when client doesn't ask for game bin
  1363. common->DPrintf( "no game pak request\n" );
  1364. } else {
  1365. common->DPrintf( "no pak %d\n", i );
  1366. }
  1367. continue;
  1368. }
  1369. for ( j = 0; j < dlTable.Num(); j++ ) {
  1370. if ( !fileSystem->FilenameCompare( pakList[ i ], dlTable[ j ] ) ) {
  1371. break;
  1372. }
  1373. }
  1374. if ( j == dlTable.Num() ) {
  1375. common->Printf( "download for %s: pak not matched: %s\n", IP, pakList[ i ].c_str() );
  1376. } else {
  1377. idStr url = cvarSystem->GetCVarString( "net_serverDlBaseURL" );
  1378. url.AppendPath( dlTable[ j ] );
  1379. reply += url;
  1380. common->DPrintf( "download for %s: %s\n", IP, url.c_str() );
  1381. }
  1382. }
  1383. idStr::Copynz( urls, reply, MAX_STRING_CHARS );
  1384. return true;
  1385. }
  1386. return false;
  1387. }
  1388. /*
  1389. ===============
  1390. idEventQueue::Alloc
  1391. ===============
  1392. */
  1393. entityNetEvent_t* idEventQueue::Alloc() {
  1394. entityNetEvent_t* event = eventAllocator.Alloc();
  1395. event->prev = NULL;
  1396. event->next = NULL;
  1397. return event;
  1398. }
  1399. /*
  1400. ===============
  1401. idEventQueue::Free
  1402. ===============
  1403. */
  1404. void idEventQueue::Free( entityNetEvent_t *event ) {
  1405. // should only be called on an unlinked event!
  1406. assert( !event->next && !event->prev );
  1407. eventAllocator.Free( event );
  1408. }
  1409. /*
  1410. ===============
  1411. idEventQueue::Shutdown
  1412. ===============
  1413. */
  1414. void idEventQueue::Shutdown() {
  1415. eventAllocator.Shutdown();
  1416. this->Init();
  1417. }
  1418. /*
  1419. ===============
  1420. idEventQueue::Init
  1421. ===============
  1422. */
  1423. void idEventQueue::Init( void ) {
  1424. start = NULL;
  1425. end = NULL;
  1426. }
  1427. /*
  1428. ===============
  1429. idEventQueue::Dequeue
  1430. ===============
  1431. */
  1432. entityNetEvent_t* idEventQueue::Dequeue( void ) {
  1433. entityNetEvent_t* event = start;
  1434. if ( !event ) {
  1435. return NULL;
  1436. }
  1437. start = start->next;
  1438. if ( !start ) {
  1439. end = NULL;
  1440. } else {
  1441. start->prev = NULL;
  1442. }
  1443. event->next = NULL;
  1444. event->prev = NULL;
  1445. return event;
  1446. }
  1447. /*
  1448. ===============
  1449. idEventQueue::RemoveLast
  1450. ===============
  1451. */
  1452. entityNetEvent_t* idEventQueue::RemoveLast( void ) {
  1453. entityNetEvent_t *event = end;
  1454. if ( !event ) {
  1455. return NULL;
  1456. }
  1457. end = event->prev;
  1458. if ( !end ) {
  1459. start = NULL;
  1460. } else {
  1461. end->next = NULL;
  1462. }
  1463. event->next = NULL;
  1464. event->prev = NULL;
  1465. return event;
  1466. }
  1467. /*
  1468. ===============
  1469. idEventQueue::Enqueue
  1470. ===============
  1471. */
  1472. void idEventQueue::Enqueue( entityNetEvent_t *event, outOfOrderBehaviour_t behaviour ) {
  1473. if ( behaviour == OUTOFORDER_DROP ) {
  1474. // go backwards through the queue and determine if there are
  1475. // any out-of-order events
  1476. while ( end && end->time > event->time ) {
  1477. entityNetEvent_t *outOfOrder = RemoveLast();
  1478. 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 );
  1479. Free( outOfOrder );
  1480. }
  1481. } else if ( behaviour == OUTOFORDER_SORT && end ) {
  1482. // NOT TESTED -- sorting out of order packets hasn't been
  1483. // tested yet... wasn't strictly necessary for
  1484. // the patch fix.
  1485. entityNetEvent_t *cur = end;
  1486. // iterate until we find a time < the new event's
  1487. while ( cur && cur->time > event->time ) {
  1488. cur = cur->prev;
  1489. }
  1490. if ( !cur ) {
  1491. // add to start
  1492. event->next = start;
  1493. event->prev = NULL;
  1494. start = event;
  1495. } else {
  1496. // insert
  1497. event->prev = cur;
  1498. event->next = cur->next;
  1499. cur->next = event;
  1500. }
  1501. return;
  1502. }
  1503. // add the new event
  1504. event->next = NULL;
  1505. event->prev = NULL;
  1506. if ( end ) {
  1507. end->next = event;
  1508. event->prev = end;
  1509. } else {
  1510. start = event;
  1511. }
  1512. end = event;
  1513. }