record-daemon: fix gamephase event handling

This commit is contained in:
2026-03-19 22:05:13 +01:00
parent 7e346a33e0
commit dbb224e118
4 changed files with 37 additions and 0 deletions

View File

@@ -33,11 +33,27 @@ pub enum GameEvent {
#[serde(rename = "lcu-game-end")] #[serde(rename = "lcu-game-end")]
GameEnd(GameEndInfo), GameEnd(GameEndInfo),
/// Gameflow phase changed.
#[serde(rename = "lcu-phase-change")]
PhaseChange(PhaseChangeInfo),
/// Unknown event type. /// Unknown event type.
#[serde(other)] #[serde(other)]
Unknown, Unknown,
} }
/// Phase change event data.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PhaseChangeInfo {
/// The new phase.
pub phase: String,
/// Timestamp when phase changed.
#[serde(default = "Utc::now")]
pub timestamp: DateTime<Utc>,
}
/// Match found event data. /// Match found event data.
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
@@ -314,6 +330,9 @@ impl GameEvent {
let result = if end.victory { "Victory" } else { "Defeat" }; let result = if end.victory { "Victory" } else { "Defeat" };
format!("Game ended: {} ({:.1}s)", result, end.duration) format!("Game ended: {} ({:.1}s)", result, end.duration)
} }
GameEvent::PhaseChange(info) => {
format!("Phase changed to: {}", info.phase)
}
GameEvent::Unknown => "Unknown event".to_string(), GameEvent::Unknown => "Unknown event".to_string(),
} }
} }

View File

@@ -210,6 +210,13 @@ impl Daemon {
// Handle recording start/stop // Handle recording start/stop
match transition { match transition {
StateTransition::GameStarted { game_id, champion } => { StateTransition::GameStarted { game_id, champion } => {
// If already recording, stop the current recording first
if self.state_machine.is_recording() {
info!("Stopping previous recording before starting new one");
if let Err(e) = self.stop_recording().await {
warn!("Failed to stop previous recording: {}", e);
}
}
self.start_recording(game_id, champion.as_deref()).await?; self.start_recording(game_id, champion.as_deref()).await?;
} }
StateTransition::GameEnded => { StateTransition::GameEnded => {

View File

@@ -178,6 +178,8 @@ impl DaemonStateMachine {
// From Recording // From Recording
(DaemonState::Recording, StateTransition::GameEnded) => Some(DaemonState::Monitoring), (DaemonState::Recording, StateTransition::GameEnded) => Some(DaemonState::Monitoring),
// Allow GameStarted from Recording (handles case where GameEnded wasn't received)
(DaemonState::Recording, StateTransition::GameStarted { .. }) => Some(DaemonState::Recording),
(DaemonState::Recording, StateTransition::ClientStopped) => Some(DaemonState::Idle), (DaemonState::Recording, StateTransition::ClientStopped) => Some(DaemonState::Idle),
(DaemonState::Recording, StateTransition::Error(_)) => Some(DaemonState::Error), (DaemonState::Recording, StateTransition::Error(_)) => Some(DaemonState::Error),
(DaemonState::Recording, StateTransition::Shutdown) => Some(DaemonState::ShuttingDown), (DaemonState::Recording, StateTransition::Shutdown) => Some(DaemonState::ShuttingDown),
@@ -212,6 +214,14 @@ impl DaemonStateMachine {
champion: info.champion.clone(), champion: info.champion.clone(),
}), }),
GameEvent::GameEnd(_) => Some(StateTransition::GameEnded), GameEvent::GameEnd(_) => Some(StateTransition::GameEnded),
GameEvent::PhaseChange(info) => {
// When phase changes to None while recording, the player left the game
if info.phase == "None" && self.is_recording() {
Some(StateTransition::GameEnded)
} else {
None
}
}
_ => None, _ => None,
} }
} }

View File

@@ -143,6 +143,7 @@ fn event_type_name(event: &GameEvent) -> String {
GameEvent::Death(_) => "death", GameEvent::Death(_) => "death",
GameEvent::Objective(_) => "objective", GameEvent::Objective(_) => "objective",
GameEvent::GameEnd(_) => "game_end", GameEvent::GameEnd(_) => "game_end",
GameEvent::PhaseChange(_) => "phase_change",
GameEvent::Unknown => "unknown", GameEvent::Unknown => "unknown",
} }
.to_string() .to_string()