JaneDoe-ZS/nap_gameserver/src/handlers/world.rs
xeon 84397a847e Implement proper Avatar and Buddy UnitID (Base/Robot), refactor template id
TemplateID::new now returns Result<T, TemplateNotFoundError>
Cleanup code in some of new handlers
2024-08-06 21:42:03 +03:00

371 lines
11 KiB
Rust

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<EnterWorldScRsp> {
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<AdvanceBeginnerProcedureScRsp> {
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<BeginnerBattleBeginScRsp> {
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<BeginnerBattleEndScRsp> {
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<BeginnerBattleRebeginScRsp> {
Ok(BeginnerBattleRebeginScRsp {
retcode: Retcode::RetSucc.into(),
})
}
pub async fn on_sync_hall_event(
_session: &NetSession,
_player: &mut Player,
_req: SyncHallEventCsReq,
) -> NetResult<SyncHallEventScRsp> {
Ok(SyncHallEventScRsp {
retcode: Retcode::RetSucc.into(),
})
}
pub async fn on_save_pos_in_main_city(
_session: &NetSession,
player: &mut Player,
req: SavePosInMainCityCsReq,
) -> NetResult<SavePosInMainCityScRsp> {
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<WorldInitFinishScRsp> {
Ok(WorldInitFinishScRsp {
retcode: Retcode::RetSucc.into(),
})
}
pub async fn on_start_trial_fighting_mission(
session: &NetSession,
player: &mut Player,
req: StartTrialFightingMissionCsReq,
) -> NetResult<StartTrialFightingMissionScRsp> {
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<EndBattleScRsp> {
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<LeaveCurDungeonScRsp> {
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<InteractWithUnitScRsp> {
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<EnterSectionScRsp> {
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<JumpPageSystemScRsp> {
Ok(JumpPageSystemScRsp {
retcode: Retcode::RetSucc.into(),
..Default::default()
})
}
pub async fn on_start_hollow_quest(
session: &NetSession,
player: &mut Player,
req: StartHollowQuestCsReq,
) -> NetResult<StartHollowQuestScRsp> {
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<FinishHollowBattleEventScRsp> {
Ok(FinishHollowBattleEventScRsp {
retcode: Retcode::RetSucc.into(),
})
}
pub async fn on_long_fight_progress_update(
_session: &NetSession,
_player: &mut Player,
_req: LongFightProgressUpdateCsReq,
) -> NetResult<LongFightProgressUpdateScRsp> {
Ok(LongFightProgressUpdateScRsp {
retcode: Retcode::RetSucc.into(),
})
}