refactor(vm): add proper reagent interface, trace VM, fix slot serialization
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
This commit is contained in:
@@ -26,11 +26,13 @@ strum_macros = "0.26.2"
|
||||
thiserror = "1.0.61"
|
||||
time = { version = "0.3.36", features = [
|
||||
"formatting",
|
||||
"parsing",
|
||||
"serde",
|
||||
"local-offset",
|
||||
] }
|
||||
tsify = { version = "0.4.5", optional = true, features = ["js"] }
|
||||
wasm-bindgen = { version = "0.2.92", optional = true }
|
||||
tracing = "0.1.40"
|
||||
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
getrandom = { version = "0.2", features = ["js"] }
|
||||
@@ -54,3 +56,7 @@ tsify = ["dep:tsify", "dep:wasm-bindgen", "stationeers_data/tsify"]
|
||||
prefab_database = [
|
||||
"stationeers_data/prefab_database",
|
||||
] # compile with the prefab database enabled
|
||||
|
||||
reagent_database = [
|
||||
"stationeers_data/reagent_database",
|
||||
] # compile with the prefab database enabled
|
||||
|
||||
@@ -35,7 +35,7 @@ pub enum VMError {
|
||||
IdInUse(u32),
|
||||
#[error("device(s) with ids {0:?} already exist")]
|
||||
IdsInUse(Vec<u32>),
|
||||
#[error("atempt to use a set of id's with duplicates: id(s) {0:?} exsist more than once")]
|
||||
#[error("attempt to use a set of id's with duplicates: id(s) {0:?} exist more than once")]
|
||||
DuplicateIds(Vec<u32>),
|
||||
#[error("object {0} is not a device")]
|
||||
NotADevice(ObjectID),
|
||||
@@ -64,7 +64,7 @@ pub enum VMError {
|
||||
#[error("object {0} is not logicable")]
|
||||
NotLogicable(ObjectID),
|
||||
#[error("network object {0} is not a network")]
|
||||
NonNetworkNetwork(ObjectID)
|
||||
NonNetworkNetwork(ObjectID),
|
||||
}
|
||||
|
||||
#[derive(Error, Debug, Serialize, Deserialize)]
|
||||
@@ -81,8 +81,7 @@ pub enum TemplateError {
|
||||
#[error("incorrect template for concrete impl {0} from prefab {1}: {2:?}")]
|
||||
IncorrectTemplate(String, Prefab, ObjectTemplate),
|
||||
#[error("frozen memory size error: {0} is not {1}")]
|
||||
MemorySize(usize, usize)
|
||||
|
||||
MemorySize(usize, usize),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
@@ -90,6 +89,7 @@ pub enum TemplateError {
|
||||
pub struct LineError {
|
||||
pub error: ICError,
|
||||
pub line: u32,
|
||||
pub msg: String,
|
||||
}
|
||||
|
||||
impl Display for LineError {
|
||||
@@ -154,6 +154,7 @@ impl ParseError {
|
||||
}
|
||||
|
||||
#[derive(Debug, Error, Clone, Serialize, Deserialize)]
|
||||
#[serde(tag = "typ")]
|
||||
#[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
|
||||
pub enum ICError {
|
||||
#[error("error compiling code: {0}")]
|
||||
@@ -162,8 +163,12 @@ pub enum ICError {
|
||||
LogicError(#[from] LogicError),
|
||||
#[error("{0}")]
|
||||
MemoryError(#[from] MemoryError),
|
||||
#[error("duplicate label {0}")]
|
||||
DuplicateLabel(String),
|
||||
#[error("duplicate label {label}: first encountered on line {source_line}")]
|
||||
DuplicateLabel {
|
||||
label: String,
|
||||
line: u32,
|
||||
source_line: u32,
|
||||
},
|
||||
#[error("instruction pointer out of range: '{0}'")]
|
||||
InstructionPointerOutOfRange(usize),
|
||||
#[error("register pointer out of range: '{0}'")]
|
||||
@@ -176,8 +181,8 @@ pub enum ICError {
|
||||
SlotIndexOutOfRange(f64),
|
||||
#[error("pin index {0} out of range 0-6")]
|
||||
PinIndexOutOfRange(usize),
|
||||
#[error("connection index {0} out of range {1}")]
|
||||
ConnectionIndexOutOfRange(usize, usize),
|
||||
#[error("connection index {index} out of range {range}")]
|
||||
ConnectionIndexOutOfRange { index: usize, range: usize },
|
||||
#[error("unknown device ID '{0}'")]
|
||||
UnknownDeviceID(f64),
|
||||
#[error("too few operands!: provide: '{provided}', desired: '{desired}'")]
|
||||
@@ -240,11 +245,16 @@ pub enum ICError {
|
||||
SlotNotOccupied,
|
||||
#[error("generated Enum {0} has no value attached. Report this error.")]
|
||||
NoGeneratedValue(String),
|
||||
#[error("generated Enum {0}'s value does not parse as {1} . Report this error.")]
|
||||
BadGeneratedValueParse(String, String),
|
||||
#[error("IC with id {0} is not sloted into a circuit holder")]
|
||||
#[error(
|
||||
"generated Enum {enum_name}'s value does not parse as {parse_type} . Report this error."
|
||||
)]
|
||||
BadGeneratedValueParse {
|
||||
enum_name: String,
|
||||
parse_type: String,
|
||||
},
|
||||
#[error("IC with id {0} is not slotted into a circuit holder")]
|
||||
NoCircuitHolder(ObjectID),
|
||||
#[error("IC with id {0} is sloted into a circuit holder with no logic interface?")]
|
||||
#[error("IC with id {0} is slotted into a circuit holder with no logic interface?")]
|
||||
CircuitHolderNotLogicable(ObjectID),
|
||||
#[error("object {0} is not slot writeable")]
|
||||
NotSlotWriteable(ObjectID),
|
||||
@@ -254,8 +264,12 @@ pub enum ICError {
|
||||
NotLogicable(ObjectID),
|
||||
#[error("{0} is not a valid number of sleep seconds")]
|
||||
SleepDurationError(f64),
|
||||
#[error("{0} can not be added to {1} ")]
|
||||
SleepAddtionError(time::Duration, #[cfg_attr(feature = "tsify", tsify(type = "Date"))] time::OffsetDateTime),
|
||||
#[error("{duration} can not be added to {time} ")]
|
||||
SleepAdditionError {
|
||||
duration: time::Duration,
|
||||
#[cfg_attr(feature = "tsify", tsify(type = "Date"))]
|
||||
time: time::OffsetDateTime,
|
||||
},
|
||||
}
|
||||
|
||||
impl ICError {
|
||||
|
||||
@@ -29,7 +29,9 @@ pub enum ICState {
|
||||
Running,
|
||||
Yield,
|
||||
Sleep(
|
||||
#[cfg_attr(feature = "tsify", tsify(type = "Date"))] time::OffsetDateTime,
|
||||
#[cfg_attr(feature = "tsify", tsify(type = "string"))]
|
||||
#[serde(with = "time::serde::rfc3339")]
|
||||
time::OffsetDateTime,
|
||||
f64,
|
||||
),
|
||||
Error(LineError),
|
||||
@@ -119,7 +121,13 @@ impl Program {
|
||||
Some(code) => match code {
|
||||
grammar::Code::Label(label) => {
|
||||
if labels_set.contains(&label.id.name) {
|
||||
Err(ICError::DuplicateLabel(label.id.name))
|
||||
let source_line =
|
||||
labels.get(&label.id.name).copied().unwrap_or_default();
|
||||
Err(ICError::DuplicateLabel {
|
||||
label: label.id.name,
|
||||
line: line_number as u32,
|
||||
source_line,
|
||||
})
|
||||
} else {
|
||||
labels_set.insert(label.id.name.clone());
|
||||
labels.insert(label.id.name, line_number as u32);
|
||||
@@ -157,7 +165,13 @@ impl Program {
|
||||
Some(code) => match code {
|
||||
grammar::Code::Label(label) => {
|
||||
if labels_set.contains(&label.id.name) {
|
||||
errors.push(ICError::DuplicateLabel(label.id.name));
|
||||
let source_line =
|
||||
labels.get(&label.id.name).copied().unwrap_or_default();
|
||||
errors.push(ICError::DuplicateLabel {
|
||||
label: label.id.name,
|
||||
line: line_number as u32,
|
||||
source_line,
|
||||
});
|
||||
} else {
|
||||
labels_set.insert(label.id.name.clone());
|
||||
labels.insert(label.id.name, line_number as u32);
|
||||
|
||||
@@ -2485,6 +2485,7 @@ impl<T: IC10Marker> LrInstruction for T {
|
||||
indirection,
|
||||
target,
|
||||
} = r.as_register(self)?;
|
||||
let vm = self.get_vm();
|
||||
let (device, connection) = d.as_device(self)?;
|
||||
let reagent_mode = reagent_mode.as_reagent_mode(self)?;
|
||||
let int = int.as_value(self)?;
|
||||
@@ -2526,7 +2527,7 @@ impl<T: IC10Marker> LrInstruction for T {
|
||||
}
|
||||
LogicReagentMode::Required => {
|
||||
let reagent_interface = logicable
|
||||
.as_reagent_interface()
|
||||
.as_reagent_requirer()
|
||||
.ok_or(ICError::NotReagentReadable(*logicable.get_id()))?;
|
||||
reagent_interface
|
||||
.get_current_required()
|
||||
@@ -2537,13 +2538,26 @@ impl<T: IC10Marker> LrInstruction for T {
|
||||
}
|
||||
LogicReagentMode::Recipe => {
|
||||
let reagent_interface = logicable
|
||||
.as_reagent_interface()
|
||||
.as_reagent_requirer()
|
||||
.ok_or(ICError::NotReagentReadable(*logicable.get_id()))?;
|
||||
reagent_interface
|
||||
.get_current_recipe()
|
||||
.iter()
|
||||
.find(|(hash, _)| *hash as f64 == int)
|
||||
.map(|(_, quantity)| *quantity)
|
||||
.and_then(|recipe_order| {
|
||||
recipe_order
|
||||
.recipe
|
||||
.reagents
|
||||
.iter()
|
||||
.map(|(name, quantity)| {
|
||||
(
|
||||
vm.lookup_reagent_by_name(name)
|
||||
.map(|reagent| reagent.hash)
|
||||
.unwrap_or(0),
|
||||
quantity,
|
||||
)
|
||||
})
|
||||
.find(|(hash, _)| *hash as f64 == int)
|
||||
.map(|(_, quantity)| *quantity)
|
||||
})
|
||||
.unwrap_or(0.0)
|
||||
}
|
||||
};
|
||||
@@ -2709,6 +2723,34 @@ impl<T: IC10Marker> RmapInstruction for T {
|
||||
d: &crate::vm::instructions::operands::InstOperand,
|
||||
reagent_hash: &crate::vm::instructions::operands::InstOperand,
|
||||
) -> Result<(), crate::errors::ICError> {
|
||||
todo!()
|
||||
let RegisterSpec {
|
||||
indirection,
|
||||
target,
|
||||
} = r.as_register(self)?;
|
||||
let (device, connection) = d.as_device(self)?;
|
||||
|
||||
let reagent_hash = reagent_hash.as_value_i32(self, true)?;
|
||||
let val = self
|
||||
.get_circuit_holder()
|
||||
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
|
||||
.borrow()
|
||||
.as_circuit_holder()
|
||||
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
|
||||
.get_logicable_from_index(device, connection)
|
||||
.ok_or(ICError::DeviceNotSet)
|
||||
.and_then(|obj| {
|
||||
obj.map(|obj_ref| {
|
||||
obj_ref
|
||||
.as_reagent_requirer()
|
||||
.ok_or(ICError::NotReagentReadable(*obj_ref.get_id()))
|
||||
.map(|reagent_interface| {
|
||||
reagent_interface
|
||||
.get_prefab_hash_from_reagent_hash(reagent_hash)
|
||||
.unwrap_or(0)
|
||||
})
|
||||
})
|
||||
})?;
|
||||
self.set_register(indirection, target, val as f64)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ pub enum CableConnectionType {
|
||||
PowerAndData,
|
||||
}
|
||||
|
||||
#[serde_with::skip_serializing_none]
|
||||
#[derive(Debug, Default, Clone, Copy, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
|
||||
pub enum Connection {
|
||||
@@ -146,7 +147,7 @@ impl Connection {
|
||||
},
|
||||
Self::RoboticArmRail { role } => ConnectionInfo {
|
||||
typ: ConnectionType::RoboticArmRail,
|
||||
role: *role
|
||||
role: *role,
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -181,6 +182,9 @@ pub struct CableNetwork {
|
||||
}
|
||||
|
||||
impl Storage for CableNetwork {
|
||||
fn debug_storage(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, "UNIMPLEMENTED") //TODO: Implement
|
||||
}
|
||||
fn slots_count(&self) -> usize {
|
||||
0
|
||||
}
|
||||
@@ -190,15 +194,18 @@ impl Storage for CableNetwork {
|
||||
fn get_slot_mut(&mut self, _index: usize) -> Option<&mut crate::vm::object::Slot> {
|
||||
None
|
||||
}
|
||||
fn get_slots(&self) -> Vec<&crate::vm::object::Slot> {
|
||||
fn get_slots(&self) -> Vec<(usize, &crate::vm::object::Slot)> {
|
||||
vec![]
|
||||
}
|
||||
fn get_slots_mut(&mut self) -> Vec<&mut crate::vm::object::Slot> {
|
||||
fn get_slots_mut(&mut self) -> Vec<(usize, &mut crate::vm::object::Slot)> {
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
|
||||
impl Logicable for CableNetwork {
|
||||
fn debug_logicable(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, "UNIMPLEMENTED") //TODO: Implement
|
||||
}
|
||||
fn prefab_hash(&self) -> i32 {
|
||||
0
|
||||
}
|
||||
@@ -282,6 +289,9 @@ impl Logicable for CableNetwork {
|
||||
}
|
||||
|
||||
impl Network for CableNetwork {
|
||||
fn debug_network(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, "UNIMPLEMENTED") //TODO: Implement
|
||||
}
|
||||
fn contains(&self, id: &ObjectID) -> bool {
|
||||
self.devices.contains(id) || self.power_only.contains(id)
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ use stationeers_data::{
|
||||
script::{LogicBatchMethod, LogicSlotType, LogicType},
|
||||
ConnectionRole,
|
||||
},
|
||||
templates::ObjectTemplate,
|
||||
templates::{ObjectTemplate, Reagent},
|
||||
};
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
@@ -47,6 +47,7 @@ pub struct VM {
|
||||
/// list of object id's touched on the last operation
|
||||
operation_modified: RefCell<Vec<ObjectID>>,
|
||||
template_database: RefCell<Option<BTreeMap<i32, ObjectTemplate>>>,
|
||||
reagent_database: RefCell<Option<BTreeMap<u8, Reagent>>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
@@ -93,6 +94,7 @@ impl VM {
|
||||
random: Rc::new(RefCell::new(crate::rand_mscorlib::Random::new())),
|
||||
operation_modified: RefCell::new(Vec::new()),
|
||||
template_database: RefCell::new(stationeers_data::build_prefab_database()),
|
||||
reagent_database: RefCell::new(stationeers_data::build_reagent_database()),
|
||||
});
|
||||
|
||||
let default_network = VMObject::new(CableNetwork::new(default_network_key, vm.clone()));
|
||||
@@ -109,7 +111,7 @@ impl VM {
|
||||
self.random.borrow_mut().next_f64()
|
||||
}
|
||||
|
||||
/// Take ownership of an iterable the produces (prefab hash, ObjectTemplate) pairs and build a prefab
|
||||
/// Take ownership of an iterable that produces (prefab hash, ObjectTemplate) pairs and build a prefab
|
||||
/// database
|
||||
pub fn import_template_database(
|
||||
self: &Rc<Self>,
|
||||
@@ -120,6 +122,53 @@ impl VM {
|
||||
.replace(db.into_iter().collect());
|
||||
}
|
||||
|
||||
pub fn import_reagent_database(self: &Rc<Self>, db: impl IntoIterator<Item = (u8, Reagent)>) {
|
||||
self.reagent_database
|
||||
.borrow_mut()
|
||||
.replace(db.into_iter().collect());
|
||||
}
|
||||
|
||||
pub fn lookup_reagent_by_hash(self: &Rc<Self>, hash: i32) -> Option<Reagent> {
|
||||
self.reagent_database.borrow().as_ref().and_then(|db| {
|
||||
db.iter().find_map(|(_id, reagent)| {
|
||||
if reagent.hash == hash {
|
||||
Some(reagent.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub fn lookup_reagent_by_name(self: &Rc<Self>, name: impl AsRef<str>) -> Option<Reagent> {
|
||||
let name = name.as_ref();
|
||||
self.reagent_database.borrow().as_ref().and_then(|db| {
|
||||
db.iter().find_map(|(_id, reagent)| {
|
||||
if reagent.name.as_str() == name {
|
||||
Some(reagent.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub fn lookup_template_by_name(
|
||||
self: &Rc<Self>,
|
||||
name: impl AsRef<str>,
|
||||
) -> Option<ObjectTemplate> {
|
||||
let name = name.as_ref();
|
||||
self.template_database.borrow().as_ref().and_then(|db| {
|
||||
db.iter().find_map(|(_hash, template)| {
|
||||
if &template.prefab().prefab_name == name {
|
||||
Some(template.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/// Get a Object Template by either prefab name or hash
|
||||
pub fn get_template(self: &Rc<Self>, prefab: Prefab) -> Option<ObjectTemplate> {
|
||||
let hash = match prefab {
|
||||
@@ -140,7 +189,7 @@ impl VM {
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
/// Add an number of object to the VM state using Frozen Object strusts.
|
||||
/// Add an number of object to the VM state using Frozen Object structs.
|
||||
/// See also `add_objects_frozen`
|
||||
/// Returns the built objects' IDs
|
||||
pub fn add_objects_frozen(
|
||||
@@ -293,17 +342,20 @@ impl VM {
|
||||
for obj in self.objects.borrow().values() {
|
||||
let mut obj_ref = obj.borrow_mut();
|
||||
if let Some(device) = obj_ref.as_mut_device() {
|
||||
device.get_slots_mut().iter_mut().for_each(|slot| {
|
||||
if slot.parent == old_id {
|
||||
slot.parent = new_id;
|
||||
}
|
||||
match slot.occupant.as_mut() {
|
||||
Some(info) if info.id == old_id => {
|
||||
info.id = new_id;
|
||||
device
|
||||
.get_slots_mut()
|
||||
.iter_mut()
|
||||
.for_each(|(_index, slot)| {
|
||||
if slot.parent == old_id {
|
||||
slot.parent = new_id;
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
});
|
||||
match slot.occupant.as_mut() {
|
||||
Some(info) if info.id == old_id => {
|
||||
info.id = new_id;
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -727,6 +779,7 @@ impl VM {
|
||||
self.operation_modified.borrow_mut().push(id);
|
||||
}
|
||||
|
||||
#[tracing::instrument]
|
||||
pub fn reset_programmable(self: &Rc<Self>, id: ObjectID) -> Result<bool, VMError> {
|
||||
let obj = self
|
||||
.objects
|
||||
@@ -734,12 +787,33 @@ impl VM {
|
||||
.get(&id)
|
||||
.cloned()
|
||||
.ok_or(VMError::UnknownId(id))?;
|
||||
let mut obj_ref = obj.borrow_mut();
|
||||
let programmable = obj_ref
|
||||
.as_mut_programmable()
|
||||
.ok_or(VMError::NotProgrammable(id))?;
|
||||
programmable.reset();
|
||||
Ok(true)
|
||||
{
|
||||
let mut obj_ref = obj.borrow_mut();
|
||||
if let Some(programmable) = obj_ref.as_mut_programmable() {
|
||||
tracing::debug!(id, "resetting");
|
||||
programmable.reset();
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
let ic_obj = {
|
||||
let obj_ref = obj.borrow();
|
||||
if let Some(circuit_holder) = obj_ref.as_circuit_holder() {
|
||||
circuit_holder.get_ic()
|
||||
} else {
|
||||
return Err(VMError::NotCircuitHolderOrProgrammable(id));
|
||||
}
|
||||
};
|
||||
if let Some(ic_obj) = ic_obj {
|
||||
let mut ic_obj_ref = ic_obj.borrow_mut();
|
||||
let ic_id = *ic_obj_ref.get_id();
|
||||
if let Some(programmable) = ic_obj_ref.as_mut_programmable() {
|
||||
tracing::debug!(id = ic_id, "resetting");
|
||||
programmable.reset();
|
||||
return Ok(true);
|
||||
}
|
||||
return Err(VMError::NotProgrammable(ic_id));
|
||||
}
|
||||
Err(VMError::NoIC(id))
|
||||
}
|
||||
|
||||
pub fn get_object(self: &Rc<Self>, id: ObjectID) -> Option<VMObject> {
|
||||
@@ -918,7 +992,11 @@ impl VM {
|
||||
let connections = device.connection_list_mut();
|
||||
if connection >= connections.len() {
|
||||
let conn_len = connections.len();
|
||||
return Err(ICError::ConnectionIndexOutOfRange(connection, conn_len).into());
|
||||
return Err(ICError::ConnectionIndexOutOfRange {
|
||||
index: connection,
|
||||
range: conn_len,
|
||||
}
|
||||
.into());
|
||||
}
|
||||
|
||||
// scope this borrow
|
||||
@@ -1570,7 +1648,7 @@ impl LogicBatchMethodWrapper {
|
||||
pub fn apply(&self, samples: &[f64]) -> f64 {
|
||||
match self.0 {
|
||||
LogicBatchMethod::Sum => samples.iter().sum(),
|
||||
// Both c-charp and rust return NaN for 0.0/0.0 so we're good here
|
||||
// Both c-sharp and rust return NaN for 0.0/0.0 so we're good here
|
||||
LogicBatchMethod::Average => {
|
||||
samples.iter().copied().sum::<f64>() / samples.len() as f64
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ pub struct RegisterSpec {
|
||||
pub target: u32,
|
||||
}
|
||||
|
||||
#[serde_with::skip_serializing_none]
|
||||
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
|
||||
pub struct DeviceSpec {
|
||||
@@ -50,6 +51,7 @@ pub enum Number {
|
||||
Enum(f64),
|
||||
}
|
||||
|
||||
#[serde_with::skip_serializing_none]
|
||||
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
|
||||
pub enum Operand {
|
||||
@@ -133,32 +135,36 @@ impl InstOperand {
|
||||
.get_str("value")
|
||||
.ok_or_else(|| ICError::NoGeneratedValue(lt.to_string()))?
|
||||
.parse::<u16>()
|
||||
.map_err(|_| {
|
||||
ICError::BadGeneratedValueParse(lt.to_string(), "u16".to_owned())
|
||||
.map_err(|_| ICError::BadGeneratedValueParse {
|
||||
enum_name: lt.to_string(),
|
||||
parse_type: "u16".to_owned(),
|
||||
})? as f64)
|
||||
} else if let Some(slt) = slot_logic_type {
|
||||
Ok(slt
|
||||
.get_str("value")
|
||||
.ok_or_else(|| ICError::NoGeneratedValue(slt.to_string()))?
|
||||
.parse::<u8>()
|
||||
.map_err(|_| {
|
||||
ICError::BadGeneratedValueParse(slt.to_string(), "u8".to_owned())
|
||||
.map_err(|_| ICError::BadGeneratedValueParse {
|
||||
enum_name: slt.to_string(),
|
||||
parse_type: "u8".to_owned(),
|
||||
})? as f64)
|
||||
} else if let Some(bm) = batch_mode {
|
||||
Ok(bm
|
||||
.get_str("value")
|
||||
.ok_or_else(|| ICError::NoGeneratedValue(bm.to_string()))?
|
||||
.parse::<u8>()
|
||||
.map_err(|_| {
|
||||
ICError::BadGeneratedValueParse(bm.to_string(), "u8".to_owned())
|
||||
.map_err(|_| ICError::BadGeneratedValueParse {
|
||||
enum_name: bm.to_string(),
|
||||
parse_type: "u8".to_owned(),
|
||||
})? as f64)
|
||||
} else if let Some(rm) = reagent_mode {
|
||||
Ok(rm
|
||||
.get_str("value")
|
||||
.ok_or_else(|| ICError::NoGeneratedValue(rm.to_string()))?
|
||||
.parse::<u8>()
|
||||
.map_err(|_| {
|
||||
ICError::BadGeneratedValueParse(rm.to_string(), "u8".to_owned())
|
||||
.map_err(|_| ICError::BadGeneratedValueParse {
|
||||
enum_name: rm.to_string(),
|
||||
parse_type: "u8".to_owned(),
|
||||
})? as f64)
|
||||
} else {
|
||||
Err(ICError::TypeValueNotKnown)
|
||||
|
||||
@@ -122,27 +122,30 @@ pub struct SlotOccupantInfo {
|
||||
pub id: ObjectID,
|
||||
}
|
||||
|
||||
#[serde_with::skip_serializing_none]
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
|
||||
pub struct Slot {
|
||||
pub parent: ObjectID,
|
||||
pub index: usize,
|
||||
pub name: String,
|
||||
pub typ: Class,
|
||||
pub class: Class,
|
||||
pub readable_logic: Vec<LogicSlotType>,
|
||||
pub writeable_logic: Vec<LogicSlotType>,
|
||||
pub occupant: Option<SlotOccupantInfo>,
|
||||
pub proxy: bool,
|
||||
}
|
||||
|
||||
impl Slot {
|
||||
#[must_use]
|
||||
pub fn new(parent: ObjectID, index: usize, name: String, typ: Class) -> Self {
|
||||
pub fn new(parent: ObjectID, index: usize, name: String, class: Class) -> Self {
|
||||
Slot {
|
||||
parent,
|
||||
index,
|
||||
name,
|
||||
typ,
|
||||
readable_logic: vec![
|
||||
class,
|
||||
readable_logic:
|
||||
vec![
|
||||
LogicSlotType::Class,
|
||||
LogicSlotType::Damage,
|
||||
LogicSlotType::MaxQuantity,
|
||||
@@ -155,6 +158,7 @@ impl Slot {
|
||||
],
|
||||
writeable_logic: vec![],
|
||||
occupant: None,
|
||||
proxy: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ macro_rules! GWThermal {
|
||||
fn thermal_info(&self) -> &ThermalInfo {
|
||||
self.thermal_info
|
||||
.as_ref()
|
||||
.expect("GWTherml::thermal_info called on non thermal")
|
||||
.expect("GWThermal::thermal_info called on non thermal")
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -64,10 +64,10 @@ macro_rules! GWStorage {
|
||||
}
|
||||
) => {
|
||||
impl GWStorage for $struct {
|
||||
fn slots(&self) -> &Vec<Slot> {
|
||||
fn slots(&self) -> &BTreeMap<u32, Slot> {
|
||||
&self.slots
|
||||
}
|
||||
fn slots_mut(&mut self) -> &mut Vec<Slot> {
|
||||
fn slots_mut(&mut self) -> &mut BTreeMap<u32, Slot> {
|
||||
&mut self.slots
|
||||
}
|
||||
}
|
||||
@@ -156,10 +156,10 @@ macro_rules! GWDevice {
|
||||
fn pins_mut(&mut self) -> Option<&mut [Option<ObjectID>]> {
|
||||
self.pins.as_mut().map(|pins| pins.as_mut_slice())
|
||||
}
|
||||
fn reagents(&self) -> Option<&BTreeMap<i32, f64>> {
|
||||
fn reagents(&self) -> Option<&BTreeMap<u8, f64>> {
|
||||
self.reagents.as_ref()
|
||||
}
|
||||
fn reagents_mut(&mut self) -> &mut Option<BTreeMap<i32, f64>> {
|
||||
fn reagents_mut(&mut self) -> &mut Option<BTreeMap<u8, f64>> {
|
||||
&mut self.reagents
|
||||
}
|
||||
}
|
||||
@@ -228,11 +228,9 @@ macro_rules! GWCircuitHolderItem {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
pub(crate) use GWCircuitHolderItem;
|
||||
|
||||
|
||||
macro_rules! GWCircuitHolderSuit {
|
||||
(
|
||||
$( #[$attr:meta] )*
|
||||
@@ -250,11 +248,9 @@ macro_rules! GWCircuitHolderSuit {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
pub(crate) use GWCircuitHolderSuit;
|
||||
|
||||
|
||||
macro_rules! GWCircuitHolderDevice {
|
||||
(
|
||||
$( #[$attr:meta] )*
|
||||
@@ -272,6 +268,61 @@ macro_rules! GWCircuitHolderDevice {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
pub(crate) use GWCircuitHolderDevice;
|
||||
|
||||
macro_rules! GWReagentConsumer {
|
||||
(
|
||||
$( #[$attr:meta] )*
|
||||
$viz:vis struct $struct:ident {
|
||||
$($body:tt)*
|
||||
}
|
||||
) => {
|
||||
impl GWReagentConsumer for $struct {
|
||||
fn consumer_info(&self) -> &ConsumerInfo {
|
||||
&self.consumer_info
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
pub(crate) use GWReagentConsumer;
|
||||
|
||||
macro_rules! GWReagentRequirer {
|
||||
(
|
||||
$( #[$attr:meta] )*
|
||||
$viz:vis struct $struct:ident {
|
||||
$($body:tt)*
|
||||
}
|
||||
) => {
|
||||
impl GWReagentRequirer for $struct {
|
||||
fn get_current_recipe_gw(&self) -> Option<(u32, u32)> {
|
||||
self.current_recipe
|
||||
}
|
||||
fn get_fab_info_gw(&self) -> Option<&FabricatorInfo> {
|
||||
self.fabricator_info.as_ref()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
pub(crate) use GWReagentRequirer;
|
||||
|
||||
macro_rules! GWFabricator {
|
||||
(
|
||||
$( #[$attr:meta] )*
|
||||
$viz:vis struct $struct:ident {
|
||||
$($body:tt)*
|
||||
}
|
||||
) => {
|
||||
impl GWFabricator for $struct {
|
||||
fn is_fabricator(&self) -> bool {
|
||||
self.fabricator_info.is_some()
|
||||
}
|
||||
fn fabricator_info(&self) -> &FabricatorInfo {
|
||||
self.fabricator_info
|
||||
.as_ref()
|
||||
.expect("GWFabricator::fabricator_info call on non Fabricator")
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
pub(crate) use GWFabricator;
|
||||
|
||||
@@ -54,7 +54,7 @@ pub struct GenericStorage {
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub small_grid: bool,
|
||||
pub slots: Vec<Slot>,
|
||||
pub slots: BTreeMap<u32, Slot>,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
@@ -79,7 +79,7 @@ pub struct GenericLogicable {
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub small_grid: bool,
|
||||
pub slots: Vec<Slot>,
|
||||
pub slots: BTreeMap<u32, Slot>,
|
||||
pub fields: BTreeMap<LogicType, LogicField>,
|
||||
pub modes: Option<BTreeMap<u32, String>>,
|
||||
}
|
||||
@@ -107,13 +107,13 @@ pub struct GenericLogicableDevice {
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub small_grid: bool,
|
||||
pub slots: Vec<Slot>,
|
||||
pub slots: BTreeMap<u32, Slot>,
|
||||
pub fields: BTreeMap<LogicType, LogicField>,
|
||||
pub modes: Option<BTreeMap<u32, String>>,
|
||||
pub device_info: DeviceInfo,
|
||||
pub connections: Vec<Connection>,
|
||||
pub pins: Option<Vec<Option<ObjectID>>>,
|
||||
pub reagents: Option<BTreeMap<i32, f64>>,
|
||||
pub reagents: Option<BTreeMap<u8, f64>>,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
@@ -140,13 +140,13 @@ pub struct GenericCircuitHolder {
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub small_grid: bool,
|
||||
pub slots: Vec<Slot>,
|
||||
pub slots: BTreeMap<u32, Slot>,
|
||||
pub fields: BTreeMap<LogicType, LogicField>,
|
||||
pub modes: Option<BTreeMap<u32, String>>,
|
||||
pub device_info: DeviceInfo,
|
||||
pub connections: Vec<Connection>,
|
||||
pub pins: Option<Vec<Option<ObjectID>>>,
|
||||
pub reagents: Option<BTreeMap<i32, f64>>,
|
||||
pub reagents: Option<BTreeMap<u8, f64>>,
|
||||
pub error: i32,
|
||||
}
|
||||
|
||||
@@ -154,12 +154,12 @@ pub struct GenericCircuitHolder {
|
||||
ObjectInterface!,
|
||||
GWThermal!, GWInternalAtmo!,
|
||||
GWStructure!, GWStorage!, GWLogicable!,
|
||||
GWDevice!
|
||||
GWDevice!, GWReagentConsumer!,
|
||||
)]
|
||||
#[custom(implements(Object {
|
||||
Thermal[GWThermal::is_thermal],
|
||||
InternalAtmosphere[GWInternalAtmo::is_internal_atmo],
|
||||
Structure, Storage, Logicable, Device
|
||||
Structure, Storage, Logicable, Device, ReagentConsumer
|
||||
}))]
|
||||
pub struct GenericLogicableDeviceConsumer {
|
||||
#[custom(object_id)]
|
||||
@@ -173,13 +173,13 @@ pub struct GenericLogicableDeviceConsumer {
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub small_grid: bool,
|
||||
pub slots: Vec<Slot>,
|
||||
pub slots: BTreeMap<u32, Slot>,
|
||||
pub fields: BTreeMap<LogicType, LogicField>,
|
||||
pub modes: Option<BTreeMap<u32, String>>,
|
||||
pub device_info: DeviceInfo,
|
||||
pub connections: Vec<Connection>,
|
||||
pub pins: Option<Vec<Option<ObjectID>>>,
|
||||
pub reagents: Option<BTreeMap<i32, f64>>,
|
||||
pub reagents: Option<BTreeMap<u8, f64>>,
|
||||
pub consumer_info: ConsumerInfo,
|
||||
}
|
||||
|
||||
@@ -207,13 +207,13 @@ pub struct GenericLogicableDeviceMemoryReadable {
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub small_grid: bool,
|
||||
pub slots: Vec<Slot>,
|
||||
pub slots: BTreeMap<u32, Slot>,
|
||||
pub fields: BTreeMap<LogicType, LogicField>,
|
||||
pub modes: Option<BTreeMap<u32, String>>,
|
||||
pub device_info: DeviceInfo,
|
||||
pub connections: Vec<Connection>,
|
||||
pub pins: Option<Vec<Option<ObjectID>>>,
|
||||
pub reagents: Option<BTreeMap<i32, f64>>,
|
||||
pub reagents: Option<BTreeMap<u8, f64>>,
|
||||
pub memory: Vec<f64>,
|
||||
}
|
||||
|
||||
@@ -221,12 +221,15 @@ pub struct GenericLogicableDeviceMemoryReadable {
|
||||
ObjectInterface!,
|
||||
GWThermal!, GWInternalAtmo!,
|
||||
GWStructure!, GWStorage!, GWLogicable!,
|
||||
GWDevice!, GWMemoryReadable!, GWMemoryWritable!
|
||||
GWDevice!, GWMemoryReadable!, GWMemoryWritable!,
|
||||
GWReagentConsumer!, GWReagentRequirer!, GWFabricator!,
|
||||
)]
|
||||
#[custom(implements(Object {
|
||||
Thermal[GWThermal::is_thermal],
|
||||
InternalAtmosphere[GWInternalAtmo::is_internal_atmo],
|
||||
Structure, Storage, Logicable, Device, MemoryReadable
|
||||
Structure, Storage, Logicable, Device, MemoryReadable,
|
||||
ReagentConsumer, ReagentRequirer,
|
||||
Fabricator[GWFabricator::is_fabricator]
|
||||
}))]
|
||||
pub struct GenericLogicableDeviceConsumerMemoryReadable {
|
||||
#[custom(object_id)]
|
||||
@@ -240,15 +243,17 @@ pub struct GenericLogicableDeviceConsumerMemoryReadable {
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub small_grid: bool,
|
||||
pub slots: Vec<Slot>,
|
||||
pub slots: BTreeMap<u32, Slot>,
|
||||
pub fields: BTreeMap<LogicType, LogicField>,
|
||||
pub modes: Option<BTreeMap<u32, String>>,
|
||||
pub device_info: DeviceInfo,
|
||||
pub connections: Vec<Connection>,
|
||||
pub pins: Option<Vec<Option<ObjectID>>>,
|
||||
pub reagents: Option<BTreeMap<i32, f64>>,
|
||||
pub reagents: Option<BTreeMap<u8, f64>>,
|
||||
pub consumer_info: ConsumerInfo,
|
||||
pub fabricator_info: Option<FabricatorInfo>,
|
||||
/// (fabricator_info.recipes index, quantity)
|
||||
pub current_recipe: Option<(u32, u32)>,
|
||||
pub memory: Vec<f64>,
|
||||
}
|
||||
|
||||
@@ -275,13 +280,13 @@ pub struct GenericLogicableDeviceMemoryReadWriteable {
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub small_grid: bool,
|
||||
pub slots: Vec<Slot>,
|
||||
pub slots: BTreeMap<u32, Slot>,
|
||||
pub fields: BTreeMap<LogicType, LogicField>,
|
||||
pub modes: Option<BTreeMap<u32, String>>,
|
||||
pub device_info: DeviceInfo,
|
||||
pub connections: Vec<Connection>,
|
||||
pub pins: Option<Vec<Option<ObjectID>>>,
|
||||
pub reagents: Option<BTreeMap<i32, f64>>,
|
||||
pub reagents: Option<BTreeMap<u8, f64>>,
|
||||
pub memory: Vec<f64>,
|
||||
}
|
||||
|
||||
@@ -289,12 +294,15 @@ pub struct GenericLogicableDeviceMemoryReadWriteable {
|
||||
ObjectInterface!,
|
||||
GWThermal!, GWInternalAtmo!,
|
||||
GWStructure!, GWStorage!, GWLogicable!,
|
||||
GWDevice!, GWMemoryReadable!, GWMemoryWritable!
|
||||
GWDevice!, GWMemoryReadable!, GWMemoryWritable!,
|
||||
GWReagentConsumer!, GWReagentRequirer!, GWFabricator!,
|
||||
)]
|
||||
#[custom(implements(Object {
|
||||
Thermal[GWThermal::is_thermal],
|
||||
InternalAtmosphere[GWInternalAtmo::is_internal_atmo],
|
||||
Structure, Storage, Logicable, Device, MemoryReadable, MemoryWritable
|
||||
Structure, Storage, Logicable, Device, MemoryReadable, MemoryWritable,
|
||||
ReagentConsumer, ReagentRequirer,
|
||||
Fabricator[GWFabricator::is_fabricator]
|
||||
}))]
|
||||
pub struct GenericLogicableDeviceConsumerMemoryReadWriteable {
|
||||
#[custom(object_id)]
|
||||
@@ -308,15 +316,17 @@ pub struct GenericLogicableDeviceConsumerMemoryReadWriteable {
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub small_grid: bool,
|
||||
pub slots: Vec<Slot>,
|
||||
pub slots: BTreeMap<u32, Slot>,
|
||||
pub fields: BTreeMap<LogicType, LogicField>,
|
||||
pub modes: Option<BTreeMap<u32, String>>,
|
||||
pub device_info: DeviceInfo,
|
||||
pub connections: Vec<Connection>,
|
||||
pub pins: Option<Vec<Option<ObjectID>>>,
|
||||
pub reagents: Option<BTreeMap<i32, f64>>,
|
||||
pub reagents: Option<BTreeMap<u8, f64>>,
|
||||
pub consumer_info: ConsumerInfo,
|
||||
pub fabricator_info: Option<FabricatorInfo>,
|
||||
// index of target recipe in fabricator_info
|
||||
pub current_recipe: Option<(u32, u32)>,
|
||||
pub memory: Vec<f64>,
|
||||
}
|
||||
|
||||
@@ -362,14 +372,18 @@ pub struct GenericItemStorage {
|
||||
pub item_info: ItemInfo,
|
||||
pub parent_slot: Option<ParentSlotInfo>,
|
||||
pub damage: Option<f32>,
|
||||
pub slots: Vec<Slot>,
|
||||
pub slots: BTreeMap<u32, Slot>,
|
||||
}
|
||||
|
||||
#[derive(ObjectInterface!, GWThermal!, GWInternalAtmo!, GWItem!, GWStorage! )]
|
||||
#[derive(
|
||||
ObjectInterface!, GWThermal!,
|
||||
GWInternalAtmo!, GWItem!, GWStorage!,
|
||||
GWReagentConsumer!
|
||||
)]
|
||||
#[custom(implements(Object {
|
||||
Thermal[GWThermal::is_thermal],
|
||||
InternalAtmosphere[GWInternalAtmo::is_internal_atmo],
|
||||
Item, Storage
|
||||
Item, Storage, ReagentConsumer
|
||||
}))]
|
||||
pub struct GenericItemConsumer {
|
||||
#[custom(object_id)]
|
||||
@@ -385,7 +399,7 @@ pub struct GenericItemConsumer {
|
||||
pub item_info: ItemInfo,
|
||||
pub parent_slot: Option<ParentSlotInfo>,
|
||||
pub damage: Option<f32>,
|
||||
pub slots: Vec<Slot>,
|
||||
pub slots: BTreeMap<u32, Slot>,
|
||||
pub consumer_info: ConsumerInfo,
|
||||
}
|
||||
|
||||
@@ -413,7 +427,7 @@ pub struct GenericItemLogicable {
|
||||
pub item_info: ItemInfo,
|
||||
pub parent_slot: Option<ParentSlotInfo>,
|
||||
pub damage: Option<f32>,
|
||||
pub slots: Vec<Slot>,
|
||||
pub slots: BTreeMap<u32, Slot>,
|
||||
pub fields: BTreeMap<LogicType, LogicField>,
|
||||
pub modes: Option<BTreeMap<u32, String>>,
|
||||
}
|
||||
@@ -443,7 +457,7 @@ pub struct GenericItemLogicableMemoryReadable {
|
||||
pub item_info: ItemInfo,
|
||||
pub parent_slot: Option<ParentSlotInfo>,
|
||||
pub damage: Option<f32>,
|
||||
pub slots: Vec<Slot>,
|
||||
pub slots: BTreeMap<u32, Slot>,
|
||||
pub fields: BTreeMap<LogicType, LogicField>,
|
||||
pub modes: Option<BTreeMap<u32, String>>,
|
||||
pub memory: Vec<f64>,
|
||||
@@ -474,7 +488,7 @@ pub struct GenericItemLogicableMemoryReadWriteable {
|
||||
pub item_info: ItemInfo,
|
||||
pub parent_slot: Option<ParentSlotInfo>,
|
||||
pub damage: Option<f32>,
|
||||
pub slots: Vec<Slot>,
|
||||
pub slots: BTreeMap<u32, Slot>,
|
||||
pub fields: BTreeMap<LogicType, LogicField>,
|
||||
pub modes: Option<BTreeMap<u32, String>>,
|
||||
pub memory: Vec<f64>,
|
||||
@@ -506,7 +520,7 @@ pub struct GenericItemCircuitHolder {
|
||||
pub item_info: ItemInfo,
|
||||
pub parent_slot: Option<ParentSlotInfo>,
|
||||
pub damage: Option<f32>,
|
||||
pub slots: Vec<Slot>,
|
||||
pub slots: BTreeMap<u32, Slot>,
|
||||
pub fields: BTreeMap<LogicType, LogicField>,
|
||||
pub modes: Option<BTreeMap<u32, String>>,
|
||||
pub error: i32,
|
||||
@@ -537,7 +551,7 @@ pub struct GenericItemSuitLogic {
|
||||
pub item_info: ItemInfo,
|
||||
pub parent_slot: Option<ParentSlotInfo>,
|
||||
pub damage: Option<f32>,
|
||||
pub slots: Vec<Slot>,
|
||||
pub slots: BTreeMap<u32, Slot>,
|
||||
pub suit_info: SuitInfo,
|
||||
pub fields: BTreeMap<LogicType, LogicField>,
|
||||
pub modes: Option<BTreeMap<u32, String>>,
|
||||
@@ -570,7 +584,7 @@ pub struct GenericItemSuitCircuitHolder {
|
||||
pub item_info: ItemInfo,
|
||||
pub parent_slot: Option<ParentSlotInfo>,
|
||||
pub damage: Option<f32>,
|
||||
pub slots: Vec<Slot>,
|
||||
pub slots: BTreeMap<u32, Slot>,
|
||||
pub suit_info: SuitInfo,
|
||||
pub fields: BTreeMap<LogicType, LogicField>,
|
||||
pub modes: Option<BTreeMap<u32, String>>,
|
||||
@@ -602,6 +616,6 @@ pub struct GenericItemSuit {
|
||||
pub item_info: ItemInfo,
|
||||
pub parent_slot: Option<ParentSlotInfo>,
|
||||
pub damage: Option<f32>,
|
||||
pub slots: Vec<Slot>,
|
||||
pub slots: BTreeMap<u32, Slot>,
|
||||
pub suit_info: SuitInfo,
|
||||
}
|
||||
|
||||
@@ -7,14 +7,18 @@ use crate::{
|
||||
},
|
||||
};
|
||||
|
||||
use itertools::Itertools;
|
||||
use stationeers_data::{
|
||||
enums::{
|
||||
basic::{Class, GasType, SortingClass},
|
||||
script::{LogicSlotType, LogicType},
|
||||
},
|
||||
templates::{DeviceInfo, InternalAtmoInfo, ItemInfo, SuitInfo, ThermalInfo},
|
||||
templates::{
|
||||
ConsumerInfo, DeviceInfo, FabricatorInfo, InternalAtmoInfo, ItemInfo, RecipeOrder,
|
||||
SuitInfo, ThermalInfo,
|
||||
},
|
||||
};
|
||||
use std::{collections::BTreeMap, usize};
|
||||
use std::collections::BTreeMap;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
pub trait GWThermal {
|
||||
@@ -29,6 +33,9 @@ impl<T: GWThermal + Object> Thermal for T {
|
||||
fn get_convection_factor(&self) -> f32 {
|
||||
self.thermal_info().convection_factor
|
||||
}
|
||||
fn debug_thermal(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, "thermal_info: {:?}", self.thermal_info())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GWInternalAtmo {
|
||||
@@ -40,6 +47,9 @@ impl<T: GWInternalAtmo + Object> InternalAtmosphere for T {
|
||||
fn get_volume(&self) -> f64 {
|
||||
self.internal_atmo_info().volume as f64
|
||||
}
|
||||
fn debug_internal_atmosphere(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, "internal_atmo_info: {:?}", self.internal_atmo_info())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GWStructure {
|
||||
@@ -50,11 +60,14 @@ impl<T: GWStructure + Object> Structure for T {
|
||||
fn is_small_grid(&self) -> bool {
|
||||
self.small_grid()
|
||||
}
|
||||
fn debug_structure(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, "small_grid: {}", self.small_grid())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GWStorage {
|
||||
fn slots(&self) -> &Vec<Slot>;
|
||||
fn slots_mut(&mut self) -> &mut Vec<Slot>;
|
||||
fn slots(&self) -> &BTreeMap<u32, Slot>;
|
||||
fn slots_mut(&mut self) -> &mut BTreeMap<u32, Slot>;
|
||||
}
|
||||
|
||||
impl<T: GWStorage + Object> Storage for T {
|
||||
@@ -62,16 +75,25 @@ impl<T: GWStorage + Object> Storage for T {
|
||||
self.slots().len()
|
||||
}
|
||||
fn get_slot(&self, index: usize) -> Option<&Slot> {
|
||||
self.slots().get(index)
|
||||
self.slots().get(&(index as u32))
|
||||
}
|
||||
fn get_slot_mut(&mut self, index: usize) -> Option<&mut Slot> {
|
||||
self.slots_mut().get_mut(index)
|
||||
self.slots_mut().get_mut(&(index as u32))
|
||||
}
|
||||
fn get_slots(&self) -> Vec<&Slot> {
|
||||
self.slots().iter().collect()
|
||||
fn get_slots(&self) -> Vec<(usize, &Slot)> {
|
||||
self.slots()
|
||||
.iter()
|
||||
.map(|(index, slot)| (*index as usize, slot))
|
||||
.collect()
|
||||
}
|
||||
fn get_slots_mut(&mut self) -> Vec<&mut Slot> {
|
||||
self.slots_mut().iter_mut().collect()
|
||||
fn get_slots_mut(&mut self) -> Vec<(usize, &mut Slot)> {
|
||||
self.slots_mut()
|
||||
.iter_mut()
|
||||
.map(|(index, slot)| (*index as usize, slot))
|
||||
.collect()
|
||||
}
|
||||
fn debug_storage(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, "slots: {:?}", self.slots())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,6 +104,14 @@ pub trait GWLogicable: Storage {
|
||||
}
|
||||
|
||||
impl<T: GWLogicable + Object> Logicable for T {
|
||||
fn debug_logicable(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"fields: {:?}, modes: {:?}",
|
||||
self.fields(),
|
||||
self.known_modes()
|
||||
)
|
||||
}
|
||||
fn prefab_hash(&self) -> i32 {
|
||||
self.get_prefab().hash
|
||||
}
|
||||
@@ -213,7 +243,7 @@ impl<T: GWLogicable + Object> Logicable for T {
|
||||
}
|
||||
Class => {
|
||||
if slot.occupant.is_some() {
|
||||
Ok(slot.typ as i32 as f64)
|
||||
Ok(slot.class as i32 as f64)
|
||||
} else {
|
||||
Ok(0.0)
|
||||
}
|
||||
@@ -349,6 +379,14 @@ pub trait GWMemoryReadable {
|
||||
}
|
||||
|
||||
impl<T: GWMemoryReadable + Object> MemoryReadable for T {
|
||||
fn debug_memory_readable(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"size: {}, values: {:?}",
|
||||
self.memory_size(),
|
||||
self.memory()
|
||||
)
|
||||
}
|
||||
fn memory_size(&self) -> usize {
|
||||
self.memory_size()
|
||||
}
|
||||
@@ -371,6 +409,14 @@ pub trait GWMemoryWritable: MemoryReadable {
|
||||
}
|
||||
|
||||
impl<T: GWMemoryWritable + MemoryReadable + Object> MemoryWritable for T {
|
||||
fn debug_memory_writable(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"size: {}, values: {:?}",
|
||||
self.memory_size(),
|
||||
self.get_memory_slice()
|
||||
)
|
||||
}
|
||||
fn set_memory(&mut self, index: i32, val: f64) -> Result<(), MemoryError> {
|
||||
if index < 0 {
|
||||
Err(MemoryError::StackUnderflow(index, self.memory_size()))
|
||||
@@ -392,11 +438,20 @@ pub trait GWDevice: GWLogicable + Logicable {
|
||||
fn connections_mut(&mut self) -> &mut [Connection];
|
||||
fn pins(&self) -> Option<&[Option<ObjectID>]>;
|
||||
fn pins_mut(&mut self) -> Option<&mut [Option<ObjectID>]>;
|
||||
fn reagents(&self) -> Option<&BTreeMap<i32, f64>>;
|
||||
fn reagents_mut(&mut self) -> &mut Option<BTreeMap<i32, f64>>;
|
||||
fn reagents(&self) -> Option<&BTreeMap<u8, f64>>;
|
||||
fn reagents_mut(&mut self) -> &mut Option<BTreeMap<u8, f64>>;
|
||||
}
|
||||
|
||||
impl<T: GWDevice + GWStorage + Object> Device for T {
|
||||
fn debug_device(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"device_info: {:?}, connections: {:?}, pins: {:?}",
|
||||
self.device_info(),
|
||||
self.connections(),
|
||||
self.pins()
|
||||
)
|
||||
}
|
||||
fn can_slot_logic_write(&self, slt: LogicSlotType, index: f64) -> bool {
|
||||
if index < 0.0 {
|
||||
false
|
||||
@@ -499,7 +554,7 @@ impl<T: GWDevice + GWStorage + Object> Device for T {
|
||||
fn has_atmosphere(&self) -> bool {
|
||||
self.device_info().has_atmosphere
|
||||
}
|
||||
fn get_reagents(&self) -> Vec<(i32, f64)> {
|
||||
fn get_reagents(&self) -> Vec<(u8, f64)> {
|
||||
self.reagents()
|
||||
.map(|reagents| {
|
||||
reagents
|
||||
@@ -509,11 +564,11 @@ impl<T: GWDevice + GWStorage + Object> Device for T {
|
||||
})
|
||||
.unwrap_or_default()
|
||||
}
|
||||
fn set_reagents(&mut self, reagents: &[(i32, f64)]) {
|
||||
fn set_reagents(&mut self, reagents: &[(u8, f64)]) {
|
||||
let reagents_ref = self.reagents_mut();
|
||||
*reagents_ref = Some(reagents.iter().copied().collect());
|
||||
}
|
||||
fn add_reagents(&mut self, reagents: &[(i32, f64)]) {
|
||||
fn add_reagents(&mut self, reagents: &[(u8, f64)]) {
|
||||
let reagents_ref = self.reagents_mut();
|
||||
if let Some(ref mut reagents_ref) = reagents_ref {
|
||||
reagents_ref.extend(reagents.iter().map(|(hash, quant)| (hash, quant)));
|
||||
@@ -532,6 +587,15 @@ pub trait GWItem {
|
||||
}
|
||||
|
||||
impl<T: GWItem + Object> Item for T {
|
||||
fn debug_item(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"item_info: {:?}, parent_slot: {:?}, damage: {:?}",
|
||||
self.item_info(),
|
||||
self.parent_slot(),
|
||||
self.damage()
|
||||
)
|
||||
}
|
||||
fn consumable(&self) -> bool {
|
||||
self.item_info().consumable
|
||||
}
|
||||
@@ -572,6 +636,9 @@ pub trait GWSuit: Storage {
|
||||
}
|
||||
|
||||
impl<T: GWSuit + Item + Object> Suit for T {
|
||||
fn debug_suit(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, "suit_info: {:?}", self.suit_info())
|
||||
}
|
||||
fn pressure_waste_max(&self) -> f32 {
|
||||
self.suit_info().waste_max_pressure
|
||||
}
|
||||
@@ -654,7 +721,7 @@ pub trait GWCircuitHolderWrapper<T: GWCircuitHolder, H = <T as GWCircuitHolder>:
|
||||
connection: Option<usize>,
|
||||
) -> Option<ObjectRefMut>;
|
||||
fn get_ic_gw(&self) -> Option<VMObject>;
|
||||
fn hault_and_catch_fire_gw(&mut self);
|
||||
fn halt_and_catch_fire_gw(&mut self);
|
||||
}
|
||||
|
||||
impl<T> CircuitHolder for T
|
||||
@@ -662,6 +729,9 @@ where
|
||||
T: GWCircuitHolder,
|
||||
Self: GWCircuitHolderWrapper<T>,
|
||||
{
|
||||
fn debug_circuit_holder(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, "GenericCircuitHolder, Limited Info")
|
||||
}
|
||||
fn clear_error(&mut self) {
|
||||
self.clear_error_gw()
|
||||
}
|
||||
@@ -702,7 +772,7 @@ where
|
||||
self.get_ic_gw()
|
||||
}
|
||||
fn halt_and_catch_fire(&mut self) {
|
||||
self.hault_and_catch_fire_gw()
|
||||
self.halt_and_catch_fire_gw()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -822,15 +892,15 @@ where
|
||||
fn get_ic_gw(&self) -> Option<crate::vm::object::VMObject> {
|
||||
self.get_slots()
|
||||
.into_iter()
|
||||
.find(|slot| slot.typ == Class::ProgrammableChip)
|
||||
.and_then(|slot| {
|
||||
.find(|(_, slot)| slot.class == Class::ProgrammableChip)
|
||||
.and_then(|(_, slot)| {
|
||||
slot.occupant
|
||||
.as_ref()
|
||||
.and_then(|info| self.get_vm().get_object(info.id))
|
||||
})
|
||||
}
|
||||
|
||||
fn hault_and_catch_fire_gw(&mut self) {
|
||||
fn halt_and_catch_fire_gw(&mut self) {
|
||||
// TODO: do something here??
|
||||
}
|
||||
}
|
||||
@@ -937,7 +1007,7 @@ where
|
||||
let contained_ids: Vec<ObjectID> = self
|
||||
.get_slots()
|
||||
.into_iter()
|
||||
.filter_map(|slot| slot.occupant.as_ref().map(|info| info.id))
|
||||
.filter_map(|(_, slot)| slot.occupant.as_ref().map(|info| info.id))
|
||||
.collect();
|
||||
if contained_ids.contains(&device) {
|
||||
self.get_vm()
|
||||
@@ -959,7 +1029,7 @@ where
|
||||
let contained_ids: Vec<ObjectID> = self
|
||||
.get_slots()
|
||||
.into_iter()
|
||||
.filter_map(|slot| slot.occupant.as_ref().map(|info| info.id))
|
||||
.filter_map(|(_, slot)| slot.occupant.as_ref().map(|info| info.id))
|
||||
.collect();
|
||||
if contained_ids.contains(&device) {
|
||||
self.get_vm()
|
||||
@@ -973,15 +1043,15 @@ where
|
||||
fn get_ic_gw(&self) -> Option<crate::vm::object::VMObject> {
|
||||
self.get_slots()
|
||||
.into_iter()
|
||||
.find(|slot| slot.typ == Class::ProgrammableChip)
|
||||
.and_then(|slot| {
|
||||
.find(|(_, slot)| slot.class == Class::ProgrammableChip)
|
||||
.and_then(|(_, slot)| {
|
||||
slot.occupant
|
||||
.as_ref()
|
||||
.and_then(|info| self.get_vm().get_object(info.id))
|
||||
})
|
||||
}
|
||||
|
||||
fn hault_and_catch_fire_gw(&mut self) {
|
||||
fn halt_and_catch_fire_gw(&mut self) {
|
||||
// TODO: do something here??
|
||||
}
|
||||
}
|
||||
@@ -1112,7 +1182,7 @@ where
|
||||
let contained_ids: Vec<ObjectID> = self
|
||||
.get_slots()
|
||||
.into_iter()
|
||||
.filter_map(|slot| slot.occupant.as_ref().map(|info| info.id))
|
||||
.filter_map(|(_, slot)| slot.occupant.as_ref().map(|info| info.id))
|
||||
.collect();
|
||||
if contained_ids.contains(&device) {
|
||||
self.get_vm()
|
||||
@@ -1134,7 +1204,7 @@ where
|
||||
let contained_ids: Vec<ObjectID> = self
|
||||
.get_slots()
|
||||
.into_iter()
|
||||
.filter_map(|slot| slot.occupant.as_ref().map(|info| info.id))
|
||||
.filter_map(|(_, slot)| slot.occupant.as_ref().map(|info| info.id))
|
||||
.collect();
|
||||
if contained_ids.contains(&device) {
|
||||
self.get_vm()
|
||||
@@ -1148,15 +1218,130 @@ where
|
||||
fn get_ic_gw(&self) -> Option<crate::vm::object::VMObject> {
|
||||
self.get_slots()
|
||||
.into_iter()
|
||||
.find(|slot| slot.typ == Class::ProgrammableChip)
|
||||
.and_then(|slot| {
|
||||
.find(|(_, slot)| slot.class == Class::ProgrammableChip)
|
||||
.and_then(|(_, slot)| {
|
||||
slot.occupant
|
||||
.as_ref()
|
||||
.and_then(|info| self.get_vm().get_object(info.id))
|
||||
})
|
||||
}
|
||||
|
||||
fn hault_and_catch_fire_gw(&mut self) {
|
||||
fn halt_and_catch_fire_gw(&mut self) {
|
||||
// TODO: do something here??
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GWReagentConsumer {
|
||||
fn consumer_info(&self) -> &ConsumerInfo;
|
||||
}
|
||||
|
||||
impl<T: GWReagentConsumer + Object> ReagentConsumer for T {
|
||||
fn debug_reagent_consumer(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, "") // TODO: implement
|
||||
}
|
||||
fn get_resources_used(&self) -> Vec<i32> {
|
||||
let info = self.consumer_info();
|
||||
let vm = self.get_vm();
|
||||
info.consumed_resources
|
||||
.iter()
|
||||
.filter_map(|resource| {
|
||||
let prefab = vm.lookup_template_by_name(resource);
|
||||
prefab.map(|prefab| prefab.prefab().prefab_hash)
|
||||
})
|
||||
.collect_vec()
|
||||
}
|
||||
fn can_process_reagent(&self, reagent_id: u8) -> bool {
|
||||
let info = self.consumer_info();
|
||||
let vm = self.get_vm();
|
||||
let processed = info
|
||||
.processed_reagents
|
||||
.iter()
|
||||
.filter_map(|reagent_hash| vm.lookup_reagent_by_hash(*reagent_hash))
|
||||
.collect_vec();
|
||||
processed
|
||||
.iter()
|
||||
.find(|reagent| reagent.id == reagent_id)
|
||||
.is_some()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GWReagentRequirer: Device {
|
||||
fn get_current_recipe_gw(&self) -> Option<(u32, u32)>;
|
||||
fn get_fab_info_gw(&self) -> Option<&FabricatorInfo>;
|
||||
}
|
||||
|
||||
impl<T: GWReagentRequirer + Object> ReagentRequirer for T {
|
||||
fn debug_reagent_requirer(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"current: {:?}, required: {:?}",
|
||||
self.get_current_recipe(),
|
||||
self.get_current_required()
|
||||
)
|
||||
}
|
||||
fn get_current_recipe(&self) -> Option<RecipeOrder> {
|
||||
if let Some((current, quantity)) = self.get_current_recipe_gw() {
|
||||
let info = self.get_fab_info_gw();
|
||||
let recipe = info.and_then(|info| info.recipes.get(current as usize));
|
||||
recipe.map(|recipe| RecipeOrder {
|
||||
recipe: recipe.clone(),
|
||||
quantity,
|
||||
})
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
fn get_current_required(&self) -> Vec<(u8, f64)> {
|
||||
let current = self.get_current_recipe();
|
||||
let vm = self.get_vm();
|
||||
let have = self.get_reagents();
|
||||
let needed = current.map_or_else(std::default::Default::default, |current| {
|
||||
current
|
||||
.recipe
|
||||
.reagents
|
||||
.iter()
|
||||
.filter_map(|(reagent_name, reagent_quantity)| {
|
||||
if let Some(reagent) = vm.lookup_reagent_by_name(&reagent_name) {
|
||||
if let Some((_id, have_quantity)) = have
|
||||
.iter()
|
||||
.find(|(id, quantity)| &reagent.id == id && quantity < reagent_quantity)
|
||||
{
|
||||
Some((reagent.id, reagent_quantity - have_quantity))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect_vec()
|
||||
});
|
||||
needed
|
||||
}
|
||||
fn get_prefab_hash_from_reagent_hash(&self, reagent_hash: i32) -> Option<i32> {
|
||||
let vm = self.get_vm();
|
||||
let reagent = vm.lookup_reagent_by_hash(reagent_hash);
|
||||
reagent.and_then(|reagent| {
|
||||
reagent
|
||||
.sources
|
||||
.iter()
|
||||
.find(|(source_prefab, _quant)| source_prefab.contains("Ingot"))
|
||||
.map(|(prefab, _quant)| {
|
||||
vm.lookup_template_by_name(prefab)
|
||||
.map(|template| template.prefab().prefab_hash)
|
||||
})
|
||||
.flatten()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GWFabricator: ReagentRequirer {
|
||||
fn is_fabricator(&self) -> bool;
|
||||
fn fabricator_info(&self) -> &FabricatorInfo;
|
||||
}
|
||||
|
||||
impl<T: GWFabricator + Object> Fabricator for T {
|
||||
fn debug_fabricator(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, "UNIMPLEMENTED") // TODO: implement
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use macro_rules_attribute::derive;
|
||||
use stationeers_data::{
|
||||
enums::{basic::Class, Species},
|
||||
};
|
||||
use stationeers_data::enums::{basic::Class, Species};
|
||||
#[cfg(feature = "tsify")]
|
||||
use tsify::Tsify;
|
||||
#[cfg(feature = "tsify")]
|
||||
@@ -193,32 +191,43 @@ impl Thermal for HumanPlayer {
|
||||
fn get_convection_factor(&self) -> f32 {
|
||||
0.1
|
||||
}
|
||||
fn debug_thermal(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"radiation: {}, convection: {}",
|
||||
self.get_radiation_factor(),
|
||||
self.get_convection_factor()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Storage for HumanPlayer {
|
||||
fn get_slots(&self) -> Vec<&Slot> {
|
||||
fn debug_storage(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, "slots: {:?}", self.get_slots())
|
||||
}
|
||||
fn get_slots(&self) -> Vec<(usize, &Slot)> {
|
||||
vec![
|
||||
&self.left_hand_slot,
|
||||
&self.right_hand_slot,
|
||||
&self.helmet_slot,
|
||||
&self.suit_slot,
|
||||
&self.backpack_slot,
|
||||
&self.uniform_slot,
|
||||
&self.toolbelt_slot,
|
||||
&self.glasses_slot,
|
||||
(0, &self.left_hand_slot),
|
||||
(1, &self.right_hand_slot),
|
||||
(2, &self.helmet_slot),
|
||||
(3, &self.suit_slot),
|
||||
(4, &self.backpack_slot),
|
||||
(5, &self.uniform_slot),
|
||||
(6, &self.toolbelt_slot),
|
||||
(7, &self.glasses_slot),
|
||||
]
|
||||
}
|
||||
|
||||
fn get_slots_mut(&mut self) -> Vec<&mut Slot> {
|
||||
fn get_slots_mut(&mut self) -> Vec<(usize, &mut Slot)> {
|
||||
vec![
|
||||
&mut self.left_hand_slot,
|
||||
&mut self.right_hand_slot,
|
||||
&mut self.helmet_slot,
|
||||
&mut self.suit_slot,
|
||||
&mut self.backpack_slot,
|
||||
&mut self.uniform_slot,
|
||||
&mut self.toolbelt_slot,
|
||||
&mut self.glasses_slot,
|
||||
(0, &mut self.left_hand_slot),
|
||||
(1, &mut self.right_hand_slot),
|
||||
(2, &mut self.helmet_slot),
|
||||
(3, &mut self.suit_slot),
|
||||
(4, &mut self.backpack_slot),
|
||||
(5, &mut self.uniform_slot),
|
||||
(6, &mut self.toolbelt_slot),
|
||||
(7, &mut self.glasses_slot),
|
||||
]
|
||||
}
|
||||
|
||||
@@ -255,6 +264,20 @@ impl Storage for HumanPlayer {
|
||||
}
|
||||
|
||||
impl Human for HumanPlayer {
|
||||
fn debug_human(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, "species: {:?}, damage: {}, hydration: {}, nutrition:, {}, oxygenation: {}, food_quality: {}, mood: {}, hygiene: {}, artificial: {}, battery: {:?}",
|
||||
self.get_species(),
|
||||
self.get_damage(),
|
||||
self.get_hydration(),
|
||||
self.get_nutrition(),
|
||||
self.get_oxygenation(),
|
||||
self.get_food_quality(),
|
||||
self.get_mood(),
|
||||
self.get_hygiene(),
|
||||
self.is_artificial(),
|
||||
self.robot_battery()
|
||||
)
|
||||
}
|
||||
fn get_species(&self) -> Species {
|
||||
self.species
|
||||
}
|
||||
|
||||
@@ -55,6 +55,15 @@ macro_rules! object_trait {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Debug for [<$trait_name Interfaces>]<'a> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
$(
|
||||
write!(f, "{}: {:?}, ", stringify!([<$trt:snake>]), &self.[<$trt:snake>])?;
|
||||
)*
|
||||
write!(f, "")
|
||||
}
|
||||
}
|
||||
|
||||
pub enum [<$trait_name Ref>]<'a> {
|
||||
DynRef(&'a dyn $trait_name),
|
||||
VMObject(crate::vm::object::VMObject),
|
||||
@@ -524,6 +533,20 @@ macro_rules! tag_object_traits {
|
||||
$(#[$attr])*
|
||||
$viz trait $trt : $( $trt_bound_first $(+ $trt_bound_others)* +)? $trt_name {
|
||||
$($tbody)*
|
||||
paste::paste! {
|
||||
fn [<debug_ $trt:snake>](&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result;
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Debug for dyn $trt + 'a {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, "{}{{", stringify!($trt))?;
|
||||
|
||||
paste::paste! {
|
||||
self.[<debug_ $trt:snake>](f)?;
|
||||
}
|
||||
write!(f, "}}")
|
||||
}
|
||||
}
|
||||
|
||||
$crate::vm::object::macros::tag_object_traits!{
|
||||
|
||||
@@ -14,7 +14,7 @@ use stationeers_data::enums::{
|
||||
script::{LogicSlotType, LogicType},
|
||||
ConnectionRole,
|
||||
};
|
||||
use std::rc::Rc;
|
||||
use std::{collections::BTreeMap, rc::Rc};
|
||||
use strum::EnumProperty;
|
||||
|
||||
#[derive(ObjectInterface!)]
|
||||
@@ -58,7 +58,7 @@ impl StructureCircuitHousing {
|
||||
parent: id,
|
||||
index: 0,
|
||||
name: "Programmable Chip".to_string(),
|
||||
typ: Class::ProgrammableChip,
|
||||
class: Class::ProgrammableChip,
|
||||
readable_logic: vec![
|
||||
LogicSlotType::Class,
|
||||
LogicSlotType::Damage,
|
||||
@@ -73,6 +73,7 @@ impl StructureCircuitHousing {
|
||||
],
|
||||
writeable_logic: vec![],
|
||||
occupant: None,
|
||||
proxy: false,
|
||||
},
|
||||
pins: [None, None, None, None, None, None],
|
||||
connections: [
|
||||
@@ -95,9 +96,15 @@ impl Structure for StructureCircuitHousing {
|
||||
fn is_small_grid(&self) -> bool {
|
||||
true
|
||||
}
|
||||
fn debug_structure(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, "small_grid: {}", self.is_small_grid())
|
||||
}
|
||||
}
|
||||
|
||||
impl Storage for StructureCircuitHousing {
|
||||
fn debug_storage(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, "slots: {:?}", self.get_slots())
|
||||
}
|
||||
fn slots_count(&self) -> usize {
|
||||
1
|
||||
}
|
||||
@@ -115,15 +122,31 @@ impl Storage for StructureCircuitHousing {
|
||||
Some(&mut self.slot)
|
||||
}
|
||||
}
|
||||
fn get_slots(&self) -> Vec<&Slot> {
|
||||
vec![&self.slot]
|
||||
fn get_slots(&self) -> Vec<(usize, &Slot)> {
|
||||
vec![(0, &self.slot)]
|
||||
}
|
||||
fn get_slots_mut(&mut self) -> Vec<&mut Slot> {
|
||||
vec![&mut self.slot]
|
||||
fn get_slots_mut(&mut self) -> Vec<(usize, &mut Slot)> {
|
||||
vec![(0, &mut self.slot)]
|
||||
}
|
||||
}
|
||||
|
||||
impl Logicable for StructureCircuitHousing {
|
||||
fn debug_logicable(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
let values: BTreeMap<LogicType, Option<f64>> = self
|
||||
.valid_logic_types()
|
||||
.into_iter()
|
||||
.map(|lt| (lt, self.get_logic(lt).ok()))
|
||||
.collect();
|
||||
write!(
|
||||
f,
|
||||
"prefab_hash: {}, name_hash: {}, readable: {}, writable: {}, values{:?}",
|
||||
self.prefab_hash(),
|
||||
self.name_hash(),
|
||||
self.is_logic_readable(),
|
||||
self.is_logic_writeable(),
|
||||
values
|
||||
)
|
||||
}
|
||||
fn prefab_hash(&self) -> i32 {
|
||||
self.get_prefab().hash
|
||||
}
|
||||
@@ -253,6 +276,13 @@ impl Logicable for StructureCircuitHousing {
|
||||
}
|
||||
|
||||
impl Device for StructureCircuitHousing {
|
||||
fn debug_device(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"pins: {:?}, connections: {:?}",
|
||||
self.pins, self.connections
|
||||
)
|
||||
}
|
||||
fn has_reagents(&self) -> bool {
|
||||
false
|
||||
}
|
||||
@@ -277,13 +307,13 @@ impl Device for StructureCircuitHousing {
|
||||
fn has_on_off_state(&self) -> bool {
|
||||
true
|
||||
}
|
||||
fn get_reagents(&self) -> Vec<(i32, f64)> {
|
||||
fn get_reagents(&self) -> Vec<(u8, f64)> {
|
||||
vec![]
|
||||
}
|
||||
fn set_reagents(&mut self, _reagents: &[(i32, f64)]) {
|
||||
fn set_reagents(&mut self, _reagents: &[(u8, f64)]) {
|
||||
// nope
|
||||
}
|
||||
fn add_reagents(&mut self, _reagents: &[(i32, f64)]) {
|
||||
fn add_reagents(&mut self, _reagents: &[(u8, f64)]) {
|
||||
// nope
|
||||
}
|
||||
fn connection_list(&self) -> &[crate::network::Connection] {
|
||||
@@ -313,6 +343,9 @@ impl Device for StructureCircuitHousing {
|
||||
}
|
||||
|
||||
impl CircuitHolder for StructureCircuitHousing {
|
||||
fn debug_circuit_holder(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, "error: {}, setting: {}", self.error, self.setting)
|
||||
}
|
||||
fn clear_error(&mut self) {
|
||||
self.error = 0
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
errors::ICError,
|
||||
errors::{ICError, LineError},
|
||||
interpreter::{instructions::IC10Marker, ICState, Program},
|
||||
vm::{
|
||||
instructions::{operands::Operand, Instruction},
|
||||
@@ -22,7 +22,7 @@ use std::{collections::BTreeMap, rc::Rc};
|
||||
static RETURN_ADDRESS_INDEX: usize = 17;
|
||||
static STACK_POINTER_INDEX: usize = 16;
|
||||
|
||||
#[derive(ObjectInterface!)]
|
||||
#[derive(ObjectInterface!, Debug)]
|
||||
#[custom(implements(Object {
|
||||
Item, Storage, Logicable,
|
||||
MemoryReadable, MemoryWritable,
|
||||
@@ -57,6 +57,9 @@ pub struct ItemIntegratedCircuit10 {
|
||||
}
|
||||
|
||||
impl Item for ItemIntegratedCircuit10 {
|
||||
fn debug_item(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, "UNIMPLEMENTED") //TODO: Implement
|
||||
}
|
||||
fn consumable(&self) -> bool {
|
||||
false
|
||||
}
|
||||
@@ -93,6 +96,9 @@ impl Item for ItemIntegratedCircuit10 {
|
||||
}
|
||||
|
||||
impl Storage for ItemIntegratedCircuit10 {
|
||||
fn debug_storage(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, "UNIMPLEMENTED") //TODO: Implement
|
||||
}
|
||||
fn slots_count(&self) -> usize {
|
||||
0
|
||||
}
|
||||
@@ -102,15 +108,18 @@ impl Storage for ItemIntegratedCircuit10 {
|
||||
fn get_slot_mut(&mut self, _index: usize) -> Option<&mut Slot> {
|
||||
None
|
||||
}
|
||||
fn get_slots(&self) -> Vec<&Slot> {
|
||||
fn get_slots(&self) -> Vec<(usize, &Slot)> {
|
||||
vec![]
|
||||
}
|
||||
fn get_slots_mut(&mut self) -> Vec<&mut Slot> {
|
||||
fn get_slots_mut(&mut self) -> Vec<(usize, &mut Slot)> {
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
|
||||
impl Logicable for ItemIntegratedCircuit10 {
|
||||
fn debug_logicable(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, "UNIMPLEMENTED") //TODO: Implement
|
||||
}
|
||||
fn prefab_hash(&self) -> i32 {
|
||||
self.get_prefab().hash
|
||||
}
|
||||
@@ -170,7 +179,7 @@ impl Logicable for ItemIntegratedCircuit10 {
|
||||
_ => Err(LogicError::CantWrite(lt)),
|
||||
})
|
||||
}
|
||||
fn can_slot_logic_read(&self, _slt: LogicSlotType, _indexx: f64) -> bool {
|
||||
fn can_slot_logic_read(&self, _slt: LogicSlotType, _index: f64) -> bool {
|
||||
false
|
||||
}
|
||||
fn get_slot_logic(&self, _slt: LogicSlotType, index: f64) -> Result<f64, LogicError> {
|
||||
@@ -185,6 +194,9 @@ impl Logicable for ItemIntegratedCircuit10 {
|
||||
}
|
||||
|
||||
impl MemoryReadable for ItemIntegratedCircuit10 {
|
||||
fn debug_memory_readable(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, "UNIMPLEMENTED") //TODO: Implement
|
||||
}
|
||||
fn memory_size(&self) -> usize {
|
||||
self.memory.len()
|
||||
}
|
||||
@@ -203,6 +215,9 @@ impl MemoryReadable for ItemIntegratedCircuit10 {
|
||||
}
|
||||
|
||||
impl MemoryWritable for ItemIntegratedCircuit10 {
|
||||
fn debug_memory_writable(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, "UNIMPLEMENTED") //TODO: Implement
|
||||
}
|
||||
fn set_memory(&mut self, index: i32, val: f64) -> Result<(), MemoryError> {
|
||||
if index < 0 {
|
||||
Err(MemoryError::StackUnderflow(index, self.memory.len()))
|
||||
@@ -219,6 +234,9 @@ impl MemoryWritable for ItemIntegratedCircuit10 {
|
||||
}
|
||||
|
||||
impl SourceCode for ItemIntegratedCircuit10 {
|
||||
fn debug_source_code(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, "UNIMPLEMENTED") //TODO: Implement
|
||||
}
|
||||
fn set_source_code(&mut self, code: &str) -> Result<(), ICError> {
|
||||
self.program = Program::try_from_code(code)?;
|
||||
self.code = code.to_string();
|
||||
@@ -240,6 +258,9 @@ impl SourceCode for ItemIntegratedCircuit10 {
|
||||
}
|
||||
|
||||
impl IntegratedCircuit for ItemIntegratedCircuit10 {
|
||||
fn debug_integrated_circuit(&self,f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, "UNIMPLEMENTED") //TODO: Implement
|
||||
}
|
||||
fn get_circuit_holder(&self) -> Option<VMObject> {
|
||||
self.get_parent_slot()
|
||||
.and_then(|parent_slot| self.get_vm().get_object(parent_slot.parent))
|
||||
@@ -388,31 +409,42 @@ impl IntegratedCircuit for ItemIntegratedCircuit10 {
|
||||
impl IC10Marker for ItemIntegratedCircuit10 {}
|
||||
|
||||
impl Programmable for ItemIntegratedCircuit10 {
|
||||
fn debug_programmable(&self,f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, "UNIMPLEMENTED") //TODO: Implement
|
||||
}
|
||||
#[tracing::instrument]
|
||||
fn step(&mut self, advance_ip_on_err: bool) -> Result<(), crate::errors::ICError> {
|
||||
tracing::trace!(ignore_error = advance_ip_on_err, "stepping IC");
|
||||
if matches!(&self.state, ICState::HasCaughtFire) {
|
||||
tracing::debug!("IC on Fire!");
|
||||
return Ok(());
|
||||
}
|
||||
if matches!(&self.state, ICState::Error(_)) && !advance_ip_on_err {
|
||||
tracing::debug!("IC in an error state, not advancing");
|
||||
return Ok(());
|
||||
}
|
||||
if let ICState::Sleep(then, sleep_for) = &self.state {
|
||||
if let Some(duration) = time::Duration::checked_seconds_f64(*sleep_for) {
|
||||
if let Some(sleep_till) = then.checked_add(duration) {
|
||||
if sleep_till
|
||||
<= time::OffsetDateTime::now_local()
|
||||
.unwrap_or_else(|_| time::OffsetDateTime::now_utc())
|
||||
{
|
||||
let now = time::OffsetDateTime::now_local()
|
||||
.unwrap_or_else(|_| time::OffsetDateTime::now_utc());
|
||||
if sleep_till > now {
|
||||
tracing::debug!("Sleeping: {sleep_till} > {now}");
|
||||
return Ok(());
|
||||
}
|
||||
// else sleep duration ended, continue
|
||||
} else {
|
||||
return Err(ICError::SleepAddtionError(duration, *then));
|
||||
return Err(ICError::SleepAdditionError {
|
||||
duration,
|
||||
time: *then,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
return Err(ICError::SleepDurationError(*sleep_for));
|
||||
}
|
||||
}
|
||||
if self.ip >= self.program.len() || self.program.is_empty() {
|
||||
tracing::debug!("IC at end of program");
|
||||
self.state = ICState::Ended;
|
||||
return Ok(());
|
||||
}
|
||||
@@ -423,7 +455,13 @@ impl Programmable for ItemIntegratedCircuit10 {
|
||||
let instruction = line.instruction;
|
||||
let result = instruction.execute(self, operands);
|
||||
|
||||
let was_error = if let Err(_err) = result {
|
||||
let was_error = if let Err(err) = result {
|
||||
let msg = err.to_string();
|
||||
self.state = ICState::Error(LineError {
|
||||
error: err,
|
||||
line: self.ip as u32,
|
||||
msg,
|
||||
});
|
||||
self.get_circuit_holder()
|
||||
.ok_or(ICError::NoCircuitHolder(self.id))?
|
||||
.borrow_mut()
|
||||
@@ -437,7 +475,7 @@ impl Programmable for ItemIntegratedCircuit10 {
|
||||
|
||||
if !was_error || advance_ip_on_err {
|
||||
self.ip = self.next_ip;
|
||||
if self.ip >= self.program.len() {
|
||||
if self.ip >= self.program.len() && !matches!(&self.state, ICState::Error(_)) {
|
||||
self.state = ICState::Ended;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ use crate::{
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use stationeers_data::{
|
||||
enums::{
|
||||
basic::Class,
|
||||
prefabs::StationpediaPrefab,
|
||||
script::{LogicSlotType, LogicType},
|
||||
},
|
||||
@@ -64,6 +65,7 @@ impl std::fmt::Display for Prefab {
|
||||
}
|
||||
}
|
||||
|
||||
#[serde_with::skip_serializing_none]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
|
||||
pub struct ObjectInfo {
|
||||
@@ -77,8 +79,7 @@ pub struct ObjectInfo {
|
||||
pub damage: Option<f32>,
|
||||
pub device_pins: Option<BTreeMap<u32, ObjectID>>,
|
||||
pub connections: Option<BTreeMap<u32, ObjectID>>,
|
||||
pub reagents: Option<BTreeMap<i32, f64>>,
|
||||
pub memory: Option<Vec<f64>>,
|
||||
pub reagents: Option<BTreeMap<u8, f64>>, pub memory: Option<Vec<f64>>,
|
||||
pub logic_values: Option<BTreeMap<LogicType, f64>>,
|
||||
pub slot_logic_values: Option<BTreeMap<u32, BTreeMap<LogicSlotType, f64>>>,
|
||||
pub entity: Option<EntityInfo>,
|
||||
@@ -201,7 +202,6 @@ impl ObjectInfo {
|
||||
self.slots.replace(
|
||||
slots
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.filter_map(|(index, slot)| {
|
||||
slot.occupant
|
||||
.as_ref()
|
||||
@@ -245,7 +245,7 @@ impl ObjectInfo {
|
||||
.collect()
|
||||
});
|
||||
}
|
||||
let reagents: BTreeMap<i32, f64> = device.get_reagents().iter().copied().collect();
|
||||
let reagents: BTreeMap<u8, f64> = device.get_reagents().iter().copied().collect();
|
||||
if reagents.is_empty() {
|
||||
self.reagents = None;
|
||||
} else {
|
||||
@@ -393,6 +393,7 @@ pub struct FrozenObjectFull {
|
||||
pub template: ObjectTemplate,
|
||||
}
|
||||
|
||||
#[serde_with::skip_serializing_none]
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
#[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
|
||||
pub struct FrozenObject {
|
||||
@@ -480,53 +481,66 @@ impl FrozenObject {
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
fn build_slots(
|
||||
fn build_slots<'a>(
|
||||
&self,
|
||||
id: ObjectID,
|
||||
slots_info: &[SlotInfo],
|
||||
slots_info: impl IntoIterator<Item = (&'a u32, &'a SlotInfo)>,
|
||||
logic_info: Option<&LogicInfo>,
|
||||
) -> Vec<Slot> {
|
||||
) -> BTreeMap<u32, Slot> {
|
||||
slots_info
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, info)| Slot {
|
||||
parent: id,
|
||||
index,
|
||||
name: info.name.clone(),
|
||||
typ: info.typ,
|
||||
readable_logic: logic_info
|
||||
.and_then(|info| {
|
||||
info.logic_slot_types.get(&(index as u32)).map(|s_info| {
|
||||
s_info
|
||||
.iter()
|
||||
.filter_map(|(key, access)| match access {
|
||||
MemoryAccess::Read | MemoryAccess::ReadWrite => Some(key),
|
||||
_ => None,
|
||||
.into_iter()
|
||||
.map(|(index, info)| {
|
||||
let (name, class, proxy) = match info {
|
||||
SlotInfo::Direct { name, class, .. } => (name.clone(), *class, false),
|
||||
SlotInfo::Proxy { name, .. } => (name.clone(), Class::None, true),
|
||||
};
|
||||
(
|
||||
*index,
|
||||
Slot {
|
||||
parent: id,
|
||||
index: *index as usize,
|
||||
name,
|
||||
class,
|
||||
proxy,
|
||||
readable_logic: logic_info
|
||||
.and_then(|info| {
|
||||
info.logic_slot_types.get(index).map(|s_info| {
|
||||
s_info
|
||||
.iter()
|
||||
.filter_map(|(key, access)| match access {
|
||||
MemoryAccess::Read | MemoryAccess::ReadWrite => {
|
||||
Some(key)
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.copied()
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
.copied()
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
})
|
||||
.unwrap_or_default(),
|
||||
writeable_logic: logic_info
|
||||
.and_then(|info| {
|
||||
info.logic_slot_types.get(&(index as u32)).map(|s_info| {
|
||||
s_info
|
||||
.iter()
|
||||
.filter_map(|(key, access)| match access {
|
||||
MemoryAccess::Write | MemoryAccess::ReadWrite => Some(key),
|
||||
_ => None,
|
||||
})
|
||||
.unwrap_or_default(),
|
||||
writeable_logic: logic_info
|
||||
.and_then(|info| {
|
||||
info.logic_slot_types.get(index).map(|s_info| {
|
||||
s_info
|
||||
.iter()
|
||||
.filter_map(|(key, access)| match access {
|
||||
MemoryAccess::Write | MemoryAccess::ReadWrite => {
|
||||
Some(key)
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.copied()
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
.copied()
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
})
|
||||
.unwrap_or_default(),
|
||||
occupant: self
|
||||
.obj_info
|
||||
.slots
|
||||
.as_ref()
|
||||
.and_then(|slots| slots.get(&(index as u32)).cloned()),
|
||||
})
|
||||
.unwrap_or_default(),
|
||||
occupant: self
|
||||
.obj_info
|
||||
.slots
|
||||
.as_ref()
|
||||
.and_then(|slots| slots.get(index).cloned()),
|
||||
},
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
@@ -748,6 +762,7 @@ impl FrozenObject {
|
||||
reagents: self.obj_info.reagents.clone(),
|
||||
consumer_info: s.consumer_info.clone(),
|
||||
fabricator_info: s.fabricator_info.clone(),
|
||||
current_recipe: None,
|
||||
memory: self.build_memory(&s.memory),
|
||||
},
|
||||
))
|
||||
@@ -771,6 +786,7 @@ impl FrozenObject {
|
||||
consumer_info: s.consumer_info.clone(),
|
||||
fabricator_info: s.fabricator_info.clone(),
|
||||
memory: self.build_memory(&s.memory),
|
||||
current_recipe: None,
|
||||
},
|
||||
)),
|
||||
Item(i) => Ok(VMObject::new(GenericItem {
|
||||
@@ -998,7 +1014,8 @@ fn try_template_from_interfaces(
|
||||
plant: None,
|
||||
suit: None,
|
||||
chargeable: None,
|
||||
reagent_interface: None,
|
||||
reagent_requirer: None,
|
||||
reagent_consumer: None,
|
||||
fabricator: None,
|
||||
internal_atmosphere,
|
||||
thermal,
|
||||
@@ -1033,7 +1050,8 @@ fn try_template_from_interfaces(
|
||||
plant: None,
|
||||
suit: None,
|
||||
chargeable: None,
|
||||
reagent_interface: None,
|
||||
reagent_requirer: None,
|
||||
reagent_consumer: None,
|
||||
fabricator: None,
|
||||
internal_atmosphere,
|
||||
thermal,
|
||||
@@ -1065,7 +1083,8 @@ fn try_template_from_interfaces(
|
||||
plant: None,
|
||||
suit: None,
|
||||
chargeable: None,
|
||||
reagent_interface: None,
|
||||
reagent_requirer: None,
|
||||
reagent_consumer: None,
|
||||
fabricator: None,
|
||||
internal_atmosphere,
|
||||
thermal,
|
||||
@@ -1098,7 +1117,8 @@ fn try_template_from_interfaces(
|
||||
plant: None,
|
||||
suit: None,
|
||||
chargeable: None,
|
||||
reagent_interface: None,
|
||||
reagent_requirer: None,
|
||||
reagent_consumer: None,
|
||||
fabricator: None,
|
||||
internal_atmosphere,
|
||||
thermal,
|
||||
@@ -1134,7 +1154,8 @@ fn try_template_from_interfaces(
|
||||
plant: None,
|
||||
suit: None,
|
||||
chargeable: None,
|
||||
reagent_interface: None,
|
||||
reagent_requirer: None,
|
||||
reagent_consumer: None,
|
||||
fabricator: None,
|
||||
internal_atmosphere,
|
||||
thermal,
|
||||
@@ -1173,7 +1194,8 @@ fn try_template_from_interfaces(
|
||||
plant: None,
|
||||
suit: None,
|
||||
chargeable: None,
|
||||
reagent_interface: None,
|
||||
reagent_requirer: None,
|
||||
reagent_consumer: None,
|
||||
fabricator: None,
|
||||
internal_atmosphere,
|
||||
thermal,
|
||||
@@ -1204,7 +1226,8 @@ fn try_template_from_interfaces(
|
||||
plant: None,
|
||||
suit: None,
|
||||
chargeable: None,
|
||||
reagent_interface: None,
|
||||
reagent_requirer: None,
|
||||
reagent_consumer: None,
|
||||
fabricator: None,
|
||||
internal_atmosphere,
|
||||
thermal,
|
||||
@@ -1236,7 +1259,8 @@ fn try_template_from_interfaces(
|
||||
plant: None,
|
||||
suit: None,
|
||||
chargeable: None,
|
||||
reagent_interface: None,
|
||||
reagent_requirer: None,
|
||||
reagent_consumer: None,
|
||||
fabricator: None,
|
||||
internal_atmosphere,
|
||||
thermal,
|
||||
@@ -1269,7 +1293,8 @@ fn try_template_from_interfaces(
|
||||
plant: None,
|
||||
suit: None,
|
||||
chargeable: None,
|
||||
reagent_interface: None,
|
||||
reagent_requirer: None,
|
||||
reagent_consumer: None,
|
||||
fabricator: None,
|
||||
internal_atmosphere,
|
||||
thermal,
|
||||
@@ -1303,7 +1328,8 @@ fn try_template_from_interfaces(
|
||||
plant: None,
|
||||
suit: None,
|
||||
chargeable: None,
|
||||
reagent_interface: None,
|
||||
reagent_requirer: None,
|
||||
reagent_consumer: None,
|
||||
fabricator: None,
|
||||
internal_atmosphere: None,
|
||||
thermal: Some(_),
|
||||
@@ -1312,13 +1338,16 @@ fn try_template_from_interfaces(
|
||||
prefab: PrefabInfo {
|
||||
prefab_name: "Character".to_string(),
|
||||
prefab_hash: 294335127,
|
||||
desc: "Charater".to_string(),
|
||||
name: "Charater".to_string(),
|
||||
desc: "Character".to_string(),
|
||||
name: "Character".to_string(),
|
||||
},
|
||||
species: human.get_species(),
|
||||
slots: storage.into(),
|
||||
})),
|
||||
_ => Err(TemplateError::NonConformingObject(obj.get_id())),
|
||||
_ => {
|
||||
tracing::error!("Object interface has a non conforming pattern: {:?}", obj);
|
||||
Err(TemplateError::NonConformingObject(obj.get_id()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1341,6 +1370,7 @@ impl From<&VMObject> for PrefabInfo {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<LogicableRef<'_>> for LogicInfo {
|
||||
fn from(logic: LogicableRef) -> Self {
|
||||
// Logicable: Storage -> !None
|
||||
@@ -1352,10 +1382,9 @@ impl From<LogicableRef<'_>> for LogicInfo {
|
||||
logic_slot_types: storage
|
||||
.get_slots()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, slot)| {
|
||||
(
|
||||
index as u32,
|
||||
*index as u32,
|
||||
LogicSlotType::iter()
|
||||
.filter_map(|slt| {
|
||||
let readable = slot.readable_logic.contains(&slt);
|
||||
@@ -1418,7 +1447,7 @@ impl From<ItemRef<'_>> for ItemInfo {
|
||||
|
||||
impl From<DeviceRef<'_>> for DeviceInfo {
|
||||
fn from(device: DeviceRef) -> Self {
|
||||
let _reagents: BTreeMap<i32, f64> = device.get_reagents().iter().copied().collect();
|
||||
let _reagents: BTreeMap<u8, f64> = device.get_reagents().iter().copied().collect();
|
||||
DeviceInfo {
|
||||
connection_list: device
|
||||
.connection_list()
|
||||
@@ -1478,14 +1507,27 @@ impl From<ThermalRef<'_>> for ThermalInfo {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StorageRef<'_>> for Vec<SlotInfo> {
|
||||
impl From<StorageRef<'_>> for BTreeMap<u32, SlotInfo> {
|
||||
fn from(storage: StorageRef<'_>) -> Self {
|
||||
storage
|
||||
.get_slots()
|
||||
.iter()
|
||||
.map(|slot| SlotInfo {
|
||||
name: slot.name.clone(),
|
||||
typ: slot.typ,
|
||||
.map(|(_index, slot)| {
|
||||
(
|
||||
slot.index as u32,
|
||||
if slot.proxy {
|
||||
SlotInfo::Proxy {
|
||||
name: slot.name.clone(),
|
||||
index: slot.index as u32,
|
||||
}
|
||||
} else {
|
||||
SlotInfo::Direct {
|
||||
name: slot.name.clone(),
|
||||
class: slot.class,
|
||||
index: slot.index as u32,
|
||||
}
|
||||
},
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
@@ -13,10 +13,13 @@ use crate::{
|
||||
},
|
||||
},
|
||||
};
|
||||
use stationeers_data::enums::{
|
||||
basic::{Class, GasType, SortingClass},
|
||||
script::{LogicSlotType, LogicType},
|
||||
Species,
|
||||
use stationeers_data::{
|
||||
enums::{
|
||||
basic::{Class, GasType, SortingClass},
|
||||
script::{LogicSlotType, LogicType},
|
||||
Species,
|
||||
},
|
||||
templates::RecipeOrder,
|
||||
};
|
||||
use std::{collections::BTreeMap, fmt::Debug};
|
||||
#[cfg(feature = "tsify")]
|
||||
@@ -75,9 +78,9 @@ tag_object_traits! {
|
||||
/// Get a mutable reference to a indexed slot
|
||||
fn get_slot_mut(&mut self, index: usize) -> Option<&mut Slot>;
|
||||
/// Get a vector of references to all an object's slots
|
||||
fn get_slots(&self) -> Vec<&Slot>;
|
||||
fn get_slots(&self) -> Vec<(usize, &Slot)>;
|
||||
/// Get a vector a mutable references to all an object's slots
|
||||
fn get_slots_mut(&mut self) -> Vec<&mut Slot>;
|
||||
fn get_slots_mut(&mut self) -> Vec<(usize, &mut Slot)>;
|
||||
}
|
||||
|
||||
pub trait MemoryReadable {
|
||||
@@ -394,21 +397,29 @@ tag_object_traits! {
|
||||
/// Does the device store reagents
|
||||
fn has_reagents(&self) -> bool;
|
||||
/// Return vector of (reagent_hash, quantity) pairs
|
||||
fn get_reagents(&self) -> Vec<(i32, f64)>;
|
||||
fn get_reagents(&self) -> Vec<(u8, f64)>;
|
||||
/// Overwrite present reagents
|
||||
fn set_reagents(&mut self, reagents: &[(i32, f64)]);
|
||||
fn set_reagents(&mut self, reagents: &[(u8, f64)]);
|
||||
/// Adds the reagents to contents
|
||||
fn add_reagents(&mut self, reagents: &[(i32, f64)]);
|
||||
fn add_reagents(&mut self, reagents: &[(u8, f64)]);
|
||||
}
|
||||
|
||||
pub trait ReagentInterface: Device {
|
||||
/// Reagents required by current recipe
|
||||
fn get_current_recipe(&self) -> Vec<(i32, f64)>;
|
||||
pub trait ReagentConsumer {
|
||||
fn can_process_reagent(&self, reagent: u8) -> bool;
|
||||
fn get_resources_used(&self) -> Vec<i32>;
|
||||
}
|
||||
|
||||
pub trait ReagentRequirer: Device {
|
||||
/// the currently selected Recipe and Order
|
||||
fn get_current_recipe(&self) -> Option<RecipeOrder>;
|
||||
/// Reagents required to complete current recipe
|
||||
fn get_current_required(&self) -> Vec<(i32, f64)>;
|
||||
fn get_current_required(&self) -> Vec<(u8, f64)>;
|
||||
/// Map Reagent hash to Prefab Hash
|
||||
fn get_prefab_hash_from_reagent_hash(&self, reagent_hash: i32) -> Option<i32>;
|
||||
}
|
||||
|
||||
pub trait Fabricator: ReagentInterface {}
|
||||
pub trait Fabricator: ReagentRequirer {
|
||||
}
|
||||
|
||||
pub trait WirelessTransmit: Logicable {}
|
||||
|
||||
@@ -493,14 +504,18 @@ impl Debug for dyn Object {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"Object: (ID = {:?}, Type = {})",
|
||||
"Object{{id: {:?}, type: {}, interfaces: {:?}}}",
|
||||
self.get_id(),
|
||||
self.type_name()
|
||||
self.type_name(),
|
||||
ObjectInterfaces::from_object(self),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: CircuitHolder> SourceCode for T {
|
||||
fn debug_source_code(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, "source_code: {:?}", self.get_source_code())
|
||||
}
|
||||
fn get_line(&self, line: usize) -> Result<Instruction, ICError> {
|
||||
let ic = self.get_ic().ok_or(ICError::DeviceHasNoIC)?;
|
||||
let result = ic
|
||||
@@ -546,4 +561,3 @@ impl<T: CircuitHolder> SourceCode for T {
|
||||
.unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ tsify = { version = "0.4.5", features = ["js"] }
|
||||
thiserror = "1.0.61"
|
||||
serde_derive = "1.0.203"
|
||||
serde_json = "1.0.117"
|
||||
tracing-wasm = "0.2.1"
|
||||
|
||||
[features]
|
||||
default = ["console_error_panic_hook"]
|
||||
|
||||
@@ -478,6 +478,7 @@ impl Default for VMRef {
|
||||
#[wasm_bindgen]
|
||||
pub fn init() -> VMRef {
|
||||
utils::set_panic_hook();
|
||||
tracing_wasm::set_as_global_default();
|
||||
let vm = VMRef::new();
|
||||
log!("Hello from ic10emu!");
|
||||
vm
|
||||
|
||||
@@ -6,11 +6,13 @@ 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
|
||||
reagent_database = [] # compile with the reagent_database enabled
|
||||
tsify = ["dep:tsify", "dep:wasm-bindgen"]
|
||||
wasm-bindgen = ["dep:wasm-bindgen"]
|
||||
|
||||
[dependencies]
|
||||
const-crc32 = "1.3.0"
|
||||
num-integer = "0.1.46"
|
||||
phf = "0.11.2"
|
||||
serde = "1.0.202"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
581
stationeers_data/src/database/reagent_map.rs
Normal file
581
stationeers_data/src/database/reagent_map.rs
Normal file
@@ -0,0 +1,581 @@
|
||||
// =================================================
|
||||
// !! <-----> DO NOT MODIFY <-----> !!
|
||||
//
|
||||
// This module was automatically generated by an
|
||||
// xtask
|
||||
//
|
||||
// run
|
||||
//
|
||||
// `cargo xtask generate -m database`
|
||||
//
|
||||
// from the workspace to regenerate
|
||||
//
|
||||
// =================================================
|
||||
|
||||
use crate::templates::Reagent;
|
||||
pub fn build_reagent_database() -> std::collections::BTreeMap<
|
||||
u8,
|
||||
crate::templates::Reagent,
|
||||
> {
|
||||
#[allow(clippy::unreadable_literal)]
|
||||
let mut map: std::collections::BTreeMap<u8, crate::templates::Reagent> = std::collections::BTreeMap::new();
|
||||
map.insert(
|
||||
20u8,
|
||||
Reagent {
|
||||
id: 20u8,
|
||||
name: "Alcohol".into(),
|
||||
hash: 1565803737i32,
|
||||
unit: "ml".into(),
|
||||
is_organic: true,
|
||||
sources: vec![].into_iter().collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
36u8,
|
||||
Reagent {
|
||||
id: 36u8,
|
||||
name: "Astroloy".into(),
|
||||
hash: -1493155787i32,
|
||||
unit: "g".into(),
|
||||
is_organic: true,
|
||||
sources: vec![("ItemAstroloyIngot".into(), 1f64)].into_iter().collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
40u8,
|
||||
Reagent {
|
||||
id: 40u8,
|
||||
name: "Biomass".into(),
|
||||
hash: 925270362i32,
|
||||
unit: "".into(),
|
||||
is_organic: true,
|
||||
sources: vec![("ItemBiomass".into(), 1f64)].into_iter().collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
5u8,
|
||||
Reagent {
|
||||
id: 5u8,
|
||||
name: "Carbon".into(),
|
||||
hash: 1582746610i32,
|
||||
unit: "g".into(),
|
||||
is_organic: true,
|
||||
sources: vec![("HumanSkull".into(), 1f64), ("ItemCharcoal".into(), 1f64)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
37u8,
|
||||
Reagent {
|
||||
id: 37u8,
|
||||
name: "Cobalt".into(),
|
||||
hash: 1702246124i32,
|
||||
unit: "g".into(),
|
||||
is_organic: true,
|
||||
sources: vec![("ItemCobaltOre".into(), 1f64)].into_iter().collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
44u8,
|
||||
Reagent {
|
||||
id: 44u8,
|
||||
name: "Cocoa".into(),
|
||||
hash: 678781198i32,
|
||||
unit: "g".into(),
|
||||
is_organic: true,
|
||||
sources: vec![
|
||||
("ItemCocoaPowder".into(), 1f64), ("ItemCocoaTree".into(), 1f64)
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
27u8,
|
||||
Reagent {
|
||||
id: 27u8,
|
||||
name: "ColorBlue".into(),
|
||||
hash: 557517660i32,
|
||||
unit: "g".into(),
|
||||
is_organic: true,
|
||||
sources: vec![("ReagentColorBlue".into(), 10f64)].into_iter().collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
26u8,
|
||||
Reagent {
|
||||
id: 26u8,
|
||||
name: "ColorGreen".into(),
|
||||
hash: 2129955242i32,
|
||||
unit: "g".into(),
|
||||
is_organic: true,
|
||||
sources: vec![("ReagentColorGreen".into(), 10f64)].into_iter().collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
29u8,
|
||||
Reagent {
|
||||
id: 29u8,
|
||||
name: "ColorOrange".into(),
|
||||
hash: 1728153015i32,
|
||||
unit: "g".into(),
|
||||
is_organic: true,
|
||||
sources: vec![("ReagentColorOrange".into(), 10f64)].into_iter().collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
25u8,
|
||||
Reagent {
|
||||
id: 25u8,
|
||||
name: "ColorRed".into(),
|
||||
hash: 667001276i32,
|
||||
unit: "g".into(),
|
||||
is_organic: true,
|
||||
sources: vec![("ReagentColorRed".into(), 10f64)].into_iter().collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
28u8,
|
||||
Reagent {
|
||||
id: 28u8,
|
||||
name: "ColorYellow".into(),
|
||||
hash: -1430202288i32,
|
||||
unit: "g".into(),
|
||||
is_organic: true,
|
||||
sources: vec![("ReagentColorYellow".into(), 10f64)].into_iter().collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
15u8,
|
||||
Reagent {
|
||||
id: 15u8,
|
||||
name: "Constantan".into(),
|
||||
hash: 1731241392i32,
|
||||
unit: "g".into(),
|
||||
is_organic: true,
|
||||
sources: vec![("ItemConstantanIngot".into(), 1f64)].into_iter().collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
7u8,
|
||||
Reagent {
|
||||
id: 7u8,
|
||||
name: "Copper".into(),
|
||||
hash: -1172078909i32,
|
||||
unit: "g".into(),
|
||||
is_organic: true,
|
||||
sources: vec![
|
||||
("ItemCopperIngot".into(), 1f64), ("ItemCopperOre".into(), 1f64)
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
38u8,
|
||||
Reagent {
|
||||
id: 38u8,
|
||||
name: "Corn".into(),
|
||||
hash: 1550709753i32,
|
||||
unit: "".into(),
|
||||
is_organic: true,
|
||||
sources: vec![("ItemCookedCorn".into(), 1f64), ("ItemCorn".into(), 1f64)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
2u8,
|
||||
Reagent {
|
||||
id: 2u8,
|
||||
name: "Egg".into(),
|
||||
hash: 1887084450i32,
|
||||
unit: "".into(),
|
||||
is_organic: true,
|
||||
sources: vec![
|
||||
("ItemCookedPowderedEggs".into(), 1f64), ("ItemEgg".into(), 1f64),
|
||||
("ItemFertilizedEgg".into(), 1f64)
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
13u8,
|
||||
Reagent {
|
||||
id: 13u8,
|
||||
name: "Electrum".into(),
|
||||
hash: 478264742i32,
|
||||
unit: "g".into(),
|
||||
is_organic: true,
|
||||
sources: vec![("ItemElectrumIngot".into(), 1f64)].into_iter().collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
24u8,
|
||||
Reagent {
|
||||
id: 24u8,
|
||||
name: "Fenoxitone".into(),
|
||||
hash: -865687737i32,
|
||||
unit: "g".into(),
|
||||
is_organic: true,
|
||||
sources: vec![("ItemFern".into(), 1f64)].into_iter().collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
0u8,
|
||||
Reagent {
|
||||
id: 0u8,
|
||||
name: "Flour".into(),
|
||||
hash: -811006991i32,
|
||||
unit: "g".into(),
|
||||
is_organic: true,
|
||||
sources: vec![("ItemFlour".into(), 50f64)].into_iter().collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
4u8,
|
||||
Reagent {
|
||||
id: 4u8,
|
||||
name: "Gold".into(),
|
||||
hash: -409226641i32,
|
||||
unit: "g".into(),
|
||||
is_organic: true,
|
||||
sources: vec![("ItemGoldIngot".into(), 1f64), ("ItemGoldOre".into(), 1f64)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
35u8,
|
||||
Reagent {
|
||||
id: 35u8,
|
||||
name: "Hastelloy".into(),
|
||||
hash: 2019732679i32,
|
||||
unit: "g".into(),
|
||||
is_organic: true,
|
||||
sources: vec![("ItemHastelloyIngot".into(), 1f64)].into_iter().collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
9u8,
|
||||
Reagent {
|
||||
id: 9u8,
|
||||
name: "Hydrocarbon".into(),
|
||||
hash: 2003628602i32,
|
||||
unit: "g".into(),
|
||||
is_organic: true,
|
||||
sources: vec![("ItemCoalOre".into(), 1f64), ("ItemSolidFuel".into(), 1f64)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
34u8,
|
||||
Reagent {
|
||||
id: 34u8,
|
||||
name: "Inconel".into(),
|
||||
hash: -586072179i32,
|
||||
unit: "g".into(),
|
||||
is_organic: true,
|
||||
sources: vec![("ItemInconelIngot".into(), 1f64)].into_iter().collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
14u8,
|
||||
Reagent {
|
||||
id: 14u8,
|
||||
name: "Invar".into(),
|
||||
hash: -626453759i32,
|
||||
unit: "g".into(),
|
||||
is_organic: true,
|
||||
sources: vec![("ItemInvarIngot".into(), 1f64)].into_iter().collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
3u8,
|
||||
Reagent {
|
||||
id: 3u8,
|
||||
name: "Iron".into(),
|
||||
hash: -666742878i32,
|
||||
unit: "g".into(),
|
||||
is_organic: true,
|
||||
sources: vec![("ItemIronIngot".into(), 1f64), ("ItemIronOre".into(), 1f64)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
12u8,
|
||||
Reagent {
|
||||
id: 12u8,
|
||||
name: "Lead".into(),
|
||||
hash: -2002530571i32,
|
||||
unit: "g".into(),
|
||||
is_organic: true,
|
||||
sources: vec![("ItemLeadIngot".into(), 1f64), ("ItemLeadOre".into(), 1f64)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
1u8,
|
||||
Reagent {
|
||||
id: 1u8,
|
||||
name: "Milk".into(),
|
||||
hash: 471085864i32,
|
||||
unit: "ml".into(),
|
||||
is_organic: true,
|
||||
sources: vec![
|
||||
("ItemCookedCondensedMilk".into(), 1f64), ("ItemMilk".into(), 1f64)
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
42u8,
|
||||
Reagent {
|
||||
id: 42u8,
|
||||
name: "Mushroom".into(),
|
||||
hash: 516242109i32,
|
||||
unit: "g".into(),
|
||||
is_organic: true,
|
||||
sources: vec![
|
||||
("ItemCookedMushroom".into(), 1f64), ("ItemMushroom".into(), 1f64)
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
11u8,
|
||||
Reagent {
|
||||
id: 11u8,
|
||||
name: "Nickel".into(),
|
||||
hash: 556601662i32,
|
||||
unit: "g".into(),
|
||||
is_organic: true,
|
||||
sources: vec![
|
||||
("ItemNickelIngot".into(), 1f64), ("ItemNickelOre".into(), 1f64)
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
21u8,
|
||||
Reagent {
|
||||
id: 21u8,
|
||||
name: "Oil".into(),
|
||||
hash: 1958538866i32,
|
||||
unit: "ml".into(),
|
||||
is_organic: true,
|
||||
sources: vec![("ItemSoyOil".into(), 1f64)].into_iter().collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
17u8,
|
||||
Reagent {
|
||||
id: 17u8,
|
||||
name: "Plastic".into(),
|
||||
hash: 791382247i32,
|
||||
unit: "g".into(),
|
||||
is_organic: true,
|
||||
sources: vec![].into_iter().collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
22u8,
|
||||
Reagent {
|
||||
id: 22u8,
|
||||
name: "Potato".into(),
|
||||
hash: -1657266385i32,
|
||||
unit: "".into(),
|
||||
is_organic: true,
|
||||
sources: vec![("ItemPotato".into(), 1f64), ("ItemPotatoBaked".into(), 1f64)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
30u8,
|
||||
Reagent {
|
||||
id: 30u8,
|
||||
name: "Pumpkin".into(),
|
||||
hash: -1250164309i32,
|
||||
unit: "".into(),
|
||||
is_organic: true,
|
||||
sources: vec![
|
||||
("ItemCookedPumpkin".into(), 1f64), ("ItemPumpkin".into(), 1f64)
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
31u8,
|
||||
Reagent {
|
||||
id: 31u8,
|
||||
name: "Rice".into(),
|
||||
hash: 1951286569i32,
|
||||
unit: "g".into(),
|
||||
is_organic: true,
|
||||
sources: vec![("ItemCookedRice".into(), 1f64), ("ItemRice".into(), 1f64)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
19u8,
|
||||
Reagent {
|
||||
id: 19u8,
|
||||
name: "SalicylicAcid".into(),
|
||||
hash: -2086114347i32,
|
||||
unit: "g".into(),
|
||||
is_organic: true,
|
||||
sources: vec![].into_iter().collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
18u8,
|
||||
Reagent {
|
||||
id: 18u8,
|
||||
name: "Silicon".into(),
|
||||
hash: -1195893171i32,
|
||||
unit: "g".into(),
|
||||
is_organic: true,
|
||||
sources: vec![
|
||||
("ItemSiliconIngot".into(), 0.1f64), ("ItemSiliconOre".into(), 1f64)
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
10u8,
|
||||
Reagent {
|
||||
id: 10u8,
|
||||
name: "Silver".into(),
|
||||
hash: 687283565i32,
|
||||
unit: "g".into(),
|
||||
is_organic: true,
|
||||
sources: vec![
|
||||
("ItemSilverIngot".into(), 1f64), ("ItemSilverOre".into(), 1f64)
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
16u8,
|
||||
Reagent {
|
||||
id: 16u8,
|
||||
name: "Solder".into(),
|
||||
hash: -1206542381i32,
|
||||
unit: "g".into(),
|
||||
is_organic: true,
|
||||
sources: vec![("ItemSolderIngot".into(), 1f64)].into_iter().collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
41u8,
|
||||
Reagent {
|
||||
id: 41u8,
|
||||
name: "Soy".into(),
|
||||
hash: 1510471435i32,
|
||||
unit: "".into(),
|
||||
is_organic: true,
|
||||
sources: vec![
|
||||
("ItemCookedSoybean".into(), 1f64), ("ItemSoybean".into(), 1f64)
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
8u8,
|
||||
Reagent {
|
||||
id: 8u8,
|
||||
name: "Steel".into(),
|
||||
hash: 1331613335i32,
|
||||
unit: "g".into(),
|
||||
is_organic: true,
|
||||
sources: vec![("ItemEmptyCan".into(), 1f64), ("ItemSteelIngot".into(), 1f64)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
33u8,
|
||||
Reagent {
|
||||
id: 33u8,
|
||||
name: "Stellite".into(),
|
||||
hash: -500544800i32,
|
||||
unit: "g".into(),
|
||||
is_organic: true,
|
||||
sources: vec![("ItemStelliteIngot".into(), 1f64)].into_iter().collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
43u8,
|
||||
Reagent {
|
||||
id: 43u8,
|
||||
name: "Sugar".into(),
|
||||
hash: 1778746875i32,
|
||||
unit: "g".into(),
|
||||
is_organic: true,
|
||||
sources: vec![("ItemSugar".into(), 10f64), ("ItemSugarCane".into(), 1f64)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
23u8,
|
||||
Reagent {
|
||||
id: 23u8,
|
||||
name: "Tomato".into(),
|
||||
hash: 733496620i32,
|
||||
unit: "".into(),
|
||||
is_organic: true,
|
||||
sources: vec![("ItemCookedTomato".into(), 1f64), ("ItemTomato".into(), 1f64)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
6u8,
|
||||
Reagent {
|
||||
id: 6u8,
|
||||
name: "Uranium".into(),
|
||||
hash: -208860272i32,
|
||||
unit: "g".into(),
|
||||
is_organic: true,
|
||||
sources: vec![("ItemUraniumOre".into(), 1f64)].into_iter().collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
32u8,
|
||||
Reagent {
|
||||
id: 32u8,
|
||||
name: "Waspaloy".into(),
|
||||
hash: 1787814293i32,
|
||||
unit: "g".into(),
|
||||
is_organic: true,
|
||||
sources: vec![("ItemWaspaloyIngot".into(), 1f64)].into_iter().collect(),
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
39u8,
|
||||
Reagent {
|
||||
id: 39u8,
|
||||
name: "Wheat".into(),
|
||||
hash: -686695134i32,
|
||||
unit: "".into(),
|
||||
is_organic: true,
|
||||
sources: vec![("ItemWheat".into(), 1f64)].into_iter().collect(),
|
||||
},
|
||||
);
|
||||
map
|
||||
}
|
||||
@@ -2001,6 +2001,12 @@ impl std::str::FromStr for BasicEnum {
|
||||
"logictype.stress" => Ok(Self::LogicType(LogicType::Stress)),
|
||||
"logictype.survey" => Ok(Self::LogicType(LogicType::Survey)),
|
||||
"logictype.targetpadindex" => Ok(Self::LogicType(LogicType::TargetPadIndex)),
|
||||
"logictype.targetprefabhash" => {
|
||||
Ok(Self::LogicType(LogicType::TargetPrefabHash))
|
||||
}
|
||||
"logictype.targetslotindex" => {
|
||||
Ok(Self::LogicType(LogicType::TargetSlotIndex))
|
||||
}
|
||||
"logictype.targetx" => Ok(Self::LogicType(LogicType::TargetX)),
|
||||
"logictype.targety" => Ok(Self::LogicType(LogicType::TargetY)),
|
||||
"logictype.targetz" => Ok(Self::LogicType(LogicType::TargetZ)),
|
||||
|
||||
@@ -1255,6 +1255,9 @@ pub enum StationpediaPrefab {
|
||||
)
|
||||
)]
|
||||
ItemWallCooler = -1567752627i32,
|
||||
#[strum(serialize = "StructureLarreDockCargo")]
|
||||
#[strum(props(name = "LARrE Dock (Cargo)", desc = "", value = "-1555459562"))]
|
||||
StructureLarreDockCargo = -1555459562i32,
|
||||
#[strum(serialize = "StructureSolarPanel45")]
|
||||
#[strum(
|
||||
props(
|
||||
@@ -2153,6 +2156,9 @@ pub enum StationpediaPrefab {
|
||||
props(name = "Kitchen Table (Simple Tall)", desc = "", value = "-1068629349")
|
||||
)]
|
||||
KitchenTableSimpleTall = -1068629349i32,
|
||||
#[strum(serialize = "ItemKitLarreDockCargo")]
|
||||
#[strum(props(name = "Kit (LArRE Dock Cargo)", desc = "", value = "-1067485367"))]
|
||||
ItemKitLarreDockCargo = -1067485367i32,
|
||||
#[strum(serialize = "ItemGasFilterOxygenM")]
|
||||
#[strum(props(name = "Medium Filter (Oxygen)", desc = "", value = "-1067319543"))]
|
||||
ItemGasFilterOxygenM = -1067319543i32,
|
||||
@@ -2341,6 +2347,9 @@ pub enum StationpediaPrefab {
|
||||
#[strum(serialize = "ItemKitElevator")]
|
||||
#[strum(props(name = "Kit (Elevator)", desc = "", value = "-945806652"))]
|
||||
ItemKitElevator = -945806652i32,
|
||||
#[strum(serialize = "ItemKitLarreDockBypass")]
|
||||
#[strum(props(name = "Kit (LArRE Dock Bypass)", desc = "", value = "-940470326"))]
|
||||
ItemKitLarreDockBypass = -940470326i32,
|
||||
#[strum(serialize = "StructureSolarPanelReinforced")]
|
||||
#[strum(
|
||||
props(
|
||||
@@ -3086,6 +3095,15 @@ pub enum StationpediaPrefab {
|
||||
#[strum(serialize = "StructurePipeLiquidOneWayValveLever")]
|
||||
#[strum(props(name = "One Way Valve (Liquid)", desc = "", value = "-523832822"))]
|
||||
StructurePipeLiquidOneWayValveLever = -523832822i32,
|
||||
#[strum(serialize = "StructureLarreDockCollector")]
|
||||
#[strum(
|
||||
props(
|
||||
name = "LARrE Dock (Collector)",
|
||||
desc = "0.Outward\n1.Inward",
|
||||
value = "-522428667"
|
||||
)
|
||||
)]
|
||||
StructureLarreDockCollector = -522428667i32,
|
||||
#[strum(serialize = "StructureWaterDigitalValve")]
|
||||
#[strum(props(name = "Liquid Digital Valve", desc = "", value = "-517628750"))]
|
||||
StructureWaterDigitalValve = -517628750i32,
|
||||
@@ -4023,6 +4041,9 @@ pub enum StationpediaPrefab {
|
||||
#[strum(serialize = "CartridgeTracker")]
|
||||
#[strum(props(name = "Cartridge (Tracker)", desc = "", value = "81488783"))]
|
||||
CartridgeTracker = 81488783i32,
|
||||
#[strum(serialize = "StructureLarreDockHydroponics")]
|
||||
#[strum(props(name = "LARrE Dock (Hydroponics)", desc = "", value = "85133079"))]
|
||||
StructureLarreDockHydroponics = 85133079i32,
|
||||
#[strum(serialize = "ToyLuna")]
|
||||
#[strum(props(name = "Toy Luna", desc = "", value = "94730034"))]
|
||||
ToyLuna = 94730034i32,
|
||||
@@ -4604,6 +4625,9 @@ pub enum StationpediaPrefab {
|
||||
)
|
||||
)]
|
||||
StructurePictureFrameThickMountLandscapeSmall = 347154462i32,
|
||||
#[strum(serialize = "ItemKitLarreDockCollector")]
|
||||
#[strum(props(name = "Kit (LArRE Dock Collector)", desc = "", value = "347658127"))]
|
||||
ItemKitLarreDockCollector = 347658127i32,
|
||||
#[strum(serialize = "RoverCargo")]
|
||||
#[strum(
|
||||
props(
|
||||
@@ -4652,6 +4676,9 @@ pub enum StationpediaPrefab {
|
||||
#[strum(serialize = "ItemMiningPackage")]
|
||||
#[strum(props(name = "Mining Supplies Package", desc = "", value = "384478267"))]
|
||||
ItemMiningPackage = 384478267i32,
|
||||
#[strum(serialize = "ItemKitLarreDockAtmos")]
|
||||
#[strum(props(name = "Kit (LArRE Dock Atmos)", desc = "", value = "385528206"))]
|
||||
ItemKitLarreDockAtmos = 385528206i32,
|
||||
#[strum(serialize = "ItemPureIceNitrous")]
|
||||
#[strum(
|
||||
props(
|
||||
@@ -5086,6 +5113,11 @@ pub enum StationpediaPrefab {
|
||||
)
|
||||
)]
|
||||
ItemRocketMiningDrillHeadHighSpeedIce = 653461728i32,
|
||||
#[strum(serialize = "ItemKitLarreDockHydroponics")]
|
||||
#[strum(
|
||||
props(name = "Kit (LArRE Dock Hydroponics)", desc = "", value = "656181408")
|
||||
)]
|
||||
ItemKitLarreDockHydroponics = 656181408i32,
|
||||
#[strum(serialize = "ItemWreckageStructureWeatherStation007")]
|
||||
#[strum(props(name = "Wreckage", desc = "", value = "656649558"))]
|
||||
ItemWreckageStructureWeatherStation007 = 656649558i32,
|
||||
@@ -5724,6 +5756,9 @@ pub enum StationpediaPrefab {
|
||||
)
|
||||
)]
|
||||
EntityChickenWhite = 1010807532i32,
|
||||
#[strum(serialize = "StructureLarreDockBypass")]
|
||||
#[strum(props(name = "LARrE Dock (Bypass)", desc = "", value = "1011275082"))]
|
||||
StructureLarreDockBypass = 1011275082i32,
|
||||
#[strum(serialize = "ItemKitStacker")]
|
||||
#[strum(props(name = "Kit (Stacker)", desc = "", value = "1013244511"))]
|
||||
ItemKitStacker = 1013244511i32,
|
||||
@@ -7396,6 +7431,15 @@ pub enum StationpediaPrefab {
|
||||
#[strum(serialize = "StructureRoboticArmRailCornerStop")]
|
||||
#[strum(props(name = "Linear Rail Corner Station", desc = "", value = "1974053060"))]
|
||||
StructureRoboticArmRailCornerStop = 1974053060i32,
|
||||
#[strum(serialize = "StructureLarreDockAtmos")]
|
||||
#[strum(
|
||||
props(
|
||||
name = "LARrE Dock (Atmos)",
|
||||
desc = "0.Outward\n1.Inward",
|
||||
value = "1978422481"
|
||||
)
|
||||
)]
|
||||
StructureLarreDockAtmos = 1978422481i32,
|
||||
#[strum(serialize = "StructureWallGeometryCorner")]
|
||||
#[strum(props(name = "Wall (Geometry Corner)", desc = "", value = "1979212240"))]
|
||||
StructureWallGeometryCorner = 1979212240i32,
|
||||
|
||||
@@ -2103,6 +2103,17 @@ pub enum LogicType {
|
||||
)
|
||||
)]
|
||||
Altitude = 269u16,
|
||||
#[strum(serialize = "TargetSlotIndex")]
|
||||
#[strum(
|
||||
props(
|
||||
docs = "The slot index that the target device that this device will try to interact with",
|
||||
value = "270"
|
||||
)
|
||||
)]
|
||||
TargetSlotIndex = 270u16,
|
||||
#[strum(serialize = "TargetPrefabHash")]
|
||||
#[strum(props(docs = "The prefab", value = "271"))]
|
||||
TargetPrefabHash = 271u16,
|
||||
}
|
||||
impl TryFrom<f64> for LogicType {
|
||||
type Error = super::ParseError;
|
||||
|
||||
@@ -173,8 +173,22 @@ pub fn build_prefab_database() -> Option<BTreeMap<i32, templates::ObjectTemplate
|
||||
map
|
||||
}
|
||||
|
||||
#[cfg(feature = "prefab_database")]
|
||||
pub mod database {
|
||||
mod prefab_map;
|
||||
pub use prefab_map::build_prefab_database;
|
||||
pub fn build_reagent_database() -> Option<BTreeMap<u8, templates::Reagent>> {
|
||||
#[cfg(feature = "reagent_database")]
|
||||
let map = Some(database::build_reagent_database());
|
||||
#[cfg(not(feature = "reagent_database"))]
|
||||
let map = None;
|
||||
|
||||
map
|
||||
}
|
||||
|
||||
pub mod database {
|
||||
#[cfg(feature = "prefab_database")]
|
||||
mod prefab_map;
|
||||
#[cfg(feature = "prefab_database")]
|
||||
pub use prefab_map::build_prefab_database;
|
||||
#[cfg(feature = "reagent_database")]
|
||||
mod reagent_map;
|
||||
#[cfg(feature = "reagent_database")]
|
||||
pub use reagent_map::build_reagent_database;
|
||||
}
|
||||
|
||||
@@ -179,7 +179,7 @@ impl From<HumanTemplate> for ObjectTemplate {
|
||||
pub struct HumanTemplate {
|
||||
pub prefab: PrefabInfo,
|
||||
pub species: Species,
|
||||
pub slots: Vec<SlotInfo>,
|
||||
pub slots: BTreeMap<u32, SlotInfo>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
|
||||
@@ -193,21 +193,31 @@ pub struct PrefabInfo {
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
|
||||
pub struct SlotInfo {
|
||||
pub name: String,
|
||||
pub typ: Class,
|
||||
pub enum SlotInfo {
|
||||
Direct {
|
||||
name: String,
|
||||
class: Class,
|
||||
index: u32,
|
||||
},
|
||||
Proxy {
|
||||
name: String,
|
||||
index: u32,
|
||||
},
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
|
||||
pub struct LogicInfo {
|
||||
#[serde_as( as = "BTreeMap<DisplayFromStr, _>")]
|
||||
#[cfg_attr(feature = "tsify", tsify(type = "Map<string, Map<LogicSlotType, MemoryAccess>>"))]
|
||||
#[serde_as(as = "BTreeMap<DisplayFromStr, _>")]
|
||||
#[cfg_attr(
|
||||
feature = "tsify",
|
||||
tsify(type = "Map<string, Map<LogicSlotType, MemoryAccess>>")
|
||||
)]
|
||||
pub logic_slot_types: BTreeMap<u32, BTreeMap<LogicSlotType, MemoryAccess>>,
|
||||
pub logic_types: BTreeMap<LogicType, MemoryAccess>,
|
||||
#[serde_as( as = "Option<BTreeMap<DisplayFromStr, _>>")]
|
||||
#[cfg_attr(feature = "tsify", tsify(type = "Map<string, string> | undefined"))]
|
||||
#[serde_as(as = "Option<BTreeMap<DisplayFromStr, _>>")]
|
||||
#[cfg_attr(feature = "tsify", tsify(optional, type = "Map<string, string>"))]
|
||||
pub modes: Option<BTreeMap<u32, String>>,
|
||||
pub transmission_receiver: bool,
|
||||
pub wireless_logic: bool,
|
||||
@@ -218,9 +228,11 @@ pub struct LogicInfo {
|
||||
#[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
|
||||
pub struct ItemInfo {
|
||||
pub consumable: bool,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub filter_type: Option<GasType>,
|
||||
pub ingredient: bool,
|
||||
pub max_quantity: u32,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub reagents: Option<BTreeMap<String, f64>>,
|
||||
pub slot_class: Class,
|
||||
pub sorting_class: SortingClass,
|
||||
@@ -238,6 +250,7 @@ pub struct ConnectionInfo {
|
||||
#[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
|
||||
pub struct DeviceInfo {
|
||||
pub connection_list: Vec<ConnectionInfo>,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub device_pins_length: Option<u32>,
|
||||
pub has_activate_state: bool,
|
||||
pub has_atmosphere: bool,
|
||||
@@ -256,6 +269,24 @@ pub struct ConsumerInfo {
|
||||
pub processed_reagents: Vec<i32>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
|
||||
pub struct Reagent {
|
||||
pub id: u8,
|
||||
pub name: String,
|
||||
pub hash: i32,
|
||||
pub unit: String,
|
||||
pub is_organic: bool,
|
||||
pub sources: BTreeMap<String, f64>,
|
||||
}
|
||||
|
||||
impl Reagent {
|
||||
pub fn with_name(mut self, name: impl Into<String>) -> Self {
|
||||
self.name = name.into();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
|
||||
pub struct RecipeRange {
|
||||
@@ -276,6 +307,8 @@ pub struct RecipeGasMix {
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
|
||||
pub struct Recipe {
|
||||
pub target_prefab: String,
|
||||
pub target_prefab_hash: i32,
|
||||
pub tier: MachineTier,
|
||||
pub time: f64,
|
||||
pub energy: f64,
|
||||
@@ -286,11 +319,27 @@ pub struct Recipe {
|
||||
pub reagents: BTreeMap<String, f64>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
|
||||
pub struct RecipeOrder {
|
||||
pub recipe: Recipe,
|
||||
pub quantity: u32,
|
||||
}
|
||||
|
||||
impl Recipe {
|
||||
pub fn with_target(mut self, prefab: impl Into<String>) -> Self {
|
||||
let prefab: String = prefab.into();
|
||||
self.target_prefab_hash = const_crc32::crc32(prefab.as_bytes()) as i32;
|
||||
self.target_prefab = prefab;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
|
||||
pub struct FabricatorInfo {
|
||||
pub tier: MachineTier,
|
||||
pub recipes: BTreeMap<String, Recipe>,
|
||||
pub recipes: Vec<Recipe>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
|
||||
@@ -334,6 +383,7 @@ pub struct Instruction {
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
|
||||
pub struct MemoryInfo {
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub instructions: Option<BTreeMap<String, Instruction>>,
|
||||
pub memory_access: MemoryAccess,
|
||||
pub memory_size: u32,
|
||||
@@ -364,7 +414,9 @@ pub struct SuitInfo {
|
||||
pub struct StructureTemplate {
|
||||
pub prefab: PrefabInfo,
|
||||
pub structure: StructureInfo,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
}
|
||||
|
||||
@@ -373,9 +425,11 @@ pub struct StructureTemplate {
|
||||
pub struct StructureSlotsTemplate {
|
||||
pub prefab: PrefabInfo,
|
||||
pub structure: StructureInfo,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub slots: Vec<SlotInfo>,
|
||||
pub slots: BTreeMap<u32, SlotInfo>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
|
||||
@@ -383,10 +437,12 @@ pub struct StructureSlotsTemplate {
|
||||
pub struct StructureLogicTemplate {
|
||||
pub prefab: PrefabInfo,
|
||||
pub structure: StructureInfo,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub logic: LogicInfo,
|
||||
pub slots: Vec<SlotInfo>,
|
||||
pub slots: BTreeMap<u32, SlotInfo>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
|
||||
@@ -394,10 +450,12 @@ pub struct StructureLogicTemplate {
|
||||
pub struct StructureLogicDeviceTemplate {
|
||||
pub prefab: PrefabInfo,
|
||||
pub structure: StructureInfo,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub logic: LogicInfo,
|
||||
pub slots: Vec<SlotInfo>,
|
||||
pub slots: BTreeMap<u32, SlotInfo>,
|
||||
pub device: DeviceInfo,
|
||||
}
|
||||
|
||||
@@ -406,12 +464,15 @@ pub struct StructureLogicDeviceTemplate {
|
||||
pub struct StructureLogicDeviceConsumerTemplate {
|
||||
pub prefab: PrefabInfo,
|
||||
pub structure: StructureInfo,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub logic: LogicInfo,
|
||||
pub slots: Vec<SlotInfo>,
|
||||
pub slots: BTreeMap<u32, SlotInfo>,
|
||||
pub device: DeviceInfo,
|
||||
pub consumer_info: ConsumerInfo,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub fabricator_info: Option<FabricatorInfo>,
|
||||
}
|
||||
|
||||
@@ -420,10 +481,12 @@ pub struct StructureLogicDeviceConsumerTemplate {
|
||||
pub struct StructureLogicDeviceMemoryTemplate {
|
||||
pub prefab: PrefabInfo,
|
||||
pub structure: StructureInfo,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub logic: LogicInfo,
|
||||
pub slots: Vec<SlotInfo>,
|
||||
pub slots: BTreeMap<u32, SlotInfo>,
|
||||
pub device: DeviceInfo,
|
||||
pub memory: MemoryInfo,
|
||||
}
|
||||
@@ -433,10 +496,12 @@ pub struct StructureLogicDeviceMemoryTemplate {
|
||||
pub struct StructureCircuitHolderTemplate {
|
||||
pub prefab: PrefabInfo,
|
||||
pub structure: StructureInfo,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub logic: LogicInfo,
|
||||
pub slots: Vec<SlotInfo>,
|
||||
pub slots: BTreeMap<u32, SlotInfo>,
|
||||
pub device: DeviceInfo,
|
||||
}
|
||||
|
||||
@@ -445,12 +510,15 @@ pub struct StructureCircuitHolderTemplate {
|
||||
pub struct StructureLogicDeviceConsumerMemoryTemplate {
|
||||
pub prefab: PrefabInfo,
|
||||
pub structure: StructureInfo,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub logic: LogicInfo,
|
||||
pub slots: Vec<SlotInfo>,
|
||||
pub slots: BTreeMap<u32, SlotInfo>,
|
||||
pub device: DeviceInfo,
|
||||
pub consumer_info: ConsumerInfo,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub fabricator_info: Option<FabricatorInfo>,
|
||||
pub memory: MemoryInfo,
|
||||
}
|
||||
@@ -460,7 +528,9 @@ pub struct StructureLogicDeviceConsumerMemoryTemplate {
|
||||
pub struct ItemTemplate {
|
||||
pub prefab: PrefabInfo,
|
||||
pub item: ItemInfo,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
}
|
||||
|
||||
@@ -469,9 +539,11 @@ pub struct ItemTemplate {
|
||||
pub struct ItemSlotsTemplate {
|
||||
pub prefab: PrefabInfo,
|
||||
pub item: ItemInfo,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub slots: Vec<SlotInfo>,
|
||||
pub slots: BTreeMap<u32, SlotInfo>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
|
||||
@@ -479,9 +551,11 @@ pub struct ItemSlotsTemplate {
|
||||
pub struct ItemConsumerTemplate {
|
||||
pub prefab: PrefabInfo,
|
||||
pub item: ItemInfo,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub slots: Vec<SlotInfo>,
|
||||
pub slots: BTreeMap<u32, SlotInfo>,
|
||||
pub consumer_info: ConsumerInfo,
|
||||
}
|
||||
|
||||
@@ -490,10 +564,12 @@ pub struct ItemConsumerTemplate {
|
||||
pub struct ItemLogicTemplate {
|
||||
pub prefab: PrefabInfo,
|
||||
pub item: ItemInfo,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub logic: LogicInfo,
|
||||
pub slots: Vec<SlotInfo>,
|
||||
pub slots: BTreeMap<u32, SlotInfo>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
|
||||
@@ -501,10 +577,12 @@ pub struct ItemLogicTemplate {
|
||||
pub struct ItemLogicMemoryTemplate {
|
||||
pub prefab: PrefabInfo,
|
||||
pub item: ItemInfo,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub logic: LogicInfo,
|
||||
pub slots: Vec<SlotInfo>,
|
||||
pub slots: BTreeMap<u32, SlotInfo>,
|
||||
pub memory: MemoryInfo,
|
||||
}
|
||||
|
||||
@@ -513,10 +591,12 @@ pub struct ItemLogicMemoryTemplate {
|
||||
pub struct ItemCircuitHolderTemplate {
|
||||
pub prefab: PrefabInfo,
|
||||
pub item: ItemInfo,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub logic: LogicInfo,
|
||||
pub slots: Vec<SlotInfo>,
|
||||
pub slots: BTreeMap<u32, SlotInfo>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
|
||||
@@ -524,9 +604,11 @@ pub struct ItemCircuitHolderTemplate {
|
||||
pub struct ItemSuitTemplate {
|
||||
pub prefab: PrefabInfo,
|
||||
pub item: ItemInfo,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub slots: Vec<SlotInfo>,
|
||||
pub slots: BTreeMap<u32, SlotInfo>,
|
||||
pub suit_info: SuitInfo,
|
||||
}
|
||||
|
||||
@@ -535,10 +617,12 @@ pub struct ItemSuitTemplate {
|
||||
pub struct ItemSuitLogicTemplate {
|
||||
pub prefab: PrefabInfo,
|
||||
pub item: ItemInfo,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub logic: LogicInfo,
|
||||
pub slots: Vec<SlotInfo>,
|
||||
pub slots: BTreeMap<u32, SlotInfo>,
|
||||
pub suit_info: SuitInfo,
|
||||
}
|
||||
|
||||
@@ -547,10 +631,12 @@ pub struct ItemSuitLogicTemplate {
|
||||
pub struct ItemSuitCircuitHolderTemplate {
|
||||
pub prefab: PrefabInfo,
|
||||
pub item: ItemInfo,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
#[cfg_attr(feature = "tsify", tsify(optional))]
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub logic: LogicInfo,
|
||||
pub slots: Vec<SlotInfo>,
|
||||
pub slots: BTreeMap<u32, SlotInfo>,
|
||||
pub suit_info: SuitInfo,
|
||||
pub memory: MemoryInfo,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user