From b3f2dd8e78c366e1dd1ecae20fd02e12971b5a94 Mon Sep 17 00:00:00 2001 From: Maple Nebel Date: Wed, 8 Jul 2026 19:43:09 +0200 Subject: [PATCH] mc wii u matchmaking functions --- rnex-core/src/nex/matchmake.rs | 32 +++++++ rnex-core/src/nex/user.rs | 91 +++++++++++-------- .../src/rmc/protocols/matchmake_extension.rs | 14 +++ rnex-core/src/rmc/structures/resultsrange.rs | 16 +++- 4 files changed, 113 insertions(+), 40 deletions(-) diff --git a/rnex-core/src/nex/matchmake.rs b/rnex-core/src/nex/matchmake.rs index ef699e1..c42e3c0 100644 --- a/rnex-core/src/nex/matchmake.rs +++ b/rnex-core/src/nex/matchmake.rs @@ -100,6 +100,38 @@ impl MatchmakeManager { } }); } + + // this could be far more efficient but it is INCREDIBLY difficult to iterate over something + // asyncronously propperly + pub async fn search_by_criteria( + &self, + criterias: &[MatchmakeSessionSearchCriteria], + ) -> Result>>, ErrorCode> { + let sessions = self.sessions.read().await; + let mut list = Vec::with_capacity(sessions.len()); + for session in sessions.values() { + let inner_session = session.lock().await; + if !inner_session.is_joinable() { + continue; + } + + let mut bool_matched_criteria = false; + + for criteria in criterias { + if inner_session.matches_criteria(criteria)? { + bool_matched_criteria = true; + } + } + + if bool_matched_criteria { + println!("matched session: {:?}", session); + list.push(session.clone()); + } + } + + drop(sessions); + Ok(list) + } } #[derive(Default, Debug)] diff --git a/rnex-core/src/nex/user.rs b/rnex-core/src/nex/user.rs index 7441e7d..dceed5d 100644 --- a/rnex-core/src/nex/user.rs +++ b/rnex-core/src/nex/user.rs @@ -72,6 +72,8 @@ use rnex_core::{ use std::sync::{Arc, Weak}; use tokio::sync::{Mutex, RwLock}; +use crate::rmc::structures::resultsrange::ResultsRange; + cfg_if! { if #[cfg(feature = "datastore")] { use rnex_core::rmc::protocols::datastore::{DataStore, RawDataStore, RawDataStoreInfo, RemoteDataStore}; @@ -216,6 +218,27 @@ impl MatchmakeExtension for User { Ok(()) } + async fn browse_matchmake_session( + &self, + browse_criteria: MatchmakeSessionSearchCriteria, + result_range: ResultsRange, + ) -> Result>, ErrorCode> { + let results = self + .matchmake_manager + .search_by_criteria(&[browse_criteria]) + .await?; + let mm_list = result_range.make_from_list(&results[..]); + + let mut list = Vec::with_capacity(mm_list.len()); + + for mm_sess in mm_list { + let mm_sess = mm_sess.lock().await; + list.push(Any::new(&mm_sess.session).expect("type error")); + } + + Ok(list) + } + async fn get_playing_session(&self, _pids: Vec) -> Result, ErrorCode> { Ok(Vec::new()) } @@ -376,45 +399,18 @@ impl MatchmakeExtension for User { drop(users); - let sessions = self.matchmake_manager.sessions.read().await; - for session in sessions.values() { + let sessions = self + .matchmake_manager + .search_by_criteria(¶m.search_criteria[..]) + .await?; + + if let Some(session) = sessions.get(0) { let mut session = session.lock().await; - if !session.is_joinable() { - continue; - } - println!("checking session!"); + session + .add_players(&joining_players, param.join_message) + .await; - let mut bool_matched_criteria = false; - - for criteria in ¶m.search_criteria { - if session.matches_criteria(criteria)? { - bool_matched_criteria = true; - } - } - - if bool_matched_criteria { - println!("matched session: {:?}", session); - let is_joinable_by_all = join_all( - joining_players - .iter() - .filter_map(|f| f.upgrade()) - .map(|v| session.is_joinable_by(v)), - ) - .await - .iter() - .copied() - .fold(true, |a, b| a && b); - if is_joinable_by_all { - warn!( - "tripped unreachable host detection for one of the users who were trying to join" - ); - } - session - .add_players(&joining_players, param.join_message) - .await; - - return Ok(session.session.clone()); - } + return Ok(session.session.clone()); } drop(sessions); @@ -546,6 +542,27 @@ impl MatchmakeExtension for User { Ok(()) } + async fn update_application_buffer( + &self, + gid: u32, + application_buffer: Vec, + ) -> Result<(), ErrorCode> { + let session = self.matchmake_manager.get_session(gid).await?; + + let mut session = session.lock().await; + + if session.session.gathering.host_pid == self.pid { + return Err(ErrorCode::RendezVous_PermissionDenied); + } + if session.session.gathering.owner_pid == self.pid { + return Err(ErrorCode::RendezVous_PermissionDenied); + } + + session.session.application_buffer = application_buffer; + + Ok(()) + } + async fn join_matchmake_session_ex( &self, gid: u32, diff --git a/rnex-core/src/rmc/protocols/matchmake_extension.rs b/rnex-core/src/rmc/protocols/matchmake_extension.rs index 2d745ba..effb0a7 100644 --- a/rnex-core/src/rmc/protocols/matchmake_extension.rs +++ b/rnex-core/src/rmc/protocols/matchmake_extension.rs @@ -7,6 +7,7 @@ use rnex_core::rmc::structures::matchmake::{ use crate::rmc::protocols::notifications::NotificationEvent; use crate::rmc::structures::any::Any; use crate::rmc::structures::matchmake::{Gathering, MatchmakeSessionSearchCriteria}; +use crate::rmc::structures::resultsrange::ResultsRange; #[rmc_proto(109)] pub trait MatchmakeExtension { @@ -15,6 +16,13 @@ pub trait MatchmakeExtension { #[method_id(2)] async fn open_participation(&self, gid: u32) -> Result<(), ErrorCode>; + + #[method_id(4)] + async fn browse_matchmake_session( + &self, + borwse_criteria: MatchmakeSessionSearchCriteria, + result_range: ResultsRange, + ) -> Result>, ErrorCode>; #[method_id(6)] async fn create_matchmake_session( &self, @@ -36,6 +44,12 @@ pub trait MatchmakeExtension { &self, ty: i32, ) -> Result, ErrorCode>; + #[method_id(11)] + async fn update_application_buffer( + &self, + gid: u32, + application_buffer: Vec, + ) -> Result<(), ErrorCode>; #[method_id(15)] async fn auto_matchmake_with_search_criteria_postpone( &self, diff --git a/rnex-core/src/rmc/structures/resultsrange.rs b/rnex-core/src/rmc/structures/resultsrange.rs index ba62e49..0fbaced 100644 --- a/rnex-core/src/rmc/structures/resultsrange.rs +++ b/rnex-core/src/rmc/structures/resultsrange.rs @@ -2,7 +2,17 @@ use macros::RmcSerialize; #[derive(RmcSerialize, Debug, Default, Clone)] #[rmc_struct(0)] -pub struct ResultsRange{ +pub struct ResultsRange { pub offset: u32, - pub size: u32 -} \ No newline at end of file + pub size: u32, +} + +impl ResultsRange { + pub fn make_from_list(&self, list: &[T]) -> Vec { + let end = usize::max(list.len(), self.offset as usize + self.size as usize); + + list.get(self.offset as usize..end) + .unwrap_or_default() + .into() + } +}