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

📄 sv_user.pas

📁 雷神之锤2(Quake2)Delphi源码
💻 PAS
📖 第 1 页 / 共 2 页
字号:
  sv_client^.downloadcount := sv_client^.downloadcount + r;
  size := sv_client^.downloadsize;
  if (size = 0) then
    size := 1;

  percent := (sv_client^.downloadcount * 100) div size;
  MSG_WriteByte(sv_client^.netchan.message, percent);
  SZ_Write(sv_client^.netchan.message, Pointer(Cardinal(sv_client^.download) + sv_client^.downloadcount - r), r);

  if (sv_client^.downloadcount <> sv_client^.downloadsize) then
    Exit;

  FS_FreeFile(sv_client^.download);
  sv_client^.download := nil;
end;

(* ==================
SV_BeginDownload_f
================== *)

procedure SV_BeginDownload_f;
var
  name: PChar;
  offset: Integer;
begin
  (*
  extern	cvar_t *allow_download;
  extern	cvar_t *allow_download_players;
  extern	cvar_t *allow_download_models;
  extern	cvar_t *allow_download_sounds;
  extern	cvar_t *allow_download_maps;
  extern	int		file_from_pak; // ZOID did file come from pak? *)
  offset := 0;

  name := Cmd_Argv(1);

  if (Cmd_Argc > 2) then
    offset := StrToInt(Cmd_Argv(2)); // downloaded offset

  { hacked by zoid to allow more conrol over download
    first off, no .. or global allow check }
  if (    (strstr (name, '..')<>nil)
          OR (NOT (allow_download.value<>0))
          // leading dot is no good
          OR (name^ = '.')
          // leading slash bad as well, must be in subdir
          OR (name^ = '/')
          // next up, skin check
          OR ((strncmp(name, 'players/', 6) = 0) AND (NOT (allow_download_players.value<>0)))
          // now models
          OR ((strncmp(name, 'models/', 6) = 0) AND (NOT (allow_download_models.value<>0)))
          // now sounds
          OR ((strncmp(name, 'sound/', 6) = 0) AND (NOT (allow_download_sounds.value<>0)))
          // now maps (note special case for maps, must not be in pak)
          OR ((strncmp(name, 'maps/', 6) = 0) AND (NOT (allow_download_maps.value<>0)))
          // MUST be in a subdirectory
          OR (strstr(name, '/')=nil)
          ) then
  begin	{ don't allow anything with .. path }
    MSG_WriteByte(sv_client^.netchan.message, Integer(svc_download));
    MSG_WriteShort(sv_client^.netchan.message, -1);
    MSG_WriteByte(sv_client^.netchan.message, 0);
    Exit;
  end;


  if (sv_client^.download <> nil) then
    FS_FreeFile(sv_client^.download);

  sv_client^.downloadsize := FS_LoadFile(name, @sv_client^.download);
  sv_client^.downloadcount := offset;

  if (offset > sv_client^.downloadsize) then
    sv_client^.downloadcount := sv_client^.downloadsize;

  if (NOT (sv_client^.download<>nil)
          // special check for maps, if it came from a pak file, don't allow
          // download  ZOID
          OR (strncmp(name, 'maps/', 5) = 0) AND (file_from_pak<>0)) then
  begin
    Com_DPrintf('Couldn''t download %s to %s'#10, [name, sv_client^.name]);
    if (sv_client^.download <> nil) then
    begin
      FS_FreeFile(sv_client^.download);
      sv_client^.download := nil;
    end;

    MSG_WriteByte(sv_client^.netchan.message, Integer(svc_download));
    MSG_WriteShort(sv_client^.netchan.message, -1);
    MSG_WriteByte(sv_client^.netchan.message, 0);
    Exit;
  end;

  SV_NextDownload_f;
  Com_DPrintf('Downloading %s to %s'#10, [name, sv_client^.name]);
end;

(* =================
SV_Disconnect_f

The client is going to disconnect, so remove the connection immediately
================= *)
procedure SV_Disconnect_f;
begin
//	SV_EndRedirect ();
  SV_DropClient(sv_client);
end;

(* ==================
SV_ShowServerinfo_f

Dumps the serverinfo info string
================== *)
procedure SV_ShowServerinfo_f;
begin
  Info_Print(Cvar_Serverinfo_);
end;

procedure SV_Nextserver;
var
  v: PChar;
begin
  //ZOID, ss_pic can be nextserver'd in coop mode
  if (sv.state = ss_game) OR ((sv.state = ss_pic) AND (NOT (Cvar_VariableValue('coop')<>0))) then
    Exit;  // can't nextserver while playing a normal game

  Inc(svs.spawncount);	// make sure another doesn't sneak in
  v := Cvar_VariableString('nextserver');
  if (v[0] = #0) then
    Cbuf_AddText('killserver'#10)
  else
  begin
    Cbuf_AddText(v);
    Cbuf_AddText(#10);
  end;
  Cvar_Set('nextserver','');
end;

(* ==================
SV_Nextserver_f

A cinematic has completed or been aborted by a client, so move
to the next server,
================== *)
procedure SV_Nextserver_f;
begin
  if (StrToInt(Cmd_Argv(1)) <> svs.spawncount) then
  begin
    Com_DPrintf('Nextserver() from wrong level, from %s'#10, [sv_client^.name]);
    Exit;  // leftover from last server
  end;

  Com_DPrintf('Nextserver() from %s'#10, [sv_client^.name]);

  SV_Nextserver;
end;

(* ==================
SV_ExecuteUserCommand
================== *)
procedure SV_ExecuteUserCommand(s: PChar);
var
  i: Integer;
begin
  Cmd_TokenizeString(s, true);
  sv_player := sv_client^.edict;

//  SV_BeginRedirect (RD_CLIENT);

  i := 0;
  while (ucmds[i].name <> nil) do
  begin
    if (strcmp(Cmd_Argv(0), ucmds[i].name) = 0) then
    begin
      ucmds[i].func;
      Exit;
    end;
    Inc(i);
  end;

  if ((ucmds[i].name = nil) AND (sv.state = ss_game)) then
    ge^.ClientCommand(sv_player);

//  SV_EndRedirect ();
end;

(* ===========================================================================

USER CMD EXECUTION

=========================================================================== *)

procedure SV_ClientThink(cl: client_p; cmd: usercmd_p);
begin
  cl^.commandMsec := (cl^.commandMsec - cmd.msec);

  if (cl^.commandMsec < 0) AND (sv_enforcetime^.value<>0) then
  begin
    Com_DPrintf('commandMsec underflow from %s'#10, [cl^.name]);
    Exit;
  end;

  ge^.ClientThink(cl^.edict, cmd);
end;

(* ===================
SV_ExecuteClientMessage

The current net_message is parsed for the given client
=================== *)
procedure SV_ExecuteClientMessage(cl: client_p);
var
  c, net_drop, stringCmdCount, checksum, calculatedChecksum, checksumIndex,
  lastframe: Integer;
  s: PChar;
  nullcmd, oldest, oldcmd, newcmd: usercmd_t;
  move_issued: qboolean;
begin
  sv_client := cl;
  sv_player := sv_client^.edict;

  // only allow one move command
  move_issued := false;
  stringCmdCount := 0;

  while (True) do
  begin
    if (net_message.readcount > net_message.cursize) then
    begin
      Com_Printf('SV_ReadClientMessage: badread'#10, []);
      SV_DropClient(cl);
      Exit;
    end;

    c := MSG_ReadByte(net_message);
    if (c = -1) then
      Break;

    case clc_ops_e(c) of
      clc_nop:;

      clc_userinfo:  begin
        strncpy(cl^.userinfo, MSG_ReadString(net_message), (SizeOf(cl^.userinfo) - 1));
        SV_UserinfoChanged(cl);
      end;

      clc_move:  begin
        if (move_issued) then
          Exit;		{ someone is trying to cheat... }

        move_issued := true;
        checksumIndex := net_message.readcount;
        checksum := MSG_ReadByte(net_message);
        lastframe := MSG_ReadLong(net_message);
        if (lastframe <> cl^.lastframe) then
        begin
          cl^.lastframe := lastframe;
          if (cl^.lastframe > 0) then
          begin
            cl^.frame_latency[cl^.lastframe AND (LATENCY_COUNTS-1)] :=
              svs.realtime - cl^.frames[cl^.lastframe AND UPDATE_MASK].senttime;
          end;
        end;

        FillChar(nullcmd, SizeOf(nullcmd), 0);
        MSG_ReadDeltaUsercmd(net_message, nullcmd, oldest);
        MSG_ReadDeltaUsercmd(net_message, oldest, oldcmd);
        MSG_ReadDeltaUsercmd(net_message, oldcmd, newcmd);

        if (cl^.state <> cs_spawned) then
        begin
          cl^.lastframe := -1;
          Break;
        end;

        { if the checksum fails, ignore the rest of the packet }
        calculatedChecksum := COM_BlockSequenceCRCByte(
          Pointer(Cardinal(net_message.data) + checksumIndex + 1),
          net_message.readcount - checksumIndex - 1,
          cl.netchan.incoming_sequence);

        if (calculatedChecksum <> checksum) then
        begin
          Com_DPrintf('Failed command checksum for %s (%d != %d)/%d'#10,
            [cl.name, calculatedChecksum, checksum,
            cl.netchan.incoming_sequence]);
          Exit;
        end;

        if (sv_paused.value = 0) then
        begin
          net_drop := cl.netchan.dropped;
          if (net_drop < 20) then
          begin
//if (net_drop > 2)

//	Com_Printf ("drop %d\n", net_drop);
            while (net_drop > 2) do
            begin
              SV_ClientThink(cl, @cl.lastcmd);

              Dec(net_drop);
            end;

            if (net_drop > 1) then
              SV_ClientThink(cl, @oldest);

            if (net_drop > 0) then
              SV_ClientThink(cl, @oldcmd);

          end;
          SV_ClientThink(cl, @newcmd);
        end;

        cl.lastcmd := newcmd;
      end;

      clc_stringcmd:  begin
        s := MSG_ReadString(net_message);

        { malicious users may try using too many string commands }
        Inc(stringCmdCount);
        if (stringCmdCount < MAX_STRINGCMDS) then
          SV_ExecuteUserCommand(s);

        if (cl^.state = cs_zombie) then
          Exit;	{ disconnect command }

      end;
    else
      Com_Printf('SV_ReadClientMessage: unknown command char'#10, []);
      SV_DropClient(cl);
      Exit;
    end;
  end;
end;




end.

⌨️ 快捷键说明

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