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 nil_util::vec::VecExt as _;
15use smallvec::SmallVec;
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 for 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 the owner of the city at the specified coordinate, if any.
34  fn emit_to_city_owner(&self, coord: Coord, event: Event) -> Result<()> {
35    let city = self.city(coord)?;
36    if let Some(player) = city.player() {
37      self.emitter.emit_to(player.clone(), event)?;
38    }
39
40    Ok(())
41  }
42
43  /// Emits [`Event::ChatMessage`].
44  pub(super) fn emit_chat_message(&self, message: ChatMessage) -> Result<()> {
45    let world = self.config.id();
46    self.broadcast(Event::ChatMessage { world, message })
47  }
48
49  /// Emits [`Event::City`].
50  pub(super) fn emit_city(&self, coord: Coord) -> Result<()> {
51    let world = self.config.id();
52    self.emit_to_city_owner(coord, Event::City { world, coord })
53  }
54
55  /// Emits [`Event::Drop`].
56  /// This should never be called manually.
57  pub(super) fn emit_drop(&self) -> Result<()> {
58    let world = self.config.id();
59    self.broadcast(Event::Drop { world })
60  }
61
62  /// Emits [`Event::Military`].
63  pub(super) fn emit_military(&self, player: PlayerId) -> Result<()> {
64    let world = self.config.id();
65    self.emit_to(player.clone(), Event::Military { world, player })
66  }
67
68  /// Emits [`Event::Military`] to all players participating in the specified maneuver.
69  pub(super) fn emit_military_to_maneuver_players(&self, id: ManeuverId) -> Result<()> {
70    let maneuver = self.military.maneuver(id)?;
71    let mut players = SmallVec::<[_; 3]>::new();
72
73    if let Some(player) = self
74      .military
75      .army(maneuver.army())?
76      .owner()
77      .player()
78    {
79      players.push(player);
80    }
81
82    if let Some(player) = self.city(maneuver.origin())?.player() {
83      players.push_unique(player);
84    }
85
86    if let Some(player) = self.city(maneuver.destination())?.player() {
87      players.push_unique(player);
88    }
89
90    for player in players {
91      self.emit_military(player.clone())?;
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 = SmallVec::<[_; 2]>::new();
117    if let Some(player) = report.attacker().player() {
118      players.push(player);
119    }
120
121    if let Some(player) = report.defender().player() {
122      players.push_unique(player);
123    }
124
125    for player in players {
126      self.emit_report(player.clone(), report.clone().into())?;
127    }
128
129    Ok(())
130  }
131
132  pub(super) fn emit_support_report(&self, report: &SupportReport) -> Result<()> {
133    let mut players = SmallVec::<[_; 2]>::new();
134    if let Some(player) = report.sender().player() {
135      players.push(player);
136    }
137
138    if let Some(player) = report.receiver().player() {
139      players.push_unique(player);
140    }
141
142    for player in players {
143      self.emit_report(player.clone(), 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}