use std::{
clone::Clone,
collections::{HashMap, HashSet, VecDeque},
hash::Hash,
};
use crate::{
messages::channels::senders::indexed_message_writer::IndexedMessageWriter,
sequence_list::SequenceList,
world::{
entity::entity_converters::GlobalWorldManagerType, local_world_manager::LocalWorldManager,
},
BitWrite, BitWriter, ComponentKind, ComponentKinds, ConstBitLength, EntityAction,
EntityActionType, EntityAndLocalEntityConverter, EntityConverterMut, HostWorldEvents,
HostWorldManager, Instant, MessageIndex, PacketIndex, Serde, UnsignedVariableInteger,
WorldRefType,
};
use super::entity_action_event::EntityActionEvent;
pub type ActionId = MessageIndex;
pub struct HostWorldWriter;
impl HostWorldWriter {
fn write_action_id(
writer: &mut dyn BitWrite,
last_id_opt: &mut Option<ActionId>,
current_id: &ActionId,
) {
IndexedMessageWriter::write_message_index(writer, last_id_opt, current_id);
*last_id_opt = Some(*current_id);
}
pub fn write_into_packet<E: Copy + Eq + Hash + Send + Sync, W: WorldRefType<E>>(
component_kinds: &ComponentKinds,
now: &Instant,
writer: &mut BitWriter,
packet_index: &PacketIndex,
world: &W,
global_world_manager: &dyn GlobalWorldManagerType<E>,
local_world_manager: &mut LocalWorldManager<E>,
has_written: &mut bool,
host_manager: &mut HostWorldManager<E>,
world_events: &mut HostWorldEvents<E>,
) {
Self::write_updates(
component_kinds,
now,
writer,
&packet_index,
world,
global_world_manager,
local_world_manager,
has_written,
host_manager,
&mut world_events.next_send_updates,
);
Self::write_actions(
component_kinds,
now,
writer,
&packet_index,
world,
global_world_manager,
local_world_manager,
has_written,
host_manager,
&mut world_events.next_send_actions,
);
}
fn write_actions<E: Copy + Eq + Hash + Send + Sync, W: WorldRefType<E>>(
component_kinds: &ComponentKinds,
now: &Instant,
writer: &mut BitWriter,
packet_index: &PacketIndex,
world: &W,
global_world_manager: &dyn GlobalWorldManagerType<E>,
local_world_manager: &mut LocalWorldManager<E>,
has_written: &mut bool,
host_manager: &mut HostWorldManager<E>,
next_send_actions: &mut VecDeque<(ActionId, EntityActionEvent<E>)>,
) {
let mut last_counted_id: Option<MessageIndex> = None;
let mut last_written_id: Option<MessageIndex> = None;
loop {
if next_send_actions.is_empty() {
break;
}
let mut counter = writer.counter();
true.ser(&mut counter);
Self::write_action(
component_kinds,
world,
global_world_manager,
local_world_manager,
packet_index,
&mut counter,
&mut last_counted_id,
false,
host_manager,
next_send_actions,
);
if counter.overflowed() {
if !*has_written {
Self::warn_overflow_action(
component_kinds,
counter.bits_needed(),
writer.bits_free(),
next_send_actions,
);
}
break;
}
*has_written = true;
if !host_manager
.sent_action_packets
.contains_scan_from_back(packet_index)
{
host_manager
.sent_action_packets
.insert_scan_from_back(*packet_index, (now.clone(), Vec::new()));
}
true.ser(writer);
Self::write_action(
component_kinds,
world,
global_world_manager,
local_world_manager,
packet_index,
writer,
&mut last_written_id,
true,
host_manager,
next_send_actions,
);
next_send_actions.pop_front();
}
writer.release_bits(1);
false.ser(writer);
}
#[allow(clippy::too_many_arguments)]
fn write_action<E: Copy + Eq + Hash + Send + Sync, W: WorldRefType<E>>(
component_kinds: &ComponentKinds,
world: &W,
global_world_manager: &dyn GlobalWorldManagerType<E>,
local_world_manager: &mut LocalWorldManager<E>,
packet_index: &PacketIndex,
writer: &mut dyn BitWrite,
last_written_id: &mut Option<ActionId>,
is_writing: bool,
host_manager: &mut HostWorldManager<E>,
next_send_actions: &mut VecDeque<(ActionId, EntityActionEvent<E>)>,
) {
let (action_id, action) = next_send_actions.front().unwrap();
Self::write_action_id(writer, last_written_id, action_id);
match action {
EntityActionEvent::SpawnEntity(world_entity, component_kind_list) => {
EntityActionType::SpawnEntity.ser(writer);
local_world_manager
.entity_to_host_entity(world_entity)
.unwrap()
.ser(writer);
let components_num =
UnsignedVariableInteger::<3>::new(component_kind_list.len() as i128);
components_num.ser(writer);
for component_kind in component_kind_list {
let mut converter =
EntityConverterMut::new(global_world_manager, local_world_manager);
world
.component_of_kind(world_entity, component_kind)
.expect("Component does not exist in World")
.write(component_kinds, writer, &mut converter);
}
if is_writing {
Self::record_action_written(
&mut host_manager.sent_action_packets,
packet_index,
action_id,
EntityAction::SpawnEntity(*world_entity, component_kind_list.clone()),
);
}
}
EntityActionEvent::DespawnEntity(world_entity) => {
EntityActionType::DespawnEntity.ser(writer);
local_world_manager
.entity_to_host_entity(world_entity)
.unwrap()
.ser(writer);
if is_writing {
Self::record_action_written(
&mut host_manager.sent_action_packets,
packet_index,
action_id,
EntityAction::DespawnEntity(*world_entity),
);
}
}
EntityActionEvent::InsertComponent(world_entity, component) => {
if !host_manager
.world_channel
.entity_channel_is_open(world_entity)
|| !world.has_component_of_kind(world_entity, component)
{
EntityActionType::Noop.ser(writer);
if is_writing {
Self::record_action_written(
&mut host_manager.sent_action_packets,
packet_index,
action_id,
EntityAction::Noop,
);
}
} else {
EntityActionType::InsertComponent.ser(writer);
local_world_manager
.entity_to_host_entity(world_entity)
.unwrap()
.ser(writer);
let mut converter =
EntityConverterMut::new(global_world_manager, local_world_manager);
world
.component_of_kind(world_entity, component)
.expect("Component does not exist in World")
.write(component_kinds, writer, &mut converter);
if is_writing {
Self::record_action_written(
&mut host_manager.sent_action_packets,
packet_index,
action_id,
EntityAction::InsertComponent(*world_entity, *component),
);
}
}
}
EntityActionEvent::RemoveComponent(world_entity, component_kind) => {
if !host_manager
.world_channel
.entity_channel_is_open(world_entity)
{
EntityActionType::Noop.ser(writer);
if is_writing {
Self::record_action_written(
&mut host_manager.sent_action_packets,
packet_index,
action_id,
EntityAction::Noop,
);
}
} else {
EntityActionType::RemoveComponent.ser(writer);
local_world_manager
.entity_to_host_entity(world_entity)
.unwrap()
.ser(writer);
component_kind.ser(component_kinds, writer);
if is_writing {
Self::record_action_written(
&mut host_manager.sent_action_packets,
packet_index,
action_id,
EntityAction::RemoveComponent(*world_entity, *component_kind),
);
}
}
}
}
}
#[allow(clippy::type_complexity)]
fn record_action_written<E: Copy + Eq + Hash + Send + Sync>(
sent_actions: &mut SequenceList<(Instant, Vec<(ActionId, EntityAction<E>)>)>,
packet_index: &PacketIndex,
action_id: &ActionId,
action_record: EntityAction<E>,
) {
let (_, sent_actions_list) = sent_actions.get_mut_scan_from_back(packet_index).unwrap();
sent_actions_list.push((*action_id, action_record));
}
fn warn_overflow_action<E: Copy + Eq + Hash + Send + Sync>(
component_kinds: &ComponentKinds,
bits_needed: u32,
bits_free: u32,
next_send_actions: &VecDeque<(ActionId, EntityActionEvent<E>)>,
) {
let (_action_id, action) = next_send_actions.front().unwrap();
match action {
EntityActionEvent::SpawnEntity(_entity, component_kind_list) => {
let mut component_names = "".to_owned();
let mut added = false;
for component_kind in component_kind_list {
if added {
component_names.push(',');
} else {
added = true;
}
let name = component_kinds.kind_to_name(component_kind);
component_names.push_str(&name);
}
panic!(
"Packet Write Error: Blocking overflow detected! Entity Spawn message with Components `{component_names}` requires {bits_needed} bits, but packet only has {bits_free} bits available! Recommend slimming down these Components."
)
}
EntityActionEvent::InsertComponent(_entity, component_kind) => {
let component_name = component_kinds.kind_to_name(component_kind);
panic!(
"Packet Write Error: Blocking overflow detected! Component Insertion message of type `{component_name}` requires {bits_needed} bits, but packet only has {bits_free} bits available! This condition should never be reached, as large Messages should be Fragmented in the Reliable channel"
)
}
_ => {
panic!(
"Packet Write Error: Blocking overflow detected! Action requires {bits_needed} bits, but packet only has {bits_free} bits available! This message should never display..."
)
}
}
}
fn write_updates<E: Copy + Eq + Hash + Send + Sync, W: WorldRefType<E>>(
component_kinds: &ComponentKinds,
now: &Instant,
writer: &mut BitWriter,
packet_index: &PacketIndex,
world: &W,
global_world_manager: &dyn GlobalWorldManagerType<E>,
local_world_manager: &mut LocalWorldManager<E>,
has_written: &mut bool,
host_manager: &mut HostWorldManager<E>,
next_send_updates: &mut HashMap<E, HashSet<ComponentKind>>,
) {
let all_update_entities: Vec<E> = next_send_updates.keys().copied().collect();
for entity in all_update_entities {
let host_entity = local_world_manager.entity_to_host_entity(&entity).unwrap();
let mut counter = writer.counter();
counter.write_bit(true);
counter.write_bit(true);
host_entity.ser(&mut counter);
if counter.overflowed() {
break;
}
writer.reserve_bits(1);
true.ser(writer);
host_entity.ser(writer);
Self::write_update(
component_kinds,
now,
world,
global_world_manager,
local_world_manager,
packet_index,
writer,
&entity,
has_written,
host_manager,
next_send_updates,
);
writer.release_bits(1);
false.ser(writer);
}
writer.release_bits(1);
false.ser(writer);
}
fn write_update<E: Copy + Eq + Hash + Send + Sync, W: WorldRefType<E>>(
component_kinds: &ComponentKinds,
now: &Instant,
world: &W,
global_world_manager: &dyn GlobalWorldManagerType<E>,
local_world_manager: &mut LocalWorldManager<E>,
packet_index: &PacketIndex,
writer: &mut BitWriter,
entity: &E,
has_written: &mut bool,
host_manager: &mut HostWorldManager<E>,
next_send_updates: &mut HashMap<E, HashSet<ComponentKind>>,
) {
let mut written_component_kinds = Vec::new();
let component_kind_set = next_send_updates.get(entity).unwrap();
for component_kind in component_kind_set {
let diff_mask = host_manager
.world_channel
.diff_handler
.diff_mask(entity, component_kind)
.clone();
let mut converter = EntityConverterMut::new(global_world_manager, local_world_manager);
let mut counter = writer.counter();
true.ser(&mut counter);
counter.count_bits(<ComponentKind as ConstBitLength>::const_bit_length());
world
.component_of_kind(entity, component_kind)
.expect("Component does not exist in World")
.write_update(&diff_mask, &mut counter, &mut converter);
if counter.overflowed() {
if !*has_written {
let component_name = component_kinds.kind_to_name(component_kind);
Self::warn_overflow_update(
component_name,
counter.bits_needed(),
writer.bits_free(),
);
}
break;
}
*has_written = true;
true.ser(writer);
component_kind.ser(component_kinds, writer);
world
.component_of_kind(entity, component_kind)
.expect("Component does not exist in World")
.write_update(&diff_mask, writer, &mut converter);
written_component_kinds.push(*component_kind);
host_manager.last_update_packet_index = *packet_index;
if !host_manager.sent_updates.contains_key(packet_index) {
host_manager
.sent_updates
.insert(*packet_index, (now.clone(), HashMap::new()));
}
let (_, sent_updates_map) = host_manager.sent_updates.get_mut(packet_index).unwrap();
sent_updates_map.insert((*entity, *component_kind), diff_mask);
host_manager
.world_channel
.diff_handler
.clear_diff_mask(entity, component_kind);
}
let update_kinds = next_send_updates.get_mut(entity).unwrap();
for component_kind in &written_component_kinds {
update_kinds.remove(component_kind);
}
if update_kinds.is_empty() {
next_send_updates.remove(entity);
}
}
fn warn_overflow_update(component_name: String, bits_needed: u32, bits_free: u32) {
panic!(
"Packet Write Error: Blocking overflow detected! Data update of Component `{component_name}` requires {bits_needed} bits, but packet only has {bits_free} bits available! Recommended to slim down this Component"
)
}
}