📄 cl_parse.pas
字号:
unit cl_parse;
interface
{
---
cl_parse.pas converted from cl_parse.c by Ter Roshak
All MY comments begin with TER:
all other comments are ORIGINAL comments!
Tools used : Delphi 6 (unit checks),
Maybe someone can recheck this file for errors or advantages using the pchar vars! :)
---
ToDo : - Make a nicer conversion of sscanf();
- Make compatible with delphi versions 3,4,5
}
{
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
uses
q_shared,
client;
const
svc_strings: array [0..255] of PChar =
(
'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',
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil
);
procedure CL_ParseClientinfo (player: Integer);
procedure CL_LoadClientinfo (ci: clientinfo_p; s: pchar);
procedure CL_ParseServerMessage ();
procedure CL_RegisterSounds ();
function CL_CheckOrDownloadFile(filename : pchar): qboolean;
procedure CL_Download_f (); cdecl;
procedure SHOWNET(s: pchar);
implementation
uses
cl_inv,
cl_cin,
cl_main,
cl_tent,
cl_ents,
cl_view,
cl_fx,
cl_scrn,
cd_win,
net_chan,
sys_win,
SysUtils,
snd_dma,
Files,
Common,
Cmd,
vid_dll,
Console,
CModel,
CVar,
CPas;
//=============================================================================
procedure CL_DownloadFileName(dest : pchar; destlen : integer; fn : pchar);
begin
if strncmp(fn, 'players', 7) = 0 then
Com_sprintf (dest, destlen, '%s/%s', [BASEDIRNAME, fn])
else
Com_sprintf (dest, destlen, '%s/%s', [FS_Gamedir(), fn]);
end;
(*
===============
CL_CheckOrDownloadFile
Returns true if the file exists, otherwise it attempts
to start a download from the server.
===============
*)
function CL_CheckOrDownloadFile(filename : pchar): qboolean;
var
fp: integer;
name: array[0..MAX_OSPATH-1] of char;
len: Integer;
begin
if (strstr (filename, '..') <> nil) then
begin
Com_Printf ('Refusing to download a path with ..'#10, []);
Result := True;
exit;
end;
if (FS_LoadFile (filename, nil) <> -1) then begin
// it exists, no need to download
Result := True;
exit;
end;
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 := FileOpen (name, fmOpenReadWrite);
if (fp<>-1) then begin // it exists
len := FileSeek(fp, 0, 2);
cls.download := fp;
// give the server an offset to start the download
Com_Printf ('Resuming %s'#10, [cls.downloadname]);
MSG_WriteByte (cls.netchan.message, Integer(clc_stringcmd));
MSG_WriteString (cls.netchan.message,
va('download %s %d', [cls.downloadname, len]));
end else begin
Com_Printf ('Downloading %s'#10, [cls.downloadname]);
MSG_WriteByte (cls.netchan.message, Integer(clc_stringcmd));
MSG_WriteString (cls.netchan.message,
va('download %s', [cls.downloadname]));
end;
Inc(cls.downloadnumber);
Result := false;
end;
(*
===============
CL_Download_f
Request a download from the server
===============
*)
procedure CL_Download_f ();
var
filename: array[0..MAX_OSPATH-1] of char;
begin
if (Cmd_Argc() <> 2) then begin
Com_Printf('Usage: download <filename>'#10);
exit;
end;
Com_sprintf(filename, sizeof(filename), '%s', [Cmd_Argv(1)]);
if (strstr (filename, '..') <> nil) then begin
Com_Printf ('Refusing to download a path with ..'#10);
exit;
end;
if (FS_LoadFile (filename, nil) <> -1) then begin
// it exists, no need to download
Com_Printf('File already exists.'#10);
exit;
end;
strcpy (cls.downloadname, filename);
Com_Printf ('Downloading %s'#10, [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, Integer(clc_stringcmd));
MSG_WriteString (cls.netchan.message,
va('download %s', [cls.downloadname]));
Inc(cls.downloadnumber);
end;
(*
======================
CL_RegisterSounds
======================
*)
procedure CL_RegisterSounds ();
var
i: integer;
begin
S_BeginRegistration ();
CL_RegisterTEntSounds ();
for i := 1 to MAX_SOUNDS-1 do begin
if (cl.configstrings[CS_SOUNDS+i][0] = #0) then
break;
cl.sound_precache[i] := S_RegisterSound (cl.configstrings[CS_SOUNDS+i]);
Sys_SendKeyEvents (); // pump message loop
end;
S_EndRegistration ();
end;
(*
=====================
CL_ParseDownload
A download message has been received from the server
=====================
*)
procedure CL_ParseDownload ();
var
size, percent: Integer;
name: array[0..MAX_OSPATH-1] of char;
r: boolean;
oldn: array[0..MAX_OSPATH-1] of char;
newn: array[0..MAX_OSPATH-1] of char;
begin
// read the data
size := MSG_ReadShort (net_message);
percent := MSG_ReadByte (net_message);
if (size = -1) then begin
Com_Printf ('Server does not have this file.'#10);
if (cls.download > 0) then begin
// if here, we tried to resume a file but the server said no
FileClose (cls.download);
cls.download := 0;
end;
CL_RequestNextDownload ();
exit;
end;
// open the file if not opened yet
if (cls.download <= 0) then begin
CL_DownloadFileName(name, sizeof(name), cls.downloadtempname);
FS_CreatePath (name);
cls.download := FileOpen (name, fmOpenReadWrite);
if (cls.download = -1) then begin
net_message.readcount := net_message.readcount + size;
Com_Printf ('Failed to open %s'#10, [cls.downloadtempname]);
CL_RequestNextDownload ();
cls.download := 0;
exit;
end;
end;
FileWrite (cls.download, Pointer(Cardinal(net_message.data) + net_message.readcount)^, size);
net_message.readcount := net_message.readcount + size;
if (percent <> 100) then begin
// request next block
// change display routines by zoid
{$IFDEF neverever}
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, Integer(clc_stringcmd));
SZ_Print (cls.netchan.message, 'nextdl');
end
else
begin
// Com_Printf ("100%%\n");
FileClose (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 := renamefile (oldn, newn);
if (not r) then
Com_Printf ('failed to rename.'#10);
cls.download := 0;
cls.downloadpercent := 0;
// get another file if needed
CL_RequestNextDownload ();
end;
end;
(*
=====================================================================
SERVER CONNECTING MESSAGES
=====================================================================
*)
(*
==================
CL_ParseServerData
==================
*)
procedure CL_ParseServerData ();
var
//extern cvar_t *fs_gamedirvar;
str: PChar;
i: Integer;
begin
Com_DPrintf ('Serverdata packet received.'#10);
//
// 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()<>0) and (PROTOCOL_VERSION = 34) then begin
end
else if (i <> PROTOCOL_VERSION) then
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) <> 0;
// game directory
str := MSG_ReadString (net_message);
strncpy (cl.gamedir, str, sizeof(cl.gamedir)-1);
// set gamedir
if ((str<>nil) and ((fs_gamedirvar^.string_ = nil) or (fs_gamedirvar^.string_=#0) or (strcmp(fs_gamedirvar^.string_, str)<>0)) or
((str = nil) and ((fs_gamedirvar^.string_ <> nil) or (fs_gamedirvar^.string_<>nil)))) then
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) then begin
// playing a cinematic or showing a pic, not a level
SCR_PlayCinematic (str);
end
else
begin
// seperate the printfs so the server message can have a color
Com_Printf(#10#10#29#30#30#30#30#30#30#30#30#30#30#30#30#30#30#30#30#30#30#30#30#30#30#30#30#30#30#30#30#30#30#30#30#30#30#30#31#10#10);
Com_Printf ('%s%s'#10, [#2, str]);
// need to prep refresh at next oportunity
cl.refresh_prepped := false;
end;
end;
(*
==================
CL_ParseBaseline
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -