use std::collections::VecDeque;
use crate::world::sync::ordered_ids::OrderedIds;
use crate::{
sequence_equal_or_less_than, world::sync::remote_entity_channel::EntityChannelState,
ComponentKind, EntityMessage, EntityMessageType, MessageIndex,
};
pub(crate) struct RemoteComponentChannel {
inserted: bool,
last_epoch_id: Option<MessageIndex>,
buffered_messages: OrderedIds<bool>,
incoming_messages: VecDeque<EntityMessageType>,
}
impl RemoteComponentChannel {
pub(crate) fn new() -> Self {
Self {
inserted: false,
last_epoch_id: None,
buffered_messages: OrderedIds::new(),
incoming_messages: VecDeque::new(),
}
}
pub(crate) fn drain_messages_into(
&mut self,
component_kind: &ComponentKind,
outgoing_messages: &mut Vec<EntityMessage<()>>,
) {
let mut received_messages = Vec::new();
for msg_type in std::mem::take(&mut self.incoming_messages) {
received_messages.push(msg_type.with_component_kind(component_kind));
}
outgoing_messages.append(&mut received_messages);
}
pub(crate) fn buffer_pop_front_until_and_excluding(&mut self, id: MessageIndex) {
self.buffered_messages.pop_front_until_and_excluding(id);
}
pub(crate) fn accept_message(
&mut self,
entity_state: EntityChannelState,
id: MessageIndex,
msg: EntityMessage<()>,
) {
if let Some(last_epoch_id) = self.last_epoch_id {
if sequence_equal_or_less_than(id, last_epoch_id) {
return;
}
}
let insert = match &msg {
EntityMessage::InsertComponent(_, _) => true,
EntityMessage::RemoveComponent(_, _) => false,
_ => panic!(
"ComponentChannel can only accept InsertComponent or RemoveComponent messages"
),
};
self.buffered_messages.push_back(id, insert);
self.process_messages(entity_state);
}
pub(crate) fn process_messages(&mut self, entity_state: EntityChannelState) {
if entity_state != EntityChannelState::Spawned {
return;
}
loop {
let Some((id, insert)) = self.buffered_messages.peek_front() else {
break;
};
let id = *id;
match *insert {
true => {
if self.inserted {
break;
}
self.set_inserted(true, id);
}
false => {
if !self.inserted {
break;
}
self.set_inserted(false, id);
}
}
let (_, insert) = self.buffered_messages.pop_front().unwrap();
if insert {
self.incoming_messages
.push_back(EntityMessageType::InsertComponent);
} else {
self.incoming_messages
.push_back(EntityMessageType::RemoveComponent);
}
}
}
pub(crate) fn set_inserted(&mut self, inserted: bool, last_epoch_id: MessageIndex) {
self.inserted = inserted;
self.last_epoch_id = Some(last_epoch_id);
}
pub(crate) fn is_inserted(&self) -> bool {
self.inserted
}
pub(crate) fn force_drain_buffers(&mut self, _entity_state: EntityChannelState) {
while let Some((id, insert)) = self.buffered_messages.pop_front() {
if insert {
self.incoming_messages
.push_back(EntityMessageType::InsertComponent);
} else {
self.incoming_messages
.push_back(EntityMessageType::RemoveComponent);
}
self.inserted = insert;
self.last_epoch_id = Some(id);
}
}
}