naia_shared/world/sync/
auth_channel.rs1use crate::{
2 world::{
3 host::host_world_manager::SubCommandId,
4 sync::{
5 auth_channel_receiver::AuthChannelReceiver, auth_channel_sender::AuthChannelSender,
6 remote_entity_channel::EntityChannelState,
7 },
8 },
9 EntityAuthStatus, EntityCommand, EntityMessage, EntityMessageType, HostType, MessageIndex,
10};
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub enum EntityAuthChannelState {
15 Unpublished,
17 Published,
19 Delegated,
21}
22
23pub(crate) struct AuthChannel {
24 host_type: HostType,
25 state: EntityAuthChannelState,
26 auth_status: Option<EntityAuthStatus>,
27 sender: AuthChannelSender,
28 receiver: AuthChannelReceiver,
29}
30
31impl AuthChannel {
32 pub(crate) fn new(host_type: HostType) -> Self {
33 let state = match host_type {
34 HostType::Client => EntityAuthChannelState::Unpublished,
35 HostType::Server => EntityAuthChannelState::Published,
36 };
37 Self {
38 host_type,
39 state,
40 auth_status: None,
41 sender: AuthChannelSender::new(),
42 receiver: AuthChannelReceiver::new(),
43 }
44 }
45
46 pub(crate) fn validate_command(&mut self, command: &EntityCommand) {
47 let entity = command.entity();
48
49 match command.get_type() {
50 EntityMessageType::Publish => {
51 if self.state != EntityAuthChannelState::Unpublished {
52 panic!(
53 "Cannot publish Entity: {:?} that is already published",
54 entity
55 );
56 }
57 self.state = EntityAuthChannelState::Published;
58 }
59 EntityMessageType::Unpublish => {
60 if self.state != EntityAuthChannelState::Published {
61 panic!(
62 "Cannot unpublish Entity: {:?} that is not published",
63 entity
64 );
65 }
66 self.state = EntityAuthChannelState::Unpublished;
67 }
68 EntityMessageType::EnableDelegation => {
69 if self.state != EntityAuthChannelState::Published {
70 panic!(
71 "Cannot enable delegation on Entity: {:?} that is not published",
72 entity
73 );
74 }
75 self.state = EntityAuthChannelState::Delegated;
76 self.auth_status = Some(EntityAuthStatus::Available);
77 }
78 EntityMessageType::DisableDelegation => {
79 #[cfg(feature = "e2e_debug")]
80 crate::e2e_trace!(
81 "[CLIENT_RECV] DisableDelegation entity={:?} current_state={:?}",
82 entity,
83 self.state
84 );
85 if self.state != EntityAuthChannelState::Delegated {
86 panic!(
87 "Cannot disable delegation on Entity: {:?} that is not delegated",
88 entity
89 );
90 }
91 self.state = EntityAuthChannelState::Published;
92 }
93 EntityMessageType::ReleaseAuthority => {
94 if self.state != EntityAuthChannelState::Delegated {
95 panic!(
96 "Cannot release authority on Entity: {:?} that is not delegated",
97 entity
98 );
99 }
100
101 self.auth_status = Some(EntityAuthStatus::Available);
103 }
104 EntityMessageType::SetAuthority => {
105 if self.state != EntityAuthChannelState::Delegated {
106 panic!(
107 "Cannot set authority on Entity: {:?} that is not delegated",
108 entity
109 );
110 }
111
112 let EntityCommand::SetAuthority(_, _entity, next_status) = command else {
113 panic!("Expected SetAuthority command");
114 };
115
116 let from_status = self.auth_status.unwrap();
117 #[cfg(feature = "e2e_debug")]
118 crate::e2e_trace!(
119 "[CLIENT_RECV] SetAuthority entity={:?} from_status={:?} to_status={:?}",
120 command.entity(),
121 from_status,
122 next_status
123 );
124
125 match (from_status, next_status) {
126 (EntityAuthStatus::Available, EntityAuthStatus::Requested)
127 | (EntityAuthStatus::Available, EntityAuthStatus::Granted)
128 | (EntityAuthStatus::Available, EntityAuthStatus::Denied)
129 | (EntityAuthStatus::Requested, EntityAuthStatus::Granted)
130 | (EntityAuthStatus::Requested, EntityAuthStatus::Denied)
131 | (EntityAuthStatus::Requested, EntityAuthStatus::Available)
132 | (EntityAuthStatus::Denied, EntityAuthStatus::Granted)
133 | (EntityAuthStatus::Denied, EntityAuthStatus::Available)
134 | (EntityAuthStatus::Granted, EntityAuthStatus::Available)
135 | (EntityAuthStatus::Granted, EntityAuthStatus::Denied)
136 | (EntityAuthStatus::Granted, EntityAuthStatus::Releasing)
137 | (EntityAuthStatus::Releasing, EntityAuthStatus::Available)
138 | (EntityAuthStatus::Releasing, EntityAuthStatus::Denied) => {
139 }
141 (from_status, to_status) => {
142 panic!(
143 "Invalid authority transition from {:?} to {:?}",
144 from_status, to_status
145 );
146 }
147 }
148
149 self.auth_status = Some(*next_status);
150 }
151 EntityMessageType::RequestAuthority => {
152 if self.state != EntityAuthChannelState::Delegated {
154 panic!(
155 "Cannot request authority on Entity: {:?} that is not delegated",
156 entity
157 );
158 }
159 }
161 EntityMessageType::EnableDelegationResponse => {
162 if self.state != EntityAuthChannelState::Delegated {
165 panic!("Cannot send EnableDelegationResponse for Entity: {:?} that is not delegated", entity);
166 }
167 }
168 EntityMessageType::MigrateResponse => {
169 if self.state != EntityAuthChannelState::Delegated {
173 panic!(
174 "Cannot send MigrateResponse for Entity: {:?} that is not delegated",
175 entity
176 );
177 }
178 }
179 EntityMessageType::Noop => {
180 }
182 e => {
183 panic!("Unsupported command type for AuthChannelSender: {:?}", e);
184 }
185 }
186 }
187
188 pub(crate) fn send_command(&mut self, command: EntityCommand) {
189 self.sender.send_command(command);
190 }
191
192 pub(crate) fn sender_drain_messages_into(&mut self, commands: &mut Vec<EntityCommand>) {
193 self.sender.drain_messages_into(commands);
194 }
195
196 pub fn state(&self) -> EntityAuthChannelState {
198 self.state
199 }
200
201 pub fn auth_status(&self) -> Option<EntityAuthStatus> {
203 self.auth_status
204 }
205
206 pub fn is_delegated(&self) -> bool {
208 self.state == EntityAuthChannelState::Delegated
209 }
210
211 pub(crate) fn reset(&mut self) {
213 *self = Self::new(self.host_type);
214 }
215
216 pub(crate) fn receiver_drain_messages_into(
217 &mut self,
218 outgoing_messages: &mut Vec<EntityMessage<()>>,
219 ) {
220 self.receiver.drain_messages_into(outgoing_messages);
221 }
222
223 pub(crate) fn receiver_buffer_pop_front_until_and_including(&mut self, id: MessageIndex) {
224 self.receiver.buffer_pop_front_until_and_including(id);
225 }
226
227 pub(crate) fn receiver_receive_message(
228 &mut self,
229 entity_state_opt: Option<EntityChannelState>,
230 id: MessageIndex,
231 msg: EntityMessage<()>,
232 ) {
233 self.receiver.receive_message(entity_state_opt, id, msg);
234 }
235
236 pub(crate) fn receiver_process_messages(&mut self, entity_state: EntityChannelState) {
237 self.receiver.process_messages(Some(entity_state));
238 }
239
240 pub(crate) fn receiver_set_next_subcommand_id(&mut self, id: SubCommandId) {
242 self.receiver.set_next_subcommand_id(id);
243 }
244
245 pub(crate) fn force_publish(&mut self) {
247 self.state = EntityAuthChannelState::Published;
248 }
249
250 pub(crate) fn force_enable_delegation(&mut self) {
252 self.state = EntityAuthChannelState::Delegated;
253 self.auth_status = Some(EntityAuthStatus::Available);
254 }
255
256 pub(crate) fn force_set_auth_status(&mut self, auth_status: EntityAuthStatus) {
258 self.auth_status = Some(auth_status);
259 }
260
261 #[cfg(feature = "e2e_debug")]
262 pub(crate) fn receiver_debug_diagnostic(
263 &self,
264 ) -> (SubCommandId, usize, Option<SubCommandId>, usize) {
265 self.receiver.debug_diagnostic()
266 }
267}