109 lines
3.8 KiB
Rust
109 lines
3.8 KiB
Rust
use std::path::Path;
|
|
use std::sync::Arc;
|
|
use logic::{table, LogicDataRef, LogicDataTables};
|
|
use crate::config::{CardRef, DataSelector};
|
|
pub const GOLD_RESOURCE_FALLBACK_INSTANCE: i32 = 1;
|
|
pub const ARENA_FALLBACK_INSTANCE: i32 = 1;
|
|
pub struct Catalog {
|
|
tables: Arc<LogicDataTables>,
|
|
}
|
|
impl Catalog {
|
|
pub fn empty() -> Self {
|
|
Self {
|
|
tables: Arc::new(LogicDataTables::empty()),
|
|
}
|
|
}
|
|
pub fn load(root: Option<&Path>) -> Self {
|
|
let Some(root) = root else {
|
|
tracing::info!("no csv root configured, starter profiles must use explicit table ids");
|
|
return Self::empty();
|
|
};
|
|
match LogicDataTables::load_from_dir(root) {
|
|
Ok(tables) => {
|
|
tracing::info!(
|
|
root = %root.display(),
|
|
loaded = tables.loaded_files().len(),
|
|
skipped = tables.skipped_files().len(),
|
|
"logic data tables loaded"
|
|
);
|
|
let tables = Arc::new(tables);
|
|
if !LogicDataTables::install(Arc::clone(&tables)) {
|
|
tracing::warn!("data tables were already installed for this process");
|
|
}
|
|
Self { tables }
|
|
}
|
|
Err(error) => {
|
|
tracing::warn!(root = %root.display(), %error, "falling back to explicit table ids");
|
|
Self::empty()
|
|
}
|
|
}
|
|
}
|
|
pub fn tables(&self) -> &LogicDataTables {
|
|
&self.tables
|
|
}
|
|
pub fn is_loaded(&self) -> bool {
|
|
self.tables.is_loaded()
|
|
}
|
|
pub fn resolve_card(&self, card: &CardRef) -> Option<LogicDataRef> {
|
|
match card {
|
|
CardRef::Explicit { table, instance } => Some(LogicDataRef::of(*table, *instance)),
|
|
CardRef::Named(name) => {
|
|
let resolved = LogicDataRef::by_name(table::SPELLS, name);
|
|
if resolved.is_none() {
|
|
tracing::warn!(card = %name, "unknown card name, dropping it from the profile");
|
|
return None;
|
|
}
|
|
Some(resolved)
|
|
}
|
|
}
|
|
}
|
|
pub fn resolve(
|
|
&self,
|
|
selector: &DataSelector,
|
|
table_index: i32,
|
|
fallback: i32,
|
|
) -> LogicDataRef {
|
|
match selector {
|
|
DataSelector::Instance(instance) => LogicDataRef::of(table_index, *instance),
|
|
DataSelector::Named(name) => {
|
|
let resolved = LogicDataRef::by_name(table_index, name);
|
|
if resolved.is_none() {
|
|
tracing::warn!(
|
|
name = %name,
|
|
table = table_index,
|
|
fallback,
|
|
"unknown data name, using the fallback instance"
|
|
);
|
|
return LogicDataRef::of(table_index, fallback);
|
|
}
|
|
resolved
|
|
}
|
|
}
|
|
}
|
|
pub fn card_pool(&self) -> Vec<LogicDataRef> {
|
|
const CARD_TABLES: [i32; 3] = [
|
|
table::SPELLS_CHARACTERS,
|
|
table::SPELLS_BUILDINGS,
|
|
table::SPELLS_OTHER,
|
|
];
|
|
let mut pool = Vec::new();
|
|
for card_table in CARD_TABLES {
|
|
let Some(rows) = self.tables.table(card_table) else {
|
|
continue;
|
|
};
|
|
for row in rows.iter() {
|
|
if row.boolean("NotInUse") {
|
|
continue;
|
|
}
|
|
pool.push(LogicDataRef::from(std::sync::Arc::clone(row)));
|
|
}
|
|
}
|
|
pool
|
|
}
|
|
pub fn resolve_arena(&self, selector: &DataSelector) -> LogicDataRef {
|
|
self.resolve(selector, table::ARENAS, ARENA_FALLBACK_INSTANCE)
|
|
}
|
|
pub fn resolve_resource(&self, selector: &DataSelector) -> LogicDataRef {
|
|
self.resolve(selector, table::RESOURCES, GOLD_RESOURCE_FALLBACK_INSTANCE)
|
|
}
|
|
}
|