// cl_parse.c -- parse a message received from the server #include <u.h>#include <libc.h>#include <stdio.h>#include "dat.h"#include "fns.h" char *svc_strings[256] ={ "svc_bad", "svc_muzzleflash", "svc_muzzlflash2", "svc_temp_entity", "svc_layout", "svc_inventory", "svc_nop", "svc_disconnect", "svc_reconnect", "svc_sound", "svc_print", "svc_stufftext", "svc_serverdata", "svc_configstring", "svc_spawnbaseline", "svc_centerprint", "svc_download", "svc_playerinfo", "svc_packetentities", "svc_deltapacketentities", "svc_frame"}; //============================================================================= void CL_DownloadFileName(char *dest, int destlen, char *fn){ if (strncmp(fn, "players", 7) == 0) Com_sprintf (dest, destlen, "%s/%s", BASEDIRNAME, fn); else Com_sprintf (dest, destlen, "%s/%s", FS_Gamedir(), fn);} /*===============CL_CheckOrDownloadFile Returns true if the file exists, otherwise it attemptsto start a download from the server.===============*/qboolean CL_CheckOrDownloadFile (char *filename){ FILE *fp; char name[MAX_OSPATH]; if (strstr (filename, "..")) { Com_Printf ("Refusing to download a path with ..\n"); return true; } if (FS_LoadFile (filename, NULL) != -1) { // it exists, no need to download return true; } strcpy (cls.downloadname, filename); // download to a temp name, and only rename // to the real name when done, so if interrupted // a runt file wont be left COM_StripExtension (cls.downloadname, cls.downloadtempname); strcat (cls.downloadtempname, ".tmp"); //ZOID // check to see if we already have a tmp for this file, if so, try to resume // open the file if not opened yet CL_DownloadFileName(name, sizeof(name), cls.downloadtempname); // FS_CreatePath (name); fp = fopen (name, "r+b"); if (fp) { // it exists int len; fseek(fp, 0, SEEK_END); len = ftell(fp); cls.download = fp; // give the server an offset to start the download Com_Printf ("Resuming %s\n", cls.downloadname); MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteString (&cls.netchan.message, va("download %s %i", cls.downloadname, len)); } else { Com_Printf ("Downloading %s\n", cls.downloadname); MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteString (&cls.netchan.message, va("download %s", cls.downloadname)); } cls.downloadnumber++; return false;} /*===============CL_Download_f Request a download from the server===============*/void CL_Download_f (void){ char filename[MAX_OSPATH]; if (Cmd_Argc() != 2) { Com_Printf("Usage: download <filename>\n"); return; } Com_sprintf(filename, sizeof(filename), "%s", Cmd_Argv(1)); if (strstr (filename, "..")) { Com_Printf ("Refusing to download a path with ..\n"); return; } if (FS_LoadFile (filename, NULL) != -1) { // it exists, no need to download Com_Printf("File already exists.\n"); return; } strcpy (cls.downloadname, filename); Com_Printf ("Downloading %s\n", cls.downloadname); // download to a temp name, and only rename // to the real name when done, so if interrupted // a runt file wont be left COM_StripExtension (cls.downloadname, cls.downloadtempname); strcat (cls.downloadtempname, ".tmp"); MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteString (&cls.netchan.message, va("download %s", cls.downloadname)); cls.downloadnumber++;} /*======================CL_RegisterSounds======================*/void CL_RegisterSounds (void){ int i; S_BeginRegistration (); CL_RegisterTEntSounds (); for (i=1 ; i<MAX_SOUNDS ; i++) { if (!cl.configstrings[CS_SOUNDS+i][0]) break; cl.sound_precache[i] = S_RegisterSound (cl.configstrings[CS_SOUNDS+i]); Sys_SendKeyEvents (); // pump message loop } S_EndRegistration ();} static voidrename(char *old, char *new){ char *p; Dir d; if((p = strrchr(new, '/')) == nil) p = new; else p++; nulldir(&d); d.name = p; if(dirwstat(old, &d) < 0) fprint(2, "rename: %r\n");} /*=====================CL_ParseDownload A download message has been received from the server=====================*/void CL_ParseDownload (void){ int size, percent; char name[MAX_OSPATH]; // read the data size = MSG_ReadShort (&net_message); percent = MSG_ReadByte (&net_message); if (size == -1) { Com_Printf ("Server does not have this file.\n"); if (cls.download) { // if here, we tried to resume a file but the server said no fclose (cls.download); cls.download = NULL; } CL_RequestNextDownload (); return; } // open the file if not opened yet if (!cls.download) { CL_DownloadFileName(name, sizeof(name), cls.downloadtempname); FS_CreatePath (name); cls.download = fopen (name, "wb"); if (!cls.download) { net_message.readcount += size; Com_Printf ("Failed to open %s\n", cls.downloadtempname); CL_RequestNextDownload (); return; } } fwrite (net_message.data + net_message.readcount, 1, size, cls.download); net_message.readcount += size; if (percent != 100) { // request next block// change display routines by zoid/* Com_Printf ("."); if (10*(percent/10) != cls.downloadpercent) { cls.downloadpercent = 10*(percent/10); Com_Printf ("%i%%", cls.downloadpercent); }*/ cls.downloadpercent = percent; MSG_WriteByte (&cls.netchan.message, clc_stringcmd); SZ_Print (&cls.netchan.message, "nextdl"); } else { char oldn[MAX_OSPATH]; char newn[MAX_OSPATH]; // Com_Printf ("100%%\n"); fclose (cls.download); // rename the temp file to it's final name CL_DownloadFileName(oldn, sizeof(oldn), cls.downloadtempname); CL_DownloadFileName(newn, sizeof(newn), cls.downloadname); rename (oldn, newn); /* FIXME */ cls.download = NULL; cls.downloadpercent = 0; // get another file if needed CL_RequestNextDownload (); }} /*===================================================================== SERVER CONNECTING MESSAGES =====================================================================*/ /*==================CL_ParseServerData==================*/void CL_ParseServerData (void){ extern cvar_t *fs_gamedirvar; char *str; int i; Com_DPrintf ("Serverdata packet received.\n");//// wipe the client_state_t struct// CL_ClearState (); cls.state = ca_connected; // parse protocol version number i = MSG_ReadLong (&net_message); cls.serverProtocol = i; // BIG HACK to let demos from release work with the 3.0x patch!!! if (Com_ServerState() && PROTOCOL_VERSION == 34) { } else if (i != PROTOCOL_VERSION) Com_Error (ERR_DROP,"Server returned version %i, not %i", i, PROTOCOL_VERSION); cl.servercount = MSG_ReadLong (&net_message); cl.attractloop = MSG_ReadByte (&net_message); // game directory str = MSG_ReadString (&net_message); strncpy (cl.gamedir, str, sizeof(cl.gamedir)-1); // set gamedir if ((*str && (!fs_gamedirvar->string || !*fs_gamedirvar->string || strcmp(fs_gamedirvar->string, str))) || (!*str && (fs_gamedirvar->string || *fs_gamedirvar->string))) Cvar_Set("game", str); // parse player entity number cl.playernum = MSG_ReadShort (&net_message); // get the full level name str = MSG_ReadString (&net_message); if (cl.playernum == -1) { // playing a cinematic or showing a pic, not a level SCR_PlayCinematic (str); } else { // seperate the printfs so the server message can have a color Com_Printf("\n\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n\n"); Com_Printf ("%c%s\n", 2, str); // need to prep refresh at next oportunity cl.refresh_prepped = false; }} /*==================CL_ParseBaseline==================*/void CL_ParseBaseline (void){ entity_state_t *es; int bits; int newnum; entity_state_t nullstate; memset (&nullstate, 0, sizeof(nullstate)); newnum = CL_ParseEntityBits (&bits); es = &cl_entities[newnum].baseline; CL_ParseDelta (&nullstate, es, newnum, bits);} /*================CL_LoadClientinfo ================*/void CL_LoadClientinfo (clientinfo_t *ci, char *s){ int i; char *t; char model_name[MAX_QPATH]; char skin_name[MAX_QPATH]; char model_filename[MAX_QPATH]; char skin_filename[MAX_QPATH]; char weapon_filename[MAX_QPATH]; strncpy(ci->cinfo, s, sizeof(ci->cinfo)); ci->cinfo[sizeof(ci->cinfo)-1] = 0; // isolate the player's name strncpy(ci->name, s, sizeof(ci->name)); ci->name[sizeof(ci->name)-1] = 0; t = strstr (s, "\\"); if (t) { ci->name[t-s] = 0; s = t+1; } if (cl_noskins->value || *s == 0) { Com_sprintf (model_filename, sizeof(model_filename), "players/male/tris.md2"); Com_sprintf (weapon_filename, sizeof(weapon_filename), "players/male/weapon.md2"); Com_sprintf (skin_filename, sizeof(skin_filename), "players/male/grunt.pcx"); Com_sprintf (ci->iconname, sizeof(ci->iconname), "/players/male/grunt_i.pcx"); ci->model = re.RegisterModel (model_filename); memset(ci->weaponmodel, 0, sizeof(ci->weaponmodel)); ci->weaponmodel[0] = re.RegisterModel (weapon_filename); ci->skin = re.RegisterSkin (skin_filename); ci->icon = re.RegisterPic (ci->iconname); } else { // isolate the model name strcpy (model_name, s); t = strstr(model_name, "/"); if (!t) t = strstr(model_name, "\\"); if (!t) t = model_name; *t = 0; // isolate the skin name strcpy (skin_name, s + strlen(model_name) + 1); // model file Com_sprintf (model_filename, sizeof(model_filename), "players/%s/tris.md2", model_name); ci->model = re.RegisterModel (model_filename); if (!ci->model) { strcpy(model_name, "male"); Com_sprintf (model_filename, sizeof(model_filename), "players/male/tris.md2"); ci->model = re.RegisterModel (model_filename); } // skin file Com_sprintf (skin_filename, sizeof(skin_filename), "players/%s/%s.pcx", model_name, skin_name); ci->skin = re.RegisterSkin (skin_filename); // if we don't have the skin and the model wasn't male, // see if the male has it (this is for CTF's skins) if (!ci->skin && cistrcmp(model_name, "male")) { // change model to male strcpy(model_name, "male"); Com_sprintf (model_filename, sizeof(model_filename), "players/male/tris.md2"); ci->model = re.RegisterModel (model_filename); // see if the skin exists for the male model Com_sprintf (skin_filename, sizeof(skin_filename), "players/%s/%s.pcx", model_name, skin_name); ci->skin = re.RegisterSkin (skin_filename); } // if we still don't have a skin, it means that the male model didn't have // it, so default to grunt if (!ci->skin) { // see if the skin exists for the male model Com_sprintf (skin_filename, sizeof(skin_filename), "players/%s/grunt.pcx", model_name, skin_name); ci->skin = re.RegisterSkin (skin_filename); } // weapon file for (i = 0; i < num_cl_weaponmodels; i++) { Com_sprintf (weapon_filename, sizeof(weapon_filename), "players/%s/%s", model_name, cl_weaponmodels[i]); ci->weaponmodel[i] = re.RegisterModel(weapon_filename); if (!ci->weaponmodel[i] && strcmp(model_name, "cyborg") == 0) { // try male Com_sprintf (weapon_filename, sizeof(weapon_filename), "players/male/%s", cl_weaponmodels[i]); ci->weaponmodel[i] = re.RegisterModel(weapon_filename); } if (!cl_vwep->value) break; // only one when vwep is off } // icon file Com_sprintf (ci->iconname, sizeof(ci->iconname), "/players/%s/%s_i.pcx", model_name, skin_name); ci->icon = re.RegisterPic (ci->iconname); } // must have loaded all data types to be valud if (!ci->skin || !ci->icon || !ci->model || !ci->weaponmodel[0]) { ci->skin = NULL; ci->icon = NULL; ci->model = NULL; ci->weaponmodel[0] = NULL; return; }} /*================CL_ParseClientinfo Load the skin, icon, and model for a client================*/void CL_ParseClientinfo (int player){ char *s;Lines 1–500 of 803. Load more
// cl_parse.c -- parse a message received from the server #include <u.h> #include <libc.h> #include <stdio.h> #include "dat.h" #include "fns.h" char *svc_strings[256] = { "svc_bad", "svc_muzzleflash", "svc_muzzlflash2", "svc_temp_entity", "svc_layout", "svc_inventory", "svc_nop", "svc_disconnect", "svc_reconnect", "svc_sound", "svc_print", "svc_stufftext", "svc_serverdata", "svc_configstring", "svc_spawnbaseline", "svc_centerprint", "svc_download", "svc_playerinfo", "svc_packetentities", "svc_deltapacketentities", "svc_frame" }; //============================================================================= void CL_DownloadFileName(char *dest, int destlen, char *fn) { if (strncmp(fn, "players", 7) == 0) Com_sprintf (dest, destlen, "%s/%s", BASEDIRNAME, fn); else Com_sprintf (dest, destlen, "%s/%s", FS_Gamedir(), fn); } /* =============== CL_CheckOrDownloadFile Returns true if the file exists, otherwise it attempts to start a download from the server. =============== */ qboolean CL_CheckOrDownloadFile (char *filename) { FILE *fp; char name[MAX_OSPATH]; if (strstr (filename, "..")) { Com_Printf ("Refusing to download a path with ..\n"); return true; } if (FS_LoadFile (filename, NULL) != -1) { // it exists, no need to download return true; } strcpy (cls.downloadname, filename); // download to a temp name, and only rename // to the real name when done, so if interrupted // a runt file wont be left COM_StripExtension (cls.downloadname, cls.downloadtempname); strcat (cls.downloadtempname, ".tmp"); //ZOID // check to see if we already have a tmp for this file, if so, try to resume // open the file if not opened yet CL_DownloadFileName(name, sizeof(name), cls.downloadtempname); // FS_CreatePath (name); fp = fopen (name, "r+b"); if (fp) { // it exists int len; fseek(fp, 0, SEEK_END); len = ftell(fp); cls.download = fp; // give the server an offset to start the download Com_Printf ("Resuming %s\n", cls.downloadname); MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteString (&cls.netchan.message, va("download %s %i", cls.downloadname, len)); } else { Com_Printf ("Downloading %s\n", cls.downloadname); MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteString (&cls.netchan.message, va("download %s", cls.downloadname)); } cls.downloadnumber++; return false; } /* =============== CL_Download_f Request a download from the server =============== */ void CL_Download_f (void) { char filename[MAX_OSPATH]; if (Cmd_Argc() != 2) { Com_Printf("Usage: download <filename>\n"); return; } Com_sprintf(filename, sizeof(filename), "%s", Cmd_Argv(1)); if (strstr (filename, "..")) { Com_Printf ("Refusing to download a path with ..\n"); return; } if (FS_LoadFile (filename, NULL) != -1) { // it exists, no need to download Com_Printf("File already exists.\n"); return; } strcpy (cls.downloadname, filename); Com_Printf ("Downloading %s\n", cls.downloadname); // download to a temp name, and only rename // to the real name when done, so if interrupted // a runt file wont be left COM_StripExtension (cls.downloadname, cls.downloadtempname); strcat (cls.downloadtempname, ".tmp"); MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteString (&cls.netchan.message, va("download %s", cls.downloadname)); cls.downloadnumber++; } /* ====================== CL_RegisterSounds ====================== */ void CL_RegisterSounds (void) { int i; S_BeginRegistration (); CL_RegisterTEntSounds (); for (i=1 ; i<MAX_SOUNDS ; i++) { if (!cl.configstrings[CS_SOUNDS+i][0]) break; cl.sound_precache[i] = S_RegisterSound (cl.configstrings[CS_SOUNDS+i]); Sys_SendKeyEvents (); // pump message loop } S_EndRegistration (); } static void rename(char *old, char *new) { char *p; Dir d; if((p = strrchr(new, '/')) == nil) p = new; else p++; nulldir(&d); d.name = p; if(dirwstat(old, &d) < 0) fprint(2, "rename: %r\n"); } /* ===================== CL_ParseDownload A download message has been received from the server ===================== */ void CL_ParseDownload (void) { int size, percent; char name[MAX_OSPATH]; // read the data size = MSG_ReadShort (&net_message); percent = MSG_ReadByte (&net_message); if (size == -1) { Com_Printf ("Server does not have this file.\n"); if (cls.download) { // if here, we tried to resume a file but the server said no fclose (cls.download); cls.download = NULL; } CL_RequestNextDownload (); return; } // open the file if not opened yet if (!cls.download) { CL_DownloadFileName(name, sizeof(name), cls.downloadtempname); FS_CreatePath (name); cls.download = fopen (name, "wb"); if (!cls.download) { net_message.readcount += size; Com_Printf ("Failed to open %s\n", cls.downloadtempname); CL_RequestNextDownload (); return; } } fwrite (net_message.data + net_message.readcount, 1, size, cls.download); net_message.readcount += size; if (percent != 100) { // request next block // change display routines by zoid /* Com_Printf ("."); if (10*(percent/10) != cls.downloadpercent) { cls.downloadpercent = 10*(percent/10); Com_Printf ("%i%%", cls.downloadpercent); } */ cls.downloadpercent = percent; MSG_WriteByte (&cls.netchan.message, clc_stringcmd); SZ_Print (&cls.netchan.message, "nextdl"); } else { char oldn[MAX_OSPATH]; char newn[MAX_OSPATH]; // Com_Printf ("100%%\n"); fclose (cls.download); // rename the temp file to it's final name CL_DownloadFileName(oldn, sizeof(oldn), cls.downloadtempname); CL_DownloadFileName(newn, sizeof(newn), cls.downloadname); rename (oldn, newn); /* FIXME */ cls.download = NULL; cls.downloadpercent = 0; // get another file if needed CL_RequestNextDownload (); } } /* ===================================================================== SERVER CONNECTING MESSAGES ===================================================================== */ /* ================== CL_ParseServerData ================== */ void CL_ParseServerData (void) { extern cvar_t *fs_gamedirvar; char *str; int i; Com_DPrintf ("Serverdata packet received.\n"); // // wipe the client_state_t struct // CL_ClearState (); cls.state = ca_connected; // parse protocol version number i = MSG_ReadLong (&net_message); cls.serverProtocol = i; // BIG HACK to let demos from release work with the 3.0x patch!!! if (Com_ServerState() && PROTOCOL_VERSION == 34) { } else if (i != PROTOCOL_VERSION) Com_Error (ERR_DROP,"Server returned version %i, not %i", i, PROTOCOL_VERSION); cl.servercount = MSG_ReadLong (&net_message); cl.attractloop = MSG_ReadByte (&net_message); // game directory str = MSG_ReadString (&net_message); strncpy (cl.gamedir, str, sizeof(cl.gamedir)-1); // set gamedir if ((*str && (!fs_gamedirvar->string || !*fs_gamedirvar->string || strcmp(fs_gamedirvar->string, str))) || (!*str && (fs_gamedirvar->string || *fs_gamedirvar->string))) Cvar_Set("game", str); // parse player entity number cl.playernum = MSG_ReadShort (&net_message); // get the full level name str = MSG_ReadString (&net_message); if (cl.playernum == -1) { // playing a cinematic or showing a pic, not a level SCR_PlayCinematic (str); } else { // seperate the printfs so the server message can have a color Com_Printf("\n\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n\n"); Com_Printf ("%c%s\n", 2, str); // need to prep refresh at next oportunity cl.refresh_prepped = false; } } /* ================== CL_ParseBaseline ================== */ void CL_ParseBaseline (void) { entity_state_t *es; int bits; int newnum; entity_state_t nullstate; memset (&nullstate, 0, sizeof(nullstate)); newnum = CL_ParseEntityBits (&bits); es = &cl_entities[newnum].baseline; CL_ParseDelta (&nullstate, es, newnum, bits); } /* ================ CL_LoadClientinfo ================ */ void CL_LoadClientinfo (clientinfo_t *ci, char *s) { int i; char *t; char model_name[MAX_QPATH]; char skin_name[MAX_QPATH]; char model_filename[MAX_QPATH]; char skin_filename[MAX_QPATH]; char weapon_filename[MAX_QPATH]; strncpy(ci->cinfo, s, sizeof(ci->cinfo)); ci->cinfo[sizeof(ci->cinfo)-1] = 0; // isolate the player's name strncpy(ci->name, s, sizeof(ci->name)); ci->name[sizeof(ci->name)-1] = 0; t = strstr (s, "\\"); if (t) { ci->name[t-s] = 0; s = t+1; } if (cl_noskins->value || *s == 0) { Com_sprintf (model_filename, sizeof(model_filename), "players/male/tris.md2"); Com_sprintf (weapon_filename, sizeof(weapon_filename), "players/male/weapon.md2"); Com_sprintf (skin_filename, sizeof(skin_filename), "players/male/grunt.pcx"); Com_sprintf (ci->iconname, sizeof(ci->iconname), "/players/male/grunt_i.pcx"); ci->model = re.RegisterModel (model_filename); memset(ci->weaponmodel, 0, sizeof(ci->weaponmodel)); ci->weaponmodel[0] = re.RegisterModel (weapon_filename); ci->skin = re.RegisterSkin (skin_filename); ci->icon = re.RegisterPic (ci->iconname); } else { // isolate the model name strcpy (model_name, s); t = strstr(model_name, "/"); if (!t) t = strstr(model_name, "\\"); if (!t) t = model_name; *t = 0; // isolate the skin name strcpy (skin_name, s + strlen(model_name) + 1); // model file Com_sprintf (model_filename, sizeof(model_filename), "players/%s/tris.md2", model_name); ci->model = re.RegisterModel (model_filename); if (!ci->model) { strcpy(model_name, "male"); Com_sprintf (model_filename, sizeof(model_filename), "players/male/tris.md2"); ci->model = re.RegisterModel (model_filename); } // skin file Com_sprintf (skin_filename, sizeof(skin_filename), "players/%s/%s.pcx", model_name, skin_name); ci->skin = re.RegisterSkin (skin_filename); // if we don't have the skin and the model wasn't male, // see if the male has it (this is for CTF's skins) if (!ci->skin && cistrcmp(model_name, "male")) { // change model to male strcpy(model_name, "male"); Com_sprintf (model_filename, sizeof(model_filename), "players/male/tris.md2"); ci->model = re.RegisterModel (model_filename); // see if the skin exists for the male model Com_sprintf (skin_filename, sizeof(skin_filename), "players/%s/%s.pcx", model_name, skin_name); ci->skin = re.RegisterSkin (skin_filename); } // if we still don't have a skin, it means that the male model didn't have // it, so default to grunt if (!ci->skin) { // see if the skin exists for the male model Com_sprintf (skin_filename, sizeof(skin_filename), "players/%s/grunt.pcx", model_name, skin_name); ci->skin = re.RegisterSkin (skin_filename); } // weapon file for (i = 0; i < num_cl_weaponmodels; i++) { Com_sprintf (weapon_filename, sizeof(weapon_filename), "players/%s/%s", model_name, cl_weaponmodels[i]); ci->weaponmodel[i] = re.RegisterModel(weapon_filename); if (!ci->weaponmodel[i] && strcmp(model_name, "cyborg") == 0) { // try male Com_sprintf (weapon_filename, sizeof(weapon_filename), "players/male/%s", cl_weaponmodels[i]); ci->weaponmodel[i] = re.RegisterModel(weapon_filename); } if (!cl_vwep->value) break; // only one when vwep is off } // icon file Com_sprintf (ci->iconname, sizeof(ci->iconname), "/players/%s/%s_i.pcx", model_name, skin_name); ci->icon = re.RegisterPic (ci->iconname); } // must have loaded all data types to be valud if (!ci->skin || !ci->icon || !ci->model || !ci->weaponmodel[0]) { ci->skin = NULL; ci->icon = NULL; ci->model = NULL; ci->weaponmodel[0] = NULL; return; } } /* ================ CL_ParseClientinfo Load the skin, icon, and model for a client ================ */ void CL_ParseClientinfo (int player) { char *s;