Skip to content

Commit

Permalink
Map exclusions
Browse files Browse the repository at this point in the history
- Support being able to change excluded map history count in popstate
- Support for being able to exclude maps in nominations
  • Loading branch information
Razer2015 committed Nov 21, 2022
1 parent c3cfa0b commit 145915f
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 17 deletions.
33 changes: 33 additions & 0 deletions battlefox/src/mapmanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ pub struct PopState {
pub pool: MapPool,
/// At `min_players` or more players, activate this pool. Unless a pool with even higher `min_players` exists.
pub min_players: usize,
/// The amount of map history to be excluded when generating a new vote
pub excluded_maps_count: Option<usize>,
}

impl PopState {
Expand Down Expand Up @@ -128,6 +130,9 @@ impl Plugin for MapManager {
// Err(MapListError::Rcon(r)) => return Err(r),
Err(mle) => error!("While starting up MapManager: {:?}. MapManager is *not* starting now!", mle),
}

// Populate the current map in the history
let _ = self.current_map(&bf4).await;
}

async fn event(self: Arc<Self>, bf4: Arc<Bf4Client>, event: Event) -> RconResult<()> {
Expand Down Expand Up @@ -393,6 +398,34 @@ impl MapManager {
Some(hist[0])
}
}

pub fn recent_maps(&self) -> Vec<Map> {
let hist = {
let inner = self.inner.lock().unwrap();
inner.map_history.clone()
};

let popstate = {
let lock = self.inner.lock().unwrap();
lock.pop_state.clone()
};

hist.iter()
.take(popstate.excluded_maps_count.unwrap_or(1))
.cloned()
.collect()
}

pub fn is_recently_played(&self, map: &Map) -> bool {
let recent_maps = self.recent_maps();

for m in recent_maps.iter() {
if map.eq(&m) {
return true;
}
};
false
}
}

impl std::fmt::Debug for MapManager {
Expand Down
12 changes: 12 additions & 0 deletions battlefox/src/mapmanager/pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,18 @@ impl MapPool {
.collect(),
}
}

/// Returns a new map pool which contains the same items, except with any with `map` removed.
pub fn without_many_vec(&self, maps: &Vec<Map>) -> Self {
Self {
pool: self
.pool
.iter()
.filter(|&mip| !maps.contains(&mip.map))
.cloned()
.collect(),
}
}
}

#[cfg(test)]
Expand Down
43 changes: 26 additions & 17 deletions battlefox/src/mapvote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,9 +217,9 @@ impl Inner {
}
}

fn set_up_new_vote(&mut self, n_options: usize, without: Option<Map>) {
fn set_up_new_vote(&mut self, n_options: usize, without: Option<Vec<Map>>) {
let pool = if let Some(without) = without {
self.popstate.pool.without(without)
self.popstate.pool.without_many_vec(&without)
} else {
self.popstate.pool.clone()
};
Expand Down Expand Up @@ -761,22 +761,31 @@ impl Mapvote {
if inner.popstate.pool.contains_map(map) {
// make sure this VIP hasn't exceeded their nomination limit this round.
if inner.vip_n_noms(&player) < self.config.max_noms_per_vip {
// phew, that was a lot of ifs...
info!("Player {} has nominated {} (vehicles: {:?})", player.name, map.Pretty(), vehicles);
inner.vip_nom(&player, map, vehicles);
info!("The new alternatives are {:?}.", inner.alternatives);

let announce = self.config.announce_nominator.unwrap_or(true);
if announce {
futures.push(bf4.say_lines(vec![
format!("Our beloved VIP {} has nominated {}!", &*player, map.Pretty()),
format!("{} has been added to the options, everyone can vote on it now <3", map.Pretty()),
], Visibility::All));
// Check if the nominated map has recently been played
if !self.mapman.is_recently_played(&map) {
// phew, that was a lot of ifs...
info!("Player {} has nominated {} (vehicles: {:?})", player.name, map.Pretty(), vehicles);
inner.vip_nom(&player, map, vehicles);
info!("The new alternatives are {:?}.", inner.alternatives);

let announce = self.config.announce_nominator.unwrap_or(true);
if announce {
futures.push(bf4.say_lines(vec![
format!("Our beloved VIP {} has nominated {}!", &*player, map.Pretty()),
format!("{} has been added to the options, everyone can vote on it now <3", map.Pretty()),
], Visibility::All));
}
else {
futures.push(bf4.say_lines(vec![
format!("{} has been added to the options, everyone can vote on it now <3", map.Pretty()),
], Visibility::All));
}
}
else {
futures.push(bf4.say_lines(vec![
format!("{} has been added to the options, everyone can vote on it now <3", map.Pretty()),
], Visibility::All));
format!("Apologies, {}, that map was just recently played.", &*player),
"Try nominating some other map".to_string(),
], player.get().into()));
}
} else {
futures.push(bf4.say_lines(vec![
Expand Down Expand Up @@ -999,7 +1008,7 @@ impl Mapvote {
}

async fn handle_round_over(&self, bf4: &Arc<Bf4Client>) {
let current_map = self.mapman.current_map(bf4).await;
let recent_maps = self.mapman.recent_maps();
self.broadcast_status(bf4).await; // send everyone the voting options.
// let's wait like 10 seconds because people might still vote in the end screen.
let _ = bf4.say(format!("Mapvote is still going for {}s! Hurry!", self.config.endscreen_votetime.as_secs()), Visibility::All).await;
Expand All @@ -1019,7 +1028,7 @@ impl Mapvote {
// get each player's votes, so we can simulate how the votes go later.
let assignment = inner.to_assignment();

inner.set_up_new_vote(self.config.n_options, current_map);
inner.set_up_new_vote(self.config.n_options, Some(recent_maps));
Some((profile, assignment, inner.anim_override_override.clone()))
} else {
None
Expand Down

0 comments on commit 145915f

Please sign in to comment.