parent
b807c40589
commit
434bf19ae5
@ -0,0 +1 @@
|
|||||||
|
/target
|
@ -0,0 +1,80 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "binary_serialize_derive"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "logicworld-subassembly"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"binary_serialize_derive",
|
||||||
|
"quaternion",
|
||||||
|
"vecmath",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "piston-float"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ad78bf43dcf80e8f950c92b84f938a0fc7590b7f6866fbcbeca781609c115590"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.101"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quaternion"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a6a23cd933813dea6a8e24391c80634deba6a70ca5a14b2b944b8cb6d871e071"
|
||||||
|
dependencies = [
|
||||||
|
"vecmath",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.40"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.106"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vecmath"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "956ae1e0d85bca567dee1dcf87fb1ca2e792792f66f87dced8381f99cd91156a"
|
||||||
|
dependencies = [
|
||||||
|
"piston-float",
|
||||||
|
]
|
@ -0,0 +1,9 @@
|
|||||||
|
[package]
|
||||||
|
name = "logicworld-subassembly"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
binary_serialize_derive = { path = "../binary_serialize_derive" }
|
||||||
|
quaternion = "2.0.0"
|
||||||
|
vecmath = "1.0.0"
|
@ -0,0 +1,128 @@
|
|||||||
|
use std::{
|
||||||
|
fs::{self, File}, i32, io::{self, Write}, path::Path
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::lw::{BinarySerializable, ComponentIdMap, ModVersion, Version};
|
||||||
|
|
||||||
|
pub mod lw;
|
||||||
|
|
||||||
|
enum SaveType {
|
||||||
|
_World = 1,
|
||||||
|
Subassembly = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_subassembly(
|
||||||
|
name: String,
|
||||||
|
path: &Path,
|
||||||
|
components: &[lw::Component],
|
||||||
|
wires: &[lw::Wire],
|
||||||
|
) -> io::Result<()> {
|
||||||
|
let directory = Path::join(path, &name);
|
||||||
|
fs::create_dir_all(&directory)?;
|
||||||
|
|
||||||
|
let mut file = File::create(Path::join(&directory, "data.partialworld"))?;
|
||||||
|
write_subassembly_file(&mut file, &components, &wires)?;
|
||||||
|
|
||||||
|
let mut placing_info_file = File::create(Path::join(&directory, "LastMainPlacingInfo.jecs"))?;
|
||||||
|
write_placing_info_file(&mut placing_info_file)?;
|
||||||
|
|
||||||
|
let mut placements_file = File::create(Path::join(&directory, "placements.jecs"))?;
|
||||||
|
write_placements_file(&mut placements_file)?;
|
||||||
|
|
||||||
|
let mut meta_file = File::create(Path::join(&directory, "meta.jecs"))?;
|
||||||
|
write_meta_file(&mut meta_file, &name)?;
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_subassembly_file(
|
||||||
|
file: &mut impl Write,
|
||||||
|
components: &[lw::Component],
|
||||||
|
wires: &[lw::Wire],
|
||||||
|
) -> io::Result<()> {
|
||||||
|
// Header:
|
||||||
|
file.write_all(b"Logic World save")?; // Magic bytes
|
||||||
|
file.write_all(&[7 as u8])?; // Version 7
|
||||||
|
Version::new(0, 92, 0, 455).write_to(file)?; // Game Version
|
||||||
|
file.write_all(&[SaveType::Subassembly as u8])?;
|
||||||
|
|
||||||
|
(components.len() as i32).write_to(file)?;
|
||||||
|
(wires.len() as i32).write_to(file)?;
|
||||||
|
|
||||||
|
// Body:
|
||||||
|
let mods = vec![ModVersion {
|
||||||
|
id: "MHG".to_owned(),
|
||||||
|
version: Version::new(0, 91, 4, -1),
|
||||||
|
}];
|
||||||
|
mods.write_to(file)?;
|
||||||
|
|
||||||
|
let component_id_map = vec![ComponentIdMap {
|
||||||
|
numeric_id: 15,
|
||||||
|
text_id: "MHG.CircuitBoard".to_owned(),
|
||||||
|
}];
|
||||||
|
component_id_map.write_to(file)?;
|
||||||
|
|
||||||
|
for component in components {
|
||||||
|
component.write_to(file)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
for wire in wires {
|
||||||
|
wire.write_to(file)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
0i32.write_to(file)?; // We don't have any turned on nets
|
||||||
|
|
||||||
|
// Footer:
|
||||||
|
file.write_all(b"redstone sux lol")?;
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_placing_info_file(file: &mut impl Write) -> io::Result<()> {
|
||||||
|
file.write_all(
|
||||||
|
b"PlacingInfo:
|
||||||
|
RaiseOnChangedEvents: true
|
||||||
|
Flipped: false
|
||||||
|
RotationAboutUpVector: 180
|
||||||
|
Offset:
|
||||||
|
x: 0
|
||||||
|
y: 0
|
||||||
|
BoardIsFlat: true
|
||||||
|
BoardRotationState: 0
|
||||||
|
",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
fn write_placements_file(file: &mut impl Write) -> io::Result<()> {
|
||||||
|
file.write_all(
|
||||||
|
b"Placements:
|
||||||
|
-
|
||||||
|
CornerMidpointPositionBeforeFlipping:
|
||||||
|
x: 0
|
||||||
|
y: 0
|
||||||
|
z: 0
|
||||||
|
RotationBeforeFlipping:
|
||||||
|
x: 0
|
||||||
|
y: 0
|
||||||
|
z: 0
|
||||||
|
w: 1
|
||||||
|
PlacementType: OnTerrain
|
||||||
|
Flipped: false
|
||||||
|
BoardRotationState: 0
|
||||||
|
Type: Standard
|
||||||
|
data_format_version: 1
|
||||||
|
",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_meta_file(file: &mut impl Write, title: &str) -> io::Result<()> {
|
||||||
|
file.write_all(
|
||||||
|
format!(
|
||||||
|
"Title: {}
|
||||||
|
Column: null
|
||||||
|
Category: null
|
||||||
|
",
|
||||||
|
title
|
||||||
|
)
|
||||||
|
.as_bytes(),
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,149 @@
|
|||||||
|
use std::io::{self, Write};
|
||||||
|
|
||||||
|
use binary_serialize_derive::BinarySerializable;
|
||||||
|
use quaternion::Quaternion;
|
||||||
|
use vecmath::Vector3;
|
||||||
|
|
||||||
|
pub trait BinarySerializable {
|
||||||
|
fn write_to<W: Write>(&self, writer: &mut W) -> io::Result<()>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(u8)]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub enum PegType {
|
||||||
|
Input = 1,
|
||||||
|
Output = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Int = i32;
|
||||||
|
pub type Float = f32;
|
||||||
|
pub type ComponentAddress = u32;
|
||||||
|
|
||||||
|
#[derive(BinarySerializable)]
|
||||||
|
pub struct Version {
|
||||||
|
pub major: Int,
|
||||||
|
pub minor: Int,
|
||||||
|
pub build: Int,
|
||||||
|
pub revision: Int,
|
||||||
|
}
|
||||||
|
impl Version {
|
||||||
|
pub fn new(major: Int, minor: Int, build: Int, revision: Int) -> Self {
|
||||||
|
Self {
|
||||||
|
major,
|
||||||
|
minor,
|
||||||
|
build,
|
||||||
|
revision,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(BinarySerializable)]
|
||||||
|
pub struct ModVersion {
|
||||||
|
pub id: String,
|
||||||
|
pub version: Version,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(BinarySerializable)]
|
||||||
|
pub struct Input {
|
||||||
|
circuit_state_id: Int,
|
||||||
|
}
|
||||||
|
#[derive(BinarySerializable)]
|
||||||
|
pub struct Output {
|
||||||
|
circuit_state_id: Int,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(BinarySerializable)]
|
||||||
|
pub struct ComponentIdMap {
|
||||||
|
pub numeric_id: i16,
|
||||||
|
pub text_id: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(BinarySerializable)]
|
||||||
|
pub struct PegAddress {
|
||||||
|
peg_type: PegType,
|
||||||
|
component_address: ComponentAddress,
|
||||||
|
index: Int,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(BinarySerializable)]
|
||||||
|
pub struct Component {
|
||||||
|
pub address: ComponentAddress,
|
||||||
|
pub parent: ComponentAddress,
|
||||||
|
pub numeric_id: u16,
|
||||||
|
pub position: Vector3<Int>,
|
||||||
|
pub rotation: Quaternion<Float>,
|
||||||
|
pub inputs: Vec<Input>,
|
||||||
|
pub outputs: Vec<Output>,
|
||||||
|
pub custom_data: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(BinarySerializable)]
|
||||||
|
pub struct Wire {
|
||||||
|
first_point: PegAddress,
|
||||||
|
second_point: PegAddress,
|
||||||
|
circuit_state_id: Int,
|
||||||
|
wire_rotation: Float,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: BinarySerializable> BinarySerializable for Vec<T> {
|
||||||
|
fn write_to<W: Write>(&self, writer: &mut W) -> io::Result<()> {
|
||||||
|
writer.write_all(&(self.len() as Int).to_le_bytes())?;
|
||||||
|
for value in self {
|
||||||
|
value.write_to(writer)?;
|
||||||
|
}
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BinarySerializable for Vec<u8> {
|
||||||
|
fn write_to<W: Write>(&self, writer: &mut W) -> io::Result<()> {
|
||||||
|
writer.write_all(&(self.len() as Int).to_le_bytes())?;
|
||||||
|
writer.write_all(&self)?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BinarySerializable for PegType {
|
||||||
|
fn write_to<W: Write>(&self, writer: &mut W) -> io::Result<()> {
|
||||||
|
writer.write_all(&[*self as u8])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BinarySerializable for String {
|
||||||
|
fn write_to<W: Write>(&self, writer: &mut W) -> io::Result<()> {
|
||||||
|
writer.write_all(&(self.len() as Int).to_le_bytes())?;
|
||||||
|
writer.write_all(self.as_bytes())?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BinarySerializable for Vector3<Int> {
|
||||||
|
fn write_to<W: Write>(&self, writer: &mut W) -> io::Result<()> {
|
||||||
|
self[0].write_to(writer)?; // x
|
||||||
|
self[1].write_to(writer)?; // y
|
||||||
|
self[2].write_to(writer)?; // z
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BinarySerializable for Quaternion<Float> {
|
||||||
|
fn write_to<W: Write>(&self, writer: &mut W) -> io::Result<()> {
|
||||||
|
self.1[0].write_to(writer)?; // x
|
||||||
|
self.1[1].write_to(writer)?; // y
|
||||||
|
self.1[2].write_to(writer)?; // z
|
||||||
|
self.0.write_to(writer)?; // w
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_binary_num {
|
||||||
|
($($t:ty),*) => {
|
||||||
|
$(impl BinarySerializable for $t {
|
||||||
|
fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
|
||||||
|
writer.write_all(&self.to_le_bytes())
|
||||||
|
}
|
||||||
|
})*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_binary_num!(i16, u16, i32, u32, f32);
|
Loading…
Reference in new issue