📄 cl_main.pas
字号:
end;
Netchan_Setup (NS_CLIENT, @cls.netchan, net_from, cls.quakePort);
MSG_WriteChar (cls.netchan.message, Byte(clc_stringcmd));
MSG_WriteString (cls.netchan.message, 'new');
cls.state := ca_connected;
exit;
end;
// server responding to a status broadcast
if (strcmp(c, 'info') = 0) then begin
CL_ParseStatusMessage ();
exit;
end;
// remote command from gui front end
if (strcmp(c, 'cmd') = 0) then begin
if (not NET_IsLocalAddress(net_from)) then begin
Com_Printf ('Command packet from remote host. Ignored.'#10);
exit;
end;
Sys_AppActivate ();
s := MSG_ReadString (net_message);
Cbuf_AddText (s);
Cbuf_AddText (#10);
exit;
end;
// print command from somewhere
if (strcmp(c, 'print') = 0) then begin
s := MSG_ReadString (net_message);
Com_Printf ('%s', [s]);
exit;
end;
// ping from somewhere
if (strcmp(c, 'ping') = 0) then begin
Netchan_OutOfBandPrint (NS_CLIENT, net_from, 'ack', []);
exit;
end;
// challenge from the server we are connecting to
if (strcmp(c, 'challenge') = 0) then begin
cls.challenge := StrToInt(Cmd_Argv(1));
CL_SendConnectPacket ();
exit;
end;
// echo request from server
if (strcmp(c, 'echo') = 0) then begin
Netchan_OutOfBandPrint (NS_CLIENT, net_from, '%s', [Cmd_Argv(1)] );
exit;
end;
Com_Printf ('Unknown command.'#10);
end;
(*
=================
CL_DumpPackets
A vain attempt to help bad TCP stacks that cause problems
when they overflow
=================
*)
procedure CL_DumpPackets;
begin
while (NET_GetPacket (NS_CLIENT, net_from, net_message)) do begin
Com_Printf ('dumping a packet'#10);
end;
end;
(*
=================
CL_ReadPackets
=================
*)
procedure CL_ReadPackets;
begin
while (NET_GetPacket (NS_CLIENT, net_from, net_message)) do begin
// Com_Printf ("packet"#10);
//
// remote command packet
//
if (PInteger(net_message.data)^ = -1) then begin
CL_ConnectionlessPacket ();
continue;
end;
if (cls.state = ca_disconnected) or (cls.state = ca_connecting) then
continue; // dump it if not connected
if (net_message.cursize < 8) then begin
Com_Printf ('%s: Runt packet'#10, [NET_AdrToString(net_from)]);
continue;
end;
//
// packet from server
//
if (not NET_CompareAdr (net_from, cls.netchan.remote_address)) then begin
Com_DPrintf ('%s:sequenced packet without connection'#10
,[NET_AdrToString(net_from)]);
continue;
end;
if (not Netchan_Process(cls.netchan, net_message)) then
continue; // wasn't accepted for some reason
CL_ParseServerMessage ();
end;
//
// check timeout
//
if (cls.state >= ca_connected) and
(cls.realtime - cls.netchan.last_received > cl_timeout.value*1000) then begin
Inc(cl.timeoutcount);
if (cl.timeoutcount > 5) then begin// timeoutcount saves debugger
Com_Printf (#10'Server connection timed out.'#10);
CL_Disconnect ();
exit;
end;
end
else
cl.timeoutcount := 0;
end;
//=============================================================================
(*
==============
CL_FixUpGender_f
==============
*)
procedure CL_FixUpGender;
var
p: pchar;
sk: array[0..80-1] of char;
begin
if (gender_auto.value<>0)then begin
if (gender.modified) then begin
// was set directly, don't override the user
gender.modified := false;
exit;
end;
strncpy(sk, skin.string_, sizeof(sk) - 1);
p := strchr(sk, Byte('/'));
if (p <> nil) then
p^ := #0;
if (Q_stricmp(sk, 'male') = 0) or (Q_stricmp(sk, 'cyborg') = 0) then
Cvar_Set ('gender', 'male')
else if (Q_stricmp(sk, 'female') = 0) or (Q_stricmp(sk, 'crackhor') = 0) then
Cvar_Set ('gender', 'female')
else
Cvar_Set ('gender', 'none');
gender.modified := false;
end;
end;
(*
==============
CL_Userinfo_f
==============
*)
procedure CL_Userinfo_f; cdecl;
begin
Com_Printf ('User info settings:'#10);
Info_Print (Cvar_Userinfo_());
end;
(*
=================
CL_Snd_Restart_f
Restart the sound subsystem so it can pick up
new parameters and flush all sounds
=================
*)
procedure CL_Snd_Restart_f; cdecl;
begin
S_Shutdown ();
S_Init ();
CL_RegisterSounds ();
end;
var
precache_check, // for autodownload of precache items
precache_spawncount,
precache_tex,
precache_model_skin: integer;
precache_model: PByte; // used for skin checking in alias models
const
PLAYER_MULT = 5;
// ENV_CNT is map load, ENV_CNT+1 is first env map
ENV_CNT = (CS_PLAYERSKINS + MAX_CLIENTS * PLAYER_MULT);
TEXTURE_CNT = (ENV_CNT+13);
var
env_suf: array[0..5] of pchar = ('rt', 'bk', 'lf', 'ft', 'up', 'dn');
procedure CL_RequestNextDownload;
var
map_checksum: Cardinal; // for detecting cheater maps
fn: array[0..MAX_OSPATH-1] of char;
pheader: dmdl_p;
i, n: integer;
model, skin: array[0..MAX_QPATH-1] of char;
p: pchar;
begin
if (cls.state <> ca_connected) then
exit;
if (allow_download.value=0) and (precache_check < ENV_CNT) then
precache_check := ENV_CNT;
//ZOID
if (precache_check = CS_MODELS) then begin // confirm map
precache_check := CS_MODELS+2; // 0 isn't used
if (allow_download_maps.value<>0) then
if (not CL_CheckOrDownloadFile(cl.configstrings[CS_MODELS+1])) then
exit; // started a download
end;
if (precache_check >= CS_MODELS) and (precache_check < CS_MODELS+MAX_MODELS) then begin
if (allow_download_models.value<>0) then begin
while (precache_check < CS_MODELS+MAX_MODELS) and
(cl.configstrings[precache_check][0]<>#0) do begin
if (cl.configstrings[precache_check][0] = '*') or
(cl.configstrings[precache_check][0] = '#') then begin
Inc(precache_check);
continue;
end;
if (precache_model_skin = 0) then begin
if (not CL_CheckOrDownloadFile(cl.configstrings[precache_check])) then begin
precache_model_skin := 1;
exit; // started a download
end;
precache_model_skin := 1;
end;
// checking for skins in the model
if (precache_model = nil) then begin
FS_LoadFile (cl.configstrings[precache_check], @precache_model);
if (precache_model = nil) then begin
precache_model_skin := 0;
Inc(precache_check);
continue; // couldn't load it
end;
if (LittleLong(PCardinal(precache_model)^) <> IDALIASHEADER) then begin
// not an alias model
FS_FreeFile(precache_model);
precache_model := nil;
precache_model_skin := 0;
Inc(precache_check);
continue;
end;
pheader := dmdl_p(precache_model);
if (LittleLong (pheader.version) <> ALIAS_VERSION) then begin
Inc(precache_check);
precache_model_skin := 0;
continue; // couldn't load it
end;
end;
pheader := dmdl_p(precache_model);
while (precache_model_skin - 1 < LittleLong(pheader.num_skins)) do begin
if (not CL_CheckOrDownloadFile(Pointer(Cardinal(precache_model) +
LittleLong(pheader.ofs_skins) +
(precache_model_skin - 1)*MAX_SKINNAME))) then begin
Inc(precache_model_skin);
exit; // started a download
end;
Inc(precache_model_skin);
end;
if (precache_model <> nil) then begin
FS_FreeFile(precache_model);
precache_model := nil;
end;
precache_model_skin := 0;
Inc(precache_check);
end;
end;
precache_check := CS_SOUNDS;
end;
if (precache_check >= CS_SOUNDS) and (precache_check < CS_SOUNDS+MAX_SOUNDS) then begin
if (allow_download_sounds.value<>0) then begin
if (precache_check = CS_SOUNDS) then
Inc(precache_check); // zero is blank
while (precache_check < CS_SOUNDS+MAX_SOUNDS) and
(cl.configstrings[precache_check][0] <> #0) do begin
if (cl.configstrings[precache_check][0] = '*') then begin
Inc(precache_check);
continue;
end;
Com_sprintf(fn, sizeof(fn), 'sound/%s', [cl.configstrings[precache_check]]);
Inc(precache_check);
if (not CL_CheckOrDownloadFile(fn)) then
exit; // started a download
end;
end;
precache_check := CS_IMAGES;
end;
if (precache_check >= CS_IMAGES) and (precache_check < CS_IMAGES+MAX_IMAGES) then begin
if (precache_check = CS_IMAGES) then
Inc(precache_check); // zero is blank
while (precache_check < CS_IMAGES+MAX_IMAGES) and
(cl.configstrings[precache_check][0]<>#0) do begin
Com_sprintf(fn, sizeof(fn), 'pics/%s.pcx', [cl.configstrings[precache_check]]);
Inc(precache_check);
if (not CL_CheckOrDownloadFile(fn)) then
exit; // started a download
end;
precache_check := CS_PLAYERSKINS;
end;
// 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) and (precache_check < CS_PLAYERSKINS + MAX_CLIENTS * PLAYER_MULT) then begin
if (allow_download_players.value<>0) then begin
while (precache_check < CS_PLAYERSKINS + MAX_CLIENTS * PLAYER_MULT) do begin
i := (precache_check - CS_PLAYERSKINS) div PLAYER_MULT;
n := (precache_check - CS_PLAYERSKINS) mod PLAYER_MULT;
if (cl.configstrings[CS_PLAYERSKINS+i][0] = #0) then begin
precache_check := CS_PLAYERSKINS + (i + 1) * PLAYER_MULT;
continue;
end;
p := strchr(cl.configstrings[CS_PLAYERSKINS+i], Byte('\'));
if (p <> nil) then
Inc(p)
else
p := cl.configstrings[CS_PLAYERSKINS+i];
strcpy(model, p);
p := strchr(model, Byte('/'));
if (p = nil) then
p := strchr(model, Byte('\'));
if (p <> nil) then begin
p := #0;
inc(p);
strcpy(skin, p);
end else
skin := #0;
if (n=0) then begin // model
Com_sprintf(fn, sizeof(fn), 'players/%s/tris.md2', [model]);
if (not CL_CheckOrDownloadFile(fn)) then begin
precache_check := CS_PLAYERSKINS + i * PLAYER_MULT + 1;
exit; // started a download
end;
Inc(n);
(*FALL THROUGH*)
end;
if (n=1) then begin // weapon model
Com_sprintf(fn, sizeof(fn), 'players/%s/weapon.md2', [model]);
if (not CL_CheckOrDownloadFile(fn)) then begin
precache_check := CS_PLAYERSKINS + i * PLAYER_MULT + 2;
exit; // started a download
end;
Inc(n);
(*FALL THROUGH*)
end;
if (n=2) then begin // weapon skin
Com_sprintf(fn, sizeof(fn), 'players/%s/weapon.pcx', [model]);
if (not CL_CheckOrDownloadFile(fn)) then begin
precache_check := CS_PLAYERSKINS + i * PLAYER_MULT + 3;
exit; // started a download
end;
Inc(n);
(*FALL THROUGH*)
end;
if (n=3) then begin // skin
Com_sprintf(fn, sizeof(fn), 'players/%s/%s.pcx', [model, skin]);
if (not CL_CheckOrDownloadFile(fn)) then begin
precache_check := CS_PLAYERSKINS + i * PLAYER_MULT + 4;
exit; // started a download
end;
Inc(n);
(*FALL THROUGH*)
end;
if (N=4) then begin // skin_i
Com_sprintf(fn, sizeof(fn), 'players/%s/%s_i.pcx', [model, skin]);
if (not CL_CheckOrDownloadFile(fn)) then begin
precache_check := CS_PLAYERSKINS + i * PLAYER_MULT + 5;
exit; // started a download
end;
// move on to next model
precache_check := CS_PLAYERSKINS + (i + 1) * PLAYER_MULT;
end;
end;
end;
// precache phase completed
precache_check := ENV_CNT;
end;
if (precache_check = ENV_CNT) then begin
precache_check := ENV_CNT + 1;
CM_LoadMap (cl.configstrings[CS_MODELS+1], true, map_checksum);
// Note : map_checksum has been typecasted to Integer in the conversion - by burnin
if (Integer(map_checksum) <> StrToInt(cl.configstrings[CS_MAPCHECKSUM])) then begin
Com_Error (ERR_DROP, 'Local map version differs from server: %d != ''%s'''#10,
[map_checksum, cl.configstrings[CS_MAPCHECKSUM]]);
exit;
end;
end;
if (precache_check > ENV_CNT) and (precache_check < TEXTURE_CNT) then begin
if (allow_download.value<>0) and (allow_download_maps.value<>0) then begin
while (precache_check < TEXTURE_CNT) do begin
n := precache_check - ENV_CNT - 1;
Inc(precache_check);
if (n and 1<>0) then
Com_sprintf(fn, sizeof(fn), 'env/%s%s.pcx',
[cl.configstrings[CS_SKY], env_suf[n div 2]])
else
Com_sprintf(fn, sizeof(fn), 'env/%s%s.tga',
[cl.configstrings[CS_SKY], env_suf[n div 2]]);
if (not CL_CheckOrDownloadFile(fn)) then
exit; // started a download
end;
end;
precache_check := TEXTURE_CNT;
end;
if (precache_check = TEXTURE_CNT) then begin
precache_check := TEXTURE_CNT+1;
precache_tex := 0;
end;
// confirm existance of textures, download any that don't exist
if (precache_check = TEXTURE_CNT+1) then begin
if (allow_download.value<>0) and (allow_download_maps.value<>0) then begin
while (precache_tex < numtexinfo) do begin
Com_sprintf(fn, sizeof(fn), 'textures/%s.wal', [map_surfaces[precache_tex].rname]);
Inc(precache_tex);
if (not CL_CheckOrDownloadFile(fn)) then
exit; // started a download
end;
end;
precache_check := TEXTURE_CNT+999;
end;
//ZOID
CL_RegisterSounds ();
CL_PrepRefresh ();
MSG_WriteByte (cls.netchan.message, Byte(clc_stringcmd));
MSG_WriteString (cls.netchan.message, va('begin %d'#10, [precache_spawncount]) );
end;
(*
=================
CL_Precache_f
The server will send this command right
before allowing the client into the server
=================
*)
procedure CL_Precache_f; cdecl;
var
map_checksum: Cardinal; // for detecting cheater maps
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -