use crate::commands::command::{CommandRegistryEntry, LogicCommand}; use std::collections::HashMap; use std::sync::{Arc, OnceLock}; use titan::{ByteStreamReader, ByteStreamWriter, Error, Payload, Result}; static REGISTRY: OnceLock>> = OnceLock::new(); pub struct LogicCommandManager; impl LogicCommandManager { pub fn registry() -> Arc> { Arc::clone(REGISTRY.get_or_init(|| { let mut entries = HashMap::new(); for entry in titan::inventory::iter:: { if let Some(previous) = entries.insert(entry.command_type, *entry) { tracing::warn!( command_type = entry.command_type, previous = previous.name, replacement = entry.name, "two commands declare the same type" ); } } tracing::debug!(commands = entries.len(), "command registry collected"); Arc::new(entries) })) } pub fn lookup(command_type: i32) -> Option { Self::registry().get(&command_type).copied() } pub fn decode_command(reader: &mut ByteStreamReader<'_>) -> Result> { let command_type = reader.read_vint()?; let entry = Self::lookup(command_type).ok_or(Error::UnknownCommandType(command_type))?; entry.decode(reader) } pub fn encode_command(writer: &mut ByteStreamWriter, command: &dyn LogicCommand) -> Result<()> { writer.write_vint(command.command_type()); command.encode_body(writer) } } impl Payload for Box { fn encode(&self, writer: &mut ByteStreamWriter) -> Result<()> { LogicCommandManager::encode_command(writer, self.as_ref()) } fn decode(reader: &mut ByteStreamReader<'_>) -> Result { LogicCommandManager::decode_command(reader) } }