================
*/
char hosterrorstring[4096];
+extern char sv_spawnmap[MAX_QPATH];
+extern char sv_loadgame[MAX_OSPATH];
void Host_Error (const char *error, ...)
{
va_list argptr;
static qboolean inerror = false;
+ // make sure we don't get in a loading loop
+ sv_loadgame[0] = 0;
+ sv_spawnmap[0] = 0;
+
// LordHavoc: if first frame has not been shown, or currently shutting
// down, do Sys_Error instead
if (!host_loopactive || host_shuttingdown)
va_end (argptr);
Con_Printf ("Host_Error: %s\n",hosterrorstring);
+ CL_Parse_DumpPacket();
+
PR_Crash();
if (sv.active)
CL_Disconnect ();
cls.demonum = -1;
+ // unload any partially loaded models
+ Mod_ClearErrorModels();
+
inerror = false;
longjmp (host_abortserver, 1);
{
int i, numplayers;
- numplayers = 1;
-
- i = COM_CheckParm ("-dedicated");
- if (i)
+ if (cl_available)
{
- cls.state = ca_dedicated;
- numplayers = 0;
- if (i != (com_argc - 1))
- numplayers = atoi (com_argv[i+1]);
+ // client exists, check what mode the user wants
+ i = COM_CheckParm ("-dedicated");
+ if (i)
+ {
+ cls.state = ca_dedicated;
+ numplayers = 8;
+ if (i != (com_argc - 1))
+ numplayers = atoi (com_argv[i+1]);
+ if (COM_CheckParm ("-listen"))
+ Sys_Error ("Only one of -dedicated or -listen can be specified");
+ }
+ else
+ {
+ numplayers = 1;
+ cls.state = ca_disconnected;
+ i = COM_CheckParm ("-listen");
+ if (i)
+ {
+ numplayers = 8;
+ if (i != (com_argc - 1))
+ numplayers = atoi (com_argv[i+1]);
+ }
+ }
}
else
- cls.state = ca_disconnected;
-
- i = COM_CheckParm ("-listen");
- if (i)
{
- if (cls.state == ca_dedicated)
- Sys_Error ("Only one of -dedicated or -listen can be specified");
- numplayers = 0;
- if (i != (com_argc - 1))
+ // no client in the executable, start dedicated server
+ if (COM_CheckParm ("-listen"))
+ Sys_Error ("-listen not available in a dedicated server executable");
+ numplayers = 8;
+ cls.state = ca_dedicated;
+ // check for -dedicated specifying how many players
+ i = COM_CheckParm ("-dedicated");
+ if (i && i != (com_argc - 1))
numplayers = atoi (com_argv[i+1]);
}
*/
void Host_WriteConfiguration (void)
{
- QFile *f;
+ qfile_t *f;
// dedicated servers initialize the host but don't parse and set the
// config.cfg cvars
if (host_initialized && cls.state != ca_dedicated)
{
- f = Qopen (va("%s/config.cfg",com_gamedir), "w");
+ f = FS_Open ("config.cfg", "w", false);
if (!f)
{
Con_Printf ("Couldn't write config.cfg.\n");
Key_WriteBindings (f);
Cvar_WriteVariables (f);
- Qclose (f);
+ FS_Close (f);
}
}
int i;
client_t *client;
+ Con_Printf ("Client \"%s\" dropped\n", host_client->name);
+
if (!crash)
{
// send any final messages (don't check for errors)
- if (NET_CanSendMessage (host_client->netconnection))
+ if (host_client->netconnection && !host_client->netconnection->disconnected)
{
+#if 1
+ // LordHavoc: no opportunity for resending, so reliable is silly
MSG_WriteByte (&host_client->message, svc_disconnect);
- NET_SendMessage (host_client->netconnection, &host_client->message);
- }
-
- if (sv.active && host_client->edict && host_client->spawned) // LordHavoc: don't call QC if server is dead (avoids recursive Host_Error in some mods when they run out of edicts)
- {
- // call the prog function for removing a client
- // this will set the body to a dead frame, among other things
- saveSelf = pr_global_struct->self;
- pr_global_struct->self = EDICT_TO_PROG(host_client->edict);
- PR_ExecuteProgram (pr_global_struct->ClientDisconnect, "QC function ClientDisconnect is missing");
- pr_global_struct->self = saveSelf;
+ NET_SendUnreliableMessage (host_client->netconnection, &host_client->message);
+#else
+ if (NET_CanSendMessage (host_client->netconnection))
+ {
+ MSG_WriteByte (&host_client->message, svc_disconnect);
+ NET_SendMessage (host_client->netconnection, &host_client->message);
+ }
+#endif
}
-
- Sys_Printf ("Client %s removed\n",host_client->name);
}
// break the net connection
// free the client (the body stays around)
host_client->active = false;
+ // note: don't clear name yet
+ net_activeconnections--;
+
+ if (sv.active && host_client->edict && host_client->spawned) // LordHavoc: don't call QC if server is dead (avoids recursive Host_Error in some mods when they run out of edicts)
+ {
+ // call the prog function for removing a client
+ // this will set the body to a dead frame, among other things
+ saveSelf = pr_global_struct->self;
+ pr_global_struct->self = EDICT_TO_PROG(host_client->edict);
+ PR_ExecuteProgram (pr_global_struct->ClientDisconnect, "QC function ClientDisconnect is missing");
+ pr_global_struct->self = saveSelf;
+ }
+
+ // now clear name (after ClientDisconnect was called)
host_client->name[0] = 0;
host_client->old_frags = -999999;
- net_activeconnections--;
-// send notification to all clients
+ // send notification to all clients
for (i=0, client = svs.clients ; i<svs.maxclients ; i++, client++)
{
if (!client->active)
MSG_WriteByte (&client->message, host_client - svs.clients);
MSG_WriteByte (&client->message, 0);
}
+
+ NET_Heartbeat (1);
}
/*
// stop all client sounds immediately
CL_Disconnect ();
+ NET_Heartbeat (2);
+ NET_Heartbeat (2);
+
// flush any pending messages - like the score!!!
start = Sys_DoubleTime();
do
for (i=0, host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
if (host_client->active)
- SV_DropClient(crash);
+ SV_DropClient(crash); // server shutdown
//
// clear structures
// send all messages to the clients
SV_SendClientMessages ();
+
+// send an heartbeat if enough time has passed since the last one
+ NET_Heartbeat (0);
}
// process console commands
Cbuf_Execute ();
+ // LordHavoc: map and load are delayed until video is initialized
+ Host_PerformSpawnServerAndLoadGame();
+
NET_Poll();
// if running the server locally, make intentions now
time1 = Sys_DoubleTime ();
_Host_Frame (time);
- time2 = Sys_DoubleTime ();
-
+ time2 = Sys_DoubleTime ();
+
timetotal += time2 - time1;
timecount++;
-
+
if (timecount < 1000)
return;
//============================================================================
void Render_Init(void);
-void QuakeIO_Init(void);
/*
====================
Memory_Init_Commands();
R_Modules_Init();
Cbuf_Init ();
- QuakeIO_Init ();
V_Init ();
COM_Init ();
Host_InitLocal ();
if (cls.state != ca_dedicated)
{
- VID_InitCvars();
-
- Gamma_Init();
-
Palette_Init();
-
-#ifndef _WIN32 // on non win32, mouse comes before video for security reasons
- IN_Init ();
-#endif
- VID_Init (vid_fullscreen.integer, vid_width.integer, vid_height.integer);
+ VID_Shared_Init();
+ VID_Init();
Render_Init();
S_Init ();
CDAudio_Init ();
- Sbar_Init ();
CL_Init ();
-#ifdef _WIN32 // on non win32, mouse comes before video for security reasons
- IN_Init ();
-#endif
}
Cbuf_InsertText ("exec quake.rc\n");
+ Cbuf_Execute ();
+ Cbuf_Execute ();
+ Cbuf_Execute ();
+ Cbuf_Execute ();
host_initialized = true;
-
- Sys_Printf ("========Quake Initialized=========\n");
+
+ Con_Printf ("========Quake Initialized=========\n");
+
+ if (cls.state != ca_dedicated)
+ VID_Open();
}
void Host_Shutdown(void)
{
static qboolean isdown = false;
-
+
if (isdown)
{
- printf ("recursive shutdown\n");
+ Con_Printf ("recursive shutdown\n");
return;
}
isdown = true;
- Host_WriteConfiguration ();
+ Host_WriteConfiguration ();
CDAudio_Shutdown ();
NET_Shutdown ();
S_Shutdown();
- IN_Shutdown ();
if (cls.state != ca_dedicated)
{