TemplateID::new now returns Result<T, TemplateNotFoundError> Cleanup code in some of new handlers
235 lines
7.3 KiB
Rust
235 lines
7.3 KiB
Rust
use data::{
|
|
gacha::{
|
|
gacha_config::{CharacterGachaPool, GachaAddedItemType},
|
|
global_gacha_config,
|
|
},
|
|
tables::{AvatarBaseID, ItemID, WeaponID},
|
|
};
|
|
use proto::{GainItemInfo, GetGachaDataScRsp};
|
|
|
|
use super::*;
|
|
use crate::{
|
|
handlers::core::NetError,
|
|
logic::{item::ItemModel, role::RoleModel},
|
|
};
|
|
use chrono::{DateTime, Local};
|
|
|
|
pub async fn on_get_gacha_data(
|
|
_session: &NetSession,
|
|
_player: &mut Player,
|
|
req: GetGachaDataCsReq,
|
|
) -> NetResult<GetGachaDataScRsp> {
|
|
if req.gacha_type != 3 {
|
|
// tracing::info!("non-supported gacha type {}", body.gacha_type);
|
|
Ok(GetGachaDataScRsp {
|
|
retcode: Retcode::RetSucc.into(),
|
|
gacha_type: req.gacha_type,
|
|
gacha_data: Some(GachaData::default()),
|
|
})
|
|
} else {
|
|
// tracing::info!("construct gacha info");
|
|
Ok(GetGachaDataScRsp {
|
|
retcode: Retcode::RetSucc.into(),
|
|
gacha_type: req.gacha_type,
|
|
gacha_data: Some(_player.gacha_model.to_client(&Local::now())),
|
|
})
|
|
}
|
|
}
|
|
|
|
pub async fn on_do_gacha(
|
|
_session: &NetSession,
|
|
_player: &mut Player,
|
|
req: DoGachaCsReq,
|
|
) -> NetResult<DoGachaScRsp> {
|
|
let gachaconf = global_gacha_config();
|
|
let gacha_model = &mut _player.gacha_model;
|
|
let item_model = &mut _player.item_model;
|
|
let role_model = &mut _player.role_model;
|
|
let pull_time = Local::now();
|
|
let target_pool = get_gacha_pool(
|
|
&gachaconf.character_gacha_pool_list,
|
|
&req.gacha_parent_schedule_id,
|
|
&pull_time,
|
|
)?;
|
|
|
|
// tracing::info!("cost_item_count: {}", req.cost_item_count);
|
|
let pull_count = if req.cost_item_count > 1 { 10 } else { 1 };
|
|
let mut cost_count = gacha_model.get_actual_cost_count(target_pool, &pull_count);
|
|
if pull_count != req.cost_item_count {
|
|
tracing::info!(
|
|
"refuse gacha because: expected cost item {cost_count}, found {}",
|
|
req.cost_item_count
|
|
);
|
|
return Err(NetError::from(Retcode::RetFail));
|
|
} else {
|
|
// TODO: cost resource
|
|
}
|
|
|
|
let mut gain_item_list: Vec<GainItemInfo> = vec![];
|
|
while cost_count > 0 {
|
|
let pull_result = gacha_model.perform_pull_pool(&pull_time, target_pool);
|
|
|
|
let uid = add_item(
|
|
role_model,
|
|
item_model,
|
|
&pull_result.obtained_item_id,
|
|
&pull_result.item_type,
|
|
)?;
|
|
let (mut extra_item_id, mut extra_item_count) = (0, 0);
|
|
if let Some(extra_resources) = &pull_result.extra_resources {
|
|
(extra_item_id, extra_item_count) = (
|
|
extra_resources.extra_item_id.value(),
|
|
extra_resources.extra_item_count.clone(),
|
|
);
|
|
item_model.add_resource(extra_item_id, extra_item_count);
|
|
}
|
|
gain_item_list.push(GainItemInfo {
|
|
item_id: pull_result.obtained_item_id.value(),
|
|
extra_item_id,
|
|
extra_item_count,
|
|
uid,
|
|
num: 1,
|
|
..GainItemInfo::default()
|
|
});
|
|
cost_count -= 1;
|
|
gacha_model.gacha_records.push(pull_result);
|
|
}
|
|
|
|
_session
|
|
.notify(construct_sync(role_model, item_model))
|
|
.await?;
|
|
Ok(DoGachaScRsp {
|
|
retcode: Retcode::RetSucc.into(),
|
|
gain_item_list,
|
|
gacha_data: Some(gacha_model.to_client(&pull_time)),
|
|
cost_item_count: req.cost_item_count,
|
|
})
|
|
}
|
|
|
|
pub async fn on_gacha_free_agent(
|
|
_session: &NetSession,
|
|
_player: &mut Player,
|
|
req: GachaFreeAgentCsReq,
|
|
) -> NetResult<GachaFreeAgentScRsp> {
|
|
let gachaconf = global_gacha_config();
|
|
let gacha_model = &mut _player.gacha_model;
|
|
let role_model = &mut _player.role_model;
|
|
let item_model = &mut _player.item_model;
|
|
let pull_time = Local::now();
|
|
let target_pool = get_gacha_pool(
|
|
&gachaconf.character_gacha_pool_list,
|
|
&req.gacha_parent_schedule_id,
|
|
&pull_time,
|
|
)?;
|
|
|
|
let item_id = ItemID::new(req.avatar_id);
|
|
if item_id.is_err() {
|
|
return Err(NetError::from(Retcode::RetFail));
|
|
}
|
|
let item_id = item_id.unwrap();
|
|
|
|
let item_type = gacha_model.request_free_agent(target_pool, &item_id);
|
|
if item_type == GachaAddedItemType::None {
|
|
return Err(NetError::from(Retcode::RetFail));
|
|
}
|
|
let _ = add_item(role_model, item_model, &item_id, &item_type);
|
|
|
|
_session
|
|
.notify(construct_sync(role_model, item_model))
|
|
.await?;
|
|
Ok(GachaFreeAgentScRsp {
|
|
retcode: Retcode::RetSucc.into(),
|
|
})
|
|
}
|
|
|
|
pub async fn on_choose_gacha_up(
|
|
_session: &NetSession,
|
|
_player: &mut Player,
|
|
req: ChooseGachaUpCsReq,
|
|
) -> NetResult<ChooseGachaUpScRsp> {
|
|
let gachaconf = global_gacha_config();
|
|
let gacha_model = &mut _player.gacha_model;
|
|
let pull_time = Local::now();
|
|
let target_pool = get_gacha_pool(
|
|
&gachaconf.character_gacha_pool_list,
|
|
&req.gacha_parent_schedule_id,
|
|
&pull_time,
|
|
)?;
|
|
|
|
let item_id = ItemID::new(req.item_id);
|
|
if item_id.is_err() {
|
|
return Err(NetError::from(Retcode::RetFail));
|
|
}
|
|
let item_id = item_id.unwrap();
|
|
|
|
Ok(ChooseGachaUpScRsp {
|
|
retcode: if gacha_model.choose_gacha_up(target_pool, &item_id) {
|
|
Retcode::RetSucc.into()
|
|
} else {
|
|
Retcode::RetFail.into()
|
|
},
|
|
..Default::default()
|
|
})
|
|
}
|
|
|
|
fn get_gacha_pool<'conf>(
|
|
character_gacha_pool_list: &'conf Vec<CharacterGachaPool>,
|
|
gacha_parent_schedule_id: &u32,
|
|
pull_time: &DateTime<Local>,
|
|
) -> NetResult<&'conf CharacterGachaPool> {
|
|
for target_pool in character_gacha_pool_list.iter() {
|
|
if &target_pool.gacha_parent_schedule_id == gacha_parent_schedule_id
|
|
&& target_pool.is_still_open(pull_time)
|
|
{
|
|
return Ok(target_pool);
|
|
}
|
|
}
|
|
tracing::info!(
|
|
"refuse gacha op because: pool of parent_schedule_id {} not found or isn't in open time",
|
|
gacha_parent_schedule_id
|
|
);
|
|
Err(NetError::from(Retcode::RetFail))
|
|
}
|
|
|
|
/// Return is item UID (weapon specific)
|
|
fn add_item(
|
|
role_model: &mut RoleModel,
|
|
item_model: &mut ItemModel,
|
|
item_id: &ItemID,
|
|
item_type: &GachaAddedItemType,
|
|
) -> NetResult<u32> {
|
|
match item_type {
|
|
GachaAddedItemType::Character => match AvatarBaseID::new(item_id.value()) {
|
|
Ok(avatar_id) => {
|
|
role_model.add_avatar(avatar_id);
|
|
Ok(0)
|
|
}
|
|
Err(_) => {
|
|
tracing::info!("add item failed for avatar id {item_id}");
|
|
Err(NetError::from(Retcode::RetFail))
|
|
}
|
|
},
|
|
GachaAddedItemType::Weapon => match WeaponID::new(item_id.value()) {
|
|
Ok(weapon_id) => Ok(item_model.add_weapon(weapon_id).value()),
|
|
Err(_) => {
|
|
tracing::info!("add item failed for weapon id {item_id}");
|
|
Err(NetError::from(Retcode::RetFail))
|
|
}
|
|
},
|
|
GachaAddedItemType::Bangboo => Ok(0),
|
|
_ => {
|
|
tracing::info!(
|
|
"add item failed due to undefined item type (from {item_id}) in configuration"
|
|
);
|
|
Err(NetError::from(Retcode::RetFail))
|
|
}
|
|
}
|
|
}
|
|
|
|
fn construct_sync(role_model: &RoleModel, item_model: &ItemModel) -> PlayerSyncScNotify {
|
|
PlayerSyncScNotify {
|
|
avatar: Some(role_model.avatar_sync()),
|
|
item_sync: Some(item_model.item_sync()),
|
|
..Default::default()
|
|
}
|
|
}
|