refactor(vm+frontend): better logging, fix slot serialization

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
This commit is contained in:
Rachel Powers
2024-09-16 21:40:51 -07:00
parent f05f81cce5
commit a34fb426b7
26 changed files with 310 additions and 93 deletions

3
Cargo.lock generated
View File

@@ -659,6 +659,7 @@ dependencies = [
"serde_with",
"stationeers_data",
"thiserror",
"tracing",
"tracing-wasm",
"tsify",
"wasm-bindgen",
@@ -694,6 +695,8 @@ dependencies = [
"js-sys",
"tokio",
"tower-lsp",
"tracing",
"tracing-wasm",
"wasm-bindgen",
"wasm-bindgen-futures",
"wasm-streams",

View File

@@ -113,16 +113,22 @@ impl VM {
/// Take ownership of an iterable that produces (prefab hash, ObjectTemplate) pairs and build a prefab
/// database
#[tracing::instrument(skip(db))]
pub fn import_template_database(
self: &Rc<Self>,
db: impl IntoIterator<Item = (i32, ObjectTemplate)>,
) {
tracing::info!("importing new template database");
self.template_database
.borrow_mut()
.replace(db.into_iter().collect());
}
/// Take ownership of an iterable that produces (reagent id, Reagent) pairs and build a reagent
/// database
#[tracing::instrument(skip(db))]
pub fn import_reagent_database(self: &Rc<Self>, db: impl IntoIterator<Item = (u8, Reagent)>) {
tracing::info!("importing new reagent database");
self.reagent_database
.borrow_mut()
.replace(db.into_iter().collect());
@@ -192,6 +198,7 @@ impl VM {
/// Add an number of object to the VM state using Frozen Object structs.
/// See also `add_objects_frozen`
/// Returns the built objects' IDs
#[tracing::instrument(skip(frozen_objects))]
pub fn add_objects_frozen(
self: &Rc<Self>,
frozen_objects: impl IntoIterator<Item = FrozenObject>,
@@ -249,6 +256,7 @@ impl VM {
/// current database.
/// Errors if the object can not be built do to a template error
/// Returns the built object's ID
#[tracing::instrument]
pub fn add_object_frozen(self: &Rc<Self>, frozen: FrozenObject) -> Result<ObjectID, VMError> {
let mut transaction = VMTransaction::new(self);
@@ -295,6 +303,7 @@ impl VM {
}
/// Creates a new network adn return it's ID
#[tracing::instrument]
pub fn add_network(self: &Rc<Self>) -> ObjectID {
let next_id = self.network_id_space.borrow_mut().next();
self.networks.borrow_mut().insert(
@@ -322,6 +331,7 @@ impl VM {
///
/// Iterates over all objects borrowing them mutably, never call unless VM is not currently
/// stepping or you'll get reborrow panics
#[tracing::instrument]
pub fn change_device_id(
self: &Rc<Self>,
old_id: ObjectID,
@@ -385,6 +395,7 @@ impl VM {
/// Set program code if it's valid
/// Object Id is the programmable Id or the circuit holder's id
#[tracing::instrument]
pub fn set_code(self: &Rc<Self>, id: ObjectID, code: &str) -> Result<bool, VMError> {
let obj = self
.objects
@@ -420,6 +431,7 @@ impl VM {
/// Set program code and translate invalid lines to Nop, collecting errors
/// Object Id is the programmable Id or the circuit holder's id
#[tracing::instrument]
pub fn set_code_invalid(self: &Rc<Self>, id: ObjectID, code: &str) -> Result<bool, VMError> {
let obj = self
.objects
@@ -455,6 +467,7 @@ impl VM {
/// Get program code
/// Object Id is the programmable Id or the circuit holder's id
#[tracing::instrument]
pub fn get_code(self: &Rc<Self>, id: ObjectID) -> Result<String, VMError> {
let obj = self
.objects
@@ -488,6 +501,7 @@ impl VM {
/// Get a vector of any errors compiling the source code
/// Object Id is the programmable Id or the circuit holder's id
#[tracing::instrument]
pub fn get_compile_errors(self: &Rc<Self>, id: ObjectID) -> Result<Vec<ICError>, VMError> {
let obj = self
.objects
@@ -521,6 +535,7 @@ impl VM {
/// Set register of integrated circuit
/// Object Id is the circuit Id or the circuit holder's id
#[tracing::instrument]
pub fn set_register(
self: &Rc<Self>,
id: ObjectID,
@@ -561,6 +576,7 @@ impl VM {
/// Set memory at address of object with memory
/// Object Id is the memory writable Id or the circuit holder's id
#[tracing::instrument]
pub fn set_memory(
self: &Rc<Self>,
id: ObjectID,
@@ -610,6 +626,7 @@ impl VM {
}
/// Set logic field on a logicable object
#[tracing::instrument]
pub fn set_logic_field(
self: &Rc<Self>,
id: ObjectID,
@@ -634,6 +651,7 @@ impl VM {
}
/// Set slot logic filed on device object
#[tracing::instrument]
pub fn set_slot_logic_field(
self: &Rc<Self>,
id: ObjectID,
@@ -661,6 +679,7 @@ impl VM {
self.operation_modified.borrow().clone()
}
#[tracing::instrument]
pub fn step_programmable(
self: &Rc<Self>,
id: ObjectID,
@@ -705,6 +724,7 @@ impl VM {
}
/// returns true if executed 128 lines, false if returned early.
#[tracing::instrument]
pub fn run_programmable(
self: &Rc<Self>,
id: ObjectID,
@@ -816,10 +836,12 @@ impl VM {
Err(VMError::NoIC(id))
}
#[tracing::instrument]
pub fn get_object(self: &Rc<Self>, id: ObjectID) -> Option<VMObject> {
self.objects.borrow().get(&id).cloned()
}
#[tracing::instrument]
pub fn batch_device(
self: &Rc<Self>,
source: ObjectID,
@@ -850,6 +872,7 @@ impl VM {
.into_iter()
}
#[tracing::instrument]
pub fn get_device_same_network(
self: &Rc<Self>,
source: ObjectID,
@@ -862,6 +885,7 @@ impl VM {
}
}
#[tracing::instrument]
pub fn get_network_channel(
self: &Rc<Self>,
id: ObjectID,
@@ -887,6 +911,7 @@ impl VM {
}
}
#[tracing::instrument]
pub fn set_network_channel(
self: &Rc<Self>,
id: ObjectID,
@@ -913,6 +938,7 @@ impl VM {
}
}
#[tracing::instrument]
pub fn devices_on_same_network(self: &Rc<Self>, ids: &[ObjectID]) -> bool {
for net in self.networks.borrow().values() {
if net
@@ -928,6 +954,7 @@ impl VM {
}
/// return a vector with the device ids the source id can see via it's connected networks
#[tracing::instrument]
pub fn visible_devices(self: &Rc<Self>, source: ObjectID) -> Vec<ObjectID> {
self.networks
.borrow()
@@ -944,6 +971,7 @@ impl VM {
.concat()
}
#[tracing::instrument]
pub fn set_pin(
self: &Rc<Self>,
id: ObjectID,
@@ -976,6 +1004,7 @@ impl VM {
}
}
#[tracing::instrument]
pub fn set_device_connection(
self: &Rc<Self>,
id: ObjectID,
@@ -1076,6 +1105,7 @@ impl VM {
Ok(true)
}
#[tracing::instrument]
pub fn remove_device_from_network(
self: &Rc<Self>,
id: ObjectID,
@@ -1108,6 +1138,7 @@ impl VM {
}
}
#[tracing::instrument]
pub fn set_batch_device_field(
self: &Rc<Self>,
source: ObjectID,
@@ -1129,6 +1160,7 @@ impl VM {
.try_collect()
}
#[tracing::instrument]
pub fn set_batch_device_slot_field(
self: &Rc<Self>,
source: ObjectID,
@@ -1151,6 +1183,7 @@ impl VM {
.try_collect()
}
#[tracing::instrument]
pub fn set_batch_name_device_field(
self: &Rc<Self>,
source: ObjectID,
@@ -1173,6 +1206,7 @@ impl VM {
.try_collect()
}
#[tracing::instrument]
pub fn get_batch_device_field(
self: &Rc<Self>,
source: ObjectID,
@@ -1195,6 +1229,7 @@ impl VM {
Ok(LogicBatchMethodWrapper(mode).apply(&samples))
}
#[tracing::instrument]
pub fn get_batch_name_device_field(
self: &Rc<Self>,
source: ObjectID,
@@ -1218,6 +1253,7 @@ impl VM {
Ok(LogicBatchMethodWrapper(mode).apply(&samples))
}
#[tracing::instrument]
pub fn get_batch_name_device_slot_field(
self: &Rc<Self>,
source: ObjectID,
@@ -1242,6 +1278,7 @@ impl VM {
Ok(LogicBatchMethodWrapper(mode).apply(&samples))
}
#[tracing::instrument]
pub fn get_batch_device_slot_field(
self: &Rc<Self>,
source: ObjectID,
@@ -1265,6 +1302,7 @@ impl VM {
Ok(LogicBatchMethodWrapper(mode).apply(&samples))
}
#[tracing::instrument]
pub fn remove_object(self: &Rc<Self>, id: ObjectID) -> Result<(), VMError> {
let Some(obj) = self.objects.borrow_mut().remove(&id) else {
return Err(VMError::UnknownId(id));
@@ -1294,6 +1332,7 @@ impl VM {
/// object must already be added to the VM
/// does not clean up previous object
/// returns the id of any former occupant
#[tracing::instrument]
pub fn set_slot_occupant(
self: &Rc<Self>,
id: ObjectID,
@@ -1348,6 +1387,7 @@ impl VM {
}
/// returns former occupant id if any
#[tracing::instrument]
pub fn remove_slot_occupant(
self: &Rc<Self>,
id: ObjectID,
@@ -1368,6 +1408,7 @@ impl VM {
Ok(last)
}
#[tracing::instrument]
pub fn freeze_object(self: &Rc<Self>, id: ObjectID) -> Result<FrozenObjectFull, VMError> {
let Some(obj) = self.objects.borrow().get(&id).cloned() else {
return Err(VMError::UnknownId(id));
@@ -1375,6 +1416,7 @@ impl VM {
Ok(FrozenObject::freeze_object(&obj, self)?)
}
#[tracing::instrument(skip(ids))]
pub fn freeze_objects(
self: &Rc<Self>,
ids: impl IntoIterator<Item = ObjectID>,
@@ -1389,6 +1431,7 @@ impl VM {
.collect()
}
#[tracing::instrument]
pub fn freeze_network(self: &Rc<Self>, id: ObjectID) -> Result<FrozenCableNetwork, VMError> {
Ok(self
.networks
@@ -1401,6 +1444,7 @@ impl VM {
.into())
}
#[tracing::instrument(skip(ids))]
pub fn freeze_networks(
self: &Rc<Self>,
ids: impl IntoIterator<Item = ObjectID>,
@@ -1420,7 +1464,9 @@ impl VM {
.collect::<Result<Vec<FrozenCableNetwork>, VMError>>()
}
#[tracing::instrument]
pub fn save_vm_state(self: &Rc<Self>) -> Result<FrozenVM, VMError> {
tracing::trace!("saving vm state");
Ok(FrozenVM {
objects: self
.objects
@@ -1449,7 +1495,9 @@ impl VM {
})
}
#[tracing::instrument]
pub fn restore_vm_state(self: &Rc<Self>, state: FrozenVM) -> Result<(), VMError> {
tracing::trace!("restoring vm state from {:?}", &state);
let mut transaction_network_id_space = IdSpace::new();
transaction_network_id_space
.use_ids(&state.networks.iter().map(|net| net.id).collect_vec())?;
@@ -1624,6 +1672,7 @@ impl VMTransaction {
}
pub fn finalize(&mut self) -> Result<(), VMError> {
tracing::trace!("finalizing vm transaction: {:?}", &self);
for (child, (slot, parent)) in &self.object_parents {
let child_obj = self
.objects

View File

@@ -27,6 +27,7 @@ thiserror = "1.0.61"
serde_derive = "1.0.203"
serde_json = "1.0.117"
tracing-wasm = "0.2.1"
tracing = "0.1.40"
[features]
default = ["console_error_panic_hook"]

View File

@@ -18,7 +18,7 @@ use serde_derive::{Deserialize, Serialize};
use stationeers_data::{
enums::script::{LogicSlotType, LogicType},
templates::ObjectTemplate,
templates::{ObjectTemplate, Reagent},
};
use std::{collections::BTreeMap, rc::Rc};
@@ -60,6 +60,18 @@ impl IntoIterator for TemplateDatabase {
}
}
#[derive(Clone, Debug, Serialize, Deserialize, Tsify)]
#[tsify(into_wasm_abi, from_wasm_abi)]
pub struct ReagentDatabase(BTreeMap<u8, Reagent>);
impl IntoIterator for ReagentDatabase {
type Item = (u8, Reagent);
type IntoIter = std::collections::btree_map::IntoIter<u8, Reagent>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
#[derive(Clone, Debug, Serialize, Deserialize, Tsify)]
#[tsify(into_wasm_abi, from_wasm_abi)]
pub struct FrozenObjects(Vec<FrozenObjectFull>);
@@ -115,7 +127,7 @@ pub fn parse_value<'a, T: serde::Deserialize<'a>>(
let mut track = serde_path_to_error::Track::new();
let path = serde_path_to_error::Deserializer::new(jd, &mut track);
let mut fun = |path: serde_ignored::Path| {
log!("Found ignored key: {path}");
tracing::warn!("Found ignored key: {path}");
};
serde_ignored::deserialize(path, &mut fun).map_err(|e| {
eyre::eyre!(
@@ -125,6 +137,7 @@ pub fn parse_value<'a, T: serde::Deserialize<'a>>(
})
}
#[allow(non_snake_case)]
#[wasm_bindgen]
impl VMRef {
#[wasm_bindgen(constructor)]
@@ -137,6 +150,11 @@ impl VMRef {
self.vm.import_template_database(db);
}
#[wasm_bindgen(js_name = "importReagentDatabase")]
pub fn import_reagent_database(&self, db: ReagentDatabase) {
self.vm.import_reagent_database(db);
}
#[wasm_bindgen(js_name = "importTemplateDatabaseSerdeWasm")]
pub fn import_template_database_serde_wasm(&self, db: JsValue) -> Result<(), JsError> {
let parsed_db: BTreeMap<i32, ObjectTemplate> =
@@ -480,6 +498,6 @@ pub fn init() -> VMRef {
utils::set_panic_hook();
tracing_wasm::set_as_global_default();
let vm = VMRef::new();
log!("Hello from ic10emu!");
tracing::info!("Hello from ic10emu!");
vm
}

View File

@@ -11,12 +11,3 @@ pub fn set_panic_hook() {
web_sys::console::log_1(&"Panic hook set...".into());
}
}
extern crate web_sys;
// A macro to provide `println!(..)`-style syntax for `console.log` logging.
macro_rules! log {
( $( $t:tt )* ) => {
web_sys::console::log_1(&format!( $( $t )* ).into());
}
}

View File

@@ -26,6 +26,8 @@ wasm-bindgen-futures = { version = "0.4.42", features = [
wasm-streams = "0.4"
# web-tree-sitter-sys = "1.3"
ic10lsp = { git = "https://github.com/Ryex/ic10lsp.git", branch = "wasm" }
tracing-wasm = "0.2.1"
tracing = "0.1.40"
# ic10lsp = { path = "../../ic10lsp" }
[package.metadata.wasm-pack.profile.dev]

View File

@@ -30,8 +30,9 @@ impl ServerConfig {
#[wasm_bindgen]
pub async fn serve(config: ServerConfig) -> Result<(), JsValue> {
console_error_panic_hook::set_once();
tracing_wasm::set_as_global_default();
web_sys::console::log_1(&"server::serve".into());
tracing::trace!("server::serv error:");
let ServerConfig {
into_server,
@@ -51,6 +52,7 @@ pub async fn serve(config: ServerConfig) -> Result<(), JsValue> {
})
.map_err(|err| {
web_sys::console::log_2(&"server::input Error: ".into(), &err);
tracing::error!("server::input error: {:?}", &err);
std::io::Error::from(std::io::ErrorKind::Other)
})
@@ -67,7 +69,7 @@ pub async fn serve(config: ServerConfig) -> Result<(), JsValue> {
});
Server::new(input, output, messages).serve(service).await;
web_sys::console::log_1(&"server::serve ic10lsp started".into());
tracing::info!("server::serve ic10lsp started");
Ok(())
}

View File

@@ -174,11 +174,14 @@ impl From<HumanTemplate> for ObjectTemplate {
}
}
#[serde_as]
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
pub struct HumanTemplate {
pub prefab: PrefabInfo,
pub species: Species,
#[serde_as(as = "BTreeMap<DisplayFromStr, _>")]
#[cfg_attr(feature = "tsify", tsify(type = "Map<string, SlotInfo>"))]
pub slots: BTreeMap<u32, SlotInfo>,
}
@@ -420,6 +423,7 @@ pub struct StructureTemplate {
pub internal_atmo_info: Option<InternalAtmoInfo>,
}
#[serde_as]
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
pub struct StructureSlotsTemplate {
@@ -429,9 +433,12 @@ pub struct StructureSlotsTemplate {
pub thermal_info: Option<ThermalInfo>,
#[cfg_attr(feature = "tsify", tsify(optional))]
pub internal_atmo_info: Option<InternalAtmoInfo>,
#[serde_as(as = "BTreeMap<DisplayFromStr, _>")]
#[cfg_attr(feature = "tsify", tsify(type = "Map<string, SlotInfo>"))]
pub slots: BTreeMap<u32, SlotInfo>,
}
#[serde_as]
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
pub struct StructureLogicTemplate {
@@ -442,9 +449,12 @@ pub struct StructureLogicTemplate {
#[cfg_attr(feature = "tsify", tsify(optional))]
pub internal_atmo_info: Option<InternalAtmoInfo>,
pub logic: LogicInfo,
#[serde_as(as = "BTreeMap<DisplayFromStr, _>")]
#[cfg_attr(feature = "tsify", tsify(type = "Map<string, SlotInfo>"))]
pub slots: BTreeMap<u32, SlotInfo>,
}
#[serde_as]
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
pub struct StructureLogicDeviceTemplate {
@@ -455,10 +465,13 @@ pub struct StructureLogicDeviceTemplate {
#[cfg_attr(feature = "tsify", tsify(optional))]
pub internal_atmo_info: Option<InternalAtmoInfo>,
pub logic: LogicInfo,
#[serde_as(as = "BTreeMap<DisplayFromStr, _>")]
#[cfg_attr(feature = "tsify", tsify(type = "Map<string, SlotInfo>"))]
pub slots: BTreeMap<u32, SlotInfo>,
pub device: DeviceInfo,
}
#[serde_as]
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
pub struct StructureLogicDeviceConsumerTemplate {
@@ -469,6 +482,8 @@ pub struct StructureLogicDeviceConsumerTemplate {
#[cfg_attr(feature = "tsify", tsify(optional))]
pub internal_atmo_info: Option<InternalAtmoInfo>,
pub logic: LogicInfo,
#[serde_as(as = "BTreeMap<DisplayFromStr, _>")]
#[cfg_attr(feature = "tsify", tsify(type = "Map<string, SlotInfo>"))]
pub slots: BTreeMap<u32, SlotInfo>,
pub device: DeviceInfo,
pub consumer_info: ConsumerInfo,
@@ -476,6 +491,7 @@ pub struct StructureLogicDeviceConsumerTemplate {
pub fabricator_info: Option<FabricatorInfo>,
}
#[serde_as]
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
pub struct StructureLogicDeviceMemoryTemplate {
@@ -486,11 +502,14 @@ pub struct StructureLogicDeviceMemoryTemplate {
#[cfg_attr(feature = "tsify", tsify(optional))]
pub internal_atmo_info: Option<InternalAtmoInfo>,
pub logic: LogicInfo,
#[serde_as(as = "BTreeMap<DisplayFromStr, _>")]
#[cfg_attr(feature = "tsify", tsify(type = "Map<string, SlotInfo>"))]
pub slots: BTreeMap<u32, SlotInfo>,
pub device: DeviceInfo,
pub memory: MemoryInfo,
}
#[serde_as]
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
pub struct StructureCircuitHolderTemplate {
@@ -501,10 +520,13 @@ pub struct StructureCircuitHolderTemplate {
#[cfg_attr(feature = "tsify", tsify(optional))]
pub internal_atmo_info: Option<InternalAtmoInfo>,
pub logic: LogicInfo,
#[serde_as(as = "BTreeMap<DisplayFromStr, _>")]
#[cfg_attr(feature = "tsify", tsify(type = "Map<string, SlotInfo>"))]
pub slots: BTreeMap<u32, SlotInfo>,
pub device: DeviceInfo,
}
#[serde_as]
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
pub struct StructureLogicDeviceConsumerMemoryTemplate {
@@ -515,6 +537,8 @@ pub struct StructureLogicDeviceConsumerMemoryTemplate {
#[cfg_attr(feature = "tsify", tsify(optional))]
pub internal_atmo_info: Option<InternalAtmoInfo>,
pub logic: LogicInfo,
#[serde_as(as = "BTreeMap<DisplayFromStr, _>")]
#[cfg_attr(feature = "tsify", tsify(type = "Map<string, SlotInfo>"))]
pub slots: BTreeMap<u32, SlotInfo>,
pub device: DeviceInfo,
pub consumer_info: ConsumerInfo,
@@ -534,6 +558,7 @@ pub struct ItemTemplate {
pub internal_atmo_info: Option<InternalAtmoInfo>,
}
#[serde_as]
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
pub struct ItemSlotsTemplate {
@@ -543,9 +568,12 @@ pub struct ItemSlotsTemplate {
pub thermal_info: Option<ThermalInfo>,
#[cfg_attr(feature = "tsify", tsify(optional))]
pub internal_atmo_info: Option<InternalAtmoInfo>,
#[serde_as(as = "BTreeMap<DisplayFromStr, _>")]
#[cfg_attr(feature = "tsify", tsify(type = "Map<string, SlotInfo>"))]
pub slots: BTreeMap<u32, SlotInfo>,
}
#[serde_as]
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
pub struct ItemConsumerTemplate {
@@ -555,10 +583,13 @@ pub struct ItemConsumerTemplate {
pub thermal_info: Option<ThermalInfo>,
#[cfg_attr(feature = "tsify", tsify(optional))]
pub internal_atmo_info: Option<InternalAtmoInfo>,
#[serde_as(as = "BTreeMap<DisplayFromStr, _>")]
#[cfg_attr(feature = "tsify", tsify(type = "Map<string, SlotInfo>"))]
pub slots: BTreeMap<u32, SlotInfo>,
pub consumer_info: ConsumerInfo,
}
#[serde_as]
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
pub struct ItemLogicTemplate {
@@ -569,9 +600,12 @@ pub struct ItemLogicTemplate {
#[cfg_attr(feature = "tsify", tsify(optional))]
pub internal_atmo_info: Option<InternalAtmoInfo>,
pub logic: LogicInfo,
#[serde_as(as = "BTreeMap<DisplayFromStr, _>")]
#[cfg_attr(feature = "tsify", tsify(type = "Map<string, SlotInfo>"))]
pub slots: BTreeMap<u32, SlotInfo>,
}
#[serde_as]
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
pub struct ItemLogicMemoryTemplate {
@@ -582,10 +616,13 @@ pub struct ItemLogicMemoryTemplate {
#[cfg_attr(feature = "tsify", tsify(optional))]
pub internal_atmo_info: Option<InternalAtmoInfo>,
pub logic: LogicInfo,
#[serde_as(as = "BTreeMap<DisplayFromStr, _>")]
#[cfg_attr(feature = "tsify", tsify(type = "Map<string, SlotInfo>"))]
pub slots: BTreeMap<u32, SlotInfo>,
pub memory: MemoryInfo,
}
#[serde_as]
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
pub struct ItemCircuitHolderTemplate {
@@ -596,9 +633,12 @@ pub struct ItemCircuitHolderTemplate {
#[cfg_attr(feature = "tsify", tsify(optional))]
pub internal_atmo_info: Option<InternalAtmoInfo>,
pub logic: LogicInfo,
#[serde_as(as = "BTreeMap<DisplayFromStr, _>")]
#[cfg_attr(feature = "tsify", tsify(type = "Map<string, SlotInfo>"))]
pub slots: BTreeMap<u32, SlotInfo>,
}
#[serde_as]
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
pub struct ItemSuitTemplate {
@@ -608,10 +648,13 @@ pub struct ItemSuitTemplate {
pub thermal_info: Option<ThermalInfo>,
#[cfg_attr(feature = "tsify", tsify(optional))]
pub internal_atmo_info: Option<InternalAtmoInfo>,
#[serde_as(as = "BTreeMap<DisplayFromStr, _>")]
#[cfg_attr(feature = "tsify", tsify(type = "Map<string, SlotInfo>"))]
pub slots: BTreeMap<u32, SlotInfo>,
pub suit_info: SuitInfo,
}
#[serde_as]
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
pub struct ItemSuitLogicTemplate {
@@ -622,10 +665,13 @@ pub struct ItemSuitLogicTemplate {
#[cfg_attr(feature = "tsify", tsify(optional))]
pub internal_atmo_info: Option<InternalAtmoInfo>,
pub logic: LogicInfo,
#[serde_as(as = "BTreeMap<DisplayFromStr, _>")]
#[cfg_attr(feature = "tsify", tsify(type = "Map<string, SlotInfo>"))]
pub slots: BTreeMap<u32, SlotInfo>,
pub suit_info: SuitInfo,
}
#[serde_as]
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
pub struct ItemSuitCircuitHolderTemplate {
@@ -636,6 +682,8 @@ pub struct ItemSuitCircuitHolderTemplate {
#[cfg_attr(feature = "tsify", tsify(optional))]
pub internal_atmo_info: Option<InternalAtmoInfo>,
pub logic: LogicInfo,
#[serde_as(as = "BTreeMap<DisplayFromStr, _>")]
#[cfg_attr(feature = "tsify", tsify(type = "Map<string, SlotInfo>"))]
pub slots: BTreeMap<u32, SlotInfo>,
pub suit_info: SuitInfo,
pub memory: MemoryInfo,

View File

@@ -60,6 +60,7 @@
"dbutils",
"Depressurising",
"deviceslength",
"dodgerblue",
"endpos",
"getd",
"Hardsuit",
@@ -72,6 +73,7 @@
"jetpack",
"Keybind",
"labelledby",
"lawngreen",
"lbns",
"leeoniya",
"logicable",
@@ -136,6 +138,7 @@
"VMIC",
"VMUI",
"vstack",
"whitesmoke",
"whos"
],
"flagWords": [],

View File

@@ -9,6 +9,7 @@ import { IC10Editor } from "../editor";
import { Session } from "../session";
import { VirtualMachine } from "../virtualMachine";
import { openFile, saveFile } from "../utils";
import * as log from "log";
import "../virtualMachine/ui";
import "./save";
@@ -103,8 +104,8 @@ export class App extends BaseElement {
<app-nav appVer=${this.appVersion} gitVer=${this.gitVer} buildDate=${this.buildDate} ></app-nav>
<div class="app-body">
${until(
mainBody,
html`
mainBody,
html`
<div class="w-full h-full place-content-center">
<div class="w-full h-fit justify-center">
<p class="mt-auto mr-auto ml-auto w-fit text-2xl">
@@ -115,7 +116,7 @@ export class App extends BaseElement {
</div>
</div>
`
)}
)}
</div>
<session-share-dialog></session-share-dialog>
<save-dialog></save-dialog>
@@ -138,7 +139,7 @@ export class App extends BaseElement {
const saved = JSON.parse(seenVersionsStr);
seenVersions = saved;
} catch (e) {
console.log("error pulling seen versions", e);
log.error("error pulling seen versions", e);
}
}
const ourVer = `${this.appVersion}_${this.gitVer}_${this.buildDate}`;
@@ -155,7 +156,7 @@ export class App extends BaseElement {
const saved = JSON.parse(seenVersionsStr);
seenVersions.concat(saved);
} catch (e) {
console.log("error pulling seen versions", e);
log.error("error pulling seen versions", e);
}
}
const unique = new Set(seenVersions);

View File

@@ -1,6 +1,7 @@
import { HTMLTemplateResult, html, css } from "lit";
import { customElement, property } from "lit/decorators.js";
import { BaseElement, defaultCss } from "components";
import * as log from "log";
import SlMenuItem from "@shoelace-style/shoelace/dist/components/menu-item/menu-item.js";
@@ -213,7 +214,7 @@ export class Nav extends BaseElement {
`;
}
firstUpdated(): void {}
firstUpdated(): void { }
_menuClickHandler(e: CustomEvent) {
const item = e.detail.item as SlMenuItem;
@@ -248,7 +249,7 @@ export class Nav extends BaseElement {
this.dispatchEvent(new CustomEvent("app-changelog", { bubbles: true }));
break;
default:
console.log("Unknown main menu item", item.value);
log.debug("Unknown main menu item", item.value);
}
}
}

View File

@@ -2,6 +2,7 @@ import { html, css} from "lit";
import { customElement, query, state } from "lit/decorators.js";
import { BaseElement, defaultCss } from "components";
import { SessionDB } from "sessionDB";
import * as log from "log";
import SlInput from "@shoelace-style/shoelace/dist/components/input/input.js";
import { repeat } from "lit/directives/repeat.js";
@@ -256,7 +257,7 @@ export class SaveDialog extends BaseElement {
async _handleSaveButtonClick(_e: CustomEvent) {
const name = this.saveInput.value;
const app = await window.App.get();
console.log(app);
log.debug(app);
await app.session.saveLocal(name);
this.saveDialog.hide();
}

View File

@@ -6,7 +6,7 @@ import { isSome } from "utils";
export type PrefabName = keyof typeof prefabDatabase.prefabs;
export type Prefab<K extends PrefabName> = typeof prefabDatabase.prefabs[K]
export type ReagentName = keyof typeof prefabDatabase.reagents;
export type ReagentHash = (typeof prefabDatabase.reagents)[ReagentName]["Hash"]
export type ReagentHash = (typeof prefabDatabase.reagents)[ReagentName]["hash"]
export type NetworkChannels = [number, number, number, number, number, number, number, number]
export const validCircuitPrefabsNames = ["ItemIntegratedCircuit10"] as const;
@@ -25,7 +25,7 @@ export interface ObjectFromTemplateOptions<K extends PrefabName> {
obj: ObjectID,
slot: number,
} : never,
slots?: Prefab<K> extends { slots: readonly unknown[] } ? Record<number, {
slots?: Prefab<K> extends { slots: {} } ? Record<number, {
quantity: number,
occupant: ObjectID
}> : never,
@@ -102,7 +102,7 @@ export function objectFromTemplate<K extends PrefabName>(
}
if (isSome(options?.reagents)) {
frozen.obj_info.reagents = new Map(Object.entries(options.reagents).map(([reagent, value]: [ReagentName, number]) => {
return [prefabDatabase.reagents[reagent].Hash, value]
return [prefabDatabase.reagents[reagent].hash, value]
}))
}

View File

@@ -10,7 +10,7 @@ import { Mode as TextMode } from "ace-builds/src-noconflict/mode-text";
export async function setupLspWorker() {
// Create a web worker
let worker = new Worker(new URL("./lspWorker.ts", import.meta.url));
let worker = new Worker(new URL("./lspWorker.ts", import.meta.url), { name: "ic10lsp-Worker" });
const loaded = (w: Worker) =>
new Promise((r) => w.addEventListener("message", r, { once: true }));

View File

@@ -40,6 +40,8 @@ import { VirtualMachine } from "virtualMachine";
import { isSome } from "utils";
import { Session } from "session";
import * as log from "log";
interface SessionStateExtension {
state?: {
errorMarkers?: Ace.MarkerGroup;
@@ -108,7 +110,7 @@ export class IC10Editor extends BaseElement {
constructor() {
super();
console.log("constructing editor");
log.trace("constructing editor");
window.Editor = this;
}
@@ -158,7 +160,7 @@ export class IC10Editor extends BaseElement {
async firstUpdated() {
await this.setupApp();
console.log("editor firstUpdated");
log.trace("editor firstUpdated");
if (!ace.require("ace/ext/language_tools")) {
await import("ace-builds/src-noconflict/ext-language_tools");
}
@@ -608,7 +610,7 @@ export class IC10Editor extends BaseElement {
const temp = Object.assign({}, this.settings, saved);
Object.assign(this.settings, temp);
} catch (e) {
console.log("error loading editor settings", e);
log.error("error loading editor settings", e);
}
}
}

View File

@@ -1,5 +1,7 @@
import { ServerConfig, serve } from "ic10lsp_wasm";
import * as log from "log";
export const encoder = new TextEncoder();
export const decoder = new TextDecoder();
@@ -120,9 +122,7 @@ export class AsyncStreamQueueUint8Array
async next(): Promise<IteratorResult<Uint8Array>> {
const done = false;
// console.log(`AsyncStream(${this.tag}) waiting for message`)
const value = await this.dequeue();
// console.log(`AsyncStream(${this.tag}) got message`, decoder.decode(value))
return { done, value };
}
@@ -194,7 +194,7 @@ function sendClient(data: any) {
async function listen() {
let contentLength: number | null = null;
let buffer = new Uint8Array();
console.log("Worker: listening for lsp messages...");
log.trace("Worker: listening for lsp messages...");
for await (const bytes of serverMsgStream) {
buffer = Bytes.append(Uint8Array, buffer, bytes);
let waitingForFullContent = false;
@@ -236,18 +236,18 @@ async function listen() {
try {
const message = JSON.parse(delimited);
console.log(
log.debug(
"Lsp Message:",
`| This Loop: ${messagesThisLoop} |`,
message,
);
postMessage(message);
} catch (e) {
console.log("Error parsing Lsp Message:", e);
log.error("Error parsing Lsp Message:", e);
}
}
}
console.log("Worker: lsp message queue done?");
log.debug("Worker: lsp message queue done?");
}
listen();
@@ -255,9 +255,9 @@ listen();
postMessage("ready");
onmessage = function (e) {
console.log("Client Message:", e.data);
log.debug("Client Message:", e.data);
sendClient(e.data);
};
console.log("Starting LSP...");
log.trace("Starting LSP...");
start();

View File

@@ -1,7 +1,5 @@
import { prompt as ace_prompt } from "ace-builds/src-noconflict/ext-prompt"
console.log(ace_prompt);
function prompt(editor: { cmdLine: { setTheme: (arg0: string) => void; }; }, message: any, options: any, callback: any) {
ace_prompt(editor, message, options, callback);
if (editor.cmdLine) {

51
www/src/ts/log.ts Normal file
View File

@@ -0,0 +1,51 @@
export function logHeaderFormatting(msg: string, style: string, origin: string,): string[] {
return [
`%c${msg}%c ${origin}%c`,
style,
"color: gray; font-style: italic",
"color: inherit"
];
}
declare var WorkerGlobalScope: {
prototype: any;
new(): any;
};
export function getOrigin(framesUp: number = 1) {
const origin = new Error().stack.split('\n')[framesUp + 1];
if (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope) {
const workerName = self.name ?? "worker"
return `(worker: ${workerName})|${origin}`;
} else {
return origin;
}
}
export function error(...args: any[]): void {
const header = logHeaderFormatting("ERROR", "color: red; background: #444", getOrigin());
console.error(...header, ...args)
}
export function warn(...args: any[]): void {
const header = logHeaderFormatting("WARN", "color: orange; background: #444", getOrigin());
console.warn(...header, ...args)
}
export function info(...args: any[]): void {
const header = logHeaderFormatting("INFO", "color: whitesmoke; background: #444", getOrigin());
console.info(...header, ...args)
}
export function debug(...args: any[]): void {
const header = logHeaderFormatting("DEBUG", "color: lawngreen; background: #444", getOrigin());
console.debug(...header, ...args)
}
export function trace(...args: any[]): void {
const header = logHeaderFormatting("TRACE", "color: dodgerblue; background: #444", getOrigin());
console.log(...header, ...args)
}

View File

@@ -10,6 +10,8 @@ import {
toJson,
} from "./utils";
import * as log from "log";
import * as presets from "./presets";
import { computed, signal, Signal } from "@lit-labs/preact-signals";
import { SessionDB } from "sessionDB";
@@ -97,7 +99,7 @@ export class Session extends TypedEventTarget<SessionEventMap, typeof EventTarge
const fragment = base64url_encode(c_bytes);
window.history.replaceState(null, "", `#${fragment}`);
} catch (e) {
console.log("Error compressing content fragment:", e);
log.error("Error compressing content fragment:", e);
return;
}
}
@@ -144,7 +146,7 @@ export class Session extends TypedEventTarget<SessionEventMap, typeof EventTarge
} else if ("vm" in data && "activeIC" in data) {
this.load(data as SessionDB.CurrentDBVmState);
} else {
console.log("Bad session data:", data);
log.error("Bad session data:", data);
}
}
} else {
@@ -280,11 +282,11 @@ function guessFormat(bytes: ArrayBuffer): CompressionFormat {
async function decompressFragment(c_bytes: ArrayBuffer) {
try {
const format = guessFormat(c_bytes);
console.log("Decompressing fragment with:", format);
log.info("Decompressing fragment with:", format);
const bytes = await decompress(c_bytes, format);
return bytes;
} catch (e) {
console.log("Error decompressing content fragment:", e);
log.error("Error decompressing content fragment:", e);
return null;
}
}

View File

@@ -1,5 +1,6 @@
import { Ace } from "ace-builds";
import { TransferHandler } from "comlink";
import * as log from "log";
export function isSome<T>(object: T | null | undefined): object is T {
return typeof object !== "undefined" && object !== null;
@@ -230,7 +231,7 @@ export function makeRequest(opts: {
export async function saveFile(content: BlobPart) {
const blob = new Blob([content], { type: "text/plain" });
if (typeof window.showSaveFilePicker !== "undefined") {
console.log("Saving via FileSystem API");
log.info("Saving via FileSystem API");
try {
const saveHandle = await window.showSaveFilePicker({
types: [
@@ -247,10 +248,10 @@ export async function saveFile(content: BlobPart) {
await ws.write(blob);
await ws.close();
} catch (e) {
console.log(e);
log.error(e);
}
} else {
console.log("saving file via hidden link event");
log.info("saving file via hidden link event");
var a = document.createElement("a");
const date = new Date().valueOf().toString(16);
a.download = `code_${date}.ic10`;
@@ -261,7 +262,7 @@ export async function saveFile(content: BlobPart) {
export async function openFile(editor: Ace.Editor) {
if (typeof window.showOpenFilePicker !== "undefined") {
console.log("opening file via FileSystem Api");
log.info("opening file via FileSystem Api");
try {
const [fileHandle] = await window.showOpenFilePicker();
const file = await fileHandle.getFile();
@@ -269,16 +270,16 @@ export async function openFile(editor: Ace.Editor) {
const session = editor.getSession();
session.setValue(contents);
} catch (e) {
console.log(e);
log.error(e);
}
} else {
console.log("opening file via hidden input event");
log.info("opening file via hidden input event");
let input = document.createElement("input");
input.type = "file";
input.accept = ".txt,.ic10,.mips,text/*";
input.onchange = (_) => {
const files = Array.from(input.files!);
console.log(files);
log.trace(files);
const file = files[0];
var reader = new FileReader();
reader.onload = (e) => {

View File

@@ -15,6 +15,8 @@ import { repeat } from "lit/directives/repeat.js";
import { Connection } from "ic10emu_wasm";
import { createRef, ref, Ref } from "lit/directives/ref.js";
import * as log from "log";
export type CardTab = "fields" | "slots" | "reagents" | "networks" | "pins";
@customElement("vm-device-card")
@@ -119,7 +121,7 @@ export class VMDeviceCard extends VMObjectMixin(BaseElement) {
onImageErr(e: Event) {
this.image_err = true;
console.log("Image load error", e);
log.error("Image load error", e);
}
thisIsActiveIc = computed(() => {
@@ -327,7 +329,7 @@ export class VMDeviceCard extends VMObjectMixin(BaseElement) {
});
const connectionSelectRef = this.getConnectionSelectRef(index);
selectOptions.subscribe(() => {this.forceSelectUpdate(connectionSelectRef)})
selectOptions.subscribe(() => { this.forceSelectUpdate(connectionSelectRef) })
connNet.subscribe((net) => {
if (isSome(connectionSelectRef.value)) {

View File

@@ -82,8 +82,8 @@ export class VMSlotAddDialog extends VMObjectMixin(BaseElement) {
const obj = this.vm.value?.state.getObject(this.objectIDSignal.value).value;
if (isSome(obj)) {
const template = obj.template;
const slot = "slots" in template ? template.slots[this.slotIndex.value] : null;
const typ = slot?.typ;
const slot = "slots" in template ? template.slots.get(this.slotIndex.value.toString()) : null;
const typ = typeof slot === "object" && "Direct" in slot ? slot.Direct.class : null;
if (typeof typ === "string" && typ !== "None") {
filtered = Array.from(Object.values(this.items.value)).filter(

View File

@@ -151,8 +151,7 @@ export class VmObjectTemplate extends VMObjectMixin(
).map(
(slot, _index) =>
({
typ: slot.class
,
typ: typeof slot === "object" && "Direct" in slot ? slot.Direct.class : null,
quantity: 0,
}) as SlotTemplate,
);

View File

@@ -28,6 +28,8 @@ import {
import { getJsonContext } from "./jsonErrorUtils";
import { VMState } from "./state";
import * as log from "log";
export interface VirtualMachineEventMap {
"vm-template-db-loaded": CustomEvent<TemplateDatabase>;
"vm-objects-update": CustomEvent<number[]>;
@@ -62,11 +64,11 @@ class VirtualMachine extends TypedEventTarget<VirtualMachineEventMap, typeof Eve
async setupVM() {
this.vmWorker = new Worker(new URL("./vmWorker.ts", import.meta.url));
this.vmWorker = new Worker(new URL("./vmWorker.ts", import.meta.url), { name: "ic10emu-Worker"});
const loaded = (w: Worker) =>
new Promise((r) => w.addEventListener("message", r, { once: true }));
await Promise.all([loaded(this.vmWorker)]);
console.info("VM Worker loaded");
log.info("VM Worker loaded");
const vm = Comlink.wrap<VMRef>(this.vmWorker);
this.ic10vm = vm;
this.state.vm.value = await this.ic10vm.saveVMState();
@@ -133,11 +135,11 @@ class VirtualMachine extends TypedEventTarget<VirtualMachineEventMap, typeof Eve
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);
log.error(message, err);
if (args.jsonContext != null) {
const jsonTypeError = err.message.match(jsonErrorRegex)
if (jsonTypeError) {
console.log(
log.debug(
"Json Error context",
getJsonContext(
parseInt(jsonTypeError.groups["errorLine"]),
@@ -307,14 +309,14 @@ class VirtualMachine extends TypedEventTarget<VirtualMachineEventMap, typeof Eve
setupTemplateDatabase(db: TemplateDatabase) {
this.state.templateDB.value = db;
console.log("Loaded Template Database", this.state.templateDB.value);
log.debug("Loaded Template Database", this.state.templateDB.value);
this.dispatchCustomEvent("vm-template-db-loaded", this.state.templateDB.value);
}
async addObjectFrozen(frozen: FrozenObject): Promise<ObjectID | undefined> {
let id = undefined;
try {
console.log("adding device", frozen);
log.trace("adding device", frozen);
id = await this.ic10vm.addObjectFrozen(frozen);
} catch (err) {
this.handleVmError(err);
@@ -329,7 +331,7 @@ class VirtualMachine extends TypedEventTarget<VirtualMachineEventMap, typeof Eve
): Promise<ObjectID[] | undefined> {
let ids = undefined;
try {
console.log("adding devices", frozenObjects);
log.trace("adding devices", frozenObjects);
ids = await this.ic10vm.addObjectsFrozen(frozenObjects);
} catch (err) {
this.handleVmError(err);
@@ -357,7 +359,7 @@ class VirtualMachine extends TypedEventTarget<VirtualMachineEventMap, typeof Eve
quantity: number,
): Promise<boolean> {
try {
console.log("setting slot occupant", frozen);
log.trace("setting slot occupant", frozen);
await this.ic10vm.setSlotOccupant(id, index, frozen, quantity);
} catch (err) {
this.handleVmError(err);
@@ -384,7 +386,7 @@ class VirtualMachine extends TypedEventTarget<VirtualMachineEventMap, typeof Eve
async restoreVMState(state: FrozenVM) {
try {
console.info("Restoring VM State from", state);
log.info("Restoring VM State from", state);
await this.ic10vm.restoreVMState(state);
} catch (e) {
this.handleVmError(e, { jsonContext: JSON.stringify(state) });

View File

@@ -2,6 +2,8 @@ import { computed, ReadonlySignal, signal, Signal } from "@lit-labs/preact-signa
import { Class, Connection, FrozenCableNetwork, FrozenObject, FrozenVM, ICInfo, ICState, LineError, LogicField, LogicSlotType, LogicType, ObjectID, Operand, Slot, TemplateDatabase } from "ic10emu_wasm";
import { isSome, structuralEqual } from "utils";
import * as log from "log";
export interface ObjectSlotInfo {
parent: ObjectID;
@@ -232,7 +234,7 @@ export class VMState {
const s = computed((): number => {
const obj = this.getObject(id).value;
const template = obj?.template;
return isSome(template) && "slots" in template ? template.slots.length : 0
return isSome(template) && "slots" in template ? template.slots.size : 0
});
this.signalCacheSet(key, s);
return s;
@@ -248,13 +250,15 @@ export class VMState {
const obj = this.getObject(id).value;
const info = obj?.obj_info.slots.get(index);
const template = obj?.template;
const slotTemplate = isSome(template) && "slots" in template ? template.slots[index] : null;
const slotTemplate = isSome(template) && "slots" in template ? template.slots.get(index.toString()) : null;
const name = typeof slotTemplate === "object" && "Direct" in slotTemplate ? slotTemplate.Direct.name : slotTemplate?.Proxy.name;
const typ = typeof slotTemplate === "object" && "Direct" in slotTemplate ? slotTemplate.Direct.class : null;
if (isSome(obj)) {
const next = {
parent: obj?.obj_info.id,
index,
name: slotTemplate?.name,
typ: slotTemplate?.typ,
name,
typ,
quantity: info?.quantity,
occupant: info?.id
}
@@ -713,7 +717,7 @@ export class VMState {
} else if (this.programHolderIds.value?.includes(id)) {
return this.getObject(id).value?.obj_info.source_code ?? null;
} else {
console.error(`(objectId: ${id}) does not refer to a object with a known program interface`)
log.error(`(objectId: ${id}) does not refer to a object with a known program interface`)
return null;
}
})
@@ -735,7 +739,7 @@ export class VMState {
} else if (this.programHolderIds.value?.includes(id)) {
ic = this.getObject(id).value ?? null;
} else {
console.error(`(objectId: ${id}) does not refer to a object with a known program interface`)
log.error(`(objectId: ${id}) does not refer to a object with a known program interface`)
return null;
}
const errors = ic?.obj_info.compile_errors?.flatMap((error): LineError[] => {

View File

@@ -1,42 +1,78 @@
import { VMRef, init } from "ic10emu_wasm";
import type {
TemplateDatabase,
Reagent,
ObjectTemplate,
} from "ic10emu_wasm";
import * as Comlink from "comlink";
import * as log from "log";
import prefabDatabase from "../database/prefabDatabase";
import { comlinkSpecialJsonTransferHandler } from "utils";
Comlink.transferHandlers.set("SpecialJson", comlinkSpecialJsonTransferHandler);
console.info("Processing Json prefab Database ", prefabDatabase);
const vm: VMRef = init();
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 {
// vm.importTemplateDatabase(template_database);
vm.importTemplateDatabase(template_database);
const now = performance.now();
const time_elapsed = (now - start_time) / 1000;
console.info(`Prefab Template Database loaded in ${time_elapsed} seconds`);
} catch (e) {
if ("stack" in e) {
console.error("Error importing template database:", e.toString(), e.stack);
} else {
console.error("Error importing template database:", e.toString());
log.info("Processing Json Database", prefabDatabase);
{
const start_time = performance.now();
const template_database = new Map(
Object.entries(prefabDatabase.prefabsByHash).map(([hash, prefabName]) => [
parseInt(hash),
prefabDatabase.prefabs[prefabName] as ObjectTemplate,
]),
);
log.info("Loading Prefab Template Database into VM", template_database);
try {
vm.importTemplateDatabase(template_database);
const now = performance.now();
const time_elapsed = (now - start_time) / 1000;
log.info(`Prefab Template Database loaded in ${time_elapsed} seconds`);
} catch (e) {
if ("stack" in e) {
log.error("Error importing template database:", e.toString(), e.stack);
} else {
log.error("Error importing template database:", e.toString());
}
}
console.info(JSON.stringify(template_database));
}
{
const start_time = performance.now();
const reagent_database = new Map(
Object.entries(prefabDatabase.reagents).map(([_name, entry]) => [
entry.id,
{
id: entry.id satisfies number,
name: entry.name satisfies string,
hash: entry.hash satisfies number,
unit: entry.unit satisfies string,
is_organic: entry.is_organic satisfies boolean,
sources: new Map(Object.entries(entry.sources))
} satisfies Reagent
])
)
log.info("Loading Reagent Database into VM", reagent_database);
try {
vm.importReagentDatabase(reagent_database);
const now = performance.now();
const time_elapsed = (now - start_time) / 1000;
log.info(`Prefab Reagent Database loaded in ${time_elapsed} seconds`);
} catch (e) {
if ("stack" in e) {
log.error("Error importing reagent database:", e.toString(), e.stack);
} else {
log.error("Error importing reagent database:", e.toString());
}
}
}
postMessage("ready");
Comlink.expose(vm);