?? cl_main.c
字號(hào):
{
byte final[32];
if (cls.state == ca_disconnected)
return;
if (cl_timedemo && cl_timedemo->value)
{
int time;
time = Sys_Milliseconds () - cl.timedemo_start;
if (time > 0)
Com_Printf ("%i frames, %3.1f seconds: %3.1f fps\n", cl.timedemo_frames,
time/1000.0, cl.timedemo_frames*1000.0 / time);
}
VectorClear (cl.refdef.blend);
re.CinematicSetPalette(NULL);
M_ForceMenuOff ();
cls.connect_time = 0;
SCR_StopCinematic ();
if (cls.demorecording)
CL_Stop_f ();
// send a disconnect message to the server
final[0] = clc_stringcmd;
strcpy ((char *)final+1, "disconnect");
Netchan_Transmit (&cls.netchan, strlen(final), final);
Netchan_Transmit (&cls.netchan, strlen(final), final);
Netchan_Transmit (&cls.netchan, strlen(final), final);
CL_ClearState ();
// stop download
if (cls.download) {
fclose(cls.download);
cls.download = NULL;
}
cls.state = ca_disconnected;
}
void CL_Disconnect_f (void)
{
Com_Error (ERR_DROP, "Disconnected from server");
}
/*
====================
CL_Packet_f
packet <destination> <contents>
Contents allows \n escape character
====================
*/
void CL_Packet_f (void)
{
char send[2048];
int i, l;
char *in, *out;
netadr_t adr;
if (Cmd_Argc() != 3)
{
Com_Printf ("packet <destination> <contents>\n");
return;
}
NET_Config (true); // allow remote
if (!NET_StringToAdr (Cmd_Argv(1), &adr))
{
Com_Printf ("Bad address\n");
return;
}
if (!adr.port)
adr.port = BigShort (PORT_SERVER);
in = Cmd_Argv(2);
out = send+4;
send[0] = send[1] = send[2] = send[3] = (char)0xff;
l = strlen (in);
for (i=0 ; i<l ; i++)
{
if (in[i] == '\\' && in[i+1] == 'n')
{
*out++ = '\n';
i++;
}
else
*out++ = in[i];
}
*out = 0;
NET_SendPacket (NS_CLIENT, out-send, send, adr);
}
/*
=================
CL_Changing_f
Just sent as a hint to the client that they should
drop to full console
=================
*/
void CL_Changing_f (void)
{
//ZOID
//if we are downloading, we don't change! This so we don't suddenly stop downloading a map
if (cls.download)
return;
SCR_BeginLoadingPlaque ();
cls.state = ca_connected; // not active anymore, but not disconnected
Com_Printf ("\nChanging map...\n");
}
/*
=================
CL_Reconnect_f
The server is changing levels
=================
*/
void CL_Reconnect_f (void)
{
//ZOID
//if we are downloading, we don't change! This so we don't suddenly stop downloading a map
if (cls.download)
return;
S_StopAllSounds ();
if (cls.state == ca_connected) {
Com_Printf ("reconnecting...\n");
cls.state = ca_connected;
MSG_WriteChar (&cls.netchan.message, clc_stringcmd);
MSG_WriteString (&cls.netchan.message, "new");
return;
}
if (*cls.servername) {
if (cls.state >= ca_connected) {
CL_Disconnect();
cls.connect_time = cls.realtime - 1500;
} else
cls.connect_time = -99999; // fire immediately
cls.state = ca_connecting;
Com_Printf ("reconnecting...\n");
}
}
/*
=================
CL_ParseStatusMessage
Handle a reply from a ping
=================
*/
void CL_ParseStatusMessage (void)
{
char *s;
s = MSG_ReadString(&net_message);
Com_Printf ("%s\n", s);
M_AddToServerList (net_from, s);
}
/*
=================
CL_PingServers_f
=================
*/
void CL_PingServers_f (void)
{
int i;
netadr_t adr;
char name[32];
char *adrstring;
cvar_t *noudp;
cvar_t *noipx;
NET_Config (true); // allow remote
// send a broadcast packet
Com_Printf ("pinging broadcast...\n");
noudp = Cvar_Get ("noudp", "0", CVAR_NOSET);
if (!noudp->value)
{
adr.type = NA_BROADCAST;
adr.port = BigShort(PORT_SERVER);
Netchan_OutOfBandPrint (NS_CLIENT, adr, va("info %i", PROTOCOL_VERSION));
}
noipx = Cvar_Get ("noipx", "0", CVAR_NOSET);
if (!noipx->value)
{
adr.type = NA_BROADCAST_IPX;
adr.port = BigShort(PORT_SERVER);
Netchan_OutOfBandPrint (NS_CLIENT, adr, va("info %i", PROTOCOL_VERSION));
}
// send a packet to each address book entry
for (i=0 ; i<16 ; i++)
{
Com_sprintf (name, sizeof(name), "adr%i", i);
adrstring = Cvar_VariableString (name);
if (!adrstring || !adrstring[0])
continue;
Com_Printf ("pinging %s...\n", adrstring);
if (!NET_StringToAdr (adrstring, &adr))
{
Com_Printf ("Bad address: %s\n", adrstring);
continue;
}
if (!adr.port)
adr.port = BigShort(PORT_SERVER);
Netchan_OutOfBandPrint (NS_CLIENT, adr, va("info %i", PROTOCOL_VERSION));
}
}
/*
=================
CL_Skins_f
Load or download any custom player skins and models
=================
*/
void CL_Skins_f (void)
{
int i;
for (i=0 ; i<MAX_CLIENTS ; i++)
{
if (!cl.configstrings[CS_PLAYERSKINS+i][0])
continue;
Com_Printf ("client %i: %s\n", i, cl.configstrings[CS_PLAYERSKINS+i]);
SCR_UpdateScreen ();
Sys_SendKeyEvents (); // pump message loop
CL_ParseClientinfo (i);
}
}
/*
=================
CL_ConnectionlessPacket
Responses to broadcasts, etc
=================
*/
void CL_ConnectionlessPacket (void)
{
char *s;
char *c;
MSG_BeginReading (&net_message);
MSG_ReadLong (&net_message); // skip the -1
s = MSG_ReadStringLine (&net_message);
Cmd_TokenizeString (s, false);
c = Cmd_Argv(0);
Com_Printf ("%s: %s\n", NET_AdrToString (net_from), c);
// server connection
if (!strcmp(c, "client_connect"))
{
if (cls.state == ca_connected)
{
Com_Printf ("Dup connect received. Ignored.\n");
return;
}
Netchan_Setup (NS_CLIENT, &cls.netchan, net_from, cls.quakePort);
MSG_WriteChar (&cls.netchan.message, clc_stringcmd);
MSG_WriteString (&cls.netchan.message, "new");
cls.state = ca_connected;
return;
}
// server responding to a status broadcast
if (!strcmp(c, "info"))
{
CL_ParseStatusMessage ();
return;
}
// remote command from gui front end
if (!strcmp(c, "cmd"))
{
if (!NET_IsLocalAddress(net_from))
{
Com_Printf ("Command packet from remote host. Ignored.\n");
return;
}
Sys_AppActivate ();
s = MSG_ReadString (&net_message);
Cbuf_AddText (s);
Cbuf_AddText ("\n");
return;
}
// print command from somewhere
if (!strcmp(c, "print"))
{
s = MSG_ReadString (&net_message);
Com_Printf ("%s", s);
return;
}
// ping from somewhere
if (!strcmp(c, "ping"))
{
Netchan_OutOfBandPrint (NS_CLIENT, net_from, "ack");
return;
}
// challenge from the server we are connecting to
if (!strcmp(c, "challenge"))
{
cls.challenge = atoi(Cmd_Argv(1));
CL_SendConnectPacket ();
return;
}
// echo request from server
if (!strcmp(c, "echo"))
{
Netchan_OutOfBandPrint (NS_CLIENT, net_from, "%s", Cmd_Argv(1) );
return;
}
Com_Printf ("Unknown command.\n");
}
/*
=================
CL_DumpPackets
A vain attempt to help bad TCP stacks that cause problems
when they overflow
=================
*/
void CL_DumpPackets (void)
{
while (NET_GetPacket (NS_CLIENT, &net_from, &net_message))
{
Com_Printf ("dumnping a packet\n");
}
}
/*
=================
CL_ReadPackets
=================
*/
void CL_ReadPackets (void)
{
while (NET_GetPacket (NS_CLIENT, &net_from, &net_message))
{
// Com_Printf ("packet\n");
//
// remote command packet
//
if (*(int *)net_message.data == -1)
{
CL_ConnectionlessPacket ();
continue;
}
if (cls.state == ca_disconnected || cls.state == ca_connecting)
continue; // dump it if not connected
if (net_message.cursize < 8)
{
Com_Printf ("%s: Runt packet\n",NET_AdrToString(net_from));
continue;
}
//
// packet from server
//
if (!NET_CompareAdr (net_from, cls.netchan.remote_address))
{
Com_DPrintf ("%s:sequenced packet without connection\n"
,NET_AdrToString(net_from));
continue;
}
if (!Netchan_Process(&cls.netchan, &net_message))
continue; // wasn't accepted for some reason
CL_ParseServerMessage ();
}
//
// check timeout
//
if (cls.state >= ca_connected
&& cls.realtime - cls.netchan.last_received > cl_timeout->value*1000)
{
if (++cl.timeoutcount > 5) // timeoutcount saves debugger
{
Com_Printf ("\nServer connection timed out.\n");
CL_Disconnect ();
return;
}
}
else
cl.timeoutcount = 0;
}
//=============================================================================
/*
==============
CL_FixUpGender_f
==============
*/
void CL_FixUpGender(void)
{
char *p;
char sk[80];
if (gender_auto->value) {
if (gender->modified) {
// was set directly, don't override the user
gender->modified = false;
return;
}
strncpy(sk, skin->string, sizeof(sk) - 1);
if ((p = strchr(sk, '/')) != NULL)
*p = 0;
if (Q_stricmp(sk, "male") == 0 || Q_stricmp(sk, "cyborg") == 0)
Cvar_Set ("gender", "male");
else if (Q_stricmp(sk, "female") == 0 || Q_stricmp(sk, "crackhor") == 0)
Cvar_Set ("gender", "female");
else
Cvar_Set ("gender", "none");
gender->modified = false;
}
}
/*
==============
CL_Userinfo_f
==============
*/
void CL_Userinfo_f (void)
{
Com_Printf ("User info settings:\n");
Info_Print (Cvar_Userinfo());
}
/*
=================
CL_Snd_Restart_f
Restart the sound subsystem so it can pick up
new parameters and flush all sounds
=================
*/
void CL_Snd_Restart_f (void)
{
S_Shutdown ();
S_Init ();
CL_RegisterSounds ();
}
int precache_check; // for autodownload of precache items
int precache_spawncount;
int precache_tex;
int precache_model_skin;
byte *precache_model; // used for skin checking in alias models
#define PLAYER_MULT 5
// ENV_CNT is map load, ENV_CNT+1 is first env map
#define ENV_CNT (CS_PLAYERSKINS + MAX_CLIENTS * PLAYER_MULT)
#define TEXTURE_CNT (ENV_CNT+13)
static const char *env_suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"};
void CL_RequestNextDownload (void)
{
unsigned map_checksum; // for detecting cheater maps
char fn[MAX_OSPATH];
dmdl_t *pheader;
if (cls.state != ca_connected)
return;
if (!allow_download->value && precache_check < ENV_CNT)
precache_check = ENV_CNT;
//ZOID
if (precache_check == CS_MODELS) { // confirm map
precache_check = CS_MODELS+2; // 0 isn't used
if (allow_download_maps->value)
if (!CL_CheckOrDownloadFile(cl.configstrings[CS_MODELS+1]))
return; // started a download
}
if (precache_check >= CS_MODELS && precache_check < CS_MODELS+MAX_MODELS) {
if (allow_download_models->value) {
while (precache_check < CS_MODELS+MAX_MODELS &&
cl.configstrings[precache_check][0]) {
if (cl.configstrings[precache_check][0] == '*' ||
cl.configstrings[precache_check][0] == '#') {
precache_check++;
continue;
}
if (precache_model_skin == 0) {
if (!CL_CheckOrDownloadFile(cl.configstrings[precache_check])) {
precache_model_skin = 1;
return; // started a download
}
precache_model_skin = 1;
}
// checking for skins in the model
if (!precache_model) {
FS_LoadFile (cl.configstrings[precache_check], (void **)&precache_model);
if (!precache_model) {
precache_model_skin = 0;
precache_check++;
continue; // couldn't load it
}
if (LittleLong(*(unsigned *)precache_model) != IDALIASHEADER) {
// not an alias model
FS_FreeFile(precache_model);
precache_model = 0;
precache_model_skin = 0;
precache_check++;
continue;
}
pheader = (dmdl_t *)precache_model;
if (LittleLong (pheader->version) != ALIAS_VERSION) {
precache_check++;
precache_model_skin = 0;
continue; // couldn't load it
}
}
pheader = (dmdl_t *)precache_model;
while (precache_model_skin - 1 < LittleLong(pheader->num_skins)) {
if (!CL_CheckOrDownloadFile((char *)precache_model +
LittleLong(pheader->ofs_skins) +
(precache_model_skin - 1)*MAX_SKINNAME)) {
precache_model_skin++;
return; // started a download
}
precache_model_skin++;
}
if (precache_model) {
FS_FreeFile(precache_model);
precache_model = 0;
}
precache_model_skin = 0;
precache_check++;
}
}
precache_check = CS_SOUNDS;
}
if (precache_check >= CS_SOUNDS && precache_check < CS_SOUNDS+MAX_SOUNDS) {
if (allow_download_sounds->value) {
if (precache_check == CS_SOUNDS)
precache_check++; // zero is blank
while (precache_check < CS_SOUNDS+MAX_SOUNDS &&
cl.configstrings[precache_check][0]) {
if (cl.configstrings[precache_check][0] == '*') {
precache_check++;
continue;
}
Com_sprintf(fn, sizeof(fn), "sound/%s", cl.configstrings[precache_check++]);
if (!CL_CheckOrDownloadFile(fn))
return; // started a download
}
}
precache_check = CS_IMAGES;
}
if (precache_check >= CS_IMAGES && precache_check < CS_IMAGES+MAX_IMAGES) {
if (precache_check == CS_IMAGES)
precache_check++; // zero is blank
while (precache_check < CS_IMAGES+MAX_IMAGES &&
cl.configstrings[precache_check][0]) {
Com_sprintf(fn, sizeof(fn), "pics/%s.pcx", cl.configstrings[precache_check++]);
if (!CL_CheckOrDownloadFile(fn))
return; // started a download
}
precache_check = CS_PLAYERSKINS;
}
// skins are special, since a player has three things to download:
// model, weapon model and skin
// so precache_check is now *3
if (precache_check >= CS_PLAYERSKINS && precache_check < CS_PLAYERSKINS + MAX_CLIENTS * PLAYER_MULT) {
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -