mirror of
https://git.ngram.ca/OpenJam/rc-servers
synced 2026-08-23 23:08:52 +00:00
Platoons social functionality (#91)
### Description This implements and completes #87 (to the best of my knowledge) ### Game Robocraft ### Please confirm - [x] I am the legal owner or represent the owner of all work submitted - [x] I consent to my submission being added to this FOSS project - [ ] This PR used LLMs to generate some or all of the code changes Reviewed-on: https://git.ngram.ca/OpenJam/rc-servers/pulls/91 Co-authored-by: NG (Graham) <ngniusness@gmail.com> Co-committed-by: NG (Graham) <ngniusness@gmail.com>
This commit is contained in:
@@ -12,6 +12,7 @@ impl ChatChannelInfo {
|
||||
(Typed::Str("channelName".into()), Typed::Str(self.channel_name.clone().into())),
|
||||
(Typed::Str("members".into()), Typed::Arr(Arr {
|
||||
ty: polariton::serdes::TypePrefix::HashMap, // hashtable
|
||||
custom_ty: None,
|
||||
items: self.members.iter().map(|x| x.as_transmissible()).collect(),
|
||||
})),
|
||||
(Typed::Str("channelType".into()), Typed::Int(self.channel_ty as _)),
|
||||
|
||||
@@ -32,6 +32,7 @@ impl GarageSlotInfo {
|
||||
(Typed::Str("wasRated".into()), Typed::Bool(self.was_rated)),
|
||||
(Typed::Str("movementCategories".into()), Typed::Arr(Arr {
|
||||
ty: TypePrefix::Int, // int
|
||||
custom_ty: None,
|
||||
items: self.movement_categories.iter().map(|x| Typed::Int(x.but_bigger())).collect(),
|
||||
})),
|
||||
(Typed::Str("uniqueId1".into()), Typed::Int(self.uuid.0 as i32)),
|
||||
@@ -49,6 +50,7 @@ impl GarageSlotInfo {
|
||||
(Typed::Str("baySkinId".into()), Typed::Str(self.bay_skin_id.clone().into())),
|
||||
(Typed::Str("weaponOrder".into()), Typed::Arr(Arr {
|
||||
ty: TypePrefix::Int, // int
|
||||
custom_ty: None,
|
||||
items: self.weapon_order.iter().map(|x| Typed::Int(*x)).collect(),
|
||||
})),
|
||||
].into())
|
||||
@@ -85,6 +87,7 @@ impl ControlOptions {
|
||||
pub fn as_transmissible<C>(&self) -> Typed<C> {
|
||||
Typed::Arr(Arr {
|
||||
ty: TypePrefix::Bool, // bool
|
||||
custom_ty: None,
|
||||
items: vec![
|
||||
Typed::Bool(self.vertical_strafing),
|
||||
Typed::Bool(self.sideways_driving),
|
||||
|
||||
@@ -21,6 +21,7 @@ impl TechTreeNode {
|
||||
(Typed::Str("tp".into()), Typed::Int(self.tech_points as i32)),
|
||||
(Typed::Str("neighbours".into()), Typed::Arr(Arr {
|
||||
ty: TypePrefix::Str, // str
|
||||
custom_ty: None,
|
||||
items: self.neighbours.iter().map(|cube_id| Typed::Str(hex::encode(cube_id.to_be_bytes()).into())).collect(),
|
||||
})),
|
||||
].into())
|
||||
|
||||
@@ -117,6 +117,7 @@ impl WeaponData {
|
||||
let typed_arr: Vec<Typed<C>> = self.group_fire_scales.iter().map(|x| Typed::Float(*x)).collect();
|
||||
out.push((Typed::Str("groupFireScales".into()), Typed::Arr(polariton::operation::Arr {
|
||||
ty: polariton::serdes::TypePrefix::Float,
|
||||
custom_ty: None,
|
||||
items: typed_arr,
|
||||
})));
|
||||
}
|
||||
|
||||
@@ -284,6 +284,7 @@ impl <C: Clone + Send> super::ConfigProvider<C> for CubeConfig {
|
||||
fn public_channels(&self) -> Typed<C> {
|
||||
Typed::Arr(polariton::operation::Arr {
|
||||
ty: TypePrefix::Str,
|
||||
custom_ty: None,
|
||||
items: self.chat.public_channels.iter().map(|s| Typed::Str(s.into())).collect(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -193,6 +193,7 @@ impl GameEventSequence {
|
||||
GameEventTransmissible {
|
||||
maps: Typed::Arr(polariton::operation::Arr {
|
||||
ty: polariton::serdes::TypePrefix::Str,
|
||||
custom_ty: None,
|
||||
items: vec![
|
||||
Typed::Str(crate::data::game_mode::GameMap::from_persist(item_now.singleplayer.map).as_str().into()),
|
||||
Typed::Str(crate::data::game_mode::GameMap::from_persist(item_now.multiplayer.map).as_str().into()),
|
||||
@@ -200,6 +201,7 @@ impl GameEventSequence {
|
||||
}),
|
||||
visibilities: Typed::Arr(polariton::operation::Arr {
|
||||
ty: polariton::serdes::TypePrefix::Int,
|
||||
custom_ty: None,
|
||||
items: vec![
|
||||
Typed::Int(crate::data::game_mode::MapVisibility::from_persist(item_now.singleplayer.visibility) as _),
|
||||
Typed::Int(crate::data::game_mode::MapVisibility::from_persist(item_now.multiplayer.visibility) as _),
|
||||
@@ -207,6 +209,7 @@ impl GameEventSequence {
|
||||
}),
|
||||
modes: Typed::Arr(polariton::operation::Arr {
|
||||
ty: polariton::serdes::TypePrefix::Int,
|
||||
custom_ty: None,
|
||||
items: vec![
|
||||
Typed::Int(crate::data::game_mode::GameMode::from_persist(item_now.singleplayer.mode) as _),
|
||||
Typed::Int(crate::data::game_mode::GameMode::from_persist(item_now.multiplayer.mode) as _),
|
||||
@@ -214,6 +217,7 @@ impl GameEventSequence {
|
||||
}),
|
||||
auto_heals: Typed::Arr(polariton::operation::Arr {
|
||||
ty: polariton::serdes::TypePrefix::Bool,
|
||||
custom_ty: None,
|
||||
items: vec![
|
||||
Typed::Bool(item_now.singleplayer.auto_heal),
|
||||
Typed::Bool(item_now.multiplayer.auto_heal),
|
||||
|
||||
@@ -7,6 +7,7 @@ impl super::ChatUser for UserData {
|
||||
log::info!("User is subscribed to channels {:?}", channels);
|
||||
Ok(polariton::operation::Typed::Arr(polariton::operation::Arr {
|
||||
ty: polariton::serdes::TypePrefix::HashMap, // hashtable
|
||||
custom_ty: None,
|
||||
items: channels.into_iter().map(|name| crate::data::channel::ChatChannelInfo {
|
||||
channel_name: name,
|
||||
members: vec![
|
||||
@@ -103,6 +104,7 @@ impl super::ChatUser for UserData {
|
||||
})?;
|
||||
Ok(polariton::operation::Typed::Arr(polariton::operation::Arr {
|
||||
ty: polariton::serdes::TypePrefix::Str,
|
||||
custom_ty: None,
|
||||
items: sanctions.into_iter().map(|x| {
|
||||
let data = crate::data::sanction::SanctionJson {
|
||||
type_: crate::data::sanction::SanctionType::from_db(x.descriptor),
|
||||
|
||||
@@ -11,7 +11,7 @@ mod inventory;
|
||||
pub use inventory::{UnlockedParts, UnlockOverride};
|
||||
|
||||
mod traits;
|
||||
pub use traits::{UserProvider, User, UserToken, UserSlots, UserSlotData, VehicleData, UserAuthInfo, UserLoginInfo, UserAuthenticator, NewSlotData, UserId, RegistrationInfo, VehicleUploadData, ChatUser, AvatarInfo, GetAvatarInfo, ControlData, ControlType, CustomisationData, GetCustomisationData, SetSanction, SanctionType, LobbyUser, GameDescriptor, PlayerLobbyDescriptor, MultiplayerUser, PlayerScore, MultiplayerError, MultiplayerErrorCode, PlayerDescriptor, GameEventSetter, CurrentGameEvent, AuthError, IntercomUser, FakePlayers, ResolvedVehicle, CommonUser, IntercomListener, UserRole, SocialUser, SocialUserC, CurrencyType, CurrencyOp, MatchRewards, SingleplayerUser, PurchaseResult, FactoryUser, FriendInviteReturn, FriendData, FriendInviteStatus};
|
||||
pub use traits::{UserProvider, User, UserToken, UserSlots, UserSlotData, VehicleData, UserAuthInfo, UserLoginInfo, UserAuthenticator, NewSlotData, UserId, RegistrationInfo, VehicleUploadData, ChatUser, AvatarInfo, GetAvatarInfo, ControlData, ControlType, CustomisationData, GetCustomisationData, SetSanction, SanctionType, LobbyUser, GameDescriptor, PlayerLobbyDescriptor, MultiplayerUser, PlayerScore, MultiplayerError, MultiplayerErrorCode, PlayerDescriptor, GameEventSetter, CurrentGameEvent, AuthError, IntercomUser, FakePlayers, ResolvedVehicle, CommonUser, IntercomListener, UserRole, SocialUser, SocialUserC, CurrencyType, CurrencyOp, MatchRewards, SingleplayerUser, PurchaseResult, FactoryUser, FriendInviteReturn, FriendData, FriendInviteStatus, SocialInfo};
|
||||
|
||||
pub mod intercom;
|
||||
pub use intercom::generate_token as generate_intercom_token;
|
||||
|
||||
@@ -57,7 +57,7 @@ impl super::SocialUser for UserData {
|
||||
format!("Failed to retrieve friends: {}", e),
|
||||
)
|
||||
})?;
|
||||
let friend_ids: Vec<i32> = friends.iter().map(|(_, user)| user.id).collect();
|
||||
let friend_ids = friends.iter().map(|(_, user)| user.id);
|
||||
let friend_avatars = self.db.user_auxs_by_user_ids_and_descriptor(friend_ids, oj_rc_database::schema::user_aux::Descriptor::AvatarId).await
|
||||
.map_err(|e| {
|
||||
log::error!("Failed to retrieve friend avatars for user {} : {}", self.account.id, e);
|
||||
@@ -81,6 +81,37 @@ impl super::SocialUser for UserData {
|
||||
)
|
||||
}
|
||||
|
||||
async fn list_social_info(&self, public_ids: &[String]) -> Result<Vec<super::SocialInfo>, polariton_server::operations::SimpleOpError> {
|
||||
let users = self.db.users_by_public_id(public_ids.iter()).await
|
||||
.map_err(|e| {
|
||||
log::error!("Failed to retrieve friend avatars for user {} : {}", self.account.id, e);
|
||||
polariton_server::operations::SimpleOpError::with_message(
|
||||
crate::data::error_codes::SocialErrorCode::DatabaseError as i16,
|
||||
format!("Failed to retrieve friend avatars: {}", e),
|
||||
)
|
||||
})?;
|
||||
let user_ids = users.iter().map(|user| user.id);
|
||||
let user_avatars = self.db.user_auxs_by_user_ids_and_descriptor(user_ids, oj_rc_database::schema::user_aux::Descriptor::AvatarId).await
|
||||
.map_err(|e| {
|
||||
log::error!("Failed to retrieve friend avatars for user {} : {}", self.account.id, e);
|
||||
polariton_server::operations::SimpleOpError::with_message(
|
||||
crate::data::error_codes::SocialErrorCode::DatabaseError as i16,
|
||||
format!("Failed to retrieve friend avatars: {}", e),
|
||||
)
|
||||
})?;
|
||||
let avatar_map: std::collections::HashMap<i32, u32> = user_avatars.iter()
|
||||
.filter_map(|avatar| avatar.data.parse().ok().map(|avatar_id| (avatar.user_id, avatar_id)))
|
||||
.collect();
|
||||
Ok(users.iter()
|
||||
.map(|user| super::SocialInfo {
|
||||
public_id: user.public_id.clone(),
|
||||
display_name: user.display_name.clone(),
|
||||
avatar_id: avatar_map.get(&user.id).and_then(|&avatar_id| if avatar_id == u32::MAX { None } else { Some(avatar_id as i32) }),
|
||||
})
|
||||
.collect()
|
||||
)
|
||||
}
|
||||
|
||||
async fn has_unclaimed_match_rewards(&self) -> Result<bool, polariton_server::operations::SimpleOpError> {
|
||||
let count = self.db.count_score_by_user_id_and_claimed(self.account.id, false).await
|
||||
.map_err(|e| {
|
||||
|
||||
@@ -458,6 +458,7 @@ pub trait SocialUser: Send + Sync {
|
||||
async fn cancel_friend(&self, username: String) -> Result<bool, polariton_server::operations::SimpleOpError>;
|
||||
async fn remove_friend(&self, username: String) -> Result<bool, polariton_server::operations::SimpleOpError>;
|
||||
async fn list_friends(&self) -> Result<Vec<FriendData>, polariton_server::operations::SimpleOpError>;
|
||||
async fn list_social_info(&self, public_ids: &[String]) -> Result<Vec<SocialInfo>, polariton_server::operations::SimpleOpError>;
|
||||
async fn has_unclaimed_match_rewards(&self) -> Result<bool, polariton_server::operations::SimpleOpError>;
|
||||
async fn get_unclaimed_match_rewards(&self) -> Result<MatchRewards, polariton_server::operations::SimpleOpError>;
|
||||
async fn claim_match_rewards(&self) -> Result<bool, polariton_server::operations::SimpleOpError>;
|
||||
@@ -498,6 +499,13 @@ pub struct FriendData {
|
||||
pub avatar_id: u32,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SocialInfo {
|
||||
pub public_id: String,
|
||||
pub display_name: String,
|
||||
pub avatar_id: Option<i32>,
|
||||
}
|
||||
|
||||
pub enum FriendInviteStatus {
|
||||
InviteSent,
|
||||
InvitePending,
|
||||
|
||||
Reference in New Issue
Block a user