void PR_Profile_f (void) { int i, j; int max; dfunction_t *f, *bestFunc; int total; int funcCount; qboolean byHC; char saveName[MAX_OSPATH]; FILE *saveFile = NULL; int currentFile; int bestFile; int tally; const char *s; byHC = false; funcCount = 10; *saveName = 0; for (i = 1; i < Cmd_Argc(); i++) { s = Cmd_Argv(i); if (tolower(*s) == 'h') { // Sort by HC source file byHC = true; } else if (tolower(*s) == 's') { // Save to file if (i + 1 < Cmd_Argc() && !isdigit(*Cmd_Argv(i + 1))) { i++; sprintf(saveName, "%s/%s", fs_userdir, Cmd_Argv(i)); } else { sprintf(saveName, "%s/profile.txt", fs_userdir); } } else if (isdigit(*s)) { // Specify function count funcCount = atoi(Cmd_Argv(i)); if (funcCount < 1) { funcCount = 1; } } } total = 0; for (i = 0; i < progs->numfunctions; i++) { total += pr_functions[i].profile; } if (*saveName) { // Create the output file saveFile = fopen(saveName, "w"); if (saveFile == NULL) Con_Printf("Could not open %s\n", saveName); } #ifdef TIMESNAP_ACTIVE if (saveFile) { fprintf(saveFile, "(Timesnap Profile)\n"); } else { Con_Printf("(Timesnap Profile)\n"); } #endif if (byHC == false) { j = 0; do { max = 0; bestFunc = NULL; for (i = 0; i < progs->numfunctions; i++) { f = &pr_functions[i]; if (f->profile > max) { max = f->profile; bestFunc = f; } } if (bestFunc) { if (j < funcCount) { if (saveFile) { fprintf(saveFile, "%05.2f %s\n", ((float)bestFunc->profile / (float)total) * 100.0, PR_GetString(bestFunc->s_name)); } else { Con_Printf("%05.2f %s\n", ((float)bestFunc->profile / (float)total) * 100.0, PR_GetString(bestFunc->s_name)); } } j++; bestFunc->profile = 0; } } while (bestFunc); if (saveFile) { fclose(saveFile); } return; } currentFile = -1; do { tally = 0; bestFile = Q_MAXINT; for (i = 0; i < progs->numfunctions; i++) { if (pr_functions[i].s_file > currentFile && pr_functions[i].s_file < bestFile) { bestFile = pr_functions[i].s_file; tally = pr_functions[i].profile; continue; } if (pr_functions[i].s_file == bestFile) { tally += pr_functions[i].profile; } } currentFile = bestFile; if (tally && currentFile != Q_MAXINT) { if (saveFile) { fprintf(saveFile, "\"%s\"\n", PR_GetString(currentFile)); } else { Con_Printf("\"%s\"\n", PR_GetString(currentFile)); } j = 0; do { max = 0; bestFunc = NULL; for (i = 0; i < progs->numfunctions; i++) { f = &pr_functions[i]; if (f->s_file == currentFile && f->profile > max) { max = f->profile; bestFunc = f; } } if (bestFunc) { if (j < funcCount) { if (saveFile) { fprintf(saveFile, " %05.2f %s\n", ((float)bestFunc->profile / (float)total) * 100.0, PR_GetString(bestFunc->s_name)); } else { Con_Printf(" %05.2f %s\n", ((float)bestFunc->profile / (float)total) * 100.0, PR_GetString(bestFunc->s_name)); } } j++; bestFunc->profile = 0; } } while (bestFunc); } } while (currentFile != Q_MAXINT); if (saveFile) { fclose(saveFile); } }
/* ================ SV_MapRestart_f Completely restarts a level, but doesn't send a new gamestate to the clients. This allows fair starts with variable load times. ================ */ static void SV_MapRestart_f( void ) { int i; client_t *client; char *denied; qboolean isBot; int delay; // make sure we aren't restarting twice in the same frame if ( com_frameTime == sv.serverId ) { return; } // make sure server is running if ( !com_sv_running->integer ) { Com_Printf( "Server is not running.\n" ); return; } if ( sv.restartTime ) { return; } if (Cmd_Argc() > 1 ) { delay = atoi( Cmd_Argv(1) ); } else { delay = 5; } if( delay ) { sv.restartTime = sv.time + delay * 1000; SV_SetConfigstring( CS_WARMUP, va("%i", sv.restartTime) ); return; } // check for changes in variables that can't just be restarted // check for maxclients change if ( sv_maxclients->modified || sv_gametype->modified ) { char mapname[MAX_QPATH]; Com_Printf( "variable change -- restarting.\n" ); // restart the map the slow way Q_strncpyz( mapname, Cvar_VariableString( "mapname" ), sizeof( mapname ) ); SV_SpawnServer( mapname, qfalse, eForceReload_NOTHING ); return; } SV_StopAutoRecordDemos(); // toggle the server bit so clients can detect that a // map_restart has happened svs.snapFlagServerBit ^= SNAPFLAG_SERVERCOUNT; // generate a new serverid // TTimo - don't update restartedserverId there, otherwise we won't deal correctly with multiple map_restart sv.serverId = com_frameTime; Cvar_Set( "sv_serverid", va("%i", sv.serverId ) ); time( &sv.realMapTimeStarted ); sv.demosPruned = qfalse; // if a map_restart occurs while a client is changing maps, we need // to give them the correct time so that when they finish loading // they don't violate the backwards time check in cl_cgame.c for (i=0 ; i<sv_maxclients->integer ; i++) { if (svs.clients[i].state == CS_PRIMED) { svs.clients[i].oldServerTime = sv.restartTime; } } // reset all the vm data in place without changing memory allocation // note that we do NOT set sv.state = SS_LOADING, so configstrings that // had been changed from their default values will generate broadcast updates sv.state = SS_LOADING; sv.restarting = qtrue; SV_RestartGame(); // run a few frames to allow everything to settle for ( i = 0 ;i < 3 ; i++ ) { GVM_RunFrame( sv.time ); sv.time += 100; svs.time += 100; } sv.state = SS_GAME; sv.restarting = qfalse; // connect and begin all the clients for (i=0 ; i<sv_maxclients->integer ; i++) { client = &svs.clients[i]; // send the new gamestate to all connected clients if ( client->state < CS_CONNECTED) { continue; } if ( client->netchan.remoteAddress.type == NA_BOT ) { isBot = qtrue; } else { isBot = qfalse; } // add the map_restart command SV_AddServerCommand( client, "map_restart\n" ); // connect the client again, without the firstTime flag denied = GVM_ClientConnect( i, qfalse, isBot ); if ( denied ) { // this generally shouldn't happen, because the client // was connected before the level change SV_DropClient( client, denied ); Com_Printf( "SV_MapRestart_f(%d): dropped client %i - denied!\n", delay, i ); continue; } if(client->state == CS_ACTIVE) SV_ClientEnterWorld(client, &client->lastUsercmd); else { // If we don't reset client->lastUsercmd and are restarting during map load, // the client will hang because we'll use the last Usercmd from the previous map, // which is wrong obviously. SV_ClientEnterWorld(client, NULL); } } // run another frame to allow things to look at all the players GVM_RunFrame( sv.time ); sv.time += 100; svs.time += 100; SV_BeginAutoRecordDemos(); }
static void SV_DelBanFromList( qboolean isexception ) { int index, count = 0, todel, mask; netadr_t ip; char *banstring; // make sure server is running if ( !com_sv_running->integer ) { Com_Printf( "Server is not running.\n" ); return; } if ( Cmd_Argc() != 2 ) { Com_Printf( "Usage: %s (ip[/subnet] | num)\n", Cmd_Argv( 0 ) ); return; } banstring = Cmd_Argv( 1 ); if ( strchr( banstring, '.' ) || strchr( banstring, ':' ) ) { serverBan_t *curban; if ( SV_ParseCIDRNotation( &ip, &mask, banstring ) ) { Com_Printf( "Error: Invalid address %s\n", banstring ); return; } index = 0; while ( index < serverBansCount ) { curban = &serverBans[index]; if ( curban->isexception == isexception && curban->subnet >= mask && NET_CompareBaseAdrMask( curban->ip, ip, mask ) ) { Com_Printf( "Deleting %s %s/%d\n", isexception ? "exception" : "ban", NET_AdrToString( curban->ip ), curban->subnet ); SV_DelBanEntryFromList( index ); } else index++; } } else { todel = atoi( Cmd_Argv( 1 ) ); if ( todel < 1 || todel > serverBansCount ) { Com_Printf( "Error: Invalid ban number given\n" ); return; } for ( index = 0; index < serverBansCount; index++ ) { if ( serverBans[index].isexception == isexception ) { count++; if ( count == todel ) { Com_Printf( "Deleting %s %s/%d\n", isexception ? "exception" : "ban", NET_AdrToString( serverBans[index].ip ), serverBans[index].subnet ); SV_DelBanEntryFromList( index ); break; } } } } SV_WriteBans(); }
/* ======================================================================================================================================= Cvar_List_f ======================================================================================================================================= */ void Cvar_List_f(void) { cvar_t *var; int i; char *match; if (Cmd_Argc() > 1) { match = Cmd_Argv(1); } else { match = NULL; } i = 0; for (var = cvar_vars; var; var = var->next, i++) { if (!var->name || (match && !Com_Filter(match, var->name, qfalse))) { continue; } if (var->flags & CVAR_SERVERINFO) { Com_Printf("S"); } else { Com_Printf(" "); } if (var->flags & CVAR_SYSTEMINFO) { Com_Printf("s"); } else { Com_Printf(" "); } if (var->flags & CVAR_USERINFO) { Com_Printf("U"); } else { Com_Printf(" "); } if (var->flags & CVAR_ROM) { Com_Printf("R"); } else { Com_Printf(" "); } if (var->flags & CVAR_INIT) { Com_Printf("I"); } else { Com_Printf(" "); } if (var->flags & CVAR_ARCHIVE) { Com_Printf("A"); } else { Com_Printf(" "); } if (var->flags & CVAR_LATCH) { Com_Printf("L"); } else { Com_Printf(" "); } if (var->flags & CVAR_CHEAT) { Com_Printf("C"); } else { Com_Printf(" "); } if (var->flags & CVAR_USER_CREATED) { Com_Printf("?"); } else { Com_Printf(" "); } Com_Printf(" %s \"%s\"\n", var->name, var->string); } Com_Printf("\n%i total cvars\n", i); Com_Printf("%i cvar indexes\n", cvar_numIndexes); }
/* ================ SV_Status_f ================ */ static void SV_Status_f( void ) { int i, humans, bots; client_t *cl; playerState_t *ps; const char *s; int ping; char state[32]; qboolean avoidTruncation = qfalse; // make sure server is running if ( !com_sv_running->integer ) { Com_Printf( "Server is not running.\n" ); return; } if ( Cmd_Argc() > 1 ) { if (!Q_stricmp("notrunc", Cmd_Argv(1))) { avoidTruncation = qtrue; } } humans = bots = 0; for ( i = 0 ; i < sv_maxclients->integer ; i++ ) { if ( svs.clients[i].state >= CS_CONNECTED ) { if ( svs.clients[i].netchan.remoteAddress.type != NA_BOT ) { humans++; } else { bots++; } } } #if defined(_WIN32) #define STATUS_OS "Windows" #elif defined(__linux__) #define STATUS_OS "Linux" #elif defined(MACOS_X) #define STATUS_OS "OSX" #else #define STATUS_OS "Unknown" #endif const char *ded_table[] = { "listen", "lan dedicated", "public dedicated", }; char hostname[MAX_HOSTNAMELENGTH] = { 0 }; Q_strncpyz( hostname, sv_hostname->string, sizeof(hostname) ); Q_StripColor( hostname ); Com_Printf( "hostname: %s^7\n", hostname ); Com_Printf( "version : %s %i\n", VERSION_STRING_DOTTED, PROTOCOL_VERSION ); Com_Printf( "game : %s\n", FS_GetCurrentGameDir() ); Com_Printf( "udp/ip : %s:%i os(%s) type(%s)\n", Cvar_VariableString( "net_ip" ), Cvar_VariableIntegerValue( "net_port" ), STATUS_OS, ded_table[com_dedicated->integer] ); Com_Printf( "map : %s gametype(%i)\n", sv_mapname->string, sv_gametype->integer ); Com_Printf( "players : %i humans, %i bots (%i max)\n", humans, bots, sv_maxclients->integer - sv_privateClients->integer ); Com_Printf( "uptime : %s\n", SV_CalcUptime() ); Com_Printf ("cl score ping name address rate \n"); Com_Printf ("-- ----- ---- --------------- --------------------------------------- -----\n"); for (i=0,cl=svs.clients ; i < sv_maxclients->integer ; i++,cl++) { if ( !cl->state ) continue; if ( cl->state == CS_CONNECTED ) Q_strncpyz( state, "CON ", sizeof( state ) ); else if ( cl->state == CS_ZOMBIE ) Q_strncpyz( state, "ZMB ", sizeof( state ) ); else { ping = cl->ping < 9999 ? cl->ping : 9999; Com_sprintf( state, sizeof(state), "%4i", ping ); } ps = SV_GameClientNum( i ); s = NET_AdrToString( cl->netchan.remoteAddress ); if (!avoidTruncation) { Com_Printf ("%2i %5i %s %-15.15s ^7%39s %5i\n", i, ps->persistant[PERS_SCORE], state, cl->name, s, cl->rate ); } else { Com_Printf ("%2i %5i %s %s ^7%39s %5i\n", i, ps->persistant[PERS_SCORE], state, cl->name, s, cl->rate ); } } Com_Printf ("\n"); }
/* ================== SV_WriteDownloadToClient Check to see if the client wants a file, open it if needed and start pumping the client Fill up msg with data, return number of download blocks added ================== */ int SV_WriteDownloadToClient(client_t *cl, msg_t *msg) { int curindex; int unreferenced = 1; char errorMessage[1024]; char pakbuf[MAX_QPATH], *pakptr; int numRefPaks; if (!*cl->downloadName) return 0; // Nothing being downloaded if(!cl->download) { // Chop off filename extension. Com_sprintf(pakbuf, sizeof(pakbuf), "%s", cl->downloadName); pakptr = strrchr(pakbuf, '.'); if(pakptr) { *pakptr = '\0'; // Check for pk3 filename extension if(!Q_stricmp(pakptr + 1, "pk3")) { const char *referencedPaks = FS_ReferencedPakNames(); // Check whether the file appears in the list of referenced // paks to prevent downloading of arbitrary files. Cmd_TokenizeStringIgnoreQuotes(referencedPaks); numRefPaks = Cmd_Argc(); for(curindex = 0; curindex < numRefPaks; curindex++) { if(!FS_FilenameCompare(Cmd_Argv(curindex), pakbuf)) { unreferenced = 0; break; } } } } cl->download = 0; // We open the file here if ( !(sv_allowDownload->integer & DLF_ENABLE) || (sv_allowDownload->integer & DLF_NO_UDP) || unreferenced || ( cl->downloadSize = FS_SV_FOpenFileRead( cl->downloadName, &cl->download ) ) < 0 ) { // cannot auto-download file if(unreferenced) { Com_Printf("clientDownload: %d : \"%s\" is not referenced and cannot be downloaded.\n", (int) (cl - svs.clients), cl->downloadName); Com_sprintf(errorMessage, sizeof(errorMessage), "File \"%s\" is not referenced and cannot be downloaded.", cl->downloadName); } else if ( !(sv_allowDownload->integer & DLF_ENABLE) || (sv_allowDownload->integer & DLF_NO_UDP) ) { Com_Printf("clientDownload: %d : \"%s\" download disabled\n", (int) (cl - svs.clients), cl->downloadName); if (sv_pure->integer) { Com_sprintf(errorMessage, sizeof(errorMessage), "Could not download \"%s\" because autodownloading is disabled on the server.\n\n" "You will need to get this file elsewhere before you " "can connect to this pure server.\n", cl->downloadName); } else { Com_sprintf(errorMessage, sizeof(errorMessage), "Could not download \"%s\" because autodownloading is disabled on the server.\n\n" "The server you are connecting to is not a pure server, " "set autodownload to No in your settings and you might be " "able to join the game anyway.\n", cl->downloadName); } } else { // NOTE TTimo this is NOT supposed to happen unless bug in our filesystem scheme? // if the pk3 is referenced, it must have been found somewhere in the filesystem Com_Printf("clientDownload: %d : \"%s\" file not found on server\n", (int) (cl - svs.clients), cl->downloadName); Com_sprintf(errorMessage, sizeof(errorMessage), "File \"%s\" not found on server for autodownloading.\n", cl->downloadName); } MSG_WriteByte( msg, svc_download ); MSG_WriteShort( msg, 0 ); // client is expecting block zero MSG_WriteLong( msg, -1 ); // illegal file size MSG_WriteString( msg, errorMessage ); *cl->downloadName = 0; if(cl->download) FS_FCloseFile(cl->download); return 1; } Com_Printf( "clientDownload: %d : beginning \"%s\"\n", (int) (cl - svs.clients), cl->downloadName ); // Init cl->downloadCurrentBlock = cl->downloadClientBlock = cl->downloadXmitBlock = 0; cl->downloadCount = 0; cl->downloadEOF = qfalse; } // Perform any reads that we need to while (cl->downloadCurrentBlock - cl->downloadClientBlock < MAX_DOWNLOAD_WINDOW && cl->downloadSize != cl->downloadCount) { curindex = (cl->downloadCurrentBlock % MAX_DOWNLOAD_WINDOW); if (!cl->downloadBlocks[curindex]) cl->downloadBlocks[curindex] = Z_Malloc(MAX_DOWNLOAD_BLKSIZE); cl->downloadBlockSize[curindex] = FS_Read( cl->downloadBlocks[curindex], MAX_DOWNLOAD_BLKSIZE, cl->download ); if (cl->downloadBlockSize[curindex] < 0) { // EOF right now cl->downloadCount = cl->downloadSize; break; } cl->downloadCount += cl->downloadBlockSize[curindex]; // Load in next block cl->downloadCurrentBlock++; } // Check to see if we have eof condition and add the EOF block if (cl->downloadCount == cl->downloadSize && !cl->downloadEOF && cl->downloadCurrentBlock - cl->downloadClientBlock < MAX_DOWNLOAD_WINDOW) { cl->downloadBlockSize[cl->downloadCurrentBlock % MAX_DOWNLOAD_WINDOW] = 0; cl->downloadCurrentBlock++; cl->downloadEOF = qtrue; // We have added the EOF block } if (cl->downloadClientBlock == cl->downloadCurrentBlock) return 0; // Nothing to transmit // Write out the next section of the file, if we have already reached our window, // automatically start retransmitting if (cl->downloadXmitBlock == cl->downloadCurrentBlock) { // We have transmitted the complete window, should we start resending? if (svs.time - cl->downloadSendTime > 1000) cl->downloadXmitBlock = cl->downloadClientBlock; else return 0; } // Send current block curindex = (cl->downloadXmitBlock % MAX_DOWNLOAD_WINDOW); MSG_WriteByte( msg, svc_download ); MSG_WriteShort( msg, cl->downloadXmitBlock ); // block zero is special, contains file size if ( cl->downloadXmitBlock == 0 ) MSG_WriteLong( msg, cl->downloadSize ); MSG_WriteShort( msg, cl->downloadBlockSize[curindex] ); // Write the block if(cl->downloadBlockSize[curindex]) MSG_WriteData(msg, cl->downloadBlocks[curindex], cl->downloadBlockSize[curindex]); Com_DPrintf( "clientDownload: %d : writing block %d\n", (int) (cl - svs.clients), cl->downloadXmitBlock ); // Move on to the next block // It will get sent with next snap shot. The rate will keep us in line. cl->downloadXmitBlock++; cl->downloadSendTime = svs.time; return 1; }
/* * record <demoname> * Begins recording a demo from the current position */ void CL_Record_f(void) { char name[MAX_OSPATH]; byte buf_data[MAX_MSGLEN]; sizebuf_t buf; int i; int len; entity_state_t *ent; entity_state_t nullstate; if (Cmd_Argc() != 2) { Com_Printf("record <demoname>\n"); return; } if (cls.demorecording) { Com_Printf("Already recording.\n"); return; } if (cls.state != ca_active) { Com_Printf("You must be in a level to record.\n"); return; } Com_sprintf(name, sizeof(name), "%s/demos/%s.dm2", FS_Gamedir(), Cmd_Argv(1)); Com_Printf("recording to %s.\n", name); FS_CreatePath(name); cls.demofile = fopen(name, "wb"); if (!cls.demofile) { Com_Printf("ERROR: couldn't open.\n"); return; } cls.demorecording = true; /* don't start saving messages until a non-delta compressed message is received */ cls.demowaiting = true; /* write out messages to hold the startup information */ SZ_Init(&buf, buf_data, sizeof(buf_data)); /* send the serverdata */ MSG_WriteByte(&buf, svc_serverdata); MSG_WriteLong(&buf, PROTOCOL_VERSION); MSG_WriteLong(&buf, 0x10000 + cl.servercount); MSG_WriteByte(&buf, 1); /* demos are always attract loops */ MSG_WriteString(&buf, cl.gamedir); MSG_WriteShort(&buf, cl.playernum); MSG_WriteString(&buf, cl.configstrings[CS_NAME]); /* configstrings */ for (i = 0; i < MAX_CONFIGSTRINGS; i++) { if (cl.configstrings[i][0]) { if (buf.cursize + strlen(cl.configstrings[i]) + 32 > buf.maxsize) { len = LittleLong(buf.cursize); fwrite(&len, 4, 1, cls.demofile); fwrite(buf.data, buf.cursize, 1, cls.demofile); buf.cursize = 0; } MSG_WriteByte(&buf, svc_configstring); MSG_WriteShort(&buf, i); MSG_WriteString(&buf, cl.configstrings[i]); } } /* baselines */ memset(&nullstate, 0, sizeof(nullstate)); for (i = 0; i < MAX_EDICTS; i++) { ent = &cl_entities[i].baseline; if (!ent->modelindex) { continue; } if (buf.cursize + 64 > buf.maxsize) { len = LittleLong(buf.cursize); fwrite(&len, 4, 1, cls.demofile); fwrite(buf.data, buf.cursize, 1, cls.demofile); buf.cursize = 0; } MSG_WriteByte(&buf, svc_spawnbaseline); MSG_WriteDeltaEntity(&nullstate, &cl_entities[i].baseline, &buf, true, true); } MSG_WriteByte(&buf, svc_stufftext); MSG_WriteString(&buf, "precache\n"); /* write it to the demo file */ len = LittleLong(buf.cursize); fwrite(&len, 4, 1, cls.demofile); fwrite(buf.data, buf.cursize, 1, cls.demofile); }
/* ==================== CL_CgameSystemCalls The cgame module is making a system call ==================== */ intptr_t CL_CgameSystemCalls( intptr_t *args ) { switch ( args[0] ) { case CG_PRINT: Com_Printf( "%s", VMA( 1 ) ); return 0; case CG_ERROR: Com_Error( ERR_DROP, "%s", VMA( 1 ) ); return 0; case CG_MILLISECONDS: return Sys_Milliseconds(); case CG_CVAR_REGISTER: Cvar_Register( VMA( 1 ), VMA( 2 ), VMA( 3 ), args[4] ); return 0; case CG_CVAR_UPDATE: Cvar_Update( VMA( 1 ) ); return 0; case CG_CVAR_SET: Cvar_Set( VMA( 1 ), VMA( 2 ) ); return 0; case CG_CVAR_VARIABLESTRINGBUFFER: Cvar_VariableStringBuffer( VMA( 1 ), VMA( 2 ), args[3] ); return 0; case CG_ARGC: return Cmd_Argc(); case CG_ARGV: Cmd_ArgvBuffer( args[1], VMA( 2 ), args[3] ); return 0; case CG_ARGS: Cmd_ArgsBuffer( VMA( 1 ), args[2] ); return 0; case CG_FS_FOPENFILE: return FS_FOpenFileByMode( VMA( 1 ), VMA( 2 ), args[3] ); case CG_FS_READ: FS_Read( VMA( 1 ), args[2], args[3] ); return 0; case CG_FS_WRITE: return FS_Write( VMA( 1 ), args[2], args[3] ); case CG_FS_FCLOSEFILE: FS_FCloseFile( args[1] ); return 0; case CG_SENDCONSOLECOMMAND: Cbuf_AddText( VMA( 1 ) ); return 0; case CG_ADDCOMMAND: CL_AddCgameCommand( VMA( 1 ) ); return 0; case CG_REMOVECOMMAND: Cmd_RemoveCommand( VMA( 1 ) ); return 0; case CG_SENDCLIENTCOMMAND: CL_AddReliableCommand( VMA( 1 ) ); return 0; case CG_UPDATESCREEN: // this is used during lengthy level loading, so pump message loop // Com_EventLoop(); // FIXME: if a server restarts here, BAD THINGS HAPPEN! // We can't call Com_EventLoop here, a restart will crash and this _does_ happen // if there is a map change while we are downloading at pk3. // ZOID SCR_UpdateScreen(); return 0; case CG_CM_LOADMAP: CL_CM_LoadMap( VMA( 1 ) ); return 0; case CG_CM_NUMINLINEMODELS: return CM_NumInlineModels(); case CG_CM_INLINEMODEL: return CM_InlineModel( args[1] ); case CG_CM_TEMPBOXMODEL: return CM_TempBoxModel( VMA( 1 ), VMA( 2 ), qfalse ); case CG_CM_TEMPCAPSULEMODEL: return CM_TempBoxModel( VMA( 1 ), VMA( 2 ), qtrue ); case CG_CM_POINTCONTENTS: return CM_PointContents( VMA( 1 ), args[2] ); case CG_CM_TRANSFORMEDPOINTCONTENTS: return CM_TransformedPointContents( VMA( 1 ), args[2], VMA( 3 ), VMA( 4 ) ); case CG_CM_BOXTRACE: CM_BoxTrace( VMA( 1 ), VMA( 2 ), VMA( 3 ), VMA( 4 ), VMA( 5 ), args[6], args[7], /*int capsule*/ qfalse ); return 0; case CG_CM_TRANSFORMEDBOXTRACE: CM_TransformedBoxTrace( VMA( 1 ), VMA( 2 ), VMA( 3 ), VMA( 4 ), VMA( 5 ), args[6], args[7], VMA( 8 ), VMA( 9 ), /*int capsule*/ qfalse ); return 0; case CG_CM_CAPSULETRACE: CM_BoxTrace( VMA( 1 ), VMA( 2 ), VMA( 3 ), VMA( 4 ), VMA( 5 ), args[6], args[7], /*int capsule*/ qtrue ); return 0; case CG_CM_TRANSFORMEDCAPSULETRACE: CM_TransformedBoxTrace( VMA( 1 ), VMA( 2 ), VMA( 3 ), VMA( 4 ), VMA( 5 ), args[6], args[7], VMA( 8 ), VMA( 9 ), /*int capsule*/ qtrue ); return 0; case CG_CM_MARKFRAGMENTS: return re.MarkFragments( args[1], VMA( 2 ), VMA( 3 ), args[4], VMA( 5 ), args[6], VMA( 7 ) ); case CG_S_STARTSOUND: S_StartSound( VMA( 1 ), args[2], args[3], args[4] ); return 0; //----(SA) added case CG_S_STARTSOUNDEX: S_StartSoundEx( VMA( 1 ), args[2], args[3], args[4], args[5] ); return 0; //----(SA) end case CG_S_STARTLOCALSOUND: S_StartLocalSound( args[1], args[2] ); return 0; case CG_S_CLEARLOOPINGSOUNDS: S_ClearLoopingSounds(); // (SA) modified so no_pvs sounds can function // RF, if killall, then stop all sounds if ( args[1] == 1 ) { S_ClearSounds( qtrue, qfalse ); } else if ( args[1] == 2 ) { S_ClearSounds( qtrue, qtrue ); } return 0; case CG_S_ADDLOOPINGSOUND: // FIXME MrE: handling of looping sounds changed S_AddLoopingSound( args[1], VMA( 2 ), VMA( 3 ), args[4], args[5], args[6] ); return 0; // not in use // case CG_S_ADDREALLOOPINGSOUND: // S_AddLoopingSound( args[1], VMA(2), VMA(3), args[4], args[5], args[6] ); // //S_AddRealLoopingSound( args[1], VMA(2), VMA(3), args[4], args[5] ); // return 0; //----(SA) added case CG_S_STOPSTREAMINGSOUND: S_StopEntStreamingSound( args[1] ); return 0; //----(SA) end case CG_S_STOPLOOPINGSOUND: // RF, not functional anymore, since we reverted to old looping code //S_StopLoopingSound( args[1] ); return 0; case CG_S_UPDATEENTITYPOSITION: S_UpdateEntityPosition( args[1], VMA( 2 ) ); return 0; // Ridah, talking animations case CG_S_GETVOICEAMPLITUDE: return S_GetVoiceAmplitude( args[1] ); // done. case CG_S_RESPATIALIZE: S_Respatialize( args[1], VMA( 2 ), VMA( 3 ), args[4] ); return 0; case CG_S_REGISTERSOUND: #ifdef DOOMSOUND ///// (SA) DOOMSOUND return S_RegisterSound( VMA( 1 ) ); #else return S_RegisterSound( VMA( 1 ), qfalse ); #endif ///// (SA) DOOMSOUND case CG_S_STARTBACKGROUNDTRACK: S_StartBackgroundTrack( VMA( 1 ), VMA( 2 ), args[3] ); //----(SA) added fadeup time return 0; case CG_S_FADESTREAMINGSOUND: S_FadeStreamingSound( VMF( 1 ), args[2], args[3] ); //----(SA) added music/all-streaming options return 0; case CG_S_STARTSTREAMINGSOUND: S_StartStreamingSound( VMA( 1 ), VMA( 2 ), args[3], args[4], args[5] ); return 0; case CG_S_FADEALLSOUNDS: S_FadeAllSounds( VMF( 1 ), args[2] ); //----(SA) added return 0; case CG_R_LOADWORLDMAP: re.LoadWorld( VMA( 1 ) ); return 0; case CG_R_REGISTERMODEL: return re.RegisterModel( VMA( 1 ) ); case CG_R_REGISTERSKIN: return re.RegisterSkin( VMA( 1 ) ); //----(SA) added case CG_R_GETSKINMODEL: return re.GetSkinModel( args[1], VMA( 2 ), VMA( 3 ) ); case CG_R_GETMODELSHADER: return re.GetShaderFromModel( args[1], args[2], args[3] ); //----(SA) end case CG_R_REGISTERSHADER: return re.RegisterShader( VMA( 1 ) ); case CG_R_REGISTERFONT: re.RegisterFont( VMA( 1 ), args[2], VMA( 3 ) ); case CG_R_REGISTERSHADERNOMIP: return re.RegisterShaderNoMip( VMA( 1 ) ); case CG_R_CLEARSCENE: re.ClearScene(); return 0; case CG_R_ADDREFENTITYTOSCENE: re.AddRefEntityToScene( VMA( 1 ) ); return 0; case CG_R_ADDPOLYTOSCENE: re.AddPolyToScene( args[1], args[2], VMA( 3 ) ); return 0; // Ridah case CG_R_ADDPOLYSTOSCENE: re.AddPolysToScene( args[1], args[2], VMA( 3 ), args[4] ); return 0; case CG_RB_ZOMBIEFXADDNEWHIT: re.ZombieFXAddNewHit( args[1], VMA( 2 ), VMA( 3 ) ); return 0; // done. // case CG_R_LIGHTFORPOINT: // return re.LightForPoint( VMA(1), VMA(2), VMA(3), VMA(4) ); case CG_R_ADDLIGHTTOSCENE: re.AddLightToScene( VMA( 1 ), VMF( 2 ), VMF( 3 ), VMF( 4 ), VMF( 5 ), args[6] ); return 0; // case CG_R_ADDADDITIVELIGHTTOSCENE: // re.AddAdditiveLightToScene( VMA(1), VMF(2), VMF(3), VMF(4), VMF(5) ); // return 0; case CG_R_ADDCORONATOSCENE: re.AddCoronaToScene( VMA( 1 ), VMF( 2 ), VMF( 3 ), VMF( 4 ), VMF( 5 ), args[6], args[7] ); return 0; case CG_R_SETFOG: re.SetFog( args[1], args[2], args[3], VMF( 4 ), VMF( 5 ), VMF( 6 ), VMF( 7 ) ); return 0; case CG_R_RENDERSCENE: re.RenderScene( VMA( 1 ) ); return 0; case CG_R_SETCOLOR: re.SetColor( VMA( 1 ) ); return 0; case CG_R_DRAWSTRETCHPIC: re.DrawStretchPic( VMF( 1 ), VMF( 2 ), VMF( 3 ), VMF( 4 ), VMF( 5 ), VMF( 6 ), VMF( 7 ), VMF( 8 ), args[9] ); return 0; case CG_R_DRAWSTRETCHPIC_GRADIENT: re.DrawStretchPicGradient( VMF( 1 ), VMF( 2 ), VMF( 3 ), VMF( 4 ), VMF( 5 ), VMF( 6 ), VMF( 7 ), VMF( 8 ), args[9], VMA( 10 ), args[11] ); return 0; case CG_R_MODELBOUNDS: re.ModelBounds( args[1], VMA( 2 ), VMA( 3 ) ); return 0; case CG_R_LERPTAG: return re.LerpTag( VMA( 1 ), VMA( 2 ), VMA( 3 ), args[4] ); case CG_GETGLCONFIG: CL_GetGlconfig( VMA( 1 ) ); return 0; case CG_GETGAMESTATE: CL_GetGameState( VMA( 1 ) ); return 0; case CG_GETCURRENTSNAPSHOTNUMBER: CL_GetCurrentSnapshotNumber( VMA( 1 ), VMA( 2 ) ); return 0; case CG_GETSNAPSHOT: return CL_GetSnapshot( args[1], VMA( 2 ) ); case CG_GETSERVERCOMMAND: return CL_GetServerCommand( args[1] ); case CG_GETCURRENTCMDNUMBER: return CL_GetCurrentCmdNumber(); case CG_GETUSERCMD: return CL_GetUserCmd( args[1], VMA( 2 ) ); case CG_SETUSERCMDVALUE: CL_SetUserCmdValue( args[1], args[2], VMF( 3 ), args[4] ); //----(SA) modified // NERVE - SMF - added fourth arg [cld] return 0; case CG_MEMORY_REMAINING: return Hunk_MemoryRemaining(); case CG_KEY_ISDOWN: return Key_IsDown( args[1] ); case CG_KEY_GETCATCHER: return Key_GetCatcher(); case CG_KEY_SETCATCHER: Key_SetCatcher( args[1] ); return 0; case CG_KEY_GETKEY: return Key_GetKey( VMA( 1 ) ); case CG_MEMSET: return (intptr_t)memset( VMA( 1 ), args[2], args[3] ); case CG_MEMCPY: return (intptr_t)memcpy( VMA( 1 ), VMA( 2 ), args[3] ); case CG_STRNCPY: return (intptr_t)strncpy( VMA( 1 ), VMA( 2 ), args[3] ); case CG_SIN: return FloatAsInt( sin( VMF( 1 ) ) ); case CG_COS: return FloatAsInt( cos( VMF( 1 ) ) ); case CG_ATAN2: return FloatAsInt( atan2( VMF( 1 ), VMF( 2 ) ) ); case CG_SQRT: return FloatAsInt( sqrt( VMF( 1 ) ) ); case CG_FLOOR: return FloatAsInt( floor( VMF( 1 ) ) ); case CG_CEIL: return FloatAsInt( ceil( VMF( 1 ) ) ); case CG_ACOS: return FloatAsInt( Q_acos( VMF( 1 ) ) ); case CG_PC_ADD_GLOBAL_DEFINE: return botlib_export->PC_AddGlobalDefine( VMA( 1 ) ); case CG_PC_LOAD_SOURCE: return botlib_export->PC_LoadSourceHandle( VMA( 1 ) ); case CG_PC_FREE_SOURCE: return botlib_export->PC_FreeSourceHandle( args[1] ); case CG_PC_READ_TOKEN: return botlib_export->PC_ReadTokenHandle( args[1], VMA( 2 ) ); case CG_PC_SOURCE_FILE_AND_LINE: return botlib_export->PC_SourceFileAndLine( args[1], VMA( 2 ), VMA( 3 ) ); case CG_S_STOPBACKGROUNDTRACK: S_StopBackgroundTrack(); return 0; case CG_REAL_TIME: return Com_RealTime( VMA( 1 ) ); case CG_SNAPVECTOR: Sys_SnapVector( VMA( 1 ) ); return 0; case CG_SENDMOVESPEEDSTOGAME: SV_SendMoveSpeedsToGame( args[1], VMA( 2 ) ); return 0; case CG_CIN_PLAYCINEMATIC: return CIN_PlayCinematic( VMA( 1 ), args[2], args[3], args[4], args[5], args[6] ); case CG_CIN_STOPCINEMATIC: return CIN_StopCinematic( args[1] ); case CG_CIN_RUNCINEMATIC: return CIN_RunCinematic( args[1] ); case CG_CIN_DRAWCINEMATIC: CIN_DrawCinematic( args[1] ); return 0; case CG_CIN_SETEXTENTS: CIN_SetExtents( args[1], args[2], args[3], args[4], args[5] ); return 0; case CG_R_REMAP_SHADER: re.RemapShader( VMA( 1 ), VMA( 2 ), VMA( 3 ) ); return 0; case CG_TESTPRINTINT: Com_Printf( "%s%i\n", VMA( 1 ), args[2] ); return 0; case CG_TESTPRINTFLOAT: Com_Printf( "%s%f\n", VMA( 1 ), VMF( 2 ) ); return 0; case CG_LOADCAMERA: return loadCamera( args[1], VMA( 2 ) ); case CG_STARTCAMERA: if ( args[1] == 0 ) { // CAM_PRIMARY cl.cameraMode = qtrue; //----(SA) added } startCamera( args[1], args[2] ); return 0; //----(SA) added case CG_STOPCAMERA: if ( args[1] == 0 ) { // CAM_PRIMARY cl.cameraMode = qfalse; } // stopCamera(args[1]); return 0; //----(SA) end case CG_GETCAMERAINFO: return getCameraInfo( args[1], args[2], VMA( 3 ), VMA( 4 ), VMA( 5 ) ); case CG_GET_ENTITY_TOKEN: return re.GetEntityToken( VMA( 1 ), args[2] ); case CG_INGAME_POPUP: if ( VMA( 1 ) && !Q_stricmp( VMA( 1 ), "briefing" ) ) { //----(SA) added VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_BRIEFING ); return 0; } if ( cls.state == CA_ACTIVE && !clc.demoplaying ) { // NERVE - SMF if ( VMA( 1 ) && !Q_stricmp( VMA( 1 ), "UIMENU_WM_PICKTEAM" ) ) { VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_WM_PICKTEAM ); } else if ( VMA( 1 ) && !Q_stricmp( VMA( 1 ), "UIMENU_WM_PICKPLAYER" ) ) { VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_WM_PICKPLAYER ); } else if ( VMA( 1 ) && !Q_stricmp( VMA( 1 ), "UIMENU_WM_QUICKMESSAGE" ) ) { VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_WM_QUICKMESSAGE ); } else if ( VMA( 1 ) && !Q_stricmp( VMA( 1 ), "UIMENU_WM_LIMBO" ) ) { VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_WM_LIMBO ); } // -NERVE - SMF else if ( VMA( 1 ) && !Q_stricmp( VMA( 1 ), "hbook1" ) ) { //----(SA) VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_BOOK1 ); } else if ( VMA( 1 ) && !Q_stricmp( VMA( 1 ), "hbook2" ) ) { //----(SA) VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_BOOK2 ); } else if ( VMA( 1 ) && !Q_stricmp( VMA( 1 ), "hbook3" ) ) { //----(SA) VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_BOOK3 ); } else if ( VMA( 1 ) && !Q_stricmp( VMA( 1 ), "pregame" ) ) { //----(SA) added VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_PREGAME ); } else { VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_CLIPBOARD ); } } return 0; // NERVE - SMF case CG_INGAME_CLOSEPOPUP: VM_Call( uivm, UI_KEY_EVENT, K_ESCAPE, qtrue ); return 0; case CG_LIMBOCHAT: if ( VMA( 1 ) ) { CL_AddToLimboChat( VMA( 1 ) ); } return 0; // - NERVE - SMF case CG_GETMODELINFO: return SV_GetModelInfo( args[1], VMA( 2 ), VMA( 3 ) ); default: Com_Error( ERR_DROP, "Bad cgame system trap: %i", args[0] ); } return 0; }
/** * Get the number of param from an execution context * @param[in] context The execution context * @return The requested param */ int UI_GetParamNumber (const uiCallContext_t* context) { if (context->useCmdParam) return Cmd_Argc() - 1; return context->paramNumber; }
/** * @brief Recursively removes files matching a given pattern from homepath. * * Useful for removing incomplete downloads and other garbage. * Files listed in the com_cleanWhitelist cvar are protected from deletion. * Additionally, executable and configuration files are protected unless 'force' * argument is passed to this command. */ void Cmd_CleanHomepath_f(void) { int i, j, patternFiles = 0, delFiles = 0, totalFiles = 0; char path[MAX_OSPATH]; qboolean force = qfalse, pretend = qfalse; // *.so and *.dll are denied per default in FS_Remove but throw a Com_Error() -> game aborts const char whitelist[] = ".txt .cfg .dat .gm .way .so .dll"; if (Cmd_Argc() < 3) { // files in fs_homepath are downloaded again when required - but better print a warning for inexperienced users Com_Printf("usage: clean [force | pretend] [modname / all] [pattern 1] [pattern n]\n" "example: clean all *tmp */zzz* etmain/etkey\n" "Warning: This command deletes files in fs_homepath. If you are not sure how to use this command do not play with fire!\n"); return; } // if home- and basepath are same better don't start to clean ... if (FS_IsSamePath(Cvar_VariableString("fs_homepath"), Cvar_VariableString("fs_basepath"))) { Com_Printf("Invalid configuration to run clean cmd - 'fs_homepath' and 'fs_basepath' are equal.\n"); return; } // avoid unreferenced pk3 runtime issues (not on HD but still referenced in game) #ifndef DEDICATED if (cls.state != CA_DISCONNECTED) { Com_Printf("You are connected to a server - enter '/disconnect' to run '/clean'.\n"); return; } #else if (com_sv_running && com_sv_running->integer) { Com_Printf("Server is running - enter '/killserver' to run '/clean'.\n"); return; } #endif // DEDICATED Cvar_VariableStringBuffer("fs_homepath", path, sizeof(path)); // if there are any command options, they must be at the very beginning for (i = 1; i < Cmd_Argc(); i++) { if (!Q_stricmp(Cmd_Argv(i), "force") || !Q_stricmp(Cmd_Argv(i), "f")) { force = qtrue; continue; } if (!Q_stricmp(Cmd_Argv(i), "pretend") || !Q_stricmp(Cmd_Argv(i), "p")) { pretend = qtrue; continue; } break; } // if the first argument is "all" or "*", search the whole homepath if (Q_stricmp(Cmd_Argv(i), "all") && Q_stricmp(Cmd_Argv(i), "*")) { Q_strcat(path, sizeof(path), va("%c%s", PATH_SEP, Cmd_Argv(i))); // check if it points to a valid directory if (FS_OSStatFile(path) != 1) { Com_Printf("Cannot commence cleaning, because \"%s\" is not a valid directory under fs_homepath (%s)\n", Cmd_Argv(i), path); return; } } for (i++; i < Cmd_Argc(); i++) { char **pFiles = NULL; pFiles = Sys_ListFiles(path, NULL, Cmd_Argv(i), &patternFiles, qtrue); Com_Printf("Found %i files matching the pattern \"%s\" under %s\n", patternFiles, Cmd_Argv(i), path); for (j = 0; j < patternFiles; j++) { char *tokens; char tmp_whitelist[MAX_OSPATH]; qboolean whitelisted = qfalse; totalFiles++; Q_strncpyz(tmp_whitelist, (force ? Cvar_VariableString("com_cleanwhitelist") : va("%s %s", Cvar_VariableString("com_cleanwhitelist"), whitelist)), sizeof(tmp_whitelist)); // Check if this file is in the whitelist tokens = strtok(tmp_whitelist, " ,;"); while (tokens != NULL) { if (strstr(pFiles[j], tokens)) { Com_Printf("- skipping file[%i]: %s%c%s (whitelisted by pattern: %s)\n", j + 1, path, PATH_SEP, pFiles[j], tokens); whitelisted = qtrue; break; } tokens = strtok(NULL, " ,;"); } if (whitelisted) { continue; } if (!pretend) { Com_Printf("- removing file[%i]: %s%c%s\n", j + 1, path, PATH_SEP, pFiles[j]); if (force) { remove(va("%s%c%s", path, PATH_SEP, pFiles[j])); // enable *.so & *.dll lib deletion } else { FS_Remove(va("%s%c%s", path, PATH_SEP, pFiles[j])); } delFiles++; } else { Com_Printf("- pretending to remove file[%i]: %s%c%s\n", j + 1, path, PATH_SEP, pFiles[j]); } } Sys_FreeFileList(pFiles); patternFiles = 0; } Com_Printf("Path of fs_homepath cleaned - %i matches - %i files skipped - %i files deleted.\n", totalFiles, totalFiles - delFiles, delFiles); }
/** * @brief A complete command line has been parsed, so try to execute it * @param text */ void Cmd_ExecuteString(const char *text) { cmd_function_t *cmd, **prev; // execute the command line Cmd_TokenizeString(text); if (!Cmd_Argc()) { return; // no tokens } // check registered command functions for (prev = &cmd_functions ; *prev ; prev = &cmd->next) { cmd = *prev; if (!Q_stricmp(cmd_argv[0], cmd->name)) { // rearrange the links so that the command will be // near the head of the list next time it is used *prev = cmd->next; cmd->next = cmd_functions; cmd_functions = cmd; // perform the action if (!cmd->function) { // let the cgame or game handle it break; } else { cmd->function(); } return; } } // check cvars if (Cvar_Command()) { return; } // check client game commands if (com_cl_running && com_cl_running->integer && CL_GameCommand()) { return; } // check server game commands if (com_sv_running && com_sv_running->integer && SV_GameCommand()) { return; } // check ui commands if (com_cl_running && com_cl_running->integer && UI_GameCommand()) { return; } // send it as a server command if we are connected CL_ForwardCommandToServer(text); }
/* ==================== CL_CgameSystemCalls The cgame module is making a system call ==================== */ intptr_t CL_CgameSystemCalls( intptr_t *args ) { switch ( args[ 0 ] ) { case CG_PRINT: Com_Printf( "%s", ( char * ) VMA( 1 ) ); return 0; case CG_ERROR: Com_Error( ERR_DROP, "%s", ( char * ) VMA( 1 ) ); case CG_MILLISECONDS: return Sys_Milliseconds(); case CG_CVAR_REGISTER: Cvar_Register( VMA( 1 ), VMA( 2 ), VMA( 3 ), args[ 4 ] ); return 0; case CG_CVAR_UPDATE: Cvar_Update( VMA( 1 ) ); return 0; case CG_CVAR_SET: Cvar_Set( VMA( 1 ), VMA( 2 ) ); return 0; case CG_CVAR_VARIABLESTRINGBUFFER: VM_CheckBlock( args[2], args[3], "CVARVSB" ); Cvar_VariableStringBuffer( VMA( 1 ), VMA( 2 ), args[ 3 ] ); return 0; case CG_CVAR_LATCHEDVARIABLESTRINGBUFFER: VM_CheckBlock( args[2], args[3], "CVARLVSB" ); Cvar_LatchedVariableStringBuffer( VMA( 1 ), VMA( 2 ), args[ 3 ] ); return 0; case CG_CVAR_VARIABLEINTEGERVALUE: return Cvar_VariableIntegerValue( VMA( 1 ) ); case CG_ARGC: return Cmd_Argc(); case CG_ARGV: VM_CheckBlock( args[2], args[3], "ARGV" ); Cmd_ArgvBuffer( args[ 1 ], VMA( 2 ), args[ 3 ] ); return 0; case CG_ARGS: VM_CheckBlock( args[1], args[2], "ARGS" ); Cmd_ArgsBuffer( VMA( 1 ), args[ 2 ] ); return 0; case CG_LITERAL_ARGS: // FIXME VM_CheckBlock( args[1], args[2], "LARGS" ); Cmd_LiteralArgsBuffer( VMA( 1 ), args[ 2 ] ); // Cmd_ArgsBuffer(VMA(1), args[2]); return 0; case CG_GETDEMOSTATE: return CL_DemoState(); case CG_GETDEMOPOS: return CL_DemoPos(); case CG_FS_FOPENFILE: return FS_FOpenFileByMode( VMA( 1 ), VMA( 2 ), args[ 3 ] ); case CG_FS_READ: VM_CheckBlock( args[1], args[2], "FSREAD" ); FS_Read2( VMA( 1 ), args[ 2 ], args[ 3 ] ); return 0; case CG_FS_WRITE: VM_CheckBlock( args[1], args[2], "FSWRITE" ); return FS_Write( VMA( 1 ), args[ 2 ], args[ 3 ] ); case CG_FS_FCLOSEFILE: FS_FCloseFile( args[ 1 ] ); return 0; case CG_FS_GETFILELIST: VM_CheckBlock( args[3], args[4], "FSGFL" ); return FS_GetFileList( VMA( 1 ), VMA( 2 ), VMA( 3 ), args[ 4 ] ); case CG_FS_DELETEFILE: return FS_Delete( VMA( 1 ) ); case CG_SENDCONSOLECOMMAND: Cbuf_AddText( VMA( 1 ) ); return 0; case CG_ADDCOMMAND: CL_AddCgameCommand( VMA( 1 ) ); return 0; case CG_REMOVECOMMAND: Cmd_RemoveCommand( VMA( 1 ) ); return 0; case CG_COMPLETE_CALLBACK: if ( completer ) { completer( VMA( 1 ) ); } return 0; case CG_SENDCLIENTCOMMAND: CL_AddReliableCommand( VMA( 1 ) ); return 0; case CG_UPDATESCREEN: SCR_UpdateScreen(); return 0; case CG_CM_LOADMAP: CL_CM_LoadMap( VMA( 1 ) ); return 0; case CG_CM_NUMINLINEMODELS: return CM_NumInlineModels(); case CG_CM_INLINEMODEL: return CM_InlineModel( args[ 1 ] ); case CG_CM_TEMPBOXMODEL: return CM_TempBoxModel( VMA( 1 ), VMA( 2 ), qfalse ); case CG_CM_TEMPCAPSULEMODEL: return CM_TempBoxModel( VMA( 1 ), VMA( 2 ), qtrue ); case CG_CM_POINTCONTENTS: return CM_PointContents( VMA( 1 ), args[ 2 ] ); case CG_CM_TRANSFORMEDPOINTCONTENTS: return CM_TransformedPointContents( VMA( 1 ), args[ 2 ], VMA( 3 ), VMA( 4 ) ); case CG_CM_BOXTRACE: CM_BoxTrace( VMA( 1 ), VMA( 2 ), VMA( 3 ), VMA( 4 ), VMA( 5 ), args[ 6 ], args[ 7 ], TT_AABB ); return 0; case CG_CM_TRANSFORMEDBOXTRACE: CM_TransformedBoxTrace( VMA( 1 ), VMA( 2 ), VMA( 3 ), VMA( 4 ), VMA( 5 ), args[ 6 ], args[ 7 ], VMA( 8 ), VMA( 9 ), TT_AABB ); return 0; case CG_CM_CAPSULETRACE: CM_BoxTrace( VMA( 1 ), VMA( 2 ), VMA( 3 ), VMA( 4 ), VMA( 5 ), args[ 6 ], args[ 7 ], TT_CAPSULE ); return 0; case CG_CM_TRANSFORMEDCAPSULETRACE: CM_TransformedBoxTrace( VMA( 1 ), VMA( 2 ), VMA( 3 ), VMA( 4 ), VMA( 5 ), args[ 6 ], args[ 7 ], VMA( 8 ), VMA( 9 ), TT_CAPSULE ); return 0; case CG_CM_BISPHERETRACE: CM_BiSphereTrace( VMA( 1 ), VMA( 2 ), VMA( 3 ), VMF( 4 ), VMF( 5 ), args[ 6 ], args[ 7 ] ); return 0; case CG_CM_TRANSFORMEDBISPHERETRACE: CM_TransformedBiSphereTrace( VMA( 1 ), VMA( 2 ), VMA( 3 ), VMF( 4 ), VMF( 5 ), args[ 6 ], args[ 7 ], VMA( 8 ) ); return 0; case CG_CM_MARKFRAGMENTS: return re.MarkFragments( args[ 1 ], VMA( 2 ), VMA( 3 ), args[ 4 ], VMA( 5 ), args[ 6 ], VMA( 7 ) ); case CG_R_PROJECTDECAL: re.ProjectDecal( args[ 1 ], args[ 2 ], VMA( 3 ), VMA( 4 ), VMA( 5 ), args[ 6 ], args[ 7 ] ); return 0; case CG_R_CLEARDECALS: re.ClearDecals(); return 0; case CG_S_STARTSOUND: S_StartSound( VMA( 1 ), args[ 2 ], args[ 3 ], args[ 4 ] ); return 0; case CG_S_STARTSOUNDEX: S_StartSoundEx( VMA( 1 ), args[ 2 ], args[ 3 ], args[ 4 ] ); return 0; case CG_S_STARTLOCALSOUND: S_StartLocalSound( args[ 1 ], args[ 2 ] ); return 0; case CG_S_CLEARLOOPINGSOUNDS: S_ClearLoopingSounds( args[ 1 ] ); return 0; case CG_S_CLEARSOUNDS: /*if(args[1] == 0) { S_ClearSounds(qtrue, qfalse); } else if(args[1] == 1) { S_ClearSounds(qtrue, qtrue); }*/ return 0; case CG_S_ADDLOOPINGSOUND: S_AddLoopingSound( args[ 1 ], VMA( 2 ), VMA( 3 ), args[ 4 ] ); return 0; case CG_S_ADDREALLOOPINGSOUND: S_AddRealLoopingSound( args[ 1 ], VMA( 2 ), VMA( 3 ), args[ 4 ] ); return 0; case CG_S_STOPLOOPINGSOUND: S_StopLoopingSound( args[ 1 ] ); return 0; case CG_S_STOPSTREAMINGSOUND: // FIXME //S_StopEntStreamingSound(args[1]); return 0; case CG_S_UPDATEENTITYPOSITION: S_UpdateEntityPosition( args[ 1 ], VMA( 2 ) ); return 0; case CG_S_GETVOICEAMPLITUDE: return S_GetVoiceAmplitude( args[ 1 ] ); case CG_S_GETSOUNDLENGTH: return S_GetSoundLength( args[ 1 ] ); // ydnar: for looped sound starts case CG_S_GETCURRENTSOUNDTIME: return S_GetCurrentSoundTime(); case CG_S_RESPATIALIZE: S_Respatialize( args[ 1 ], VMA( 2 ), VMA( 3 ), args[ 4 ] ); return 0; case CG_S_REGISTERSOUND: #ifdef DOOMSOUND ///// (SA) DOOMSOUND return S_RegisterSound( VMA( 1 ) ); #else return S_RegisterSound( VMA( 1 ), args[ 2 ] ); #endif ///// (SA) DOOMSOUND case CG_S_STARTBACKGROUNDTRACK: //S_StartBackgroundTrack(VMA(1), VMA(2), args[3]); //----(SA) added fadeup time S_StartBackgroundTrack( VMA( 1 ), VMA( 2 ) ); return 0; case CG_S_FADESTREAMINGSOUND: // FIXME //S_FadeStreamingSound(VMF(1), args[2], args[3]); //----(SA) added music/all-streaming options return 0; case CG_S_STARTSTREAMINGSOUND: // FIXME //return S_StartStreamingSound(VMA(1), VMA(2), args[3], args[4], args[5]); return 0; case CG_R_LOADWORLDMAP: re.SetWorldVisData( CM_ClusterPVS( -1 ) ); re.LoadWorld( VMA( 1 ) ); return 0; case CG_R_REGISTERMODEL: return re.RegisterModel( VMA( 1 ) ); case CG_R_REGISTERSKIN: return re.RegisterSkin( VMA( 1 ) ); //----(SA) added case CG_R_GETSKINMODEL: return re.GetSkinModel( args[ 1 ], VMA( 2 ), VMA( 3 ) ); case CG_R_GETMODELSHADER: return re.GetShaderFromModel( args[ 1 ], args[ 2 ], args[ 3 ] ); //----(SA) end case CG_R_REGISTERSHADER: return re.RegisterShader( VMA( 1 ) ); case CG_R_REGISTERFONT: re.RegisterFontVM( VMA( 1 ), VMA( 2 ), args[ 3 ], VMA( 4 ) ); return 0; case CG_R_REGISTERSHADERNOMIP: return re.RegisterShaderNoMip( VMA( 1 ) ); #if defined( USE_REFLIGHT ) case CG_R_REGISTERSHADERLIGHTATTENUATION: return re.RegisterShaderLightAttenuation( VMA( 1 ) ); #endif case CG_R_CLEARSCENE: re.ClearScene(); return 0; case CG_R_ADDREFENTITYTOSCENE: re.AddRefEntityToScene( VMA( 1 ) ); return 0; #if defined( USE_REFLIGHT ) case CG_R_ADDREFLIGHTSTOSCENE: re.AddRefLightToScene( VMA( 1 ) ); return 0; #endif case CG_R_ADDPOLYTOSCENE: re.AddPolyToScene( args[ 1 ], args[ 2 ], VMA( 3 ) ); return 0; case CG_R_ADDPOLYSTOSCENE: re.AddPolysToScene( args[ 1 ], args[ 2 ], VMA( 3 ), args[ 4 ] ); return 0; case CG_R_ADDPOLYBUFFERTOSCENE: re.AddPolyBufferToScene( VMA( 1 ) ); return 0; case CG_R_ADDLIGHTTOSCENE: re.AddLightToScene( VMA( 1 ), VMF( 2 ), VMF( 3 ), VMF( 4 ), VMF( 5 ), VMF( 6 ), args[ 7 ], args[ 8 ] ); return 0; case CG_R_ADDADDITIVELIGHTTOSCENE: re.AddAdditiveLightToScene( VMA( 1 ), VMF( 2 ), VMF( 3 ), VMF( 4 ), VMF( 5 ) ); return 0; case CG_FS_SEEK: return FS_Seek( args[ 1 ], args[ 2 ], args[ 3 ] ); case CG_R_ADDCORONATOSCENE: re.AddCoronaToScene( VMA( 1 ), VMF( 2 ), VMF( 3 ), VMF( 4 ), VMF( 5 ), args[ 6 ], args[ 7 ] ); return 0; case CG_R_SETFOG: re.SetFog( args[ 1 ], args[ 2 ], args[ 3 ], VMF( 4 ), VMF( 5 ), VMF( 6 ), VMF( 7 ) ); return 0; case CG_R_SETGLOBALFOG: re.SetGlobalFog( args[ 1 ], args[ 2 ], VMF( 3 ), VMF( 4 ), VMF( 5 ), VMF( 6 ) ); return 0; case CG_R_RENDERSCENE: re.RenderScene( VMA( 1 ) ); return 0; case CG_R_SAVEVIEWPARMS: re.SaveViewParms(); return 0; case CG_R_RESTOREVIEWPARMS: re.RestoreViewParms(); return 0; case CG_R_SETCOLOR: re.SetColor( VMA( 1 ) ); return 0; // Tremulous case CG_R_SETCLIPREGION: re.SetClipRegion( VMA( 1 ) ); return 0; case CG_R_DRAWSTRETCHPIC: re.DrawStretchPic( VMF( 1 ), VMF( 2 ), VMF( 3 ), VMF( 4 ), VMF( 5 ), VMF( 6 ), VMF( 7 ), VMF( 8 ), args[ 9 ] ); return 0; case CG_R_DRAWROTATEDPIC: re.DrawRotatedPic( VMF( 1 ), VMF( 2 ), VMF( 3 ), VMF( 4 ), VMF( 5 ), VMF( 6 ), VMF( 7 ), VMF( 8 ), args[ 9 ], VMF( 10 ) ); return 0; case CG_R_DRAWSTRETCHPIC_GRADIENT: re.DrawStretchPicGradient( VMF( 1 ), VMF( 2 ), VMF( 3 ), VMF( 4 ), VMF( 5 ), VMF( 6 ), VMF( 7 ), VMF( 8 ), args[ 9 ], VMA( 10 ), args[ 11 ] ); return 0; case CG_R_DRAW2DPOLYS: re.Add2dPolys( VMA( 1 ), args[ 2 ], args[ 3 ] ); return 0; case CG_R_MODELBOUNDS: re.ModelBounds( args[ 1 ], VMA( 2 ), VMA( 3 ) ); return 0; case CG_R_LERPTAG: return re.LerpTag( VMA( 1 ), VMA( 2 ), VMA( 3 ), args[ 4 ] ); case CG_GETGLCONFIG: CL_GetGlconfig( VMA( 1 ) ); return 0; case CG_GETGAMESTATE: CL_GetGameState( VMA( 1 ) ); return 0; case CG_GETCURRENTSNAPSHOTNUMBER: CL_GetCurrentSnapshotNumber( VMA( 1 ), VMA( 2 ) ); return 0; case CG_GETSNAPSHOT: return CL_GetSnapshot( args[ 1 ], VMA( 2 ) ); case CG_GETSERVERCOMMAND: return CL_GetServerCommand( args[ 1 ] ); case CG_GETCURRENTCMDNUMBER: return CL_GetCurrentCmdNumber(); case CG_GETUSERCMD: return CL_GetUserCmd( args[ 1 ], VMA( 2 ) ); case CG_SETUSERCMDVALUE: CL_SetUserCmdValue( args[ 1 ], args[ 2 ], VMF( 3 ), args[ 4 ] ); return 0; case CG_SETCLIENTLERPORIGIN: CL_SetClientLerpOrigin( VMF( 1 ), VMF( 2 ), VMF( 3 ) ); return 0; case CG_MEMORY_REMAINING: return Hunk_MemoryRemaining(); case CG_KEY_ISDOWN: return Key_IsDown( args[ 1 ] ); case CG_KEY_GETCATCHER: return Key_GetCatcher(); case CG_KEY_SETCATCHER: Key_SetCatcher( args[ 1 ] ); return 0; case CG_KEY_GETKEY: return Key_GetKey( VMA( 1 ) ); case CG_KEY_GETOVERSTRIKEMODE: return Key_GetOverstrikeMode(); case CG_KEY_SETOVERSTRIKEMODE: Key_SetOverstrikeMode( args[ 1 ] ); return 0; case CG_S_STOPBACKGROUNDTRACK: S_StopBackgroundTrack(); return 0; case CG_REAL_TIME: return Com_RealTime( VMA( 1 ) ); case CG_SNAPVECTOR: Q_SnapVector( VMA( 1 ) ); return 0; case CG_CIN_PLAYCINEMATIC: return CIN_PlayCinematic( VMA( 1 ), args[ 2 ], args[ 3 ], args[ 4 ], args[ 5 ], args[ 6 ] ); case CG_CIN_STOPCINEMATIC: return CIN_StopCinematic( args[ 1 ] ); case CG_CIN_RUNCINEMATIC: return CIN_RunCinematic( args[ 1 ] ); case CG_CIN_DRAWCINEMATIC: CIN_DrawCinematic( args[ 1 ] ); return 0; case CG_CIN_SETEXTENTS: CIN_SetExtents( args[ 1 ], args[ 2 ], args[ 3 ], args[ 4 ], args[ 5 ] ); return 0; case CG_R_REMAP_SHADER: re.RemapShader( VMA( 1 ), VMA( 2 ), VMA( 3 ) ); return 0; case CG_GET_ENTITY_TOKEN: VM_CheckBlock( args[1], args[2], "GETET" ); return re.GetEntityToken( VMA( 1 ), args[ 2 ] ); case CG_INGAME_POPUP: if ( cls.state == CA_ACTIVE && !clc.demoplaying ) { if ( uivm ) { // Gordon: can be called as the system is shutting down VM_Call( uivm, UI_SET_ACTIVE_MENU, args[ 1 ] ); } } return 0; case CG_INGAME_CLOSEPOPUP: return 0; case CG_KEY_GETBINDINGBUF: VM_CheckBlock( args[2], args[3], "KEYGBB" ); Key_GetBindingBuf( args[ 1 ], VMA( 2 ), args[ 3 ] ); return 0; case CG_KEY_SETBINDING: Key_SetBinding( args[ 1 ], VMA( 2 ) ); return 0; case CG_PARSE_ADD_GLOBAL_DEFINE: return Parse_AddGlobalDefine( VMA( 1 ) ); case CG_PARSE_LOAD_SOURCE: return Parse_LoadSourceHandle( VMA( 1 ) ); case CG_PARSE_FREE_SOURCE: return Parse_FreeSourceHandle( args[ 1 ] ); case CG_PARSE_READ_TOKEN: return Parse_ReadTokenHandle( args[ 1 ], VMA( 2 ) ); case CG_PARSE_SOURCE_FILE_AND_LINE: return Parse_SourceFileAndLine( args[ 1 ], VMA( 2 ), VMA( 3 ) ); case CG_KEY_KEYNUMTOSTRINGBUF: VM_CheckBlock( args[2], args[3], "KEYNTSB" ); Key_KeynumToStringBuf( args[ 1 ], VMA( 2 ), args[ 3 ] ); return 0; case CG_KEY_BINDINGTOKEYS: Key_GetBindingByString( VMA( 1 ), VMA( 2 ), VMA( 3 ) ); return 0; case CG_S_FADEALLSOUNDS: // FIXME //S_FadeAllSounds(VMF(1), args[2], args[3]); return 0; case CG_R_INPVS: return re.inPVS( VMA( 1 ), VMA( 2 ) ); case CG_GETHUNKDATA: Com_GetHunkInfo( VMA( 1 ), VMA( 2 ) ); return 0; //bani - dynamic shaders case CG_R_LOADDYNAMICSHADER: return re.LoadDynamicShader( VMA( 1 ), VMA( 2 ) ); // fretn - render to texture case CG_R_RENDERTOTEXTURE: re.RenderToTexture( args[ 1 ], args[ 2 ], args[ 3 ], args[ 4 ], args[ 5 ] ); return 0; //bani case CG_R_GETTEXTUREID: return re.GetTextureId( VMA( 1 ) ); //bani - flush gl rendering buffers case CG_R_FINISH: re.Finish(); return 0; case CG_GETDEMONAME: VM_CheckBlock( args[1], args[2], "GETDM" ); CL_DemoName( VMA( 1 ), args[ 2 ] ); return 0; case CG_R_LIGHTFORPOINT: return re.LightForPoint( VMA( 1 ), VMA( 2 ), VMA( 3 ), VMA( 4 ) ); case CG_S_SOUNDDURATION: return S_SoundDuration( args[ 1 ] ); #if defined( USE_REFENTITY_ANIMATIONSYSTEM ) case CG_R_REGISTERANIMATION: return re.RegisterAnimation( VMA( 1 ) ); case CG_R_CHECKSKELETON: return re.CheckSkeleton( VMA( 1 ), args[ 2 ], args[ 3 ] ); case CG_R_BUILDSKELETON: return re.BuildSkeleton( VMA( 1 ), args[ 2 ], args[ 3 ], args[ 4 ], VMF( 5 ), args[ 6 ] ); case CG_R_BLENDSKELETON: return re.BlendSkeleton( VMA( 1 ), VMA( 2 ), VMF( 3 ) ); case CG_R_BONEINDEX: return re.BoneIndex( args[ 1 ], VMA( 2 ) ); case CG_R_ANIMNUMFRAMES: return re.AnimNumFrames( args[ 1 ] ); case CG_R_ANIMFRAMERATE: return re.AnimFrameRate( args[ 1 ] ); #endif case CG_REGISTER_BUTTON_COMMANDS: CL_RegisterButtonCommands( VMA( 1 ) ); return 0; case CG_GETCLIPBOARDDATA: VM_CheckBlock( args[1], args[2], "GETCLIP" ); if ( cl_allowPaste->integer ) { CL_GetClipboardData( VMA(1), args[2], args[3] ); } else { ( (char *) VMA( 1 ) )[0] = '\0'; } return 0; case CG_QUOTESTRING: Cmd_QuoteStringBuffer( VMA( 1 ), VMA( 2 ), args[ 3 ] ); return 0; case CG_GETTEXT: strncpy( VMA(1), __(VMA(2)), args[3] ); return 0; case CG_PGETTEXT: strncpy( VMA( 1 ), C__( VMA( 2 ), VMA( 3 ) ), args[ 4 ] ); return 0; case CG_R_GLYPH: re.GlyphVM( args[1], VMA(2), VMA(3) ); return 0; case CG_R_GLYPHCHAR: re.GlyphCharVM( args[1], args[2], VMA(3) ); return 0; case CG_R_UREGISTERFONT: re.UnregisterFontVM( args[1] ); return 0; default: Com_Error( ERR_DROP, "Bad cgame system trap: %ld", ( long int ) args[ 0 ] ); } return 0; }
/* =================== CL_GetServerCommand Set up argc/argv for the given command =================== */ qboolean CL_GetServerCommand( int serverCommandNumber ) { const char *s; char *cmd; static char bigConfigString[ BIG_INFO_STRING ]; int argc; // if we have irretrievably lost a reliable command, drop the connection if ( serverCommandNumber <= clc.serverCommandSequence - MAX_RELIABLE_COMMANDS ) { // when a demo record was started after the client got a whole bunch of // reliable commands then the client never got those first reliable commands if ( clc.demoplaying ) { return qfalse; } Com_Error( ERR_DROP, "CL_GetServerCommand: a reliable command was cycled out" ); } if ( serverCommandNumber > clc.serverCommandSequence ) { Com_Error( ERR_DROP, "CL_GetServerCommand: requested a command not received" ); } s = clc.serverCommands[ serverCommandNumber & ( MAX_RELIABLE_COMMANDS - 1 ) ]; clc.lastExecutedServerCommand = serverCommandNumber; if ( cl_showServerCommands->integer ) { // NERVE - SMF Com_Printf( "serverCommand: %i : %s\n", serverCommandNumber, s ); } rescan: Cmd_TokenizeString( s ); cmd = Cmd_Argv( 0 ); argc = Cmd_Argc(); if ( !strcmp( cmd, "disconnect" ) ) { // NERVE - SMF - allow server to indicate why they were disconnected if ( argc >= 2 ) { Com_Error( ERR_SERVERDISCONNECT, "Server disconnected: %s", Cmd_Argv( 1 ) ); } else { Com_Error( ERR_SERVERDISCONNECT, "Server disconnected" ); } } if ( !strcmp( cmd, "bcs0" ) ) { Com_sprintf( bigConfigString, BIG_INFO_STRING, "cs %s %s", Cmd_Argv( 1 ), Cmd_QuoteString( Cmd_Argv( 2 ) ) ); return qfalse; } if ( !strcmp( cmd, "bcs1" ) ) { s = Cmd_QuoteString( Cmd_Argv( 2 ) ); if ( strlen( bigConfigString ) + strlen( s ) >= BIG_INFO_STRING ) { Com_Error( ERR_DROP, "bcs exceeded BIG_INFO_STRING" ); } strcat( bigConfigString, s ); return qfalse; } if ( !strcmp( cmd, "bcs2" ) ) { s = Cmd_QuoteString( Cmd_Argv( 2 ) ); if ( strlen( bigConfigString ) + strlen( s ) + 1 >= BIG_INFO_STRING ) { Com_Error( ERR_DROP, "bcs exceeded BIG_INFO_STRING" ); } strcat( bigConfigString, s ); strcat( bigConfigString, "\"" ); s = bigConfigString; goto rescan; } if ( !strcmp( cmd, "cs" ) ) { CL_ConfigstringModified(); // reparse the string, because CL_ConfigstringModified may have done another Cmd_TokenizeString() Cmd_TokenizeString( s ); return qtrue; } if ( !strcmp( cmd, "map_restart" ) ) { // clear notify lines and outgoing commands before passing // the restart to the cgame Con_ClearNotify(); memset( cl.cmds, 0, sizeof( cl.cmds ) ); return qtrue; } if ( !strcmp( cmd, "popup" ) ) { // direct server to client popup request, bypassing cgame // trap_UI_Popup(Cmd_Argv(1)); // if ( cls.state == CA_ACTIVE && !clc.demoplaying ) { // VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_CLIPBOARD); // Menus_OpenByName(Cmd_Argv(1)); // } return qfalse; } if ( !strcmp( cmd, "pubkey_decrypt" ) ) { char buffer[ MAX_STRING_CHARS ] = "pubkey_identify "; unsigned int msg_len = MAX_STRING_CHARS - 16; mpz_t message; if ( argc == 1 ) { Com_Printf("%s", _( "^3Server sent a pubkey_decrypt command, but sent nothing to decrypt!\n" )); return qfalse; } mpz_init_set_str( message, Cmd_Argv( 1 ), 16 ); if ( rsa_decrypt( &private_key, &msg_len, ( unsigned char * ) buffer + 16, message ) ) { nettle_mpz_set_str_256_u( message, msg_len, ( unsigned char * ) buffer + 16 ); mpz_get_str( buffer + 16, 16, message ); CL_AddReliableCommand( buffer ); } mpz_clear( message ); return qfalse; } // we may want to put a "connect to other server" command here // cgame can now act on the command return qtrue; }
/* ================= SV_VerifyPaks_f If we are pure, disconnect the client if they do no meet the following conditions: 1. the first two checksums match our view of cgame and ui 2. there are no any additional checksums that we do not have This routine would be a bit simpler with a goto but i abstained ================= */ static void SV_VerifyPaks_f( client_t *cl ) { int nChkSum1, nChkSum2, nClientPaks, nServerPaks, i, j, nCurArg; int nClientChkSum[1024]; int nServerChkSum[1024]; const char *pPaks, *pArg; qboolean bGood = qtrue; // if we are pure, we "expect" the client to load certain things from // certain pk3 files, namely we want the client to have loaded the // ui and cgame that we think should be loaded based on the pure setting // if ( sv_pure->integer != 0 ) { bGood = qtrue; nChkSum1 = nChkSum2 = 0; // we run the game, so determine which cgame and ui the client "should" be running //dlls are valid too now -rww bGood = (qboolean)(FS_FileIsInPAK("cgamex86.dll", &nChkSum1) == 1); if (bGood) bGood = (qboolean)(FS_FileIsInPAK("uix86.dll", &nChkSum2) == 1); nClientPaks = Cmd_Argc(); // start at arg 1 ( skip cl_paks ) nCurArg = 1; // we basically use this while loop to avoid using 'goto' :) while (bGood) { // must be at least 6: "cl_paks cgame ui @ firstref ... numChecksums" // numChecksums is encoded if (nClientPaks < 6) { bGood = qfalse; break; } // verify first to be the cgame checksum pArg = Cmd_Argv(nCurArg++); if (!pArg || *pArg == '@' || atoi(pArg) != nChkSum1 ) { bGood = qfalse; break; } // verify the second to be the ui checksum pArg = Cmd_Argv(nCurArg++); if (!pArg || *pArg == '@' || atoi(pArg) != nChkSum2 ) { bGood = qfalse; break; } // should be sitting at the delimeter now pArg = Cmd_Argv(nCurArg++); if (*pArg != '@') { bGood = qfalse; break; } // store checksums since tokenization is not re-entrant for (i = 0; nCurArg < nClientPaks; i++) { nClientChkSum[i] = atoi(Cmd_Argv(nCurArg++)); } // store number to compare against (minus one cause the last is the number of checksums) nClientPaks = i - 1; // make sure none of the client check sums are the same // so the client can't send 5 the same checksums for (i = 0; i < nClientPaks; i++) { for (j = 0; j < nClientPaks; j++) { if (i == j) continue; if (nClientChkSum[i] == nClientChkSum[j]) { bGood = qfalse; break; } } if (bGood == qfalse) break; } if (bGood == qfalse) break; // get the pure checksums of the pk3 files loaded by the server pPaks = FS_LoadedPakPureChecksums(); Cmd_TokenizeString( pPaks ); nServerPaks = Cmd_Argc(); if (nServerPaks > 1024) nServerPaks = 1024; for (i = 0; i < nServerPaks; i++) { nServerChkSum[i] = atoi(Cmd_Argv(i)); } // check if the client has provided any pure checksums of pk3 files not loaded by the server for (i = 0; i < nClientPaks; i++) { for (j = 0; j < nServerPaks; j++) { if (nClientChkSum[i] == nServerChkSum[j]) { break; } } if (j >= nServerPaks) { bGood = qfalse; break; } } if ( bGood == qfalse ) { break; } // check if the number of checksums was correct nChkSum1 = sv.checksumFeed; for (i = 0; i < nClientPaks; i++) { nChkSum1 ^= nClientChkSum[i]; } nChkSum1 ^= nClientPaks; if (nChkSum1 != nClientChkSum[nClientPaks]) { bGood = qfalse; break; } // break out break; } cl->gotCP = qtrue; if (bGood) { cl->pureAuthentic = 1; } else { cl->pureAuthentic = 0; cl->nextSnapshotTime = -1; cl->state = CS_ACTIVE; SV_SendClientSnapshot( cl ); SV_DropClient( cl, "Unpure client detected. Invalid .PK3 files referenced!" ); } } }
/* =================== CL_GetServerCommand Set up argc/argv for the given command =================== */ qboolean CL_GetServerCommand( int serverCommandNumber ) { char *s; char *cmd; static char bigConfigString[BIG_INFO_STRING]; int argc; // if we have irretrievably lost a reliable command, drop the connection if ( serverCommandNumber <= clc.serverCommandSequence - MAX_RELIABLE_COMMANDS ) { // when a demo record was started after the client got a whole bunch of // reliable commands then the client never got those first reliable commands if ( clc.demoplaying ) return qfalse; Com_Error( ERR_DROP, "CL_GetServerCommand: a reliable command was cycled out" ); return qfalse; } if ( serverCommandNumber > clc.serverCommandSequence ) { Com_Error( ERR_DROP, "CL_GetServerCommand: requested a command not received" ); return qfalse; } s = clc.serverCommands[ serverCommandNumber & ( MAX_RELIABLE_COMMANDS - 1 ) ]; clc.lastExecutedServerCommand = serverCommandNumber; Com_DPrintf( "serverCommand: %i : %s\n", serverCommandNumber, s ); rescan: Cmd_TokenizeString( s ); cmd = Cmd_Argv(0); argc = Cmd_Argc(); if ( !strcmp( cmd, "disconnect" ) ) { // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=552 // allow server to indicate why they were disconnected if ( argc >= 2 ) Com_Error( ERR_SERVERDISCONNECT, "Server disconnected - %s", Cmd_Argv( 1 ) ); else Com_Error( ERR_SERVERDISCONNECT, "Server disconnected" ); } if ( !strcmp( cmd, "bcs0" ) ) { Com_sprintf( bigConfigString, BIG_INFO_STRING, "cs %s \"%s", Cmd_Argv(1), Cmd_Argv(2) ); return qfalse; } if ( !strcmp( cmd, "bcs1" ) ) { s = Cmd_Argv(2); if( strlen(bigConfigString) + strlen(s) >= BIG_INFO_STRING ) { Com_Error( ERR_DROP, "bcs exceeded BIG_INFO_STRING" ); } strcat( bigConfigString, s ); return qfalse; } if ( !strcmp( cmd, "bcs2" ) ) { s = Cmd_Argv(2); if( strlen(bigConfigString) + strlen(s) + 1 >= BIG_INFO_STRING ) { Com_Error( ERR_DROP, "bcs exceeded BIG_INFO_STRING" ); } strcat( bigConfigString, s ); strcat( bigConfigString, "\"" ); s = bigConfigString; goto rescan; } if ( !strcmp( cmd, "cs" ) ) { CL_ConfigstringModified(); // reparse the string, because CL_ConfigstringModified may have done another Cmd_TokenizeString() Cmd_TokenizeString( s ); return qtrue; } if ( !strcmp( cmd, "map_restart" ) ) { // clear notify lines and outgoing commands before passing // the restart to the cgame Con_ClearNotify(); // reparse the string, because Con_ClearNotify() may have done another Cmd_TokenizeString() Cmd_TokenizeString( s ); Com_Memset( cl.cmds, 0, sizeof( cl.cmds ) ); return qtrue; } // the clientLevelShot command is used during development // to generate 128*128 screenshots from the intermission // point of levels for the menu system to use // we pass it along to the cgame to make apropriate adjustments, // but we also clear the console and notify lines here if ( !strcmp( cmd, "clientLevelShot" ) ) { // don't do it if we aren't running the server locally, // otherwise malicious remote servers could overwrite // the existing thumbnails if ( !com_sv_running->integer ) { return qfalse; } // close the console Con_Close(); // take a special screenshot next frame Cbuf_AddText( "wait ; wait ; wait ; wait ; screenshot levelshot\n" ); return qtrue; } // we may want to put a "connect to other server" command here // cgame can now act on the command return qtrue; }
static void dissect_quakeworld_ConnectionlessPacket(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int direction) { proto_tree *cl_tree; proto_tree *text_tree = NULL; proto_item *pi = NULL; guint8 *text; int len; int offset; guint32 marker; int command_len; const char *command = ""; gboolean command_finished = FALSE; marker = tvb_get_ntohl(tvb, 0); cl_tree = proto_tree_add_subtree(tree, tvb, 0, -1, ett_quakeworld_connectionless, NULL, "Connectionless"); proto_tree_add_uint(cl_tree, hf_quakeworld_connectionless_marker, tvb, 0, 4, marker); /* all the rest of the packet is just text */ offset = 4; text = tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, &len, ENC_ASCII|ENC_NA); /* actually, we should look for a eol char and stop already there */ if (cl_tree) { proto_item *text_item; text_item = proto_tree_add_string(cl_tree, hf_quakeworld_connectionless_text, tvb, offset, len, text); text_tree = proto_item_add_subtree(text_item, ett_quakeworld_connectionless_text); } if (direction == DIR_C2S) { /* client to server commands */ const char *c; Cmd_TokenizeString(text, len); c = Cmd_Argv(0); /* client to sever commands */ if (strcmp(c,"ping") == 0) { command = "Ping"; command_len = 4; } else if (strcmp(c,"status") == 0) { command = "Status"; command_len = 6; } else if (strcmp(c,"log") == 0) { command = "Log"; command_len = 3; } else if (strcmp(c,"connect") == 0) { guint32 version = 0; guint16 qport = 0; guint32 challenge = 0; gboolean version_valid = TRUE; gboolean qport_valid = TRUE; gboolean challenge_valid = TRUE; const char *infostring; proto_tree *argument_tree = NULL; command = "Connect"; command_len = Cmd_Argv_length(0); if (text_tree) { proto_item *argument_item; pi = proto_tree_add_string(text_tree, hf_quakeworld_connectionless_command, tvb, offset, command_len, command); argument_item = proto_tree_add_string(text_tree, hf_quakeworld_connectionless_arguments, tvb, offset + Cmd_Argv_start(1), len + 1 - Cmd_Argv_start(1), text + Cmd_Argv_start(1)); argument_tree = proto_item_add_subtree(argument_item, ett_quakeworld_connectionless_arguments); command_finished=TRUE; } version_valid = ws_strtou32(Cmd_Argv(1), NULL, &version); qport_valid = ws_strtou16(Cmd_Argv(2), NULL, &qport); challenge_valid = ws_strtou32(Cmd_Argv(3), NULL, &challenge); infostring = Cmd_Argv(4); if (text_tree && (!version_valid || !qport_valid || !challenge_valid)) expert_add_info(pinfo, pi, &ei_quakeworld_connectionless_command_invalid); if (argument_tree) { proto_item *info_item; proto_tree *info_tree; proto_tree_add_uint(argument_tree, hf_quakeworld_connectionless_connect_version, tvb, offset + Cmd_Argv_start(1), Cmd_Argv_length(1), version); proto_tree_add_uint(argument_tree, hf_quakeworld_connectionless_connect_qport, tvb, offset + Cmd_Argv_start(2), Cmd_Argv_length(2), qport); proto_tree_add_int(argument_tree, hf_quakeworld_connectionless_connect_challenge, tvb, offset + Cmd_Argv_start(3), Cmd_Argv_length(3), challenge); info_item = proto_tree_add_string(argument_tree, hf_quakeworld_connectionless_connect_infostring, tvb, offset + Cmd_Argv_start(4), Cmd_Argv_length(4), infostring); info_tree = proto_item_add_subtree( info_item, ett_quakeworld_connectionless_connect_infostring); dissect_id_infostring(tvb, info_tree, offset + Cmd_Argv_start(4), wmem_strdup(wmem_packet_scope(), infostring), ett_quakeworld_connectionless_connect_infostring_key_value, hf_quakeworld_connectionless_connect_infostring_key_value, hf_quakeworld_connectionless_connect_infostring_key, hf_quakeworld_connectionless_connect_infostring_value); } } else if (strcmp(c,"getchallenge") == 0) { command = "Get Challenge"; command_len = Cmd_Argv_length(0); } else if (strcmp(c,"rcon") == 0) { const char* password; int i; char remaining[MAX_TEXT_SIZE+1]; proto_tree *argument_tree = NULL; command = "Remote Command"; command_len = Cmd_Argv_length(0); if (text_tree) { proto_item *argument_item; proto_tree_add_string(text_tree, hf_quakeworld_connectionless_command, tvb, offset, command_len, command); argument_item = proto_tree_add_string(text_tree, hf_quakeworld_connectionless_arguments, tvb, offset + Cmd_Argv_start(1), len - Cmd_Argv_start(1), text + Cmd_Argv_start(1)); argument_tree = proto_item_add_subtree(argument_item, ett_quakeworld_connectionless_arguments); command_finished=TRUE; } password = Cmd_Argv(1); if (argument_tree) { proto_tree_add_string(argument_tree, hf_quakeworld_connectionless_rcon_password, tvb, offset + Cmd_Argv_start(1), Cmd_Argv_length(1), password); } remaining[0] = '\0'; for (i=2; i<Cmd_Argc() ; i++) { g_strlcat (remaining, Cmd_Argv(i), MAX_TEXT_SIZE+1); g_strlcat (remaining, " ", MAX_TEXT_SIZE+1); } if (text_tree) { proto_tree_add_string(argument_tree, hf_quakeworld_connectionless_rcon_command, tvb, offset + Cmd_Argv_start(2), Cmd_Argv_start(Cmd_Argc()-1) + Cmd_Argv_length(Cmd_Argc()-1) - Cmd_Argv_start(2), remaining); } } else if (c[0]==A2A_PING && ( c[1]=='\0' || c[1]=='\n')) { command = "Ping"; command_len = 1; } else if (c[0]==A2A_ACK && ( c[1]=='\0' || c[1]=='\n')) { command = "Ack"; command_len = 1; } else { command = "Unknown"; command_len = len - 1; } } else { /* server to client commands */ if (text[0] == S2C_CONNECTION) { command = "Connected"; command_len = 1; } else if (text[0] == A2C_CLIENT_COMMAND) { command = "Client Command"; command_len = 1; /* stringz (command), stringz (localid) */ } else if (text[0] == A2C_PRINT) { command = "Print"; command_len = 1; /* string */ } else if (text[0] == A2A_PING) { command = "Ping"; command_len = 1; } else if (text[0] == S2C_CHALLENGE) { command = "Challenge"; command_len = 1; /* string, conversion */ } else { command = "Unknown"; command_len = len - 1; } } col_append_fstr(pinfo->cinfo, COL_INFO, " %s", command); if (!command_finished) { proto_tree_add_string(text_tree, hf_quakeworld_connectionless_command, tvb, offset, command_len, command); } /*offset += len;*/ }
/* ==================== CL_CgameSystemCalls The cgame module is making a system call ==================== */ intptr_t CL_CgameSystemCalls( intptr_t *args ) { switch( args[0] ) { case CG_PRINT: Com_Printf( "%s", (const char*)VMA(1) ); return 0; case CG_ERROR: Com_Error( ERR_DROP, "%s", (const char*)VMA(1) ); return 0; case CG_MILLISECONDS: return Sys_Milliseconds(); case CG_CVAR_REGISTER: Cvar_Register( VMA(1), VMA(2), VMA(3), args[4] ); return 0; case CG_CVAR_UPDATE: Cvar_Update( VMA(1) ); return 0; case CG_CVAR_SET: Cvar_SetSafe( VMA(1), VMA(2) ); return 0; case CG_CVAR_VARIABLESTRINGBUFFER: Cvar_VariableStringBuffer( VMA(1), VMA(2), args[3] ); return 0; case CG_ARGC: return Cmd_Argc(); case CG_ARGV: Cmd_ArgvBuffer( args[1], VMA(2), args[3] ); return 0; case CG_ARGS: Cmd_ArgsBuffer( VMA(1), args[2] ); return 0; case CG_FS_FOPENFILE: return FS_FOpenFileByMode( VMA(1), VMA(2), args[3] ); case CG_FS_READ: FS_Read2( VMA(1), args[2], args[3] ); return 0; case CG_FS_WRITE: FS_Write( VMA(1), args[2], args[3] ); return 0; case CG_FS_FCLOSEFILE: FS_FCloseFile( args[1] ); return 0; case CG_FS_SEEK: return FS_Seek( args[1], args[2], args[3] ); case CG_SENDCONSOLECOMMAND: Cbuf_AddText( VMA(1) ); return 0; case CG_ADDCOMMAND: CL_AddCgameCommand( VMA(1) ); return 0; case CG_REMOVECOMMAND: Cmd_RemoveCommandSafe( VMA(1) ); return 0; case CG_SENDCLIENTCOMMAND: CL_AddReliableCommand(VMA(1), qfalse); return 0; case CG_UPDATESCREEN: // this is used during lengthy level loading, so pump message loop // Com_EventLoop(); // FIXME: if a server restarts here, BAD THINGS HAPPEN! // We can't call Com_EventLoop here, a restart will crash and this _does_ happen // if there is a map change while we are downloading at pk3. // ZOID SCR_UpdateScreen(); return 0; case CG_CM_LOADMAP: CL_CM_LoadMap( VMA(1) ); return 0; case CG_CM_NUMINLINEMODELS: return CM_NumInlineModels(); case CG_CM_INLINEMODEL: return CM_InlineModel( args[1] ); case CG_CM_TEMPBOXMODEL: return CM_TempBoxModel( VMA(1), VMA(2), /*int capsule*/ qfalse ); case CG_CM_TEMPCAPSULEMODEL: return CM_TempBoxModel( VMA(1), VMA(2), /*int capsule*/ qtrue ); case CG_CM_POINTCONTENTS: return CM_PointContents( VMA(1), args[2] ); case CG_CM_TRANSFORMEDPOINTCONTENTS: return CM_TransformedPointContents( VMA(1), args[2], VMA(3), VMA(4) ); case CG_CM_BOXTRACE: CM_BoxTrace( VMA(1), VMA(2), VMA(3), VMA(4), VMA(5), args[6], args[7], /*int capsule*/ qfalse ); return 0; case CG_CM_CAPSULETRACE: CM_BoxTrace( VMA(1), VMA(2), VMA(3), VMA(4), VMA(5), args[6], args[7], /*int capsule*/ qtrue ); return 0; case CG_CM_TRANSFORMEDBOXTRACE: CM_TransformedBoxTrace( VMA(1), VMA(2), VMA(3), VMA(4), VMA(5), args[6], args[7], VMA(8), VMA(9), /*int capsule*/ qfalse ); return 0; case CG_CM_TRANSFORMEDCAPSULETRACE: CM_TransformedBoxTrace( VMA(1), VMA(2), VMA(3), VMA(4), VMA(5), args[6], args[7], VMA(8), VMA(9), /*int capsule*/ qtrue ); return 0; case CG_CM_MARKFRAGMENTS: return re.MarkFragments( args[1], VMA(2), VMA(3), args[4], VMA(5), args[6], VMA(7) ); case CG_S_STARTSOUND: S_StartSound( VMA(1), args[2], args[3], args[4] ); return 0; case CG_S_STARTLOCALSOUND: S_StartLocalSound( args[1], args[2] ); return 0; case CG_S_CLEARLOOPINGSOUNDS: S_ClearLoopingSounds(args[1]); return 0; case CG_S_ADDLOOPINGSOUND: S_AddLoopingSound( args[1], VMA(2), VMA(3), args[4] ); return 0; case CG_S_ADDREALLOOPINGSOUND: S_AddRealLoopingSound( args[1], VMA(2), VMA(3), args[4] ); return 0; case CG_S_STOPLOOPINGSOUND: S_StopLoopingSound( args[1] ); return 0; case CG_S_UPDATEENTITYPOSITION: S_UpdateEntityPosition( args[1], VMA(2) ); return 0; case CG_S_RESPATIALIZE: S_Respatialize( args[1], VMA(2), VMA(3), args[4] ); return 0; case CG_S_REGISTERSOUND: return S_RegisterSound( VMA(1), args[2] ); case CG_S_STARTBACKGROUNDTRACK: S_StartBackgroundTrack( VMA(1), VMA(2) ); return 0; case CG_R_LOADWORLDMAP: re.LoadWorld( VMA(1) ); return 0; case CG_R_REGISTERMODEL: return re.RegisterModel( VMA(1) ); case CG_R_REGISTERSKIN: return re.RegisterSkin( VMA(1) ); case CG_R_REGISTERSHADER: return re.RegisterShader( VMA(1) ); case CG_R_REGISTERSHADERNOMIP: return re.RegisterShaderNoMip( VMA(1) ); case CG_R_REGISTERFONT: re.RegisterFont( VMA(1), args[2], VMA(3)); return 0; case CG_R_CLEARSCENE: re.ClearScene(); return 0; case CG_R_ADDREFENTITYTOSCENE: re.AddRefEntityToScene( VMA(1) ); return 0; case CG_R_ADDPOLYTOSCENE: re.AddPolyToScene( args[1], args[2], VMA(3), 1 ); return 0; case CG_R_ADDPOLYSTOSCENE: re.AddPolyToScene( args[1], args[2], VMA(3), args[4] ); return 0; case CG_R_LIGHTFORPOINT: return re.LightForPoint( VMA(1), VMA(2), VMA(3), VMA(4) ); case CG_R_ADDLIGHTTOSCENE: re.AddLightToScene( VMA(1), VMF(2), VMF(3), VMF(4), VMF(5) ); return 0; case CG_R_ADDADDITIVELIGHTTOSCENE: re.AddAdditiveLightToScene( VMA(1), VMF(2), VMF(3), VMF(4), VMF(5) ); return 0; case CG_R_RENDERSCENE: re.RenderScene( VMA(1) ); return 0; case CG_R_SETCOLOR: re.SetColor( VMA(1) ); return 0; case CG_R_DRAWSTRETCHPIC: re.DrawStretchPic( VMF(1), VMF(2), VMF(3), VMF(4), VMF(5), VMF(6), VMF(7), VMF(8), args[9] ); return 0; case CG_R_MODELBOUNDS: re.ModelBounds( args[1], VMA(2), VMA(3) ); return 0; case CG_R_LERPTAG: return re.LerpTag( VMA(1), args[2], args[3], args[4], VMF(5), VMA(6) ); case CG_GETGLCONFIG: CL_GetGlconfig( VMA(1) ); return 0; case CG_GETGAMESTATE: CL_GetGameState( VMA(1) ); return 0; case CG_GETCURRENTSNAPSHOTNUMBER: CL_GetCurrentSnapshotNumber( VMA(1), VMA(2) ); return 0; case CG_GETSNAPSHOT: return CL_GetSnapshot( args[1], VMA(2) ); case CG_GETSERVERCOMMAND: return CL_GetServerCommand( args[1] ); case CG_GETCURRENTCMDNUMBER: return CL_GetCurrentCmdNumber(); case CG_GETUSERCMD: return CL_GetUserCmd( args[1], VMA(2) ); case CG_SETUSERCMDVALUE: CL_SetUserCmdValue( args[1], VMF(2) ); return 0; case CG_MEMORY_REMAINING: return Hunk_MemoryRemaining(); case CG_KEY_ISDOWN: return Key_IsDown( args[1] ); case CG_KEY_GETCATCHER: return Key_GetCatcher(); case CG_KEY_SETCATCHER: // Don't allow the cgame module to close the console Key_SetCatcher( args[1] | ( Key_GetCatcher( ) & KEYCATCH_CONSOLE ) ); return 0; case CG_KEY_GETKEY: return Key_GetKey( VMA(1) ); case CG_MEMSET: Com_Memset( VMA(1), args[2], args[3] ); return 0; case CG_MEMCPY: Com_Memcpy( VMA(1), VMA(2), args[3] ); return 0; case CG_STRNCPY: strncpy( VMA(1), VMA(2), args[3] ); return args[1]; case CG_SIN: return FloatAsInt( sin( VMF(1) ) ); case CG_COS: return FloatAsInt( cos( VMF(1) ) ); case CG_ATAN2: return FloatAsInt( atan2( VMF(1), VMF(2) ) ); case CG_SQRT: return FloatAsInt( sqrt( VMF(1) ) ); case CG_FLOOR: return FloatAsInt( floor( VMF(1) ) ); case CG_CEIL: return FloatAsInt( ceil( VMF(1) ) ); case CG_ACOS: return FloatAsInt( Q_acos( VMF(1) ) ); case CG_PC_ADD_GLOBAL_DEFINE: return botlib_export->PC_AddGlobalDefine( VMA(1) ); case CG_PC_LOAD_SOURCE: return botlib_export->PC_LoadSourceHandle( VMA(1) ); case CG_PC_FREE_SOURCE: return botlib_export->PC_FreeSourceHandle( args[1] ); case CG_PC_READ_TOKEN: return botlib_export->PC_ReadTokenHandle( args[1], VMA(2) ); case CG_PC_SOURCE_FILE_AND_LINE: return botlib_export->PC_SourceFileAndLine( args[1], VMA(2), VMA(3) ); case CG_S_STOPBACKGROUNDTRACK: S_StopBackgroundTrack(); return 0; case CG_REAL_TIME: return Com_RealTime( VMA(1) ); case CG_SNAPVECTOR: Q_SnapVector(VMA(1)); return 0; case CG_CIN_PLAYCINEMATIC: return CIN_PlayCinematic(VMA(1), args[2], args[3], args[4], args[5], args[6]); case CG_CIN_STOPCINEMATIC: return CIN_StopCinematic(args[1]); case CG_CIN_RUNCINEMATIC: return CIN_RunCinematic(args[1]); case CG_CIN_DRAWCINEMATIC: CIN_DrawCinematic(args[1]); return 0; case CG_CIN_SETEXTENTS: CIN_SetExtents(args[1], args[2], args[3], args[4], args[5]); return 0; case CG_R_REMAP_SHADER: re.RemapShader( VMA(1), VMA(2), VMA(3) ); return 0; /* case CG_LOADCAMERA: return loadCamera(VMA(1)); case CG_STARTCAMERA: startCamera(args[1]); return 0; case CG_GETCAMERAINFO: return getCameraInfo(args[1], VMA(2), VMA(3)); */ case CG_GET_ENTITY_TOKEN: return re.GetEntityToken( VMA(1), args[2] ); case CG_R_INPVS: return re.inPVS( VMA(1), VMA(2) ); default: assert(0); Com_Error( ERR_DROP, "Bad cgame system trap: %ld", (long int) args[0] ); } return 0; }
/* * SVC_InfoResponse * * Responds with short info for broadcast scans * The second parameter should be the current protocol version number. */ static void SVC_InfoResponse( const socket_t *socket, const netadr_t *address ) { int i, count; char *string; bool allow_empty = false, allow_full = false; if( sv_showInfoQueries->integer ) Com_Printf( "Info Packet %s\n", NET_AddressToString( address ) ); // KoFFiE: When not public and coming from a LAN address // assume broadcast and respond anyway, otherwise ignore if( ( ( !sv_public->integer ) && ( !NET_IsLANAddress( address ) ) ) || ( sv_maxclients->integer == 1 ) ) { return; } // ignore when in invalid server state if( sv.state < ss_loading || sv.state > ss_game ) return; // don't reply when we are locked for mm // if( SV_MM_IsLocked() ) // return; // different protocol version if( atoi( Cmd_Argv( 1 ) ) != APP_PROTOCOL_VERSION ) return; // check for full/empty filtered states for( i = 0; i < Cmd_Argc(); i++ ) { if( !Q_stricmp( Cmd_Argv( i ), "full" ) ) allow_full = true; if( !Q_stricmp( Cmd_Argv( i ), "empty" ) ) allow_empty = true; } count = 0; for( i = 0; i < sv_maxclients->integer; i++ ) { if( svs.clients[i].state >= CS_CONNECTED ) { count++; } } if( ( count == sv_maxclients->integer ) && !allow_full ) { return; } if( ( count == 0 ) && !allow_empty ) { return; } string = SV_ShortInfoString(); if( string ) Netchan_OutOfBandPrint( socket, address, "info\n%s", string ); }
/* ================= SV_VerifyPaks_f If we are pure, disconnect the client if they do no meet the following conditions: 1. the first two checksums match our view of cgame and ui 2. there are no any additional checksums that we do not have This routine would be a bit simpler with a goto but i abstained ================= */ static void SV_VerifyPaks_f( client_t *cl ) { int nChkSum1, nChkSum2, nClientPaks, nServerPaks, i, j, nCurArg; int nClientChkSum[1024]; int nServerChkSum[1024]; const char *pPaks, *pArg; qboolean bGood = qtrue; // if we are pure, we "expect" the client to load certain things from // certain pk3 files, namely we want the client to have loaded the // ui and cgame that we think should be loaded based on the pure setting // if ( sv_pure->integer != 0 ) { nChkSum1 = nChkSum2 = 0; // we run the game, so determine which cgame and ui the client "should" be running bGood = (FS_FileIsInPAK("vm/cgame.qvm", &nChkSum1) == 1); if (bGood) bGood = (FS_FileIsInPAK("vm/ui.qvm", &nChkSum2) == 1); nClientPaks = Cmd_Argc(); // start at arg 2 ( skip serverId cl_paks ) nCurArg = 1; pArg = Cmd_Argv(nCurArg++); if(!pArg) { bGood = qfalse; } else { // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=475 // we may get incoming cp sequences from a previous checksumFeed, which we need to ignore // since serverId is a frame count, it always goes up if (atoi(pArg) < sv.checksumFeedServerId) { Com_DPrintf("ignoring outdated cp command from client %s\n", cl->name); return; } } // we basically use this while loop to avoid using 'goto' :) while (bGood) { // must be at least 6: "cl_paks cgame ui @ firstref ... numChecksums" // numChecksums is encoded if (nClientPaks < 6) { bGood = qfalse; break; } // verify first to be the cgame checksum pArg = Cmd_Argv(nCurArg++); if (!pArg || *pArg == '@' || atoi(pArg) != nChkSum1 ) { bGood = qfalse; break; } // verify the second to be the ui checksum pArg = Cmd_Argv(nCurArg++); if (!pArg || *pArg == '@' || atoi(pArg) != nChkSum2 ) { bGood = qfalse; break; } // should be sitting at the delimeter now pArg = Cmd_Argv(nCurArg++); if (*pArg != '@') { bGood = qfalse; break; } // store checksums since tokenization is not re-entrant for (i = 0; nCurArg < nClientPaks; i++) { nClientChkSum[i] = atoi(Cmd_Argv(nCurArg++)); } // store number to compare against (minus one cause the last is the number of checksums) nClientPaks = i - 1; // make sure none of the client check sums are the same // so the client can't send 5 the same checksums for (i = 0; i < nClientPaks; i++) { for (j = 0; j < nClientPaks; j++) { if (i == j) continue; if (nClientChkSum[i] == nClientChkSum[j]) { bGood = qfalse; break; } } if (bGood == qfalse) break; } if (bGood == qfalse) break; // get the pure checksums of the pk3 files loaded by the server pPaks = FS_LoadedPakPureChecksums(); Cmd_TokenizeString( pPaks ); nServerPaks = Cmd_Argc(); if (nServerPaks > 1024) nServerPaks = 1024; for (i = 0; i < nServerPaks; i++) { nServerChkSum[i] = atoi(Cmd_Argv(i)); } // check if the client has provided any pure checksums of pk3 files not loaded by the server for (i = 0; i < nClientPaks; i++) { for (j = 0; j < nServerPaks; j++) { if (nClientChkSum[i] == nServerChkSum[j]) { break; } } if (j >= nServerPaks) { bGood = qfalse; break; } } if ( bGood == qfalse ) { break; } // check if the number of checksums was correct nChkSum1 = sv.checksumFeed; for (i = 0; i < nClientPaks; i++) { nChkSum1 ^= nClientChkSum[i]; } nChkSum1 ^= nClientPaks; if (nChkSum1 != nClientChkSum[nClientPaks]) { bGood = qfalse; break; } // break out break; } cl->gotCP = qtrue; if (bGood) { cl->pureAuthentic = 1; } else { cl->pureAuthentic = 0; cl->lastSnapshotTime = 0; cl->state = CS_ACTIVE; SV_SendClientSnapshot( cl ); SV_SendServerCommand( cl, "disconnect \"Unpure Client. " "You may need to enable in-game downloads " "to connect to this server (set " "cl_allowDownload 1)\"" ); SV_DropClient( cl, "Unpure client detected. Invalid .PK3 files referenced!" ); } } }
/* * SVC_DirectConnect * A connection request that did not come from the master */ static void SVC_DirectConnect( const socket_t *socket, const netadr_t *address ) { #ifdef TCP_ALLOW_CONNECT int incoming = 0; #endif char userinfo[MAX_INFO_STRING]; client_t *cl, *newcl; int i, version, game_port, challenge; int previousclients; int session_id; char *session_id_str; unsigned int ticket_id; bool tv_client; unsigned int time; Com_DPrintf( "SVC_DirectConnect (%s)\n", Cmd_Args() ); version = atoi( Cmd_Argv( 1 ) ); if( version != APP_PROTOCOL_VERSION ) { if( version <= 6 ) { // before reject packet was added Netchan_OutOfBandPrint( socket, address, "print\nServer is version %4.2f. Protocol %3i\n", APP_VERSION, APP_PROTOCOL_VERSION ); } else { Netchan_OutOfBandPrint( socket, address, "reject\n%i\n%i\nServer and client don't have the same version\n", DROP_TYPE_GENERAL, 0 ); } Com_DPrintf( " rejected connect from protocol %i\n", version ); return; } game_port = atoi( Cmd_Argv( 2 ) ); challenge = atoi( Cmd_Argv( 3 ) ); tv_client = ( atoi( Cmd_Argv( 5 ) ) & 1 ? true : false ); if( !Info_Validate( Cmd_Argv( 4 ) ) ) { Netchan_OutOfBandPrint( socket, address, "reject\n%i\n%i\nInvalid userinfo string\n", DROP_TYPE_GENERAL, 0 ); Com_DPrintf( "Connection from %s refused: invalid userinfo string\n", NET_AddressToString( address ) ); return; } Q_strncpyz( userinfo, Cmd_Argv( 4 ), sizeof( userinfo ) ); // force the IP key/value pair so the game can filter based on ip if( !Info_SetValueForKey( userinfo, "socket", NET_SocketTypeToString( socket->type ) ) ) { Netchan_OutOfBandPrint( socket, address, "reject\n%i\n%i\nError: Couldn't set userinfo (socket)\n", DROP_TYPE_GENERAL, 0 ); Com_DPrintf( "Connection from %s refused: couldn't set userinfo (socket)\n", NET_AddressToString( address ) ); return; } if( !Info_SetValueForKey( userinfo, "ip", NET_AddressToString( address ) ) ) { Netchan_OutOfBandPrint( socket, address, "reject\n%i\n%i\nError: Couldn't set userinfo (ip)\n", DROP_TYPE_GENERAL, 0 ); Com_DPrintf( "Connection from %s refused: couldn't set userinfo (ip)\n", NET_AddressToString( address ) ); return; } if( Cmd_Argc() >= 7 ) { // we have extended information, ticket-id and session-id Com_Printf("Extended information %s\n", Cmd_Argv(6) ); ticket_id = (unsigned int)atoi( Cmd_Argv(6) ); session_id_str = Info_ValueForKey( userinfo, "cl_mm_session" ); if( session_id_str != NULL ) session_id = atoi( session_id_str ); else session_id = 0; } else { ticket_id = 0; session_id = 0; } #ifdef TCP_ALLOW_CONNECT if( socket->type == SOCKET_TCP ) { // find the connection for( i = 0; i < MAX_INCOMING_CONNECTIONS; i++ ) { if( !svs.incoming[i].active ) continue; if( NET_CompareAddress( &svs.incoming[i].address, address ) && socket == &svs.incoming[i].socket ) break; } if( i == MAX_INCOMING_CONNECTIONS ) { Com_Error( ERR_FATAL, "Incoming connection not found.\n" ); return; } incoming = i; } #endif // see if the challenge is valid for( i = 0; i < MAX_CHALLENGES; i++ ) { if( NET_CompareBaseAddress( address, &svs.challenges[i].adr ) ) { if( challenge == svs.challenges[i].challenge ) { svs.challenges[i].challenge = 0; // wsw : r1q2 : reset challenge svs.challenges[i].time = 0; NET_InitAddress( &svs.challenges[i].adr, NA_NOTRANSMIT ); break; // good } Netchan_OutOfBandPrint( socket, address, "reject\n%i\n%i\nBad challenge\n", DROP_TYPE_GENERAL, DROP_FLAG_AUTORECONNECT ); return; } } if( i == MAX_CHALLENGES ) { Netchan_OutOfBandPrint( socket, address, "reject\n%i\n%i\nNo challenge for address\n", DROP_TYPE_GENERAL, DROP_FLAG_AUTORECONNECT ); return; } //r1: limit connections from a single IP if( sv_iplimit->integer ) { previousclients = 0; for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ ) { if( cl->state == CS_FREE ) continue; if( NET_CompareBaseAddress( address, &cl->netchan.remoteAddress ) ) { //r1: zombies are less dangerous if( cl->state == CS_ZOMBIE ) previousclients++; else previousclients += 2; } } if( previousclients >= sv_iplimit->integer * 2 ) { Netchan_OutOfBandPrint( socket, address, "reject\n%i\n%i\nToo many connections from your host\n", DROP_TYPE_GENERAL, DROP_FLAG_AUTORECONNECT ); Com_DPrintf( "%s:connect rejected : too many connections\n", NET_AddressToString( address ) ); return; } } newcl = NULL; // if there is already a slot for this ip, reuse it time = Sys_Milliseconds(); for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ ) { if( cl->state == CS_FREE ) continue; if( NET_CompareAddress( address, &cl->netchan.remoteAddress ) || ( NET_CompareBaseAddress( address, &cl->netchan.remoteAddress ) && cl->netchan.game_port == game_port ) ) { if( !NET_IsLocalAddress( address ) && ( time - cl->lastconnect ) < (unsigned)( sv_reconnectlimit->integer * 1000 ) ) { Com_DPrintf( "%s:reconnect rejected : too soon\n", NET_AddressToString( address ) ); return; } Com_Printf( "%s:reconnect\n", NET_AddressToString( address ) ); newcl = cl; break; } } // find a client slot if( !newcl ) { for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ ) { if( cl->state == CS_FREE ) { newcl = cl; break; } // overwrite fakeclient if no free spots found if( cl->state && cl->edict && ( cl->edict->r.svflags & SVF_FAKECLIENT ) ) newcl = cl; } if( !newcl ) { Netchan_OutOfBandPrint( socket, address, "reject\n%i\n%i\nServer is full\n", DROP_TYPE_GENERAL, DROP_FLAG_AUTORECONNECT ); Com_DPrintf( "Server is full. Rejected a connection.\n" ); return; } if( newcl->state && newcl->edict && ( newcl->edict->r.svflags & SVF_FAKECLIENT ) ) SV_DropClient( newcl, DROP_TYPE_GENERAL, "%s", "Need room for a real player" ); } // get the game a chance to reject this connection or modify the userinfo if( !SV_ClientConnect( socket, address, newcl, userinfo, game_port, challenge, false, tv_client, ticket_id, session_id ) ) { char *rejtype, *rejflag, *rejtypeflag, *rejmsg; rejtype = Info_ValueForKey( userinfo, "rejtype" ); if( !rejtype ) rejtype = "0"; rejflag = Info_ValueForKey( userinfo, "rejflag" ); if( !rejflag ) rejflag = "0"; // hax because Info_ValueForKey can only be called twice in a row rejtypeflag = va( "%s\n%s", rejtype, rejflag ); rejmsg = Info_ValueForKey( userinfo, "rejmsg" ); if( !rejmsg ) rejmsg = "Game module rejected connection"; Netchan_OutOfBandPrint( socket, address, "reject\n%s\n%s\n", rejtypeflag, rejmsg ); Com_DPrintf( "Game rejected a connection.\n" ); return; } // send the connect packet to the client Netchan_OutOfBandPrint( socket, address, "client_connect\n%s", newcl->session ); // free the incoming entry #ifdef TCP_ALLOW_CONNECT if( socket->type == SOCKET_TCP ) { svs.incoming[incoming].active = false; svs.incoming[incoming].socket.open = false; } #endif }
/* ======================================================================================================================================= Cvar_ListModified_f ======================================================================================================================================= */ void Cvar_ListModified_f(void) { cvar_t *var; int totalModified; char *value; char *match; if (Cmd_Argc() > 1) { match = Cmd_Argv(1); } else { match = NULL; } totalModified = 0; for (var = cvar_vars; var; var = var->next) { if (!var->name || !var->modificationCount) { continue; } value = var->latchedString ? var->latchedString : var->string; if (!strcmp(value, var->resetString)) { continue; } totalModified++; if (match && !Com_Filter(match, var->name, qfalse)) { continue; } if (var->flags & CVAR_SERVERINFO) { Com_Printf("S"); } else { Com_Printf(" "); } if (var->flags & CVAR_SYSTEMINFO) { Com_Printf("s"); } else { Com_Printf(" "); } if (var->flags & CVAR_USERINFO) { Com_Printf("U"); } else { Com_Printf(" "); } if (var->flags & CVAR_ROM) { Com_Printf("R"); } else { Com_Printf(" "); } if (var->flags & CVAR_INIT) { Com_Printf("I"); } else { Com_Printf(" "); } if (var->flags & CVAR_ARCHIVE) { Com_Printf("A"); } else { Com_Printf(" "); } if (var->flags & CVAR_LATCH) { Com_Printf("L"); } else { Com_Printf(" "); } if (var->flags & CVAR_CHEAT) { Com_Printf("C"); } else { Com_Printf(" "); } if (var->flags & CVAR_USER_CREATED) { Com_Printf("?"); } else { Com_Printf(" "); } Com_Printf(" %s \"%s\", default \"%s\"\n", var->name, value, var->resetString); } Com_Printf("\n%i total modified cvars\n", totalModified); }
static void CD_f(void) { const char *command; int n; if (Cmd_Argc() < 2) return; command = Cmd_Argv(1); if (strcasecmp(command, "on") == 0) { enabled = true; return; } if (strcasecmp(command, "off") == 0) { if (playing) CDAudio_Stop(); enabled = false; return; } if (strcasecmp(command, "reset") == 0) { enabled = true; if (playing) CDAudio_Stop(); for (n = 0; n < 100; n++) remap[n] = n; CDAudio_GetAudioDiskInfo(); return; } if (strcasecmp(command, "remap") == 0) { int ret = Cmd_Argc() - 2; if (ret <= 0) { for (n = 1; n < 100; n++) if (remap[n] != n) Con_Printf(" %u -> %u\n", n, remap[n]); return; } for (n = 1; n <= ret; n++) remap[n] = Q_atoi(Cmd_Argv(n + 1)); return; } if (strcasecmp(command, "close") == 0) { CDAudio_CloseDoor(); return; } if (!cdValid) { CDAudio_GetAudioDiskInfo(); if (!cdValid) { Con_Printf("No CD in player.\n"); return; } } if (strcasecmp(command, "play") == 0) { CDAudio_Play((byte)Q_atoi(Cmd_Argv(2)), false); return; } if (strcasecmp(command, "loop") == 0) { CDAudio_Play((byte)Q_atoi(Cmd_Argv(2)), true); return; } if (strcasecmp(command, "stop") == 0) { CDAudio_Stop(); return; } if (strcasecmp(command, "pause") == 0) { CDAudio_Pause(); return; } if (strcasecmp(command, "resume") == 0) { CDAudio_Resume(); return; } if (strcasecmp(command, "eject") == 0) { if (playing) CDAudio_Stop(); CDAudio_Eject(); cdValid = false; return; } if (strcasecmp(command, "info") == 0) { Con_Printf("%u tracks\n", maxTrack); if (playing) Con_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack); else if (wasPlaying) Con_Printf("Paused %s track %u\n", playLooping ? "looping" : "playing", playTrack); Con_Printf("Volume is %f\n", bgmvolume.value); return; } }
/* ================ Con_Grep_f Find all console lines containing a string ================ */ void Con_Grep_f( void ) { int l; char *search; char *printbuf = NULL; size_t pbAlloc = 0, pbLength = 0; if ( Cmd_Argc() != 2 ) { Com_Printf("%s", _( "usage: grep <string>\n" )); return; } // skip empty lines for ( l = consoleState.currentLine - consoleState.maxScrollbackLengthInLines + 1; l <= consoleState.currentLine; l++ ) { if ( consoleState.text[ CON_LINE( l ) ].ch ) { break; } } // check the remaining lines search = Cmd_Argv( 1 ); for ( ; l <= consoleState.currentLine; l++ ) { const char *buffer = Con_LineToString( l, qfalse ); if ( Q_stristr( buffer, search ) ) { size_t i; buffer = Con_LineToColouredString( l, qtrue ); i = strlen( buffer ); if ( pbLength + i >= pbAlloc ) { char *nb; // allocate in 16K chunks - more than adequate pbAlloc = ( pbLength + i + 1 + 16383) & ~16383; nb = Z_Malloc( pbAlloc ); if( printbuf ) { strcpy( nb, printbuf ); Z_Free( printbuf ); } printbuf = nb; } Q_strcat( printbuf, pbAlloc, buffer ); pbLength += i; } } if( printbuf ) { char tmpbuf[ MAXPRINTMSG ]; int i; // print out in chunks so we don't go over the MAXPRINTMSG limit for ( i = 0; i < pbLength; i += MAXPRINTMSG - 1 ) { Q_strncpyz( tmpbuf, printbuf + i, sizeof( tmpbuf ) ); Com_Printf( "%s", tmpbuf ); } Z_Free( printbuf ); } }
intptr_t CL_UISystemCalls( intptr_t *args ) { switch ( args[0] ) { //rww - alright, DO NOT EVER add a GAME/CGAME/UI generic call without adding a trap to match, and //all of these traps must be shared and have cases in sv_game, cl_cgame, and cl_ui. They must also //all be in the same order, and start at 100. case TRAP_MEMSET: Com_Memset( VMA(1), args[2], args[3] ); return 0; case TRAP_MEMCPY: Com_Memcpy( VMA(1), VMA(2), args[3] ); return 0; case TRAP_STRNCPY: strncpy( (char *)VMA(1), (const char *)VMA(2), args[3] ); return args[1]; case TRAP_SIN: return FloatAsInt( sin( VMF(1) ) ); case TRAP_COS: return FloatAsInt( cos( VMF(1) ) ); case TRAP_ATAN2: return FloatAsInt( atan2( VMF(1), VMF(2) ) ); case TRAP_SQRT: return FloatAsInt( sqrt( VMF(1) ) ); case TRAP_MATRIXMULTIPLY: MatrixMultiply( (vec3_t *)VMA(1), (vec3_t *)VMA(2), (vec3_t *)VMA(3) ); return 0; case TRAP_ANGLEVECTORS: AngleVectors( (const float *)VMA(1), (float *)VMA(2), (float *)VMA(3), (float *)VMA(4) ); return 0; case TRAP_PERPENDICULARVECTOR: PerpendicularVector( (float *)VMA(1), (const float *)VMA(2) ); return 0; case TRAP_FLOOR: return FloatAsInt( floor( VMF(1) ) ); case TRAP_CEIL: return FloatAsInt( ceil( VMF(1) ) ); case TRAP_TESTPRINTINT: return 0; case TRAP_TESTPRINTFLOAT: return 0; case TRAP_ACOS: return FloatAsInt( Q_acos( VMF(1) ) ); case TRAP_ASIN: return FloatAsInt( Q_asin( VMF(1) ) ); case UI_ERROR: Com_Error( ERR_DROP, "%s", VMA(1) ); return 0; case UI_PRINT: Com_Printf( "%s", VMA(1) ); return 0; case UI_MILLISECONDS: return Sys_Milliseconds(); case UI_CVAR_REGISTER: Cvar_Register( (vmCvar_t *)VMA(1), (const char *)VMA(2), (const char *)VMA(3), args[4] ); return 0; case UI_CVAR_UPDATE: Cvar_Update( (vmCvar_t *)VMA(1) ); return 0; case UI_CVAR_SET: Cvar_VM_Set( (const char *)VMA(1), (const char *)VMA(2), VM_UI ); return 0; case UI_CVAR_VARIABLEVALUE: return FloatAsInt( Cvar_VariableValue( (const char *)VMA(1) ) ); case UI_CVAR_VARIABLESTRINGBUFFER: Cvar_VariableStringBuffer( (const char *)VMA(1), (char *)VMA(2), args[3] ); return 0; case UI_CVAR_SETVALUE: Cvar_VM_SetValue( (const char *)VMA(1), VMF(2), VM_UI ); return 0; case UI_CVAR_RESET: Cvar_Reset( (const char *)VMA(1) ); return 0; case UI_CVAR_CREATE: Cvar_Get( (const char *)VMA(1), (const char *)VMA(2), args[3] ); return 0; case UI_CVAR_INFOSTRINGBUFFER: Cvar_InfoStringBuffer( args[1], (char *)VMA(2), args[3] ); return 0; case UI_ARGC: return Cmd_Argc(); case UI_ARGV: Cmd_ArgvBuffer( args[1], (char *)VMA(2), args[3] ); return 0; case UI_CMD_EXECUTETEXT: Cbuf_ExecuteText( args[1], (const char *)VMA(2) ); return 0; case UI_FS_FOPENFILE: return FS_FOpenFileByMode( (const char *)VMA(1), (int *)VMA(2), (fsMode_t)args[3] ); case UI_FS_READ: FS_Read( VMA(1), args[2], args[3] ); return 0; case UI_FS_WRITE: FS_Write( VMA(1), args[2], args[3] ); return 0; case UI_FS_FCLOSEFILE: FS_FCloseFile( args[1] ); return 0; case UI_FS_GETFILELIST: return FS_GetFileList( (const char *)VMA(1), (const char *)VMA(2), (char *)VMA(3), args[4] ); case UI_R_REGISTERMODEL: return re->RegisterModel( (const char *)VMA(1) ); case UI_R_REGISTERSKIN: return re->RegisterSkin( (const char *)VMA(1) ); case UI_R_REGISTERSHADERNOMIP: return re->RegisterShaderNoMip( (const char *)VMA(1) ); case UI_R_SHADERNAMEFROMINDEX: CL_R_ShaderNameFromIndex( (char *)VMA(1), args[2] ); return 0; case UI_R_CLEARSCENE: re->ClearScene(); return 0; case UI_R_ADDREFENTITYTOSCENE: re->AddRefEntityToScene( (const refEntity_t *)VMA(1) ); return 0; case UI_R_ADDPOLYTOSCENE: re->AddPolyToScene( args[1], args[2], (const polyVert_t *)VMA(3), 1 ); return 0; case UI_R_ADDLIGHTTOSCENE: re->AddLightToScene( (const float *)VMA(1), VMF(2), VMF(3), VMF(4), VMF(5) ); return 0; case UI_R_RENDERSCENE: re->RenderScene( (const refdef_t *)VMA(1) ); return 0; case UI_R_SETCOLOR: re->SetColor( (const float *)VMA(1) ); return 0; case UI_R_DRAWSTRETCHPIC: re->DrawStretchPic( VMF(1), VMF(2), VMF(3), VMF(4), VMF(5), VMF(6), VMF(7), VMF(8), args[9] ); return 0; case UI_R_MODELBOUNDS: re->ModelBounds( args[1], (float *)VMA(2), (float *)VMA(3) ); return 0; case UI_UPDATESCREEN: SCR_UpdateScreen(); return 0; case UI_CM_LERPTAG: re->LerpTag( (orientation_t *)VMA(1), args[2], args[3], args[4], VMF(5), (const char *)VMA(6) ); return 0; case UI_S_REGISTERSOUND: return S_RegisterSound( (const char *)VMA(1) ); case UI_S_STARTLOCALSOUND: S_StartLocalSound( args[1], args[2] ); return 0; case UI_KEY_KEYNUMTOSTRINGBUF: Key_KeynumToStringBuf( args[1], (char *)VMA(2), args[3] ); return 0; case UI_KEY_GETBINDINGBUF: Key_GetBindingBuf( args[1], (char *)VMA(2), args[3] ); return 0; case UI_KEY_SETBINDING: Key_SetBinding( args[1], (const char *)VMA(2) ); return 0; case UI_KEY_ISDOWN: return Key_IsDown( args[1] ); case UI_KEY_GETOVERSTRIKEMODE: return Key_GetOverstrikeMode(); case UI_KEY_SETOVERSTRIKEMODE: Key_SetOverstrikeMode( (qboolean)args[1] ); return 0; case UI_KEY_CLEARSTATES: Key_ClearStates(); return 0; case UI_KEY_GETCATCHER: return Key_GetCatcher(); case UI_KEY_SETCATCHER: CL_Key_SetCatcher( args[1] ); return 0; case UI_GETCLIPBOARDDATA: GetClipboardData( (char *)VMA(1), args[2] ); return 0; case UI_GETCLIENTSTATE: CL_GetClientState( (uiClientState_t *)VMA(1) ); return 0; case UI_GETGLCONFIG: CL_GetGlconfig( (glconfig_t *)VMA(1) ); return 0; case UI_GETCONFIGSTRING: return GetConfigString( args[1], (char *)VMA(2), args[3] ); case UI_LAN_LOADCACHEDSERVERS: LAN_LoadCachedServers(); return 0; case UI_LAN_SAVECACHEDSERVERS: LAN_SaveServersToCache(); return 0; case UI_LAN_ADDSERVER: return LAN_AddServer(args[1], (const char *)VMA(2), (const char *)VMA(3)); case UI_LAN_REMOVESERVER: LAN_RemoveServer(args[1], (const char *)VMA(2)); return 0; case UI_LAN_GETPINGQUEUECOUNT: return LAN_GetPingQueueCount(); case UI_LAN_CLEARPING: LAN_ClearPing( args[1] ); return 0; case UI_LAN_GETPING: LAN_GetPing( args[1], (char *)VMA(2), args[3], (int *)VMA(4) ); return 0; case UI_LAN_GETPINGINFO: LAN_GetPingInfo( args[1], (char *)VMA(2), args[3] ); return 0; case UI_LAN_GETSERVERCOUNT: return LAN_GetServerCount(args[1]); case UI_LAN_GETSERVERADDRESSSTRING: LAN_GetServerAddressString( args[1], args[2], (char *)VMA(3), args[4] ); return 0; case UI_LAN_GETSERVERINFO: LAN_GetServerInfo( args[1], args[2], (char *)VMA(3), args[4] ); return 0; case UI_LAN_GETSERVERPING: return LAN_GetServerPing( args[1], args[2] ); case UI_LAN_MARKSERVERVISIBLE: LAN_MarkServerVisible( args[1], args[2], (qboolean)args[3] ); return 0; case UI_LAN_SERVERISVISIBLE: return LAN_ServerIsVisible( args[1], args[2] ); case UI_LAN_UPDATEVISIBLEPINGS: return LAN_UpdateVisiblePings( args[1] ); case UI_LAN_RESETPINGS: LAN_ResetPings( args[1] ); return 0; case UI_LAN_SERVERSTATUS: return LAN_GetServerStatus( (char *)VMA(1), (char *)VMA(2), args[3] ); case UI_LAN_COMPARESERVERS: return LAN_CompareServers( args[1], args[2], args[3], args[4], args[5] ); case UI_MEMORY_REMAINING: return Hunk_MemoryRemaining(); case UI_R_REGISTERFONT: return re->RegisterFont( (const char *)VMA(1) ); case UI_R_FONT_STRLENPIXELS: return re->Font_StrLenPixels( (const char *)VMA(1), args[2], VMF(3) ); case UI_R_FONT_STRLENCHARS: return re->Font_StrLenChars( (const char *)VMA(1) ); case UI_R_FONT_STRHEIGHTPIXELS: return re->Font_HeightPixels( args[1], VMF(2) ); case UI_R_FONT_DRAWSTRING: re->Font_DrawString( args[1], args[2], (const char *)VMA(3), (const float *) VMA(4), args[5], args[6], VMF(7) ); return 0; case UI_LANGUAGE_ISASIAN: return re->Language_IsAsian(); case UI_LANGUAGE_USESSPACES: return re->Language_UsesSpaces(); case UI_ANYLANGUAGE_READCHARFROMSTRING: return re->AnyLanguage_ReadCharFromString( (const char *)VMA(1), (int *) VMA(2), (qboolean *) VMA(3) ); case UI_PC_ADD_GLOBAL_DEFINE: return botlib_export->PC_AddGlobalDefine( (char *)VMA(1) ); case UI_PC_LOAD_SOURCE: return botlib_export->PC_LoadSourceHandle( (const char *)VMA(1) ); case UI_PC_FREE_SOURCE: return botlib_export->PC_FreeSourceHandle( args[1] ); case UI_PC_READ_TOKEN: return botlib_export->PC_ReadTokenHandle( args[1], (struct pc_token_s *)VMA(2) ); case UI_PC_SOURCE_FILE_AND_LINE: return botlib_export->PC_SourceFileAndLine( args[1], (char *)VMA(2), (int *)VMA(3) ); case UI_PC_LOAD_GLOBAL_DEFINES: return botlib_export->PC_LoadGlobalDefines ( (char *)VMA(1) ); case UI_PC_REMOVE_ALL_GLOBAL_DEFINES: botlib_export->PC_RemoveAllGlobalDefines ( ); return 0; case UI_S_STOPBACKGROUNDTRACK: S_StopBackgroundTrack(); return 0; case UI_S_STARTBACKGROUNDTRACK: S_StartBackgroundTrack( (const char *)VMA(1), (const char *)VMA(2), qfalse ); return 0; case UI_REAL_TIME: return Com_RealTime( (struct qtime_s *)VMA(1) ); case UI_CIN_PLAYCINEMATIC: Com_DPrintf("UI_CIN_PlayCinematic\n"); return CIN_PlayCinematic((const char *)VMA(1), args[2], args[3], args[4], args[5], args[6]); case UI_CIN_STOPCINEMATIC: return CIN_StopCinematic(args[1]); case UI_CIN_RUNCINEMATIC: return CIN_RunCinematic(args[1]); case UI_CIN_DRAWCINEMATIC: CIN_DrawCinematic(args[1]); return 0; case UI_CIN_SETEXTENTS: CIN_SetExtents(args[1], args[2], args[3], args[4], args[5]); return 0; case UI_R_REMAP_SHADER: re->RemapShader( (const char *)VMA(1), (const char *)VMA(2), (const char *)VMA(3) ); return 0; case UI_SP_GETNUMLANGUAGES: return SE_GetNumLanguages(); case UI_SP_GETLANGUAGENAME: CL_SE_GetLanguageName( args[1], (char *)VMA(2) ); return 0; case UI_SP_GETSTRINGTEXTSTRING: return CL_SE_GetStringTextString( (const char *)VMA(1), (char *)VMA(2), args[3] ); case UI_G2_LISTSURFACES: re->G2API_ListSurfaces( (CGhoul2Info *) args[1] ); return 0; case UI_G2_LISTBONES: re->G2API_ListBones( (CGhoul2Info *) args[1], args[2]); return 0; case UI_G2_HAVEWEGHOULMODELS: return re->G2API_HaveWeGhoul2Models( *((CGhoul2Info_v *)args[1]) ); case UI_G2_SETMODELS: re->G2API_SetGhoul2ModelIndexes( *((CGhoul2Info_v *)args[1]),(qhandle_t *)VMA(2),(qhandle_t *)VMA(3)); return 0; case UI_G2_GETBOLT: return re->G2API_GetBoltMatrix(*((CGhoul2Info_v *)args[1]), args[2], args[3], (mdxaBone_t *)VMA(4), (const float *)VMA(5),(const float *)VMA(6), args[7], (qhandle_t *)VMA(8), (float *)VMA(9)); case UI_G2_GETBOLT_NOREC: re->G2API_BoltMatrixReconstruction( qfalse );//gG2_GBMNoReconstruct = qtrue; return re->G2API_GetBoltMatrix(*((CGhoul2Info_v *)args[1]), args[2], args[3], (mdxaBone_t *)VMA(4), (const float *)VMA(5),(const float *)VMA(6), args[7], (qhandle_t *)VMA(8), (float *)VMA(9)); case UI_G2_GETBOLT_NOREC_NOROT: // cgame reconstructs bolt matrix, why is this different? re->G2API_BoltMatrixReconstruction( qfalse );//gG2_GBMNoReconstruct = qtrue; re->G2API_BoltMatrixSPMethod( qtrue );//gG2_GBMUseSPMethod = qtrue; return re->G2API_GetBoltMatrix(*((CGhoul2Info_v *)args[1]), args[2], args[3], (mdxaBone_t *)VMA(4), (const float *)VMA(5),(const float *)VMA(6), args[7], (qhandle_t *)VMA(8), (float *)VMA(9)); case UI_G2_INITGHOUL2MODEL: #ifdef _FULL_G2_LEAK_CHECKING g_G2AllocServer = 0; #endif return re->G2API_InitGhoul2Model((CGhoul2Info_v **)VMA(1), (const char *)VMA(2), args[3], (qhandle_t) args[4], (qhandle_t) args[5], args[6], args[7]); case UI_G2_COLLISIONDETECT: case UI_G2_COLLISIONDETECTCACHE: return 0; //not supported for ui case UI_G2_ANGLEOVERRIDE: return re->G2API_SetBoneAngles(*((CGhoul2Info_v *)args[1]), args[2], (const char *)VMA(3), (float *)VMA(4), args[5], (const Eorientations) args[6], (const Eorientations) args[7], (const Eorientations) args[8], (qhandle_t *)VMA(9), args[10], args[11] ); case UI_G2_CLEANMODELS: #ifdef _FULL_G2_LEAK_CHECKING g_G2AllocServer = 0; #endif re->G2API_CleanGhoul2Models((CGhoul2Info_v **)VMA(1)); // re->G2API_CleanGhoul2Models((CGhoul2Info_v **)args[1]); return 0; case UI_G2_PLAYANIM: return re->G2API_SetBoneAnim(*((CGhoul2Info_v *)args[1]), args[2], (const char *)VMA(3), args[4], args[5], args[6], VMF(7), args[8], VMF(9), args[10]); case UI_G2_GETBONEANIM: { CGhoul2Info_v &g2 = *((CGhoul2Info_v *)args[1]); int modelIndex = args[10]; return re->G2API_GetBoneAnim(g2, modelIndex, (const char*)VMA(2), args[3], (float *)VMA(4), (int *)VMA(5), (int *)VMA(6), (int *)VMA(7), (float *)VMA(8), (int *)VMA(9)); } case UI_G2_GETBONEFRAME: { //rwwFIXMEFIXME: Just make a G2API_GetBoneFrame func too. This is dirty. CGhoul2Info_v &g2 = *((CGhoul2Info_v *)args[1]); int modelIndex = args[6]; int iDontCare1 = 0, iDontCare2 = 0, iDontCare3 = 0; float fDontCare1 = 0; return re->G2API_GetBoneAnim(g2, modelIndex, (const char*)VMA(2), args[3], (float *)VMA(4), &iDontCare1, &iDontCare2, &iDontCare3, &fDontCare1, (int *)VMA(5)); } case UI_G2_GETGLANAME: // return (int)G2API_GetGLAName(*((CGhoul2Info_v *)VMA(1)), args[2]); { char *point = ((char *)VMA(3)); char *local; local = re->G2API_GetGLAName(*((CGhoul2Info_v *)args[1]), args[2]); if (local) { strcpy(point, local); } } return 0; case UI_G2_COPYGHOUL2INSTANCE: return (int)re->G2API_CopyGhoul2Instance(*((CGhoul2Info_v *)args[1]), *((CGhoul2Info_v *)args[2]), args[3]); case UI_G2_COPYSPECIFICGHOUL2MODEL: re->G2API_CopySpecificG2Model(*((CGhoul2Info_v *)args[1]), args[2], *((CGhoul2Info_v *)args[3]), args[4]); return 0; case UI_G2_DUPLICATEGHOUL2INSTANCE: #ifdef _FULL_G2_LEAK_CHECKING g_G2AllocServer = 0; #endif re->G2API_DuplicateGhoul2Instance(*((CGhoul2Info_v *)args[1]), (CGhoul2Info_v **)VMA(2)); return 0; case UI_G2_HASGHOUL2MODELONINDEX: return (int)re->G2API_HasGhoul2ModelOnIndex((CGhoul2Info_v **)VMA(1), args[2]); //return (int)G2API_HasGhoul2ModelOnIndex((CGhoul2Info_v **)args[1], args[2]); case UI_G2_REMOVEGHOUL2MODEL: #ifdef _FULL_G2_LEAK_CHECKING g_G2AllocServer = 0; #endif return (int)re->G2API_RemoveGhoul2Model((CGhoul2Info_v **)VMA(1), args[2]); //return (int)G2API_RemoveGhoul2Model((CGhoul2Info_v **)args[1], args[2]); case UI_G2_ADDBOLT: return re->G2API_AddBolt(*((CGhoul2Info_v *)args[1]), args[2], (const char *)VMA(3)); case UI_G2_SETBOLTON: re->G2API_SetBoltInfo(*((CGhoul2Info_v *)args[1]), args[2], args[3]); return 0; case UI_G2_SETROOTSURFACE: return re->G2API_SetRootSurface(*((CGhoul2Info_v *)args[1]), args[2], (const char *)VMA(3)); case UI_G2_SETSURFACEONOFF: return re->G2API_SetSurfaceOnOff(*((CGhoul2Info_v *)args[1]), (const char *)VMA(2), /*(const int)VMA(3)*/args[3]); case UI_G2_SETNEWORIGIN: return re->G2API_SetNewOrigin(*((CGhoul2Info_v *)args[1]), /*(const int)VMA(2)*/args[2]); case UI_G2_GETTIME: return re->G2API_GetTime(0); case UI_G2_SETTIME: re->G2API_SetTime(args[1], args[2]); return 0; case UI_G2_SETRAGDOLL: return 0; //not supported for ui break; case UI_G2_ANIMATEG2MODELS: return 0; //not supported for ui break; case UI_G2_SETBONEIKSTATE: return re->G2API_SetBoneIKState(*((CGhoul2Info_v *)args[1]), args[2], (const char *)VMA(3), args[4], (sharedSetBoneIKStateParams_t *)VMA(5)); case UI_G2_IKMOVE: return re->G2API_IKMove(*((CGhoul2Info_v *)args[1]), args[2], (sharedIKMoveParams_t *)VMA(3)); case UI_G2_GETSURFACENAME: { //Since returning a pointer in such a way to a VM seems to cause MASSIVE FAILURE<tm>, we will shove data into the pointer the vm passes instead char *point = ((char *)VMA(4)); char *local; int modelindex = args[3]; CGhoul2Info_v &g2 = *((CGhoul2Info_v *)args[1]); local = re->G2API_GetSurfaceName(g2, modelindex, args[2]); if (local) { strcpy(point, local); } } return 0; case UI_G2_SETSKIN: { CGhoul2Info_v &g2 = *((CGhoul2Info_v *)args[1]); int modelIndex = args[2]; return re->G2API_SetSkin(g2, modelIndex, args[3], args[4]); } case UI_G2_ATTACHG2MODEL: { CGhoul2Info_v *g2From = ((CGhoul2Info_v *)args[1]); CGhoul2Info_v *g2To = ((CGhoul2Info_v *)args[3]); return re->G2API_AttachG2Model(*g2From, args[2], *g2To, args[4], args[5]); } default: Com_Error( ERR_DROP, "Bad UI system trap: %ld", (long int) args[0] ); } return 0; }
// code is a merge of the cl_main.cpp function of the same name and SV_SendClientGameState in sv_client.cpp static void SV_Record_f( void ) { char demoName[MAX_OSPATH]; char name[MAX_OSPATH]; int i; char *s; client_t *cl; if ( svs.clients == NULL ) { Com_Printf( "cannot record server demo - null svs.clients\n" ); return; } if ( Cmd_Argc() > 3 ) { Com_Printf( "record <demoname> <clientnum>\n" ); return; } if ( Cmd_Argc() == 3 ) { int clIndex = atoi( Cmd_Argv( 2 ) ); if ( clIndex < 0 || clIndex >= sv_maxclients->integer ) { Com_Printf( "Unknown client number %d.\n", clIndex ); return; } cl = &svs.clients[clIndex]; } else { for ( i=0, cl=svs.clients ; i < sv_maxclients->integer ; i++, cl++ ) { if ( !cl->state ) { continue; } if ( cl->demo.demorecording ) { continue; } if ( cl->state == CS_ACTIVE ) { break; } } } if (cl - svs.clients >= sv_maxclients->integer) { Com_Printf( "No active client could be found.\n" ); return; } if ( cl->demo.demorecording ) { Com_Printf( "Already recording.\n" ); return; } if ( cl->state != CS_ACTIVE ) { Com_Printf( "Client is not active.\n" ); return; } if ( Cmd_Argc() >= 2 ) { s = Cmd_Argv( 1 ); Q_strncpyz( demoName, s, sizeof( demoName ) ); Com_sprintf( name, sizeof( name ), "demos/%s.dm_%d", demoName, PROTOCOL_VERSION ); } else { // timestamp the file SV_DemoFilename( demoName, sizeof( demoName ) ); Com_sprintf (name, sizeof(name), "demos/%s.dm_%d", demoName, PROTOCOL_VERSION ); if ( FS_FileExists( name ) ) { Com_Printf( "Record: Couldn't create a file\n"); return; } } SV_RecordDemo( cl, demoName ); }
int CL_CgameSystemCalls( int *args ) { #ifndef __NO_JK2 if( Cvar_VariableIntegerValue("com_jk2") ) { args[0] = (int)CL_ConvertJK2SysCall((cgameJK2Import_t)args[0]); } #endif switch( args[0] ) { case CG_PRINT: Com_Printf( "%s", VMA(1) ); return 0; case CG_ERROR: Com_Error( ERR_DROP, S_COLOR_RED"%s", VMA(1) ); return 0; case CG_MILLISECONDS: return Sys_Milliseconds(); case CG_CVAR_REGISTER: Cvar_Register( (vmCvar_t *) VMA(1), (const char *) VMA(2), (const char *) VMA(3), args[4] ); return 0; case CG_CVAR_UPDATE: Cvar_Update( (vmCvar_t *) VMA(1) ); return 0; case CG_CVAR_SET: Cvar_Set( (const char *) VMA(1), (const char *) VMA(2) ); return 0; case CG_ARGC: return Cmd_Argc(); case CG_ARGV: Cmd_ArgvBuffer( args[1], (char *) VMA(2), args[3] ); return 0; case CG_ARGS: Cmd_ArgsBuffer( (char *) VMA(1), args[2] ); return 0; case CG_FS_FOPENFILE: return FS_FOpenFileByMode( (const char *) VMA(1), (int *) VMA(2), (fsMode_t) args[3] ); case CG_FS_READ: FS_Read( VMA(1), args[2], args[3] ); return 0; case CG_FS_WRITE: FS_Write( VMA(1), args[2], args[3] ); return 0; case CG_FS_FCLOSEFILE: FS_FCloseFile( args[1] ); return 0; case CG_SENDCONSOLECOMMAND: Cbuf_AddText( (const char *) VMA(1) ); return 0; case CG_ADDCOMMAND: CL_AddCgameCommand( (const char *) VMA(1) ); return 0; case CG_SENDCLIENTCOMMAND: CL_AddReliableCommand( (const char *) VMA(1) ); return 0; case CG_UPDATESCREEN: // this is used during lengthy level loading, so pump message loop Com_EventLoop(); // FIXME: if a server restarts here, BAD THINGS HAPPEN! SCR_UpdateScreen(); return 0; #ifdef _XBOX case CG_RMG_INIT: case CG_CM_REGISTER_TERRAIN: case CG_RE_INIT_RENDERER_TERRAIN: Com_Error( ERR_FATAL, "ERROR: Terrain unsupported on Xbox.\n" ); #else case CG_RMG_INIT: /* if (!com_sv_running->integer) { // don't do this if we are connected locally if (!TheRandomMissionManager) { TheRandomMissionManager = new CRMManager; } TheRandomMissionManager->SetLandScape( cmg.landScapes[args[1]] ); TheRandomMissionManager->LoadMission(qfalse); TheRandomMissionManager->SpawnMission(qfalse); cmg.landScapes[args[1]]->UpdatePatches(); } */ //this is SP.. I guess we're always the client and server. // cl.mRMGChecksum = cm.landScapes[args[1]]->get_rand_seed(); RM_CreateRandomModels(args[1], (const char *)VMA(2)); //cmg.landScapes[args[1]]->rand_seed(cl.mRMGChecksum); // restore it, in case we do a vid restart cmg.landScape->rand_seed(cmg.landScape->get_rand_seed()); // TheRandomMissionManager->CreateMap(); return 0; case CG_CM_REGISTER_TERRAIN: return CM_RegisterTerrain((const char *)VMA(1), false)->GetTerrainId(); case CG_RE_INIT_RENDERER_TERRAIN: RE_InitRendererTerrain((const char *)VMA(1)); return 0; #endif // _XBOX case CG_CM_LOADMAP: #ifdef _XBOX CL_CM_LoadMap( (const char *) VMA(1) ); #else CL_CM_LoadMap( (const char *) VMA(1), args[2] ); #endif return 0; case CG_CM_NUMINLINEMODELS: return CM_NumInlineModels(); case CG_CM_INLINEMODEL: return CM_InlineModel( args[1] ); case CG_CM_TEMPBOXMODEL: return CM_TempBoxModel( (const float *) VMA(1), (const float *) VMA(2) );//, (int) VMA(3) ); case CG_CM_POINTCONTENTS: return CM_PointContents( (float *)VMA(1), args[2] ); case CG_CM_TRANSFORMEDPOINTCONTENTS: return CM_TransformedPointContents( (const float *) VMA(1), args[2], (const float *) VMA(3), (const float *) VMA(4) ); case CG_CM_BOXTRACE: CM_BoxTrace( (trace_t *) VMA(1), (const float *) VMA(2), (const float *) VMA(3), (const float *) VMA(4), (const float *) VMA(5), args[6], args[7] ); return 0; case CG_CM_TRANSFORMEDBOXTRACE: CM_TransformedBoxTrace( (trace_t *) VMA(1), (const float *) VMA(2), (const float *) VMA(3), (const float *) VMA(4), (const float *) VMA(5), args[6], args[7], (const float *) VMA(8), (const float *) VMA(9) ); return 0; case CG_CM_MARKFRAGMENTS: return re.MarkFragments( args[1], (float(*)[3]) VMA(2), (const float *) VMA(3), args[4], (float *) VMA(5), args[6], (markFragment_t *) VMA(7) ); case CG_CM_SNAPPVS: CM_SnapPVS((float(*))VMA(1),(byte *) VMA(2)); return 0; case CG_S_STOPSOUNDS: S_StopSounds( ); return 0; case CG_S_STARTSOUND: // stops an ERR_DROP internally if called illegally from game side, but note that it also gets here // legally during level start where normally the internal s_soundStarted check would return. So ok to hit this. if (!cls.cgameStarted) { return 0; } S_StartSound( (float *) VMA(1), args[2], (soundChannel_t)args[3], args[4] ); return 0; case CG_S_UPDATEAMBIENTSET: // stops an ERR_DROP internally if called illegally from game side, but note that it also gets here // legally during level start where normally the internal s_soundStarted check would return. So ok to hit this. if (!cls.cgameStarted) { return 0; } S_UpdateAmbientSet( (const char *) VMA(1), (float *) VMA(2) ); return 0; case CG_S_ADDLOCALSET: return S_AddLocalSet( (const char *) VMA(1), (float *) VMA(2), (float *) VMA(3), args[4], args[5] ); case CG_AS_PARSESETS: AS_ParseSets(); return 0; case CG_AS_ADDENTRY: AS_AddPrecacheEntry( (const char *) VMA(1) ); return 0; case CG_AS_GETBMODELSOUND: return AS_GetBModelSound( (const char *) VMA(1), args[2] ); case CG_S_STARTLOCALSOUND: // stops an ERR_DROP internally if called illegally from game side, but note that it also gets here // legally during level start where normally the internal s_soundStarted check would return. So ok to hit this. if (!cls.cgameStarted) { return 0; } S_StartLocalSound( args[1], args[2] ); return 0; case CG_S_CLEARLOOPINGSOUNDS: S_ClearLoopingSounds(); return 0; case CG_S_ADDLOOPINGSOUND: // stops an ERR_DROP internally if called illegally from game side, but note that it also gets here // legally during level start where normally the internal s_soundStarted check would return. So ok to hit this. if (!cls.cgameStarted) { return 0; } S_AddLoopingSound( args[1], (const float *) VMA(2), (const float *) VMA(3), args[4], (soundChannel_t)args[5] ); return 0; case CG_S_UPDATEENTITYPOSITION: S_UpdateEntityPosition( args[1], (const float *) VMA(2) ); return 0; case CG_S_RESPATIALIZE: S_Respatialize( args[1], (const float *) VMA(2), (float(*)[3]) VMA(3), args[4] ); return 0; case CG_S_REGISTERSOUND: return S_RegisterSound( (const char *) VMA(1) ); case CG_S_STARTBACKGROUNDTRACK: S_StartBackgroundTrack( (const char *) VMA(1), (const char *) VMA(2), args[3]); return 0; case CG_S_GETSAMPLELENGTH: return S_GetSampleLengthInMilliSeconds( args[1]); case CG_R_LOADWORLDMAP: re.LoadWorld( (const char *) VMA(1) ); return 0; case CG_R_REGISTERMODEL: return re.RegisterModel( (const char *) VMA(1) ); case CG_R_REGISTERSKIN: return re.RegisterSkin( (const char *) VMA(1) ); case CG_R_REGISTERSHADER: return re.RegisterShader( (const char *) VMA(1) ); case CG_R_REGISTERSHADERNOMIP: return re.RegisterShaderNoMip( (const char *) VMA(1) ); case CG_R_REGISTERFONT: return re.RegisterFont( (const char *) VMA(1) ); case CG_R_FONTSTRLENPIXELS: return re.Font_StrLenPixels( (const char *) VMA(1), args[2], VMF(3) ); case CG_R_FONTSTRLENCHARS: return re.Font_StrLenChars( (const char *) VMA(1) ); case CG_R_FONTHEIGHTPIXELS: return re.Font_HeightPixels( args[1], VMF(2) ); case CG_R_FONTDRAWSTRING: re.Font_DrawString(args[1],args[2], (const char *) VMA(3), (float*)args[4], args[5], args[6], VMF(7)); return 0; case CG_LANGUAGE_ISASIAN: return re.Language_IsAsian(); case CG_LANGUAGE_USESSPACES: return re.Language_UsesSpaces(); case CG_ANYLANGUAGE_READFROMSTRING: return re.AnyLanguage_ReadCharFromString( (char *) VMA(1), (int *) VMA(2), (qboolean *) VMA(3) ); case CG_ANYLANGUAGE_READFROMSTRING2: return re.AnyLanguage_ReadCharFromString2( (char **) VMA(1), (qboolean *) VMA(3) ); case CG_R_SETREFRACTIONPROP: tr_distortionAlpha = VMF(1); tr_distortionStretch = VMF(2); tr_distortionPrePost = (qboolean)args[3]; tr_distortionNegate = (qboolean)args[4]; return 0; case CG_R_CLEARSCENE: re.ClearScene(); return 0; case CG_R_ADDREFENTITYTOSCENE: re.AddRefEntityToScene( (const refEntity_t *) VMA(1) ); return 0; case CG_R_INPVS: return R_inPVS((float *) VMA(1), (float *) VMA(2)); case CG_R_GETLIGHTING: return re.GetLighting( (const float * ) VMA(1), (float *) VMA(2), (float *) VMA(3), (float *) VMA(4) ); case CG_R_ADDPOLYTOSCENE: re.AddPolyToScene( args[1], args[2], (const polyVert_t *) VMA(3) ); return 0; case CG_R_ADDLIGHTTOSCENE: #ifdef VV_LIGHTING VVLightMan.RE_AddLightToScene ( (const float *) VMA(1), VMF(2), VMF(3), VMF(4), VMF(5) ); #else re.AddLightToScene( (const float *) VMA(1), VMF(2), VMF(3), VMF(4), VMF(5) ); #endif return 0; case CG_R_RENDERSCENE: re.RenderScene( (const refdef_t *) VMA(1) ); return 0; case CG_R_SETCOLOR: re.SetColor( (const float *) VMA(1) ); return 0; case CG_R_DRAWSTRETCHPIC: re.DrawStretchPic( VMF(1), VMF(2), VMF(3), VMF(4), VMF(5), VMF(6), VMF(7), VMF(8), args[9] ); return 0; // The below was commented out for whatever reason... /me shrugs --eez case CG_R_DRAWSCREENSHOT: re.DrawStretchRaw( VMF(1), VMF(2), VMF(3), VMF(4), SG_SCR_WIDTH, SG_SCR_HEIGHT, SCR_GetScreenshot(0), 0, qtrue); return 0; case CG_R_MODELBOUNDS: re.ModelBounds( args[1], (float *) VMA(2), (float *) VMA(3) ); return 0; case CG_R_LERPTAG: re.LerpTag( (orientation_t *) VMA(1), args[2], args[3], args[4], VMF(5), (const char *) VMA(6) ); return 0; case CG_R_DRAWROTATEPIC: re.DrawRotatePic( VMF(1), VMF(2), VMF(3), VMF(4), VMF(5), VMF(6), VMF(7), VMF(8), VMF(9), args[10] ); return 0; case CG_R_DRAWROTATEPIC2: re.DrawRotatePic2( VMF(1), VMF(2), VMF(3), VMF(4), VMF(5), VMF(6), VMF(7), VMF(8), VMF(9), args[10] ); return 0; case CG_R_SETRANGEFOG: if (tr.rangedFog <= 0.0f) { g_oldRangedFog = tr.rangedFog; } tr.rangedFog = VMF(1); if (tr.rangedFog == 0.0f && g_oldRangedFog) { //restore to previous state if applicable tr.rangedFog = g_oldRangedFog; } return 0; case CG_R_LA_GOGGLES: re.LAGoggles(); return 0; case CG_R_SCISSOR: re.Scissor( VMF(1), VMF(2), VMF(3), VMF(4)); return 0; case CG_GETGLCONFIG: CL_GetGlconfig( (glconfig_t *) VMA(1) ); return 0; case CG_GETGAMESTATE: CL_GetGameState( (gameState_t *) VMA(1) ); return 0; case CG_GETCURRENTSNAPSHOTNUMBER: CL_GetCurrentSnapshotNumber( (int *) VMA(1), (int *) VMA(2) ); return 0; case CG_GETSNAPSHOT: return CL_GetSnapshot( args[1], (snapshot_t *) VMA(2) ); case CG_GETDEFAULTSTATE: return CL_GetDefaultState(args[1], (entityState_t *)VMA(2)); case CG_GETSERVERCOMMAND: return CL_GetServerCommand( args[1] ); case CG_GETCURRENTCMDNUMBER: return CL_GetCurrentCmdNumber(); case CG_GETUSERCMD: return CL_GetUserCmd( args[1], (usercmd_s *) VMA(2) ); case CG_SETUSERCMDVALUE: CL_SetUserCmdValue( args[1], VMF(2), VMF(3), VMF(4) ); return 0; case CG_SETUSERCMDANGLES: CL_SetUserCmdAngles( VMF(1), VMF(2), VMF(3) ); return 0; case COM_SETORGANGLES: Com_SetOrgAngles((float *)VMA(1),(float *)VMA(2)); return 0; /* Ghoul2 Insert Start */ case CG_G2_LISTSURFACES: G2API_ListSurfaces( (CGhoul2Info *) VMA(1) ); return 0; case CG_G2_LISTBONES: G2API_ListBones( (CGhoul2Info *) VMA(1), args[2]); return 0; case CG_G2_HAVEWEGHOULMODELS: return G2API_HaveWeGhoul2Models( *((CGhoul2Info_v *)VMA(1)) ); case CG_G2_SETMODELS: G2API_SetGhoul2ModelIndexes( *((CGhoul2Info_v *)VMA(1)),(qhandle_t *)VMA(2),(qhandle_t *)VMA(3)); return 0; /* Ghoul2 Insert End */ case CG_R_GET_LIGHT_STYLE: re.GetLightStyle(args[1], (byte*) VMA(2) ); return 0; case CG_R_SET_LIGHT_STYLE: re.SetLightStyle(args[1], args[2] ); return 0; case CG_R_GET_BMODEL_VERTS: re.GetBModelVerts( args[1], (float (*)[3])VMA(2), (float *)VMA(3) ); return 0; case CG_R_WORLD_EFFECT_COMMAND: re.WorldEffectCommand( (const char *) VMA(1) ); return 0; case CG_CIN_PLAYCINEMATIC: return CIN_PlayCinematic( (const char *) VMA(1), args[2], args[3], args[4], args[5], args[6], (const char *) VMA(7)); case CG_CIN_STOPCINEMATIC: return CIN_StopCinematic(args[1]); case CG_CIN_RUNCINEMATIC: return CIN_RunCinematic(args[1]); case CG_CIN_DRAWCINEMATIC: CIN_DrawCinematic(args[1]); return 0; case CG_CIN_SETEXTENTS: CIN_SetExtents(args[1], args[2], args[3], args[4], args[5]); return 0; case CG_Z_MALLOC: return (int)Z_Malloc(args[1], (memtag_t) args[2], qfalse); case CG_Z_FREE: Z_Free((void *) VMA(1)); return 0; case CG_UI_SETACTIVE_MENU: UI_SetActiveMenu((const char *) VMA(1),NULL); return 0; case CG_UI_MENU_OPENBYNAME: Menus_OpenByName((const char *) VMA(1)); return 0; case CG_UI_MENU_RESET: Menu_Reset(); return 0; case CG_UI_MENU_NEW: Menu_New((char *) VMA(1)); return 0; case CG_UI_PARSE_INT: PC_ParseInt((int *) VMA(1)); return 0; case CG_UI_PARSE_STRING: PC_ParseString((const char **) VMA(1)); return 0; case CG_UI_PARSE_FLOAT: PC_ParseFloat((float *) VMA(1)); return 0; case CG_UI_STARTPARSESESSION: return(PC_StartParseSession((char *) VMA(1),(char **) VMA(2))); case CG_UI_ENDPARSESESSION: PC_EndParseSession((char *) VMA(1)); return 0; case CG_UI_PARSEEXT: char **holdPtr; holdPtr = (char **) VMA(1); if(!holdPtr) { Com_Error(ERR_FATAL, "CG_UI_PARSEEXT: NULL holdPtr"); } *holdPtr = PC_ParseExt(); return 0; case CG_UI_MENUCLOSE_ALL: Menus_CloseAll(); return 0; case CG_UI_MENUPAINT_ALL: Menu_PaintAll(); return 0; case CG_UI_STRING_INIT: String_Init(); return 0; case CG_UI_GETMENUINFO: menuDef_t *menu; int *xPos,*yPos,*w,*h,result; #ifndef __NO_JK2 if(!Cvar_VariableIntegerValue("com_jk2")) { #endif menu = Menus_FindByName((char *) VMA(1)); // Get menu if (menu) { xPos = (int *) VMA(2); *xPos = (int) menu->window.rect.x; yPos = (int *) VMA(3); *yPos = (int) menu->window.rect.y; w = (int *) VMA(4); *w = (int) menu->window.rect.w; h = (int *) VMA(5); *h = (int) menu->window.rect.h; result = qtrue; } else { result = qfalse; } return result; #ifndef __NO_JK2 } else { menu = Menus_FindByName((char *) VMA(1)); // Get menu if (menu) { xPos = (int *) VMA(2); *xPos = (int) menu->window.rect.x; yPos = (int *) VMA(3); *yPos = (int) menu->window.rect.y; result = qtrue; } else { result = qfalse; } return result; } #endif break; case CG_UI_GETITEMTEXT: itemDef_t *item; menu = Menus_FindByName((char *) VMA(1)); // Get menu if (menu) { item = (itemDef_s *) Menu_FindItemByName((menuDef_t *) menu, (char *) VMA(2)); if (item) { Q_strncpyz( (char *) VMA(3), item->text, 256 ); result = qtrue; } else { result = qfalse; } } else { result = qfalse; } return result; case CG_UI_GETITEMINFO: menu = Menus_FindByName((char *) VMA(1)); // Get menu if (menu) { qhandle_t *background; item = (itemDef_s *) Menu_FindItemByName((menuDef_t *) menu, (char *) VMA(2)); if (item) { xPos = (int *) VMA(3); *xPos = (int) item->window.rect.x; yPos = (int *) VMA(4); *yPos = (int) item->window.rect.y; w = (int *) VMA(5); *w = (int) item->window.rect.w; h = (int *) VMA(6); *h = (int) item->window.rect.h; vec4_t *color; color = (vec4_t *) VMA(7); if (!color) { return qfalse; } (*color)[0] = (float) item->window.foreColor[0]; (*color)[1] = (float) item->window.foreColor[1]; (*color)[2] = (float) item->window.foreColor[2]; (*color)[3] = (float) item->window.foreColor[3]; background = (qhandle_t *) VMA(8); if (!background) { return qfalse; } *background = item->window.background; result = qtrue; } else { result = qfalse; } } else { result = qfalse; } return result; case CG_SP_GETSTRINGTEXTSTRING: #ifndef __NO_JK2 case CG_SP_GETSTRINGTEXT: if(Cvar_VariableIntegerValue("com_jk2")) { const char* text; assert(VMA(1)); // assert(VMA(2)); // can now pass in NULL to just query the size if (args[0] == CG_SP_GETSTRINGTEXT) { text = JK2SP_GetStringText( args[1] ); } else { text = JK2SP_GetStringTextString( (const char *) VMA(1) ); } if (VMA(2)) // only if dest buffer supplied... { if ( text[0] ) { Q_strncpyz( (char *) VMA(2), text, args[3] ); } else { Q_strncpyz( (char *) VMA(2), "??", args[3] ); } } return strlen(text); } else { #endif const char* text; assert(VMA(1)); text = SE_GetString( (const char *) VMA(1) ); if (VMA(2)) // only if dest buffer supplied... { if ( text[0] ) { Q_strncpyz( (char *) VMA(2), text, args[3] ); } else { Com_sprintf( (char *) VMA(2), args[3], "??%s", VMA(1) ); } } return strlen(text); #ifndef __NO_JK2 } //break; case CG_SP_REGISTER: return JK2SP_Register( (const char *) VMA(1), args[2]?(SP_REGISTER_MENU|SP_REGISTER_REQUIRED):SP_REGISTER_CLIENT ); #endif default: Com_Error( ERR_DROP, "Bad cgame system trap: %i", args[0] ); } return 0; }
static void SV_AddBanToList( qboolean isexception ) { char *banstring; char addy2[NET_ADDRSTRMAXLEN]; netadr_t ip; int index, argc, mask; serverBan_t *curban; // make sure server is running if ( !com_sv_running->integer ) { Com_Printf( "Server is not running.\n" ); return; } argc = Cmd_Argc(); if ( argc < 2 || argc > 3 ) { Com_Printf( "Usage: %s (ip[/subnet] | clientnum [subnet])\n", Cmd_Argv( 0 ) ); return; } if ( serverBansCount >= (int)ARRAY_LEN( serverBans ) ) { Com_Printf( "Error: Maximum number of bans/exceptions exceeded.\n" ); return; } banstring = Cmd_Argv( 1 ); if ( strchr( banstring, '.' ) /*|| strchr( banstring, ':' )*/ ) { // This is an ip address, not a client num. if ( SV_ParseCIDRNotation( &ip, &mask, banstring ) ) { Com_Printf( "Error: Invalid address %s\n", banstring ); return; } } else { client_t *cl; // client num. cl = SV_GetPlayerByNum(); if ( !cl ) { Com_Printf( "Error: Playernum %s does not exist.\n", Cmd_Argv( 1 ) ); return; } ip = cl->netchan.remoteAddress; if ( argc == 3 ) { mask = atoi( Cmd_Argv( 2 ) ); if ( ip.type == NA_IP ) { if ( mask < 1 || mask > 32 ) mask = 32; } else mask = 32; } else mask = 32; } if ( ip.type != NA_IP ) { Com_Printf( "Error: Can ban players connected via the internet only.\n" ); return; } // first check whether a conflicting ban exists that would supersede the new one. for ( index = 0; index < serverBansCount; index++ ) { curban = &serverBans[index]; if ( curban->subnet <= mask ) { if ( (curban->isexception || !isexception) && NET_CompareBaseAdrMask( curban->ip, ip, curban->subnet ) ) { Q_strncpyz( addy2, NET_AdrToString( ip ), sizeof( addy2 ) ); Com_Printf( "Error: %s %s/%d supersedes %s %s/%d\n", curban->isexception ? "Exception" : "Ban", NET_AdrToString( curban->ip ), curban->subnet, isexception ? "exception" : "ban", addy2, mask ); return; } } if ( curban->subnet >= mask ) { if ( !curban->isexception && isexception && NET_CompareBaseAdrMask( curban->ip, ip, mask ) ) { Q_strncpyz( addy2, NET_AdrToString( curban->ip ), sizeof( addy2 ) ); Com_Printf( "Error: %s %s/%d supersedes already existing %s %s/%d\n", isexception ? "Exception" : "Ban", NET_AdrToString( ip ), mask, curban->isexception ? "exception" : "ban", addy2, curban->subnet ); return; } } } // now delete bans that are superseded by the new one index = 0; while ( index < serverBansCount ) { curban = &serverBans[index]; if ( curban->subnet > mask && (!curban->isexception || isexception) && NET_CompareBaseAdrMask( curban->ip, ip, mask ) ) SV_DelBanEntryFromList( index ); else index++; } serverBans[serverBansCount].ip = ip; serverBans[serverBansCount].subnet = mask; serverBans[serverBansCount].isexception = isexception; serverBansCount++; SV_WriteBans(); Com_Printf( "Added %s: %s/%d\n", isexception ? "ban exception" : "ban", NET_AdrToString( ip ), mask ); }
/* ================== SV_WriteDownloadToClient Check to see if the client wants a file, open it if needed and start pumping the client Fill up msg with data ================== */ void SV_WriteDownloadToClient( client_t *cl , msg_t *msg ) { int curindex; int rate; int blockspersnap; int idPack = 0, missionPack = 0, unreferenced = 1; char errorMessage[1024]; char pakbuf[MAX_QPATH], *pakptr; int numRefPaks; if (!*cl->downloadName) return; // Nothing being downloaded if (!cl->download) { // Chop off filename extension. Com_sprintf(pakbuf, sizeof(pakbuf), "%s", cl->downloadName); pakptr = Q_strrchr(pakbuf, '.'); if(pakptr) { *pakptr = '\0'; // Check for pk3 filename extension if(!Q_stricmp(pakptr + 1, "pk3")) { const char *referencedPaks = FS_ReferencedPakNames(); // Check whether the file appears in the list of referenced // paks to prevent downloading of arbitrary files. Cmd_TokenizeStringIgnoreQuotes(referencedPaks); numRefPaks = Cmd_Argc(); for(curindex = 0; curindex < numRefPaks; curindex++) { if(!FS_FilenameCompare(Cmd_Argv(curindex), pakbuf)) { unreferenced = 0; // now that we know the file is referenced, // check whether it's legal to download it. missionPack = FS_idPak(pakbuf, "missionpack"); idPack = missionPack || FS_idPak(pakbuf, BASEGAME); break; } } } } // We open the file here if ( !(sv_allowDownload->integer & DLF_ENABLE) || (sv_allowDownload->integer & DLF_NO_UDP) || idPack || unreferenced || ( cl->downloadSize = FS_SV_FOpenFileRead( cl->downloadName, &cl->download ) ) <= 0 ) { // cannot auto-download file if(unreferenced) { Com_Printf("clientDownload: %d : \"%s\" is not referenced and cannot be downloaded.\n", (int) (cl - svs.clients), cl->downloadName); Com_sprintf(errorMessage, sizeof(errorMessage), "File \"%s\" is not referenced and cannot be downloaded.", cl->downloadName); } else if (idPack) { Com_Printf("clientDownload: %d : \"%s\" cannot download id pk3 files\n", (int) (cl - svs.clients), cl->downloadName); if (missionPack) { Com_sprintf(errorMessage, sizeof(errorMessage), "Cannot autodownload Team Arena file \"%s\"\n" "The Team Arena mission pack can be found in your local game store.", cl->downloadName); } else { Com_sprintf(errorMessage, sizeof(errorMessage), "Cannot autodownload id pk3 file \"%s\"", cl->downloadName); } } else if ( !(sv_allowDownload->integer & DLF_ENABLE) || (sv_allowDownload->integer & DLF_NO_UDP) ) { Com_Printf("clientDownload: %d : \"%s\" download disabled", (int) (cl - svs.clients), cl->downloadName); if (sv_pure->integer) { Com_sprintf(errorMessage, sizeof(errorMessage), "Could not download \"%s\" because autodownloading is disabled on the server.\n\n" "You will need to get this file elsewhere before you " "can connect to this pure server.\n", cl->downloadName); } else { Com_sprintf(errorMessage, sizeof(errorMessage), "Could not download \"%s\" because autodownloading is disabled on the server.\n\n" "The server you are connecting to is not a pure server, " "set autodownload to No in your settings and you might be " "able to join the game anyway.\n", cl->downloadName); } } else { // NOTE TTimo this is NOT supposed to happen unless bug in our filesystem scheme? // if the pk3 is referenced, it must have been found somewhere in the filesystem Com_Printf("clientDownload: %d : \"%s\" file not found on server\n", (int) (cl - svs.clients), cl->downloadName); Com_sprintf(errorMessage, sizeof(errorMessage), "File \"%s\" not found on server for autodownloading.\n", cl->downloadName); } MSG_WriteByte( msg, svc_download ); MSG_WriteShort( msg, 0 ); // client is expecting block zero MSG_WriteLong( msg, -1 ); // illegal file size MSG_WriteString( msg, errorMessage ); *cl->downloadName = 0; return; } Com_Printf( "clientDownload: %d : beginning \"%s\"\n", (int) (cl - svs.clients), cl->downloadName ); // Init cl->downloadCurrentBlock = cl->downloadClientBlock = cl->downloadXmitBlock = 0; cl->downloadCount = 0; cl->downloadEOF = qfalse; } // Perform any reads that we need to while (cl->downloadCurrentBlock - cl->downloadClientBlock < MAX_DOWNLOAD_WINDOW && cl->downloadSize != cl->downloadCount) { curindex = (cl->downloadCurrentBlock % MAX_DOWNLOAD_WINDOW); if (!cl->downloadBlocks[curindex]) cl->downloadBlocks[curindex] = Z_Malloc( MAX_DOWNLOAD_BLKSIZE ); cl->downloadBlockSize[curindex] = FS_Read( cl->downloadBlocks[curindex], MAX_DOWNLOAD_BLKSIZE, cl->download ); if (cl->downloadBlockSize[curindex] < 0) { // EOF right now cl->downloadCount = cl->downloadSize; break; } cl->downloadCount += cl->downloadBlockSize[curindex]; // Load in next block cl->downloadCurrentBlock++; } // Check to see if we have eof condition and add the EOF block if (cl->downloadCount == cl->downloadSize && !cl->downloadEOF && cl->downloadCurrentBlock - cl->downloadClientBlock < MAX_DOWNLOAD_WINDOW) { cl->downloadBlockSize[cl->downloadCurrentBlock % MAX_DOWNLOAD_WINDOW] = 0; cl->downloadCurrentBlock++; cl->downloadEOF = qtrue; // We have added the EOF block } // Loop up to window size times based on how many blocks we can fit in the // client snapMsec and rate // based on the rate, how many bytes can we fit in the snapMsec time of the client // normal rate / snapshotMsec calculation rate = cl->rate; if ( sv_maxRate->integer ) { if ( sv_maxRate->integer < 1000 ) { Cvar_Set( "sv_MaxRate", "1000" ); } if ( sv_maxRate->integer < rate ) { rate = sv_maxRate->integer; } } if ( sv_minRate->integer ) { if ( sv_minRate->integer < 1000 ) Cvar_Set( "sv_minRate", "1000" ); if ( sv_minRate->integer > rate ) rate = sv_minRate->integer; } if (!rate) { blockspersnap = 1; } else { blockspersnap = ( (rate * cl->snapshotMsec) / 1000 + MAX_DOWNLOAD_BLKSIZE ) / MAX_DOWNLOAD_BLKSIZE; } if (blockspersnap < 0) blockspersnap = 1; while (blockspersnap--) { // Write out the next section of the file, if we have already reached our window, // automatically start retransmitting if (cl->downloadClientBlock == cl->downloadCurrentBlock) return; // Nothing to transmit if (cl->downloadXmitBlock == cl->downloadCurrentBlock) { // We have transmitted the complete window, should we start resending? //FIXME: This uses a hardcoded one second timeout for lost blocks //the timeout should be based on client rate somehow if (svs.time - cl->downloadSendTime > 1000) cl->downloadXmitBlock = cl->downloadClientBlock; else return; } // Send current block curindex = (cl->downloadXmitBlock % MAX_DOWNLOAD_WINDOW); MSG_WriteByte( msg, svc_download ); MSG_WriteShort( msg, cl->downloadXmitBlock ); // block zero is special, contains file size if ( cl->downloadXmitBlock == 0 ) MSG_WriteLong( msg, cl->downloadSize ); MSG_WriteShort( msg, cl->downloadBlockSize[curindex] ); // Write the block if ( cl->downloadBlockSize[curindex] ) { MSG_WriteData( msg, cl->downloadBlocks[curindex], cl->downloadBlockSize[curindex] ); } Com_DPrintf( "clientDownload: %d : writing block %d\n", (int) (cl - svs.clients), cl->downloadXmitBlock ); // Move on to the next block // It will get sent with next snap shot. The rate will keep us in line. cl->downloadXmitBlock++; cl->downloadSendTime = svs.time; } }
/* ================== SV_BeginDownload_f ================== */ void SV_BeginDownload_f(void) { char *name, *p; size_t length; qboolean valid; // extern int file_from_pak; // ZOID did file come from pak? int offset = 0; name = Cmd_Argv(1); if (Cmd_Argc() > 2) offset = atoi(Cmd_Argv(2)); // downloaded offset // r1ch fix: name is always filtered for security reasons StripHighBits (name, 1); // hacked by zoid to allow more conrol over download // first off, no .. or global allow check // r1ch fix: for some ./ references in maps, eg ./textures/map/file length = strlen(name); p = name; while ((p = strstr (p, "./"))) { memmove (p, p+2, length - (p - name) - 1); length -= 2; } // r1ch fix: block the really nasty ones - \server.cfg will download from mod root on win32, .. is obvious if (name[0] == '\\' || strstr (name, "..")) { Com_Printf ("Refusing illegal download path %s to %s\n", name, sv_client->name); MSG_WriteByte (&sv_client->netchan.message, svc_download); MSG_WriteShort (&sv_client->netchan.message, -1); MSG_WriteByte (&sv_client->netchan.message, 0); Com_Printf ("Client %s[%s] tried to download illegal path: %s\n", sv_client->name, NET_AdrToString (sv_client->netchan.remote_address), name); SV_DropClient (sv_client); return; } else if (offset < 0) // r1ch fix: negative offset will crash on read { Com_Printf ("Refusing illegal download offset %d to %s\n", offset, sv_client->name); MSG_WriteByte (&sv_client->netchan.message, svc_download); MSG_WriteShort (&sv_client->netchan.message, -1); MSG_WriteByte (&sv_client->netchan.message, 0); Com_Printf ("Client %s[%s] supplied illegal download offset for %s: %d\n", sv_client->name, NET_AdrToString (sv_client->netchan.remote_address), name, offset); SV_DropClient (sv_client); return; } else if ( !length || name[0] == 0 // empty name, maybe as result of ./ normalize || !IsValidChar(name[0]) // r1ch: \ is bad in general, client won't even write properly if we do sent it || strchr (name, '\\') // MUST be in a subdirectory, unless a pk3 || (!strstr (name, "/") && strcmp(name+strlen(name)-4, ".pk3")) // r1ch: another bug, maps/. will fopen(".") -> crash || !IsValidChar(name[length-1]) ) /* if (strstr (name, "..") || !allow_download->value // leading dot is no good || *name == '.' // leading slash bad as well, must be in subdir || *name == '/' // next up, skin check || (strncmp(name, "players/", 8) == 0 && !allow_download_players->value) // now models || (strncmp(name, "models/", 7) == 0 && !allow_download_models->value) // now sounds || (strncmp(name, "sound/", 6) == 0 && !allow_download_sounds->value) // now maps (note special case for maps, must not be in pak) || (strncmp(name, "maps/", 5) == 0 && !allow_download_maps->value) // MUST be in a subdirectory, unless a pk3 || (!strstr (name, "/") && strcmp(name+strlen(name)-4, ".pk3")) ) */ { // don't allow anything with .. path MSG_WriteByte (&sv_client->netchan.message, svc_download); MSG_WriteShort (&sv_client->netchan.message, -1); MSG_WriteByte (&sv_client->netchan.message, 0); return; } valid = true; if ( !allow_download->value || (strncmp(name, "players/", 8) == 0 && !allow_download_players->value) || (strncmp(name, "models/", 7) == 0 && !allow_download_models->value) || (strncmp(name, "sound/", 6) == 0 && !allow_download_sounds->value) || (strncmp(name, "maps/", 5) == 0 && !allow_download_maps->value) || (strncmp(name, "pics/", 5) == 0 && !allow_download_pics->value) || ( ((strncmp(name, "env/", 4) == 0 || strncmp(name, "textures/", 9) == 0)) && !allow_download_textures->value ) ) valid = false; if (!valid) { MSG_WriteByte (&sv_client->netchan.message, svc_download); MSG_WriteShort (&sv_client->netchan.message, -1); MSG_WriteByte (&sv_client->netchan.message, 0); return; } if (sv_client->download) FS_FreeFile (sv_client->download); sv_client->downloadsize = FS_LoadFile (name, (void **)&sv_client->download); sv_client->downloadcount = offset; if (offset > sv_client->downloadsize) sv_client->downloadcount = sv_client->downloadsize; // ZOID- special check for maps, if it came from a pak file, don't allow download if (!sv_client->download || (strncmp(name, "maps/", 5) == 0 && file_from_pak)) { Com_DPrintf ("Couldn't download %s to %s\n", name, sv_client->name); if (sv_client->download) { FS_FreeFile (sv_client->download); sv_client->download = NULL; } MSG_WriteByte (&sv_client->netchan.message, svc_download); MSG_WriteShort (&sv_client->netchan.message, -1); MSG_WriteByte (&sv_client->netchan.message, 0); return; } SV_NextDownload_f (); Com_DPrintf ("Downloading %s to %s\n", name, sv_client->name); }
static void Log_log_f(void) { char *fulllogname; FILE *templog; void *buf; switch (Cmd_Argc()) { case 1: if (autologging) Com_Printf("Auto console logging is in progress\n"); else if (Log_IsLogging()) Com_Printf("Logging to %s\n", logfilename); else Com_Printf("Not logging\n"); return; case 2: if (!strcasecmp(Cmd_Argv(1), "stop")) { if (autologging) { Log_AutoLogging_StopMatch(); } else { if (Log_IsLogging()) { Log_Stop(); Com_Printf("Stopped logging to %s\n", logfilename); } else { Com_Printf("Not logging\n"); } } return; } if (autologging) { Com_Printf("Auto console logging must be stopped first!\n"); return; } if (Log_IsLogging()) { Log_Stop(); Com_Printf("Stopped logging to %s\n", logfilename); } strlcpy(logfilename, Cmd_Argv(1), sizeof(logfilename) - 4); Util_Process_Filename(logfilename); if (!Util_Is_Valid_Filename(logfilename)) { Com_Printf(Util_Invalid_Filename_Msg("filename")); return; } COM_ForceExtensionEx (logfilename, ".log", sizeof (logfilename)); fulllogname = va("%s/%s", Log_LogDirectory(), logfilename); if (!(templog = fopen (fulllogname, log_readable.value ? "w" : "wb"))) { FS_CreatePath(fulllogname); if (!(templog = fopen (fulllogname, log_readable.value ? "w" : "wb"))) { Com_Printf("Error: Couldn't open %s\n", logfilename); return; } } buf = Q_calloc(1, LOGFILEBUFFER); if (!buf) { Com_Printf("Not enough memory to allocate log buffer\n"); return; } memlogfile = FSMMAP_OpenVFS(buf, LOGFILEBUFFER); Com_Printf("Logging to %s\n", logfilename); logfile = templog; break; default: Com_Printf("Usage: %s [filename | stop]\n", Cmd_Argv(0)); return; } }