use data::{ event, tables::{HollowQuestID, ProcedureConfigID, SectionConfigID, TrainingQuestID}, }; use super::core::NetError; use crate::{ logic::{ game::*, procedure::ProcedureAction, EHollowQuestType, ELocalPlayType, ENPCInteraction, }, net::NetSessionState, }; use super::*; pub async fn on_enter_world( session: &NetSession, player: &mut Player, _req: EnterWorldCsReq, ) -> NetResult { session.set_state(NetSessionState::EndBasicsReq); if let Some(procedure_id) = player.basic_data_model.beginner_procedure_id { player.game_instance = GameInstance::Fresh(FreshGame::new(procedure_id)) } else { player.init_frontend_game()?; } let world_init_notify = player.game_instance.create_world_init_notify()?; session.notify(world_init_notify).await?; session.set_state(NetSessionState::EnterWorldScRsp); Ok(EnterWorldScRsp { retcode: Retcode::RetSucc.into(), }) } pub async fn on_advance_beginner_procedure( session: &NetSession, player: &mut Player, req: AdvanceBeginnerProcedureCsReq, ) -> NetResult { let is_end = { let GameInstance::Fresh(fresh_game) = &mut player.game_instance else { return Err(NetError::from(Retcode::RetFail)); }; let procedure_id = ProcedureConfigID::new(req.procedure_id as u32).map_err(LogicError::from)?; fresh_game .procedure_mgr .try_complete_procedure(procedure_id) .map_err(LogicError::from)?; player.basic_data_model.beginner_procedure_id = fresh_game.procedure_mgr.procedure_id(); fresh_game.procedure_mgr.is_end() }; if is_end { player.init_frontend_game()?; let world_init_notify = player.game_instance.create_world_init_notify()?; session.notify(world_init_notify).await?; } Ok(AdvanceBeginnerProcedureScRsp { retcode: Retcode::RetSucc.into(), next_procedure_id: req.procedure_id, }) } pub async fn on_beginner_battle_begin( _session: &NetSession, player: &mut Player, req: BeginnerBattleBeginCsReq, ) -> NetResult { let GameInstance::Fresh(fresh_game) = &mut player.game_instance else { return Err(NetError::from(Retcode::RetFail)); }; fresh_game .procedure_mgr .on_action(ProcedureAction::BeginnerBattleBegin) .map_err(LogicError::from)?; Ok(BeginnerBattleBeginScRsp { retcode: Retcode::RetSucc.into(), battle_uid: req.battle_id as i64, }) } pub async fn on_beginner_battle_end( _session: &NetSession, player: &mut Player, req: BeginnerBattleEndCsReq, ) -> NetResult { let GameInstance::Fresh(fresh_game) = &mut player.game_instance else { return Err(NetError::from(Retcode::RetFail)); }; tracing::info!( "beginner battle end, id: {}, uid: {}, statistics: {:?}", req.battle_id, req.battle_uid, req.battle_statistics ); fresh_game .procedure_mgr .on_action(ProcedureAction::BeginnerBattleEnd) .map_err(LogicError::from)?; Ok(BeginnerBattleEndScRsp { retcode: Retcode::RetSucc.into(), }) } pub async fn on_beginner_battle_rebegin( _session: &NetSession, _player: &mut Player, _req: BeginnerBattleRebeginCsReq, ) -> NetResult { Ok(BeginnerBattleRebeginScRsp { retcode: Retcode::RetSucc.into(), }) } pub async fn on_sync_hall_event( _session: &NetSession, _player: &mut Player, _req: SyncHallEventCsReq, ) -> NetResult { Ok(SyncHallEventScRsp { retcode: Retcode::RetSucc.into(), }) } pub async fn on_save_pos_in_main_city( _session: &NetSession, player: &mut Player, req: SavePosInMainCityCsReq, ) -> NetResult { if let Some(transform) = req.position { player .main_city_model .update_position(transform.position, transform.rotation); } Ok(SavePosInMainCityScRsp { retcode: Retcode::RetSucc.into(), }) } pub async fn on_world_init_finish( _session: &NetSession, _player: &mut Player, _req: WorldInitFinishCsReq, ) -> NetResult { Ok(WorldInitFinishScRsp { retcode: Retcode::RetSucc.into(), }) } pub async fn on_start_trial_fighting_mission( session: &NetSession, player: &mut Player, req: StartTrialFightingMissionCsReq, ) -> NetResult { let quest_id = TrainingQuestID::new(req.quest_id).map_err(LogicError::from)?; player.game_instance = GameInstance::Hollow( HollowGame::create_training_game(quest_id, ELocalPlayType::TrainingRoomFight, &req.avatars) .map_err(LogicError::from)?, ); let world_init_notify = player.game_instance.create_world_init_notify()?; session.notify(world_init_notify).await?; Ok(StartTrialFightingMissionScRsp { retcode: Retcode::RetSucc.into(), }) } pub async fn on_end_battle( session: &NetSession, player: &mut Player, req: EndBattleCsReq, ) -> NetResult { match &mut player.game_instance { GameInstance::Hollow(hollow) if hollow.quest_manager.has_active_quests() => { hollow .quest_manager .finish_quest(hollow.battle_event_id.value()) .map_err(LogicError::from)?; session .notify(DungeonQuestFinishedScNotify { result: req.battle_result.unwrap().result as u32, quest_id: hollow.quest_id, ..Default::default() }) .await?; } GameInstance::LongFight(fight) => { fight .quest_manager .finish_quest(fight.battle_event_id.value()) .map_err(LogicError::from)?; session .notify(DungeonQuestFinishedScNotify { result: req.battle_result.unwrap().result as u32, quest_id: fight.quest_id, ..Default::default() }) .await?; } _ => (), }; Ok(EndBattleScRsp { battle_reward: Some(BattleRewardInfo::default()), retcode: Retcode::RetSucc.into(), }) } pub async fn on_leave_cur_dungeon( session: &NetSession, player: &mut Player, _req: LeaveCurDungeonCsReq, ) -> NetResult { player.init_frontend_game()?; let world_init_notify = player.game_instance.create_world_init_notify()?; session.notify(world_init_notify).await?; Ok(LeaveCurDungeonScRsp { retcode: Retcode::RetSucc.into(), }) } pub async fn on_interact_with_unit( session: &NetSession, _player: &mut Player, req: InteractWithUnitCsReq, ) -> NetResult { tracing::info!("interact: {req:?}"); if let Some(graph) = event::interacts().find(|e| e.event_id == req.interaction as u32) { session .notify(SyncEventInfoScNotify { owner_id: req.interaction as u32, npc_interaction: ENPCInteraction::OnInteract.to_string(), tag: req.unit_tag as u32, owner_type: EventGraphOwnerType::SceneUnit.into(), action_list: graph.actions.iter().map(|a| a.to_protocol()).collect(), ..Default::default() }) .await?; } else { tracing::warn!("no event graph for interaction: {}", req.interaction); } Ok(InteractWithUnitScRsp { retcode: Retcode::RetSucc.into(), }) } pub async fn on_enter_section( session: &NetSession, player: &mut Player, req: EnterSectionCsReq, ) -> NetResult { let section_id = SectionConfigID::new(req.section_id).map_err(LogicError::from)?; player.main_city_model.switch_section(section_id); player.init_frontend_game()?; let GameInstance::Frontend(frontend_game) = &mut player.game_instance else { unreachable!() }; frontend_game.set_entry_transform(req.transform); session .notify(player.game_instance.create_world_init_notify()?) .await?; Ok(EnterSectionScRsp { retcode: Retcode::RetSucc.into(), }) } pub async fn on_jump_page_system( _session: &NetSession, _player: &mut Player, _req: JumpPageSystemCsReq, ) -> NetResult { Ok(JumpPageSystemScRsp { retcode: Retcode::RetSucc.into(), ..Default::default() }) } pub async fn on_start_hollow_quest( session: &NetSession, player: &mut Player, req: StartHollowQuestCsReq, ) -> NetResult { use crate::logic::{TimePeriodType, WeatherType}; let quest_id = HollowQuestID::new(req.quest_id).map_err(LogicError::from)?; let quest_type = EHollowQuestType::from(quest_id.template().hollow_quest_type); match quest_type { EHollowQuestType::RallyBattle => { player.game_instance = GameInstance::LongFight( LongFightGame::create_rally_game( quest_id, &req.avatars, req.buddy_id, TimePeriodType::from_str(&req.quest_time_period), WeatherType::from_str(&req.quest_weather), ) .map_err(LogicError::from)?, ) } _ => { player.game_instance = GameInstance::Hollow( HollowGame::create_pure_hollow_battle( quest_id, &req.avatars, req.buddy_id, TimePeriodType::from_str(&req.quest_time_period), WeatherType::from_str(&req.quest_weather), ) .map_err(LogicError::from)?, ) } } let world_init_notify = player.game_instance.create_world_init_notify()?; session.notify(world_init_notify).await?; Ok(StartHollowQuestScRsp { retcode: Retcode::RetSucc.into(), quest_id: 0, }) } pub async fn on_finish_hollow_battle_event( _session: &NetSession, _player: &mut Player, _req: FinishHollowBattleEventCsReq, ) -> NetResult { Ok(FinishHollowBattleEventScRsp { retcode: Retcode::RetSucc.into(), }) } pub async fn on_long_fight_progress_update( _session: &NetSession, _player: &mut Player, _req: LongFightProgressUpdateCsReq, ) -> NetResult { Ok(LongFightProgressUpdateScRsp { retcode: Retcode::RetSucc.into(), }) }