static qboolean G_VoteGametype( gentity_t *ent, int numArgs, const char *arg1, const char *arg2 ) { int gt = atoi( arg2 ); if ( arg2[0] && isalpha( arg2[0] ) ) {// ffa, ctf, tdm, etc gt = GametypeIDForString( arg2 ); if ( gt == -1 ) { trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), va( "print \"Gametype (%s) unrecognised, defaulting to Duel\n\"", arg2 ) ); gt = GT_DUEL; } } else if ( gt < 0 || gt >= GT_NUM_GAMETYPES ) {// numeric but out of range trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), va( "print \"Gametype (%i) is out of range, defaulting to Duel\n\"", gt ) ); gt = GT_DUEL; } level.votingGametype = qtrue; level.votingGametypeTo = gt; Com_sprintf( level.voteString, sizeof( level.voteString ), "%s %d", arg1, gt ); Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "%s %s", arg1, gametypeStringShort[gt] ); Q_strncpyz( level.voteStringClean, level.voteString, sizeof( level.voteStringClean ) ); return qtrue; }
void G_PrintCommands( gentity_t *ent ) { const command_t *command = NULL; char buf[256] = {0}; int toggle = 0; size_t count = 0; const unsigned int limit = 72; Q_strcat( buf, sizeof( buf ), "Regular commands:\n " ); for ( command=commands; command && command->name; command++ ) { const char *tmpMsg = NULL; // if it's not allowed to be executed at the moment, continue if ( G_CmdValid( ent, command ) ) continue; tmpMsg = va( " ^%c%s", (++toggle&1?COLOR_GREEN:COLOR_YELLOW), command->name ); //newline if we reach limit if ( count >= limit ) { tmpMsg = va( "\n %s", tmpMsg ); count = 0; } if ( strlen( buf ) + strlen( tmpMsg ) >= sizeof( buf ) ) { trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), va( "print \"%s\"", buf ) ); buf[0] = '\0'; } count += strlen( tmpMsg ); Q_strcat( buf, sizeof( buf ), tmpMsg ); } trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), va( "print \"%s\n\n\"", buf ) ); }
static void Cmd_Team_f( gentity_t *ent ) { int oldTeam; char s[MAX_TOKEN_CHARS]; if ( trap->Cmd_Argc() != 2 ) { oldTeam = ent->client->sess.sessionTeam; switch ( oldTeam ) { case TEAM_BLUE: trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), "print \"Blue team\n\"" ); break; case TEAM_RED: trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), "print \"Red team\n\"" ); break; case TEAM_FREE: trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), "print \"Free team\n\"" ); break; case TEAM_SPECTATOR: trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), "print \"Spectator team\n\"" ); break; } return; } if ( ent->client->switchTeamTime > level.time ) { trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), "print \"May not switch teams more than once per 5 seconds.\n\"" ); return; } trap->Cmd_Argv( 1, s, sizeof( s ) ); SetTeam( ent, s ); ent->client->switchTeamTime = level.time + 5000; }
void Cmd_Vote_f( gentity_t *ent ) { char msg[64]; if ( !level.voteTime ) { trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), "print \"No vote in progress\n\"" ); return; } if ( ent->client->gameFlags & GF_VOTED ) { trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), "print \"Vote already cast\n\"" ); return; } if ( level.gametype != GT_DUEL ) { if ( ent->client->sess.sessionTeam == TEAM_SPECTATOR ) { trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), "print \"Not allowed to vote as spectator\n\"" ); return; } } trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), "print \"Vote cast\n\"" ); ent->client->gameFlags |= GF_VOTED; trap->Cmd_Argv( 1, msg, sizeof( msg ) ); if ( tolower( msg[0] ) == 'y' || msg[0] == '1' ) { level.voteYes++; ent->client->pers.vote = 1; trap->SV_SetConfigstring( CS_VOTE_YES, va("%i", level.voteYes ) ); } else { level.voteNo++; ent->client->pers.vote = 2; trap->SV_SetConfigstring( CS_VOTE_NO, va("%i", level.voteNo ) ); } }
static void Cmd_GiveOther_f( gentity_t *ent ) { char name[MAX_TOKEN_CHARS] = {0}; int i; char otherindex[MAX_TOKEN_CHARS]; gentity_t *otherEnt = NULL; trap->Cmd_Argv( 1, otherindex, sizeof( otherindex ) ); if ( !otherindex[0] ) { trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), "print \"giveother requires that the second argument be a client index number.\n\"" ); return; } i = atoi( otherindex ); if ( i < 0 || i >= MAX_CLIENTS ) { trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), va( "print \"%i is not a client index.\n\"", i ) ); return; } otherEnt = &g_entities[i]; if ( !otherEnt->inuse || !otherEnt->client ) { trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), va( "print \"%i is not an active client.\n\"", i ) ); return; } trap->Cmd_Argv( 2, name, sizeof( name ) ); G_Give( otherEnt, name, ConcatArgs( 3 ), trap->Cmd_Argc()-1 ); }
static void Cmd_MapList_f( gentity_t *ent ) { int i, toggle=0; char map[24] = "--", buf[512] = {0}; Q_strcat( buf, sizeof( buf ), "Map list:" ); for ( i=0; i<level.arenas.num; i++ ) { Q_strncpyz( map, Info_ValueForKey( level.arenas.infos[i], "map" ), sizeof( map ) ); Q_CleanColorStr( map ); if ( G_DoesMapSupportGametype( map, level.gametype ) ) { const char *tmpMsg = va( " ^%c%s", (++toggle&1) ? '2' : '3', map ); if ( strlen( buf ) + strlen( tmpMsg ) >= sizeof( buf ) ) { trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), va( "print \"%s\"", buf ) ); buf[0] = '\0'; } Q_strcat( buf, sizeof( buf ), tmpMsg ); } } trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), va( "print \"%s\n\"", buf ) ); }
static void G_SayTo( gentity_t *ent, gentity_t *other, int mode, int color, const char *message ) { if ( !other || !other->inuse || !other->client ) return; if ( other->client->pers.connected != CON_CONNECTED ) return; if ( mode == SAY_TEAM && !OnSameTeam( ent, other ) ) return; //QTZTODO: specmute /* // no chatting to players in tournaments if ( (level.gametype == GT_DUEL || level.gametype == GT_POWERDUEL) && other->client->sess.sessionTeam == TEAM_FREE && ent->client->sess.sessionTeam != TEAM_FREE ) { //Hmm, maybe some option to do so if allowed? Or at least in developer mode... return; } */ trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, other ), va( "%s %i \"%c%c%s\"", mode == SAY_TEAM ? "tchat" : "chat", ent->s.number, Q_COLOR_ESCAPE, color, message)); }
static UCHAR EmsMap(USHORT Handle, UCHAR PhysicalPage, USHORT LogicalPage) { PEMS_PAGE PageEntry; PEMS_HANDLE HandleEntry = GetHandleRecord(Handle); if (!ValidateHandle(HandleEntry)) return EMS_STATUS_INVALID_HANDLE; if (PhysicalPage >= EMS_PHYSICAL_PAGES) return EMS_STATUS_INV_PHYSICAL_PAGE; if (LogicalPage == 0xFFFF) { /* Unmap */ Mapping[PhysicalPage] = NULL; return EMS_STATUS_SUCCESS; } PageEntry = GetLogicalPage(HandleEntry, LogicalPage); if (!PageEntry) return EMS_STATUS_INV_LOGICAL_PAGE; Mapping[PhysicalPage] = (PVOID)((ULONG_PTR)EmsMemory + ARRAY_INDEX(PageEntry, PageTable) * EMS_PAGE_SIZE); return EMS_STATUS_SUCCESS; }
static UCHAR EmsFree(USHORT Handle) { PLIST_ENTRY Entry; PEMS_HANDLE HandleEntry = GetHandleRecord(Handle); if (!ValidateHandle(HandleEntry)) return EMS_STATUS_INVALID_HANDLE; for (Entry = HandleEntry->PageList.Flink; Entry != &HandleEntry->PageList; Entry = Entry->Flink) { PEMS_PAGE PageEntry = (PEMS_PAGE)CONTAINING_RECORD(Entry, EMS_PAGE, Entry); ULONG PageNumber = ARRAY_INDEX(PageEntry, PageTable); /* Free the page */ RtlClearBits(&AllocBitmap, PageNumber, 1); } InitializeListHead(&HandleEntry->PageList); if (Handle != EMS_SYSTEM_HANDLE) FreeHandle(HandleEntry); return EMS_STATUS_SUCCESS; }
// Returns a player number for either a number or name string // Returns -1 if invalid int ClientNumberFromString( gentity_t *to, const char *s ) { gclient_t *cl; int idnum; char cleanName[MAX_STRING_CHARS]; // numeric values could be slot numbers if ( StringIsInteger( s ) ) { idnum = atoi( s ); if ( idnum >= 0 && idnum < level.maxclients ) { cl = &level.clients[idnum]; if ( cl->pers.connected == CON_CONNECTED ) return idnum; } } // check for a name match for ( idnum=0, cl=level.clients; idnum<level.maxclients; idnum++, cl++ ) { if ( cl->pers.connected != CON_CONNECTED ) continue; Q_strncpyz( cleanName, cl->pers.netname, sizeof( cleanName ) ); Q_CleanStr( cleanName ); if ( !Q_stricmp( cleanName, s ) ) return idnum; } trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, to ), va( "print \"User %s is not on the server\n\"", s ) ); return -1; }
// If the client being followed leaves the game, or you just want to drop to free floating spectator mode void StopFollowing( gentity_t *ent ) { ent->client->ps.persistent[ PERS_TEAM ] = TEAM_SPECTATOR; ent->client->sess.sessionTeam = TEAM_SPECTATOR; ent->client->sess.spectatorState = SPECTATOR_FREE; ent->client->ps.pm_flags &= ~PMF_FOLLOW; ent->r.svFlags &= ~SVF_BOT; ent->client->ps.clientNum = ARRAY_INDEX( g_entities, ent ); }
// Traces down to find where an item should rest, instead of letting them free fall from their spawn points void FinishSpawningItem( gentity_t *ent ) { trace_t tr; vector3 dest; vector3 mins=ITEM_MINS, maxs=ITEM_MAXS; VectorCopy( &mins, &ent->r.mins ); VectorCopy( &maxs, &ent->r.maxs ); ent->s.eType = ET_ITEM; ent->s.modelindex = ARRAY_INDEX( bg_itemlist, ent->item ); // store item number in modelindex ent->s.modelindex2 = 0; // zero indicates this isn't a dropped item ent->r.contents = CONTENTS_TRIGGER; ent->touch = Touch_Item; // useing an item causes it to respawn ent->use = Use_Item; if ( ent->spawnflags & 1 ) { // suspended G_SetOrigin( ent, &ent->s.origin ); } else { // drop to floor VectorSet( &dest, ent->s.origin.x, ent->s.origin.y, ent->s.origin.z - 4096 ); trap->SV_Trace( &tr, &ent->s.origin, &ent->r.mins, &ent->r.maxs, &dest, ent->s.number, MASK_SOLID ); if ( tr.startsolid ) { trap->Print ("FinishSpawningItem: %s startsolid at %s\n", ent->classname, vtos(&ent->s.origin)); G_FreeEntity( ent ); return; } // allow to ride movers ent->s.groundEntityNum = tr.entityNum; G_SetOrigin( ent, &tr.endpos ); } // team slaves and targeted items aren't present at start if ( ( ent->flags & FL_TEAMSLAVE ) || ent->targetname ) { ent->s.eFlags |= EF_NODRAW; ent->r.contents = 0; return; } // powerups don't spawn in for a while if ( ent->item->giType == IT_POWERUP ) { float respawn; respawn = 45 + crandom() * 15; ent->s.eFlags |= EF_NODRAW; ent->r.contents = 0; ent->nextthink = level.time + (int)(respawn * 1000); ent->think = RespawnItem; return; } trap->SV_LinkEntity ((sharedEntity_t *)ent); }
/* Clear a bit in the used_frames bitmap */ static void _pmm_clear_frame(uint32 phys_addr) { assert(interrupts_enabled() == false); uint32 frame_index = phys_addr / PAGE_SIZE; uint32 index = ARRAY_INDEX(frame_index); assert (index <= nframes/32); uint32 offset = OFFSET_INTO_DWORD(frame_index); assert((used_frames[index] & (1 << offset)) != 0); used_frames[index] &= ~(1 << offset); }
static qboolean G_VoteAllready( gentity_t *ent, int numArgs, const char *arg1, const char *arg2 ) { if ( !level.warmupTime ) { trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), "print \"allready is only available during warmup.\n\"" ); return qfalse; } Com_sprintf( level.voteString, sizeof( level.voteString ), "%s", arg1 ); Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "%s", level.voteString ); Q_strncpyz( level.voteStringClean, level.voteString, sizeof( level.voteStringClean ) ); return qtrue; }
/* Test whether a bit is set in the used_frames bitmap */ static bool _pmm_test_frame(uint32 phys_addr) { assert(interrupts_enabled() == false); uint32 frame_index = phys_addr / PAGE_SIZE; uint32 index = ARRAY_INDEX(frame_index); assert (index <= nframes/32); uint32 offset = OFFSET_INTO_DWORD(frame_index); if ((used_frames[index] & (1 << offset)) != 0) return true; else return false; }
static qboolean G_VoteClientkick( gentity_t *ent, int numArgs, const char *arg1, const char *arg2 ) { int n = atoi ( arg2 ); if ( n < 0 || n >= MAX_CLIENTS ) { trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), va("print \"invalid client number %d.\n\"", n ) ); return qfalse; } if ( g_entities[n].client->pers.connected == CON_DISCONNECTED ) { trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), va("print \"there is no client with the client number %d.\n\"", n ) ); return qfalse; } Com_sprintf( level.voteString, sizeof(level.voteString ), "%s %s", arg1, arg2 ); Com_sprintf( level.voteDisplayString, sizeof(level.voteDisplayString), "%s %s", arg1, g_entities[n].client->pers.netname ); Q_strncpyz( level.voteStringClean, level.voteString, sizeof( level.voteStringClean ) ); return qtrue; }
static void Cmd_Noclip_f( gentity_t *ent ) { char *msg = NULL; ent->client->noclip = (qboolean)!ent->client->noclip; if ( !ent->client->noclip ) msg = "noclip OFF"; else msg = "noclip ON"; trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), va("print \"%s\"", msg)); }
static void Cmd_God_f( gentity_t *ent ) { char *msg = NULL; ent->flags ^= FL_GODMODE; if ( !(ent->flags & FL_GODMODE) ) msg = "godmode OFF"; else msg = "godmode ON"; trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), va("print \"%s\"", msg)); }
static void Cmd_Ready_f( gentity_t *ent ) { const char *publicMsg = NULL; gentity_t *e = NULL; int i = 0; ent->client->pers.ready = (qboolean)!ent->client->pers.ready; if ( ent->client->pers.ready ) { publicMsg = va( "cp \"%s\n^7is ready\"", ent->client->pers.netname ); trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), va( "cp \"^2You are ready\"" ) ); } else { publicMsg = va( "cp \"%s\n^3is NOT ready\"", ent->client->pers.netname ); trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), va( "cp \"^3You are NOT ready\"" ) ); } // send public message to everyone BUT this client, so they see their own message for ( i=0, e=g_entities; i<level.maxclients; i++, e++ ) { if ( e != ent ) trap->SV_GameSendServerCommand( i, publicMsg ); } }
static qboolean G_VoteNextmap( gentity_t *ent, int numArgs, const char *arg1, const char *arg2 ) { char s[MAX_CVAR_VALUE_STRING]; trap->Cvar_VariableStringBuffer( "nextmap", s, sizeof(s) ); if ( !*s ) { trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), "print \"nextmap not set.\n\"" ); return qfalse; } Com_sprintf( level.voteString, sizeof( level.voteString ), "vstr nextmap"); Q_strncpyz( level.voteDisplayString, level.voteString, sizeof( level.voteDisplayString ) ); Q_strncpyz( level.voteStringClean, level.voteString, sizeof( level.voteStringClean ) ); return qtrue; }
int Pickup_PersistantPowerup( gentity_t *ent, gentity_t *other ) { other->client->ps.stats[STAT_PERSISTENT_POWERUP] = ARRAY_INDEX( bg_itemlist, ent->item ); other->client->persistentPowerup = ent; switch( ent->item->giTag ) { case PW_GUARD: //QTZTODO: hmmm break; default: break; } return -1; }
static void SV_AreaEntities_r( worldSector_t *node, areaParms_t *ap ) { svEntity_t *check, *next; sharedEntity_t *gcheck; for ( check = node->entities ; check ; check = next ) { next = check->nextEntityInWorldSector; gcheck = SV_GEntityForSvEntity( check ); if ( gcheck->r.absmin.x > ap->maxs->x || gcheck->r.absmin.y > ap->maxs->y || gcheck->r.absmin.z > ap->maxs->z || gcheck->r.absmax.x < ap->mins->x || gcheck->r.absmax.y < ap->mins->y || gcheck->r.absmax.z < ap->mins->z ) { continue; } if ( ap->count == ap->maxcount ) { Com_Printf ("SV_AreaEntities: MAXCOUNT\n"); return; } ap->list[ap->count] = ARRAY_INDEX( sv.svEntities, check ); ap->count++; } if (node->axis == -1) { return; // terminal node } // recurse down both sides if ( ap->maxs->data[node->axis] > node->dist ) { SV_AreaEntities_r ( node->children[0], ap ); } if ( ap->mins->data[node->axis] < node->dist ) { SV_AreaEntities_r ( node->children[1], ap ); } }
// Spawns an item and tosses it forward gentity_t *LaunchItem( const gitem_t *item, vector3 *origin, vector3 *velocity ) { gentity_t *dropped; vector3 mins=ITEM_MINS, maxs=ITEM_MAXS; dropped = G_Spawn(); dropped->s.eType = ET_ITEM; dropped->s.modelindex = ARRAY_INDEX( bg_itemlist, item ); // store item number in modelindex dropped->s.modelindex2 = 1; // This is non-zero is it's a dropped item dropped->classname = item->classname; dropped->item = item; VectorCopy( &mins, &dropped->r.mins ); VectorCopy( &maxs, &dropped->r.maxs ); dropped->r.contents = CONTENTS_TRIGGER; dropped->touch = Touch_Item; G_SetOrigin( dropped, origin ); dropped->s.pos.trType = TR_GRAVITY; dropped->s.pos.trTime = level.time; VectorCopy( velocity, &dropped->s.pos.trDelta ); dropped->flags |= FL_BOUNCE_HALF; if ((level.gametype == GT_FLAGS || level.gametype == GT_TROJAN) && item->giType == IT_TEAM) { // Special case for CTF flags dropped->think = Team_DroppedFlagThink; dropped->nextthink = level.time + 30000; Team_CheckDroppedItem( dropped ); } else { // auto-remove after 30 seconds dropped->think = G_FreeEntity; dropped->nextthink = level.time + 30000; } dropped->flags = FL_DROPPED_ITEM; trap->SV_LinkEntity ((sharedEntity_t *)dropped); return dropped; }
static qboolean G_VoteMap( gentity_t *ent, int numArgs, const char *arg1, const char *arg2 ) { char s[MAX_CVAR_VALUE_STRING] = {0}, *mapName = NULL, *mapName2 = NULL; const char *arenaInfo; if ( numArgs < 3 ) {// didn't specify a map, show available maps Cmd_MapList_f( ent ); return qfalse; } if ( !G_DoesMapSupportGametype( arg2, level.gametype ) ) { trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), "print \"That map is not supported by this gametype\n\"" ); return qfalse; } //preserve the map rotation trap->Cvar_VariableStringBuffer( "nextmap", s, sizeof( s ) ); if ( *s ) Com_sprintf( level.voteString, sizeof( level.voteString ), "%s %s; set nextmap \"%s\"", arg1, arg2, s ); else Com_sprintf( level.voteString, sizeof( level.voteString ), "%s %s", arg1, arg2 ); arenaInfo = G_GetArenaInfoByMap(arg2); if ( arenaInfo ) { mapName = Info_ValueForKey(arenaInfo, "longname"); mapName2 = Info_ValueForKey(arenaInfo, "map"); } if ( !mapName || !mapName[0] ) mapName = "ERROR"; if ( !mapName2 || !mapName2[0] ) mapName2 = "ERROR"; Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "map %s (%s)", mapName, mapName2 ); Q_strncpyz( level.voteStringClean, level.voteString, sizeof( level.voteStringClean ) ); return qtrue; }
void G_InitGentity( gentity_t *e ) { e->inuse = qtrue; e->classname = "noclass"; e->s.number = ARRAY_INDEX( g_entities, e ); e->r.ownerNum = ENTITYNUM_NONE; }
int main(int argc, char *argv[]) { unsigned char signature[64]; array pubkeys, signatures; array_init(&pubkeys, sizeof(ecc_25519_work_t), 5); array_init(&signatures, sizeof(signature), 5); int min_good_signatures = 1; int opt; while ((opt = getopt(argc, argv, "s:p:n:")) != -1) { ecc_int256_t pubkey_packed; ecc_25519_work_t pubkey; switch (opt) { case 's': if (!parsehex(signature, optarg, 64)) { fprintf(stderr, "Error while reading signature %s\n", optarg); break; } if (!array_add(&signatures, signature, sizeof(signature))) { fprintf(stderr, "Error in array_add\n"); goto error_out; } break; case 'p': if (!parsehex(pubkey_packed.p, optarg, 32)) { fprintf(stderr, "Error while reading pubkey %s\n", optarg); break; } int ret; ret = ecc_25519_load_packed(&pubkey, &pubkey_packed); if (!ret || !ecdsa_is_valid_pubkey(&pubkey)) { fprintf(stderr, "Invalid pubkey %s\n", optarg); break; } if (!array_add(&pubkeys, &pubkey, sizeof(ecc_25519_work_t))) { fprintf(stderr, "Error in array_add\n"); goto error_out; } break; case 'n': min_good_signatures = atoi(optarg); } } if (optind >= argc) { fprintf(stderr, "Usage: %s [-s signature ...] [-p pubkey ...] [-n num] file\n", argv[0]); goto error_out; } ecc_int256_t hash; if (!sha256_file(argv[optind], hash.p)) { fprintf(stderr, "Error while hashing file\n"); goto error_out; } int good_signatures = 0; array_nub(&pubkeys); array_nub(&signatures); for (int i = 0; i < signatures.size; i++) { unsigned char *signature; ecdsa_verify_context ctx; signature = ARRAY_INDEX(signatures, i); ecdsa_verify_prepare(&ctx, &hash, signature); for (int i = 0; i < pubkeys.size; i++) { ecc_25519_work_t *pubkey; pubkey = ARRAY_INDEX(pubkeys, i); if (ecdsa_verify_with_pubkey(&ctx, pubkey)) { good_signatures++; array_rm(&pubkeys, i); break; } } } array_destroy(&pubkeys); array_destroy(&signatures); if (good_signatures >= min_good_signatures) return 0; return 1; error_out: array_destroy(&pubkeys); array_destroy(&signatures); return 1; }
static void Cmd_Drop_f( gentity_t *ent ) { char arg[128] = {0}; trap->Cmd_Argv( 1, arg, sizeof( arg ) ); if ( !Q_stricmp( arg, "flag" ) ) { powerup_t powerup = (ent->client->ps.persistent[PERS_TEAM]==TEAM_RED) ? PW_BLUEFLAG : PW_REDFLAG; if ( !g_allowFlagDrop->integer ) { trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), "print \"^3Not allowed to drop the flag\n\"" ); return; } if ( level.gametype != GT_FLAGS || (ent->client->ps.powerups[powerup] <= level.time) ) { trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), "print \"^3No flag to drop\n\"" ); return; } if ( ent->client->ps.powerups[ powerup ] > level.time ) { const gitem_t *item = BG_FindItemForPowerup( powerup ); gentity_t *drop = NULL; vector3 angs = { 0.0f, 0.0f, 0.0f }; AngleVectors( &ent->client->ps.viewangles, &angs, NULL, NULL ); drop = Drop_Item( ent, item, angs.yaw ); //Raz: speed caps drop->genericValue1 = trap->Milliseconds() - (int)ent->client->pers.teamState.flagsince; // drop->genericValue2 = ARRAY_INDEX( g_entities, ent ); // drop->genericValue2 |= (1<<5); // 6th bit indicates a client dropped it on purpose // drop->genericValue2 |= level.time << 6; ent->client->ps.powerups[powerup] = 0; } } else if ( !Q_stricmp( arg, "weapon" ) ) { weapon_t wp = (weapon_t)ent->client->ps.weapon, newWeap = -1; const gitem_t *item = NULL; gentity_t *drop = NULL; vector3 angs = { 0.0f, 0.0f, 0.0f }; int ammo, i=0; if ( !g_allowWeaponDrop->integer ) { trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), "print \"^3Not allowed to drop weapons\n\"" ); return; } if ( !(ent->client->ps.stats[STAT_WEAPONS] & (1<<wp)) || !ent->client->ps.ammo[wp] || wp == WP_QUANTIZER || wp <= WP_NONE || wp > WP_NUM_WEAPONS ) {// We don't have this weapon or ammo for it, or it's a 'weapon' that can't be dropped trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), "print \"^3Can't drop this weapon\n\"" ); return; } item = BG_FindItemForWeapon( wp ); if ( !ent->client->ps.ammo[wp] ) { trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), "print \"^3No ammo for this weapon\n\"" ); return; } else if ( ent->client->ps.ammo[wp] > item->quantity ) ammo = item->quantity; else ammo = ent->client->ps.ammo[wp]; AngleVectors( &ent->client->ps.viewangles, &angs, NULL, NULL ); drop = Drop_Item( ent, item, angs.yaw ); drop->count = ammo; ent->client->ps.ammo[wp] -= ammo; ent->client->ps.stats[STAT_WEAPONS] &= ~(1<<wp); #if 1 for ( i=0; i<WP_NUM_WEAPONS; i++ ) { if ((ent->client->ps.stats[STAT_WEAPONS] & (1 << i)) && i != WP_NONE) { //this one's good newWeap = (weapon_t)i; break; } } if (newWeap != -1) { ent->s.weapon = newWeap; ent->client->ps.weapon = newWeap; } else { ent->s.weapon = 0; ent->client->ps.weapon = 0; } G_AddEvent( ent, EV_NOAMMO, wp ); #else for ( i=wp+1; i != wp-1; i++ ) { if ( i == WP_NUM_WEAPONS ) i = WP_NONE+1; if ( ent->client->ps.stats[STAT_WEAPONS] & (1<<i) ) { ent->client->ps.weapon = i; break; } } G_AddEvent( ent, EV_NOAMMO, wp ); #endif drop->genericValue2 = ARRAY_INDEX( g_entities, ent ); drop->genericValue2 |= (1<<5); // 6th bit indicates a client dropped it on purpose drop->genericValue2 |= level.time << 6; } else if ( !Q_stricmp( arg, "powerup" ) ) { //RAZTODO: /drop powerup return; } }
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 ) ); }
void SetTeam( gentity_t *ent, char *s ) { int clientNum, specClient=0; team_t team, oldTeam; gclient_t *client = ent->client; spectatorState_t specState = SPECTATOR_NOT; // see what change is requested clientNum = ARRAY_INDEX( level.clients, client ); if ( !Q_stricmp( s, "scoreboard" ) || !Q_stricmp( s, "score" ) ) { team = TEAM_SPECTATOR; specState = SPECTATOR_SCOREBOARD; } else if ( !Q_stricmp( s, "follow1" ) ) { team = TEAM_SPECTATOR; specState = SPECTATOR_FOLLOW; specClient = -1; } else if ( !Q_stricmp( s, "follow2" ) ) { team = TEAM_SPECTATOR; specState = SPECTATOR_FOLLOW; specClient = -2; } else if ( !Q_stricmp( s, "spectator" ) || !Q_stricmp( s, "s" ) ) { team = TEAM_SPECTATOR; specState = SPECTATOR_FREE; } // if running a team game, assign player to one of the teams else if ( level.gametype >= GT_TEAMBLOOD ) { specState = SPECTATOR_NOT; if ( !Q_stricmp( s, "red" ) || !Q_stricmp( s, "r" ) ) team = TEAM_RED; else if ( !Q_stricmp( s, "blue" ) || !Q_stricmp( s, "b" ) ) team = TEAM_BLUE; else team = PickTeam( clientNum ); // pick the team with the least number of players if ( g_teamForceBalance->integer ) { int counts[TEAM_NUM_TEAMS]; counts[TEAM_BLUE] = TeamCount( clientNum, TEAM_BLUE ); counts[TEAM_RED] = TeamCount( clientNum, TEAM_RED ); // We allow a spread of two if ( team == TEAM_RED && counts[TEAM_RED] - counts[TEAM_BLUE] > 1 ) { trap->SV_GameSendServerCommand( clientNum, "cp \"Red team has too many players.\n\"" ); return; // ignore the request } if ( team == TEAM_BLUE && counts[TEAM_BLUE] - counts[TEAM_RED] > 1 ) { trap->SV_GameSendServerCommand( clientNum, "cp \"Blue team has too many players.\n\"" ); return; // ignore the request } // It's ok, the team we are switching to has less or same number of players } } else team = TEAM_FREE; // force them to spectators if there aren't any spots free // override decision if limiting the players if ( (level.gametype == GT_DUEL) && level.numNonSpectatorClients >= 2 ) team = TEAM_SPECTATOR; else if ( g_maxGameClients->integer > 0 && level.numNonSpectatorClients >= g_maxGameClients->integer ) team = TEAM_SPECTATOR; // decide if we will allow the change oldTeam = client->sess.sessionTeam; if ( team == oldTeam && team != TEAM_SPECTATOR ) return; // if the player was dead leave the body if ( client->ps.stats[STAT_HEALTH] <= 0 ) { CopyToBodyQue( ent ); } // he starts at 'base' client->pers.teamState.state = TEAM_BEGIN; if ( oldTeam != TEAM_SPECTATOR ) { // Kill him (makes sure he loses flags, etc) ent->flags &= ~FL_GODMODE; ent->client->ps.stats[STAT_HEALTH] = ent->health = 0; player_die( ent, ent, ent, 100000, MOD_SUICIDE ); } // they go to the end of the line for tournaments if ( team == TEAM_SPECTATOR && oldTeam != team ) AddTournamentQueue( client ); // exploit fix: with 3 (any odd amount?) players connected, one could /callvote map x followed by /team s to force the vote G_ClearVote( ent ); client->sess.sessionTeam = team; client->sess.spectatorState = specState; client->sess.spectatorClient = specClient; BroadcastTeamChange( client, oldTeam ); ClientUserinfoChanged( clientNum ); ClientBegin( clientNum ); }
static void Cmd_AddBot_f( gentity_t *ent ) { trap->SV_GameSendServerCommand( ARRAY_INDEX( g_entities, ent ), "print \"You can only add bots as the server\n\"" ); }