📄 sv_ents.pas
字号:
(*
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 + -