Minor content cleanup

master
Mark 2024-02-07 15:40:43 -08:00
parent acb5b9d31c
commit f56fd7ea49
Signed by: Mark
GPG Key ID: C6D63995FE72FD80
7 changed files with 87 additions and 78 deletions

View File

@ -1,4 +1,5 @@
# TODO: big objects in one config # TODO: big objects in one config
# TODO: satisfy conditions to land
[system."12 Autumn Above"] [system."12 Autumn Above"]
name = "12 Autumn Above" name = "12 Autumn Above"
@ -13,10 +14,9 @@ object.earth.position.angle = 0
object.earth.position.z = 10.0 object.earth.position.z = 10.0
object.earth.size = 1000 object.earth.size = 1000
# TODO: satisfy conditions to land
object.earth.landable = true object.earth.landable.name = "Earth"
object.earth.name = "Earth" object.earth.landable.desc = """
object.earth.desc = """
The ancestral home world of humanity, Earth has a population twice that of any other inhabited planet. The ancestral home world of humanity, Earth has a population twice that of any other inhabited planet.
Sprawling cities cover large portions of its surface, many of them overcrowded and dangerous. Sprawling cities cover large portions of its surface, many of them overcrowded and dangerous.
Some people work to scrape together enough money to leave, while at the same time others, born Some people work to scrape together enough money to leave, while at the same time others, born
@ -28,8 +28,13 @@ one planet has a greater population than a hundred planets elsewhere. As a resul
settlements of less than a million are grouped together into planetary districts that settlements of less than a million are grouped together into planetary districts that
elect a single representative between them - a source of much frustration in the frontier worlds. elect a single representative between them - a source of much frustration in the frontier worlds.
""" """
object.earth.image = "ui::landscape::test" object.earth.landable.image = "ui::landscape::test"
object.earth.landable.outfitter = [
"plasma engines",
"shield generator",
"blaster",
]
object.luna.sprite = "planet::luna" object.luna.sprite = "planet::luna"
object.luna.position.center = "earth" object.luna.position.center = "earth"

View File

@ -165,8 +165,7 @@ impl Display for ContentIndex {
/// Stores temporary data while building context objects /// Stores temporary data while building context objects
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct ContentBuildContext { pub(crate) struct ContentBuildContext {
/// Map effect names to handles pub effect_index: HashMap<ContentIndex, Arc<Effect>>,
pub effect_index: HashMap<String, Arc<Effect>>,
} }
impl ContentBuildContext { impl ContentBuildContext {

View File

@ -1,7 +1,7 @@
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use std::{collections::HashMap, sync::Arc}; use std::{collections::HashMap, sync::Arc};
use crate::{Content, ContentBuildContext, Sprite}; use crate::{Content, ContentBuildContext, ContentIndex, Sprite};
pub(crate) mod syntax { pub(crate) mod syntax {
use std::sync::Arc; use std::sync::Arc;
@ -138,12 +138,12 @@ pub(crate) mod syntax {
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
#[serde(untagged)] #[serde(untagged)]
pub enum EffectReference { pub enum EffectReference {
Label(String), Label(ContentIndex),
Effect(Effect), Effect(Effect),
} }
impl EffectReference { impl EffectReference {
pub fn to_handle( pub fn resolve(
self, self,
build_context: &mut ContentBuildContext, build_context: &mut ContentBuildContext,
content: &mut Content, content: &mut Content,
@ -246,7 +246,9 @@ impl crate::Build for Effect {
let h = effect let h = effect
.add_to(build_context, content, &effect_name) .add_to(build_context, content, &effect_name)
.with_context(|| format!("while evaluating effect `{}`", effect_name))?; .with_context(|| format!("while evaluating effect `{}`", effect_name))?;
build_context.effect_index.insert(effect_name, h); build_context
.effect_index
.insert(ContentIndex::new(&effect_name), h);
} }
return Ok(()); return Ok(());

View File

@ -81,12 +81,12 @@ pub(crate) mod syntax {
}; };
let impact_effect = match self.projectile.impact_effect { let impact_effect = match self.projectile.impact_effect {
Some(e) => Some(e.to_handle(build_context, content, "")?), Some(e) => Some(e.resolve(build_context, content, "")?),
None => None, None => None,
}; };
let expire_effect = match self.projectile.expire_effect { let expire_effect = match self.projectile.expire_effect {
Some(e) => Some(e.to_handle(build_context, content, "")?), Some(e) => Some(e.resolve(build_context, content, "")?),
None => None, None => None,
}; };
@ -143,7 +143,7 @@ pub struct Outfit {
pub space: OutfitSpace, pub space: OutfitSpace,
/// The name of this outfit /// The name of this outfit
pub name: String, pub display_name: String,
/// Thie outfit's index /// Thie outfit's index
pub index: ContentIndex, pub index: ContentIndex,
@ -281,7 +281,7 @@ impl crate::Build for Outfit {
let mut o = Self { let mut o = Self {
index: ContentIndex::new(&outfit_name), index: ContentIndex::new(&outfit_name),
name: outfit.name, display_name: outfit.name,
thumbnail, thumbnail,
gun, gun,
engine_thrust: 0.0, engine_thrust: 0.0,

View File

@ -298,7 +298,7 @@ impl crate::Build for Ship {
effects.push(CollapseEffectSpawner { effects.push(CollapseEffectSpawner {
effect: e effect: e
.effect .effect
.to_handle(build_context, ct, "") .resolve(build_context, ct, "")
.with_context(|| format!("while loading ship `{}`", ship_name))?, .with_context(|| format!("while loading ship `{}`", ship_name))?,
count: e.count, count: e.count,
pos: e.pos.map(|p| { pos: e.pos.map(|p| {
@ -316,7 +316,7 @@ impl crate::Build for Ship {
effects.push(CollapseEffectSpawner { effects.push(CollapseEffectSpawner {
effect: g effect: g
.effect .effect
.to_handle(build_context, ct, "") .resolve(build_context, ct, "")
.with_context(|| { .with_context(|| {
format!("while loading ship `{}`", ship_name) format!("while loading ship `{}`", ship_name)
})?, })?,
@ -360,7 +360,7 @@ impl crate::Build for Ship {
effects.push(DamageEffectSpawner { effects.push(DamageEffectSpawner {
effect: e effect: e
.effect .effect
.to_handle(build_context, ct, "") .resolve(build_context, ct, "")
.with_context(|| format!("while loading ship `{}`", ship_name))?, .with_context(|| format!("while loading ship `{}`", ship_name))?,
frequency: e.frequency, frequency: e.frequency,
pos: e.pos.map(|p| { pos: e.pos.map(|p| {

View File

@ -1,4 +1,4 @@
use anyhow::{anyhow, bail, Context, Result}; use anyhow::{bail, Context, Result};
use galactica_util::to_radians; use galactica_util::to_radians;
use nalgebra::{Point2, Point3}; use nalgebra::{Point2, Point3};
use std::{ use std::{
@ -6,7 +6,7 @@ use std::{
sync::Arc, sync::Arc,
}; };
use crate::{util::Polar, Content, ContentBuildContext, ContentIndex, Sprite}; use crate::{util::Polar, Content, ContentBuildContext, ContentIndex, Outfit, Sprite};
pub(crate) mod syntax { pub(crate) mod syntax {
use serde::Deserialize; use serde::Deserialize;
@ -26,15 +26,18 @@ pub(crate) mod syntax {
pub struct Object { pub struct Object {
pub sprite: ContentIndex, pub sprite: ContentIndex,
pub position: Position, pub position: Position,
pub size: f32, pub size: f32,
pub radius: Option<f32>, pub radius: Option<f32>,
pub angle: Option<f32>, pub angle: Option<f32>,
pub landable: Option<bool>, pub landable: Option<Landable>,
pub name: Option<String>, }
pub desc: Option<String>,
pub image: Option<ContentIndex>, #[derive(Debug, Deserialize)]
pub struct Landable {
pub name: String,
pub desc: String,
pub image: ContentIndex,
pub outfitter: Vec<ContentIndex>,
} }
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
@ -107,9 +110,6 @@ pub struct System {
/// System objects to not interact with the physics engine. /// System objects to not interact with the physics engine.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct SystemObject { pub struct SystemObject {
/// This object's name
pub display_name: Option<String>,
/// This object's index /// This object's index
pub index: ContentIndex, pub index: ContentIndex,
@ -130,13 +130,22 @@ pub struct SystemObject {
pub angle: f32, pub angle: f32,
/// If true, ships may land on this object /// If true, ships may land on this object
pub landable: bool, pub landable: Option<LandableSystemObject>,
}
/// The description of this object (shown on landed ui) #[derive(Debug, Clone)]
pub desc: Option<String>, pub struct LandableSystemObject {
/// This object's name
pub display_name: String,
/// This object's image (shown on landed ui) /// The description of this object
pub image: Option<Arc<Sprite>>, pub desc: String,
/// This object's image
pub image: Arc<Sprite>,
/// The outfits we can buy here
pub outfitter: Vec<Arc<Outfit>>,
} }
/// Helper function for resolve_position, never called on its own. /// Helper function for resolve_position, never called on its own.
@ -210,71 +219,64 @@ impl crate::Build for System {
for (system_name, system) in system { for (system_name, system) in system {
let mut objects = HashMap::new(); let mut objects = HashMap::new();
for (index, obj) in &system.object { for (index, object) in &system.object {
let mut cycle_detector = HashSet::new(); let mut cycle_detector = HashSet::new();
cycle_detector.insert(index.clone()); cycle_detector.insert(index.clone());
let sprite = match content.sprites.get(&obj.sprite) { let sprite = match content.sprites.get(&object.sprite) {
None => bail!( None => bail!(
"In system `{}`: sprite `{}` doesn't exist", "In system `{}`: sprite `{}` doesn't exist",
system_name, system_name,
obj.sprite object.sprite
), ),
Some(t) => t.clone(), Some(t) => t.clone(),
}; };
let image = match &obj.image { let landable = 'landable: {
Some(x) => match content.sprites.get(x) { if object.landable.is_none() {
break 'landable None;
}
let l = object.landable.as_ref().unwrap();
let image = match content.sprites.get(&l.image) {
None => bail!( None => bail!(
"In system `{}`: sprite `{}` doesn't exist", "In system `{}`: sprite `{}` doesn't exist",
system_name, system_name,
obj.sprite object.sprite
), ),
Some(t) => Some(t.clone()), Some(t) => t.clone(),
},
None => None,
}; };
if obj.landable.unwrap_or(false) { let mut outfitter = Vec::new();
if obj.name.is_none() { for o in &l.outfitter {
return Err(anyhow!("if an object is landable, it must have a name")) match content.outfits.get(&o) {
.with_context(|| format!("in object labeled `{}`", index)) Some(x) => outfitter.push(x.clone()),
.with_context(|| format!("in system `{}`", system_name)); None => {
bail!("In system `{}`: outfit `{}` doesn't exist", system_name, o)
}
}
} }
if obj.desc.is_none() { break 'landable Some(LandableSystemObject {
return Err(anyhow!( image,
"if an object is landable, it must have a description" outfitter,
)) display_name: l.name.clone(),
.with_context(|| format!("in object labeled `{}`", index)) // TODO: better linebreaks, handle double spaces
.with_context(|| format!("in system `{}`", system_name)); // Tabs
} desc: l.desc.replace("\n", " ").replace("<br>", "\n"),
});
if obj.image.is_none() { };
return Err(anyhow!("if an object is landable, it must have an image"))
.with_context(|| format!("in object labeled `{}`", index))
.with_context(|| format!("in system `{}`", system_name));
}
}
objects.insert( objects.insert(
index.clone(), index.clone(),
Arc::new(SystemObject { Arc::new(SystemObject {
index: index.clone(), index: index.clone(),
sprite, sprite,
image, pos: resolve_position(&system.object, &object, cycle_detector)
pos: resolve_position(&system.object, &obj, cycle_detector)
.with_context(|| format!("in object {:#?}", index))?, .with_context(|| format!("in object {:#?}", index))?,
size: obj.size, size: object.size,
angle: to_radians(obj.angle.unwrap_or(0.0)), angle: to_radians(object.angle.unwrap_or(0.0)),
landable: obj.landable.unwrap_or(false), landable: landable,
display_name: obj.name.as_ref().map(|x| x.clone()),
// TODO: better linebreaks, handle double spaces
// Tabs
desc: obj
.desc
.as_ref()
.map(|x| x.replace("\n", " ").replace("<br>", "\n")),
}), }),
); );
} }

View File

@ -234,7 +234,8 @@ impl SpriteAutomaton {
// Edge case: we're stopped and got a request to transition. // Edge case: we're stopped and got a request to transition.
// we should transition right away. // we should transition right away.
if let Some(e) = self.next_edge_override.take() { if self.next_edge_override.is_some() {
let e = self.next_edge_override.take().unwrap();
self.take_edge(&e); self.take_edge(&e);
} }