mirror of
https://git.ngram.ca/OpenJam/rc-servers
synced 2026-08-23 23:08:52 +00:00
Use real spawn points when available #30
This commit is contained in:
@@ -55,14 +55,14 @@ impl GameMap {
|
||||
#[inline]
|
||||
pub fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Mars1 => "RC_Planet_Mars_01_CTF",
|
||||
Self::Mars2 => "RC_Planet_Mars_02_BA",
|
||||
Self::Mars3 => "RC_Planet_Mars_03_BA",
|
||||
Self::Neptune1 => "RC_Planet_Neptune_01_CTF",
|
||||
Self::Neptune2 => "RC_Planet_Neptune_02_BA",
|
||||
Self::Neptune3 => "RC_Planet_Neptune_03_BA",
|
||||
Self::Earth1 => "RC_Planet_Earth_01_BA",
|
||||
Self::Earth2 => "RC_Planet_Earth_02_BA",
|
||||
Self::Mars1 => "RC_Planet_Mars_01_CTF", // og flat mars
|
||||
Self::Mars2 => "RC_Planet_Mars_02_BA", // the one with the bridge in the middle
|
||||
Self::Mars3 => "RC_Planet_Mars_03_BA", // tharsis rift without the rift
|
||||
Self::Neptune1 => "RC_Planet_Neptune_01_CTF", // og flat GJ1214b gliese lake without the lake
|
||||
Self::Neptune2 => "RC_Planet_Neptune_02_BA", // the one with the cave
|
||||
Self::Neptune3 => "RC_Planet_Neptune_03_BA", // spitzer dam
|
||||
Self::Earth1 => "RC_Planet_Earth_01_BA", // birmingham power station
|
||||
Self::Earth2 => "RC_Planet_Earth_02_BA", // vanguard
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ impl GameMap {
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Copy, Clone, Hash, Eq, PartialEq)]
|
||||
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
|
||||
pub enum GameMode {
|
||||
BattleArena = 0,
|
||||
SuddenDeath = 1,
|
||||
|
||||
@@ -14,6 +14,8 @@ pub struct BattleConfig {
|
||||
pub rotation: GameEventSequence,
|
||||
#[serde(default = "default_multiplayer")]
|
||||
pub multiplayer: super::MultiplayerConfig,
|
||||
#[serde(default = "default_maps")]
|
||||
pub maps: super::MapsConfig,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
@@ -144,7 +146,7 @@ pub struct GameEvent {
|
||||
}
|
||||
|
||||
impl GameEvent {
|
||||
pub fn into_conf(self) -> crate::persist::config::GameEvent {
|
||||
pub(super) fn into_conf(self) -> crate::persist::config::GameEvent {
|
||||
crate::persist::config::GameEvent {
|
||||
map: self.map.into_conf(),
|
||||
visibility: self.visibility.into_conf(),
|
||||
@@ -154,7 +156,7 @@ impl GameEvent {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, Copy)]
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, Copy, Hash, Eq, PartialEq)]
|
||||
pub enum GameMap {
|
||||
// TODO put some more obvious aliases on these
|
||||
Mars1,
|
||||
@@ -168,7 +170,7 @@ pub enum GameMap {
|
||||
}
|
||||
|
||||
impl GameMap {
|
||||
fn into_conf(self) -> crate::persist::config::GameMap {
|
||||
pub(super) fn into_conf(self) -> crate::persist::config::GameMap {
|
||||
match self {
|
||||
Self::Mars1 => crate::persist::config::GameMap::Mars1,
|
||||
Self::Mars2 => crate::persist::config::GameMap::Mars2,
|
||||
@@ -477,8 +479,14 @@ fn default_rotation() -> GameEventSequence {
|
||||
|
||||
fn default_multiplayer() -> super::MultiplayerConfig {
|
||||
super::MultiplayerConfig {
|
||||
players_per_game: 2,
|
||||
players_per_game: 1,
|
||||
enabled: true,
|
||||
network: super::multiplayer::default_net_conf(),
|
||||
}
|
||||
}
|
||||
|
||||
fn default_maps() -> super::MapsConfig {
|
||||
super::MapsConfig {
|
||||
map: super::maps::default_map(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,4 +370,40 @@ impl <C: Clone + Send> super::ConfigProvider<C> for CubeConfig {
|
||||
fn network_config(&self) -> crate::persist::NetworkConf {
|
||||
self.battle.multiplayer.network.clone()
|
||||
}
|
||||
|
||||
fn maps(&self) -> std::collections::HashMap<super::GameMap, super::MapConfig> {
|
||||
self.battle.maps.map.iter().map(|(map, conf)| {
|
||||
let mut spawns = std::collections::HashMap::<u8, Vec<super::Point>>::with_capacity(2); // usually 2 teams
|
||||
for point in conf.spawn_points.iter() {
|
||||
if let Some(list) = spawns.get_mut(&point.team) {
|
||||
list.push(super::Point {
|
||||
x: point.x,
|
||||
y: point.y,
|
||||
z: point.z,
|
||||
});
|
||||
} else {
|
||||
let mut list = Vec::with_capacity(10); // usually 10 spawn points (suddent death has the most)
|
||||
list.push(super::Point {
|
||||
x: point.x,
|
||||
y: point.y,
|
||||
z: point.z,
|
||||
});
|
||||
spawns.insert(point.team, list);
|
||||
}
|
||||
}
|
||||
let bases = conf.bases.iter().map(|base| (base.team, super::Sphere {
|
||||
radius: base.radius,
|
||||
center: super::Point {
|
||||
x: base.x,
|
||||
y: base.y,
|
||||
z: base.z,
|
||||
},
|
||||
})).collect();
|
||||
let map_conf = super::MapConfig {
|
||||
spawns,
|
||||
bases,
|
||||
};
|
||||
(map.into_conf(), map_conf)
|
||||
}).collect()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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};
|
||||
pub use traits::{ConfigProvider, CompleteCampaignProvider, DevMessageProvider, ServerConfig, GarageUpgrades, GarageUpgradeIncrement, ChatSystemConfig, GameEventSequence, GameEvents, GameRotationStrategy, GameEvent, GameMap, GameVisibility, GameType, SingleplayerConfig, VehicleInfo, VehicleDescriptor, QueueChangeMode, Point, Sphere, MapConfig};
|
||||
|
||||
pub type ConfigImpl = CubeConfig;
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ pub trait ConfigProvider<C: Clone> {
|
||||
fn is_multiplayer_enabled(&self) -> bool;
|
||||
// FIXME don't use serializable types in traits
|
||||
fn network_config(&self) -> crate::persist::NetworkConf;
|
||||
fn maps(&self) -> std::collections::HashMap<GameMap, MapConfig>;
|
||||
}
|
||||
|
||||
pub struct CompleteCampaignProvider {
|
||||
@@ -270,7 +271,7 @@ pub struct GameEvent {
|
||||
pub auto_heal: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Copy)]
|
||||
#[derive(Clone, Debug, Copy, Hash, PartialEq, Eq)]
|
||||
pub enum GameMap {
|
||||
Mars1,
|
||||
Mars2,
|
||||
@@ -329,3 +330,22 @@ pub enum VehicleDescriptor {
|
||||
}
|
||||
// TODO File
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Point {
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
pub z: f32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Sphere {
|
||||
pub radius: f32,
|
||||
pub center: Point,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MapConfig {
|
||||
pub spawns: std::collections::HashMap<u8, Vec<Point>>, // team -> points
|
||||
pub bases: std::collections::HashMap<u8, Sphere>, // team -> base
|
||||
}
|
||||
|
||||
211
rc_core/src/persist/maps.rs
Normal file
211
rc_core/src/persist/maps.rs
Normal file
@@ -0,0 +1,211 @@
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct MapsConfig {
|
||||
#[serde(default = "default_map")]
|
||||
pub map: std::collections::HashMap<super::combat::GameMap, MapConfig>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct MapConfig {
|
||||
pub spawn_points: Vec<SpawnPoint>,
|
||||
pub bases: Vec<CaptureBase>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct SpawnPoint {
|
||||
pub team: u8,
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
pub z: f32,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct CaptureBase {
|
||||
pub team: u8,
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
pub z: f32,
|
||||
pub radius: f32,
|
||||
}
|
||||
|
||||
pub(super) fn default_map() -> std::collections::HashMap<super::combat::GameMap, MapConfig> {
|
||||
let mut map = std::collections::HashMap::with_capacity(9);
|
||||
let coords_t0 = corner_to_center((6.60, 4.09, 20.3), 10.0);
|
||||
let coords_t1 = corner_to_center((364.60, 10.63, 372.20), 10.0);
|
||||
map.insert(super::combat::GameMap::Mars1, MapConfig {
|
||||
spawn_points: vec![
|
||||
// team 0
|
||||
SpawnPoint {
|
||||
team: 0,
|
||||
x: 32.07,
|
||||
y: 1.73,
|
||||
z: 49.75,
|
||||
},
|
||||
SpawnPoint {
|
||||
team: 0,
|
||||
x: 39.20,
|
||||
y: 1.73,
|
||||
z: 40.21,
|
||||
},
|
||||
SpawnPoint {
|
||||
team: 0,
|
||||
x: 21.14,
|
||||
y: 1.73,
|
||||
z: 44.16,
|
||||
},
|
||||
SpawnPoint {
|
||||
team: 0,
|
||||
x: 32.50,
|
||||
y: 1.73,
|
||||
z: 30.66,
|
||||
},
|
||||
SpawnPoint {
|
||||
team: 0,
|
||||
x: 31.1,
|
||||
y: 1.73,
|
||||
z: 6.80,
|
||||
},
|
||||
SpawnPoint {
|
||||
team: 0,
|
||||
x: 43.40,
|
||||
y: 1.73,
|
||||
z: 8.60,
|
||||
},
|
||||
SpawnPoint {
|
||||
team: 0,
|
||||
x: 36.00,
|
||||
y: 1.73,
|
||||
z: 18.70,
|
||||
},
|
||||
SpawnPoint {
|
||||
team: 0,
|
||||
x: 3.00,
|
||||
y: 1.73,
|
||||
z: 57.4,
|
||||
},
|
||||
SpawnPoint {
|
||||
team: 0,
|
||||
x: 9.90,
|
||||
y: 1.73,
|
||||
z: 47.90,
|
||||
},
|
||||
SpawnPoint {
|
||||
team: 0,
|
||||
x: -2.40,
|
||||
y: 1.73,
|
||||
z: 46.40,
|
||||
},
|
||||
// team 1
|
||||
SpawnPoint {
|
||||
team: 1,
|
||||
x: 346.09,
|
||||
y: 8.10,
|
||||
z: 339.18,
|
||||
},
|
||||
SpawnPoint {
|
||||
team: 1,
|
||||
x: 337.10,
|
||||
y: 8.10,
|
||||
z: 346.80,
|
||||
},
|
||||
SpawnPoint {
|
||||
team: 1,
|
||||
x: 356.10,
|
||||
y: 8.10,
|
||||
z: 344.90,
|
||||
},
|
||||
SpawnPoint {
|
||||
team: 1,
|
||||
x: 340.10,
|
||||
y: 8.10,
|
||||
z: 358.20,
|
||||
},
|
||||
SpawnPoint {
|
||||
team: 1,
|
||||
x: 327.15,
|
||||
y: 8.10,
|
||||
z: 381.87,
|
||||
},
|
||||
SpawnPoint {
|
||||
team: 1,
|
||||
x: 339.10,
|
||||
y: 8.10,
|
||||
z: 383.60,
|
||||
},
|
||||
SpawnPoint {
|
||||
team: 1,
|
||||
x: 334.80,
|
||||
y: 8.10,
|
||||
z: 372.40,
|
||||
},
|
||||
SpawnPoint {
|
||||
team: 1,
|
||||
x: 382.50,
|
||||
y: 8.10,
|
||||
z: 335.10,
|
||||
},
|
||||
SpawnPoint {
|
||||
team: 1,
|
||||
x: 373.10,
|
||||
y: 8.10,
|
||||
z: 342.40,
|
||||
},
|
||||
SpawnPoint {
|
||||
team: 1,
|
||||
x: 384.50,
|
||||
y: 8.10,
|
||||
z: 346.80,
|
||||
},
|
||||
],
|
||||
bases: vec![
|
||||
CaptureBase {
|
||||
team: 0,
|
||||
x: coords_t0.0,
|
||||
y: coords_t0.1,
|
||||
z: coords_t0.2,
|
||||
radius: 10.0,
|
||||
},
|
||||
CaptureBase {
|
||||
team: 1,
|
||||
x: coords_t1.0,
|
||||
y: coords_t1.1,
|
||||
z: coords_t1.2,
|
||||
radius: 10.0,
|
||||
},
|
||||
],
|
||||
});
|
||||
map.insert(super::combat::GameMap::Mars2, MapConfig {
|
||||
spawn_points: vec![],
|
||||
bases: vec![],
|
||||
});
|
||||
map.insert(super::combat::GameMap::Mars3, MapConfig {
|
||||
spawn_points: vec![],
|
||||
bases: vec![],
|
||||
});
|
||||
map.insert(super::combat::GameMap::Neptune1, MapConfig {
|
||||
spawn_points: vec![],
|
||||
bases: vec![],
|
||||
});
|
||||
map.insert(super::combat::GameMap::Neptune2, MapConfig {
|
||||
spawn_points: vec![],
|
||||
bases: vec![],
|
||||
});
|
||||
map.insert(super::combat::GameMap::Neptune3, MapConfig {
|
||||
spawn_points: vec![],
|
||||
bases: vec![],
|
||||
});
|
||||
map.insert(super::combat::GameMap::Earth1, MapConfig {
|
||||
spawn_points: vec![],
|
||||
bases: vec![],
|
||||
});
|
||||
map.insert(super::combat::GameMap::Earth2, MapConfig {
|
||||
spawn_points: vec![],
|
||||
bases: vec![],
|
||||
});
|
||||
map
|
||||
}
|
||||
|
||||
const fn corner_to_center(corner: (f32, f32, f32), radius: f32) -> (f32, f32, f32) {
|
||||
(corner.0 + radius, corner.1, corner.2 + radius)
|
||||
}
|
||||
@@ -38,6 +38,9 @@ pub use vehicle_factory::{FactoryConfig, AdapterSettings, ArcFactorySettings};
|
||||
mod multiplayer;
|
||||
pub use multiplayer::{MultiplayerConfig, NetworkConf};
|
||||
|
||||
mod maps;
|
||||
pub use maps::{MapsConfig, MapConfig};
|
||||
|
||||
pub(self) const VALID_ROBOT: &[u8] = &[64,
|
||||
0,
|
||||
0,
|
||||
|
||||
@@ -1367,4 +1367,32 @@ impl super::MultiplayerUser for UserData {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async fn game_info(&self, guid: &str) -> Result<Option<super::GameDescriptor>, super::MultiplayerError> {
|
||||
if let Some(guid) = crate::persist::user::str_to_i64(guid) {
|
||||
let game_opt = self.db.game_by_guid(guid.to_owned()).await
|
||||
.map_err(|e| {
|
||||
log::error!("Failed to retrieve game {} with user {}: {}", guid, self.account.id, e);
|
||||
super::MultiplayerError {
|
||||
code: super::MultiplayerErrorCode::CustomString,
|
||||
message: format!("Failed to retrieve game {}: {}", guid, e),
|
||||
}
|
||||
})?;
|
||||
Ok(game_opt.map(|game| super::GameDescriptor {
|
||||
guid: crate::persist::user::i64_as_uuid_str(game.guid),
|
||||
map: game.map,
|
||||
mode: crate::data::game_mode::GameMode::from_db(game.mode),
|
||||
visibility: crate::data::game_mode::MapVisibility::from_db(game.visibility),
|
||||
auto_heal: game.auto_heal,
|
||||
is_ranked: matches!(game.variant, oj_rc_database::schema::multiplayer_game::GameType::Ranked),
|
||||
is_custom: matches!(game.variant, oj_rc_database::schema::multiplayer_game::GameType::Custom),
|
||||
is_complete: game.is_complete,
|
||||
}))
|
||||
} else {
|
||||
Err(super::MultiplayerError {
|
||||
code: super::MultiplayerErrorCode::IncorrectGameGuid,
|
||||
message: format!("Failed to parse game GUID {}", guid),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -320,4 +320,5 @@ pub trait MultiplayerUser {
|
||||
async fn current_game(&self) -> Result<Option<GameDescriptor>, MultiplayerError>;
|
||||
async fn game_players(&self, guid: &str) -> Result<Vec<PlayerDescriptor>, MultiplayerError>;
|
||||
async fn complete_game(&self, guid: &str) -> Result<(), MultiplayerError>;
|
||||
async fn game_info(&self, guid: &str) -> Result<Option<GameDescriptor>, MultiplayerError>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user