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

📄 cl_parse.pas

📁 delphi编的不错的贪吃蛇
💻 PAS
📖 第 1 页 / 共 2 页
字号:
{$ALIGN ON}{$MINENUMSIZE 4}
{----------------------------------------------------------------------------}
{                                                                            }
{ File(s): cl_parse                                                          }
{ Content: parse a message received from the server                          }
{                                                                            }
{ Initial conversion by : Ter Roshak                                         }
{ Initial conversion on : -                                                  }
{                                                                            }
{ This File contains part of convertion of Quake2 source to ObjectPascal.    }
{ More information about this project can be found at:                       }
{ http://www.sulaco.co.za/quake2/                                            }
{                                                                            }
{ 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.                       }
{                                                                            }
{----------------------------------------------------------------------------}
// cl_parse.c  -- parse a message received from the server
unit cl_parse;

interface

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,
  {$IFDEF WIN32}
  cd_win,
  sys_win,
  vid_dll,
  {$ELSE}
  cd_sdl,
  sys_linux,
  vid_so,
  {$ENDIF}
  net_chan,
  SysUtils,
  snd_dma,
  Files,
  Common,
  Cmd,
  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
  {
    Com_Printf (".");
    if (10*(percent/10) != cls.downloadpercent)
    begin
     cls.downloadpercent = 10*(percent/10);
     Com_Printf ("%i%%", cls.downloadpercent);
      end;
  }
    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
  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^ <> #0) and ((fs_gamedirvar^.string_ = nil) or (fs_gamedirvar^.string_^ = #0) or (strcmp(fs_gamedirvar^.string_, str) <> 0)) or
    ((str^ = #0) and ((fs_gamedirvar^.string_ <> nil) or (fs_gamedirvar^.string_^ <> #0)))) 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
==================
*}
procedure CL_ParseBaseline();
var
  es: entity_state_p;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -