Implement non-multiplayer parts of custom games

This commit is contained in:
NG (Graham) committed 2026-03-12 22:44:04 -04:00
1 parent 6ce456a739
commit af04c4093c
34 files changed
+1751 -78

No files matched your search

@@ -0,0 +1,50 @@
use polariton_server::operations::{SimpleOpError, SimpleOperation, SimpleOpImpl};
use polariton::operation::{ParameterTable, Typed};
const CODE: u8 = 149;
const FIELD_PARAM_KEY: u8 = 179; // str; in
const VALUE_PARAM_KEY: u8 = 180; // any; in
const RESPONSE_CODE_PARAM_KEY: u8 = 168; // int enum; out
pub(super) struct CustomGameConfigChanger {
games: std::sync::Arc<crate::custom_game_tracker::CustomGameMesh>,
mesh: std::sync::Arc<crate::user_service::UserMesh>,
}
#[async_trait::async_trait]
impl <C: Send + 'static> SimpleOperation<C> for CustomGameConfigChanger {
type User = crate::UserTy;
const CODE: u8 = CODE;
async fn handle(&self, mut params: ParameterTable<C>, user: &Self::User) -> Result<ParameterTable<C>, SimpleOpError> {
if let Some(Typed::Str(field_name)) = params.remove(&FIELD_PARAM_KEY) {
if let Some(Typed::Str(value)) = params.remove(&VALUE_PARAM_KEY) {
let user_info = user.user()?;
let my_pub_id = user_info.public_id();
let (resp_code, session_opt) = self.games.set_config_field(my_pub_id, &field_name.string, &value.string).await;
if let Some(session) = session_opt {
let event = crate::events::CustomGameConfigRefresh {
field: field_name.string.clone(),
value: value.string.clone(),
};
let session_members_iter = session.users.iter()
.filter(|mem| !mem.is_invited && mem.public_id != my_pub_id)
.map(|mem| &mem.public_id as &str);
self.mesh.broadcast_event_to(session_members_iter, event).await;
}
params.insert(RESPONSE_CODE_PARAM_KEY, Typed::Int(resp_code as _));
}
} else {
log::warn!("Missing custom game field name parameter string");
}
Ok(params)
}
}
pub(super) fn game_adjust_provider<C: Send + 'static>(init_ctx: &crate::InitConfig) -> SimpleOpImpl<C, crate::UserTy, CustomGameConfigChanger> {
SimpleOpImpl::new(CustomGameConfigChanger {
games: init_ctx.custom_games.clone(),
mesh: init_ctx.user_mesh.clone(),
})
}
@@ -0,0 +1,43 @@
use polariton_server::operations::{SimpleOpError, SimpleOperation, SimpleOpImpl};
use polariton::operation::{ParameterTable, Typed};
const CODE: u8 = 153;
const RESPONSE_CODE_PARAM_KEY: u8 = 168; // int enum; out
pub(super) struct CustomGameCanJoinQueue {
games: std::sync::Arc<crate::custom_game_tracker::CustomGameMesh>,
validator: std::sync::Arc<crate::vehicle_validators::InitedVehicleValidator>,
}
#[async_trait::async_trait]
impl <C: Send + 'static> SimpleOperation<C> for CustomGameCanJoinQueue {
type User = crate::UserTy;
const CODE: u8 = CODE;
async fn handle(&self, mut params: ParameterTable<C>, user: &Self::User) -> Result<ParameterTable<C>, SimpleOpError> {
let user_info = user.user()?;
let my_pub_id = user_info.public_id();
let resp_code = if let Some(session) = self.games.get_user_game(my_pub_id).await {
let vehicle = user_info.selected_vehicle_data().await?;
match self.validator.validate(&vehicle.robot_data, &vehicle.colour_data) {
oj_rc_plugins::vehicle_validation::ValidationResultCode::Ok => crate::data::custom_games::CheckCanJoinQueueResponseCode::Ok,
err_code => {
log::debug!("Failed to validate user {} vehicle for custom game {}: {:?}", my_pub_id, session.session_id, err_code);
crate::data::custom_games::CheckCanJoinQueueResponseCode::Unbalanced
}
}
} else {
crate::data::custom_games::CheckCanJoinQueueResponseCode::UserNotInSession0
};
params.insert(RESPONSE_CODE_PARAM_KEY, Typed::Int(resp_code as _));
Ok(params)
}
}
pub(super) fn game_can_queue_provider<C: Send + 'static>(init_ctx: &crate::InitConfig) -> SimpleOpImpl<C, crate::UserTy, CustomGameCanJoinQueue> {
SimpleOpImpl::new(CustomGameCanJoinQueue {
games: init_ctx.custom_games.clone(),
validator: init_ctx.vehicle_validators.custom_game.clone(),
})
}
@@ -0,0 +1,38 @@
use polariton_server::operations::{SimpleOpError, SimpleOperation, SimpleOpImpl};
use polariton::operation::{ParameterTable, Typed};
const CODE: u8 = 143;
const RESPONSE_CODE_PARAM_KEY: u8 = 168; // int enum; out
const IDK_PARAM_KEY: u8 = 169; // ???; out (let's send back the game id)
pub(super) struct CustomGameCreator {
games: std::sync::Arc<crate::custom_game_tracker::CustomGameMesh>,
}
#[async_trait::async_trait]
impl <C: Send + 'static> SimpleOperation<C> for CustomGameCreator {
type User = crate::UserTy;
const CODE: u8 = CODE;
async fn handle(&self, mut params: ParameterTable<C>, user: &Self::User) -> Result<ParameterTable<C>, SimpleOpError> {
let user_info = user.user()?;
let result = self.games.create_game(user_info.public_id()).await;
match result {
Err(e) => {
params.insert(RESPONSE_CODE_PARAM_KEY, Typed::Int(e as _));
},
Ok(game_id) => {
params.insert(RESPONSE_CODE_PARAM_KEY, Typed::Int(crate::data::custom_games::SessionCreateResponseCode::SessionCreated as _));
params.insert(IDK_PARAM_KEY, Typed::Str(game_id.into()));
}
}
Ok(params)
}
}
pub(super) fn game_create_provider<C: Send + 'static>(games: &std::sync::Arc<crate::custom_game_tracker::CustomGameMesh>) -> SimpleOpImpl<C, crate::UserTy, CustomGameCreator> {
SimpleOpImpl::new(CustomGameCreator {
games: games.to_owned(),
})
}
@@ -0,0 +1,53 @@
use polariton_server::operations::{SimpleOpError, SimpleOperation, SimpleOpImpl};
use polariton::operation::{ParameterTable, Typed};
const CODE: u8 = 148;
const ACCEPT_PARAM_KEY: u8 = 173; // bool; in
const RESPONSE_CODE_PARAM_KEY: u8 = 168; // int enum; out
pub(super) struct CustomGameInviteResponder {
games: std::sync::Arc<crate::custom_game_tracker::CustomGameMesh>,
mesh: std::sync::Arc<crate::user_service::UserMesh>,
}
#[async_trait::async_trait]
impl <C: Send + 'static> SimpleOperation<C> for CustomGameInviteResponder {
type User = crate::UserTy;
const CODE: u8 = CODE;
async fn handle(&self, mut params: ParameterTable<C>, user: &Self::User) -> Result<ParameterTable<C>, SimpleOpError> {
if let Some(Typed::Bool(is_accept)) = params.remove(&ACCEPT_PARAM_KEY) {
let user_info = user.user()?;
let my_pub_id = user_info.public_id();
let (resp_code, session_opt) = self.games.update_invite_user(my_pub_id, is_accept).await;
if let Some(session) = session_opt {
if !is_accept {
let event = crate::events::CustomGameInviteDecline {
public_id: my_pub_id.to_owned(),
};
let session_members_iter = session.users.iter()
.filter(|mem| !mem.is_invited && mem.public_id != my_pub_id)
.map(|mem| &mem.public_id as &str);
self.mesh.broadcast_event_to(session_members_iter, event).await;
}
let event = crate::events::CustomGameRefresh {
session: session.session_id,
};
let other_session_members_iter = session.users.iter()
.filter(|mem| !mem.is_invited && mem.public_id != my_pub_id)
.map(|mem| &mem.public_id as &str);
self.mesh.broadcast_event_to(other_session_members_iter, event).await;
}
params.insert(RESPONSE_CODE_PARAM_KEY, Typed::Int(resp_code as _));
}
Ok(params)
}
}
pub(super) fn game_invite_respond_provider<C: Send + 'static>(init_ctx: &crate::InitConfig) -> SimpleOpImpl<C, crate::UserTy, CustomGameInviteResponder> {
SimpleOpImpl::new(CustomGameInviteResponder {
games: init_ctx.custom_games.clone(),
mesh: init_ctx.user_mesh.clone(),
})
}
@@ -0,0 +1,70 @@
use polariton_server::operations::{SimpleOpError, SimpleOperation, SimpleOpImpl};
use polariton::operation::{ParameterTable, Typed};
const CODE: u8 = 147;
const INVITEE_PARAM_KEY: u8 = 171; // str; in
const IS_TEAM_A_PARAM_KEY: u8 = 175; // bool; in
const RESPONSE_CODE_PARAM_KEY: u8 = 168; // int enum; out
pub(super) struct CustomGameInviter {
games: std::sync::Arc<crate::custom_game_tracker::CustomGameMesh>,
mesh: std::sync::Arc<crate::user_service::UserMesh>,
}
#[async_trait::async_trait]
impl <C: Send + 'static> SimpleOperation<C> for CustomGameInviter {
type User = crate::UserTy;
const CODE: u8 = CODE;
async fn handle(&self, mut params: ParameterTable<C>, user: &Self::User) -> Result<ParameterTable<C>, SimpleOpError> {
if let Some(Typed::Str(invitee_id)) = params.remove(&INVITEE_PARAM_KEY) {
if let Some(Typed::Bool(is_team_a)) = params.remove(&IS_TEAM_A_PARAM_KEY) {
let user_info = user.user()?;
let my_pub_id = user_info.public_id();
let avatars = user_info.list_avatar_info(&[my_pub_id.to_owned(), invitee_id.string.clone()]).await?;
// TODO resolve public_id of invitee by provided display name
let resp_code = if avatars.iter().find(|x| x.public_id == invitee_id.string).is_none() {
crate::data::custom_games::InviteToCustomGameResponseCode::UserDoesNotExist
} else {
let (resp_code, session_opt) = self.games.invite_user(my_pub_id, &invitee_id.string, is_team_a).await;
if let Some(session) = session_opt {
if self.mesh.is_user_online(&invitee_id.string).await {
let my_avatar = avatars.iter().find(|x| x.public_id == my_pub_id).unwrap();
log::debug!("User {} invited {} to custom game {}", my_pub_id, invitee_id.string, session.session_id);
let event = crate::events::CustomGameInvite {
inviter_public_id: my_pub_id.to_owned(),
inviter_display_name: user_info.display_name().to_owned(),
session: session.session_id.clone(),
avatar_id: my_avatar.avatar_id,
invited_to_team_a: is_team_a,
};
self.mesh.send_event_to(&invitee_id.string, event).await;
let event = crate::events::CustomGameRefresh {
session: session.session_id,
};
let other_members = session.users.iter()
.filter(|mem| !mem.is_invited)
.map(|mem| &mem.public_id as &str);
self.mesh.broadcast_event_to(other_members, event).await;
resp_code
} else {
crate::data::custom_games::InviteToCustomGameResponseCode::UserIsNotOnline
}
} else {
resp_code
}
};
params.insert(RESPONSE_CODE_PARAM_KEY, Typed::Int(resp_code as _));
}
}
Ok(params)
}
}
pub(super) fn game_invite_provider<C: Send + 'static>(init_ctx: &crate::InitConfig) -> SimpleOpImpl<C, crate::UserTy, CustomGameInviter> {
SimpleOpImpl::new(CustomGameInviter {
games: init_ctx.custom_games.clone(),
mesh: init_ctx.user_mesh.clone(),
})
}
@@ -0,0 +1,49 @@
use polariton_server::operations::{SimpleOpError, SimpleOperation, SimpleOpImpl};
use polariton::operation::{ParameterTable, Typed};
const CODE: u8 = 150;
const TO_KICK_PARAM_KEY: u8 = 183; // str; in
const RESPONSE_CODE_PARAM_KEY: u8 = 168; // int enum; out
pub(super) struct CustomGameMemberKicker {
games: std::sync::Arc<crate::custom_game_tracker::CustomGameMesh>,
mesh: std::sync::Arc<crate::user_service::UserMesh>,
}
#[async_trait::async_trait]
impl <C: Send + 'static> SimpleOperation<C> for CustomGameMemberKicker {
type User = crate::UserTy;
const CODE: u8 = CODE;
async fn handle(&self, mut params: ParameterTable<C>, user: &Self::User) -> Result<ParameterTable<C>, SimpleOpError> {
if let Some(Typed::Str(user_to_kick)) = params.remove(&TO_KICK_PARAM_KEY) {
let user_info = user.user()?;
let my_pub_id = user_info.public_id();
let (resp_code, session_opt) = self.games.kick_from_game(my_pub_id, &user_to_kick.string).await;
if let Some((kick_info, session)) = session_opt {
log::debug!("User {} kicked {} from custom game {}", my_pub_id, user_to_kick.string, session.session_id);
let kick_event = crate::events::CustomGameKick {
session: kick_info.session_id,
was_invited: kick_info.was_invited,
};
self.mesh.send_event_to(&user_to_kick.string, kick_event).await;
let update_event = crate::events::CustomGameRefresh {
session: session.session_id,
};
let members_iter = session.users.iter()
.map(|mem| &mem.public_id as &str);
self.mesh.broadcast_event_to(members_iter, update_event).await;
}
params.insert(RESPONSE_CODE_PARAM_KEY, Typed::Int(resp_code as _));
}
Ok(params)
}
}
pub(super) fn game_kick_provider<C: Send + 'static>(init_ctx: &crate::InitConfig) -> SimpleOpImpl<C, crate::UserTy, CustomGameMemberKicker> {
SimpleOpImpl::new(CustomGameMemberKicker {
games: init_ctx.custom_games.clone(),
mesh: init_ctx.user_mesh.clone(),
})
}
@@ -0,0 +1,39 @@
use polariton_server::operations::{SimpleOpError, SimpleOperation, SimpleOpImpl};
use polariton::operation::{ParameterTable, Typed};
const CODE: u8 = 145;
const RESPONSE_CODE_PARAM_KEY: u8 = 168; // int enum; out
pub(super) struct CustomGameLeaver {
games: std::sync::Arc<crate::custom_game_tracker::CustomGameMesh>,
mesh: std::sync::Arc<crate::user_service::UserMesh>,
}
#[async_trait::async_trait]
impl <C: Send + 'static> SimpleOperation<C> for CustomGameLeaver {
type User = crate::UserTy;
const CODE: u8 = CODE;
async fn handle(&self, mut params: ParameterTable<C>, user: &Self::User) -> Result<ParameterTable<C>, SimpleOpError> {
let user_info = user.user()?;
let (resp_code, session_opt) = self.games.leave_game(user_info.public_id()).await;
if let Some(session) = session_opt {
let event = crate::events::CustomGameRefresh {
session: session.session_id,
};
let session_members = session.users.iter()
.map(|mem| &mem.public_id as &str);
self.mesh.broadcast_event_to(session_members, event).await;
}
params.insert(RESPONSE_CODE_PARAM_KEY, Typed::Int(resp_code as _));
Ok(params)
}
}
pub(super) fn game_leave_provider<C: Send + 'static>(init_ctx: &crate::InitConfig) -> SimpleOpImpl<C, crate::UserTy, CustomGameLeaver> {
SimpleOpImpl::new(CustomGameLeaver {
games: init_ctx.custom_games.clone(),
mesh: init_ctx.user_mesh.clone(),
})
}
@@ -0,0 +1,46 @@
use polariton_server::operations::{SimpleOpError, SimpleOperation, SimpleOpImpl};
use polariton::operation::{ParameterTable, Typed};
const CODE: u8 = 152;
const NEW_STATE_PARAM_KEY: u8 = 188; // int enum; in
pub(super) struct CustomGameMemberStateUpdate {
games: std::sync::Arc<crate::custom_game_tracker::CustomGameMesh>,
mesh: std::sync::Arc<crate::user_service::UserMesh>,
}
#[async_trait::async_trait]
impl <C: Send + 'static> SimpleOperation<C> for CustomGameMemberStateUpdate {
type User = crate::UserTy;
const CODE: u8 = CODE;
async fn handle(&self, mut params: ParameterTable<C>, user: &Self::User) -> Result<ParameterTable<C>, SimpleOpError> {
if let Some(Typed::Int(new_state)) = params.remove(&NEW_STATE_PARAM_KEY) {
let new_status_enum = crate::data::custom_games::PlayerSessionStatus::from_u8(new_state as _)
.ok_or_else(|| SimpleOpError::with_message(
oj_rc_core::data::error_codes::WebServicesError::UnexpectedError as _,
format!("Unrecognized PlayerSessionStatus {}", new_state),
))?;
let user_info = user.user()?;
let my_pub_id = user_info.public_id();
let session_opt = self.games.update_user_status(my_pub_id, new_status_enum).await;
if let Some(session) = session_opt {
let update_event = crate::events::CustomGameRefresh {
session: session.session_id,
};
let members_iter = session.users.iter()
.map(|mem| &mem.public_id as &str);
self.mesh.broadcast_event_to(members_iter, update_event).await;
}
}
Ok(params)
}
}
pub(super) fn game_player_status_update_provider<C: Send + 'static>(init_ctx: &crate::InitConfig) -> SimpleOpImpl<C, crate::UserTy, CustomGameMemberStateUpdate> {
SimpleOpImpl::new(CustomGameMemberStateUpdate {
games: init_ctx.custom_games.clone(),
mesh: init_ctx.user_mesh.clone(),
})
}
@@ -1,13 +1,71 @@
use polariton_server::operations::SimpleFunc;
use polariton_server::operations::{SimpleOpError, SimpleOperation, SimpleOpImpl};
use polariton::operation::{ParameterTable, Typed};
const RESPONSE_CODE_PARAM_KEY: u8 = 168;
//const CUSTOM_GAME_DATA_PARAM_KEY: u8 = 169;
const CODE: u8 = 144;
pub(super) fn get_custom_session_provider() -> SimpleFunc<144, crate::UserTy, impl (Fn(ParameterTable, &crate::UserTy) -> Result<ParameterTable, i16>) + Sync + Sync> {
SimpleFunc::new(|params, _| {
let mut params = params.to_dict();
params.insert(RESPONSE_CODE_PARAM_KEY, Typed::Int(0 /* Not in any session */));
Ok(params.into())
const RESPONSE_CODE_PARAM_KEY: u8 = 168; // int enum; out
const RESPONSE_DATA_PARAM_KEY: u8 = 169; // hashtable; out
pub(super) struct CustomGameRetriever {
games: std::sync::Arc<crate::custom_game_tracker::CustomGameMesh>,
}
#[async_trait::async_trait]
impl <C: Send + 'static> SimpleOperation<C> for CustomGameRetriever {
type User = crate::UserTy;
const CODE: u8 = CODE;
async fn handle(&self, mut params: ParameterTable<C>, user: &Self::User) -> Result<ParameterTable<C>, SimpleOpError> {
let user_info = user.user()?;
let my_pub_id = user_info.public_id();
let game_opt = self.games.get_user_game(my_pub_id).await;
if let Some(game) = game_opt {
log::debug!("User {} retrieved their custom game session {} info", my_pub_id, game.session_id);
params.insert(RESPONSE_CODE_PARAM_KEY, Typed::Int(crate::data::custom_games::SessionRetrieveResponse::SessionRetrieved as _));
let pub_ids: Vec<String> = game.users.iter()
.map(|member| member.public_id.clone())
.collect();
let avatars = user_info.list_avatar_info(&pub_ids).await?;
let avatar_map: std::collections::HashMap<_, _> = avatars.into_iter()
.map(|avatar| (avatar.public_id.clone(), avatar)).collect();
let resp = crate::data::custom_games::Session {
leader: game.users.first().map(|leader| leader.public_id.clone()).unwrap_or_default(),
session: game.session_id,
members: game.users.iter().map(|mem| mem.public_id.clone()).collect(),
members_display_name: game.users.iter()
.filter_map(|mem| avatar_map.get(&mem.public_id))
.map(|mem| mem.display_name.clone())
.collect(),
invited: game.users.iter()
.filter(|mem| mem.is_invited)
.map(|mem| mem.public_id.clone())
.collect(),
team_b_members: game.users.iter()
.filter(|mem| mem.team == 1)
.map(|mem| mem.public_id.clone())
.collect(),
config: game.config,
avatar_info: avatar_map.iter()
.map(|(pub_id, avatar)| (pub_id.to_owned(), oj_rc_core::data::player_data::AvatarInfo {
avatar_id: avatar.avatar_id,
}))
.collect(),
player_session_state: game.users.iter()
.map(|mem| (mem.public_id.clone(), mem.state))
.collect(),
};
params.insert(RESPONSE_DATA_PARAM_KEY, resp.as_transmissible());
} else {
log::debug!("User {} is not in any custom game session", my_pub_id);
params.insert(RESPONSE_CODE_PARAM_KEY, Typed::Int(crate::data::custom_games::SessionRetrieveResponse::UserNotInAnySession as _));
}
Ok(params)
}
}
pub(super) fn custom_session_provider<C: Send + 'static>(games: &std::sync::Arc<crate::custom_game_tracker::CustomGameMesh>) -> SimpleOpImpl<C, crate::UserTy, CustomGameRetriever> {
SimpleOpImpl::new(CustomGameRetriever {
games: games.to_owned(),
})
}
@@ -1,15 +1,56 @@
use polariton_server::operations::SimpleFunc;
use polariton_server::operations::{SimpleOpError, SimpleOperation, SimpleOpImpl};
use polariton::operation::{ParameterTable, Typed};
use crate::data::custom_games::*;
const PARAM_KEY: u8 = 168;
//const INVITE_PARAM_KEY: u8 = 189; // hashtable (refer to C# CheckIfHasBeenInvitedToCustomGameSessionRequest)
const CODE: u8 = 0;
pub(super) fn pending_invite_provider() -> SimpleFunc<0, crate::UserTy, impl (Fn(ParameterTable, &crate::UserTy) -> Result<ParameterTable, i16>) + Sync + Sync> {
SimpleFunc::new(|params, _| {
let mut params = params.to_dict();
params.insert(PARAM_KEY, Typed::Int(CustomGameInviteCode::NoInvite as _));
Ok(params.into())
const RESULT_CODE_PARAM_KEY: u8 = 168; // int enum; out
const INVITE_PARAM_KEY: u8 = 189; // hashtable (refer to C# CheckIfHasBeenInvitedToCustomGameSessionRequest)
pub(super) struct CustomGamePendingInvites {
games: std::sync::Arc<crate::custom_game_tracker::CustomGameMesh>,
}
#[async_trait::async_trait]
impl <C: Send + 'static> SimpleOperation<C> for CustomGamePendingInvites {
type User = crate::UserTy;
const CODE: u8 = CODE;
async fn handle(&self, mut params: ParameterTable<C>, user: &Self::User) -> Result<ParameterTable<C>, SimpleOpError> {
let user_info = user.user()?;
let my_pub_id = user_info.public_id();
if let Some(session) = self.games.get_user_game(my_pub_id).await {
let myself = session.users.iter().find(|u| u.public_id == my_pub_id).unwrap();
if myself.is_invited {
log::debug!("User {} has checked and is invited to custom game {}", my_pub_id, session.session_id);
params.insert(RESULT_CODE_PARAM_KEY, Typed::Int(CustomGameInviteCode::PendingInvite as _));
// build invite data
let leader = session.users.first().unwrap();
let leader_avatar = user_info.list_avatar_info(&[leader.public_id.clone()]).await?;
let resp = CustomGameInvite {
inviter_public_id: leader_avatar[0].public_id.clone(),
inviter_display_name: leader_avatar[0].display_name.clone(),
session: session.session_id,
avatar_id: leader_avatar[0].avatar_id,
invited_to_team_b: myself.team == 1,
};
params.insert(INVITE_PARAM_KEY, resp.as_transmissible());
} else {
log::debug!("User {} has already accepted invite to custom game {}", my_pub_id, session.session_id);
params.insert(RESULT_CODE_PARAM_KEY, Typed::Int(CustomGameInviteCode::NoInvite as _));
}
} else {
log::debug!("User {} is not invited to any custom game", my_pub_id);
params.insert(RESULT_CODE_PARAM_KEY, Typed::Int(CustomGameInviteCode::NoInvite as _));
}
Ok(params)
}
}
pub(super) fn pending_invite_provider<C: Send + 'static>(init_ctx: &crate::InitConfig) -> SimpleOpImpl<C, crate::UserTy, CustomGamePendingInvites> {
SimpleOpImpl::new(CustomGamePendingInvites {
games: init_ctx.custom_games.clone(),
})
}
@@ -1,11 +1,20 @@
use polariton_server::operations::SimpleFunc;
use polariton::{operation::{Dict, ParameterTable, Typed}, serdes::TypePrefix};
use crate::data::custom_games::*;
const MODE_MAP_PARAM_KEY: u8 = 170;
const MAP_NAMES_PARAM_KEY: u8 = 178;
const ALL_MAPS: &[&str] = &[
"RC_Planet_Mars_01_CTF", // og flat mars
"RC_Planet_Mars_02_BA", // the one with the bridge in the middle
"RC_Planet_Mars_03_BA", // tharsis rift without the rift
"RC_Planet_Neptune_01_CTF", // og flat GJ1214b gliese lake without the lake
"RC_Planet_Neptune_02_BA", // the one with the cave
"RC_Planet_Neptune_03_BA", // spitzer dam
"RC_Planet_Earth_01_BA", // birmingham power station
"RC_Planet_Earth_02_BA", // vanguard
];
pub(super) fn allowed_maps_provider() -> SimpleFunc<146, crate::UserTy, impl (Fn(ParameterTable, &crate::UserTy) -> Result<ParameterTable, i16>) + Sync + Sync> {
SimpleFunc::new(|params, _| {
let mut params = params.to_dict();
@@ -13,19 +22,33 @@ pub(super) fn allowed_maps_provider() -> SimpleFunc<146, crate::UserTy, impl (Fn
key_ty: TypePrefix::Str, // str
val_ty: TypePrefix::ObjArr, // obj arr
items: vec![
(Typed::Str(GameMode::BattleArena.as_str().into()), Typed::ObjArr(vec![
Typed::Str("RC_Planet_Neptune_02_BA".into()),
Typed::Str("RC_Planet_Mars_03_BA".into()),
Typed::Str("RC_Planet_Mars_02_BA".into()),
Typed::Str("RC_Planet_Earth_02_BA".into()),
Typed::Str("RC_Planet_Earth_01_BA".into()),
Typed::Str("RC_Planet_Neptune_03_BA".into()),
].into())
(Typed::Str(oj_rc_core::data::game_mode::GameMode::BattleArena.as_str().into()), Typed::ObjArr(
ALL_MAPS.iter()
.map(|x| Typed::Str(x.into()))
.collect::<Vec<_>>()
.into()
)
),
(Typed::Str(GameMode::TeamDeathmatch.as_str().into()), Typed::ObjArr(vec![
Typed::Str("RC_Planet_Neptune_01_CTF".into()),
Typed::Str("RC_Planet_Mars_01_CTF".into()),
].into())
(Typed::Str(oj_rc_core::data::game_mode::GameMode::TeamDeathmatch.as_str().into()), Typed::ObjArr(
ALL_MAPS.iter()
.map(|x| Typed::Str(x.into()))
.collect::<Vec<_>>()
.into()
)
),
(Typed::Str(oj_rc_core::data::game_mode::GameMode::Pit.as_str().into()), Typed::ObjArr(
ALL_MAPS.iter()
.map(|x| Typed::Str(x.into()))
.collect::<Vec<_>>()
.into()
)
),
(Typed::Str(oj_rc_core::data::game_mode::GameMode::SuddenDeath.as_str().into()), Typed::ObjArr(
ALL_MAPS.iter()
.map(|x| Typed::Str(x.into()))
.collect::<Vec<_>>()
.into()
)
),
],
}));
@@ -1,8 +1,6 @@
use polariton_server::operations::SimpleFunc;
use polariton::{operation::{Dict, ParameterTable, Typed}, serdes::TypePrefix};
use crate::data::custom_games::*;
const PARAM_KEY: u8 = 168;
pub(super) fn team_setup_provider() -> SimpleFunc<162, crate::UserTy, impl (Fn(ParameterTable, &crate::UserTy) -> Result<ParameterTable, i16>) + Sync + Sync> {
@@ -12,13 +10,13 @@ pub(super) fn team_setup_provider() -> SimpleFunc<162, crate::UserTy, impl (Fn(P
key_ty: TypePrefix::Str, // str
val_ty: TypePrefix::Int, // int
items: vec![
(Typed::Str(GameMode::BattleArena.as_str().into()), Typed::Int(10)),
(Typed::Str(GameMode::SuddenDeath.as_str().into()), Typed::Int(10)),
(Typed::Str(GameMode::Pit.as_str().into()), Typed::Int(10)),
(Typed::Str(GameMode::TestMode.as_str().into()), Typed::Int(10)),
(Typed::Str(GameMode::SinglePlayer.as_str().into()), Typed::Int(1)),
(Typed::Str(GameMode::TeamDeathmatch.as_str().into()), Typed::Int(10)),
(Typed::Str(GameMode::Campaign.as_str().into()), Typed::Int(6)),
(Typed::Str(oj_rc_core::data::game_mode::GameMode::BattleArena.as_str().into()), Typed::Int(10)),
(Typed::Str(oj_rc_core::data::game_mode::GameMode::SuddenDeath.as_str().into()), Typed::Int(10)),
(Typed::Str(oj_rc_core::data::game_mode::GameMode::Pit.as_str().into()), Typed::Int(20)),
(Typed::Str(oj_rc_core::data::game_mode::GameMode::TestMode.as_str().into()), Typed::Int(10)),
(Typed::Str(oj_rc_core::data::game_mode::GameMode::SinglePlayer.as_str().into()), Typed::Int(1)),
(Typed::Str(oj_rc_core::data::game_mode::GameMode::TeamDeathmatch.as_str().into()), Typed::Int(10)),
(Typed::Str(oj_rc_core::data::game_mode::GameMode::Campaign.as_str().into()), Typed::Int(1)),
] }));
Ok(params.into())
})
+20 -4
View File
@@ -108,6 +108,14 @@ mod crf_make_featured;
mod crf_unmake_featured;
mod tech_tree_unlock_cube;
mod crf_remove;
mod custom_game_create;
mod custom_game_adjust;
mod custom_game_leave;
mod custom_game_invite_to;
mod custom_game_invite_respond;
mod custom_game_kick;
mod custom_game_player_state;
mod custom_game_can_join_queue;
use polariton_server::operations::OperationsHandler;
@@ -115,7 +123,7 @@ pub fn handler(init_ctx: &crate::InitConfig) -> OperationsHandler<crate::UserTy>
OperationsHandler::new()
.modify(oj_rc_core::polariton::RcOpModifier)
.add(eac::EacChallengeIgnorer)
.add(more_auth::MoreLobbyAuth)
.add(more_auth::more_auth_provider(&init_ctx.user_mesh))
.add(versioner::version_teller(&init_ctx.cubes))
.add(maintenancer::maintenace_teller(&init_ctx.cubes))
.add(game_quality::QualityConfigTeller)
@@ -154,7 +162,7 @@ pub fn handler(init_ctx: &crate::InitConfig) -> OperationsHandler<crate::UserTy>
.add(dev_message::dev_message_provider(&init_ctx.cubes))
.add(custom_games_maps::allowed_maps_provider())
.add(avatar_info::avatar_get_provider())
.add(custom_game_session::get_custom_session_provider())
.add(custom_game_session::custom_session_provider(&init_ctx.custom_games))
.add(user_xp::get_user_xp_provider())
.add(garage_upgrades::garage_upgrades_provider(&init_ctx.cubes))
.add(game_event_params::event_system_params_provider(&init_ctx.cubes))
@@ -174,8 +182,8 @@ pub fn handler(init_ctx: &crate::InitConfig) -> OperationsHandler<crate::UserTy>
.add(robot_mastery_settings::robot_mastery_settings_provider())
.add(player_started_purchase::started_purchase_provider())
.add(custom_games_team::team_setup_provider())
.add(polariton_server::operations::Ack::<152, _>::default()) // custom game player state changed (188 is desired state)
.add(custom_games_invite::pending_invite_provider())
//.add(polariton_server::operations::Ack::<152, _>::default()) // custom game player state changed (188 is desired state)
.add(custom_games_invite::pending_invite_provider(init_ctx))
.add(chat_settings::chat_settings_provider())
.add(polariton_server::operations::Ack::<19, _>::default()) // save chat settings
.add(prebuilt_robots::garage_robot_data_provider())
@@ -240,4 +248,12 @@ pub fn handler(init_ctx: &crate::InitConfig) -> OperationsHandler<crate::UserTy>
.add(tech_tree_unlock_cube::tech_tree_cube_unlock_provider(&init_ctx.cubes))
.add(crf_remove::factory_remove_provider(&init_ctx.factory))
.add(polariton_server::operations::Ack::<94, _>::default()) // ReportCommunityShopItemRequest FIXME: log reports
.add(custom_game_create::game_create_provider(&init_ctx.custom_games))
.add(custom_game_adjust::game_adjust_provider(init_ctx))
.add(custom_game_leave::game_leave_provider(init_ctx))
.add(custom_game_invite_to::game_invite_provider(init_ctx))
.add(custom_game_invite_respond::game_invite_respond_provider(init_ctx))
.add(custom_game_kick::game_kick_provider(init_ctx))
.add(custom_game_player_state::game_player_status_update_provider(init_ctx))
.add(custom_game_can_join_queue::game_can_queue_provider(init_ctx))
}
+16 -2
View File
@@ -1,7 +1,15 @@
use polariton::operation::Typed;
use polariton_server::operations::{Operation, OperationCode};
pub struct MoreLobbyAuth;
pub struct MoreLobbyAuth {
mesh: std::sync::Arc<crate::user_service::UserMesh>,
}
pub fn more_auth_provider(mesh: &std::sync::Arc<crate::user_service::UserMesh>) -> MoreLobbyAuth {
MoreLobbyAuth {
mesh: mesh.to_owned()
}
}
impl MoreLobbyAuth {
const AUTH_PAYLOAD_KEY: u8 = 245;
@@ -27,6 +35,11 @@ impl <C: Send + 'static> Operation<C> for MoreLobbyAuth {
} else {
match user_info.webservice_listener().await {
Ok(listener) => {
self.mesh.add_user(
user_info.public_id().to_owned(),
user.event_sender().to_owned().downgrade(),
).await;
crate::ONLINE_USERS.store(self.mesh.user_count().await as u64, std::sync::atomic::Ordering::SeqCst);
crate::update_status(user_info.as_ref().as_ref()).await;
let mut resp_params = std::collections::HashMap::with_capacity(1);
resp_params.insert(Self::AUTH_PAYLOAD_KEY, polariton::operation::Typed::Byte(0));
@@ -49,7 +62,8 @@ impl <C: Send + 'static> Operation<C> for MoreLobbyAuth {
},
}
}
} else {
log::debug!("Authentication failed for user");
}
}
polariton::operation::OperationResponse {