static qbool SV_CanSave(void)
{
prvm_prog_t *prog = SVVM_prog;
- if(SV_IsLocalGame() == 1)
+ if(SV_IsLocalServer() == 1)
{
// singleplayer checks
- if (!(svs.clients[0].active && PRVM_serveredictfloat(svs.clients[0].edict, deadflag)))
+ if ((svs.clients[0].active && PRVM_serveredictfloat(svs.clients[0].edict, deadflag)))
{
Con_Print("Can't savegame with a dead player\n");
return false;
}
- if(!host.hook.CL_Intermission || !host.hook.CL_Intermission())
+ if(host.hook.CL_Intermission && host.hook.CL_Intermission())
{
Con_Print("Can't save in intermission.\n");
return false;
}
+static void SV_ServerOptions (void)
+{
+ int i;
+
+ // general default
+ svs.maxclients = 8;
+
+// COMMANDLINEOPTION: Server: -dedicated [playerlimit] starts a dedicated server (with a command console), default playerlimit is 8
+// COMMANDLINEOPTION: Server: -listen [playerlimit] starts a multiplayer server with graphical client, like singleplayer but other players can connect, default playerlimit is 8
+ // if no client is in the executable or -dedicated is specified on
+ // commandline, start a dedicated server
+ i = Sys_CheckParm ("-dedicated");
+ if (i || !cl_available)
+ {
+ cls.state = ca_dedicated;
+ // check for -dedicated specifying how many players
+ if (i && i + 1 < sys.argc && atoi (sys.argv[i+1]) >= 1)
+ svs.maxclients = atoi (sys.argv[i+1]);
+ if (Sys_CheckParm ("-listen"))
+ Con_Printf ("Only one of -dedicated or -listen can be specified\n");
+ // default sv_public on for dedicated servers (often hosted by serious administrators), off for listen servers (often hosted by clueless users)
+ Cvar_SetValue(&cvars_all, "sv_public", 1);
+ }
+ else if (cl_available)
+ {
+ // client exists and not dedicated, check if -listen is specified
+ cls.state = ca_disconnected;
+ i = Sys_CheckParm ("-listen");
+ if (i)
+ {
+ // default players unless specified
+ if (i + 1 < sys.argc && atoi (sys.argv[i+1]) >= 1)
+ svs.maxclients = atoi (sys.argv[i+1]);
+ }
+ else
+ {
+ // default players in some games, singleplayer in most
+ if (gamemode != GAME_GOODVSBAD2 && !IS_NEXUIZ_DERIVED(gamemode) && gamemode != GAME_BATTLEMECH)
+ svs.maxclients = 1;
+ }
+ }
+
+ svs.maxclients = svs.maxclients_next = bound(1, svs.maxclients, MAX_SCOREBOARD);
+
+ svs.clients = (client_t *)Mem_Alloc(sv_mempool, sizeof(client_t) * svs.maxclients);
+
+ if (svs.maxclients > 1 && !deathmatch.integer && !coop.integer)
+ Cvar_SetValueQuick(&deathmatch, 1);
+}
+
/*
===============
SV_Init
host.hook.SV_CanSave = SV_CanSave;
sv_mempool = Mem_AllocPool("server", 0, NULL);
+
+ SV_ServerOptions();
}
static void SV_SaveEntFile_f(cmd_state_t *cmd)
*/
int SV_ModelIndex(const char *s, int precachemode)
{
- int i, limit = ((sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3) ? 256 : MAX_MODELS);
+ int i, limit = ((sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE) ? 256 : MAX_MODELS);
char filename[MAX_QPATH];
if (!s || !*s)
return 0;
*/
int SV_SoundIndex(const char *s, int precachemode)
{
- int i, limit = ((sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3) ? 256 : MAX_SOUNDS);
+ int i, limit = ((sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_NEHAHRABJP) ? 256 : MAX_SOUNDS);
char filename[MAX_QPATH];
if (!s || !*s)
return 0;
return 0;
}
-dp_model_t *SV_GetModelByIndex(int modelindex)
+model_t *SV_GetModelByIndex(int modelindex)
{
return (modelindex > 0 && modelindex < MAX_MODELS) ? sv.models[modelindex] : NULL;
}
-dp_model_t *SV_GetModelFromEdict(prvm_edict_t *ed)
+model_t *SV_GetModelFromEdict(prvm_edict_t *ed)
{
prvm_prog_t *prog = SVVM_prog;
int modelindex;
}
}
-qbool SV_IsLocalServer(void)
+// Returns 1 if we're singleplayer, > 1 if we're a listen server
+int SV_IsLocalServer(void)
{
- if(host_isclient.integer && host_client && LHNETADDRESS_GetAddressType(&host_client->netconnection->peeraddress) == LHNETADDRESSTYPE_LOOP)
- return true;
- return false;
+ return (host_isclient.integer && sv.active ? svs.maxclients : 0);
}
/*
prvm_edict_t *ent;
int i;
char *entities;
- dp_model_t *worldmodel;
+ model_t *worldmodel;
char modelname[sizeof(sv.worldname)];
char vabuf[1024];
// SV_UnlockThreadMutex();
}
-/*
- * Returns number of slots if we're a listen server.
- * Returns 0 if we're a dedicated server.
- */
-int SV_IsLocalGame(void)
-{
- if (sv.active && LHNETADDRESS_GetAddressType(&host_client->netconnection->peeraddress) == LHNETADDRESSTYPE_LOOP)
- return svs.maxclients;
- return 0;
-}
-
/*
==================
SV_Shutdown
SV_Prepare_CSQC();
}
+static void SV_CheckTimeouts(void)
+{
+ int i;
+
+ // never timeout loopback connections
+ for (i = (host_isclient.integer ? 1 : 0), host_client = &svs.clients[i]; i < svs.maxclients; i++, host_client++)
+ {
+ if (host_client->netconnection && host.realtime > host_client->netconnection->timeout)
+ {
+ Con_Printf("Client \"%s\" connection timed out\n", host_client->name);
+ SV_DropClient(false);
+ }
+ }
+}
+
extern cvar_t host_maxwait;
extern cvar_t host_framerate;
extern cvar_t cl_maxphysicsframesperserverframe;
* be undersleeping due to select() detecting a new packet
*/
if (sv.active)
+ {
NetConn_ServerFrame();
+ SV_CheckTimeouts();
+ }
}
/*
// get new packets
if (sv.active)
+ {
NetConn_ServerFrame();
+ SV_CheckTimeouts();
+ }
// if the accumulators haven't become positive yet, wait a while
wait = sv_timer * -1000000.0;