use std::{collections::HashMap, fmt::Debug, hash::Hash};
use crate::EntityCommand;
use crate::{
world::{
entity::entity_message::EntityMessage,
sync::{config::EngineConfig, remote_entity_channel::RemoteEntityChannel},
},
EntityAuthStatus, EntityMessageType, HostType, InScopeEntities, MessageIndex, RemoteEntity,
};
pub struct RemoteEngine<E: Copy + Hash + Eq + Debug> {
host_type: HostType,
pub config: EngineConfig,
entity_channels: HashMap<E, RemoteEntityChannel>,
incoming_events: Vec<EntityMessage<E>>,
outgoing_commands: Vec<EntityCommand>,
}
impl<E: Copy + Hash + Eq + Debug> RemoteEngine<E> {
pub(crate) fn new(host_type: HostType) -> Self {
Self {
host_type,
config: EngineConfig::default(),
incoming_events: Vec::new(),
entity_channels: HashMap::new(),
outgoing_commands: Vec::new(),
}
}
pub(crate) fn take_incoming_events(&mut self) -> Vec<EntityMessage<E>> {
std::mem::take(&mut self.incoming_events)
}
pub(crate) fn take_outgoing_commands(&mut self) -> Vec<EntityCommand> {
std::mem::take(&mut self.outgoing_commands)
}
pub(crate) fn get_world(&self) -> &HashMap<E, RemoteEntityChannel> {
&self.entity_channels
}
pub fn receive_message(&mut self, id: MessageIndex, msg: EntityMessage<E>) {
if msg.get_type() == EntityMessageType::Noop {
return;
}
let entity = msg.entity().unwrap();
if !self.entity_channels.contains_key(&entity) {
self.insert_entity_channel(entity, RemoteEntityChannel::new(self.host_type))
}
let entity_channel = self.entity_channels.get_mut(&entity).unwrap();
entity_channel.receive_message(id, msg.strip_entity());
entity_channel.drain_incoming_messages_into(entity, &mut self.incoming_events);
}
pub fn send_auth_command(&mut self, entity: E, command: EntityCommand) {
if !self.entity_channels.contains_key(&entity) {
panic!(
"Cannot send a command to an entity that does not exist in the engine: {:?}",
entity
);
}
let entity_channel = self.entity_channels.get_mut(&entity).unwrap();
entity_channel.send_command(command);
entity_channel.drain_outgoing_messages_into(&mut self.outgoing_commands);
}
pub fn receive_set_auth_status(&mut self, entity: E, auth_status: EntityAuthStatus) {
if let Some(channel) = self.entity_channels.get_mut(&entity) {
channel.update_auth_status(auth_status);
}
}
pub fn get_entity_auth_status(&self, entity: &E) -> Option<EntityAuthStatus> {
self.entity_channels
.get(entity)
.and_then(|channel| channel.auth_status())
}
pub fn send_entity_command(&mut self, entity: E, command: EntityCommand) {
if !self.entity_channels.contains_key(&entity) {
panic!(
"Cannot send a command to an entity that does not exist in the engine: {:?}",
entity
);
}
match command {
EntityCommand::Despawn(_) => {
self.entity_channels.remove(&entity);
}
EntityCommand::InsertComponent(_, component_kind) => {
if let Some(channel) = self.entity_channels.get_mut(&entity) {
channel.insert_component(component_kind);
}
}
EntityCommand::RemoveComponent(_, component_kind) => {
if let Some(channel) = self.entity_channels.get_mut(&entity) {
channel.remove_component(component_kind);
}
}
_ => {
}
}
}
pub(crate) fn remove_entity_channel(&mut self, entity: &E) -> RemoteEntityChannel {
self.entity_channels
.remove(entity)
.expect("Cannot remove entity channel that doesn't exist")
}
pub(crate) fn insert_entity_channel(&mut self, entity: E, channel: RemoteEntityChannel) {
if self.entity_channels.contains_key(&entity) {
panic!(
"Cannot insert entity channel that already exists for entity: {:?}",
entity
);
}
self.entity_channels.insert(entity, channel);
}
pub(crate) fn has_entity(&self, entity: &E) -> bool {
self.entity_channels.contains_key(entity)
}
pub(crate) fn get_entity_channel_mut(
&mut self,
entity: &E,
) -> Option<&mut RemoteEntityChannel> {
self.entity_channels.get_mut(entity)
}
pub(crate) fn get_world_mut(&mut self) -> &mut HashMap<E, RemoteEntityChannel> {
&mut self.entity_channels
}
}
impl InScopeEntities<RemoteEntity> for RemoteEngine<RemoteEntity> {
fn has_entity(&self, entity: &RemoteEntity) -> bool {
self.get_world().contains_key(entity)
}
}