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

📄 sv_send.pas

📁 雷神之锤2(Quake2)Delphi源码
💻 PAS
📖 第 1 页 / 共 2 页
字号:
      SZ_Write (client.datagram, sv.multicast.data, sv.multicast.cursize);
  end;

  SZ_Clear (sv.multicast);
end;


(*
==================
SV_StartSound

Each entity can have eight independant sound sources, like voice,
weapon, feet, etc.

If cahnnel & 8, the sound will be sent to everyone, not just
things in the PHS.

FIXME: if entity isn't in PHS, they must be forced to be sent or
have the origin explicitly sent.

Channel 0 is an auto-allocate channel, the others override anything
already running on that entity/channel pair.

An attenuation of 0 will play full volume everywhere in the level.
Larger attenuations will drop off.  (max 4 attenuation)

Timeofs can range from 0.0 to 0.1 to cause sounds to be started
later in the frame than they normally would.

If origin is NULL, the origin is determined from the entity origin
or the midpoint of the entity box for bmodels.
==================
*)
procedure SV_StartSound (origin: vec3_p; entity: edict_p; channel: integer;
					soundindex: integer; volume: single;
					attenuation: single; timeofs: single);
var
  sendchan:integer;
  flags:integer;
  i:integer;
  ent:integer;
  origin_v:vec3_t;
  use_phs:boolean;
begin
  if (volume < 0) or (volume > 1.0) then
    Com_Error (ERR_FATAL, 'SV_StartSound: volume = %f', [volume]);

  if (attenuation < 0) or (attenuation > 4) then
    Com_Error (ERR_FATAL, 'SV_StartSound: attenuation = %f', [attenuation]);

//	if (channel < 0 || channel > 15)
//		Com_Error (ERR_FATAL, "SV_StartSound: channel = %i", channel);

  if (timeofs < 0) or (timeofs > 0.255) then
    Com_Error (ERR_FATAL, 'SV_StartSound: timeofs = %f', [timeofs]);

  ent := NUM_FOR_EDICT(entity);

  if (channel and 8<>0) then	// no PHS flag
    begin
      use_phs := false;
      channel := channel and 7;
    end
  else
    use_phs := true;

  sendchan := (ent shl 3) or (channel and 7);

  flags := 0;
  if (volume <> DEFAULT_SOUND_PACKET_VOLUME) then
    flags := flags or SND_VOLUME;
  if (attenuation <> DEFAULT_SOUND_PACKET_ATTENUATION) then
    flags := flags or SND_ATTENUATION;

  // the client doesn't know that bmodels have weird origins
  // the origin can also be explicitly set
  if ( (entity^.svflags and SVF_NOCLIENT<>0) or (entity^.solid = SOLID_BSP) or (origin<>nil) ) then
    flags := flags or SND_POS;

  // always send the entity number for channel overrides
    flags := flags or SND_ENT;

  if (timeofs<>0) then
    flags := flags or SND_OFFSET;

  // use the entity origin unless it is a bmodel or explicitly specified
  if (origin = nil) then
    begin
      origin := @origin_v;
      if (entity.solid = SOLID_BSP) then
        for i:=0  to 2 do
          origin_v[i] := entity^.s.origin[i]+0.5*(entity^.mins[i]+entity^.maxs[i])
      else
        VectorCopy (entity^.s.origin, origin_v);
    end;

    MSG_WriteByte (sv.multicast, Integer(svc_sound));
    MSG_WriteByte (sv.multicast, flags);
    MSG_WriteByte (sv.multicast, soundindex);

    if (flags and SND_VOLUME<>0) then
      MSG_WriteByte (sv.multicast, Round(volume*255));
    if (flags and SND_ATTENUATION<>0) then
      MSG_WriteByte (sv.multicast, Round(attenuation*64));
    if (flags and SND_OFFSET<>0) then
      MSG_WriteByte (sv.multicast, Round(timeofs*1000));

    if (flags and SND_ENT<>0) then
      MSG_WriteShort (sv.multicast, sendchan);

    if (flags and SND_POS<>0) then
      MSG_WritePos (sv.multicast, origin^);

    // if the sound doesn't attenuate,send it to everyone
    // (global radio chatter, voiceovers, etc)
    if (attenuation = ATTN_NONE) then
      use_phs := false;

    if (channel and CHAN_RELIABLE<>0) then
      begin
        if (use_phs) then
          SV_Multicast (origin, MULTICAST_PHS_R)
        else
          SV_Multicast (origin, MULTICAST_ALL_R);
      end
    else
      begin
        if (use_phs) then
          SV_Multicast (origin, MULTICAST_PHS)
        else
          SV_Multicast (origin, MULTICAST_ALL);
      end;
end;


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

FRAME UPDATES

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



(*
=======================
SV_SendClientDatagram
=======================
*)
function SV_SendClientDatagram (client: client_p): qboolean;
var
  msg_buf: array [0..MAX_MSGLEN-1] of byte;
  msg: sizebuf_t;
begin
  SV_BuildClientFrame (client);

  SZ_Init (msg, @msg_buf, sizeof(msg_buf));
  msg.allowoverflow := true;

  // send over all the relevant entity_state_t
  // and the player_state_t
  SV_WriteFrameToClient (client, @msg);

  // copy the accumulated multicast datagram
  // for this client out to the message
  // it is necessary for this to be after the WriteEntities
  // so that entity references will be current
  if (client^.datagram.overflowed) then
    Com_Printf ('WARNING: datagram overflowed for %s'#10, [client^.name])
  else
    SZ_Write (msg, client.datagram.data, client.datagram.cursize);
  SZ_Clear (client.datagram);

  if (msg.overflowed) then
    begin
      // must have room left for the packet header
      Com_Printf ('WARNING: msg overflowed for %s'#10, [client.name]);
      SZ_Clear (msg);
    end;

  // send the datagram
  Netchan_Transmit (client.netchan, msg.cursize, PByte(msg.data));

  // record the size for rate estimation
  client^.message_size[sv.framenum mod RATE_MESSAGES] := msg.cursize;

  Result := True;
end;


(*
==================
SV_DemoCompleted
==================
*)
procedure SV_DemoCompleted;
begin
  if (sv.demofile > 0) then
    begin
      FileClose (sv.demofile);
      sv.demofile := 0;
    end
  else
    SV_Nextserver;
end;


(*
=======================
SV_RateDrop

Returns true if the client is over its current
bandwidth estimation and should not be sent another packet
=======================
*)
function SV_RateDrop (c: client_p):boolean;
var
  total:integer;
  i:integer;
begin
  // never drop over the loopback
  if (c.netchan.remote_address.type_ = NA_LOOPBACK) then
    begin
      Result := False;
      exit;
    end;

  total := 0;

  for i:=0 to RATE_MESSAGES-1 do
    inc(total,c^.message_size[i]);

  if (total > c^.rate) then
    begin
      c^.surpressCount := c^.surpressCount+1;
      c^.message_size[sv.framenum mod RATE_MESSAGES] := 0;
      Result := True;
      exit;
    end;

  Result := False;
end;

(*
=======================
SV_SendClientMessages
=======================
*)
procedure SV_SendClientMessages;
var
  i: integer;
  c: client_p;
  msglen: integer;
  msgbuf: array[0..MAX_MSGLEN-1] of byte;
  r: integer;
begin
  msglen := 0;

  // read the next demo message if needed
  if (sv.state = ss_demo) and (sv.demofile>0) then
    begin
      if (sv_paused.value<>0) then
        msglen := 0
      else
        begin
          // get the next message
          r := FileRead (sv.demofile, msglen, 4);
          if (r <> 4) then
            begin
              SV_DemoCompleted;
              exit;
            end;
          msglen := LittleLong (msglen);
          if (msglen = -1) then
            begin
              SV_DemoCompleted;
              exit;
            end;
          if (msglen > MAX_MSGLEN) then
            Com_Error (ERR_DROP, 'SV_SendClientMessages: msglen > MAX_MSGLEN', []);
          r := FileRead (sv.demofile, msgbuf, msglen);
          if (r <> msglen) then
            begin
              SV_DemoCompleted;
              exit;
            end;
        end;
    end;

  // send a message to each connected client
  c := client_p(svs.clients);
  for i := 0 to Round(maxclients.value-1) do
    begin
      if (Integer(c^.state) = 0) then
        begin
          inc(c);
          continue;
        end;
      // if the reliable message overflowed,
      // drop the client
      if (c^.netchan.message.overflowed) then
        begin
          SZ_Clear (c^.netchan.message);
          SZ_Clear (c^.datagram);
          SV_BroadcastPrintf (PRINT_HIGH, '%s overflowed'#10, [c^.name]);
          SV_DropClient (c);
        end;

      if (sv.state = ss_cinematic) or (sv.state = ss_demo) or (sv.state = ss_pic) then
        Netchan_Transmit (c^.netchan, msglen, @msgbuf)
      else if (c^.state = cs_spawned) then
        begin
          // don't overrun bandwidth
          if (SV_RateDrop (c)) then
            begin
              inc(c);
              continue;
            end;

            SV_SendClientDatagram (c);
        end
      else
        begin
          // just update reliable if needed
          if (c^.netchan.message.cursize<>0) or (curtime - c^.netchan.last_sent > 1000 ) then
            Netchan_Transmit (c.netchan, 0, nil);
        end;
      inc(c);
    end;
end;

end.

⌨️ 快捷键说明

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