use crate::content::Guid;
use crate::content::icons::{Icon, Pixels};
use crate::content::items::{FuelSetup, ImpactUiValue, NewItem};
use crate::content::recipes::NewRecipe;
use crate::content::workshops::{NewWorkshop, StationRecipe, WorkshopId};
use crate::{Load, Off};
pub const MANIFEST_FILE: &str = "pack.toml";
pub const ITEMS_FILE: &str = "items.toml";
pub const RECIPES_FILE: &str = "recipes.toml";
pub const WORKSHOPS_FILE: &str = "workshops.toml";
pub const LOOT_FILE: &str = "loot.toml";
pub const TEXTS_FILE: &str = "texts.toml";
pub const FILES: [&str; 6] = [
MANIFEST_FILE,
ITEMS_FILE,
RECIPES_FILE,
WORKSHOPS_FILE,
LOOT_FILE,
TEXTS_FILE,
];
pub const SCRIPT_EXTENSION: &str = "luau";
pub const SCRIPT_MAIN: &str = "main.luau";
pub const DEFINITIONS_SUFFIX: &str = ".d.luau";
pub const MAX_SCRIPTS: usize = 256;
pub const MAX_SCRIPT_DEPTH: usize = 4;
pub const MAX_FILE: u64 = 4 << 20;
pub const MAX_ICONS: usize = 1024;
pub const MAX_ICON_FILE: u64 = 1 << 20;
impl Load<'_> {
pub fn add_pack(&mut self, pack: &Pack) -> Result<(), Off> {
let texts = self.texts(&pack.texts)?;
let tag = |load: &mut Self, key: &Option<String>| -> Result<Option<Guid>, Off> {
key.as_ref()
.map(|key| {
let tag = id(&format!("{}:text/{key}", pack.namespace))?;
load.add_texts(&texts, &[(key, tag)])?;
Ok(tag.guid())
})
.transpose()
};
for workshop in &pack.workshops {
let base = &workshop.id;
let name = tag(self, &workshop.name)?;
let description = tag(self, &workshop.description)?;
let station_recipe = workshop
.cost
.map(|cost| -> Result<StationRecipe, Off> {
Ok(StationRecipe {
id: id(&format!("{base}.recipe"))?,
cost,
})
})
.transpose()?;
self.add_workshop(NewWorkshop {
like: workshop.like,
item: id(base)?,
template: id(&format!("{base}.template"))?,
workshop: id(&format!("{base}.workshop"))?,
name,
description,
station_recipe,
debug_name: workshop.debug_name.clone(),
})?;
}
for item in &pack.items {
let own = id(&item.id)?;
let name = tag(self, &item.name)?;
let description = tag(self, &item.description)?;
let mut stats = Vec::new();
for (label, value, format) in &item.stats {
let label = tag(self, &Some(label.clone()))?.unwrap_or(Guid([0; 16]));
stats.push(ImpactUiValue {
loca_id: label,
value: *value,
value_format: *format,
});
}
let meter = item
.meter
.map(|(max, start)| -> Result<FuelSetup, Off> {
Ok(FuelSetup {
template: id(&format!("{}.meter", item.id))?,
max_fuel_charges: max,
start,
})
})
.transpose()?;
let icon = item
.icon
.as_ref()
.map(|icon| -> Result<Icon, Off> {
let (like, pixels) = match icon {
PackIcon::Tint { like, tint } => (*like, Pixels::Tint(*tint)),
PackIcon::Png(bytes) => {
let bytes: &'static [u8] = Box::leak(bytes.clone().into_boxed_slice());
(item.like, Pixels::Png(bytes))
}
};
Ok(Icon {
id: id(&format!("{}.icon", item.id))?,
like,
pixels,
})
})
.transpose()?;
self.add_item(NewItem {
name,
description,
debug_name: item.debug_name.clone(),
meter,
stats,
icon,
..NewItem::new(own, item.like)
})?;
}
self.add_pack_rest(pack)
}
fn add_pack_rest(&mut self, pack: &Pack) -> Result<(), Off> {
for recipe in &pack.recipes {
self.push_recipe(NewRecipe {
id: id(&recipe.id)?,
like: recipe.like,
output: recipe.output,
output_count: recipe.count,
cost: recipe.cost,
workshop: recipe.workshop.map(WorkshopId::new),
})?;
}
for (change, source) in &pack.changes {
self.change(change, source)?;
}
for (change, source) in &pack.selections {
self.change_items(change, source)?;
}
for (change, source) in &pack.recipe_selections {
self.change_recipes(change, source)?;
}
let group = group(&pack.namespace);
for drop in &pack.drops {
self.add_loot_in(group, drop.clone())?;
}
Ok(())
}
}
mod changes;
mod entries;
mod files;
mod manifest;
mod pack;
#[cfg(test)]
mod tests;
#[cfg(feature = "schema")]
pub use entries::schemas;
pub use files::*;
pub use manifest::*;
pub use pack::*;