mirror of
https://git.ngram.ca/OpenJam/rc-servers
synced 2026-08-23 23:08:52 +00:00
Implement basic battle arena functionality #32
This commit is contained in:
1 parent
1403a6e3d0
commit
7f9ed8bf35
41 files changed
+1836
-327
No files matched your search
@@ -417,6 +417,130 @@ impl UserData {
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) async fn resolve_vehicle(&self, vehicle: &crate::persist::config::VehicleInfo, factory: &dyn oj_rc_factory::VehicleFactoryAdapter, weapon_order: &crate::cubes::WeaponListParser, cpu_counter: &crate::cubes::CpuListParser) -> Result<super::ResolvedVehicle, polariton_server::operations::SimpleOpError> {
|
||||
match &vehicle.id {
|
||||
crate::persist::config::VehicleDescriptor::Factory { factory: factory_id } => {
|
||||
match factory.vehicle(*factory_id).await {
|
||||
Ok(Some(factory_vehicle)) => {
|
||||
let uuid_i64 = crate::persist::user::uuid_sanitize(crate::persist::user::i64_join((1 << 30, *factory_id)));
|
||||
let uuid_str = crate::persist::user::i64_as_uuid_str(uuid_i64);
|
||||
let weapons_guess = weapon_order.guess_weapons(&mut std::io::Cursor::new(&factory_vehicle.0.cube_data));
|
||||
let weapons_guess = vec![weapons_guess[0], 0, 0];
|
||||
let weapon_ranks = weapons_guess.iter().map(|&x| (x, if x == 0 { 0 } else { 1 })).collect();
|
||||
let cpu_count = if factory_vehicle.1.cpu == 0 {
|
||||
cpu_counter.calculate_cpu(&mut std::io::Cursor::new(&factory_vehicle.0.cube_data)).total as i32
|
||||
} else {
|
||||
factory_vehicle.1.cpu as i32
|
||||
};
|
||||
Ok(super::ResolvedVehicle {
|
||||
mastery: 1,
|
||||
tier: 1, // FIXME
|
||||
robot_name: vehicle.name.clone().unwrap_or_else(|| factory_vehicle.1.name.clone()),
|
||||
robot_map: factory_vehicle.0.cube_data,
|
||||
robot_uuid: uuid_str,
|
||||
cpu: cpu_count,
|
||||
weapon_order: weapons_guess,
|
||||
colour_map: factory_vehicle.0.colour_data,
|
||||
spawn_effect: "Spawn".to_owned(),
|
||||
death_effect: "Explosion".to_owned(),
|
||||
weapon_rank: weapon_ranks,
|
||||
})
|
||||
},
|
||||
Ok(None) => {
|
||||
log::error!("Prefab vehicle {} does not exist in factory", factory_id);
|
||||
return Err(polariton_server::operations::SimpleOpError::with_message(
|
||||
crate::data::error_codes::SingleplayerErrorCode::UnexpectedError as i16,
|
||||
format!("Prefab vehicle {} does not exist in factory", factory_id),
|
||||
));
|
||||
},
|
||||
Err(e) => {
|
||||
log::error!("Failed to retrieve prefab vehicle {} from factory: {}", factory_id, e);
|
||||
return Err(polariton_server::operations::SimpleOpError::with_message(
|
||||
crate::data::error_codes::SingleplayerErrorCode::DatabaseError as i16,
|
||||
format!("Failed to retrieve prefab vehicle {} from factory: {}", factory_id, e),
|
||||
));
|
||||
}
|
||||
}
|
||||
},
|
||||
crate::persist::config::VehicleDescriptor::Database { garage } => {
|
||||
match self.db.garage_by_id(*garage).await {
|
||||
Ok(Some(db_vehicle)) => {
|
||||
let cpu_count = if db_vehicle.total_robot_cpu <= 0 {
|
||||
cpu_counter.calculate_cpu(&mut std::io::Cursor::new(&db_vehicle.robot_data)).total as i32
|
||||
} else {
|
||||
db_vehicle.total_robot_cpu
|
||||
};
|
||||
let uuid_i64 = crate::persist::user::uuid_sanitize(crate::persist::user::i64_join((1 << 31, *garage as u32)));
|
||||
let uuid_str = crate::persist::user::i64_as_uuid_str(uuid_i64);
|
||||
Ok(super::ResolvedVehicle {
|
||||
mastery: 1,
|
||||
tier: 1, // FIXME
|
||||
robot_name: vehicle.name.clone().unwrap_or_else(|| db_vehicle.name.clone()),
|
||||
robot_map: db_vehicle.robot_data,
|
||||
robot_uuid: uuid_str,
|
||||
cpu: cpu_count,
|
||||
weapon_order: oj_rc_database::schema::parse_int_csv(&db_vehicle.weapon_order).into_iter().map(|x| x as i32).collect::<Vec<_>>(),
|
||||
colour_map: db_vehicle.colour_data,
|
||||
spawn_effect: db_vehicle.spawn_animation_id,
|
||||
death_effect: db_vehicle.death_animation_id,
|
||||
weapon_rank: oj_rc_database::schema::parse_int_csv(&db_vehicle.weapon_order).into_iter().map(|x| (x as i32, if x == 0 { 0 } else { 1 })).collect(),
|
||||
})
|
||||
},
|
||||
Ok(None) => {
|
||||
log::error!("Prefab vehicle {} does not exist in main garage database", garage);
|
||||
return Err(polariton_server::operations::SimpleOpError::with_message(
|
||||
crate::data::error_codes::SingleplayerErrorCode::UnexpectedError as i16,
|
||||
format!("Prefab vehicle {} does not exist in main garage database", garage),
|
||||
));
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("Failed to retrieve prefab vehicle {} from main garage database: {}", garage, e);
|
||||
return Err(polariton_server::operations::SimpleOpError::with_message(
|
||||
crate::data::error_codes::SingleplayerErrorCode::DatabaseError as i16,
|
||||
format!("Failed to retrieve prefab vehicle {} from main garage database: {}", garage, e),
|
||||
));
|
||||
}
|
||||
}
|
||||
},
|
||||
crate::persist::config::VehicleDescriptor::Raw {
|
||||
cube_data,
|
||||
colour_data,
|
||||
} => {
|
||||
use sha2::Digest;
|
||||
let sha_bytes = sha2::Sha256::digest(&cube_data);
|
||||
let u32_bytes = [
|
||||
sha_bytes[0],
|
||||
sha_bytes[1],
|
||||
sha_bytes[2],
|
||||
sha_bytes[3],
|
||||
];
|
||||
let uuid_i64 = crate::persist::user::uuid_sanitize(crate::persist::user::i64_join((1 << 29, u32::from_le_bytes(u32_bytes))));
|
||||
let uuid_str = crate::persist::user::i64_as_uuid_str(uuid_i64);
|
||||
let weapons_guess = weapon_order.guess_weapons(&mut std::io::Cursor::new(&cube_data));
|
||||
let weapons_guess = vec![
|
||||
weapons_guess.get(0).map(|x| *x).unwrap_or(0),
|
||||
weapons_guess.get(1).map(|x| *x).unwrap_or(0),
|
||||
weapons_guess.get(2).map(|x| *x).unwrap_or(0),
|
||||
];
|
||||
let weapon_ranks = weapons_guess.iter().map(|&x| (x, if x == 0 { 0 } else { 1 })).collect();
|
||||
let cpu_counts = cpu_counter.calculate_cpu(&mut std::io::Cursor::new(&cube_data));
|
||||
Ok(super::ResolvedVehicle {
|
||||
mastery: 1,
|
||||
tier: 1, // FIXME
|
||||
robot_name: vehicle.name.clone().unwrap_or_else(|| "Raw Robot".to_owned()),
|
||||
robot_map: cube_data.to_owned(),
|
||||
robot_uuid: uuid_str,
|
||||
cpu: cpu_counts.total as i32,
|
||||
weapon_order: weapons_guess,
|
||||
colour_map: colour_data.to_owned(),
|
||||
spawn_effect: "Spawn".to_owned(),
|
||||
death_effect: "Explosion".to_owned(),
|
||||
weapon_rank: weapon_ranks,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn resolve_some_singleplayer_vehicles(&self, factory: &dyn oj_rc_factory::VehicleFactoryAdapter, weapon_order: &crate::cubes::WeaponListParser, singleplayer_config: &crate::persist::config::SingleplayerConfig, cpu_counter: &crate::cubes::CpuListParser) -> Result<Vec<crate::data::player_data::PlayerData>, i16> {
|
||||
use rand::seq::IndexedRandom;
|
||||
let mut players = Vec::with_capacity((singleplayer_config.max_enemies + singleplayer_config.max_teammates + 1) as usize);
|
||||
@@ -439,121 +563,29 @@ impl UserData {
|
||||
};
|
||||
seen_usernames.insert(username.clone());
|
||||
let team_num = if i < singleplayer_config.max_enemies { 1 } else { 0 };
|
||||
let enemy = match &vehicle.id {
|
||||
crate::persist::config::VehicleDescriptor::Factory { factory: factory_id } => {
|
||||
//use oj_rc_factory::VehicleFactoryAdapter;
|
||||
match factory.vehicle(*factory_id).await {
|
||||
Ok(Some(factory_vehicle)) => {
|
||||
let weapons_guess = weapon_order.guess_weapons(&mut std::io::Cursor::new(&factory_vehicle.0.cube_data));
|
||||
let weapons_guess = vec![weapons_guess[0], 0, 0];
|
||||
let weapon_ranks = weapons_guess.iter().map(|&x| (x, if x == 0 { 0 } else { 1 })).collect();
|
||||
let cpu_count = if factory_vehicle.1.cpu == 0 {
|
||||
cpu_counter.calculate_cpu(&mut std::io::Cursor::new(&factory_vehicle.0.cube_data)).total as i32
|
||||
} else {
|
||||
factory_vehicle.1.cpu as i32
|
||||
};
|
||||
crate::data::player_data::PlayerData {
|
||||
name: username.clone(),
|
||||
display_name: username.clone(),
|
||||
mastery: 1,
|
||||
tier: 1, // FIXME
|
||||
robot_name: vehicle.name.clone().unwrap_or_else(|| factory_vehicle.1.name.clone()),
|
||||
robot_map: factory_vehicle.0.cube_data,
|
||||
group: None,
|
||||
team: team_num,
|
||||
has_premium: false,
|
||||
robot_uuid: uuid_str,
|
||||
cpu: cpu_count,
|
||||
avatar_id: None, // not serialised
|
||||
weapon_order: weapons_guess,
|
||||
colour_map: factory_vehicle.0.colour_data,
|
||||
is_ai: true,
|
||||
spawn_effect: "Spawn".to_owned(),
|
||||
death_effect: "Explosion".to_owned(),
|
||||
player_rank: 1,
|
||||
weapon_rank: weapon_ranks,
|
||||
}
|
||||
},
|
||||
Ok(None) => {
|
||||
log::error!("Prefab vehicle {} does not exist in factory", factory_id);
|
||||
return Err(crate::data::error_codes::SingleplayerErrorCode::UnexpectedError as i16);
|
||||
},
|
||||
Err(e) => {
|
||||
log::error!("Failed to retrieve prefab vehicle {} from factory: {}", factory_id, e);
|
||||
return Err(crate::data::error_codes::SingleplayerErrorCode::DatabaseError as i16);
|
||||
}
|
||||
}
|
||||
},
|
||||
crate::persist::config::VehicleDescriptor::Database { garage } => {
|
||||
match self.db.garage_by_id(*garage).await {
|
||||
Ok(Some(db_vehicle)) => {
|
||||
let cpu_count = if db_vehicle.total_robot_cpu <= 0 {
|
||||
cpu_counter.calculate_cpu(&mut std::io::Cursor::new(&db_vehicle.robot_data)).total as i32
|
||||
} else {
|
||||
db_vehicle.total_robot_cpu
|
||||
};
|
||||
crate::data::player_data::PlayerData {
|
||||
name: username.clone(),
|
||||
display_name: username.clone(),
|
||||
mastery: 1,
|
||||
tier: 1, // FIXME
|
||||
robot_name: vehicle.name.clone().unwrap_or_else(|| db_vehicle.name.clone()),
|
||||
robot_map: db_vehicle.robot_data,
|
||||
group: None,
|
||||
team: team_num,
|
||||
has_premium: false,
|
||||
robot_uuid: uuid_str,
|
||||
cpu: cpu_count,
|
||||
avatar_id: None, // not serialised
|
||||
weapon_order: oj_rc_database::schema::parse_int_csv(&db_vehicle.weapon_order).into_iter().map(|x| x as i32).collect::<Vec<_>>(),
|
||||
colour_map: db_vehicle.colour_data,
|
||||
is_ai: true,
|
||||
spawn_effect: "Spawn".to_owned(),
|
||||
death_effect: "Explosion".to_owned(),
|
||||
player_rank: 1,
|
||||
weapon_rank: oj_rc_database::schema::parse_int_csv(&db_vehicle.weapon_order).into_iter().map(|x| (x as i32, if x == 0 { 0 } else { 1 })).collect(),
|
||||
}
|
||||
},
|
||||
Ok(None) => {
|
||||
log::error!("Prefab vehicle {} does not exist in main garage database", garage);
|
||||
return Err(crate::data::error_codes::SingleplayerErrorCode::UnexpectedError as i16);
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("Failed to retrieve prefab vehicle {} from main garage database: {}", garage, e);
|
||||
return Err(crate::data::error_codes::SingleplayerErrorCode::DatabaseError as i16);
|
||||
}
|
||||
}
|
||||
},
|
||||
crate::persist::config::VehicleDescriptor::Raw {
|
||||
cube_data,
|
||||
colour_data,
|
||||
} => {
|
||||
let weapons_guess = weapon_order.guess_weapons(&mut std::io::Cursor::new(&cube_data));
|
||||
let weapons_guess = vec![weapons_guess[0], 0, 0];
|
||||
let weapon_ranks = weapons_guess.iter().map(|&x| (x, if x == 0 { 0 } else { 1 })).collect();
|
||||
let cpu_counts = cpu_counter.calculate_cpu(&mut std::io::Cursor::new(&cube_data));
|
||||
crate::data::player_data::PlayerData {
|
||||
name: username.clone(),
|
||||
display_name: username.clone(),
|
||||
mastery: 1,
|
||||
tier: 1, // FIXME
|
||||
robot_name: vehicle.name.clone().unwrap_or_else(|| "Raw Robot".to_owned()),
|
||||
robot_map: cube_data.to_owned(),
|
||||
group: None,
|
||||
team: team_num,
|
||||
has_premium: false,
|
||||
robot_uuid: uuid_str,
|
||||
cpu: cpu_counts.total as i32,
|
||||
avatar_id: None, // not serialised
|
||||
weapon_order: weapons_guess,
|
||||
colour_map: colour_data.to_owned(),
|
||||
is_ai: true,
|
||||
spawn_effect: "Spawn".to_owned(),
|
||||
death_effect: "Explosion".to_owned(),
|
||||
player_rank: 1,
|
||||
weapon_rank: weapon_ranks,
|
||||
}
|
||||
}
|
||||
let enemy_vehicle = self.resolve_vehicle(vehicle, factory, weapon_order, cpu_counter).await?;
|
||||
let weapons = vec![enemy_vehicle.weapon_order[0], 0, 0];
|
||||
let weapon_ranks = weapons.iter().map(|&x| (x, if x == 0 { 0 } else { 1 })).collect();
|
||||
let enemy = crate::data::player_data::PlayerData {
|
||||
name: username.clone(),
|
||||
display_name: username.clone(),
|
||||
mastery: enemy_vehicle.mastery,
|
||||
tier: enemy_vehicle.tier,
|
||||
robot_name: enemy_vehicle.robot_name,
|
||||
robot_map: enemy_vehicle.robot_map,
|
||||
group: None,
|
||||
team: team_num,
|
||||
has_premium: false,
|
||||
robot_uuid: uuid_str,
|
||||
cpu: enemy_vehicle.cpu,
|
||||
avatar_id: None, // not serialised
|
||||
weapon_order: weapons,
|
||||
colour_map: enemy_vehicle.colour_map,
|
||||
is_ai: true,
|
||||
spawn_effect: enemy_vehicle.spawn_effect,
|
||||
death_effect: enemy_vehicle.death_effect,
|
||||
player_rank: 1,
|
||||
weapon_rank: weapon_ranks,
|
||||
};
|
||||
next_id += 1;
|
||||
players.push(enemy);
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
use super::account_json::UserData;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl super::CommonUser for UserData {
|
||||
async fn resolve_config_vehicle(&self, vehicle: &crate::persist::config::VehicleInfo, factory: &dyn oj_rc_factory::VehicleFactoryAdapter, weapon_order: &crate::cubes::WeaponListParser, cpu_counter: &crate::cubes::CpuListParser) -> Result<super::ResolvedVehicle, polariton_server::operations::SimpleOpError> {
|
||||
self.resolve_vehicle(vehicle, factory, weapon_order, cpu_counter).await
|
||||
}
|
||||
}
|
||||
@@ -11,13 +11,14 @@ mod inventory;
|
||||
pub use inventory::UnlockedParts;
|
||||
|
||||
mod traits;
|
||||
pub use traits::{UserProvider, User, UserToken, UserSlots, UserSlotData, VehicleData, UserInfo, UserLoginInfo, ExtraUserInfo, UserAuthenticator, NewSlotData, UserId, RegistrationInfo, VehicleUploadData, ChatUser, AvatarInfo, GetAvatarInfo, ControlData, ControlType, CustomisationData, GetCustomisationData, SetSanction, SanctionType, LobbyUser, GameDescriptor, PlayerLobbyDescriptor, MultiplayerUser, MultiplayerError, MultiplayerErrorCode, PlayerDescriptor, GameEventSetter, CurrentGameEvent, AuthError, IntercomUser, FakePlayers};
|
||||
pub use traits::{UserProvider, User, UserToken, UserSlots, UserSlotData, VehicleData, UserInfo, UserLoginInfo, ExtraUserInfo, UserAuthenticator, NewSlotData, UserId, RegistrationInfo, VehicleUploadData, ChatUser, AvatarInfo, GetAvatarInfo, ControlData, ControlType, CustomisationData, GetCustomisationData, SetSanction, SanctionType, LobbyUser, GameDescriptor, PlayerLobbyDescriptor, MultiplayerUser, MultiplayerError, MultiplayerErrorCode, PlayerDescriptor, GameEventSetter, CurrentGameEvent, AuthError, IntercomUser, FakePlayers, ResolvedVehicle, CommonUser};
|
||||
|
||||
mod intercom;
|
||||
pub use intercom::generate_token as generate_intercom_token;
|
||||
|
||||
mod multiplayer;
|
||||
mod lobby;
|
||||
mod common;
|
||||
|
||||
pub const TOKEN_SECRET_FILENAME: &str = "token_secret.key";
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ pub trait UserAuthenticator {
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
pub trait User<C>: ChatUser + LobbyUser + MultiplayerUser + IntercomUser {
|
||||
pub trait User<C>: ChatUser + LobbyUser + MultiplayerUser + IntercomUser + CommonUser {
|
||||
fn public_id(&self) -> &'_ str;
|
||||
fn is_mod(&self) -> bool;
|
||||
fn is_admin(&self) -> bool;
|
||||
@@ -203,7 +203,7 @@ pub struct AvatarInfo {
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
pub trait ChatUser {
|
||||
pub trait ChatUser: CommonUser {
|
||||
async fn subscribed_channels(&self) -> Result<polariton::operation::Typed<()>, i16>;
|
||||
async fn subscribed_channels_strings(&self) -> Result<Vec<String>, i16>;
|
||||
async fn add_subscribed_channel(&self, channel: String, channel_ty: crate::data::channel::ChatChannelType) -> Result<polariton::operation::Typed<()>, i16>;
|
||||
@@ -325,7 +325,7 @@ pub enum MultiplayerErrorCode {
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
pub trait MultiplayerUser {
|
||||
pub trait MultiplayerUser: CommonUser {
|
||||
fn user_id(&self) -> i32;
|
||||
fn user_name(&self) -> &'_ str;
|
||||
fn display_name(&self) -> &'_ str;
|
||||
@@ -339,3 +339,22 @@ pub trait MultiplayerUser {
|
||||
pub trait IntercomUser {
|
||||
async fn save_custom_avatar(&self, image: Vec<u8>) -> Result<(), polariton_server::operations::SimpleOpError>;
|
||||
}
|
||||
|
||||
pub struct ResolvedVehicle {
|
||||
pub mastery: i32,
|
||||
pub tier: i32,
|
||||
pub robot_name: String,
|
||||
pub robot_map: Vec<u8>,
|
||||
pub robot_uuid: String,
|
||||
pub cpu: i32,
|
||||
pub weapon_order: Vec<i32>,
|
||||
pub colour_map: Vec<u8>,
|
||||
pub spawn_effect: String,
|
||||
pub death_effect: String,
|
||||
pub weapon_rank: std::collections::HashMap<i32, i32>,
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
pub trait CommonUser: Send + Sync {
|
||||
async fn resolve_config_vehicle(&self, vehicle: &crate::persist::config::VehicleInfo, factory: &dyn oj_rc_factory::VehicleFactoryAdapter, weapon_order: &crate::cubes::WeaponListParser, cpu_counter: &crate::cubes::CpuListParser) -> Result<ResolvedVehicle, polariton_server::operations::SimpleOpError>;
|
||||
}
|
||||
Reference in new issue
Block a user