1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
use crate::events::ApplicableEvent;
use crate::game_mode::GameMode;
use crate::team::Team;
use crate::units::player_unit_system_identifier::PlayerUnitSystemIdentifier;
use crate::units::player_unit_system_upgradepath::PlayerUnitSystemUpgradePath;
use crate::universe::Universe;
use crate::universe_group::UniverseGroup;
use serde_derive::{Deserialize, Serialize};
use std::sync::Arc;

/// This event notifies about the meta information a [`UniverseGroup`] has, like name,
/// description, teams, rules... You actually don't need to parse this event because it's also
/// parsed by the connector and the results are presented in fields on the [`UniverseGroup`].
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct UniverseGroupInfoEvent {
    /// The name of the [`UniverseGroup`].
    pub name: String,
    /// The description of the [`UniverseGroup`].
    pub description: String,
    /// The [`GameMode`] of the [`UniverseGroup`].
    pub mode: GameMode,
    pub metrics: Metrics,
    /// The [`Team`]s in the [`UniverseGroup`].
    pub teams: Vec<Team>,
    /// The [`Universe`]s in the [`UniverseGroup`].
    universes: Vec<Universe>,
    /// The system upgrade paths in the [`UniverseGroup`].
    systems: Vec<PlayerUnitSystemUpgradePath>,
}

impl ApplicableEvent<UniverseGroup> for UniverseGroupInfoEvent {
    fn apply(self, group: &mut UniverseGroup) {
        group.name = self.name;
        group.description = self.description;
        group.mode = self.mode;

        for system in self.systems {
            group.systems.insert(
                PlayerUnitSystemIdentifier {
                    system: system.kind,
                    level: Some(system.level),
                },
                system,
            );
        }

        self.metrics.apply(group);

        group.teams = Default::default();
        for mut team in self.teams {
            let id = team.id.0;
            team.connection = Arc::downgrade(&group.connection);
            group.teams[id] = Some(team);
        }

        group.universes = {
            const EMPTY: Option<Universe> = None;
            [EMPTY; 64]
        };
        for mut universe in self.universes {
            let id = universe.id;
            universe.connection = Arc::downgrade(&group.connection);
            group.universes[id.0] = Some(universe);
        }
    }
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Metrics {
    /// The amount of players together in the [`UniverseGroup`].
    #[serde(rename = "maxPlayers")]
    pub max_players: u32,
    /// The amount of ships a player can have in the [`UniverseGroup`].
    #[serde(rename = "maxShipsPerPlayer")]
    pub max_ships_per_player: u32,
    /// The amount of ships a team can have in the [`UniverseGroup`].
    #[serde(rename = "maxShipsPerTeam")]
    pub max_ships_per_team: u32,
    /// The amount of bases a player can have in the [`UniverseGroup`].
    #[serde(rename = "maxBasesPerPlayer")]
    pub max_bases_per_player: u32,
    /// The amount of bases a team can have in the [`UniverseGroup`].
    #[serde(rename = "maxBasesPerTeam")]
    pub max_bases_per_team: u32,
    /// True, if joining this universe as a spectator is allowed.
    pub spectators: bool,
    /// The amount of ships that you can register in the [`UniverseGroup`].
    #[serde(rename = "registerShipLimit")]
    pub register_ship_limit: u32,
}

impl ApplicableEvent<UniverseGroup> for Metrics {
    fn apply(self, group: &mut UniverseGroup) {
        group.max_players = self.max_players;
        group.max_ships_per_player = self.max_ships_per_player;
        group.max_ships_per_team = self.max_ships_per_team;
        group.max_bases_per_player = self.max_bases_per_player;
        group.max_bases_per_team = self.max_bases_per_team;
        group.spectators = self.spectators;
        group.register_ship_limit = self.register_ship_limit;
    }
}