// common.c -- misc functions used in client and server #include <u.h>#include <libc.h>#include <stdio.h>#include "dat.h"#include "fns.h" #define MAXPRINTMSG 4096 #define MAX_NUM_ARGVS 50 int com_argc;char *com_argv[MAX_NUM_ARGVS+1]; int realtime; jmp_buf abortframe; // an ERR_DROP occured, exit the entire frame FILE *log_stats_file; cvar_t *host_speeds;cvar_t *log_stats;cvar_t *developer;cvar_t *timescale;cvar_t *fixedtime;cvar_t *logfile_active; // 1 = buffer log, 2 = flush after each printcvar_t *showtrace;cvar_t *dedicated; FILE *logfile; int server_state; // host_speeds timesint time_before_game;int time_after_game;int time_before_ref;int time_after_ref; /*============================================================================ CLIENT / SERVER interactions ============================================================================*/ static int rd_target;static char *rd_buffer;static int rd_buffersize;static void (*rd_flush)(int target, char *buffer); void Com_BeginRedirect (int target, char *buffer, int buffersize, void (*flush)){ if (!target || !buffer || !buffersize || !flush) return; rd_target = target; rd_buffer = buffer; rd_buffersize = buffersize; rd_flush = flush; *rd_buffer = 0;} void Com_EndRedirect (void){ rd_flush(rd_target, rd_buffer); rd_target = 0; rd_buffer = NULL; rd_buffersize = 0; rd_flush = NULL;} /*=============Com_Printf Both client and server can use this, and it will outputto the apropriate place.=============*/void Com_Printf (char *fmt, ...){ va_list argptr; char msg[MAXPRINTMSG]; va_start (argptr,fmt); vsprintf (msg,fmt,argptr); va_end (argptr); if (rd_target) { if ((strlen (msg) + strlen(rd_buffer)) > (rd_buffersize - 1)) { rd_flush(rd_target, rd_buffer); *rd_buffer = 0; } strcat (rd_buffer, msg); return; } Con_Print (msg); // also echo to debugging console Sys_ConsoleOutput (msg); // logfile if (logfile_active && logfile_active->value) { char name[MAX_QPATH]; if (!logfile) { Com_sprintf (name, sizeof(name), "%s/qconsole.log", FS_Gamedir ()); logfile = fopen (name, "w"); } if (logfile) fprintf (logfile, "%s", msg); if (logfile_active->value > 1) fflush (logfile); // force it to save every time }} /*================Com_DPrintf A Com_Printf that only shows up if the "developer" cvar is set================*/void Com_DPrintf (char *fmt, ...){ va_list argptr; char msg[MAXPRINTMSG]; if (!developer || !developer->value) return; // don't confuse non-developers with techie stuff... va_start (argptr,fmt); vsprintf (msg,fmt,argptr); va_end (argptr); Com_Printf ("%s", msg);} /*=============Com_Error Both client and server can use this, and it willdo the apropriate things.=============*/void Com_Error (int code, char *fmt, ...){ va_list argptr; static char msg[MAXPRINTMSG]; static qboolean recursive; if (recursive) Sys_Error ("recursive error after: %s", msg); recursive = true; va_start (argptr,fmt); vsprintf (msg,fmt,argptr); va_end (argptr); if (code == ERR_DISCONNECT) { CL_Drop (); recursive = false; longjmp (abortframe, -1); } else if (code == ERR_DROP) { Com_Printf ("********************\nERROR: %s\n********************\n", msg); SV_Shutdown (va("Server crashed: %s\n", msg), false); CL_Drop (); recursive = false; longjmp (abortframe, -1); } else { SV_Shutdown (va("Server fatal crashed: %s\n", msg), false); CL_Shutdown (); } if (logfile) { fclose (logfile); logfile = NULL; } Sys_Error ("%s", msg);} /*=============Com_Quit Both client and server can use this, and it willdo the apropriate things.=============*/void Com_Quit (void){ SV_Shutdown ("Server quit\n", false); CL_Shutdown (); if (logfile) { fclose (logfile); logfile = NULL; } Sys_Quit ();} /*==================Com_ServerState==================*/// this should've just been a cvar...int Com_ServerState (void){ return server_state;} /*==================Com_SetServerState==================*/void Com_SetServerState (int state){ server_state = state;} /*============================================================================== MESSAGE IO FUNCTIONS Handles byte ordering and avoids alignment errors==============================================================================*/ vec3_t bytedirs[NUMVERTEXNORMALS] ={#include "anorms.h"}; //// writing functions// void MSG_WriteChar (sizebuf_t *sb, int c){ byte *buf; #ifdef PARANOID if (c < -128 || c > 127) Com_Error (ERR_FATAL, "MSG_WriteChar: range error");#endif buf = SZ_GetSpace (sb, 1); buf[0] = c;} void MSG_WriteByte (sizebuf_t *sb, int c){ byte *buf; #ifdef PARANOID if (c < 0 || c > 255) Com_Error (ERR_FATAL, "MSG_WriteByte: range error");#endif buf = SZ_GetSpace (sb, 1); buf[0] = c;} void MSG_WriteShort (sizebuf_t *sb, int c){ byte *buf; #ifdef PARANOID if (c < ((short)0x8000) || c > (short)0x7fff) Com_Error (ERR_FATAL, "MSG_WriteShort: range error");#endif buf = SZ_GetSpace (sb, 2); buf[0] = c&0xff; buf[1] = c>>8;} void MSG_WriteLong (sizebuf_t *sb, int c){ byte *buf; buf = SZ_GetSpace (sb, 4); buf[0] = c&0xff; buf[1] = (c>>8)&0xff; buf[2] = (c>>16)&0xff; buf[3] = c>>24;} void MSG_WriteFloat (sizebuf_t *sb, float f){ union { float f; int l; } dat; dat.f = f; dat.l = LittleLong (dat.l); SZ_Write (sb, &dat.l, 4);} void MSG_WriteString (sizebuf_t *sb, char *s){ if (!s) SZ_Write (sb, "", 1); else SZ_Write (sb, s, strlen(s)+1);} void MSG_WriteCoord (sizebuf_t *sb, float f){ MSG_WriteShort (sb, (int)(f*8));} void MSG_WritePos (sizebuf_t *sb, vec3_t pos){ MSG_WriteShort (sb, (int)(pos[0]*8)); MSG_WriteShort (sb, (int)(pos[1]*8)); MSG_WriteShort (sb, (int)(pos[2]*8));} void MSG_WriteAngle (sizebuf_t *sb, float f){ MSG_WriteByte (sb, (int)(f*256/360) & 255);} void MSG_WriteAngle16 (sizebuf_t *sb, float f){ MSG_WriteShort (sb, ANGLE2SHORT(f));} void MSG_WriteDeltaUsercmd (sizebuf_t *buf, usercmd_t *from, usercmd_t *cmd){ int bits; //// send the movement message// bits = 0; if (cmd->angles[0] != from->angles[0]) bits |= CM_ANGLE1; if (cmd->angles[1] != from->angles[1]) bits |= CM_ANGLE2; if (cmd->angles[2] != from->angles[2]) bits |= CM_ANGLE3; if (cmd->forwardmove != from->forwardmove) bits |= CM_FORWARD; if (cmd->sidemove != from->sidemove) bits |= CM_SIDE; if (cmd->upmove != from->upmove) bits |= CM_UP; if (cmd->buttons != from->buttons) bits |= CM_BUTTONS; if (cmd->impulse != from->impulse) bits |= CM_IMPULSE; MSG_WriteByte (buf, bits); if (bits & CM_ANGLE1) MSG_WriteShort (buf, cmd->angles[0]); if (bits & CM_ANGLE2) MSG_WriteShort (buf, cmd->angles[1]); if (bits & CM_ANGLE3) MSG_WriteShort (buf, cmd->angles[2]); if (bits & CM_FORWARD) MSG_WriteShort (buf, cmd->forwardmove); if (bits & CM_SIDE) MSG_WriteShort (buf, cmd->sidemove); if (bits & CM_UP) MSG_WriteShort (buf, cmd->upmove); if (bits & CM_BUTTONS) MSG_WriteByte (buf, cmd->buttons); if (bits & CM_IMPULSE) MSG_WriteByte (buf, cmd->impulse); MSG_WriteByte (buf, cmd->msec); MSG_WriteByte (buf, cmd->lightlevel);} void MSG_WriteDir (sizebuf_t *sb, vec3_t dir){ int i, best; float d, bestd; if (!dir) { MSG_WriteByte (sb, 0); return; } bestd = 0; best = 0; for (i=0 ; i<NUMVERTEXNORMALS ; i++) { d = DotProduct (dir, bytedirs[i]); if (d > bestd) { bestd = d; best = i; } } MSG_WriteByte (sb, best);} void MSG_ReadDir (sizebuf_t *sb, vec3_t dir){ int b; b = MSG_ReadByte (sb); if (b >= NUMVERTEXNORMALS) Com_Error (ERR_DROP, "MSF_ReadDir: out of range"); VectorCopy (bytedirs[b], dir);} /*==================MSG_WriteDeltaEntity Writes part of a packetentities message.Can delta from either a baseline or a previous packet_entity==================*/void MSG_WriteDeltaEntity (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qboolean force, qboolean newentity){ int bits; if (!to->number) Com_Error (ERR_FATAL, "Unset entity number"); if (to->number >= MAX_EDICTS) Com_Error (ERR_FATAL, "Entity number >= MAX_EDICTS"); // send an update bits = 0; if (to->number >= 256) bits |= U_NUMBER16; // number8 is implicit otherwise if (to->origin[0] != from->origin[0]) bits |= U_ORIGIN1; if (to->origin[1] != from->origin[1]) bits |= U_ORIGIN2; if (to->origin[2] != from->origin[2]) bits |= U_ORIGIN3; if ( to->angles[0] != from->angles[0] ) bits |= U_ANGLE1; if ( to->angles[1] != from->angles[1] ) bits |= U_ANGLE2; if ( to->angles[2] != from->angles[2] ) bits |= U_ANGLE3; if ( to->skinnum != from->skinnum ) { if ((unsigned)to->skinnum < 256) bits |= U_SKIN8; else if ((unsigned)to->skinnum < 0x10000) bits |= U_SKIN16; else bits |= (U_SKIN8|U_SKIN16); } Lines 1–500 of 1573. Load more
// common.c -- misc functions used in client and server #include <u.h> #include <libc.h> #include <stdio.h> #include "dat.h" #include "fns.h" #define MAXPRINTMSG 4096 #define MAX_NUM_ARGVS 50 int com_argc; char *com_argv[MAX_NUM_ARGVS+1]; int realtime; jmp_buf abortframe; // an ERR_DROP occured, exit the entire frame FILE *log_stats_file; cvar_t *host_speeds; cvar_t *log_stats; cvar_t *developer; cvar_t *timescale; cvar_t *fixedtime; cvar_t *logfile_active; // 1 = buffer log, 2 = flush after each print cvar_t *showtrace; cvar_t *dedicated; FILE *logfile; int server_state; // host_speeds times int time_before_game; int time_after_game; int time_before_ref; int time_after_ref; /* ============================================================================ CLIENT / SERVER interactions ============================================================================ */ static int rd_target; static char *rd_buffer; static int rd_buffersize; static void (*rd_flush)(int target, char *buffer); void Com_BeginRedirect (int target, char *buffer, int buffersize, void (*flush)) { if (!target || !buffer || !buffersize || !flush) return; rd_target = target; rd_buffer = buffer; rd_buffersize = buffersize; rd_flush = flush; *rd_buffer = 0; } void Com_EndRedirect (void) { rd_flush(rd_target, rd_buffer); rd_target = 0; rd_buffer = NULL; rd_buffersize = 0; rd_flush = NULL; } /* ============= Com_Printf Both client and server can use this, and it will output to the apropriate place. ============= */ void Com_Printf (char *fmt, ...) { va_list argptr; char msg[MAXPRINTMSG]; va_start (argptr,fmt); vsprintf (msg,fmt,argptr); va_end (argptr); if (rd_target) { if ((strlen (msg) + strlen(rd_buffer)) > (rd_buffersize - 1)) { rd_flush(rd_target, rd_buffer); *rd_buffer = 0; } strcat (rd_buffer, msg); return; } Con_Print (msg); // also echo to debugging console Sys_ConsoleOutput (msg); // logfile if (logfile_active && logfile_active->value) { char name[MAX_QPATH]; if (!logfile) { Com_sprintf (name, sizeof(name), "%s/qconsole.log", FS_Gamedir ()); logfile = fopen (name, "w"); } if (logfile) fprintf (logfile, "%s", msg); if (logfile_active->value > 1) fflush (logfile); // force it to save every time } } /* ================ Com_DPrintf A Com_Printf that only shows up if the "developer" cvar is set ================ */ void Com_DPrintf (char *fmt, ...) { va_list argptr; char msg[MAXPRINTMSG]; if (!developer || !developer->value) return; // don't confuse non-developers with techie stuff... va_start (argptr,fmt); vsprintf (msg,fmt,argptr); va_end (argptr); Com_Printf ("%s", msg); } /* ============= Com_Error Both client and server can use this, and it will do the apropriate things. ============= */ void Com_Error (int code, char *fmt, ...) { va_list argptr; static char msg[MAXPRINTMSG]; static qboolean recursive; if (recursive) Sys_Error ("recursive error after: %s", msg); recursive = true; va_start (argptr,fmt); vsprintf (msg,fmt,argptr); va_end (argptr); if (code == ERR_DISCONNECT) { CL_Drop (); recursive = false; longjmp (abortframe, -1); } else if (code == ERR_DROP) { Com_Printf ("********************\nERROR: %s\n********************\n", msg); SV_Shutdown (va("Server crashed: %s\n", msg), false); CL_Drop (); recursive = false; longjmp (abortframe, -1); } else { SV_Shutdown (va("Server fatal crashed: %s\n", msg), false); CL_Shutdown (); } if (logfile) { fclose (logfile); logfile = NULL; } Sys_Error ("%s", msg); } /* ============= Com_Quit Both client and server can use this, and it will do the apropriate things. ============= */ void Com_Quit (void) { SV_Shutdown ("Server quit\n", false); CL_Shutdown (); if (logfile) { fclose (logfile); logfile = NULL; } Sys_Quit (); } /* ================== Com_ServerState ================== */ // this should've just been a cvar... int Com_ServerState (void) { return server_state; } /* ================== Com_SetServerState ================== */ void Com_SetServerState (int state) { server_state = state; } /* ============================================================================== MESSAGE IO FUNCTIONS Handles byte ordering and avoids alignment errors ============================================================================== */ vec3_t bytedirs[NUMVERTEXNORMALS] = { #include "anorms.h" }; // // writing functions // void MSG_WriteChar (sizebuf_t *sb, int c) { byte *buf; #ifdef PARANOID if (c < -128 || c > 127) Com_Error (ERR_FATAL, "MSG_WriteChar: range error"); #endif buf = SZ_GetSpace (sb, 1); buf[0] = c; } void MSG_WriteByte (sizebuf_t *sb, int c) { byte *buf; #ifdef PARANOID if (c < 0 || c > 255) Com_Error (ERR_FATAL, "MSG_WriteByte: range error"); #endif buf = SZ_GetSpace (sb, 1); buf[0] = c; } void MSG_WriteShort (sizebuf_t *sb, int c) { byte *buf; #ifdef PARANOID if (c < ((short)0x8000) || c > (short)0x7fff) Com_Error (ERR_FATAL, "MSG_WriteShort: range error"); #endif buf = SZ_GetSpace (sb, 2); buf[0] = c&0xff; buf[1] = c>>8; } void MSG_WriteLong (sizebuf_t *sb, int c) { byte *buf; buf = SZ_GetSpace (sb, 4); buf[0] = c&0xff; buf[1] = (c>>8)&0xff; buf[2] = (c>>16)&0xff; buf[3] = c>>24; } void MSG_WriteFloat (sizebuf_t *sb, float f) { union { float f; int l; } dat; dat.f = f; dat.l = LittleLong (dat.l); SZ_Write (sb, &dat.l, 4); } void MSG_WriteString (sizebuf_t *sb, char *s) { if (!s) SZ_Write (sb, "", 1); else SZ_Write (sb, s, strlen(s)+1); } void MSG_WriteCoord (sizebuf_t *sb, float f) { MSG_WriteShort (sb, (int)(f*8)); } void MSG_WritePos (sizebuf_t *sb, vec3_t pos) { MSG_WriteShort (sb, (int)(pos[0]*8)); MSG_WriteShort (sb, (int)(pos[1]*8)); MSG_WriteShort (sb, (int)(pos[2]*8)); } void MSG_WriteAngle (sizebuf_t *sb, float f) { MSG_WriteByte (sb, (int)(f*256/360) & 255); } void MSG_WriteAngle16 (sizebuf_t *sb, float f) { MSG_WriteShort (sb, ANGLE2SHORT(f)); } void MSG_WriteDeltaUsercmd (sizebuf_t *buf, usercmd_t *from, usercmd_t *cmd) { int bits; // // send the movement message // bits = 0; if (cmd->angles[0] != from->angles[0]) bits |= CM_ANGLE1; if (cmd->angles[1] != from->angles[1]) bits |= CM_ANGLE2; if (cmd->angles[2] != from->angles[2]) bits |= CM_ANGLE3; if (cmd->forwardmove != from->forwardmove) bits |= CM_FORWARD; if (cmd->sidemove != from->sidemove) bits |= CM_SIDE; if (cmd->upmove != from->upmove) bits |= CM_UP; if (cmd->buttons != from->buttons) bits |= CM_BUTTONS; if (cmd->impulse != from->impulse) bits |= CM_IMPULSE; MSG_WriteByte (buf, bits); if (bits & CM_ANGLE1) MSG_WriteShort (buf, cmd->angles[0]); if (bits & CM_ANGLE2) MSG_WriteShort (buf, cmd->angles[1]); if (bits & CM_ANGLE3) MSG_WriteShort (buf, cmd->angles[2]); if (bits & CM_FORWARD) MSG_WriteShort (buf, cmd->forwardmove); if (bits & CM_SIDE) MSG_WriteShort (buf, cmd->sidemove); if (bits & CM_UP) MSG_WriteShort (buf, cmd->upmove); if (bits & CM_BUTTONS) MSG_WriteByte (buf, cmd->buttons); if (bits & CM_IMPULSE) MSG_WriteByte (buf, cmd->impulse); MSG_WriteByte (buf, cmd->msec); MSG_WriteByte (buf, cmd->lightlevel); } void MSG_WriteDir (sizebuf_t *sb, vec3_t dir) { int i, best; float d, bestd; if (!dir) { MSG_WriteByte (sb, 0); return; } bestd = 0; best = 0; for (i=0 ; i<NUMVERTEXNORMALS ; i++) { d = DotProduct (dir, bytedirs[i]); if (d > bestd) { bestd = d; best = i; } } MSG_WriteByte (sb, best); } void MSG_ReadDir (sizebuf_t *sb, vec3_t dir) { int b; b = MSG_ReadByte (sb); if (b >= NUMVERTEXNORMALS) Com_Error (ERR_DROP, "MSF_ReadDir: out of range"); VectorCopy (bytedirs[b], dir); } /* ================== MSG_WriteDeltaEntity Writes part of a packetentities message. Can delta from either a baseline or a previous packet_entity ================== */ void MSG_WriteDeltaEntity (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qboolean force, qboolean newentity) { int bits; if (!to->number) Com_Error (ERR_FATAL, "Unset entity number"); if (to->number >= MAX_EDICTS) Com_Error (ERR_FATAL, "Entity number >= MAX_EDICTS"); // send an update bits = 0; if (to->number >= 256) bits |= U_NUMBER16; // number8 is implicit otherwise if (to->origin[0] != from->origin[0]) bits |= U_ORIGIN1; if (to->origin[1] != from->origin[1]) bits |= U_ORIGIN2; if (to->origin[2] != from->origin[2]) bits |= U_ORIGIN3; if ( to->angles[0] != from->angles[0] ) bits |= U_ANGLE1; if ( to->angles[1] != from->angles[1] ) bits |= U_ANGLE2; if ( to->angles[2] != from->angles[2] ) bits |= U_ANGLE3; if ( to->skinnum != from->skinnum ) { if ((unsigned)to->skinnum < 256) bits |= U_SKIN8; else if ((unsigned)to->skinnum < 0x10000) bits |= U_SKIN16; else bits |= (U_SKIN8|U_SKIN16); }