refactor(frontend) finish signal conversion, fix passing data to VM

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
This commit is contained in:
Rachel Powers
2024-08-19 22:22:39 -07:00
parent 70833e0b00
commit b1c9db278d
45 changed files with 5009 additions and 2363 deletions

16
Cargo.lock generated
View File

@@ -621,7 +621,6 @@ dependencies = [
"color-eyre",
"const-crc32",
"getrandom",
"ic10emu",
"itertools",
"macro_rules_attribute",
"paste",
@@ -651,14 +650,13 @@ dependencies = [
"itertools",
"js-sys",
"serde",
"serde-wasm-bindgen",
"serde-wasm-bindgen 0.6.5",
"serde_derive",
"serde_ignored",
"serde_json",
"serde_path_to_error",
"serde_with",
"stationeers_data",
"strum",
"thiserror",
"tsify",
"wasm-bindgen",
@@ -1280,6 +1278,17 @@ dependencies = [
"serde_derive",
]
[[package]]
name = "serde-wasm-bindgen"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3b143e2833c57ab9ad3ea280d21fd34e285a42837aeb0ee301f4f41890fa00e"
dependencies = [
"js-sys",
"serde",
"wasm-bindgen",
]
[[package]]
name = "serde-wasm-bindgen"
version = "0.6.5"
@@ -1796,6 +1805,7 @@ checksum = "d6b26cf145f2f3b9ff84e182c448eaf05468e247f148cf3d2a7d67d78ff023a0"
dependencies = [
"gloo-utils",
"serde",
"serde-wasm-bindgen 0.5.0",
"serde_json",
"tsify-macros",
"wasm-bindgen",

View File

@@ -1 +1,148 @@
{"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"]}
{
"language": "en",
"flagWords": [],
"version": "0.2",
"words": [
"arn't",
"Astroloy",
"Atmo",
"Autolathe",
"Autotagged",
"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",
"Depressurising",
"dylib",
"endpos",
"getd",
"Hardsuit",
"hashables",
"hstack",
"impls",
"indexmap",
"inext",
"inextp",
"infile",
"Instructable",
"intf",
"itertools",
"jetpack",
"kbshortcutmenu",
"Keybind",
"lbns",
"logicable",
"LogicSlotType",
"logicslottypes",
"LogicSlotTypes",
"logictype",
"logictypes",
"lparen",
"lzma",
"Mineables",
"mscorlib",
"MSEED",
"ninf",
"nomatch",
"nops",
"oprs",
"overcolumn",
"Overlength",
"pedia",
"peekable",
"prec",
"preproc",
"Pressurising",
"putd",
"QUICKFIX",
"reagentmode",
"reagentmodes",
"repr",
"retval",
"rocketstation",
"rparen",
"sapz",
"sattellite",
"sdns",
"sdse",
"searchbox",
"searchbtn",
"seqz",
"serde",
"settingsmenu",
"sgez",
"sgtz",
"slez",
"slotlogic",
"slotlogicable",
"slottype",
"sltz",
"snan",
"snanz",
"snaz",
"snez",
"splitn",
"Stationeers",
"stationpedia",
"stdweb",
"tbody",
"thiserror",
"tokentype",
"toolbelt",
"trunc",
"Tsify",
"uneval",
"whos"
]
}

View File

@@ -29,7 +29,7 @@ time = { version = "0.3.36", features = [
"serde",
"local-offset",
] }
tsify = { version = "0.4.5", optional = true, features = ["json"] }
tsify = { version = "0.4.5", optional = true, features = ["js"] }
wasm-bindgen = { version = "0.2.92", optional = true }
[target.'cfg(target_arch = "wasm32")'.dependencies]
@@ -46,7 +46,7 @@ color-eyre = "0.6.3"
serde_json = "1.0.117"
# Self dev dependency to enable prefab_database feature for tests
ic10emu = { path = ".", features = ["prefab_database"] }
# ic10emu = { path = ".", features = ["prefab_database"] }
[features]
default = []

View File

@@ -2540,7 +2540,7 @@ impl<T: IC10Marker> LrInstruction for T {
.as_reagent_interface()
.ok_or(ICError::NotReagentReadable(*logicable.get_id()))?;
reagent_interface
.get_current_recipie()
.get_current_recipe()
.iter()
.find(|(hash, _)| *hash as f64 == int)
.map(|(_, quantity)| *quantity)
@@ -2686,7 +2686,7 @@ impl<T: IC10Marker> HcfInstruction for T {
.borrow_mut()
.as_mut_circuit_holder()
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
.hault_and_catch_fire();
.halt_and_catch_fire();
}
self.set_state(ICState::HasCaughtFire);
Ok(())

View File

@@ -53,6 +53,9 @@ pub enum Connection {
PipeLiquid {
role: ConnectionRole,
},
RoboticArmRail {
role: ConnectionRole,
},
#[default]
None,
}
@@ -83,6 +86,7 @@ impl Connection {
ConnectionType::LandingPad => Self::LandingPad { role },
ConnectionType::LaunchPad => Self::LaunchPad { role },
ConnectionType::PipeLiquid => Self::PipeLiquid { role },
ConnectionType::RoboticArmRail => Self::RoboticArmRail { role },
}
}
@@ -140,6 +144,10 @@ impl Connection {
typ: ConnectionType::LaunchPad,
role: *role,
},
Self::RoboticArmRail { role } => ConnectionInfo {
typ: ConnectionType::RoboticArmRail,
role: *role
},
}
}

View File

@@ -701,7 +701,7 @@ where
fn get_ic(&self) -> Option<VMObject> {
self.get_ic_gw()
}
fn hault_and_catch_fire(&mut self) {
fn halt_and_catch_fire(&mut self) {
self.hault_and_catch_fire_gw()
}
}

View File

@@ -327,7 +327,7 @@ impl Human for HumanPlayer {
fn set_hygiene(&mut self, hygiene: f32) {
self.hygiene = hygiene.clamp(0.0, MAX_HYGIENE);
}
fn hygine_state(&self) -> StatState {
fn hygiene_state(&self) -> StatState {
if self.hygiene < CRITICAL_HYGIENE {
return StatState::Critical;
}

View File

@@ -22,13 +22,13 @@ macro_rules! object_trait {
paste::paste! {
$(
#[doc = "Return a `& dyn " $trt "` if implimented by the object"]
#[doc = "Return a `& dyn " $trt "` if implemented by the object"]
#[inline(always)]
fn [<as_ $trt:snake>](&self) -> Option<[<$trt Ref>]> {
None
}
#[doc = "Return a `&mut dyn " $trt "` if implimented by the object"]
#[doc = "Return a `&mut dyn " $trt "` if implemented by the object"]
#[inline(always)]
fn [<as_mut_ $trt:snake>](&mut self) -> Option<[<$trt RefMut>]> {
None
@@ -74,7 +74,7 @@ macro_rules! object_trait {
}
}
/// call func on the dyn refrence or a borrow of the vm object
/// call func on the dyn reference or a borrow of the vm object
pub fn map<F, R>(&self, mut func: F ) -> R
where
F: std::ops::FnMut(& dyn $trait_name) -> R
@@ -103,12 +103,12 @@ macro_rules! object_trait {
}
pub fn get_id(&self) -> u32 {
match self {
Self::DynRef(refrence) => *refrence.get_id(),
Self::DynRef(reference) => *reference.get_id(),
Self::VMObject(obj) => *obj.borrow().get_id(),
}
}
/// call func on the dyn refrence or a borrow of the vm object
/// call func on the dyn reference or a borrow of the vm object
pub fn map<F, R>(&mut self, mut func: F ) -> R
where
F: std::ops::FnMut(&mut dyn $trait_name) -> R

View File

@@ -411,7 +411,7 @@ impl CircuitHolder for StructureCircuitHousing {
.and_then(|info| self.vm.get_object(info.id))
}
fn hault_and_catch_fire(&mut self) {
fn halt_and_catch_fire(&mut self) {
// TODO: do something here??
}
}

View File

@@ -72,6 +72,8 @@ pub struct ObjectInfo {
pub prefab: Option<String>,
pub prefab_hash: Option<i32>,
pub slots: Option<BTreeMap<u32, SlotOccupantInfo>>,
pub parent_slot: Option<(ObjectID, u32)>,
pub root_parent_human: Option<ObjectID>,
pub damage: Option<f32>,
pub device_pins: Option<BTreeMap<u32, ObjectID>>,
pub connections: Option<BTreeMap<u32, ObjectID>>,
@@ -96,6 +98,8 @@ impl From<&VMObject> for ObjectInfo {
prefab: Some(obj_ref.get_prefab().value.clone()),
prefab_hash: Some(obj_ref.get_prefab().hash),
slots: None,
parent_slot: None,
root_parent_human: None,
damage: None,
device_pins: None,
connections: None,
@@ -136,6 +140,8 @@ impl ObjectInfo {
prefab: Some(prefab_name),
prefab_hash: Some(prefab_hash),
slots: None,
parent_slot: None,
root_parent_human: None,
damage: None,
device_pins: None,
connections: None,
@@ -215,6 +221,14 @@ impl ObjectInfo {
} else {
self.damage.replace(damage);
}
let parent_slot = item.get_parent_slot();
if let Some(parent_slot) = parent_slot {
self.parent_slot = Some((parent_slot.parent, parent_slot.slot as u32));
}
let root_parent_human = item.root_parent_human();
if let Some(root_parent_human) = root_parent_human {
self.root_parent_human = Some(root_parent_human.get_id());
}
self
}

View File

@@ -190,7 +190,7 @@ tag_object_traits! {
/// Get the programmable circuit object slotted into this circuit holder
fn get_ic(&self) -> Option<VMObject>;
/// Execute a `hcf` instruction
fn hault_and_catch_fire(&mut self);
fn halt_and_catch_fire(&mut self);
}
pub trait Item {
@@ -403,7 +403,7 @@ tag_object_traits! {
pub trait ReagentInterface: Device {
/// Reagents required by current recipe
fn get_current_recipie(&self) -> Vec<(i32, f64)>;
fn get_current_recipe(&self) -> Vec<(i32, f64)>;
/// Reagents required to complete current recipe
fn get_current_required(&self) -> Vec<(i32, f64)>;
}
@@ -465,8 +465,8 @@ tag_object_traits! {
fn set_mood(&mut self, mood: f32);
fn mood_state(&self) -> StatState;
fn get_hygiene(&self) -> f32;
fn set_hygiene(&mut self, hygine: f32);
fn hygine_state(&self) -> StatState;
fn set_hygiene(&mut self, hygiene: f32);
fn hygiene_state(&self) -> StatState;
fn is_artificial(&self) -> bool;
fn robot_battery(&self) -> Option<VMObject>;
fn suit_slot(&self) -> &Slot;

View File

@@ -22,16 +22,11 @@ color-eyre = "0.6.3"
itertools = "0.13.0"
serde = { version = "1.0.202", features = ["derive"] }
serde_with = "3.8.1"
tsify = { version = "0.4.5", features = ["json"] }
tsify = { version = "0.4.5", features = ["js"] }
thiserror = "1.0.61"
serde_derive = "1.0.203"
serde_json = "1.0.117"
[build-dependencies]
ic10emu = { path = "../ic10emu" }
strum = { version = "0.26.2" }
itertools = "0.13.0"
[features]
default = ["console_error_panic_hook"]
console_error_panic_hook = ["dep:console_error_panic_hook"]

View File

@@ -1,92 +0,0 @@
fn main() {
// let out_dir = env::var_os("OUT_DIR").unwrap();
// let dest_path = Path::new(&out_dir).join("ts_types.rs");
// let output_file = File::create(dest_path).unwrap();
// let mut writer = BufWriter::new(&output_file);
//
// let mut ts_types: String = String::new();
//
// let lt_tsunion: String = Itertools::intersperse(
// ic10emu::grammar::generated::LogicType::iter().map(|lt| format!("\"{}\"", lt.as_ref())),
// "\n | ".to_owned(),
// )
// .collect();
// let lt_tstype = format!("\nexport type LogicType = {};", lt_tsunion);
// ts_types.push_str(&lt_tstype);
//
// let slt_tsunion: String = Itertools::intersperse(
// ic10emu::grammar::generated::LogicSlotType::iter()
// .map(|slt| format!("\"{}\"", slt.as_ref())),
// "\n | ".to_owned(),
// )
// .collect();
// let slt_tstype = format!("\nexport type LogicSlotType = {};", slt_tsunion);
// ts_types.push_str(&slt_tstype);
//
// let bm_tsunion: String = Itertools::intersperse(
// ic10emu::grammar::generated::BatchMode::iter().map(|bm| format!("\"{}\"", bm.as_ref())),
// "\n | ".to_owned(),
// )
// .collect();
// let bm_tstype = format!("\nexport type BatchMode = {};", bm_tsunion);
// ts_types.push_str(&bm_tstype);
//
// let rm_tsunion: String = Itertools::intersperse(
// ic10emu::grammar::generated::ReagentMode::iter().map(|rm| format!("\"{}\"", rm.as_ref())),
// "\n | ".to_owned(),
// )
// .collect();
// let rm_tstype = format!("\nexport type ReagentMode = {};", rm_tsunion);
// ts_types.push_str(&rm_tstype);
//
// let sc_tsunion: String = Itertools::intersperse(
// ic10emu::device::SortingClass::iter().map(|rm| format!("\"{}\"", rm.as_ref())),
// "\n | ".to_owned(),
// )
// .collect();
// let sc_tstype = format!("\nexport type SortingClass = {};", sc_tsunion);
// ts_types.push_str(&sc_tstype);
//
// let st_tsunion: String = Itertools::intersperse(
// ic10emu::device::SlotType::iter().map(|rm| format!("\"{}\"", rm.as_ref())),
// "\n | ".to_owned(),
// )
// .collect();
// let st_tstype = format!("\nexport type SlotType = {};", st_tsunion);
// ts_types.push_str(&st_tstype);
//
// let ct_tsunion: String = Itertools::intersperse(
// ic10emu::network::ConnectionType::iter().map(|rm| format!("\"{}\"", rm.as_ref())),
// "\n | ".to_owned(),
// )
// .collect();
// let ct_tstype = format!("\nexport type ConnectionType = {};", ct_tsunion);
// ts_types.push_str(&ct_tstype);
//
// let cr_tsunion: String = Itertools::intersperse(
// ic10emu::network::ConnectionRole::iter().map(|rm| format!("\"{}\"", rm.as_ref())),
// "\n | ".to_owned(),
// )
// .collect();
// let cr_tstype = format!("\nexport type ConnectionRole = {};", cr_tsunion);
// ts_types.push_str(&cr_tstype);
//
// let infile = Path::new("src/types.ts");
// let contents = fs::read_to_string(infile).unwrap();
//
// ts_types.push('\n');
// ts_types.push_str(&contents);
//
// write!(
// &mut writer,
// "#[wasm_bindgen(typescript_custom_section)]\n\
// const TYPES: &'static str = r#\"{ts_types}\"#;
// "
// )
// .unwrap();
}

File diff suppressed because it is too large Load Diff

View File

@@ -583,9 +583,9 @@ pub enum ReEntryProfile {
#[strum(props(docs = "", value = "0"))]
#[default]
None = 0u8,
#[strum(serialize = "Optimal")]
#[strum(serialize = "Low")]
#[strum(props(docs = "", value = "1"))]
Optimal = 1u8,
Low = 1u8,
#[strum(serialize = "Medium")]
#[strum(props(docs = "", value = "2"))]
Medium = 2u8,
@@ -874,6 +874,12 @@ pub enum Class {
#[strum(serialize = "SuitMod")]
#[strum(props(docs = "", value = "39"))]
SuitMod = 39u8,
#[strum(serialize = "Crate")]
#[strum(props(docs = "", value = "40"))]
Crate = 40u8,
#[strum(serialize = "Portables")]
#[strum(props(docs = "", value = "41"))]
Portables = 41u8,
}
impl TryFrom<f64> for Class {
type Error = super::ParseError;
@@ -1559,6 +1565,7 @@ impl std::str::FromStr for BasicEnum {
"logictype.activate" => Ok(Self::LogicType(LogicType::Activate)),
"logictype.airrelease" => Ok(Self::LogicType(LogicType::AirRelease)),
"logictype.alignmenterror" => Ok(Self::LogicType(LogicType::AlignmentError)),
"logictype.altitude" => Ok(Self::LogicType(LogicType::Altitude)),
"logictype.apex" => Ok(Self::LogicType(LogicType::Apex)),
"logictype.autoland" => Ok(Self::LogicType(LogicType::AutoLand)),
"logictype.autoshutoff" => Ok(Self::LogicType(LogicType::AutoShutOff)),
@@ -2103,10 +2110,10 @@ impl std::str::FromStr for BasicEnum {
Ok(Self::PrinterInstruction(PrinterInstruction::WaitUntilNextValid))
}
"reentryprofile.high" => Ok(Self::ReEntryProfile(ReEntryProfile::High)),
"reentryprofile.low" => Ok(Self::ReEntryProfile(ReEntryProfile::Low)),
"reentryprofile.max" => Ok(Self::ReEntryProfile(ReEntryProfile::Max)),
"reentryprofile.medium" => Ok(Self::ReEntryProfile(ReEntryProfile::Medium)),
"reentryprofile.none" => Ok(Self::ReEntryProfile(ReEntryProfile::None)),
"reentryprofile.optimal" => Ok(Self::ReEntryProfile(ReEntryProfile::Optimal)),
"robotmode.follow" => Ok(Self::RobotMode(RobotMode::Follow)),
"robotmode.movetotarget" => Ok(Self::RobotMode(RobotMode::MoveToTarget)),
"robotmode.none" => Ok(Self::RobotMode(RobotMode::None)),
@@ -2130,6 +2137,7 @@ impl std::str::FromStr for BasicEnum {
"slotclass.cartridge" => Ok(Self::SlotClass(Class::Cartridge)),
"slotclass.circuit" => Ok(Self::SlotClass(Class::Circuit)),
"slotclass.circuitboard" => Ok(Self::SlotClass(Class::Circuitboard)),
"slotclass.crate" => Ok(Self::SlotClass(Class::Crate)),
"slotclass.creditcard" => Ok(Self::SlotClass(Class::CreditCard)),
"slotclass.datadisk" => Ok(Self::SlotClass(Class::DataDisk)),
"slotclass.dirtcanister" => Ok(Self::SlotClass(Class::DirtCanister)),
@@ -2150,6 +2158,7 @@ impl std::str::FromStr for BasicEnum {
"slotclass.ore" => Ok(Self::SlotClass(Class::Ore)),
"slotclass.organ" => Ok(Self::SlotClass(Class::Organ)),
"slotclass.plant" => Ok(Self::SlotClass(Class::Plant)),
"slotclass.portables" => Ok(Self::SlotClass(Class::Portables)),
"slotclass.programmablechip" => Ok(Self::SlotClass(Class::ProgrammableChip)),
"slotclass.scanninghead" => Ok(Self::SlotClass(Class::ScanningHead)),
"slotclass.sensorprocessingunit" => {

View File

@@ -47,11 +47,14 @@ pub enum StationpediaPrefab {
#[strum(
props(
name = "Small Satellite Dish",
desc = "This small communications unit can be used to communicate with nearby trade vessels.\n\n When connected to a <link=ThingStructureComputer><color=green>Computer</color></link> containing a <link=ThingMotherboardComms><color=green>Communications Motherboard</color></link> motherboard, a <link=ThingLandingpad_CenterPiece01><color=green>Landingpad Center</color></link>, and a <link=ThingStructureVendingMachine><color=green>Vending Machine</color></link>, this allows Stationeers to contact traders. Adjust its horizontal and vertical attributes either directly or through logic.",
desc = "This small communications unit can be used to communicate with nearby trade vessels.\n\n When connected to a <link=ThingStructureComputer><color=green>Computer (Modern)</color></link> containing a <link=ThingMotherboardComms><color=green>Communications Motherboard</color></link> motherboard, a <link=ThingLandingpad_CenterPiece01><color=green>Landingpad Center</color></link>, and a <link=ThingStructureVendingMachine><color=green>Vending Machine</color></link>, this allows Stationeers to contact traders. Adjust its horizontal and vertical attributes either directly or through logic.",
value = "-2138748650"
)
)]
StructureSmallSatelliteDish = -2138748650i32,
#[strum(serialize = "StructureRobotArmDoor")]
#[strum(props(name = "Linear Rail Door", desc = "", value = "-2131782367"))]
StructureRobotArmDoor = -2131782367i32,
#[strum(serialize = "StructureStairwellBackRight")]
#[strum(props(name = "Stairwell (Back Right)", desc = "", value = "-2128896573"))]
StructureStairwellBackRight = -2128896573i32,
@@ -62,7 +65,7 @@ pub enum StationpediaPrefab {
#[strum(
props(
name = "Kit (Liquid Pipe Valve)",
desc = "This kit creates a <link=ThingStructureLiquidValve><color=green>Liquid Valve</color></link>.",
desc = "This kit creates a <link=ThingStructureLiquidValve><color=green>Valve (Liquid)</color></link>.",
value = "-2126113312"
)
)]
@@ -189,6 +192,15 @@ pub enum StationpediaPrefab {
)
)]
StructureWindTurbine = -2082355173i32,
#[strum(serialize = "StructureCompositeWindowShutterController")]
#[strum(
props(
name = "Composite Window Shutter Controller",
desc = "",
value = "-2078371660"
)
)]
StructureCompositeWindowShutterController = -2078371660i32,
#[strum(serialize = "StructureInsulatedPipeTJunction")]
#[strum(
props(
@@ -455,7 +467,7 @@ pub enum StationpediaPrefab {
)]
PortableComposter = -1958705204i32,
#[strum(serialize = "CartridgeGPS")]
#[strum(props(name = "GPS", desc = "", value = "-1957063345"))]
#[strum(props(name = "Cartridge (GPS)", desc = "", value = "-1957063345"))]
CartridgeGps = -1957063345i32,
#[strum(serialize = "StructureConsoleLED1x3")]
#[strum(
@@ -545,7 +557,7 @@ pub enum StationpediaPrefab {
#[strum(
props(
name = "Sorter Motherboard",
desc = "Motherboards are connected to <link=ThingStructureComputer><color=green>Computer</color></link>s to perform various technical functions.\nThe <link=Norsec><color=#0080FFFF>Norsec-designed</color></link> K-cops 10-10 sorter motherboard permits <link=Stationeers><color=#0080FFFF>Stationeers</color></link> to control which items a <link=ThingStructureSorter><color=green>Sorter</color></link> does, and does not, permit to pass.",
desc = "Motherboards are connected to <link=ThingStructureComputer><color=green>Computer (Modern)</color></link>s to perform various technical functions.\nThe <link=Norsec><color=#0080FFFF>Norsec-designed</color></link> K-cops 10-10 sorter motherboard permits <link=Stationeers><color=#0080FFFF>Stationeers</color></link> to control which items a <link=ThingStructureSorter><color=green>Sorter</color></link> does, and does not, permit to pass.",
value = "-1908268220"
)
)]
@@ -725,11 +737,20 @@ pub enum StationpediaPrefab {
#[strum(props(name = "Kit (Wall)", desc = "", value = "-1826855889"))]
ItemKitWall = -1826855889i32,
#[strum(serialize = "ItemWreckageAirConditioner1")]
#[strum(props(name = "Wreckage Air Conditioner", desc = "", value = "-1826023284"))]
#[strum(props(name = "Wreckage", desc = "", value = "-1826023284"))]
ItemWreckageAirConditioner1 = -1826023284i32,
#[strum(serialize = "ItemKitStirlingEngine")]
#[strum(props(name = "Kit (Stirling Engine)", desc = "", value = "-1821571150"))]
ItemKitStirlingEngine = -1821571150i32,
#[strum(serialize = "StructureRoboticArmDock")]
#[strum(
props(
name = "LArRE Dock",
desc = "The Linear Articulated Rail Entity or LArRE can be used to plant, harvest and fertilize plants in plant trays. It can also grab items from a <link=ThingStructureChuteExportBin><color=green>Chute Export Bin</color></link> and drop them in a <link=ThingStructureChuteBin><color=green>Chute Import Bin</color></link>. LArRE can interact with plant trays or chute bins built under a linear rail station or built under its dock.",
value = "-1818718810"
)
)]
StructureRoboticArmDock = -1818718810i32,
#[strum(serialize = "StructureGasUmbilicalMale")]
#[strum(
props(
@@ -822,6 +843,9 @@ pub enum StationpediaPrefab {
)
)]
LandingpadLiquidConnectorOutwardPiece = -1788929869i32,
#[strum(serialize = "StructureRoboticArmRailStraight")]
#[strum(props(name = "Linear Rail Straight", desc = "", value = "-1785844184"))]
StructureRoboticArmRailStraight = -1785844184i32,
#[strum(serialize = "StructurePipeCorner")]
#[strum(
props(
@@ -846,7 +870,7 @@ pub enum StationpediaPrefab {
#[strum(serialize = "CartridgeOreScanner")]
#[strum(
props(
name = "Ore Scanner",
name = "Cartridge (Ore Scanner)",
desc = "When inserted into a <link=ThingItemTablet><color=green>Handheld Tablet</color></link> the scanner will display minerals hidden underground on the tablet.",
value = "-1768732546"
)
@@ -1064,7 +1088,7 @@ pub enum StationpediaPrefab {
#[strum(props(name = "Appliance Desk Lamp Left", desc = "", value = "-1683849799"))]
ApplianceDeskLampLeft = -1683849799i32,
#[strum(serialize = "ItemWreckageWallCooler1")]
#[strum(props(name = "Wreckage Wall Cooler", desc = "", value = "-1682930158"))]
#[strum(props(name = "Wreckage", desc = "", value = "-1682930158"))]
ItemWreckageWallCooler1 = -1682930158i32,
#[strum(serialize = "StructureGasUmbilicalFemale")]
#[strum(props(name = "Umbilical Socket (Gas)", desc = "", value = "-1680477930"))]
@@ -1121,9 +1145,7 @@ pub enum StationpediaPrefab {
#[strum(props(name = "Astroloy Sheets", desc = "", value = "-1662476145"))]
ItemAstroloySheets = -1662476145i32,
#[strum(serialize = "ItemWreckageTurbineGenerator1")]
#[strum(
props(name = "Wreckage Turbine Generator", desc = "", value = "-1662394403")
)]
#[strum(props(name = "Wreckage", desc = "", value = "-1662394403"))]
ItemWreckageTurbineGenerator1 = -1662394403i32,
#[strum(serialize = "ItemMiningBackPack")]
#[strum(props(name = "Mining Backpack", desc = "", value = "-1650383245"))]
@@ -1248,7 +1270,7 @@ pub enum StationpediaPrefab {
#[strum(serialize = "CartridgeAtmosAnalyser")]
#[strum(
props(
name = "Atmos Analyzer",
name = "Cartridge (Atmos Analyzer)",
desc = "The Lorenz atmos analyzer is a multi-functional mass-spectrometer designed by <link=ExMin><color=#0080FFFF>ExMin</color></link> for use with the OreCore <link=ThingItemTablet><color=green>Handheld Tablet</color></link>. It displays the pressure, concentration and molar quantity of <link=GasPage><color=#0080FFFF>gas</color></link> in rooms, tanks, or pipe networks.",
value = "-1550278665"
)
@@ -1391,7 +1413,7 @@ pub enum StationpediaPrefab {
#[strum(props(name = "Sleeper", desc = "", value = "-1467449329"))]
StructureSleeper = -1467449329i32,
#[strum(serialize = "CartridgeElectronicReader")]
#[strum(props(name = "eReader", desc = "", value = "-1462180176"))]
#[strum(props(name = "Cartridge (eReader)", desc = "", value = "-1462180176"))]
CartridgeElectronicReader = -1462180176i32,
#[strum(serialize = "StructurePictureFrameThickMountPortraitLarge")]
#[strum(
@@ -1622,6 +1644,9 @@ pub enum StationpediaPrefab {
#[strum(serialize = "StructureLogicWriter")]
#[strum(props(name = "Logic Writer", desc = "", value = "-1326019434"))]
StructureLogicWriter = -1326019434i32,
#[strum(serialize = "StructureRoboticArmRailCorner")]
#[strum(props(name = "Linear Rail Corner", desc = "", value = "-1323992709"))]
StructureRoboticArmRailCorner = -1323992709i32,
#[strum(serialize = "StructureLogicWriterSwitch")]
#[strum(props(name = "Logic Writer Switch", desc = "", value = "-1321250424"))]
StructureLogicWriterSwitch = -1321250424i32,
@@ -1798,6 +1823,9 @@ pub enum StationpediaPrefab {
)
)]
StructureLargeDirectHeatExchangeGastoGas = -1230658883i32,
#[strum(serialize = "ItemKitRoboticArm")]
#[strum(props(name = "Kit (LArRE)", desc = "", value = "-1228287398"))]
ItemKitRoboticArm = -1228287398i32,
#[strum(serialize = "ItemSensorProcessingUnitOreScanner")]
#[strum(
props(
@@ -1823,13 +1851,7 @@ pub enum StationpediaPrefab {
#[strum(props(name = "Landingpad Liquid Input", desc = "", value = "-1216167727"))]
LandingpadLiquidConnectorInwardPiece = -1216167727i32,
#[strum(serialize = "ItemWreckageStructureWeatherStation008")]
#[strum(
props(
name = "Wreckage Structure Weather Station",
desc = "",
value = "-1214467897"
)
)]
#[strum(props(name = "Wreckage", desc = "", value = "-1214467897"))]
ItemWreckageStructureWeatherStation008 = -1214467897i32,
#[strum(serialize = "ItemPlantThermogenic_Creative")]
#[strum(
@@ -2025,7 +2047,7 @@ pub enum StationpediaPrefab {
#[strum(
props(
name = "Active Vent",
desc = "The active vent is a powered device for maintaining <link=GasPage><color=#0080FFFF>gas</color></link> pressure by pumping gas into (or out of) a pipe network. The vent has two modes: 'Outward' sets it to pump gas into a space until pressure is reached; 'Inward' sets it to pump gas out until pressure is reached. The pressure parameter can be set on a connected <link=ThingStructureConsole><color=green>Console</color></link>. Default pressure is 101kPa for Outward; 0kPa for Inward ...",
desc = "The active vent is a powered device for maintaining <link=GasPage><color=#0080FFFF>gas</color></link> pressure by pumping gas into (or out of) a pipe network. The vent has two modes: 'Outward' sets it to pump gas into a space until pressure is reached; 'Inward' sets it to pump gas out until pressure is reached. The pressure parameter can be set on a connected <link=ThingStructureConsole><color=green>Console</color></link>. Default pressure is 101kPa for Outward; 0kPa for Inward...",
value = "-1129453144"
)
)]
@@ -2057,7 +2079,7 @@ pub enum StationpediaPrefab {
#[strum(serialize = "CartridgeMedicalAnalyser")]
#[strum(
props(
name = "Medical Analyzer",
name = "Cartridge (Medical Analyzer)",
desc = "When added to the OreCore <link=ThingItemTablet><color=green>Handheld Tablet</color></link>, <link=Asura><color=#0080FFFF>Asura's</color></link>'s ReadyMed medical analyzer reveals the health, or otherwise, of users various organs. Due to a design flaw, older models were notorious for producing quasar-like levels of x-ray radiation. Recent advances in shielding have more than halved the risk to users.",
value = "-1116110181"
)
@@ -2076,13 +2098,7 @@ pub enum StationpediaPrefab {
#[strum(props(name = "Cake", desc = "", value = "-1108244510"))]
ItemPlainCake = -1108244510i32,
#[strum(serialize = "ItemWreckageStructureWeatherStation004")]
#[strum(
props(
name = "Wreckage Structure Weather Station",
desc = "",
value = "-1104478996"
)
)]
#[strum(props(name = "Wreckage", desc = "", value = "-1104478996"))]
ItemWreckageStructureWeatherStation004 = -1104478996i32,
#[strum(serialize = "StructureCableFuse1k")]
#[strum(props(name = "Fuse (1kW)", desc = "", value = "-1103727120"))]
@@ -2301,6 +2317,9 @@ pub enum StationpediaPrefab {
#[strum(serialize = "ItemDynamicScrubber")]
#[strum(props(name = "Kit (Portable Scrubber)", desc = "", value = "-971920158"))]
ItemDynamicScrubber = -971920158i32,
#[strum(serialize = "ItemWaterBottlePackage")]
#[strum(props(name = "Water Bottle Package", desc = "", value = "-971586619"))]
ItemWaterBottlePackage = -971586619i32,
#[strum(serialize = "StructureCondensationValve")]
#[strum(
props(
@@ -2337,7 +2356,7 @@ pub enum StationpediaPrefab {
)]
ItemKitRocketTransformerSmall = -932335800i32,
#[strum(serialize = "CartridgeConfiguration")]
#[strum(props(name = "Configuration", desc = "", value = "-932136011"))]
#[strum(props(name = "Cartridge (Configuration)", desc = "", value = "-932136011"))]
CartridgeConfiguration = -932136011i32,
#[strum(serialize = "ItemSilverIngot")]
#[strum(props(name = "Ingot (Silver)", desc = "", value = "-929742000"))]
@@ -2353,13 +2372,7 @@ pub enum StationpediaPrefab {
)]
StructureSmallTableRectangleSingle = -924678969i32,
#[strum(serialize = "ItemWreckageStructureWeatherStation005")]
#[strum(
props(
name = "Wreckage Structure Weather Station",
desc = "",
value = "-919745414"
)
)]
#[strum(props(name = "Wreckage", desc = "", value = "-919745414"))]
ItemWreckageStructureWeatherStation005 = -919745414i32,
#[strum(serialize = "ItemSilverOre")]
#[strum(
@@ -2465,7 +2478,7 @@ pub enum StationpediaPrefab {
#[strum(serialize = "StructureChuteBin")]
#[strum(
props(
name = "Chute Bin",
name = "Chute Import Bin",
desc = "The <link=Stationeers><color=#0080FFFF>Stationeer's</color></link> goal is to make off-world survival less of a struggle for themselves, and those who will follow in their footsteps.\nLike most <link=Recurso><color=#0080FFFF>Recurso</color></link>-designed systems, chute bins are simple and robust powered items, allowing items to be manually passed into chute networks by pulling a lever. They can also be programmed with <link=LogicUnitPage><color=#0080FFFF>logic</color></link> to operate automatically, although full automation requires the use items such as a <link=ThingStructureSDBHopper><color=green>SDB Hopper</color></link>.",
value = "-850484480"
)
@@ -2493,13 +2506,7 @@ pub enum StationpediaPrefab {
)]
ItemFlashlight = -838472102i32,
#[strum(serialize = "ItemWreckageStructureWeatherStation001")]
#[strum(
props(
name = "Wreckage Structure Weather Station",
desc = "",
value = "-834664349"
)
)]
#[strum(props(name = "Wreckage", desc = "", value = "-834664349"))]
ItemWreckageStructureWeatherStation001 = -834664349i32,
#[strum(serialize = "ItemBiomass")]
#[strum(
@@ -2650,15 +2657,6 @@ pub enum StationpediaPrefab {
)
)]
StructurePowerConnector = -782951720i32,
#[strum(serialize = "StructureLiquidPipeOneWayValve")]
#[strum(
props(
name = "One Way Valve (Liquid)",
desc = "The one way valve moves liquid in one direction only: from input side to output side. It only permits flow if the input pressure is higher than output pressure..",
value = "-782453061"
)
)]
StructureLiquidPipeOneWayValve = -782453061i32,
#[strum(serialize = "StructureWallLargePanelArrow")]
#[strum(props(name = "Wall (Large Panel Arrow)", desc = "", value = "-776581573"))]
StructureWallLargePanelArrow = -776581573i32,
@@ -2695,6 +2693,9 @@ pub enum StationpediaPrefab {
#[strum(serialize = "StructureWaterBottleFillerPowered")]
#[strum(props(name = "Waterbottle Filler", desc = "", value = "-756587791"))]
StructureWaterBottleFillerPowered = -756587791i32,
#[strum(serialize = "ItemKitRobotArmDoor")]
#[strum(props(name = "Kit (Linear Rail Door)", desc = "", value = "-753675589"))]
ItemKitRobotArmDoor = -753675589i32,
#[strum(serialize = "AppliancePackagingMachine")]
#[strum(
props(
@@ -2791,7 +2792,7 @@ pub enum StationpediaPrefab {
)]
StructureLogicTransmitter = -693235651i32,
#[strum(serialize = "StructureValve")]
#[strum(props(name = "Valve", desc = "", value = "-692036078"))]
#[strum(props(name = "Valve (Gas)", desc = "", value = "-692036078"))]
StructureValve = -692036078i32,
#[strum(serialize = "StructureCompositeWindowIron")]
#[strum(props(name = "Iron Window", desc = "", value = "-688284639"))]
@@ -2919,8 +2920,8 @@ pub enum StationpediaPrefab {
#[strum(serialize = "StructureComputer")]
#[strum(
props(
name = "Computer",
desc = "In some ways a relic, the 'Chonk R1' was designed by severely conflicted <link=Norsec><color=#0080FFFF>Norsec</color></link> technicians, who needed a unit that could operate with a wide range of <link=LogicUnitPage><color=#0080FFFF>motherboards</color></link>, while also enduring the worst a new Cadet could throw at it.\nThe result is a machine described by some as 'the only PC likely to survive our collision with a black hole', while other, less appreciative users regard it as sharing most of its technological DNA with a cheese grater.\nCompatible motherboards:\n- <link=ThingMotherboardLogic><color=green>Logic Motherboard</color></link>\n- <link=ThingMotherboardManufacturing><color=green>Manufacturing Motherboard</color></link>\n- <link=ThingMotherboardSorter><color=green>Sorter Motherboard</color></link>\n- <link=ThingMotherboardComms><color=green>Communications Motherboard</color></link>\n- <link=ThingMotherboardProgrammableChip><color=green>IC Editor Motherboard</color></link>",
name = "Computer (Modern)",
desc = "This unit operates with a wide range of <link=LogicUnitPage><color=#0080FFFF>motherboards</color></link>.",
value = "-626563514"
)
)]
@@ -3082,6 +3083,9 @@ pub enum StationpediaPrefab {
)
)]
ItemEggCarton = -524289310i32,
#[strum(serialize = "StructurePipeLiquidOneWayValveLever")]
#[strum(props(name = "One Way Valve (Liquid)", desc = "", value = "-523832822"))]
StructurePipeLiquidOneWayValveLever = -523832822i32,
#[strum(serialize = "StructureWaterDigitalValve")]
#[strum(props(name = "Liquid Digital Valve", desc = "", value = "-517628750"))]
StructureWaterDigitalValve = -517628750i32,
@@ -3127,6 +3131,9 @@ pub enum StationpediaPrefab {
#[strum(serialize = "ItemIronSheets")]
#[strum(props(name = "Iron Sheets", desc = "", value = "-487378546"))]
ItemIronSheets = -487378546i32,
#[strum(serialize = "StructureReinforcedWall")]
#[strum(props(name = "Reinforced Wall", desc = "", value = "-475746988"))]
StructureReinforcedWall = -475746988i32,
#[strum(serialize = "ItemGasCanisterVolatiles")]
#[strum(props(name = "Canister (Volatiles)", desc = "", value = "-472094806"))]
ItemGasCanisterVolatiles = -472094806i32,
@@ -3190,6 +3197,9 @@ pub enum StationpediaPrefab {
)
)]
StructureVendingMachine = -443130773i32,
#[strum(serialize = "ItemKitLinearRail")]
#[strum(props(name = "Kit (Linear Rail)", desc = "", value = "-441759975"))]
ItemKitLinearRail = -441759975i32,
#[strum(serialize = "StructurePipeHeater")]
#[strum(
props(
@@ -3229,6 +3239,15 @@ pub enum StationpediaPrefab {
)
)]
CircuitboardCameraDisplay = -412104504i32,
#[strum(serialize = "StructureComputerUpright")]
#[strum(
props(
name = "Computer (Retro)",
desc = "This unit operates with a wide range of <link=LogicUnitPage><color=#0080FFFF>motherboards</color></link>.",
value = "-405593895"
)
)]
StructureComputerUpright = -405593895i32,
#[strum(serialize = "ItemCopperIngot")]
#[strum(
props(
@@ -3238,6 +3257,9 @@ pub enum StationpediaPrefab {
)
)]
ItemCopperIngot = -404336834i32,
#[strum(serialize = "ItemCerealBarBox")]
#[strum(props(name = "Cereal Bar Box", desc = "", value = "-401648353"))]
ItemCerealBarBox = -401648353i32,
#[strum(serialize = "ReagentColorOrange")]
#[strum(props(name = "Color Dye (Orange)", desc = "", value = "-400696159"))]
ReagentColorOrange = -400696159i32,
@@ -3359,7 +3381,7 @@ pub enum StationpediaPrefab {
#[strum(
props(
name = "Communications Motherboard",
desc = "When placed in a <link=ThingStructureComputer><color=green>Computer</color></link> and connected to a <link=ThingLandingpad_DataConnectionPiece><color=green>Landingpad Data And Power</color></link>, a <link=ThingStructureSatelliteDish><color=green>Medium Satellite Dish</color></link>, and a <link=ThingStructureVendingMachine><color=green>Vending Machine</color></link> allows Stationeers to trade with suppliers. Adjust the horizontal and vertical attributes of the <link=ThingStructureSatelliteDish><color=green>Medium Satellite Dish</color></link> either directly or through logic. You need a communications signal of 95% or above to establish reliable communications with a trader. A minimum of a 3x3 clear pad area with a <link=ThingLandingpad_CenterPiece01><color=green>Landingpad Center</color></link> at the center is required for a trader to land.",
desc = "When placed in a <link=ThingStructureComputer><color=green>Computer (Modern)</color></link> and connected to a <link=ThingLandingpad_DataConnectionPiece><color=green>Landingpad Data And Power</color></link>, a <link=ThingStructureSatelliteDish><color=green>Medium Satellite Dish</color></link>, and a <link=ThingStructureVendingMachine><color=green>Vending Machine</color></link> allows Stationeers to trade with suppliers. Adjust the horizontal and vertical attributes of the <link=ThingStructureSatelliteDish><color=green>Medium Satellite Dish</color></link> either directly or through logic. You need a communications signal of 95% or above to establish reliable communications with a trader. A minimum of a 3x3 clear pad area with a <link=ThingLandingpad_CenterPiece01><color=green>Landingpad Center</color></link> at the center is required for a trader to land.",
value = "-337075633"
)
)]
@@ -3379,7 +3401,7 @@ pub enum StationpediaPrefab {
#[strum(
props(
name = "Portable Gas Tank (CO2)",
desc = "Portable gas tanks do one thing: store gas. To refill the tank, bolt it to a <link=ThingItemTankConnector><color=green>Kit (Tank Connector)</color></link>, then connect it to a pipe network. Try to avoid pushing it above 10 MPa, or ... boom. Once it's full, you can refill a <link=ThingItemGasCanisterCarbonDioxide><color=green>Canister (CO2)</color></link> by attaching it to the tank's striped section. Or you could vent the tank's variable flow rate valve into a room and create an atmosphere ... of sorts.",
desc = "Portable gas tanks do one thing: store gas. To refill the tank, bolt it to a <link=ThingItemTankConnector><color=green>Kit (Tank Connector)</color></link>, then connect it to a pipe network. Try to avoid pushing it above 10 MPa, or... boom. Once it's full, you can refill a <link=ThingItemGasCanisterCarbonDioxide><color=green>Canister (CO2)</color></link> by attaching it to the tank's striped section. Or you could vent the tank's variable flow rate valve into a room and create an atmosphere... of sorts.",
value = "-322413931"
)
)]
@@ -3415,7 +3437,7 @@ pub enum StationpediaPrefab {
)]
ElectronicPrinterMod = -311170652i32,
#[strum(serialize = "ItemWreckageHydroponicsTray1")]
#[strum(props(name = "Wreckage Hydroponics Tray", desc = "", value = "-310178617"))]
#[strum(props(name = "Wreckage", desc = "", value = "-310178617"))]
ItemWreckageHydroponicsTray1 = -310178617i32,
#[strum(serialize = "ItemKitRocketCelestialTracker")]
#[strum(
@@ -3449,6 +3471,9 @@ pub enum StationpediaPrefab {
)
)]
StructureLiquidPipeHeater = -287495560i32,
#[strum(serialize = "StructureRoboticArmRailInnerCorner")]
#[strum(props(name = "Linear Rail Inner Corner", desc = "", value = "-267108827"))]
StructureRoboticArmRailInnerCorner = -267108827i32,
#[strum(serialize = "ItemChocolateCake")]
#[strum(props(name = "Chocolate Cake", desc = "", value = "-261575861"))]
ItemChocolateCake = -261575861i32,
@@ -3456,7 +3481,7 @@ pub enum StationpediaPrefab {
#[strum(
props(
name = "Stirling Engine",
desc = "Harnessing an ancient thermal exploit, the <link=Recurso><color=#0080FFFF>Recurso</color></link> 'Libra' Stirling Engine generates power via the expansion and contraction of a working gas to drive pistons operating an electrical generator.\n \nWhen high pressure hot gas is supplied into the input pipe, this gas will heat the hot side of the unit, then pass into the output pipe. The cooler side uses the room's ambient atmosphere, which must be kept at a lower temperature and pressure in order to create a differential. Add a working gas by inserting a <link=SlotGasCanister><color=orange>Gas Canister</color></link>. The unit must be deactivated when adding or removing canisters, or the working gas may leak into the surrounding atmosphere.\n \nGases with a low molecular mass make the most efficient working gases. Increasing the moles of working gas can result in a greater potential power output. However, overpressuring the unit may have ... sub-optimal results.",
desc = "Harnessing an ancient thermal exploit, the <link=Recurso><color=#0080FFFF>Recurso</color></link> 'Libra' Stirling Engine generates power via the expansion and contraction of a working gas to drive pistons operating an electrical generator.\n \nWhen high pressure hot gas is supplied into the input pipe, this gas will heat the hot side of the unit, then pass into the output pipe. The cooler side uses the room's ambient atmosphere, which must be kept at a lower temperature and pressure in order to create a differential. Add a working gas by inserting a <link=SlotGasCanister><color=orange>Gas Canister</color></link>. The unit must be deactivated when adding or removing canisters, or the working gas may leak into the surrounding atmosphere.\n \nGases with a low molecular mass make the most efficient working gases. Increasing the moles of working gas can result in a greater potential power output. However, overpressuring the unit may have... sub-optimal results.",
value = "-260316435"
)
)]
@@ -3491,7 +3516,7 @@ pub enum StationpediaPrefab {
#[strum(
props(
name = "Handheld Tablet",
desc = "The <link=Xigo><color=#0080FFFF>Xigo</color></link> handheld 'Padi' tablet is an all-purpose data platform, provided as standard issue to all <link=Stationeers><color=#0080FFFF>Stationeers</color></link>. A dynamic multi-tool that accepts a range of <link=CartridgePage><color=#0080FFFF>cartridges</color></link>, the Padi becomes an <link=ThingCartridgeAtmosAnalyser><color=green>Atmos Analyzer</color></link> or <link=ThingCartridgeTracker><color=green>Tracker</color></link>, <link=ThingCartridgeMedicalAnalyser><color=green>Medical Analyzer</color></link>, <link=ThingCartridgeOreScanner><color=green>Ore Scanner</color></link>, <link=ThingCartridgeElectronicReader><color=green>eReader</color></link>, and various other functions.",
desc = "The <link=Xigo><color=#0080FFFF>Xigo</color></link> handheld 'Padi' tablet is an all-purpose data platform, provided as standard issue to all <link=Stationeers><color=#0080FFFF>Stationeers</color></link>. A dynamic multi-tool that accepts a range of <link=CartridgePage><color=#0080FFFF>cartridges</color></link>, the Padi becomes an <link=ThingCartridgeAtmosAnalyser><color=green>Cartridge (Atmos Analyzer)</color></link> or <link=ThingCartridgeTracker><color=green>Cartridge (Tracker)</color></link>, <link=ThingCartridgeMedicalAnalyser><color=green>Cartridge (Medical Analyzer)</color></link>, <link=ThingCartridgeOreScanner><color=green>Cartridge (Ore Scanner)</color></link>, <link=ThingCartridgeElectronicReader><color=green>Cartridge (eReader)</color></link>, and various other functions.",
value = "-229808600"
)
)]
@@ -3575,7 +3600,7 @@ pub enum StationpediaPrefab {
#[strum(
props(
name = "IC Editor Motherboard",
desc = "When placed in a <link=ThingStructureComputer><color=green>Computer</color></link>, the IC Editor allows players to write and edit IC code, which can then be uploaded to a <link=ThingItemIntegratedCircuit10><color=green>Integrated Circuit (IC10)</color></link> if housed in an <link=ThingStructureCircuitHousing><color=green>IC Housing</color></link>.",
desc = "When placed in a <link=ThingStructureComputer><color=green>Computer (Modern)</color></link>, the IC Editor allows players to write and edit IC code, which can then be uploaded to a <link=ThingItemIntegratedCircuit10><color=green>Integrated Circuit (IC10)</color></link> if housed in an <link=ThingStructureCircuitHousing><color=green>IC Housing</color></link>.",
value = "-161107071"
)
)]
@@ -3707,6 +3732,9 @@ pub enum StationpediaPrefab {
props(name = "Kitchen Table (Simple Short)", desc = "", value = "-78099334")
)]
KitchenTableSimpleShort = -78099334i32,
#[strum(serialize = "ItemCerealBarBag")]
#[strum(props(name = "Cereal Bar Bag", desc = "", value = "-75205276"))]
ItemCerealBarBag = -75205276i32,
#[strum(serialize = "ImGuiCircuitboardAirlockControl")]
#[strum(props(name = "Airlock (Experimental)", desc = "", value = "-73796547"))]
ImGuiCircuitboardAirlockControl = -73796547i32,
@@ -3785,6 +3813,9 @@ pub enum StationpediaPrefab {
#[strum(serialize = "StructureWallPaddedWindowThin")]
#[strum(props(name = "Wall (Padded Window Thin)", desc = "", value = "-37302931"))]
StructureWallPaddedWindowThin = -37302931i32,
#[strum(serialize = "StructureRoboticArmRailOuterCorner")]
#[strum(props(name = "Linear Rail Outer Corner", desc = "", value = "-33470826"))]
StructureRoboticArmRailOuterCorner = -33470826i32,
#[strum(serialize = "StructureInsulatedTankConnector")]
#[strum(props(name = "Insulated Tank Connector", desc = "", value = "-31273349"))]
StructureInsulatedTankConnector = -31273349i32,
@@ -3835,12 +3866,10 @@ pub enum StationpediaPrefab {
)]
ItemPureIcePollutant = -1755356i32,
#[strum(serialize = "ItemWreckageLargeExtendableRadiator01")]
#[strum(
props(name = "Wreckage Large Extendable Radiator", desc = "", value = "-997763")
)]
#[strum(props(name = "Wreckage", desc = "", value = "-997763"))]
ItemWreckageLargeExtendableRadiator01 = -997763i32,
#[strum(serialize = "StructureSingleBed")]
#[strum(props(name = "Single Bed", desc = "Description coming.", value = "-492611"))]
#[strum(props(name = "Single Bed", desc = "", value = "-492611"))]
StructureSingleBed = -492611i32,
#[strum(serialize = "StructureCableCorner3HBurnt")]
#[strum(
@@ -3971,7 +4000,7 @@ pub enum StationpediaPrefab {
#[strum(props(name = "Canister", desc = "", value = "42280099"))]
ItemGasCanisterEmpty = 42280099i32,
#[strum(serialize = "ItemWreckageWallCooler2")]
#[strum(props(name = "Wreckage Wall Cooler", desc = "", value = "45733800"))]
#[strum(props(name = "Wreckage", desc = "", value = "45733800"))]
ItemWreckageWallCooler2 = 45733800i32,
#[strum(serialize = "ItemPumpkinPie")]
#[strum(props(name = "Pumpkin Pie", desc = "", value = "62768076"))]
@@ -3992,13 +4021,13 @@ pub enum StationpediaPrefab {
#[strum(props(name = "Kit (Docking Port)", desc = "", value = "77421200"))]
ItemKitDockingPort = 77421200i32,
#[strum(serialize = "CartridgeTracker")]
#[strum(props(name = "Tracker", desc = "", value = "81488783"))]
#[strum(props(name = "Cartridge (Tracker)", desc = "", value = "81488783"))]
CartridgeTracker = 81488783i32,
#[strum(serialize = "ToyLuna")]
#[strum(props(name = "Toy Luna", desc = "", value = "94730034"))]
ToyLuna = 94730034i32,
#[strum(serialize = "ItemWreckageTurbineGenerator2")]
#[strum(props(name = "Wreckage Turbine Generator", desc = "", value = "98602599"))]
#[strum(props(name = "Wreckage", desc = "", value = "98602599"))]
ItemWreckageTurbineGenerator2 = 98602599i32,
#[strum(serialize = "StructurePowerUmbilicalFemale")]
#[strum(props(name = "Umbilical Socket (Power)", desc = "", value = "101488029"))]
@@ -4165,7 +4194,7 @@ pub enum StationpediaPrefab {
#[strum(props(name = "Kit (Door)", desc = "", value = "168615924"))]
ItemKitDoor = 168615924i32,
#[strum(serialize = "ItemWreckageAirConditioner2")]
#[strum(props(name = "Wreckage Air Conditioner", desc = "", value = "169888054"))]
#[strum(props(name = "Wreckage", desc = "", value = "169888054"))]
ItemWreckageAirConditioner2 = 169888054i32,
#[strum(serialize = "Landingpad_GasCylinderTankPiece")]
#[strum(
@@ -4312,7 +4341,7 @@ pub enum StationpediaPrefab {
#[strum(props(name = "Chocolate Bar", desc = "", value = "234601764"))]
ItemChocolateBar = 234601764i32,
#[strum(serialize = "ItemExplosive")]
#[strum(props(name = "Remote Explosive", desc = "", value = "235361649"))]
#[strum(props(name = "Demolition Charge", desc = "", value = "235361649"))]
ItemExplosive = 235361649i32,
#[strum(serialize = "StructureConsole")]
#[strum(
@@ -4326,8 +4355,8 @@ pub enum StationpediaPrefab {
#[strum(serialize = "ItemPassiveVent")]
#[strum(
props(
name = "Passive Vent",
desc = "This kit creates a <link=ThingItemPassiveVent><color=green>Passive Vent</color></link> among other variants.",
name = "Kit (Passive Vent)",
desc = "This kit creates a <link=ThingItemPassiveVent><color=green>Kit (Passive Vent)</color></link> among other variants.",
value = "238631271"
)
)]
@@ -4620,6 +4649,9 @@ pub enum StationpediaPrefab {
)
)]
StructurePressureFedLiquidEngine = 379750958i32,
#[strum(serialize = "ItemMiningPackage")]
#[strum(props(name = "Mining Supplies Package", desc = "", value = "384478267"))]
ItemMiningPackage = 384478267i32,
#[strum(serialize = "ItemPureIceNitrous")]
#[strum(
props(
@@ -4644,7 +4676,7 @@ pub enum StationpediaPrefab {
)]
ItemMkiiDuctTape = 388774906i32,
#[strum(serialize = "ItemWreckageStructureRTG1")]
#[strum(props(name = "Wreckage Structure RTG", desc = "", value = "391453348"))]
#[strum(props(name = "Wreckage", desc = "", value = "391453348"))]
ItemWreckageStructureRtg1 = 391453348i32,
#[strum(serialize = "ItemPipeLabel")]
#[strum(
@@ -4723,7 +4755,7 @@ pub enum StationpediaPrefab {
#[strum(
props(
name = "Pipe Analyzer",
desc = "Allegedly the outcome of a weekend father-daughter electronics project by an overzealous {<link=ExMin><color=#0080FFFF>ExMin</color></link> engineer, the pipe analyzer is essentially a more advanced version of the <link=ThingStructurePipeMeter><color=green>Pipe Meter</color></link>.\nDisplaying the internal pressure of pipe networks, it also reads out temperature and gas contents, and can be connected to a <link=ThingStructureConsole><color=green>Console</color></link> or <link=ThingStructureComputer><color=green>Computer</color></link> via a {<link=LogicPage><color=#0080FFFF>Logic</color></link> system.",
desc = "Allegedly the outcome of a weekend father-daughter electronics project by an overzealous {<link=ExMin><color=#0080FFFF>ExMin</color></link> engineer, the pipe analyzer is essentially a more advanced version of the <link=ThingStructurePipeMeter><color=green>Pipe Meter</color></link>.\nDisplaying the internal pressure of pipe networks, it also reads out temperature and gas contents, and can be connected to a <link=ThingStructureConsole><color=green>Console</color></link> or <link=ThingStructureComputer><color=green>Computer (Modern)</color></link> via a {<link=LogicPage><color=#0080FFFF>Logic</color></link> system.",
value = "435685051"
)
)]
@@ -4735,7 +4767,7 @@ pub enum StationpediaPrefab {
#[strum(
props(
name = "Medium Satellite Dish",
desc = "This medium communications unit can be used to communicate with nearby trade vessels.\n \nWhen connected to a <link=ThingStructureComputer><color=green>Computer</color></link> containing a <link=ThingMotherboardComms><color=green>Communications Motherboard</color></link> motherboard, a <link=ThingLandingpad_CenterPiece01><color=green>Landingpad Center</color></link>, and a <link=ThingStructureVendingMachine><color=green>Vending Machine</color></link>, this allows Stationeers to contact traders. Adjust its horizontal and vertical attributes either directly or through logic.",
desc = "This medium communications unit can be used to communicate with nearby trade vessels.\n \nWhen connected to a <link=ThingStructureComputer><color=green>Computer (Modern)</color></link> containing a <link=ThingMotherboardComms><color=green>Communications Motherboard</color></link> motherboard, a <link=ThingLandingpad_CenterPiece01><color=green>Landingpad Center</color></link>, and a <link=ThingStructureVendingMachine><color=green>Vending Machine</color></link>, this allows Stationeers to contact traders. Adjust its horizontal and vertical attributes either directly or through logic.",
value = "439026183"
)
)]
@@ -4855,7 +4887,7 @@ pub enum StationpediaPrefab {
#[strum(
props(
name = "Logic Motherboard",
desc = "Motherboards are connected to <link=ThingStructureComputer><color=green>Computer</color></link>s to perform various technical functions.\nThe <link=Norsec><color=#0080FFFF>Norsec-designed</color></link> K-cops logic motherboard allows <link=Stationeers><color=#0080FFFF>Stationeers</color></link> to set variables and actions on specific <link=LogicUnitPage><color=#0080FFFF>logic</color></link>-controlled items.",
desc = "Motherboards are connected to <link=ThingStructureComputer><color=green>Computer (Modern)</color></link>s to perform various technical functions.\nThe <link=Norsec><color=#0080FFFF>Norsec-designed</color></link> K-cops logic motherboard allows <link=Stationeers><color=#0080FFFF>Stationeers</color></link> to set variables and actions on specific <link=LogicUnitPage><color=#0080FFFF>logic</color></link>-controlled items.",
value = "502555944"
)
)]
@@ -4863,6 +4895,11 @@ pub enum StationpediaPrefab {
#[strum(serialize = "StructureStairwellBackLeft")]
#[strum(props(name = "Stairwell (Back Left)", desc = "", value = "505924160"))]
StructureStairwellBackLeft = 505924160i32,
#[strum(serialize = "ItemResidentialPackage")]
#[strum(
props(name = "Residential Supplies Package", desc = "", value = "509629504")
)]
ItemResidentialPackage = 509629504i32,
#[strum(serialize = "ItemKitAccessBridge")]
#[strum(props(name = "Kit (Access Bridge)", desc = "", value = "513258369"))]
ItemKitAccessBridge = 513258369i32,
@@ -4903,13 +4940,7 @@ pub enum StationpediaPrefab {
)]
ItemPureIceLiquidOxygen = 541621589i32,
#[strum(serialize = "ItemWreckageStructureWeatherStation003")]
#[strum(
props(
name = "Wreckage Structure Weather Station",
desc = "",
value = "542009679"
)
)]
#[strum(props(name = "Wreckage", desc = "", value = "542009679"))]
ItemWreckageStructureWeatherStation003 = 542009679i32,
#[strum(serialize = "StructureInLineTankLiquid1x1")]
#[strum(
@@ -5056,13 +5087,7 @@ pub enum StationpediaPrefab {
)]
ItemRocketMiningDrillHeadHighSpeedIce = 653461728i32,
#[strum(serialize = "ItemWreckageStructureWeatherStation007")]
#[strum(
props(
name = "Wreckage Structure Weather Station",
desc = "",
value = "656649558"
)
)]
#[strum(props(name = "Wreckage", desc = "", value = "656649558"))]
ItemWreckageStructureWeatherStation007 = 656649558i32,
#[strum(serialize = "ItemRice")]
#[strum(
@@ -5092,7 +5117,9 @@ pub enum StationpediaPrefab {
#[strum(props(name = "Space Ice", desc = "", value = "675686937"))]
ItemSpaceIce = 675686937i32,
#[strum(serialize = "ItemRemoteDetonator")]
#[strum(props(name = "Remote Detonator", desc = "", value = "678483886"))]
#[strum(
props(name = "Remote Detonator", desc = "0.Mode0\n1.Mode1", value = "678483886")
)]
ItemRemoteDetonator = 678483886i32,
#[strum(serialize = "ItemCocoaTree")]
#[strum(props(name = "Cocoa", desc = "", value = "680051921"))]
@@ -5128,9 +5155,7 @@ pub enum StationpediaPrefab {
)]
StructureCentrifuge = 690945935i32,
#[strum(serialize = "StructureBlockBed")]
#[strum(
props(name = "Block Bed", desc = "Description coming.", value = "697908419")
)]
#[strum(props(name = "Block Bed", desc = "", value = "697908419"))]
StructureBlockBed = 697908419i32,
#[strum(serialize = "ItemBatteryCell")]
#[strum(
@@ -5221,6 +5246,15 @@ pub enum StationpediaPrefab {
#[strum(serialize = "WeaponEnergy")]
#[strum(props(name = "Weapon Energy", desc = "", value = "789494694"))]
WeaponEnergy = 789494694i32,
#[strum(serialize = "StructureCompositeWindowShutterConnector")]
#[strum(
props(
name = "Composite Window Shutter Connector",
desc = "",
value = "791407452"
)
)]
StructureCompositeWindowShutterConnector = 791407452i32,
#[strum(serialize = "ItemCerealBar")]
#[strum(
props(
@@ -5249,7 +5283,7 @@ pub enum StationpediaPrefab {
#[strum(
props(
name = "Kit (Pipe Valve)",
desc = "This kit creates a <link=ThingStructureValve><color=green>Valve</color></link>.",
desc = "This kit creates a <link=ThingStructureValve><color=green>Valve (Gas)</color></link>.",
value = "799323450"
)
)]
@@ -5349,6 +5383,9 @@ pub enum StationpediaPrefab {
)
)]
StructureCompositeCladdingAngledCornerLong = 850558385i32,
#[strum(serialize = "ItemEmergencySuppliesBox")]
#[strum(props(name = "Emergency Supplies", desc = "", value = "851103794"))]
ItemEmergencySuppliesBox = 851103794i32,
#[strum(serialize = "ItemPlantEndothermic_Genepool1")]
#[strum(
props(
@@ -5401,7 +5438,7 @@ pub enum StationpediaPrefab {
)]
ItemRoadFlare = 871811564i32,
#[strum(serialize = "CartridgeGuide")]
#[strum(props(name = "Guide", desc = "", value = "872720793"))]
#[strum(props(name = "Cartridge (Guide)", desc = "", value = "872720793"))]
CartridgeGuide = 872720793i32,
#[strum(serialize = "StructureLogicSorter")]
#[strum(
@@ -5841,7 +5878,7 @@ pub enum StationpediaPrefab {
)]
LandingpadCrossPiece = 1101296153i32,
#[strum(serialize = "CartridgePlantAnalyser")]
#[strum(props(name = "Cartridge Plant Analyser", desc = "", value = "1101328282"))]
#[strum(props(name = "Cartridge (Plant Analyser)", desc = "", value = "1101328282"))]
CartridgePlantAnalyser = 1101328282i32,
#[strum(serialize = "ItemSiliconOre")]
#[strum(
@@ -6053,7 +6090,7 @@ pub enum StationpediaPrefab {
#[strum(
props(
name = "Ice (Volatiles)",
desc = "An extremely reactive ice with numerous hydrocarbons trapped inside. For simplicity's sake, these are often displayed as H2 by devices like the <link=ThingCartridgeAtmosAnalyser><color=green>Atmos Analyzer</color></link>.\n \n<link=GasVolatiles><color=#44AD83>Volatiles</color></link> combust in a 2:1 ratio with <link=GasOxygen><color=#44AD83>Oxygen</color></link>, creating <link=GasCarbonDioxide><color=#44AD83>Carbon Dioxide</color></link> and pollutants. However when catalysed via devices such as the <link=ThingH2Combustor><color=green>H2 Combustor</color></link> in the presence of <link=GasOxygen><color=#44AD83>Oxygen</color></link>, they produce\n <link=GasSteam><color=#44AD83>Steam</color></link> and heat with a modicum of <link=GasCarbonDioxide><color=#44AD83>Carbon Dioxide</color></link> and <link=GasPollutant><color=#44AD83>Pollutant</color></link> due to the autoignition of the volatiles in the chamber. Along with <link=GasOxygen><color=#44AD83>Oxygen</color></link>, volatiles gas is also the major component of fuel for such devices as the <link=ThingItemWeldingTorch><color=green>Welding Torch</color></link>.\n",
desc = "An extremely reactive ice with numerous hydrocarbons trapped inside. For simplicity's sake, these are often displayed as H2 by devices like the <link=ThingCartridgeAtmosAnalyser><color=green>Cartridge (Atmos Analyzer)</color></link>.\n \n<link=GasVolatiles><color=#44AD83>Volatiles</color></link> combust in a 2:1 ratio with <link=GasOxygen><color=#44AD83>Oxygen</color></link>, creating <link=GasCarbonDioxide><color=#44AD83>Carbon Dioxide</color></link> and pollutants. However when catalysed via devices such as the <link=ThingH2Combustor><color=green>H2 Combustor</color></link> in the presence of <link=GasOxygen><color=#44AD83>Oxygen</color></link>, they produce\n <link=GasSteam><color=#44AD83>Steam</color></link> and heat with a modicum of <link=GasCarbonDioxide><color=#44AD83>Carbon Dioxide</color></link> and <link=GasPollutant><color=#44AD83>Pollutant</color></link> due to the autoignition of the volatiles in the chamber. Along with <link=GasOxygen><color=#44AD83>Oxygen</color></link>, volatiles gas is also the major component of fuel for such devices as the <link=ThingItemWeldingTorch><color=green>Welding Torch</color></link>.\n",
value = "1253102035"
)
)]
@@ -6131,6 +6168,9 @@ pub enum StationpediaPrefab {
#[strum(serialize = "StructureWallIron")]
#[strum(props(name = "Iron Wall (Type 1)", desc = "", value = "1287324802"))]
StructureWallIron = 1287324802i32,
#[strum(serialize = "StructurePipeOneWayValveLever")]
#[strum(props(name = "One Way Valve (Gas)", desc = "", value = "1289581593"))]
StructurePipeOneWayValveLever = 1289581593i32,
#[strum(serialize = "ItemSprayGun")]
#[strum(
props(
@@ -6243,13 +6283,7 @@ pub enum StationpediaPrefab {
#[strum(props(name = "Graph Display", desc = "", value = "1344368806"))]
CircuitboardGraphDisplay = 1344368806i32,
#[strum(serialize = "ItemWreckageStructureWeatherStation006")]
#[strum(
props(
name = "Wreckage Structure Weather Station",
desc = "",
value = "1344576960"
)
)]
#[strum(props(name = "Wreckage", desc = "", value = "1344576960"))]
ItemWreckageStructureWeatherStation006 = 1344576960i32,
#[strum(serialize = "ItemCookedCorn")]
#[strum(
@@ -6384,13 +6418,7 @@ pub enum StationpediaPrefab {
#[strum(props(name = "Water Bottle Filler Bottom", desc = "", value = "1433754995"))]
StructureWaterBottleFillerBottom = 1433754995i32,
#[strum(serialize = "StructureLightRoundSmall")]
#[strum(
props(
name = "Light Round (Small)",
desc = "Description coming.",
value = "1436121888"
)
)]
#[strum(props(name = "Light Round (Small)", desc = "", value = "1436121888"))]
StructureLightRoundSmall = 1436121888i32,
#[strum(serialize = "ItemRocketMiningDrillHeadHighSpeedMineral")]
#[strum(
@@ -6432,17 +6460,14 @@ pub enum StationpediaPrefab {
props(name = "Kit (Medium Radiator Liquid)", desc = "", value = "1453961898")
)]
ItemKitPassiveLargeRadiatorLiquid = 1453961898i32,
#[strum(serialize = "ItemPortablesPackage")]
#[strum(props(name = "Portables Package", desc = "", value = "1459105919"))]
ItemPortablesPackage = 1459105919i32,
#[strum(serialize = "ItemKitReinforcedWindows")]
#[strum(props(name = "Kit (Reinforced Windows)", desc = "", value = "1459985302"))]
#[strum(props(name = "Kit (Reinforced Walls)", desc = "", value = "1459985302"))]
ItemKitReinforcedWindows = 1459985302i32,
#[strum(serialize = "ItemWreckageStructureWeatherStation002")]
#[strum(
props(
name = "Wreckage Structure Weather Station",
desc = "",
value = "1464424921"
)
)]
#[strum(props(name = "Wreckage", desc = "", value = "1464424921"))]
ItemWreckageStructureWeatherStation002 = 1464424921i32,
#[strum(serialize = "StructureHydroponicsTray")]
#[strum(
@@ -6477,6 +6502,12 @@ pub enum StationpediaPrefab {
#[strum(serialize = "StructureTorpedoRack")]
#[strum(props(name = "Torpedo Rack", desc = "", value = "1473807953"))]
StructureTorpedoRack = 1473807953i32,
#[strum(serialize = "ItemWaterBottleBag")]
#[strum(props(name = "Water Bottle Bag", desc = "", value = "1476318823"))]
ItemWaterBottleBag = 1476318823i32,
#[strum(serialize = "ItemInsulatedCanisterPackage")]
#[strum(props(name = "Insulated Canister Package", desc = "", value = "1485675617"))]
ItemInsulatedCanisterPackage = 1485675617i32,
#[strum(serialize = "StructureWallIron02")]
#[strum(props(name = "Iron Wall (Type 2)", desc = "", value = "1485834215"))]
StructureWallIron02 = 1485834215i32,
@@ -6496,9 +6527,7 @@ pub enum StationpediaPrefab {
)]
ItemSprayCanRed = 1514393921i32,
#[strum(serialize = "StructureLightRound")]
#[strum(
props(name = "Light Round", desc = "Description coming.", value = "1514476632")
)]
#[strum(props(name = "Light Round", desc = "", value = "1514476632"))]
StructureLightRound = 1514476632i32,
#[strum(serialize = "Fertilizer")]
#[strum(
@@ -6590,15 +6619,9 @@ pub enum StationpediaPrefab {
#[strum(serialize = "ItemHastelloyIngot")]
#[strum(props(name = "Ingot (Hastelloy)", desc = "", value = "1579842814"))]
ItemHastelloyIngot = 1579842814i32,
#[strum(serialize = "StructurePipeOneWayValve")]
#[strum(
props(
name = "One Way Valve (Gas)",
desc = "The one way valve moves gas in one direction only: from input side to output side. It only permits flow if the input pressure is higher than output pressure.\n",
value = "1580412404"
)
)]
StructurePipeOneWayValve = 1580412404i32,
#[strum(serialize = "StructureCompositeWindowShutter")]
#[strum(props(name = "Composite Window Shutter", desc = "", value = "1580592998"))]
StructureCompositeWindowShutter = 1580592998i32,
#[strum(serialize = "StructureStackerReverse")]
#[strum(
props(
@@ -6624,13 +6647,7 @@ pub enum StationpediaPrefab {
#[strum(props(name = "Wall (Padded Arch)", desc = "", value = "1590330637"))]
StructureWallPaddedArch = 1590330637i32,
#[strum(serialize = "StructureLightRoundAngled")]
#[strum(
props(
name = "Light Round (Angled)",
desc = "Description coming.",
value = "1592905386"
)
)]
#[strum(props(name = "Light Round (Angled)", desc = "", value = "1592905386"))]
StructureLightRoundAngled = 1592905386i32,
#[strum(serialize = "StructureWallGeometryT")]
#[strum(props(name = "Wall (Geometry T)", desc = "", value = "1602758612"))]
@@ -6644,7 +6661,7 @@ pub enum StationpediaPrefab {
#[strum(serialize = "CartridgeNetworkAnalyser")]
#[strum(
props(
name = "Network Analyzer",
name = "Cartridge (Network Analyzer)",
desc = "A minor masterpiece of micro-electronic engineering, the network analyzer displays the current, voltage and wattage of a cable network, as well as any devices connected to it. Based on a widely-copied <link=Sinotai><color=#0080FFFF>Sinotai</color></link> design, it's used in conjunction with the OreCore <link=ThingItemTablet><color=green>Handheld Tablet</color></link>.",
value = "1606989119"
)
@@ -6750,13 +6767,7 @@ pub enum StationpediaPrefab {
#[strum(props(name = "Emergency Tool Belt", desc = "", value = "1661941301"))]
ItemEmergencyToolBelt = 1661941301i32,
#[strum(serialize = "StructureEmergencyButton")]
#[strum(
props(
name = "Important Button",
desc = "Description coming.",
value = "1668452680"
)
)]
#[strum(props(name = "Important Button", desc = "", value = "1668452680"))]
StructureEmergencyButton = 1668452680i32,
#[strum(serialize = "ItemKitAutoMinerSmall")]
#[strum(props(name = "Kit (Autominer Small)", desc = "", value = "1668815415"))]
@@ -6881,7 +6892,7 @@ pub enum StationpediaPrefab {
#[strum(
props(
name = "Advanced Tablet",
desc = "The advanced <link=Xigo><color=#0080FFFF>Xigo</color></link> Padi 2 tablet is an improved version of the basic <link=ThingItemTablet><color=green>Handheld Tablet</color></link>, boasting two <link=CartridgePage><color=#0080FFFF>cartridge</color></link> slots. The Padi 2 accepts <link=ThingCartridgeAtmosAnalyser><color=green>Atmos Analyzer</color></link>, <link=ThingCartridgeTracker><color=green>Tracker</color></link>, <link=ThingCartridgeMedicalAnalyser><color=green>Medical Analyzer</color></link>, <link=ThingCartridgeOreScanner><color=green>Ore Scanner</color></link>, <link=ThingCartridgeElectronicReader><color=green>eReader</color></link>, and various other cartridges.\n\t \n\t With a <link=ThingItemIntegratedCircuit10><color=green>Integrated Circuit (IC10)</color></link> in the <link=SlotProgrammableChip><color=orange>Programmable Chip</color></link>, you can access variable slots on the carrying human using the device numbers (d0, d1, etc...), so long as the item can be access via logic, such as the <link=ThingItemHardSuit><color=green>Hardsuit</color></link>.Connects to <pos=300><link=ThingStructureLogicTransmitter><color=green>Logic Transmitter</color></link>",
desc = "The advanced <link=Xigo><color=#0080FFFF>Xigo</color></link> Padi 2 tablet is an improved version of the basic <link=ThingItemTablet><color=green>Handheld Tablet</color></link>, boasting two <link=CartridgePage><color=#0080FFFF>cartridge</color></link> slots. The Padi 2 accepts <link=ThingCartridgeAtmosAnalyser><color=green>Cartridge (Atmos Analyzer)</color></link>, <link=ThingCartridgeTracker><color=green>Cartridge (Tracker)</color></link>, <link=ThingCartridgeMedicalAnalyser><color=green>Cartridge (Medical Analyzer)</color></link>, <link=ThingCartridgeOreScanner><color=green>Cartridge (Ore Scanner)</color></link>, <link=ThingCartridgeElectronicReader><color=green>Cartridge (eReader)</color></link>, and various other cartridges.\n\t \n\t With a <link=ThingItemIntegratedCircuit10><color=green>Integrated Circuit (IC10)</color></link> in the <link=SlotProgrammableChip><color=orange>Programmable Chip</color></link>, you can access variable slots on the carrying human using the device numbers (d0, d1, etc...), so long as the item can be access via logic, such as the <link=ThingItemHardSuit><color=green>Hardsuit</color></link>.Connects to <pos=300><link=ThingStructureLogicTransmitter><color=green>Logic Transmitter</color></link>",
value = "1722785341"
)
)]
@@ -6919,7 +6930,7 @@ pub enum StationpediaPrefab {
#[strum(serialize = "CartridgeOreScannerColor")]
#[strum(
props(
name = "Ore Scanner (Color)",
name = "Cartridge (Ore Scanner Color)",
desc = "When inserted into a <link=ThingItemTablet><color=green>Handheld Tablet</color></link> the scanner will display minerals hidden underground in different colors on the tablet.",
value = "1738236580"
)
@@ -6943,7 +6954,7 @@ pub enum StationpediaPrefab {
#[strum(serialize = "ItemAreaPowerControl")]
#[strum(
props(
name = "Kit (Power Controller)",
name = "Kit (Area Power Controller)",
desc = "This kit places a <link=ThingStructureAreaPowerControl><color=green>Area Power Control</color></link> (APC) on any support structure. The APC kit has two options, selecting which direction you would like the APC power to flow.",
value = "1757673317"
)
@@ -6977,7 +6988,9 @@ pub enum StationpediaPrefab {
)]
StructureWallPaddedThinNoBorderCorner = 1769527556i32,
#[strum(serialize = "ItemKitWindowShutter")]
#[strum(props(name = "Kit (Window Shutter)", desc = "", value = "1779979754"))]
#[strum(
props(name = "Kit (Composite Window Shutter)", desc = "", value = "1779979754")
)]
ItemKitWindowShutter = 1779979754i32,
#[strum(serialize = "StructureRocketManufactory")]
#[strum(props(name = "Rocket Manufactory", desc = "", value = "1781051034"))]
@@ -7000,6 +7013,11 @@ pub enum StationpediaPrefab {
#[strum(serialize = "ItemCoffeeMug")]
#[strum(props(name = "Coffee Mug", desc = "", value = "1800622698"))]
ItemCoffeeMug = 1800622698i32,
#[strum(serialize = "StructureRoboticArmRailStraightStop")]
#[strum(
props(name = "Linear Rail Straight Station", desc = "", value = "1800701885")
)]
StructureRoboticArmRailStraightStop = 1800701885i32,
#[strum(serialize = "StructureAngledBench")]
#[strum(props(name = "Bench (Angled)", desc = "", value = "1811979158"))]
StructureAngledBench = 1811979158i32,
@@ -7118,7 +7136,7 @@ pub enum StationpediaPrefab {
)]
ItemCookedPumpkin = 1849281546i32,
#[strum(serialize = "StructureLiquidValve")]
#[strum(props(name = "Liquid Valve", desc = "", value = "1849974453"))]
#[strum(props(name = "Valve (Liquid)", desc = "", value = "1849974453"))]
StructureLiquidValve = 1849974453i32,
#[strum(serialize = "ApplianceTabletDock")]
#[strum(props(name = "Tablet Dock", desc = "", value = "1853941363"))]
@@ -7167,7 +7185,7 @@ pub enum StationpediaPrefab {
#[strum(
props(
name = "Large Satellite Dish",
desc = "This large communications unit can be used to communicate with nearby trade vessels.\n\n When connected to a <link=ThingStructureComputer><color=green>Computer</color></link> containing a <link=ThingMotherboardComms><color=green>Communications Motherboard</color></link> motherboard, a <link=ThingLandingpad_CenterPiece01><color=green>Landingpad Center</color></link>, and a <link=ThingStructureVendingMachine><color=green>Vending Machine</color></link>, this allows Stationeers to contact traders. Adjust its horizontal and vertical attributes either directly or through logic.",
desc = "This large communications unit can be used to communicate with nearby trade vessels.\n\n When connected to a <link=ThingStructureComputer><color=green>Computer (Modern)</color></link> containing a <link=ThingMotherboardComms><color=green>Communications Motherboard</color></link> motherboard, a <link=ThingLandingpad_CenterPiece01><color=green>Landingpad Center</color></link>, and a <link=ThingStructureVendingMachine><color=green>Vending Machine</color></link>, this allows Stationeers to contact traders. Adjust its horizontal and vertical attributes either directly or through logic.",
value = "1913391845"
)
)]
@@ -7217,7 +7235,7 @@ pub enum StationpediaPrefab {
)]
StructureInsulatedPipeLiquidCrossJunction = 1926651727i32,
#[strum(serialize = "ItemWreckageTurbineGenerator3")]
#[strum(props(name = "Wreckage Turbine Generator", desc = "", value = "1927790321"))]
#[strum(props(name = "Wreckage", desc = "", value = "1927790321"))]
ItemWreckageTurbineGenerator3 = 1927790321i32,
#[strum(serialize = "StructurePassthroughHeatExchangerGasToLiquid")]
#[strum(
@@ -7336,6 +7354,9 @@ pub enum StationpediaPrefab {
)
)]
StructureCompositeCladdingRoundedCorner = 1951525046i32,
#[strum(serialize = "StructureChuteExportBin")]
#[strum(props(name = "Chute Export Bin", desc = "", value = "1957571043"))]
StructureChuteExportBin = 1957571043i32,
#[strum(serialize = "ItemGasFilterPollutantsL")]
#[strum(props(name = "Heavy Filter (Pollutants)", desc = "", value = "1959564765"))]
ItemGasFilterPollutantsL = 1959564765i32,
@@ -7354,8 +7375,8 @@ pub enum StationpediaPrefab {
#[strum(serialize = "StructureDrinkingFountain")]
#[strum(
props(
name = "<N:EN:StructureDrinkingFountain>",
desc = "<N:EN:StructureDrinkingFountain>",
name = "Drinking Fountain",
desc = "The Drinking Fountain can be interacted with directly to increase hydration. It needs a <link=GasWater><color=#44AD83>Water</color></link> supply.",
value = "1968371847"
)
)]
@@ -7372,6 +7393,9 @@ pub enum StationpediaPrefab {
#[strum(serialize = "ItemKitEngineMedium")]
#[strum(props(name = "Kit (Engine Medium)", desc = "", value = "1969312177"))]
ItemKitEngineMedium = 1969312177i32,
#[strum(serialize = "StructureRoboticArmRailCornerStop")]
#[strum(props(name = "Linear Rail Corner Station", desc = "", value = "1974053060"))]
StructureRoboticArmRailCornerStop = 1974053060i32,
#[strum(serialize = "StructureWallGeometryCorner")]
#[strum(props(name = "Wall (Geometry Corner)", desc = "", value = "1979212240"))]
StructureWallGeometryCorner = 1979212240i32,
@@ -7541,15 +7565,6 @@ pub enum StationpediaPrefab {
#[strum(serialize = "StructureStairwellNoDoors")]
#[strum(props(name = "Stairwell (No Doors)", desc = "", value = "2049879875"))]
StructureStairwellNoDoors = 2049879875i32,
#[strum(serialize = "StructureWindowShutter")]
#[strum(
props(
name = "Window Shutter",
desc = "For those special, private moments, a window that can be closed to prying eyes. \n \nWhen closed, has the heat transfer characteristics of a basic wall. Requires power, and can be connected to logic systems.",
value = "2056377335"
)
)]
StructureWindowShutter = 2056377335i32,
#[strum(serialize = "ItemKitHydroponicStation")]
#[strum(props(name = "Kit (Hydroponic Station)", desc = "", value = "2057179799"))]
ItemKitHydroponicStation = 2057179799i32,
@@ -7557,7 +7572,7 @@ pub enum StationpediaPrefab {
#[strum(
props(
name = "Cable Coil (Heavy)",
desc = "Use heavy cable coil for power systems with large draws. Unlike <link=ThingStructureCableCoil><color=green><N:EN:StructureCableCoil></color></link>, which can only safely conduct 5kW, heavy cables can transmit up to 100kW.",
desc = "Use heavy cable coil for power systems with large draws. Unlike <link=ThingItemCableCoil><color=green>Cable Coil</color></link>, which can only safely conduct 5kW, heavy cables can transmit up to 100kW.",
value = "2060134443"
)
)]

View File

@@ -153,7 +153,7 @@ pub enum LogicSlotType {
#[strum(serialize = "OccupantHash")]
#[strum(
props(
docs = "returns the has of the current occupant, the unique identifier of the thing",
docs = "returns the hash of the current occupant, the unique identifier of the thing",
value = "2"
)
)]
@@ -2095,6 +2095,14 @@ pub enum LogicType {
)
)]
NameHash = 268u16,
#[strum(serialize = "Altitude")]
#[strum(
props(
docs = "The altitude that the rocket above the planet's surface. -1 if the rocket is in space.",
value = "269"
)
)]
Altitude = 269u16,
}
impl TryFrom<f64> for LogicType {
type Error = super::ParseError;

View File

@@ -69,6 +69,7 @@ pub mod enums {
LandingPad,
LaunchPad,
PowerAndData,
RoboticArmRail,
#[serde(other)]
#[default]
None,

View File

@@ -6,7 +6,7 @@ use crate::enums::{
ConnectionRole, ConnectionType, MachineTier, MemoryAccess, Species,
};
use serde_with::{serde_as, DisplayFromStr, Map};
use serde_with::{serde_as, DisplayFromStr};
use serde_derive::{Deserialize, Serialize};
#[cfg(feature = "tsify")]
@@ -250,7 +250,7 @@ pub struct DeviceInfo {
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
pub struct ConsumerInfo {
pub consumed_resouces: Vec<String>,
pub consumed_resources: Vec<String>,
pub processed_reagents: Vec<i32>,
}
@@ -353,7 +353,7 @@ pub struct InternalAtmoInfo {
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
pub struct SuitInfo {
pub hygine_reduction_multiplier: f32,
pub hygiene_reduction_multiplier: f32,
pub waste_max_pressure: f32,
}

View File

@@ -56,6 +56,7 @@
"codegen",
"Comlink",
"datapoints",
"dbutils",
"Depressurising",
"deviceslength",
"endpos",
@@ -64,12 +65,14 @@
"hardwrap",
"hashables",
"hstack",
"IDBP",
"idxs",
"infile",
"jetpack",
"Keybind",
"labelledby",
"lbns",
"leeoniya",
"logicable",
"LogicSlotType",
"logicslottypes",
@@ -97,6 +100,8 @@
"regen",
"rocketstation",
"rparen",
"rsbuild",
"rspack",
"sapz",
"sattellite",
"sdns",
@@ -106,6 +111,7 @@
"sgez",
"sgtz",
"slez",
"Slotable",
"slotclass",
"slotlogic",
"slotlogicable",
@@ -124,6 +130,9 @@
"themelist",
"tokentype",
"trunc",
"ufuzzy",
"VMIC",
"vstack",
"whos"
],
"flagWords": [],

View File

@@ -27,6 +27,7 @@
"@oneidentity/zstd-js": "^1.0.3",
"@rsbuild/core": "^0.7.10",
"@rsbuild/plugin-image-compress": "^0.7.10",
"@rsbuild/plugin-sass": "^0.7.10",
"@rsbuild/plugin-type-check": "^0.7.10",
"@rspack/cli": "^0.7.5",
"@rspack/core": "^0.7.5",

258
www/pnpm-lock.yaml generated
View File

@@ -84,6 +84,9 @@ importers:
'@rsbuild/plugin-image-compress':
specifier: ^0.7.10
version: 0.7.10(@rsbuild/core@0.7.10)
'@rsbuild/plugin-sass':
specifier: ^0.7.10
version: 0.7.10(@rsbuild/core@0.7.10)(@swc/helpers@0.5.12)
'@rsbuild/plugin-type-check':
specifier: ^0.7.10
version: 0.7.10(@rsbuild/core@0.7.10)(@swc/helpers@0.5.12)(typescript@5.5.4)
@@ -158,6 +161,9 @@ packages:
resolution: {integrity: sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==}
engines: {node: '>=6.9.0'}
'@bufbuild/protobuf@1.10.0':
resolution: {integrity: sha512-QDdVFLoN93Zjg36NoQPZfsVH9tZew7wKDKyV5qRdj8ntT4wQCOradQjRaTdwMhWUYsgKsvCINKKm87FdEk96Ag==}
'@ctrl/tinycolor@4.1.0':
resolution: {integrity: sha512-WyOx8cJQ+FQus4Mm4uPIZA64gbk3Wxh0so5Lcii0aJifqwoVOlfFtorjLE0Hen4OYyHZMXDWqMmaQemBhgxFRQ==}
engines: {node: '>=14'}
@@ -363,6 +369,11 @@ packages:
peerDependencies:
'@rsbuild/core': ^0.7.10
'@rsbuild/plugin-sass@0.7.10':
resolution: {integrity: sha512-gtYNH+xgxWyroG1z2wqh/l7v88CiH89HtrIs+BbEgn1CV12dQvMI3YtF4aEwS6Ogr+byomdirFLhdBy0WBCbzQ==}
peerDependencies:
'@rsbuild/core': ^0.7.10
'@rsbuild/plugin-type-check@0.7.10':
resolution: {integrity: sha512-EGNeHEZEWvABqTGt+CEtw5kQskNrg2nch4wRuAechPgmHmzU/k65EoXTMsB/ImmcdUeU2ax2kdlQOdxs6fNgoA==}
peerDependencies:
@@ -734,6 +745,9 @@ packages:
batch@0.6.1:
resolution: {integrity: sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==}
big.js@5.2.2:
resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==}
binary-extensions@2.3.0:
resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
engines: {node: '>=8'}
@@ -797,6 +811,9 @@ packages:
resolution: {integrity: sha512-iOJg8pr7wq2tg/zSlCCHMi3hMm5JTOxLTagf3zxhcenHsFp+c6uOs6K7W5UE7A4QIJGtqh/ZovFNMP4mOPJynQ==}
engines: {node: '>=16.20.1'}
buffer-builder@0.2.0:
resolution: {integrity: sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==}
buffer-from@1.1.2:
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
@@ -1099,6 +1116,10 @@ packages:
emoji-regex@9.2.2:
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
emojis-list@3.0.0:
resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==}
engines: {node: '>= 4'}
encodeurl@1.0.2:
resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==}
engines: {node: '>= 0.8'}
@@ -1566,6 +1587,10 @@ packages:
resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==}
engines: {node: '>=6.11.5'}
loader-utils@2.0.4:
resolution: {integrity: sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==}
engines: {node: '>=8.9.0'}
lodash.deburr@4.1.0:
resolution: {integrity: sha512-m/M1U1f3ddMCs6Hq2tAsYThTBDaAKFDX3dwDo97GEYzamXi9SqUpjWi/Rrj/gf3X2n8ktwgZrlP1z6E3v/IExQ==}
@@ -1991,6 +2016,9 @@ packages:
run-parallel@1.2.0:
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
rxjs@7.8.1:
resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==}
safe-buffer@5.1.2:
resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==}
@@ -2000,6 +2028,125 @@ packages:
safer-buffer@2.1.2:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
sass-embedded-android-arm64@1.77.8:
resolution: {integrity: sha512-EmWHLbEx0Zo/f/lTFzMeH2Du+/I4RmSRlEnERSUKQWVp3aBSO04QDvdxfFezgQ+2Yt/ub9WMqBpma9P/8MPsLg==}
engines: {node: '>=14.0.0'}
cpu: [arm64]
os: [android]
hasBin: true
sass-embedded-android-arm@1.77.8:
resolution: {integrity: sha512-GpGL7xZ7V1XpFbnflib/NWbM0euRzineK0iwoo31/ntWKAXGj03iHhGzkSiOwWSFcXgsJJi3eRA5BTmBvK5Q+w==}
engines: {node: '>=14.0.0'}
cpu: [arm]
os: [android]
hasBin: true
sass-embedded-android-ia32@1.77.8:
resolution: {integrity: sha512-+GjfJ3lDezPi4dUUyjQBxlNKXNa+XVWsExtGvVNkv1uKyaOxULJhubVo2G6QTJJU0esJdfeXf5Ca5/J0ph7+7w==}
engines: {node: '>=14.0.0'}
cpu: [ia32]
os: [android]
hasBin: true
sass-embedded-android-x64@1.77.8:
resolution: {integrity: sha512-YZbFDzGe5NhaMCygShqkeCWtzjhkWxGVunc7ULR97wmxYPQLPeVyx7XFQZc84Aj0lKAJBJS4qRZeqphMqZEJsQ==}
engines: {node: '>=14.0.0'}
cpu: [x64]
os: [android]
hasBin: true
sass-embedded-darwin-arm64@1.77.8:
resolution: {integrity: sha512-aifgeVRNE+i43toIkDFFJc/aPLMo0PJ5s5hKb52U+oNdiJE36n65n2L8F/8z3zZRvCa6eYtFY2b7f1QXR3B0LA==}
engines: {node: '>=14.0.0'}
cpu: [arm64]
os: [darwin]
hasBin: true
sass-embedded-darwin-x64@1.77.8:
resolution: {integrity: sha512-/VWZQtcWIOek60Zj6Sxk6HebXA1Qyyt3sD8o5qwbTgZnKitB1iEBuNunyGoAgMNeUz2PRd6rVki6hvbas9hQ6w==}
engines: {node: '>=14.0.0'}
cpu: [x64]
os: [darwin]
hasBin: true
sass-embedded-linux-arm64@1.77.8:
resolution: {integrity: sha512-6iIOIZtBFa2YfMsHqOb3qake3C9d/zlKxjooKKnTSo+6g6z+CLTzMXe1bOfayb7yxeenElmFoK1k54kWD/40+g==}
engines: {node: '>=14.0.0'}
cpu: [arm64]
os: [linux]
hasBin: true
sass-embedded-linux-arm@1.77.8:
resolution: {integrity: sha512-2edZMB6jf0whx3T0zlgH+p131kOEmWp+I4wnKj7ZMUeokiY4Up05d10hSvb0Q63lOrSjFAWu6P5/pcYUUx8arQ==}
engines: {node: '>=14.0.0'}
cpu: [arm]
os: [linux]
hasBin: true
sass-embedded-linux-ia32@1.77.8:
resolution: {integrity: sha512-63GsFFHWN5yRLTWiSef32TM/XmjhCBx1DFhoqxmj+Yc6L9Z1h0lDHjjwdG6Sp5XTz5EmsaFKjpDgnQTP9hJX3Q==}
engines: {node: '>=14.0.0'}
cpu: [ia32]
os: [linux]
hasBin: true
sass-embedded-linux-musl-arm64@1.77.8:
resolution: {integrity: sha512-j8cgQxNWecYK+aH8ESFsyam/Q6G+9gg8eJegiRVpA9x8yk3ykfHC7UdQWwUcF22ZcuY4zegrjJx8k+thsgsOVA==}
engines: {node: '>=14.0.0'}
cpu: [arm64]
os: [linux]
sass-embedded-linux-musl-arm@1.77.8:
resolution: {integrity: sha512-nFkhSl3uu9btubm+JBW7uRglNVJ8W8dGfzVqh3fyQJKS1oyBC3vT3VOtfbT9YivXk28wXscSHpqXZwY7bUuopA==}
engines: {node: '>=14.0.0'}
cpu: [arm]
os: [linux]
sass-embedded-linux-musl-ia32@1.77.8:
resolution: {integrity: sha512-oWveMe+8TFlP8WBWPna/+Ec5TV0CE+PxEutyi0ltSruBds2zxRq9dPVOqrpPcDN9QUx50vNZC0Afgch0aQEd0g==}
engines: {node: '>=14.0.0'}
cpu: [ia32]
os: [linux]
sass-embedded-linux-musl-x64@1.77.8:
resolution: {integrity: sha512-2NtRpMXHeFo9kaYxuZ+Ewwo39CE7BTS2JDfXkTjZTZqd8H+8KC53eBh516YQnn2oiqxSiKxm7a6pxbxGZGwXOQ==}
engines: {node: '>=14.0.0'}
cpu: [x64]
os: [linux]
sass-embedded-linux-x64@1.77.8:
resolution: {integrity: sha512-ND5qZLWUCpOn7LJfOf0gLSZUWhNIysY+7NZK1Ctq+pM6tpJky3JM5I1jSMplNxv5H3o8p80n0gSm+fcjsEFfjQ==}
engines: {node: '>=14.0.0'}
cpu: [x64]
os: [linux]
hasBin: true
sass-embedded-win32-arm64@1.77.8:
resolution: {integrity: sha512-7L8zT6xzEvTYj86MvUWnbkWYCNQP+74HvruLILmiPPE+TCgOjgdi750709BtppVJGGZSs40ZuN6mi/YQyGtwXg==}
engines: {node: '>=14.0.0'}
cpu: [arm64]
os: [win32]
hasBin: true
sass-embedded-win32-ia32@1.77.8:
resolution: {integrity: sha512-7Buh+4bP0WyYn6XPbthkIa3M2vtcR8QIsFVg3JElVlr+8Ng19jqe0t0SwggDgbMX6AdQZC+Wj4F1BprZSok42A==}
engines: {node: '>=14.0.0'}
cpu: [ia32]
os: [win32]
hasBin: true
sass-embedded-win32-x64@1.77.8:
resolution: {integrity: sha512-rZmLIx4/LLQm+4GW39sRJW0MIlDqmyV0fkRzTmhFP5i/wVC7cuj8TUubPHw18rv2rkHFfBZKZJTCkPjCS5Z+SA==}
engines: {node: '>=14.0.0'}
cpu: [x64]
os: [win32]
hasBin: true
sass-embedded@1.77.8:
resolution: {integrity: sha512-WGXA6jcaoBo5Uhw0HX/s6z/sl3zyYQ7ZOnLOJzqwpctFcFmU4L07zn51e2VSkXXFpQZFAdMZNqOGz/7h/fvcRA==}
engines: {node: '>=16.0.0'}
sass@1.77.8:
resolution: {integrity: sha512-4UHg6prsrycW20fqLGPShtEvo/WyHRVRHwOP4DzkUrObWoWI05QBSfzU71TVB7PFaL104TwNaHpjlWXAZbQiNQ==}
engines: {node: '>=14.0.0'}
@@ -2313,6 +2460,9 @@ packages:
resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==}
hasBin: true
varint@6.0.0:
resolution: {integrity: sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==}
vary@1.1.2:
resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
engines: {node: '>= 0.8'}
@@ -2551,6 +2701,8 @@ snapshots:
dependencies:
regenerator-runtime: 0.14.1
'@bufbuild/protobuf@1.10.0': {}
'@ctrl/tinycolor@4.1.0': {}
'@discoveryjs/json-ext@0.5.7': {}
@@ -2754,6 +2906,16 @@ snapshots:
'@rsbuild/core': 0.7.10
svgo: 3.3.2
'@rsbuild/plugin-sass@0.7.10(@rsbuild/core@0.7.10)(@swc/helpers@0.5.12)':
dependencies:
'@rsbuild/core': 0.7.10
'@rsbuild/shared': 0.7.10(@swc/helpers@0.5.12)
loader-utils: 2.0.4
postcss: 8.4.41
sass-embedded: 1.77.8
transitivePeerDependencies:
- '@swc/helpers'
'@rsbuild/plugin-type-check@0.7.10(@rsbuild/core@0.7.10)(@swc/helpers@0.5.12)(typescript@5.5.4)':
dependencies:
'@rsbuild/core': 0.7.10
@@ -3259,6 +3421,8 @@ snapshots:
batch@0.6.1: {}
big.js@5.2.2: {}
binary-extensions@2.3.0: {}
bn.js@4.12.0: {}
@@ -3357,6 +3521,8 @@ snapshots:
bson@6.8.0: {}
buffer-builder@0.2.0: {}
buffer-from@1.1.2: {}
buffer-xor@1.0.3: {}
@@ -3683,6 +3849,8 @@ snapshots:
emoji-regex@9.2.2: {}
emojis-list@3.0.0: {}
encodeurl@1.0.2: {}
enhanced-resolve@5.17.1:
@@ -4184,6 +4352,12 @@ snapshots:
loader-runner@4.3.0: {}
loader-utils@2.0.4:
dependencies:
big.js: 5.2.2
emojis-list: 3.0.0
json5: 2.2.3
lodash.deburr@4.1.0: {}
lodash@4.17.21: {}
@@ -4555,12 +4729,94 @@ snapshots:
dependencies:
queue-microtask: 1.2.3
rxjs@7.8.1:
dependencies:
tslib: 2.6.3
safe-buffer@5.1.2: {}
safe-buffer@5.2.1: {}
safer-buffer@2.1.2: {}
sass-embedded-android-arm64@1.77.8:
optional: true
sass-embedded-android-arm@1.77.8:
optional: true
sass-embedded-android-ia32@1.77.8:
optional: true
sass-embedded-android-x64@1.77.8:
optional: true
sass-embedded-darwin-arm64@1.77.8:
optional: true
sass-embedded-darwin-x64@1.77.8:
optional: true
sass-embedded-linux-arm64@1.77.8:
optional: true
sass-embedded-linux-arm@1.77.8:
optional: true
sass-embedded-linux-ia32@1.77.8:
optional: true
sass-embedded-linux-musl-arm64@1.77.8:
optional: true
sass-embedded-linux-musl-arm@1.77.8:
optional: true
sass-embedded-linux-musl-ia32@1.77.8:
optional: true
sass-embedded-linux-musl-x64@1.77.8:
optional: true
sass-embedded-linux-x64@1.77.8:
optional: true
sass-embedded-win32-arm64@1.77.8:
optional: true
sass-embedded-win32-ia32@1.77.8:
optional: true
sass-embedded-win32-x64@1.77.8:
optional: true
sass-embedded@1.77.8:
dependencies:
'@bufbuild/protobuf': 1.10.0
buffer-builder: 0.2.0
immutable: 4.3.7
rxjs: 7.8.1
supports-color: 8.1.1
varint: 6.0.0
optionalDependencies:
sass-embedded-android-arm: 1.77.8
sass-embedded-android-arm64: 1.77.8
sass-embedded-android-ia32: 1.77.8
sass-embedded-android-x64: 1.77.8
sass-embedded-darwin-arm64: 1.77.8
sass-embedded-darwin-x64: 1.77.8
sass-embedded-linux-arm: 1.77.8
sass-embedded-linux-arm64: 1.77.8
sass-embedded-linux-ia32: 1.77.8
sass-embedded-linux-musl-arm: 1.77.8
sass-embedded-linux-musl-arm64: 1.77.8
sass-embedded-linux-musl-ia32: 1.77.8
sass-embedded-linux-musl-x64: 1.77.8
sass-embedded-linux-x64: 1.77.8
sass-embedded-win32-arm64: 1.77.8
sass-embedded-win32-ia32: 1.77.8
sass-embedded-win32-x64: 1.77.8
sass@1.77.8:
dependencies:
chokidar: 3.6.0
@@ -4929,6 +5185,8 @@ snapshots:
uuid@8.3.2: {}
varint@6.0.0: {}
vary@1.1.2: {}
vm-browserify@1.1.2: {}

View File

@@ -1,6 +1,7 @@
import { defineConfig } from "@rsbuild/core";
import { pluginTypeCheck } from "@rsbuild/plugin-type-check";
import { pluginImageCompress } from "@rsbuild/plugin-image-compress";
import { pluginSass } from "@rsbuild/plugin-sass";
const rspack = require("@rspack/core");
const { CssExtractRspackPlugin } = require("@rspack/core");
@@ -72,5 +73,5 @@ export default defineConfig({
template: "./src/index.html",
},
},
plugins: [pluginTypeCheck(), pluginImageCompress()],
plugins: [pluginSass(), pluginTypeCheck(), pluginImageCompress()],
});

View File

@@ -19,19 +19,23 @@ $accordion-icon-color-dark: #dee2e6;
$accordion-icon-active-color-dark: #dee2e6;
$accordion-button-padding-y: 0.5rem;
// Required
@import "bootstrap/scss/variables";
@import "bootstrap/scss/variables-dark";
@import "bootstrap/scss/maps";
@import "bootstrap/scss/mixins";
@import "bootstrap/scss/utilities";
@import "bootstrap/scss/root";
@import "bootstrap/scss/reboot";
// // Required
// @import "bootstrap/scss/variables";
// @import "bootstrap/scss/variables-dark";
// @import "bootstrap/scss/maps";
// @import "bootstrap/scss/mixins";
// @import "bootstrap/scss/utilities";
// @import "bootstrap/scss/root";
// @import "bootstrap/scss/reboot";
//
// @import "bootstrap/scss/type";
// // @import "bootstrap/scss/images";
// @import "bootstrap/scss/containers";
// @import "bootstrap/scss/grid";
@import "bootstrap/scss/type";
// @import "bootstrap/scss/images";
@import "bootstrap/scss/containers";
@import "bootstrap/scss/grid";
// @import "bootstrap/scss/tables";
// @import "bootstrap/scss/forms";
// @import "bootstrap/scss/buttons";
@@ -59,11 +63,11 @@ $accordion-button-padding-y: 0.5rem;
// @import "bootstrap/scss/offcanvas"; // Requires transitions
// @import "bootstrap/scss/placeholders";
// Helpers
@import "bootstrap/scss/helpers";
// // Helpers
// @import "bootstrap/scss/helpers";
// Utilities
@import "bootstrap/scss/utilities/api";
// // Utilities
// @import "bootstrap/scss/utilities/api";
// Sholace theme
@import "@shoelace-style/shoelace/dist/themes/dark.css";

View File

@@ -72,16 +72,18 @@ export const demoVMState: SessionDB.CurrentDBVmState = {
id: 1,
prefab: "StructureCircuitHousing",
socketed_ic: 2,
slots: {
0: { id: 2, quantity: 1 },
},
connections: {
0: 1,
},
slots: new Map([
[0, { id: 2, quantity: 1 }],
]),
connections: new Map([
[0, 1],
]),
// unused, provided to make compiler happy
name: undefined,
prefab_hash: undefined,
compile_errors: undefined,
parent_slot: undefined,
root_parent_human: undefined,
damage: undefined,
device_pins: undefined,
reagents: undefined,
@@ -106,9 +108,9 @@ export const demoVMState: SessionDB.CurrentDBVmState = {
instruction_pointer: 0,
yield_instruction_count: 0,
state: "Start",
aliases: {},
defines: {},
labels: {},
aliases: new Map(),
defines: new Map(),
labels: new Map(),
registers: new Array(18).fill(0),
},
@@ -117,6 +119,8 @@ export const demoVMState: SessionDB.CurrentDBVmState = {
prefab_hash: undefined,
compile_errors: undefined,
slots: undefined,
parent_slot: undefined,
root_parent_human: undefined,
damage: undefined,
device_pins: undefined,
connections: undefined,

View File

@@ -417,14 +417,16 @@ export namespace SessionDB {
instruction_pointer: ic.ip,
yield_instruction_count: ic.ic,
state: ic.state as ICState,
aliases: Object.fromEntries(ic.aliases.entries()),
defines: Object.fromEntries(ic.defines.entries()),
labels: {},
aliases: ic.aliases,
defines: ic.defines,
labels: new Map(),
registers: ic.registers,
},
// unused
slots: undefined,
parent_slot: undefined,
root_parent_human: undefined,
damage: undefined,
device_pins: undefined,
connections: undefined,
@@ -492,7 +494,7 @@ export namespace SessionDB {
id: template.id,
prefab: template.prefab_name,
prefab_hash: undefined,
slots: Object.fromEntries(
slots: new Map(
Array.from(slotOccupantsPairs.entries()).map(
([index, [obj, quantity]]) => [
index,
@@ -505,17 +507,19 @@ export namespace SessionDB {
),
socketed_ic: socketedIcFn(template.id),
logic_values: Object.fromEntries(
logic_values: new Map(
Object.entries(template.fields).map(([key, val]) => {
return [key, val.value];
return [key as LogicType, val.value];
}),
) as Record<LogicType, number>,
),
// unused
memory: undefined,
source_code: undefined,
compile_errors: undefined,
circuit: undefined,
parent_slot: undefined,
root_parent_human: undefined,
damage: undefined,
device_pins: undefined,
connections: undefined,

View File

@@ -1,4 +1,5 @@
import { Ace } from "ace-builds";
import { TransferHandler } from "comlink";
export function docReady(fn: () => void) {
// see if DOM is already available
@@ -92,6 +93,26 @@ export function fromJson(value: string): any {
return JSON.parse(value, reviver);
}
// this is a hack that *may* not be needed
type SuitableForSpecialJson = any;
export const comlinkSpecialJsonTransferHandler: TransferHandler<any, string> = {
canHandle: (obj: unknown): obj is SuitableForSpecialJson => {
return typeof obj === "object"
|| (
typeof obj === "number"
&& (!Number.isFinite(obj) || Number.isNaN(obj) || isZeroNegative(obj))
)
|| typeof obj === "undefined";
},
serialize: (obj: SuitableForSpecialJson) => {
const sJson = toJson(obj);
return [
sJson,
[],
]
},
deserialize: (obj: string) => fromJson(obj)
};
export function compareMaps(map1: Map<any, any>, map2: Map<any, any>): boolean {
let testVal;

View File

@@ -21,6 +21,7 @@ import { LitElement, PropertyValueMap } from "lit";
import {
computed,
signal,
} from '@lit-labs/preact-signals';
import type { Signal } from '@lit-labs/preact-signals';
@@ -138,7 +139,7 @@ export class ComputedObjectSignals {
return slotsTemplate.map((template, index) => {
const fieldEntryInfos = Array.from(
Object.entries(logicTemplate?.logic_slot_types[index]) ?? [],
Object.entries(logicTemplate?.logic_slot_types.get(index)) ?? [],
);
const logicFields = new Map(
fieldEntryInfos.map(([slt, access]) => {
@@ -321,11 +322,11 @@ export const globalObjectSignalMap = new ObjectComputedSignalMap();
type Constructor<T = {}> = new (...args: any[]) => T;
export declare class VMObjectMixinInterface {
objectID: ObjectID;
activeICId: ObjectID;
objectID: Signal<ObjectID>;
activeICId: Signal<ObjectID>;
objectSignals: ComputedObjectSignals | null;
_handleDeviceModified(e: CustomEvent): void;
updateDevice(): void;
updateObject(): void;
subscribe(...sub: VMObjectMixinSubscription[]): void;
unsubscribe(filter: (sub: VMObjectMixinSubscription) => boolean): void;
}
@@ -338,14 +339,12 @@ export const VMObjectMixin = <T extends Constructor<LitElement>>(
superClass: T,
) => {
class VMObjectMixinClass extends superClass {
private _objectID: number;
get objectID() {
return this._objectID;
}
@property({ type: Number })
set objectID(val: number) {
this._objectID = val;
this.updateDevice();
objectID: Signal<ObjectID | null>;
constructor (...args: any[]) {
super(...args);
this.objectID = signal(null);
this.objectID.subscribe((_) => {this.updateObject()})
}
@state() private objectSubscriptions: VMObjectMixinSubscription[] = [];
@@ -354,16 +353,16 @@ export const VMObjectMixin = <T extends Constructor<LitElement>>(
this.objectSubscriptions = this.objectSubscriptions.concat(sub);
}
// remove subscripotions matching the filter
// remove subscriptions matching the filter
unsubscribe(filter: (sub: VMObjectMixinSubscription) => boolean) {
this.objectSubscriptions = this.objectSubscriptions.filter(
(sub) => !filter(sub),
);
}
@state() objectSignals: ComputedObjectSignals | null;
@state() objectSignals: ComputedObjectSignals | null = null;
@state() activeICId: number;
activeICId: Signal<number> = signal(null);
connectedCallback(): void {
const root = super.connectedCallback();
@@ -385,7 +384,7 @@ export const VMObjectMixin = <T extends Constructor<LitElement>>(
this._handleDevicesRemoved.bind(this),
);
});
this.updateDevice();
this.updateObject();
return root;
}
@@ -413,20 +412,20 @@ export const VMObjectMixin = <T extends Constructor<LitElement>>(
async _handleDeviceModified(e: CustomEvent) {
const id = e.detail;
const activeIcId = window.App.app.session.activeIC;
if (this.objectID === id) {
this.updateDevice();
if (this.objectID.peek() === id) {
this.updateObject();
} else if (
id === activeIcId &&
this.objectSubscriptions.includes("active-ic")
) {
this.updateDevice();
this.updateObject();
this.requestUpdate();
} else if (this.objectSubscriptions.includes("visible-devices")) {
const visibleDevices = await window.VM.vm.visibleDeviceIds(
this.objectID,
this.objectID.peek(),
);
if (visibleDevices.includes(id)) {
this.updateDevice();
this.updateObject();
this.requestUpdate();
}
}
@@ -435,8 +434,8 @@ export const VMObjectMixin = <T extends Constructor<LitElement>>(
async _handleDevicesModified(e: CustomEvent<number[]>) {
const activeIcId = window.App.app.session.activeIC;
const ids = e.detail;
if (ids.includes(this.objectID)) {
this.updateDevice();
if (ids.includes(this.objectID.peek())) {
this.updateObject();
if (this.objectSubscriptions.includes("visible-devices")) {
this.requestUpdate();
}
@@ -444,25 +443,25 @@ export const VMObjectMixin = <T extends Constructor<LitElement>>(
ids.includes(activeIcId) &&
this.objectSubscriptions.includes("active-ic")
) {
this.updateDevice();
this.updateObject();
this.requestUpdate();
} else if (this.objectSubscriptions.includes("visible-devices")) {
const visibleDevices = await window.VM.vm.visibleDeviceIds(
this.objectID,
this.objectID.peek(),
);
if (ids.some((id) => visibleDevices.includes(id))) {
this.updateDevice();
this.updateObject();
this.requestUpdate();
}
}
}
async _handleDeviceIdChange(e: CustomEvent<{ old: number; new: number }>) {
if (this.objectID === e.detail.old) {
this.objectID = e.detail.new;
if (this.objectID.peek() === e.detail.old) {
this.objectID.value = e.detail.new;
} else if (this.objectSubscriptions.includes("visible-devices")) {
const visibleDevices = await window.VM.vm.visibleDeviceIds(
this.objectID,
this.objectID.peek(),
);
if (
visibleDevices.some(
@@ -481,8 +480,9 @@ export const VMObjectMixin = <T extends Constructor<LitElement>>(
}
}
updateDevice() {
const newObjSignals = globalObjectSignalMap.get(this.objectID);
updateObject() {
this.activeICId.value = window.App.app.session.activeIC;
const newObjSignals = globalObjectSignalMap.get(this.objectID.peek());
if (newObjSignals !== this.objectSignals) {
this.objectSignals = newObjSignals
}
@@ -503,9 +503,9 @@ export const VMActiveICMixin = <T extends Constructor<LitElement>>(
superClass: T,
) => {
class VMActiveICMixinClass extends VMObjectMixin(superClass) {
constructor() {
super();
this.objectID = window.App.app.session.activeIC;
constructor(...args: any[]) {
super(...args);
this.objectID.value = window.App.app.session.activeIC;
}
connectedCallback(): void {
@@ -535,10 +535,10 @@ export const VMActiveICMixin = <T extends Constructor<LitElement>>(
_handleActiveIC(e: CustomEvent) {
const id = e.detail;
if (this.objectID !== id) {
this.objectID = id;
if (this.objectID.value !== id) {
this.objectID.value = id;
}
this.updateDevice();
this.updateObject();
}
}
@@ -569,7 +569,7 @@ export const VMTemplateDBMixin = <T extends Constructor<LitElement>>(
disconnectedCallback(): void {
window.VM.vm.removeEventListener(
"vm-device-db-loaded",
"vm-template-db-loaded",
this._handleDeviceDBLoad.bind(this),
);
}

View File

@@ -1,16 +1,28 @@
import { html, css } from "lit";
import { html, css, nothing } from "lit";
import { customElement, query } from "lit/decorators.js";
import { BaseElement, defaultCss } from "components";
import { VMActiveICMixin } from "virtualMachine/baseDevice";
import { ComputedObjectSignals, globalObjectSignalMap, VMActiveICMixin } from "virtualMachine/baseDevice";
import SlSelect from "@shoelace-style/shoelace/dist/components/select/select.js";
import { computed, Signal, watch } from "@lit-labs/preact-signals";
import { FrozenObjectFull } from "ic10emu_wasm";
@customElement("vm-ic-controls")
export class VMICControls extends VMActiveICMixin(BaseElement) {
circuitHolders: Signal<ComputedObjectSignals[]>;
constructor() {
super();
this.subscribe("ic", "active-ic")
this.subscribe("active-ic")
this.circuitHolders = computed(() => {
const ids = window.VM.vm.circuitHolderIds.value;
const circuitHolders = [];
for (const id of ids) {
circuitHolders.push(globalObjectSignalMap.get(id));
}
return circuitHolders;
});
}
static styles = [
@@ -64,8 +76,49 @@ export class VMICControls extends VMActiveICMixin(BaseElement) {
@query(".active-ic-select") activeICSelect: SlSelect;
forceSelectUpdate() {
if (this.activeICSelect != null) {
this.activeICSelect.handleValueChange();
}
}
protected render() {
const ics = Array.from(window.VM.vm.circuitHolders);
const icsOptions = computed(() => {
return this.circuitHolders.value.map((circuitHolder) => {
circuitHolder.prefabName.subscribe((_) => {this.forceSelectUpdate()});
circuitHolder.id.subscribe((_) => {this.forceSelectUpdate()});
circuitHolder.displayName.subscribe((_) => {this.forceSelectUpdate()});
const span = circuitHolder.name ? html`<span slot="suffix">${watch(circuitHolder.prefabName)}</span>` : nothing ;
return html`
<sl-option
prefabName=${watch(circuitHolder.prefabName)}
value=${watch(circuitHolder.id)}
>
${span}
Device:${watch(circuitHolder.id)} ${watch(circuitHolder.displayName)}
</sl-option>`
});
});
icsOptions.subscribe((_) => {this.forceSelectUpdate()});
const icErrors = computed(() => {
return this.objectSignals?.errors.value?.map(
(err) =>
typeof err === "object"
&& "ParseError" in err
? html`<div class="hstack">
<span>
Line: ${err.ParseError.line} -
${"ParseError" in err ? err.ParseError.start : "N/A"}:${err.ParseError.end}
</span>
<span class="ms-auto">${err.ParseError.msg}</span>
</div>`
: html`${JSON.stringify(err)}`,
) ?? nothing;
});
return html`
<sl-card class="card">
<div class="controls" slot="header">
@@ -116,57 +169,33 @@ export class VMICControls extends VMActiveICMixin(BaseElement) {
hoist
size="small"
placement="bottom"
value="${this.objectID}"
value="${watch(this.objectID)}"
@sl-change=${this._handleChangeActiveIC}
class="active-ic-select"
>
${ics.map(
([id, device], _index) =>
html`<sl-option
name=${device.obj_info.name}
prefabName=${device.obj_info.prefab}
value=${id}
>
${device.obj_info.name
? html`<span slot="suffix">${device.obj_info.prefab}</span>`
: ""}
Device:${id} ${device.obj_info.name ?? device.obj_info.prefab}
</sl-option>`,
)}
${watch(icsOptions)}
</sl-select>
</div>
</div>
<div class="stats">
<div class="hstack">
<span>Instruction Pointer</span>
<span class="ms-auto">${this.icIP}</span>
<span class="ms-auto">${this.objectSignals ? watch(this.objectSignals.icIP) : nothing}</span>
</div>
<sl-divider></sl-divider>
<div class="hstack">
<span>Last Run Operations Count</span>
<span class="ms-auto">${this.icOpCount}</span>
<span class="ms-auto">${this.objectSignals ? watch(this.objectSignals.icOpCount) : nothing}</span>
</div>
<sl-divider></sl-divider>
<div class="hstack">
<span>Last State</span>
<span class="ms-auto">${this.icState}</span>
<span class="ms-auto">${this.objectSignals ? watch(this.objectSignals.icState) : nothing}</span>
</div>
<sl-divider></sl-divider>
<div class="vstack">
<span>Errors</span>
${this.errors?.map(
(err) =>
typeof err === "object"
&& "ParseError" in err
? html`<div class="hstack">
<span>
Line: ${err.ParseError.line} -
${"ParseError" in err ? err.ParseError.start : "N/A"}:${err.ParseError.end}
</span>
<span class="ms-auto">${err.ParseError.msg}</span>
</div>`
: html`${JSON.stringify(err)}`,
)}
${watch(icErrors)}
</div>
</div>
</sl-card>
@@ -183,18 +212,6 @@ export class VMICControls extends VMActiveICMixin(BaseElement) {
window.VM.get().then((vm) => vm.reset());
}
updateIC(): void {
super.updateIC();
this.activeICSelect?.dispatchEvent(new Event("slotchange"));
// if (this.activeICSelect) {
// const val = this.activeICSelect.value;
// this.activeICSelect.value = "";
// this.activeICSelect.requestUpdate();
// this.activeICSelect.value = val;
// this.activeICSelect.
// }
}
_handleChangeActiveIC(e: CustomEvent) {
const select = e.target as SlSelect;
const icId = parseInt(select.value as string);

View File

@@ -122,7 +122,7 @@ export class VMDeviceCard extends VMTemplateDBMixin(
_handleDeviceDBLoad(e: CustomEvent<any>): void {
super._handleDeviceDBLoad(e);
this.updateDevice();
this.updateObject();
}
onImageErr(e: Event) {
@@ -131,24 +131,38 @@ export class VMDeviceCard extends VMTemplateDBMixin(
}
renderHeader(): HTMLTemplateResult {
const thisIsActiveIc = this.activeICId === this.objectID;
const badges: HTMLTemplateResult[] = [];
if (thisIsActiveIc) {
badges.push(html`<sl-badge variant="primary" pill pulse>db</sl-badge>`);
}
const activeIc = globalObjectSignalMap.get(this.activeICId);
const thisIsActiveIc = computed(() => {
return this.activeICId.value === this.objectID.value;
});
const numPins = activeIc.numPins.value;
const pins = new Array(numPins)
.fill(true)
.map((_, index) => this.objectSignals.pins.value.get(index));
pins.forEach((id, index) => {
if (this.objectID == id) {
badges.push(
html`<sl-badge variant="success" pill>d${index}</sl-badge>`,
);
const activeIc = computed(() => {
return globalObjectSignalMap.get(this.activeICId.value);
});
const numPins = computed(() => {
return activeIc.value.numPins.value;
});
const pins = computed(() => {
return new Array(numPins.value)
.fill(true)
.map((_, index) => this.objectSignals.pins.value.get(index));
});
const badgesHtml = computed(() => {
const badges: HTMLTemplateResult[] = [];
if (thisIsActiveIc.value) {
badges.push(html`<sl-badge variant="primary" pill pulse>db</sl-badge>`);
}
}, this);
pins.value.forEach((id, index) => {
if (this.objectID.value == id) {
badges.push(
html`<sl-badge variant="success" pill>d${index}</sl-badge>`,
);
}
}, this);
return badges
});
return html`
<sl-tooltip content="${watch(this.objectSignals.prefabName)}">
<img
@@ -159,21 +173,21 @@ export class VMDeviceCard extends VMTemplateDBMixin(
</sl-tooltip>
<div class="header-name">
<sl-input
id="vmDeviceCard${this.objectID}Id"
id="vmDeviceCard${watch(this.objectID)}Id"
class="device-id me-1"
size="small"
pill
value=${this.objectID.toString()}
value=${watch(this.objectID)}
@sl-change=${this._handleChangeID}
>
<span slot="prefix">Id</span>
<sl-copy-button
slot="suffix"
.value=${this.objectID.toString()}
.value=${watch(this.objectID)}
></sl-copy-button>
</sl-input>
<sl-input
id="vmDeviceCard${this.objectID}Name"
id="vmDeviceCard${watch(this.objectID)}Name"
class="device-name me-1"
size="small"
pill
@@ -184,11 +198,11 @@ export class VMDeviceCard extends VMTemplateDBMixin(
<span slot="prefix">Name</span>
<sl-copy-button
slot="suffix"
from="vmDeviceCard${this.objectID}Name.value"
from="vmDeviceCard${watch(this.objectID)}Name.value"
></sl-copy-button>
</sl-input>
<sl-input
id="vmDeviceCard${this.objectID}NameHash"
id="vmDeviceCard${watch(this.objectID)}NameHash"
size="small"
pill
class="device-name-hash me-1"
@@ -201,7 +215,7 @@ export class VMDeviceCard extends VMTemplateDBMixin(
from="vmDeviceCard${this.objectID}NameHash.value"
></sl-copy-button>
</sl-input>
${badges.map((badge) => badge)}
${watch(badgesHtml)}
</div>
<div class="ms-auto mt-auto mb-auto me-2">
<sl-tooltip
@@ -256,7 +270,7 @@ export class VMDeviceCard extends VMTemplateDBMixin(
}
renderNetworks() {
const vmNetworks = window.VM.vm.networks;
const vmNetworks = window.VM.vm.networkIds;
const networks = this.objectSignals.connections.value.map((connection, index, _conns) => {
const conn =
typeof connection === "object" && "CableNetwork" in connection
@@ -273,7 +287,7 @@ export class VMDeviceCard extends VMTemplateDBMixin(
@sl-change=${this._handleChangeConnection}
>
<span slot="prefix">Connection:${index} </span>
${vmNetworks.map(
${vmNetworks.value.map(
(net) =>
html`<sl-option value=${net.toString()}
>Network ${net}</sl-option
@@ -421,7 +435,7 @@ export class VMDeviceCard extends VMTemplateDBMixin(
const val = parseIntWithHexOrBinary(input.value);
if (!isNaN(val)) {
window.VM.get().then((vm) => {
if (!vm.changeObjectID(this.objectID, val)) {
if (!vm.changeObjectID(this.objectID.peek(), val)) {
input.value = this.objectID.toString();
}
});
@@ -434,10 +448,10 @@ export class VMDeviceCard extends VMTemplateDBMixin(
const input = e.target as SlInput;
const name = input.value.length === 0 ? undefined : input.value;
window.VM.get().then((vm) => {
if (!vm.setObjectName(this.objectID, name)) {
if (!vm.setObjectName(this.objectID.peek(), name)) {
input.value = this.objectSignals.name.value;
}
this.updateDevice();
this.updateObject();
});
}
_handleDeviceRemoveButton(_e: Event) {
@@ -446,7 +460,7 @@ export class VMDeviceCard extends VMTemplateDBMixin(
_removeDialogRemove() {
this.removeDialog.hide();
window.VM.get().then((vm) => vm.removeDevice(this.objectID));
window.VM.get().then((vm) => vm.removeDevice(this.objectID.peek()));
}
_handleChangeConnection(e: CustomEvent) {
@@ -454,8 +468,8 @@ export class VMDeviceCard extends VMTemplateDBMixin(
const conn = parseInt(select.getAttribute("key")!);
const val = select.value ? parseInt(select.value as string) : undefined;
window.VM.get().then((vm) =>
vm.setDeviceConnection(this.objectID, conn, val),
vm.setDeviceConnection(this.objectID.peek(), conn, val),
);
this.updateDevice();
this.updateObject();
}
}

View File

@@ -12,7 +12,7 @@ export function connectionFromConnectionInfo(conn: ConnectionInfo): Connection {
) {
connection = {
CableNetwork: {
net: window.VM.vm.defaultNetwork,
net: window.VM.vm.defaultNetwork.peek(),
typ: conn.typ as CableConnectionType,
role: conn.role,
},

View File

@@ -10,10 +10,15 @@ import { default as uFuzzy } from "@leeoniya/ufuzzy";
import { VMSlotAddDialog } from "./slotAddDialog";
import "./addDevice"
import { SlotModifyEvent } from "./slot";
import { computed, Signal, signal, SignalWatcher, watch } from "@lit-labs/preact-signals";
import { globalObjectSignalMap } from "virtualMachine/baseDevice";
import { ObjectID } from "ic10emu_wasm";
@customElement("vm-device-list")
export class VMDeviceList extends BaseElement {
@state() devices: number[];
export class VMDeviceList extends SignalWatcher(BaseElement) {
devices: Signal<ObjectID[]>;
private _filter: Signal<string> = signal("");
private _filteredDeviceIds: Signal<number[] | undefined>;
static styles = [
...defaultCss,
@@ -43,17 +48,50 @@ export class VMDeviceList extends BaseElement {
constructor() {
super();
this.devices = [...window.VM.vm.objectIds];
}
this.devices = computed(() => {
const objIds = window.VM.vm.objectIds.value;
const deviceIds = [];
for (const id of objIds) {
const obj = window.VM.vm.objects.get(id);
const info = obj.value.obj_info;
if (!(info.parent_slot != null || info.root_parent_human != null)) {
deviceIds.push(id)
}
}
deviceIds.sort();
return deviceIds;
});
this._filteredDeviceIds = computed(() => {
if (this._filter.value) {
const datapoints: [string, number][] = [];
for (const device_id of this.devices.value) {
const device = globalObjectSignalMap.get(device_id);
if (device) {
const name = device.name.peek();
const id = device.id.peek();
const prefab = device.prefabName.peek();
if (name != null) {
datapoints.push([name, id]);
}
if (prefab != null) {
datapoints.push([prefab, id]);
}
}
}
const haystack: string[] = datapoints.map((data) => data[0]);
const uf = new uFuzzy({});
const [_idxs, info, order] = uf.search(haystack, this._filter.value, 0, 1e3);
connectedCallback(): void {
super.connectedCallback();
window.VM.get().then((vm) =>
vm.addEventListener(
"vm-devices-update",
this._handleDevicesUpdate.bind(this),
),
);
const filtered = order?.map((infoIdx) => datapoints[info.idx[infoIdx]]);
const deviceIds: number[] =
filtered
?.map((data) => data[1])
?.filter((val, index, arr) => arr.indexOf(val) === index) ?? [];
return deviceIds;
} else {
return Array.from(this.devices.value);
}
});
}
protected firstUpdated(_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void {
@@ -63,27 +101,20 @@ export class VMDeviceList extends BaseElement {
);
}
_handleDevicesUpdate(e: CustomEvent) {
const ids = e.detail;
if (!structuralEqual(this.devices, ids)) {
this.devices = ids;
this.devices.sort();
}
}
protected render(): HTMLTemplateResult {
const deviceCards = repeat(
this.filteredDeviceIds,
this.filteredDeviceIds.value,
(id) => id,
(id) =>
html`<vm-device-card .deviceID=${id} class="device-list-card">
</vm-device-card>`,
);
const numDevices = computed(() => this.devices.value.length);
const result = html`
<div class="header">
<span>
Devices:
<sl-badge variant="neutral" pill>${this.devices.length}</sl-badge>
<sl-badge variant="neutral" pill>${watch(numDevices)}</sl-badge>
</span>
<sl-input
class="device-filter-input"
@@ -118,18 +149,14 @@ export class VMDeviceList extends BaseElement {
}
}
private _filteredDeviceIds: number[] | undefined;
private _filter: string = "";
@query(".device-filter-input") filterInput: SlInput;
get filter() {
return this._filter;
return this._filter.value;
}
@state()
set filter(val: string) {
this._filter = val;
this.performSearch();
this._filter.value = val;
}
private filterTimeout: number | undefined;
@@ -144,34 +171,5 @@ export class VMDeviceList extends BaseElement {
that.filterTimeout = undefined;
}, 500);
}
performSearch() {
if (this._filter) {
const datapoints: [string, number][] = [];
for (const device_id of this.devices) {
const device = window.VM.vm.objects.get(device_id);
if (device) {
if (typeof device.obj_info.name !== "undefined") {
datapoints.push([device.obj_info.name, device.obj_info.id]);
}
if (typeof device.obj_info.prefab !== "undefined") {
datapoints.push([device.obj_info.prefab, device.obj_info.id]);
}
}
}
const haystack: string[] = datapoints.map((data) => data[0]);
const uf = new uFuzzy({});
const [_idxs, info, order] = uf.search(haystack, this._filter, 0, 1e3);
const filtered = order?.map((infoIdx) => datapoints[info.idx[infoIdx]]);
const deviceIds: number[] =
filtered
?.map((data) => data[1])
?.filter((val, index, arr) => arr.indexOf(val) === index) ?? [];
this._filteredDeviceIds = deviceIds;
} else {
this._filteredDeviceIds = undefined;
}
}
}

View File

@@ -53,10 +53,10 @@ export class VMDeviceSlot extends VMObjectMixin(VMTemplateDBMixin(BaseElement))
const field = input.getAttribute("key")! as LogicType;
const val = parseNumber(input.value);
window.VM.get().then((vm) => {
if (!vm.setObjectField(this.objectID, field, val, true)) {
if (!vm.setObjectField(this.objectID.peek(), field, val, true)) {
input.value = this.objectSignals.logicFields.value.get(field).value.toString();
}
this.updateDevice();
this.updateObject();
});
}
}

View File

@@ -63,7 +63,7 @@ export class VMDevicePins extends VMObjectMixin(VMTemplateDBMixin(BaseElement))
const select = e.target as SlSelect;
const pin = parseInt(select.getAttribute("key")!);
const val = select.value ? parseInt(select.value as string) : undefined;
window.VM.get().then((vm) => vm.setDevicePin(this.objectID, pin, val));
this.updateDevice();
window.VM.get().then((vm) => vm.setDevicePin(this.objectID.peek(), pin, val));
this.updateObject();
}
}

View File

@@ -268,7 +268,7 @@ export class VMDeviceSlot extends VMObjectMixin(VMTemplateDBMixin(SignalWatcher(
}
_handleSlotOccupantRemove() {
window.VM.vm.removeSlotOccupant(this.objectID, this.slotIndex);
window.VM.vm.removeSlotOccupant(this.objectID.peek(), this.slotIndex);
}
_handleSlotClick(_e: Event) {
@@ -276,7 +276,7 @@ export class VMDeviceSlot extends VMObjectMixin(VMTemplateDBMixin(SignalWatcher(
new CustomEvent<SlotModifyEvent>("device-modify-slot", {
bubbles: true,
composed: true,
detail: { deviceID: this.objectID, slotIndex: this.slotIndex },
detail: { deviceID: this.objectID.peek(), slotIndex: this.slotIndex },
}),
);
}
@@ -293,7 +293,7 @@ export class VMDeviceSlot extends VMObjectMixin(VMTemplateDBMixin(SignalWatcher(
);
if (
!window.VM.vm.setObjectSlotField(
this.objectID,
this.objectID.peek(),
this.slotIndex,
"Quantity",
val,
@@ -365,7 +365,7 @@ export class VMDeviceSlot extends VMObjectMixin(VMTemplateDBMixin(SignalWatcher(
}
window.VM.get().then((vm) => {
if (
!vm.setObjectSlotField(this.objectID, this.slotIndex, field, val, true)
!vm.setObjectSlotField(this.objectID.peek(), this.slotIndex, field, val, true)
) {
input.value = (
this.slotSignal.value.logicFields ??
@@ -374,7 +374,7 @@ export class VMDeviceSlot extends VMObjectMixin(VMTemplateDBMixin(SignalWatcher(
.get(field)
.toString();
}
this.updateDevice();
this.updateObject();
});
}

View File

@@ -1,7 +1,7 @@
import { html, css } from "lit";
import { html, css, nothing } from "lit";
import { customElement, property, query, state } from "lit/decorators.js";
import { BaseElement, defaultCss } from "components";
import { VMTemplateDBMixin } from "virtualMachine/baseDevice";
import { ComputedObjectSignals, globalObjectSignalMap, VMTemplateDBMixin } from "virtualMachine/baseDevice";
import SlInput from "@shoelace-style/shoelace/dist/components/input/input.component.js";
import SlDialog from "@shoelace-style/shoelace/dist/components/dialog/dialog.component.js";
import { VMDeviceCard } from "./card";
@@ -15,6 +15,8 @@ import {
ObjectInfo,
ObjectTemplate,
} from "ic10emu_wasm";
import { computed, ReadonlySignal, signal, Signal, watch } from "@lit-labs/preact-signals";
import { repeat } from "lit/directives/repeat.js";
type SlotableItemTemplate = Extract<ObjectTemplate, { item: ItemInfo }>;
@@ -38,30 +40,33 @@ export class VMSlotAddDialog extends VMTemplateDBMixin(BaseElement) {
`,
];
private _items: Map<string, SlotableItemTemplate> = new Map();
private _filteredItems: SlotableItemTemplate[];
private _datapoints: [string, string][] = [];
private _haystack: string[] = [];
private _items: Signal<Record<string, SlotableItemTemplate>> = signal({});
private _filteredItems: ReadonlySignal<SlotableItemTemplate[]>;
private _datapoints: ReadonlySignal<[string, string][]>;
private _haystack: ReadonlySignal<string[]>;
private _filter: string = "";
private _filter: Signal<string> = signal("");
get filter() {
return this._filter;
return this._filter.peek();
}
@state()
set filter(val: string) {
this._filter = val;
this.performSearch();
this._filter.value = val;
}
private _searchResults: {
private _searchResults: ReadonlySignal<{
entry: SlotableItemTemplate;
haystackEntry: string;
ranges: number[];
}[] = [];
}[]>;
constructor() {
super();
this.setupSearch();
}
postDBSetUpdate(): void {
this._items = new Map(
this._items.value = Object.fromEntries(
Array.from(Object.values(this.templateDB)).flatMap((template) => {
if ("item" in template) {
return [[template.prefab.prefab_name, template]] as [
@@ -73,77 +78,84 @@ export class VMSlotAddDialog extends VMTemplateDBMixin(BaseElement) {
}
}),
);
this.setupSearch();
this.performSearch();
}
setupSearch() {
let filteredItems = Array.from(this._items.values());
if (
typeof this.objectID !== "undefined" &&
typeof this.slotIndex !== "undefined"
) {
const obj = window.VM.vm.objects.get(this.objectID);
const template = obj.template;
const slot = "slots" in template ? template.slots[this.slotIndex] : null;
const typ = slot.typ;
const filteredItems = computed(() => {
let filtered = Array.from(Object.values(this._items.value));
const obj = globalObjectSignalMap.get(this.objectID.value ?? null);
if (obj != null) {
const template = obj.template;
const slot = "slots" in template.value ? template.value.slots[this.slotIndex.value] : null;
const typ = slot.typ;
if (typeof typ === "string" && typ !== "None") {
filteredItems = Array.from(this._items.values()).filter(
(item) => item.item.slot_class === typ,
if (typeof typ === "string" && typ !== "None") {
filtered = Array.from(Object.values(this._items.value)).filter(
(item) => item.item.slot_class === typ,
);
}
}
return filtered;
});
this._filteredItems = filteredItems;
const datapoints = computed(() => {
const datapoints: [string, string][] = [];
for (const entry of this._filteredItems.value) {
datapoints.push(
[entry.prefab.name, entry.prefab.prefab_name],
[entry.prefab.prefab_name, entry.prefab.prefab_name],
[entry.prefab.desc, entry.prefab.prefab_name],
);
}
}
this._filteredItems = filteredItems;
const datapoints: [string, string][] = [];
for (const entry of this._filteredItems) {
datapoints.push(
[entry.prefab.name, entry.prefab.prefab_name],
[entry.prefab.prefab_name, entry.prefab.prefab_name],
[entry.prefab.desc, entry.prefab.prefab_name],
);
}
const haystack: string[] = datapoints.map((data) => data[0]);
return datapoints;
});
this._datapoints = datapoints;
const haystack: Signal<string[]> = computed(() => {
return datapoints.value.map((data) => data[0]);
});
this._haystack = haystack;
}
performSearch() {
if (this._filter) {
const uf = new uFuzzy({});
const [_idxs, info, order] = uf.search(
this._haystack,
this._filter,
0,
1e3,
);
const searchResults = computed(() => {
let results;
if (this._filter.value) {
const uf = new uFuzzy({});
const [_idxs, info, order] = uf.search(
this._haystack.value,
this._filter.value,
0,
1e3,
);
const filtered =
order?.map((infoIdx) => ({
name: this._datapoints[info.idx[infoIdx]][1],
haystackEntry: this._haystack[info.idx[infoIdx]],
ranges: info.ranges[infoIdx],
})) ?? [];
const filtered =
order?.map((infoIdx) => ({
name: this._datapoints.value[info.idx[infoIdx]][1],
haystackEntry: this._haystack.value[info.idx[infoIdx]],
ranges: info.ranges[infoIdx],
})) ?? [];
const uniqueNames = new Set(filtered.map((obj) => obj.name));
const unique = [...uniqueNames].map((result) => {
return filtered.find((obj) => obj.name === result);
});
const uniqueNames = new Set(filtered.map((obj) => obj.name));
const unique = [...uniqueNames].map((result) => {
return filtered.find((obj) => obj.name === result);
});
this._searchResults = unique.map(({ name, haystackEntry, ranges }) => ({
entry: this._items.get(name)!,
haystackEntry,
ranges,
}));
} else {
// return everything
this._searchResults = [...this._filteredItems].map((st) => ({
entry: st,
haystackEntry: st.prefab.prefab_name,
ranges: [],
}));
}
results = unique.map(({ name, haystackEntry, ranges }) => ({
entry: this._items.value[name]!,
haystackEntry,
ranges,
}));
} else {
// return everything
results = [...this._filteredItems.value].map((st) => ({
entry: st,
haystackEntry: st.prefab.prefab_name,
ranges: [],
}));
}
return results;
});
this._searchResults = searchResults;
}
renderSearchResults() {
@@ -156,10 +168,13 @@ export class VMSlotAddDialog extends VMTemplateDBMixin(BaseElement) {
None
</div>
`;
return html`
<div class="mt-2 max-h-48 overflow-y-auto w-full">
${enableNone ? none : ""}
${this._searchResults.map((result) => {
const resultsHtml = computed(() => {
return repeat(
this._searchResults.value,
(result) => {
return result.entry.prefab.prefab_hash;
},
(result) => {
const imgSrc = `img/stationpedia/${result.entry.prefab.prefab_name}.png`;
const img = html`
<img
@@ -178,22 +193,28 @@ export class VMSlotAddDialog extends VMTemplateDBMixin(BaseElement) {
<div>${result.entry.prefab.name}</div>
</div>
`;
})}
}
);
});
return html`
<div class="mt-2 max-h-48 overflow-y-auto w-full">
${enableNone ? none : ""}
${watch(resultsHtml)}
</div>
`;
}
_handleClickNone() {
window.VM.vm.removeSlotOccupant(this.objectID, this.slotIndex);
window.VM.vm.removeSlotOccupant(this.objectID.peek(), this.slotIndex.peek());
this.hide();
}
_handleClickItem(e: Event) {
const div = e.currentTarget as HTMLDivElement;
const key = parseInt(div.getAttribute("key"));
const entry = this.templateDB[key] as SlotableItemTemplate;
const obj = window.VM.vm.objects.get(this.objectID);
const dbTemplate = obj.template;
const entry = this.templateDB.get(key) as SlotableItemTemplate;
const obj = window.VM.vm.objects.get(this.objectID.peek());
const dbTemplate = obj.peek().template;
console.log("using entry", dbTemplate);
const template: FrozenObject = {
@@ -203,7 +224,7 @@ export class VMSlotAddDialog extends VMTemplateDBMixin(BaseElement) {
database_template: true,
template: undefined,
};
window.VM.vm.setSlotOccupant(this.objectID, this.slotIndex, template, 1);
window.VM.vm.setSlotOccupant(this.objectID.peek(), this.slotIndex.peek(), template, 1);
this.hide();
}
@@ -211,12 +232,22 @@ export class VMSlotAddDialog extends VMTemplateDBMixin(BaseElement) {
@query(".device-search-input") searchInput: SlInput;
render() {
const device = window.VM.vm.objects.get(this.objectID);
const name = device?.obj_info.name ?? device?.obj_info.prefab ?? "";
const id = this.objectID ?? 0;
const device = computed(() => {
return globalObjectSignalMap.get(this.objectID.value) ?? null;
});
const name = computed(() => {
return device.value?.displayName.value ?? nothing;
});
const id = computed(() => this.objectID.value ?? 0);
const resultsHtml = html`
<div class="flex flex-row overflow-x-auto">
${this.renderSearchResults()}
</div>
`;
return html`
<sl-dialog
label="Edit device ${id} : ${name} Slot ${this.slotIndex}"
label="Edit device ${watch(id)} : ${watch(name)} Slot ${watch(this.slotIndex)}"
class="slot-add-dialog"
@sl-hide=${this._handleDialogHide}
>
@@ -230,16 +261,7 @@ export class VMSlotAddDialog extends VMTemplateDBMixin(BaseElement) {
<span slot="prefix">Search Items</span>
<sl-icon slot="suffix" name="search"></sl-icon>
</sl-input>
${when(
typeof this.objectID !== "undefined" &&
typeof this.slotIndex !== "undefined",
() => html`
<div class="flex flex-row overflow-x-auto">
${this.renderSearchResults()}
</div>
`,
() => html``,
)}
${resultsHtml}
</sl-dialog>
`;
}
@@ -262,14 +284,12 @@ export class VMSlotAddDialog extends VMTemplateDBMixin(BaseElement) {
this.slotIndex = undefined;
}
@state() private objectID: number;
@state() private slotIndex: number;
private objectID: Signal<number> = signal(null);
private slotIndex: Signal<number> = signal(0);
show(objectID: number, slotIndex: number) {
this.objectID = objectID;
this.slotIndex = slotIndex;
this.setupSearch();
this.performSearch();
this.objectID.value = objectID;
this.slotIndex.value = slotIndex;
this.dialog.show();
this.searchInput.select();
}

View File

@@ -24,7 +24,9 @@ import { crc32, displayNumber, parseNumber } from "utils";
import SlInput from "@shoelace-style/shoelace/dist/components/input/input.component.js";
import SlSelect from "@shoelace-style/shoelace/dist/components/select/select.component.js";
import { VMDeviceCard } from "./card";
import { VMTemplateDBMixin } from "virtualMachine/baseDevice";
import { globalObjectSignalMap, VMTemplateDBMixin } from "virtualMachine/baseDevice";
import { computed, Signal, watch } from "@lit-labs/preact-signals";
import { createRef, ref, Ref } from "lit/directives/ref.js";
export interface SlotTemplate {
typ: Class;
@@ -74,13 +76,13 @@ export class VmObjectTemplate extends VMTemplateDBMixin(BaseElement) {
`,
];
@state() fields: Map<LogicType, number>;
@state() slots: SlotTemplate[];
@state() pins: (ObjectID | undefined)[];
@state() template: FrozenObject;
@state() objectId: number | undefined;
@state() objectName: string | undefined;
@state() connections: Connection[];
fields: Signal<Record<LogicType, number>>;
slots: Signal<SlotTemplate[]>;
pins: Signal<(ObjectID | undefined)[]>;
template: Signal<FrozenObject>;
objectId: Signal<number | undefined>;
objectName: Signal<string | undefined>;
connections: Signal<Connection[]>;
constructor() {
super();
@@ -105,13 +107,13 @@ export class VmObjectTemplate extends VMTemplateDBMixin(BaseElement) {
}
get dbTemplate(): ObjectTemplate {
return this.templateDB[this._prefabHash];
return this.templateDB.get(this._prefabHash);
}
setupState() {
const dbTemplate = this.dbTemplate;
this.fields = new Map(
this.fields.value = Object.fromEntries(
(
Array.from(
"logic" in dbTemplate
@@ -123,9 +125,9 @@ export class VmObjectTemplate extends VMTemplateDBMixin(BaseElement) {
lt === "PrefabHash" ? this.dbTemplate.prefab.prefab_hash : 0.0;
return [lt, value];
}),
);
) as Record<LogicType, number>;
this.slots = (
this.slots.value = (
("slots" in dbTemplate ? dbTemplate.slots ?? [] : []) as SlotInfo[]
).map(
(slot, _index) =>
@@ -152,17 +154,18 @@ export class VmObjectTemplate extends VMTemplateDBMixin(BaseElement) {
}
});
this.connections = connections.map((conn) => conn[1]);
this.connections.value = connections.map((conn) => conn[1]);
const numPins =
"device" in dbTemplate ? dbTemplate.device.device_pins_length : 0;
this.pins = new Array(numPins).fill(undefined);
this.pins.value = new Array(numPins).fill(undefined);
}
renderFields(): HTMLTemplateResult {
const fields = Object.entries(this.fields);
return html`
${fields.map(([name, field], _index, _fields) => {
return html`
return html`
<sl-input
key="${name}"
value="${displayNumber(field.value)}"
@@ -174,7 +177,7 @@ export class VmObjectTemplate extends VMTemplateDBMixin(BaseElement) {
<span slot="suffix">${field.field_type}</span>
</sl-input>
`;
})}
})}
`;
}
@@ -182,13 +185,22 @@ export class VmObjectTemplate extends VMTemplateDBMixin(BaseElement) {
const input = e.target as SlInput;
const field = input.getAttribute("key")! as LogicType;
const val = parseNumber(input.value);
this.fields.set(field, val);
this.fields.value = { ...this.fields.value, [field]: val};
if (field === "ReferenceId" && val !== 0) {
this.objectId = val;
this.objectId.value = val;
}
this.requestUpdate();
}
forceSelectUpdate(...slSelects: Ref<SlSelect>[]) {
for (const slSelect of slSelects) {
if (slSelect.value != null && "handleValueChange" in slSelect.value) {
slSelect.value.handleValueChange();
}
}
}
private networksSelectRef: Ref<SlSelect> = createRef();
renderSlot(slot: Slot, slotIndex: number): HTMLTemplateResult {
return html`<sl-card class="slot-card"> </sl-card>`;
}
@@ -203,34 +215,37 @@ export class VmObjectTemplate extends VMTemplateDBMixin(BaseElement) {
renderNetworks() {
const vm = window.VM.vm;
const vmNetworks = vm.networks;
const connections = this.connections;
const vmNetworks = computed(() => {
return vm.networkIds.value.map((net) => html`<sl-option value=${net}>Network ${net}</sl-option>`);
});
const connections = computed(() => {
this.connections.value.map((connection, index, _conns) => {
const conn =
typeof connection === "object" && "CableNetwork" in connection
? connection.CableNetwork
: null;
return html`
<sl-select
hoist
placement="top"
clearable
key=${index}
value=${conn?.net}
?disabled=${conn === null}
@sl-change=${this._handleChangeConnection}
${ref(this.networksSelectRef)}
>
<span slot="prefix">Connection:${index} </span>
${watch(vmNetworks)}
<span slot="prefix"> ${conn?.typ} </span>
</sl-select>
`;
});
});
vmNetworks.subscribe((_) => { this.forceSelectUpdate(this.networksSelectRef)})
return html`
<div class="networks">
${connections.map((connection, index, _conns) => {
const conn =
typeof connection === "object" && "CableNetwork" in connection
? connection.CableNetwork
: null;
return html`
<sl-select
hoist
placement="top"
clearable
key=${index}
value=${conn?.net}
?disabled=${conn === null}
@sl-change=${this._handleChangeConnection}
>
<span slot="prefix">Connection:${index} </span>
${vmNetworks.map(
(net) =>
html`<sl-option value=${net}>Network ${net}</sl-option>`,
)}
<span slot="prefix"> ${conn?.typ} </span>
</sl-select>
`;
})}
${watch(connections)}
</div>
`;
}
@@ -239,53 +254,89 @@ export class VmObjectTemplate extends VMTemplateDBMixin(BaseElement) {
const select = e.target as SlSelect;
const conn = parseInt(select.getAttribute("key")!);
const val = select.value ? parseInt(select.value as string) : undefined;
(this.connections[conn] as ConnectionCableNetwork).CableNetwork.net = val;
this.requestUpdate();
const copy = [...this.connections.value];
(copy[conn] as ConnectionCableNetwork).CableNetwork.net = val;
this.connections.value = copy;
}
private _pinsSelectRefMap: Map<number, Ref<SlSelect>> = new Map();
getPinRef(index: number) : Ref<SlSelect> {
if (!this._pinsSelectRefMap.has(index)) {
this._pinsSelectRefMap.set(index, createRef());
}
return this._pinsSelectRefMap.get(index);
}
forcePinSelectUpdate() {
this.forceSelectUpdate(...this._pinsSelectRefMap.values());
}
renderPins(): HTMLTemplateResult {
const networks = this.connections.flatMap((connection, index) => {
return typeof connection === "object" && "CableNetwork" in connection
? [connection.CableNetwork.net]
: [];
const networks = computed(() => {
return this.connections.value.flatMap((connection, index) => {
return typeof connection === "object" && "CableNetwork" in connection
? [connection.CableNetwork.net]
: [];
});
});
const visibleDeviceIds = [
const visibleDeviceIds = computed(() => {
return [
...new Set(
networks.flatMap((net) => window.VM.vm.networkDataDevices(net)),
networks.value.flatMap((net) => window.VM.vm.networkDataDevicesSignal(net).value),
),
];
const visibleDevices = visibleDeviceIds.map((id) =>
window.VM.vm.objects.get(id),
);
const pinsHtml = this.pins?.map(
(pin, index) =>
html` <sl-select
hoist
placement="top"
clearable
key=${index}
.value=${pin}
@sl-change=${this._handleChangePin}
>
<span slot="prefix">d${index}</span>
${visibleDevices.map(
(device, _index) => html`
<sl-option value=${device.obj_info.id.toString()}>
Device ${device.obj_info.id} :
${device.obj_info.name ?? device.obj_info.prefab}
</sl-option>
`,
)}
</sl-select>`,
);
return html`<div class="pins">${pinsHtml}</div>`;
});
const visibleDevices = computed(() => {
return visibleDeviceIds.value.map((id) =>
globalObjectSignalMap.get(id),
);
});
const visibleDevicesHtml = computed(() => {
return visibleDevices.value.map(
(device, _index) => {
device.id.subscribe((_) => { this.forcePinSelectUpdate(); });
device.displayName.subscribe((_) => { this.forcePinSelectUpdate(); });
return html`
<sl-option value=${watch(device.id)}>
Device ${watch(device.id)} :
${watch(device.displayName)}
</sl-option>
`
}
)
});
visibleDeviceIds.subscribe((_) => { this.forcePinSelectUpdate(); });
const pinsHtml = computed(() => {
this.pins.value.map(
(pin, index) => {
const pinRef = this.getPinRef(index)
return html` <sl-select
hoist
placement="top"
clearable
key=${index}
.value=${pin}
@sl-change=${this._handleChangePin}
${ref(pinRef)}
>
<span slot="prefix">d${index}</span>
${watch(visibleDevicesHtml)}
</sl-select>`
}
);
});
return html`<div class="pins">${watch(pinsHtml)}</div>`;
}
_handleChangePin(e: CustomEvent) {
const select = e.target as SlSelect;
const pin = parseInt(select.getAttribute("key")!);
const val = select.value ? parseInt(select.value as string) : undefined;
this.pins[pin] = val;
const val = select.value ? parseInt(select.value as string) : null;
const copy = [...this.pins.value];
copy[pin] = val;
this.pins.value = copy;
}
render() {
@@ -339,13 +390,13 @@ export class VmObjectTemplate extends VMTemplateDBMixin(BaseElement) {
);
// Typescript doesn't like fileds defined as `X | undefined` not being present, hence cast
const objInfo: ObjectInfo = {
id: this.objectId,
name: this.objectName,
id: this.objectId.value,
name: this.objectName.value,
prefab: this.prefabName,
} as ObjectInfo;
if (this.slots.length > 0) {
const slotOccupants: [FrozenObject, number][] = this.slots.flatMap(
if (this.slots.value.length > 0) {
const slotOccupants: [FrozenObject, number][] = this.slots.value.flatMap(
(slot, index) => {
return typeof slot.occupant !== "undefined"
? [[slot.occupant, index]]
@@ -367,8 +418,8 @@ export class VmObjectTemplate extends VMTemplateDBMixin(BaseElement) {
}),
);
}
objInfo.slots = Object.fromEntries(
this.slots.flatMap((slot, index) => {
objInfo.slots = new Map(
this.slots.value.flatMap((slot, index) => {
const occupantId = slotOccupantIdsMap.get(index);
if (typeof occupantId !== "undefined") {
const info: SlotOccupantInfo = {
@@ -383,9 +434,9 @@ export class VmObjectTemplate extends VMTemplateDBMixin(BaseElement) {
);
}
if (this.connections.length > 0) {
objInfo.connections = Object.fromEntries(
this.connections.flatMap((conn, index) => {
if (this.connections.value.length > 0) {
objInfo.connections = new Map(
this.connections.value.flatMap((conn, index) => {
return typeof conn === "object" &&
"CableNetwork" in conn &&
typeof conn.CableNetwork.net !== "undefined"
@@ -395,11 +446,8 @@ export class VmObjectTemplate extends VMTemplateDBMixin(BaseElement) {
);
}
if (this.fields.size > 0) {
objInfo.logic_values = Object.fromEntries(this.fields) as Record<
LogicType,
number
>;
if (Object.keys(this.fields.value).length > 0) {
objInfo.logic_values = new Map(Object.entries(this.fields.value) as [LogicType, number][]);
}
const template: FrozenObject = {

View File

@@ -14,7 +14,7 @@ import * as Comlink from "comlink";
import "./baseDevice";
import "./device";
import { App } from "app";
import { structuralEqual, TypedEventTarget } from "utils";
import { comlinkSpecialJsonTransferHandler, structuralEqual, TypedEventTarget } from "utils";
export interface ToastMessage {
variant: "warning" | "danger" | "success" | "primary" | "neutral";
icon: string;
@@ -26,8 +26,10 @@ import {
signal,
computed,
effect,
batch,
} from '@lit-labs/preact-signals';
import type { Signal } from '@lit-labs/preact-signals';
import { getJsonContext } from "./jsonErrorUtils";
export interface VirtualMachineEventMap {
"vm-template-db-loaded": CustomEvent<TemplateDatabase>;
@@ -41,16 +43,23 @@ export interface VirtualMachineEventMap {
"vm-message": CustomEvent<ToastMessage>;
}
Comlink.transferHandlers.set("SpecialJson", comlinkSpecialJsonTransferHandler);
const jsonErrorRegex = /((invalid type: .*)|(missing field .*)) at line (?<errorLine>\d+) column (?<errorColumn>\d+)/;
class VirtualMachine extends TypedEventTarget<VirtualMachineEventMap>() {
ic10vm: Comlink.Remote<VMRef>;
templateDBPromise: Promise<TemplateDatabase>;
templateDB: TemplateDatabase;
private _vmState: Signal<FrozenVM>;
private _vmState: Signal<FrozenVM> = signal(null);
private _objects: Map<number, Signal<FrozenObjectFull>>;
private _objectIds: Signal<ObjectID[]>;
private _circuitHolders: Map<number, Signal<FrozenObjectFull>>;
private _circuitHolderIds: Signal<ObjectID[]>;
private _networks: Map<number, Signal<FrozenCableNetwork>>;
private _networkIds: Signal<ObjectID[]>;
private _default_network: Signal<number>;
private vm_worker: Worker;
@@ -62,15 +71,17 @@ class VirtualMachine extends TypedEventTarget<VirtualMachineEventMap>() {
this.app = app;
this._objects = new Map();
this._objectIds = signal([]);
this._circuitHolders = new Map();
this._circuitHolderIds = signal([]);
this._networks = new Map();
this._networkIds = signal([]);
this._networkDevicesSignals = new Map();
this.setupVM();
}
async setupVM() {
this.templateDBPromise = this.ic10vm.getTemplateDatabase();
this.templateDBPromise.then((db) => this.setupTemplateDatabase(db));
this.vm_worker = new Worker(new URL("./vmWorker.ts", import.meta.url));
const loaded = (w: Worker) =>
@@ -82,6 +93,9 @@ class VirtualMachine extends TypedEventTarget<VirtualMachineEventMap>() {
this._vmState.value = await this.ic10vm.saveVMState();
window.VM.set(this);
this.templateDBPromise = this.ic10vm.getTemplateDatabase();
this.templateDBPromise.then((db) => this.setupTemplateDatabase(db));
effect(() => {
this.updateObjects(this._vmState.value);
this.updateNetworks(this._vmState.value);
@@ -98,26 +112,24 @@ class VirtualMachine extends TypedEventTarget<VirtualMachineEventMap>() {
return this._objects;
}
get objectIds(): ObjectID[] {
const ids = Array.from(this._objects.keys());
ids.sort();
return ids;
get objectIds(): Signal<ObjectID[]> {
return this._objectIds;
}
get circuitHolders() {
return this._circuitHolders;
}
get circuitHolderIds(): ObjectID[] {
const ids = Array.from(this._circuitHolders.keys());
ids.sort();
return ids;
get circuitHolderIds(): Signal<ObjectID[]> {
return this._circuitHolderIds;
}
get networks(): ObjectID[] {
const ids = Array.from(this._networks.keys());
ids.sort();
return ids;
get networks() {
return this._networks;
}
get networkIds(): Signal<ObjectID[]> {
return this._networkIds;
}
get defaultNetwork() {
@@ -187,6 +199,9 @@ class VirtualMachine extends TypedEventTarget<VirtualMachineEventMap>() {
}
this.app.session.save();
}
networkIds.sort();
this._networkIds.value = networkIds;
}
async updateObjects(state: FrozenVM) {
@@ -260,6 +275,15 @@ class VirtualMachine extends TypedEventTarget<VirtualMachineEventMap>() {
}
this.app.session.save();
}
objectIds.sort();
const circuitHolderIds = Array.from(this._circuitHolders.keys());
circuitHolderIds.sort();
batch(() => {
this._objectIds.value = objectIds;
this._circuitHolderIds.value = circuitHolderIds;
});
}
async updateCode() {
@@ -332,23 +356,52 @@ class VirtualMachine extends TypedEventTarget<VirtualMachineEventMap>() {
}
}
handleVmError(err: Error) {
console.log("Error in Virtual Machine", err);
const message: ToastMessage = {
handleVmError(err: Error, args: { context?: string, jsonContext?: string, trace?: boolean } = {}) {
const message = args.context ? `Error in Virtual Machine {${args.context}}` : "Error in Virtual Machine";
console.log(message, err);
if (args.jsonContext != null) {
const jsonTypeError = err.message.match(jsonErrorRegex)
if (jsonTypeError) {
console.log(
"Json Error context",
getJsonContext(
parseInt(jsonTypeError.groups["errorLine"]),
parseInt(jsonTypeError.groups["errorColumn"]),
args.jsonContext,
100
)
)
}
}
if (args.trace) {
console.trace();
}
const toastMessage: ToastMessage = {
variant: "danger",
icon: "bug",
title: `Error in Virtual Machine ${err.name}`,
msg: err.message,
id: Date.now().toString(16),
};
this.dispatchCustomEvent("vm-message", message);
this.dispatchCustomEvent("vm-message", toastMessage);
}
// return the data connected oject ids for a network
networkDataDevices(network: ObjectID): number[] {
networkDataDevices(network: ObjectID): ObjectID[] {
return this._networks.get(network)?.peek().devices ?? [];
}
private _networkDevicesSignals: Map<ObjectID, Signal<ObjectID[]>>;
networkDataDevicesSignal(network: ObjectID): Signal<ObjectID[]> {
if (!this._networkDevicesSignals.has(network) && this._networks.get(network) != null) {
this._networkDevicesSignals.set(network, computed(
() => this._networks.get(network).value.devices ?? []
));
}
return this._networkDevicesSignals.get(network);
}
async changeObjectID(oldID: number, newID: number): Promise<boolean> {
try {
await this.ic10vm.changeDeviceId(oldID, newID);
@@ -581,12 +634,13 @@ class VirtualMachine extends TypedEventTarget<VirtualMachineEventMap>() {
async restoreVMState(state: FrozenVM) {
try {
console.info("Restoring VM State from", state);
await this.ic10vm.restoreVMState(state);
this._objects = new Map();
this._circuitHolders = new Map();
await this.update();
} catch (e) {
this.handleVmError(e);
this.handleVmError(e, {jsonContext: JSON.stringify(state)});
}
}

View File

@@ -0,0 +1,192 @@
function jsonMatchingBrace(char: string): string {
switch (char) {
case "[":
return "]";
case "]":
return "[";
case "{":
return "}";
case "}":
return "{";
default:
return char;
}
}
function readJsonContextBack(ctx: string, maxLen: number, stringCanEnd: boolean): string {
const tokenContexts: string[] = [];
let inStr: boolean = false;
let foundOpen: boolean = false;
let ctxEnd: number = 0;
let lastChar: string | null = null;
let lastNonWhitespaceChar: string | null = null;
let countStringOpens: number = 0;
let countObjectsFound: number = 0;
const chars = ctx.split("");
for (let i = chars.length; i >= 0; i--) {
const c = chars[i];
if (c === ":" && inStr && countStringOpens === 1 && lastNonWhitespaceChar === '"') {
inStr = false;
tokenContexts.pop();
}
if (c === "\\" && !inStr && lastChar === '"') {
if (lastChar != null) {
tokenContexts.push(lastChar);
}
foundOpen = false;
inStr = true;
continue;
}
if (c === '"') {
if (inStr && (tokenContexts.length > 0 ? tokenContexts[tokenContexts.length - 1] : null) === c) {
inStr = false;
if (stringCanEnd) {
foundOpen = true;
}
tokenContexts.pop();
} else {
inStr = true;
countStringOpens += 1;
tokenContexts.push(c);
}
}
if ((c === "]" || c === "}") && !inStr) {
tokenContexts.push(c);
}
if (
(c === "[" || c === "{")
&& !inStr
&& (tokenContexts.length > 0 ? tokenContexts[tokenContexts.length - 1] : null) === jsonMatchingBrace(c)
) {
tokenContexts.pop();
foundOpen = true;
}
if (
(c === ",")
&& !inStr
&& (lastNonWhitespaceChar === "[" || lastNonWhitespaceChar === "{" || lastNonWhitespaceChar === '"')
) {
foundOpen = true;
}
lastChar = c;
if (!(' \t\n\r\v'.indexOf(c) > -1)) {
lastNonWhitespaceChar = c;
}
if (foundOpen && !tokenContexts.length) {
countObjectsFound += 1;
}
if (countObjectsFound >= 2) {
ctxEnd = i;
break;
}
}
if (ctxEnd > 0) {
ctx = ctx.substring(ctxEnd);
}
if (maxLen > 0 && ctx.length > maxLen) {
ctx = "... " + ctx.substring(maxLen);
}
return ctx;
}
function readJsonContextForward(ctx: string, maxLen: number, stringCanEnd: boolean): string {
const tokenContexts: string[] = [];
let inStr: boolean = false;
let foundClose: boolean = false;
let ctxEnd: number = 0;
let lastChar: string | null = null;
let lastNonWhitespaceChar: string | null = null;
let countStringOpens: number = 0;
let countObjectsFound: number = 0;
const chars = ctx.split("");
for (let i = 0; i < chars.length; i++) {
const c = chars[i];
if (c === ":" && inStr && countStringOpens === 1 && lastNonWhitespaceChar === '"') {
inStr = false;
tokenContexts.pop();
}
if (c === "\\" && !inStr && lastChar === "'") {
if (lastChar != null) {
tokenContexts.push(lastChar);
}
foundClose = false;
inStr = true;
continue;
}
if (c === '"') {
if (
inStr
&& (tokenContexts.length > 0 ? tokenContexts[tokenContexts.length - 1] : null) === c
) {
inStr = false;
if (stringCanEnd) {
foundClose = true;
}
tokenContexts.pop();
} else {
inStr = true;
countStringOpens += 1;
tokenContexts.push(c);
}
}
if (
(c === "]" || c === "}")
&& !inStr
) {
tokenContexts.pop();
foundClose = true;
}
if (
(c === "[" || c === "{")
&& !inStr
&& (tokenContexts.length > 0 ? tokenContexts[tokenContexts.length - 1] : null) === jsonMatchingBrace(c)
) {
tokenContexts.push(c);
}
if (
(c === ",")
&& !inStr
&& (lastNonWhitespaceChar === "]" || lastNonWhitespaceChar === "}" || lastNonWhitespaceChar === '"')
) {
foundClose = true;
}
lastChar = c;
if (!(' \t\n\r\v'.indexOf(c) > -1)) {
lastNonWhitespaceChar = c;
}
if (foundClose && !tokenContexts.length) {
countObjectsFound += 1;
}
if (countObjectsFound >= 2) {
ctxEnd = i;
break;
}
}
if (ctxEnd > 0) {
ctx = ctx.substring(0, ctxEnd);
}
if (maxLen > 0 && ctx.length > maxLen) {
ctx = ctx.substring(0, maxLen) + " ...";
}
return ctx
}
export function getJsonContext(errLine: number, errColumn: number, body: string, maxLen: number): string {
if (!body.length) {
return body;
}
const stringCanEnd = body[0] !== '[' && body[0] !== "{";
const lineOffset = (body.split("").map((c, i) => [c, i]).filter(([c, _]) => c === "\n")[errLine - 1] as [string, number] ?? ["", 0] as [string, number])[1];
const preLine = body.substring(0, lineOffset);
const ctxLine = body.substring(lineOffset);
const ctxBefore = preLine + ctxLine.substring(0, errColumn);
const ctxAfter = ctxLine.substring(errColumn);
return readJsonContextBack(ctxBefore, maxLen, stringCanEnd) + "<~~" + readJsonContextForward(ctxAfter, maxLen, stringCanEnd);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
import { html, css } from "lit";
import { html, css, nothing } from "lit";
import { customElement } from "lit/decorators.js";
import { BaseElement, defaultCss } from "components";
import { VMActiveICMixin } from "virtualMachine/baseDevice";
@@ -6,6 +6,7 @@ import { VMActiveICMixin } from "virtualMachine/baseDevice";
import { RegisterSpec } from "ic10emu_wasm";
import SlInput from "@shoelace-style/shoelace/dist/components/input/input.js";
import { displayNumber, parseNumber } from "utils";
import { computed, Signal, watch } from "@lit-labs/preact-signals";
@customElement("vm-ic-registers")
export class VMICRegisters extends VMActiveICMixin(BaseElement) {
@@ -40,12 +41,12 @@ export class VMICRegisters extends VMActiveICMixin(BaseElement) {
constructor() {
super();
this.subscribe("ic", "active-ic")
this.subscribe("active-ic")
}
protected render() {
const registerAliases: [string, number][] =
[...(Array.from(this.aliases?.entries() ?? []))].flatMap(
const registerAliases: Signal<[string, number][]> = computed(() => {
return [...(Array.from(this.objectSignals.aliases.value?.entries() ?? []))].flatMap(
([alias, target]) => {
if ("RegisterSpec" in target && target.RegisterSpec.indirection === 0) {
return [[alias, target.RegisterSpec.target]] as [string, number][];
@@ -54,33 +55,49 @@ export class VMICRegisters extends VMActiveICMixin(BaseElement) {
}
}
).concat(VMICRegisters.defaultAliases);
});
const registerHtml = this.objectSignals?.registers.peek().map((val, index) => {
const aliases = computed(() => {
return registerAliases.value
.filter(([_alias, target]) => index === target)
.map(([alias, _target]) => alias);
});
const aliasesList = computed(() => {
return aliases.value.join(", ");
});
const aliasesText = computed(() => {
return aliasesList.value || "None";
});
const valDisplay = computed(() => {
const val = this.objectSignals.registers.value[index];
return displayNumber(val);
});
return html`
<sl-tooltip placement="left" class="tooltip">
<div slot="content">
<strong>Register r${index}</strong> Aliases:
<em>${watch(aliasesText)}</em>
</div>
<sl-input
type="text"
value="${watch(valDisplay)}"
size="small"
class="reg-input"
@sl-change=${this._handleCellChange}
key=${index}
>
<span slot="prefix">r${index}</span>
<span slot="suffix">${watch(aliasesList)}</span>
</sl-input>
</sl-tooltip>
`;
}) ?? nothing;
return html`
<sl-card class="card">
<div class="card-body">
${this.registers?.map((val, index) => {
const aliases = registerAliases
.filter(([_alias, target]) => index === target)
.map(([alias, _target]) => alias);
return html`
<sl-tooltip placement="left" class="tooltip">
<div slot="content">
<strong>Register r${index}</strong> Aliases:
<em>${aliases.join(", ") || "None"}</em>
</div>
<sl-input
type="text"
value="${displayNumber(val)}"
size="small"
class="reg-input"
@sl-change=${this._handleCellChange}
key=${index}
>
<span slot="prefix">r${index}</span>
<span slot="suffix">${aliases.join(", ")}</span>
</sl-input>
</sl-tooltip>
`;
})}
${registerHtml}
</div>
</sl-card>
`;

View File

@@ -1,10 +1,11 @@
import { html, css } from "lit";
import { html, css, nothing } from "lit";
import { customElement } from "lit/decorators.js";
import { BaseElement, defaultCss } from "components";
import { VMActiveICMixin } from "virtualMachine/baseDevice";
import SlInput from "@shoelace-style/shoelace/dist/components/input/input.js";
import { displayNumber, parseNumber } from "utils";
import { computed, watch } from "@lit-labs/preact-signals";
@customElement("vm-ic-stack")
export class VMICStack extends VMActiveICMixin(BaseElement) {
@@ -37,35 +38,49 @@ export class VMICStack extends VMActiveICMixin(BaseElement) {
constructor() {
super();
this.subscribe("ic", "active-ic")
this.subscribe("active-ic")
}
protected render() {
const sp = this.registers != null ? this.registers[16] : 0;
const sp = computed(() => {
return this.objectSignals.registers.value != null ? this.objectSignals.registers.value[16] : 0;
});
const memoryHtml = this.objectSignals?.memory.peek()?.map((val, index) => {
const content = computed(() => {
return sp.value === index ? html`<strong>Stack Pointer</strong>` : nothing;
});
const pointerClass = computed(() => {
return sp.value === index ? "stack-pointer" : nothing;
});
const displayVal = computed(() => {
return displayNumber(this.objectSignals.memory.value[index]);
});
return html`
<sl-tooltip placement="left">
<div slot="content">
${watch(content)}
Address ${index}
</div>
<sl-input
type="text"
value="${watch(displayVal)}"
size="small"
class="stack-input ${watch(pointerClass)}"
@sl-change=${this._handleCellChange}
key=${index}
>
<span slot="prefix"> ${index} </span>
</sl-input>
</sl-tooltip>
`;
}) ?? nothing;
return html`
<sl-card class="card">
<div class="card-body">
${this.memory?.map((val, index) => {
return html`
<sl-tooltip placement="left">
<div slot="content">
${sp === index ? html`<strong>Stack Pointer</strong>` : ""}
Address ${index}
</div>
<sl-input
type="text"
value="${displayNumber(val)}"
size="small"
class="stack-input ${sp === index ? "stack-pointer" : ""}"
@sl-change=${this._handleCellChange}
key=${index}
>
<span slot="prefix"> ${index} </span>
</sl-input>
</sl-tooltip>
`;
})}
${memoryHtml}
</div>
</sl-card>
`;

View File

@@ -6,24 +6,24 @@ import type {
import * as Comlink from "comlink";
import prefabDatabase from "./prefabDatabase";
import { parseNumber } from "utils";
import { comlinkSpecialJsonTransferHandler, parseNumber } from "utils";
Comlink.transferHandlers.set("SpecialJson", comlinkSpecialJsonTransferHandler);
console.info("Processing Json prefab Database ", prefabDatabase);
const vm: VMRef = init();
const template_database = Object.fromEntries(
const start_time = performance.now();
const template_database = new Map(
Object.entries(prefabDatabase.prefabsByHash).map(([hash, prefabName]) => [
parseInt(hash),
prefabDatabase.prefabs[prefabName],
]),
) as TemplateDatabase;
console.info("Loading Prefab Template Database into VM", template_database);
try {
console.info("Loading Prefab Template Database into VM", template_database);
const start_time = performance.now();
// vm.importTemplateDatabase(template_database);
vm.importTemplateDatabase(template_database);
const now = performance.now();

View File

@@ -191,7 +191,7 @@ pub fn generate_database(
.join("www")
.join("src")
.join("ts")
.join("virtual_machine");
.join("virtualMachine");
if !data_path.exists() {
std::fs::create_dir(&data_path)?;
}
@@ -860,7 +860,7 @@ fn slot_inserts_to_info(slots: &[stationpedia::SlotInsert]) -> Vec<SlotInfo> {
typ: slot
.slot_type
.parse()
.unwrap_or_else(|err| panic!("faild to parse slot class: {err}")),
.unwrap_or_else(|err| panic!("failed to parse slot class: {err}")),
})
.collect()
}
@@ -891,7 +891,7 @@ pub struct ObjectDatabase {
impl From<&stationpedia::SuitInfo> for SuitInfo {
fn from(value: &stationpedia::SuitInfo) -> Self {
SuitInfo {
hygine_reduction_multiplier: value.hygine_reduction_multiplier,
hygiene_reduction_multiplier: value.hygiene_reduction_multiplier,
waste_max_pressure: value.waste_max_pressure,
}
}
@@ -979,11 +979,17 @@ impl From<&stationpedia::Item> for ItemInfo {
slot_class: item
.slot_class
.parse()
.unwrap_or_else(|err| panic!("failed to parse slot class: {err}")),
.unwrap_or_else(|err| {
let slot_class = &item.slot_class;
panic!("failed to parse slot class `{slot_class}`: {err}");
}),
sorting_class: item
.sorting_class
.parse()
.unwrap_or_else(|err| panic!("failed to parse sorting class: {err}")),
.unwrap_or_else(|err| {
let sorting_class = &item.sorting_class;
panic!("failed to parse sorting class `{sorting_class}`: {err}");
}),
}
}
}
@@ -997,10 +1003,10 @@ impl From<&stationpedia::Device> for DeviceInfo {
.map(|(typ, role)| ConnectionInfo {
typ: typ
.parse()
.unwrap_or_else(|err| panic!("failed to parse connection type: {err}")),
.unwrap_or_else(|err| panic!("failed to parse connection type `{typ}`: {err}")),
role: role
.parse()
.unwrap_or_else(|err| panic!("failed to parse connection role: {err}")),
.unwrap_or_else(|err| panic!("failed to parse connection role `{role}`: {err}")),
})
.collect(),
device_pins_length: value.devices_length,
@@ -1111,7 +1117,7 @@ impl From<&stationpedia::Memory> for MemoryInfo {
impl From<&stationpedia::ResourceConsumer> for ConsumerInfo {
fn from(value: &stationpedia::ResourceConsumer) -> Self {
ConsumerInfo {
consumed_resouces: value.consumed_resources.clone(),
consumed_resources: value.consumed_resources.clone(),
processed_reagents: value.processed_reagents.clone(),
}
}

View File

@@ -91,7 +91,7 @@ pub struct Page {
#[serde(rename = "SourceCode", default)]
pub source_code: bool,
#[serde(rename = "Chargeable")]
pub chargeable: Option<Chargable>,
pub chargeable: Option<Chargeable>,
#[serde(rename = "ResourceConsumer")]
pub resource_consumer: Option<ResourceConsumer>,
#[serde(rename = "InternalAtmosphere")]
@@ -257,8 +257,8 @@ pub struct Item {
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct SuitInfo {
#[serde(rename = "HygineReductionMultiplier")]
pub hygine_reduction_multiplier: f32,
#[serde(rename = "HygieneReductionMultiplier")]
pub hygiene_reduction_multiplier: f32,
#[serde(rename = "WasteMaxPressure")]
pub waste_max_pressure: f32,
}
@@ -269,9 +269,9 @@ pub struct Recipe {
pub creator_prefab_name: String,
#[serde(rename = "TierName")]
pub tier_name: String,
#[serde(rename = "Time")]
#[serde(rename = "Time", default)]
pub time: f64,
#[serde(rename = "Energy")]
#[serde(rename = "Energy", default)]
pub energy: f64,
#[serde(rename = "Temperature")]
pub temperature: RecipeTemperature,
@@ -279,7 +279,7 @@ pub struct Recipe {
pub pressure: RecipePressure,
#[serde(rename = "RequiredMix")]
pub required_mix: RecipeGasMix,
#[serde(rename = "CountTypes")]
#[serde(rename = "CountTypes", default)]
pub count_types: i64,
#[serde(flatten)]
pub reagents: indexmap::IndexMap<String, f64>,
@@ -354,7 +354,7 @@ pub struct Fabricator {
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct Chargable {
pub struct Chargeable {
#[serde(rename = "PowerMaximum")]
pub power_maximum: f32,
}