add basic wii sports club support
All checks were successful
Build and Test / splatoon (push) Successful in 3m0s
Build and Test / splatoon-testfire (push) Successful in 3m7s
Build and Test / mario-tennis (push) Successful in 3m7s
Build and Test / terraria (push) Successful in 3m17s
Build and Test / minecraft-wiiu (push) Successful in 3m30s
Build and Test / wii-u-chat (push) Successful in 3m37s
Build and Test / sonic-transformed (push) Successful in 3m37s
Build and Test / fast-racing-neo (push) Successful in 3m37s
Build and Test / friends (push) Successful in 3m40s
Build and Test / super-mario-maker (push) Successful in 3m43s
Build and Test / puyopuyo (push) Successful in 3m49s
Build and Test / wii-sports-club (push) Successful in 3m59s

This commit is contained in:
red binder 2026-08-10 20:48:31 +02:00
commit d4ede0ca83
24 changed files with 152 additions and 32 deletions

View file

@ -27,8 +27,7 @@ wii-sports-club:
include-in-checkall: true
features:
- prudpv1
- third-notif-param
- v3-8-15
- v3-4-7
- match-making
- ranking
- datastore

View file

@ -18,6 +18,7 @@ database-support = []
nx = []
third-notif-param = []
v3-3-2 = []
v3-4-7 = ["v3-3-2"]
v3-4-0 = ["v3-3-2", "third-notif-param"]
v3-5-0 = ["v3-4-0"]
v3-8-13 = ["v3-5-0"]

View file

@ -17,6 +17,7 @@ nx = []
third-notif-param = []
friends = []
v3-3-2 = []
v3-4-7 = ["v3-3-2"]
v3-4-0 = ["v3-3-2", "third-notif-param"]
v3-5-0 = ["v3-4-0"]
v3-8-13 = ["v3-5-0"]

View file

@ -17,6 +17,7 @@ nx = []
third-notif-param = []
friends = []
v3-3-2 = []
v3-4-7 = ["v3-3-2"]
v3-4-0 = ["v3-3-2", "third-notif-param"]
v3-5-0 = ["v3-4-0"]
v3-8-13 = ["v3-5-0"]

View file

@ -16,6 +16,7 @@ nx = []
third-notif-param = []
friends = []
v3-3-2 = []
v3-4-7 = ["v3-3-2"]
v3-4-0 = ["v3-3-2", "third-notif-param"]
v3-5-0 = ["v3-4-0"]
v3-8-13 = ["v3-5-0"]

View file

@ -14,6 +14,7 @@ tracing = "0.1.44"
[features]
third-notif-param = []
v3-3-2 = []
v3-4-7 = ["v3-3-2"]
v3-4-0 = ["v3-3-2", "third-notif-param"]
v3-5-0 = ["v3-4-0"]
v3-8-13 = ["v3-5-0"]

View file

@ -59,6 +59,23 @@ cfg_if! {
pub user_password_enabled: bool,
pub system_password_enabled: bool,
}
} else if #[cfg(feature = "v3-4-7")] {
#[derive(RmcSerialize, Debug, Clone, Default, PartialEq)]
#[rmc_struct(0)]
pub struct MatchmakeSession {
//inherits from
#[extends]
pub gathering: Gathering,
pub gamemode: u32,
pub attributes: Vec<u32>,
pub open_participation: bool,
pub matchmake_system_type: u32,
pub application_buffer: Vec<u8>,
pub participation_count: u32,
pub progress_score: u8,
pub session_key: Vec<u8>,
}
} else {
#[derive(RmcSerialize, Debug, Clone, Default, PartialEq)]
#[rmc_struct(0)]
@ -98,6 +115,21 @@ cfg_if! {
pub exclude_system_password_set: bool,
pub refer_gid: u32,
}
} else if #[cfg(feature = "v3-4-7")] {
#[derive(RmcSerialize, Debug, Clone)]
#[rmc_struct(0)]
pub struct MatchmakeSessionSearchCriteria {
pub attribs: Vec<String>,
pub game_mode: String,
pub minimum_participants: String,
pub maximum_participants: String,
pub matchmake_system_type: String,
pub vacant_only: bool,
pub exclude_locked: bool,
pub exclude_non_host_pid: bool,
pub selection_method: u32,
pub vacant_participants: u16,
}
} else {
#[derive(RmcSerialize, Debug, Clone)]
#[rmc_struct(3)]
@ -213,6 +245,8 @@ pub trait Matchmake {
async fn get_detailed_participants(&self, gid: u32) -> Result<Vec<ParticipantDetails>, ErrorCode>;
#[method_id(21)]
async fn find_by_single_id(&self, gid: u32) -> Result<(bool, Any<Gathering>), ErrorCode>;
#[method_id(40)]
async fn update_session_host_v1(&self, gid: u32) -> Result<(), ErrorCode>;
#[method_id(41)]
async fn get_session_urls(&self, gid: u32) -> Result<Vec<StationUrl>, ErrorCode>;
#[method_id(42)]

View file

@ -15,6 +15,7 @@ database-support = []
nx = []
third-notif-param = []
v3-3-2 = []
v3-4-7 = ["v3-3-2"]
v3-4-0 = ["v3-3-2", "third-notif-param"]
v3-5-0 = ["v3-4-0"]
v3-8-13 = ["v3-5-0"]

View file

@ -17,6 +17,7 @@ database-support = []
nx = []
third-notif-param = []
v3-3-2 = []
v3-4-7 = ["v3-3-2"]
v3-4-0 = ["v3-3-2", "third-notif-param"]
v3-5-0 = ["v3-4-0"]
v3-8-13 = ["v3-5-0"]

View file

@ -23,6 +23,7 @@ nx = []
third-notif-param = []
v3-3-2 = []
v3-4-0 = ["v3-3-2", "third-notif-param"]
v3-4-7 = ["v3-3-2"]
v3-5-0 = ["v3-4-0"]
v3-8-13 = ["v3-5-0"]
v3-8-15 = ["v3-5-0"]

View file

@ -24,6 +24,7 @@ nx = []
third-notif-param = []
v3-3-2 = []
v3-4-0 = ["v3-3-2", "third-notif-param", "rmc_struct_header"]
v3-4-7 = ["v3-3-2"]
v3-5-0 = ["v3-4-0"]
v3-8-13 = ["v3-5-0"]
v3-8-15 = ["v3-5-0"]

View file

@ -26,6 +26,7 @@ big_pid = []
third-notif-param = []
v3-3-2 = []
v3-4-0 = ["v3-3-2", "third-notif-param", "rmc_struct_header"]
v3-4-7 = ["v3-3-2"]
v3-5-0 = ["v3-4-0"]
v3-8-13 = ["v3-5-0"]
v3-8-15 = ["v3-5-0"]

View file

@ -21,6 +21,7 @@ nx = []
third-notif-param = []
v3-3-2 = []
v3-4-0 = ["v3-3-2", "third-notif-param"]
v3-4-7 = ["v3-3-2"]
v3-5-0 = ["v3-4-0"]
v3-8-13 = ["v3-5-0"]
v3-8-15 = ["v3-5-0"]

View file

@ -30,6 +30,7 @@ nx = []
third-notif-param = []
v3-3-2 = []
v3-4-0 = ["v3-3-2", "third-notif-param"]
v3-4-7 = ["v3-3-2"]
v3-5-0 = ["v3-4-0"]
v3-8-13 = ["v3-5-0"]
v3-8-15 = ["v3-5-0"]

View file

@ -31,6 +31,7 @@ big_pid = []
third-notif-param = []
v3-3-2 = []
v3-4-0 = ["v3-3-2", "third-notif-param", "rmc_struct_header"]
v3-4-7 = ["v3-3-2"]
v3-5-0 = ["v3-4-0"]
v3-8-13 = ["v3-5-0"]
v3-8-15 = ["v3-5-0"]

View file

@ -26,6 +26,7 @@ big_pid = []
third-notif-param = []
v3-3-2 = []
v3-4-0 = ["v3-3-2", "third-notif-param", "rmc_struct_header"]
v3-4-7 = ["v3-3-2"]
v3-5-0 = ["v3-4-0"]
v3-8-13 = ["v3-5-0"]
v3-8-15 = ["v3-5-0"]
@ -33,7 +34,7 @@ v3-10-22 = ["v3-8-15"]
v4-3-11 = ["v3-8-15"]
nx = ["big_pid"]
splatoon = ["v3-5-0"]
datastore = ["database-support", "v3-8-15"]
datastore = ["database-support"]
database-support = []
[lints]

View file

@ -70,7 +70,7 @@ impl MatchmakeManager {
}
async fn garbage_collect(&self) {
info!("running rnex garbage collector over all sessions and users");
println!("running rnex garbage collector over all sessions and users");
let mut idx = 0;
@ -121,24 +121,35 @@ impl MatchmakeManager {
) -> Result<Vec<Arc<Mutex<ExtendedMatchmakeSession>>>, ErrorCode> {
let sessions = self.sessions.read().await;
let mut list = Vec::with_capacity(sessions.len());
for session in sessions.values() {
for (key, session) in sessions.iter() {
let inner_session = session.lock().await;
if !inner_session.is_joinable() {
println!("dropped session {:?}: not joinable", key);
continue;
}
let mut bool_matched_criteria = false;
for criteria in criterias {
if inner_session.matches_criteria(criteria)? {
match inner_session.matches_criteria(criteria) {
Ok(true) => {
bool_matched_criteria = true;
}
Ok(false) => {}
Err(e) => {
println!("dropped session {:?}: criteria check returned error {:?}", key, e);
return Err(e);
}
}
}
if bool_matched_criteria {
println!("matched session: {:?}", session);
list.push(session.clone());
} else {
println!("dropped session {:?}: did not match any criteria", key);
}
}
@ -357,11 +368,23 @@ impl ExtendedMatchmakeSession {
}
pub fn has_min_active_players(&self) -> bool {
self.connected_players
let required = self.session.gathering.minimum_participants as usize;
let active_count = self
.connected_players
.iter()
.filter(|v| v.upgrade().is_some())
.count()
>= self.session.gathering.minimum_participants as _
.filter_map(|v| v.upgrade())
.filter(|player| {
true
})
.count();
println!(
"[DEBUG] has_min_active_players: active_count={}, required={}",
active_count, required
);
active_count >= required
}
#[inline]
@ -372,20 +395,53 @@ impl ExtendedMatchmakeSession {
#[inline]
pub fn is_reachable(&self) -> bool {
self.get_active_players()
.any(|v| v.base.pid == self.session.gathering.host_pid)
&& (if self.session.gathering.flags & PERSISTENT_GATHERING != 0 {
if self.has_min_active_players() {
let host_pid = self.session.gathering.host_pid;
let host_active = self
.get_active_players()
.any(|v| v.base.pid == host_pid);
let is_persistent = (self.session.gathering.flags & PERSISTENT_GATHERING) != 0;
let has_min_players = self.has_min_active_players();
let open_part = self.session.open_participation;
#[cfg(feature = "v3-4-7")]
let persistent_check_passed = if is_persistent || open_part {
has_min_players || open_part
} else {
has_min_players
};
#[cfg(not(feature = "v3-4-7"))]
let persistent_check_passed = (if is_persistent {
if has_min_players {
true
} else {
self.session.open_participation
open_part
}
} else {
self.has_min_active_players()
}) & self.has_min_active_players()
has_min_players
}) & has_min_players;
let result = host_active && persistent_check_passed;
println!(
"[DEBUG] is_reachable: host_active={}, host_pid={}, is_persistent={}, has_min_players={}, open_participation={}, persistent_check_passed={}, final_result={}",
host_active,
host_pid,
is_persistent,
has_min_players,
open_part,
persistent_check_passed,
result
);
result
}
#[inline]
pub fn is_joinable(&self) -> bool {
#[cfg(feature = "v3-4-7")]
let is_open = true;
#[cfg(not(feature = "splatoon"))]
let is_open = self.session.open_participation;
#[cfg(feature = "splatoon")]

View file

@ -24,7 +24,7 @@ use rnex_util::{
};
use tokio::sync::Mutex;
use tracing::info;
use rnex_mm_protos::matchmake::gathering_flags;
use crate::matchmake::{ExtendedMatchmakeSession, MatchmakeManager};
/*cfg_if! {
@ -108,7 +108,7 @@ impl MatchmakeExtension for MatchmakeUser {
browse_criteria: MatchmakeSessionSearchCriteria,
result_range: ResultsRange,
) -> Result<Vec<Any<Gathering>>, ErrorCode> {
info!("browsing matchmake sessions with criteria: {:?}", browse_criteria);
println!("browsing matchmake sessions with criteria: {:?}", browse_criteria);
let results = self
.matchmake_manager
@ -116,20 +116,20 @@ impl MatchmakeExtension for MatchmakeUser {
.await?;
let mm_list = result_range.make_from_list(&results[..]);
info!("filtered mm_list count: {}", mm_list.len());
println!("filtered mm_list count: {}", mm_list.len());
let mut list = Vec::with_capacity(mm_list.len());
for (index, mm_sess) in mm_list.iter().enumerate() {
let mm_sess_guard = mm_sess.lock().await;
info!("processing session [{}]: {:?}", index, *mm_sess_guard);
println!("processing session [{}]: {:?}", index, *mm_sess_guard);
let gathering_any = Any::new(&mm_sess_guard.session).expect("type error");
list.push(gathering_any);
}
info!("successfully collected {} sessions into output list", list.len());
println!("successfully collected {} sessions into output list", list.len());
Ok(list)
}
@ -153,7 +153,7 @@ impl MatchmakeExtension for MatchmakeUser {
&self,
create_session_param: CreateMatchmakeSessionParam,
) -> Result<MatchmakeSession, ErrorCode> {
info!("session paramater: {:?}", create_session_param);
println!("session paramater: {:?}", create_session_param);
let gid = self.matchmake_manager.next_gid();
@ -269,7 +269,7 @@ impl MatchmakeExtension for MatchmakeUser {
&self,
param: AutoMatchmakeParam,
) -> Result<MatchmakeSession, ErrorCode> {
info!("autommparam: {:?}", param);
println!("autommparam: {:?}", param);
let mut joining_players = vec![self.this.clone()];
@ -315,7 +315,7 @@ impl MatchmakeExtension for MatchmakeUser {
drop(sessions);
info!("making new session!");
println!("making new session!");
let AutoMatchmakeParam {
join_message,
@ -366,7 +366,7 @@ impl MatchmakeExtension for MatchmakeUser {
gathering: Any<Gathering>,
message: String,
) -> Result<(u32, Vec<u8>), ErrorCode> {
info!("gathering: {:?}", gathering);
println!("gathering: {:?}", gathering);
let session: MatchmakeSession = gathering.try_get_as()?;
let session = self
@ -485,7 +485,7 @@ impl MatchmakeExtension for MatchmakeUser {
) -> Result<Any<Gathering>, ErrorCode> {
let session: MatchmakeSession = gathering.try_get_as()?;
info!("automm criteria: {:?}", criteria);
println!("automm criteria: {:?}", criteria);
let session = self
.auto_matchmake_with_param_postpone(AutoMatchmakeParam {
@ -654,6 +654,17 @@ impl Matchmake for MatchmakeUser {
Ok(participant_details)
}
async fn update_session_host_v1(&self, gid: u32) -> Result<(), ErrorCode> {
let should_migrate_owner = {
let session = self.matchmake_manager.get_session(gid).await?;
let session = session.lock().await;
(session.session.gathering.flags & gathering_flags::PARTICIPANTS_CHANGE_OWNER) != 0
};
self.update_session_host(gid, should_migrate_owner).await
}
}
impl MatchmakeExt for MatchmakeUser {

View file

@ -11,6 +11,7 @@ big_pid = []
third-notif-param = []
v3-3-2 = []
v3-4-0 = ["v3-3-2", "third-notif-param", "rmc_struct_header"]
v3-4-7 = ["v3-3-2"]
v3-5-0 = ["v3-4-0"]
v3-8-13 = ["v3-5-0"]
v3-8-15 = ["v3-5-0"]

View file

@ -11,6 +11,7 @@ big_pid = []
third-notif-param = []
v3-3-2 = []
v3-4-0 = ["v3-3-2", "third-notif-param", "rmc_struct_header"]
v3-4-7 = ["v3-3-2"]
v3-5-0 = ["v3-4-0"]
v3-8-13 = ["v3-5-0"]
v3-8-15 = ["v3-5-0"]

View file

@ -24,6 +24,7 @@ nx = []
third-notif-param = []
v3-3-2 = []
v3-4-0 = ["v3-3-2", "third-notif-param"]
v3-4-7 = ["v3-3-2"]
v3-5-0 = ["v3-4-0"]
v3-8-13 = ["v3-5-0"]
v3-8-15 = ["v3-5-0"]

View file

@ -11,6 +11,7 @@ nx = []
third-notif-param = []
v3-3-2 = []
v3-4-0 = ["v3-3-2", "third-notif-param"]
v3-4-7 = ["v3-3-2"]
v3-5-0 = ["v3-4-0"]
v3-8-13 = ["v3-5-0"]
v3-8-15 = ["v3-5-0"]

View file

@ -25,6 +25,7 @@ nx = []
third-notif-param = []
v3-3-2 = []
v3-4-0 = ["v3-3-2", "third-notif-param"]
v3-4-7 = ["v3-3-2"]
v3-5-0 = ["v3-4-0"]
v3-8-13 = ["v3-5-0"]
v3-8-15 = ["v3-5-0"]

View file

@ -20,6 +20,7 @@ big_pid = []
third-notif-param = []
v3-3-2 = []
v3-4-0 = ["v3-3-2", "third-notif-param", "rmc_struct_header"]
v3-4-7 = ["v3-3-2"]
v3-5-0 = ["v3-4-0"]
v3-8-13 = ["v3-5-0"]
v3-8-15 = ["v3-5-0"]