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, EventId, 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 { id: EventId::new(), 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 { id: EventId::new(), 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 { id: EventId::new(), 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 { id: EventId::new(), world })
72  }
73
74  /// Emits [`Event::Military`].
75  pub(super) fn emit_military(&self, player: PlayerId) -> Result<()> {
76    let world = self.config.id();
77    let event = Event::Military {
78      id: EventId::new(),
79      world,
80      player: player.clone(),
81    };
82
83    self.emit_to(player, event)
84  }
85
86  /// Emits [`Event::Military`] to all players participating in the specified maneuver.
87  pub(super) fn emit_military_to_maneuver_players(&self, id: ManeuverId) -> Result<()> {
88    let maneuver = self.military.maneuver(id)?;
89    let mut players = HashSet::with_capacity(3);
90
91    if let Some(player) = self
92      .military
93      .army(maneuver.army())?
94      .owner()
95      .player()
96    {
97      players.insert(player);
98    }
99
100    if let Some(player) = self.city(maneuver.origin())?.player() {
101      players.insert(player);
102    }
103
104    if let Some(player) = self.city(maneuver.destination())?.player() {
105      players.insert(player);
106    }
107
108    for player in players {
109      self.emit_military(player.clone())?;
110    }
111
112    Ok(())
113  }
114
115  /// Emits [`Event::Player`].
116  pub(super) fn emit_player(&self, player: PlayerId) -> Result<()> {
117    let world = self.config.id();
118    let event = Event::Player {
119      id: EventId::new(),
120      world,
121      player: player.clone(),
122    };
123
124    self.emit_to(player, event)
125  }
126
127  /// Emits [`Event::PublicCity`] **and** [`Event::City`].
128  pub(super) fn emit_public_city(&self, coord: Coord) -> Result<()> {
129    let world = self.config.id();
130    self.broadcast(Event::PublicCity { id: EventId::new(), world, coord })?;
131    self.emit_city(coord)?;
132    Ok(())
133  }
134
135  /// Emits [`Event::Report`].
136  pub(super) fn emit_report(&self, player: PlayerId, report: ReportKind) -> Result<()> {
137    let world = self.config.id();
138    let event = Event::Report {
139      id: EventId::new(),
140      world,
141      report: Box::new(report),
142    };
143
144    self.emit_to(player, event)
145  }
146
147  /// Emits [`Event::Player`] if the ruler is a player.
148  pub(super) fn emit_ruler(&self, ruler: &Ruler) -> Result<()> {
149    if let Some(player) = ruler.player() {
150      self.emit_player(player.clone())?;
151    }
152
153    Ok(())
154  }
155
156  pub(super) fn emit_battle_report(&self, report: &BattleReport) -> Result<()> {
157    let mut players = HashSet::with_capacity(2);
158    if let Some(player) = report.attacker().player() {
159      players.insert(player);
160    }
161
162    if let Some(player) = report.defender().player() {
163      players.insert(player);
164    }
165
166    for player in players {
167      self.emit_report(player.clone(), report.clone().into())?;
168    }
169
170    Ok(())
171  }
172
173  pub(super) fn emit_support_report(&self, report: &SupportReport) -> Result<()> {
174    let mut players = HashSet::with_capacity(2);
175    if let Some(player) = report.sender().player() {
176      players.insert(player);
177    }
178
179    if let Some(player) = report.receiver().player() {
180      players.insert(player);
181    }
182
183    for player in players {
184      self.emit_report(player.clone(), report.clone().into())?;
185    }
186
187    Ok(())
188  }
189
190  /// Emits [`Event::Round`].
191  pub(super) fn emit_round(&self) -> Result<()> {
192    let world = self.config.id();
193    let round = self.round.clone();
194    self.broadcast(Event::Round { id: EventId::new(), world, round })
195  }
196}