refactor(vm): rework object freazing

- let vm carry object dtabase
 - seperate frozen object info and templates
This commit is contained in:
Rachel Powers
2024-05-23 23:04:42 -07:00
parent d79726a794
commit 24778b21b7
25 changed files with 18268 additions and 1262 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -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)]

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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))

View File

@@ -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,

View File

@@ -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))
}
}
}

View File

@@ -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>,
}

View File

@@ -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 {

View File

@@ -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>,
}

View File

@@ -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

View File

@@ -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))

View File

@@ -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) {

View File

@@ -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

View File

@@ -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

View File

@@ -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,

View File

@@ -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")]

View File

@@ -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,
}

View File

@@ -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)?;

View 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(),
}
}
}

View File

@@ -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(())
}

View File

@@ -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)]