diff --git a/Cargo.lock b/Cargo.lock index aa20a30..5045ce6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -594,6 +594,19 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +[[package]] +name = "gloo-utils" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037fcb07216cb3a30f7292bd0176b050b7b9a052ba830ef7d5d65f6dc64ba58e" +dependencies = [ + "js-sys", + "serde", + "serde_json", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -690,6 +703,8 @@ dependencies = [ "strum_macros", "thiserror", "time", + "tsify", + "wasm-bindgen", ] [[package]] @@ -1594,6 +1609,8 @@ dependencies = [ "serde", "serde_derive", "strum", + "tsify", + "wasm-bindgen", ] [[package]] @@ -1943,8 +1960,10 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6b26cf145f2f3b9ff84e182c448eaf05468e247f148cf3d2a7d67d78ff023a0" dependencies = [ + "gloo-utils", "serde", "serde-wasm-bindgen 0.5.0", + "serde_json", "tsify-macros", "wasm-bindgen", ] diff --git a/ic10emu/Cargo.toml b/ic10emu/Cargo.toml index bf79e9c..2b17415 100644 --- a/ic10emu/Cargo.toml +++ b/ic10emu/Cargo.toml @@ -29,6 +29,8 @@ time = { version = "0.3.36", features = [ "serde", "local-offset", ] } +tsify = { version = "0.4.5", optional = true, features = ["js"] } +wasm-bindgen = { version = "0.2.92", optional = true } [target.'cfg(target_arch = "wasm32")'.dependencies] getrandom = { version = "0.2", features = ["js"] } @@ -42,3 +44,7 @@ time = { version = "0.3.36", features = [ [dev-dependencies] color-eyre = "0.6.3" serde_json = "1.0.117" + +[features] +tsify = ["dep:tsify", "dep:wasm-bindgen", "stationeers_data/tsify"] +wasm-bindgen = ["dep:wasm-bindgen"] diff --git a/ic10emu/src/errors.rs b/ic10emu/src/errors.rs index b7e79a1..2eb2a4a 100644 --- a/ic10emu/src/errors.rs +++ b/ic10emu/src/errors.rs @@ -1,15 +1,23 @@ use crate::vm::{ instructions::enums::InstructionOp, object::{ - errors::{LogicError, MemoryError}, templates::Prefab, ObjectID + errors::{LogicError, MemoryError}, + templates::Prefab, + ObjectID, }, }; use serde_derive::{Deserialize, Serialize}; use std::error::Error as StdError; use std::fmt::Display; use thiserror::Error; +#[cfg(feature = "tsify")] +use tsify::Tsify; +#[cfg(feature = "tsify")] +use wasm_bindgen::prelude::*; #[derive(Error, Debug, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub enum VMError { #[error("device with id '{0}' does not exist")] UnknownId(u32), @@ -50,6 +58,8 @@ pub enum VMError { } #[derive(Error, Debug, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub enum TemplateError { #[error("object id {0} has a non conforming set of interfaces")] NonConformingObject(ObjectID), @@ -59,9 +69,16 @@ pub enum TemplateError { NoTemplateForPrefab(Prefab), #[error("no prefab provided")] MissingPrefab, + #[error("incorrect template for concreet impl {0} from prefab {1}")] + IncorrectTemplate(String, Prefab), + #[error("frozen memory size error: {0} is not {1}")] + MemorySize(usize, usize) + } #[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct LineError { pub error: ICError, pub line: u32, @@ -76,6 +93,8 @@ impl Display for LineError { impl StdError for LineError {} #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct ParseError { pub line: usize, pub start: usize, @@ -128,6 +147,8 @@ impl ParseError { } #[derive(Debug, Error, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub enum ICError { #[error("error compiling code: {0}")] ParseError(#[from] ParseError), diff --git a/ic10emu/src/interpreter.rs b/ic10emu/src/interpreter.rs index d414422..008bf31 100644 --- a/ic10emu/src/interpreter.rs +++ b/ic10emu/src/interpreter.rs @@ -7,18 +7,24 @@ use std::{ }; use itertools::Itertools; +#[cfg(feature = "tsify")] +use tsify::Tsify; +#[cfg(feature = "tsify")] +use wasm_bindgen::prelude::*; use time::format_description; use crate::{ errors::{ICError, LineError}, grammar, - vm::instructions::{enums::InstructionOp, Instruction}, + vm::instructions::{enums::InstructionOp, operands::Operand, Instruction}, }; pub mod instructions; #[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub enum ICState { Start, Running, @@ -29,6 +35,19 @@ pub enum ICState { Ended, } +#[derive(Clone, Debug, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] +pub struct ICInfo { + pub instruction_pointer: u32, + pub registers: Vec, + pub aliases: BTreeMap, + pub defines: BTreeMap, + pub labels: BTreeMap, + pub state: ICState, + pub yield_instruciton_count: u16, +} + impl Display for ICState { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let out = match self { @@ -52,6 +71,8 @@ impl Display for ICState { } #[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct Program { pub instructions: Vec, pub errors: Vec, diff --git a/ic10emu/src/network.rs b/ic10emu/src/network.rs index 43d5a5a..9f6bca9 100644 --- a/ic10emu/src/network.rs +++ b/ic10emu/src/network.rs @@ -13,8 +13,14 @@ use stationeers_data::{ }; use strum_macros::{AsRefStr, EnumIter}; use thiserror::Error; +#[cfg(feature = "tsify")] +use tsify::Tsify; +#[cfg(feature = "tsify")] +use wasm_bindgen::prelude::*; #[derive(Debug, Default, Clone, Copy, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub enum CableConnectionType { Power, Data, @@ -23,6 +29,8 @@ pub enum CableConnectionType { } #[derive(Debug, Default, Clone, Copy, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub enum Connection { CableNetwork { net: Option, @@ -337,6 +345,8 @@ impl Network for CableNetwork { } #[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct FrozenCableNetwork { pub id: ObjectID, pub devices: Vec, diff --git a/ic10emu/src/vm.rs b/ic10emu/src/vm.rs index 81fe336..0595614 100644 --- a/ic10emu/src/vm.rs +++ b/ic10emu/src/vm.rs @@ -23,6 +23,10 @@ use std::{ collections::{BTreeMap, HashSet}, rc::Rc, }; +#[cfg(feature = "tsify")] +use tsify::Tsify; +#[cfg(feature = "tsify")] +use wasm_bindgen::prelude::*; use itertools::Itertools; use serde_derive::{Deserialize, Serialize}; @@ -119,15 +123,15 @@ impl VM { .and_then(|db| db.get(&hash).cloned()) } - pub fn add_devices_frozen( + pub fn add_objects_frozen( self: &Rc, - frozen_devices: impl IntoIterator, + frozen_objects: impl IntoIterator, ) -> Result, VMError> { let mut transaction = VMTransaction::new(self); let mut obj_ids = Vec::new(); - for frozen in frozen_devices { - let obj_id = transaction.add_device_from_frozen(frozen)?; + for frozen in frozen_objects { + let obj_id = transaction.add_object_from_frozen(frozen)?; obj_ids.push(obj_id) } @@ -171,13 +175,13 @@ impl VM { Ok(obj_ids) } - pub fn add_device_from_frozen( + pub fn add_object_from_frozen( self: &Rc, frozen: FrozenObject, ) -> Result { let mut transaction = VMTransaction::new(self); - let obj_id = transaction.add_device_from_frozen(frozen)?; + let obj_id = transaction.add_object_from_frozen(frozen)?; transaction.finialize()?; @@ -274,12 +278,12 @@ impl VM { self.circuit_holders.borrow_mut().iter_mut().for_each(|id| { if *id == old_id { - *id = new_id + *id = new_id; } }); self.program_holders.borrow_mut().iter_mut().for_each(|id| { if *id == old_id { - *id = new_id + *id = new_id; } }); self.networks.borrow().iter().for_each(|(_net_id, net)| { @@ -1005,7 +1009,7 @@ impl VM { state.default_network_key, ); for frozen in state.objects { - let _ = transaction.add_device_from_frozen(frozen)?; + let _ = transaction.add_object_from_frozen(frozen)?; } transaction.finialize()?; @@ -1101,7 +1105,7 @@ impl VMTransaction { } } - pub fn add_device_from_frozen(&mut self, frozen: FrozenObject) -> Result { + pub fn add_object_from_frozen(&mut self, frozen: FrozenObject) -> Result { for net_id in &frozen.connected_networks() { if !self.networks.contains_key(net_id) { return Err(VMError::InvalidNetwork(*net_id)); @@ -1134,14 +1138,14 @@ impl VMTransaction { self.program_holders.push(obj_id); } if let Some(device) = obj.borrow_mut().as_mut_device() { - for conn in device.connection_list().iter() { + for conn in device.connection_list() { if let Connection::CableNetwork { net: Some(net_id), typ, role: ConnectionRole::None, } = conn { - if let Some(net) = self.networks.get_mut(net_id) { + if let Some(net) = self.networks.get_mut(&net_id) { match typ { CableConnectionType::Power => net.power_only.push(obj_id), _ => net.devices.push(obj_id), @@ -1290,6 +1294,8 @@ impl IdSpace { } #[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct FrozenVM { pub objects: Vec, pub circuit_holders: Vec, diff --git a/ic10emu/src/vm/instructions/enums.rs b/ic10emu/src/vm/instructions/enums.rs index 9ceb1f4..62d68c8 100644 --- a/ic10emu/src/vm/instructions/enums.rs +++ b/ic10emu/src/vm/instructions/enums.rs @@ -1,6 +1,10 @@ use serde_derive::{Deserialize, Serialize}; use strum::{Display, EnumIter, EnumProperty, EnumString, FromRepr}; use crate::vm::object::traits::Programmable; +#[cfg(feature = "tsify")] +use tsify::Tsify; +#[cfg(feature = "tsify")] +use wasm_bindgen::prelude::*; #[derive( Debug, Display, @@ -14,6 +18,8 @@ use crate::vm::object::traits::Programmable; Deserialize )] #[derive(EnumIter, EnumString, EnumProperty, FromRepr)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] #[strum(use_phf, serialize_all = "lowercase")] #[serde(rename_all = "lowercase")] pub enum InstructionOp { diff --git a/ic10emu/src/vm/instructions/operands.rs b/ic10emu/src/vm/instructions/operands.rs index ab70f0e..c35797d 100644 --- a/ic10emu/src/vm/instructions/operands.rs +++ b/ic10emu/src/vm/instructions/operands.rs @@ -6,8 +6,14 @@ use stationeers_data::enums::script::{ LogicBatchMethod as BatchMode, LogicReagentMode as ReagentMode, LogicSlotType, LogicType, }; use strum::EnumProperty; +#[cfg(feature = "tsify")] +use tsify::Tsify; +#[cfg(feature = "tsify")] +use wasm_bindgen::prelude::*; #[derive(PartialEq, Eq, Debug, Clone, Copy, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub enum Device { Db, Numbered(u32), @@ -15,23 +21,31 @@ pub enum Device { } #[derive(PartialEq, Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct RegisterSpec { pub indirection: u32, pub target: u32, } #[derive(PartialEq, Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct DeviceSpec { pub device: Device, pub connection: Option, } #[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct Identifier { pub name: String, } #[derive(PartialEq, Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub enum Number { Float(f64), Binary(i64), @@ -42,6 +56,8 @@ pub enum Number { } #[derive(PartialEq, Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub enum Operand { RegisterSpec(RegisterSpec), DeviceSpec(DeviceSpec), diff --git a/ic10emu/src/vm/object/errors.rs b/ic10emu/src/vm/object/errors.rs index bf3d270..0c1db59 100644 --- a/ic10emu/src/vm/object/errors.rs +++ b/ic10emu/src/vm/object/errors.rs @@ -2,8 +2,14 @@ use serde_derive::{Deserialize, Serialize}; use thiserror::Error; use stationeers_data::enums::script::{LogicSlotType, LogicType}; +#[cfg(feature = "tsify")] +use tsify::Tsify; +#[cfg(feature = "tsify")] +use wasm_bindgen::prelude::*; #[derive(Error, Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub enum LogicError { #[error("can't read LogicType {0}")] CantRead(LogicType), @@ -18,6 +24,8 @@ pub enum LogicError { } #[derive(Error, Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub enum MemoryError { #[error("stack underflow: {0} < range [0..{1})")] StackUnderflow(i32, usize), diff --git a/ic10emu/src/vm/object/humans.rs b/ic10emu/src/vm/object/humans.rs index 9132f61..af856e8 100644 --- a/ic10emu/src/vm/object/humans.rs +++ b/ic10emu/src/vm/object/humans.rs @@ -1,15 +1,50 @@ +use std::collections::BTreeMap; + use macro_rules_attribute::derive; -use stationeers_data::enums::basic::Class as SlotClass; +use stationeers_data::{ + enums::{basic::Class as SlotClass, Species}, + templates::SlotInfo, +}; +#[cfg(feature = "tsify")] +use tsify::Tsify; +#[cfg(feature = "tsify")] +use wasm_bindgen::prelude::*; use crate::vm::{ object::{ macros::ObjectInterface, - traits::{Human, HumanRef, HumanRefMut, Object, Storage, StorageRef, StorageRefMut}, - Name, ObjectID, Slot, + traits::{ + Human, HumanRef, HumanRefMut, Object, StatState, Storage, StorageRef, StorageRefMut, + Thermal, + }, + Name, ObjectID, Slot, SlotOccupantInfo, }, VM, }; +static MAX_NUTRITION: f32 = 50.0; +// static FULL_NUTRITION: f32 = 45.0; +static WARNING_NUTRITION: f32 = 15.0; +static CRITICAL_NUTRITION: f32 = 5.0; + +static MAX_HYDRATION: f32 = 8.75; +static WARNING_HYDRATION: f32 = 2.0; +static CRITICAL_HYDRATION: f32 = 1.0; + +static MAX_OXYGENATION: f32 = 0.024; + +static MAX_FOOD_QUALITY: f32 = 1.0; + +static MAX_MOOD: f32 = 1.0; +static WARNING_MOOD: f32 = 0.5; +static CRITICAL_MOOD: f32 = 0.0; + +static MAX_HYGIENE: f32 = 1.25; +static WARNING_HYGIENE: f32 = 0.25; +static CRITICAL_HYGIENE: f32 = 0.0; + +use serde_derive::{Deserialize, Serialize}; + #[derive(ObjectInterface!)] #[custom(implements(Object { Human, Storage @@ -24,12 +59,15 @@ pub struct HumanPlayer { #[custom(object_vm_ref)] pub vm: std::rc::Rc, + pub species: Species, + + pub damage: f32, pub hydration: f32, pub nutrition: f32, pub oxygenation: f32, pub food_quality: f32, pub mood: f32, - pub hygine: f32, + pub hygiene: f32, left_hand_slot: Slot, right_hand_slot: Slot, @@ -41,6 +79,18 @@ pub struct HumanPlayer { toolbelt_slot: Slot, } +#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] +pub struct EntityInfo { + pub hydration: f32, + pub nutrition: f32, + pub oxygenation: f32, + pub food_quality: f32, + pub mood: f32, + pub hygiene: f32, +} + impl HumanPlayer { pub fn new(id: ObjectID, vm: std::rc::Rc) -> Self { HumanPlayer { @@ -48,22 +98,103 @@ impl HumanPlayer { prefab: Name::new(""), name: Name::new(""), vm, + species: Species::Human, + damage: 0.0, hydration: 5.0, - nutrition: 5.0, - oxygenation: 1.0, + nutrition: 50.0, + oxygenation: 0.024, food_quality: 0.75, mood: 1.0, - hygine: 1.0, + hygiene: 1.0, left_hand_slot: Slot::new(id, 0, "LeftHand".to_string(), SlotClass::None), right_hand_slot: Slot::new(id, 1, "RightHand".to_string(), SlotClass::None), - suit_slot: Slot::new(id, 2, "Helmet".to_string(), SlotClass::Suit), - helmet_slot: Slot::new(id, 3, "LeftHand".to_string(), SlotClass::Helmet), - glasses_slot: Slot::new(id, 4, "LeftHand".to_string(), SlotClass::Glasses), - backpack_slot: Slot::new(id, 5, "LeftHand".to_string(), SlotClass::Back), - uniform_slot: Slot::new(id, 6, "LeftHand".to_string(), SlotClass::Uniform), - toolbelt_slot: Slot::new(id, 7, "LeftHand".to_string(), SlotClass::Belt), + suit_slot: Slot::new(id, 2, "Suit".to_string(), SlotClass::Suit), + helmet_slot: Slot::new(id, 3, "Helmet".to_string(), SlotClass::Helmet), + glasses_slot: Slot::new(id, 4, "Glasses".to_string(), SlotClass::Glasses), + backpack_slot: Slot::new(id, 5, "Back".to_string(), SlotClass::Back), + uniform_slot: Slot::new(id, 6, "Uniform".to_string(), SlotClass::Uniform), + toolbelt_slot: Slot::new(id, 7, "Belt".to_string(), SlotClass::Belt), } } + pub fn with_species(id: ObjectID, vm: std::rc::Rc, species: Species) -> Self { + let uniform_slot = if species == Species::Robot { + Slot::new(id, 6, "Battery".to_string(), SlotClass::Battery) + } else { + Slot::new(id, 6, "Uniform".to_string(), SlotClass::Uniform) + }; + HumanPlayer { + id, + prefab: Name::new(""), + name: Name::new(""), + vm, + species, + damage: 0.0, + hydration: 5.0, + nutrition: 50.0, + oxygenation: 0.024, + food_quality: 0.75, + mood: 1.0, + hygiene: 1.0, + left_hand_slot: Slot::new(id, 0, "LeftHand".to_string(), SlotClass::None), + right_hand_slot: Slot::new(id, 1, "RightHand".to_string(), SlotClass::None), + suit_slot: Slot::new(id, 2, "Suit".to_string(), SlotClass::Suit), + helmet_slot: Slot::new(id, 3, "Helmet".to_string(), SlotClass::Helmet), + glasses_slot: Slot::new(id, 4, "Glasses".to_string(), SlotClass::Glasses), + backpack_slot: Slot::new(id, 5, "Back".to_string(), SlotClass::Back), + uniform_slot, + toolbelt_slot: Slot::new(id, 7, "Belt".to_string(), SlotClass::Belt), + } + } + + pub fn update_entity_info(&mut self, info: &EntityInfo) { + self.hydration = info.hydration; + self.nutrition = info.nutrition; + self.oxygenation = info.oxygenation; + self.food_quality = info.food_quality; + self.mood = info.mood; + self.hygiene = info.hygiene; + } + + pub fn update_slots_from_info(&mut self, info: &BTreeMap) { + for (index, slot_info) in info { + match index { + 0 => { + self.left_hand_slot.occupant.replace(slot_info.clone()); + } + 1 => { + self.right_hand_slot.occupant.replace(slot_info.clone()); + } + 2 => { + self.helmet_slot.occupant.replace(slot_info.clone()); + } + 3 => { + self.suit_slot.occupant.replace(slot_info.clone()); + } + 4 => { + self.backpack_slot.occupant.replace(slot_info.clone()); + } + 5 => { + self.uniform_slot.occupant.replace(slot_info.clone()); + } + 6 => { + self.toolbelt_slot.occupant.replace(slot_info.clone()); + } + 7 => { + self.glasses_slot.occupant.replace(slot_info.clone()); + } + _ => {} + } + } + } +} + +impl Thermal for HumanPlayer { + fn get_radiation_factor(&self) -> f32 { + 0.1 + } + fn get_convection_factor(&self) -> f32 { + 0.1 + } } impl Storage for HumanPlayer { @@ -71,12 +202,12 @@ impl Storage for HumanPlayer { vec![ &self.left_hand_slot, &self.right_hand_slot, - &self.suit_slot, &self.helmet_slot, - &self.glasses_slot, + &self.suit_slot, &self.backpack_slot, &self.uniform_slot, &self.toolbelt_slot, + &self.glasses_slot, ] } @@ -84,12 +215,12 @@ impl Storage for HumanPlayer { vec![ &mut self.left_hand_slot, &mut self.right_hand_slot, - &mut self.suit_slot, &mut self.helmet_slot, - &mut self.glasses_slot, + &mut self.suit_slot, &mut self.backpack_slot, &mut self.uniform_slot, &mut self.toolbelt_slot, + &mut self.glasses_slot, ] } @@ -101,12 +232,12 @@ impl Storage for HumanPlayer { match index { 0 => Some(&self.left_hand_slot), 1 => Some(&self.right_hand_slot), - 2 => Some(&self.suit_slot), - 3 => Some(&self.helmet_slot), - 4 => Some(&self.glasses_slot), - 5 => Some(&self.backpack_slot), - 6 => Some(&self.uniform_slot), - 7 => Some(&self.toolbelt_slot), + 2 => Some(&self.helmet_slot), + 3 => Some(&self.suit_slot), + 4 => Some(&self.backpack_slot), + 5 => Some(&self.uniform_slot), + 6 => Some(&self.toolbelt_slot), + 7 => Some(&self.glasses_slot), _ => None, } } @@ -114,59 +245,111 @@ impl Storage for HumanPlayer { match index { 0 => Some(&mut self.left_hand_slot), 1 => Some(&mut self.right_hand_slot), - 2 => Some(&mut self.suit_slot), - 3 => Some(&mut self.helmet_slot), - 4 => Some(&mut self.glasses_slot), - 5 => Some(&mut self.backpack_slot), - 6 => Some(&mut self.uniform_slot), - 7 => Some(&mut self.toolbelt_slot), + 2 => Some(&mut self.helmet_slot), + 3 => Some(&mut self.suit_slot), + 4 => Some(&mut self.backpack_slot), + 5 => Some(&mut self.uniform_slot), + 6 => Some(&mut self.toolbelt_slot), + 7 => Some(&mut self.glasses_slot), _ => None, } } } impl Human for HumanPlayer { + fn get_species(&self) -> Species { + self.species + } + fn get_damage(&self) -> f32 { + self.damage + } + fn set_damage(&mut self, damage: f32) { + self.damage = damage; + } fn get_hydration(&self) -> f32 { self.hydration } fn set_hydration(&mut self, hydration: f32) { - self.hydration = hydration; + self.hydration = hydration.clamp(0.0, MAX_HYDRATION); + } + fn hydration_state(&self) -> super::traits::StatState { + if self.hydration < CRITICAL_HYDRATION { + return StatState::Critical; + } + if self.hydration < WARNING_HYDRATION { + return StatState::Warning; + } + StatState::Normal } fn get_nutrition(&self) -> f32 { self.nutrition } fn set_nutrition(&mut self, nutrition: f32) { - self.nutrition = nutrition; + self.nutrition = nutrition.clamp(0.0, MAX_NUTRITION); + } + fn nutrition_state(&self) -> StatState { + if self.nutrition < CRITICAL_NUTRITION { + return StatState::Critical; + } + if self.nutrition < WARNING_NUTRITION { + return StatState::Warning; + } + StatState::Normal } fn get_oxygenation(&self) -> f32 { self.oxygenation } fn set_oxygenation(&mut self, oxygenation: f32) { - self.oxygenation = oxygenation; + self.oxygenation = oxygenation.clamp(0.0, MAX_OXYGENATION); } fn get_food_quality(&self) -> f32 { self.food_quality } fn set_food_quality(&mut self, quality: f32) { - self.food_quality = quality; + self.food_quality = quality.clamp(0.0, MAX_FOOD_QUALITY); } fn get_mood(&self) -> f32 { self.mood } fn set_mood(&mut self, mood: f32) { - self.mood = mood; + self.mood = mood.clamp(0.0, MAX_MOOD); } - fn get_hygine(&self) -> f32 { - self.hygine + fn mood_state(&self) -> StatState { + if self.mood < CRITICAL_MOOD { + return StatState::Critical; + } + if self.mood < WARNING_MOOD { + return StatState::Warning; + } + StatState::Normal } - fn set_hygine(&mut self, hygine: f32) { - self.hygine = hygine; + fn get_hygiene(&self) -> f32 { + self.hygiene + } + fn set_hygiene(&mut self, hygiene: f32) { + self.hygiene = hygiene.clamp(0.0, MAX_HYGIENE); + } + fn hygine_state(&self) -> StatState { + if self.hygiene < CRITICAL_HYGIENE { + return StatState::Critical; + } + if self.hygiene < WARNING_HYGIENE { + return StatState::Warning; + } + StatState::Normal } fn is_artificial(&self) -> bool { - false + self.species == Species::Robot } fn robot_battery(&self) -> Option { - None + if self.species != Species::Robot { + return None; + } + + self.uniform_slot() + .occupant + .as_ref() + .and_then(|info| self.vm.get_object(info.id)) } fn suit_slot(&self) -> &Slot { &self.suit_slot diff --git a/ic10emu/src/vm/object/stationpedia.rs b/ic10emu/src/vm/object/stationpedia.rs index ec4419d..e6c6998 100644 --- a/ic10emu/src/vm/object/stationpedia.rs +++ b/ic10emu/src/vm/object/stationpedia.rs @@ -1,34 +1,152 @@ use std::rc::Rc; -use stationeers_data::{enums::prefabs::StationpediaPrefab, templates::ObjectTemplate}; - -use crate::vm::object::{ - templates::{FrozenObject, ObjectInfo, Prefab}, - VMObject, +use stationeers_data::{ + enums::prefabs::StationpediaPrefab, + templates::{ObjectTemplate, PrefabInfo}, }; -use crate::vm::VM; + +use crate::{ + errors::TemplateError, + vm::object::{ + templates::{FrozenObject, ObjectInfo, Prefab}, + Name, VMObject, + }, +}; +use crate::{ + interpreter::Program, + vm::{object::LogicField, VM}, +}; +use strum::EnumProperty; use super::ObjectID; pub mod structs; #[allow(unused)] -pub fn object_from_frozen(obj: &ObjectInfo, id: ObjectID, vm: &Rc) -> Option { +pub fn object_from_frozen( + obj: &ObjectInfo, + id: ObjectID, + vm: &Rc, +) -> Result, TemplateError> { #[allow(clippy::cast_possible_wrap)] let hash = match &obj.prefab { Some(Prefab::Hash(hash)) => *hash, Some(Prefab::Name(name)) => const_crc32::crc32(name.as_bytes()) as i32, - None => return None, + None => return Ok(None), }; let prefab = StationpediaPrefab::from_repr(hash); #[allow(clippy::match_single_binding)] match prefab { - // Some(StationpediaPrefab::ItemIntegratedCircuit10) => { - // Some(VMObject::new(structs::ItemIntegratedCircuit10)) - // } + Some(prefab @ StationpediaPrefab::ItemIntegratedCircuit10) => { + let template = vm + .get_template(Prefab::Hash(hash)) + .ok_or(TemplateError::NoTemplateForPrefab(Prefab::Hash(hash)))?; + let ObjectTemplate::ItemLogicMemory(template) = template else { + return Err(TemplateError::IncorrectTemplate( + "ItemIntegratedCircuit10".to_string(), + Prefab::Name("ItemIntegratedCircuit10".to_string()), + )); + }; + + Ok(Some(VMObject::new(structs::ItemIntegratedCircuit10 { + id, + vm: vm.clone(), + name: Name::new( + &(obj + .name + .clone() + .unwrap_or_else(|| prefab.get_str("name").unwrap().to_string())), + ), + prefab: Name::from_prefab_name(&prefab.to_string()), + fields: template + .logic + .logic_types + .iter() + .map(|(key, access)| { + ( + *key, + LogicField { + field_type: *access, + value: obj + .logic_values + .as_ref() + .and_then(|values| values.get(key)) + .copied() + .unwrap_or(0.0), + }, + ) + }) + .collect(), + memory: obj + .memory + .clone() + .map(TryInto::try_into) + .transpose() + .map_err(|vec: Vec| TemplateError::MemorySize(vec.len(), 512))? + .unwrap_or_else(|| [0.0f64; 512]), + parent_slot: None, + registers: obj + .circuit + .as_ref() + .map(|circuit| circuit.registers.clone().try_into()) + .transpose() + .map_err(|vec: Vec| TemplateError::MemorySize(vec.len(), 18))? + .unwrap_or_else(|| [0.0f64; 18]), + ip: obj + .circuit + .as_ref() + .map(|circuit| circuit.instruction_pointer as usize) + .unwrap_or(0), + next_ip: 0, + ic: obj + .circuit + .as_ref() + .map(|circuit| circuit.yield_instruciton_count) + .unwrap_or(0), + aliases: obj + .circuit + .as_ref() + .map(|circuit| circuit.aliases.clone()) + .unwrap_or_default(), + defines: obj + .circuit + .as_ref() + .map(|circuit| circuit.defines.clone()) + .unwrap_or_default(), + pins: obj + .device_pins + .as_ref() + .map(|pins| { + (0..6) + .map(|index| pins.get(&index).copied()) + .collect::>() + .try_into() + .unwrap() // fixed sized iterator into array should not panic + }) + .unwrap_or_default(), + state: obj + .circuit + .as_ref() + .map(|circuit| circuit.state.clone()) + .unwrap_or(crate::interpreter::ICState::Start), + code: obj.source_code.clone().unwrap_or_default(), + damage: obj.damage.unwrap_or(0.0), + program: obj + .source_code + .as_ref() + .map(|code| { + if code.is_empty() { + Program::default() + } else { + Program::from_code_with_invalid(code) + } + }) + .unwrap_or_default(), + }))) + } // Some(StationpediaPrefab::StructureCircuitHousing) => Some() // Some(StationpediaPrefab::StructureRocketCircuitHousing) => Some() - _ => None, + _ => Ok(None), } } diff --git a/ic10emu/src/vm/object/stationpedia/structs/integrated_circuit.rs b/ic10emu/src/vm/object/stationpedia/structs/integrated_circuit.rs index c2a90c4..4a9fb7c 100644 --- a/ic10emu/src/vm/object/stationpedia/structs/integrated_circuit.rs +++ b/ic10emu/src/vm/object/stationpedia/structs/integrated_circuit.rs @@ -237,8 +237,8 @@ impl IntegratedCircuit for ItemIntegratedCircuit10 { self.get_parent_slot() .and_then(|parent_slot| self.get_vm().get_object(parent_slot.parent)) } - fn get_instruction_pointer(&self) -> f64 { - self.ip as f64 + fn get_instruction_pointer(&self) -> u32 { + self.ip as u32 } fn set_next_instruction(&mut self, next_instruction: f64) { self.next_ip = next_instruction as usize; @@ -285,6 +285,12 @@ impl IntegratedCircuit for ItemIntegratedCircuit10 { self.registers[t as usize] = val; Ok(old_val) } + fn get_registers(&self) -> &[f64] { + &self.registers + } + fn get_registers_mut(&mut self) -> &mut [f64] { + &mut self.registers + } fn set_return_address(&mut self, addr: f64) { self.registers[RETURN_ADDRESS_INDEX] = addr; } @@ -364,6 +370,9 @@ impl IntegratedCircuit for ItemIntegratedCircuit10 { fn set_state(&mut self, state: crate::interpreter::ICState) { self.state = state; } + fn get_instructions_since_yield(&self) -> u16 { + self.ic + } } impl IC10Marker for ItemIntegratedCircuit10 {} diff --git a/ic10emu/src/vm/object/templates.rs b/ic10emu/src/vm/object/templates.rs index 6f408b3..2abb3dc 100644 --- a/ic10emu/src/vm/object/templates.rs +++ b/ic10emu/src/vm/object/templates.rs @@ -2,6 +2,7 @@ use std::{collections::BTreeMap, rc::Rc, str::FromStr}; use crate::{ errors::TemplateError, + interpreter::ICInfo, network::Connection, vm::{ object::{ @@ -16,6 +17,7 @@ use crate::{ GenericLogicableDeviceMemoryReadWriteable, GenericLogicableDeviceMemoryReadable, GenericStorage, }, + humans::{EntityInfo, HumanPlayer}, traits::*, LogicField, Name, Slot, SlotOccupantInfo, }, @@ -33,10 +35,16 @@ use stationeers_data::{ templates::*, }; use strum::{EnumProperty, IntoEnumIterator}; +#[cfg(feature = "tsify")] +use tsify::Tsify; +#[cfg(feature = "tsify")] +use wasm_bindgen::prelude::*; use super::{stationpedia, MemoryAccess, ObjectID, VMObject}; #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub enum Prefab { Hash(i32), Name(String), @@ -59,7 +67,9 @@ impl std::fmt::Display for Prefab { } } -#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct ObjectInfo { pub name: Option, pub id: Option, @@ -71,6 +81,9 @@ pub struct ObjectInfo { pub reagents: Option>, pub memory: Option>, pub logic_values: Option>, + pub entity: Option, + pub source_code: Option, + pub circuit: Option, } impl From<&VMObject> for ObjectInfo { @@ -87,6 +100,9 @@ impl From<&VMObject> for ObjectInfo { reagents: None, memory: None, logic_values: None, + entity: None, + source_code: None, + circuit: None, } } } @@ -108,6 +124,15 @@ impl ObjectInfo { if let Some(item) = interfaces.item { self.update_from_item(item); } + if let Some(human) = interfaces.human { + self.update_from_human(human); + } + if let Some(source) = interfaces.source_code { + self.update_from_source_code(source); + } + if let Some(circuit) = interfaces.integrated_circuit { + self.update_from_circuit(circuit); + } self } @@ -120,9 +145,10 @@ impl ObjectInfo { slots .into_iter() .enumerate() - .filter_map(|(index, slot)| match slot.occupant.as_ref() { - Some(occupant) => Some((index as u32, occupant.clone())), - None => None, + .filter_map(|(index, slot)| { + slot.occupant + .as_ref() + .map(|occupant| (index as u32, occupant.clone())) }) .collect(), ); @@ -142,16 +168,13 @@ impl ObjectInfo { pub fn update_from_device(&mut self, device: DeviceRef<'_>) -> &mut Self { let pins = device.device_pins(); - if pins.is_some_and(|pins| pins.is_empty()) { + if pins.is_some_and(<[Option]>::is_empty) { self.device_pins = None; } else { self.device_pins = pins.map(|pins| { - pins.into_iter() + pins.iter() .enumerate() - .filter_map(|(index, pin)| match pin { - Some(pin) => Some((index as u32, *pin)), - None => None, - }) + .filter_map(|(index, pin)| pin.as_ref().map(|pin| (index as u32, *pin))) .collect() }); } @@ -201,11 +224,65 @@ impl ObjectInfo { ); self } + + pub fn update_from_human(&mut self, human: HumanRef<'_>) -> &mut Self { + let damage = human.get_damage(); + if damage == 0.0 { + self.damage = None; + } else { + self.damage.replace(damage); + } + self.entity.replace(EntityInfo { + hydration: human.get_hydration(), + nutrition: human.get_nutrition(), + oxygenation: human.get_oxygenation(), + food_quality: human.get_food_quality(), + mood: human.get_mood(), + hygiene: human.get_hygiene(), + }); + self + } + + pub fn update_from_source_code(&mut self, source: SourceCodeRef<'_>) -> &mut Self { + let code = source.get_source_code(); + if !code.is_empty() { + self.source_code.replace(code); + } + self + } + + pub fn update_from_circuit(&mut self, circuit: IntegratedCircuitRef<'_>) -> &mut Self { + self.circuit.replace(ICInfo { + instruction_pointer: circuit.get_instruction_pointer(), + registers: circuit.get_registers().to_vec(), + aliases: circuit + .get_aliases() + .iter() + .map(|(key, val)| (key.clone(), val.clone())) + .collect(), + defines: circuit + .get_defines() + .iter() + .map(|(key, val)| (key.clone(), *val)) + .collect(), + labels: circuit + .get_labels() + .iter() + .map(|(key, val)| (key.clone(), *val)) + .collect(), + state: circuit.get_state(), + yield_instruciton_count: circuit.get_instructions_since_yield(), + }); + self + } } #[derive(Debug, Clone, Deserialize, Serialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct FrozenObject { pub obj_info: ObjectInfo, + pub database_template: bool, pub template: Option, } @@ -213,6 +290,7 @@ impl FrozenObject { pub fn new(obj_info: ObjectInfo) -> Self { FrozenObject { obj_info, + database_template: false, template: None, } } @@ -220,6 +298,7 @@ impl FrozenObject { pub fn with_template(obj_info: ObjectInfo, template: ObjectTemplate) -> Self { FrozenObject { obj_info, + database_template: false, template: Some(template), } } @@ -239,7 +318,7 @@ impl FrozenObject { }, |template| Ok(template.clone()), )?; - if let Some(obj) = stationpedia::object_from_frozen(&self.obj_info, id, vm) { + if let Some(obj) = stationpedia::object_from_frozen(&self.obj_info, id, vm)? { Ok(obj) } else { self.build_generic(id, &template, vm.clone()) @@ -251,7 +330,7 @@ impl FrozenObject { .connections .as_ref() .map(|connections| connections.values().copied().collect()) - .unwrap_or_else(Vec::new) + .unwrap_or_default() } pub fn contained_object_ids(&self) -> Vec { @@ -259,7 +338,7 @@ impl FrozenObject { .slots .as_ref() .map(|slots| slots.values().map(|slot| slot.id).collect()) - .unwrap_or_else(Vec::new) + .unwrap_or_default() } pub fn contained_object_slots(&self) -> Vec<(u32, ObjectID)> { @@ -272,17 +351,17 @@ impl FrozenObject { .map(|(index, slot)| (*index, slot.id)) .collect() }) - .unwrap_or_else(Vec::new) + .unwrap_or_default() } fn build_slots( &self, id: ObjectID, - slots_info: &Vec, + slots_info: &[SlotInfo], logic_info: Option<&LogicInfo>, ) -> Vec { slots_info - .into_iter() + .iter() .enumerate() .map(|(index, info)| Slot { parent: id, @@ -402,7 +481,7 @@ impl FrozenObject { Structure(s) => Ok(VMObject::new(Generic { id, prefab: Name::from_prefab_name(&s.prefab.prefab_name), - name: Name::new(&s.prefab.name), + name: Name::new(&self.obj_info.name.clone().unwrap_or(s.prefab.name.clone())), vm, internal_atmo_info: s.internal_atmo_info.clone(), thermal_info: s.thermal_info.clone(), @@ -411,7 +490,7 @@ impl FrozenObject { StructureSlots(s) => Ok(VMObject::new(GenericStorage { id, prefab: Name::from_prefab_name(&s.prefab.prefab_name), - name: Name::new(&s.prefab.name), + name: Name::new(&self.obj_info.name.clone().unwrap_or(s.prefab.name.clone())), vm, internal_atmo_info: s.internal_atmo_info.clone(), thermal_info: s.thermal_info.clone(), @@ -421,7 +500,7 @@ impl FrozenObject { StructureLogic(s) => Ok(VMObject::new(GenericLogicable { id, prefab: Name::from_prefab_name(&s.prefab.prefab_name), - name: Name::new(&s.prefab.name), + name: Name::new(&self.obj_info.name.clone().unwrap_or(s.prefab.name.clone())), vm, internal_atmo_info: s.internal_atmo_info.clone(), thermal_info: s.thermal_info.clone(), @@ -433,7 +512,7 @@ impl FrozenObject { StructureLogicDevice(s) => Ok(VMObject::new(GenericLogicableDevice { id, prefab: Name::from_prefab_name(&s.prefab.prefab_name), - name: Name::new(&s.prefab.name), + name: Name::new(&self.obj_info.name.clone().unwrap_or(s.prefab.name.clone())), vm, internal_atmo_info: s.internal_atmo_info.clone(), thermal_info: s.thermal_info.clone(), @@ -449,7 +528,7 @@ impl FrozenObject { StructureLogicDeviceConsumer(s) => Ok(VMObject::new(GenericLogicableDeviceConsumer { id, prefab: Name::from_prefab_name(&s.prefab.prefab_name), - name: Name::new(&s.prefab.name), + name: Name::new(&self.obj_info.name.clone().unwrap_or(s.prefab.name.clone())), vm, internal_atmo_info: s.internal_atmo_info.clone(), thermal_info: s.thermal_info.clone(), @@ -466,7 +545,7 @@ impl FrozenObject { StructureCircuitHolder(s) => Ok(VMObject::new(GenericCircuitHolder { id, prefab: Name::from_prefab_name(&s.prefab.prefab_name), - name: Name::new(&s.prefab.name), + name: Name::new(&self.obj_info.name.clone().unwrap_or(s.prefab.name.clone())), vm, internal_atmo_info: s.internal_atmo_info.clone(), thermal_info: s.thermal_info.clone(), @@ -485,7 +564,7 @@ impl FrozenObject { Ok(VMObject::new(GenericLogicableDeviceMemoryReadable { id, prefab: Name::from_prefab_name(&s.prefab.prefab_name), - name: Name::new(&s.prefab.name), + name: Name::new(&self.obj_info.name.clone().unwrap_or(s.prefab.name.clone())), vm, internal_atmo_info: s.internal_atmo_info.clone(), thermal_info: s.thermal_info.clone(), @@ -504,7 +583,7 @@ impl FrozenObject { Ok(VMObject::new(GenericLogicableDeviceMemoryReadWriteable { id, prefab: Name::from_prefab_name(&s.prefab.prefab_name), - name: Name::new(&s.prefab.name), + name: Name::new(&self.obj_info.name.clone().unwrap_or(s.prefab.name.clone())), vm, internal_atmo_info: s.internal_atmo_info.clone(), thermal_info: s.thermal_info.clone(), @@ -526,7 +605,9 @@ impl FrozenObject { GenericLogicableDeviceConsumerMemoryReadable { id, prefab: Name::from_prefab_name(&s.prefab.prefab_name), - name: Name::new(&s.prefab.name), + name: Name::new( + &self.obj_info.name.clone().unwrap_or(s.prefab.name.clone()), + ), vm, internal_atmo_info: s.internal_atmo_info.clone(), thermal_info: s.thermal_info.clone(), @@ -548,7 +629,7 @@ impl FrozenObject { GenericLogicableDeviceConsumerMemoryReadWriteable { id, prefab: Name::from_prefab_name(&s.prefab.prefab_name), - name: Name::new(&s.prefab.name), + name: Name::new(&self.obj_info.name.clone().unwrap_or(s.prefab.name.clone())), vm, internal_atmo_info: s.internal_atmo_info.clone(), thermal_info: s.thermal_info.clone(), @@ -568,7 +649,7 @@ impl FrozenObject { Item(i) => Ok(VMObject::new(GenericItem { id, prefab: Name::from_prefab_name(&i.prefab.prefab_name), - name: Name::new(&i.prefab.name), + name: Name::new(&self.obj_info.name.clone().unwrap_or(i.prefab.name.clone())), vm, internal_atmo_info: i.internal_atmo_info.clone(), thermal_info: i.thermal_info.clone(), @@ -579,7 +660,7 @@ impl FrozenObject { ItemSlots(i) => Ok(VMObject::new(GenericItemStorage { id, prefab: Name::from_prefab_name(&i.prefab.prefab_name), - name: Name::new(&i.prefab.name), + name: Name::new(&self.obj_info.name.clone().unwrap_or(i.prefab.name.clone())), vm, internal_atmo_info: i.internal_atmo_info.clone(), thermal_info: i.thermal_info.clone(), @@ -591,7 +672,7 @@ impl FrozenObject { ItemConsumer(i) => Ok(VMObject::new(GenericItemConsumer { id, prefab: Name::from_prefab_name(&i.prefab.prefab_name), - name: Name::new(&i.prefab.name), + name: Name::new(&self.obj_info.name.clone().unwrap_or(i.prefab.name.clone())), vm, internal_atmo_info: i.internal_atmo_info.clone(), thermal_info: i.thermal_info.clone(), @@ -604,7 +685,7 @@ impl FrozenObject { ItemLogic(i) => Ok(VMObject::new(GenericItemLogicable { id, prefab: Name::from_prefab_name(&i.prefab.prefab_name), - name: Name::new(&i.prefab.name), + name: Name::new(&self.obj_info.name.clone().unwrap_or(i.prefab.name.clone())), vm, internal_atmo_info: i.internal_atmo_info.clone(), thermal_info: i.thermal_info.clone(), @@ -619,7 +700,7 @@ impl FrozenObject { Ok(VMObject::new(GenericItemLogicableMemoryReadable { id, prefab: Name::from_prefab_name(&i.prefab.prefab_name), - name: Name::new(&i.prefab.name), + name: Name::new(&self.obj_info.name.clone().unwrap_or(i.prefab.name.clone())), vm, internal_atmo_info: i.internal_atmo_info.clone(), thermal_info: i.thermal_info.clone(), @@ -635,7 +716,7 @@ impl FrozenObject { ItemLogicMemory(i) => Ok(VMObject::new(GenericItemLogicableMemoryReadWriteable { id, prefab: Name::from_prefab_name(&i.prefab.prefab_name), - name: Name::new(&i.prefab.name), + name: Name::new(&self.obj_info.name.clone().unwrap_or(i.prefab.name.clone())), vm, internal_atmo_info: i.internal_atmo_info.clone(), thermal_info: i.thermal_info.clone(), @@ -650,7 +731,7 @@ impl FrozenObject { ItemCircuitHolder(i) => Ok(VMObject::new(GenericItemCircuitHolder { id, prefab: Name::from_prefab_name(&i.prefab.prefab_name), - name: Name::new(&i.prefab.name), + name: Name::new(&self.obj_info.name.clone().unwrap_or(i.prefab.name.clone())), vm, internal_atmo_info: i.internal_atmo_info.clone(), thermal_info: i.thermal_info.clone(), @@ -664,7 +745,7 @@ impl FrozenObject { ItemSuit(i) => Ok(VMObject::new(GenericItemSuit { id, prefab: Name::from_prefab_name(&i.prefab.prefab_name), - name: Name::new(&i.prefab.name), + name: Name::new(&self.obj_info.name.clone().unwrap_or(i.prefab.name.clone())), vm, internal_atmo_info: i.internal_atmo_info.clone(), thermal_info: i.thermal_info.clone(), @@ -677,7 +758,7 @@ impl FrozenObject { ItemSuitLogic(i) => Ok(VMObject::new(GenericItemSuitLogic { id, prefab: Name::from_prefab_name(&i.prefab.prefab_name), - name: Name::new(&i.prefab.name), + name: Name::new(&self.obj_info.name.clone().unwrap_or(i.prefab.name.clone())), vm, internal_atmo_info: i.internal_atmo_info.clone(), thermal_info: i.thermal_info.clone(), @@ -692,7 +773,7 @@ impl FrozenObject { ItemSuitCircuitHolder(i) => Ok(VMObject::new(GenericItemSuitCircuitHolder { id, prefab: Name::from_prefab_name(&i.prefab.prefab_name), - name: Name::new(&i.prefab.name), + name: Name::new(&self.obj_info.name.clone().unwrap_or(i.prefab.name.clone())), vm, internal_atmo_info: i.internal_atmo_info.clone(), thermal_info: i.thermal_info.clone(), @@ -705,6 +786,19 @@ impl FrozenObject { modes: i.logic.modes.clone(), memory: self.build_memory(&i.memory), })), + Human(h) => { + let mut human = HumanPlayer::with_species(id, vm, h.species); + if let Some(info) = &self.obj_info.entity { + human.update_entity_info(info); + } + if let Some(slot_info) = &self.obj_info.slots { + human.update_slots_from_info(slot_info); + } + if let Some(damage) = &self.obj_info.damage { + human.damage = *damage; + } + Ok(VMObject::new(human)) + } } } @@ -714,15 +808,48 @@ impl FrozenObject { let mut obj_info: ObjectInfo = obj.into(); obj_info.update_from_interfaces(&interfaces); // if the template is known, omit it. else build it from interfaces + let mut database_template = false; let template = vm .get_template(Prefab::Hash(obj_ref.get_prefab().hash)) .map_or_else( || Some(try_template_from_interfaces(&interfaces, obj)), - |_| None, + |template| { + database_template = true; + Some(Ok(template)) + }, ) .transpose()?; - Ok(FrozenObject { obj_info, template }) + Ok(FrozenObject { + obj_info, + template, + database_template, + }) + } + + pub fn freeze_object_sparse(obj: &VMObject, vm: &Rc) -> Result { + let obj_ref = obj.borrow(); + let interfaces = ObjectInterfaces::from_object(&*obj_ref); + let mut obj_info: ObjectInfo = obj.into(); + obj_info.update_from_interfaces(&interfaces); + // if the template is known, omit it. else build it from interfaces + let mut database_template = false; + let template = vm + .get_template(Prefab::Hash(obj_ref.get_prefab().hash)) + .map_or_else( + || Some(try_template_from_interfaces(&interfaces, obj)), + |_| { + database_template = true; + None + }, + ) + .transpose()?; + + Ok(FrozenObject { + obj_info, + template, + database_template, + }) } } @@ -804,7 +931,7 @@ fn try_template_from_interfaces( memory_readable: None, memory_writable: None, logicable: Some(logic), - source_code: None, + source_code: _sc, circuit_holder: _ch, item: None, integrated_circuit: None, @@ -837,7 +964,7 @@ fn try_template_from_interfaces( memory_readable: None, memory_writable: None, logicable: Some(logic), - source_code: None, + source_code: _sc, circuit_holder: _ch, item: None, integrated_circuit: None, @@ -873,7 +1000,7 @@ fn try_template_from_interfaces( memory_readable: Some(mem_r), memory_writable: _mem_w, logicable: Some(logic), - source_code: None, + source_code: _sc, circuit_holder: _ch, item: None, integrated_circuit: None, @@ -975,7 +1102,7 @@ fn try_template_from_interfaces( memory_readable: None, memory_writable: None, logicable: Some(logic), - source_code: None, + source_code: _sc, circuit_holder: _ch, item: Some(item), integrated_circuit: None, @@ -1008,10 +1135,10 @@ fn try_template_from_interfaces( memory_readable: Some(mem_r), memory_writable: _mem_w, logicable: Some(logic), - source_code: None, + source_code: _sc, circuit_holder: _ch, item: Some(item), - integrated_circuit: None, + integrated_circuit: _ic, programmable: None, instructable: _inst, logic_stack: _logic_stack, @@ -1036,6 +1163,41 @@ fn try_template_from_interfaces( logic: logic.into(), memory: mem_r.into(), })), + ObjectInterfaces { + structure: None, + storage: Some(storage), + memory_readable: None, + memory_writable: None, + logicable: None, + source_code: None, + circuit_holder: None, + item: None, + integrated_circuit: None, + programmable: None, + instructable: None, + logic_stack: None, + device: None, + wireless_transmit: None, + wireless_receive: None, + network: None, + plant: None, + suit: None, + chargeable: None, + reagent_interface: None, + fabricator: None, + internal_atmosphere: None, + thermal: Some(_), + human: Some(human), + } => Ok(ObjectTemplate::Human(HumanTemplate { + prefab: PrefabInfo { + prefab_name: "Character".to_string(), + prefab_hash: 294335127, + desc: "Charater".to_string(), + name: "Charater".to_string(), + }, + species: human.get_species(), + slots: storage.into(), + })), _ => Err(TemplateError::NonConformingObject(obj.get_id())), } } diff --git a/ic10emu/src/vm/object/traits.rs b/ic10emu/src/vm/object/traits.rs index 9355dd0..210e128 100644 --- a/ic10emu/src/vm/object/traits.rs +++ b/ic10emu/src/vm/object/traits.rs @@ -16,14 +16,52 @@ use crate::{ use stationeers_data::enums::{ basic::{Class as SlotClass, GasType, SortingClass}, script::{LogicSlotType, LogicType}, + Species, }; use std::{collections::BTreeMap, fmt::Debug}; +#[cfg(feature = "tsify")] +use tsify::Tsify; +#[cfg(feature = "tsify")] +use wasm_bindgen::prelude::*; + +use strum::{AsRefStr, Display, EnumIter, EnumProperty, EnumString, FromRepr}; #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct ParentSlotInfo { pub parent: ObjectID, pub slot: usize, } + +#[derive( + Default, + Debug, + Display, + Clone, + Copy, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + EnumString, + AsRefStr, + EnumProperty, + EnumIter, + FromRepr, + Serialize, + Deserialize, +)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] +pub enum StatState { + #[default] + Normal, + Warning, + Critical, +} + tag_object_traits! { #![object_trait(Object: Debug)] @@ -155,18 +193,20 @@ tag_object_traits! { pub trait IntegratedCircuit: Logicable + MemoryWritable + SourceCode + Item { fn get_circuit_holder(&self) -> Option; - fn get_instruction_pointer(&self) -> f64; + fn get_instruction_pointer(&self) -> u32; fn set_next_instruction(&mut self, next_instruction: f64); fn set_next_instruction_relative(&mut self, offset: f64) { - self.set_next_instruction(self.get_instruction_pointer() + offset); + self.set_next_instruction(self.get_instruction_pointer() as f64 + offset); } fn reset(&mut self); fn get_real_target(&self, indirection: u32, target: u32) -> Result; fn get_register(&self, indirection: u32, target: u32) -> Result; + fn get_registers(&self) -> &[f64]; + fn get_registers_mut(&mut self) -> &mut [f64]; fn set_register(&mut self, indirection: u32, target: u32, val: f64) -> Result; fn set_return_address(&mut self, addr: f64); fn al(&mut self) { - self.set_return_address(self.get_instruction_pointer() + 1.0); + self.set_return_address(self.get_instruction_pointer() as f64 + 1.0); } fn push_stack(&mut self, val: f64) -> Result; fn pop_stack(&mut self) -> Result; @@ -180,6 +220,7 @@ tag_object_traits! { fn get_labels(&self) -> &BTreeMap; fn get_state(&self) -> ICState; fn set_state(&mut self, state: ICState); + fn get_instructions_since_yield(&self) -> u16; } pub trait Programmable: ICInstructable { @@ -270,24 +311,25 @@ tag_object_traits! { } pub trait Human : Storage { - fn get_hygine(&self) -> f32; - fn set_hygine(&mut self, hygine: f32); - fn hygine_ok(&self) -> bool { - self.get_hygine() > 0.25 - } - fn hygine_low(&self) -> bool { - self.get_hygine() <= 0.0 - } - fn get_mood(&self) -> f32; - fn set_mood(&mut self, mood: f32); + fn get_species(&self) -> Species; + fn get_damage(&self) -> f32; + fn set_damage(&mut self, damage: f32); fn get_nutrition(&self) -> f32; fn set_nutrition(&mut self, nutrition: f32); - fn get_food_quality(&self) -> f32; - fn set_food_quality(&mut self, quality: f32); + fn nutrition_state(&self) -> StatState; fn get_hydration(&self) -> f32; fn set_hydration(&mut self, hydration: f32); + fn hydration_state(&self) -> StatState; fn get_oxygenation(&self) -> f32; fn set_oxygenation(&mut self, oxygenation: f32); + fn get_food_quality(&self) -> f32; + fn set_food_quality(&mut self, quality: f32); + fn get_mood(&self) -> f32; + fn set_mood(&mut self, mood: f32); + fn mood_state(&self) -> StatState; + fn get_hygiene(&self) -> f32; + fn set_hygiene(&mut self, hygine: f32); + fn hygine_state(&self) -> StatState; fn is_artificial(&self) -> bool; fn robot_battery(&self) -> Option; fn suit_slot(&self) -> &Slot; diff --git a/ic10emu_wasm/Cargo.toml b/ic10emu_wasm/Cargo.toml index 587f187..4ba219b 100644 --- a/ic10emu_wasm/Cargo.toml +++ b/ic10emu_wasm/Cargo.toml @@ -5,7 +5,7 @@ version.workspace = true edition.workspace = true [dependencies] -ic10emu = { path = "../ic10emu" } +ic10emu = { path = "../ic10emu", feaures = ["tsify"] } console_error_panic_hook = {version = "0.1.7", optional = true} js-sys = "0.3.69" web-sys = { version = "0.3.69", features = ["WritableStream", "console"] } @@ -18,7 +18,7 @@ serde-wasm-bindgen = "0.6.5" itertools = "0.13.0" serde = { version = "1.0.202", features = ["derive"] } serde_with = "3.8.1" -tsify = { version = "0.4.5", default-features = false, features = ["js", "wasm-bindgen"] } +tsify = { version = "0.4.5", default-features = false, features = ["js"] } thiserror = "1.0.61" [build-dependencies] diff --git a/rust-analyzer.json b/rust-analyzer.json index 7021847..50418a4 100644 --- a/rust-analyzer.json +++ b/rust-analyzer.json @@ -1,4 +1,5 @@ { "rust-analyzer.cargo.features": [ + "tsify" ] } diff --git a/stationeers_data/Cargo.toml b/stationeers_data/Cargo.toml index 71ddfd8..798fabd 100644 --- a/stationeers_data/Cargo.toml +++ b/stationeers_data/Cargo.toml @@ -6,7 +6,9 @@ edition.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] -prefab_database = [] # compile with the prefab database enabled +prefab_database = [] # compile with the prefab database enabled +tsify = ["dep:tsify", "dep:wasm-bindgen"] +wasm-bindgen = ["dep:wasm-bindgen"] [dependencies] num-integer = "0.1.46" @@ -14,3 +16,5 @@ phf = "0.11.2" serde = "1.0.202" serde_derive = "1.0.202" strum = { version = "0.26.2", features = ["derive", "phf", "strum_macros"] } +tsify = { version = "0.4.5", optional = true, features = ["js"] } +wasm-bindgen = { version = "0.2.92", optional = true } diff --git a/stationeers_data/src/enums/basic.rs b/stationeers_data/src/enums/basic.rs index 5f29bb6..13cbf0f 100644 --- a/stationeers_data/src/enums/basic.rs +++ b/stationeers_data/src/enums/basic.rs @@ -1,5 +1,9 @@ use serde_derive::{Deserialize, Serialize}; use strum::{AsRefStr, Display, EnumIter, EnumProperty, EnumString, FromRepr}; +#[cfg(feature = "tsify")] +use tsify::Tsify; +#[cfg(feature = "tsify")] +use wasm_bindgen::prelude::*; use super::script::{LogicSlotType, LogicType}; #[derive( Debug, @@ -19,6 +23,8 @@ use super::script::{LogicSlotType, LogicType}; Serialize, Deserialize )] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] #[strum(use_phf)] #[repr(u8)] pub enum AirConditioningMode { @@ -65,6 +71,8 @@ impl TryFrom for AirConditioningMode { Serialize, Deserialize )] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] #[strum(use_phf)] #[repr(u8)] pub enum AirControlMode { @@ -115,6 +123,8 @@ impl TryFrom for AirControlMode { Serialize, Deserialize )] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] #[strum(use_phf)] #[repr(u8)] pub enum ColorType { @@ -189,6 +199,8 @@ impl TryFrom for ColorType { Serialize, Deserialize )] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] #[strum(use_phf)] #[repr(u8)] pub enum DaylightSensorMode { @@ -238,6 +250,8 @@ impl TryFrom for DaylightSensorMode { Serialize, Deserialize )] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] #[strum(use_phf)] #[repr(u8)] pub enum ElevatorMode { @@ -284,6 +298,8 @@ impl TryFrom for ElevatorMode { Serialize, Deserialize )] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] #[strum(use_phf)] #[repr(u8)] pub enum EntityState { @@ -333,6 +349,8 @@ impl TryFrom for EntityState { Serialize, Deserialize )] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] #[strum(use_phf)] #[repr(u32)] pub enum GasType { @@ -424,6 +442,8 @@ impl TryFrom for GasType { Serialize, Deserialize )] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] #[strum(use_phf)] #[repr(u8)] pub enum PowerMode { @@ -477,6 +497,8 @@ impl TryFrom for PowerMode { Serialize, Deserialize )] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] #[strum(use_phf)] #[repr(u8)] pub enum PrinterInstruction { @@ -548,6 +570,8 @@ impl TryFrom for PrinterInstruction { Serialize, Deserialize )] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] #[strum(use_phf)] #[repr(u8)] pub enum ReEntryProfile { @@ -602,6 +626,8 @@ impl TryFrom for ReEntryProfile { Serialize, Deserialize )] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] #[strum(use_phf)] #[repr(u8)] pub enum RobotMode { @@ -662,6 +688,8 @@ impl TryFrom for RobotMode { Serialize, Deserialize )] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] #[strum(use_phf)] #[repr(u8)] pub enum RocketMode { @@ -719,6 +747,8 @@ impl TryFrom for RocketMode { Serialize, Deserialize )] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] #[strum(use_phf)] #[repr(u8)] pub enum Class { @@ -878,6 +908,8 @@ impl TryFrom for Class { Serialize, Deserialize )] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] #[strum(use_phf)] #[repr(u8)] pub enum SorterInstruction { @@ -938,6 +970,8 @@ impl TryFrom for SorterInstruction { Serialize, Deserialize )] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] #[strum(use_phf)] #[repr(u8)] pub enum SortingClass { @@ -1010,6 +1044,8 @@ impl TryFrom for SortingClass { Serialize, Deserialize )] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] #[strum(use_phf)] #[repr(u8)] pub enum SoundAlert { @@ -1186,6 +1222,8 @@ impl TryFrom for SoundAlert { Serialize, Deserialize )] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] #[strum(use_phf)] #[repr(u8)] pub enum LogicTransmitterMode { @@ -1231,6 +1269,8 @@ impl TryFrom for LogicTransmitterMode { Serialize, Deserialize )] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] #[strum(use_phf)] #[repr(u8)] pub enum VentDirection { @@ -1274,6 +1314,8 @@ impl TryFrom for VentDirection { Serialize, Deserialize )] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] #[strum(use_phf)] #[repr(u8)] pub enum ConditionOperation { diff --git a/stationeers_data/src/enums/prefabs.rs b/stationeers_data/src/enums/prefabs.rs index e33b183..920933a 100644 --- a/stationeers_data/src/enums/prefabs.rs +++ b/stationeers_data/src/enums/prefabs.rs @@ -1,5 +1,9 @@ use serde_derive::{Deserialize, Serialize}; use strum::{AsRefStr, Display, EnumIter, EnumProperty, EnumString, FromRepr}; +#[cfg(feature = "tsify")] +use tsify::Tsify; +#[cfg(feature = "tsify")] +use wasm_bindgen::prelude::*; #[derive( Debug, Display, @@ -18,6 +22,8 @@ use strum::{AsRefStr, Display, EnumIter, EnumProperty, EnumString, FromRepr}; Serialize, Deserialize )] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] #[strum(use_phf)] #[repr(i32)] pub enum StationpediaPrefab { diff --git a/stationeers_data/src/enums/script.rs b/stationeers_data/src/enums/script.rs index 1be73d5..81ad20b 100644 --- a/stationeers_data/src/enums/script.rs +++ b/stationeers_data/src/enums/script.rs @@ -1,5 +1,9 @@ use serde_derive::{Deserialize, Serialize}; use strum::{AsRefStr, Display, EnumIter, EnumProperty, EnumString, FromRepr}; +#[cfg(feature = "tsify")] +use tsify::Tsify; +#[cfg(feature = "tsify")] +use wasm_bindgen::prelude::*; #[derive( Debug, Display, @@ -18,6 +22,8 @@ use strum::{AsRefStr, Display, EnumIter, EnumProperty, EnumString, FromRepr}; Serialize, Deserialize )] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] #[strum(use_phf)] #[repr(u8)] pub enum LogicBatchMethod { @@ -67,6 +73,8 @@ impl TryFrom for LogicBatchMethod { Serialize, Deserialize )] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] #[strum(use_phf)] #[repr(u8)] pub enum LogicReagentMode { @@ -117,6 +125,8 @@ impl TryFrom for LogicReagentMode { Serialize, Deserialize )] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] #[strum(use_phf)] #[repr(u8)] pub enum LogicSlotType { @@ -310,6 +320,8 @@ impl TryFrom for LogicSlotType { Serialize, Deserialize )] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] #[strum(use_phf)] #[repr(u16)] pub enum LogicType { diff --git a/stationeers_data/src/lib.rs b/stationeers_data/src/lib.rs index 63cd167..88d5931 100644 --- a/stationeers_data/src/lib.rs +++ b/stationeers_data/src/lib.rs @@ -3,12 +3,18 @@ use std::collections::BTreeMap; pub mod templates; pub mod enums { use serde_derive::{Deserialize, Serialize}; + + #[cfg(feature = "tsify")] + use tsify::Tsify; + #[cfg(feature = "tsify")] + use wasm_bindgen::prelude::*; + use std::fmt::Display; use strum::{AsRefStr, EnumIter, EnumString, FromRepr}; pub mod basic; - pub mod script; pub mod prefabs; + pub mod script; #[derive(Debug)] pub struct ParseError { @@ -26,6 +32,8 @@ pub mod enums { #[derive( Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, EnumString, )] + #[cfg_attr(feature = "tsify", derive(Tsify))] + #[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub enum MemoryAccess { Read, Write, @@ -49,6 +57,8 @@ pub mod enums { FromRepr, EnumString, )] + #[cfg_attr(feature = "tsify", derive(Tsify))] + #[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub enum ConnectionType { Pipe, Power, @@ -81,6 +91,8 @@ pub mod enums { FromRepr, EnumString, )] + #[cfg_attr(feature = "tsify", derive(Tsify))] + #[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub enum ConnectionRole { Input, Input2, @@ -92,7 +104,6 @@ pub mod enums { None, } - #[derive( Debug, Default, @@ -110,6 +121,8 @@ pub mod enums { FromRepr, EnumString, )] + #[cfg_attr(feature = "tsify", derive(Tsify))] + #[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] #[repr(u32)] pub enum MachineTier { #[default] @@ -120,6 +133,33 @@ pub mod enums { #[serde(other)] Max, } + + #[derive( + Default, + Debug, + Clone, + Copy, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + EnumString, + AsRefStr, + EnumIter, + FromRepr, + Serialize, + Deserialize, + )] + #[cfg_attr(feature = "tsify", derive(Tsify))] + #[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] + pub enum Species { + None, + #[default] + Human, + Zrilian, + Robot, + } } #[must_use] diff --git a/stationeers_data/src/templates.rs b/stationeers_data/src/templates.rs index ff3279d..07c91db 100644 --- a/stationeers_data/src/templates.rs +++ b/stationeers_data/src/templates.rs @@ -3,11 +3,17 @@ use std::collections::BTreeMap; use crate::enums::{ basic::{Class as SlotClass, GasType, SortingClass}, script::{LogicSlotType, LogicType}, - ConnectionRole, ConnectionType, MachineTier, MemoryAccess, + ConnectionRole, ConnectionType, MachineTier, MemoryAccess, Species, }; use serde_derive::{Deserialize, Serialize}; +#[cfg(feature = "tsify")] +use tsify::Tsify; +#[cfg(feature = "tsify")] +use wasm_bindgen::prelude::*; #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] #[serde(untagged)] pub enum ObjectTemplate { Structure(StructureTemplate), @@ -27,6 +33,7 @@ pub enum ObjectTemplate { ItemSuit(ItemSuitTemplate), ItemSuitLogic(ItemSuitLogicTemplate), ItemSuitCircuitHolder(ItemSuitCircuitHolderTemplate), + Human(HumanTemplate), } #[allow(dead_code)] @@ -53,6 +60,7 @@ impl ObjectTemplate { ItemSuit(i) => &i.prefab, ItemSuitLogic(i) => &i.prefab, ItemSuitCircuitHolder(i) => &i.prefab, + Human(h) => &h.prefab, } } } @@ -158,20 +166,42 @@ impl From for ObjectTemplate { } } +impl From for ObjectTemplate { + fn from(value: HumanTemplate) -> Self { + Self::Human(value) + } +} + +#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] +pub struct HumanTemplate { + pub prefab: PrefabInfo, + pub species: Species, + pub slots: Vec, +} + #[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct PrefabInfo { pub prefab_name: String, pub prefab_hash: i32, pub desc: String, pub name: String, } + #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct SlotInfo { pub name: String, pub typ: SlotClass, } #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct LogicInfo { pub logic_slot_types: BTreeMap>, pub logic_types: BTreeMap, @@ -182,6 +212,8 @@ pub struct LogicInfo { } #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct ItemInfo { pub consumable: bool, pub filter_type: Option, @@ -193,6 +225,8 @@ pub struct ItemInfo { } #[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct ConnectionInfo { pub typ: ConnectionType, pub role: ConnectionRole, @@ -200,6 +234,8 @@ pub struct ConnectionInfo { #[allow(clippy::struct_excessive_bools)] #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct DeviceInfo { pub connection_list: Vec, pub device_pins_length: Option, @@ -214,12 +250,16 @@ pub struct DeviceInfo { } #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct ConsumerInfo { pub consumed_resouces: Vec, pub processed_reagents: Vec, } #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct RecipeRange { pub start: f64, pub stop: f64, @@ -227,6 +267,8 @@ pub struct RecipeRange { } #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct RecipeGasMix { pub rule: i64, pub is_any: bool, @@ -235,6 +277,8 @@ pub struct RecipeGasMix { } #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct Recipe { pub tier: MachineTier, pub time: f64, @@ -243,21 +287,27 @@ pub struct Recipe { pub pressure: RecipeRange, pub required_mix: RecipeGasMix, pub count_types: i64, - pub reagents: BTreeMap + pub reagents: BTreeMap, } #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct FabricatorInfo { pub tier: MachineTier, pub recipes: BTreeMap, } #[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct StructureInfo { pub small_grid: bool, } #[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct Instruction { pub description: String, pub typ: String, @@ -265,6 +315,8 @@ pub struct Instruction { } #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct MemoryInfo { pub instructions: Option>, pub memory_access: MemoryAccess, @@ -272,23 +324,31 @@ pub struct MemoryInfo { } #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct ThermalInfo { pub convection_factor: f32, pub radiation_factor: f32, } #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct InternalAtmoInfo { pub volume: f32, } #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct SuitInfo { pub hygine_reduction_multiplier: f32, pub waste_max_pressure: f32, } #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct StructureTemplate { pub prefab: PrefabInfo, pub structure: StructureInfo, @@ -297,6 +357,8 @@ pub struct StructureTemplate { } #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct StructureSlotsTemplate { pub prefab: PrefabInfo, pub structure: StructureInfo, @@ -306,6 +368,8 @@ pub struct StructureSlotsTemplate { } #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct StructureLogicTemplate { pub prefab: PrefabInfo, pub structure: StructureInfo, @@ -316,6 +380,8 @@ pub struct StructureLogicTemplate { } #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct StructureLogicDeviceTemplate { pub prefab: PrefabInfo, pub structure: StructureInfo, @@ -327,6 +393,8 @@ pub struct StructureLogicDeviceTemplate { } #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct StructureLogicDeviceConsumerTemplate { pub prefab: PrefabInfo, pub structure: StructureInfo, @@ -340,6 +408,8 @@ pub struct StructureLogicDeviceConsumerTemplate { } #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct StructureLogicDeviceMemoryTemplate { pub prefab: PrefabInfo, pub structure: StructureInfo, @@ -352,6 +422,8 @@ pub struct StructureLogicDeviceMemoryTemplate { } #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct StructureCircuitHolderTemplate { pub prefab: PrefabInfo, pub structure: StructureInfo, @@ -363,6 +435,8 @@ pub struct StructureCircuitHolderTemplate { } #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct StructureLogicDeviceConsumerMemoryTemplate { pub prefab: PrefabInfo, pub structure: StructureInfo, @@ -377,6 +451,8 @@ pub struct StructureLogicDeviceConsumerMemoryTemplate { } #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct ItemTemplate { pub prefab: PrefabInfo, pub item: ItemInfo, @@ -385,6 +461,8 @@ pub struct ItemTemplate { } #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct ItemSlotsTemplate { pub prefab: PrefabInfo, pub item: ItemInfo, @@ -394,6 +472,8 @@ pub struct ItemSlotsTemplate { } #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct ItemConsumerTemplate { pub prefab: PrefabInfo, pub item: ItemInfo, @@ -404,6 +484,8 @@ pub struct ItemConsumerTemplate { } #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct ItemLogicTemplate { pub prefab: PrefabInfo, pub item: ItemInfo, @@ -414,6 +496,8 @@ pub struct ItemLogicTemplate { } #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct ItemLogicMemoryTemplate { pub prefab: PrefabInfo, pub item: ItemInfo, @@ -425,6 +509,8 @@ pub struct ItemLogicMemoryTemplate { } #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct ItemCircuitHolderTemplate { pub prefab: PrefabInfo, pub item: ItemInfo, @@ -435,6 +521,8 @@ pub struct ItemCircuitHolderTemplate { } #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct ItemSuitTemplate { pub prefab: PrefabInfo, pub item: ItemInfo, @@ -445,6 +533,8 @@ pub struct ItemSuitTemplate { } #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct ItemSuitLogicTemplate { pub prefab: PrefabInfo, pub item: ItemInfo, @@ -456,6 +546,8 @@ pub struct ItemSuitLogicTemplate { } #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "tsify", derive(Tsify))] +#[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] pub struct ItemSuitCircuitHolderTemplate { pub prefab: PrefabInfo, pub item: ItemInfo, diff --git a/xtask/src/generate/database.rs b/xtask/src/generate/database.rs index ac03063..efc9a2c 100644 --- a/xtask/src/generate/database.rs +++ b/xtask/src/generate/database.rs @@ -14,17 +14,15 @@ use crate::{ stationpedia::{self, Memory, Page, Stationpedia}, }; -use stationeers_data::{ - templates::{ - ConnectionInfo, ConsumerInfo, DeviceInfo, FabricatorInfo, Instruction, InternalAtmoInfo, - ItemCircuitHolderTemplate, ItemConsumerTemplate, ItemInfo, ItemLogicMemoryTemplate, - ItemLogicTemplate, ItemSlotsTemplate, ItemSuitCircuitHolderTemplate, ItemSuitLogicTemplate, - ItemSuitTemplate, ItemTemplate, LogicInfo, MemoryInfo, ObjectTemplate, PrefabInfo, Recipe, - RecipeGasMix, RecipeRange, SlotInfo, StructureCircuitHolderTemplate, StructureInfo, - StructureLogicDeviceConsumerMemoryTemplate, StructureLogicDeviceConsumerTemplate, - StructureLogicDeviceMemoryTemplate, StructureLogicDeviceTemplate, StructureLogicTemplate, - StructureSlotsTemplate, StructureTemplate, SuitInfo, ThermalInfo, - }, +use stationeers_data::templates::{ + ConnectionInfo, ConsumerInfo, DeviceInfo, FabricatorInfo, Instruction, InternalAtmoInfo, + ItemCircuitHolderTemplate, ItemConsumerTemplate, ItemInfo, ItemLogicMemoryTemplate, + ItemLogicTemplate, ItemSlotsTemplate, ItemSuitCircuitHolderTemplate, ItemSuitLogicTemplate, + ItemSuitTemplate, ItemTemplate, LogicInfo, MemoryInfo, ObjectTemplate, PrefabInfo, Recipe, + RecipeGasMix, RecipeRange, SlotInfo, StructureCircuitHolderTemplate, StructureInfo, + StructureLogicDeviceConsumerMemoryTemplate, StructureLogicDeviceConsumerTemplate, + StructureLogicDeviceMemoryTemplate, StructureLogicDeviceTemplate, StructureLogicTemplate, + StructureSlotsTemplate, StructureTemplate, SuitInfo, ThermalInfo, }; #[allow(clippy::too_many_lines)] @@ -67,7 +65,8 @@ pub fn generate_database( | ItemLogicMemory(_) | ItemSuit(_) | ItemSuitLogic(_) - | ItemSuitCircuitHolder(_) => None, + | ItemSuitCircuitHolder(_) + | Human(_) => None, } }) .collect(); @@ -83,7 +82,8 @@ pub fn generate_database( | StructureCircuitHolder(_) | StructureLogicDeviceConsumer(_) | StructureLogicDeviceMemory(_) - | StructureLogicDeviceConsumerMemory(_) => None, + | StructureLogicDeviceConsumerMemory(_) + | Human(_) => None, Item(_) | ItemSlots(_) | ItemConsumer(_) @@ -112,7 +112,8 @@ pub fn generate_database( | Item(_) | ItemSlots(_) | ItemSuit(_) - | ItemConsumer(_) => None, + | ItemConsumer(_) + | Human(_) => None, ItemLogic(_) | ItemCircuitHolder(_) | ItemLogicMemory(_) @@ -138,7 +139,8 @@ pub fn generate_database( | ItemLogicMemory(_) | ItemSuit(_) | ItemSuitLogic(_) - | ItemSuitCircuitHolder(_) => None, + | ItemSuitCircuitHolder(_) + | Human(_) => None, StructureLogicDevice(_) | StructureCircuitHolder(_) | StructureLogicDeviceMemory(_) diff --git a/xtask/src/generate/enums.rs b/xtask/src/generate/enums.rs index 32a1d43..8dd44b2 100644 --- a/xtask/src/generate/enums.rs +++ b/xtask/src/generate/enums.rs @@ -27,15 +27,13 @@ pub fn generate( .map(|enm| enm.enum_name.clone()) .collect::>(); - let mut writer = - std::io::BufWriter::new(std::fs::File::create(enums_path.join("script.rs"))?); + let mut writer = std::io::BufWriter::new(std::fs::File::create(enums_path.join("script.rs"))?); write_repr_enum_use_header(&mut writer)?; for enm in enums.script_enums.values() { write_enum_listing(&mut writer, enm)?; } - let mut writer = - std::io::BufWriter::new(std::fs::File::create(enums_path.join("basic.rs"))?); + let mut writer = std::io::BufWriter::new(std::fs::File::create(enums_path.join("basic.rs"))?); write_repr_enum_use_header(&mut writer)?; let script_enums_in_basic = enums .script_enums @@ -327,6 +325,11 @@ fn write_repr_enum_use_header( use strum::{ AsRefStr, Display, EnumIter, EnumProperty, EnumString, FromRepr, }; + + #[cfg(feature = "tsify")] + use tsify::Tsify; + #[cfg(feature = "tsify")] + use wasm_bindgen::prelude::*; } )?; Ok(()) @@ -341,11 +344,7 @@ fn write_repr_basic_use_header( .map(|enm| Ident::new(&enm.enum_name.to_case(Case::Pascal), Span::call_site())) .collect::>(); - write!( - writer, - "{}", - quote! {use super::script::{ #(#enums),*};}, - )?; + write!(writer, "{}", quote! {use super::script::{ #(#enums),*};},)?; Ok(()) } @@ -434,6 +433,8 @@ where "{}", quote! { #[derive(#(#derives),*)] + #[cfg_attr(feature = "tsify", derive(Tsify))] + #[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] #additional_strum #[repr(#repr)] pub enum #name { diff --git a/xtask/src/generate/instructions.rs b/xtask/src/generate/instructions.rs index fea2579..4555a76 100644 --- a/xtask/src/generate/instructions.rs +++ b/xtask/src/generate/instructions.rs @@ -56,6 +56,11 @@ fn write_instructions_enum( Display, EnumIter, EnumProperty, EnumString, FromRepr, }; use crate::vm::object::traits::Programmable; + + #[cfg(feature = "tsify")] + use tsify::Tsify; + #[cfg(feature = "tsify")] + use wasm_bindgen::prelude::*; } )?; @@ -78,10 +83,12 @@ fn write_instructions_enum( writer, "{}", quote::quote! {#[derive(Debug, Display, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Serialize, Deserialize)] - #[derive(EnumIter, EnumString, EnumProperty, FromRepr)] - #[strum(use_phf, serialize_all = "lowercase")] - #[serde(rename_all = "lowercase")] - pub enum InstructionOp { + #[derive(EnumIter, EnumString, EnumProperty, FromRepr)] + #[cfg_attr(feature = "tsify", derive(Tsify))] + #[cfg_attr(feature = "tsify", tsify(into_wasm_abi, from_wasm_abi))] + #[strum(use_phf, serialize_all = "lowercase")] + #[serde(rename_all = "lowercase")] + pub enum InstructionOp { Nop, #(#inst_variants)* diff --git a/xtask/src/stationpedia.rs b/xtask/src/stationpedia.rs index ccbb353..ab3bb2d 100644 --- a/xtask/src/stationpedia.rs +++ b/xtask/src/stationpedia.rs @@ -4,7 +4,7 @@ use stationeers_data::enums::MachineTier; use std::collections::BTreeMap; #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[serde(rename = "Stationpedia", deny_unknown_fields)] +#[serde(rename = "Stationpedia")] pub struct Stationpedia { pub pages: Vec, pub reagents: BTreeMap,