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

Implement vehicle validation before match

This commit is contained in:
NG (Graham)
2026-02-28 10:51:12 -05:00
parent 5d4123026d
commit 3d2b7078e4
27 changed files with 468 additions and 54 deletions

View File

@@ -108,7 +108,7 @@ impl PlayerDatas {
pub fn as_transmissible<C>(&self) -> Typed<C> {
let mut buf = Vec::new();
let write_size = self.dump(&mut std::io::Cursor::new(&mut buf)).unwrap();
log::debug!("PlayerDatas serialized to {} bytes: {:?}", write_size, buf);
log::debug!("PlayerDatas serialized to {} bytes", write_size);
Typed::Bytes(buf.into())
}
}

View File

@@ -428,6 +428,7 @@ pub(super) fn default_campaigns() -> super::SingleplayerConfig {
time_max: 60,
}
],
vehicle_validator: super::VehicleValidator::None,
}
],
vehicles: vec![
@@ -454,6 +455,7 @@ pub(super) fn default_campaigns() -> super::SingleplayerConfig {
],
max_teammates: 0,
max_enemies: 5,
vehicle_validator: super::VehicleValidator::None,
}
}
@@ -629,6 +631,7 @@ fn default_multiplayer() -> super::MultiplayerConfig {
battle_arena: super::multiplayer::default_ba_conf(),
pit_config: super::multiplayer::default_pit_conf(),
team_death_match: super::multiplayer::default_tdm_conf(),
vehicle_validator: super::multiplayer::default_validator(),
}
}

View File

@@ -553,4 +553,15 @@ impl <C: Clone + Send> super::ConfigProvider<C> for CubeConfig {
}
map
}
fn vehicle_validation(&self) -> super::VehicleValidators {
super::VehicleValidators {
multiplayer: self.battle.multiplayer.vehicle_validator.clone(),
custom_game: crate::persist::VehicleValidator::None, // TODO
singleplayer: self.battle.singleplayer.vehicle_validator.clone(),
campaigns: self.battle.singleplayer.campaigns.iter()
.map(|campaign| (campaign.id.clone(), campaign.vehicle_validator.clone()))
.collect(),
}
}
}

View File

@@ -2,7 +2,7 @@ mod cubes_json;
pub use cubes_json::CubeConfig;
mod traits;
pub use traits::{ConfigProvider, DevMessageProvider, ServerConfig, GarageUpgrades, GarageUpgradeIncrement, ChatSystemConfig, GameEventSequence, GameEvents, GameRotationStrategy, GameEvent, GameMap, GameVisibility, GameType, SingleplayerConfig, VehicleInfo, VehicleDescriptor, QueueChangeMode, Point, Sphere, MapConfig, LinksConfig, FakePlayer, ClientEmulator, EnergyConfig, BattleArenaResolver, PitSettings, PitWinCondition, TeamDeathMatchSettings, ShopEntriesResolver, ShopAction, ShopGain, PromoCode, MultiplayerSettings, BattleArenaCrystalParams};
pub use traits::{ConfigProvider, DevMessageProvider, ServerConfig, GarageUpgrades, GarageUpgradeIncrement, ChatSystemConfig, GameEventSequence, GameEvents, GameRotationStrategy, GameEvent, GameMap, GameVisibility, GameType, SingleplayerConfig, VehicleInfo, VehicleDescriptor, QueueChangeMode, Point, Sphere, MapConfig, LinksConfig, FakePlayer, ClientEmulator, EnergyConfig, BattleArenaResolver, PitSettings, PitWinCondition, TeamDeathMatchSettings, ShopEntriesResolver, ShopAction, ShopGain, PromoCode, MultiplayerSettings, BattleArenaCrystalParams, VehicleValidators};
mod validation;
pub use validation::{SelfValidator, ValidationInfo, ValidationMessage};

View File

@@ -40,6 +40,7 @@ pub trait ConfigProvider<C: Clone> {
fn tdm_settings(&self) -> TeamDeathMatchSettings;
fn shop_entries(&self) -> ShopEntriesResolver;
fn promo_codes(&self) -> std::collections::HashMap<String, PromoCode>;
fn vehicle_validation(&self) -> VehicleValidators;
}
pub struct DevMessageProvider<C: Clone> {
@@ -536,3 +537,11 @@ pub struct MultiplayerSettings {
pub lobby_autostart_after: Option<std::time::Duration>,
pub loading_autostart_after: Option<std::time::Duration>,
}
pub struct VehicleValidators {
// FIXME don't use serializable types in traits
pub multiplayer: crate::persist::VehicleValidator,
pub custom_game: crate::persist::VehicleValidator,
pub singleplayer: crate::persist::VehicleValidator,
pub campaigns: std::collections::HashMap<String, crate::persist::VehicleValidator>,
}

View File

@@ -44,6 +44,9 @@ pub use maps::{MapsConfig, MapConfig};
mod item_shop;
pub use item_shop::{ItemShopConfig, ItemBundle};
mod vehicle_validator;
pub use vehicle_validator::VehicleValidator;
const VALID_ROBOT: &[u8] = &[64,
0,
0,

View File

@@ -20,6 +20,8 @@ pub struct MultiplayerConfig {
pub pit_config: PitConfig,
#[serde(default = "default_tdm_conf")]
pub team_death_match: TeamDeathMatchConfig,
#[serde(default = "default_validator")]
pub vehicle_validator: super::VehicleValidator,
}
impl super::config::SelfValidator for MultiplayerConfig {
@@ -525,3 +527,10 @@ pub(super) fn default_tdm_conf() -> TeamDeathMatchConfig {
self_destruct_is_kill: true,
}
}
pub(super) fn default_validator() -> super::VehicleValidator {
super::VehicleValidator::Cpu {
min: 100,
max: 2_000,
}
}

View File

@@ -7,6 +7,8 @@ pub struct SingleplayerConfig {
pub vehicles: Vec<super::PrefabVehicle>,
pub max_teammates: u32,
pub max_enemies: u32,
#[serde(default = "default_singleplayer_vehicle_validator")]
pub vehicle_validator: super::VehicleValidator,
}
impl SingleplayerConfig {
@@ -62,6 +64,8 @@ pub struct Campaign {
pub map: String,
pub campaign_type: CampaignType,
pub waves: Vec<Wave>,
#[serde(default = "default_campaign_vehicle_validator")]
pub vehicle_validator: super::VehicleValidator,
}
impl Campaign {
@@ -193,3 +197,11 @@ impl std::convert::From<CampaignType> for crate::data::campaign::CampaignType {
fn default_campaigns() -> Vec<Campaign> {
super::combat::default_campaigns().campaigns
}
fn default_campaign_vehicle_validator() -> super::VehicleValidator {
super::VehicleValidator::None
}
fn default_singleplayer_vehicle_validator() -> super::VehicleValidator {
super::VehicleValidator::None
}

View File

@@ -859,6 +859,36 @@ impl <C: Clone + Send> super::User<C> for UserData {
})
}
async fn selected_vehicle_data(&self) -> Result<super::VehicleData, polariton_server::operations::SimpleOpError> {
let garage = self.db.garage_selected(self.account.id).await
.map_err(|e| {
log::error!("Failed to retrieve selected garage data for user_id {}: {}", self.account.id, e);
polariton_server::operations::SimpleOpError::with_message(
crate::data::error_codes::WebServicesError::DatabaseError as i16,
"Failed to retrieve selected garage data for user".to_owned(),
)
})?
.ok_or_else(|| {
log::error!("No selected garage data for user_id {}", self.account.id);
polariton_server::operations::SimpleOpError::with_message(
crate::data::error_codes::WebServicesError::UnexpectedError as i16,
"No selected garage data for user".to_owned(),
)
})?;
Ok(super::VehicleData {
name: Some(garage.name),
slot: garage.slot,
robot_data: garage.robot_data,
colour_data: garage.colour_data,
weapon_order: oj_rc_database::schema::parse_int_csv(&garage.weapon_order)
.into_iter()
.map(|x| x as i32)
.collect(),
crf_id: garage.crf_id,
was_rated: Some(garage.was_rated),
})
}
async fn all_slots(&self) -> super::UserSlots<C> {
let slots = match self.all_vehicles().await {
Ok(slots) => slots,

View File

@@ -78,6 +78,7 @@ pub trait User<C>: ChatUser + SocialUser + SocialUserC<C> + LobbyUser + Multipla
async fn unlock_parts(&self, parts: &[u32]) -> Result<(), polariton_server::operations::SimpleOpError>;
async fn selected_garage(&self) -> (String, u32);
async fn select_garage(&self, slot: i32) -> Result<(), i16>;
async fn selected_vehicle_data(&self) -> Result<VehicleData, polariton_server::operations::SimpleOpError>;
async fn all_slots(&self) -> UserSlots<C>;
async fn slot_by_id(&self, id: i32) -> Result<UserSlotData<C>, i16>;
async fn save_slot(&self, vehicle: VehicleData, cpu_counter: &crate::cubes::CpuListParser) -> Result<(), i16>;

View File

@@ -0,0 +1,22 @@
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(tag = "validator")]
pub enum VehicleValidator {
None,
Cpu {
min: u32,
max: u32,
},
// TODO other validators
All {
all: Vec<Self>,
},
Any {
any: Vec<Self>,
},
Custom {
#[serde(alias = "library")]
path: String,
},
}