📄 sv_main.pas
字号:
{----------------------------------------------------------------------------}
{ }
{ File(s): sv_main.c }
{ }
{ Initial conversion by : George Melekos (inet_crow@hotmail.com) }
{ Initial conversion on : 13-Feb-2002 }
{ }
{ This File contains part of convertion of Quake2 source to ObjectPascal. }
{ More information about this project can be found at: }
{ http://www.sulaco.co.za/quake2/ }
{ }
{ 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. }
{ }
{----------------------------------------------------------------------------}
{ Updated on : }
{ Updated by : }
{ }
{----------------------------------------------------------------------------}
{ * Still dependent (to compile correctly) on: }
{----------------------------------------------------------------------------}
{ * TODO: }
{----------------------------------------------------------------------------}
// 25.07.2002 Juha: Proof-readed this unit
// address of group servers
// current client
// seconds without any message
// seconds to sink messages after disconnect
// password for remote server commands
// don't reload level state when reentering
// FIXME: rename sv_maxclients
// should heartbeats be sent
// minimum seconds between connect messages
unit Sv_main;
interface
uses
Windows,
SysUtils,
Common,
q_shared,
Server,
ref;
var
master_adr: array[0..MAX_MASTERS-1] of netadr_t; // address of group servers
sv_client: client_p; // current client
sv_paused,
sv_timedemo,
sv_enforcetime,
timeout, // seconds without any message
zombietime, // seconds to sink messages after disconnect
rcon_password, // password for remote server commands
allow_download,
allow_download_players,
allow_download_models,
allow_download_sounds,
allow_download_maps,
sv_airaccelerate,
sv_noreload, // don't reload level state when reentering
maxclients, // FIXME: rename sv_maxclients
sv_showclamp,
hostname,
public_server, // should heartbeats be sent
sv_reconnect_limit: cvar_p; // minimum seconds between connect messages
//============================================================================
(*
=====================
SV_DropClient
Called when the player is totally leaving the server, either willingly
or unwillingly. This is NOT called if the entire server is quiting
or crashing.
=====================
*)
procedure SV_DropClient (drop : client_p);
// add the disconnect
(*
==============================================================================
CONNECTIONLESS COMMANDS
==============================================================================
*)
(*
===============
SV_StatusString
Builds the string that is sent as heartbeats and status replies
===============
*)
function SV_StatusString : PChar;
(*
================
SVC_Status
Responds with all the info that qplug or qspy can see
================
*)
procedure SVC_Status;
(*
================
SVC_Ack
================
*)
procedure SVC_Ack;
(*
================
SVC_Info
Responds with short info for broadcast scans
The second parameter should be the current protocol version number.
================
*)
procedure SVC_Info;
(*
================
SVC_Ping
Just responds with an acknowledgement
================
*)
procedure SVC_Ping;
(*
=================
SVC_GetChallenge
Returns a challenge number that can be used
in a subsequent client_connect command.
We do this to prevent denial of service attacks that
flood the server with invalid connection IPs. With a
challenge, they must give a valid IP address.
=================
*)
procedure SVC_GetChallenge;
(*
==================
SVC_DirectConnect
A connection request that did not come from the master
==================
*)
procedure SVC_DirectConnect;
function Rcon_Validate : Integer;
(*
===============
SVC_RemoteCommand
A client issued an rcon command.
Shift down the remaining args
Redirect all printfs
===============
*)
procedure SVC_RemoteCommand;
(*
=================
SV_ConnectionlessPacket
A connectionless packet has four leading $ff
characters to distinguish it from a game channel.
Clients that are in the game can still send
connectionless packets.
=================
*)
procedure SV_ConnectionlessPacket;
//============================================================================
(*
===================
SV_CalcPings
Updates the cl^.ping variables
===================
*)
procedure SV_CalcPings;
(*
===================
SV_GiveMsec
Every few frames, gives all clients an allotment of milliseconds
for their command moves. If they exceed it, assume cheating.
===================
*)
procedure SV_GiveMsec;
(*
=================
SV_ReadPackets
=================
*)
procedure SV_ReadPackets;
(*
==================
SV_CheckTimeouts
If a packet has not been received from a client for timeout^.value
seconds, drop the conneciton. Server frames are used instead of
realtime to aprocedure dropping the local client while debugging.
When a client is normally dropped, the client_t goes into a zombie state
for a few seconds to make sure any final reliable message gets resent
if necessary
==================
*)
procedure SV_CheckTimeouts;
(*
================
SV_PrepWorldFrame
This has to be done before the world logic, because
player processing happens outside RunWorldFrame
================
*)
procedure SV_PrepWorldFrame;
(*
=================
SV_RunGameFrame
=================
*)
procedure SV_RunGameFrame;
(*
==================
SV_Frame
==================
*)
procedure SV_Frame (msec : Integer);
//============================================================================
(*
================
Master_Heartbeat
Send a message to the master every few minutes to
let it know we are alive, and log information
================
*)
const
HEARTBEAT_SECONDS = 300;
procedure Master_Heartbeat;
(*
=================
Master_Shutdown
Informs all masters that this server is going down
=================
*)
procedure Master_Shutdown;
//============================================================================
(*
=================
SV_UserinfoChanged
Pull specific info from a newly changed userinfo string
into a more C freindly form.
=================
*)
procedure SV_UserinfoChanged (cl : client_p);
//============================================================================
(*
===============
SV_Init
Only called at quake2.exe startup, not for each game
===============
*)
procedure SV_Init;
(*
==================
SV_FinalMessage
Used by SV_Shutdown to send a final message to all
connected clients before the server goes down. The messages are sent immediately,
not just stuck on the outgoing message list, because the server is going
to totally exit after returning from this function.
==================
*)
procedure SV_FinalMessage (message_ : PChar; reconnect : qboolean);
(*
================
SV_Shutdown
Called when each game quits,
before Sys_Quit or Sys_Error
================
*)
procedure SV_Shutdown (finalmsg : PChar; reconnect : qboolean);
implementation
uses
CVar,
CPas,
Cmd,
Files,
net_wins,
net_chan,
g_local,
q_shwin,
sv_ccmds,
sv_send,
sv_ents,
sv_init,
sv_user,
sv_game;
(*
=====================
SV_DropClient
Called when the player is totally leaving the server, either willingly
or unwillingly. This is NOT called if the entire server is quiting
or crashing.
=====================
*)
procedure SV_DropClient (drop: client_p);
begin
// add the disconnect
MSG_WriteByte (drop.netchan.message, Integer(svc_disconnect));
if (drop^.state = cs_spawned) then begin
// call the prog function for removing a client
// this will remove the body, among other things
ge^.ClientDisconnect (drop^.edict);
end;
if (drop^.download <> nil) then begin
FS_FreeFile (drop^.download);
drop^.download := nil;
end;
drop^.state := cs_zombie; // become free in a few seconds
drop^.name[0] := #0;
end;
(*
==============================================================================
CONNECTIONLESS COMMANDS
==============================================================================
*)
(*
===============
SV_StatusString
Builds the string that is sent as heartbeats and status replies
===============
*)
var
status: array[0..MAX_MSGLEN - 16-1] of char;
function SV_StatusString (): pchar;
var
player: array[0..1024-1] of char;
i: integer;
cl: client_p;
statusLength: integer;
playerLength: integer;
begin
strcpy (status, Cvar_Serverinfo_());
strcat (status, #10);
statusLength := strlen(status);
for i := 0 to Round(maxclients^.value)-1 do begin
cl := @svs.clients^[i];
if (cl^.state = cs_connected) or (cl^.state = cs_spawned) then begin
Com_sprintf (player, sizeof(player), '%i %i "%s"'#10,
[cl^.edict^.client^.ps.stats[STAT_FRAGS], cl^.ping, cl^.name]);
playerLength := strlen(player);
if (statusLength + playerLength >= sizeof(status)) then
break; // can't hold any more
strcpy (status + statusLength, player);
statusLength := statusLength + playerLength;
end;
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -