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::ruler::Ruler;
14use crate::world::World;
15use std::collections::HashSet;
16
17impl World {
18  #[inline]
19  pub fn subscribe(&self) -> Listener {
20    self.emitter.subscribe()
21  }
22
23  /// Emits the event to all players.
24  fn broadcast(&self, event: Event) -> Result<()> {
25    self.emitter.broadcast(event)
26  }
27
28  /// Emits the event to a specific player.
29  fn emit_to(&self, target: PlayerId, event: Event) -> Result<()> {
30    self.emitter.emit_to(target, event)
31  }
32
33  /// Emits the event to a specific ruler, if they're a player.
34  fn emit_to_ruler(&self, ruler: &Ruler, event: Event) -> Result<()> {
35    if let Some(player) = ruler.player() {
36      self.emitter.emit_to(player.clone(), event)?;
37    }
38
39    Ok(())
40  }
41
42  /// Emits the event to the owner of the city at the specified coordinate, if they're a player.
43  fn emit_to_city_owner(&self, coord: Coord, event: Event) -> Result<()> {
44    let city = self.city(coord)?;
45    self.emit_to_ruler(city.owner(), event)?;
46    Ok(())
47  }
48
49  /// Emits [`Event::ChatMessage`].
50  pub(super) fn emit_chat_message(&self, message: ChatMessage) -> Result<()> {
51    let world = self.config.id();
52    self.broadcast(Event::ChatMessage { world, message })
53  }
54
55  /// Emits [`Event::City`] to the city owner, if they're a player.
56  pub(super) fn emit_city(&self, coord: Coord) -> Result<()> {
57    let world = self.config.id();
58    self.emit_to_city_owner(coord, Event::City { world, coord })
59  }
60
61  /// Emits [`Event::Drop`].
62  /// This should never be called manually.
63  pub(super) fn emit_drop(&self) -> Result<()> {
64    let world = self.config.id();
65    self.broadcast(Event::Drop { world })
66  }
67
68  /// Emits [`Event::Market`].
69  pub(super) fn emit_market(&self) -> Result<()> {
70    let world = self.config.id();
71    self.broadcast(Event::Market { world })
72  }
73
74  /// Emits [`Event::Military`].
75  pub(super) fn emit_military(&self, player: PlayerId) -> Result<()> {
76    let world = self.config.id();
77    self.emit_to(player.clone(), Event::Military { world, player })
78  }
79
80  /// Emits [`Event::Military`] to all players participating in the specified maneuver.
81  pub(super) fn emit_military_to_maneuver_players(&self, id: ManeuverId) -> Result<()> {
82    let maneuver = self.military.maneuver(id)?;
83    let mut players = HashSet::with_capacity(3);
84
85    if let Some(player) = self
86      .military
87      .army(maneuver.army())?
88      .owner()
89      .player()
90    {
91      players.insert(player);
92    }
93
94    if let Some(player) = self.city(maneuver.origin())?.player() {
95      players.insert(player);
96    }
97
98    if let Some(player) = self.city(maneuver.destination())?.player() {
99      players.insert(player);
100    }
101
102    for player in players {
103      self.emit_military(player.clone())?;
104    }
105
106    Ok(())
107  }
108
109  /// Emits [`Event::Player`].
110  pub(super) fn emit_player(&self, player: PlayerId) -> Result<()> {
111    let world = self.config.id();
112    self.emit_to(player.clone(), Event::Player { world, player })
113  }
114
115  /// Emits [`Event::PublicCity`] **and** [`Event::City`].
116  pub(super) fn emit_public_city(&self, coord: Coord) -> Result<()> {
117    let world = self.config.id();
118    self.broadcast(Event::PublicCity { world, coord })?;
119    self.emit_city(coord)?;
120    Ok(())
121  }
122
123  /// Emits [`Event::Report`].
124  pub(super) fn emit_report(&self, player: PlayerId, report: ReportKind) -> Result<()> {
125    let world = self.config.id();
126    self.emit_to(player, Event::Report { world, report: Box::new(report) })
127  }
128
129  /// Emits [`Event::Player`] if the ruler is a player.
130  pub(super) fn emit_ruler(&self, ruler: &Ruler) -> Result<()> {
131    if let Some(player) = ruler.player() {
132      self.emit_player(player.clone())?;
133    }
134
135    Ok(())
136  }
137
138  pub(super) fn emit_battle_report(&self, report: &BattleReport) -> Result<()> {
139    let mut players = HashSet::with_capacity(2);
140    if let Some(player) = report.attacker().player() {
141      players.insert(player);
142    }
143
144    if let Some(player) = report.defender().player() {
145      players.insert(player);
146    }
147
148    for player in players {
149      self.emit_report(player.clone(), report.clone().into())?;
150    }
151
152    Ok(())
153  }
154
155  pub(super) fn emit_support_report(&self, report: &SupportReport) -> Result<()> {
156    let mut players = HashSet::with_capacity(2);
157    if let Some(player) = report.sender().player() {
158      players.insert(player);
159    }
160
161    if let Some(player) = report.receiver().player() {
162      players.insert(player);
163    }
164
165    for player in players {
166      self.emit_report(player.clone(), report.clone().into())?;
167    }
168
169    Ok(())
170  }
171
172  /// Emits [`Event::Round`].
173  pub(super) fn emit_round(&self) -> Result<()> {
174    let world = self.config.id();
175    let round = self.round.clone();
176    self.broadcast(Event::Round { world, round })
177  }
178}