refactor(vm) use generated enums wherever possible

This commit is contained in:
Rachel Powers
2024-05-09 13:58:28 -07:00
parent 371167db45
commit 096e272b07
36 changed files with 13655 additions and 13388 deletions

1
Cargo.lock generated
View File

@@ -2193,4 +2193,5 @@ dependencies = [
"serde_with",
"textwrap",
"thiserror",
"tracing",
]

View File

@@ -1 +1 @@
{"language":"en","flagWords":[],"version":"0.2","words":["Astroloy","Autolathe","bapal","bapz","bapzal","batchmode","batchmodes","bdns","bdnsal","bdse","bdseal","beqal","beqz","beqzal","bgeal","bgez","bgezal","bgtal","bgtz","bgtzal","bindgen","bleal","blez","blezal","bltal","bltz","bltzal","bnaal","bnan","bnaz","bnazal","bneal","bnez","bnezal","brap","brapz","brdns","brdse","breq","breqz","brge","brgez","brgt","brgtz","brle","brlez","brlt","brltz","brna","brnan","brnaz","brne","brnez","Circuitboard","codegen","conv","cstyle","endpos","getd","Hardsuit","hashables","inext","inextp","infile","itertools","jetpack","kbshortcutmenu","Keybind","lbns","logicable","logictype","logictypes","lzma","Mineables","mscorlib","MSEED","ninf","nomatch","oprs","overcolumn","Overlength","pedia","peekable","prec","preproc","putd","QUICKFIX","reagentmode","reagentmodes","repr","retval","rocketstation","sapz","sattellite","sdns","sdse","searchbox","searchbtn","seqz","serde","settingsmenu","sgez","sgtz","slez","slotlogic","slotlogicable","slotlogictype","slotlogictypes","slottype","sltz","snan","snanz","snaz","snez","splitn","Stationeers","stationpedia","stdweb","thiserror","tokentype","trunc","Tsify","whos","Depressurising","Pressurising","logicslottypes","lparen","rparen","hstack","dylib"]}
{"language":"en","flagWords":[],"version":"0.2","words":["Astroloy","Autolathe","bapal","bapz","bapzal","batchmode","batchmodes","bdns","bdnsal","bdse","bdseal","beqal","beqz","beqzal","bgeal","bgez","bgezal","bgtal","bgtz","bgtzal","bindgen","bleal","blez","blezal","bltal","bltz","bltzal","bnaal","bnan","bnaz","bnazal","bneal","bnez","bnezal","brap","brapz","brdns","brdse","breq","breqz","brge","brgez","brgt","brgtz","brle","brlez","brlt","brltz","brna","brnan","brnaz","brne","brnez","Circuitboard","codegen","conv","cstyle","endpos","getd","Hardsuit","hashables","inext","inextp","infile","itertools","jetpack","kbshortcutmenu","Keybind","lbns","logicable","logictype","logictypes","lzma","Mineables","mscorlib","MSEED","ninf","nomatch","oprs","overcolumn","Overlength","pedia","peekable","prec","preproc","putd","QUICKFIX","reagentmode","reagentmodes","repr","retval","rocketstation","sapz","sattellite","sdns","sdse","searchbox","searchbtn","seqz","serde","settingsmenu","sgez","sgtz","slez","slotlogic","slotlogicable","LogicSlotType","LogicSlotTypes","slottype","sltz","snan","snanz","snaz","snez","splitn","Stationeers","stationpedia","stdweb","thiserror","tokentype","trunc","Tsify","whos","Depressurising","Pressurising","logicslottypes","lparen","rparen","hstack","dylib"]}

File diff suppressed because one or more lines are too long

View File

@@ -2,8 +2,9 @@ use crate::{
errors::ICError,
interpreter::ICState,
network::{CableConnectionType, Connection},
vm::enums::script_enums::{
LogicReagentMode as ReagentMode, LogicSlotType as SlotLogicType, LogicType,
vm::enums::{
script_enums::{LogicReagentMode as ReagentMode, LogicSlotType, LogicType},
basic_enums::{Class as SlotClass, SortingClass},
},
vm::VM,
};
@@ -12,10 +13,9 @@ use std::{collections::BTreeMap, ops::Deref};
use itertools::Itertools;
use serde_derive::{Deserialize, Serialize};
use strum_macros::{AsRefStr, EnumIter, EnumString};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum FieldType {
pub enum MemoryAccess {
Read,
Write,
ReadWrite,
@@ -23,7 +23,7 @@ pub enum FieldType {
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LogicField {
pub field_type: FieldType,
pub field_type: MemoryAccess,
pub value: f64,
}
@@ -35,7 +35,7 @@ pub struct SlotOccupant {
pub max_quantity: u32,
pub sorting_class: SortingClass,
pub damage: f64,
fields: BTreeMap<SlotLogicType, LogicField>,
fields: BTreeMap<LogicSlotType, LogicField>,
}
impl SlotOccupant {
@@ -47,24 +47,25 @@ impl SlotOccupant {
SlotOccupant {
id: template.id.unwrap_or_else(id_fn),
prefab_hash: fields
.remove(&SlotLogicType::PrefabHash)
.remove(&LogicSlotType::PrefabHash)
.map(|field| field.value as i32)
.unwrap_or(0),
quantity: fields
.remove(&SlotLogicType::Quantity)
.remove(&LogicSlotType::Quantity)
.map(|field| field.value as u32)
.unwrap_or(1),
max_quantity: fields
.remove(&SlotLogicType::MaxQuantity)
.remove(&LogicSlotType::MaxQuantity)
.map(|field| field.value as u32)
.unwrap_or(1),
damage: fields
.remove(&SlotLogicType::Damage)
.remove(&LogicSlotType::Damage)
.map(|field| field.value)
.unwrap_or(0.0),
sorting_class: fields
.remove(&SlotLogicType::SortingClass)
.map(|field| (field.value as u32).into())
.remove(&LogicSlotType::SortingClass)
.map(|field| SortingClass::from_repr(field.value as u8))
.flatten()
.unwrap_or(SortingClass::Default),
fields,
}
@@ -74,7 +75,7 @@ impl SlotOccupant {
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SlotOccupantTemplate {
pub id: Option<u32>,
pub fields: BTreeMap<SlotLogicType, LogicField>,
pub fields: BTreeMap<LogicSlotType, LogicField>,
}
impl SlotOccupant {
@@ -109,65 +110,65 @@ impl SlotOccupant {
}
/// chainable constructor
pub fn with_fields(mut self, fields: BTreeMap<SlotLogicType, LogicField>) -> Self {
pub fn with_fields(mut self, fields: BTreeMap<LogicSlotType, LogicField>) -> Self {
self.fields.extend(fields);
self
}
/// chainable constructor
pub fn get_fields(&self) -> BTreeMap<SlotLogicType, LogicField> {
pub fn get_fields(&self) -> BTreeMap<LogicSlotType, LogicField> {
let mut copy = self.fields.clone();
copy.insert(
SlotLogicType::PrefabHash,
LogicSlotType::PrefabHash,
LogicField {
field_type: FieldType::Read,
field_type: MemoryAccess::Read,
value: self.prefab_hash as f64,
},
);
copy.insert(
SlotLogicType::SortingClass,
LogicSlotType::SortingClass,
LogicField {
field_type: FieldType::Read,
field_type: MemoryAccess::Read,
value: self.sorting_class as u32 as f64,
},
);
copy.insert(
SlotLogicType::Quantity,
LogicSlotType::Quantity,
LogicField {
field_type: FieldType::Read,
field_type: MemoryAccess::Read,
value: self.quantity as f64,
},
);
copy.insert(
SlotLogicType::MaxQuantity,
LogicSlotType::MaxQuantity,
LogicField {
field_type: FieldType::Read,
field_type: MemoryAccess::Read,
value: self.max_quantity as f64,
},
);
copy.insert(
SlotLogicType::Damage,
LogicSlotType::Damage,
LogicField {
field_type: FieldType::Read,
field_type: MemoryAccess::Read,
value: self.damage,
},
);
copy
}
pub fn set_field(&mut self, typ: SlotLogicType, val: f64, force: bool) -> Result<(), ICError> {
if (typ == SlotLogicType::Quantity) && force {
pub fn set_field(&mut self, typ: LogicSlotType, val: f64, force: bool) -> Result<(), ICError> {
if (typ == LogicSlotType::Quantity) && force {
self.quantity = val as u32;
Ok(())
} else if (typ == SlotLogicType::MaxQuantity) && force {
} else if (typ == LogicSlotType::MaxQuantity) && force {
self.max_quantity = val as u32;
Ok(())
} else if (typ == SlotLogicType::Damage) && force {
} else if (typ == LogicSlotType::Damage) && force {
self.damage = val;
Ok(())
} else if let Some(logic) = self.fields.get_mut(&typ) {
match logic.field_type {
FieldType::ReadWrite | FieldType::Write => {
MemoryAccess::ReadWrite | MemoryAccess::Write => {
logic.value = val;
Ok(())
}
@@ -184,7 +185,7 @@ impl SlotOccupant {
self.fields.insert(
typ,
LogicField {
field_type: FieldType::ReadWrite,
field_type: MemoryAccess::ReadWrite,
value: val,
},
);
@@ -194,17 +195,23 @@ impl SlotOccupant {
}
}
pub fn can_logic_read(&self, field: SlotLogicType) -> bool {
pub fn can_logic_read(&self, field: LogicSlotType) -> bool {
if let Some(logic) = self.fields.get(&field) {
matches!(logic.field_type, FieldType::Read | FieldType::ReadWrite)
matches!(
logic.field_type,
MemoryAccess::Read | MemoryAccess::ReadWrite
)
} else {
false
}
}
pub fn can_logic_write(&self, field: SlotLogicType) -> bool {
pub fn can_logic_write(&self, field: LogicSlotType) -> bool {
if let Some(logic) = self.fields.get(&field) {
matches!(logic.field_type, FieldType::Write | FieldType::ReadWrite)
matches!(
logic.field_type,
MemoryAccess::Write | MemoryAccess::ReadWrite
)
} else {
false
}
@@ -213,47 +220,47 @@ impl SlotOccupant {
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct Slot {
pub typ: SlotType,
pub typ: SlotClass,
pub occupant: Option<SlotOccupant>,
}
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct SlotTemplate {
pub typ: SlotType,
pub typ: SlotClass,
pub occupant: Option<SlotOccupantTemplate>,
}
impl Slot {
pub fn new(typ: SlotType) -> Self {
pub fn new(typ: SlotClass) -> Self {
Slot {
typ,
occupant: None,
}
}
pub fn with_occupant(typ: SlotType, occupant: SlotOccupant) -> Self {
pub fn with_occupant(typ: SlotClass, occupant: SlotOccupant) -> Self {
Slot {
typ,
occupant: Some(occupant),
}
}
pub fn get_fields(&self) -> BTreeMap<SlotLogicType, LogicField> {
pub fn get_fields(&self) -> BTreeMap<LogicSlotType, LogicField> {
let mut copy = self
.occupant
.as_ref()
.map(|occupant| occupant.get_fields())
.unwrap_or_default();
copy.insert(
SlotLogicType::Occupied,
LogicSlotType::Occupied,
LogicField {
field_type: FieldType::Read,
field_type: MemoryAccess::Read,
value: if self.occupant.is_some() { 1.0 } else { 0.0 },
},
);
copy.insert(
SlotLogicType::OccupantHash,
LogicSlotType::OccupantHash,
LogicField {
field_type: FieldType::Read,
field_type: MemoryAccess::Read,
value: self
.occupant
.as_ref()
@@ -262,9 +269,9 @@ impl Slot {
},
);
copy.insert(
SlotLogicType::Quantity,
LogicSlotType::Quantity,
LogicField {
field_type: FieldType::Read,
field_type: MemoryAccess::Read,
value: self
.occupant
.as_ref()
@@ -273,9 +280,9 @@ impl Slot {
},
);
copy.insert(
SlotLogicType::Damage,
LogicSlotType::Damage,
LogicField {
field_type: FieldType::Read,
field_type: MemoryAccess::Read,
value: self
.occupant
.as_ref()
@@ -284,16 +291,16 @@ impl Slot {
},
);
copy.insert(
SlotLogicType::Class,
LogicSlotType::Class,
LogicField {
field_type: FieldType::Read,
field_type: MemoryAccess::Read,
value: self.typ as u32 as f64,
},
);
copy.insert(
SlotLogicType::MaxQuantity,
LogicSlotType::MaxQuantity,
LogicField {
field_type: FieldType::Read,
field_type: MemoryAccess::Read,
value: self
.occupant
.as_ref()
@@ -302,9 +309,9 @@ impl Slot {
},
);
copy.insert(
SlotLogicType::PrefabHash,
LogicSlotType::PrefabHash,
LogicField {
field_type: FieldType::Read,
field_type: MemoryAccess::Read,
value: self
.occupant
.as_ref()
@@ -313,9 +320,9 @@ impl Slot {
},
);
copy.insert(
SlotLogicType::SortingClass,
LogicSlotType::SortingClass,
LogicField {
field_type: FieldType::Read,
field_type: MemoryAccess::Read,
value: self
.occupant
.as_ref()
@@ -324,9 +331,9 @@ impl Slot {
},
);
copy.insert(
SlotLogicType::ReferenceId,
LogicSlotType::ReferenceId,
LogicField {
field_type: FieldType::Read,
field_type: MemoryAccess::Read,
value: self
.occupant
.as_ref()
@@ -337,34 +344,34 @@ impl Slot {
copy
}
pub fn get_field(&self, field: SlotLogicType) -> f64 {
pub fn get_field(&self, field: LogicSlotType) -> f64 {
let fields = self.get_fields();
fields
.get(&field)
.map(|field| match field.field_type {
FieldType::Read | FieldType::ReadWrite => field.value,
MemoryAccess::Read | MemoryAccess::ReadWrite => field.value,
_ => 0.0,
})
.unwrap_or(0.0)
}
pub fn can_logic_read(&self, field: SlotLogicType) -> bool {
pub fn can_logic_read(&self, field: LogicSlotType) -> bool {
match field {
SlotLogicType::Pressure | SlotLogicType::Temperature | SlotLogicType::Volume => {
LogicSlotType::Pressure | LogicSlotType::Temperature | LogicSlotType::Volume => {
matches!(
self.typ,
SlotType::GasCanister | SlotType::LiquidCanister | SlotType::LiquidBottle
SlotClass::GasCanister | SlotClass::LiquidCanister | SlotClass::LiquidBottle
)
}
SlotLogicType::Charge | SlotLogicType::ChargeRatio => {
matches!(self.typ, SlotType::Battery)
LogicSlotType::Charge | LogicSlotType::ChargeRatio => {
matches!(self.typ, SlotClass::Battery)
}
SlotLogicType::Open => matches!(
LogicSlotType::Open => matches!(
self.typ,
SlotType::Helmet | SlotType::Tool | SlotType::Appliance
SlotClass::Helmet | SlotClass::Tool | SlotClass::Appliance
),
SlotLogicType::Lock => matches!(self.typ, SlotType::Helmet),
SlotLogicType::FilterType => matches!(self.typ, SlotType::GasFilter),
LogicSlotType::Lock => matches!(self.typ, SlotClass::Helmet),
LogicSlotType::FilterType => matches!(self.typ, SlotClass::GasFilter),
_ => {
if let Some(occupant) = self.occupant.as_ref() {
occupant.can_logic_read(field)
@@ -375,20 +382,20 @@ impl Slot {
}
}
pub fn can_logic_write(&self, field: SlotLogicType) -> bool {
pub fn can_logic_write(&self, field: LogicSlotType) -> bool {
match field {
SlotLogicType::Open => matches!(
LogicSlotType::Open => matches!(
self.typ,
SlotType::Helmet
| SlotType::GasCanister
| SlotType::LiquidCanister
| SlotType::LiquidBottle
SlotClass::Helmet
| SlotClass::GasCanister
| SlotClass::LiquidCanister
| SlotClass::LiquidBottle
),
SlotLogicType::On => matches!(
LogicSlotType::On => matches!(
self.typ,
SlotType::Helmet | SlotType::Tool | SlotType::Appliance
SlotClass::Helmet | SlotClass::Tool | SlotClass::Appliance
),
SlotLogicType::Lock => matches!(self.typ, SlotType::Helmet),
LogicSlotType::Lock => matches!(self.typ, SlotClass::Helmet),
_ => {
if let Some(occupant) = self.occupant.as_ref() {
occupant.can_logic_write(field)
@@ -399,15 +406,15 @@ impl Slot {
}
}
pub fn set_field(&mut self, typ: SlotLogicType, val: f64, force: bool) -> Result<(), ICError> {
pub fn set_field(&mut self, typ: LogicSlotType, val: f64, force: bool) -> Result<(), ICError> {
if matches!(
typ,
SlotLogicType::Occupied
| SlotLogicType::OccupantHash
| SlotLogicType::Class
| SlotLogicType::PrefabHash
| SlotLogicType::SortingClass
| SlotLogicType::ReferenceId
LogicSlotType::Occupied
| LogicSlotType::OccupantHash
| LogicSlotType::Class
| LogicSlotType::PrefabHash
| LogicSlotType::SortingClass
| LogicSlotType::ReferenceId
) {
return Err(ICError::ReadOnlyField(typ.to_string()));
}
@@ -419,114 +426,6 @@ impl Slot {
}
}
#[derive(
Debug,
Default,
Clone,
Copy,
PartialEq,
Eq,
Hash,
strum_macros::Display,
EnumString,
EnumIter,
AsRefStr,
Serialize,
Deserialize,
)]
#[strum(serialize_all = "PascalCase")]
pub enum SortingClass {
#[default]
Default = 0,
Kits = 1,
Tools = 2,
Resources,
Food = 4,
Clothing,
Appliances,
Atmospherics,
Storage = 8,
Ores,
Ices,
}
impl From<u32> for SortingClass {
fn from(value: u32) -> Self {
match value {
1 => Self::Kits,
2 => Self::Tools,
3 => Self::Resources,
4 => Self::Food,
5 => Self::Clothing,
6 => Self::Appliances,
7 => Self::Atmospherics,
8 => Self::Storage,
9 => Self::Ores,
10 => Self::Ices,
_ => Self::Default,
}
}
}
#[derive(
Debug,
Default,
Clone,
Copy,
PartialEq,
Eq,
Hash,
strum_macros::Display,
EnumString,
EnumIter,
AsRefStr,
Serialize,
Deserialize,
)]
#[strum(serialize_all = "PascalCase")]
pub enum SlotType {
Helmet = 1,
Suit = 2,
Back,
GasFilter = 4,
GasCanister,
MotherBoard,
Circuitboard,
DataDisk = 8,
Organ,
Ore,
Plant,
Uniform,
Entity,
Battery,
Egg,
Belt = 16,
Tool,
Appliance,
Ingot,
Torpedo,
Cartridge,
AccessCard,
Magazine,
Circuit = 24,
Bottle,
ProgrammableChip,
Glasses,
CreditCard,
DirtCanister,
SensorProcessingUnit,
LiquidCanister,
LiquidBottle = 32,
Wreckage,
SoundCartridge,
DrillHead,
ScanningHead,
Flare,
Blocked,
#[default]
None = 0,
}
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct Prefab {
pub name: String,
@@ -591,28 +490,28 @@ impl Device {
(
LogicType::Setting,
LogicField {
field_type: FieldType::ReadWrite,
field_type: MemoryAccess::ReadWrite,
value: 0.0,
},
),
(
LogicType::RequiredPower,
LogicField {
field_type: FieldType::Read,
field_type: MemoryAccess::Read,
value: 0.0,
},
),
(
LogicType::PrefabHash,
LogicField {
field_type: FieldType::Read,
field_type: MemoryAccess::Read,
value: -128473777.0,
},
),
]);
let occupant = SlotOccupant::new(ic, -744098481);
device.slots.push(Slot::with_occupant(
SlotType::ProgrammableChip,
SlotClass::ProgrammableChip,
// -744098481 = ItemIntegratedCircuit10
occupant,
));
@@ -627,14 +526,14 @@ impl Device {
copy.insert(
LogicType::LineNumber,
LogicField {
field_type: FieldType::ReadWrite,
field_type: MemoryAccess::ReadWrite,
value: ic.ip() as f64,
},
);
copy.insert(
LogicType::Error,
LogicField {
field_type: FieldType::Read,
field_type: MemoryAccess::Read,
value: match *ic.state.borrow() {
ICState::Error(_) => 1.0,
_ => 0.0,
@@ -646,7 +545,7 @@ impl Device {
copy.insert(
LogicType::Power,
LogicField {
field_type: FieldType::Read,
field_type: MemoryAccess::Read,
value: if self.has_power_connection() {
1.0
} else {
@@ -658,7 +557,7 @@ impl Device {
copy.insert(
LogicType::ReferenceId,
LogicField {
field_type: FieldType::Read,
field_type: MemoryAccess::Read,
value: self.id as f64,
},
);
@@ -692,7 +591,10 @@ impl Device {
LogicType::Power if self.has_power_state() => true,
_ => {
if let Some(logic) = self.fields.get(&field) {
matches!(logic.field_type, FieldType::Read | FieldType::ReadWrite)
matches!(
logic.field_type,
MemoryAccess::Read | MemoryAccess::ReadWrite
)
} else {
false
}
@@ -706,7 +608,10 @@ impl Device {
LogicType::LineNumber if self.ic.is_some() => true,
_ => {
if let Some(logic) = self.fields.get(&field) {
matches!(logic.field_type, FieldType::Write | FieldType::ReadWrite)
matches!(
logic.field_type,
MemoryAccess::Write | MemoryAccess::ReadWrite
)
} else {
false
}
@@ -714,7 +619,7 @@ impl Device {
}
}
pub fn can_slot_logic_read(&self, field: SlotLogicType, slot: usize) -> bool {
pub fn can_slot_logic_read(&self, field: LogicSlotType, slot: usize) -> bool {
if self.slots.is_empty() {
return false;
}
@@ -724,7 +629,7 @@ impl Device {
slot.can_logic_read(field)
}
pub fn can_slot_logic_write(&self, field: SlotLogicType, slot: usize) -> bool {
pub fn can_slot_logic_write(&self, field: LogicSlotType, slot: usize) -> bool {
if self.slots.is_empty() {
return false;
}
@@ -743,7 +648,8 @@ impl Device {
.borrow();
Ok(ic.ip() as f64)
} else if let Some(field) = self.get_fields(vm).get(&typ) {
if field.field_type == FieldType::Read || field.field_type == FieldType::ReadWrite {
if field.field_type == MemoryAccess::Read || field.field_type == MemoryAccess::ReadWrite
{
Ok(field.value)
} else {
Err(ICError::WriteOnlyField(typ.to_string()))
@@ -774,8 +680,8 @@ impl Device {
ic.set_ip(val as u32);
Ok(())
} else if let Some(field) = self.fields.get_mut(&typ) {
if field.field_type == FieldType::Write
|| field.field_type == FieldType::ReadWrite
if field.field_type == MemoryAccess::Write
|| field.field_type == MemoryAccess::ReadWrite
|| force
{
field.value = val;
@@ -787,7 +693,7 @@ impl Device {
self.fields.insert(
typ,
LogicField {
field_type: FieldType::ReadWrite,
field_type: MemoryAccess::ReadWrite,
value: val,
},
);
@@ -797,15 +703,15 @@ impl Device {
}
}
pub fn get_slot_field(&self, index: f64, typ: SlotLogicType, vm: &VM) -> Result<f64, ICError> {
pub fn get_slot_field(&self, index: f64, typ: LogicSlotType, vm: &VM) -> Result<f64, ICError> {
let slot = self
.slots
.get(index as usize)
.ok_or(ICError::SlotIndexOutOfRange(index))?;
if slot.typ == SlotType::ProgrammableChip
if slot.typ == SlotClass::ProgrammableChip
&& slot.occupant.is_some()
&& self.ic.is_some()
&& typ == SlotLogicType::LineNumber
&& typ == LogicSlotType::LineNumber
{
let ic = vm
.ics
@@ -822,22 +728,22 @@ impl Device {
&self,
index: f64,
vm: &VM,
) -> Result<BTreeMap<SlotLogicType, LogicField>, ICError> {
) -> Result<BTreeMap<LogicSlotType, LogicField>, ICError> {
let slot = self
.slots
.get(index as usize)
.ok_or(ICError::SlotIndexOutOfRange(index))?;
let mut fields = slot.get_fields();
if slot.typ == SlotType::ProgrammableChip && slot.occupant.is_some() && self.ic.is_some() {
if slot.typ == SlotClass::ProgrammableChip && slot.occupant.is_some() && self.ic.is_some() {
let ic = vm
.ics
.get(&self.ic.unwrap())
.ok_or_else(|| ICError::UnknownDeviceID(self.ic.unwrap() as f64))?
.borrow();
fields.insert(
SlotLogicType::LineNumber,
LogicSlotType::LineNumber,
LogicField {
field_type: FieldType::ReadWrite,
field_type: MemoryAccess::ReadWrite,
value: ic.ip() as f64,
},
);
@@ -848,7 +754,7 @@ impl Device {
pub fn set_slot_field(
&mut self,
index: f64,
typ: SlotLogicType,
typ: LogicSlotType,
val: f64,
_vm: &VM,
force: bool,
@@ -945,7 +851,7 @@ impl Device {
let ic = slots
.iter()
.find_map(|slot| {
if slot.typ == SlotType::ProgrammableChip && slot.occupant.is_some() {
if slot.typ == SlotClass::ProgrammableChip && slot.occupant.is_some() {
Some(slot.occupant.clone()).flatten()
} else {
None

View File

@@ -157,7 +157,7 @@ pub enum ICError {
#[error("unknown logic type '{0}'")]
UnknownLogicType(f64),
#[error("unknown slot logic type '{0}'")]
UnknownSlotLogicType(f64),
UnknownLogicSlotType(f64),
#[error("unknown batch mode '{0}'")]
UnknownBatchMode(f64),
#[error("unknown reagent mode '{0}'")]

View File

@@ -35,7 +35,7 @@ impl TryFrom<f64> for LogicSlotType {
if let Some(slt) = LogicSlotType::iter().find(|lt| *lt as u8 as f64 == value) {
Ok(slt)
} else {
Err(ICError::UnknownSlotLogicType(value))
Err(ICError::UnknownLogicSlotType(value))
}
}
}
@@ -1106,7 +1106,7 @@ mod tests {
assert_eq!(lt as u16, value.unwrap().parse::<u16>().unwrap());
}
for slt in LogicSlotType::iter() {
println!("testing SlotLogicType.{slt}");
println!("testing LogicSlotType.{slt}");
let value = slt.get_str("value");
assert!(value.is_some());
assert!(value.unwrap().parse::<u8>().is_ok());

View File

@@ -16,11 +16,13 @@ use itertools::Itertools;
use time::format_description;
use crate::{
device::SlotType,
errors::{ICError, LineError},
grammar,
vm::{
enums::script_enums::{LogicSlotType as SlotLogicType, LogicType},
enums::{
basic_enums::Class as SlotClass,
script_enums::{LogicSlotType, LogicType},
},
instructions::{
enums::InstructionOp,
operands::{DeviceSpec, Operand, RegisterSpec},
@@ -400,16 +402,16 @@ impl IC {
}
}
pub fn propgate_line_number(&self, vm: &VM) {
pub fn propagate_line_number(&self, vm: &VM) {
if let Some(device) = vm.devices.get(&self.device) {
let mut device_ref = device.borrow_mut();
let _ = device_ref.set_field(LogicType::LineNumber, self.ip.get() as f64, vm, true);
if let Some(slot) = device_ref
.slots
.iter_mut()
.find(|slot| slot.typ == SlotType::ProgrammableChip)
.find(|slot| slot.typ == SlotClass::ProgrammableChip)
{
let _ = slot.set_field(SlotLogicType::LineNumber, self.ip.get() as f64, true);
let _ = slot.set_field(LogicSlotType::LineNumber, self.ip.get() as f64, true);
}
}
}
@@ -2327,7 +2329,7 @@ impl IC {
return Err(DeviceNotSet);
};
let slt = slt.as_slot_logic_type(this, inst, 4)?;
if slt == SlotLogicType::LineNumber && this.device == device_id {
if slt == LogicSlotType::LineNumber && this.device == device_id {
// HACK: we can't use device.get_slot_field as that will try to reborrow our
// ic which will panic
this.set_register(indirection, target, this.ip() as f64)?;
@@ -2449,7 +2451,7 @@ impl IC {
if result.is_ok() || advance_ip_on_err {
self.ic.set(self.ic.get() + 1);
self.set_ip(next_ip);
self.propgate_line_number(vm);
self.propagate_line_number(vm);
}
result
}

View File

@@ -25,7 +25,19 @@ pub enum Connection {
}
#[derive(
Debug, Default, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, EnumIter, AsRefStr,
Debug,
Default,
Clone,
Copy,
PartialEq,
PartialOrd,
Eq,
Ord,
Hash,
Serialize,
Deserialize,
EnumIter,
AsRefStr,
)]
pub enum ConnectionType {
Pipe,
@@ -43,7 +55,19 @@ pub enum ConnectionType {
}
#[derive(
Debug, Default, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, EnumIter, AsRefStr,
Debug,
Default,
Clone,
Copy,
PartialEq,
PartialOrd,
Eq,
Ord,
Hash,
Serialize,
Deserialize,
EnumIter,
AsRefStr,
)]
pub enum ConnectionRole {
Input,

View File

@@ -7,9 +7,7 @@ use crate::{
errors::{ICError, VMError},
interpreter::{self, FrozenIC},
network::{CableConnectionType, Connection, FrozenNetwork, Network},
vm::enums::script_enums::{
LogicBatchMethod as BatchMode, LogicSlotType as SlotLogicType, LogicType,
},
vm::enums::script_enums::{LogicBatchMethod as BatchMode, LogicSlotType, LogicType},
};
use std::{
cell::RefCell,
@@ -620,7 +618,7 @@ impl VM {
source: u32,
prefab: f64,
index: f64,
typ: SlotLogicType,
typ: LogicSlotType,
val: f64,
write_readonly: bool,
) -> Result<(), ICError> {
@@ -690,7 +688,7 @@ impl VM {
prefab: f64,
name: f64,
index: f64,
typ: SlotLogicType,
typ: LogicSlotType,
mode: BatchMode,
) -> Result<f64, ICError> {
let samples = self
@@ -706,7 +704,7 @@ impl VM {
source: u32,
prefab: f64,
index: f64,
typ: SlotLogicType,
typ: LogicSlotType,
mode: BatchMode,
) -> Result<f64, ICError> {
let samples = self

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,7 @@
use crate::errors::ICError;
use crate::interpreter;
use crate::vm::enums::script_enums::{
LogicBatchMethod as BatchMode, LogicReagentMode as ReagentMode, LogicSlotType as SlotLogicType,
LogicType,
LogicBatchMethod as BatchMode, LogicReagentMode as ReagentMode, LogicSlotType, LogicType,
};
use crate::vm::instructions::enums::InstructionOp;
use serde_derive::{Deserialize, Serialize};
@@ -49,7 +48,7 @@ pub enum Operand {
Number(Number),
Type {
logic_type: Option<LogicType>,
slot_logic_type: Option<SlotLogicType>,
slot_logic_type: Option<LogicSlotType>,
batch_mode: Option<BatchMode>,
reagent_mode: Option<ReagentMode>,
identifier: Identifier,
@@ -243,13 +242,13 @@ impl Operand {
ic: &interpreter::IC,
inst: InstructionOp,
index: u32,
) -> Result<SlotLogicType, ICError> {
) -> Result<LogicSlotType, ICError> {
match &self {
Operand::Type {
slot_logic_type: Some(slt),
..
} => Ok(*slt),
_ => SlotLogicType::try_from(self.as_value(ic, inst, index)?),
_ => LogicSlotType::try_from(self.as_value(ic, inst, index)?),
}
}

View File

@@ -1,17 +1,41 @@
use std::{cell::RefCell, ops::Deref, rc::Rc};
use macro_rules_attribute::derive;
use serde_derive::{Deserialize, Serialize};
pub mod errors;
pub mod generic;
pub mod macros;
pub mod stationpedia;
pub mod templates;
pub mod traits;
use traits::*;
use crate::{device::SlotType, vm::enums::script_enums::LogicSlotType as SlotLogicType};
use crate::vm::enums::{basic_enums::Class as SlotClass, script_enums::LogicSlotType};
pub type ObjectID = u32;
pub type BoxedObject = Box<dyn Object<ID = ObjectID>>;
pub type BoxedObject = Rc<RefCell<dyn Object<ID = ObjectID>>>;
pub struct VMObject(BoxedObject);
impl Deref for VMObject {
type Target = BoxedObject;
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl VMObject {
pub fn new<T>(val: T) -> Self
where
T: Object<ID = ObjectID> + 'static,
{
VMObject(Rc::new(RefCell::new(val)))
}
}
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct Name {
@@ -33,8 +57,8 @@ impl Name {
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum FieldType {
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub enum MemoryAccess {
Read,
Write,
ReadWrite,
@@ -42,13 +66,13 @@ pub enum FieldType {
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LogicField {
pub field_type: FieldType,
pub field_type: MemoryAccess,
pub value: f64,
}
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct Slot {
pub typ: SlotType,
pub enabled_logic: Vec<SlotLogicType>,
pub typ: SlotClass,
pub enabled_logic: Vec<LogicSlotType>,
pub occupant: Option<ObjectID>,
}

View File

@@ -1,18 +1,18 @@
use serde_derive::{Deserialize, Serialize};
use thiserror::Error;
use crate::vm::enums::script_enums::{LogicSlotType as SlotLogicType, LogicType};
use crate::vm::enums::script_enums::{LogicSlotType, LogicType};
#[derive(Error, Debug, Serialize, Deserialize)]
pub enum LogicError {
#[error("can't read LogicType {0}")]
CantRead(LogicType),
#[error("can't read slot {1} SlotLogicType {0}")]
CantSlotRead(SlotLogicType, usize),
#[error("can't read slot {1} LogicSlotType {0}")]
CantSlotRead(LogicSlotType, usize),
#[error("can't write LogicType {0}")]
CantWrite(LogicType),
#[error("can't write slot {1} SlotLogicType {0}")]
CantSlotWrite(SlotLogicType, usize),
#[error("can't write slot {1} LogicSlotType {0}")]
CantSlotWrite(LogicSlotType, usize),
#[error("slot id {0} is out of range 0..{1}")]
SlotIndexOutOfRange(usize, usize),
}

View File

@@ -0,0 +1,3 @@
pub mod macros;
pub mod structs;
pub mod traits;

View File

@@ -0,0 +1,75 @@
macro_rules! GWLogicable {
(
$( #[$attr:meta] )*
$viz:vis struct $struct:ident {
$($body:tt)*
}
) => {
impl GWLogicable for $struct {
fn name(&self) -> &Option<Name> {
&self.name
}
fn fields(&self) -> &BTreeMap<LogicType, LogicField> {
&self.fields
}
fn fields_mut(&mut self) -> &mut BTreeMap<LogicType, LogicField> {
&mut self.fields
}
fn slots(&self) -> &Vec<Slot> {
&self.slots
}
fn slots_mut(&mut self) -> &mut Vec<Slot> {
&mut self.slots
}
}
};
}
pub(crate) use GWLogicable;
macro_rules! GWMemoryReadable {
(
$( #[$attr:meta] )*
$viz:vis struct $struct:ident {
$($body:tt)*
}
) => {
impl GWMemoryReadable for $struct {
fn memory_size(&self) -> usize {
self.memory.len()
}
fn memory(&self) -> &Vec<f64> {
&self.memory
}
}
};
}
pub(crate) use GWMemoryReadable;
macro_rules! GWMemoryWritable {
(
$( #[$attr:meta] )*
$viz:vis struct $struct:ident {
$($body:tt)*
}
) => {
impl GWMemoryWritable for $struct {
fn memory_mut(&mut self) -> &mut Vec<f64> {
&mut self.memory
}
}
};
}
pub(crate) use GWMemoryWritable;
macro_rules! GWDevice {
(
$( #[$attr:meta] )*
$viz:vis struct $struct:ident {
$($body:tt)*
}
) => {
impl GWDevice for $struct {}
};
}
pub(crate) use GWDevice;

View File

@@ -0,0 +1,93 @@
use super::{macros::*, traits::*};
use crate::vm::{
enums::script_enums::LogicType,
object::{macros::ObjectInterface, traits::*, LogicField, Name, ObjectID, Slot},
};
use macro_rules_attribute::derive;
use std::{collections::BTreeMap, usize};
#[derive(ObjectInterface!)]
#[custom(implements(Object { }))]
pub struct Generic {
#[custom(object_id)]
id: ObjectID,
#[custom(object_prefab)]
prefab: Name,
}
#[derive(ObjectInterface!, GWLogicable!)]
#[custom(implements(Object { Logicable }))]
pub struct GenericLogicable {
#[custom(object_id)]
id: ObjectID,
#[custom(object_prefab)]
prefab: Name,
name: Option<Name>,
fields: BTreeMap<LogicType, LogicField>,
slots: Vec<Slot>,
}
#[derive(ObjectInterface!, GWLogicable!, GWDevice!)]
#[custom(implements(Object { Logicable, Device }))]
pub struct GenericLogicableDevice {
#[custom(object_id)]
id: ObjectID,
#[custom(object_prefab)]
prefab: Name,
name: Option<Name>,
fields: BTreeMap<LogicType, LogicField>,
slots: Vec<Slot>,
}
#[derive(ObjectInterface!, GWLogicable!, GWMemoryReadable!)]
#[custom(implements(Object { Logicable, MemoryReadable }))]
pub struct GenericLogicableMemoryReadable {
#[custom(object_id)]
id: ObjectID,
#[custom(object_prefab)]
prefab: Name,
name: Option<Name>,
fields: BTreeMap<LogicType, LogicField>,
slots: Vec<Slot>,
memory: Vec<f64>,
}
#[derive(ObjectInterface!, GWLogicable!, GWMemoryReadable!, GWMemoryWritable!)]
#[custom(implements(Object { Logicable, MemoryReadable, MemoryWritable }))]
pub struct GenericLogicableMemoryReadWritable {
#[custom(object_id)]
id: ObjectID,
#[custom(object_prefab)]
prefab: Name,
name: Option<Name>,
fields: BTreeMap<LogicType, LogicField>,
slots: Vec<Slot>,
memory: Vec<f64>,
}
#[derive(ObjectInterface!, GWLogicable!, GWDevice!, GWMemoryReadable!, GWMemoryWritable!)]
#[custom(implements(Object { Logicable, Device, MemoryReadable }))]
pub struct GenericLogicableDeviceMemoryReadable {
#[custom(object_id)]
id: ObjectID,
#[custom(object_prefab)]
prefab: Name,
name: Option<Name>,
fields: BTreeMap<LogicType, LogicField>,
slots: Vec<Slot>,
memory: Vec<f64>,
}
#[derive(ObjectInterface!, GWLogicable!, GWDevice!, GWMemoryReadable!, GWMemoryWritable!)]
#[custom(implements(Object { Logicable, Device, MemoryReadable, MemoryWritable }))]
pub struct GenericLogicableDeviceMemoryReadWriteablable {
#[custom(object_id)]
id: ObjectID,
#[custom(object_prefab)]
prefab: Name,
name: Option<Name>,
fields: BTreeMap<LogicType, LogicField>,
slots: Vec<Slot>,
memory: Vec<f64>,
}

View File

@@ -0,0 +1,162 @@
use crate::vm::{
enums::script_enums::{LogicSlotType, LogicType},
object::{
errors::{LogicError, MemoryError},
traits::*,
LogicField, MemoryAccess, Name, Slot,
},
VM,
};
use std::{collections::BTreeMap, usize};
use strum::IntoEnumIterator;
pub trait GWLogicable {
fn name(&self) -> &Option<Name>;
fn fields(&self) -> &BTreeMap<LogicType, LogicField>;
fn fields_mut(&mut self) -> &mut BTreeMap<LogicType, LogicField>;
fn slots(&self) -> &Vec<Slot>;
fn slots_mut(&mut self) -> &mut Vec<Slot>;
}
pub trait GWMemoryReadable {
fn memory_size(&self) -> usize;
fn memory(&self) -> &Vec<f64>;
}
pub trait GWMemoryWritable: GWMemoryReadable {
fn memory_mut(&mut self) -> &mut Vec<f64>;
}
pub trait GWDevice: GWLogicable {}
pub trait GWCircuitHolder: GWLogicable {}
impl<T: GWLogicable + Object> Logicable for T {
fn prefab_hash(&self) -> i32 {
self.prefab().hash
}
fn name_hash(&self) -> i32 {
self.name().as_ref().map(|name| name.hash).unwrap_or(0)
}
fn is_logic_readable(&self) -> bool {
LogicType::iter().any(|lt| self.can_logic_read(lt))
}
fn is_logic_writeable(&self) -> bool {
LogicType::iter().any(|lt| self.can_logic_write(lt))
}
fn can_logic_read(&self, lt: LogicType) -> bool {
self.fields()
.get(&lt)
.map(|field| {
matches!(
field.field_type,
MemoryAccess::Read | MemoryAccess::ReadWrite
)
})
.unwrap_or(false)
}
fn can_logic_write(&self, lt: LogicType) -> bool {
self.fields()
.get(&lt)
.map(|field| {
matches!(
field.field_type,
MemoryAccess::Write | MemoryAccess::ReadWrite
)
})
.unwrap_or(false)
}
fn get_logic(&self, lt: LogicType) -> Result<f64, LogicError> {
self.fields()
.get(&lt)
.and_then(|field| match field.field_type {
MemoryAccess::Read | MemoryAccess::ReadWrite => Some(field.value),
_ => None,
})
.ok_or(LogicError::CantRead(lt))
}
fn set_logic(&mut self, lt: LogicType, value: f64, force: bool) -> Result<(), LogicError> {
self.fields_mut()
.get_mut(&lt)
.ok_or(LogicError::CantWrite(lt))
.and_then(|field| match field.field_type {
MemoryAccess::Write | MemoryAccess::ReadWrite => {
field.value = value;
Ok(())
}
_ if force => {
field.value = value;
Ok(())
}
_ => Err(LogicError::CantWrite(lt)),
})
}
fn slots_count(&self) -> usize {
self.slots().len()
}
fn get_slot(&self, index: usize) -> Option<&Slot> {
self.slots().get(index)
}
fn get_slot_mut(&mut self, index: usize) -> Option<&mut Slot> {
self.slots_mut().get_mut(index)
}
fn can_slot_logic_read(&self, slt: LogicSlotType, index: usize) -> bool {
self.get_slot(index)
.map(|slot| slot.enabled_logic.contains(&slt))
.unwrap_or(false)
}
fn get_slot_logic(
&self,
slt: LogicSlotType,
index: usize,
_vm: &VM,
) -> Result<f64, LogicError> {
self.get_slot(index)
.ok_or_else(|| LogicError::SlotIndexOutOfRange(index, self.slots().len()))
.and_then(|slot| {
if slot.enabled_logic.contains(&slt) {
match slot.occupant {
Some(_id) => {
// FIXME: impliment by accessing VM to get occupant
Ok(0.0)
}
None => Ok(0.0),
}
} else {
Err(LogicError::CantSlotRead(slt, index))
}
})
}
}
impl<T: GWMemoryReadable + Object> MemoryReadable for T {
fn memory_size(&self) -> usize {
self.memory_size()
}
fn get_memory(&self, index: i32) -> Result<f64, MemoryError> {
if index < 0 {
Err(MemoryError::StackUnderflow(index, self.memory().len()))
} else if index as usize >= self.memory().len() {
Err(MemoryError::StackOverflow(index, self.memory().len()))
} else {
Ok(self.memory()[index as usize])
}
}
}
impl<T: GWMemoryWritable + MemoryReadable + Object> MemoryWritable for T {
fn set_memory(&mut self, index: i32, val: f64) -> Result<(), MemoryError> {
if index < 0 {
Err(MemoryError::StackUnderflow(index, self.memory().len()))
} else if index as usize >= self.memory().len() {
Err(MemoryError::StackOverflow(index, self.memory().len()))
} else {
self.memory_mut()[index as usize] = val;
Ok(())
}
}
fn clear_memory(&mut self) -> Result<(), MemoryError> {
self.memory_mut().fill(0.0);
Ok(())
}
}
impl<T: GWDevice + Object> Device for T {}

View File

@@ -1,7 +1,7 @@
use std::str::FromStr;
use crate::vm::enums::prefabs::StationpediaPrefab;
use crate::vm::object::BoxedObject;
use crate::vm::object::VMObject;
#[allow(unused)]
pub enum PrefabTemplate {
@@ -10,7 +10,7 @@ pub enum PrefabTemplate {
}
#[allow(unused)]
pub fn object_from_prefab_template(template: &PrefabTemplate) -> Option<BoxedObject> {
pub fn object_from_prefab_template(template: &PrefabTemplate) -> Option<VMObject> {
let prefab = match template {
PrefabTemplate::Hash(hash) => StationpediaPrefab::from_repr(*hash),
PrefabTemplate::Name(name) => StationpediaPrefab::from_str(name).ok(),
@@ -22,5 +22,3 @@ pub fn object_from_prefab_template(template: &PrefabTemplate) -> Option<BoxedObj
_ => None,
}
}
pub mod generic;

View File

@@ -1,306 +0,0 @@
use crate::vm::{
enums::script_enums::{LogicSlotType as SlotLogicType, LogicType},
object::{
errors::{LogicError, MemoryError},
macros::ObjectInterface,
traits::*,
FieldType, LogicField, Name, ObjectID, Slot,
},
VM,
};
use macro_rules_attribute::derive;
use std::{collections::BTreeMap, usize};
use strum::IntoEnumIterator;
pub trait GWLogicable {
fn name(&self) -> &Option<Name>;
fn fields(&self) -> &BTreeMap<LogicType, LogicField>;
fn fields_mut(&mut self) -> &mut BTreeMap<LogicType, LogicField>;
fn slots(&self) -> &Vec<Slot>;
fn slots_mut(&mut self) -> &mut Vec<Slot>;
}
macro_rules! GWLogicable {
(
$( #[$attr:meta] )*
$viz:vis struct $struct:ident {
$($body:tt)*
}
) => {
impl GWLogicable for $struct {
fn name(&self) -> &Option<Name> {
&self.name
}
fn fields(&self) -> &BTreeMap<LogicType, LogicField> {
&self.fields
}
fn fields_mut(&mut self) -> &mut BTreeMap<LogicType, LogicField> {
&mut self.fields
}
fn slots(&self) -> &Vec<Slot> {
&self.slots
}
fn slots_mut(&mut self) -> &mut Vec<Slot> {
&mut self.slots
}
}
};
}
pub trait GWMemoryReadable {
fn memory_size(&self) -> usize;
fn memory(&self) -> &Vec<f64>;
}
macro_rules! GWMemoryReadable {
(
$( #[$attr:meta] )*
$viz:vis struct $struct:ident {
$($body:tt)*
}
) => {
impl GWMemoryReadable for $struct {
fn memory_size(&self) -> usize {
self.memory.len()
}
fn memory(&self) -> &Vec<f64> {
&self.memory
}
}
};
}
pub trait GWMemoryWritable: GWMemoryReadable {
fn memory_mut(&mut self) -> &mut Vec<f64>;
}
macro_rules! GWMemoryWritable {
(
$( #[$attr:meta] )*
$viz:vis struct $struct:ident {
$($body:tt)*
}
) => {
impl GWMemoryWritable for $struct {
fn memory_mut(&mut self) -> &mut Vec<f64> {
&mut self.memory
}
}
};
}
pub trait GWDevice: GWLogicable {}
macro_rules! GWDevice {
(
$( #[$attr:meta] )*
$viz:vis struct $struct:ident {
$($body:tt)*
}
) => {
impl GWDevice for $struct {}
};
}
pub trait GWCircuitHolder: GWLogicable {}
impl<T: GWLogicable + Object> Logicable for T {
fn prefab_hash(&self) -> i32 {
self.prefab().hash
}
fn name_hash(&self) -> i32 {
self.name().as_ref().map(|name| name.hash).unwrap_or(0)
}
fn is_logic_readable(&self) -> bool {
LogicType::iter().any(|lt| self.can_logic_read(lt))
}
fn is_logic_writeable(&self) -> bool {
LogicType::iter().any(|lt| self.can_logic_write(lt))
}
fn can_logic_read(&self, lt: LogicType) -> bool {
self.fields()
.get(&lt)
.map(|field| matches!(field.field_type, FieldType::Read | FieldType::ReadWrite))
.unwrap_or(false)
}
fn can_logic_write(&self, lt: LogicType) -> bool {
self.fields()
.get(&lt)
.map(|field| matches!(field.field_type, FieldType::Write | FieldType::ReadWrite))
.unwrap_or(false)
}
fn get_logic(&self, lt: LogicType) -> Result<f64, LogicError> {
self.fields()
.get(&lt)
.and_then(|field| match field.field_type {
FieldType::Read | FieldType::ReadWrite => Some(field.value),
_ => None,
})
.ok_or(LogicError::CantRead(lt))
}
fn set_logic(&mut self, lt: LogicType, value: f64, force: bool) -> Result<(), LogicError> {
self.fields_mut()
.get_mut(&lt)
.ok_or(LogicError::CantWrite(lt))
.and_then(|field| match field.field_type {
FieldType::Write | FieldType::ReadWrite => {
field.value = value;
Ok(())
}
_ if force => {
field.value = value;
Ok(())
}
_ => Err(LogicError::CantWrite(lt)),
})
}
fn slots_count(&self) -> usize {
self.slots().len()
}
fn get_slot(&self, index: usize) -> Option<&Slot> {
self.slots().get(index)
}
fn get_slot_mut(&mut self, index: usize) -> Option<&mut Slot> {
self.slots_mut().get_mut(index)
}
fn can_slot_logic_read(&self, slt: SlotLogicType, index: usize) -> bool {
self.get_slot(index)
.map(|slot| slot.enabled_logic.contains(&slt))
.unwrap_or(false)
}
fn get_slot_logic(
&self,
slt: SlotLogicType,
index: usize,
_vm: &VM,
) -> Result<f64, LogicError> {
self.get_slot(index)
.ok_or_else(|| LogicError::SlotIndexOutOfRange(index, self.slots().len()))
.and_then(|slot| {
if slot.enabled_logic.contains(&slt) {
match slot.occupant {
Some(_id) => {
// FIXME: impliment by accessing VM to get occupant
Ok(0.0)
}
None => Ok(0.0),
}
} else {
Err(LogicError::CantSlotRead(slt, index))
}
})
}
}
impl<T: GWMemoryReadable + Object> MemoryReadable for T {
fn memory_size(&self) -> usize {
self.memory_size()
}
fn get_memory(&self, index: i32) -> Result<f64, MemoryError> {
if index < 0 {
Err(MemoryError::StackUnderflow(index, self.memory().len()))
} else if index as usize >= self.memory().len() {
Err(MemoryError::StackOverflow(index, self.memory().len()))
} else {
Ok(self.memory()[index as usize])
}
}
}
impl<T: GWMemoryWritable + MemoryReadable + Object> MemoryWritable for T {
fn set_memory(&mut self, index: i32, val: f64) -> Result<(), MemoryError> {
if index < 0 {
Err(MemoryError::StackUnderflow(index, self.memory().len()))
} else if index as usize >= self.memory().len() {
Err(MemoryError::StackOverflow(index, self.memory().len()))
} else {
self.memory_mut()[index as usize] = val;
Ok(())
}
}
fn clear_memory(&mut self) -> Result<(), MemoryError> {
self.memory_mut().fill(0.0);
Ok(())
}
}
impl<T: GWDevice + Object> Device for T {}
#[derive(ObjectInterface!)]
#[custom(implements(Object { }))]
pub struct Generic {
#[custom(object_id)]
id: ObjectID,
#[custom(object_prefab)]
prefab: Name,
}
#[derive(ObjectInterface!, GWLogicable!)]
#[custom(implements(Object { Logicable }))]
pub struct GenericLogicable {
#[custom(object_id)]
id: ObjectID,
#[custom(object_prefab)]
prefab: Name,
name: Option<Name>,
fields: BTreeMap<LogicType, LogicField>,
slots: Vec<Slot>,
}
#[derive(ObjectInterface!, GWLogicable!, GWDevice!)]
#[custom(implements(Object { Logicable, Device }))]
pub struct GenericLogicableDevice {
#[custom(object_id)]
id: ObjectID,
#[custom(object_prefab)]
prefab: Name,
name: Option<Name>,
fields: BTreeMap<LogicType, LogicField>,
slots: Vec<Slot>,
}
#[derive(ObjectInterface!, GWLogicable!, GWMemoryReadable!)]
#[custom(implements(Object { Logicable, MemoryReadable }))]
pub struct GenericLogicableMemoryReadable {
#[custom(object_id)]
id: ObjectID,
#[custom(object_prefab)]
prefab: Name,
name: Option<Name>,
fields: BTreeMap<LogicType, LogicField>,
slots: Vec<Slot>,
memory: Vec<f64>,
}
#[derive(ObjectInterface!, GWLogicable!, GWMemoryReadable!, GWMemoryWritable!)]
#[custom(implements(Object { Logicable, MemoryReadable, MemoryWritable }))]
pub struct GenericLogicableMemoryReadWritable {
#[custom(object_id)]
id: ObjectID,
#[custom(object_prefab)]
prefab: Name,
name: Option<Name>,
fields: BTreeMap<LogicType, LogicField>,
slots: Vec<Slot>,
memory: Vec<f64>,
}
#[derive(ObjectInterface!, GWLogicable!, GWDevice!, GWMemoryReadable!, GWMemoryWritable!)]
#[custom(implements(Object { Logicable, Device, MemoryReadable }))]
pub struct GenericLogicableDeviceMemoryReadable {
#[custom(object_id)]
id: ObjectID,
#[custom(object_prefab)]
prefab: Name,
name: Option<Name>,
fields: BTreeMap<LogicType, LogicField>,
slots: Vec<Slot>,
memory: Vec<f64>,
}
#[derive(ObjectInterface!, GWLogicable!, GWDevice!, GWMemoryReadable!, GWMemoryWritable!)]
#[custom(implements(Object { Logicable, Device, MemoryReadable, MemoryWritable }))]
pub struct GenericLogicableDeviceMemoryReadWriteablable {
#[custom(object_id)]
id: ObjectID,
#[custom(object_prefab)]
prefab: Name,
name: Option<Name>,
fields: BTreeMap<LogicType, LogicField>,
slots: Vec<Slot>,
memory: Vec<f64>,
}

View File

@@ -0,0 +1,247 @@
use std::collections::BTreeMap;
use crate::{
network::{ConnectionRole, ConnectionType},
vm::enums::{
basic_enums::{Class as SlotClass, GasType, SortingClass},
script_enums::{LogicSlotType, LogicType},
},
};
use serde_derive::{Deserialize, Serialize};
use super::{MemoryAccess, ObjectID};
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ObjectTemplate {
Structure(StructureTemplate),
StructureSlots(StructureSlotsTemplate),
StructureLogic(StructureLogicTemplate),
StructureLogicDevice(StructureLogicDeviceTemplate),
StructureLogicDeviceMemory(StructureLogicDeviceMemoryTemplate),
Item(ItemTemplate),
ItemSlots(ItemSlotsTemplate),
ItemLogic(ItemLogicTemplate),
ItemLogicMemory(ItemLogicMemoryTemplate),
}
impl ObjectTemplate {
fn prefab(&self) -> &PrefabInfo {
use ObjectTemplate::*;
match self {
Structure(s) => &s.prefab,
StructureSlots(s) => &s.prefab,
StructureLogic(s) => &s.prefab,
StructureLogicDevice(s) => &s.prefab,
StructureLogicDeviceMemory(s) => &s.prefab,
Item(i) => &i.prefab,
ItemSlots(i) => &i.prefab,
ItemLogic(i) => &i.prefab,
ItemLogicMemory(i) => &i.prefab,
}
}
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PrefabInfo {
pub prefab_name: String,
pub prefab_hash: i32,
pub desc: String,
pub name: String,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ObjectInfo {
pub name: Option<String>,
pub id: Option<ObjectID>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SlotInfo {
pub name: String,
pub typ: String,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
pub struct LogicSlotTypes {
#[serde(flatten)]
pub slot_types: BTreeMap<LogicSlotType, MemoryAccess>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
pub struct LogicTypes {
#[serde(flatten)]
pub types: BTreeMap<LogicType, MemoryAccess>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct LogicInfo {
pub logic_slot_types: BTreeMap<u32, LogicSlotTypes>,
pub logic_types: LogicTypes,
#[serde(skip_serializing_if = "Option::is_none")]
pub modes: Option<BTreeMap<u32, String>>,
pub transmission_receiver: bool,
pub wireless_logic: bool,
pub circuit_holder: bool,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ItemInfo {
pub consumable: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub filter_type: Option<GasType>,
pub ingredient: bool,
pub max_quantity: f64,
#[serde(skip_serializing_if = "Option::is_none")]
pub reagents: Option<BTreeMap<String, f64>>,
pub slot_class: SlotClass,
pub sorting_class: SortingClass,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ConnectionInfo {
pub typ: ConnectionType,
pub role: ConnectionRole,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct DeviceInfo {
pub connection_list: Vec<ConnectionInfo>,
#[serde(skip_serializing_if = "Option::is_none")]
pub device_pins_length: Option<i64>,
pub has_activate_state: bool,
pub has_atmosphere: bool,
pub has_color_state: bool,
pub has_lock_state: bool,
pub has_mode_state: bool,
pub has_on_off_state: bool,
pub has_open_state: bool,
pub has_reagents: bool,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct StructureInfo {
pub small_grid: bool,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Instruction {
pub description: String,
pub typ: String,
pub value: i64,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MemoryInfo {
#[serde(skip_serializing_if = "Option::is_none")]
pub instructions: Option<BTreeMap<String, Instruction>>,
pub memory_access: MemoryAccess,
pub memory_size: i64,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct StructureTemplate {
#[serde(skip_serializing_if = "Option::is_none")]
pub object: Option<ObjectInfo>,
pub prefab: PrefabInfo,
pub structure: StructureInfo,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct StructureSlotsTemplate {
#[serde(skip_serializing_if = "Option::is_none")]
pub object: Option<ObjectInfo>,
pub prefab: PrefabInfo,
pub structure: StructureInfo,
pub slots: Vec<SlotInfo>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct StructureLogicTemplate {
#[serde(skip_serializing_if = "Option::is_none")]
pub object: Option<ObjectInfo>,
pub prefab: PrefabInfo,
pub structure: StructureInfo,
pub logic: LogicInfo,
pub slots: Vec<SlotInfo>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct StructureLogicDeviceTemplate {
#[serde(skip_serializing_if = "Option::is_none")]
pub object: Option<ObjectInfo>,
pub prefab: PrefabInfo,
pub structure: StructureInfo,
pub logic: LogicInfo,
pub slots: Vec<SlotInfo>,
pub device: DeviceInfo,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct StructureLogicDeviceMemoryTemplate {
#[serde(skip_serializing_if = "Option::is_none")]
pub object: Option<ObjectInfo>,
pub prefab: PrefabInfo,
pub structure: StructureInfo,
pub logic: LogicInfo,
pub slots: Vec<SlotInfo>,
pub device: DeviceInfo,
pub memory: MemoryInfo,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ItemTemplate {
#[serde(skip_serializing_if = "Option::is_none")]
pub object: Option<ObjectInfo>,
pub prefab: PrefabInfo,
pub item: ItemInfo,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ItemSlotsTemplate {
#[serde(skip_serializing_if = "Option::is_none")]
pub object: Option<ObjectInfo>,
pub prefab: PrefabInfo,
pub item: ItemInfo,
pub slots: Vec<SlotInfo>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ItemLogicTemplate {
#[serde(skip_serializing_if = "Option::is_none")]
pub object: Option<ObjectInfo>,
pub prefab: PrefabInfo,
pub item: ItemInfo,
pub logic: LogicInfo,
pub slots: Vec<SlotInfo>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ItemLogicMemoryTemplate {
#[serde(skip_serializing_if = "Option::is_none")]
pub object: Option<ObjectInfo>,
pub prefab: PrefabInfo,
pub item: ItemInfo,
pub logic: LogicInfo,
pub slots: Vec<SlotInfo>,
pub memory: MemoryInfo,
}

View File

@@ -25,12 +25,12 @@ fn main() {
ts_types.push_str(&lt_tstype);
let slt_tsunion: String = Itertools::intersperse(
ic10emu::grammar::generated::SlotLogicType::iter()
ic10emu::grammar::generated::LogicSlotType::iter()
.map(|slt| format!("\"{}\"", slt.as_ref())),
"\n | ".to_owned(),
)
.collect();
let slt_tstype = format!("\nexport type SlotLogicType = {};", slt_tsunion);
let slt_tstype = format!("\nexport type LogicSlotType = {};", slt_tsunion);
ts_types.push_str(&slt_tstype);
let bm_tsunion: String = Itertools::intersperse(

View File

@@ -4,7 +4,7 @@ mod types;
use ic10emu::{
device::{Device, DeviceTemplate, SlotOccupantTemplate},
grammar::{LogicType, SlotLogicType},
grammar::{LogicSlotType, LogicType},
vm::{FrozenVM, VMError, VM},
};
use serde_derive::{Deserialize, Serialize};
@@ -308,7 +308,7 @@ impl DeviceRef {
value: f64,
force: bool,
) -> Result<(), JsError> {
let logic_typ = SlotLogicType::from_str(field)?;
let logic_typ = LogicSlotType::from_str(field)?;
let mut device_ref = self.device.borrow_mut();
device_ref.set_slot_field(slot, logic_typ, value, &self.vm.borrow(), force)?;
Ok(())
@@ -316,7 +316,7 @@ impl DeviceRef {
#[wasm_bindgen(js_name = "getSlotField", skip_typescript)]
pub fn get_slot_field(&self, slot: f64, field: &str) -> Result<f64, JsError> {
let logic_typ = SlotLogicType::from_str(field)?;
let logic_typ = LogicSlotType::from_str(field)?;
let device_ref = self.device.borrow_mut();
Ok(device_ref.get_slot_field(slot, logic_typ, &self.vm.borrow())?)
}

View File

@@ -27,7 +27,7 @@ pub struct SlotOccupant {
pub quantity: u32,
pub max_quantity: u32,
pub damage: f64,
pub fields: BTreeMap<ic10emu::grammar::SlotLogicType, ic10emu::device::LogicField>,
pub fields: BTreeMap<ic10emu::grammar::LogicSlotType, ic10emu::device::LogicField>,
}
impl From<&ic10emu::device::SlotOccupant> for SlotOccupant {
@@ -49,7 +49,7 @@ impl From<&ic10emu::device::SlotOccupant> for SlotOccupant {
pub struct Slot {
pub typ: ic10emu::device::SlotType,
pub occupant: Option<SlotOccupant>,
pub fields: BTreeMap<ic10emu::grammar::SlotLogicType, ic10emu::device::LogicField>,
pub fields: BTreeMap<ic10emu::grammar::LogicSlotType, ic10emu::device::LogicField>,
}
impl From<&ic10emu::device::Slot> for Slot {

View File

@@ -1,11 +1,11 @@
export type FieldType = "Read" | "Write" | "ReadWrite";
export type MemoryAccess = "Read" | "Write" | "ReadWrite";
export interface LogicField {
field_type: FieldType;
field_type: MemoryAccess;
value: number;
}
export type LogicFields = Map<LogicType, LogicField>;
export type SlotLogicFields = Map<SlotLogicType, LogicField>;
export type SlotLogicFields = Map<LogicSlotType, LogicField>;
export type Reagents = Map<string, Map<number, number>>;
@@ -39,7 +39,7 @@ export type DeviceSpec = {
readonly connection: number | undefined;
};
export type OperandLogicType = { readonly LogicType: string };
export type OperandSlotLogicType = { readonly SlotLogicType: string };
export type OperandLogicSlotType = { readonly LogicSlotType: string };
export type OperandBatchMode = { readonly BatchMode: string };
export type OperandReagentMode = { readonly ReagentMode: string };
export type Identifier = { readonly Identifier: { name: string } };
@@ -65,7 +65,7 @@ export type Operand =
| DeviceSpec
| NumberOperand
| OperandLogicType
| OperandSlotLogicType
| OperandLogicSlotType
| OperandBatchMode
| OperandReagentMode
| Identifier;
@@ -109,13 +109,13 @@ export interface DeviceRef {
readonly program?: Program;
getSlotFields(slot: number): SlotLogicFields;
setField(field: LogicType, value: number, force: boolean): void;
setSlotField(slot: number, field: SlotLogicType, value: number, force: boolean): void;
getSlotField(slot: number, field: SlotLogicType): number;
setSlotField(slot: number, field: LogicSlotType, value: number, force: boolean): void;
getSlotField(slot: number, field: LogicSlotType): number;
}
export interface SlotOccupantTemplate {
id?: number;
fields: { [key in SlotLogicType]?: LogicField };
fields: { [key in LogicSlotType]?: LogicField };
}
export interface SlotTemplate {

View File

@@ -103,8 +103,8 @@
"slotclass",
"slotlogic",
"slotlogicable",
"slotlogictype",
"slotlogictypes",
"LogicSlotType",
"LogicSlotTypes",
"slottype",
"sltz",
"snan",

View File

@@ -8,7 +8,7 @@ import {
parseNumber,
} from "utils";
import {
SlotLogicType,
LogicSlotType,
SlotType,
} from "ic10emu_wasm";
import SlInput from "@shoelace-style/shoelace/dist/components/input/input.component.js";
@@ -265,7 +265,7 @@ export class VMDeviceSlot extends VMDeviceMixin(VMDeviceDBMixin(BaseElement)) {
_handleChangeSlotField(e: CustomEvent) {
const input = e.target as SlInput;
const field = input.getAttribute("key")! as SlotLogicType;
const field = input.getAttribute("key")! as LogicSlotType;
let val = parseNumber(input.value);
if (field === "Quantity") {
const slot = this.slots[this.slotIndex];

View File

@@ -8,7 +8,7 @@ import SlDialog from "@shoelace-style/shoelace/dist/components/dialog/dialog.com
import { VMDeviceCard } from "./card";
import { when } from "lit/directives/when.js";
import uFuzzy from "@leeoniya/ufuzzy";
import { LogicField, SlotLogicType, SlotOccupantTemplate } from "ic10emu_wasm";
import { LogicField, LogicSlotType, SlotOccupantTemplate } from "ic10emu_wasm";
@customElement("vm-slot-add-dialog")
export class VMSlotAddDialog extends VMDeviceDBMixin(BaseElement) {
@@ -169,10 +169,10 @@ export class VMSlotAddDialog extends VMDeviceDBMixin(BaseElement) {
const dbDevice = this.deviceDB.db[device.prefabName]
const sorting = this.deviceDB.enums["SortingClass"][entry.item.sorting ?? "Default"] ?? 0;
console.log("using entry", dbDevice);
const fields: { [key in SlotLogicType]?: LogicField } = Object.fromEntries(
const fields: { [key in LogicSlotType]?: LogicField } = Object.fromEntries(
Object.entries(dbDevice.slotlogic[this.slotIndex] ?? {})
.map(([slt_s, field_type]) => {
let slt = slt_s as SlotLogicType;
let slt = slt_s as LogicSlotType;
let value = 0.0
if (slt === "FilterType") {
value = this.deviceDB.enums["GasType"][entry.item.filtertype]

View File

@@ -1,9 +1,9 @@
import {
LogicType,
SlotLogicType,
LogicSlotType,
SortingClass,
SlotType,
FieldType,
MemoryAccess,
ReagentMode,
BatchMode,
ConnectionType,
@@ -54,8 +54,8 @@ export interface DeviceDBEntry {
title: string;
desc: string;
slots?: { name: string; typ: SlotType }[];
logic?: { [key in LogicType]?: FieldType };
slotlogic?: { [key: number]: {[key in SlotLogicType]?: FieldType } };
logic?: { [key in LogicType]?: MemoryAccess };
slotlogic?: { [key: number]: {[key in LogicSlotType]?: MemoryAccess } };
modes?: { [key: number]: string };
conn?: { [key: number]: DeviceDBConnection }
item?: DeviceDBItem;

View File

@@ -3,7 +3,7 @@ import {
DeviceTemplate,
FrozenVM,
LogicType,
SlotLogicType,
LogicSlotType,
SlotOccupantTemplate,
Slots,
VMRef,
@@ -365,7 +365,7 @@ class VirtualMachine extends EventTarget {
setDeviceSlotField(
id: number,
slot: number,
field: SlotLogicType,
field: LogicSlotType,
val: number,
force?: boolean,
): boolean {

View File

@@ -21,4 +21,5 @@ textwrap = { version = "0.16.1", default-features = false }
thiserror = "1.0.58"
onig = { git = "https://github.com/rust-onig/rust-onig", revision = "fa90c0e97e90a056af89f183b23cd417b59ee6a2" }
tracing = "0.1.40"

View File

@@ -493,11 +493,19 @@ impl From<&stationpedia::Item> for ItemInfo {
}
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct ConnectionInfo {
pub typ: String,
pub role: String,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct DeviceInfo {
pub connection_list: Vec<(String, String)>,
pub connection_list: Vec<ConnectionInfo>,
#[serde(skip_serializing_if = "Option::is_none")]
pub device_pins_length: Option<i64>,
pub has_activate_state: bool,
@@ -513,7 +521,14 @@ pub struct DeviceInfo {
impl From<&stationpedia::Device> for DeviceInfo {
fn from(value: &stationpedia::Device) -> Self {
DeviceInfo {
connection_list: value.connection_list.clone(),
connection_list: value
.connection_list
.iter()
.map(|(typ, role)| ConnectionInfo {
typ: typ.to_string(),
role: role.to_string(),
})
.collect(),
device_pins_length: value.devices_length,
has_activate_state: value.has_activate_state,
has_atmosphere: value.has_atmosphere,

View File

@@ -326,7 +326,7 @@ pub fn write_enum_listing<T: std::io::Write>(
struct ReprEnumVariant<P>
where
P: Display + FromStr,
P: Display + FromStr + Ord,
{
pub value: P,
pub deprecated: bool,
@@ -353,19 +353,30 @@ fn write_repr_enum<'a, T: std::io::Write, I, P>(
use_phf: bool,
) -> color_eyre::Result<()>
where
P: Display + FromStr + 'a,
P: Display + FromStr + Ord + 'a,
I: IntoIterator<Item = &'a (String, ReprEnumVariant<P>)>,
{
let additional_strum = if use_phf { "#[strum(use_phf)]\n" } else { "" };
let repr = std::any::type_name::<P>();
let mut sorted: Vec<_> = variants.into_iter().collect::<Vec<_>>();
sorted.sort_by_key(|(_, variant)| &variant.value);
let default_derive = if sorted
.iter()
.find(|(name, _)| name == "None" || name == "Default")
.is_some()
{
"Default, "
} else {
""
};
write!(
writer,
"#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, EnumString, AsRefStr, EnumProperty, EnumIter, FromRepr, Serialize, Deserialize)]\n\
"#[derive(Debug, {default_derive}Display, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, EnumString, AsRefStr, EnumProperty, EnumIter, FromRepr, Serialize, Deserialize)]\n\
{additional_strum}\
#[repr({repr})]\n\
pub enum {name} {{\n"
)?;
for (name, variant) in variants {
for (name, variant) in sorted {
let variant_name = name.replace('.', "").to_case(Case::Pascal);
let serialize = vec![name.clone()];
let serialize_str = serialize
@@ -387,9 +398,14 @@ where
} else {
"".to_owned()
};
let default = if variant_name == "None" || variant_name == "Default" {
"#[default]"
} else {
""
};
writeln!(
writer,
" #[strum({serialize_str}{props_str})] {variant_name} = {val}{repr},"
" #[strum({serialize_str}{props_str})]{default} {variant_name} = {val}{repr},"
)?;
}
writeln!(writer, "}}")?;

View File

@@ -216,7 +216,7 @@ fn main() -> color_eyre::Result<()> {
{
generate::generate(&path, &workspace)?;
} else {
return Err(Error::BadStationeresPath(path).into());
return Err(Error::BadStationeersPath(path).into());
}
}
}

View File

@@ -38,14 +38,12 @@ pub struct Reagent {
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Command {
pub desc: String,
pub example: String,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Page {
#[serde(rename = "ConnectionInsert")]
pub connection_insert: Vec<ConnectionInsert>,
@@ -92,7 +90,6 @@ pub struct Page {
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Constructs {
#[serde(rename = "NameOfThing")]
pub name_of_thing: String,
@@ -103,7 +100,6 @@ pub struct Constructs {
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Structure {
#[serde(rename = "SmallGrid")]
pub small_grid: bool,
@@ -115,7 +111,6 @@ pub struct Structure {
pub struct BuildStates(pub Vec<BuildState>);
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct BuildState {
#[serde(rename = "Tool")]
pub tool: Option<Vec<Tool>>,
@@ -137,7 +132,6 @@ pub enum MachineTier {
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Tool {
#[serde(rename = "IsTool", default)]
pub is_tool: bool,
@@ -149,7 +143,6 @@ pub struct Tool {
#[serde_as]
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct SlotInsert {
#[serde(rename = "SlotIndex")]
#[serde_as(as = "DisplayFromStr")]
@@ -161,7 +154,6 @@ pub struct SlotInsert {
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct LogicInsert {
#[serde(rename = "LogicAccessTypes")]
pub logic_access_types: String,
@@ -170,7 +162,6 @@ pub struct LogicInsert {
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct LogicSlotInsert {
#[serde(rename = "LogicAccessTypes")]
pub logic_access_types: String,
@@ -180,7 +171,6 @@ pub struct LogicSlotInsert {
#[serde_as]
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ModeInsert {
#[serde(rename = "LogicAccessTypes")]
#[serde_as(as = "DisplayFromStr")]
@@ -190,7 +180,6 @@ pub struct ModeInsert {
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ConnectionInsert {
#[serde(rename = "LogicAccessTypes")]
pub logic_access_types: String,
@@ -199,7 +188,6 @@ pub struct ConnectionInsert {
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct LogicInfo {
#[serde(rename = "LogicSlotTypes")]
pub logic_slot_types: BTreeMap<u32, LogicSlotTypes>,
@@ -220,7 +208,6 @@ pub struct LogicTypes {
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Memory {
#[serde(rename = "Instructions")]
pub instructions: Option<BTreeMap<String, Instruction>>,
@@ -233,7 +220,6 @@ pub struct Memory {
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Instruction {
#[serde(rename = "Description")]
pub description: String,
@@ -244,7 +230,6 @@ pub struct Instruction {
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Item {
#[serde(rename = "Consumable")]
pub consumable: Option<bool>,
@@ -287,7 +272,6 @@ pub struct Recipe {
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct RecipeTemperature {
#[serde(rename = "Start")]
pub start: f64,
@@ -298,7 +282,6 @@ pub struct RecipeTemperature {
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct RecipePressure {
#[serde(rename = "Start")]
pub start: f64,