// This will only happen on the very first snapshot, or on tourney restarts. // All other times will use CG_TransitionSnapshot instead. // FIXME: Also called by map_restart? void CG_SetInitialSnapshot( snapshot_t *snap ) { int i; centity_t *cent; entityState_t *state; cg.snap = snap; if ( !cg_entities[snap->ps.clientNum].ghoul2 && trap->G2_HaveWeGhoul2Models( cgs.clientinfo[snap->ps.clientNum].ghoul2Model ) ) { trap->G2API_DuplicateGhoul2Instance( cgs.clientinfo[snap->ps.clientNum].ghoul2Model, &cg_entities[snap->ps.clientNum].ghoul2 ); CG_CopyG2WeaponInstance( &cg_entities[snap->ps.clientNum], FIRST_WEAPON, cg_entities[snap->ps.clientNum].ghoul2 ); // check now to see if we have this bone for setting anims and such if ( trap->G2API_AddBolt( cg_entities[snap->ps.clientNum].ghoul2, 0, "face" ) == -1 ) cg_entities[snap->ps.clientNum].noFace = qtrue; } BG_PlayerStateToEntityState( &snap->ps, &cg_entities[snap->ps.clientNum].currentState, qfalse ); // sort out solid entities CG_BuildSolidList(); CG_ExecuteNewServerCommands( snap->serverCommandSequence ); // set our local weapon selection pointer to // what the server has indicated the current weapon is CG_Respawn(); for ( i = 0; i < cg.snap->numEntities; i++ ) { state = &cg.snap->entities[i]; cent = &cg_entities[state->number]; memcpy( ¢->currentState, state, sizeof(entityState_t) ); // cent->currentState = *state; cent->interpolate = qfalse; cent->currentValid = qtrue; CG_ResetEntity( cent ); // check for events CG_CheckEvents( cent ); } // auto record demo if ( cg_autoRecordDemo.integer & (1 << cgs.gametype) && cg.warmup <= 0 && !cg.demoPlayback ) { time_t rawtime; char buf[256] = { 0 }, timeStr[64] = { 0 }, mapName[MAX_QPATH] = { 0 }; time( &rawtime ); strftime( timeStr, sizeof(timeStr), "%Y-%m-%d_%H-%M-%S", localtime( &rawtime ) ); Q_strncpyz( mapName, cgs.mapname + 5, sizeof(mapName) ); Q_strstrip( mapName, "/", "-" ); COM_StripExtension( mapName, mapName, sizeof(mapName) ); Com_sprintf( buf, sizeof(buf), "%s_%s_%s_%s", timeStr, gametypeStringShort[cgs.gametype], mapName, cgs.clientinfo[cg.clientNum].name ); Q_strstrip( buf, "\n\r;?*<>|\\/\"", NULL ); Q_strstrip( buf, " ", "_" ); Q_CleanString( buf, STRIP_COLOUR | STRIP_EXTASCII ); trap->SendConsoleCommand( va( "stoprecord; record %s\n", buf ) ); } }
static void JPLua_PostInit( lua_State *L ) { char folderList[16384] = {0}, *folderName = NULL; int i=0, numFolders=0, folderLen=0; trap->Print( "^5**************** ^3JA++ Lua (SV) is initialising ^5****************\n" ); JPLua_LoadFile( L, JPLUA_DIRECTORY"init"JPLUA_EXTENSION ); lua_getfield( L, LUA_GLOBALSINDEX, "JPLua" ); lua_getfield( L, -1, "version" ); JPLua.version = lua_tointeger( L, -1 ); lua_pop( L, 1 ); trap->Print( "%-15s%-32s%-8s%s\n", " ", "Name", "Version", "Unique ID" ); numFolders = trap->FS_GetFileList( JPLUA_DIRECTORY, "/", folderList, sizeof( folderList ) ); folderName = folderList; for ( i=0; i<numFolders; i++ ) { Q_strstrip( folderName, "/\\", NULL ); folderLen = strlen( folderName ); //folderName[folderLen] = '\0'; // not necessary? if ( Q_stricmp( folderName, "." ) && Q_stricmp( folderName, ".." ) ) { char fileList[16384] = {0}, *fileName = NULL; int j=0, numFiles=0, fileLen=0; numFiles = trap->FS_GetFileList( va( JPLUA_DIRECTORY"%s", folderName ), JPLUA_EXTENSION, fileList, sizeof( fileList ) ); fileName = fileList; for ( j=0; j<numFiles; j++ ) { Q_strstrip( fileName, "/\\", NULL ); fileLen = strlen( fileName ); // fileName[fileLen] = '\0'; // not necessary? if ( !Q_stricmp( fileName, "plugin"JPLUA_EXTENSION ) ) { JPLua_LoadPlugin( folderName, fileName ); break; } fileName += fileLen+1; } } folderName += folderLen+1; } trap->Print( "^5**************** ^2JA++ Lua (SV) is initialised ^5****************\n" ); return; }
void SV_AutoRecordDemo( client_t *cl ) { char demoName[MAX_OSPATH]; char demoFolderName[MAX_OSPATH]; char demoFileName[MAX_OSPATH]; char *demoNames[] = { demoFolderName, demoFileName }; char date[MAX_OSPATH]; char folderDate[MAX_OSPATH]; char folderTreeDate[MAX_OSPATH]; char demoPlayerName[MAX_NAME_LENGTH]; time_t rawtime; struct tm * timeinfo; time( &rawtime ); timeinfo = localtime( &rawtime ); strftime( date, sizeof( date ), "%Y-%m-%d_%H-%M-%S", timeinfo ); timeinfo = localtime( &sv.realMapTimeStarted ); strftime( folderDate, sizeof( folderDate ), "%Y-%m-%d_%H-%M-%S", timeinfo ); strftime( folderTreeDate, sizeof( folderTreeDate ), "%Y/%m/%d", timeinfo ); Q_strncpyz( demoPlayerName, cl->name, sizeof( demoPlayerName ) ); Q_CleanStr( demoPlayerName ); Com_sprintf( demoFileName, sizeof( demoFileName ), "%d %s %s %s", cl - svs.clients, demoPlayerName, Cvar_VariableString( "mapname" ), date ); Com_sprintf( demoFolderName, sizeof( demoFolderName ), "%s %s", Cvar_VariableString( "mapname" ), folderDate ); // sanitize filename for ( char **start = demoNames; start - demoNames < (ptrdiff_t)ARRAY_LEN( demoNames ); start++ ) { Q_strstrip( *start, "\n\r;:.?*<>|\\/\"", NULL ); } Com_sprintf( demoName, sizeof( demoName ), "autorecord/%s/%s/%s", folderTreeDate, demoFolderName, demoFileName ); SV_RecordDemo( cl, demoName ); }
void G_Say( gentity_t *ent, gentity_t *target, int mode, const char *chatText ) { int j, color; gentity_t *other; char text[MAX_SAY_TEXT]; if ( level.gametype < GT_TEAMBLOOD && mode == SAY_TEAM ) mode = SAY_ALL; switch ( mode ) { default: case SAY_ALL: G_LogPrintf( "say: %s: %s\n", ent->client->pers.netname, chatText ); color = COLOR_GREEN; break; case SAY_TEAM: G_LogPrintf( "sayteam: %s: %s\n", ent->client->pers.netname, chatText ); color = COLOR_CYAN; break; case SAY_TELL: color = COLOR_PINK; break; } Q_strncpyz( text, chatText, sizeof(text) ); Q_strstrip( text, "\n\r", NULL ); if ( target ) { G_SayTo( ent, target, mode, color, text ); return; } // echo the text to the console if ( dedicated->integer ) trap->Print( "%s%s\n", ent->client->pers.netname, text); // send it to all the appropriate clients for ( j=0, other=g_entities; j<level.maxclients; j++, other++ ) G_SayTo( ent, other, mode, color, text ); }
void Svcmd_Say_f( void ) { char *p = NULL; // don't let text be too long for malicious reasons char text[MAX_SAY_TEXT] = {0}; if ( trap->Argc () < 2 ) return; p = ConcatArgs( 1 ); if ( strlen( p ) >= MAX_SAY_TEXT ) { p[MAX_SAY_TEXT-1] = '\0'; G_SecurityLogPrintf( "Cmd_Say_f from -1 (server) has been truncated: %s\n", p ); } Q_strncpyz( text, p, sizeof(text) ); Q_strstrip( text, "\n\r", " " ); //G_LogPrintf( "say: server: %s\n", text ); trap->SendServerCommand( -1, va("print \"server: %s\n\"", text ) ); }
static void Cmd_CallVote_f( gentity_t *ent ) { int i=0, numArgs=trap->Cmd_Argc(); char arg1[MAX_CVAR_VALUE_STRING] = {0}, arg2[MAX_CVAR_VALUE_STRING] = {0}; voteString_t *vote = NULL; if ( !g_allowVote->integer ) {// not allowed to vote at all trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), "print \"Not allowed to vote\n\"" ); return; } else if ( level.voteTime || level.voteExecuteTime >= level.time ) {// vote in progress trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), "print \"A vote is already in progress\n\"" ); return; } else if ( level.gametype != GT_DUEL && ent->client->sess.sessionTeam == TEAM_SPECTATOR ) {// can't vote as a spectator, except in duel trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), "print \"Not allowed to call a vote as spectator\n\"" ); return; } // make sure it is a valid command to vote on numArgs = trap->Cmd_Argc(); trap->Cmd_Argv( 1, arg1, sizeof( arg1 ) ); if ( numArgs > 1 ) Q_strncpyz( arg2, ConcatArgs( 2 ), sizeof( arg2 ) ); //trap->Cmd_Argv( 2, arg2, sizeof( arg2 ) ); //Raz: callvote exploit, filter \n and \r ==> in both args if ( Q_strchrs( arg1, ";\r\n" ) || Q_strchrs( arg2, ";\r\n" ) ) { trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), "print \"Invalid vote string.\n\"" ); return; } for ( i=0; i<validVoteStringsSize; i++ ) {// check for invalid votes if ( (g_voteDisable->integer & (1<<i)) ) continue; if ( !Q_stricmp( arg1, validVoteStrings[i].string ) ) break; if ( validVoteStrings[i].aliases ) {// see if they're using an alias, and set arg1 to the actual vote string char tmp[MAX_TOKEN_CHARS] = {0}, *p = NULL, *delim = " "; Q_strncpyz( tmp, validVoteStrings[i].aliases, sizeof( tmp ) ); p = strtok( tmp, delim ); while ( p != NULL ) { if ( !Q_stricmp( arg1, p ) ) { Q_strncpyz( arg1, validVoteStrings[i].string, sizeof( arg1 ) ); goto validVote; } p = strtok( NULL, delim ); } } } if ( i == validVoteStringsSize ) {// invalid vote string, abandon ship char buf[1024] = {0}; int toggle = 0; trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), "print \"Invalid vote string.\n\"" ); trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), "print \"Allowed vote strings are: \"" ); for ( i=0; i<validVoteStringsSize; i++ ) { if ( (g_voteDisable->integer & (1<<i)) ) continue; toggle = !toggle; if ( validVoteStrings[i].shortHelp ) { Q_strcat( buf, sizeof( buf ), va( "^%c%s %s ", toggle?'2':'3', validVoteStrings[i].string, validVoteStrings[i].shortHelp ) ); } else { Q_strcat( buf, sizeof( buf ), va( "^%c%s ", toggle?'2':'3', validVoteStrings[i].string ) ); } } //RAZTODO: buffer and send in multiple messages in case of overflow trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), va( "print \"%s\n\"", buf ) ); return; } validVote: vote = &validVoteStrings[i]; if ( !(vote->validGT & (1<<level.gametype)) ) { trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), va( "print \"%s is not applicable in this gametype.\n\"", arg1 ) ); return; } if ( numArgs < vote->numArgs ) { trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), va( "print \"%s requires more arguments: %s\n\"", arg1, vote->shortHelp ) ); return; } level.votingGametype = qfalse; level.voteExecuteDelay = vote->voteDelay ? g_voteDelay->integer : 0; if ( level.voteExecuteTime ) {// there is still a vote to be executed, execute it and store the new vote level.voteExecuteTime = 0; if ( level.votePoll ) trap->Cbuf_ExecuteText( EXEC_APPEND, va( "%s\n", level.voteString ) ); } if ( vote->func ) { if ( !vote->func( ent, numArgs, arg1, arg2 ) ) return; } else { Com_sprintf( level.voteString, sizeof( level.voteString ), "%s \"%s\"", arg1, arg2 ); Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "%s", level.voteString ); Q_strncpyz( level.voteStringClean, level.voteString, sizeof( level.voteStringClean ) ); } Q_strstrip( level.voteStringClean, "\"\n\r", NULL ); trap->SV_GameSendServerCommand( -1, va( "print \"%s^7 called a vote (%s)\n\"", ent->client->pers.netname, level.voteStringClean ) ); // start the voting, the caller automatically votes yes level.voteTime = level.time; level.voteYes = 1; level.voteNo = 0; level.votePoll = qfalse; for ( i=0; i<level.maxclients; i++ ) { level.clients[i].gameFlags &= ~GF_VOTED; level.clients[i].pers.vote = 0; } ent->client->gameFlags |= GF_VOTED; ent->client->pers.vote = 1; trap->SV_SetConfigstring( CS_VOTE_TIME, va( "%i", level.voteTime ) ); trap->SV_SetConfigstring( CS_VOTE_STRING, level.voteDisplayString ); trap->SV_SetConfigstring( CS_VOTE_YES, va( "%i", level.voteYes ) ); trap->SV_SetConfigstring( CS_VOTE_NO, va( "%i", level.voteNo ) ); }