?? cl_parse.c
字號(hào):
/*
Copyright (C) 1997-2001 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// cl_parse.c -- parse a message received from the server
#include "client.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 ();
}
/*
=====================
CL_ParseDownload
A download message has been received from the server
=====================
*/
void CL_ParseDownload (void)
{
int size, percent;
char name[MAX_OSPATH];
int r;
// 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
#if 0
Com_Printf (".");
if (10*(percent/10) != cls.downloadpercent)
{
cls.downloadpercent = 10*(percent/10);
Com_Printf ("%i%%", cls.downloadpercent);
}
#endif
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);
r = rename (oldn, newn);
if (r)
Com_Printf ("failed to rename.\n");
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");
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -