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.clone(), 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`] to the city owner.
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    {
78      players.insert(player);
79    }
80
81    if let Some(player) = self.city(maneuver.origin())?.player() {
82      players.insert(player);
83    }
84
85    if let Some(player) = self.city(maneuver.destination())?.player() {
86      players.insert(player);
87    }
88
89    for player in players {
90      self.emit_military(player.clone())?;
91    }
92
93    Ok(())
94  }
95
96  /// Emits [`Event::Player`].
97  pub(super) fn emit_player(&self, player: PlayerId) -> Result<()> {
98    let world = self.config.id();
99    self.emit_to(player.clone(), Event::Player { world, player })
100  }
101
102  /// Emits [`Event::PublicCity`] **and** [`Event::City`].
103  pub(super) fn emit_public_city(&self, coord: Coord) -> Result<()> {
104    let world = self.config.id();
105    self.broadcast(Event::PublicCity { world, coord })?;
106    self.emit_city(coord)?;
107    Ok(())
108  }
109
110  /// Emits [`Event::Report`].
111  pub(super) fn emit_report(&self, player: PlayerId, report: ReportKind) -> Result<()> {
112    let world = self.config.id();
113    self.emit_to(player, Event::Report { world, report: Box::new(report) })
114  }
115
116  pub(super) fn emit_battle_report(&self, report: &BattleReport) -> Result<()> {
117    let mut players = HashSet::with_capacity(2);
118    if let Some(player) = report.attacker().player() {
119      players.insert(player);
120    }
121
122    if let Some(player) = report.defender().player() {
123      players.insert(player);
124    }
125
126    for player in players {
127      self.emit_report(player.clone(), report.clone().into())?;
128    }
129
130    Ok(())
131  }
132
133  pub(super) fn emit_support_report(&self, report: &SupportReport) -> Result<()> {
134    let mut players = HashSet::with_capacity(2);
135    if let Some(player) = report.sender().player() {
136      players.insert(player);
137    }
138
139    if let Some(player) = report.receiver().player() {
140      players.insert(player);
141    }
142
143    for player in players {
144      self.emit_report(player.clone(), report.clone().into())?;
145    }
146
147    Ok(())
148  }
149
150  /// Emits [`Event::Round`].
151  pub(super) fn emit_round(&self) -> Result<()> {
152    let world = self.config.id();
153    let round = self.round.clone();
154    self.broadcast(Event::Round { world, round })
155  }
156}