refactor(vm) use generated enums wherever possible
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -2193,4 +2193,5 @@ dependencies = [
|
||||
"serde_with",
|
||||
"textwrap",
|
||||
"thiserror",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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}'")]
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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)?),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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>,
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
}
|
||||
|
||||
3
ic10emu/src/vm/object/generic.rs
Normal file
3
ic10emu/src/vm/object/generic.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
pub mod macros;
|
||||
pub mod structs;
|
||||
pub mod traits;
|
||||
75
ic10emu/src/vm/object/generic/macros.rs
Normal file
75
ic10emu/src/vm/object/generic/macros.rs
Normal 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;
|
||||
93
ic10emu/src/vm/object/generic/structs.rs
Normal file
93
ic10emu/src/vm/object/generic/structs.rs
Normal 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>,
|
||||
}
|
||||
162
ic10emu/src/vm/object/generic/traits.rs
Normal file
162
ic10emu/src/vm/object/generic/traits.rs
Normal 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(<)
|
||||
.map(|field| {
|
||||
matches!(
|
||||
field.field_type,
|
||||
MemoryAccess::Read | MemoryAccess::ReadWrite
|
||||
)
|
||||
})
|
||||
.unwrap_or(false)
|
||||
}
|
||||
fn can_logic_write(&self, lt: LogicType) -> bool {
|
||||
self.fields()
|
||||
.get(<)
|
||||
.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(<)
|
||||
.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(<)
|
||||
.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 {}
|
||||
@@ -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;
|
||||
|
||||
@@ -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(<)
|
||||
.map(|field| matches!(field.field_type, FieldType::Read | FieldType::ReadWrite))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
fn can_logic_write(&self, lt: LogicType) -> bool {
|
||||
self.fields()
|
||||
.get(<)
|
||||
.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(<)
|
||||
.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(<)
|
||||
.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>,
|
||||
}
|
||||
247
ic10emu/src/vm/object/templates.rs
Normal file
247
ic10emu/src/vm/object/templates.rs
Normal 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,
|
||||
}
|
||||
@@ -25,12 +25,12 @@ fn main() {
|
||||
ts_types.push_str(<_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(
|
||||
|
||||
@@ -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())?)
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -103,8 +103,8 @@
|
||||
"slotclass",
|
||||
"slotlogic",
|
||||
"slotlogicable",
|
||||
"slotlogictype",
|
||||
"slotlogictypes",
|
||||
"LogicSlotType",
|
||||
"LogicSlotTypes",
|
||||
"slottype",
|
||||
"sltz",
|
||||
"snan",
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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, "}}")?;
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user