45 lines
2 KiB
Rust
45 lines
2 KiB
Rust
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<Arc<HashMap<i32, CommandRegistryEntry>>> = OnceLock::new();
|
|
pub struct LogicCommandManager;
|
|
impl LogicCommandManager {
|
|
pub fn registry() -> Arc<HashMap<i32, CommandRegistryEntry>> {
|
|
Arc::clone(REGISTRY.get_or_init(|| {
|
|
let mut entries = HashMap::new();
|
|
for entry in titan::inventory::iter::<CommandRegistryEntry> {
|
|
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<CommandRegistryEntry> {
|
|
Self::registry().get(&command_type).copied()
|
|
}
|
|
pub fn decode_command(reader: &mut ByteStreamReader<'_>) -> Result<Box<dyn LogicCommand>> {
|
|
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<dyn LogicCommand> {
|
|
fn encode(&self, writer: &mut ByteStreamWriter) -> Result<()> {
|
|
LogicCommandManager::encode_command(writer, self.as_ref())
|
|
}
|
|
fn decode(reader: &mut ByteStreamReader<'_>) -> Result<Self> {
|
|
LogicCommandManager::decode_command(reader)
|
|
}
|
|
}
|