bool DataTable_ParseClassInfosFromBuffer( CClientState *pState, bf_read *pBuf ) { if(pState->m_pServerClasses) { delete [] pState->m_pServerClasses; } pState->m_nServerClasses = pBuf->ReadShort(); Assert( pState->m_nServerClasses ); pState->m_pServerClasses = new C_ServerClassInfo[pState->m_nServerClasses]; if ( !pState->m_pServerClasses ) { Host_EndGame(true, "CL_ParseClassInfo: can't allocate %d C_ServerClassInfos.\n", pState->m_nServerClasses); return false; } for ( int i = 0; i < pState->m_nServerClasses; i++ ) { int classID = pBuf->ReadShort(); if( classID >= pState->m_nServerClasses ) { Host_EndGame(true, "DataTable_ParseClassInfosFromBuffer: invalid class index (%d).\n", classID); return false; } pState->m_pServerClasses[classID].m_ClassName = pBuf->ReadAndAllocateString(); pState->m_pServerClasses[classID].m_DatatableName = pBuf->ReadAndAllocateString(); } return true; }
void VID_Restart(void) { int i; if (!display) return; VID_Close(); VID_Open(); for(i=1;i < MAX_MODELS;i++) { if (cl.model_name[i][0] == 0) break; cl.model_precache[i] = Mod_ForName(cl.model_name[i], false); if (!cl.model_precache[i]) { Com_Printf("Unable to reload model '%s'.\n", cl.model_name[i]); Host_EndGame(); return; } } if (cl.model_precache[1]) { cl.worldmodel = cl.model_precache[1]; R_NewMap(); R_DrawFlat_NewMap(); } CL_ClearTEnts(); /* Not the prettiest, but the safest for now... */ vid_restarted = 1; }
/* ================= FlushEntityPacket ================= */ void FlushEntityPacket (void) { int word; entity_state_t olde, newe; Con_DPrintf ("FlushEntityPacket\n"); memset (&olde, 0, sizeof(olde)); cl.validsequence = 0; // can't render a frame cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].invalid = true; // read it all, but ignore it while (1) { word = (unsigned short)MSG_ReadShort (); if (msg_badread) { // something didn't parse right... Host_EndGame ("msg_badread in packetentities"); return; } if (!word) break; // done CL_ParseDelta (&olde, &newe, word); } }
bool CHLTVClientState::ProcessClassInfo( SVC_ClassInfo *msg ) { if ( !msg->m_bCreateOnClient ) { ConMsg("HLTV SendTable CRC differs from server.\n"); Disconnect(); return false; } #ifdef _HLTVTEST RecvTable_Term( false ); #endif // Create all of the send tables locally DataTable_CreateClientTablesFromServerTables(); // Now create all of the server classes locally, too DataTable_CreateClientClassInfosFromServerClasses( this ); LinkClasses(); // link server and client classes if ( !RecvTable_CreateDecoders( serverGameDLL->GetStandardSendProxies() ) ) // create receive table decoders { Host_EndGame( true, "CL_ParseClassInfo_EndClasses: CreateDecoders failed.\n" ); return false; } return true; }
void CClientState::ConnectionCrashed( const char * reason ) { // if connected, shut down host if ( m_nSignonState > SIGNONSTATE_NONE ) { COM_ExplainDisconnection( true, "Disconnect: %s.\n", reason ); SCR_EndLoadingPlaque(); Host_EndGame ( true, reason ); } }
/* ================ CL_Connect_f MAUTH version -- kick off an authentication sequence as first part of connection routine. ================ */ void CL_Connect_f (void) { char *server; char *masterserver; char data[2048]; if (Cmd_Argc() != 3) { Com_Printf ("usage: connect <master> <server>\n"); return; } Host_EndGame (); server = Cmd_Argv (1); strlcpy (cls.servername, server, sizeof(cls.servername)); // Have to check for valid server address here as we must send to master... if (!NET_StringToAdr (cls.servername, &cls.server_adr)) { Com_Printf ("Bad server address\n"); return; } if (cls.server_adr.port == 0) cls.server_adr.port = BigShort (PORT_SERVER); masterserver = Cmd_Argv (2); strlcpy (cls.masterservername, masterserver, sizeof(cls.masterservername)); // Start off auth sequence before trying to connect... if (!NET_StringToAdr (cls.masterservername, &cls.masterserver_adr)) { Com_Printf ("Bad master server address\n"); return; } if (cls.masterserver_adr.port == 0) cls.masterserver_adr.port = BigShort (27000); // master port Com_Printf ("Attempting to auth with %s...\n", cls.masterservername); sprintf (data, "%c\n%s\n%s:%d\n", C2M_AUTH_INIT, Cvar_String("name"), cls.servername, cls.server_adr.port); NET_SendPacket (NS_CLIENT, strlen(data), data, cls.masterserver_adr); // Normal connection procedure... // FIXME wait? // FIXME use some qbools to work out if we get a NACK to stop trying to connect -- ie preserve state CL_BeginServerConnect(); }
/* =============== SV_ClearWorld =============== */ void SV_ClearWorld (void) { // Clean up static props from the previous level StaticPropMgr()->LevelShutdown(); for ( int i = 0; i < 3; i++ ) { if ( host_state.worldmodel->mins[i] < MIN_COORD_INTEGER || host_state.worldmodel->maxs[i] > MAX_COORD_INTEGER ) { Host_EndGame("Map coordinate extents are too large!!\nCheck for errors!\n" ); } } SpatialPartition()->Init( host_state.worldmodel->mins, host_state.worldmodel->maxs ); // Load all static props into the spatial partition StaticPropMgr()->LevelInit(); }
void CL_NQConnect_f (void) { char *server; if (Cmd_Argc() != 2) { Com_Printf ("usage: nqconnect <server>\n"); return; } server = Cmd_Argv (1); Host_EndGame (); cls.nqprotocol = true; strlcpy (cls.servername, server, sizeof(cls.servername)); CL_BeginServerConnect(); }
void DataTable_CreateClientClassInfosFromServerClasses( CBaseClientState *pState ) { if ( !serverGameDLL ) { Sys_Error( "DataTable_CreateClientClassInfosFromServerClasses: No serverGameDLL loaded!" ); } ServerClass *pClasses = serverGameDLL->GetAllServerClasses(); // Count the number of classes. int nClasses = 0; for ( ServerClass *pCount=pClasses; pCount; pCount=pCount->m_pNext ) { ++nClasses; } // Remove old if ( pState->m_pServerClasses ) { delete [] pState->m_pServerClasses; } Assert( nClasses > 0 ); pState->m_nServerClasses = nClasses; pState->m_pServerClasses = new C_ServerClassInfo[ pState->m_nServerClasses ]; if ( !pState->m_pServerClasses ) { Host_EndGame(true, "CL_ParseClassInfo: can't allocate %d C_ServerClassInfos.\n", pState->m_nServerClasses); return; } // Now fill in the entries int curID = 0; for ( ServerClass *pClass=pClasses; pClass; pClass=pClass->m_pNext ) { Assert( pClass->m_ClassID >= 0 && pClass->m_ClassID < nClasses ); pClass->m_ClassID = curID++; pState->m_pServerClasses[ pClass->m_ClassID ].m_ClassName = COM_StringCopy( pClass->m_pNetworkName ); pState->m_pServerClasses[ pClass->m_ClassID ].m_DatatableName = COM_StringCopy( pClass->m_pTable->GetName() ); } }
bool CClientState::ProcessClassInfo( SVC_ClassInfo *msg ) { if ( msg->m_bCreateOnClient ) { #ifndef _XBOX if ( !demoplayer->IsPlayingBack() ) #endif { // Create all of the send tables locally DataTable_CreateClientTablesFromServerTables(); // Now create all of the server classes locally, too DataTable_CreateClientClassInfosFromServerClasses( this ); // store the current data tables in demo file to make sure // they are the same during playback #ifndef _XBOX demorecorder->RecordServerClasses( serverGameDLL->GetAllServerClasses() ); #endif } LinkClasses(); // link server and client classes } else { CBaseClientState::ProcessClassInfo( msg ); } if ( !RecvTable_CreateDecoders( serverGameDLL->GetStandardSendProxies() ) ) // create receive table decoders { Host_EndGame( true, "CL_ParseClassInfo_EndClasses: CreateDecoders failed.\n" ); return false; } #ifndef _XBOX if ( !demoplayer->IsPlayingBack() ) #endif { CLocalNetworkBackdoor::InitFastCopy(); } return true; }
void SV_LoadGame_f (void) { char name[MAX_OSPATH], mapname[MAX_QPATH], str[32 * 1024], *start; FILE *f; float time, tfloat, spawn_parms[NUM_SPAWN_PARMS]; edict_t *ent; int entnum, version, r; unsigned int i; if (Cmd_Argc() != 2) { Com_Printf ("Usage: %s <savename> : load a game\n", Cmd_Argv(0)); return; } snprintf (name, sizeof (name), "%s/save/%s", com_gamedir, Cmd_Argv(1)); COM_DefaultExtension (name, ".sav"); Com_Printf ("Loading game from %s...\n", name); if (!(f = fopen (name, "rb"))) { Com_Printf ("ERROR: couldn't open.\n"); return; } fscanf (f, "%i\n", &version); if (version != SAVEGAME_VERSION) { fclose (f); Com_Printf ("Savegame is version %i, not %i\n", version, SAVEGAME_VERSION); return; } fscanf (f, "%s\n", str); for (i = 0; i < NUM_SPAWN_PARMS; i++) fscanf (f, "%f\n", &spawn_parms[i]); // this silliness is so we can load 1.06 save files, which have float skill values fscanf (f, "%f\n", &tfloat); current_skill = (int)(tfloat + 0.1); Cvar_Set (&skill, va("%i", current_skill)); Cvar_SetValue (&deathmatch, 0); Cvar_SetValue (&coop, 0); Cvar_SetValue (&teamplay, 0); Cvar_SetValue (&maxclients, 1); fscanf (f, "%s\n", mapname); fscanf (f, "%f\n", &time); Host_EndGame(); CL_BeginLocalConnection (); SV_SpawnServer (mapname, false); if (sv.state != ss_active) { Com_Printf ("Couldn't load map\n"); return; } Cvar_ForceSet (&sv_paused, "1"); // pause until all clients connect sv.loadgame = true; // load the light styles for (i = 0; i < MAX_LIGHTSTYLES; i++) { fscanf (f, "%s\n", str); sv.lightstyles[i] = (char *) Hunk_Alloc (strlen(str) + 1); strlcpy (sv.lightstyles[i], str, strlen(str) + 1); } // load the edicts out of the savegame file entnum = -1; // -1 is the globals while (!feof(f)) { for (i = 0; i < sizeof(str) - 1; i++) { r = fgetc (f); if (r == EOF || !r) break; str[i] = r; if (r == '}') { i++; break; } } if (i == sizeof(str)-1) Host_Error ("Loadgame buffer overflow"); str[i] = 0; start = str; start = COM_Parse(str); if (!com_token[0]) break; // end of file if (strcmp(com_token,"{")) Host_Error ("First token isn't a brace"); if (entnum == -1) { // parse the global vars ED_ParseGlobals (start); } else { // parse an edict ent = EDICT_NUM(entnum); memset (&ent->v, 0, progs->entityfields * 4); ent->free = false; ED_ParseEdict (start, ent); // link it into the bsp tree if (!ent->free) SV_LinkEdict (ent, false); } entnum++; } sv.num_edicts = entnum; sv.time = time; fclose (f); for (i = 0; i < NUM_SPAWN_PARMS; i++) svs.clients->spawn_parms[i] = spawn_parms[i]; }
/* ===================== CL_ParseServerMessage ===================== */ void CL_ParseServerMessage(void) { unsigned int bits; int i, cmd, prevcmd; int playernum, version, stylenum, signon, statnum; int stopsound, entitynum, channel; byte colors; player_info_t *player; lightstyle_t *style; const char *stylemap, *name; // // if recording demos, copy the message out // if (cl_shownet.value == 1) Con_Printf("%i ", net_message.cursize); else if (cl_shownet.value == 2) Con_Printf("------------------\n"); cl.onground = false; // unless the server says otherwise // // parse the message // prevcmd = svc_bad; MSG_BeginReading(); while (1) { if (msg_badread) Host_Error("%s: Bad server message", __func__); cmd = MSG_ReadByte(); if (cmd == -1) { SHOWNET("END OF MESSAGE"); return; // end of message } // if the high bit of the command byte is set, it is a fast update if (cmd & 128) { SHOWNET("fast update"); CL_ParseUpdate(cmd & 127); continue; } SHOWNET(svc_strings[cmd]); // other commands switch (cmd) { case svc_nop: break; case svc_time: cl.mtime[1] = cl.mtime[0]; cl.mtime[0] = MSG_ReadFloat(); break; case svc_clientdata: CL_ParseClientdata(); break; case svc_version: version = MSG_ReadLong(); if (!Protocol_Known(version)) Host_Error("%s: Server returned unknown protocol version %i", __func__, version); cl.protocol = version; break; case svc_disconnect: Host_EndGame("Server disconnected\n"); case svc_print: Con_Printf("%s", MSG_ReadString()); break; case svc_centerprint: SCR_CenterPrint(MSG_ReadString()); break; case svc_stufftext: Cbuf_AddText("%s", MSG_ReadString()); break; case svc_damage: V_ParseDamage(); break; case svc_serverinfo: CL_ParseServerInfo(); vid.recalc_refdef = true; // leave intermission full screen break; case svc_setangle: for (i = 0; i < 3; i++) cl.viewangles[i] = MSG_ReadAngle(); break; case svc_setview: cl.viewentity = MSG_ReadShort(); break; case svc_lightstyle: stylenum = MSG_ReadByte(); if (stylenum >= MAX_LIGHTSTYLES) Sys_Error("svc_lightstyle > MAX_LIGHTSTYLES"); stylemap = MSG_ReadString(); style = cl_lightstyle + stylenum; snprintf(style->map, MAX_STYLESTRING, "%s", stylemap); style->length = strlen(style->map); break; case svc_sound: CL_ParseStartSoundPacket(); break; case svc_stopsound: stopsound = MSG_ReadShort(); /* 3-bit channel encoded in lsb */ entitynum = stopsound >> 3; channel = stopsound & 7; S_StopSound(entitynum, channel); break; case svc_updatename: Sbar_Changed(); playernum = MSG_ReadByte(); if (playernum >= cl.maxclients) Host_Error("%s: svc_updatename > MAX_SCOREBOARD", __func__); name = MSG_ReadString(); player = cl.players + playernum; snprintf(player->name, MAX_SCOREBOARDNAME, "%s", name); break; case svc_updatefrags: Sbar_Changed(); playernum = MSG_ReadByte(); if (playernum >= cl.maxclients) Host_Error("%s: svc_updatefrags > MAX_SCOREBOARD", __func__); player = cl.players + playernum; player->frags = MSG_ReadShort(); break; case svc_updatecolors: Sbar_Changed(); playernum = MSG_ReadByte(); if (playernum >= cl.maxclients) Host_Error("%s: svc_updatecolors > MAX_SCOREBOARD", __func__); colors = MSG_ReadByte(); player = cl.players + playernum; player->topcolor = (colors & 0xf0) >> 4; player->bottomcolor = colors & 0x0f; /* FIXME - is this the right check for current player? */ if (playernum == cl.viewentity) cl_color.value = colors; CL_NewTranslation(playernum); break; case svc_particle: R_ParseParticleEffect(); break; case svc_spawnbaseline: entitynum = MSG_ReadShort(); // must use CL_EntityNum() to force cl.num_entities up CL_ParseBaseline(CL_EntityNum(entitynum), 0); break; case svc_fitz_spawnbaseline2: /* FIXME - check here that protocol is FITZ? => Host_Error() */ entitynum = MSG_ReadShort(); bits = MSG_ReadByte(); // must use CL_EntityNum() to force cl.num_entities up CL_ParseBaseline(CL_EntityNum(entitynum), bits); break; case svc_spawnstatic: CL_ParseStatic(0); break; case svc_fitz_spawnstatic2: /* FIXME - check here that protocol is FITZ? => Host_Error() */ bits = MSG_ReadByte(); CL_ParseStatic(bits); break; case svc_temp_entity: CL_ParseTEnt(); break; case svc_setpause: cl.paused = MSG_ReadByte(); if (cl.paused) CDAudio_Pause(); else CDAudio_Resume(); break; case svc_signonnum: signon = MSG_ReadByte(); if (signon <= cls.signon) Host_Error("Received signon %d when at %d", signon, cls.signon); cls.signon = signon; CL_SignonReply(); break; case svc_killedmonster: cl.stats[STAT_MONSTERS]++; break; case svc_foundsecret: cl.stats[STAT_SECRETS]++; break; case svc_updatestat: statnum = MSG_ReadByte(); if (statnum < 0 || statnum >= MAX_CL_STATS) Sys_Error("svc_updatestat: %d is invalid", statnum); cl.stats[statnum] = MSG_ReadLong(); break; case svc_spawnstaticsound: CL_ParseStaticSound(); break; case svc_fitz_spawnstaticsound2: /* FIXME - check here that protocol is FITZ? => Host_Error() */ CL_ParseFitzStaticSound2(); break; case svc_cdtrack: cl.cdtrack = MSG_ReadByte(); cl.looptrack = MSG_ReadByte(); if ((cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1)) CDAudio_Play((byte)cls.forcetrack, true); else CDAudio_Play((byte)cl.cdtrack, true); break; case svc_intermission: cl.intermission = 1; cl.completed_time = cl.time; vid.recalc_refdef = true; // go to full screen break; case svc_finale: cl.intermission = 2; cl.completed_time = cl.time; vid.recalc_refdef = true; // go to full screen SCR_CenterPrint(MSG_ReadString()); break; case svc_cutscene: cl.intermission = 3; cl.completed_time = cl.time; vid.recalc_refdef = true; // go to full screen SCR_CenterPrint(MSG_ReadString()); break; case svc_sellscreen: Cmd_ExecuteString("help", src_command); break; /* Various FITZ protocol messages - FIXME - !protocol => Host_Error */ case svc_fitz_skybox: MSG_ReadString(); // FIXME - TODO break; case svc_fitz_bf: Cmd_ExecuteString("bf", src_command); break; case svc_fitz_fog: /* FIXME - TODO */ MSG_ReadByte(); // density MSG_ReadByte(); // red MSG_ReadByte(); // green MSG_ReadByte(); // blue MSG_ReadShort(); // time break; default: Host_Error("%s: Illegible server message. Previous was %s", __func__, svc_strings[prevcmd]); } prevcmd = cmd; } }
/* ============== SV_KillGame_f ============== */ void SV_KillGame_f( void ) { Host_EndGame( "The End" ); }
/* ============== SV_EndGame_f ============== */ void SV_EndGame_f( void ) { Host_EndGame( Cmd_Argv( 1 )); }
void CL_ParseServerMessage (void) { int cmd; int i; // // if recording demos, copy the message out // if (cl_shownet.value == 1) Con_Printf ("%i ",net_message.cursize); else if (cl_shownet.value == 2) Con_Printf ("------------------\n"); cl.onground = false; // unless the server says otherwise // // parse the message // MSG_BeginReading (); while (1) { if (msg_badread) Host_Error ("CL_ParseServerMessage: Bad server message"); cmd = MSG_ReadByte (); if (cmd == -1) { SHOWNET("END OF MESSAGE"); return; // end of message } // if the high bit of the command byte is set, it is a fast update if (cmd & 128) { SHOWNET("fast update"); CL_ParseUpdate (cmd&127); continue; } SHOWNET(svc_strings[cmd]); // other commands switch (cmd) { default: Host_Error ("CL_ParseServerMessage: Illegible server message\n"); break; case svc_nop: // Con_Printf ("svc_nop\n"); break; case svc_time: cl.mtime[1] = cl.mtime[0]; cl.mtime[0] = MSG_ReadFloat (); break; case svc_clientdata: i = MSG_ReadShort (); CL_ParseClientdata (i); break; case svc_version: i = MSG_ReadLong (); if (i != PROTOCOL_VERSION) Host_Error ("CL_ParseServerMessage: Server is protocol %i instead of %i\n", i, PROTOCOL_VERSION); break; case svc_disconnect: Host_EndGame ("Server disconnected\n"); case svc_print: Con_Printf ("%s", MSG_ReadString ()); break; case svc_centerprint: SCR_CenterPrint (MSG_ReadString ()); break; case svc_stufftext: Cbuf_AddText (MSG_ReadString ()); break; case svc_damage: V_ParseDamage (); break; case svc_serverinfo: CL_ParseServerInfo (); vid.recalc_refdef = true; // leave intermission full screen break; case svc_setangle: for (i=0 ; i<3 ; i++) cl.viewangles[i] = MSG_ReadAngle (); break; case svc_setview: cl.viewentity = MSG_ReadShort (); break; case svc_lightstyle: i = MSG_ReadByte (); if (i >= MAX_LIGHTSTYLES) Sys_Error ("svc_lightstyle > MAX_LIGHTSTYLES"); Q_strcpy (cl_lightstyle[i].map, MSG_ReadString()); cl_lightstyle[i].length = Q_strlen(cl_lightstyle[i].map); break; case svc_sound: CL_ParseStartSoundPacket(); break; case svc_stopsound: i = MSG_ReadShort(); S_StopSound(i>>3, i&7); break; case svc_updatename: Sbar_Changed (); i = MSG_ReadByte (); if (i >= cl.maxclients) Host_Error ("CL_ParseServerMessage: svc_updatename > MAX_SCOREBOARD"); strcpy (cl.scores[i].name, MSG_ReadString ()); break; case svc_updatefrags: Sbar_Changed (); i = MSG_ReadByte (); if (i >= cl.maxclients) Host_Error ("CL_ParseServerMessage: svc_updatefrags > MAX_SCOREBOARD"); cl.scores[i].frags = MSG_ReadShort (); break; case svc_updatecolors: Sbar_Changed (); i = MSG_ReadByte (); if (i >= cl.maxclients) Host_Error ("CL_ParseServerMessage: svc_updatecolors > MAX_SCOREBOARD"); cl.scores[i].colors = MSG_ReadByte (); CL_NewTranslation (i); break; case svc_particle: R_ParseParticleEffect (); break; case svc_spawnbaseline: i = MSG_ReadShort (); // must use CL_EntityNum() to force cl.num_entities up CL_ParseBaseline (CL_EntityNum(i)); break; case svc_spawnstatic: CL_ParseStatic (); break; case svc_temp_entity: CL_ParseTEnt (); break; case svc_setpause: { cl.paused = MSG_ReadByte (); if (cl.paused) { CDAudio_Pause (); #ifdef _WIN32 VID_HandlePause (true); #endif } else { CDAudio_Resume (); #ifdef _WIN32 VID_HandlePause (false); #endif } } break; case svc_signonnum: i = MSG_ReadByte (); if (i <= cls.signon) Host_Error ("Received signon %i when at %i", i, cls.signon); cls.signon = i; CL_SignonReply (); break; case svc_killedmonster: cl.stats[STAT_MONSTERS]++; break; case svc_foundsecret: cl.stats[STAT_SECRETS]++; break; case svc_updatestat: i = MSG_ReadByte (); if (i < 0 || i >= MAX_CL_STATS) Sys_Error ("svc_updatestat: %i is invalid", i); cl.stats[i] = MSG_ReadLong ();; break; case svc_spawnstaticsound: CL_ParseStaticSound (); break; case svc_cdtrack: cl.cdtrack = MSG_ReadByte (); cl.looptrack = MSG_ReadByte (); if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) ) CDAudio_Play ((byte)cls.forcetrack, true); else CDAudio_Play ((byte)cl.cdtrack, true); break; case svc_intermission: cl.intermission = 1; cl.completed_time = (int) cl.time; vid.recalc_refdef = true; // go to full screen break; case svc_finale: cl.intermission = 2; cl.completed_time = (int) cl.time; vid.recalc_refdef = true; // go to full screen SCR_CenterPrint (MSG_ReadString ()); break; case svc_cutscene: cl.intermission = 3; cl.completed_time = (int) cl.time; vid.recalc_refdef = true; // go to full screen SCR_CenterPrint (MSG_ReadString ()); break; case svc_sellscreen: Cmd_ExecuteString2 ("help", src_command); break; } } }
/* ================== CL_ParsePacketEntities An svc_packetentities has just been parsed, deal with the rest of the data stream. ================== */ void CL_ParsePacketEntities (qboolean delta) { int oldpacket, newpacket; packet_entities_t *oldp, *newp, dummy; int oldindex, newindex; int word, newnum, oldnum; qboolean full; byte from; newpacket = cls.netchan.incoming_sequence&UPDATE_MASK; newp = &cl.frames[newpacket].packet_entities; cl.frames[newpacket].invalid = false; if (delta) { from = MSG_ReadByte (); oldpacket = cl.frames[newpacket].delta_sequence; if ( (from&UPDATE_MASK) != (oldpacket&UPDATE_MASK) ) Con_DPrintf ("WARNING: from mismatch\n"); } else oldpacket = -1; full = false; if (oldpacket != -1) { if (cls.netchan.outgoing_sequence - oldpacket >= UPDATE_BACKUP-1) { // we can't use this, it is too old FlushEntityPacket (); return; } cl.validsequence = cls.netchan.incoming_sequence; oldp = &cl.frames[oldpacket&UPDATE_MASK].packet_entities; } else { // this is a full update that we can start delta compressing from now oldp = &dummy; dummy.num_entities = 0; cl.validsequence = cls.netchan.incoming_sequence; full = true; } oldindex = 0; newindex = 0; newp->num_entities = 0; while (1) { word = (unsigned short)MSG_ReadShort (); if (msg_badread) { // something didn't parse right... Host_EndGame ("msg_badread in packetentities"); return; } if (!word) { while (oldindex < oldp->num_entities) { // copy all the rest of the entities from the old packet //Con_Printf ("copy %i\n", oldp->entities[oldindex].number); if (newindex >= MAX_PACKET_ENTITIES) Host_EndGame ("CL_ParsePacketEntities: newindex == MAX_PACKET_ENTITIES ... 1"); newp->entities[newindex] = oldp->entities[oldindex]; newindex++; oldindex++; } break; } newnum = word&511; oldnum = oldindex >= oldp->num_entities ? 9999 : oldp->entities[oldindex].number; while (newnum > oldnum) { if (full) { Con_Printf ("WARNING: oldcopy on full update"); FlushEntityPacket (); return; } //Con_Printf ("copy %i\n", oldnum); // copy one of the old entities over to the new packet unchanged if (newindex >= MAX_PACKET_ENTITIES) Host_EndGame ("CL_ParsePacketEntities: newindex == MAX_PACKET_ENTITIES ... 2"); newp->entities[newindex] = oldp->entities[oldindex]; newindex++; oldindex++; oldnum = oldindex >= oldp->num_entities ? 9999 : oldp->entities[oldindex].number; } if (newnum < oldnum) { // new from baseline //Con_Printf ("baseline %i\n", newnum); if (word & U_REMOVE) { if (full) { cl.validsequence = 0; Con_Printf ("WARNING: U_REMOVE on full update\n"); FlushEntityPacket (); return; } continue; } if (newindex >= MAX_PACKET_ENTITIES) Host_EndGame ("CL_ParsePacketEntities: newindex == MAX_PACKET_ENTITIES ... 3"); CL_ParseDelta (&cl_baselines[newnum], &newp->entities[newindex], word); newindex++; continue; } if (newnum == oldnum) { // delta from previous if (full) { cl.validsequence = 0; Con_Printf ("WARNING: delta on full update"); } if (word & U_REMOVE) { oldindex++; continue; } //Con_Printf ("delta %i\n",newnum); CL_ParseDelta (&oldp->entities[oldindex], &newp->entities[newindex], word); newindex++; oldindex++; } } newp->num_entities = newindex; }
void SV_Endgame_f( void ) { Host_EndGame( "The End" ); }
/* ===================== CL_ParseServerMessage ===================== */ void CL_ParseServerMessage (void) { int cmd; int i, j, k; int EntityCount = 0; int EntitySize = 0; int before; static double lasttime; static qboolean packet_loss = false; entity_t *ent; short RemovePlace, OrigPlace, NewPlace, AddedIndex; int sc1, sc2; byte test; float compangles[2][3]; vec3_t deltaangles; // // if recording demos, copy the message out // if (net_message.cursize > LastServerMessageSize) { LastServerMessageSize = net_message.cursize; } if (cl_shownet.integer == 1) { Con_Printf ("Time: %2.2f Pck: %i ", realtime - lasttime, net_message.cursize); lasttime = realtime; } else if (cl_shownet.integer == 2) Con_Printf ("------------------\n"); cl.onground = false; // unless the server says otherwise // // parse the message // MSG_BeginReading (); while (1) { if (msg_badread) Host_Error ("%s: Bad server message", __thisfunc__); cmd = MSG_ReadByte (); if (cmd == -1) { if (cl_shownet.integer == 1) Con_Printf ("Ent: %i (%i bytes)",EntityCount,EntitySize); SHOWNET("END OF MESSAGE"); return; // end of message } // if the high bit of the command byte is set, it is a fast update if (cmd & 128) { before = msg_readcount; SHOWNET("fast update"); if (packet_loss) CL_ParseUpdate2 (cmd&127); else CL_ParseUpdate (cmd&127); EntityCount++; EntitySize += msg_readcount - before + 1; continue; } if (cmd < NUM_SVC_STRINGS) // else, it'll hit the illegible message below { SHOWNET(svc_strings[cmd]); } // other commands switch (cmd) { default: // CL_DumpPacket (); Host_Error ("%s: Illegible server message %d", __thisfunc__, cmd); break; case svc_nop: // Con_Printf ("svc_nop\n"); break; case svc_time: cl.mtime[1] = cl.mtime[0]; cl.mtime[0] = MSG_ReadFloat (); break; case svc_clientdata: i = MSG_ReadShort (); CL_ParseClientdata (i); break; case svc_version: cl_protocol = MSG_ReadLong (); switch (cl_protocol) { case PROTOCOL_RAVEN_111: case PROTOCOL_RAVEN_112: case PROTOCOL_UQE_113: Con_Printf ("Server using protocol %i\n", cl_protocol); break; default: Host_Error ("%s: Server is protocol %i instead of %i or %i", __thisfunc__, cl_protocol, PROTOCOL_RAVEN_112, PROTOCOL_UQE_113); } break; case svc_disconnect: Host_EndGame ("Server disconnected\n"); break; case svc_print: if (intro_playing) MSG_ReadString (); else Con_Printf ("%s", MSG_ReadString ()); break; case svc_centerprint: SCR_CenterPrint (MSG_ReadString ()); break; case svc_stufftext: stufftext_frame = host_framecount; // allow full frame update // on stuff messages. Pa3PyX Cbuf_AddText (MSG_ReadString ()); break; case svc_damage: V_ParseDamage (); break; case svc_serverinfo: CL_ParseServerInfo (); vid.recalc_refdef = true; // leave intermission full screen break; case svc_setangle: for (i = 0; i < 3; i++) cl.viewangles[i] = MSG_ReadAngle (); break; case svc_setangle_interpolate: compangles[0][0] = MSG_ReadAngle(); compangles[0][1] = MSG_ReadAngle(); compangles[0][2] = MSG_ReadAngle(); for (i = 0; i < 3; i++) { compangles[1][i] = cl.viewangles[i]; for (j = 0; j < 2; j++) {//standardize both old and new angles to +-180 if (compangles[j][i] >= 360) compangles[j][i] -= 360*((int)(compangles[j][i]/360)); else if (compangles[j][i] <= 360) compangles[j][i] += 360*(1+(int)(-compangles[j][i]/360)); if (compangles[j][i] > 180) compangles[j][i] = -360 + compangles[j][i]; else if (compangles[j][i] < -180) compangles[j][i] = 360 + compangles[j][i]; } //get delta deltaangles[i] = compangles[0][i] - compangles[1][i]; //cap delta to <=180,>=-180 if (deltaangles[i] > 180) deltaangles[i] += -360; else if (deltaangles[i] < -180) deltaangles[i] += 360; //add the delta cl.viewangles[i]+=(deltaangles[i]/8);//8 step interpolation //cap newangles to +-180 if (cl.viewangles[i] >= 360) cl.viewangles[i] -= 360*((int)(cl.viewangles[i]/360)); else if (cl.viewangles[i] <= 360) cl.viewangles[i] += 360*(1+(int)(-cl.viewangles[i]/360)); if (cl.viewangles[i] > 180) cl.viewangles[i] += -360; else if (cl.viewangles[i] < -180) cl.viewangles[i] += 360; } break; case svc_setview: cl.viewentity = MSG_ReadShort (); break; case svc_lightstyle: i = MSG_ReadByte (); if (i >= MAX_LIGHTSTYLES) Sys_Error ("svc_lightstyle > MAX_LIGHTSTYLES"); q_strlcpy (cl_lightstyle[i].map, MSG_ReadString(), MAX_STYLESTRING); cl_lightstyle[i].length = strlen(cl_lightstyle[i].map); break; case svc_sound: CL_ParseStartSoundPacket(); break; case svc_sound_update_pos: {//FIXME: put a field on the entity that lists the channels //it should update when it moves- if a certain flag //is on the ent, this update_channels field could //be set automatically by each sound and stopSound //called for this ent? vec3_t pos; int channel, ent_num; channel = MSG_ReadShort (); ent_num = channel >> 3; channel &= 7; if (ent_num > MAX_EDICTS) Host_Error ("svc_sound_update_pos: ent = %i", ent_num); for (i = 0; i < 3; i++) pos[i] = MSG_ReadCoord (); S_UpdateSoundPos (ent_num, channel, pos); } break; case svc_stopsound: i = MSG_ReadShort(); S_StopSound(i>>3, i&7); break; case svc_updatename: Sbar_Changed(); i = MSG_ReadByte (); if (i >= cl.maxclients) Host_Error ("%s: svc_updatename > MAX_CLIENTS", __thisfunc__); q_strlcpy (cl.scores[i].name, MSG_ReadString(), MAX_SCOREBOARDNAME); break; case svc_updateclass: Sbar_Changed(); i = MSG_ReadByte (); if (i >= cl.maxclients) Host_Error ("%s: svc_updateclass > MAX_CLIENTS", __thisfunc__); cl.scores[i].playerclass = (float)MSG_ReadByte(); CL_NewTranslation(i); // update the color break; case svc_updatefrags: Sbar_Changed(); i = MSG_ReadByte (); if (i >= cl.maxclients) Host_Error ("%s: svc_updatefrags > MAX_CLIENTS", __thisfunc__); cl.scores[i].frags = MSG_ReadShort (); break; case svc_update_kingofhill: sv_kingofhill = MSG_ReadShort() - 1; break; case svc_updatecolors: Sbar_Changed(); i = MSG_ReadByte (); if (i >= cl.maxclients) Host_Error ("%s: svc_updatecolors > MAX_CLIENTS", __thisfunc__); cl.scores[i].colors = MSG_ReadByte (); CL_NewTranslation (i); break; case svc_particle: R_ParseParticleEffect (); break; case svc_particle2: R_ParseParticleEffect2 (); break; case svc_particle3: R_ParseParticleEffect3 (); break; case svc_particle4: R_ParseParticleEffect4 (); break; case svc_spawnbaseline: i = MSG_ReadShort (); // must use CL_EntityNum() to force cl.num_entities up CL_ParseBaseline (CL_EntityNum(i)); break; case svc_spawnstatic: CL_ParseStatic (); break; case svc_raineffect: CL_ParseRainEffect(); break; case svc_temp_entity: CL_ParseTEnt (); break; case svc_setpause: cl.paused = MSG_ReadByte (); if (cl.paused) { CDAudio_Pause (); VID_HandlePause (true); } else { CDAudio_Resume (); VID_HandlePause (false); } break; case svc_signonnum: i = MSG_ReadByte (); if (i <= cls.signon) Host_Error ("Received signon %i when at %i", i, cls.signon); cls.signon = i; CL_SignonReply (); break; case svc_killedmonster: cl.stats[STAT_MONSTERS]++; break; case svc_foundsecret: cl.stats[STAT_SECRETS]++; break; case svc_updatestat: i = MSG_ReadByte (); if (i < 0 || i >= MAX_CL_STATS) Sys_Error ("svc_updatestat: %i is invalid", i); cl.stats[i] = MSG_ReadLong (); break; case svc_spawnstaticsound: CL_ParseStaticSound (); break; case svc_cdtrack: cl.cdtrack = MSG_ReadByte (); cl.looptrack = MSG_ReadByte (); if (q_strcasecmp(bgmtype.string,"cd") == 0) { if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) ) CDAudio_Play ((byte)cls.forcetrack, true); else CDAudio_Play ((byte)cl.cdtrack, true); } else CDAudio_Stop(); break; case svc_midi_name: q_strlcpy (cl.midi_name, MSG_ReadString(), sizeof(cl.midi_name)); if (q_strcasecmp(bgmtype.string,"midi") == 0) MIDI_Play(cl.midi_name); else MIDI_Stop(); break; case svc_toggle_statbar: break; case svc_intermission: cl.intermission = MSG_ReadByte(); if (oem.integer && cl.intermission == 1) cl.intermission = 9; // skip intermissions while recording demos in single // player games, but stop recording at ending scenes. // skip intermissions when playing demos. if (cls.demorecording) { // 5: finale for the demo version // 6, 7, 8: eidolon end-1 to end-3 // 9: finale for the bundle version // 10: praevus ending if (sv.active && svs.maxclients == 1 && (cl.intermission < 5 || cl.intermission > 10)) { cl.intermission = 0; demohack = true; Cbuf_AddText("+attack\n"); // HACK !.. break; } CL_Stop_f (); } else if (cls.demoplayback) { cl.intermission = 0; break; } cl.completed_time = cl.time; vid.recalc_refdef = true; // go to full screen break; /* case svc_finale: cl.intermission = 2; cl.completed_time = cl.time; vid.recalc_refdef = true; // go to full screen SCR_CenterPrint (MSG_ReadString ()); break; case svc_cutscene: cl.intermission = 3; cl.completed_time = cl.time; vid.recalc_refdef = true; // go to full screen SCR_CenterPrint (MSG_ReadString ()); break; case svc_sellscreen: Cmd_ExecuteString ("help", src_command); break; */ case svc_set_view_flags: cl.viewent.drawflags |= MSG_ReadByte(); break; case svc_clear_view_flags: cl.viewent.drawflags &= ~MSG_ReadByte(); break; case svc_start_effect: CL_ParseEffect(); break; case svc_end_effect: CL_EndEffect(); break; case svc_plaque: CL_Plaque(); break; case svc_particle_explosion: CL_ParticleExplosion(); break; case svc_set_view_tint: i = MSG_ReadByte(); cl.viewent.colorshade = i; break; case svc_reference: packet_loss = false; cl.last_frame = cl.current_frame; cl.last_sequence = cl.current_sequence; cl.current_frame = MSG_ReadByte(); cl.current_sequence = MSG_ReadByte(); if (cl.need_build == 2) { // Con_Printf("CL: NB2 CL(%d,%d) R(%d)\n", cl.current_sequence, cl.current_frame,cl.reference_frame); cl.frames[0].count = cl.frames[1].count = cl.frames[2].count = 0; cl.need_build = 1; cl.reference_frame = cl.current_frame; } else if (cl.last_sequence != cl.current_sequence) { // Con_Printf("CL: Sequence CL(%d,%d) R(%d)\n", cl.current_sequence, cl.current_frame,cl.reference_frame); if (cl.reference_frame >= 1 && cl.reference_frame <= MAX_FRAMES) { RemovePlace = OrigPlace = NewPlace = AddedIndex = 0; for (i = 0; i < cl.num_entities; i++) { if (RemovePlace >= cl.NumToRemove || cl.RemoveList[RemovePlace] != i) { if (NewPlace < cl.frames[1].count && cl.frames[1].states[NewPlace].index == i) { cl.frames[2].states[AddedIndex] = cl.frames[1].states[NewPlace]; AddedIndex++; cl.frames[2].count++; } else if (OrigPlace < cl.frames[0].count && cl.frames[0].states[OrigPlace].index == i) { cl.frames[2].states[AddedIndex] = cl.frames[0].states[OrigPlace]; AddedIndex++; cl.frames[2].count++; } } else RemovePlace++; if (cl.frames[0].states[OrigPlace].index == i) OrigPlace++; if (cl.frames[1].states[NewPlace].index == i) NewPlace++; } cl.frames[0] = cl.frames[2]; } cl.frames[1].count = cl.frames[2].count = 0; cl.need_build = 1; cl.reference_frame = cl.current_frame; } else { // Con_Printf("CL: Normal CL(%d,%d) R(%d)\n", cl.current_sequence, cl.current_frame,cl.reference_frame); cl.need_build = 0; } for (i = 1, ent = cl_entities+1; i < cl.num_entities; i++, ent++) { ent->baseline.flags &= ~BE_ON; } for (i = 0; i < cl.frames[0].count; i++) { ent = CL_EntityNum (cl.frames[0].states[i].index); ent->model = cl.model_precache[cl.frames[0].states[i].modelindex]; ent->baseline.flags |= BE_ON; } break; case svc_clear_edicts: j = MSG_ReadByte(); if (cl.need_build) { cl.NumToRemove = j; } for (i = 0; i < j; i++) { k = MSG_ReadShort(); if (cl.need_build) cl.RemoveList[i] = k; ent = CL_EntityNum (k); ent->baseline.flags &= ~BE_ON; } break; case svc_update_inv: sc1 = sc2 = 0; test = MSG_ReadByte(); if (test & 1) sc1 |= ((int)MSG_ReadByte()); if (test & 2) sc1 |= ((int)MSG_ReadByte())<<8; if (test & 4) sc1 |= ((int)MSG_ReadByte())<<16; if (test & 8) sc1 |= ((int)MSG_ReadByte())<<24; if (test & 16) sc2 |= ((int)MSG_ReadByte()); if (test & 32) sc2 |= ((int)MSG_ReadByte())<<8; if (test & 64) sc2 |= ((int)MSG_ReadByte())<<16; if (test & 128) sc2 |= ((int)MSG_ReadByte())<<24; if (sc1 & SC1_HEALTH) cl.v.health = MSG_ReadShort(); if (sc1 & SC1_LEVEL) cl.v.level = MSG_ReadByte(); if (sc1 & SC1_INTELLIGENCE) cl.v.intelligence = MSG_ReadByte(); if (sc1 & SC1_WISDOM) cl.v.wisdom = MSG_ReadByte(); if (sc1 & SC1_STRENGTH) cl.v.strength = MSG_ReadByte(); if (sc1 & SC1_DEXTERITY) cl.v.dexterity = MSG_ReadByte(); if (sc1 & SC1_WEAPON) cl.v.weapon = MSG_ReadByte(); if (sc1 & SC1_BLUEMANA) cl.v.bluemana = MSG_ReadByte(); if (sc1 & SC1_GREENMANA) cl.v.greenmana = MSG_ReadByte(); if (sc1 & SC1_EXPERIENCE) cl.v.experience = MSG_ReadLong(); if (sc1 & SC1_CNT_TORCH) cl.v.cnt_torch = MSG_ReadByte(); if (sc1 & SC1_CNT_H_BOOST) cl.v.cnt_h_boost = MSG_ReadByte(); if (sc1 & SC1_CNT_SH_BOOST) cl.v.cnt_sh_boost = MSG_ReadByte(); if (sc1 & SC1_CNT_MANA_BOOST) cl.v.cnt_mana_boost = MSG_ReadByte(); if (sc1 & SC1_CNT_TELEPORT) cl.v.cnt_teleport = MSG_ReadByte(); if (sc1 & SC1_CNT_TOME) cl.v.cnt_tome = MSG_ReadByte(); if (sc1 & SC1_CNT_SUMMON) cl.v.cnt_summon = MSG_ReadByte(); if (sc1 & SC1_CNT_INVISIBILITY) cl.v.cnt_invisibility = MSG_ReadByte(); if (sc1 & SC1_CNT_GLYPH) cl.v.cnt_glyph = MSG_ReadByte(); if (sc1 & SC1_CNT_HASTE) cl.v.cnt_haste = MSG_ReadByte(); if (sc1 & SC1_CNT_BLAST) cl.v.cnt_blast = MSG_ReadByte(); if (sc1 & SC1_CNT_POLYMORPH) cl.v.cnt_polymorph = MSG_ReadByte(); if (sc1 & SC1_CNT_FLIGHT) cl.v.cnt_flight = MSG_ReadByte(); if (sc1 & SC1_CNT_CUBEOFFORCE) cl.v.cnt_cubeofforce = MSG_ReadByte(); if (sc1 & SC1_CNT_INVINCIBILITY) cl.v.cnt_invincibility = MSG_ReadByte(); if (sc1 & SC1_ARTIFACT_ACTIVE) cl.v.artifact_active = MSG_ReadFloat(); if (sc1 & SC1_ARTIFACT_LOW) cl.v.artifact_low = MSG_ReadFloat(); if (sc1 & SC1_MOVETYPE) cl.v.movetype = MSG_ReadByte(); if (sc1 & SC1_CAMERAMODE) cl.v.cameramode = MSG_ReadByte(); if (sc1 & SC1_HASTED) cl.v.hasted = MSG_ReadFloat(); if (sc1 & SC1_INVENTORY) cl.v.inventory = MSG_ReadByte(); if (sc1 & SC1_RINGS_ACTIVE) cl.v.rings_active = MSG_ReadFloat(); if (sc2 & SC2_RINGS_LOW) cl.v.rings_low = MSG_ReadFloat(); if (sc2 & SC2_AMULET) cl.v.armor_amulet = MSG_ReadByte(); if (sc2 & SC2_BRACER) cl.v.armor_bracer = MSG_ReadByte(); if (sc2 & SC2_BREASTPLATE) cl.v.armor_breastplate = MSG_ReadByte(); if (sc2 & SC2_HELMET) cl.v.armor_helmet = MSG_ReadByte(); if (sc2 & SC2_FLIGHT_T) cl.v.ring_flight = MSG_ReadByte(); if (sc2 & SC2_WATER_T) cl.v.ring_water = MSG_ReadByte(); if (sc2 & SC2_TURNING_T) cl.v.ring_turning = MSG_ReadByte(); if (sc2 & SC2_REGEN_T) cl.v.ring_regeneration = MSG_ReadByte(); if (sc2 & SC2_HASTE_T) cl.v.haste_time = MSG_ReadFloat(); if (sc2 & SC2_TOME_T) cl.v.tome_time = MSG_ReadFloat(); if (sc2 & SC2_PUZZLE1) q_snprintf(cl.puzzle_pieces[0], sizeof(cl.puzzle_pieces[0]), "%.9s", MSG_ReadString()); if (sc2 & SC2_PUZZLE2) q_snprintf(cl.puzzle_pieces[1], sizeof(cl.puzzle_pieces[0]), "%.9s", MSG_ReadString()); if (sc2 & SC2_PUZZLE3) q_snprintf(cl.puzzle_pieces[2], sizeof(cl.puzzle_pieces[0]), "%.9s", MSG_ReadString()); if (sc2 & SC2_PUZZLE4) q_snprintf(cl.puzzle_pieces[3], sizeof(cl.puzzle_pieces[0]), "%.9s", MSG_ReadString()); if (sc2 & SC2_PUZZLE5) q_snprintf(cl.puzzle_pieces[4], sizeof(cl.puzzle_pieces[0]), "%.9s", MSG_ReadString()); if (sc2 & SC2_PUZZLE6) q_snprintf(cl.puzzle_pieces[5], sizeof(cl.puzzle_pieces[0]), "%.9s", MSG_ReadString()); if (sc2 & SC2_PUZZLE7) q_snprintf(cl.puzzle_pieces[6], sizeof(cl.puzzle_pieces[0]), "%.9s", MSG_ReadString()); if (sc2 & SC2_PUZZLE8) q_snprintf(cl.puzzle_pieces[7], sizeof(cl.puzzle_pieces[0]), "%.9s", MSG_ReadString()); if (sc2 & SC2_MAXHEALTH) cl.v.max_health = MSG_ReadShort(); if (sc2 & SC2_MAXMANA) cl.v.max_mana = MSG_ReadByte(); if (sc2 & SC2_FLAGS) cl.v.flags = MSG_ReadFloat(); // SC2_OBJ, SC2_OBJ2: mission pack objectives // With protocol 18 (PROTOCOL_RAVEN_111), these // bits get set somehow (?!): let's avoid them. if (cl_protocol > PROTOCOL_RAVEN_111) { if (sc2 & SC2_OBJ) cl.info_mask = MSG_ReadLong(); if (sc2 & SC2_OBJ2) cl.info_mask2 = MSG_ReadLong(); } if ((sc1 & SC1_STAT_BAR) || (sc2 & SC2_STAT_BAR)) Sbar_Changed(); if ((sc1 & SC1_INV) || (sc2 & SC2_INV)) SB_InvChanged(); break; case svc_mod_name: case svc_skybox: MSG_ReadString(); Con_DPrintf ("Ignored server msg %d (%s)\n", cmd, svc_strings[cmd]); break; } } }
void CLNQ_ParseServerMessage (void) { int cmd; int i; qbool message_with_datagram; // hack to fix glitches when receiving a packet // without a datagram nq_player_teleported = false; // OMG, it's a hack! message_with_datagram = false; cl_entframecount++; if (cl_shownet.value == 1) Com_Printf ("%i ", net_message.cursize); else if (cl_shownet.value == 2) Com_Printf ("------------------\n"); cl.onground = false; // unless the server says otherwise // // parse the message // //MSG_BeginReading (); while (1) { if (msg_badread) Host_Error ("CL_ParseServerMessage: Bad server message"); cmd = MSG_ReadByte (); if (cmd == -1) { SHOWNET("END OF MESSAGE"); if (!message_with_datagram) { cl_entframecount--; } else { VectorCopy (nq_mviewangles[0], nq_mviewangles[1]); VectorCopy (nq_mviewangles_temp, nq_mviewangles[0]); } return; // end of message } // if the high bit of the command byte is set, it is a fast update if (cmd & 128) { SHOWNET("fast update"); NQD_ParseUpdate (cmd&127); continue; } if (cmd < num_svc_strings) SHOWNET(svc_strings[cmd]); // other commands switch (cmd) { default: Host_Error ("CL_ParseServerMessage: Illegible server message"); break; case svc_nop: break; case nq_svc_time: nq_mtime[1] = nq_mtime[0]; nq_mtime[0] = MSG_ReadFloat (); cl.servertime = nq_mtime[0]; message_with_datagram = true; break; case nq_svc_clientdata: i = MSG_ReadShort (); NQD_ParseClientdata (i); break; case nq_svc_version: i = MSG_ReadLong (); if (i != NQ_PROTOCOL_VERSION) Host_Error ("CL_ParseServerMessage: Server is protocol %i instead of %i\n", i, NQ_PROTOCOL_VERSION); break; case svc_disconnect: Com_Printf ("\n======== End of demo ========\n\n"); CL_NextDemo (); Host_EndGame (); Host_Abort (); break; case svc_print: NQD_ParsePrint (); break; case svc_centerprint: SCR_CenterPrint (MSG_ReadString ()); break; case svc_stufftext: NQD_ParseStufftext (); break; case svc_damage: V_ParseDamage (); break; case svc_serverdata: NQD_ParseServerData (); break; case svc_setangle: for (i=0 ; i<3 ; i++) nq_last_fixangle[i] = cl.simangles[i] = cl.viewangles[i] = MSG_ReadAngle (); break; case svc_setview: nq_viewentity = MSG_ReadShort (); if (nq_viewentity <= nq_maxclients) cl.playernum = nq_viewentity - 1; else { // just let cl.playernum stay where it was } break; case svc_lightstyle: i = MSG_ReadByte (); if (i >= MAX_LIGHTSTYLES) Sys_Error ("svc_lightstyle > MAX_LIGHTSTYLES"); strlcpy (cl_lightstyle[i].map, MSG_ReadString(), sizeof(cl_lightstyle[0].map)); cl_lightstyle[i].length = strlen(cl_lightstyle[i].map); break; case svc_sound: NQD_ParseStartSoundPacket(); break; case svc_stopsound: i = MSG_ReadShort(); S_StopSound(i>>3, i&7); break; case nq_svc_updatename: Sbar_Changed (); i = MSG_ReadByte (); if (i >= nq_maxclients) Host_Error ("CL_ParseServerMessage: svc_updatename > NQ_MAX_CLIENTS"); strlcpy (cl.players[i].name, MSG_ReadString(), sizeof(cl.players[i].name)); break; case svc_updatefrags: Sbar_Changed (); i = MSG_ReadByte (); if (i >= nq_maxclients) Host_Error ("CL_ParseServerMessage: svc_updatefrags > NQ_MAX_CLIENTS"); cl.players[i].frags = MSG_ReadShort(); break; case nq_svc_updatecolors: NQD_ParseUpdatecolors (); break; case nq_svc_particle: CL_ParseParticleEffect (); break; case svc_spawnbaseline: i = MSG_ReadShort (); if (i >= NQ_MAX_EDICTS) Host_Error ("svc_spawnbaseline: ent > MAX_EDICTS"); NQD_BumpEntityCount (i); CL_ParseBaseline (&cl_entities[i].baseline); break; case svc_spawnstatic: CL_ParseStatic (); break; case svc_temp_entity: CL_ParseTEnt (); break; case svc_setpause: if (MSG_ReadByte() != 0) cl.paused |= PAUSED_SERVER; else cl.paused &= ~PAUSED_SERVER; if (cl.paused) CDAudio_Pause (); else CDAudio_Resume (); break; case nq_svc_signonnum: i = MSG_ReadByte (); if (i <= nq_signon) Host_Error ("Received signon %i when at %i", i, nq_signon); nq_signon = i; CLNQ_SignonReply (); break; case svc_killedmonster: cl.stats[STAT_MONSTERS]++; break; case svc_foundsecret: cl.stats[STAT_SECRETS]++; break; case svc_updatestat: i = MSG_ReadByte (); if (i < 0 || i >= MAX_CL_STATS) Sys_Error ("svc_updatestat: %i is invalid", i); cl.stats[i] = MSG_ReadLong ();; break; case svc_spawnstaticsound: CL_ParseStaticSound (); break; case svc_cdtrack: cl.cdtrack = MSG_ReadByte (); MSG_ReadByte(); // loop track (unused) if (nq_forcecdtrack != -1) CDAudio_Play ((byte)nq_forcecdtrack, true); else CDAudio_Play ((byte)cl.cdtrack, true); break; case svc_intermission: cl.intermission = 1; cl.completed_time = cl.time; VectorCopy (nq_last_fixangle, cl.simangles); break; case svc_finale: cl.intermission = 2; cl.completed_time = cl.time; SCR_CenterPrint (MSG_ReadString ()); VectorCopy (nq_last_fixangle, cl.simangles); break; case nq_svc_cutscene: cl.intermission = 3; cl.completed_time = cl.time; SCR_CenterPrint (MSG_ReadString ()); VectorCopy (nq_last_fixangle, cl.simangles); break; case svc_sellscreen: break; } } }
/* ===================== CL_ParseServerMessage ===================== */ void CL_ParseServerMessage (void) { int cmd; int i; const char *str; //johnfitz int total, j, lastcmd; //johnfitz // // if recording demos, copy the message out // if (cl_shownet.value == 1) Con_Printf ("%i ",net_message.cursize); else if (cl_shownet.value == 2) Con_Printf ("------------------\n"); cl.onground = false; // unless the server says otherwise // // parse the message // MSG_BeginReading (); lastcmd = 0; while (1) { if (msg_badread) Host_Error ("CL_ParseServerMessage: Bad server message"); cmd = MSG_ReadByte (); if (cmd == -1) { SHOWNET("END OF MESSAGE"); return; // end of message } // if the high bit of the command byte is set, it is a fast update if (cmd & U_SIGNAL) //johnfitz -- was 128, changed for clarity { SHOWNET("fast update"); CL_ParseUpdate (cmd&127); continue; } SHOWNET(svc_strings[cmd]); // other commands switch (cmd) { default: Host_Error ("Illegible server message, previous was %s\n", svc_strings[lastcmd]); //johnfitz -- added svc_strings[lastcmd] break; case svc_nop: // Con_Printf ("svc_nop\n"); break; case svc_time: cl.mtime[1] = cl.mtime[0]; cl.mtime[0] = MSG_ReadFloat (); break; case svc_clientdata: CL_ParseClientdata (); //johnfitz -- removed bits parameter, we will read this inside CL_ParseClientdata() break; case svc_version: i = MSG_ReadLong (); //johnfitz -- support multiple protocols if (i != PROTOCOL_NETQUAKE && i != PROTOCOL_FITZQUAKE) Host_Error ("Server returned version %i, not %i or %i\n", i, PROTOCOL_NETQUAKE, PROTOCOL_FITZQUAKE); cl.protocol = i; //johnfitz break; case svc_disconnect: Host_EndGame ("Server disconnected\n"); case svc_print: Con_Printf ("%s", MSG_ReadString ()); break; case svc_centerprint: //johnfitz -- log centerprints to console str = MSG_ReadString (); SCR_CenterPrint (str); Con_LogCenterPrint (str); //johnfitz break; case svc_stufftext: cls.stufftext_frame = host_framecount; // allow full frame update // in demo playback -- Pa3PyX Cbuf_AddText (MSG_ReadString ()); break; case svc_damage: V_ParseDamage (); break; case svc_serverinfo: CL_ParseServerInfo (); vid.recalc_refdef = true; // leave intermission full screen break; case svc_setangle: for (i=0 ; i<3 ; i++) cl.viewangles[i] = MSG_ReadAngle (); break; case svc_setview: cl.viewentity = MSG_ReadShort (); break; case svc_lightstyle: i = MSG_ReadByte (); if (i >= MAX_LIGHTSTYLES) Sys_Error ("svc_lightstyle > MAX_LIGHTSTYLES"); q_strlcpy (cl_lightstyle[i].map, MSG_ReadString(), MAX_STYLESTRING); cl_lightstyle[i].length = Q_strlen(cl_lightstyle[i].map); //johnfitz -- save extra info if (cl_lightstyle[i].length) { total = 0; cl_lightstyle[i].peak = 'a'; for (j=0; j<cl_lightstyle[i].length; j++) { total += cl_lightstyle[i].map[j] - 'a'; cl_lightstyle[i].peak = q_max(cl_lightstyle[i].peak, cl_lightstyle[i].map[j]); } cl_lightstyle[i].average = total / cl_lightstyle[i].length + 'a'; } else cl_lightstyle[i].average = cl_lightstyle[i].peak = 'm'; //johnfitz break; case svc_sound: CL_ParseStartSoundPacket(); break; case svc_stopsound: i = MSG_ReadShort(); S_StopSound(i>>3, i&7); break; case svc_updatename: Sbar_Changed (); i = MSG_ReadByte (); if (i >= cl.maxclients) Host_Error ("CL_ParseServerMessage: svc_updatename > MAX_SCOREBOARD"); q_strlcpy (cl.scores[i].name, MSG_ReadString(), MAX_SCOREBOARDNAME); break; case svc_updatefrags: Sbar_Changed (); i = MSG_ReadByte (); if (i >= cl.maxclients) Host_Error ("CL_ParseServerMessage: svc_updatefrags > MAX_SCOREBOARD"); cl.scores[i].frags = MSG_ReadShort (); break; case svc_updatecolors: Sbar_Changed (); i = MSG_ReadByte (); if (i >= cl.maxclients) Host_Error ("CL_ParseServerMessage: svc_updatecolors > MAX_SCOREBOARD"); cl.scores[i].colors = MSG_ReadByte (); CL_NewTranslation (i); break; case svc_particle: R_ParseParticleEffect (); break; case svc_spawnbaseline: i = MSG_ReadShort (); // must use CL_EntityNum() to force cl.num_entities up CL_ParseBaseline (CL_EntityNum(i), 1); // johnfitz -- added second parameter break; case svc_spawnstatic: CL_ParseStatic (1); //johnfitz -- added parameter break; case svc_temp_entity: CL_ParseTEnt (); break; case svc_setpause: cl.paused = MSG_ReadByte (); if (cl.paused) { CDAudio_Pause (); BGM_Pause (); } else { CDAudio_Resume (); BGM_Resume (); } break; case svc_signonnum: i = MSG_ReadByte (); if (i <= cls.signon) Host_Error ("Received signon %i when at %i", i, cls.signon); cls.signon = i; //johnfitz -- if signonnum==2, signon packet has been fully parsed, so check for excessive static ents and efrags if (i == 2) { if (cl.num_statics > 128) Con_Warning ("%i static entities exceeds standard limit of 128.\n", cl.num_statics); R_CheckEfrags (); } //johnfitz CL_SignonReply (); break; case svc_killedmonster: cl.stats[STAT_MONSTERS]++; break; case svc_foundsecret: cl.stats[STAT_SECRETS]++; break; case svc_updatestat: i = MSG_ReadByte (); if (i < 0 || i >= MAX_CL_STATS) Sys_Error ("svc_updatestat: %i is invalid", i); cl.stats[i] = MSG_ReadLong ();; break; case svc_spawnstaticsound: CL_ParseStaticSound (1); //johnfitz -- added parameter break; case svc_cdtrack: cl.cdtrack = MSG_ReadByte (); cl.looptrack = MSG_ReadByte (); if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) ) BGM_PlayCDtrack ((byte)cls.forcetrack, true); else BGM_PlayCDtrack ((byte)cl.cdtrack, true); break; case svc_intermission: cl.intermission = 1; cl.completed_time = cl.time; vid.recalc_refdef = true; // go to full screen break; case svc_finale: cl.intermission = 2; cl.completed_time = cl.time; vid.recalc_refdef = true; // go to full screen //johnfitz -- log centerprints to console str = MSG_ReadString (); SCR_CenterPrint (str); Con_LogCenterPrint (str); //johnfitz break; case svc_cutscene: cl.intermission = 3; cl.completed_time = cl.time; vid.recalc_refdef = true; // go to full screen //johnfitz -- log centerprints to console str = MSG_ReadString (); SCR_CenterPrint (str); Con_LogCenterPrint (str); //johnfitz break; case svc_sellscreen: Cmd_ExecuteString ("help", src_command); break; //johnfitz -- new svc types case svc_skybox: Sky_LoadSkyBox (MSG_ReadString()); break; case svc_bf: Cmd_ExecuteString ("bf", src_command); break; case svc_fog: Fog_ParseServerMessage (); break; case svc_spawnbaseline2: //PROTOCOL_FITZQUAKE i = MSG_ReadShort (); // must use CL_EntityNum() to force cl.num_entities up CL_ParseBaseline (CL_EntityNum(i), 2); break; case svc_spawnstatic2: //PROTOCOL_FITZQUAKE CL_ParseStatic (2); break; case svc_spawnstaticsound2: //PROTOCOL_FITZQUAKE CL_ParseStaticSound (2); break; //johnfitz } lastcmd = cmd; //johnfitz } }
/* ==================== CL_PlayDemo_f play [demoname] ==================== */ void CL_PlayDemo_f (void) { char name[256]; qbool try_dem; if (Cmd_Argc() != 2) { Com_Printf ("playdemo <demoname> : plays a demo\n"); return; } // // disconnect from server // Host_EndGame (); // // open the demo file // strlcpy (name, Cmd_Argv(1), sizeof(name)-4); #ifdef _WIN32 if (strlen(name) > 4 && !Q_stricmp(name + strlen(name) - 4, ".qwz")) { PlayQWZDemo (); return; } #endif if (COM_FileExtension(name)[0] == 0) { COM_DefaultExtension (name, ".qwd"); try_dem = true; // if we can't open the .qwd, try .dem also } else try_dem = false; try_again: if (!strncmp(name, "../", 3) || !strncmp(name, "..\\", 3)) cls.demofile = fopen (va("%s/%s", com_basedir, name+3), "rb"); else FS_FOpenFile (name, &cls.demofile); if (!cls.demofile && try_dem) { COM_StripExtension (name, name); strcat (name, ".dem"); try_dem = false; goto try_again; } if (!cls.demofile) { Com_Printf ("ERROR: couldn't open \"%s\"\n", Cmd_Argv(1)); cls.playdemos = 0; return; } Com_Printf ("Playing demo from %s.\n", COM_SkipPath(name)); cls.nqdemoplayback = !Q_stricmp(COM_FileExtension(name), "dem"); if (cls.nqdemoplayback) { NQD_StartPlayback (); } #ifdef MVDPLAY cls.mvdplayback = !Q_stricmp(COM_FileExtension(name), "mvd"); #endif cls.demoplayback = true; cls.state = ca_demostart; Netchan_Setup (NS_CLIENT, &cls.netchan, net_null, 0); cls.demotime = 0; #ifdef MVDPLAY cls.mvd_newtime = cls.mvd_oldtime = 0; cls.mvd_findtarget = true; cls.mvd_lasttype = 0; cls.mvd_lastto = 0; MVD_ClearPredict(); #endif }
/* =============== SV_LoadGame_f =============== */ void SV_LoadGame_f (void) { char name[MAX_OSPATH]; FILE *f; char mapname[MAX_QPATH]; float time, tfloat; char str[32768], *start; int i, r; edict_t *ent; int entnum; int version; float spawn_parms[NUM_SPAWN_PARMS]; qbool save_disabled_for_loading; if (Cmd_Argc() != 2) { Com_Printf ("load <savename> : load a game\n"); return; } sprintf (name, "%s/save/%s", com_gamedir, Cmd_Argv(1)); COM_DefaultExtension (name, ".sav"); // we can't call SCR_BeginLoadingPlaque, because too much stack space has // been used. The menu calls it before stuffing loadgame command // SCR_BeginLoadingPlaque (); Com_Printf ("Loading game from %s...\n", name); f = fopen (name, "r"); if (!f) { Com_Printf ("ERROR: couldn't open.\n"); return; } fscanf (f, "%i\n", &version); if (version != SAVEGAME_VERSION) { fclose (f); Com_Printf ("Savegame is version %i, not %i\n", version, SAVEGAME_VERSION); return; } fscanf (f, "%s\n", str); for (i=0 ; i<NUM_SPAWN_PARMS ; i++) fscanf (f, "%f\n", &spawn_parms[i]); // this silliness is so we can load 1.06 save files, which have float skill values fscanf (f, "%f\n", &tfloat); current_skill = (int)(tfloat + 0.1); Cvar_Set (&skill, va("%i", current_skill)); Cvar_SetValue (&deathmatch, 0); Cvar_SetValue (&coop, 0); Cvar_SetValue (&teamplay, 0); Cvar_SetValue (&maxclients, 1); fscanf (f, "%s\n",mapname); fscanf (f, "%f\n",&time); save_disabled_for_loading = scr_disabled_for_loading; Host_EndGame (); // Host_EndGame disables the loading plaque, restore it scr_disabled_for_loading = save_disabled_for_loading; CL_BeginLocalConnection (); SV_SpawnServer (mapname, false); if (sv.state != ss_active) { Com_Printf ("Couldn't load map\n"); return; } Cvar_ForceSet (&sv_paused, "1"); // pause until all clients connect sv.loadgame = true; // load the light styles for (i=0 ; i<MAX_LIGHTSTYLES ; i++) { fscanf (f, "%s\n", str); sv.lightstyles[i] = Hunk_Alloc (strlen(str)+1); strcpy (sv.lightstyles[i], str); } // load the edicts out of the savegame file entnum = -1; // -1 is the globals while (!feof(f)) { for (i=0 ; i<sizeof(str)-1 ; i++) { r = fgetc (f); if (r == EOF || !r) break; str[i] = r; if (r == '}') { i++; break; } } if (i == sizeof(str)-1) Host_Error ("Loadgame buffer overflow"); str[i] = 0; start = str; start = COM_Parse(str); if (!com_token[0]) break; // end of file if (strcmp(com_token,"{")) Host_Error ("First token isn't a brace"); if (entnum == -1) { // parse the global vars ED_ParseGlobals (start); } else { // parse an edict ent = EDICT_NUM(entnum); memset (&ent->v, 0, progs->entityfields * 4); ent->inuse = true; ED_ParseEdict (start, ent); // link it into the bsp tree if (ent->inuse) SV_LinkEdict (ent, false); } entnum++; } sv.num_edicts = entnum; sv.time = time; fclose (f); // FIXME: this assumes the player is using client slot #0 for (i = 0; i < NUM_SPAWN_PARMS; i++) svs.clients->spawn_parms[i] = spawn_parms[i]; }