diff --git a/src/app.rs b/src/app.rs index b901e52..d585146 100644 --- a/src/app.rs +++ b/src/app.rs @@ -61,6 +61,8 @@ pub struct State { pub rhai: Engine, pub script_cache: parking_lot::RwLock>, pub runtime: Handle, + + pub speedgame: RwLock<(Option, Option)>, } impl State { @@ -129,6 +131,8 @@ impl State { .register_get("moderator", ExecutorState::moderator) .register_get("vip", ExecutorState::vip) .register_get("subscriber", ExecutorState::subscriber) + .register_get("speedgame_name", ExecutorState::speedgame_name) + .register_get("speedgame_category", ExecutorState::speedgame_category) .register_fn("get_username", ExecutorState::get_username::<&str>) .register_fn("get_user_id", ExecutorState::get_user_id::<&str>) .register_fn("get_channel_info", ExecutorState::get_channel_info::<&str>); @@ -156,6 +160,8 @@ impl State { rhai, script_cache: Default::default(), runtime, + + speedgame: RwLock::new((None, None)), }); // start web task diff --git a/src/app/rhai_tools.rs b/src/app/rhai_tools.rs index b809f2e..9de12ff 100644 --- a/src/app/rhai_tools.rs +++ b/src/app/rhai_tools.rs @@ -32,6 +32,9 @@ pub struct ExecutorState { pub vip: bool, /// Always false if this is a channel point reward event pub subscriber: bool, + + pub speedgame_name: Option, + pub speedgame_category: Option, } impl ExecutorState { @@ -64,6 +67,20 @@ impl ExecutorState { self.subscriber } + pub fn speedgame_name(&mut self) -> rhai::Dynamic { + match &self.speedgame_name { + Some(name) => name.clone().into(), + None => ().into(), + } + } + + pub fn speedgame_category(&mut self) -> rhai::Dynamic { + match &self.speedgame_category { + Some(cat) => cat.clone().into(), + None => ().into(), + } + } + pub fn get_username>(&mut self, id: S) -> rhai::Dynamic { self.state.runtime.block_on(self.state.get_user_from_id(id)) .ok() diff --git a/src/app/twitch.rs b/src/app/twitch.rs index 519a358..75c3697 100644 --- a/src/app/twitch.rs +++ b/src/app/twitch.rs @@ -106,6 +106,8 @@ async fn on_privmsg(state: Arc, event: &Message, message: &str) -> anyhow match &command.executor { CommandExecutor::Text(t) => { state.irc_queue.send(t.to_string()).ok(); } CommandExecutor::Rhai(t) => { + let (speedgame_name, speedgame_category) = state.speedgame.read().await.clone(); + let fn_state = ExecutorState { state: Arc::clone(&state), args, @@ -115,6 +117,8 @@ async fn on_privmsg(state: Arc, event: &Message, message: &str) -> anyhow moderator, vip, subscriber, + speedgame_name, + speedgame_category, }; crate::app::run_rhai(Arc::clone(&state), t, fn_state); } @@ -153,6 +157,8 @@ pub async fn handle_pubsub(state: Arc, event: WsMessage) -> anyhow::Resul None => return Ok(()), }; + let (speedgame_name, speedgame_category) = state.speedgame.read().await.clone(); + let args = redemption.user_input .map(|input| input.split(' ').map(ToOwned::to_owned).map(rhai::Dynamic::from).collect()) .unwrap_or_default(); @@ -165,6 +171,8 @@ pub async fn handle_pubsub(state: Arc, event: WsMessage) -> anyhow::Resul moderator: false, vip: false, subscriber: false, + speedgame_name, + speedgame_category, }; crate::app::run_rhai(Arc::clone(&state), &action.rhai, fn_state); diff --git a/src/app/web/route/livesplit.rs b/src/app/web/route/livesplit.rs index 4c0156c..f6f120f 100644 --- a/src/app/web/route/livesplit.rs +++ b/src/app/web/route/livesplit.rs @@ -21,7 +21,7 @@ pub fn livesplit_routes(state: Arc) -> BoxedFilter<(impl Reply, )> { struct RewardPauseInfo { id: &'static str, - games: &'static [(&'static str, isize)], + games: &'static [(&'static str, &'static str, isize)], } const REWARDS: &[RewardPauseInfo] = &[ @@ -30,7 +30,7 @@ const REWARDS: &[RewardPauseInfo] = &[ id: "8ac47f16-2396-4c2d-9c43-d30bd9074a4f", games: &[ // in RCT1, only enable after the third split - ("RollerCoaster Tycoon 1", 3), + ("RollerCoaster Tycoon 1", "All Base Scenarios (OpenRCT2)", 3), ], }, @@ -39,7 +39,7 @@ const REWARDS: &[RewardPauseInfo] = &[ id: "0da50268-3237-4832-9849-9baac518e4de", games: &[ // in RCT1, only enable after the third split - ("RollerCoaster Tycoon 1", 3), + ("RollerCoaster Tycoon 1", "All Base Scenarios (OpenRCT2)", 3), ], }, ]; @@ -61,12 +61,19 @@ async fn set_rewards_paused(state: Arc, data: LiveSplitBody, paused: bool let mut results = Vec::with_capacity(REWARDS.len()); for info in REWARDS { let is_paused = state.rewards_paused.read().await.get(info.id).copied(); - let should_apply = match info.games.iter().find(|(name, _)| data.run.game_name.as_deref().map(|run_name| run_name == *name).unwrap_or_default()) { - Some((_, split_idx)) => { + let should_apply = match info.games + .iter() + .find(|&&(name, category, _)| { + let game_matches = data.run.game_name.as_deref().map(|run_name| run_name == name).unwrap_or_default(); + let category_matches = data.run.category_name.as_deref().map(|cat_name| cat_name == category).unwrap_or_default(); + game_matches && category_matches + }) + { + Some(&(_, _, split_idx)) => { // if we're unpausing and the current split index is gte to the configured index for this game - if !paused && data.current_split_index >= *split_idx { + if !paused && data.current_split_index >= split_idx { true - } else if !paused && data.current_split_index < *split_idx { + } else if !paused && data.current_split_index < split_idx { false } else { true @@ -119,7 +126,17 @@ fn livesplit_route(state: Arc, path: &'static str, paused: bool) -> Boxed .and(warp::body::json()) .and_then(move |body: LiveSplitBody| { let state = Arc::clone(&state); - rewards_filter(state, body, paused) + async move { + let mut speedgame = state.speedgame.write().await; + if body.run.game_name.is_some() || body.run.category_name.is_some() { + *speedgame = ( + body.run.game_name.clone(), + body.run.category_name.clone(), + ); + } + drop(speedgame); + rewards_filter(state, body, paused).await + } }) .untuple_one() .map(|| warp::reply())