add wii u chat functions
All checks were successful
Build and Test / wii-u-chat (push) Successful in 8m1s
Build and Test / splatoon (push) Successful in 8m1s
Build and Test / friends (push) Successful in 8m7s
Build and Test / super-mario-maker (push) Successful in 12m38s

This commit is contained in:
Maple 2026-04-28 00:13:07 +02:00
commit c828d3b973
7 changed files with 297 additions and 203 deletions

View file

@ -44,7 +44,8 @@ guest_login = []
friends = ["guest_login", "database-support"] friends = ["guest_login", "database-support"]
big_pid = [] big_pid = []
v3-3-2 = [] v3-3-2 = []
v3-8-15 = ["rmc_struct_header", "v3-3-2"] v3-5-0 = ["v3-3-2"]
v3-8-15 = ["rmc_struct_header", "v3-5-0"]
v4-3-11 = ["v3-8-15"] v4-3-11 = ["v3-8-15"]
nx = ["big_pid"] nx = ["big_pid"]
datastore = ["database-support", "v3-8-15", "dep:aws-sdk-s3", "dep:aws-config"] datastore = ["database-support", "v3-8-15", "dep:aws-sdk-s3", "dep:aws-config"]

View file

@ -1,127 +0,0 @@
#![allow(dead_code)]
#![allow(async_fn_in_trait)]
//#![warn(missing_docs)]
//! # Splatoon RNEX server
//!
//! This server still includes the code for rnex itself as this is the first rnex server and thus
//! also the first and only current usage of rnex, expect this and rnex to be split into seperate
//! repos soon.
extern crate self as rust_nex;
use once_cell::sync::Lazy;
use std::hint::black_box;
mod prudp;
pub mod rmc;
//mod protocols;
mod grpc;
mod kerberos;
mod nex;
mod result;
mod versions;
pub mod reggie;
pub mod util;
pub mod common;
pub mod config{
pub const FEATURE_HAS_STRUCT_HEADER: bool = cfg!(feature = "rmc_struct_header");
}
use std::io::Cursor;
use std::ops::Deref;
use rnex_core::kerberos::KerberosDateTime;
use rnex_core::rmc::structures::matchmake::{AutoMatchmakeParam, Gathering, MatchmakeParam, MatchmakeSession, MatchmakeSessionSearchCriteria};
use rnex_core::rmc::structures::RmcSerialize;
use rnex_core::rmc::structures::variant::Variant;
static DUMMY: Lazy<AutoMatchmakeParam> = Lazy::new(|| AutoMatchmakeParam{
additional_participants: vec![1,2,3,4],
auto_matchmake_option: 10,
gid_for_participation_check: 9,
join_message: "hi".to_string(),
participation_count: 32,
target_gids: vec![45,2,51,1,1,1,1],
search_criteria: vec![MatchmakeSessionSearchCriteria{
attribs: vec!["hi".to_string(), "ig".to_string(), "gotta put data here".to_string()],
exclude_locked: true,
exclude_non_host_pid: false,
exclude_system_password_set: true,
exclude_user_password_set: false,
game_mode: "some gamemode".to_string(),
matchmake_param: MatchmakeParam{
params: vec![
("SR".to_string(), Variant::Bool(true)),
("SR2".to_string(), Variant::Double(1.0)),
("SR3".to_string(), Variant::SInt64(42)),
("SR4".to_string(), Variant::String("test".to_string()))
]
},
matchmake_system_type: "some type".to_string(),
maximum_participants: "???".to_string(),
minimum_participants: "-99".to_string(),
refer_gid: 123,
selection_method: 9999999,
vacant_only: true,
vacant_participants: 1000
}],
matchmake_session: MatchmakeSession{
refer_gid: 10,
matchmake_system_type: 139,
matchmake_param: MatchmakeParam{
params: vec![
("QSR".to_string(), Variant::Bool(false)),
("SRQ2".to_string(), Variant::Double(1.1)),
("SQR3".to_string(), Variant::SInt64(422)),
("SDR4".to_string(), Variant::String("tetst".to_string()))
]
},
participation_count: 99,
application_buffer: vec![1,2,3,4,5,6,7,8,9],
attributes: vec![10,20,99,100000],
datetime: KerberosDateTime::now(),
gamemode: 111,
open_participation: false,
option0: 100,
progress_score: 1,
system_password_enabled: false,
user_password: "aaa".to_string(),
session_key: vec![91,123,5,2,1,2,4,124,4],
user_password_enabled: false,
gathering: Gathering{
minimum_participants: 1,
maximum_participants: 12,
description: "aaargh".to_string(),
flags: 100,
host_pid: 999999919,
owner_pid: 138830,
participant_policy: 1,
policy_argument: 99837,
self_gid: 129,
state: 1389488
}
}
});
static DUMMY_SER: Lazy<Vec<u8>> = Lazy::new(|| serialize_to_vec(DUMMY.deref()));
fn serialize_to_vec(r: &impl RmcSerialize) -> Vec<u8>{
let vec = r.to_data();
vec.unwrap()
}
fn read_struct<T: RmcSerialize>(r: &[u8]) -> T{
T::deserialize(&mut Cursor::new(r)).unwrap()
}
fn main(){
for _ in 0..10000000 {
let v = serialize_to_vec(black_box(DUMMY.deref()));
let u = read_struct::<AutoMatchmakeParam>(black_box(DUMMY_SER.deref().as_slice()));
black_box(v);
black_box(u);
}
}

View file

@ -1,12 +1,12 @@
use crate::nex::user::User;
use crate::rmc::protocols::notifications::{NotificationEvent, RemoteNotification};
use log::info; use log::info;
use rand::random; use rand::random;
use rnex_core::PID; use rnex_core::PID;
use rnex_core::kerberos::KerberosDateTime; use rnex_core::kerberos::KerberosDateTime;
use rnex_core::nex::user::User;
use rnex_core::rmc::protocols::notifications::notification_types::{ use rnex_core::rmc::protocols::notifications::notification_types::{
HOST_CHANGED, OWNERSHIP_CHANGED, HOST_CHANGED, OWNERSHIP_CHANGED,
}; };
use rnex_core::rmc::protocols::notifications::{NotificationEvent, RemoteNotification};
use rnex_core::rmc::response::ErrorCode; use rnex_core::rmc::response::ErrorCode;
use rnex_core::rmc::response::ErrorCode::{Core_InvalidArgument, RendezVous_SessionVoid}; use rnex_core::rmc::response::ErrorCode::{Core_InvalidArgument, RendezVous_SessionVoid};
use rnex_core::rmc::structures::matchmake::gathering_flags::PERSISTENT_GATHERING; use rnex_core::rmc::structures::matchmake::gathering_flags::PERSISTENT_GATHERING;
@ -155,28 +155,47 @@ impl ExtendedMatchmakeSession {
return Default::default(); return Default::default();
}; };
let mm_session = MatchmakeSession { cfg_if::cfg_if! {
gathering: Gathering { if #[cfg(feature = "v3-5-0")]{
self_gid: gid, let mm_session = MatchmakeSession {
owner_pid: host.pid, gathering: Gathering {
host_pid: host.pid, self_gid: gid,
..session.gathering.clone() owner_pid: host.pid,
}, host_pid: host.pid,
datetime: KerberosDateTime::now(), ..session.gathering.clone()
session_key: (0..32).map(|_| random()).collect(), },
matchmake_param: MatchmakeParam { datetime: KerberosDateTime::now(),
params: vec![ session_key: (0..32).map(|_| random()).collect(),
("@SR".to_owned(), Variant::Bool(true)), matchmake_param: MatchmakeParam {
("@GIR".to_owned(), Variant::SInt64(3)), params: vec![
], ("@SR".to_owned(), Variant::Bool(true)),
}, ("@GIR".to_owned(), Variant::SInt64(3)),
system_password_enabled: false, ],
..session },
}; system_password_enabled: false,
..session
};
Self { return Self {
session: mm_session, session: mm_session,
connected_players: Default::default(), connected_players: Default::default(),
}
} else {
let mm_session = MatchmakeSession {
gathering: Gathering {
self_gid: gid,
owner_pid: host.pid,
host_pid: host.pid,
..session.gathering.clone()
},
session_key: (0..32).map(|_| random()).collect(),
..session
};
return Self {
session: mm_session,
connected_players: Default::default(),
}
}
} }
} }
@ -212,6 +231,7 @@ impl ExtendedMatchmakeSession {
param_1: self.session.gathering.self_gid as PID, param_1: self.session.gathering.self_gid as PID,
param_2: other_pid, param_2: other_pid,
str_param: "".into(), str_param: "".into(),
#[cfg(feature = "v3-5-0")]
param_3: 0, param_3: 0,
}) })
.await; .await;
@ -244,6 +264,7 @@ impl ExtendedMatchmakeSession {
param_1: self.session.gathering.self_gid as PID, param_1: self.session.gathering.self_gid as PID,
param_2: *pid, param_2: *pid,
str_param: join_msg.clone(), str_param: join_msg.clone(),
#[cfg(feature = "v3-5-0")]
param_3: self.connected_players.len() as _, param_3: self.connected_players.len() as _,
}) })
.await; .await;
@ -266,6 +287,7 @@ impl ExtendedMatchmakeSession {
param_1: self.session.gathering.self_gid as PID, param_1: self.session.gathering.self_gid as PID,
param_2: new_conn_pid, param_2: new_conn_pid,
str_param: join_msg.clone(), str_param: join_msg.clone(),
#[cfg(feature = "v3-5-0")]
param_3: self.connected_players.len() as _, param_3: self.connected_players.len() as _,
}) })
.await; .await;
@ -318,15 +340,19 @@ impl ExtendedMatchmakeSession {
} }
} }
if search_criteria.exclude_system_password_set { cfg_if::cfg_if! {
if self.session.system_password_enabled { if #[cfg(feature = "v3-5-0")]{
return Ok(false); if search_criteria.exclude_system_password_set {
} if self.session.system_password_enabled {
} return Ok(false);
}
}
if search_criteria.exclude_user_password_set { if search_criteria.exclude_user_password_set {
if self.session.user_password_enabled { if self.session.user_password_enabled {
return Ok(false); return Ok(false);
}
}
} }
} }

View file

@ -1,26 +1,29 @@
use crate::define_rmc_proto;
use crate::nex::common::get_station_urls;
use crate::nex::matchmake::{ExtendedMatchmakeSession, MatchmakeManager};
use crate::nex::remote_console::RemoteConsole;
use crate::rmc::protocols::matchmake::{
Matchmake, RawMatchmake, RawMatchmakeInfo, RemoteMatchmake,
};
use crate::rmc::protocols::nat_traversal::{
NatTraversal, RawNatTraversal, RawNatTraversalInfo, RemoteNatTraversal,
RemoteNatTraversalConsole,
};
use rnex_core::PID; use rnex_core::PID;
use rnex_core::define_rmc_proto;
use rnex_core::kerberos::KerberosDateTime; use rnex_core::kerberos::KerberosDateTime;
use rnex_core::nex::common::get_station_urls;
use rnex_core::nex::matchmake::{ExtendedMatchmakeSession, MatchmakeManager};
use rnex_core::nex::remote_console::RemoteConsole;
use rnex_core::prudp::station_url::StationUrl; use rnex_core::prudp::station_url::StationUrl;
use rnex_core::prudp::station_url::UrlOptions::{ use rnex_core::prudp::station_url::UrlOptions::{
Address, NatFiltering, NatMapping, Port, RVConnectionID, Address, NatFiltering, NatMapping, Port, RVConnectionID,
}; };
use rnex_core::rmc::protocols::matchmake::{
Matchmake, RawMatchmake, RawMatchmakeInfo, RemoteMatchmake,
};
use rnex_core::rmc::protocols::matchmake_ext::{ use rnex_core::rmc::protocols::matchmake_ext::{
MatchmakeExt, RawMatchmakeExt, RawMatchmakeExtInfo, RemoteMatchmakeExt, MatchmakeExt, RawMatchmakeExt, RawMatchmakeExtInfo, RemoteMatchmakeExt,
}; };
use rnex_core::rmc::protocols::matchmake_extension::{ use rnex_core::rmc::protocols::matchmake_extension::{
MatchmakeExtension, RawMatchmakeExtension, RawMatchmakeExtensionInfo, RemoteMatchmakeExtension, MatchmakeExtension, RawMatchmakeExtension, RawMatchmakeExtensionInfo, RemoteMatchmakeExtension,
}; };
use rnex_core::rmc::protocols::nat_traversal::{
NatTraversal, RawNatTraversal, RawNatTraversalInfo, RemoteNatTraversal,
RemoteNatTraversalConsole,
};
use rnex_core::rmc::protocols::notifications::notification_types::{
END_GATHERING, REQUEST_JOIN_GATHERING,
};
use rnex_core::rmc::protocols::ranking::{Ranking, RawRanking, RawRankingInfo, RemoteRanking}; use rnex_core::rmc::protocols::ranking::{Ranking, RawRanking, RawRankingInfo, RemoteRanking};
use rnex_core::rmc::protocols::secure::{RawSecure, RawSecureInfo, RemoteSecure, Secure}; use rnex_core::rmc::protocols::secure::{RawSecure, RawSecureInfo, RemoteSecure, Secure};
use rnex_core::rmc::response::ErrorCode; use rnex_core::rmc::response::ErrorCode;
@ -32,11 +35,13 @@ use serde::{Deserialize, Serialize};
use std::env; use std::env;
use std::str::FromStr; use std::str::FromStr;
use crate::rmc::protocols::notifications::{NotificationEvent, RemoteNotification};
use cfg_if::cfg_if; use cfg_if::cfg_if;
use log::{error, info}; use log::{error, info};
use macros::rmc_struct; use macros::rmc_struct;
use rnex_core::prudp::socket_addr::PRUDPSockAddr; use rnex_core::prudp::socket_addr::PRUDPSockAddr;
use rnex_core::rmc::protocols::notifications::{
self, Notification, NotificationEvent, RemoteNotification,
};
use rnex_core::rmc::protocols::ranking::{ use rnex_core::rmc::protocols::ranking::{
CompetitionRankingGetParam, CompetitionRankingScoreData, CompetitionRankingScoreInfo, CompetitionRankingGetParam, CompetitionRankingScoreData, CompetitionRankingScoreInfo,
}; };
@ -248,6 +253,8 @@ impl MatchmakeExtension for User {
.await?; .await?;
let mut session = session.lock().await; let mut session = session.lock().await;
#[cfg(feature = "v3-5-0")]
if join_session_param.user_password != session.session.user_password { if join_session_param.user_password != session.session.user_password {
return Err(ErrorCode::RendezVous_InvalidPassword); return Err(ErrorCode::RendezVous_InvalidPassword);
} }
@ -396,6 +403,101 @@ impl MatchmakeExtension for User {
Ok(()) Ok(())
} }
async fn create_matchmake_session(
&self,
gathering: Any,
message: String,
) -> Result<(u32, Vec<u8>), ErrorCode> {
let Some(Ok(session)): Option<Result<MatchmakeSession, _>> = gathering.try_get() else {
return Err(ErrorCode::Core_InvalidArgument);
};
let session = self
.create_matchmake_session_with_param(CreateMatchmakeSessionParam {
matchmake_session: session,
additional_participants: vec![],
gid_for_participation_check: 0,
create_matchmake_session_option: 0,
join_message: message,
participation_count: 1,
})
.await?;
Ok((session.gathering.self_gid, session.session_key))
}
async fn get_friend_notification_data(
&self,
ty: i32,
) -> Result<Vec<NotificationEvent>, ErrorCode> {
Ok(vec![])
}
async fn update_notification_data(
&self,
ty: u32,
param_1: u32,
param_2: u32,
str_param: String,
) -> Result<(), ErrorCode> {
let recpipent = param_2;
let Some(user) = self
.matchmake_manager
.users
.read()
.await
.get(&recpipent)
.and_then(|v| v.upgrade())
else {
return Err(ErrorCode::Core_InvalidArgument);
};
match ty {
REQUEST_JOIN_GATHERING => {
user.remote
.process_notification_event(NotificationEvent {
pid_source: self.pid,
notif_type: REQUEST_JOIN_GATHERING * 1000,
param_1,
param_2,
#[cfg(feature = "v3-5-0")]
param_3: 0,
str_param,
})
.await;
}
END_GATHERING => {
user.remote
.process_notification_event(NotificationEvent {
pid_source: self.pid,
notif_type: END_GATHERING * 1000,
param_1,
param_2,
#[cfg(feature = "v3-5-0")]
param_3: 0,
str_param,
})
.await;
}
_ => {
return Err(ErrorCode::Core_InvalidArgument);
}
}
Ok(())
}
async fn join_matchmake_session_ex(
&self,
gid: u32,
message: String,
dont_care_block_list: bool,
participation_count: u16,
) -> Result<Vec<u8>, ErrorCode> {
let sess = self.matchmake_manager.get_session(gid).await?;
let mut sess = sess.lock().await;
sess.add_players(&[self.this.clone()], message).await;
Ok(sess.session.session_key.clone())
}
} }
impl Matchmake for User { impl Matchmake for User {
@ -448,6 +550,7 @@ impl Matchmake for User {
pid_source: self.pid, pid_source: self.pid,
param_1: gid as PID, param_1: gid as PID,
param_2: self.pid, param_2: self.pid,
#[cfg(feature = "v3-5-0")]
param_3: 0, param_3: 0,
str_param: "".to_string(), str_param: "".to_string(),
}) })
@ -469,6 +572,7 @@ impl Matchmake for User {
pid_source: self.pid, pid_source: self.pid,
param_1: gid as PID, param_1: gid as PID,
param_2: self.pid, param_2: self.pid,
#[cfg(feature = "v3-5-0")]
param_3: 0, param_3: 0,
str_param: "".to_string(), str_param: "".to_string(),
}) })
@ -504,6 +608,7 @@ impl Matchmake for User {
pid_source: self.pid, pid_source: self.pid,
param_1: gid as PID, param_1: gid as PID,
param_2: *candidate as PID, param_2: *candidate as PID,
#[cfg(feature = "v3-5-0")]
param_3: 0, param_3: 0,
str_param: "".to_string(), str_param: "".to_string(),
}) })

View file

@ -1,17 +1,57 @@
use macros::{method_id, rmc_proto}; use macros::{method_id, rmc_proto};
use rnex_core::rmc::response::ErrorCode; use rnex_core::rmc::response::ErrorCode;
use rnex_core::rmc::structures::matchmake::{AutoMatchmakeParam, CreateMatchmakeSessionParam, JoinMatchmakeSessionParam, MatchmakeSession}; use rnex_core::rmc::structures::matchmake::{
AutoMatchmakeParam, CreateMatchmakeSessionParam, JoinMatchmakeSessionParam, MatchmakeSession,
};
use crate::rmc::protocols::notifications::NotificationEvent;
use crate::rmc::structures::any::Any;
#[rmc_proto(109)] #[rmc_proto(109)]
pub trait MatchmakeExtension{ pub trait MatchmakeExtension {
#[method_id(1)] #[method_id(1)]
async fn close_participation(&self, gid: u32) -> Result<(), ErrorCode>; async fn close_participation(&self, gid: u32) -> Result<(), ErrorCode>;
#[method_id(2)] #[method_id(2)]
async fn open_participation(&self, gid: u32) -> Result<(), ErrorCode>; async fn open_participation(&self, gid: u32) -> Result<(), ErrorCode>;
#[method_id(6)]
async fn create_matchmake_session(
&self,
gathering: Any,
message: String,
) -> Result<(u32, Vec<u8>), ErrorCode>;
#[method_id(9)]
async fn update_notification_data(
&self,
ty: u32,
param1: u32,
param2: u32,
str_param: String,
) -> Result<(), ErrorCode>;
#[method_id(10)]
async fn get_friend_notification_data(
&self,
ty: i32,
) -> Result<Vec<NotificationEvent>, ErrorCode>;
#[method_id(30)]
async fn join_matchmake_session_ex(
&self,
gid: u32,
message: String,
dont_care_block_list: bool,
participation_count: u16,
) -> Result<Vec<u8>, ErrorCode>;
#[method_id(8)] #[method_id(8)]
async fn modify_current_game_attribute(&self, gid: u32, attrib_index: u32, attrib_val: u32) -> Result<(), ErrorCode>; async fn modify_current_game_attribute(
&self,
gid: u32,
attrib_index: u32,
attrib_val: u32,
) -> Result<(), ErrorCode>;
#[method_id(16)] #[method_id(16)]
async fn get_playing_session(&self, pids: Vec<u32>) -> Result<Vec<()>, ErrorCode>; async fn get_playing_session(&self, pids: Vec<u32>) -> Result<Vec<()>, ErrorCode>;
@ -19,14 +59,26 @@ pub trait MatchmakeExtension{
#[method_id(34)] #[method_id(34)]
async fn update_progress_score(&self, gid: u32, progress: u8) -> Result<(), ErrorCode>; async fn update_progress_score(&self, gid: u32, progress: u8) -> Result<(), ErrorCode>;
#[method_id(38)] #[method_id(38)]
async fn create_matchmake_session_with_param(&self, session: CreateMatchmakeSessionParam) -> Result<MatchmakeSession, ErrorCode>; async fn create_matchmake_session_with_param(
&self,
session: CreateMatchmakeSessionParam,
) -> Result<MatchmakeSession, ErrorCode>;
#[method_id(39)] #[method_id(39)]
async fn join_matchmake_session_with_param(&self, session: JoinMatchmakeSessionParam) -> Result<MatchmakeSession, ErrorCode>; async fn join_matchmake_session_with_param(
&self,
session: JoinMatchmakeSessionParam,
) -> Result<MatchmakeSession, ErrorCode>;
#[method_id(40)] #[method_id(40)]
async fn auto_matchmake_with_param_postpone(&self, session: AutoMatchmakeParam) -> Result<MatchmakeSession, ErrorCode>; async fn auto_matchmake_with_param_postpone(
&self,
session: AutoMatchmakeParam,
) -> Result<MatchmakeSession, ErrorCode>;
#[method_id(41)] #[method_id(41)]
async fn find_matchmake_session_by_gathering_id_detail(&self, gid: u32) -> Result<MatchmakeSession, ErrorCode>; async fn find_matchmake_session_by_gathering_id_detail(
&self,
gid: u32,
) -> Result<MatchmakeSession, ErrorCode>;
} }

View file

@ -5,8 +5,12 @@ use rnex_core::PID;
pub mod notification_types { pub mod notification_types {
pub const OWNERSHIP_CHANGED: u32 = 4000; pub const OWNERSHIP_CHANGED: u32 = 4000;
pub const HOST_CHANGED: u32 = 110000; pub const HOST_CHANGED: u32 = 110000;
pub const REQUEST_JOIN_GATHERING: u32 = 101;
pub const END_GATHERING: u32 = 102;
} }
cfg_if::cfg_if! {
if #[cfg(feature = "v3-5-0")]{
#[derive(RmcSerialize, Debug, Default, Clone)] #[derive(RmcSerialize, Debug, Default, Clone)]
#[rmc_struct(0)] #[rmc_struct(0)]
pub struct NotificationEvent { pub struct NotificationEvent {
@ -17,6 +21,18 @@ pub struct NotificationEvent {
pub str_param: String, pub str_param: String,
pub param_3: PID, pub param_3: PID,
} }
} else {
#[derive(RmcSerialize, Debug, Default, Clone)]
#[rmc_struct(0)]
pub struct NotificationEvent {
pub pid_source: PID,
pub notif_type: u32,
pub param_1: PID,
pub param_2: PID,
pub str_param: String,
}
}
}
#[rmc_proto(14, NoReturn)] #[rmc_proto(14, NoReturn)]
pub trait Notification { pub trait Notification {

View file

@ -1,3 +1,4 @@
use cfg_if::cfg_if;
use macros::RmcSerialize; use macros::RmcSerialize;
use rnex_core::kerberos::KerberosDateTime; use rnex_core::kerberos::KerberosDateTime;
use rnex_core::rmc::structures::variant::Variant; use rnex_core::rmc::structures::variant::Variant;
@ -27,29 +28,49 @@ pub struct MatchmakeParam {
pub params: Vec<(String, Variant)>, pub params: Vec<(String, Variant)>,
} }
// rmc structure cfg_if! {
#[derive(RmcSerialize, Debug, Clone, Default)] if #[cfg(feature = "v3-5-0")]{
#[rmc_struct(3)] #[derive(RmcSerialize, Debug, Clone, Default)]
pub struct MatchmakeSession { #[rmc_struct(3)]
//inherits from pub struct MatchmakeSession {
#[extends] //inherits from
pub gathering: Gathering, #[extends]
pub gathering: Gathering,
pub gamemode: u32, pub gamemode: u32,
pub attributes: Vec<u32>, pub attributes: Vec<u32>,
pub open_participation: bool, pub open_participation: bool,
pub matchmake_system_type: u32, pub matchmake_system_type: u32,
pub application_buffer: Vec<u8>, pub application_buffer: Vec<u8>,
pub participation_count: u32, pub participation_count: u32,
pub progress_score: u8, pub progress_score: u8,
pub session_key: Vec<u8>, pub session_key: Vec<u8>,
pub option0: u32, pub option0: u32,
pub matchmake_param: MatchmakeParam, pub matchmake_param: MatchmakeParam,
pub datetime: KerberosDateTime, pub datetime: KerberosDateTime,
pub user_password: String, pub user_password: String,
pub refer_gid: u32, pub refer_gid: u32,
pub user_password_enabled: bool, pub user_password_enabled: bool,
pub system_password_enabled: bool, pub system_password_enabled: bool,
}
} else {
#[derive(RmcSerialize, Debug, Clone, Default)]
#[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>,
}
}
} }
#[derive(RmcSerialize, Debug, Clone)] #[derive(RmcSerialize, Debug, Clone)]