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:
@@ -10,6 +10,7 @@ authors.workspace = true
|
||||
[dependencies]
|
||||
log.workspace = true
|
||||
polariton.workspace = true
|
||||
base64 = "0.22"
|
||||
hex = "0.4"
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
|
||||
92
rc_core/src/cubes/locations_of.rs
Normal file
92
rc_core/src/cubes/locations_of.rs
Normal file
@@ -0,0 +1,92 @@
|
||||
pub struct CubeLocationsParser;
|
||||
|
||||
pub struct CubeLocationInfo {
|
||||
pub x: u8,
|
||||
pub y: u8,
|
||||
pub z: u8,
|
||||
extras: u8,
|
||||
}
|
||||
|
||||
impl CubeLocationInfo {
|
||||
pub fn orientation(&self) -> u8 {
|
||||
self.extras & 0x7F
|
||||
}
|
||||
|
||||
pub fn is_destroyed(&self) -> bool {
|
||||
self.extras & 0x80 != 0
|
||||
}
|
||||
}
|
||||
|
||||
impl CubeLocationsParser {
|
||||
pub fn with_cubes<'a, I: std::iter::Iterator<Item=&'a crate::persist::Cube>>(_iter: I) -> Self {
|
||||
Self
|
||||
}
|
||||
|
||||
pub fn locations_of(&self, r: &mut dyn std::io::Read, cube_id: u32) -> Vec<CubeLocationInfo> {
|
||||
match super::parser::Cube::parse_list(r) {
|
||||
Ok(cubes) => {
|
||||
cubes.into_iter()
|
||||
.filter(|x| x.id == cube_id)
|
||||
.map(|cube| CubeLocationInfo {
|
||||
x: cube.x,
|
||||
y: cube.y,
|
||||
z: cube.z,
|
||||
extras: cube.orientation,
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("Failed to parse cube data to find cube locations: {}", e);
|
||||
Vec::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn locations_of_by_distance_to_first(&self, r: &mut dyn std::io::Read, locations_of_id: u32, distance_to_id: u32) -> Vec<CubeLocationInfo> {
|
||||
match super::parser::Cube::parse_list(r) {
|
||||
Ok(cubes) => {
|
||||
if let Some(target) = cubes.iter().filter(|x| x.id == distance_to_id).next() {
|
||||
let target_x = target.x as f32;
|
||||
let target_y = target.y as f32;
|
||||
let target_z = target.z as f32;
|
||||
let mut relevant_cubes: Vec<(f32, CubeLocationInfo)> = cubes.into_iter()
|
||||
.filter(|x| x.id == locations_of_id)
|
||||
.map(|cube| {
|
||||
let distance = (
|
||||
(cube.x as f32 - target_x).powi(2)
|
||||
+ (cube.y as f32 - target_y).powi(2)
|
||||
+ (cube.z as f32 - target_z).powi(2)
|
||||
).sqrt();
|
||||
(distance, CubeLocationInfo {
|
||||
x: cube.x,
|
||||
y: cube.y,
|
||||
z: cube.z,
|
||||
extras: cube.orientation,
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
relevant_cubes.sort_by_key(|(distance, _)| (distance * 1_000_000.0) as i64);
|
||||
relevant_cubes.into_iter()
|
||||
.map(|(_, cube)| cube)
|
||||
.collect()
|
||||
} else {
|
||||
log::warn!("No cube with id {} to calculate distance", distance_to_id);
|
||||
cubes.into_iter()
|
||||
.filter(|x| x.id == locations_of_id)
|
||||
.map(|cube| CubeLocationInfo {
|
||||
x: cube.x,
|
||||
y: cube.y,
|
||||
z: cube.z,
|
||||
extras: cube.orientation,
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("Failed to parse cube data to find cube locations: {}", e);
|
||||
Vec::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,9 +6,15 @@ pub use weapon_list::WeaponListParser;
|
||||
mod cpu_count;
|
||||
pub use cpu_count::CpuListParser;
|
||||
|
||||
mod locations_of;
|
||||
pub use locations_of::{CubeLocationsParser, CubeLocationInfo};
|
||||
|
||||
//pub mod prefabs;
|
||||
|
||||
pub struct CubeParsers {
|
||||
weapon_list: std::sync::Arc<WeaponListParser>,
|
||||
cpu_counter: std::sync::Arc<CpuListParser>,
|
||||
locations: std::sync::Arc<CubeLocationsParser>,
|
||||
}
|
||||
|
||||
impl CubeParsers {
|
||||
@@ -17,6 +23,7 @@ impl CubeParsers {
|
||||
Self {
|
||||
weapon_list: std::sync::Arc::new(WeaponListParser::with_cubes(cubes.values())),
|
||||
cpu_counter: std::sync::Arc::new(CpuListParser::with_cubes(cubes.values())),
|
||||
locations: std::sync::Arc::new(CubeLocationsParser::with_cubes(cubes.values())),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,4 +34,8 @@ impl CubeParsers {
|
||||
pub fn cpu_counter(&self) -> std::sync::Arc<CpuListParser> {
|
||||
self.cpu_counter.clone()
|
||||
}
|
||||
|
||||
pub fn locations_of(&self) -> std::sync::Arc<CubeLocationsParser> {
|
||||
self.locations.clone()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
use std::io::Write;
|
||||
|
||||
pub struct Cube {
|
||||
pub id: u32,
|
||||
pub x: u8,
|
||||
@@ -35,6 +37,22 @@ impl Cube {
|
||||
}
|
||||
Ok(cubes)
|
||||
}
|
||||
|
||||
pub fn dump(&self, w: &mut dyn std::io::Write) -> std::io::Result<usize> {
|
||||
w.write_all(&self.id.to_le_bytes())?;
|
||||
w.write_all(&[self.x, self.y, self.z, self.orientation])?;
|
||||
Ok(8)
|
||||
}
|
||||
|
||||
pub fn dump_list(items: Vec<Self>) -> std::io::Result<Vec<u8>> {
|
||||
let mut buf = Vec::with_capacity(4 + (items.len() * 8));
|
||||
let mut dumped = std::io::Cursor::new(&mut buf);
|
||||
dumped.write_all(&(items.len() as u32).to_le_bytes())?;
|
||||
for item in items {
|
||||
item.dump(&mut dumped)?;
|
||||
}
|
||||
Ok(buf)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Colour {
|
||||
|
||||
44
rc_core/src/data/battle_arena_config.rs
Normal file
44
rc_core/src/data/battle_arena_config.rs
Normal file
@@ -0,0 +1,44 @@
|
||||
use polariton::operation::Typed;
|
||||
use base64::{Engine, engine::general_purpose::STANDARD};
|
||||
|
||||
pub struct BattleArenaData {
|
||||
pub protonium_health: i64,
|
||||
pub respawn_time_seconds: i64,
|
||||
pub heal_over_time_per_tower: Vec<u64>,
|
||||
pub base_machine_map: Vec<u8>, // aka team base model, converted into base64
|
||||
pub equalizer_model: Vec<u8>, // converted into base64
|
||||
pub equalizer_health: i64,
|
||||
pub equalizer_trigger_time_seconds: Vec<u64>,
|
||||
pub equalizer_warning_seconds: i64,
|
||||
pub equalizer_duration_seconds: Vec<u64>,
|
||||
pub capture_time_seconds_per_player: Vec<i64>,
|
||||
pub num_segments: i32,
|
||||
pub heal_escalation_time_seconds: i64,
|
||||
}
|
||||
|
||||
fn to_obj_arr_u<C>(slice: &[u64]) -> Typed<C> {
|
||||
Typed::<C>::ObjArr(slice.iter().map(|x| Typed::<C>::Long(*x as i64)).collect::<Vec<Typed<C>>>().into())
|
||||
}
|
||||
|
||||
fn to_obj_arr_i<C>(slice: &[i64]) -> Typed<C> {
|
||||
Typed::<C>::ObjArr(slice.iter().map(|x| Typed::<C>::Long(*x)).collect::<Vec<Typed<C>>>().into())
|
||||
}
|
||||
|
||||
impl BattleArenaData {
|
||||
pub fn as_transmissible<C>(&self) -> Typed<C> {
|
||||
Typed::HashMap(vec![
|
||||
(Typed::Str("protoniumHealth".into()), Typed::Long(self.protonium_health)),
|
||||
(Typed::Str("respawnTimeSeconds".into()), Typed::Long(self.respawn_time_seconds)),
|
||||
(Typed::Str("healOverTimePerTower".into()), to_obj_arr_u(&self.heal_over_time_per_tower)),
|
||||
(Typed::Str("baseMachineMap".into()), Typed::Str(STANDARD.encode(&self.base_machine_map).into())),
|
||||
(Typed::Str("equalizerModel".into()), Typed::Str(STANDARD.encode(&self.equalizer_model).into())),
|
||||
(Typed::Str("equalizerHealth".into()), Typed::Long(self.equalizer_health)),
|
||||
(Typed::Str("equalizerTriggerTimeSeconds".into()), to_obj_arr_u(&self.equalizer_trigger_time_seconds)),
|
||||
(Typed::Str("equalizerWarningSeconds".into()), Typed::Long(self.equalizer_warning_seconds)),
|
||||
(Typed::Str("equalizerDurationSeconds".into()), to_obj_arr_u(&self.equalizer_duration_seconds)),
|
||||
(Typed::Str("captureTimeSecondsPerPlayer".into()), to_obj_arr_i(&self.capture_time_seconds_per_player)),
|
||||
(Typed::Str("numSegments".into()), Typed::Int(self.num_segments)),
|
||||
(Typed::Str("healEscalationTimeSeconds".into()), Typed::Long(self.heal_escalation_time_seconds)),
|
||||
].into())
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ pub mod channel;
|
||||
pub mod sanction;
|
||||
pub mod robot_data;
|
||||
pub mod lobby;
|
||||
pub mod battle_arena_config;
|
||||
|
||||
pub mod error_codes;
|
||||
|
||||
|
||||
@@ -248,7 +248,7 @@ fn default_game_modes() -> GameModes {
|
||||
respawn_heal_duration: 10.0,
|
||||
respawn_full_heal_duration: 0.5,
|
||||
kill_limit: 0,
|
||||
game_time_m: 20,
|
||||
game_time_m: 5,
|
||||
},
|
||||
elimination: GameMode {
|
||||
respawn_heal_duration: 10.0,
|
||||
@@ -369,6 +369,21 @@ fn default_rotation() -> GameEventSequence {
|
||||
strategy: GameRotationStrategy::Sequence,
|
||||
modes: vec![
|
||||
GameEvents {
|
||||
singleplayer: GameEvent {
|
||||
map: GameMap::Earth1,
|
||||
visibility: GameVisibility::Good,
|
||||
mode: GameType::BattleArena,
|
||||
auto_heal: true,
|
||||
},
|
||||
multiplayer: GameEvent {
|
||||
map: GameMap::Earth1,
|
||||
visibility: GameVisibility::Good,
|
||||
mode: GameType::BattleArena,
|
||||
auto_heal: true,
|
||||
},
|
||||
duration_s: 5*60, // 5 minutes
|
||||
}
|
||||
/*GameEvents {
|
||||
singleplayer: GameEvent {
|
||||
map: GameMap::Neptune1,
|
||||
visibility: GameVisibility::Good,
|
||||
@@ -487,7 +502,7 @@ fn default_rotation() -> GameEventSequence {
|
||||
auto_heal: true,
|
||||
},
|
||||
duration_s: 5*60,
|
||||
},
|
||||
},*/
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -498,6 +513,7 @@ fn default_multiplayer() -> super::MultiplayerConfig {
|
||||
enabled: true,
|
||||
network: super::multiplayer::default_net_conf(),
|
||||
fakes: super::multiplayer::default_fake_users(),
|
||||
battle_arena: super::multiplayer::default_ba_conf(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -410,9 +410,18 @@ impl <C: Clone + Send> super::ConfigProvider<C> for CubeConfig {
|
||||
z: base.z,
|
||||
},
|
||||
}, base.percent_per_second))).collect();
|
||||
let capture_points = conf.capture_points.iter().map(|point| (super::Sphere {
|
||||
radius: point.radius,
|
||||
center: super::Point {
|
||||
x: point.x,
|
||||
y: point.y,
|
||||
z: point.z,
|
||||
}
|
||||
}, point.percent_per_second)).collect();
|
||||
let map_conf = super::MapConfig {
|
||||
spawns,
|
||||
bases,
|
||||
capture_points,
|
||||
};
|
||||
(map.into_conf(), map_conf)
|
||||
}).collect()
|
||||
@@ -441,4 +450,10 @@ impl <C: Clone + Send> super::ConfigProvider<C> for CubeConfig {
|
||||
total: self.battle.energy.total,
|
||||
}
|
||||
}
|
||||
|
||||
fn ba_settings(&self) -> super::BattleArenaResolver {
|
||||
super::BattleArenaResolver {
|
||||
data: self.battle.multiplayer.battle_arena.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ mod cubes_json;
|
||||
pub use cubes_json::CubeConfig;
|
||||
|
||||
mod traits;
|
||||
pub use traits::{ConfigProvider, CompleteCampaignProvider, DevMessageProvider, ServerConfig, GarageUpgrades, GarageUpgradeIncrement, ChatSystemConfig, GameEventSequence, GameEvents, GameRotationStrategy, GameEvent, GameMap, GameVisibility, GameType, SingleplayerConfig, VehicleInfo, VehicleDescriptor, QueueChangeMode, Point, Sphere, MapConfig, LinksConfig, FakePlayer, ClientEmulator, EnergyConfig};
|
||||
pub use traits::{ConfigProvider, CompleteCampaignProvider, DevMessageProvider, ServerConfig, GarageUpgrades, GarageUpgradeIncrement, ChatSystemConfig, GameEventSequence, GameEvents, GameRotationStrategy, GameEvent, GameMap, GameVisibility, GameType, SingleplayerConfig, VehicleInfo, VehicleDescriptor, QueueChangeMode, Point, Sphere, MapConfig, LinksConfig, FakePlayer, ClientEmulator, EnergyConfig, BattleArenaResolver};
|
||||
|
||||
pub type ConfigImpl = CubeConfig;
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ pub trait ConfigProvider<C: Clone> {
|
||||
fn url_links(&self) -> LinksConfig;
|
||||
fn fake_players(&self) -> Vec<FakePlayer>;
|
||||
fn energy(&self) -> EnergyConfig;
|
||||
fn ba_settings(&self) -> BattleArenaResolver;
|
||||
}
|
||||
|
||||
pub struct CompleteCampaignProvider {
|
||||
@@ -358,7 +359,8 @@ pub struct Sphere {
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MapConfig {
|
||||
pub spawns: std::collections::HashMap<u8, Vec<Point>>, // team -> points
|
||||
pub bases: std::collections::HashMap<u8, (Sphere, f32)>, // team -> base
|
||||
pub bases: std::collections::HashMap<u8, (Sphere, f32)>, // team -> (base, capture speed)
|
||||
pub capture_points: Vec<(Sphere, f32)>, // (capture point, capture speed)
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@@ -386,3 +388,38 @@ pub struct EnergyConfig {
|
||||
pub refill_rate: f32,
|
||||
pub total: u32,
|
||||
}
|
||||
|
||||
pub struct BattleArenaResolver {
|
||||
pub(super) data: crate::persist::multiplayer::BattleArenaConfig,
|
||||
}
|
||||
|
||||
impl BattleArenaResolver {
|
||||
pub async fn resolve(&self, user: &dyn crate::persist::user::CommonUser, factory: &crate::factory::Factory, weapon_list: &crate::cubes::WeaponListParser, cpu_counter: &crate::cubes::CpuListParser) -> Result<crate::data::battle_arena_config::BattleArenaData, polariton_server::operations::SimpleOpError> {
|
||||
let equalizer_data = user.resolve_config_vehicle(&self.data.equalizer.clone().into_conf(), factory, weapon_list, cpu_counter).await?;
|
||||
let base_data = user.resolve_config_vehicle(&self.data.base.clone().into_conf(), factory, weapon_list, cpu_counter).await?;
|
||||
Ok(crate::data::battle_arena_config::BattleArenaData {
|
||||
protonium_health: self.data.crystal_health as i64,
|
||||
respawn_time_seconds: self.data.respawn_time_s as i64,
|
||||
heal_over_time_per_tower: vec![10, 10, 10, 10], // Unused?
|
||||
base_machine_map: base_data.robot_map,
|
||||
equalizer_model: equalizer_data.robot_map,
|
||||
equalizer_health: self.data.equalizer_health as i64,
|
||||
equalizer_trigger_time_seconds: vec![10, 10, 10, 10, 10], // TODO
|
||||
equalizer_warning_seconds: self.data.equalizer_warning_s as i64, // TODO
|
||||
equalizer_duration_seconds: vec![20, 20, 20, 20, 20], // TODO
|
||||
capture_time_seconds_per_player: vec![30, 20, 10, 5, 1], // TODO
|
||||
num_segments: self.data.num_segments as i32,
|
||||
heal_escalation_time_seconds: 5, // Unused?
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn resolve_typed<C>(&self, user: &dyn crate::persist::user::CommonUser, factory: &crate::factory::Factory, weapon_list: &crate::cubes::WeaponListParser, cpu_counter: &crate::cubes::CpuListParser) -> Result<Typed<C>, polariton_server::operations::SimpleOpError> {
|
||||
Ok(Typed::Dict(polariton::operation::Dict {
|
||||
key_ty: polariton::serdes::TypePrefix::Str, // str
|
||||
val_ty: polariton::serdes::TypePrefix::HashMap, // hashmap
|
||||
items: vec![
|
||||
(Typed::Str("BattleArenaSettings".into()), self.resolve(user, factory, weapon_list, cpu_counter).await?.as_transmissible())
|
||||
],
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,6 +185,16 @@ pub struct PrefabVehicle {
|
||||
pub id: PrefabId,
|
||||
}
|
||||
|
||||
impl PrefabVehicle {
|
||||
pub(super) fn into_conf(&self) -> super::config::VehicleInfo {
|
||||
crate::persist::config::VehicleInfo {
|
||||
name: self.name.clone(),
|
||||
username: self.username.clone(),
|
||||
id: self.id.clone().into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
#[serde(untagged)]
|
||||
pub enum PrefabId {
|
||||
|
||||
@@ -10,6 +10,7 @@ pub struct MapsConfig {
|
||||
pub struct MapConfig {
|
||||
pub spawn_points: Vec<SpawnPoint>,
|
||||
pub bases: Vec<CaptureBase>,
|
||||
pub capture_points: Vec<CapturePoint>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
@@ -35,13 +36,12 @@ impl SpawnPoint {
|
||||
self
|
||||
}
|
||||
|
||||
fn rotated_from(mut self, x: f32, y: f32, z: f32, rot: num_quaternion::Quaternion<f32>) -> Self {
|
||||
if let Some(unit_rot) = rot.normalize() {
|
||||
let rotated = unit_rot.rotate_vector([self.x, self.y, self.z]);
|
||||
self.x = rotated[0] + x;
|
||||
self.y = rotated[1] + y;
|
||||
self.z = rotated[2] + z;
|
||||
}
|
||||
fn rotated(mut self, rot: num_quaternion::Quaternion<f32>) -> Self {
|
||||
let unit_rot = rot.normalize().expect("Bad rotation quaternion for SpawnPoint");
|
||||
let rotated = unit_rot.rotate_vector([self.x, self.y, self.z]);
|
||||
self.x = rotated[0];
|
||||
self.y = rotated[1];
|
||||
self.z = rotated[2];
|
||||
self
|
||||
}
|
||||
}
|
||||
@@ -65,8 +65,37 @@ impl CaptureBase {
|
||||
}
|
||||
}
|
||||
|
||||
const DEFAULT_PERCENT_PER_SECOND: f32 = 2.5;
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct CapturePoint {
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
pub z: f32,
|
||||
pub radius: f32,
|
||||
pub percent_per_second: f32,
|
||||
}
|
||||
|
||||
impl CapturePoint {
|
||||
const fn offset(mut self, x: f32, y: f32, z: f32) -> Self {
|
||||
self.x += x;
|
||||
self.y += y;
|
||||
self.z += z;
|
||||
self
|
||||
}
|
||||
|
||||
fn rotated(mut self, rot: num_quaternion::Quaternion<f32>) -> Self {
|
||||
let unit_rot = rot.normalize().expect("Bad rotation quaternion for CapturePoint");
|
||||
let rotated = unit_rot.rotate_vector([self.x, self.y, self.z]);
|
||||
self.x = rotated[0];
|
||||
self.y = rotated[1];
|
||||
self.z = rotated[2];
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
const DEFAULT_BASE_PERCENT_PER_SECOND: f32 = 2.5;
|
||||
const DEFAULT_BASE_RADIUS: f32 = 20.0;
|
||||
const DEFAULT_CAPTURE_PERCENT_PER_SECOND: f32 = DEFAULT_BASE_PERCENT_PER_SECOND * 1.5;
|
||||
const DEFAULT_CAPTURE_RADIUS: f32 = 14.0;
|
||||
|
||||
pub(super) fn default_map() -> std::collections::HashMap<super::combat::GameMap, MapConfig> {
|
||||
let mut map = std::collections::HashMap::with_capacity(9);
|
||||
@@ -204,7 +233,7 @@ pub(super) fn default_map() -> std::collections::HashMap<super::combat::GameMap,
|
||||
y: 2.700,
|
||||
z: -240.888,
|
||||
radius: DEFAULT_BASE_RADIUS,
|
||||
percent_per_second: DEFAULT_PERCENT_PER_SECOND,
|
||||
percent_per_second: DEFAULT_BASE_PERCENT_PER_SECOND,
|
||||
},
|
||||
CaptureBase {
|
||||
team: 1,
|
||||
@@ -212,9 +241,37 @@ pub(super) fn default_map() -> std::collections::HashMap<super::combat::GameMap,
|
||||
y: 2.770,
|
||||
z: 243.600,
|
||||
radius: DEFAULT_BASE_RADIUS,
|
||||
percent_per_second: DEFAULT_PERCENT_PER_SECOND,
|
||||
percent_per_second: DEFAULT_BASE_PERCENT_PER_SECOND,
|
||||
},
|
||||
],
|
||||
capture_points: vec![
|
||||
CapturePoint {
|
||||
x: 177.240,
|
||||
y: -0.264,
|
||||
z: 141.540,
|
||||
radius: DEFAULT_CAPTURE_RADIUS,
|
||||
percent_per_second: DEFAULT_CAPTURE_PERCENT_PER_SECOND,
|
||||
},
|
||||
CapturePoint {
|
||||
x: -9.480,
|
||||
y: 30.396,
|
||||
z: -164.676,
|
||||
radius: DEFAULT_CAPTURE_RADIUS,
|
||||
percent_per_second: DEFAULT_CAPTURE_PERCENT_PER_SECOND,
|
||||
},
|
||||
CapturePoint {
|
||||
x: -197.400,
|
||||
y: -0.228,
|
||||
z: 142.452,
|
||||
radius: DEFAULT_CAPTURE_RADIUS,
|
||||
percent_per_second: DEFAULT_CAPTURE_PERCENT_PER_SECOND,
|
||||
}
|
||||
].into_iter().map(|p| p.rotated(num_quaternion::Quaternion {
|
||||
w: 0.707107,
|
||||
x: 0.0,
|
||||
y: 0.707107,
|
||||
z: 0.0,
|
||||
}).offset(13.320, 0.0, -9.84)).collect(),
|
||||
});
|
||||
map.insert(super::combat::GameMap::Earth2, MapConfig { // level4
|
||||
spawn_points: vec![
|
||||
@@ -400,12 +457,12 @@ pub(super) fn default_map() -> std::collections::HashMap<super::combat::GameMap,
|
||||
y: -71.445,
|
||||
z: 266.000,
|
||||
},
|
||||
].into_iter().map(|x| x.rotated_from(0.0, 86.718, 0.0, num_quaternion::Quaternion {
|
||||
].into_iter().map(|x| x.rotated(num_quaternion::Quaternion {
|
||||
x: 0.0,
|
||||
y: 0.707107,
|
||||
z: 0.0,
|
||||
w: 0.707107,
|
||||
})).collect(),
|
||||
}).offset(0.0, 86.718, 0.0)).collect(),
|
||||
bases: vec![
|
||||
CaptureBase {
|
||||
team: 0,
|
||||
@@ -413,7 +470,7 @@ pub(super) fn default_map() -> std::collections::HashMap<super::combat::GameMap,
|
||||
y: 13.900,
|
||||
z: -253.920,
|
||||
radius: DEFAULT_BASE_RADIUS,
|
||||
percent_per_second: DEFAULT_PERCENT_PER_SECOND,
|
||||
percent_per_second: DEFAULT_BASE_PERCENT_PER_SECOND,
|
||||
},
|
||||
CaptureBase {
|
||||
team: 1,
|
||||
@@ -421,9 +478,10 @@ pub(super) fn default_map() -> std::collections::HashMap<super::combat::GameMap,
|
||||
y: 13.900,
|
||||
z: 259.200,
|
||||
radius: DEFAULT_BASE_RADIUS,
|
||||
percent_per_second: DEFAULT_PERCENT_PER_SECOND,
|
||||
percent_per_second: DEFAULT_BASE_PERCENT_PER_SECOND,
|
||||
},
|
||||
],
|
||||
capture_points: vec![], // TODO
|
||||
});
|
||||
map.insert(super::combat::GameMap::Mars1, MapConfig {
|
||||
spawn_points: vec![
|
||||
@@ -557,7 +615,7 @@ pub(super) fn default_map() -> std::collections::HashMap<super::combat::GameMap,
|
||||
y: 4.09,
|
||||
z: 20.3,
|
||||
radius: DEFAULT_BASE_RADIUS,
|
||||
percent_per_second: DEFAULT_PERCENT_PER_SECOND,
|
||||
percent_per_second: DEFAULT_BASE_PERCENT_PER_SECOND,
|
||||
},
|
||||
CaptureBase {
|
||||
team: 1,
|
||||
@@ -565,9 +623,10 @@ pub(super) fn default_map() -> std::collections::HashMap<super::combat::GameMap,
|
||||
y: 10.63,
|
||||
z: 372.20,
|
||||
radius: DEFAULT_BASE_RADIUS,
|
||||
percent_per_second: DEFAULT_PERCENT_PER_SECOND,
|
||||
percent_per_second: DEFAULT_BASE_PERCENT_PER_SECOND,
|
||||
},
|
||||
],
|
||||
capture_points: vec![], // TODO
|
||||
});
|
||||
map.insert(super::combat::GameMap::Mars2, MapConfig {
|
||||
spawn_points: vec![
|
||||
@@ -701,7 +760,7 @@ pub(super) fn default_map() -> std::collections::HashMap<super::combat::GameMap,
|
||||
y: 21.140,
|
||||
z: 187.560,
|
||||
radius: DEFAULT_BASE_RADIUS,
|
||||
percent_per_second: DEFAULT_PERCENT_PER_SECOND,
|
||||
percent_per_second: DEFAULT_BASE_PERCENT_PER_SECOND,
|
||||
},
|
||||
CaptureBase {
|
||||
team: 1,
|
||||
@@ -709,9 +768,10 @@ pub(super) fn default_map() -> std::collections::HashMap<super::combat::GameMap,
|
||||
y: 21.230,
|
||||
z: 620.280,
|
||||
radius: DEFAULT_BASE_RADIUS,
|
||||
percent_per_second: DEFAULT_PERCENT_PER_SECOND,
|
||||
percent_per_second: DEFAULT_BASE_PERCENT_PER_SECOND,
|
||||
},
|
||||
].into_iter().map(|x| x.offset(-434.640, 0.0, -414.720)).collect(),
|
||||
capture_points: vec![], // TODO
|
||||
});
|
||||
map.insert(super::combat::GameMap::Mars3, MapConfig {
|
||||
spawn_points: vec![
|
||||
@@ -845,7 +905,7 @@ pub(super) fn default_map() -> std::collections::HashMap<super::combat::GameMap,
|
||||
y: 32.340,
|
||||
z: -309.720,
|
||||
radius: DEFAULT_BASE_RADIUS,
|
||||
percent_per_second: DEFAULT_PERCENT_PER_SECOND,
|
||||
percent_per_second: DEFAULT_BASE_PERCENT_PER_SECOND,
|
||||
},
|
||||
CaptureBase {
|
||||
team: 1,
|
||||
@@ -853,9 +913,10 @@ pub(super) fn default_map() -> std::collections::HashMap<super::combat::GameMap,
|
||||
y: 32.320,
|
||||
z: 207.360,
|
||||
radius: DEFAULT_BASE_RADIUS,
|
||||
percent_per_second: DEFAULT_PERCENT_PER_SECOND,
|
||||
percent_per_second: DEFAULT_BASE_PERCENT_PER_SECOND,
|
||||
},
|
||||
].into_iter().map(|x| x.offset(49.608, 0.0, 52.493)).collect(),
|
||||
capture_points: vec![], // TODO
|
||||
});
|
||||
map.insert(super::combat::GameMap::Neptune1, MapConfig {
|
||||
spawn_points: vec![
|
||||
@@ -989,7 +1050,7 @@ pub(super) fn default_map() -> std::collections::HashMap<super::combat::GameMap,
|
||||
y: 1.580,
|
||||
z: -82.150,
|
||||
radius: DEFAULT_BASE_RADIUS,
|
||||
percent_per_second: DEFAULT_PERCENT_PER_SECOND,
|
||||
percent_per_second: DEFAULT_BASE_PERCENT_PER_SECOND,
|
||||
},
|
||||
CaptureBase {
|
||||
team: 1,
|
||||
@@ -997,9 +1058,10 @@ pub(super) fn default_map() -> std::collections::HashMap<super::combat::GameMap,
|
||||
y: -0.110,
|
||||
z: 292.956,
|
||||
radius: DEFAULT_BASE_RADIUS,
|
||||
percent_per_second: DEFAULT_PERCENT_PER_SECOND,
|
||||
percent_per_second: DEFAULT_BASE_PERCENT_PER_SECOND,
|
||||
},
|
||||
].into_iter().map(|x| x.offset(405.542, 0.0, 10.668)).collect(),
|
||||
capture_points: vec![], // TODO
|
||||
});
|
||||
map.insert(super::combat::GameMap::Neptune2, MapConfig {
|
||||
spawn_points: vec![
|
||||
@@ -1133,7 +1195,7 @@ pub(super) fn default_map() -> std::collections::HashMap<super::combat::GameMap,
|
||||
y: 18.370,
|
||||
z: -181.488,
|
||||
radius: DEFAULT_BASE_RADIUS,
|
||||
percent_per_second: DEFAULT_PERCENT_PER_SECOND,
|
||||
percent_per_second: DEFAULT_BASE_PERCENT_PER_SECOND,
|
||||
},
|
||||
CaptureBase {
|
||||
team: 1,
|
||||
@@ -1141,9 +1203,10 @@ pub(super) fn default_map() -> std::collections::HashMap<super::combat::GameMap,
|
||||
y: 18.390,
|
||||
z: 196.416,
|
||||
radius: DEFAULT_BASE_RADIUS,
|
||||
percent_per_second: DEFAULT_PERCENT_PER_SECOND,
|
||||
percent_per_second: DEFAULT_BASE_PERCENT_PER_SECOND,
|
||||
},
|
||||
],
|
||||
capture_points: vec![], // TODO
|
||||
});
|
||||
map.insert(super::combat::GameMap::Neptune3, MapConfig {
|
||||
spawn_points: vec![
|
||||
@@ -1277,7 +1340,7 @@ pub(super) fn default_map() -> std::collections::HashMap<super::combat::GameMap,
|
||||
y: 42.270,
|
||||
z: -151.440,
|
||||
radius: DEFAULT_BASE_RADIUS,
|
||||
percent_per_second: DEFAULT_PERCENT_PER_SECOND,
|
||||
percent_per_second: DEFAULT_BASE_PERCENT_PER_SECOND,
|
||||
},
|
||||
CaptureBase {
|
||||
team: 1,
|
||||
@@ -1285,9 +1348,10 @@ pub(super) fn default_map() -> std::collections::HashMap<super::combat::GameMap,
|
||||
y: 42.290,
|
||||
z: 147.240,
|
||||
radius: DEFAULT_BASE_RADIUS,
|
||||
percent_per_second: DEFAULT_PERCENT_PER_SECOND,
|
||||
percent_per_second: DEFAULT_BASE_PERCENT_PER_SECOND,
|
||||
},
|
||||
],
|
||||
capture_points: vec![], // TODO
|
||||
});
|
||||
map
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -22,11 +22,7 @@ impl SingleplayerConfig {
|
||||
crate::persist::config::SingleplayerConfig {
|
||||
max_teammates: self.max_teammates,
|
||||
max_enemies: self.max_enemies,
|
||||
vehicles: self.vehicles.iter().map(|v| crate::persist::config::VehicleInfo {
|
||||
name: v.name.clone(),
|
||||
username: v.username.clone(),
|
||||
id: v.id.clone().into(),
|
||||
}).collect()
|
||||
vehicles: self.vehicles.iter().map(|v| v.into_conf()).collect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
8
rc_core/src/persist/user/common.rs
Normal file
8
rc_core/src/persist/user/common.rs
Normal file
@@ -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