From 5d0dd41c3f85fc0b08529d0b30ddd882f3bff5b0 Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Mon, 2 Mar 2026 00:36:21 +0100 Subject: [PATCH] Refactor event handling for character death: Updated the EventsWorker to ensure only player characters are notified of sudden child deaths, while NPCs are excluded. Adjusted health update logic to prevent player characters from reaching zero health due to accidents or illnesses. Enhanced SQL queries to filter characters based on user ID, improving clarity and functionality. --- src/worker/events.rs | 91 +++++++++++++++++++++++--------------------- src/worker/sql.rs | 6 ++- 2 files changed, 51 insertions(+), 46 deletions(-) diff --git a/src/worker/events.rs b/src/worker/events.rs index 4339970..5bc84c7 100644 --- a/src/worker/events.rs +++ b/src/worker/events.rs @@ -703,19 +703,12 @@ impl EventsWorker { } }; + // Nur NPC-Kinder werden vom Kindstod getroffen; user_id ist bei NPCs None let user_id: Option = rows .first() .and_then(|r| r.get("user_id")) .and_then(|v| v.parse::().ok()); - let user_id = match user_id { - Some(id) => id, - None => { - eprintln!("[EventsWorker] Kein user_id für Kind {} gefunden", character_id); - return Ok(()); - } - }; - // Wende Effekte an (in diesem Fall nur CharacterDeath) let mut effect_results = Vec::new(); for effect in &event.effects { @@ -740,32 +733,32 @@ impl EventsWorker { } } - // Schreibe Benachrichtigung in die Datenbank mit Event-Details - let notification_json = serde_json::json!({ - "tr": format!("random_event.{}", event.id), - "event_id": event.id, - "event_type": "personal", - "character_id": character_id, - "effects": effect_results - }); - Self::notify_user(pool, broker, user_id, ¬ification_json.to_string())?; + // Nur Spieler benachrichtigen (NPC-Kindstod hat keinen user_id) + if let Some(uid) = user_id { + let notification_json = serde_json::json!({ + "tr": format!("random_event.{}", event.id), + "event_id": event.id, + "event_type": "personal", + "character_id": character_id, + "effects": effect_results + }); + Self::notify_user(pool, broker, uid, ¬ification_json.to_string())?; - // Sende Benachrichtigung über WebSocket - let notification = json!({ - "event": "random_event", - "event_id": event.id, - "event_type": "personal", - "user_id": user_id, - "character_id": character_id, - "title": event.title, - "description": event.description, - "effects": effect_results - }); - - broker.publish(notification.to_string()); + let notification = json!({ + "event": "random_event", + "event_id": event.id, + "event_type": "personal", + "user_id": uid, + "character_id": character_id, + "title": event.title, + "description": event.description, + "effects": effect_results + }); + broker.publish(notification.to_string()); + } eprintln!( - "[EventsWorker] Plötzlicher Kindstod für Charakter {} (Spieler {}) verarbeitet", - character_id, user_id + "[EventsWorker] Plötzlicher Kindstod für Charakter {} verarbeitet", + character_id ); Ok(()) @@ -1295,8 +1288,8 @@ impl EventsWorker { min_change: i32, max_change: i32, rng: &mut impl Rng, - pool: &ConnectionPool, - broker: &MessageBroker, + _pool: &ConnectionPool, + _broker: &MessageBroker, ) -> Result<(i32, i32), DbError> { // Hole einen zufälligen Charakter des Spielers conn.prepare("get_random_character", QUERY_GET_RANDOM_CHARACTER)?; @@ -1322,19 +1315,13 @@ impl EventsWorker { .unwrap_or(100); let health_change = rng.gen_range(min_change..=max_change); - let new_health = (current_health + health_change).clamp(0, 100); + // Durch Unfälle/Krankheiten soll Gesundheit von Spieler-Charakteren nicht auf 0 fallen + let new_health = (current_health + health_change).clamp(1, 100); // Update Gesundheit conn.prepare("update_health", QUERY_UPDATE_HEALTH)?; conn.execute("update_health", &[&new_health, &character_id])?; - // Bei Health <= 0 sofort Tod prüfen und verarbeiten - if new_health <= 0 { - if let Err(e) = Self::handle_character_death(pool, broker, character_id) { - eprintln!("[EventsWorker] handle_character_death nach Health-Update: {e}"); - } - } - Ok((character_id, health_change)) } @@ -1400,7 +1387,16 @@ impl EventsWorker { .unwrap_or(100); let health_change = rng.gen_range(min_change..=max_change); - let new_health = (current_health + health_change).clamp(0, 100); + let user_id: Option = row + .get("user_id") + .and_then(|v| v.parse::().ok()); + // Durch Unfälle/Krankheiten soll Gesundheit von Spieler-Charakteren nicht auf 0 fallen + let new_health_raw = (current_health + health_change).clamp(0, 100); + let new_health = if user_id.is_some() { + new_health_raw.max(1) + } else { + new_health_raw + }; // Update Gesundheit conn.prepare("update_health_regional", QUERY_UPDATE_HEALTH)?; @@ -1444,7 +1440,14 @@ impl EventsWorker { None => continue, }; - // Verwende die existierende Logik zum Löschen von Charakteren + let user_id: Option = row + .get("user_id") + .and_then(|v| v.parse::().ok()); + // Nur NPCs (user_id IS NULL) von regionalem Tod betroffen + if user_id.is_some() { + continue; + } + if Self::handle_character_death(pool, broker, character_id).is_ok() { dead_characters.push(character_id); } diff --git a/src/worker/sql.rs b/src/worker/sql.rs index 9a06469..013d627 100644 --- a/src/worker/sql.rs +++ b/src/worker/sql.rs @@ -18,10 +18,11 @@ pub const QUERY_GET_RANDOM_USER: &str = r#" SELECT id FROM falukant_data.falukant_user ORDER BY RANDOM() LIMIT 1; "#; +/// Nur NPC-Kleinkinder (user_id IS NULL); Spieler-Charaktere sind von plötzlichem Kindstod ausgenommen. pub const QUERY_GET_RANDOM_INFANT: &str = r#" SELECT c.id AS character_id, c.user_id, CURRENT_DATE - c.birthdate::date AS age_days FROM falukant_data."character" c -WHERE c.user_id IS NOT NULL AND c.health > 0 AND CURRENT_DATE - c.birthdate::date <= 730 +WHERE c.user_id IS NULL AND c.health > 0 AND CURRENT_DATE - c.birthdate::date <= 730 ORDER BY RANDOM() LIMIT 1; "#; @@ -522,7 +523,7 @@ UPDATE falukant_data."character" SET health = $1 WHERE id = $2; "#; pub const QUERY_GET_REGION_CHARACTERS: &str = r#" -SELECT id, health FROM falukant_data."character" WHERE region_id = $1 AND health > 0; +SELECT id, health, user_id FROM falukant_data."character" WHERE region_id = $1 AND health > 0; "#; pub const QUERY_DELETE_DIRECTOR: &str = r#" @@ -605,6 +606,7 @@ pub const QUERY_GET_USERS_TO_UPDATE: &str = r#" WHERE user_id IS NOT NULL; "#; +/// Spieler-Charaktere mit Health <= 0 werden periodisch zum Tod verarbeitet. pub const QUERY_GET_CHARACTERS_ZERO_HEALTH: &str = r#" SELECT id FROM falukant_data."character" WHERE user_id IS NOT NULL AND health <= 0;