Add NEX results and fix timers

This commit is contained in:
red binder 2026-04-06 13:35:55 +00:00 committed by Maple
commit 55b3959797
8 changed files with 586 additions and 52 deletions

View file

@ -247,27 +247,29 @@ impl ExtendedMatchmakeSession {
param_3: self.connected_players.len() as _,
})
.await;
}
}
}
for old_conns in &old_particip {
let Some(old_conns) = old_conns.upgrade() else {
continue;
};
let older_pid = old_conns.pid;
initiating_user
.remote
.process_notification_event(NotificationEvent {
pid_source: initiating_pid,
notif_type: 3001,
param_1: self.session.gathering.self_gid as PID,
param_2: older_pid,
str_param: join_msg.clone(),
param_3: self.connected_players.len() as _,
})
.await;
if old_conns.pid != self.session.gathering.host_pid{
continue;
}
for new_conn_pid in conns.iter().filter_map(Weak::upgrade).map(|c| c.pid){
old_conns
.remote
.process_notification_event(NotificationEvent {
pid_source: initiating_pid,
notif_type: 3001,
param_1: self.session.gathering.self_gid as PID,
param_2: new_conn_pid,
str_param: join_msg.clone(),
param_3: self.connected_players.len() as _,
})
.await;
}
}
}
pub fn has_active_players(&self) -> bool {

View file

@ -5,10 +5,14 @@ use crate::nex::remote_console::RemoteConsole;
use crate::rmc::protocols::matchmake::{
Matchmake, RawMatchmake, RawMatchmakeInfo, RemoteMatchmake,
};
use serde::{Serialize, Deserialize};
use std::env;
use std::str::FromStr;
use crate::rmc::protocols::nat_traversal::{
NatTraversal, RawNatTraversal, RawNatTraversalInfo, RemoteNatTraversal,
RemoteNatTraversalConsole,
};
use rnex_core::kerberos::KerberosDateTime;
use rnex_core::PID;
use rnex_core::prudp::station_url::StationUrl;
use rnex_core::prudp::station_url::UrlOptions::{
@ -29,12 +33,15 @@ use rnex_core::rmc::structures::matchmake::{
};
use crate::rmc::protocols::notifications::{NotificationEvent, RemoteNotification};
use log::info;
use log::{info, error};
use macros::rmc_struct;
use rnex_core::rmc::structures::qbuffer::QBuffer;
use rnex_core::prudp::socket_addr::PRUDPSockAddr;
use rnex_core::rmc::response::ErrorCode::{Core_InvalidArgument, RendezVous_AccountExpired};
use rnex_core::rmc::structures::qresult::QResult;
use std::sync::{Arc, Weak};
use rnex_core::rmc::protocols::ranking::{CompetitionRankingScoreData, CompetitionRankingGetParam, CompetitionRankingScoreInfo};
use rnex_core::rmc::structures::ranking::{UploadCompetitionData};
use tokio::sync::{Mutex, RwLock};
define_rmc_proto!(
@ -582,4 +589,145 @@ impl NatTraversal for User {
}
}
impl Ranking for User {}
#[derive(Serialize, Deserialize)]
pub struct CompetitionPostResults {
pub splatfest_id: u32,
pub score: u32,
pub team_id: u8,
pub team_win: u8,
pub user: PID,
}
// Seperate function because I cannot give a fuck right now
fn fetch_team_votes(fest_id: u32) -> Result<Vec<u32>, ErrorCode> {
let endpoint_votes = env::var("RNEX_SPLATOON_RESULTS_VOTES_GET").map_err(|_| {
error!("RNEX_SPLATOON_RESULTS_VOTES_GET not set");
ErrorCode::RendezVous_InvalidConfiguration
})?;
let url_votes = format!("{}?splatfest_id={}", endpoint_votes, fest_id);
let mut response = ureq::get(&url_votes).call().map_err(|e| {
error!("GET for votes failed: {:?}", e);
ErrorCode::RendezVous_InvalidConfiguration
})?;
let body = response.body_mut().read_to_string().map_err(|e| {
error!("failed to read votes body: {:?}", e);
ErrorCode::RendezVous_InvalidConfiguration
})?;
let body = body.trim().trim_start_matches('[').trim_end_matches(']');
let votes: Result<Vec<u32>, _> = body
.split(',')
.map(|s| u32::from_str(s.trim()))
.collect();
votes.map_err(|e| {
error!("failed to parse votes: {:?}", e);
ErrorCode::RendezVous_InvalidConfiguration
})
}
impl Ranking for User {
async fn competition_ranking_get_param(
&self,
param: CompetitionRankingGetParam,
) -> Result<Vec<CompetitionRankingScoreInfo>, ErrorCode> {
let fest_id = param.festival_ids.get(0).copied().unwrap_or(0);
let endpoint_results = env::var("RNEX_SPLATOON_RESULTS_GET")
.map_err(|_| {
error!("RNEX_SPLATOON_RESULTS_GET not set");
ErrorCode::RendezVous_InvalidConfiguration
})?;
let url_results = format!("{}?splatfest_id={}", endpoint_results, fest_id);
let response_results = ureq::get(&url_results).call();
let results: Vec<CompetitionPostResults> = match response_results {
Ok(mut res) => res
.body_mut()
.read_json()
.map_err(|e| {
error!("failed to parse JSON: {:?}", e);
ErrorCode::RendezVous_InvalidConfiguration
})?,
Err(e) => {
error!("GET failed: {:?}", e);
return Err(ErrorCode::RendezVous_InvalidConfiguration);
}
};
let team_votes = fetch_team_votes(fest_id)?;
let score_data: Vec<CompetitionRankingScoreData> = results
.iter()
.map(|r| CompetitionRankingScoreData {
unk: 1,
pid: r.user,
score: r.score,
modified: KerberosDateTime::now(),
unk2: 1,
appdata: QBuffer(vec![]),
})
.collect();
let info = CompetitionRankingScoreInfo {
fest_id,
score_data,
unk: 0,
team_wins: results.iter().map(|r| r.team_win as u32).collect(),
team_votes,
};
Ok(vec![info])
}
async fn upload_competition_ranking_score(&self, param: UploadCompetitionData) -> Result<bool, ErrorCode> {
info!("fest results for user {:?}:", self.pid);
info!("fest id: {:?}", param.splatfest_id);
info!("score: {:?}", param.score);
info!("team id: {:?}", param.team_id);
info!("did current team win: {:?}", param.team_win);
let endpoint = match env::var("RNEX_SPLATOON_RESULTS_POST") {
Ok(url) => url,
Err(_) => {
error!("RNEX_SPLATOON_RESULTS_POST not set");
return Ok(false);
}
};
let payload = CompetitionPostResults {
splatfest_id: param.splatfest_id,
score: param.score,
team_id: param.team_id,
team_win: param.team_win,
user: self.pid,
};
let json_body = match serde_json::to_string(&payload) {
Ok(j) => j,
Err(e) => {
error!("error making json_body: {:?}", e);
return Ok(false);
}
};
let response = ureq::post(&endpoint)
.header("Content-Type", "application/json")
.send(json_body);
match response {
Ok(res) => {
info!("POST worked: {}", res.status());
}
Err(e) => {
error!("POST borked: {:?}", e);
}
}
Ok(true)
}
}