use crate::Identifier;
use bevy::prelude::*;
#[derive(Component, Clone, Copy, PartialEq, Eq, Default, Debug)]
#[repr(u8)]
pub enum Authority {
#[default]
Server,
Free,
Client(u32),
}
impl Authority {
#[inline(always)]
pub fn can_claim(&self, client_id: u32) -> bool {
use Authority::*;
match *self {
Server => false,
Free => true,
Client(owner) => owner == client_id,
}
}
}
#[repr(u8)]
#[derive(Resource, Clone, Copy, Hash, PartialEq, Eq, Debug)]
pub enum Identity {
Server,
Client(u32),
}
impl From<&Identity> for Identity {
fn from(value: &Identity) -> Self {
*value
}
}
impl Identity {
#[inline(always)]
pub fn can_send(self, auth: Option<&Authority>) -> bool {
match self {
Identity::Server => true,
Identity::Client(id) => auth == Some(&Authority::Client(id)),
}
}
pub fn as_identifier(&self) -> Identifier {
let Identity::Client(client_id) = self else {
panic!("Cannot call as_identifier on Identity::Server")
};
Identifier::new(0, *client_id)
}
}
#[derive(Resource, Deref, DerefMut, Default)]
pub struct HeldAuthority(bevy::utils::HashSet<Entity>);
pub fn track_authority(
query: Query<(Entity, &Authority), Changed<Authority>>,
mut removed: RemovedComponents<Authority>,
mut held: ResMut<HeldAuthority>,
our_ident: Res<Identity>,
) {
let Identity::Client(client_id) = *our_ident else {
return;
};
for (entity, auth) in query.iter() {
if auth.can_claim(client_id) {
held.insert(entity);
} else {
held.remove(&entity);
}
}
for entity in removed.read() {
held.remove(&entity);
}
}