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;
14
15impl World {
16  #[inline]
17  pub fn subscribe(&self) -> Listener {
18    self.emitter.subscribe()
19  }
20
21  /// Emits the event to all players.
22  fn broadcast(&self, event: Event) -> Result<()> {
23    self.emitter.broadcast(event)
24  }
25
26  /// Emits the event for a specific player.
27  fn emit_to(&self, target: PlayerId, event: Event) -> Result<()> {
28    self.emitter.emit_to(target, event)
29  }
30
31  /// Emits the event to the owner of the city at the specified coordinate, if any.
32  fn emit_to_city_owner(&self, coord: Coord, event: Event) -> Result<()> {
33    let city = self.city(coord)?;
34    if let Some(player) = city.player() {
35      self.emitter.emit_to(player, event)?;
36    }
37
38    Ok(())
39  }
40
41  /// Emits [`Event::ChatMessage`].
42  pub(super) fn emit_chat_message(&self, message: ChatMessage) -> Result<()> {
43    let world = self.config.id();
44    self.broadcast(Event::ChatMessage { world, message })
45  }
46
47  /// Emits [`Event::City`].
48  pub(super) fn emit_city(&self, coord: Coord) -> Result<()> {
49    let world = self.config.id();
50    self.emit_to_city_owner(coord, Event::City { world, coord })
51  }
52
53  /// Emits [`Event::Drop`].
54  /// This should never be called manually.
55  pub(super) fn emit_drop(&self) -> Result<()> {
56    let world = self.config.id();
57    self.broadcast(Event::Drop { world })
58  }
59
60  /// Emits [`Event::Military`].
61  pub(super) fn emit_military(&self, player: PlayerId) -> Result<()> {
62    let world = self.config.id();
63    self.emit_to(player.clone(), Event::Military { world, player })
64  }
65
66  /// Emits [`Event::Military`] to all players participating in the specified maneuver.
67  pub(super) fn emit_military_to_maneuver_players(&self, id: ManeuverId) -> Result<()> {
68    let maneuver = self.military.maneuver(id)?;
69    let sender = self.city(maneuver.origin())?.player();
70    let target = self.city(maneuver.destination())?.player();
71
72    if let Some(sender) = &sender {
73      self.emit_military(sender.clone())?;
74    }
75
76    if let Some(target) = target
77      && sender.is_none_or(|it| it != target)
78    {
79      self.emit_military(target)?;
80    }
81
82    Ok(())
83  }
84
85  /// Emits [`Event::Player`].
86  pub(super) fn emit_player(&self, player: PlayerId) -> Result<()> {
87    let world = self.config.id();
88    self.emit_to(player.clone(), Event::Player { world, player })
89  }
90
91  /// Emits [`Event::PublicCity`].
92  pub(super) fn emit_public_city(&self, coord: Coord) -> Result<()> {
93    let world = self.config.id();
94    self.broadcast(Event::PublicCity { world, coord })
95  }
96
97  /// Emits [`Event::Report`].
98  pub(super) fn emit_report(&self, player: PlayerId, report: ReportKind) -> Result<()> {
99    let world = self.config.id();
100    self.emit_to(player, Event::Report { world, report: Box::new(report) })
101  }
102
103  pub(super) fn emit_battle_report(&self, report: BattleReport) -> Result<()> {
104    if let Some(attacker) = report.attacker().player().cloned() {
105      self.emit_report(attacker, report.clone().into())?;
106    }
107
108    if let Some(defender) = report.defender().player().cloned() {
109      debug_assert_ne!(report.attacker().player(), Some(&defender));
110      self.emit_report(defender, report.into())?;
111    }
112
113    Ok(())
114  }
115
116  pub(super) fn emit_support_report(&self, report: SupportReport) -> Result<()> {
117    if let Some(sender) = report.sender().player().cloned() {
118      self.emit_report(sender, report.clone().into())?;
119    }
120
121    if let Some(receiver) = report.receiver().player().cloned() {
122      debug_assert_ne!(report.sender().player(), Some(&receiver));
123      self.emit_report(receiver, report.into())?;
124    }
125
126    Ok(())
127  }
128
129  /// Emits [`Event::Round`].
130  pub(super) fn emit_round(&self) -> Result<()> {
131    let world = self.config.id();
132    let round = self.round.clone();
133    self.broadcast(Event::Round { world, round })
134  }
135}