Skip to content
This repository has been archived by the owner on May 10, 2023. It is now read-only.

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
0xceed committed Apr 5, 2023
2 parents aa88fa6 + 8a7ab29 commit 246fa2f
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 89 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,20 @@ This repository is a part of [Yellowcake](https://github.com/yellowcake-org) pro

### What it does

The library intended to provide instruments for working with original Fallout™ resources, such as `.map`, `.pro`, `.dat` files, and many others, which were used in classic Fallout™ games. This repository also does include example tools, provided for each file format separately, using `examples` targets. Sometimes they are just print out available info, but very often they provide additional functionality, which goes beyond simple examples, like `mapview` tool.
The library is intended to provide instruments for working with original Fallout™ resources, such as `.map`, `.pro`, `.dat` files, and many others, which were used in classic Fallout™ games. This repository also does include example tools, provided for each file format separately, via `examples`' targets. Sometimes they just print out available info, but very often they additionaly provide extended functionality, which goes beyond simple examples, like `mapview` tool.

### Why this is useful

It is useful in obvious way for reproducing original game, providing modern, safe and stable codebase to work with original games' resources. It also may serve as a documenation for those, who want to learn about original file formats. And finally, it's example tools could be a good starting point for modders of original games. In very first release it can't do much, though, but it's already better than original tools released by the publisher in what it actually allows to do. For instance, again, `mapview` can be used to create some arts from maps, or guides. In case of significant demand from the community, it might become something bigger, like full-featured map editor, so stay tuned.
It is useful in obvious way for reproducing original game: providing modern, safe and stable codebase to work with original games' resources. It also may serve as a documenation for those who want to learn about original file formats. And, finally, its' example tools could be a good starting point for modders of original games. In very first release it can't do much, though, but it's already better, than original tools released by the publisher in what it actually allows to do. For instance, again, `mapview` can be used to create some arts from maps, or guides. In case of significant demand from the community, it might become something bigger, like full-featured map editor, so stay tuned.

### How to get started

Basically you just use Cargo and default Rust tooling to explore different modules and examples. Each file format is represented with different Rust module. It also has a couple of common modules, which provided basic data structures, needed for the game files' formats and abstractions. Examples' targets provide a view on intended way of using the library's functions.
Basically you just use Cargo and default Rust tooling to explore different modules and examples. Each file format is represented with different Rust module. The crate has also a couple of common modules, which provide basic data structures, needed for the game files' formats, and abstractions. Examples' targets provide a view on intended way of using the library's functions.

### Where to get help

[GitHub Discussions](https://github.com/yellowcake-org/libycresources/discussions) is a good starting point. GitHub Issues are disabled at the moment, but will be enabled in case of significant activity from community. As for now, I am handling all issues internally, using additional software.
[GitHub Discussions](https://github.com/yellowcake-org/libycresources/discussions) is the right place. GitHub Issues are disabled at the moment, but will be enabled in case of significant activity from community. As for now, I am handling all issues internally, using additional software.

### Who maintains and contributes

Currently, only [@0xceed](https://github.com/0xceed) is working on the library. While help from the community will be _very_ needed in the future, this early in development I need to focus on creating good example of my vision, guidelines and many, many more.
Currently, only [__@0xceed__](https://github.com/0xceed) is working on the library. While help from the community will be _very_ needed in the future, this early in development I need to focus on creating good example of my vision, guidelines and many, many more.
79 changes: 71 additions & 8 deletions examples/mapview/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::collections::HashMap;
use std::fs::File;
use std::io::BufWriter;

Expand All @@ -9,9 +10,13 @@ use cli::export::elevation;
use cli::export::filter::{Filter, Layers};
use libycresources::common::types::geometry::Scaled;
use libycresources::common::types::space;
use libycresources::formats::map;
use libycresources::formats::{map, pal};
use libycresources::formats::map::blueprint::prototype::Instance;
use libycresources::formats::map::tiles::Group;
use provider::CommonProvider;

use crate::cli::export::darkness::Darkness;

mod print;
mod render;
mod provider;
Expand Down Expand Up @@ -69,17 +74,75 @@ fn main() {
if export.darkness.as_ref().is_some() { println!("Darkness customization has been applied."); }
if export.elevation.as_ref().is_some() { println!("Provided elevation will be rendered only."); }

for level in levels {
let level_readable = level + 1;
let elevation = space::Elevation { level: Scaled { value: level, scale: 0..MAX_ELEVATION + 1 } };
let default = match u8::try_from(map.darkness) {
Ok(value) => value,
Err(error) => {
return eprintln!("Map darkness value is out of range. Error: {:?}", error);
}
};

let darkness = export.darkness.map_or(
default,
|d| {
match d {
Darkness::None => 1,
Darkness::Night => 2,
Darkness::Dusk => 3,
Darkness::Day => 4,
}
},
);

println!("Loading common palette...");

let file = match File::open(&options.resources.join("COLOR.PAL")) {
Err(error) => { return eprintln!("Failed to open main palette's file. Error: {:?}.", error); }
Ok(value) => value
};

let mut reader = std::io::BufReader::with_capacity(1 * 1024 * 1024, file);
let palette = match pal::parse::palette(&mut reader) {
Err(error) => { return eprintln!("Failed to parse main palette. Error: {:?}.", error); }
Ok(value) => value
};

println!("Success.");

let mut tiles = HashMap::new();
for group in &map.tiles { tiles.insert(&group.elevation, group); }

let mut protos: HashMap<&space::Elevation, Vec<&Instance>> = HashMap::new();
for proto in &map.prototypes {
if let Some(grid) = &proto.location.grid {
if let Some(protos) = protos.get_mut(&grid.elevation) {
protos.push(&proto);
} else {
let mut list = Vec::new();
list.push(proto);

protos.insert(&grid.elevation, list);
}
}
}

let drawables: Vec<(space::Elevation, &&Group, Option<&Vec<&Instance>>)> = levels.map(
|l| space::Elevation { level: Scaled { value: l, scale: 0..MAX_ELEVATION + 1 } }
).map(|e| {
let protos = protos.get(&e);
tiles.get(&e).map(|t| (e, t, protos))
}).flatten().collect();

for (elevation, tiles, protos) in drawables {
let level_readable = elevation.level.value + 1;

println!("Started rendering level {:?}...", level_readable);
let result = render::map(
&map, &filter,
export.darkness.as_ref(),
&elevation,
&tiles,
protos,
&filter,
darkness,
&provider,
&options.resources,
&palette,
);

let image = match result {
Expand Down
2 changes: 1 addition & 1 deletion examples/mapview/provider/suffix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub(crate) fn detect(weapon: &Option<weapon::Animation>, animation: &critter::An
Some(weapon::Animation::BigGun) => 8,
Some(weapon::Animation::Minigun) => 9,
Some(weapon::Animation::RocketLauncher) => 10,
}) as char
}) as char;
}

fn a_char(a: &critter::Animation) -> char {
Expand Down
104 changes: 33 additions & 71 deletions examples/mapview/render.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
use std::fs::File;
use std::path::PathBuf;

use item::Instance;
use libycresources::common::types::space::Elevation;
use libycresources::formats::{map, pal};
use libycresources::formats::map::blueprint;
use libycresources::formats::map;
use libycresources::formats::map::tiles::Group;
use libycresources::formats::pal::Palette;
use libycresources::formats::pro::meta::info::flags::Root::Flat;

use crate::cli::export::darkness::Darkness;
use crate::cli::export::filter::Layers;
use crate::error::Error;
use crate::traits::render::Provider;
Expand All @@ -21,37 +17,13 @@ mod sprite;
mod grid;

pub(crate) fn map<'a, P: Provider>(
map: &'a map::Map,
tiles: &'a Group,
protos: Option<&Vec<&map::blueprint::prototype::Instance>>,
layers: &Layers,
darkness: Option<&Darkness>,
elevation: &Elevation,
darkness: u8,
provider: &P,
resources: &PathBuf,
palette: &Palette,
) -> Result<Option<(Vec<(u8, u8, u8)>, (usize, usize))>, Error<'a>> {
let default = u8::try_from(map.darkness)
.map_err(|_| Error::Corrupted("Map darkness value is out of range."))?;

let darkness = darkness.map_or(
default,
|d| {
match d {
Darkness::None => 1,
Darkness::Night => 2,
Darkness::Dusk => 3,
Darkness::Day => 4,
}
},
);

let tiles = map.tiles
.iter()
.find(|e| { &e.elevation == elevation });

let tiles = match tiles {
None => return Ok(None),
Some(value) => value
};

let floors: Vec<Instance> = tiles::convert(&tiles.floor, provider)?;
let ceilings: Vec<Instance> = tiles::convert(&tiles.ceiling, provider)?;

Expand All @@ -66,51 +38,41 @@ pub(crate) fn map<'a, P: Provider>(
let mut pixels = vec![(u8::MIN, u8::MIN, u8::MIN); w * h];
let mut image = (&mut pixels, (w, h));

let file = File::open(&resources.join("COLOR.PAL"))
.map_err(|io| Error::IO(io, "Failed to load main palette."))?;

let mut reader = std::io::BufReader::with_capacity(1 * 1024 * 1024, file);
let palette = pal::parse::palette(&mut reader)
.map_err(|i| Error::Internal(i, "Failed to parse main palette."))?;

if layers.floor || layers.all() {
println!("Rendering floor...");
tiles::imprint(&floors, false, &palette, darkness, &mut image)?;
tiles::imprint(&floors, false, palette, darkness, &mut image)?;
}

if layers.overlay || layers.all() {
println!("Rendering hexagonal tiles' overlay...");
hexes::overlay(&mut image)?;
}

println!("Rendering prototypes...");
let flat: Vec<&blueprint::prototype::Instance> = map.prototypes.iter()
.filter(|p| p.patch.meta.flags.contains(&Flat)).collect();

let other: Vec<&blueprint::prototype::Instance> = map.prototypes.iter()
.filter(|p| !p.patch.meta.flags.contains(&Flat)).collect();

protos::imprint(
&flat,
provider,
&elevation,
&palette,
darkness,
&layers,
(tw, th),
&mut image,
)?;

protos::imprint(
&other,
provider,
&elevation,
&palette,
darkness,
&layers,
(tw, th),
&mut image,
)?;
if let Some(protos) = protos {
println!("Rendering prototypes...");
let (flat, normal) = protos.iter()
.partition(|p| p.patch.meta.flags.contains(&Flat));

protos::imprint(
&flat,
provider,
&palette,
darkness,
&layers,
(tw, th),
&mut image,
)?;

protos::imprint(
&normal,
provider,
&palette,
darkness,
&layers,
(tw, th),
&mut image,
)?;
}

if layers.roof || layers.all() {
println!("Rendering roofs...");
Expand Down
4 changes: 0 additions & 4 deletions examples/mapview/render/protos.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use std::collections::HashMap;

use libycresources::common::types::space::Elevation;
use libycresources::formats::{pal, pro};
use libycresources::formats::map::blueprint;
use libycresources::formats::pro::Type::{Critter, Item, Misc, Scenery, Tile, Wall};
Expand All @@ -13,7 +12,6 @@ use crate::traits::render::Provider;
pub(crate) fn imprint<'a, P: Provider>(
protos: &Vec<&blueprint::prototype::Instance>,
provider: &P,
elevation: &Elevation,
palette: &pal::Palette,
darkness: u8,
layers: &Layers,
Expand Down Expand Up @@ -69,8 +67,6 @@ pub(crate) fn imprint<'a, P: Provider>(
&proto.location.grid,
&proto.location.screen.correction
) {
if &location.elevation != elevation { continue; }

let identifier = &proto.appearance.sprite;
let item = provider.provide(&identifier)?;

Expand Down

0 comments on commit 246fa2f

Please sign in to comment.