refactor(vm): rework object freazing
- let vm carry object dtabase - seperate frozen object info and templates
This commit is contained in:
12631
data/database.json
12631
data/database.json
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,7 @@
|
||||
use crate::vm::{
|
||||
instructions::enums::InstructionOp,
|
||||
object::{
|
||||
errors::{LogicError, MemoryError},
|
||||
ObjectID,
|
||||
errors::{LogicError, MemoryError}, templates::Prefab, ObjectID
|
||||
},
|
||||
};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
@@ -42,14 +41,24 @@ pub enum VMError {
|
||||
NotAnItem(ObjectID),
|
||||
#[error("object {0} is not programmable")]
|
||||
NotProgrammable(ObjectID),
|
||||
#[error("{0}")]
|
||||
TemplateError(#[from] TemplateError),
|
||||
#[error("missing child object {0}")]
|
||||
MissingChild(ObjectID),
|
||||
#[error("object {0} is not parentable")]
|
||||
NotParentable(ObjectID),
|
||||
}
|
||||
|
||||
#[derive(Error, Debug, Serialize, Deserialize)]
|
||||
pub enum TemplateError {
|
||||
#[error("object id {0} has a non conforming set of interfaces")]
|
||||
NonConformingObject(ObjectID),
|
||||
#[error("ObjectID {0} is missing fomr the VM")]
|
||||
#[error("object id {0} is missing from the VM")]
|
||||
MissingVMObject(ObjectID),
|
||||
#[error("database has no template for prefab {0}")]
|
||||
NoTemplateForPrefab(Prefab),
|
||||
#[error("no prefab provided")]
|
||||
MissingPrefab,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
|
||||
@@ -10,8 +10,8 @@ use crate::{
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use stationeers_data::enums::{
|
||||
basic_enums::BasicEnum,
|
||||
script_enums::{LogicBatchMethod, LogicReagentMode, LogicSlotType, LogicType},
|
||||
basic::BasicEnum,
|
||||
script::{LogicBatchMethod, LogicReagentMode, LogicSlotType, LogicType},
|
||||
};
|
||||
use std::{fmt::Display, str::FromStr};
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
@@ -13,7 +13,7 @@ use crate::{
|
||||
},
|
||||
},
|
||||
};
|
||||
use stationeers_data::enums::script_enums::LogicReagentMode;
|
||||
use stationeers_data::enums::script::LogicReagentMode;
|
||||
pub trait IC10Marker: IntegratedCircuit {}
|
||||
|
||||
impl<T: IC10Marker> SleepInstruction for T {
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
use std::{collections::HashSet, ops::Deref, rc::Rc};
|
||||
|
||||
use crate::vm::{
|
||||
enums::script_enums::LogicType,
|
||||
object::{
|
||||
errors::LogicError, macros::ObjectInterface, templates::ConnectionInfo, traits::*, Name,
|
||||
ObjectID,
|
||||
},
|
||||
object::{errors::LogicError, macros::ObjectInterface, traits::*, Name, ObjectID},
|
||||
VM,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use macro_rules_attribute::derive;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use stationeers_data::{
|
||||
enums::{script::LogicType, ConnectionRole, ConnectionType},
|
||||
templates::ConnectionInfo,
|
||||
};
|
||||
use strum_macros::{AsRefStr, EnumIter};
|
||||
use thiserror::Error;
|
||||
|
||||
@@ -51,7 +51,6 @@ pub enum Connection {
|
||||
None,
|
||||
}
|
||||
|
||||
|
||||
impl Connection {
|
||||
#[allow(dead_code)]
|
||||
pub fn from_info(typ: ConnectionType, role: ConnectionRole, net: Option<ObjectID>) -> Self {
|
||||
@@ -86,67 +85,64 @@ impl Connection {
|
||||
Self::None => ConnectionInfo {
|
||||
typ: ConnectionType::None,
|
||||
role: ConnectionRole::None,
|
||||
network: None,
|
||||
},
|
||||
Self::CableNetwork {
|
||||
net,
|
||||
typ: CableConnectionType::Data,
|
||||
role,
|
||||
..
|
||||
} => ConnectionInfo {
|
||||
typ: ConnectionType::Data,
|
||||
role: *role,
|
||||
network: *net,
|
||||
},
|
||||
Self::CableNetwork {
|
||||
net,
|
||||
typ: CableConnectionType::Power,
|
||||
role,
|
||||
..
|
||||
} => ConnectionInfo {
|
||||
typ: ConnectionType::Power,
|
||||
role: *role,
|
||||
network: *net,
|
||||
},
|
||||
Self::CableNetwork {
|
||||
net,
|
||||
typ: CableConnectionType::PowerAndData,
|
||||
role,
|
||||
..
|
||||
} => ConnectionInfo {
|
||||
typ: ConnectionType::PowerAndData,
|
||||
role: *role,
|
||||
network: *net,
|
||||
},
|
||||
Self::Chute { role } => ConnectionInfo {
|
||||
typ: ConnectionType::Chute,
|
||||
role: *role,
|
||||
network: None,
|
||||
},
|
||||
Self::Pipe { role } => ConnectionInfo {
|
||||
typ: ConnectionType::Pipe,
|
||||
role: *role,
|
||||
network: None,
|
||||
},
|
||||
Self::PipeLiquid { role } => ConnectionInfo {
|
||||
typ: ConnectionType::PipeLiquid,
|
||||
role: *role,
|
||||
network: None,
|
||||
},
|
||||
Self::Elevator { role } => ConnectionInfo {
|
||||
typ: ConnectionType::Elevator,
|
||||
role: *role,
|
||||
network: None,
|
||||
},
|
||||
Self::LandingPad { role } => ConnectionInfo {
|
||||
typ: ConnectionType::LandingPad,
|
||||
role: *role,
|
||||
network: None,
|
||||
},
|
||||
Self::LaunchPad { role } => ConnectionInfo {
|
||||
typ: ConnectionType::LaunchPad,
|
||||
role: *role,
|
||||
network: None,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_network(&self) -> Option<ObjectID> {
|
||||
match self {
|
||||
Self::CableNetwork { net, .. } => net.clone(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(ObjectInterface!, Debug)]
|
||||
@@ -248,14 +244,14 @@ impl Logicable for CableNetwork {
|
||||
}
|
||||
fn can_slot_logic_read(
|
||||
&self,
|
||||
_slt: crate::vm::enums::script_enums::LogicSlotType,
|
||||
_slt: stationeers_data::enums::script::LogicSlotType,
|
||||
_index: f64,
|
||||
) -> bool {
|
||||
false
|
||||
}
|
||||
fn get_slot_logic(
|
||||
&self,
|
||||
slt: crate::vm::enums::script_enums::LogicSlotType,
|
||||
slt: stationeers_data::enums::script::LogicSlotType,
|
||||
index: f64,
|
||||
) -> Result<f64, LogicError> {
|
||||
Err(LogicError::CantSlotRead(slt, index))
|
||||
|
||||
@@ -5,11 +5,15 @@ use crate::{
|
||||
errors::{ICError, TemplateError, VMError},
|
||||
interpreter::ICState,
|
||||
network::{CableConnectionType, CableNetwork, Connection, FrozenCableNetwork},
|
||||
vm::object::{traits::ParentSlotInfo, ObjectID, VMObject},
|
||||
vm::object::{
|
||||
templates::{FrozenObject, Prefab},
|
||||
traits::ParentSlotInfo,
|
||||
ObjectID, SlotOccupantInfo, VMObject,
|
||||
},
|
||||
};
|
||||
use stationeers_data::{
|
||||
enums::{
|
||||
script_enums::{LogicBatchMethod, LogicSlotType, LogicType},
|
||||
script::{LogicBatchMethod, LogicSlotType, LogicType},
|
||||
ConnectionRole,
|
||||
},
|
||||
templates::ObjectTemplate,
|
||||
@@ -38,6 +42,7 @@ pub struct VM {
|
||||
|
||||
/// list of object id's touched on the last operation
|
||||
operation_modified: RefCell<Vec<ObjectID>>,
|
||||
template_database: Option<BTreeMap<i32, ObjectTemplate>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
@@ -59,6 +64,7 @@ struct VMTransaction {
|
||||
pub wireless_receivers: Vec<ObjectID>,
|
||||
pub id_space: IdSpace,
|
||||
pub networks: BTreeMap<ObjectID, VMTransactionNetwork>,
|
||||
object_parents: BTreeMap<ObjectID, (u32, ObjectID)>,
|
||||
vm: Rc<VM>,
|
||||
}
|
||||
|
||||
@@ -81,6 +87,7 @@ impl VM {
|
||||
network_id_space: RefCell::new(network_id_space),
|
||||
random: Rc::new(RefCell::new(crate::rand_mscorlib::Random::new())),
|
||||
operation_modified: RefCell::new(Vec::new()),
|
||||
template_database: stationeers_data::build_prefab_database(),
|
||||
});
|
||||
|
||||
let default_network = VMObject::new(CableNetwork::new(default_network_key, vm.clone()));
|
||||
@@ -95,13 +102,84 @@ impl VM {
|
||||
self.random.borrow_mut().next_f64()
|
||||
}
|
||||
|
||||
pub fn add_device_from_template(
|
||||
pub fn import_template_database(
|
||||
&mut self,
|
||||
db: impl IntoIterator<Item = (i32, ObjectTemplate)>,
|
||||
) {
|
||||
self.template_database.replace(db.into_iter().collect());
|
||||
}
|
||||
|
||||
pub fn get_template(&self, prefab: Prefab) -> Option<ObjectTemplate> {
|
||||
let hash = match prefab {
|
||||
Prefab::Hash(hash) => hash,
|
||||
Prefab::Name(name) => const_crc32::crc32(name.as_bytes()) as i32,
|
||||
};
|
||||
self.template_database
|
||||
.as_ref()
|
||||
.and_then(|db| db.get(&hash).cloned())
|
||||
}
|
||||
|
||||
pub fn add_devices_frozen(
|
||||
self: &Rc<Self>,
|
||||
template: ObjectTemplate,
|
||||
) -> Result<u32, VMError> {
|
||||
frozen_devices: impl IntoIterator<Item = FrozenObject>,
|
||||
) -> Result<Vec<ObjectID>, VMError> {
|
||||
let mut transaction = VMTransaction::new(self);
|
||||
|
||||
let obj_id = transaction.add_device_from_template(template)?;
|
||||
let mut obj_ids = Vec::new();
|
||||
for frozen in frozen_devices {
|
||||
let obj_id = transaction.add_device_from_frozen(frozen)?;
|
||||
obj_ids.push(obj_id)
|
||||
}
|
||||
|
||||
transaction.finialize()?;
|
||||
|
||||
let transaction_ids = transaction.id_space.in_use_ids();
|
||||
self.id_space.borrow_mut().use_new_ids(&transaction_ids);
|
||||
|
||||
self.objects.borrow_mut().extend(transaction.objects);
|
||||
self.wireless_transmitters
|
||||
.borrow_mut()
|
||||
.extend(transaction.wireless_transmitters);
|
||||
self.wireless_receivers
|
||||
.borrow_mut()
|
||||
.extend(transaction.wireless_receivers);
|
||||
self.circuit_holders
|
||||
.borrow_mut()
|
||||
.extend(transaction.circuit_holders);
|
||||
self.program_holders
|
||||
.borrow_mut()
|
||||
.extend(transaction.program_holders);
|
||||
for (net_id, trans_net) in transaction.networks.into_iter() {
|
||||
let net = self
|
||||
.networks
|
||||
.borrow()
|
||||
.get(&net_id)
|
||||
.cloned()
|
||||
.unwrap_or_else(|| panic!("desync between vm and transaction networks: {net_id}"));
|
||||
let mut net_ref = net.borrow_mut();
|
||||
let net_interface = net_ref
|
||||
.as_mut_network()
|
||||
.unwrap_or_else(|| panic!("non network network: {net_id}"));
|
||||
for id in trans_net.devices {
|
||||
net_interface.add_data(id);
|
||||
}
|
||||
for id in trans_net.power_only {
|
||||
net_interface.add_power(id);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(obj_ids)
|
||||
}
|
||||
|
||||
pub fn add_device_from_frozen(
|
||||
self: &Rc<Self>,
|
||||
frozen: FrozenObject,
|
||||
) -> Result<ObjectID, VMError> {
|
||||
let mut transaction = VMTransaction::new(self);
|
||||
|
||||
let obj_id = transaction.add_device_from_frozen(frozen)?;
|
||||
|
||||
transaction.finialize()?;
|
||||
|
||||
let transaction_ids = transaction.id_space.in_use_ids();
|
||||
self.id_space.borrow_mut().use_new_ids(&transaction_ids);
|
||||
@@ -184,11 +262,11 @@ impl VM {
|
||||
if slot.parent == old_id {
|
||||
slot.parent = new_id;
|
||||
}
|
||||
if slot
|
||||
.occupant
|
||||
.is_some_and(|occupant_id| occupant_id == old_id)
|
||||
{
|
||||
slot.occupant = Some(new_id);
|
||||
match slot.occupant.as_mut() {
|
||||
Some(info) if info.id == old_id => {
|
||||
info.id = new_id;
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -813,33 +891,37 @@ impl VM {
|
||||
.get_slot_mut(index)
|
||||
.ok_or(ICError::SlotIndexOutOfRange(index as f64))?;
|
||||
if let Some(target) = target {
|
||||
if slot.occupant.is_some_and(|occupant| occupant == target) {
|
||||
slot.quantity = quantity;
|
||||
Ok(None)
|
||||
} else {
|
||||
let Some(item_obj) = self.objects.borrow().get(&target).cloned() else {
|
||||
return Err(VMError::UnknownId(id));
|
||||
};
|
||||
let mut item_obj_ref = item_obj.borrow_mut();
|
||||
let Some(item) = item_obj_ref.as_mut_item() else {
|
||||
return Err(VMError::NotAnItem(target));
|
||||
};
|
||||
if let Some(parent_slot_info) = item.get_parent_slot() {
|
||||
self.remove_slot_occupant(parent_slot_info.parent, parent_slot_info.slot)?;
|
||||
match slot.occupant.as_mut() {
|
||||
Some(info) if info.id == target => {
|
||||
info.quantity = quantity;
|
||||
Ok(None)
|
||||
}
|
||||
_ => {
|
||||
let Some(item_obj) = self.objects.borrow().get(&target).cloned() else {
|
||||
return Err(VMError::UnknownId(id));
|
||||
};
|
||||
let mut item_obj_ref = item_obj.borrow_mut();
|
||||
let Some(item) = item_obj_ref.as_mut_item() else {
|
||||
return Err(VMError::NotAnItem(target));
|
||||
};
|
||||
if let Some(parent_slot_info) = item.get_parent_slot() {
|
||||
self.remove_slot_occupant(parent_slot_info.parent, parent_slot_info.slot)?;
|
||||
}
|
||||
item.set_parent_slot(Some(ParentSlotInfo {
|
||||
parent: id,
|
||||
slot: index,
|
||||
}));
|
||||
let last = slot.occupant.as_ref().map(|info| info.id);
|
||||
slot.occupant.replace(SlotOccupantInfo {
|
||||
id: target,
|
||||
quantity,
|
||||
});
|
||||
Ok(last)
|
||||
}
|
||||
item.set_parent_slot(Some(ParentSlotInfo {
|
||||
parent: id,
|
||||
slot: index,
|
||||
}));
|
||||
let last = slot.occupant;
|
||||
slot.occupant = Some(target);
|
||||
slot.quantity = quantity;
|
||||
Ok(last)
|
||||
}
|
||||
} else {
|
||||
let last = slot.occupant;
|
||||
let last = slot.occupant.as_ref().map(|info| info.id);
|
||||
slot.occupant = None;
|
||||
slot.quantity = 0;
|
||||
Ok(last)
|
||||
}
|
||||
}
|
||||
@@ -861,8 +943,7 @@ impl VM {
|
||||
.get_slot_mut(index)
|
||||
.ok_or(ICError::SlotIndexOutOfRange(index as f64))?;
|
||||
|
||||
let last = slot.occupant;
|
||||
slot.occupant = None;
|
||||
let last = slot.occupant.as_ref().map(|info| info.id);
|
||||
Ok(last)
|
||||
}
|
||||
|
||||
@@ -880,7 +961,7 @@ impl VM {
|
||||
{
|
||||
None
|
||||
} else {
|
||||
Some(ObjectTemplate::freeze_object(obj, self))
|
||||
Some(FrozenObject::freeze_object(obj, self))
|
||||
}
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?,
|
||||
@@ -923,9 +1004,10 @@ impl VM {
|
||||
&transaction_networks,
|
||||
state.default_network_key,
|
||||
);
|
||||
for template in state.objects {
|
||||
let _ = transaction.add_device_from_template(template)?;
|
||||
for frozen in state.objects {
|
||||
let _ = transaction.add_device_from_frozen(frozen)?;
|
||||
}
|
||||
transaction.finialize()?;
|
||||
|
||||
self.circuit_holders.borrow_mut().clear();
|
||||
self.program_holders.borrow_mut().clear();
|
||||
@@ -992,6 +1074,7 @@ impl VMTransaction {
|
||||
.keys()
|
||||
.map(|net_id| (*net_id, VMTransactionNetwork::default()))
|
||||
.collect(),
|
||||
object_parents: BTreeMap::new(),
|
||||
vm: vm.clone(),
|
||||
}
|
||||
}
|
||||
@@ -1013,41 +1096,29 @@ impl VMTransaction {
|
||||
.keys()
|
||||
.map(|net_id| (*net_id, VMTransactionNetwork::default()))
|
||||
.collect(),
|
||||
object_parents: BTreeMap::new(),
|
||||
vm: vm.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_device_from_template(
|
||||
&mut self,
|
||||
template: ObjectTemplate,
|
||||
) -> Result<ObjectID, VMError> {
|
||||
for net_id in &template.connected_networks() {
|
||||
pub fn add_device_from_frozen(&mut self, frozen: FrozenObject) -> Result<ObjectID, VMError> {
|
||||
for net_id in &frozen.connected_networks() {
|
||||
if !self.networks.contains_key(net_id) {
|
||||
return Err(VMError::InvalidNetwork(*net_id));
|
||||
}
|
||||
}
|
||||
|
||||
let obj_id = if let Some(obj_id) = template.object_info().and_then(|info| info.id) {
|
||||
let obj_id = if let Some(obj_id) = frozen.obj_info.id {
|
||||
self.id_space.use_id(obj_id)?;
|
||||
obj_id
|
||||
} else {
|
||||
self.id_space.next()
|
||||
};
|
||||
|
||||
let obj = template.build(obj_id, &self.vm);
|
||||
let obj = frozen.build_vm_obj(obj_id, &self.vm)?;
|
||||
|
||||
if let Some(storage) = obj.borrow_mut().as_mut_storage() {
|
||||
for (slot_index, occupant_template) in
|
||||
template.templates_from_slots().into_iter().enumerate()
|
||||
{
|
||||
if let Some(occupant_template) = occupant_template {
|
||||
let occupant_id = self.add_device_from_template(occupant_template)?;
|
||||
storage
|
||||
.get_slot_mut(slot_index)
|
||||
.unwrap_or_else(|| panic!("object storage slots out of sync with template which built it: {slot_index}"))
|
||||
.occupant = Some(occupant_id);
|
||||
}
|
||||
}
|
||||
for (index, child_id) in frozen.contained_object_slots() {
|
||||
self.object_parents.insert(child_id, (index, obj_id));
|
||||
}
|
||||
|
||||
if let Some(_w_logicable) = obj.borrow().as_wireless_transmit() {
|
||||
@@ -1086,6 +1157,24 @@ impl VMTransaction {
|
||||
|
||||
Ok(obj_id)
|
||||
}
|
||||
|
||||
pub fn finialize(&mut self) -> Result<(), VMError> {
|
||||
for (child, (slot, parent)) in self.object_parents {
|
||||
let child_obj = self
|
||||
.objects
|
||||
.get(&child)
|
||||
.ok_or(VMError::MissingChild(child))?;
|
||||
let child_obj_ref = child_obj.borrow_mut();
|
||||
let item = child_obj_ref
|
||||
.as_mut_item()
|
||||
.ok_or(VMError::NotParentable(child))?;
|
||||
item.set_parent_slot(Some(ParentSlotInfo {
|
||||
slot: slot as usize,
|
||||
parent,
|
||||
}))
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LogicBatchMethodWrapper(LogicBatchMethod);
|
||||
@@ -1202,7 +1291,7 @@ impl IdSpace {
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct FrozenVM {
|
||||
pub objects: Vec<ObjectTemplate>,
|
||||
pub objects: Vec<FrozenObject>,
|
||||
pub circuit_holders: Vec<ObjectID>,
|
||||
pub program_holders: Vec<ObjectID>,
|
||||
pub default_network_key: ObjectID,
|
||||
|
||||
@@ -2,7 +2,7 @@ use crate::errors::ICError;
|
||||
use crate::interpreter;
|
||||
use crate::vm::{instructions::enums::InstructionOp, object::traits::IntegratedCircuit};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use stationeers_data::enums::script_enums::{
|
||||
use stationeers_data::enums::script::{
|
||||
LogicBatchMethod as BatchMode, LogicReagentMode as ReagentMode, LogicSlotType, LogicType,
|
||||
};
|
||||
use strum::EnumProperty;
|
||||
@@ -248,7 +248,7 @@ impl InstOperand {
|
||||
} => Ok(*lt),
|
||||
_ => {
|
||||
let val = self.as_value(ic)?;
|
||||
LogicType::try_from(val).map_err(|| ICError::UnknownLogicType(val))
|
||||
LogicType::try_from(val).map_err(|_| ICError::UnknownLogicType(val))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -264,7 +264,7 @@ impl InstOperand {
|
||||
} => Ok(*slt),
|
||||
_ => {
|
||||
let val = self.as_value(ic)?;
|
||||
LogicSlotType::try_from(val).map_err(|| ICError::UnknownLogicSlotType(val))
|
||||
LogicSlotType::try_from(val).map_err(|_| ICError::UnknownLogicSlotType(val))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -277,7 +277,7 @@ impl InstOperand {
|
||||
} => Ok(*bm),
|
||||
_ => {
|
||||
let val = self.as_value(ic)?;
|
||||
BatchMode::try_from(val).map_err(|| ICError::UnknownBatchMode(val))
|
||||
BatchMode::try_from(val).map_err(|_| ICError::UnknownBatchMode(val))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -290,7 +290,7 @@ impl InstOperand {
|
||||
} => Ok(*rm),
|
||||
_ => {
|
||||
let val = self.as_value(ic)?;
|
||||
ReagentMode::try_from(val).map_err(|| ICError::UnknownReagentMode(val))
|
||||
ReagentMode::try_from(val).map_err(|_| ICError::UnknownReagentMode(val))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,8 +19,7 @@ use traits::Object;
|
||||
use crate::vm::VM;
|
||||
|
||||
use stationeers_data::enums::{
|
||||
basic_enums::Class as SlotClass, prefabs::StationpediaPrefab, script_enums::LogicSlotType,
|
||||
MemoryAccess,
|
||||
basic::Class as SlotClass, prefabs::StationpediaPrefab, script::LogicSlotType, MemoryAccess,
|
||||
};
|
||||
|
||||
pub type ObjectID = u32;
|
||||
@@ -60,6 +59,10 @@ impl VMObject {
|
||||
pub fn get_vm(&self) -> Rc<VM> {
|
||||
self.borrow().get_vm().clone()
|
||||
}
|
||||
|
||||
pub fn get_id(&self) -> ObjectID {
|
||||
*self.borrow().get_id()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||
@@ -79,7 +82,8 @@ impl Name {
|
||||
pub fn from_prefab_name(name: &str) -> Self {
|
||||
Name {
|
||||
value: name.to_string(),
|
||||
hash: StationpediaPrefab::from_str(name)
|
||||
hash: name
|
||||
.parse::<StationpediaPrefab>()
|
||||
.map(|prefab| prefab as i32)
|
||||
.unwrap_or_else(|_| const_crc32::crc32(name.as_bytes()) as i32),
|
||||
}
|
||||
@@ -102,6 +106,12 @@ pub struct LogicField {
|
||||
pub value: f64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
|
||||
pub struct SlotOccupantInfo {
|
||||
pub quantity: u32,
|
||||
pub id: ObjectID,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||
pub struct Slot {
|
||||
pub parent: ObjectID,
|
||||
@@ -110,6 +120,5 @@ pub struct Slot {
|
||||
pub typ: SlotClass,
|
||||
pub readable_logic: Vec<LogicSlotType>,
|
||||
pub writeable_logic: Vec<LogicSlotType>,
|
||||
pub occupant: Option<ObjectID>,
|
||||
pub quantity: u32,
|
||||
pub occupant: Option<SlotOccupantInfo>,
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use thiserror::Error;
|
||||
|
||||
use stationeers_data::enums::script_enums::{LogicSlotType, LogicType};
|
||||
use stationeers_data::enums::script::{LogicSlotType, LogicType};
|
||||
|
||||
#[derive(Error, Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum LogicError {
|
||||
|
||||
@@ -9,8 +9,8 @@ use crate::{
|
||||
};
|
||||
use macro_rules_attribute::derive;
|
||||
use stationeers_data::{
|
||||
enums::script_enums::LogicType,
|
||||
templates::{DeviceInfo, ItemInfo},
|
||||
enums::script::LogicType,
|
||||
templates::{ConsumerInfo, DeviceInfo, FabricatorInfo, InternalAtmoInfo, ItemInfo, ThermalInfo},
|
||||
};
|
||||
use std::{collections::BTreeMap, rc::Rc};
|
||||
|
||||
@@ -25,6 +25,8 @@ pub struct Generic {
|
||||
pub name: Name,
|
||||
#[custom(object_vm_ref)]
|
||||
pub vm: Rc<VM>,
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub small_grid: bool,
|
||||
}
|
||||
|
||||
@@ -39,6 +41,8 @@ pub struct GenericStorage {
|
||||
pub name: Name,
|
||||
#[custom(object_vm_ref)]
|
||||
pub vm: Rc<VM>,
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub small_grid: bool,
|
||||
pub slots: Vec<Slot>,
|
||||
}
|
||||
@@ -54,6 +58,8 @@ pub struct GenericLogicable {
|
||||
pub name: Name,
|
||||
#[custom(object_vm_ref)]
|
||||
pub vm: Rc<VM>,
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub small_grid: bool,
|
||||
pub slots: Vec<Slot>,
|
||||
pub fields: BTreeMap<LogicType, LogicField>,
|
||||
@@ -71,6 +77,8 @@ pub struct GenericLogicableDevice {
|
||||
pub name: Name,
|
||||
#[custom(object_vm_ref)]
|
||||
pub vm: Rc<VM>,
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub small_grid: bool,
|
||||
pub slots: Vec<Slot>,
|
||||
pub fields: BTreeMap<LogicType, LogicField>,
|
||||
@@ -81,6 +89,53 @@ pub struct GenericLogicableDevice {
|
||||
pub reagents: Option<BTreeMap<i32, f64>>,
|
||||
}
|
||||
|
||||
#[derive(ObjectInterface!, GWStructure!, GWStorage!, GWLogicable!, GWDevice!)]
|
||||
#[custom(implements(Object { Structure, Storage, Logicable, Device }))]
|
||||
pub struct GenericCircuitHolder {
|
||||
#[custom(object_id)]
|
||||
pub id: ObjectID,
|
||||
#[custom(object_prefab)]
|
||||
pub prefab: Name,
|
||||
#[custom(object_name)]
|
||||
pub name: Name,
|
||||
#[custom(object_vm_ref)]
|
||||
pub vm: Rc<VM>,
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub small_grid: bool,
|
||||
pub slots: Vec<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>>,
|
||||
}
|
||||
|
||||
#[derive(ObjectInterface!, GWStructure!, GWStorage!, GWLogicable!, GWDevice!)]
|
||||
#[custom(implements(Object { Structure, Storage, Logicable, Device }))]
|
||||
pub struct GenericLogicableDeviceConsumer {
|
||||
#[custom(object_id)]
|
||||
pub id: ObjectID,
|
||||
#[custom(object_prefab)]
|
||||
pub prefab: Name,
|
||||
#[custom(object_name)]
|
||||
pub name: Name,
|
||||
#[custom(object_vm_ref)]
|
||||
pub vm: Rc<VM>,
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub small_grid: bool,
|
||||
pub slots: Vec<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 consumer_info: ConsumerInfo,
|
||||
}
|
||||
|
||||
#[derive(ObjectInterface!, GWStructure!, GWStorage!, GWLogicable!, GWDevice!, GWMemoryReadable!, GWMemoryWritable!)]
|
||||
#[custom(implements(Object { Structure, Storage, Logicable, Device, MemoryReadable }))]
|
||||
pub struct GenericLogicableDeviceMemoryReadable {
|
||||
@@ -92,6 +147,8 @@ pub struct GenericLogicableDeviceMemoryReadable {
|
||||
pub name: Name,
|
||||
#[custom(object_vm_ref)]
|
||||
pub vm: Rc<VM>,
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub small_grid: bool,
|
||||
pub slots: Vec<Slot>,
|
||||
pub fields: BTreeMap<LogicType, LogicField>,
|
||||
@@ -103,6 +160,32 @@ pub struct GenericLogicableDeviceMemoryReadable {
|
||||
pub memory: Vec<f64>,
|
||||
}
|
||||
|
||||
#[derive(ObjectInterface!, GWStructure!, GWStorage!, GWLogicable!, GWDevice!, GWMemoryReadable!, GWMemoryWritable!)]
|
||||
#[custom(implements(Object { Structure, Storage, Logicable, Device, MemoryReadable }))]
|
||||
pub struct GenericLogicableDeviceConsumerMemoryReadable {
|
||||
#[custom(object_id)]
|
||||
pub id: ObjectID,
|
||||
#[custom(object_prefab)]
|
||||
pub prefab: Name,
|
||||
#[custom(object_name)]
|
||||
pub name: Name,
|
||||
#[custom(object_vm_ref)]
|
||||
pub vm: Rc<VM>,
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub small_grid: bool,
|
||||
pub slots: Vec<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 consumer_info: ConsumerInfo,
|
||||
pub fabricator_info: Option<FabricatorInfo>,
|
||||
pub memory: Vec<f64>,
|
||||
}
|
||||
|
||||
#[derive(ObjectInterface!, GWStructure!, GWStorage!, GWLogicable!, GWDevice!, GWMemoryReadable!, GWMemoryWritable!)]
|
||||
#[custom(implements(Object { Structure, Storage, Logicable, Device, MemoryReadable, MemoryWritable }))]
|
||||
pub struct GenericLogicableDeviceMemoryReadWriteable {
|
||||
@@ -114,6 +197,8 @@ pub struct GenericLogicableDeviceMemoryReadWriteable {
|
||||
pub name: Name,
|
||||
#[custom(object_vm_ref)]
|
||||
pub vm: Rc<VM>,
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub small_grid: bool,
|
||||
pub slots: Vec<Slot>,
|
||||
pub fields: BTreeMap<LogicType, LogicField>,
|
||||
@@ -125,6 +210,33 @@ pub struct GenericLogicableDeviceMemoryReadWriteable {
|
||||
pub memory: Vec<f64>,
|
||||
}
|
||||
|
||||
|
||||
#[derive(ObjectInterface!, GWStructure!, GWStorage!, GWLogicable!, GWDevice!, GWMemoryReadable!, GWMemoryWritable!)]
|
||||
#[custom(implements(Object { Structure, Storage, Logicable, Device, MemoryReadable, MemoryWritable }))]
|
||||
pub struct GenericLogicableDeviceConsumerMemoryReadWriteable {
|
||||
#[custom(object_id)]
|
||||
pub id: ObjectID,
|
||||
#[custom(object_prefab)]
|
||||
pub prefab: Name,
|
||||
#[custom(object_name)]
|
||||
pub name: Name,
|
||||
#[custom(object_vm_ref)]
|
||||
pub vm: Rc<VM>,
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub small_grid: bool,
|
||||
pub slots: Vec<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 consumer_info: ConsumerInfo,
|
||||
pub fabricator_info: Option<FabricatorInfo>,
|
||||
pub memory: Vec<f64>,
|
||||
}
|
||||
|
||||
#[derive(ObjectInterface!, GWItem!)]
|
||||
#[custom(implements(Object { Item }))]
|
||||
pub struct GenericItem {
|
||||
@@ -136,6 +248,8 @@ pub struct GenericItem {
|
||||
pub name: Name,
|
||||
#[custom(object_vm_ref)]
|
||||
pub vm: Rc<VM>,
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub item_info: ItemInfo,
|
||||
pub parent_slot: Option<ParentSlotInfo>,
|
||||
pub damage: Option<f32>,
|
||||
@@ -152,12 +266,34 @@ pub struct GenericItemStorage {
|
||||
pub name: Name,
|
||||
#[custom(object_vm_ref)]
|
||||
pub vm: Rc<VM>,
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub item_info: ItemInfo,
|
||||
pub parent_slot: Option<ParentSlotInfo>,
|
||||
pub damage: Option<f32>,
|
||||
pub slots: Vec<Slot>,
|
||||
}
|
||||
|
||||
#[derive(ObjectInterface!, GWItem!, GWStorage! )]
|
||||
#[custom(implements(Object { Item, Storage }))]
|
||||
pub struct GenericItemConsumer {
|
||||
#[custom(object_id)]
|
||||
pub id: ObjectID,
|
||||
#[custom(object_prefab)]
|
||||
pub prefab: Name,
|
||||
#[custom(object_name)]
|
||||
pub name: Name,
|
||||
#[custom(object_vm_ref)]
|
||||
pub vm: Rc<VM>,
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub item_info: ItemInfo,
|
||||
pub parent_slot: Option<ParentSlotInfo>,
|
||||
pub damage: Option<f32>,
|
||||
pub slots: Vec<Slot>,
|
||||
pub consumer_info: ConsumerInfo,
|
||||
}
|
||||
|
||||
#[derive(ObjectInterface!, GWItem!, GWStorage!, GWLogicable! )]
|
||||
#[custom(implements(Object { Item, Storage, Logicable }))]
|
||||
pub struct GenericItemLogicable {
|
||||
@@ -169,6 +305,8 @@ pub struct GenericItemLogicable {
|
||||
pub name: Name,
|
||||
#[custom(object_vm_ref)]
|
||||
pub vm: Rc<VM>,
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub item_info: ItemInfo,
|
||||
pub parent_slot: Option<ParentSlotInfo>,
|
||||
pub damage: Option<f32>,
|
||||
@@ -188,6 +326,8 @@ pub struct GenericItemLogicableMemoryReadable {
|
||||
pub name: Name,
|
||||
#[custom(object_vm_ref)]
|
||||
pub vm: Rc<VM>,
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub item_info: ItemInfo,
|
||||
pub parent_slot: Option<ParentSlotInfo>,
|
||||
pub damage: Option<f32>,
|
||||
@@ -208,6 +348,8 @@ pub struct GenericItemLogicableMemoryReadWriteable {
|
||||
pub name: Name,
|
||||
#[custom(object_vm_ref)]
|
||||
pub vm: Rc<VM>,
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub item_info: ItemInfo,
|
||||
pub parent_slot: Option<ParentSlotInfo>,
|
||||
pub damage: Option<f32>,
|
||||
@@ -216,3 +358,87 @@ pub struct GenericItemLogicableMemoryReadWriteable {
|
||||
pub modes: Option<BTreeMap<u32, String>>,
|
||||
pub memory: Vec<f64>,
|
||||
}
|
||||
|
||||
#[derive(ObjectInterface!, GWItem!, GWStorage!, GWLogicable! )]
|
||||
#[custom(implements(Object { Item, Storage, Logicable }))]
|
||||
pub struct GenericItemCircuitHolder {
|
||||
#[custom(object_id)]
|
||||
pub id: ObjectID,
|
||||
#[custom(object_prefab)]
|
||||
pub prefab: Name,
|
||||
#[custom(object_name)]
|
||||
pub name: Name,
|
||||
#[custom(object_vm_ref)]
|
||||
pub vm: Rc<VM>,
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub item_info: ItemInfo,
|
||||
pub parent_slot: Option<ParentSlotInfo>,
|
||||
pub damage: Option<f32>,
|
||||
pub slots: Vec<Slot>,
|
||||
pub fields: BTreeMap<LogicType, LogicField>,
|
||||
pub modes: Option<BTreeMap<u32, String>>,
|
||||
}
|
||||
|
||||
|
||||
#[derive(ObjectInterface!, GWItem!, GWStorage!, GWLogicable!)]
|
||||
#[custom(implements(Object { Item, Storage, Suit, Logicable }))]
|
||||
pub struct GenericItemSuitLogic {
|
||||
#[custom(object_id)]
|
||||
pub id: ObjectID,
|
||||
#[custom(object_prefab)]
|
||||
pub prefab: Name,
|
||||
#[custom(object_name)]
|
||||
pub name: Name,
|
||||
#[custom(object_vm_ref)]
|
||||
pub vm: Rc<VM>,
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub item_info: ItemInfo,
|
||||
pub parent_slot: Option<ParentSlotInfo>,
|
||||
pub damage: Option<f32>,
|
||||
pub slots: Vec<Slot>,
|
||||
pub fields: BTreeMap<LogicType, LogicField>,
|
||||
pub modes: Option<BTreeMap<u32, String>>,
|
||||
}
|
||||
|
||||
#[derive(ObjectInterface!, GWItem!, GWStorage!, GWLogicable!, GWMemoryReadable!, GWMemoryWritable!)]
|
||||
#[custom(implements(Object { Item, Storage, Suit, Logicable, MemoryReadable, MemoryWritable }))]
|
||||
pub struct GenericItemSuitCircuitHolder {
|
||||
#[custom(object_id)]
|
||||
pub id: ObjectID,
|
||||
#[custom(object_prefab)]
|
||||
pub prefab: Name,
|
||||
#[custom(object_name)]
|
||||
pub name: Name,
|
||||
#[custom(object_vm_ref)]
|
||||
pub vm: Rc<VM>,
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub item_info: ItemInfo,
|
||||
pub parent_slot: Option<ParentSlotInfo>,
|
||||
pub damage: Option<f32>,
|
||||
pub slots: Vec<Slot>,
|
||||
pub fields: BTreeMap<LogicType, LogicField>,
|
||||
pub modes: Option<BTreeMap<u32, String>>,
|
||||
pub memory: Vec<f64>,
|
||||
}
|
||||
|
||||
#[derive(ObjectInterface!, GWItem!, GWStorage! )]
|
||||
#[custom(implements(Object { Item, Storage, Suit }))]
|
||||
pub struct GenericItemSuit {
|
||||
#[custom(object_id)]
|
||||
pub id: ObjectID,
|
||||
#[custom(object_prefab)]
|
||||
pub prefab: Name,
|
||||
#[custom(object_name)]
|
||||
pub name: Name,
|
||||
#[custom(object_vm_ref)]
|
||||
pub vm: Rc<VM>,
|
||||
pub thermal_info: Option<ThermalInfo>,
|
||||
pub internal_atmo_info: Option<InternalAtmoInfo>,
|
||||
pub item_info: ItemInfo,
|
||||
pub parent_slot: Option<ParentSlotInfo>,
|
||||
pub damage: Option<f32>,
|
||||
pub slots: Vec<Slot>,
|
||||
}
|
||||
|
||||
@@ -9,8 +9,8 @@ use crate::{
|
||||
|
||||
use stationeers_data::{
|
||||
enums::{
|
||||
basic_enums::{Class as SlotClass, GasType, SortingClass},
|
||||
script_enums::{LogicSlotType, LogicType},
|
||||
basic::{Class as SlotClass, GasType, SortingClass},
|
||||
script::{LogicSlotType, LogicType},
|
||||
},
|
||||
templates::{DeviceInfo, ItemInfo},
|
||||
};
|
||||
@@ -167,7 +167,9 @@ impl<T: GWLogicable + Object> Logicable for T {
|
||||
.ok_or_else(|| LogicError::SlotIndexOutOfRange(index, self.slots_count()))
|
||||
.and_then(|slot| {
|
||||
use LogicSlotType::*;
|
||||
let occupant = slot.occupant.and_then(|id| self.get_vm().get_object(id));
|
||||
let occupant = slot
|
||||
.occupant
|
||||
.and_then(|info| self.get_vm().get_object(info.id));
|
||||
match slt {
|
||||
Occupied => {
|
||||
if slot.occupant.is_some() {
|
||||
@@ -177,8 +179,8 @@ impl<T: GWLogicable + Object> Logicable for T {
|
||||
}
|
||||
}
|
||||
Quantity => {
|
||||
if slot.occupant.is_some() {
|
||||
Ok(slot.quantity as f64)
|
||||
if let Some(info) = &slot.occupant {
|
||||
Ok(info.quantity as f64)
|
||||
} else {
|
||||
Ok(0.0)
|
||||
}
|
||||
@@ -261,11 +263,11 @@ impl<T: GWLogicable + Object> Logicable for T {
|
||||
Pressure => logicable.get_logic(LogicType::Pressure),
|
||||
PressureAir => logicable
|
||||
.as_suit()
|
||||
.map(|suit| suit.pressure_air())
|
||||
.map(|suit| suit.pressure_air() as f64)
|
||||
.ok_or(LogicError::CantSlotRead(slt, index)),
|
||||
PressureWaste => logicable
|
||||
.as_suit()
|
||||
.map(|suit| suit.pressure_waste())
|
||||
.map(|suit| suit.pressure_waste() as f64)
|
||||
.ok_or(LogicError::CantSlotRead(slt, index)),
|
||||
Temperature => logicable.get_logic(LogicType::Temperature),
|
||||
Seeding => logicable
|
||||
@@ -398,11 +400,13 @@ impl<T: GWDevice + GWStorage + Object> Device for T {
|
||||
.and_then(|slot| {
|
||||
// special case, update slot quantity if >= 1
|
||||
if slt == Quantity && force && value >= 1.0 {
|
||||
slot.quantity = value as u32;
|
||||
if let Some(occupant) = slot.occupant.as_mut() {
|
||||
occupant.quantity = value as u32;
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
if slot.writeable_logic.contains(&slt) {
|
||||
let occupant = slot.occupant.and_then(|id| vm.get_object(id));
|
||||
let occupant = slot.occupant.and_then(|info| vm.get_object(info.id));
|
||||
if let Some(occupant) = occupant {
|
||||
let mut occupant_ref = occupant.borrow_mut();
|
||||
let logicable = occupant_ref
|
||||
|
||||
@@ -2,7 +2,10 @@ use std::rc::Rc;
|
||||
|
||||
use stationeers_data::{enums::prefabs::StationpediaPrefab, templates::ObjectTemplate};
|
||||
|
||||
use crate::vm::object::VMObject;
|
||||
use crate::vm::object::{
|
||||
templates::{FrozenObject, ObjectInfo, Prefab},
|
||||
VMObject,
|
||||
};
|
||||
use crate::vm::VM;
|
||||
|
||||
use super::ObjectID;
|
||||
@@ -10,12 +13,14 @@ use super::ObjectID;
|
||||
pub mod structs;
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn object_from_prefab_template(
|
||||
template: &ObjectTemplate,
|
||||
id: ObjectID,
|
||||
vm: &Rc<VM>,
|
||||
) -> Option<VMObject> {
|
||||
let prefab = StationpediaPrefab::from_repr(template.prefab_info().prefab_hash);
|
||||
pub fn object_from_frozen(obj: &ObjectInfo, id: ObjectID, vm: &Rc<VM>) -> Option<VMObject> {
|
||||
let hash = match obj.prefab {
|
||||
Some(Prefab::Hash(hash)) => hash,
|
||||
Some(Prefab::Name(name)) => const_crc32::crc32(name.as_bytes()) as i32,
|
||||
None => return None,
|
||||
};
|
||||
|
||||
let prefab = StationpediaPrefab::from_repr(hash);
|
||||
match prefab {
|
||||
// Some(StationpediaPrefab::ItemIntegratedCircuit10) => {
|
||||
// Some(VMObject::new(structs::ItemIntegratedCircuit10))
|
||||
|
||||
@@ -9,9 +9,9 @@ use crate::{
|
||||
};
|
||||
use macro_rules_attribute::derive;
|
||||
use stationeers_data::enums::{
|
||||
basic_enums::Class as SlotClass,
|
||||
basic::Class as SlotClass,
|
||||
prefabs::StationpediaPrefab,
|
||||
script_enums::{LogicSlotType, LogicType},
|
||||
script::{LogicSlotType, LogicType},
|
||||
ConnectionRole,
|
||||
};
|
||||
use std::rc::Rc;
|
||||
@@ -73,7 +73,6 @@ impl StructureCircuitHousing {
|
||||
],
|
||||
writeable_logic: vec![],
|
||||
occupant: None,
|
||||
quantity: 0,
|
||||
},
|
||||
pins: [None, None, None, None, None, None],
|
||||
connections: [
|
||||
@@ -163,8 +162,8 @@ impl Logicable for StructureCircuitHousing {
|
||||
LogicType::ReferenceId => Ok(*self.get_id() as f64),
|
||||
LogicType::Error => Ok(self.error as f64),
|
||||
LogicType::LineNumber => {
|
||||
let result = self.slot.occupant.and_then(|id| {
|
||||
self.vm.get_object(id).and_then(|obj| {
|
||||
let result = self.slot.occupant.and_then(|info| {
|
||||
self.vm.get_object(info.id).and_then(|obj| {
|
||||
obj.borrow()
|
||||
.as_logicable()
|
||||
.map(|logicable| logicable.get_logic(LogicType::LineNumber))
|
||||
@@ -208,8 +207,8 @@ impl Logicable for StructureCircuitHousing {
|
||||
LogicType::LineNumber => self
|
||||
.slot
|
||||
.occupant
|
||||
.and_then(|id| {
|
||||
self.vm.get_object(id).and_then(|obj| {
|
||||
.and_then(|info| {
|
||||
self.vm.get_object(info.id).and_then(|obj| {
|
||||
obj.borrow_mut().as_mut_logicable().map(|logicable| {
|
||||
logicable.set_logic(LogicType::LineNumber, value, force)
|
||||
})
|
||||
@@ -405,11 +404,11 @@ impl CircuitHolder for StructureCircuitHousing {
|
||||
}
|
||||
|
||||
fn get_ic(&self) -> Option<VMObject> {
|
||||
self.slot.occupant.and_then(|id| self.vm.get_object(id))
|
||||
self.slot.occupant.and_then(|info| self.vm.get_object(info.id))
|
||||
}
|
||||
|
||||
fn get_ic_mut(&self) -> Option<VMObject> {
|
||||
self.slot.occupant.and_then(|id| self.vm.get_object(id))
|
||||
self.slot.occupant.and_then(|info| self.vm.get_object(info.id))
|
||||
}
|
||||
|
||||
fn hault_and_catch_fire(&mut self) {
|
||||
|
||||
@@ -14,8 +14,8 @@ use crate::{
|
||||
};
|
||||
use macro_rules_attribute::derive;
|
||||
use stationeers_data::enums::{
|
||||
basic_enums::{Class as SlotClass, GasType, SortingClass},
|
||||
script_enums::{LogicSlotType, LogicType},
|
||||
basic::{Class as SlotClass, GasType, SortingClass},
|
||||
script::{LogicSlotType, LogicType},
|
||||
};
|
||||
use std::{collections::BTreeMap, rc::Rc};
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -14,8 +14,8 @@ use crate::{
|
||||
},
|
||||
};
|
||||
use stationeers_data::enums::{
|
||||
basic_enums::{Class as SlotClass, GasType, SortingClass},
|
||||
script_enums::{LogicSlotType, LogicType},
|
||||
basic::{Class as SlotClass, GasType, SortingClass},
|
||||
script::{LogicSlotType, LogicType},
|
||||
};
|
||||
use std::{collections::BTreeMap, fmt::Debug};
|
||||
|
||||
@@ -126,8 +126,18 @@ tag_object_traits! {
|
||||
}
|
||||
|
||||
pub trait Suit {
|
||||
fn pressure_waste(&self) -> f64;
|
||||
fn pressure_air(&self) -> f64;
|
||||
fn pressure_waste(&self) -> f32;
|
||||
fn pressure_waste_max(&self) -> f32;
|
||||
fn pressure_air(&self) -> f32;
|
||||
}
|
||||
|
||||
pub trait InternalAtmosphere {
|
||||
fn get_volume(&self) -> f64;
|
||||
}
|
||||
|
||||
pub trait Thermal {
|
||||
fn get_convection_factor(&self) -> f32;
|
||||
fn get_radiation_factor(&self) -> f32;
|
||||
}
|
||||
|
||||
pub trait IntegratedCircuit: Logicable + MemoryWritable + SourceCode + Item {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use strum::{AsRefStr, Display, EnumIter, EnumProperty, EnumString, FromRepr};
|
||||
use super::script_enums::{LogicSlotType, LogicType};
|
||||
use super::script::{LogicSlotType, LogicType};
|
||||
#[derive(
|
||||
Debug,
|
||||
Display,
|
||||
@@ -4,10 +4,10 @@ pub mod templates;
|
||||
pub mod enums {
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::fmt::Display;
|
||||
use strum::{AsRefStr, EnumIter, EnumString};
|
||||
use strum::{AsRefStr, EnumIter, EnumString, FromRepr};
|
||||
|
||||
pub mod basic_enums;
|
||||
pub mod script_enums;
|
||||
pub mod basic;
|
||||
pub mod script;
|
||||
pub mod prefabs;
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -46,6 +46,7 @@ pub mod enums {
|
||||
Deserialize,
|
||||
EnumIter,
|
||||
AsRefStr,
|
||||
FromRepr,
|
||||
EnumString,
|
||||
)]
|
||||
pub enum ConnectionType {
|
||||
@@ -77,6 +78,7 @@ pub mod enums {
|
||||
Deserialize,
|
||||
EnumIter,
|
||||
AsRefStr,
|
||||
FromRepr,
|
||||
EnumString,
|
||||
)]
|
||||
pub enum ConnectionRole {
|
||||
@@ -89,16 +91,45 @@ pub mod enums {
|
||||
#[default]
|
||||
None,
|
||||
}
|
||||
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
Default,
|
||||
Clone,
|
||||
Copy,
|
||||
PartialEq,
|
||||
PartialOrd,
|
||||
Eq,
|
||||
Ord,
|
||||
Hash,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
EnumIter,
|
||||
AsRefStr,
|
||||
FromRepr,
|
||||
EnumString,
|
||||
)]
|
||||
#[repr(u32)]
|
||||
pub enum MachineTier {
|
||||
#[default]
|
||||
Undefined = 0,
|
||||
TierOne = 1,
|
||||
TierTwo = 2,
|
||||
TierThree = 3,
|
||||
#[serde(other)]
|
||||
Max,
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn build_prefab_database() -> Option<BTreeMap<i32, templates::ObjectTemplate>> {
|
||||
#[cfg(feature = "prefab_database")]
|
||||
let _map = Some(database::build_prefab_database());
|
||||
let map = Some(database::build_prefab_database());
|
||||
#[cfg(not(feature = "prefab_database"))]
|
||||
let _map = None;
|
||||
let map = None;
|
||||
|
||||
_map
|
||||
map
|
||||
}
|
||||
|
||||
#[cfg(feature = "prefab_database")]
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use crate::enums::{
|
||||
basic_enums::{Class as SlotClass, GasType, SortingClass},
|
||||
script_enums::{LogicSlotType, LogicType},
|
||||
ConnectionRole, ConnectionType, MemoryAccess,
|
||||
basic::{Class as SlotClass, GasType, SortingClass},
|
||||
script::{LogicSlotType, LogicType},
|
||||
ConnectionRole, ConnectionType, MachineTier, MemoryAccess,
|
||||
};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
|
||||
@@ -219,6 +219,39 @@ pub struct ConsumerInfo {
|
||||
pub processed_reagents: Vec<i32>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
|
||||
pub struct RecipeRange {
|
||||
pub start: f64,
|
||||
pub stop: f64,
|
||||
pub is_valid: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
|
||||
pub struct RecipeGasMix {
|
||||
pub rule: i64,
|
||||
pub is_any: bool,
|
||||
pub is_any_to_remove: bool,
|
||||
pub reagents: BTreeMap<String, f64>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
|
||||
pub struct Recipe {
|
||||
pub tier: MachineTier,
|
||||
pub time: f64,
|
||||
pub energy: f64,
|
||||
pub temperature: RecipeRange,
|
||||
pub pressure: RecipeRange,
|
||||
pub required_mix: RecipeGasMix,
|
||||
pub count_types: i64,
|
||||
pub reagents: BTreeMap<String, f64>
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
|
||||
pub struct FabricatorInfo {
|
||||
pub tier: MachineTier,
|
||||
pub recipes: BTreeMap<String, Recipe>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
|
||||
pub struct StructureInfo {
|
||||
pub small_grid: bool,
|
||||
@@ -303,6 +336,7 @@ pub struct StructureLogicDeviceConsumerTemplate {
|
||||
pub slots: Vec<SlotInfo>,
|
||||
pub device: DeviceInfo,
|
||||
pub consumer_info: ConsumerInfo,
|
||||
pub fabricator_info: Option<FabricatorInfo>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
|
||||
@@ -338,6 +372,7 @@ pub struct StructureLogicDeviceConsumerMemoryTemplate {
|
||||
pub slots: Vec<SlotInfo>,
|
||||
pub device: DeviceInfo,
|
||||
pub consumer_info: ConsumerInfo,
|
||||
pub fabricator_info: Option<FabricatorInfo>,
|
||||
pub memory: MemoryInfo,
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ pub fn generate(
|
||||
eprintln!("generating enums...");
|
||||
}
|
||||
|
||||
let enums_files = enums::generate_enums(&pedia, &enums, workspace)?;
|
||||
let enums_files = enums::generate(&pedia, &enums, workspace)?;
|
||||
eprintln!("Formatting generated files...");
|
||||
for file in &enums_files {
|
||||
prepend_generated_comment_and_format(file)?;
|
||||
|
||||
@@ -15,13 +15,12 @@ use crate::{
|
||||
};
|
||||
|
||||
use stationeers_data::{
|
||||
enums::MemoryAccess,
|
||||
templates::{
|
||||
ConnectionInfo, ConsumerInfo, DeviceInfo, Instruction, InternalAtmoInfo,
|
||||
ConnectionInfo, ConsumerInfo, DeviceInfo, FabricatorInfo, Instruction, InternalAtmoInfo,
|
||||
ItemCircuitHolderTemplate, ItemConsumerTemplate, ItemInfo, ItemLogicMemoryTemplate,
|
||||
ItemLogicTemplate, ItemSlotsTemplate, ItemSuitCircuitHolderTemplate, ItemSuitLogicTemplate,
|
||||
ItemSuitTemplate, ItemTemplate, LogicInfo, MemoryInfo, ObjectTemplate, PrefabInfo,
|
||||
SlotInfo, StructureCircuitHolderTemplate, StructureInfo,
|
||||
ItemSuitTemplate, ItemTemplate, LogicInfo, MemoryInfo, ObjectTemplate, PrefabInfo, Recipe,
|
||||
RecipeGasMix, RecipeRange, SlotInfo, StructureCircuitHolderTemplate, StructureInfo,
|
||||
StructureLogicDeviceConsumerMemoryTemplate, StructureLogicDeviceConsumerTemplate,
|
||||
StructureLogicDeviceMemoryTemplate, StructureLogicDeviceTemplate, StructureLogicTemplate,
|
||||
StructureSlotsTemplate, StructureTemplate, SuitInfo, ThermalInfo,
|
||||
@@ -203,8 +202,7 @@ pub fn generate_database(
|
||||
//
|
||||
// https://regex101.com/r/V2tXIa/1
|
||||
//
|
||||
let null_matcher = regex::Regex::new(r#"(?:(?:,\n)\s*"\w+":\snull)+(,?)"#)
|
||||
.unwrap();
|
||||
let null_matcher = regex::Regex::new(r#"(?:(?:,\n)\s*"\w+":\snull)+(,?)"#).unwrap();
|
||||
let json = null_matcher.replace_all(&json, "$1");
|
||||
write!(&mut database_file, "{json}")?;
|
||||
database_file.flush()?;
|
||||
@@ -733,6 +731,7 @@ fn generate_templates(pedia: &Stationpedia) -> Vec<ObjectTemplate> {
|
||||
slots: slot_inserts_to_info(slot_inserts),
|
||||
device: device.into(),
|
||||
consumer_info: consumer.into(),
|
||||
fabricator_info: device.fabricator.as_ref().map(Into::into),
|
||||
},
|
||||
));
|
||||
// println!("Structure")
|
||||
@@ -805,6 +804,7 @@ fn generate_templates(pedia: &Stationpedia) -> Vec<ObjectTemplate> {
|
||||
slots: slot_inserts_to_info(slot_inserts),
|
||||
device: device.into(),
|
||||
consumer_info: consumer.into(),
|
||||
fabricator_info: device.fabricator.as_ref().map(Into::into),
|
||||
memory: memory.into(),
|
||||
},
|
||||
));
|
||||
@@ -1052,3 +1052,88 @@ impl From<&stationpedia::ResourceConsumer> for ConsumerInfo {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&stationpedia::Fabricator> for FabricatorInfo {
|
||||
fn from(value: &stationpedia::Fabricator) -> Self {
|
||||
FabricatorInfo {
|
||||
tier: value
|
||||
.tier_name
|
||||
.parse()
|
||||
.unwrap_or_else(|_| panic!("Unknown MachineTier {}", value.tier_name)),
|
||||
recipes: value
|
||||
.recipes
|
||||
.iter()
|
||||
.map(|(key, val)| (key.clone(), val.into()))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&stationpedia::Recipe> for Recipe {
|
||||
fn from(value: &stationpedia::Recipe) -> Self {
|
||||
Recipe {
|
||||
tier: value
|
||||
.tier_name
|
||||
.parse()
|
||||
.unwrap_or_else(|_| panic!("Unknown MachineTier {}", value.tier_name)),
|
||||
time: value.time,
|
||||
energy: value.energy,
|
||||
temperature: (&value.temperature).into(),
|
||||
pressure: (&value.pressure).into(),
|
||||
required_mix: (&value.required_mix).into(),
|
||||
count_types: value.count_types,
|
||||
reagents: value
|
||||
.reagents
|
||||
.iter()
|
||||
.filter_map(|(key, val)| {
|
||||
if *val == 0.0 {
|
||||
None
|
||||
} else {
|
||||
Some((key.clone(), *val))
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&stationpedia::RecipeTemperature> for RecipeRange {
|
||||
fn from(value: &stationpedia::RecipeTemperature) -> Self {
|
||||
RecipeRange {
|
||||
start: value.start,
|
||||
stop: value.stop,
|
||||
is_valid: value.is_valid,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&stationpedia::RecipePressure> for RecipeRange {
|
||||
fn from(value: &stationpedia::RecipePressure) -> Self {
|
||||
RecipeRange {
|
||||
start: value.start,
|
||||
stop: value.stop,
|
||||
is_valid: value.is_valid,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&stationpedia::RecipeGasMix> for RecipeGasMix {
|
||||
fn from(value: &stationpedia::RecipeGasMix) -> Self {
|
||||
RecipeGasMix {
|
||||
rule: value.rule,
|
||||
is_any: value.is_any,
|
||||
is_any_to_remove: value.is_any_to_remove,
|
||||
reagents: value
|
||||
.reagents
|
||||
.iter()
|
||||
.filter_map(|(key, val)| {
|
||||
if *val == 0.0 {
|
||||
None
|
||||
} else {
|
||||
Some((key.clone(), *val))
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ use std::{
|
||||
use proc_macro2::{Ident, Span, TokenStream};
|
||||
use quote::quote;
|
||||
|
||||
pub fn generate_enums(
|
||||
pub fn generate(
|
||||
stationpedia: &crate::stationpedia::Stationpedia,
|
||||
enums: &crate::enums::Enums,
|
||||
workspace: &std::path::Path,
|
||||
@@ -28,14 +28,14 @@ pub fn generate_enums(
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let mut writer =
|
||||
std::io::BufWriter::new(std::fs::File::create(enums_path.join("script_enums.rs"))?);
|
||||
std::io::BufWriter::new(std::fs::File::create(enums_path.join("script.rs"))?);
|
||||
write_repr_enum_use_header(&mut writer)?;
|
||||
for enm in enums.script_enums.values() {
|
||||
write_enum_listing(&mut writer, enm)?;
|
||||
}
|
||||
|
||||
let mut writer =
|
||||
std::io::BufWriter::new(std::fs::File::create(enums_path.join("basic_enums.rs"))?);
|
||||
std::io::BufWriter::new(std::fs::File::create(enums_path.join("basic.rs"))?);
|
||||
write_repr_enum_use_header(&mut writer)?;
|
||||
let script_enums_in_basic = enums
|
||||
.script_enums
|
||||
@@ -75,8 +75,8 @@ pub fn generate_enums(
|
||||
write_repr_enum(&mut writer, "StationpediaPrefab", &prefabs, true)?;
|
||||
|
||||
Ok(vec![
|
||||
enums_path.join("script_enums.rs"),
|
||||
enums_path.join("basic_enums.rs"),
|
||||
enums_path.join("script.rs"),
|
||||
enums_path.join("basic.rs"),
|
||||
enums_path.join("prefabs.rs"),
|
||||
])
|
||||
}
|
||||
@@ -116,7 +116,7 @@ fn write_enum_aggragate_mod<T: std::io::Write>(
|
||||
};
|
||||
let display_pat = format!("{name}{display_sep}{{}}");
|
||||
let name: TokenStream = if name == "_unnamed" {
|
||||
"".to_string()
|
||||
String::new()
|
||||
} else {
|
||||
name.clone()
|
||||
}
|
||||
@@ -236,7 +236,7 @@ pub fn write_enum_listing<T: std::io::Write>(
|
||||
let variant = ReprEnumVariant {
|
||||
value: var.value as u8,
|
||||
deprecated: var.deprecated,
|
||||
props: vec![("docs".to_owned(), var.description.to_owned())],
|
||||
props: vec![("docs".to_owned(), var.description.clone())],
|
||||
};
|
||||
(n.clone(), variant)
|
||||
})
|
||||
@@ -255,7 +255,7 @@ pub fn write_enum_listing<T: std::io::Write>(
|
||||
let variant = ReprEnumVariant {
|
||||
value: var.value as u16,
|
||||
deprecated: var.deprecated,
|
||||
props: vec![("docs".to_owned(), var.description.to_owned())],
|
||||
props: vec![("docs".to_owned(), var.description.clone())],
|
||||
};
|
||||
(n.clone(), variant)
|
||||
})
|
||||
@@ -269,7 +269,7 @@ pub fn write_enum_listing<T: std::io::Write>(
|
||||
let variant = ReprEnumVariant {
|
||||
value: var.value as u32,
|
||||
deprecated: var.deprecated,
|
||||
props: vec![("docs".to_owned(), var.description.to_owned())],
|
||||
props: vec![("docs".to_owned(), var.description.clone())],
|
||||
};
|
||||
(n.clone(), variant)
|
||||
})
|
||||
@@ -283,7 +283,7 @@ pub fn write_enum_listing<T: std::io::Write>(
|
||||
let variant = ReprEnumVariant {
|
||||
value: var.value as i32,
|
||||
deprecated: var.deprecated,
|
||||
props: vec![("docs".to_owned(), var.description.to_owned())],
|
||||
props: vec![("docs".to_owned(), var.description.clone())],
|
||||
};
|
||||
(n.clone(), variant)
|
||||
})
|
||||
@@ -297,7 +297,7 @@ pub fn write_enum_listing<T: std::io::Write>(
|
||||
let variant = ReprEnumVariant {
|
||||
value: var.value as i32,
|
||||
deprecated: var.deprecated,
|
||||
props: vec![("docs".to_owned(), var.description.to_owned())],
|
||||
props: vec![("docs".to_owned(), var.description.clone())],
|
||||
};
|
||||
(n.clone(), variant)
|
||||
})
|
||||
@@ -344,7 +344,7 @@ fn write_repr_basic_use_header<T: std::io::Write>(
|
||||
write!(
|
||||
writer,
|
||||
"{}",
|
||||
quote! {use super::script_enums::{ #(#enums),*};},
|
||||
quote! {use super::script::{ #(#enums),*};},
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use serde_with::{serde_as, DisplayFromStr};
|
||||
use stationeers_data::enums::MachineTier;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
@@ -132,15 +133,6 @@ pub struct BuildState {
|
||||
pub machine_tier: Option<MachineTier>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
|
||||
pub enum MachineTier {
|
||||
Undefined,
|
||||
TierOne,
|
||||
TierTwo,
|
||||
TierThree,
|
||||
Max,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
|
||||
pub struct Tool {
|
||||
#[serde(rename = "IsTool", default)]
|
||||
@@ -354,7 +346,7 @@ pub struct Device {
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Fabricator {
|
||||
#[serde(rename = "Tier")]
|
||||
tier: u32,
|
||||
pub tier: u32,
|
||||
#[serde(rename = "TierName")]
|
||||
pub tier_name: String,
|
||||
#[serde(rename = "Recipes", default)]
|
||||
|
||||
Reference in New Issue
Block a user