common_game/protocols/
orchestrator_planet.rs

1//! # Orchestrator and Planet protocol messages
2//!
3//! Defines the types of messages exchanged of the full duplex communication channel
4//! between the Orchestrator and the Planets
5//! For a more detailed view of the interactions between these two entities, visit the communications [diagrams](https://github.com/unitn-ap-2025/common/blob/main/MESSAGE_DIAGRAMS.md)
6
7use crate::components::asteroid::Asteroid;
8use crate::components::planet::DummyPlanetState;
9use crate::components::rocket::Rocket;
10use crate::components::sunray::Sunray;
11use crate::protocols::planet_explorer::PlanetToExplorer;
12use crate::utils::ID;
13use crossbeam_channel::Sender;
14use enum_as_inner::EnumAsInner;
15use strum_macros::EnumDiscriminants;
16
17#[cfg(doc)]
18use {crate::components::energy_cell::EnergyCell, crate::components::planet::Planet};
19
20/// This enum describes all possible messages from the Orchestrator to a Planet
21#[derive(Debug, EnumAsInner, EnumDiscriminants)]
22#[strum_discriminants(name(OrchestratorToPlanetKind))]
23#[strum_discriminants(derive(Hash))]
24pub enum OrchestratorToPlanet {
25    /// This variant is used to send a [Sunray] to a planet
26    ///
27    /// **Expected Response**: [`PlanetToOrchestrator::SunrayAck`]
28    ///
29    /// **Use Case**: sending a [Sunray] to charge [`EnergyCell`]
30    Sunray(Sunray),
31    /// This variant is used to send an [Asteroid] to a planet
32    ///
33    /// **Expected Response**: [`PlanetToOrchestrator::AsteroidAck`]
34    ///
35    /// **Use Case**: sending an [Asteroid] to attack a [Planet]
36    Asteroid(Asteroid),
37    /// This variant is used to start a Planet AI and restart it if it is stopped
38    ///
39    /// **Expected Response**: [`PlanetToOrchestrator::StartPlanetAIResult`]
40    ///
41    /// **Use Case**: Starting the Planet AI at game start or restart the AI in case it is stopped
42    StartPlanetAI,
43    /// This variant is used to pause the planet Ai
44    ///
45    /// **Expected Response**: [`PlanetToOrchestrator::StopPlanetAIResult`]
46    ///
47    /// **Use Case**: Freezing Planet ability to respond to every message,
48    /// a planet in this state will only answer with [`PlanetToOrchestrator::Stopped`]
49    StopPlanetAI,
50    /// This variant is used to kill (or destroy) the planet
51    ///
52    /// **Expected Response**: [`PlanetToOrchestrator::KillPlanetResult`]
53    ///
54    /// **Use Case**: Instantly kill a Planet
55    KillPlanet,
56    /// This variant is used to obtain a Planet Internal State
57    ///
58    /// **Expected Response**: [`PlanetToOrchestrator::InternalStateResponse`]
59    ///
60    /// **Use Case**: The GUI can use this message to obtain the relevant info of the planet to be shown
61    InternalStateRequest,
62    /// This variant is used to advertise an incoming explorer to a planet
63    ///
64    /// **Expected Response**: [`PlanetToOrchestrator::IncomingExplorerResponse`]
65    ///
66    /// **Use Case**: Moving an explorer to this planet
67    IncomingExplorerRequest {
68        ///The incoming explorer's id
69        explorer_id: ID,
70        ///The new sender half of the [`crossbeam_channel`] for the planet to communicate with the incoming explorer
71        new_sender: Sender<PlanetToExplorer>,
72    },
73    /// This variant is used to advertise an outgoing explorer to a planet
74    ///
75    /// **Expected Response**: [`PlanetToOrchestrator::OutgoingExplorerResponse`]
76    ///
77    /// **Use Case**: Asking the planet to delete the [Sender] to the outgoing explorer
78    OutgoingExplorerRequest {
79        ///The outgoing explorer's id
80        explorer_id: ID,
81    },
82}
83
84/// This enum describes all possible messages from a Planet to the Orchestrator
85#[derive(Debug, EnumAsInner, EnumDiscriminants)]
86#[strum_discriminants(name(PlanetToOrchestratorKind))]
87#[strum_discriminants(derive(Hash))]
88pub enum PlanetToOrchestrator {
89    /// This variant is used to acknowledge the obtained [Sunray]
90    ///
91    /// **Response to**: [`OrchestratorToPlanet::Sunray`]
92    SunrayAck {
93        ///ID of the planet sending the message
94        planet_id: ID,
95    },
96    /// This variant is used to acknowledge the obtained [Asteroid] and notify the orchestrator
97    /// if the planet has a rocket to defend itself
98    ///
99    /// **Response to**: [`OrchestratorToPlanet::Asteroid`]
100    AsteroidAck {
101        ///ID of the planet sending the message
102        planet_id: ID,
103        ///Optional rocket returned to the Orchestrator to decide if planet can deflect the asteroid
104        rocket: Option<Rocket>,
105    },
106    /// This variant is used to acknowledge the starting of the Planet Ai
107    ///
108    /// **Response to**: [`OrchestratorToPlanet::StartPlanetAI`]
109    StartPlanetAIResult {
110        ///ID of the planet sending the message
111        planet_id: ID,
112    },
113    /// This variant is used to acknowledge the stopping of the Planet Ai, in this state a planet will only respond
114    /// to incoming messages with a [`PlanetToOrchestrator::Stopped`]
115    ///
116    /// **Response to**: [`OrchestratorToPlanet::StopPlanetAI`]
117    StopPlanetAIResult {
118        ///ID of the planet sending the message
119        planet_id: ID,
120    },
121    /// This variant is used to acknowledge the killing of a planet, in this case the planet thread will be terminated
122    /// and the planet will be deleted from the galaxy
123    ///
124    /// **Response to**: [`OrchestratorToPlanet::KillPlanet`]
125    KillPlanetResult { planet_id: ID },
126    /// This variant is used to send back the Planet State
127    ///
128    /// **Response to** [`OrchestratorToPlanet::InternalStateRequest`]
129    InternalStateResponse {
130        ///ID of the planet sending the message
131        planet_id: ID,
132        ///A struct containing the relevant information of a Planet to be shown by the GUI
133        planet_state: DummyPlanetState,
134    },
135    /// This variant is used to acknowledge the incoming explorer reception
136    ///
137    /// **Response to** [`OrchestratorToPlanet::IncomingExplorerRequest`]
138    IncomingExplorerResponse {
139        ///ID of the planet sending the message
140        planet_id: ID,
141        ///Incoming explorer's ID
142        explorer_id: ID,
143        ///Result of the operation:
144        ///
145        /// [Ok] if the [Sender] to the incoming explorer has been correctly set up
146        ///
147        /// [Err(String)] if an error occurred
148        res: Result<(), String>,
149    },
150    /// This variant is used to acknowledge that an explorer is leaving the planet
151    ///
152    /// **Response to**: [`OrchestratorToPlanet::OutgoingExplorerRequest`]
153    OutgoingExplorerResponse {
154        ///ID of the planet sending the message
155        planet_id: ID,
156        ///Incoming explorer's ID
157        explorer_id: ID,
158        ///Result of the operation:
159        ///
160        /// [Ok] if the [Sender] to the outgoing explorer has been correctly deleted
161        ///
162        /// [Err(String)] if an error occurred
163        res: Result<(), String>,
164    },
165    /// This variant is used by planets that are currently in a *stopped* state
166    /// to acknowledge any message coming from the Orchestrator (except for [`OrchestratorToPlanet::StartPlanetAI`])
167    Stopped {
168        ///ID of the planet sending the message
169        planet_id: ID,
170    },
171}
172impl PlanetToOrchestrator {
173    /// Helper method to extract the `planet_id` field from any message variant
174    /// without needing to match a specific one.
175    #[must_use]
176    pub fn planet_id(&self) -> ID {
177        match self {
178            PlanetToOrchestrator::SunrayAck { planet_id, .. }
179            | PlanetToOrchestrator::AsteroidAck { planet_id, .. }
180            | PlanetToOrchestrator::StartPlanetAIResult { planet_id, .. }
181            | PlanetToOrchestrator::StopPlanetAIResult { planet_id, .. }
182            | PlanetToOrchestrator::KillPlanetResult { planet_id, .. }
183            | PlanetToOrchestrator::InternalStateResponse { planet_id, .. }
184            | PlanetToOrchestrator::IncomingExplorerResponse { planet_id, .. }
185            | PlanetToOrchestrator::OutgoingExplorerResponse { planet_id, .. }
186            | PlanetToOrchestrator::Stopped { planet_id, .. } => *planet_id,
187        }
188    }
189}