nil-core 0.4.14

Multiplayer strategy game
Documentation
// Copyright (C) Call of Nil contributors
// SPDX-License-Identifier: AGPL-3.0-only

use crate::chat::ChatMessage;
use crate::continent::Coord;
use crate::event::{Event, Listener};
use crate::player::PlayerId;
use crate::report::battle::BattleReport;
use crate::report::support::SupportReport;
use crate::report::{Report, ReportId};
use crate::world::World;

impl World {
  #[inline]
  pub fn subscribe(&self) -> Listener {
    self.emitter.subscribe()
  }

  /// Emits the event to all players.
  fn broadcast(&self, event: Event) {
    self.emitter.broadcast(event);
  }

  /// Emits the event for a specific player.
  fn emit_to(&self, target: PlayerId, event: Event) {
    self.emitter.emit_to(target, event);
  }

  /// Emits the event to the owner of the city at the specified coordinate, if any.
  fn emit_to_owner(&self, coord: Coord, event: Event) {
    if let Ok(city) = self.city(coord)
      && let Some(player) = city.player()
    {
      self.emitter.emit_to(player, event);
    }
  }

  pub(super) fn emit_battle_report(&self, report: &BattleReport) {
    if let Some(attacker) = report.attacker().player().cloned() {
      self.emit_report(attacker, report.id());
    }

    if let Some(defender) = report.defender().player().cloned() {
      debug_assert_ne!(report.attacker().player(), Some(&defender));
      self.emit_report(defender, report.id());
    }
  }

  /// Emits [`Event::ChatUpdated`].
  pub(super) fn emit_chat_updated(&self, message: ChatMessage) {
    let world = self.config.id();
    self.broadcast(Event::ChatUpdated { world, message });
  }

  /// Emits [`Event::CityUpdated`].
  pub(super) fn emit_city_updated(&self, coord: Coord) {
    let world = self.config.id();
    self.emit_to_owner(coord, Event::CityUpdated { world, coord });
  }

  /// Emits [`Event::Drop`].
  /// This should never be called manually.
  pub(super) fn emit_drop(&self) {
    let world = self.config.id();
    self.broadcast(Event::Drop { world });
  }

  /// Emits [`Event::MilitaryUpdated`].
  pub(super) fn emit_military_updated(&self, player: PlayerId) {
    let world = self.config.id();
    self.emit_to(player.clone(), Event::MilitaryUpdated { world, player });
  }

  /// Emits [`Event::PlayerUpdated`].
  pub(super) fn emit_player_updated(&self, player: PlayerId) {
    let world = self.config.id();
    self.emit_to(player.clone(), Event::PlayerUpdated { world, player });
  }

  /// Emits [`Event::PublicCityUpdated`].
  pub(super) fn emit_public_city_updated(&self, coord: Coord) {
    let world = self.config.id();
    self.broadcast(Event::PublicCityUpdated { world, coord });
  }

  /// Emits [`Event::Report`].
  pub(super) fn emit_report(&self, player: PlayerId, report: ReportId) {
    let world = self.config.id();
    self.emit_to(player, Event::Report { world, report });
  }

  /// Emits [`Event::RoundUpdated`].
  pub(super) fn emit_round_updated(&self) {
    let world = self.config.id();
    let round = self.round.clone();
    self.broadcast(Event::RoundUpdated { world, round });
  }

  pub(super) fn emit_support_report(&self, report: &SupportReport) {
    if let Some(sender) = report.sender().player().cloned() {
      self.emit_report(sender, report.id());
    }

    if let Some(receiver) = report.receiver().player().cloned() {
      debug_assert_ne!(report.sender().player(), Some(&receiver));
      self.emit_report(receiver, report.id());
    }
  }
}