📄 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,
q_shared;
(*=============================================================================
Encode a client frame onto the network channel
=============================================================================*)
(*
// 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-1] of byte; // [modelindex] [48 bits] xyz p y 12 12 12 8 8 [entitynum] [e2]
n, i: Integer;
ent: edict_p;
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 := ((ent^.s.origin[0] + 4096) shr 1);
y := ((ent^.s.origin[1] + 4096) shr 1);
z := ((ent^.s.origin[2] + 4096) shr 1);
p := ((256 * ent^.s.angles[0] / 360) AND 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;
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;
*)
{
=============
SV_EmitPacketEntities
Writes a delta update of an entity_state_t list to the message.
=============
}
procedure SV_EmitPacketEntities(from: client_frame_p; to_: client_frame_p;
var msg: sizebuf_t);
var
oldent, newent: entity_state_p;
oldindex, newindex: Integer;
oldnum, newnum: Integer;
from_num_entities: Integer;
bits: Cardinal;
begin
{
if (numprojs <> 0) then
MSG_WriteByte(msg, svc_packetentities2)
else
}
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 < to_^.num_entities) or (oldindex < from_num_entities) do
begin
if (newindex >= to_^.num_entities) then
newnum := 9999
else
begin
newent := @svs.client_entities^[(to_^.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 <= Trunc(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
{
if (numprojs) then
SV_EmitProjectileUpdate(msg);
}
end;
(*
=============
SV_WritePlayerstateToClient
=============
*)
procedure SV_WritePlayerstateToClient(from: client_frame_p; to_: client_frame_p;
msg: sizebuf_p);
var
i: integer;
pflags: integer;
ps, ops: player_state_p;
dummy: player_state_t;
statbits: integer;
begin
ps := @to_^.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;
if (pflags and PS_M_TIME) <> 0 then
MSG_WriteByte(msg^, ps^.pmove.pm_time);
if (pflags and PS_M_FLAGS) <> 0 then
MSG_WriteByte(msg^, ps^.pmove.pm_flags);
if (pflags and PS_M_GRAVITY) <> 0 then
MSG_WriteShort(msg^, ps^.pmove.gravity);
if (pflags and PS_M_DELTA_ANGLES) <> 0 then
begin
MSG_WriteShort(msg^, ps^.pmove.delta_angles[0]);
MSG_WriteShort(msg^, ps^.pmove.delta_angles[1]);
MSG_WriteShort(msg^, ps^.pmove.delta_angles[2]);
end;
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -