Skip to main content

nil_core/world/
event.rs

1// Copyright (C) Call of Nil contributors
2// SPDX-License-Identifier: AGPL-3.0-only
3
4use crate::chat::ChatMessage;
5use crate::continent::coord::Coord;
6use crate::error::Result;
7use crate::event::{Event, Listener};
8use crate::military::maneuver::ManeuverId;
9use crate::player::PlayerId;
10use crate::report::ReportKind;
11use crate::report::battle::BattleReport;
12use crate::report::support::SupportReport;
13use crate::world::World;
14use std::collections::HashSet;
15
16impl World {
17  #[inline]
18  pub fn subscribe(&self) -> Listener {
19    self.emitter.subscribe()
20  }
21
22  /// Emits the event to all players.
23  fn broadcast(&self, event: Event) -> Result<()> {
24    self.emitter.broadcast(event)
25  }
26
27  /// Emits the event for a specific player.
28  fn emit_to(&self, target: PlayerId, event: Event) -> Result<()> {
29    self.emitter.emit_to(target, event)
30  }
31
32  /// Emits the event to the owner of the city at the specified coordinate, if any.
33  fn emit_to_city_owner(&self, coord: Coord, event: Event) -> Result<()> {
34    let city = self.city(coord)?;
35    if let Some(player) = city.player() {
36      self.emitter.emit_to(player, event)?;
37    }
38
39    Ok(())
40  }
41
42  /// Emits [`Event::ChatMessage`].
43  pub(super) fn emit_chat_message(&self, message: ChatMessage) -> Result<()> {
44    let world = self.config.id();
45    self.broadcast(Event::ChatMessage { world, message })
46  }
47
48  /// Emits [`Event::City`].
49  pub(super) fn emit_city(&self, coord: Coord) -> Result<()> {
50    let world = self.config.id();
51    self.emit_to_city_owner(coord, Event::City { world, coord })
52  }
53
54  /// Emits [`Event::Drop`].
55  /// This should never be called manually.
56  pub(super) fn emit_drop(&self) -> Result<()> {
57    let world = self.config.id();
58    self.broadcast(Event::Drop { world })
59  }
60
61  /// Emits [`Event::Military`].
62  pub(super) fn emit_military(&self, player: PlayerId) -> Result<()> {
63    let world = self.config.id();
64    self.emit_to(player.clone(), Event::Military { world, player })
65  }
66
67  /// Emits [`Event::Military`] to all players participating in the specified maneuver.
68  pub(super) fn emit_military_to_maneuver_players(&self, id: ManeuverId) -> Result<()> {
69    let maneuver = self.military.maneuver(id)?;
70    let mut players = HashSet::with_capacity(3);
71
72    if let Some(player) = self
73      .military
74      .army(maneuver.army())?
75      .owner()
76      .player()
77      .cloned()
78    {
79      players.insert(player);
80    }
81
82    if let Some(player) = self.city(maneuver.origin())?.player() {
83      players.insert(player);
84    }
85
86    if let Some(player) = self.city(maneuver.destination())?.player() {
87      players.insert(player);
88    }
89
90    for player in players {
91      self.emit_military(player)?;
92    }
93
94    Ok(())
95  }
96
97  /// Emits [`Event::Player`].
98  pub(super) fn emit_player(&self, player: PlayerId) -> Result<()> {
99    let world = self.config.id();
100    self.emit_to(player.clone(), Event::Player { world, player })
101  }
102
103  /// Emits [`Event::PublicCity`].
104  pub(super) fn emit_public_city(&self, coord: Coord) -> Result<()> {
105    let world = self.config.id();
106    self.broadcast(Event::PublicCity { world, coord })
107  }
108
109  /// Emits [`Event::Report`].
110  pub(super) fn emit_report(&self, player: PlayerId, report: ReportKind) -> Result<()> {
111    let world = self.config.id();
112    self.emit_to(player, Event::Report { world, report: Box::new(report) })
113  }
114
115  pub(super) fn emit_battle_report(&self, report: BattleReport) -> Result<()> {
116    let mut players = HashSet::with_capacity(2);
117    if let Some(player) = report.attacker().player() {
118      players.insert(player.clone());
119    }
120
121    if let Some(player) = report.defender().player() {
122      players.insert(player.clone());
123    }
124
125    for player in players {
126      self.emit_report(player, report.clone().into())?;
127    }
128
129    Ok(())
130  }
131
132  pub(super) fn emit_support_report(&self, report: SupportReport) -> Result<()> {
133    let mut players = HashSet::with_capacity(2);
134    if let Some(player) = report.sender().player() {
135      players.insert(player.clone());
136    }
137
138    if let Some(player) = report.receiver().player() {
139      players.insert(player.clone());
140    }
141
142    for player in players {
143      self.emit_report(player, report.clone().into())?;
144    }
145
146    Ok(())
147  }
148
149  /// Emits [`Event::Round`].
150  pub(super) fn emit_round(&self) -> Result<()> {
151    let world = self.config.id();
152    let round = self.round.clone();
153    self.broadcast(Event::Round { world, round })
154  }
155}