mirror of
https://git.ngram.ca/OpenJam/rc-servers
synced 2026-08-23 23:08:52 +00:00
Implement non-multiplayer parts of custom games
This commit is contained in:
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())
|
||||
})
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
Reference in new issue
Block a user