use serde::Deserialize;
use toml::Spanned;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(rename_all = "lowercase")]
pub(super) enum FormatEntry {
#[default]
Number,
Signed,
Percent,
}
#[derive(Clone, Debug, PartialEq, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(deny_unknown_fields)]
pub(super) struct StatEntry {
pub(super) label: String,
pub(super) value: i32,
#[serde(default)]
pub(super) format: FormatEntry,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(deny_unknown_fields)]
pub(super) struct MeterEntry {
pub(super) max: u16,
pub(super) start: Option<u16>,
}
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(deny_unknown_fields)]
pub(super) struct IconEntry {
pub(super) tint: Option<[u8; 3]>,
pub(super) amount: Option<u8>,
pub(super) like: Option<String>,
pub(super) png: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(deny_unknown_fields)]
pub(super) struct ItemEntry {
pub(super) id: String,
pub(super) like: String,
pub(super) name: Option<String>,
pub(super) description: Option<String>,
pub(super) debug_name: Option<String>,
pub(super) meter: Option<MeterEntry>,
#[serde(default)]
pub(super) stats: Vec<StatEntry>,
pub(super) icon: Option<IconEntry>,
}
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(deny_unknown_fields)]
pub(super) struct RecipeEntry {
pub(super) id: String,
pub(super) like: String,
pub(super) output: String,
#[serde(default = "one")]
pub(super) count: u32,
#[serde(default = "one")]
pub(super) cost: u32,
pub(super) workshop: Option<String>,
}
pub(super) const fn one() -> u32 {
1
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(deny_unknown_fields)]
pub(super) struct StationRecipeEntry {
pub(super) cost: u32,
}
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(deny_unknown_fields)]
pub(super) struct WorkshopEntry {
pub(super) id: String,
pub(super) like: String,
pub(super) name: Option<String>,
pub(super) description: Option<String>,
pub(super) recipe: Option<StationRecipeEntry>,
pub(super) debug_name: Option<String>,
}
#[derive(Clone, Copy, Debug, PartialEq, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(untagged)]
pub(super) enum ValueEntry {
Set(f64),
Scale(ScaleEntry),
}
#[derive(Clone, Copy, Debug, PartialEq, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(deny_unknown_fields)]
pub(super) struct ScaleEntry {
pub(super) times: f64,
}
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(untagged)]
pub(super) enum ItemsEntry {
Word(String),
Names(Vec<String>),
}
#[derive(Clone, Debug, PartialEq, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(deny_unknown_fields)]
pub(super) struct ItemChangeEntry {
pub(super) items: Option<ItemsEntry>,
pub(super) category: Option<Vec<String>>,
pub(super) max_stack: Option<ValueEntry>,
pub(super) slots: Option<ValueEntry>,
pub(super) damage_mod: Option<ValueEntry>,
pub(super) speed_mod: Option<ValueEntry>,
pub(super) armor: Option<ValueEntry>,
pub(super) burn_time: Option<ValueEntry>,
pub(super) energy_output: Option<ValueEntry>,
pub(super) comfort_amount: Option<ValueEntry>,
}
#[derive(Clone, Debug, PartialEq, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(deny_unknown_fields)]
pub(super) struct RecipeChangeEntry {
#[serde(default)]
pub(super) recipes: Vec<String>,
#[serde(default)]
pub(super) output: Vec<String>,
#[serde(default)]
pub(super) kind: Vec<String>,
#[serde(default)]
pub(super) workshop: Vec<String>,
pub(super) output_count: Option<ValueEntry>,
pub(super) cost: Option<ValueEntry>,
pub(super) time: Option<ValueEntry>,
#[serde(default)]
pub(super) ingredients: std::collections::BTreeMap<String, ValueEntry>,
pub(super) station: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(deny_unknown_fields)]
pub(super) struct LootChangeEntry {
pub(super) items: Vec<String>,
#[serde(default)]
pub(super) table: Vec<String>,
pub(super) stack_size: Option<ValueEntry>,
pub(super) count: Option<ValueEntry>,
pub(super) spawn_probability: Option<ValueEntry>,
pub(super) weight: Option<ValueEntry>,
}
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(untagged)]
pub(super) enum FromEntry {
One(String),
Many(Vec<String>),
}
#[derive(Clone, Debug, PartialEq, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(deny_unknown_fields)]
pub(super) struct DropEntry {
pub(super) items: Vec<String>,
pub(super) chance: f64,
pub(super) from: FromEntry,
pub(super) count: Option<[u16; 2]>,
pub(super) meter: Option<[u16; 2]>,
}
#[derive(Debug, Default, Deserialize)]
#[serde(deny_unknown_fields)]
pub(super) struct ItemsFile {
#[serde(default)]
pub(super) item: Vec<Spanned<ItemEntry>>,
#[serde(default)]
pub(super) change: Vec<Spanned<ItemChangeEntry>>,
}
#[derive(Debug, Default, Deserialize)]
#[serde(deny_unknown_fields)]
pub(super) struct RecipesFile {
#[serde(default)]
pub(super) recipe: Vec<Spanned<RecipeEntry>>,
#[serde(default)]
pub(super) change: Vec<Spanned<RecipeChangeEntry>>,
}
#[derive(Debug, Default, Deserialize)]
#[serde(deny_unknown_fields)]
pub(super) struct WorkshopsFile {
#[serde(default)]
pub(super) workshop: Vec<Spanned<WorkshopEntry>>,
}
#[derive(Debug, Default, Deserialize)]
#[serde(deny_unknown_fields)]
pub(super) struct LootFile {
#[serde(default)]
pub(super) drop: Vec<Spanned<DropEntry>>,
#[serde(default)]
pub(super) change: Vec<Spanned<LootChangeEntry>>,
}
#[cfg(feature = "schema")]
#[must_use]
pub fn schemas() -> Vec<(&'static str, String)> {
use super::manifest::PackManifest;
use super::{ITEMS_FILE, LOOT_FILE, MANIFEST_FILE, RECIPES_FILE, WORKSHOPS_FILE};
#[derive(schemars::JsonSchema)]
#[schemars(deny_unknown_fields)]
#[expect(dead_code, reason = "only its schema is read")]
struct Items {
item: Option<Vec<ItemEntry>>,
change: Option<Vec<ItemChangeEntry>>,
}
#[derive(schemars::JsonSchema)]
#[schemars(deny_unknown_fields)]
#[expect(dead_code, reason = "only its schema is read")]
struct Recipes {
recipe: Option<Vec<RecipeEntry>>,
change: Option<Vec<RecipeChangeEntry>>,
}
#[derive(schemars::JsonSchema)]
#[schemars(deny_unknown_fields)]
#[expect(dead_code, reason = "only its schema is read")]
struct Workshops {
workshop: Option<Vec<WorkshopEntry>>,
}
#[derive(schemars::JsonSchema)]
#[schemars(deny_unknown_fields)]
#[expect(dead_code, reason = "only its schema is read")]
struct Loot {
drop: Option<Vec<DropEntry>>,
change: Option<Vec<LootChangeEntry>>,
}
let json = |schema: schemars::Schema| serde_json::to_string_pretty(&schema).unwrap_or_default();
vec![
(MANIFEST_FILE, json(schemars::schema_for!(PackManifest))),
(ITEMS_FILE, json(schemars::schema_for!(Items))),
(RECIPES_FILE, json(schemars::schema_for!(Recipes))),
(WORKSHOPS_FILE, json(schemars::schema_for!(Workshops))),
(LOOT_FILE, json(schemars::schema_for!(Loot))),
]
}