📄 sv_init.pas
字号:
{----------------------------------------------------------------------------}
{ }
{ File(s): sv_init.c }
{ }
{ Initial conversion by : dhouse (david@dahsoftware.com) }
{ Initial conversion on : 013-Jan-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 : }
{ }
{----------------------------------------------------------------------------}
{ * TODO: }
{----------------------------------------------------------------------------}
// 25.07.2002 Juha: Proof-readed this unit
unit sv_init;
interface
uses
q_shared,
server;
procedure SV_InitGame;cdecl;
procedure SV_Map( attractloop: qboolean; levelstring: PChar; loadgame: qboolean);cdecl;
function SV_ModelIndex( name: PChar ): Integer;cdecl;
function SV_SoundIndex( name: PChar ): Integer;cdecl;
function SV_ImageIndex( name: PChar ): Integer;cdecl;
var
svs : server_static_t; // persistant server info
sv : server_t; // local server
implementation
uses
SysUtils,
Common,
Cpas,
CVar,
CModel,
PMoveUnit,
Files,
Cmd,
g_local,
cl_main,
cl_scrn,
net_wins,
sv_ccmds,
sv_game,
sv_world,
sv_main,
sv_send;
{
================
SV_FindIndex
================
}
function SV_FindIndex( name : PChar; start, max : Integer; create : qboolean ) : Integer;
var
i : Integer;
begin
if (name = nil) or (name[0] = #0) then begin
Result := 0;
Exit;
end; { if }
i := 1;
while (i<max) and (sv.configstrings[start+i][0] <> #0) do begin
if strcmp( sv.configstrings[start+i], name ) = 0 then begin
Result := i;
Exit;
end; { if }
Inc(i);
end; { for }
if ( not create ) then begin
Result := 0;
Exit;
end; { if }
if (i = max) then
Com_Error(ERR_DROP, '*Index: overflow');
strncpy( sv.configstrings[start+i], name, sizeof(sv.configstrings[i]) );
if ( sv.state <> ss_loading ) then begin
// Send the update to everyone
SZ_Clear(sv.multicast);
MSG_WriteChar( sv.multicast, Integer(svc_configstring) );
MSG_WriteShort( sv.multicast, start+i );
MSG_WriteString( sv.multicast, name );
SV_Multicast( @vec3_origin, MULTICAST_ALL_R );
end; { if }
Result := i;
end;
function SV_ModelIndex( name: pchar ) : Integer;
begin
Result := SV_FindIndex( name, CS_MODELS, MAX_MODELS, True );
end;
function SV_SoundIndex( name: pchar ) : Integer;
begin
Result := SV_FindIndex( name, CS_SOUNDS, MAX_SOUNDS, True );
end;
function SV_ImageIndex( name: pchar ) : Integer;
begin
Result := SV_FindIndex( name, CS_IMAGES, MAX_IMAGES, True );
end;
{
================
SV_CreateBaseline
Entity baselines are used to compress the update messages
to the clients -- only the fields that differ from the
baseline will be transmitted
================
}
procedure SV_CreateBaseline;
var
svent: edict_p;
entnum: Integer;
begin
for entnum := 1 to (ge.num_edicts - 1) do
begin
svent := EDICT_NUM(entnum);
if ( not svent^.inuse ) then
Continue;
if ( (not svent^.s.modelindex<>0) and (not svent^.s.sound<>0) and (not svent^.s.effects<>0) ) then
Continue;
svent^.s.number := entnum;
//
// take current state as baseline
//
VectorCopy (svent^.s.origin, svent^.s.old_origin);
sv.baselines[entnum] := svent^.s;
end; { for }
end;
{
=================
SV_CheckForSavegame
=================
}
procedure SV_CheckForSavegame;
var
name: array[0..MAX_OSPATH-1] of Char;
f: integer;
i: Integer;
previousState: server_state_t;
begin
if ( sv_noreload^.value<>0 ) then
Exit;
if ( Cvar_VariableValue( 'deathmatch' )<>0 ) then
Exit;
Com_sprintf( name, sizeof(name), '%s/save/current/%s.sav', [FS_Gamedir(), sv.name] );
f := FileOpen(name, fmOpenRead);
if f = -1 then
Exit; // no savegame
FileClose(f);
SV_ClearWorld;
// get configstrings and areaportals
SV_ReadLevelFile;
if ( not sv.loadgame ) then begin
// coming back to a level after being in a different
// level, so run it for ten seconds
// rlava2 was sending too many lightstyles, and overflowing the
// reliable data. temporarily changing the server state to loading
// prevents these from being passed down.
previousState := sv.state;
sv.state := ss_loading;
for i := 0 to 100-1 do
ge^.RunFrame;
sv.state := previousState;
end; { if }
end;
{
================
SV_SpawnServer
Change the server to a new map, taking all connected
clients along with it.
================
}
procedure SV_SpawnServer( server, spawnpoint: PChar; serverstate : server_state_t; attractloop, loadgame: qboolean );
var
i : Integer;
checksum : Cardinal;
begin
if ( attractloop ) then
Cvar_Set( 'paused', '0' );
Com_Printf ('------- Server Initialization -------'#10);
Com_DPrintf( 'SpawnServer: %s'#10, [server] );
if ( sv.demofile > 0 ) then begin
FileClose( sv.demofile );
sv.demofile := 0;
end;
Inc(svs.spawncount); // any partially connected client will be restarted
sv.state := ss_dead;
Com_SetServerState( Integer(sv.state) );
// wipe the entire per-level structure
FillChar( sv, sizeof(sv), 0 );
svs.realtime := 0;
sv.loadgame := loadgame;
sv.attractloop := attractloop;
// save name for levels that don't set message
strcpy( sv.configstrings[CS_NAME], server );
if ( Cvar_VariableValue( 'deathmatch' )<>0 ) then begin
Com_sprintf( sv.configstrings[CS_AIRACCEL], MAX_QPATH, '%g', [sv_airaccelerate^.value] );
pm_airaccelerate := sv_airaccelerate^.value;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -