📄 host.c
字号:
/*
=================
SV_BroadcastPrintf
Sends text to all active clients
=================
*/
void SV_BroadcastPrintf (char *fmt, ...)
{
va_list argptr;
char string[1024];
int i;
va_start (argptr,fmt);
vsprintf (string, fmt,argptr);
va_end (argptr);
for (i=0 ; i<svs.maxclients ; i++)
if (svs.clients[i].active && svs.clients[i].spawned)
{
MSG_WriteByte (&svs.clients[i].message, svc_print);
MSG_WriteString (&svs.clients[i].message, string);
}
}
/*
=================
Host_ClientCommands
Send text over to the client to be executed
=================
*/
void Host_ClientCommands (char *fmt, ...)
{
va_list argptr;
char string[1024];
va_start (argptr,fmt);
vsprintf (string, fmt,argptr);
va_end (argptr);
MSG_WriteByte (&host_client->message, svc_stufftext);
MSG_WriteString (&host_client->message, string);
}
/*
=====================
SV_DropClient
Called when the player is getting totally kicked off the host
if (crash = true), don't bother sending signofs
=====================
*/
void SV_DropClient (qboolean crash)
{
int saveSelf;
int i;
client_t *client;
if (!crash)
{
// send any final messages (don't check for errors)
if (NET_CanSendMessage (host_client->netconnection))
{
MSG_WriteByte (&host_client->message, svc_disconnect);
NET_SendMessage (host_client->netconnection, &host_client->message);
}
if (host_client->edict && host_client->spawned)
{
// 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);
pr_global_struct->self = saveSelf;
}
Sys_Printf ("Client %s removed\n",host_client->name);
}
// break the net connection
NET_Close (host_client->netconnection);
host_client->netconnection = NULL;
// free the client (the body stays around)
host_client->active = false;
host_client->name[0] = 0;
host_client->old_frags = -999999;
net_activeconnections--;
// send notification to all clients
for (i=0, client = svs.clients ; i<svs.maxclients ; i++, client++)
{
if (!client->active)
continue;
MSG_WriteByte (&client->message, svc_updatename);
MSG_WriteByte (&client->message, host_client - svs.clients);
MSG_WriteString (&client->message, "");
MSG_WriteByte (&client->message, svc_updatefrags);
MSG_WriteByte (&client->message, host_client - svs.clients);
MSG_WriteShort (&client->message, 0);
MSG_WriteByte (&client->message, svc_updatecolors);
MSG_WriteByte (&client->message, host_client - svs.clients);
MSG_WriteByte (&client->message, 0);
}
}
/*
==================
Host_ShutdownServer
This only happens at the end of a game, not between levels
==================
*/
void Host_ShutdownServer(qboolean crash)
{
int i;
int count;
sizebuf_t buf;
char message[4];
double start;
if (!sv.active)
return;
sv.active = false;
// stop all client sounds immediately
if (cls.state == ca_connected)
CL_Disconnect ();
// flush any pending messages - like the score!!!
start = Sys_FloatTime();
do
{
count = 0;
for (i=0, host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
{
if (host_client->active && host_client->message.cursize)
{
if (NET_CanSendMessage (host_client->netconnection))
{
NET_SendMessage(host_client->netconnection, &host_client->message);
SZ_Clear (&host_client->message);
}
else
{
NET_GetMessage(host_client->netconnection);
count++;
}
}
}
if ((Sys_FloatTime() - start) > 3.0)
break;
}
while (count);
// make sure all the clients know we're disconnecting
buf.data = message;
buf.maxsize = 4;
buf.cursize = 0;
MSG_WriteByte(&buf, svc_disconnect);
count = NET_SendToAll(&buf, 5);
if (count)
Con_Printf("Host_ShutdownServer: NET_SendToAll failed for %u clients\n", count);
for (i=0, host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
if (host_client->active)
SV_DropClient(crash);
//
// clear structures
//
memset (&sv, 0, sizeof(sv));
memset (svs.clients, 0, svs.maxclientslimit*sizeof(client_t));
}
/*
================
Host_ClearMemory
This clears all the memory used by both the client and server, but does
not reinitialize anything.
================
*/
void Host_ClearMemory (void)
{
Con_DPrintf ("Clearing memory\n");
D_FlushCaches ();
Mod_ClearAll ();
if (host_hunklevel)
Hunk_FreeToLowMark (host_hunklevel);
cls.signon = 0;
memset (&sv, 0, sizeof(sv));
memset (&cl, 0, sizeof(cl));
}
//============================================================================
/*
===================
Host_FilterTime
Returns false if the time is too short to run a frame
===================
*/
qboolean Host_FilterTime (float time)
{
realtime += time;
// 2001-12-16 MAX_FPS cvar by MrG start
// if (!cls.timedemo && realtime - oldrealtime < 1.0/72.0)
if (max_fps->value < 10) Cvar_Set(max_fps, "72");
if (!cls.timedemo && realtime - oldrealtime < 1.0/max_fps->value)
// 2001-12-16 MAX_FPS cvar by MrG end
return false; // framerate is too high
// 2001-10-20 TIMESCALE extension by Tomaz/Maddes start
// host_frametime = realtime - oldrealtime;
host_cpu_frametime = realtime - oldrealtime;
host_org_frametime = host_cpu_frametime;
// 2001-10-20 TIMESCALE extension by Tomaz/Maddes end
oldrealtime = realtime;
if (host_framerate->value > 0)
// 2001-10-20 TIMESCALE extension by Tomaz/Maddes start
{
// host_frametime = host_framerate->value;
host_org_frametime = host_framerate->value;
}
// 2001-10-20 TIMESCALE extension by Tomaz/Maddes end
else
{ // don't allow really long or short frames
// 2001-10-20 TIMESCALE extension by Tomaz/Maddes start
/*
if (host_frametime > 0.1)
host_frametime = 0.1;
if (host_frametime < 0.001)
host_frametime = 0.001;
*/
if (host_org_frametime > 0.1)
host_org_frametime = 0.1;
if (host_org_frametime < 0.001)
host_org_frametime = 0.001;
// 2001-10-20 TIMESCALE extension by Tomaz/Maddes end
}
host_frametime = host_org_frametime * host_timescale->value; // 2001-10-20 TIMESCALE extension by Tomaz/Maddes
return true;
}
/*
===================
Host_GetConsoleCommands
Add them exactly as if they had been typed at the console
===================
*/
void Host_GetConsoleCommands (void)
{
char *cmd;
while (1)
{
cmd = Sys_ConsoleInput ();
if (!cmd)
break;
Cbuf_AddText (cmd);
}
}
/*
==================
Host_ServerFrame
==================
*/
#ifdef FPS_20
void _Host_ServerFrame (void)
{
// run the world state
pr_global_struct->frametime = host_frametime;
// 2001-10-20 TIMESCALE extension by Tomaz/Maddes start
if (pr_global_cpu_frametime)
{
G_FLOAT(pr_global_cpu_frametime->ofs) = host_cpu_frametime;
}
if (pr_global_org_frametime)
{
G_FLOAT(pr_global_org_frametime->ofs) = host_org_frametime;
}
// 2001-10-20 TIMESCALE extension by Tomaz/Maddes end
// read client messages
SV_RunClients ();
// move things around and think
// always pause in single player if in console or menus
if (!sv.paused && (svs.maxclients > 1 || key_dest == key_game) )
SV_Physics ();
}
void Host_ServerFrame (void)
{
float save_host_frametime;
float temp_host_frametime;
int i; // 2000-05-02 NVS SVC by Maddes
// run the world state
pr_global_struct->frametime = host_frametime;
// 2001-10-20 TIMESCALE extension by Tomaz/Maddes start
if (pr_global_cpu_frametime)
{
G_FLOAT(pr_global_cpu_frametime->ofs) = host_cpu_frametime;
}
if (pr_global_org_frametime)
{
G_FLOAT(pr_global_org_frametime->ofs) = host_org_frametime;
}
// 2001-10-20 TIMESCALE extension by Tomaz/Maddes end
// set the time and clear the general datagram
SV_ClearDatagram ();
// 2000-05-02 NVS SVC by Maddes start
// clear existing clients
for (i=0 ; i<svs.maxclients ; i++)
{
if (svs.clients[i].active)
{
SZ_Clear (&svs.clients[i].datagram);
}
}
// 2000-05-02 NVS SVC by Maddes end
// check for new clients
SV_CheckForNewClients ();
temp_host_frametime = save_host_frametime = host_frametime;
while(temp_host_frametime > (1.0/72.0))
{
if (temp_host_frametime > 0.05)
host_frametime = 0.05;
else
host_frametime = temp_host_frametime;
temp_host_frametime -= host_frametime;
_Host_ServerFrame ();
}
host_frametime = save_host_frametime;
// send all messages to the clients
SV_SendClientMessages ();
}
#else
void Host_ServerFrame (void)
{
int i; // 2000-05-02 NVS SVC by Maddes
// run the world state
pr_global_struct->frametime = host_frametime;
// 2001-10-20 TIMESCALE extension by Tomaz/Maddes start
if (pr_global_cpu_frametime)
{
G_FLOAT(pr_global_cpu_frametime->ofs) = host_cpu_frametime;
}
if (pr_global_org_frametime)
{
G_FLOAT(pr_global_org_frametime->ofs) = host_org_frametime;
}
// 2001-10-20 TIMESCALE extension by Tomaz/Maddes end
// set the time and clear the general datagram
SV_ClearDatagram ();
// 2000-05-02 NVS SVC by Maddes start
// clear existing clients
for (i=0 ; i<svs.maxclients ; i++)
{
if (svs.clients[i].active)
{
SZ_Clear (&svs.clients[i].datagram);
}
}
// 2000-05-02 NVS SVC by Maddes end
// check for new clients
SV_CheckForNewClients ();
// read client messages
SV_RunClients ();
// move things around and think
// always pause in single player if in console or menus
if (!sv.paused && (svs.maxclients > 1 || key_dest == key_game) )
SV_Physics ();
// send all messages to the clients
SV_SendClientMessages ();
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -