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

Use resolvable vehicles in campaign mode instead of raw cube data

This commit is contained in:
NG (Graham)
2025-12-02 17:08:42 -05:00
parent b58af3d893
commit 687f8dabbe
10 changed files with 284 additions and 159 deletions

View File

@@ -171,7 +171,7 @@ pub fn handler(init_ctx: &crate::InitConfig) -> OperationsHandler<crate::UserTy>
.add(prebuilt_robots::garage_robot_data_provider())
.add(prebuilt_colours::garage_colour_combo_provider())
.add(robopass_preview_items::robopass_preview_provider())
.add(singleplayer_campaigns::singleplayer_campaigns_provider(&init_ctx.cubes))
.add(singleplayer_campaigns::singleplayer_campaigns_provider(init_ctx))
.add(purchases::pending_purchases_provider())
.add(building_xp_config::building_xp_config_provider())
.add(weapon_rating_static::weapon_rating_provider())
@@ -198,7 +198,7 @@ pub fn handler(init_ctx: &crate::InitConfig) -> OperationsHandler<crate::UserTy>
.add(score_multipliers_config::tdm_ai_score_config_provider())
.add(player_robot_rank::player_robot_rank_provider())
.add(validate_machine::validate_campaign_robot_provider())
.add(singleplayer_campaigns::singleplayer_complete_campaign_provider(&init_ctx.cubes))
.add(singleplayer_campaigns::singleplayer_complete_campaign_provider(init_ctx))
.add(polariton_server::operations::Ack::<78, _>::default()) // TODO handle SaveCampaignGameAwardsRequest instead of ignoring it
.add(singleplayer_campaigns::singleplayer_save_complete_campaign_provider()) // TODO handle UpdatePlayerCompletedCampaignWaveRequest saving
.add(garage_slot_limit::garage_slots_limit(&init_ctx.cubes))

View File

@@ -1,14 +1,33 @@
use polariton_server::operations::{Immediate, SimpleFunc};
use polariton_server::operations::{Operation, OperationCode};
use polariton_server::operations::{Operation, OperationCode, SimpleFunc};
use polariton::operation::{ParameterTable, Typed};
use polariton_server::operations::{SimpleOpError, SimpleOperation, SimpleOpImpl};
use oj_rc_core::ConfigProvider;
//use oj_rc_core::ConfigProvider;
const CAMPAIGNS_BYTES_PARAM_KEY: u8 = 64; // list of bytes (serialised data)
const CAMPAIGNS_WAVES_PARAM_KEY: u8 = 70; // hashtable
const CAMPAIGNS_VERSIONS_PARAM_KEY: u8 = 69; // hashtable
pub(super) fn singleplayer_campaigns_provider(conf: &oj_rc_core::ConfigImpl) -> Immediate<65, crate::UserTy> {
const CAMPAIGNS_OP_CODE: u8 = 65;
pub struct SingleplayerCampaignProvider {
resolver: oj_rc_core::persist::config::CampaignResolver,
factory: std::sync::Arc<oj_rc_core::factory::Factory>,
weapon_order: std::sync::Arc<oj_rc_core::cubes::WeaponListParser>,
cpu_counter: std::sync::Arc<oj_rc_core::cubes::CpuListParser>,
}
pub(super) fn singleplayer_campaigns_provider<C: Send + Clone + 'static>(init_ctx: &crate::InitConfig) -> SimpleOpImpl<C, crate::UserTy, SingleplayerCampaignProvider> {
let campaigns = <oj_rc_core::ConfigImpl as oj_rc_core::ConfigProvider<()>>::campaigns(&init_ctx.cubes);
SimpleOpImpl::new(SingleplayerCampaignProvider {
resolver: campaigns,
factory: init_ctx.factory.clone(),
weapon_order: init_ctx.parsers.weapon_order(),
cpu_counter: init_ctx.parsers.cpu_counter(),
})
}
/*pub(super) fn singleplayer_campaigns_provider(conf: &oj_rc_core::ConfigImpl) -> Immediate<65, crate::UserTy> {
Immediate::new(|| {
let mut params = std::collections::HashMap::new();
params.insert(CAMPAIGNS_BYTES_PARAM_KEY, conf.campaigns_parameters()); // first 4 bytes are i32 for length of the rest
@@ -24,24 +43,57 @@ pub(super) fn singleplayer_campaigns_provider(conf: &oj_rc_core::ConfigImpl) ->
// ].into()));
params.into()
})
}*/
#[async_trait::async_trait]
impl <C: Send + 'static> SimpleOperation<C> for SingleplayerCampaignProvider {
type User = crate::UserTy;
const CODE: u8 = CAMPAIGNS_OP_CODE;
async fn handle(&self, params: ParameterTable<C>, user: &Self::User) -> Result<ParameterTable<C>, SimpleOpError> {
let mut params = params.to_dict();
let user = user.user()?;
params.insert(CAMPAIGNS_BYTES_PARAM_KEY, self.resolver.campaigns_parameters());
let waves = self.resolver.campaign_waves(user.as_ref().as_ref(), self.factory.as_ref(), &self.weapon_order, &self.cpu_counter).await?;
params.insert(CAMPAIGNS_WAVES_PARAM_KEY, waves);
params.insert(CAMPAIGNS_VERSIONS_PARAM_KEY, self.resolver.campaign_version());
Ok(params.into())
}
}
const CAMPAIGN_ID_PARAM_KEY: u8 = 22; // string; in
const CAMPAIGN_DIFFICULTY_PARAM_KEY: u8 = 23; // i32; in
const CAMPAIGN_WAVES_PARAM_KEY: u8 = 75; // bytes; out
const CAMPAIGN_COMPLETE_OP_CODE: u8 = 64;
pub struct SingleplayerCompleteCampaignProvider {
campaign_details: oj_rc_core::persist::config::CompleteCampaignProvider,
factory: std::sync::Arc<oj_rc_core::factory::Factory>,
weapon_order: std::sync::Arc<oj_rc_core::cubes::WeaponListParser>,
cpu_counter: std::sync::Arc<oj_rc_core::cubes::CpuListParser>,
}
#[async_trait::async_trait]
impl <C: Send + 'static> Operation<C> for SingleplayerCompleteCampaignProvider {
type User = crate::UserTy;
fn handle(&self, params: polariton::operation::ParameterTable<C>, _user: &Self::User) -> polariton::operation::OperationResponse<C> {
async fn handle_async(&self, params: polariton::operation::ParameterTable<C>, user: &Self::User) -> polariton::operation::OperationResponse<C> {
let mut params = params.to_dict();
if let Some(Typed::Str(campaign_id)) = params.get(&CAMPAIGN_ID_PARAM_KEY) {
if let Some(Typed::Int(campaign_difficulty)) = params.get(&CAMPAIGN_DIFFICULTY_PARAM_KEY) {
match self.campaign_details.get(&campaign_id.string, campaign_difficulty) {
let user = match user.user() {
Ok(x) => x,
Err(e) => {
return polariton::operation::OperationResponse {
code: Self::op_code(),
return_code: e,
message: polariton::operation::Typed::Null,
params: std::collections::HashMap::default().into(),
}
}
};
match self.campaign_details.get(&campaign_id.string, campaign_difficulty, user.as_ref().as_ref(), self.factory.as_ref(), &self.weapon_order, &self.cpu_counter).await {
Ok(complete_campaign) => {
params.clear();
params.insert(CAMPAIGN_WAVES_PARAM_KEY, complete_campaign);
@@ -69,16 +121,21 @@ impl <C: Send + 'static> Operation<C> for SingleplayerCompleteCampaignProvider {
impl OperationCode for SingleplayerCompleteCampaignProvider {
fn op_code() -> u8 {
64
CAMPAIGN_COMPLETE_OP_CODE
}
}
pub(super) fn singleplayer_complete_campaign_provider(conf: &oj_rc_core::ConfigImpl) -> SingleplayerCompleteCampaignProvider {
let campaign_details: oj_rc_core::persist::config::CompleteCampaignProvider = <oj_rc_core::ConfigImpl as oj_rc_core::ConfigProvider<()>>::campaign_details(conf);
SingleplayerCompleteCampaignProvider { campaign_details }
pub(super) fn singleplayer_complete_campaign_provider(init_ctx: &crate::InitConfig) -> SingleplayerCompleteCampaignProvider {
let campaign_details: oj_rc_core::persist::config::CompleteCampaignProvider = <oj_rc_core::ConfigImpl as oj_rc_core::ConfigProvider<()>>::campaign_details(&init_ctx.cubes);
SingleplayerCompleteCampaignProvider {
campaign_details,
factory: init_ctx.factory.clone(),
weapon_order: init_ctx.parsers.weapon_order(),
cpu_counter: init_ctx.parsers.cpu_counter(),
}
}
const CAMPAIGN_WAVE_NUMBER_PARAM_KEYL: u8 = 73;
const CAMPAIGN_WAVE_NUMBER_PARAM_KEY: u8 = 73;
pub(super) fn singleplayer_save_complete_campaign_provider() -> SimpleFunc<68, crate::UserTy, impl (Fn(ParameterTable, &crate::UserTy) -> Result<ParameterTable, i16>) + Sync + Sync> {
//let campaign_details = <oj_rc_core::ConfigImpl as oj_rc_core::ConfigProvider<()>>::campaign_details(conf);
@@ -86,7 +143,7 @@ pub(super) fn singleplayer_save_complete_campaign_provider() -> SimpleFunc<68, c
let mut params = params.to_dict();
if let Some(Typed::Str(campaign_id)) = params.get(&CAMPAIGN_ID_PARAM_KEY) {
if let Some(Typed::Int(campaign_difficulty)) = params.get(&CAMPAIGN_DIFFICULTY_PARAM_KEY) {
if let Some(Typed::Int(wave_number)) = params.get(&CAMPAIGN_WAVE_NUMBER_PARAM_KEYL) {
if let Some(Typed::Int(wave_number)) = params.get(&CAMPAIGN_WAVE_NUMBER_PARAM_KEY) {
let user_info = user.user()?;
log::info!("User {} completed campaign {} difficulty {} wave {}", user_info.public_id(), campaign_id.string, campaign_difficulty, wave_number);
// TODO save wave as completed