1
0
mirror of https://git.ngram.ca/OpenJam/rc-servers synced 2026-08-23 23:08:52 +00:00

Add basic server-only player harness

This commit is contained in:
NG (Graham)
2025-08-16 21:32:14 -04:00
parent 94d247f8f4
commit 05bf4a097a
20 changed files with 304 additions and 21 deletions

View File

@@ -489,6 +489,7 @@ fn default_multiplayer() -> super::MultiplayerConfig {
players_per_game: 2,
enabled: true,
network: super::multiplayer::default_net_conf(),
fakes: super::multiplayer::default_fake_users(),
}
}

View File

@@ -418,4 +418,13 @@ impl <C: Clone + Send> super::ConfigProvider<C> for CubeConfig {
wiki_url: self.settings.server.wiki_url.clone(),
}
}
fn fake_players(&self) -> Vec<super::FakePlayer> {
self.battle.multiplayer.fakes.iter().map(|player| super::FakePlayer {
public_id: player.public_id.clone(),
display_name: player.display_name.clone(),
team: player.team,
implementation: player.implementation.clone().to_config(),
}).collect()
}
}

View File

@@ -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};
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};
pub type ConfigImpl = CubeConfig;

View File

@@ -33,6 +33,7 @@ pub trait ConfigProvider<C: Clone> {
fn network_config(&self) -> crate::persist::NetworkConf;
fn maps(&self) -> std::collections::HashMap<GameMap, MapConfig>;
fn url_links(&self) -> LinksConfig;
fn fake_players(&self) -> Vec<FakePlayer>;
}
pub struct CompleteCampaignProvider {
@@ -365,3 +366,16 @@ pub struct LinksConfig {
pub support_url: String,
pub wiki_url: String,
}
#[derive(Clone, Debug)]
pub struct FakePlayer {
pub public_id: String,
pub display_name: String,
pub team: u8,
pub implementation: ClientEmulator,
}
#[derive(Clone, Copy, Debug)]
pub enum ClientEmulator {
Experiment,
}

View File

@@ -6,6 +6,8 @@ pub struct MultiplayerConfig {
pub enabled: bool,
#[serde(default = "default_net_conf")]
pub network: NetworkConf,
#[serde(default = "default_fake_users")]
pub fakes: Vec<FakePlayerConf>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
@@ -46,3 +48,38 @@ pub(super) fn default_net_conf() -> NetworkConf {
max_delay_for_disconnect_ms: 1000,
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct FakePlayerConf {
pub public_id: String,
pub display_name: String,
pub team: u8,
#[serde(flatten)]
pub implementation: ClientEmulation,
}
pub(super) fn default_fake_users() -> Vec<FakePlayerConf> {
//Vec::default()
vec![
FakePlayerConf {
public_id: "ServerExperiment01".to_owned(),
display_name: "Server".to_owned(),
team: 1,
implementation: ClientEmulation::Experimental,
}
]
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(tag = "impl")]
pub enum ClientEmulation {
Experimental,
}
impl ClientEmulation {
pub(super) fn to_config(self) -> super::config::ClientEmulator {
match self {
Self::Experimental => super::config::ClientEmulator::Experiment,
}
}
}

View File

@@ -5,6 +5,7 @@ use crate::persist::config::ConfigProvider;
pub struct AccountProvider {
cubes: std::sync::Arc<Vec<u32>>,
garage_upgrades: std::sync::Arc<crate::persist::config::GarageUpgrades>,
fake_players: std::sync::Arc<Vec<crate::persist::config::FakePlayer>>,
auto_signups: bool,
cdn: std::sync::Arc<String>,
secret: std::sync::Arc<Vec<u8>>,
@@ -22,6 +23,7 @@ impl AccountProvider {
Ok(Self {
cubes: std::sync::Arc::new(<crate::persist::config::ConfigImpl as ConfigProvider<()>>::ids(conf)),
garage_upgrades: std::sync::Arc::new(<crate::persist::config::ConfigImpl as ConfigProvider<()>>::garage_upgrades(conf)),
fake_players: std::sync::Arc::new(<crate::persist::config::ConfigImpl as ConfigProvider<()>>::fake_players(conf)),
auto_signups: server_settings.auto_signup,
cdn: std::sync::Arc::new(server_settings.cdn_url),
secret: std::sync::Arc::new(std::fs::read(&token_path)?),
@@ -102,6 +104,7 @@ impl <C: Clone> super::UserProvider<C> for AccountProvider {
perms: user_perms,
cubes: self.cubes.clone(),
garage_upgrades: self.garage_upgrades.clone(),
fake_players: self.fake_players.clone(),
cdn: self.cdn.clone(),
db: self.db.clone(),
secret: self.secret.clone(),
@@ -137,6 +140,7 @@ impl <C: Clone> super::UserProvider<C> for AccountProvider {
perms: user_perms,
cubes: self.cubes.clone(),
garage_upgrades: self.garage_upgrades.clone(),
fake_players: self.fake_players.clone(),
cdn: self.cdn.clone(),
db: self.db.clone(),
secret: self.secret.clone(),
@@ -298,6 +302,7 @@ pub(super) struct UserData {
pub(super) perms: oj_rc_database::schema::permissions::Model,
pub(super) cubes: std::sync::Arc<Vec<u32>>,
pub(super) garage_upgrades: std::sync::Arc<crate::persist::config::GarageUpgrades>,
pub(super) fake_players: std::sync::Arc<Vec<crate::persist::config::FakePlayer>>,
pub(super) cdn: std::sync::Arc<String>,
pub(super) db: std::sync::Arc<oj_rc_database::Database>,
pub(super) secret: std::sync::Arc<Vec<u8>>,

View File

@@ -17,7 +17,7 @@ impl super::LobbyUser for UserData {
})
}
async fn start_game(&self, game: super::GameDescriptor, players: Vec<super::PlayerLobbyDescriptor>) -> Result<super::FakePlayers, polariton_server::operations::SimpleOpError> {
async fn start_game(&self, game: super::GameDescriptor, players: Vec<super::PlayerLobbyDescriptor>, cpu_counter: &crate::cubes::CpuListParser, weapon_lister: &crate::cubes::WeaponListParser) -> Result<super::FakePlayers, polariton_server::operations::SimpleOpError> {
let now = chrono::Utc::now().timestamp();
let guid = crate::persist::user::str_to_i64(&game.guid)
.ok_or_else(|| polariton_server::operations::SimpleOpError::with_message(
@@ -32,7 +32,7 @@ impl super::LobbyUser for UserData {
oj_rc_database::schema::multiplayer_game::GameType::Standard
};
let fake_players = self.generate_fake_players_data(guid).await;
let fake_players = self.generate_fake_players_data(guid, cpu_counter, weapon_lister).await;
let game_dbo = oj_rc_database::schema::multiplayer_game::ActiveModel {
id: oj_rc_database::sea_orm::ActiveValue::NotSet,

View File

@@ -1,30 +1,30 @@
use super::account_json::UserData;
impl UserData {
pub(super) async fn generate_fake_players_data(&self, _guid: i64) -> Vec<crate::data::player_data::PlayerData> {
vec![
crate::data::player_data::PlayerData {
name: "FakeUser".to_owned(),
display_name: "Server".to_owned(),
pub(super) async fn generate_fake_players_data(&self, _guid: i64, cpu_counter: &crate::cubes::CpuListParser, weapon_lister: &crate::cubes::WeaponListParser) -> Vec<crate::data::player_data::PlayerData> {
self.fake_players.iter()
.map(|fake| crate::data::player_data::PlayerData {
name: fake.public_id.clone(),
display_name: fake.display_name.clone(),
mastery: 1,
tier: 1,
robot_name: "Very bad but very good".to_owned(),
robot_name: "fake".to_owned(),
robot_map: crate::persist::VALID_ROBOT.into(),
group: None,
team: 2,
team: fake.team as _,
has_premium: true,
robot_uuid: "1234_1234".to_owned(),
cpu: 42,
cpu: cpu_counter.calculate_cpu(&mut std::io::Cursor::new(crate::persist::VALID_ROBOT)).total as _,
avatar_id: Some(0),
weapon_order: vec![0,0,0],
weapon_order: weapon_lister.guess_weapons(&mut std::io::Cursor::new(crate::persist::VALID_ROBOT)),
colour_map: crate::persist::VALID_COLOUR.into(),
is_ai: false,
spawn_effect: "Spawn".into(),
death_effect: "Explosion".into(),
player_rank: 1,
weapon_rank: Default::default(),
}
]
})
.collect()
}
}

View File

@@ -249,7 +249,7 @@ impl SanctionType {
pub trait LobbyUser {
fn user_id(&self) -> i32;
async fn player_data(&self, cpu_counter: &crate::cubes::CpuListParser) -> Result<crate::data::player_data::PlayerData, polariton_server::operations::SimpleOpError>;
async fn start_game(&self, game: GameDescriptor, players: Vec<PlayerLobbyDescriptor>) -> Result<FakePlayers, polariton_server::operations::SimpleOpError>;
async fn start_game(&self, game: GameDescriptor, players: Vec<PlayerLobbyDescriptor>, cpu_counter: &crate::cubes::CpuListParser, weapon_lister: &crate::cubes::WeaponListParser) -> Result<FakePlayers, polariton_server::operations::SimpleOpError>;
}
pub struct FakePlayers {