Files
edalyze/src/bindata.rs
2023-06-22 00:26:43 +02:00

147 lines
3.9 KiB
Rust

use std::io::{Read, Write, self, Seek};
use byteorder::{WriteBytesExt, BE, ReadBytesExt};
pub const IS_FUEL: u8 = 1;
pub const IS_WDRF: u8 = 2;
pub const IS_NEUT: u8 = 4;
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
pub struct Point(pub i32, pub i32, pub i32);
#[derive(Copy, Clone, Debug)]
pub struct Box(pub Point, pub Point);
const fn isortp(a: i32, b: i32) -> (i32, i32) {
if a < b { (a,b) } else { (b,a) }
}
impl Box {
pub const fn from_corners(x: Point, y: Point) -> Box {
let (ax, bx) = isortp(x.0, y.0);
let (ay, by) = isortp(x.1, y.1);
let (az, bz) = isortp(x.2, y.2);
let pt1 = Point(ax, ay, az);
let pt2 = Point(bx, by, bz);
Box(pt1, pt2)
}
pub fn contains(&self, x: Point) -> bool {
return
(self.0 .0 .. self.1 .0).contains(&x.0) &&
(self.0 .1 .. self.1 .1).contains(&x.1) &&
(self.0 .2 .. self.1 .2).contains(&x.2);
}
}
#[derive(Default)]
pub struct System {
pub coords: Point,
pub name: String,
pub name_off: usize,
pub star_flags: u8,
}
impl System {
pub fn write_name(&self, writer: &mut dyn Write) -> io::Result<usize> {
let name_len = self.name.len().min(255);
writer.write_u8(name_len as u8)?;
writer.write(&self.name.as_bytes()[..name_len])?;
return Ok(name_len + 1);
}
pub fn write_to(&self, writer: &mut dyn Write) -> io::Result<()> {
writer.write_i32::<BE>(self.coords.0)?;
writer.write_i32::<BE>(self.coords.1)?;
writer.write_i32::<BE>(self.coords.2)?;
let rest = self.star_flags as u32 + ((self.name_off as u32) << 4);
writer.write_u32::<BE>(rest)?;
Ok(())
}
pub fn read_from(r: &mut dyn Read) -> io::Result<Self> {
let x = r.read_i32::<BE>()?;
let y = r.read_i32::<BE>()?;
let z = r.read_i32::<BE>()?;
let rest = r.read_u32::<BE>()?;
let name_off = (rest >> 4) as usize;
let star_flags = (rest & 0xF) as u8;
Ok(System{
coords: Point(x,y,z),
name: String::new(),
name_off,
star_flags,
})
}
pub fn read_name<R: Read + Seek>(&mut self, r: &mut R) -> io::Result<()> {
//eprint!(".");
r.seek(io::SeekFrom::Start(self.name_off as u64))?;
let mut buf = vec![];
let len = r.read_u8()? as usize;
//eprintln!("Reading {len} bytes from {}", self.name_off);
buf.resize(len, 0);
r.read_exact(buf.as_mut_slice())?;
self.name = String::from_utf8(buf)
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
Ok(())
}
pub fn jump_scale(&self) -> f32 {
if self.star_flags & IS_NEUT != 0 {
4.0
} else if self.star_flags & IS_WDRF != 0 {
1.5
} else {
0.
}
}
}
impl rstar::Point for Point {
type Scalar = i32;
const DIMENSIONS: usize = 3;
fn generate(mut gen: impl FnMut(usize) -> Self::Scalar) -> Self {
let x = gen(0);
let y = gen(1);
let z = gen(2);
Self(x,y,z)
}
fn nth(&self, index: usize) -> Self::Scalar {
match index {
0 => self.0,
1 => self.1,
2 => self.2,
_ => 0 as Self::Scalar,
}
}
fn nth_mut(&mut self, index: usize) -> &mut Self::Scalar {
match index {
0 => &mut self.0,
1 => &mut self.1,
_ => &mut self.2,
}
}
}
impl Point {
pub fn distance_sq(&self, other: Self) -> f32 {
let Point(sx, sy, sz) = *self;
let Point(tx, ty, tz) = other;
let dx = sx as f32 - tx as f32;
let dy = sy as f32 - ty as f32;
let dz = sz as f32 - tz as f32;
(dx*dx) + (dy*dy) + (dz*dz)
}
pub fn distance(&self, other: Self) -> f32 {
self.distance_sq(other).sqrt()
}
}