Game_network.cpp 54 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799
  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. #ifdef _D3XP
  497. // Add portalSky areas to PVS
  498. if ( portalSkyEnt.GetEntity() ) {
  499. pvsHandle_t otherPVS, newPVS;
  500. idEntity *skyEnt = portalSkyEnt.GetEntity();
  501. otherPVS = gameLocal.pvs.SetupCurrentPVS( skyEnt->GetPVSAreas(), skyEnt->GetNumPVSAreas() );
  502. newPVS = gameLocal.pvs.MergeCurrentPVS( pvsHandle, otherPVS );
  503. pvs.FreeCurrentPVS( pvsHandle );
  504. pvs.FreeCurrentPVS( otherPVS );
  505. pvsHandle = newPVS;
  506. }
  507. #endif
  508. #if ASYNC_WRITE_TAGS
  509. idRandom tagRandom;
  510. tagRandom.SetSeed( random.RandomInt() );
  511. msg.WriteLong( tagRandom.GetSeed() );
  512. #endif
  513. // create the snapshot
  514. for( ent = spawnedEntities.Next(); ent != NULL; ent = ent->spawnNode.Next() ) {
  515. // if the entity is not in the player PVS
  516. if ( !ent->PhysicsTeamInPVS( pvsHandle ) && ent->entityNumber != clientNum ) {
  517. continue;
  518. }
  519. // add the entity to the snapshot pvs
  520. snapshot->pvs[ ent->entityNumber >> 5 ] |= 1 << ( ent->entityNumber & 31 );
  521. // if that entity is not marked for network synchronization
  522. if ( !ent->fl.networkSync ) {
  523. continue;
  524. }
  525. // save the write state to which we can revert when the entity didn't change at all
  526. msg.SaveWriteState( msgSize, msgWriteBit );
  527. // write the entity to the snapshot
  528. msg.WriteBits( ent->entityNumber, GENTITYNUM_BITS );
  529. base = clientEntityStates[clientNum][ent->entityNumber];
  530. if ( base ) {
  531. base->state.BeginReading();
  532. }
  533. newBase = entityStateAllocator.Alloc();
  534. newBase->entityNumber = ent->entityNumber;
  535. newBase->state.Init( newBase->stateBuf, sizeof( newBase->stateBuf ) );
  536. newBase->state.BeginWriting();
  537. deltaMsg.Init( base ? &base->state : NULL, &newBase->state, &msg );
  538. deltaMsg.WriteBits( spawnIds[ ent->entityNumber ], 32 - GENTITYNUM_BITS );
  539. deltaMsg.WriteBits( ent->GetType()->typeNum, idClass::GetTypeNumBits() );
  540. deltaMsg.WriteBits( ServerRemapDecl( -1, DECL_ENTITYDEF, ent->entityDefNumber ), entityDefBits );
  541. // write the class specific data to the snapshot
  542. ent->WriteToSnapshot( deltaMsg );
  543. if ( !deltaMsg.HasChanged() ) {
  544. msg.RestoreWriteState( msgSize, msgWriteBit );
  545. entityStateAllocator.Free( newBase );
  546. } else {
  547. newBase->next = snapshot->firstEntityState;
  548. snapshot->firstEntityState = newBase;
  549. #if ASYNC_WRITE_TAGS
  550. msg.WriteLong( tagRandom.RandomInt() );
  551. #endif
  552. }
  553. }
  554. msg.WriteBits( ENTITYNUM_NONE, GENTITYNUM_BITS );
  555. // write the PVS to the snapshot
  556. #if ASYNC_WRITE_PVS
  557. for ( i = 0; i < idEntity::MAX_PVS_AREAS; i++ ) {
  558. if ( i < numSourceAreas ) {
  559. msg.WriteLong( sourceAreas[ i ] );
  560. } else {
  561. msg.WriteLong( 0 );
  562. }
  563. }
  564. gameLocal.pvs.WritePVS( pvsHandle, msg );
  565. #endif
  566. for ( i = 0; i < ENTITY_PVS_SIZE; i++ ) {
  567. msg.WriteDeltaLong( clientPVS[clientNum][i], snapshot->pvs[i] );
  568. }
  569. // free the PVS
  570. pvs.FreeCurrentPVS( pvsHandle );
  571. // write the game and player state to the snapshot
  572. base = clientEntityStates[clientNum][ENTITYNUM_NONE]; // ENTITYNUM_NONE is used for the game and player state
  573. if ( base ) {
  574. base->state.BeginReading();
  575. }
  576. newBase = entityStateAllocator.Alloc();
  577. newBase->entityNumber = ENTITYNUM_NONE;
  578. newBase->next = snapshot->firstEntityState;
  579. snapshot->firstEntityState = newBase;
  580. newBase->state.Init( newBase->stateBuf, sizeof( newBase->stateBuf ) );
  581. newBase->state.BeginWriting();
  582. deltaMsg.Init( base ? &base->state : NULL, &newBase->state, &msg );
  583. if ( player->spectating && player->spectator != player->entityNumber && gameLocal.entities[ player->spectator ] && gameLocal.entities[ player->spectator ]->IsType( idPlayer::Type ) ) {
  584. static_cast< idPlayer * >( gameLocal.entities[ player->spectator ] )->WritePlayerStateToSnapshot( deltaMsg );
  585. } else {
  586. player->WritePlayerStateToSnapshot( deltaMsg );
  587. }
  588. WriteGameStateToSnapshot( deltaMsg );
  589. // copy the client PVS string
  590. memcpy( clientInPVS, snapshot->pvs, ( numPVSClients + 7 ) >> 3 );
  591. LittleRevBytes( clientInPVS, sizeof( int ), sizeof( clientInPVS ) / sizeof ( int ) );
  592. }
  593. /*
  594. ================
  595. idGameLocal::ServerApplySnapshot
  596. ================
  597. */
  598. bool idGameLocal::ServerApplySnapshot( int clientNum, int sequence ) {
  599. return ApplySnapshot( clientNum, sequence );
  600. }
  601. /*
  602. ================
  603. idGameLocal::NetworkEventWarning
  604. ================
  605. */
  606. void idGameLocal::NetworkEventWarning( const entityNetEvent_t *event, const char *fmt, ... ) {
  607. char buf[1024];
  608. int length = 0;
  609. va_list argptr;
  610. int entityNum = event->spawnId & ( ( 1 << GENTITYNUM_BITS ) - 1 );
  611. int id = event->spawnId >> GENTITYNUM_BITS;
  612. length += idStr::snPrintf( buf+length, sizeof(buf)-1-length, "event %d for entity %d %d: ", event->event, entityNum, id );
  613. va_start( argptr, fmt );
  614. length = idStr::vsnPrintf( buf+length, sizeof(buf)-1-length, fmt, argptr );
  615. va_end( argptr );
  616. idStr::Append( buf, sizeof(buf), "\n" );
  617. common->DWarning( buf );
  618. }
  619. /*
  620. ================
  621. idGameLocal::ServerProcessEntityNetworkEventQueue
  622. ================
  623. */
  624. void idGameLocal::ServerProcessEntityNetworkEventQueue( void ) {
  625. idEntity *ent;
  626. entityNetEvent_t *event;
  627. idBitMsg eventMsg;
  628. while ( eventQueue.Start() ) {
  629. event = eventQueue.Start();
  630. if ( event->time > time ) {
  631. break;
  632. }
  633. idEntityPtr< idEntity > entPtr;
  634. if( !entPtr.SetSpawnId( event->spawnId ) ) {
  635. NetworkEventWarning( event, "Entity does not exist any longer, or has not been spawned yet." );
  636. } else {
  637. ent = entPtr.GetEntity();
  638. assert( ent );
  639. eventMsg.Init( event->paramsBuf, sizeof( event->paramsBuf ) );
  640. eventMsg.SetSize( event->paramsSize );
  641. eventMsg.BeginReading();
  642. if ( !ent->ServerReceiveEvent( event->event, event->time, eventMsg ) ) {
  643. NetworkEventWarning( event, "unknown event" );
  644. }
  645. }
  646. entityNetEvent_t* freedEvent = eventQueue.Dequeue();
  647. assert( freedEvent == event );
  648. eventQueue.Free( event );
  649. }
  650. }
  651. /*
  652. ================
  653. idGameLocal::ServerSendChatMessage
  654. ================
  655. */
  656. void idGameLocal::ServerSendChatMessage( int to, const char *name, const char *text ) {
  657. idBitMsg outMsg;
  658. byte msgBuf[ MAX_GAME_MESSAGE_SIZE ];
  659. outMsg.Init( msgBuf, sizeof( msgBuf ) );
  660. outMsg.BeginWriting();
  661. outMsg.WriteByte( GAME_RELIABLE_MESSAGE_CHAT );
  662. outMsg.WriteString( name );
  663. outMsg.WriteString( text, -1, false );
  664. networkSystem->ServerSendReliableMessage( to, outMsg );
  665. if ( to == -1 || to == localClientNum ) {
  666. mpGame.AddChatLine( "%s^0: %s\n", name, text );
  667. }
  668. }
  669. /*
  670. ================
  671. idGameLocal::ServerProcessReliableMessage
  672. ================
  673. */
  674. void idGameLocal::ServerProcessReliableMessage( int clientNum, const idBitMsg &msg ) {
  675. int id;
  676. id = msg.ReadByte();
  677. switch( id ) {
  678. case GAME_RELIABLE_MESSAGE_CHAT:
  679. case GAME_RELIABLE_MESSAGE_TCHAT: {
  680. char name[128];
  681. char text[128];
  682. msg.ReadString( name, sizeof( name ) );
  683. msg.ReadString( text, sizeof( text ) );
  684. mpGame.ProcessChatMessage( clientNum, id == GAME_RELIABLE_MESSAGE_TCHAT, name, text, NULL );
  685. break;
  686. }
  687. case GAME_RELIABLE_MESSAGE_VCHAT: {
  688. int index = msg.ReadLong();
  689. bool team = msg.ReadBits( 1 ) != 0;
  690. mpGame.ProcessVoiceChat( clientNum, team, index );
  691. break;
  692. }
  693. case GAME_RELIABLE_MESSAGE_KILL: {
  694. mpGame.WantKilled( clientNum );
  695. break;
  696. }
  697. case GAME_RELIABLE_MESSAGE_DROPWEAPON: {
  698. mpGame.DropWeapon( clientNum );
  699. break;
  700. }
  701. case GAME_RELIABLE_MESSAGE_CALLVOTE: {
  702. mpGame.ServerCallVote( clientNum, msg );
  703. break;
  704. }
  705. case GAME_RELIABLE_MESSAGE_CASTVOTE: {
  706. bool vote = ( msg.ReadByte() != 0 );
  707. mpGame.CastVote( clientNum, vote );
  708. break;
  709. }
  710. #if 0
  711. // uncomment this if you want to track when players are in a menu
  712. case GAME_RELIABLE_MESSAGE_MENU: {
  713. bool menuUp = ( msg.ReadBits( 1 ) != 0 );
  714. break;
  715. }
  716. #endif
  717. case GAME_RELIABLE_MESSAGE_EVENT: {
  718. entityNetEvent_t *event;
  719. // allocate new event
  720. event = eventQueue.Alloc();
  721. eventQueue.Enqueue( event, idEventQueue::OUTOFORDER_DROP );
  722. event->spawnId = msg.ReadBits( 32 );
  723. event->event = msg.ReadByte();
  724. event->time = msg.ReadLong();
  725. event->paramsSize = msg.ReadBits( idMath::BitsForInteger( MAX_EVENT_PARAM_SIZE ) );
  726. if ( event->paramsSize ) {
  727. if ( event->paramsSize > MAX_EVENT_PARAM_SIZE ) {
  728. NetworkEventWarning( event, "invalid param size" );
  729. return;
  730. }
  731. msg.ReadByteAlign();
  732. msg.ReadData( event->paramsBuf, event->paramsSize );
  733. }
  734. break;
  735. }
  736. default: {
  737. Warning( "Unknown client->server reliable message: %d", id );
  738. break;
  739. }
  740. }
  741. }
  742. /*
  743. ================
  744. idGameLocal::ClientShowSnapshot
  745. ================
  746. */
  747. void idGameLocal::ClientShowSnapshot( int clientNum ) const {
  748. int baseBits;
  749. idEntity *ent;
  750. idPlayer *player;
  751. idMat3 viewAxis;
  752. idBounds viewBounds;
  753. entityState_t *base;
  754. if ( !net_clientShowSnapshot.GetInteger() ) {
  755. return;
  756. }
  757. player = static_cast<idPlayer *>( entities[clientNum] );
  758. if ( !player ) {
  759. return;
  760. }
  761. viewAxis = player->viewAngles.ToMat3();
  762. viewBounds = player->GetPhysics()->GetAbsBounds().Expand( net_clientShowSnapshotRadius.GetFloat() );
  763. for( ent = snapshotEntities.Next(); ent != NULL; ent = ent->snapshotNode.Next() ) {
  764. if ( net_clientShowSnapshot.GetInteger() == 1 && ent->snapshotBits == 0 ) {
  765. continue;
  766. }
  767. const idBounds &entBounds = ent->GetPhysics()->GetAbsBounds();
  768. if ( !entBounds.IntersectsBounds( viewBounds ) ) {
  769. continue;
  770. }
  771. base = clientEntityStates[clientNum][ent->entityNumber];
  772. if ( base ) {
  773. baseBits = base->state.GetNumBitsWritten();
  774. } else {
  775. baseBits = 0;
  776. }
  777. if ( net_clientShowSnapshot.GetInteger() == 2 && baseBits == 0 ) {
  778. continue;
  779. }
  780. gameRenderWorld->DebugBounds( colorGreen, entBounds );
  781. gameRenderWorld->DrawText( va( "%d: %s (%d,%d bytes of %d,%d)\n", ent->entityNumber,
  782. ent->name.c_str(), ent->snapshotBits >> 3, ent->snapshotBits & 7, baseBits >> 3, baseBits & 7 ),
  783. entBounds.GetCenter(), 0.1f, colorWhite, viewAxis, 1 );
  784. }
  785. }
  786. /*
  787. ================
  788. idGameLocal::UpdateLagometer
  789. ================
  790. */
  791. void idGameLocal::UpdateLagometer( int aheadOfServer, int dupeUsercmds ) {
  792. int i, j, ahead;
  793. for ( i = 0; i < LAGO_HEIGHT; i++ ) {
  794. memmove( (byte *)lagometer + LAGO_WIDTH * 4 * i, (byte *)lagometer + LAGO_WIDTH * 4 * i + 4, ( LAGO_WIDTH - 1 ) * 4 );
  795. }
  796. j = LAGO_WIDTH - 1;
  797. for ( i = 0; i < LAGO_HEIGHT; i++ ) {
  798. lagometer[i][j][0] = lagometer[i][j][1] = lagometer[i][j][2] = lagometer[i][j][3] = 0;
  799. }
  800. ahead = idMath::Rint( (float)aheadOfServer / 16.0f );
  801. if ( ahead >= 0 ) {
  802. for ( i = 2 * Max( 0, 5 - ahead ); i < 2 * 5; i++ ) {
  803. lagometer[i][j][1] = 255;
  804. lagometer[i][j][3] = 255;
  805. }
  806. } else {
  807. for ( i = 2 * 5; i < 2 * ( 5 + Min( 10, -ahead ) ); i++ ) {
  808. lagometer[i][j][0] = 255;
  809. lagometer[i][j][1] = 255;
  810. lagometer[i][j][3] = 255;
  811. }
  812. }
  813. for ( i = LAGO_HEIGHT - 2 * Min( 6, dupeUsercmds ); i < LAGO_HEIGHT; i++ ) {
  814. lagometer[i][j][0] = 255;
  815. if ( dupeUsercmds <= 2 ) {
  816. lagometer[i][j][1] = 255;
  817. }
  818. lagometer[i][j][3] = 255;
  819. }
  820. }
  821. /*
  822. ================
  823. idGameLocal::ClientReadSnapshot
  824. ================
  825. */
  826. void idGameLocal::ClientReadSnapshot( int clientNum, int sequence, const int gameFrame, const int gameTime, const int dupeUsercmds, const int aheadOfServer, const idBitMsg &msg ) {
  827. int i, typeNum, entityDefNumber, numBitsRead;
  828. idTypeInfo *typeInfo;
  829. idEntity *ent;
  830. idPlayer *player, *spectated;
  831. pvsHandle_t pvsHandle;
  832. idDict args;
  833. const char *classname;
  834. idBitMsgDelta deltaMsg;
  835. snapshot_t *snapshot;
  836. entityState_t *base, *newBase;
  837. int spawnId;
  838. int numSourceAreas, sourceAreas[ idEntity::MAX_PVS_AREAS ];
  839. idWeapon *weap;
  840. if ( net_clientLagOMeter.GetBool() && renderSystem ) {
  841. UpdateLagometer( aheadOfServer, dupeUsercmds );
  842. if ( !renderSystem->UploadImage( LAGO_IMAGE, (byte *)lagometer, LAGO_IMG_WIDTH, LAGO_IMG_HEIGHT ) ) {
  843. common->Printf( "lagometer: UploadImage failed. turning off net_clientLagOMeter\n" );
  844. net_clientLagOMeter.SetBool( false );
  845. }
  846. }
  847. InitLocalClient( clientNum );
  848. // clear any debug lines from a previous frame
  849. gameRenderWorld->DebugClearLines( time );
  850. // clear any debug polygons from a previous frame
  851. gameRenderWorld->DebugClearPolygons( time );
  852. // update the game time
  853. framenum = gameFrame;
  854. time = gameTime;
  855. previousTime = time - msec;
  856. // so that StartSound/StopSound doesn't risk skipping
  857. isNewFrame = true;
  858. // clear the snapshot entity list
  859. snapshotEntities.Clear();
  860. // allocate new snapshot
  861. snapshot = snapshotAllocator.Alloc();
  862. snapshot->sequence = sequence;
  863. snapshot->firstEntityState = NULL;
  864. snapshot->next = clientSnapshots[clientNum];
  865. clientSnapshots[clientNum] = snapshot;
  866. #if ASYNC_WRITE_TAGS
  867. idRandom tagRandom;
  868. tagRandom.SetSeed( msg.ReadLong() );
  869. #endif
  870. // read all entities from the snapshot
  871. for ( i = msg.ReadBits( GENTITYNUM_BITS ); i != ENTITYNUM_NONE; i = msg.ReadBits( GENTITYNUM_BITS ) ) {
  872. base = clientEntityStates[clientNum][i];
  873. if ( base ) {
  874. base->state.BeginReading();
  875. }
  876. newBase = entityStateAllocator.Alloc();
  877. newBase->entityNumber = i;
  878. newBase->next = snapshot->firstEntityState;
  879. snapshot->firstEntityState = newBase;
  880. newBase->state.Init( newBase->stateBuf, sizeof( newBase->stateBuf ) );
  881. newBase->state.BeginWriting();
  882. numBitsRead = msg.GetNumBitsRead();
  883. deltaMsg.Init( base ? &base->state : NULL, &newBase->state, &msg );
  884. spawnId = deltaMsg.ReadBits( 32 - GENTITYNUM_BITS );
  885. typeNum = deltaMsg.ReadBits( idClass::GetTypeNumBits() );
  886. entityDefNumber = ClientRemapDecl( DECL_ENTITYDEF, deltaMsg.ReadBits( entityDefBits ) );
  887. typeInfo = idClass::GetType( typeNum );
  888. if ( !typeInfo ) {
  889. Error( "Unknown type number %d for entity %d with class number %d", typeNum, i, entityDefNumber );
  890. }
  891. ent = entities[i];
  892. // if there is no entity or an entity of the wrong type
  893. if ( !ent || ent->GetType()->typeNum != typeNum || ent->entityDefNumber != entityDefNumber || spawnId != spawnIds[ i ] ) {
  894. if ( i < MAX_CLIENTS && ent ) {
  895. // SPAWN_PLAYER should be taking care of spawning the entity with the right spawnId
  896. common->Warning( "ClientReadSnapshot: recycling client entity %d\n", i );
  897. }
  898. delete ent;
  899. spawnCount = spawnId;
  900. args.Clear();
  901. args.SetInt( "spawn_entnum", i );
  902. args.Set( "name", va( "entity%d", i ) );
  903. if ( entityDefNumber >= 0 ) {
  904. if ( entityDefNumber >= declManager->GetNumDecls( DECL_ENTITYDEF ) ) {
  905. Error( "server has %d entityDefs instead of %d", entityDefNumber, declManager->GetNumDecls( DECL_ENTITYDEF ) );
  906. }
  907. classname = declManager->DeclByIndex( DECL_ENTITYDEF, entityDefNumber, false )->GetName();
  908. args.Set( "classname", classname );
  909. if ( !SpawnEntityDef( args, &ent ) || !entities[i] || entities[i]->GetType()->typeNum != typeNum ) {
  910. Error( "Failed to spawn entity with classname '%s' of type '%s'", classname, typeInfo->classname );
  911. }
  912. } else {
  913. ent = SpawnEntityType( *typeInfo, &args, true );
  914. if ( !entities[i] || entities[i]->GetType()->typeNum != typeNum ) {
  915. Error( "Failed to spawn entity of type '%s'", typeInfo->classname );
  916. }
  917. }
  918. if ( i < MAX_CLIENTS && i >= numClients ) {
  919. numClients = i + 1;
  920. }
  921. }
  922. // add the entity to the snapshot list
  923. ent->snapshotNode.AddToEnd( snapshotEntities );
  924. ent->snapshotSequence = sequence;
  925. // read the class specific data from the snapshot
  926. ent->ReadFromSnapshot( deltaMsg );
  927. ent->snapshotBits = msg.GetNumBitsRead() - numBitsRead;
  928. #if ASYNC_WRITE_TAGS
  929. if ( msg.ReadLong() != tagRandom.RandomInt() ) {
  930. cmdSystem->BufferCommandText( CMD_EXEC_NOW, "writeGameState" );
  931. if ( entityDefNumber >= 0 && entityDefNumber < declManager->GetNumDecls( DECL_ENTITYDEF ) ) {
  932. classname = declManager->DeclByIndex( DECL_ENTITYDEF, entityDefNumber, false )->GetName();
  933. Error( "write to and read from snapshot out of sync for classname '%s' of type '%s'", classname, typeInfo->classname );
  934. } else {
  935. Error( "write to and read from snapshot out of sync for type '%s'", typeInfo->classname );
  936. }
  937. }
  938. #endif
  939. }
  940. player = static_cast<idPlayer *>( entities[clientNum] );
  941. if ( !player ) {
  942. return;
  943. }
  944. // if prediction is off, enable local client smoothing
  945. player->SetSelfSmooth( dupeUsercmds > 2 );
  946. if ( player->spectating && player->spectator != clientNum && entities[ player->spectator ] ) {
  947. spectated = static_cast< idPlayer * >( entities[ player->spectator ] );
  948. } else {
  949. spectated = player;
  950. }
  951. // get PVS for this player
  952. // don't use PVSAreas for networking - PVSAreas depends on animations (and md5 bounds), which are not synchronized
  953. numSourceAreas = gameRenderWorld->BoundsInAreas( spectated->GetPlayerPhysics()->GetAbsBounds(), sourceAreas, idEntity::MAX_PVS_AREAS );
  954. pvsHandle = gameLocal.pvs.SetupCurrentPVS( sourceAreas, numSourceAreas, PVS_NORMAL );
  955. #ifdef _D3XP
  956. // Add portalSky areas to PVS
  957. if ( portalSkyEnt.GetEntity() ) {
  958. pvsHandle_t otherPVS, newPVS;
  959. idEntity *skyEnt = portalSkyEnt.GetEntity();
  960. otherPVS = gameLocal.pvs.SetupCurrentPVS( skyEnt->GetPVSAreas(), skyEnt->GetNumPVSAreas() );
  961. newPVS = gameLocal.pvs.MergeCurrentPVS( pvsHandle, otherPVS );
  962. pvs.FreeCurrentPVS( pvsHandle );
  963. pvs.FreeCurrentPVS( otherPVS );
  964. pvsHandle = newPVS;
  965. }
  966. #endif
  967. // read the PVS from the snapshot
  968. #if ASYNC_WRITE_PVS
  969. int serverPVS[idEntity::MAX_PVS_AREAS];
  970. i = numSourceAreas;
  971. while ( i < idEntity::MAX_PVS_AREAS ) {
  972. sourceAreas[ i++ ] = 0;
  973. }
  974. for ( i = 0; i < idEntity::MAX_PVS_AREAS; i++ ) {
  975. serverPVS[ i ] = msg.ReadLong();
  976. }
  977. if ( memcmp( sourceAreas, serverPVS, idEntity::MAX_PVS_AREAS * sizeof( int ) ) ) {
  978. common->Warning( "client PVS areas != server PVS areas, sequence 0x%x", sequence );
  979. for ( i = 0; i < idEntity::MAX_PVS_AREAS; i++ ) {
  980. common->DPrintf( "%3d ", sourceAreas[ i ] );
  981. }
  982. common->DPrintf( "\n" );
  983. for ( i = 0; i < idEntity::MAX_PVS_AREAS; i++ ) {
  984. common->DPrintf( "%3d ", serverPVS[ i ] );
  985. }
  986. common->DPrintf( "\n" );
  987. }
  988. gameLocal.pvs.ReadPVS( pvsHandle, msg );
  989. #endif
  990. for ( i = 0; i < ENTITY_PVS_SIZE; i++ ) {
  991. snapshot->pvs[i] = msg.ReadDeltaLong( clientPVS[clientNum][i] );
  992. }
  993. // add entities in the PVS that haven't changed since the last applied snapshot
  994. for( ent = spawnedEntities.Next(); ent != NULL; ent = ent->spawnNode.Next() ) {
  995. // if the entity is already in the snapshot
  996. if ( ent->snapshotSequence == sequence ) {
  997. continue;
  998. }
  999. // if the entity is not in the snapshot PVS
  1000. if ( !( snapshot->pvs[ent->entityNumber >> 5] & ( 1 << ( ent->entityNumber & 31 ) ) ) ) {
  1001. if ( ent->PhysicsTeamInPVS( pvsHandle ) ) {
  1002. if ( ent->entityNumber >= MAX_CLIENTS && ent->entityNumber < mapSpawnCount && !ent->spawnArgs.GetBool("net_dynamic", "0")) { //_D3XP
  1003. // server says it's not in PVS, client says it's in PVS
  1004. // if that happens on map entities, most likely something is wrong
  1005. // I can see that moving pieces along several PVS could be a legit situation though
  1006. // this is a band aid, which means something is not done right elsewhere
  1007. common->DWarning( "client thinks map entity 0x%x (%s) is stale, sequence 0x%x", ent->entityNumber, ent->name.c_str(), sequence );
  1008. } else {
  1009. ent->FreeModelDef();
  1010. #ifdef CTF
  1011. // possible fix for left over lights on CTF flag
  1012. ent->FreeLightDef();
  1013. #endif
  1014. ent->UpdateVisuals();
  1015. ent->GetPhysics()->UnlinkClip();
  1016. }
  1017. }
  1018. continue;
  1019. }
  1020. // add the entity to the snapshot list
  1021. ent->snapshotNode.AddToEnd( snapshotEntities );
  1022. ent->snapshotSequence = sequence;
  1023. ent->snapshotBits = 0;
  1024. base = clientEntityStates[clientNum][ent->entityNumber];
  1025. if ( !base ) {
  1026. // entity has probably fl.networkSync set to false
  1027. continue;
  1028. }
  1029. base->state.BeginReading();
  1030. deltaMsg.Init( &base->state, NULL, (const idBitMsg *)NULL );
  1031. spawnId = deltaMsg.ReadBits( 32 - GENTITYNUM_BITS );
  1032. typeNum = deltaMsg.ReadBits( idClass::GetTypeNumBits() );
  1033. entityDefNumber = deltaMsg.ReadBits( entityDefBits );
  1034. typeInfo = idClass::GetType( typeNum );
  1035. // if the entity is not the right type
  1036. if ( !typeInfo || ent->GetType()->typeNum != typeNum || ent->entityDefNumber != entityDefNumber ) {
  1037. // should never happen - it does though. with != entityDefNumber only?
  1038. 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 );
  1039. continue;
  1040. }
  1041. // read the class specific data from the base state
  1042. ent->ReadFromSnapshot( deltaMsg );
  1043. }
  1044. // free the PVS
  1045. pvs.FreeCurrentPVS( pvsHandle );
  1046. // read the game and player state from the snapshot
  1047. base = clientEntityStates[clientNum][ENTITYNUM_NONE]; // ENTITYNUM_NONE is used for the game and player state
  1048. if ( base ) {
  1049. base->state.BeginReading();
  1050. }
  1051. newBase = entityStateAllocator.Alloc();
  1052. newBase->entityNumber = ENTITYNUM_NONE;
  1053. newBase->next = snapshot->firstEntityState;
  1054. snapshot->firstEntityState = newBase;
  1055. newBase->state.Init( newBase->stateBuf, sizeof( newBase->stateBuf ) );
  1056. newBase->state.BeginWriting();
  1057. deltaMsg.Init( base ? &base->state : NULL, &newBase->state, &msg );
  1058. if ( player->spectating && player->spectator != player->entityNumber && gameLocal.entities[ player->spectator ] && gameLocal.entities[ player->spectator ]->IsType( idPlayer::Type ) ) {
  1059. static_cast< idPlayer * >( gameLocal.entities[ player->spectator ] )->ReadPlayerStateFromSnapshot( deltaMsg );
  1060. weap = static_cast< idPlayer * >( gameLocal.entities[ player->spectator ] )->weapon.GetEntity();
  1061. if ( weap && ( weap->GetRenderEntity()->bounds[0] == weap->GetRenderEntity()->bounds[1] ) ) {
  1062. // update the weapon's viewmodel bounds so that the model doesn't flicker in the spectator's view
  1063. weap->GetAnimator()->GetBounds( gameLocal.time, weap->GetRenderEntity()->bounds );
  1064. weap->UpdateVisuals();
  1065. }
  1066. } else {
  1067. player->ReadPlayerStateFromSnapshot( deltaMsg );
  1068. }
  1069. ReadGameStateFromSnapshot( deltaMsg );
  1070. // visualize the snapshot
  1071. ClientShowSnapshot( clientNum );
  1072. // process entity events
  1073. ClientProcessEntityNetworkEventQueue();
  1074. }
  1075. /*
  1076. ================
  1077. idGameLocal::ClientApplySnapshot
  1078. ================
  1079. */
  1080. bool idGameLocal::ClientApplySnapshot( int clientNum, int sequence ) {
  1081. return ApplySnapshot( clientNum, sequence );
  1082. }
  1083. /*
  1084. ================
  1085. idGameLocal::ClientProcessEntityNetworkEventQueue
  1086. ================
  1087. */
  1088. void idGameLocal::ClientProcessEntityNetworkEventQueue( void ) {
  1089. idEntity *ent;
  1090. entityNetEvent_t *event;
  1091. idBitMsg eventMsg;
  1092. while( eventQueue.Start() ) {
  1093. event = eventQueue.Start();
  1094. // only process forward, in order
  1095. if ( event->time > time ) {
  1096. break;
  1097. }
  1098. idEntityPtr< idEntity > entPtr;
  1099. if( !entPtr.SetSpawnId( event->spawnId ) ) {
  1100. if( !gameLocal.entities[ event->spawnId & ( ( 1 << GENTITYNUM_BITS ) - 1 ) ] ) {
  1101. // if new entity exists in this position, silently ignore
  1102. NetworkEventWarning( event, "Entity does not exist any longer, or has not been spawned yet." );
  1103. }
  1104. } else {
  1105. ent = entPtr.GetEntity();
  1106. assert( ent );
  1107. eventMsg.Init( event->paramsBuf, sizeof( event->paramsBuf ) );
  1108. eventMsg.SetSize( event->paramsSize );
  1109. eventMsg.BeginReading();
  1110. if ( !ent->ClientReceiveEvent( event->event, event->time, eventMsg ) ) {
  1111. NetworkEventWarning( event, "unknown event" );
  1112. }
  1113. }
  1114. entityNetEvent_t* freedEvent = eventQueue.Dequeue();
  1115. assert( freedEvent == event );
  1116. eventQueue.Free( event );
  1117. }
  1118. }
  1119. /*
  1120. ================
  1121. idGameLocal::ClientProcessReliableMessage
  1122. ================
  1123. */
  1124. void idGameLocal::ClientProcessReliableMessage( int clientNum, const idBitMsg &msg ) {
  1125. int id, line;
  1126. idPlayer *p;
  1127. idDict backupSI;
  1128. InitLocalClient( clientNum );
  1129. id = msg.ReadByte();
  1130. switch( id ) {
  1131. case GAME_RELIABLE_MESSAGE_INIT_DECL_REMAP: {
  1132. InitClientDeclRemap( clientNum );
  1133. break;
  1134. }
  1135. case GAME_RELIABLE_MESSAGE_REMAP_DECL: {
  1136. int type, index;
  1137. char name[MAX_STRING_CHARS];
  1138. type = msg.ReadByte();
  1139. index = msg.ReadLong();
  1140. msg.ReadString( name, sizeof( name ) );
  1141. const idDecl *decl = declManager->FindType( (declType_t)type, name, false );
  1142. if ( decl != NULL ) {
  1143. if ( index >= clientDeclRemap[clientNum][type].Num() ) {
  1144. clientDeclRemap[clientNum][type].AssureSize( index + 1, -1 );
  1145. }
  1146. clientDeclRemap[clientNum][type][index] = decl->Index();
  1147. }
  1148. break;
  1149. }
  1150. case GAME_RELIABLE_MESSAGE_SPAWN_PLAYER: {
  1151. int client = msg.ReadByte();
  1152. int spawnId = msg.ReadLong();
  1153. if ( !entities[ client ] ) {
  1154. SpawnPlayer( client );
  1155. entities[ client ]->FreeModelDef();
  1156. }
  1157. // fix up the spawnId to match what the server says
  1158. // otherwise there is going to be a bogus delete/new of the client entity in the first ClientReadFromSnapshot
  1159. spawnIds[ client ] = spawnId;
  1160. break;
  1161. }
  1162. case GAME_RELIABLE_MESSAGE_DELETE_ENT: {
  1163. int spawnId = msg.ReadBits( 32 );
  1164. idEntityPtr< idEntity > entPtr;
  1165. if( !entPtr.SetSpawnId( spawnId ) ) {
  1166. break;
  1167. }
  1168. delete entPtr.GetEntity();
  1169. break;
  1170. }
  1171. case GAME_RELIABLE_MESSAGE_CHAT:
  1172. case GAME_RELIABLE_MESSAGE_TCHAT: { // (client should never get a TCHAT though)
  1173. char name[128];
  1174. char text[128];
  1175. msg.ReadString( name, sizeof( name ) );
  1176. msg.ReadString( text, sizeof( text ) );
  1177. mpGame.AddChatLine( "%s^0: %s\n", name, text );
  1178. break;
  1179. }
  1180. case GAME_RELIABLE_MESSAGE_SOUND_EVENT: {
  1181. snd_evt_t snd_evt = (snd_evt_t)msg.ReadByte();
  1182. mpGame.PlayGlobalSound( -1, snd_evt );
  1183. break;
  1184. }
  1185. case GAME_RELIABLE_MESSAGE_SOUND_INDEX: {
  1186. int index = gameLocal.ClientRemapDecl( DECL_SOUND, msg.ReadLong() );
  1187. if ( index >= 0 && index < declManager->GetNumDecls( DECL_SOUND ) ) {
  1188. const idSoundShader *shader = declManager->SoundByIndex( index );
  1189. mpGame.PlayGlobalSound( -1, SND_COUNT, shader->GetName() );
  1190. }
  1191. break;
  1192. }
  1193. case GAME_RELIABLE_MESSAGE_DB: {
  1194. idMultiplayerGame::msg_evt_t msg_evt = (idMultiplayerGame::msg_evt_t)msg.ReadByte();
  1195. int parm1, parm2;
  1196. parm1 = msg.ReadByte( );
  1197. parm2 = msg.ReadByte( );
  1198. mpGame.PrintMessageEvent( -1, msg_evt, parm1, parm2 );
  1199. break;
  1200. }
  1201. case GAME_RELIABLE_MESSAGE_EVENT: {
  1202. entityNetEvent_t *event;
  1203. // allocate new event
  1204. event = eventQueue.Alloc();
  1205. eventQueue.Enqueue( event, idEventQueue::OUTOFORDER_IGNORE );
  1206. event->spawnId = msg.ReadBits( 32 );
  1207. event->event = msg.ReadByte();
  1208. event->time = msg.ReadLong();
  1209. event->paramsSize = msg.ReadBits( idMath::BitsForInteger( MAX_EVENT_PARAM_SIZE ) );
  1210. if ( event->paramsSize ) {
  1211. if ( event->paramsSize > MAX_EVENT_PARAM_SIZE ) {
  1212. NetworkEventWarning( event, "invalid param size" );
  1213. return;
  1214. }
  1215. msg.ReadByteAlign();
  1216. msg.ReadData( event->paramsBuf, event->paramsSize );
  1217. }
  1218. break;
  1219. }
  1220. case GAME_RELIABLE_MESSAGE_SERVERINFO: {
  1221. idDict info;
  1222. msg.ReadDeltaDict( info, NULL );
  1223. gameLocal.SetServerInfo( info );
  1224. break;
  1225. }
  1226. case GAME_RELIABLE_MESSAGE_RESTART: {
  1227. #ifdef _D3XP
  1228. int newServerInfo = msg.ReadBits(1);
  1229. if(newServerInfo) {
  1230. idDict info;
  1231. msg.ReadDeltaDict( info, NULL );
  1232. gameLocal.SetServerInfo( info );
  1233. }
  1234. #endif
  1235. MapRestart();
  1236. break;
  1237. }
  1238. case GAME_RELIABLE_MESSAGE_TOURNEYLINE: {
  1239. line = msg.ReadByte( );
  1240. p = static_cast< idPlayer * >( entities[ clientNum ] );
  1241. if ( !p ) {
  1242. break;
  1243. }
  1244. p->tourneyLine = line;
  1245. break;
  1246. }
  1247. case GAME_RELIABLE_MESSAGE_STARTVOTE: {
  1248. char voteString[ MAX_STRING_CHARS ];
  1249. int clientNum = msg.ReadByte( );
  1250. msg.ReadString( voteString, sizeof( voteString ) );
  1251. mpGame.ClientStartVote( clientNum, voteString );
  1252. break;
  1253. }
  1254. case GAME_RELIABLE_MESSAGE_UPDATEVOTE: {
  1255. int result = msg.ReadByte( );
  1256. int yesCount = msg.ReadByte( );
  1257. int noCount = msg.ReadByte( );
  1258. mpGame.ClientUpdateVote( (idMultiplayerGame::vote_result_t)result, yesCount, noCount );
  1259. break;
  1260. }
  1261. case GAME_RELIABLE_MESSAGE_PORTALSTATES: {
  1262. int numPortals = msg.ReadLong();
  1263. assert( numPortals == gameRenderWorld->NumPortals() );
  1264. for ( int i = 0; i < numPortals; i++ ) {
  1265. gameRenderWorld->SetPortalState( (qhandle_t) (i+1), msg.ReadBits( NUM_RENDER_PORTAL_BITS ) );
  1266. }
  1267. break;
  1268. }
  1269. case GAME_RELIABLE_MESSAGE_PORTAL: {
  1270. qhandle_t portal = msg.ReadLong();
  1271. int blockingBits = msg.ReadBits( NUM_RENDER_PORTAL_BITS );
  1272. assert( portal > 0 && portal <= gameRenderWorld->NumPortals() );
  1273. gameRenderWorld->SetPortalState( portal, blockingBits );
  1274. break;
  1275. }
  1276. case GAME_RELIABLE_MESSAGE_STARTSTATE: {
  1277. mpGame.ClientReadStartState( msg );
  1278. break;
  1279. }
  1280. case GAME_RELIABLE_MESSAGE_WARMUPTIME: {
  1281. mpGame.ClientReadWarmupTime( msg );
  1282. break;
  1283. }
  1284. default: {
  1285. Error( "Unknown server->client reliable message: %d", id );
  1286. break;
  1287. }
  1288. }
  1289. }
  1290. /*
  1291. ================
  1292. idGameLocal::ClientPrediction
  1293. ================
  1294. */
  1295. gameReturn_t idGameLocal::ClientPrediction( int clientNum, const usercmd_t *clientCmds, bool lastPredictFrame ) {
  1296. idEntity *ent;
  1297. idPlayer *player;
  1298. gameReturn_t ret;
  1299. ret.sessionCommand[ 0 ] = '\0';
  1300. player = static_cast<idPlayer *>( entities[clientNum] );
  1301. if ( !player ) {
  1302. return ret;
  1303. }
  1304. // check for local client lag
  1305. if ( networkSystem->ClientGetTimeSinceLastPacket() >= net_clientMaxPrediction.GetInteger() ) {
  1306. player->isLagged = true;
  1307. } else {
  1308. player->isLagged = false;
  1309. }
  1310. InitLocalClient( clientNum );
  1311. // update the game time
  1312. framenum++;
  1313. previousTime = time;
  1314. time += msec;
  1315. // update the real client time and the new frame flag
  1316. if ( time > realClientTime ) {
  1317. realClientTime = time;
  1318. isNewFrame = true;
  1319. } else {
  1320. isNewFrame = false;
  1321. }
  1322. #ifdef _D3XP
  1323. slow.Set( time, previousTime, msec, framenum, realClientTime );
  1324. fast.Set( time, previousTime, msec, framenum, realClientTime );
  1325. #endif
  1326. // set the user commands for this frame
  1327. memcpy( usercmds, clientCmds, numClients * sizeof( usercmds[ 0 ] ) );
  1328. // run prediction on all entities from the last snapshot
  1329. for( ent = snapshotEntities.Next(); ent != NULL; ent = ent->snapshotNode.Next() ) {
  1330. ent->thinkFlags |= TH_PHYSICS;
  1331. ent->ClientPredictionThink();
  1332. }
  1333. // service any pending events
  1334. idEvent::ServiceEvents();
  1335. // show any debug info for this frame
  1336. if ( isNewFrame ) {
  1337. RunDebugInfo();
  1338. D_DrawDebugLines();
  1339. }
  1340. if ( sessionCommand.Length() ) {
  1341. strncpy( ret.sessionCommand, sessionCommand, sizeof( ret.sessionCommand ) );
  1342. }
  1343. return ret;
  1344. }
  1345. /*
  1346. ===============
  1347. idGameLocal::Tokenize
  1348. ===============
  1349. */
  1350. void idGameLocal::Tokenize( idStrList &out, const char *in ) {
  1351. char buf[ MAX_STRING_CHARS ];
  1352. char *token, *next;
  1353. idStr::Copynz( buf, in, MAX_STRING_CHARS );
  1354. token = buf;
  1355. next = strchr( token, ';' );
  1356. while ( token ) {
  1357. if ( next ) {
  1358. *next = '\0';
  1359. }
  1360. idStr::ToLower( token );
  1361. out.Append( token );
  1362. if ( next ) {
  1363. token = next + 1;
  1364. next = strchr( token, ';' );
  1365. } else {
  1366. token = NULL;
  1367. }
  1368. }
  1369. }
  1370. /*
  1371. ===============
  1372. idGameLocal::DownloadRequest
  1373. ===============
  1374. */
  1375. bool idGameLocal::DownloadRequest( const char *IP, const char *guid, const char *paks, char urls[ MAX_STRING_CHARS ] ) {
  1376. if ( !cvarSystem->GetCVarInteger( "net_serverDownload" ) ) {
  1377. return false;
  1378. }
  1379. if ( cvarSystem->GetCVarInteger( "net_serverDownload" ) == 1 ) {
  1380. // 1: single URL redirect
  1381. if ( !strlen( cvarSystem->GetCVarString( "si_serverURL" ) ) ) {
  1382. common->Warning( "si_serverURL not set" );
  1383. return false;
  1384. }
  1385. idStr::snPrintf( urls, MAX_STRING_CHARS, "1;%s", cvarSystem->GetCVarString( "si_serverURL" ) );
  1386. return true;
  1387. } else {
  1388. // 2: table of pak URLs
  1389. // first token is the game pak if request, empty if not requested by the client
  1390. // there may be empty tokens for paks the server couldn't pinpoint - the order matters
  1391. idStr reply = "2;";
  1392. idStrList dlTable, pakList;
  1393. int i, j;
  1394. Tokenize( dlTable, cvarSystem->GetCVarString( "net_serverDlTable" ) );
  1395. Tokenize( pakList, paks );
  1396. for ( i = 0; i < pakList.Num(); i++ ) {
  1397. if ( i > 0 ) {
  1398. reply += ";";
  1399. }
  1400. if ( pakList[ i ][ 0 ] == '\0' ) {
  1401. if ( i == 0 ) {
  1402. // pak 0 will always miss when client doesn't ask for game bin
  1403. common->DPrintf( "no game pak request\n" );
  1404. } else {
  1405. common->DPrintf( "no pak %d\n", i );
  1406. }
  1407. continue;
  1408. }
  1409. for ( j = 0; j < dlTable.Num(); j++ ) {
  1410. if ( !fileSystem->FilenameCompare( pakList[ i ], dlTable[ j ] ) ) {
  1411. break;
  1412. }
  1413. }
  1414. if ( j == dlTable.Num() ) {
  1415. common->Printf( "download for %s: pak not matched: %s\n", IP, pakList[ i ].c_str() );
  1416. } else {
  1417. idStr url = cvarSystem->GetCVarString( "net_serverDlBaseURL" );
  1418. url.AppendPath( dlTable[ j ] );
  1419. reply += url;
  1420. common->DPrintf( "download for %s: %s\n", IP, url.c_str() );
  1421. }
  1422. }
  1423. idStr::Copynz( urls, reply, MAX_STRING_CHARS );
  1424. return true;
  1425. }
  1426. return false;
  1427. }
  1428. /*
  1429. ===============
  1430. idEventQueue::Alloc
  1431. ===============
  1432. */
  1433. entityNetEvent_t* idEventQueue::Alloc() {
  1434. entityNetEvent_t* event = eventAllocator.Alloc();
  1435. event->prev = NULL;
  1436. event->next = NULL;
  1437. return event;
  1438. }
  1439. /*
  1440. ===============
  1441. idEventQueue::Free
  1442. ===============
  1443. */
  1444. void idEventQueue::Free( entityNetEvent_t *event ) {
  1445. // should only be called on an unlinked event!
  1446. assert( !event->next && !event->prev );
  1447. eventAllocator.Free( event );
  1448. }
  1449. /*
  1450. ===============
  1451. idEventQueue::Shutdown
  1452. ===============
  1453. */
  1454. void idEventQueue::Shutdown() {
  1455. eventAllocator.Shutdown();
  1456. this->Init();
  1457. }
  1458. /*
  1459. ===============
  1460. idEventQueue::Init
  1461. ===============
  1462. */
  1463. void idEventQueue::Init( void ) {
  1464. start = NULL;
  1465. end = NULL;
  1466. }
  1467. /*
  1468. ===============
  1469. idEventQueue::Dequeue
  1470. ===============
  1471. */
  1472. entityNetEvent_t* idEventQueue::Dequeue( void ) {
  1473. entityNetEvent_t* event = start;
  1474. if ( !event ) {
  1475. return NULL;
  1476. }
  1477. start = start->next;
  1478. if ( !start ) {
  1479. end = NULL;
  1480. } else {
  1481. start->prev = NULL;
  1482. }
  1483. event->next = NULL;
  1484. event->prev = NULL;
  1485. return event;
  1486. }
  1487. /*
  1488. ===============
  1489. idEventQueue::RemoveLast
  1490. ===============
  1491. */
  1492. entityNetEvent_t* idEventQueue::RemoveLast( void ) {
  1493. entityNetEvent_t *event = end;
  1494. if ( !event ) {
  1495. return NULL;
  1496. }
  1497. end = event->prev;
  1498. if ( !end ) {
  1499. start = NULL;
  1500. } else {
  1501. end->next = NULL;
  1502. }
  1503. event->next = NULL;
  1504. event->prev = NULL;
  1505. return event;
  1506. }
  1507. /*
  1508. ===============
  1509. idEventQueue::Enqueue
  1510. ===============
  1511. */
  1512. void idEventQueue::Enqueue( entityNetEvent_t *event, outOfOrderBehaviour_t behaviour ) {
  1513. if ( behaviour == OUTOFORDER_DROP ) {
  1514. // go backwards through the queue and determine if there are
  1515. // any out-of-order events
  1516. while ( end && end->time > event->time ) {
  1517. entityNetEvent_t *outOfOrder = RemoveLast();
  1518. 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 );
  1519. Free( outOfOrder );
  1520. }
  1521. } else if ( behaviour == OUTOFORDER_SORT && end ) {
  1522. // NOT TESTED -- sorting out of order packets hasn't been
  1523. // tested yet... wasn't strictly necessary for
  1524. // the patch fix.
  1525. entityNetEvent_t *cur = end;
  1526. // iterate until we find a time < the new event's
  1527. while ( cur && cur->time > event->time ) {
  1528. cur = cur->prev;
  1529. }
  1530. if ( !cur ) {
  1531. // add to start
  1532. event->next = start;
  1533. event->prev = NULL;
  1534. start = event;
  1535. } else {
  1536. // insert
  1537. event->prev = cur;
  1538. event->next = cur->next;
  1539. cur->next = event;
  1540. }
  1541. return;
  1542. }
  1543. // add the new event
  1544. event->next = NULL;
  1545. event->prev = NULL;
  1546. if ( end ) {
  1547. end->next = event;
  1548. event->prev = end;
  1549. } else {
  1550. start = event;
  1551. }
  1552. end = event;
  1553. }