diff --git a/rc_core/src/factory/adapter_enum.rs b/rc_core/src/factory/adapter_enum.rs index 7228824..5419c80 100644 --- a/rc_core/src/factory/adapter_enum.rs +++ b/rc_core/src/factory/adapter_enum.rs @@ -33,6 +33,22 @@ impl oj_rc_factory::VehicleFactoryAdapter for Factory { }), } } + + async fn rate_vehicle(&self, id: i32, combat: i32, cosmetic: i32) -> Result<(), Box> { + match self { + Self::Arc(x) => x.rate_vehicle(id, combat, cosmetic).await, + Self::Custom(x) => x.rate_vehicle(id, combat, cosmetic).await, + Self::None => Ok(()), + } + } + + async fn purchase(&self, id: i32) -> Result<(), Box> { + match self { + Self::Arc(x) => x.purchase(id).await, + Self::Custom(x) => x.purchase(id).await, + Self::None => Ok(()), + } + } } impl Factory { diff --git a/rc_factory/src/arc/adapter.rs b/rc_factory/src/arc/adapter.rs index 6b77cf9..78a343f 100644 --- a/rc_factory/src/arc/adapter.rs +++ b/rc_factory/src/arc/adapter.rs @@ -265,4 +265,38 @@ impl crate::VehicleFactoryAdapter for ArcAdapter { Ok(result) } + + async fn rate_vehicle(&self, id: i32, combat: i32, cosmetic: i32) -> Result<(), Box> { + if self.is_readonly { + return Ok(()); + } + // TODO this should probably be a transaction + if let Some(meta) = super::entities::robot_metadata::Entity::find_by_id(id as u32).one(&self.orm).await? { + let total_ratings = (meta.buy_count + meta.rent_count) as f64; // idk why/how these are different + let next_combat_rating = meta.combat_rating + (((combat as f64) - meta.combat_rating) / total_ratings); + let next_cosmetic_rating = meta.cosmetic_rating + (((cosmetic as f64) - meta.cosmetic_rating) / total_ratings); + super::entities::robot_metadata::ActiveModel { + id: sea_orm::ActiveValue::Set(id as u32), + cosmetic_rating: sea_orm::ActiveValue::Set(next_cosmetic_rating), + combat_rating: sea_orm::ActiveValue::Set(next_combat_rating), + ..Default::default() + }.update(&self.orm).await?; + } + Ok(()) + } + + async fn purchase(&self, id: i32) -> Result<(), Box> { + if self.is_readonly { + return Ok(()); + } + // TODO this should probably be a transaction + if let Some(meta) = super::entities::robot_metadata::Entity::find_by_id(id as u32).one(&self.orm).await? { + super::entities::robot_metadata::ActiveModel { + id: sea_orm::ActiveValue::Set(id as u32), + buy_count: sea_orm::ActiveValue::Set(meta.buy_count + 1), + ..Default::default() + }.update(&self.orm).await?; + } + Ok(()) + } } diff --git a/rc_factory/src/traits.rs b/rc_factory/src/traits.rs index 85d378b..0aa0dbe 100644 --- a/rc_factory/src/traits.rs +++ b/rc_factory/src/traits.rs @@ -3,6 +3,9 @@ pub trait VehicleFactoryAdapter: Send + Sync + 'static { async fn vehicle(&self, id: u32) -> Result, Box>; async fn list(&self, query: libfj::robocraft::ListQuery) -> Result, Box>; async fn upload(&self, vehicle: VehicleUploadInfo) -> Result>; + async fn rate_vehicle(&self, id: i32, combat: i32, cosmetic: i32) -> Result<(), Box>; + /// Just update any purchase trackers + async fn purchase(&self, id: i32) -> Result<(), Box>; } #[derive(Debug, Clone)] diff --git a/rc_services_room/src/operations/crf_purchase.rs b/rc_services_room/src/operations/crf_purchase.rs index 1e86ce0..3850b8f 100644 --- a/rc_services_room/src/operations/crf_purchase.rs +++ b/rc_services_room/src/operations/crf_purchase.rs @@ -47,6 +47,10 @@ async fn do_handling(params: ParameterTable<()>, user: &crate::UserTy, factory: }; user_info.save_slot(to_save, cpu_counter).await?; user_info.currency_debit(oj_rc_core::persist::user::CurrencyType::Free, free_cost as _).await?; + factory.purchase(factory_id).await.map_err(|e| { + log::error!("Failed to track factory purchase of vehicle {}: {}", factory_id, e); + oj_rc_core::data::error_codes::WebServicesError::DatabaseError as i16 + })?; if paid_cost > 0 { user_info.currency_debit(oj_rc_core::persist::user::CurrencyType::Paid, paid_cost as _).await?; } diff --git a/rc_services_room/src/operations/crf_rate_vehicle.rs b/rc_services_room/src/operations/crf_rate_vehicle.rs new file mode 100644 index 0000000..ce53a74 --- /dev/null +++ b/rc_services_room/src/operations/crf_rate_vehicle.rs @@ -0,0 +1,47 @@ +use polariton_server::operations::{SimpleOpError, SimpleOperation, SimpleOpImpl}; +use polariton::operation::{ParameterTable, Typed}; +use oj_rc_factory::VehicleFactoryAdapter; + +const CODE: u8 = 90; + +const SLOT_PARAM_KEY: u8 = 43; // int; in +const COMBAT_PARAM_KEY: u8 = 97; // int; in +const COSMETIC_PARAM_KEY: u8 = 98; // bool; int +//const BUILD_NUMBER_PARAM_KEY: u8 = 99; // str; in + +pub(super) struct CrfItemRater { + factory: std::sync::Arc, +} + +#[async_trait::async_trait] +impl SimpleOperation<()> for CrfItemRater { + type User = crate::UserTy; + const CODE: u8 = CODE; + + async fn handle(&self, mut params: ParameterTable, user: &Self::User) -> Result { + if let Some(Typed::Int(slot)) = params.remove(&SLOT_PARAM_KEY) { + if let Some(Typed::Int(combat_rating)) = params.remove(&COMBAT_PARAM_KEY) { + if let Some(Typed::Int(cosmetic_rating)) = params.remove(&COSMETIC_PARAM_KEY) { + log::warn!("Slot {}", slot); + let user_info = user.user()?; + if let Some(factory_id) = user_info.rate_vehicle(slot, combat_rating, cosmetic_rating).await? { + self.factory.rate_vehicle(factory_id, combat_rating, cosmetic_rating).await.map_err(|e| { + log::error!("Failed to rate factory vehicle {}: {}", factory_id, e); + SimpleOpError::with_message( + oj_rc_core::data::error_codes::WebServicesError::DatabaseError as i16, + format!("Failed to rate factory vehicle: {}", e), + ) + })?; + } + } + } + } + Ok(params) + } +} + +pub(super) fn crf_rating_provider(factory: &std::sync::Arc) -> SimpleOpImpl<(), crate::UserTy, CrfItemRater> { + SimpleOpImpl::new(CrfItemRater { + factory: factory.to_owned(), + }) +} diff --git a/rc_services_room/src/operations/mod.rs b/rc_services_room/src/operations/mod.rs index 068d925..ce06286 100644 --- a/rc_services_room/src/operations/mod.rs +++ b/rc_services_room/src/operations/mod.rs @@ -101,6 +101,7 @@ mod steam_promo; mod campaign_save_result; mod item_shop_purchase; mod code_redeem; +mod crf_rate_vehicle; use polariton_server::operations::OperationsHandler; @@ -222,7 +223,7 @@ pub fn handler(init_ctx: &crate::InitConfig) -> OperationsHandler .add(garage_slot_name::garage_slot_rename_provider()) .add(garage_slot_copy::garage_slot_copy_provider()) .add(polariton_server::operations::Ack::<12, _>::default()) // TODO handle UpdatePlayerDailyQuestProgressRequest instead of ignoring it - .add(polariton_server::operations::Ack::<90, _>::default()) // TODO handle SubmitCRFRatingRequest instead of ignoring it + .add(crf_rate_vehicle::crf_rating_provider(&init_ctx.factory)) //.add(polariton_server::operations::Ack::<97, _>::default()) // TODO handle UpdateShopRobotOffsetRequest instead of ignoring it (this seems to break newly-uploaded vehicles for now) .add(steam_promo::steam_promos_provider()) .add(item_shop_purchase::item_purchase_provider(&init_ctx.cubes))