mirror of
https://github.com/yquake2/yquake2remaster.git
synced 2024-11-26 14:30:48 +00:00
Räume sv_init.c auf
This commit is contained in:
parent
c49f21c9d0
commit
6c2ae15351
1 changed files with 342 additions and 307 deletions
|
@ -1,470 +1,505 @@
|
|||
/*
|
||||
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.
|
||||
|
||||
*/
|
||||
* 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.
|
||||
*
|
||||
* =======================================================================
|
||||
*
|
||||
* Server startup.
|
||||
*
|
||||
* =======================================================================
|
||||
*/
|
||||
|
||||
#include "header/server.h"
|
||||
|
||||
server_static_t svs; // persistant server info
|
||||
server_t sv; // local server
|
||||
server_static_t svs; /* persistant server info */
|
||||
server_t sv; /* local server */
|
||||
|
||||
/*
|
||||
================
|
||||
SV_FindIndex
|
||||
|
||||
================
|
||||
*/
|
||||
int SV_FindIndex (char *name, int start, int max, qboolean create)
|
||||
int
|
||||
SV_FindIndex ( char *name, int start, int max, qboolean create )
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!name || !name[0])
|
||||
return 0;
|
||||
int i;
|
||||
|
||||
for (i=1 ; i<max && sv.configstrings[start+i][0] ; i++)
|
||||
if (!strcmp(sv.configstrings[start+i], name))
|
||||
return i;
|
||||
|
||||
if (!create)
|
||||
return 0;
|
||||
|
||||
if (i == max)
|
||||
Com_Error (ERR_DROP, "*Index: overflow");
|
||||
|
||||
strncpy (sv.configstrings[start+i], name, sizeof(sv.configstrings[i]));
|
||||
|
||||
if (sv.state != ss_loading)
|
||||
{ // send the update to everyone
|
||||
MSG_WriteChar (&sv.multicast, svc_configstring);
|
||||
MSG_WriteShort (&sv.multicast, start+i);
|
||||
MSG_WriteString (&sv.multicast, name);
|
||||
SV_Multicast (vec3_origin, MULTICAST_ALL_R);
|
||||
if ( !name || !name [ 0 ] )
|
||||
{
|
||||
return ( 0 );
|
||||
}
|
||||
|
||||
return i;
|
||||
for ( i = 1; i < max && sv.configstrings [ start + i ] [ 0 ]; i++ )
|
||||
{
|
||||
if ( !strcmp( sv.configstrings [ start + i ], name ) )
|
||||
{
|
||||
return ( i );
|
||||
}
|
||||
}
|
||||
|
||||
if ( !create )
|
||||
{
|
||||
return ( 0 );
|
||||
}
|
||||
|
||||
if ( i == max )
|
||||
{
|
||||
Com_Error( ERR_DROP, "*Index: overflow" );
|
||||
}
|
||||
|
||||
strncpy( sv.configstrings [ start + i ], name, sizeof ( sv.configstrings [ i ] ) );
|
||||
|
||||
if ( sv.state != ss_loading )
|
||||
{
|
||||
/* send the update to everyone */
|
||||
MSG_WriteChar( &sv.multicast, svc_configstring );
|
||||
MSG_WriteShort( &sv.multicast, start + i );
|
||||
MSG_WriteString( &sv.multicast, name );
|
||||
SV_Multicast( vec3_origin, MULTICAST_ALL_R );
|
||||
}
|
||||
|
||||
return ( i );
|
||||
}
|
||||
|
||||
|
||||
int SV_ModelIndex (char *name)
|
||||
int
|
||||
SV_ModelIndex ( char *name )
|
||||
{
|
||||
return SV_FindIndex (name, CS_MODELS, MAX_MODELS, true);
|
||||
return ( SV_FindIndex( name, CS_MODELS, MAX_MODELS, true ) );
|
||||
}
|
||||
|
||||
int SV_SoundIndex (char *name)
|
||||
int
|
||||
SV_SoundIndex ( char *name )
|
||||
{
|
||||
return SV_FindIndex (name, CS_SOUNDS, MAX_SOUNDS, true);
|
||||
return ( SV_FindIndex( name, CS_SOUNDS, MAX_SOUNDS, true ) );
|
||||
}
|
||||
|
||||
int SV_ImageIndex (char *name)
|
||||
int
|
||||
SV_ImageIndex ( char *name )
|
||||
{
|
||||
return SV_FindIndex (name, CS_IMAGES, MAX_IMAGES, true);
|
||||
return ( SV_FindIndex( name, CS_IMAGES, MAX_IMAGES, true ) );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
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
|
||||
================
|
||||
*/
|
||||
void SV_CreateBaseline (void)
|
||||
* Entity baselines are used to compress the update messages
|
||||
* to the clients -- only the fields that differ from the
|
||||
* baseline will be transmitted
|
||||
*/
|
||||
void
|
||||
SV_CreateBaseline ( void )
|
||||
{
|
||||
edict_t *svent;
|
||||
int entnum;
|
||||
edict_t *svent;
|
||||
int entnum;
|
||||
|
||||
for (entnum = 1; entnum < ge->num_edicts ; entnum++)
|
||||
for ( entnum = 1; entnum < ge->num_edicts; entnum++ )
|
||||
{
|
||||
svent = EDICT_NUM(entnum);
|
||||
if (!svent->inuse)
|
||||
svent = EDICT_NUM( entnum );
|
||||
|
||||
if ( !svent->inuse )
|
||||
{
|
||||
continue;
|
||||
if (!svent->s.modelindex && !svent->s.sound && !svent->s.effects)
|
||||
}
|
||||
|
||||
if ( !svent->s.modelindex && !svent->s.sound && !svent->s.effects )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
svent->s.number = entnum;
|
||||
|
||||
//
|
||||
// take current state as baseline
|
||||
//
|
||||
VectorCopy (svent->s.origin, svent->s.old_origin);
|
||||
sv.baselines[entnum] = svent->s;
|
||||
/* take current state as baseline */
|
||||
VectorCopy( svent->s.origin, svent->s.old_origin );
|
||||
sv.baselines [ entnum ] = svent->s;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
SV_CheckForSavegame
|
||||
=================
|
||||
*/
|
||||
void SV_CheckForSavegame (void)
|
||||
void
|
||||
SV_CheckForSavegame ( void )
|
||||
{
|
||||
char name[MAX_OSPATH];
|
||||
FILE *f;
|
||||
int i;
|
||||
char name [ MAX_OSPATH ];
|
||||
FILE *f;
|
||||
int i;
|
||||
|
||||
if (sv_noreload->value)
|
||||
if ( sv_noreload->value )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Cvar_VariableValue ("deathmatch"))
|
||||
if ( Cvar_VariableValue( "deathmatch" ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Com_sprintf (name, sizeof(name), "%s/save/current/%s.sav", FS_Gamedir(), sv.name);
|
||||
f = fopen (name, "rb");
|
||||
if (!f)
|
||||
return; // no savegame
|
||||
Com_sprintf( name, sizeof ( name ), "%s/save/current/%s.sav", FS_Gamedir(), sv.name );
|
||||
f = fopen( name, "rb" );
|
||||
|
||||
fclose (f);
|
||||
if ( !f )
|
||||
{
|
||||
return; /* no savegame */
|
||||
}
|
||||
|
||||
SV_ClearWorld ();
|
||||
fclose( f );
|
||||
|
||||
// get configstrings and areaportals
|
||||
SV_ReadLevelFile ();
|
||||
SV_ClearWorld();
|
||||
|
||||
if (!sv.loadgame)
|
||||
{ // coming back to a level after being in a different
|
||||
// level, so run it for ten seconds
|
||||
/* get configstrings and areaportals */
|
||||
SV_ReadLevelFile();
|
||||
|
||||
// rlava2 was sending too many lightstyles, and overflowing the
|
||||
// reliable data. temporarily changing the server state to loading
|
||||
// prevents these from being passed down.
|
||||
server_state_t previousState; // PGM
|
||||
if ( !sv.loadgame )
|
||||
{
|
||||
/* coming back to a level after being in a different
|
||||
level, so run it for ten seconds */
|
||||
|
||||
previousState = sv.state; // PGM
|
||||
sv.state = ss_loading; // PGM
|
||||
for (i=0 ; i<100 ; i++)
|
||||
ge->RunFrame ();
|
||||
server_state_t previousState;
|
||||
|
||||
sv.state = previousState; // PGM
|
||||
previousState = sv.state;
|
||||
sv.state = ss_loading;
|
||||
|
||||
for ( i = 0; i < 100; i++ )
|
||||
{
|
||||
ge->RunFrame();
|
||||
}
|
||||
|
||||
sv.state = previousState;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
SV_SpawnServer
|
||||
|
||||
Change the server to a new map, taking all connected
|
||||
clients along with it.
|
||||
|
||||
================
|
||||
*/
|
||||
void SV_SpawnServer (char *server, char *spawnpoint, server_state_t serverstate, qboolean attractloop, qboolean loadgame)
|
||||
* Change the server to a new map, taking all connected
|
||||
* clients along with it.
|
||||
*/
|
||||
void
|
||||
SV_SpawnServer ( char *server, char *spawnpoint, server_state_t serverstate, qboolean attractloop, qboolean loadgame )
|
||||
{
|
||||
int i;
|
||||
unsigned checksum;
|
||||
int i;
|
||||
unsigned checksum;
|
||||
|
||||
if (attractloop)
|
||||
Cvar_Set ("paused", "0");
|
||||
if ( attractloop )
|
||||
{
|
||||
Cvar_Set( "paused", "0" );
|
||||
}
|
||||
|
||||
Com_Printf ("------- server initialization ------\n");
|
||||
Com_Printf( "------- server initialization ------\n" );
|
||||
|
||||
Com_DPrintf ("SpawnServer: %s\n",server);
|
||||
if (sv.demofile)
|
||||
FS_FCloseFile ((size_t)sv.demofile);
|
||||
Com_DPrintf( "SpawnServer: %s\n", server );
|
||||
|
||||
svs.spawncount++; // any partially connected client will be
|
||||
// restarted
|
||||
if ( sv.demofile )
|
||||
{
|
||||
FS_FCloseFile( (size_t) sv.demofile );
|
||||
}
|
||||
|
||||
svs.spawncount++; /* any partially connected client will be restarted */
|
||||
sv.state = ss_dead;
|
||||
Com_SetServerState (sv.state);
|
||||
Com_SetServerState( sv.state );
|
||||
|
||||
// wipe the entire per-level structure
|
||||
memset (&sv, 0, sizeof(sv));
|
||||
/* wipe the entire per-level structure */
|
||||
memset( &sv, 0, sizeof ( sv ) );
|
||||
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"))
|
||||
/* save name for levels that don't set message */
|
||||
strcpy( sv.configstrings [ CS_NAME ], server );
|
||||
|
||||
if ( Cvar_VariableValue( "deathmatch" ) )
|
||||
{
|
||||
sprintf(sv.configstrings[CS_AIRACCEL], "%g", sv_airaccelerate->value);
|
||||
sprintf( sv.configstrings [ CS_AIRACCEL ], "%g", sv_airaccelerate->value );
|
||||
pm_airaccelerate = sv_airaccelerate->value;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(sv.configstrings[CS_AIRACCEL], "0");
|
||||
strcpy( sv.configstrings [ CS_AIRACCEL ], "0" );
|
||||
pm_airaccelerate = 0;
|
||||
}
|
||||
|
||||
SZ_Init (&sv.multicast, sv.multicast_buf, sizeof(sv.multicast_buf));
|
||||
SZ_Init( &sv.multicast, sv.multicast_buf, sizeof ( sv.multicast_buf ) );
|
||||
|
||||
strcpy (sv.name, server);
|
||||
strcpy( sv.name, server );
|
||||
|
||||
// leave slots at start for clients only
|
||||
for (i=0 ; i<maxclients->value ; i++)
|
||||
/* leave slots at start for clients only */
|
||||
for ( i = 0; i < maxclients->value; i++ )
|
||||
{
|
||||
// needs to reconnect
|
||||
if (svs.clients[i].state > cs_connected)
|
||||
svs.clients[i].state = cs_connected;
|
||||
svs.clients[i].lastframe = -1;
|
||||
/* needs to reconnect */
|
||||
if ( svs.clients [ i ].state > cs_connected )
|
||||
{
|
||||
svs.clients [ i ].state = cs_connected;
|
||||
}
|
||||
|
||||
svs.clients [ i ].lastframe = -1;
|
||||
}
|
||||
|
||||
sv.time = 1000;
|
||||
|
||||
strcpy (sv.name, server);
|
||||
strcpy (sv.configstrings[CS_NAME], server);
|
||||
|
||||
if (serverstate != ss_game)
|
||||
strcpy( sv.name, server );
|
||||
strcpy( sv.configstrings [ CS_NAME ], server );
|
||||
|
||||
if ( serverstate != ss_game )
|
||||
{
|
||||
sv.models[1] = CM_LoadMap ("", false, &checksum); // no real map
|
||||
sv.models [ 1 ] = CM_LoadMap( "", false, &checksum ); /* no real map */
|
||||
}
|
||||
else
|
||||
{
|
||||
Com_sprintf (sv.configstrings[CS_MODELS+1],sizeof(sv.configstrings[CS_MODELS+1]),
|
||||
"maps/%s.bsp", server);
|
||||
sv.models[1] = CM_LoadMap (sv.configstrings[CS_MODELS+1], false, &checksum);
|
||||
Com_sprintf( sv.configstrings [ CS_MODELS + 1 ],
|
||||
sizeof ( sv.configstrings [ CS_MODELS + 1 ] ), "maps/%s.bsp", server );
|
||||
sv.models [ 1 ] = CM_LoadMap( sv.configstrings [ CS_MODELS + 1 ], false, &checksum );
|
||||
}
|
||||
Com_sprintf (sv.configstrings[CS_MAPCHECKSUM],sizeof(sv.configstrings[CS_MAPCHECKSUM]),
|
||||
"%i", checksum);
|
||||
|
||||
//
|
||||
// clear physics interaction links
|
||||
//
|
||||
SV_ClearWorld ();
|
||||
|
||||
for (i=1 ; i< CM_NumInlineModels() ; i++)
|
||||
Com_sprintf( sv.configstrings [ CS_MAPCHECKSUM ], sizeof ( sv.configstrings [ CS_MAPCHECKSUM ] ),
|
||||
"%i", checksum );
|
||||
|
||||
/* clear physics interaction links */
|
||||
SV_ClearWorld();
|
||||
|
||||
for ( i = 1; i < CM_NumInlineModels(); i++ )
|
||||
{
|
||||
Com_sprintf (sv.configstrings[CS_MODELS+1+i], sizeof(sv.configstrings[CS_MODELS+1+i]),
|
||||
"*%i", i);
|
||||
sv.models[i+1] = CM_InlineModel (sv.configstrings[CS_MODELS+1+i]);
|
||||
Com_sprintf( sv.configstrings [ CS_MODELS + 1 + i ], sizeof ( sv.configstrings [ CS_MODELS + 1 + i ] ),
|
||||
"*%i", i );
|
||||
sv.models [ i + 1 ] = CM_InlineModel( sv.configstrings [ CS_MODELS + 1 + i ] );
|
||||
}
|
||||
|
||||
//
|
||||
// spawn the rest of the entities on the map
|
||||
//
|
||||
|
||||
// precache and static commands can be issued during
|
||||
// map initialization
|
||||
/* spawn the rest of the entities on the map */
|
||||
sv.state = ss_loading;
|
||||
Com_SetServerState (sv.state);
|
||||
Com_SetServerState( sv.state );
|
||||
|
||||
// load and spawn all other entities
|
||||
ge->SpawnEntities ( sv.name, CM_EntityString(), spawnpoint );
|
||||
/* load and spawn all other entities */
|
||||
ge->SpawnEntities( sv.name, CM_EntityString(), spawnpoint );
|
||||
|
||||
// run two frames to allow everything to settle
|
||||
ge->RunFrame ();
|
||||
ge->RunFrame ();
|
||||
/* run two frames to allow everything to settle */
|
||||
ge->RunFrame();
|
||||
ge->RunFrame();
|
||||
|
||||
//verify game didn't clobber important stuff
|
||||
if ((int)checksum != atoi(sv.configstrings[CS_MAPCHECKSUM]))
|
||||
Com_Error (ERR_DROP, "Game DLL corrupted server configstrings");
|
||||
/* verify game didn't clobber important stuff */
|
||||
if ( (int) checksum != atoi( sv.configstrings [ CS_MAPCHECKSUM ] ) )
|
||||
{
|
||||
Com_Error( ERR_DROP, "Game DLL corrupted server configstrings" );
|
||||
}
|
||||
|
||||
// all precaches are complete
|
||||
/* all precaches are complete */
|
||||
sv.state = serverstate;
|
||||
Com_SetServerState (sv.state);
|
||||
|
||||
// create a baseline for more efficient communications
|
||||
SV_CreateBaseline ();
|
||||
Com_SetServerState( sv.state );
|
||||
|
||||
// check for a savegame
|
||||
SV_CheckForSavegame ();
|
||||
/* create a baseline for more efficient communications */
|
||||
SV_CreateBaseline();
|
||||
|
||||
// set serverinfo variable
|
||||
Cvar_FullSet ("mapname", sv.name, CVAR_SERVERINFO | CVAR_NOSET);
|
||||
Cvar_SetValue("windowed_mouse", 1);
|
||||
/* check for a savegame */
|
||||
SV_CheckForSavegame();
|
||||
|
||||
Com_Printf ("------------------------------------\n\n");
|
||||
/* set serverinfo variable */
|
||||
Cvar_FullSet( "mapname", sv.name, CVAR_SERVERINFO | CVAR_NOSET );
|
||||
Cvar_SetValue( "windowed_mouse", 1 );
|
||||
|
||||
Com_Printf( "------------------------------------\n\n" );
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
SV_InitGame
|
||||
|
||||
A brand new game has been started
|
||||
==============
|
||||
*/
|
||||
void SV_InitGame (void)
|
||||
* A brand new game has been started
|
||||
*/
|
||||
void
|
||||
SV_InitGame ( void )
|
||||
{
|
||||
int i;
|
||||
edict_t *ent;
|
||||
char idmaster[32];
|
||||
int i;
|
||||
edict_t *ent;
|
||||
char idmaster [ 32 ];
|
||||
|
||||
if (svs.initialized)
|
||||
if ( svs.initialized )
|
||||
{
|
||||
// cause any connected clients to reconnect
|
||||
SV_Shutdown ("Server restarted\n", true);
|
||||
/* cause any connected clients to reconnect */
|
||||
SV_Shutdown( "Server restarted\n", true );
|
||||
}
|
||||
|
||||
#ifndef DEDICATED_ONLY
|
||||
else
|
||||
{
|
||||
// make sure the client is down
|
||||
CL_Drop ();
|
||||
SCR_BeginLoadingPlaque ();
|
||||
/* make sure the client is down */
|
||||
CL_Drop();
|
||||
SCR_BeginLoadingPlaque();
|
||||
}
|
||||
#endif
|
||||
// get any latched variable changes (maxclients, etc)
|
||||
Cvar_GetLatchedVars ();
|
||||
|
||||
/* get any latched variable changes (maxclients, etc) */
|
||||
Cvar_GetLatchedVars();
|
||||
|
||||
svs.initialized = true;
|
||||
|
||||
if (Cvar_VariableValue ("coop") && Cvar_VariableValue ("deathmatch"))
|
||||
if ( Cvar_VariableValue( "coop" ) && Cvar_VariableValue( "deathmatch" ) )
|
||||
{
|
||||
Com_Printf("Deathmatch and Coop both set, disabling Coop\n");
|
||||
Cvar_FullSet ("coop", "0", CVAR_SERVERINFO | CVAR_LATCH);
|
||||
Com_Printf( "Deathmatch and Coop both set, disabling Coop\n" );
|
||||
Cvar_FullSet( "coop", "0", CVAR_SERVERINFO | CVAR_LATCH );
|
||||
}
|
||||
|
||||
// dedicated servers are can't be single player and are usually DM
|
||||
// so unless they explicity set coop, force it to deathmatch
|
||||
if (dedicated->value)
|
||||
/* dedicated servers can't be single player and are usually DM
|
||||
so unless they explicity set coop, force it to deathmatch */
|
||||
if ( dedicated->value )
|
||||
{
|
||||
if (!Cvar_VariableValue ("coop"))
|
||||
Cvar_FullSet ("deathmatch", "1", CVAR_SERVERINFO | CVAR_LATCH);
|
||||
if ( !Cvar_VariableValue( "coop" ) )
|
||||
{
|
||||
Cvar_FullSet( "deathmatch", "1", CVAR_SERVERINFO | CVAR_LATCH );
|
||||
}
|
||||
}
|
||||
|
||||
// init clients
|
||||
if (Cvar_VariableValue ("deathmatch"))
|
||||
/* init clients */
|
||||
if ( Cvar_VariableValue( "deathmatch" ) )
|
||||
{
|
||||
if (maxclients->value <= 1)
|
||||
Cvar_FullSet ("maxclients", "8", CVAR_SERVERINFO | CVAR_LATCH);
|
||||
else if (maxclients->value > MAX_CLIENTS)
|
||||
Cvar_FullSet ("maxclients", va("%i", MAX_CLIENTS), CVAR_SERVERINFO | CVAR_LATCH);
|
||||
if ( maxclients->value <= 1 )
|
||||
{
|
||||
Cvar_FullSet( "maxclients", "8", CVAR_SERVERINFO | CVAR_LATCH );
|
||||
}
|
||||
else if ( maxclients->value > MAX_CLIENTS )
|
||||
{
|
||||
Cvar_FullSet( "maxclients", va( "%i", MAX_CLIENTS ), CVAR_SERVERINFO | CVAR_LATCH );
|
||||
}
|
||||
}
|
||||
else if (Cvar_VariableValue ("coop"))
|
||||
else if ( Cvar_VariableValue( "coop" ) )
|
||||
{
|
||||
if (maxclients->value <= 1 || maxclients->value > 4)
|
||||
Cvar_FullSet ("maxclients", "4", CVAR_SERVERINFO | CVAR_LATCH);
|
||||
if ( ( maxclients->value <= 1 ) || ( maxclients->value > 4 ) )
|
||||
{
|
||||
Cvar_FullSet( "maxclients", "4", CVAR_SERVERINFO | CVAR_LATCH );
|
||||
}
|
||||
}
|
||||
else // non-deathmatch, non-coop is one player
|
||||
else /* non-deathmatch, non-coop is one player */
|
||||
{
|
||||
Cvar_FullSet ("maxclients", "1", CVAR_SERVERINFO | CVAR_LATCH);
|
||||
Cvar_FullSet( "maxclients", "1", CVAR_SERVERINFO | CVAR_LATCH );
|
||||
}
|
||||
|
||||
svs.spawncount = rand();
|
||||
svs.clients = Z_Malloc (sizeof(client_t)*maxclients->value);
|
||||
svs.num_client_entities = maxclients->value*UPDATE_BACKUP*64;
|
||||
svs.client_entities = Z_Malloc (sizeof(entity_state_t)*svs.num_client_entities);
|
||||
svs.clients = Z_Malloc( sizeof ( client_t ) * maxclients->value );
|
||||
svs.num_client_entities = maxclients->value * UPDATE_BACKUP * 64;
|
||||
svs.client_entities = Z_Malloc( sizeof ( entity_state_t ) * svs.num_client_entities );
|
||||
|
||||
// init network stuff
|
||||
NET_Config ( (maxclients->value > 1) );
|
||||
/* init network stuff */
|
||||
NET_Config( ( maxclients->value > 1 ) );
|
||||
|
||||
// heartbeats will always be sent to the id master
|
||||
svs.last_heartbeat = -99999; // send immediately
|
||||
Com_sprintf(idmaster, sizeof(idmaster), "192.246.40.37:%i", PORT_MASTER);
|
||||
NET_StringToAdr (idmaster, &master_adr[0]);
|
||||
/* heartbeats will always be sent to the id master */
|
||||
svs.last_heartbeat = -99999; /* send immediately */
|
||||
Com_sprintf( idmaster, sizeof ( idmaster ), "192.246.40.37:%i", PORT_MASTER );
|
||||
NET_StringToAdr( idmaster, &master_adr [ 0 ] );
|
||||
|
||||
// init game
|
||||
SV_InitGameProgs ();
|
||||
for (i=0 ; i<maxclients->value ; i++)
|
||||
/* init game */
|
||||
SV_InitGameProgs();
|
||||
|
||||
for ( i = 0; i < maxclients->value; i++ )
|
||||
{
|
||||
ent = EDICT_NUM(i+1);
|
||||
ent->s.number = i+1;
|
||||
svs.clients[i].edict = ent;
|
||||
memset (&svs.clients[i].lastcmd, 0, sizeof(svs.clients[i].lastcmd));
|
||||
ent = EDICT_NUM( i + 1 );
|
||||
ent->s.number = i + 1;
|
||||
svs.clients [ i ].edict = ent;
|
||||
memset( &svs.clients [ i ].lastcmd, 0, sizeof ( svs.clients [ i ].lastcmd ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
======================
|
||||
SV_Map
|
||||
|
||||
the full syntax is:
|
||||
|
||||
map [*]<map>$<startspot>+<nextserver>
|
||||
|
||||
command from the console or progs.
|
||||
Map can also be a.cin, .pcx, or .dm2 file
|
||||
Nextserver is used to allow a cinematic to play, then proceed to
|
||||
another level:
|
||||
|
||||
map tram.cin+jail_e3
|
||||
======================
|
||||
*/
|
||||
void SV_Map (qboolean attractloop, char *levelstring, qboolean loadgame)
|
||||
* the full syntax is:
|
||||
*
|
||||
* map [*]<map>$<startspot>+<nextserver>
|
||||
*
|
||||
* command from the console or progs.
|
||||
* Map can also be a.cin, .pcx, or .dm2 file
|
||||
* Nextserver is used to allow a cinematic to play, then proceed to
|
||||
* another level:
|
||||
*
|
||||
* map tram.cin+jail_e3
|
||||
*/
|
||||
void
|
||||
SV_Map ( qboolean attractloop, char *levelstring, qboolean loadgame )
|
||||
{
|
||||
char level[MAX_QPATH];
|
||||
char *ch;
|
||||
int l;
|
||||
char spawnpoint[MAX_QPATH];
|
||||
char level [ MAX_QPATH ];
|
||||
char *ch;
|
||||
int l;
|
||||
char spawnpoint [ MAX_QPATH ];
|
||||
|
||||
sv.loadgame = loadgame;
|
||||
sv.attractloop = attractloop;
|
||||
|
||||
if (sv.state == ss_dead && !sv.loadgame)
|
||||
SV_InitGame (); // the game is just starting
|
||||
if ( ( sv.state == ss_dead ) && !sv.loadgame )
|
||||
{
|
||||
SV_InitGame(); /* the game is just starting */
|
||||
}
|
||||
|
||||
strcpy (level, levelstring);
|
||||
strcpy( level, levelstring );
|
||||
|
||||
// if there is a + in the map, set nextserver to the remainder
|
||||
ch = strstr(level, "+");
|
||||
if (ch)
|
||||
/* if there is a + in the map, set nextserver to the remainder */
|
||||
ch = strstr( level, "+" );
|
||||
|
||||
if ( ch )
|
||||
{
|
||||
*ch = 0;
|
||||
Cvar_Set ("nextserver", va("gamemap \"%s\"", ch+1));
|
||||
Cvar_Set( "nextserver", va( "gamemap \"%s\"", ch + 1 ) );
|
||||
}
|
||||
else
|
||||
Cvar_Set ("nextserver", "");
|
||||
{
|
||||
Cvar_Set( "nextserver", "" );
|
||||
}
|
||||
|
||||
//ZOID special hack for end game screen in coop mode
|
||||
if (Cvar_VariableValue ("coop") && !Q_stricmp(level, "victory.pcx"))
|
||||
Cvar_Set ("nextserver", "gamemap \"*base1\"");
|
||||
/* hack for end game screen in coop mode */
|
||||
if ( Cvar_VariableValue( "coop" ) && !Q_stricmp( level, "victory.pcx" ) )
|
||||
{
|
||||
Cvar_Set( "nextserver", "gamemap \"*base1\"" );
|
||||
}
|
||||
|
||||
// if there is a $, use the remainder as a spawnpoint
|
||||
ch = strstr(level, "$");
|
||||
if (ch)
|
||||
/* if there is a $, use the remainder as a spawnpoint */
|
||||
ch = strstr( level, "$" );
|
||||
|
||||
if ( ch )
|
||||
{
|
||||
*ch = 0;
|
||||
strcpy (spawnpoint, ch+1);
|
||||
strcpy( spawnpoint, ch + 1 );
|
||||
}
|
||||
else
|
||||
spawnpoint[0] = 0;
|
||||
|
||||
// skip the end-of-unit flag if necessary
|
||||
if (level[0] == '*')
|
||||
memmove (level, level+1, strlen(level)+1);
|
||||
|
||||
l = strlen(level);
|
||||
if (l > 4 && !strcmp (level+l-4, ".cin") )
|
||||
{
|
||||
#ifndef DEDICATED_ONLY
|
||||
SCR_BeginLoadingPlaque (); // for local system
|
||||
#endif
|
||||
SV_BroadcastCommand ("changing\n");
|
||||
SV_SpawnServer (level, spawnpoint, ss_cinematic, attractloop, loadgame);
|
||||
spawnpoint [ 0 ] = 0;
|
||||
}
|
||||
else if (l > 4 && !strcmp (level+l-4, ".dm2") )
|
||||
|
||||
/* skip the end-of-unit flag if necessary */
|
||||
if ( level [ 0 ] == '*' )
|
||||
{
|
||||
memmove( level, level + 1, strlen( level ) + 1 );
|
||||
}
|
||||
|
||||
l = strlen( level );
|
||||
|
||||
if ( ( l > 4 ) && !strcmp( level + l - 4, ".cin" ) )
|
||||
{
|
||||
#ifndef DEDICATED_ONLY
|
||||
SCR_BeginLoadingPlaque (); // for local system
|
||||
SCR_BeginLoadingPlaque(); /* for local system */
|
||||
#endif
|
||||
SV_BroadcastCommand ("changing\n");
|
||||
SV_SpawnServer (level, spawnpoint, ss_demo, attractloop, loadgame);
|
||||
SV_BroadcastCommand( "changing\n" );
|
||||
SV_SpawnServer( level, spawnpoint, ss_cinematic, attractloop, loadgame );
|
||||
}
|
||||
else if (l > 4 && !strcmp (level+l-4, ".pcx") )
|
||||
else if ( ( l > 4 ) && !strcmp( level + l - 4, ".dm2" ) )
|
||||
{
|
||||
#ifndef DEDICATED_ONLY
|
||||
SCR_BeginLoadingPlaque (); // for local system
|
||||
SCR_BeginLoadingPlaque(); /* for local system */
|
||||
#endif
|
||||
SV_BroadcastCommand ("changing\n");
|
||||
SV_SpawnServer (level, spawnpoint, ss_pic, attractloop, loadgame);
|
||||
SV_BroadcastCommand( "changing\n" );
|
||||
SV_SpawnServer( level, spawnpoint, ss_demo, attractloop, loadgame );
|
||||
}
|
||||
else if ( ( l > 4 ) && !strcmp( level + l - 4, ".pcx" ) )
|
||||
{
|
||||
#ifndef DEDICATED_ONLY
|
||||
SCR_BeginLoadingPlaque(); /* for local system */
|
||||
#endif
|
||||
SV_BroadcastCommand( "changing\n" );
|
||||
SV_SpawnServer( level, spawnpoint, ss_pic, attractloop, loadgame );
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef DEDICATED_ONLY
|
||||
SCR_BeginLoadingPlaque (); // for local system
|
||||
SCR_BeginLoadingPlaque(); /* for local system */
|
||||
#endif
|
||||
SV_BroadcastCommand ("changing\n");
|
||||
SV_SendClientMessages ();
|
||||
SV_SpawnServer (level, spawnpoint, ss_game, attractloop, loadgame);
|
||||
Cbuf_CopyToDefer ();
|
||||
SV_BroadcastCommand( "changing\n" );
|
||||
SV_SendClientMessages();
|
||||
SV_SpawnServer( level, spawnpoint, ss_game, attractloop, loadgame );
|
||||
Cbuf_CopyToDefer();
|
||||
}
|
||||
|
||||
SV_BroadcastCommand ("reconnect\n");
|
||||
SV_BroadcastCommand( "reconnect\n" );
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue