Skip to main content

naia_shared/world/
entity_command.rs

1use crate::{
2    world::host::host_world_manager::SubCommandId, ComponentKind, EntityAuthStatus,
3    EntityMessageType, GlobalEntity, HostEntity, RemoteEntity,
4};
5
6// TODO! make this agnostic to type of entity
7
8/// Wire command syncing entity lifecycle and authority transitions from host to remote.
9#[derive(Clone, PartialEq, Eq, Debug)]
10pub enum EntityCommand {
11    /// Spawn an entity with no initial components.
12    Spawn(GlobalEntity),
13    /// Spawn an entity pre-loaded with the listed component kinds.
14    SpawnWithComponents(GlobalEntity, Vec<ComponentKind>),
15    /// Despawn an existing entity.
16    Despawn(GlobalEntity),
17    /// Insert a component onto an existing entity.
18    InsertComponent(GlobalEntity, ComponentKind),
19    /// Remove a component from an existing entity.
20    RemoveComponent(GlobalEntity, ComponentKind),
21
22    /// Publish a delegated entity so it becomes visible to other users.
23    Publish(Option<SubCommandId>, GlobalEntity),
24    /// Retract a previously published entity.
25    Unpublish(Option<SubCommandId>, GlobalEntity),
26    /// Enable client-authority delegation for an entity.
27    EnableDelegation(Option<SubCommandId>, GlobalEntity),
28    /// Revoke client-authority delegation (server only).
29    DisableDelegation(Option<SubCommandId>, GlobalEntity),
30    /// Update the authority status for a delegated entity (server only).
31    SetAuthority(Option<SubCommandId>, GlobalEntity, EntityAuthStatus),
32
33    /// Client requests authority over a delegated entity.
34    RequestAuthority(Option<SubCommandId>, GlobalEntity),
35    /// Client releases previously held authority.
36    ReleaseAuthority(Option<SubCommandId>, GlobalEntity),
37    /// Client acknowledges that delegation has been enabled.
38    EnableDelegationResponse(Option<SubCommandId>, GlobalEntity),
39    /// Server notifies that an entity has migrated from remote to host (subid, global, old_remote, new_host).
40    MigrateResponse(Option<SubCommandId>, GlobalEntity, RemoteEntity, HostEntity),
41}
42
43impl EntityCommand {
44    /// Returns the primary `GlobalEntity` this command targets.
45    pub fn entity(&self) -> GlobalEntity {
46        match self {
47            Self::Spawn(entity) => *entity,
48            Self::SpawnWithComponents(entity, _) => *entity,
49            Self::Despawn(entity) => *entity,
50            Self::InsertComponent(entity, _) => *entity,
51            Self::RemoveComponent(entity, _) => *entity,
52            Self::Publish(_, entity) => *entity,
53            Self::Unpublish(_, entity) => *entity,
54            Self::EnableDelegation(_, entity) => *entity,
55            Self::DisableDelegation(_, entity) => *entity,
56            Self::SetAuthority(_, entity, _) => *entity,
57            Self::RequestAuthority(_, entity) => *entity,
58            Self::ReleaseAuthority(_, entity) => *entity,
59            Self::EnableDelegationResponse(_, entity) => *entity,
60            Self::MigrateResponse(_, entity, _, _) => *entity,
61        }
62    }
63
64    /// Returns the `ComponentKind` for insert/remove commands, or `None` for all other variants.
65    pub fn component_kind(&self) -> Option<ComponentKind> {
66        match self {
67            Self::InsertComponent(_, component_kind) => Some(*component_kind),
68            Self::RemoveComponent(_, component_kind) => Some(*component_kind),
69            _ => None,
70        }
71    }
72
73    /// Returns the `EntityMessageType` discriminant for this command.
74    pub fn get_type(&self) -> EntityMessageType {
75        match self {
76            Self::Spawn(_) => EntityMessageType::Spawn,
77            Self::SpawnWithComponents(_, _) => EntityMessageType::SpawnWithComponents,
78            Self::Despawn(_) => EntityMessageType::Despawn,
79            Self::InsertComponent(_, _) => EntityMessageType::InsertComponent,
80            Self::RemoveComponent(_, _) => EntityMessageType::RemoveComponent,
81            Self::Publish(_, _) => EntityMessageType::Publish,
82            Self::Unpublish(_, _) => EntityMessageType::Unpublish,
83            Self::EnableDelegation(_, _) => EntityMessageType::EnableDelegation,
84            Self::DisableDelegation(_, _) => EntityMessageType::DisableDelegation,
85            Self::SetAuthority(_, _, _) => EntityMessageType::SetAuthority,
86            Self::RequestAuthority(_, _) => EntityMessageType::RequestAuthority,
87            Self::ReleaseAuthority(_, _) => EntityMessageType::ReleaseAuthority,
88            Self::EnableDelegationResponse(_, _) => EntityMessageType::EnableDelegationResponse,
89            Self::MigrateResponse(_, _, _, _) => EntityMessageType::MigrateResponse,
90        }
91    }
92
93    pub(crate) fn set_subcommand_id(&mut self, id: SubCommandId) {
94        match self {
95            Self::Spawn(_)
96            | Self::SpawnWithComponents(_, _)
97            | Self::Despawn(_)
98            | Self::InsertComponent(_, _)
99            | Self::RemoveComponent(_, _) => {
100                panic!("Cannot set subcommand ID for a command that does not have one");
101            }
102            Self::Publish(sub_id, _)
103            | Self::Unpublish(sub_id, _)
104            | Self::EnableDelegation(sub_id, _)
105            | Self::DisableDelegation(sub_id, _)
106            | Self::SetAuthority(sub_id, _, _)
107            | Self::RequestAuthority(sub_id, _)
108            | Self::ReleaseAuthority(sub_id, _)
109            | Self::EnableDelegationResponse(sub_id, _)
110            | Self::MigrateResponse(sub_id, _, _, _) => {
111                *sub_id = Some(id);
112            }
113        }
114    }
115
116    /// Returns `true` if this command can be applied to a remote (client-owned) entity.
117    pub fn is_valid_for_remote_entity(&self) -> bool {
118        match self {
119            Self::Publish(_, _)
120            | Self::Unpublish(_, _)
121            | Self::EnableDelegation(_, _)
122            | Self::DisableDelegation(_, _) => false,
123
124            Self::InsertComponent(_, _) | Self::RemoveComponent(_, _) | Self::Despawn(_) => true,
125
126            _ => false,
127        }
128    }
129}