use crate::battle::logic_game_object::{LogicGameObjectEntry, COMPONENT_PASSES, OBJECT_TYPE_COUNT}; use titan::{ByteStreamReader, ByteStreamWriter, Payload, Result}; #[derive(Debug, Clone, PartialEq, Eq)] pub struct LogicGameObjectManager { pub instance_counters: [i32; OBJECT_TYPE_COUNT], pub objects: Vec, } impl Default for LogicGameObjectManager { fn default() -> Self { Self { instance_counters: [0; OBJECT_TYPE_COUNT], objects: Vec::new(), } } } impl LogicGameObjectManager { pub fn reserve_instance(&mut self, object_type: i32) -> i32 { let Ok(index) = usize::try_from(object_type) else { return 0; }; let Some(counter) = self.instance_counters.get_mut(index) else { return 0; }; let instance = *counter; *counter = instance + 1; instance } fn note(&self, index: usize, entry: &LogicGameObjectEntry, section: &str) { if !titan::checksum::checksum_trace_active() { return; } let id = match entry.global_id.0 { Some(id) => format!("{}:{}", id.class_id, id.instance_id), None => "-".to_string(), }; titan::checksum::checksum_trace_note(format!( "objects[{index}].{section} {id} {}", entry.data.name() )); } pub fn push(&mut self, entry: LogicGameObjectEntry) { let object_type = entry.object_type(); if let Ok(index) = usize::try_from(object_type) { if let Some(counter) = self.instance_counters.get_mut(index) { let instance = entry.global_id.0.map(|id| id.instance_id).unwrap_or(0); *counter = (*counter).max(instance + 1); } } self.objects.push(entry); self.objects .sort_by_key(|entry| entry.global_id.0.map(|id| (id.class_id, id.instance_id))); } } impl Payload for LogicGameObjectManager { fn encode(&self, writer: &mut ByteStreamWriter) -> Result<()> { titan::checksum::checksum_trace_note("objects.instance_counters"); for counter in self.instance_counters { writer.write_vint(counter); } titan::checksum::checksum_trace_note("objects.count"); writer.write_vint(self.objects.len() as i32); for (index, entry) in self.objects.iter().enumerate() { self.note(index, entry, "data"); entry.data.encode(writer)?; } for (index, entry) in self.objects.iter().enumerate() { self.note(index, entry, "global_id"); entry.global_id.encode(writer)?; } for (index, entry) in self.objects.iter().enumerate() { self.note(index, entry, "body"); entry.body.encode(writer)?; } for pass in 0..COMPONENT_PASSES { for (index, entry) in self.objects.iter().enumerate() { if let Some(component) = &entry.components[pass] { self.note(index, entry, component.kind()); component.encode(writer)?; } } } Ok(()) } fn decode(_reader: &mut ByteStreamReader<'_>) -> Result { Err(titan::Error::Unsupported( "LogicGameObjectManager is encode only", )) } }