## Abstract This PR implements - Showing Teleports on map - Quick Menu usage - Dynamic Wallpaper switching - Settings UP for Bangboo pool (via CLI) ## Support list - The support of Teleport with map. - Unlocking the 3 buttons (Interknow, DMs, Map) as a prerequisite of the previous feature. By pressing 'F' you can also modify the buttons in Quick Menu. - Changing Dynamic Wallpaper to a specific one instead of being randomly chosen. **Notice that you can't use one's Dynamic Wallpaper if you don't own this agent.** - Fixed some Gacha bugs, including: - Obtained items won't be sent to your bag unless you're pulling the standard banner; - Obtained items won't show in bag until relogin; - Alternative command `gacha up` to choose the UP Bangboo. Start with `gacha up [player_uid]` and follow the guide to fill params. ## Principle - Player's `UnlockModelBin` stores Quick Menu data, with the player's chosen buttons and their positions. - Separate Gacha's DTO & Saving model to make it more standardized, and ensure ID validation is always performed. - Player's bag information is now sync to client appropriately after finishing any gacha operations. - `gacha up` search for pools with a `chooseable` Category Guarantee Policy, then list included items if user has provided the target pool's `gacha_schedule_id`. ## Known issues - **Specifically for 1.1 Beta**, teleport may meet these issues leading to a 'black screen', forcing you to restart the client (or use `player kick` command as an alternative). - Don't try to teleport to `治安局光映分署`, it won't succeed. This is the 32nd teleport out of the 31 ones defined visible in assets. - Don't close the page after opening map. Teleport to somewhere. - `gacha up` command is an alternative to in-game operation. You still can not see any bangboos in the collection when choosing Bangboo. Co-authored-by: YYHEggEgg <53960525+YYHEggEgg@users.noreply.github.com> Reviewed-on: #2 Co-authored-by: YYHEggEgg <yyheggegg@xeondev.com> Co-committed-by: YYHEggEgg <yyheggegg@xeondev.com>
263 lines
7.6 KiB
Rust
263 lines
7.6 KiB
Rust
use crate::logic::{EOperator, ESystem};
|
|
|
|
use super::*;
|
|
|
|
use data::tables::{self, QuickFuncID};
|
|
|
|
pub async fn on_get_tips_info(
|
|
_session: &NetSession,
|
|
_player: &mut Player,
|
|
req: GetTipsInfoCsReq,
|
|
) -> NetResult<GetTipsInfoScRsp> {
|
|
Ok(GetTipsInfoScRsp {
|
|
retcode: Retcode::RetSucc.into(),
|
|
tips_info: Some(TipsInfo::default()),
|
|
r#type: req.r#type, // tips group type
|
|
})
|
|
}
|
|
|
|
pub async fn on_get_client_systems_info(
|
|
_session: &NetSession,
|
|
player: &mut Player,
|
|
_req: GetClientSystemsInfoCsReq,
|
|
) -> NetResult<GetClientSystemsInfoScRsp> {
|
|
let mut post_girl_data = PostGirlData {
|
|
post_girl_list: tables::post_girl_config_template_tb::iter()
|
|
.map(|template| PostGirlItem {
|
|
template_id: template.id.value(),
|
|
unlock_time: 1720052644,
|
|
})
|
|
.collect(),
|
|
..Default::default()
|
|
};
|
|
if let Some(post_girl_id) = player.basic_data_model.selected_post_girl_id {
|
|
post_girl_data
|
|
.selected_post_girl_id_list
|
|
.push(post_girl_id.value());
|
|
}
|
|
|
|
Ok(GetClientSystemsInfoScRsp {
|
|
retcode: Retcode::RetSucc.into(),
|
|
info: Some(ClientSystemsInfo {
|
|
post_girl_data: Some(post_girl_data),
|
|
unlock_data: Some(player.lock_model.to_client()),
|
|
calling_card_data: Some(CallingCardData::default()),
|
|
teleport_data: Some(TeleportData {
|
|
unlock_id_list: tables::teleport_config_template_tb::iter()
|
|
.filter(|template| template.client_visible > 0)
|
|
.map(|template| template.teleport_id.value())
|
|
.collect(),
|
|
..Default::default()
|
|
}),
|
|
..Default::default()
|
|
}),
|
|
})
|
|
}
|
|
|
|
pub async fn on_get_news_stand_data(
|
|
_session: &NetSession,
|
|
_player: &mut Player,
|
|
_req: GetNewsStandDataCsReq,
|
|
) -> NetResult<GetNewsStandDataScRsp> {
|
|
Ok(GetNewsStandDataScRsp {
|
|
retcode: Retcode::RetSucc.into(),
|
|
news_stand_data: Some(NewsStandData::default()),
|
|
})
|
|
}
|
|
|
|
pub async fn on_news_stand_seen(
|
|
_session: &NetSession,
|
|
_player: &mut Player,
|
|
_req: NewsStandSeenCsReq,
|
|
) -> NetResult<NewsStandSeenScRsp> {
|
|
Ok(NewsStandSeenScRsp {
|
|
retcode: Retcode::RetSucc.into(),
|
|
})
|
|
}
|
|
|
|
pub async fn on_get_trashbin_hermit_data(
|
|
_session: &NetSession,
|
|
_player: &mut Player,
|
|
_req: GetTrashbinHermitDataCsReq,
|
|
) -> NetResult<GetTrashbinHermitDataScRsp> {
|
|
Ok(GetTrashbinHermitDataScRsp {
|
|
retcode: Retcode::RetSucc.into(),
|
|
trashbin_hermit_data: Some(TrashbinHermitData::default()),
|
|
})
|
|
}
|
|
|
|
pub async fn on_get_exploration_data(
|
|
_session: &NetSession,
|
|
_player: &mut Player,
|
|
_req: GetExplorationDataCsReq,
|
|
) -> NetResult<GetExplorationDataScRsp> {
|
|
Ok(GetExplorationDataScRsp {
|
|
retcode: Retcode::RetSucc.into(),
|
|
..Default::default()
|
|
})
|
|
}
|
|
|
|
pub async fn on_report_ui_layout_platform(
|
|
_session: &NetSession,
|
|
_player: &mut Player,
|
|
_req: ReportUiLayoutPlatformCsReq,
|
|
) -> NetResult<ReportUiLayoutPlatformScRsp> {
|
|
Ok(ReportUiLayoutPlatformScRsp {
|
|
retcode: Retcode::RetSucc.into(),
|
|
})
|
|
}
|
|
|
|
pub async fn on_unlock_newbie_group(
|
|
_session: &NetSession,
|
|
_player: &mut Player,
|
|
req: UnlockNewbieGroupCsReq,
|
|
) -> NetResult<UnlockNewbieGroupScRsp> {
|
|
Ok(UnlockNewbieGroupScRsp {
|
|
retcode: Retcode::RetSucc.into(),
|
|
group_id: req.group_id,
|
|
})
|
|
}
|
|
|
|
pub async fn on_battle_report(
|
|
_session: &NetSession,
|
|
_player: &mut Player,
|
|
_req: BattleReportCsReq,
|
|
) -> NetResult<BattleReportScRsp> {
|
|
Ok(BattleReportScRsp {
|
|
retcode: Retcode::RetSucc.into(),
|
|
})
|
|
}
|
|
|
|
pub async fn on_player_operation(
|
|
_session: &NetSession,
|
|
_player: &mut Player,
|
|
req: PlayerOperationCsReq,
|
|
) -> NetResult<PlayerOperationScRsp> {
|
|
tracing::info!(
|
|
"PlayerOperation(system={:?}, operator={:?}, param={})",
|
|
ESystem::from(req.system),
|
|
EOperator::from(req.operator),
|
|
req.param
|
|
);
|
|
|
|
Ok(PlayerOperationScRsp {
|
|
retcode: Retcode::RetSucc.into(),
|
|
})
|
|
}
|
|
|
|
pub async fn on_player_system_parameter_change(
|
|
_session: &NetSession,
|
|
_player: &mut Player,
|
|
req: PlayerSystemParameterChangeCsReq,
|
|
) -> NetResult<PlayerSystemParameterChangeScRsp> {
|
|
tracing::info!(
|
|
"PlayerSystemParameterChange(type={}, param={})",
|
|
req.r#type,
|
|
req.params,
|
|
);
|
|
|
|
Ok(PlayerSystemParameterChangeScRsp {
|
|
retcode: Retcode::RetSucc.into(),
|
|
})
|
|
}
|
|
|
|
pub async fn on_pop_up_window_seen(
|
|
_session: &NetSession,
|
|
_player: &mut Player,
|
|
req: PopUpWindowSeenCsReq,
|
|
) -> NetResult<PopUpWindowSeenScRsp> {
|
|
Ok(PopUpWindowSeenScRsp {
|
|
retcode: Retcode::RetSucc.into(),
|
|
popup_group_id_list: req.popup_group_id_list,
|
|
})
|
|
}
|
|
|
|
pub async fn on_report_system_settings_change(
|
|
_session: &NetSession,
|
|
_player: &mut Player,
|
|
req: ReportSystemSettingsChangeCsReq,
|
|
) -> NetResult<ReportSystemSettingsChangeScRsp> {
|
|
tracing::info!("system settings change {req:?}");
|
|
|
|
Ok(ReportSystemSettingsChangeScRsp {
|
|
retcode: Retcode::RetSucc.into(),
|
|
})
|
|
}
|
|
|
|
pub async fn on_interact_with_scene_object(
|
|
_session: &NetSession,
|
|
_player: &mut Player,
|
|
_req: InteractWithSceneObjectCsReq,
|
|
) -> NetResult<InteractWithSceneObjectScRsp> {
|
|
// this request is used for interaction with STATIC scene objects (not controlled by server, e.g. door in workshop)
|
|
Ok(InteractWithSceneObjectScRsp {
|
|
retcode: Retcode::RetSucc.into(),
|
|
})
|
|
}
|
|
|
|
pub async fn on_mod_quick_menu(
|
|
_session: &NetSession,
|
|
_player: &mut Player,
|
|
_req: ModQuickMenuCsReq,
|
|
) -> NetResult<ModQuickMenuScRsp> {
|
|
let mut quick_access_data_list: Vec<QuickAccessData> = vec![];
|
|
for data in _req.quick_access_data_list.iter() {
|
|
quick_access_data_list.push(
|
|
_player
|
|
.lock_model
|
|
.mod_quick_access(data.quick_access_index, QuickFuncID::new(data.btn_id)),
|
|
);
|
|
}
|
|
_session
|
|
.notify(PlayerSyncScNotify {
|
|
client_systems_sync: Some(ClientSystemsSync {
|
|
quick_access_data_list: _player.lock_model.quick_access_to_client(),
|
|
..Default::default()
|
|
}),
|
|
..Default::default()
|
|
})
|
|
.await?;
|
|
|
|
Ok(ModQuickMenuScRsp {
|
|
retcode: Retcode::RetSucc.into(),
|
|
..Default::default()
|
|
})
|
|
}
|
|
|
|
pub async fn on_change_post_girl(
|
|
_session: &NetSession,
|
|
_player: &mut Player,
|
|
_req: ChangePostGirlCsReq,
|
|
) -> NetResult<ChangePostGirlScRsp> {
|
|
if _req.new_selected_post_girl_id_list.len() != 1 {
|
|
return Ok(ChangePostGirlScRsp {
|
|
retcode: Retcode::RetFail.into(),
|
|
..Default::default()
|
|
});
|
|
};
|
|
match tables::PostGirlConfigID::new(*_req.new_selected_post_girl_id_list.get(0).unwrap()) {
|
|
Some(post_girl_id) => {
|
|
_player.basic_data_model.selected_post_girl_id = Some(post_girl_id);
|
|
_session
|
|
.notify(PlayerSyncScNotify {
|
|
client_systems_sync: Some(ClientSystemsSync {
|
|
post_girl_data: Some(PostGirlSync {
|
|
selected_post_girl_id_list: vec![post_girl_id.value()],
|
|
..Default::default()
|
|
}),
|
|
..Default::default()
|
|
}),
|
|
..Default::default()
|
|
})
|
|
.await?;
|
|
Ok(ChangePostGirlScRsp {
|
|
retcode: Retcode::RetSucc.into(),
|
|
..Default::default()
|
|
})
|
|
}
|
|
None => Ok(ChangePostGirlScRsp {
|
|
retcode: Retcode::RetFail.into(),
|
|
..Default::default()
|
|
}),
|
|
}
|
|
}
|