⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cl_parse.pas

📁 雷神之锤2(Quake2)Delphi源码
💻 PAS
📖 第 1 页 / 共 2 页
字号:
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 + -