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: satisfy conditions to land
[system."12 Autumn Above"]
name = "12 Autumn Above"
@ -13,10 +14,9 @@ object.earth.position.angle = 0
object.earth.position.z = 10.0
object.earth.size = 1000
# TODO: satisfy conditions to land
object.earth.landable = true
object.earth.name = "Earth"
object.earth.desc = """
object.earth.landable.name = "Earth"
object.earth.landable.desc = """
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.
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
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.position.center = "earth"

View File

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

View File

@ -1,7 +1,7 @@
use anyhow::{Context, Result};
use std::{collections::HashMap, sync::Arc};
use crate::{Content, ContentBuildContext, Sprite};
use crate::{Content, ContentBuildContext, ContentIndex, Sprite};
pub(crate) mod syntax {
use std::sync::Arc;
@ -138,12 +138,12 @@ pub(crate) mod syntax {
#[derive(Debug, Deserialize)]
#[serde(untagged)]
pub enum EffectReference {
Label(String),
Label(ContentIndex),
Effect(Effect),
}
impl EffectReference {
pub fn to_handle(
pub fn resolve(
self,
build_context: &mut ContentBuildContext,
content: &mut Content,
@ -246,7 +246,9 @@ impl crate::Build for Effect {
let h = effect
.add_to(build_context, content, &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(());

View File

@ -81,12 +81,12 @@ pub(crate) mod syntax {
};
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,
};
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,
};
@ -143,7 +143,7 @@ pub struct Outfit {
pub space: OutfitSpace,
/// The name of this outfit
pub name: String,
pub display_name: String,
/// Thie outfit's index
pub index: ContentIndex,
@ -281,7 +281,7 @@ impl crate::Build for Outfit {
let mut o = Self {
index: ContentIndex::new(&outfit_name),
name: outfit.name,
display_name: outfit.name,
thumbnail,
gun,
engine_thrust: 0.0,

View File

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

View File

@ -234,7 +234,8 @@ impl SpriteAutomaton {
// Edge case: we're stopped and got a request to transition.
// 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);
}