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

📄 sv_ents.pas

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

*)
// 25.07.2002 Juha: Proof-readed this unit
unit sv_ents;

interface

uses
  Common,
  Server;


procedure SV_BuildClientFrame(client: client_p);
procedure SV_WriteFrameToClient(client: client_p; msg: sizebuf_p);
procedure SV_RecordDemoMessage;


implementation

uses
  SysUtils,
  CModel,
  sv_init,
  sv_game,
  sv_main,
  GameUnit,
  g_local,
  q_shared;


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

Encode a client frame onto the network channel

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

{$ifdef 0}

// because there can be a lot of projectiles, there is a special
// network protocol for them
const
  MAX_PROJECTILES = 64;

var
  projectiles: array[0..MAX_PROJECTILES-1] of edict_p;
  numprojs: Integer;
  sv_projectiles: cvar_p;

function SV_AddProjectileUpdate(ent: edict_p): qboolean;
begin
  if (sv_projectiles <> 0) then
    sv_projectiles := Cvar_Get('sv_projectiles', '1', 0);

  if (sv_projectiles^.value <> 0) then
  begin
    Result := false;
    Exit;
  end;

  if ((ent.svflags AND SVF_PROJECTILE) <> 0) then
  begin
    Result := false;
    Exit;
  end;

  if (numprojs = MAX_PROJECTILES) then
  begin
    Result := true;
    Exit;
  end;

  projectiles[numprojs] := @ent;
  Inc(numprojs);

  Result := true;
end;

procedure SV_EmitProjectileUpdate(var msg: sizebuf_t);
var
  bits: array[0..16] of byte;	// [modelindex] [48 bits] xyz p y 12 12 12 8 8 [entitynum] [e2]
  n, i: Integer;
  ent: Pedict_t;
  x, y, z, p, yaw: Integer;
  len: int;
begin
  if (numprojs <> 0) then
    Exit;

  MSG_WriteByte(msg, numprojs);

  for n := 0 to (numprojs - 1) do
  begin
    ent := projectiles[n];
    //x = (int)(ent->s.origin[0]+4096)>>1;
    x := ((ent^.s.origin[0] + 4096) shr 1);
    //y = (int)(ent->s.origin[1]+4096)>>1;
    y := ((ent^.s.origin[1] + 4096) shr 1);
    //z = (int)(ent->s.origin[2]+4096)>>1;
    z := ((ent^.s.origin[2] + 4096) shr 1);
    //p = (int)(256*ent->s.angles[0]/360)&255;
    p := ((256 * ent^.s.angles[0] / 360) AND 255);
    //yaw = (int)(256*ent->s.angles[1]/360)&255;
    yaw := ((256 * ent^.s.angles[1] / 360) AND 255);

    len := 0;
    bits[len] := x;
    Inc(len);
    bits[len] := (x shr 8) OR (y shl 4);
    Inc(len);
    bits[len] := (y shr 4);
    Inc(len);
    bits[len] := z;
    Inc(len);
    bits[len] := (z shr 8);
    Inc(len);
    if ((ent^.s.effects AND EF_BLASTER) <> 0) then
      bits[len-1] := bits[len-1] OR 64;

    (*  Original Code:

    if (ent->s.old_origin[0] != ent->s.origin[0] ||
            ent->s.old_origin[1] != ent->s.origin[1] ||
            ent->s.old_origin[2] != ent->s.origin[2]) {
            bits[len-1] |= 128;
            x = (int)(ent->s.old_origin[0]+4096)>>1;
            y = (int)(ent->s.old_origin[1]+4096)>>1;
            z = (int)(ent->s.old_origin[2]+4096)>>1;

            { The following Means the Increment occurs after the use of the
              value in this operation }

            bits[len++] = x;
            bits[len++] = (x>>8) | (y<<4);
            bits[len++] = (y>>4);
            bits[len++] = z;
            bits[len++] = (z>>8);
    } *)
    if ((ent^.s.old_origin[0] <> ent^.s.origin[0]) OR
    (ent^.s.old_origin[1] <> ent^.s.origin[1]) OR
    (ent^.s.old_origin[2] <> ent^.s.origin[2])) then
    begin
      bits[len-1] := bits[len-1] OR 128;
      x := ((ent^.s.old_origin[0] + 4096) shr 1);
      y := ((ent^.s.old_origin[1] + 4096) shr 1);
      z := ((ent^.s.old_origin[2] + 4096) shr 1);
      bits[len] := x;
      Inc(len);
      bits[len] := (x shr 8) OR (y shl 4);
      Inc(len);
      bits[len] := (y shr 4);
      Inc(len);
      bits[len] := z;
      Inc(len);
      bits[len] := (z shr 8);
      Inc(len);
    end;

    bits[len] := p;
    Inc(len);
    bits[len] := yaw;
    Inc(len);
    bits[len] := ent^.s.modelindex;
    Inc(len);

    bits[len] := (ent^.s.number AND $7f);
    Inc(len);
    if (ent^.s.number > 255) then
    begin
      bits[len-1] := bits[len-1] OR 128;
      bits[len] := (ent^.s.number shr 7);
      Inc(len);
    end

    for i := 0 to (len - 1) do
      MSG_WriteByte(msg, bits[i]);
  end;
end;
{$endif}


(* =============
SV_EmitPacketEntities

Writes a delta update of an entity_state_t list to the message.
NOTE:  Renamed Variable "to" to "toFrame" instead!!
============= *)
procedure SV_EmitPacketEntities(from: client_frame_p; toFrame: client_frame_p;
  var msg: sizebuf_t);
var
  oldent, newent: entity_state_p;
  oldindex, newindex: Integer;
  oldnum, newnum: Integer;
  from_num_entities: Integer;
  bits: Integer;
begin
{$ifdef 0}
  if (numprojs <> 0) then
    MSG_WriteByte(msg, svc_packetentities2)
  else
{$endif}
    MSG_WriteByte(msg, Integer(svc_packetentities));

  if (from = nil) then
    from_num_entities := 0
  else
    from_num_entities := from^.num_entities;

  newindex := 0;
  oldindex := 0;
  while (newindex < toFrame^.num_entities) OR (oldindex < from_num_entities) do
  begin
    if (newindex >= toFrame^.num_entities) then
      newnum := 9999
    else
    begin
      newent := @svs.client_entities^[(toFrame^.first_entity + newindex) mod svs.num_client_entities];
      newnum := newent^.number;
    end;

    if (oldindex >= from_num_entities) then
      oldnum := 9999
    else
    begin
      oldent := @svs.client_entities^[(from^.first_entity + oldindex) mod svs.num_client_entities];
      oldnum := oldent^.number;
    end;

    if (newnum = oldnum) then
    begin
      // delta update from old position
      // because the force parm is false, this will not result
      // in any bytes being emited if the entity has not changed at all
      // note that players are always 'newentities', this updates their oldorigin always
      // and prevents warping
      MSG_WriteDeltaEntity(oldent^, newent^, msg, false, (newent^.number <= maxclients^.value));
      Inc(oldindex);
      Inc(newindex);
      continue;
    end;

    if (newnum < oldnum) then
    begin
      // this is a new entity, send it from the baseline
      MSG_WriteDeltaEntity(sv.baselines[newnum], newent^, msg, true, true);
      Inc(newindex);
      continue;
    end;

    if (newnum > oldnum) then
    begin
      // the old entity isn't present in the new message
      bits := U_REMOVE;
      if (oldnum >= 256) then
        bits := bits OR U_NUMBER16 OR U_MOREBITS1;

      MSG_WriteByte(msg, bits AND 255);

      if ((bits AND $0000ff00) <> 0) then
        MSG_WriteByte(msg, (bits shr 8) AND 255);

      if ((bits AND U_NUMBER16) <> 0) then
        MSG_WriteShort(msg, oldnum)
      else
        MSG_WriteByte(msg, oldnum);

      Inc(oldindex);
      continue;
    end;
  end;

  MSG_WriteShort(msg, 0);	// end of packetentities

{$ifdef 0}
  if (numprojs) then
    SV_EmitProjectileUpdate(msg);
{$endif}
end;

(* =============
SV_WritePlayerstateToClient

NOTE:  Renamed Variable "to" to "toFrame" instead!!
============= *)
procedure SV_WritePlayerstateToClient(from: client_frame_p; toFrame: client_frame_p;
                                      msg: sizebuf_p);
var
  i: integer;
  pflags: integer;
  ps, ops: player_state_p;
  dummy: player_state_t;
  statbits: integer;
begin
  ps := @toFrame^.ps;
  if (from = nil) then
  begin
    FillChar(dummy, sizeof(dummy), 0);
    ops := @dummy;
  end
  else
    ops := @from^.ps;

  //
  // determine what needs to be sent
  //
  pflags := 0;

  if (ps^.pmove.pm_type <> ops^.pmove.pm_type) then
    pflags := pflags OR PS_M_TYPE;

  if (ps^.pmove.origin[0] <> ops^.pmove.origin[0]) OR
  (ps^.pmove.origin[1] <> ops^.pmove.origin[1]) OR
  (ps^.pmove.origin[2] <> ops^.pmove.origin[2]) then
    pflags := pflags OR PS_M_ORIGIN;

  if (ps^.pmove.velocity[0] <> ops^.pmove.velocity[0]) OR
  (ps^.pmove.velocity[1] <> ops^.pmove.velocity[1]) OR
  (ps^.pmove.velocity[2] <> ops^.pmove.velocity[2]) then
    pflags := pflags OR PS_M_VELOCITY;

  if (ps^.pmove.pm_time <> ops^.pmove.pm_time) then
    pflags := pflags OR PS_M_TIME;

  if (ps^.pmove.pm_flags <> ops^.pmove.pm_flags) then
    pflags := pflags OR PS_M_FLAGS;

  if (ps^.pmove.gravity <> ops^.pmove.gravity) then
    pflags := pflags OR PS_M_GRAVITY;

  if (ps^.pmove.delta_angles[0] <> ops^.pmove.delta_angles[0]) OR
  (ps^.pmove.delta_angles[1] <> ops^.pmove.delta_angles[1]) OR
  (ps^.pmove.delta_angles[2] <> ops^.pmove.delta_angles[2]) then
    pflags := pflags OR PS_M_DELTA_ANGLES;


  if (ps^.viewoffset[0] <> ops^.viewoffset[0]) OR
  (ps^.viewoffset[1] <> ops^.viewoffset[1]) OR
  (ps^.viewoffset[2] <> ops^.viewoffset[2]) then
    pflags := pflags OR PS_VIEWOFFSET;

  if (ps^.viewangles[0] <> ops^.viewangles[0]) OR
  (ps^.viewangles[1] <> ops^.viewangles[1]) OR
  (ps^.viewangles[2] <> ops^.viewangles[2]) then
    pflags := pflags OR PS_VIEWANGLES;

  if (ps^.kick_angles[0] <> ops^.kick_angles[0]) OR
  (ps^.kick_angles[1] <> ops^.kick_angles[1]) OR
  (ps^.kick_angles[2] <> ops^.kick_angles[2]) then
    pflags := pflags OR PS_KICKANGLES;

  if (ps^.blend[0] <> ops^.blend[0]) OR
  (ps^.blend[1] <> ops^.blend[1]) OR
  (ps^.blend[2] <> ops^.blend[2]) OR
  (ps^.blend[3] <> ops^.blend[3]) then
    pflags := pflags OR PS_BLEND;

  if (ps^.fov <> ops^.fov) then
    pflags := pflags OR PS_FOV;

  if (ps^.rdflags <> ops^.rdflags) then
    pflags := pflags OR PS_RDFLAGS;

  if (ps^.gunframe <> ops^.gunframe) then
    pflags := pflags OR PS_WEAPONFRAME;

  pflags := pflags OR PS_WEAPONINDEX;

  //
  // write it
  //
  MSG_WriteByte(msg^, Integer(svc_playerinfo));
  MSG_WriteShort(msg^, pflags);

  //
  // write the pmove_state_t
  //
  if (pflags AND PS_M_TYPE) <> 0 then
    MSG_WriteByte(msg^, Integer(ps^.pmove.pm_type));

  if (pflags AND PS_M_ORIGIN) <> 0 then
  begin
    MSG_WriteShort(msg^, ps^.pmove.origin[0]);
    MSG_WriteShort(msg^, ps^.pmove.origin[1]);
    MSG_WriteShort(msg^, ps^.pmove.origin[2]);
  end;

  if (pflags AND PS_M_VELOCITY) <> 0 then
  begin
    MSG_WriteShort(msg^, ps^.pmove.velocity[0]);
    MSG_WriteShort(msg^, ps^.pmove.velocity[1]);
    MSG_WriteShort(msg^, ps^.pmove.velocity[2]);
  end;

⌨️ 快捷键说明

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