From 3da16d1f03cc79621c76809003ec30b1711a6efa Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sat, 1 Jun 2024 17:31:24 -0700 Subject: [PATCH] refactor(frontend): Maps are dea dlong live Objects, also delay main body render untill VM is fully loaded --- Cargo.lock | 2 + ic10emu_wasm/Cargo.toml | 1 + ic10emu_wasm/src/lib.rs | 39 +- stationeers_data/Cargo.toml | 1 + stationeers_data/src/templates.rs | 6 + www/src/ts/app/app.ts | 43 +- www/src/ts/index.ts | 2 +- www/src/ts/presets/demo.ts | 38 +- www/src/ts/session.ts | 348 ++--- .../baseDevice.ts | 88 +- .../controls.ts | 2 +- .../device/addDevice.ts} | 48 +- .../device/card.ts | 42 +- .../device/dbutils.ts | 0 .../device/deviceList.ts} | 4 +- .../device/fields.ts | 2 +- .../device/index.ts | 12 +- .../device/pins.ts | 2 +- .../device/slot.ts | 2 +- .../device/slotAddDialog.ts} | 24 +- .../device/template.ts | 102 +- .../index.ts | 19 +- .../prefabDatabase.ts | 2 +- .../registers.ts | 2 +- .../stack.ts | 4 +- .../{virtual_machine => virtualMachine}/ui.ts | 0 www/src/ts/virtualMachine/vmWorker.ts | 42 + www/src/ts/virtual_machine/vmWorker.ts | 1158 ----------------- 28 files changed, 550 insertions(+), 1485 deletions(-) rename www/src/ts/{virtual_machine => virtualMachine}/baseDevice.ts (87%) rename www/src/ts/{virtual_machine => virtualMachine}/controls.ts (99%) rename www/src/ts/{virtual_machine/device/add_device.ts => virtualMachine/device/addDevice.ts} (89%) rename www/src/ts/{virtual_machine => virtualMachine}/device/card.ts (94%) rename www/src/ts/{virtual_machine => virtualMachine}/device/dbutils.ts (100%) rename www/src/ts/{virtual_machine/device/device_list.ts => virtualMachine/device/deviceList.ts} (98%) rename www/src/ts/{virtual_machine => virtualMachine}/device/fields.ts (95%) rename www/src/ts/{virtual_machine => virtualMachine}/device/index.ts (53%) rename www/src/ts/{virtual_machine => virtualMachine}/device/pins.ts (95%) rename www/src/ts/{virtual_machine => virtualMachine}/device/slot.ts (99%) rename www/src/ts/{virtual_machine/device/slot_add_dialog.ts => virtualMachine/device/slotAddDialog.ts} (93%) rename www/src/ts/{virtual_machine => virtualMachine}/device/template.ts (85%) rename www/src/ts/{virtual_machine => virtualMachine}/index.ts (97%) rename www/src/ts/{virtual_machine => virtualMachine}/prefabDatabase.ts (99%) rename www/src/ts/{virtual_machine => virtualMachine}/registers.ts (97%) rename www/src/ts/{virtual_machine => virtualMachine}/stack.ts (94%) rename www/src/ts/{virtual_machine => virtualMachine}/ui.ts (100%) create mode 100644 www/src/ts/virtualMachine/vmWorker.ts delete mode 100644 www/src/ts/virtual_machine/vmWorker.ts diff --git a/Cargo.lock b/Cargo.lock index e87609c..a8ba1fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -654,6 +654,7 @@ dependencies = [ "serde-wasm-bindgen", "serde_derive", "serde_ignored", + "serde_json", "serde_path_to_error", "serde_with", "stationeers_data", @@ -1440,6 +1441,7 @@ dependencies = [ "phf 0.11.2", "serde", "serde_derive", + "serde_with", "strum", "tsify", "wasm-bindgen", diff --git a/ic10emu_wasm/Cargo.toml b/ic10emu_wasm/Cargo.toml index 73264a6..8f08cae 100644 --- a/ic10emu_wasm/Cargo.toml +++ b/ic10emu_wasm/Cargo.toml @@ -25,6 +25,7 @@ serde_with = "3.8.1" tsify = { version = "0.4.5", features = ["json"] } thiserror = "1.0.61" serde_derive = "1.0.203" +serde_json = "1.0.117" [build-dependencies] ic10emu = { path = "../ic10emu" } diff --git a/ic10emu_wasm/src/lib.rs b/ic10emu_wasm/src/lib.rs index a087fb3..86cd082 100644 --- a/ic10emu_wasm/src/lib.rs +++ b/ic10emu_wasm/src/lib.rs @@ -137,8 +137,8 @@ impl VMRef { self.vm.import_template_database(db); } - #[wasm_bindgen(js_name = "importTemplateDatabaseSerde")] - pub fn import_template_database_serde(&self, db: JsValue) -> Result<(), JsError> { + #[wasm_bindgen(js_name = "importTemplateDatabaseSerdeWasm")] + pub fn import_template_database_serde_wasm(&self, db: JsValue) -> Result<(), JsError> { let parsed_db: BTreeMap = parse_value(serde_wasm_bindgen::Deserializer::from(db)).map_err(|err| { <&dyn std::error::Error as std::convert::Into>::into( @@ -148,6 +148,17 @@ impl VMRef { self.vm.import_template_database(parsed_db); Ok(()) } + #[wasm_bindgen(js_name = "importTemplateDatabaseSerdeJson")] + pub fn import_template_database_serde_json(&self, db: String) -> Result<(), JsError> { + let parsed_db: BTreeMap = + parse_value(&mut serde_json::Deserializer::from_str(&db)).map_err(|err| { + <&dyn std::error::Error as std::convert::Into>::into( + std::convert::AsRef::::as_ref(&err), + ) + })?; + self.vm.import_template_database(parsed_db); + Ok(()) + } #[wasm_bindgen(js_name = "getTemplateDatabase")] pub fn get_template_database(&self) -> TemplateDatabase { @@ -240,33 +251,33 @@ impl VMRef { Ok(self.vm.reset_programmable(id)?) } - #[wasm_bindgen(getter, js_name = "defaultNetwork")] - pub fn default_network(&self) -> ObjectID { + #[wasm_bindgen(js_name = "getDefaultNetwork")] + pub fn get_default_network(&self) -> ObjectID { *self.vm.default_network_key.borrow() } - #[wasm_bindgen(getter)] - pub fn objects(&self) -> Vec { + #[wasm_bindgen(js_name = "getObjects")] + pub fn get_objects(&self) -> Vec { self.vm.objects.borrow().keys().copied().collect_vec() } - #[wasm_bindgen(getter)] - pub fn networks(&self) -> Vec { + #[wasm_bindgen(js_name = "getNetworks")] + pub fn get_networks(&self) -> Vec { self.vm.networks.borrow().keys().copied().collect_vec() } - #[wasm_bindgen(getter)] - pub fn circuit_holders(&self) -> Vec { + #[wasm_bindgen(js_name = "getCircuitHolders")] + pub fn get_circuit_holders(&self) -> Vec { self.vm.circuit_holders.borrow().clone() } - #[wasm_bindgen(getter)] - pub fn program_holders(&self) -> Vec { + #[wasm_bindgen(js_name = "getProgramHolders")] + pub fn get_program_holders(&self) -> Vec { self.vm.program_holders.borrow().clone() } - #[wasm_bindgen(getter, js_name = "lastOperationModified")] - pub fn last_operation_modified(&self) -> Vec { + #[wasm_bindgen(js_name = "getLastOperationModified")] + pub fn get_last_operation_modified(&self) -> Vec { self.vm.last_operation_modified() } diff --git a/stationeers_data/Cargo.toml b/stationeers_data/Cargo.toml index 47caab2..4e72fcd 100644 --- a/stationeers_data/Cargo.toml +++ b/stationeers_data/Cargo.toml @@ -15,6 +15,7 @@ num-integer = "0.1.46" phf = "0.11.2" serde = "1.0.202" serde_derive = "1.0.202" +serde_with = "3.8.1" strum = { version = "0.26.2", features = ["derive", "phf", "strum_macros"] } tsify = { version = "0.4.5", optional = true, features = ["json"] } wasm-bindgen = { version = "0.2.92", optional = true } diff --git a/stationeers_data/src/templates.rs b/stationeers_data/src/templates.rs index d3eb3f4..8d1564c 100644 --- a/stationeers_data/src/templates.rs +++ b/stationeers_data/src/templates.rs @@ -5,6 +5,9 @@ use crate::enums::{ script::{LogicSlotType, LogicType}, ConnectionRole, ConnectionType, MachineTier, MemoryAccess, Species, }; + +use serde_with::{serde_as, DisplayFromStr, Map}; + use serde_derive::{Deserialize, Serialize}; #[cfg(feature = "tsify")] use tsify::Tsify; @@ -195,11 +198,14 @@ pub struct SlotInfo { pub typ: Class, } +#[serde_as] #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] #[cfg_attr(feature = "tsify", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))] pub struct LogicInfo { + #[serde_as( as = "BTreeMap")] pub logic_slot_types: BTreeMap>, pub logic_types: BTreeMap, + #[serde_as( as = "Option>")] pub modes: Option>, pub transmission_receiver: bool, pub wireless_logic: bool, diff --git a/www/src/ts/app/app.ts b/www/src/ts/app/app.ts index cc5828d..3a7c53d 100644 --- a/www/src/ts/app/app.ts +++ b/www/src/ts/app/app.ts @@ -7,10 +7,10 @@ import { ShareSessionDialog } from "./share"; import "../editor"; import { IC10Editor } from "../editor"; import { Session } from "../session"; -import { VirtualMachine } from "../virtual_machine"; +import { VirtualMachine } from "../virtualMachine"; import { openFile, saveFile } from "../utils"; -import "../virtual_machine/ui"; +import "../virtualMachine/ui"; import "./save"; import { SaveDialog } from "./save"; import "./welcome"; @@ -22,6 +22,7 @@ declare global { } import packageJson from "../../../package.json" +import { until } from "lit/directives/until.js"; @customElement("ic10emu-app") export class App extends BaseElement { @@ -83,20 +84,38 @@ export class App extends BaseElement { } protected render(): HTMLTemplateResult { + const mainBody = window.VM.get().then(vm => { + return html` + + +
+
+ `; + }); return html`
- - -
-
+ ${until( + mainBody, + html` +
+
+

+ Loading Ic10 Virtual Machine + + +

+
+
+ ` + )}
diff --git a/www/src/ts/index.ts b/www/src/ts/index.ts index 07daf7e..61798f8 100644 --- a/www/src/ts/index.ts +++ b/www/src/ts/index.ts @@ -111,6 +111,6 @@ window.App = new DeferedApp(); window.VM = new DeferedVM(); import type { App } from "./app"; -import type { VirtualMachine } from "./virtual_machine"; +import type { VirtualMachine } from "./virtualMachine"; import("./app"); diff --git a/www/src/ts/presets/demo.ts b/www/src/ts/presets/demo.ts index 03aed6f..09bc94c 100644 --- a/www/src/ts/presets/demo.ts +++ b/www/src/ts/presets/demo.ts @@ -72,9 +72,12 @@ export const demoVMState: SessionDB.CurrentDBVmState = { id: 1, prefab: "StructureCircuitHousing", socketed_ic: 2, - slots: new Map([[0, { id: 2, quantity: 1 }]]), - connections: new Map([[0, 1]]), - + slots: { + 0: { id: 2, quantity: 1 }, + }, + connections: { + 0: 1, + }, // unused, provided to make compiler happy name: undefined, prefab_hash: undefined, @@ -88,7 +91,7 @@ export const demoVMState: SessionDB.CurrentDBVmState = { visible_devices: undefined, memory: undefined, source_code: undefined, - circuit: undefined + circuit: undefined, }, template: undefined, database_template: true, @@ -103,10 +106,10 @@ export const demoVMState: SessionDB.CurrentDBVmState = { instruction_pointer: 0, yield_instruction_count: 0, state: "Start", - aliases: new Map(), - defines: new Map(), - labels: new Map(), - registers: new Array(18).fill(0) + aliases: {}, + defines: {}, + labels: {}, + registers: new Array(18).fill(0), }, // unused, provided to make compiler happy @@ -125,16 +128,25 @@ export const demoVMState: SessionDB.CurrentDBVmState = { visible_devices: undefined, }, template: undefined, - database_template: true - } + database_template: true, + }, ], networks: [ { id: 1, devices: [1], power_only: [], - channels: Array(8).fill(NaN) as [number, number, number, number, number, number, number, number], - } + channels: Array(8).fill(NaN) as [ + number, + number, + number, + number, + number, + number, + number, + number, + ], + }, ], program_holders: [2], circuit_holders: [1], @@ -143,4 +155,4 @@ export const demoVMState: SessionDB.CurrentDBVmState = { wireless_transmitters: [], }, activeIC: 1, -} +}; diff --git a/www/src/ts/session.ts b/www/src/ts/session.ts index d02f15c..641e510 100644 --- a/www/src/ts/session.ts +++ b/www/src/ts/session.ts @@ -1,19 +1,39 @@ -import type { ICError, FrozenVM, RegisterSpec, DeviceSpec, LogicType, LogicSlotType, LogicField, Class as SlotType, FrozenCableNetwork, FrozenObject, ObjectInfo, ICState, ObjectID } from "ic10emu_wasm"; +import type { + ICError, + FrozenVM, + RegisterSpec, + DeviceSpec, + LogicType, + LogicSlotType, + LogicField, + Class as SlotType, + FrozenCableNetwork, + FrozenObject, + ObjectInfo, + ICState, + ObjectID, +} from "ic10emu_wasm"; import { App } from "./app"; import { openDB, DBSchema, IDBPTransaction, IDBPDatabase } from "idb"; -import { TypedEventTarget, crc32, dispatchTypedEvent, fromJson, toJson } from "./utils"; +import { + TypedEventTarget, + crc32, + dispatchTypedEvent, + fromJson, + toJson, +} from "./utils"; import * as presets from "./presets"; const { demoVMState } = presets; export interface SessionEventMap { - "sessions-local-update": CustomEvent, - "session-active-ic": CustomEvent, - "session-id-change": CustomEvent<{ old: ObjectID, new: ObjectID }>, - "session-errors": CustomEvent, - "session-load": CustomEvent, - "active-line": CustomEvent, + "sessions-local-update": CustomEvent; + "session-active-ic": CustomEvent; + "session-id-change": CustomEvent<{ old: ObjectID; new: ObjectID }>; + "session-errors": CustomEvent; + "session-load": CustomEvent; + "active-line": CustomEvent; } export class Session extends TypedEventTarget() { @@ -66,16 +86,14 @@ export class Session extends TypedEventTarget() { this.programs.set(newID, this.programs.get(oldID)); this.programs.delete(oldID); } - this.dispatchCustomEvent("session-id-change", { old: oldID, new: newID }) + this.dispatchCustomEvent("session-id-change", { old: oldID, new: newID }); } - onIDChange( - callback: (e: CustomEvent<{ old: number; new: number }>) => any, - ) { + onIDChange(callback: (e: CustomEvent<{ old: number; new: number }>) => any) { this.addEventListener("session-id-change", callback); } - onActiveIc(callback: (e: CustomEvent) => any,) { + onActiveIc(callback: (e: CustomEvent) => any) { this.addEventListener("session-active-ic", callback); } @@ -168,8 +186,9 @@ export class Session extends TypedEventTarget() { // assign first so it's present when the // vm fires events this._activeIC = data.activeIC; - this.app.vm.restoreVMState(state); - this.programs = this.app.vm.getPrograms(); + const vm = await window.VM.get() + await vm.restoreVMState(state); + this.programs = vm.getPrograms(); // assign again to fire event this.activeIC = data.activeIC; } @@ -205,31 +224,36 @@ export class Session extends TypedEventTarget() { } async openIndexDB() { - return await openDB("ic10-vm-sessions", SessionDB.LOCAL_DB_VERSION, { - async upgrade(db, oldVersion, newVersion, transaction, event) { - if (oldVersion < SessionDB.DBVersion.V1) { - const sessionStore = db.createObjectStore("sessions"); - sessionStore.createIndex("by-date", "date"); - sessionStore.createIndex("by-name", "name"); - } - if (oldVersion < SessionDB.DBVersion.V2) { - const v1Transaction = transaction as unknown as IDBPTransaction; - const v1SessionStore = v1Transaction.objectStore("sessions"); - const v1Sessions = await v1SessionStore.getAll(); - const v2SessionStore = db.createObjectStore("sessionsV2"); - v2SessionStore.createIndex("by-date", "date"); - v2SessionStore.createIndex("by-name", "name"); - for (const v1Session of v1Sessions) { - await v2SessionStore.add({ - name: v1Session.name, - date: v1Session.date, - version: SessionDB.DBVersion.V2, - session: SessionDB.V2.fromV1State(v1Session.session) - }) + return await openDB( + "ic10-vm-sessions", + SessionDB.LOCAL_DB_VERSION, + { + async upgrade(db, oldVersion, newVersion, transaction, event) { + if (oldVersion < SessionDB.DBVersion.V1) { + const sessionStore = db.createObjectStore("sessions"); + sessionStore.createIndex("by-date", "date"); + sessionStore.createIndex("by-name", "name"); } - } + if (oldVersion < SessionDB.DBVersion.V2) { + const v1Transaction = + transaction as unknown as IDBPTransaction; + const v1SessionStore = v1Transaction.objectStore("sessions"); + const v1Sessions = await v1SessionStore.getAll(); + const v2SessionStore = db.createObjectStore("sessionsV2"); + v2SessionStore.createIndex("by-date", "date"); + v2SessionStore.createIndex("by-name", "name"); + for (const v1Session of v1Sessions) { + await v2SessionStore.add({ + name: v1Session.name, + date: v1Session.date, + version: SessionDB.DBVersion.V2, + session: SessionDB.V2.fromV1State(v1Session.session), + }); + } + } + }, }, - }); + ); } async saveLocal(name: string) { @@ -238,8 +262,13 @@ export class Session extends TypedEventTarget() { activeIC: this.activeIC, }; const db = await this.openIndexDB(); - const transaction = db.transaction([SessionDB.LOCAL_DB_SESSION_STORE], "readwrite"); - const sessionStore = transaction.objectStore(SessionDB.LOCAL_DB_SESSION_STORE); + const transaction = db.transaction( + [SessionDB.LOCAL_DB_SESSION_STORE], + "readwrite", + ); + const sessionStore = transaction.objectStore( + SessionDB.LOCAL_DB_SESSION_STORE, + ); await sessionStore.put( { name, @@ -263,8 +292,13 @@ export class Session extends TypedEventTarget() { async deleteLocalSave(name: string) { const db = await this.openIndexDB(); - const transaction = db.transaction([SessionDB.LOCAL_DB_SESSION_STORE], "readwrite"); - const sessionStore = transaction.objectStore(SessionDB.LOCAL_DB_SESSION_STORE); + const transaction = db.transaction( + [SessionDB.LOCAL_DB_SESSION_STORE], + "readwrite", + ); + const sessionStore = transaction.objectStore( + SessionDB.LOCAL_DB_SESSION_STORE, + ); await sessionStore.delete(name); this.dispatchCustomEvent("sessions-local-update"); } @@ -276,9 +310,7 @@ export class Session extends TypedEventTarget() { } export namespace SessionDB { - export namespace V1 { - export interface VMState { activeIC: number; vm: FrozenVM; @@ -306,14 +338,14 @@ export namespace SessionDB { export type DeviceSpec = { readonly DeviceSpec: { readonly device: - | "Db" - | { readonly Numbered: number } - | { - readonly Indirect: { - readonly indirection: number; - readonly target: number; - }; - }; + | "Db" + | { readonly Numbered: number } + | { + readonly Indirect: { + readonly indirection: number; + readonly target: number; + }; + }; readonly connection: number | undefined; }; }; @@ -363,11 +395,9 @@ export namespace SessionDB { state: string; code: string; } - } export namespace V2 { - export interface VMState { activeIC: number; vm: FrozenVM; @@ -387,9 +417,9 @@ export namespace SessionDB { instruction_pointer: ic.ip, yield_instruction_count: ic.ic, state: ic.state as ICState, - aliases: ic.aliases, - defines: ic.defines, - labels: new Map(), + aliases: Object.fromEntries(ic.aliases.entries()), + defines: Object.fromEntries(ic.defines.entries()), + labels: {}, registers: ic.registers, }, @@ -407,110 +437,135 @@ export namespace SessionDB { }, database_template: true, template: undefined, - } + }; } - function objectsFromV1Template(template: SessionDB.V1.DeviceTemplate, idFn: () => number, socketedIcFn: (id: number) => number | undefined): FrozenObject[] { - const slotOccupantsPairs = new Map(template.slots.flatMap((slot, index) => { - if (typeof slot.occupant !== "undefined") { - return [ - [ - index, + function objectsFromV1Template( + template: SessionDB.V1.DeviceTemplate, + idFn: () => number, + socketedIcFn: (id: number) => number | undefined, + ): FrozenObject[] { + const slotOccupantsPairs = new Map( + template.slots.flatMap((slot, index) => { + if (typeof slot.occupant !== "undefined") { + return [ [ - { - obj_info: { - name: undefined, - id: slot.occupant.id ?? idFn(), - prefab: undefined, - prefab_hash: slot.occupant.fields.PrefabHash?.value, - damage: slot.occupant.fields.Damage?.value, + index, + [ + { + obj_info: { + name: undefined, + id: slot.occupant.id ?? idFn(), + prefab: undefined, + prefab_hash: slot.occupant.fields.PrefabHash?.value, + damage: slot.occupant.fields.Damage?.value, - socketed_ic: undefined, - // unused - memory: undefined, - source_code: undefined, - compile_errors: undefined, - circuit: undefined, - slots: undefined, - device_pins: undefined, - connections: undefined, - reagents: undefined, - logic_values: undefined, - slot_logic_values: undefined, - entity: undefined, - visible_devices: undefined, + socketed_ic: undefined, + // unused + memory: undefined, + source_code: undefined, + compile_errors: undefined, + circuit: undefined, + slots: undefined, + device_pins: undefined, + connections: undefined, + reagents: undefined, + logic_values: undefined, + slot_logic_values: undefined, + entity: undefined, + visible_devices: undefined, + }, + database_template: true, + template: undefined, }, - database_template: true, - template: undefined - }, - slot.occupant.fields.Quantity ?? 1 - ] - ] - ] as [number, [FrozenObject, number]][]; - } else { - return [] as [number, [FrozenObject, number]][]; - } - })); - return [ - ...Array.from(slotOccupantsPairs.entries()).map(([_index, [obj, _quantity]]) => obj), - { - obj_info: { - name: template.name, - id: template.id, - prefab: template.prefab_name, - prefab_hash: undefined, - slots: new Map( - Array.from(slotOccupantsPairs.entries()) - .map(([index, [obj, quantity]]) => [index, { + slot.occupant.fields.Quantity ?? 1, + ], + ], + ] as [number, [FrozenObject, number]][]; + } else { + return [] as [number, [FrozenObject, number]][]; + } + }), + ); + const frozen: FrozenObject = { + obj_info: { + name: template.name, + id: template.id, + prefab: template.prefab_name, + prefab_hash: undefined, + slots: Object.fromEntries( + Array.from(slotOccupantsPairs.entries()).map( + ([index, [obj, quantity]]) => [ + index, + { quantity, id: obj.obj_info.id, - }]) + }, + ], ), - socketed_ic: socketedIcFn(template.id), + ), + socketed_ic: socketedIcFn(template.id), - logic_values: new Map(Object.entries(template.fields).map(([key, val]) => { - return [key as LogicType, val.value] - })), + logic_values: Object.fromEntries( + Object.entries(template.fields).map(([key, val]) => { + return [key, val.value]; + }), + ) as Record, - // unused - memory: undefined, - source_code: undefined, - compile_errors: undefined, - circuit: undefined, - damage: undefined, - device_pins: undefined, - connections: undefined, - reagents: undefined, - slot_logic_values: undefined, - entity: undefined, - visible_devices: undefined, - - }, - database_template: true, - template: undefined, - } + // unused + memory: undefined, + source_code: undefined, + compile_errors: undefined, + circuit: undefined, + damage: undefined, + device_pins: undefined, + connections: undefined, + reagents: undefined, + slot_logic_values: undefined, + entity: undefined, + visible_devices: undefined, + }, + database_template: true, + template: undefined, + }; + return [ + ...Array.from(slotOccupantsPairs.entries()).map( + ([_index, [obj, _quantity]]) => obj, + ), + frozen, ]; } export function fromV1State(v1State: SessionDB.V1.VMState): VMState { - const highestObjetId = Math.max(... - v1State.vm - .devices - .map(device => device.id ?? -1) - .concat( - v1State.vm - .ics - .map(ic => ic.id ?? -1) - ) + const highestObjetId = Math.max( + ...v1State.vm.devices + .map((device) => device.id ?? -1) + .concat(v1State.vm.ics.map((ic) => ic.id ?? -1)), ); let nextId = highestObjetId + 1; - const deviceIcs = new Map(v1State.vm.ics.map(ic => [ic.device, objectFromIC(ic)])); - const objects = v1State.vm.devices.flatMap(device => { - return objectsFromV1Template(device, () => nextId++, (id) => deviceIcs.get(id)?.obj_info.id ?? undefined) - }) + const deviceIcs = new Map( + v1State.vm.ics.map((ic) => [ic.device, objectFromIC(ic)]), + ); + const objects = v1State.vm.devices.flatMap((device) => { + return objectsFromV1Template( + device, + () => nextId++, + (id) => deviceIcs.get(id)?.obj_info.id ?? undefined, + ); + }); const vm: FrozenVM = { objects, - circuit_holders: objects.flatMap(obj => "socketed_ic" in obj.obj_info && typeof obj.obj_info.socketed_ic !== "undefined" ? [obj.obj_info.id] : []), - program_holders: objects.flatMap(obj => "source_code" in obj.obj_info && typeof obj.obj_info.source_code !== "undefined" ? [obj.obj_info.id] : []), + circuit_holders: objects.flatMap((obj) => + "socketed_ic" in obj.obj_info && + typeof obj.obj_info.socketed_ic !== "undefined" + ? [obj.obj_info.id] + : [], + ), + program_holders: objects.flatMap((obj) => + "source_code" in obj.obj_info && + typeof obj.obj_info.source_code !== "undefined" + ? [obj.obj_info.id] + : [], + ), default_network_key: v1State.vm.default_network, networks: v1State.vm.networks as FrozenCableNetwork[], wireless_receivers: [], @@ -522,7 +577,6 @@ export namespace SessionDB { }; return v2State; } - } export enum DBVersion { @@ -533,7 +587,7 @@ export namespace SessionDB { export const LOCAL_DB_VERSION = DBVersion.V2 as const; export type CurrentDBSchema = AppDBSchemaV2; export type CurrentDBVmState = V2.VMState; - export const LOCAL_DB_SESSION_STORE = "sessionsV2" as const + export const LOCAL_DB_SESSION_STORE = "sessionsV2" as const; export interface AppDBSchemaV1 extends DBSchema { sessions: { @@ -579,8 +633,6 @@ export namespace SessionDB { } } - - export interface OldPrograms { programs: [number, string][]; } diff --git a/www/src/ts/virtual_machine/baseDevice.ts b/www/src/ts/virtualMachine/baseDevice.ts similarity index 87% rename from www/src/ts/virtual_machine/baseDevice.ts rename to www/src/ts/virtualMachine/baseDevice.ts index 6f910bb..0d84630 100644 --- a/www/src/ts/virtual_machine/baseDevice.ts +++ b/www/src/ts/virtualMachine/baseDevice.ts @@ -260,17 +260,22 @@ export const VMObjectMixin = >( ) ) { const logicValues = - this.obj.obj_info.logic_values ?? new Map(); + this.obj.obj_info.logic_values != null + ? (new Map(Object.entries(this.obj.obj_info.logic_values)) as Map< + LogicType, + number + >) + : null; const logicTemplate = "logic" in this.obj.template ? this.obj.template.logic : null; newFields = new Map( - Array.from(logicTemplate?.logic_types.entries() ?? []).map( + Array.from(Object.entries(logicTemplate?.logic_types) ?? []).map( ([lt, access]) => { let field: LogicField = { field_type: access, - value: logicValues.get(lt) ?? 0, + value: logicValues.get(lt as LogicType) ?? 0, }; - return [lt, field]; + return [lt as LogicType, field]; }, ), ); @@ -289,25 +294,44 @@ export const VMObjectMixin = >( ) ) { const slotsOccupantInfo = - this.obj.obj_info.slots ?? new Map(); + this.obj.obj_info.slots != null + ? new Map( + Object.entries(this.obj.obj_info.slots).map(([key, val]) => [ + parseInt(key), + val, + ]), + ) + : null; const slotsLogicValues = - this.obj.obj_info.slot_logic_values ?? - new Map>(); + this.obj.obj_info.slot_logic_values != null + ? new Map>( + Object.entries(this.obj.obj_info.slot_logic_values).map( + ([index, values]) => [ + parseInt(index), + new Map(Object.entries(values)) as Map< + LogicSlotType, + number + >, + ], + ), + ) + : null; const logicTemplate = "logic" in this.obj.template ? this.obj.template.logic : null; const slotsTemplate = "slots" in this.obj.template ? this.obj.template.slots : []; newSlots = slotsTemplate.map((template, index) => { const fieldEntryInfos = Array.from( - logicTemplate?.logic_slot_types.get(index).entries() ?? [], + Object.entries(logicTemplate?.logic_slot_types[index]) ?? [], ); const logicFields = new Map( fieldEntryInfos.map(([slt, access]) => { let field: LogicField = { field_type: access, - value: slotsLogicValues.get(index)?.get(slt) ?? 0, + value: + slotsLogicValues.get(index)?.get(slt as LogicSlotType) ?? 0, }; - return [slt, field]; + return [slt as LogicSlotType, field]; }), ); let occupantInfo = slotsOccupantInfo.get(index); @@ -366,12 +390,26 @@ export const VMObjectMixin = >( this.slotsCount = slotsCount; } } else if (sub === "reagents") { - const reagents = this.obj.obj_info.reagents; + const reagents = + this.obj.obj_info.reagents != null + ? new Map( + Object.entries(this.obj.obj_info.reagents).map( + ([key, val]) => [parseInt(key), val], + ), + ) + : null; if (!structuralEqual(this.reagents, reagents)) { this.reagents = reagents; } } else if (sub === "connections") { - const connectionsMap = this.obj.obj_info.connections ?? new Map(); + const connectionsMap = + this.obj.obj_info.connections != null + ? new Map( + Object.entries(this.obj.obj_info.connections).map( + ([key, val]) => [parseInt(key), val], + ), + ) + : null; const connectionList = "device" in this.obj.template ? this.obj.template.device.connection_list @@ -483,15 +521,31 @@ export const VMObjectMixin = >( if (!structuralEqual(this.registers, registers)) { this.registers = registers; } - const aliases = this.obj.obj_info.circuit?.aliases ?? null; + const aliases = + this.obj.obj_info.circuit?.aliases != null + ? new Map(Object.entries(this.obj.obj_info.circuit.aliases)) + : null; if (!structuralEqual(this.aliases, aliases)) { this.aliases = aliases; } - const defines = this.obj.obj_info.circuit?.defines ?? null; + const defines = + this.obj.obj_info.circuit?.defines != null + ? new Map( + Object.entries(this.obj.obj_info.circuit.defines), + // .map(([key, val]) => []) + ) + : null; if (!structuralEqual(this.defines, defines)) { - this.defines = defines; + this.defines = new Map(defines); } - const pins = this.obj.obj_info.device_pins ?? new Map(); + const pins = + this.obj.obj_info.device_pins != null + ? new Map( + Object.entries(this.obj.obj_info.device_pins).map( + ([key, val]) => [parseInt(key), val], + ), + ) + : null; if (!structuralEqual(this.pins, pins)) { this.pins = pins; this.numPins = @@ -590,7 +644,7 @@ export const VMTemplateDBMixin = >( return this._templateDB; } - postDBSetUpdate(): void { } + postDBSetUpdate(): void {} @state() set templateDB(val: TemplateDatabase) { diff --git a/www/src/ts/virtual_machine/controls.ts b/www/src/ts/virtualMachine/controls.ts similarity index 99% rename from www/src/ts/virtual_machine/controls.ts rename to www/src/ts/virtualMachine/controls.ts index 7b65585..4a712d0 100644 --- a/www/src/ts/virtual_machine/controls.ts +++ b/www/src/ts/virtualMachine/controls.ts @@ -1,7 +1,7 @@ import { html, css } from "lit"; import { customElement, query } from "lit/decorators.js"; import { BaseElement, defaultCss } from "components"; -import { VMActiveICMixin } from "virtual_machine/baseDevice"; +import { VMActiveICMixin } from "virtualMachine/baseDevice"; import SlSelect from "@shoelace-style/shoelace/dist/components/select/select.js"; diff --git a/www/src/ts/virtual_machine/device/add_device.ts b/www/src/ts/virtualMachine/device/addDevice.ts similarity index 89% rename from www/src/ts/virtual_machine/device/add_device.ts rename to www/src/ts/virtualMachine/device/addDevice.ts index 3591423..f824483 100644 --- a/www/src/ts/virtual_machine/device/add_device.ts +++ b/www/src/ts/virtualMachine/device/addDevice.ts @@ -10,7 +10,7 @@ import { cache } from "lit/directives/cache.js"; import { default as uFuzzy } from "@leeoniya/ufuzzy"; import { when } from "lit/directives/when.js"; import { unsafeHTML } from "lit/directives/unsafe-html.js"; -import { VMTemplateDBMixin } from "virtual_machine/baseDevice"; +import { VMTemplateDBMixin } from "virtualMachine/baseDevice"; import { LogicInfo, ObjectTemplate, StructureInfo } from "ic10emu_wasm"; type LogicableStrucutureTemplate = Extract< @@ -44,7 +44,7 @@ export class VMAddDeviceButton extends VMTemplateDBMixin(BaseElement) { postDBSetUpdate(): void { this._structures = new Map( - Array.from(this.templateDB.values()).flatMap((template) => { + Array.from(Object.values(this.templateDB)).flatMap((template) => { if ("structure" in template && "logic" in template) { return [[template.prefab.prefab_name, template]] as [ string, @@ -162,7 +162,7 @@ export class VMAddDeviceButton extends VMTemplateDBMixin(BaseElement) { } return when( typeof this._searchResults !== "undefined" && - this._searchResults.length < 20, + this._searchResults.length < 20, () => repeat( this._searchResults ?? [], @@ -189,33 +189,33 @@ export class VMAddDeviceButton extends VMTemplateDBMixin(BaseElement) {
Page: ${pageKeys.map( - (key, index) => html` + (key, index) => html` ${key + 1}${index < totalPages - 1 ? "," : ""} `, - )} + )}
${[ - ...this._searchResults.slice( - perPage * this.page, - perPage * this.page + perPage, - ), - ...extra, - ].map((result) => { - let hay = result.haystackEntry.slice(0, 15); - if (result.haystackEntry.length > 15) hay += "..."; - const ranges = result.ranges.filter((pos) => pos < 20); - const key = result.entry.prefab.prefab_name; - return html` + ...this._searchResults.slice( + perPage * this.page, + perPage * this.page + perPage, + ), + ...extra, + ].map((result) => { + let hay = result.haystackEntry.slice(0, 15); + if (result.haystackEntry.length > 15) hay += "..."; + const ranges = result.ranges.filter((pos) => pos < 20); + const key = result.entry.prefab.prefab_name; + return html`
${result.entry.prefab.name} ( ${ranges.length - ? unsafeHTML(uFuzzy.highlight(hay, ranges)) - : hay} )
`; - })} + })}
`, @@ -284,8 +284,8 @@ export class VMAddDeviceButton extends VMTemplateDBMixin(BaseElement) { slot="footer" variant="primary" @click=${() => { - this.drawer.hide(); - }} + this.drawer.hide(); + }} > Close diff --git a/www/src/ts/virtual_machine/device/card.ts b/www/src/ts/virtualMachine/device/card.ts similarity index 94% rename from www/src/ts/virtual_machine/device/card.ts rename to www/src/ts/virtualMachine/device/card.ts index 3bc2bdd..8f79967 100644 --- a/www/src/ts/virtual_machine/device/card.ts +++ b/www/src/ts/virtualMachine/device/card.ts @@ -1,7 +1,7 @@ import { html, css, HTMLTemplateResult } from "lit"; import { customElement, property, query, state } from "lit/decorators.js"; import { BaseElement, defaultCss } from "components"; -import { VMTemplateDBMixin, VMObjectMixin } from "virtual_machine/baseDevice"; +import { VMTemplateDBMixin, VMObjectMixin } from "virtualMachine/baseDevice"; import SlSelect from "@shoelace-style/shoelace/dist/components/select/select.component.js"; import { parseIntWithHexOrBinary, parseNumber } from "utils"; import SlInput from "@shoelace-style/shoelace/dist/components/input/input.component.js"; @@ -148,8 +148,14 @@ export class VMDeviceCard extends VMTemplateDBMixin( "device" in activeIc?.template ? activeIc.template.device.device_pins_length : Math.max( - ...Array.from(activeIc?.obj_info.device_pins?.keys() ?? [0]), - ); + ...Array.from( + activeIc?.obj_info.device_pins != null + ? Object.keys(activeIc?.obj_info.device_pins).map((key) => + parseInt(key), + ) + : [0], + ), + ); const pins = new Array(numPins) .fill(true) .map((_, index) => this.pins.get(index)); @@ -217,8 +223,8 @@ export class VMDeviceCard extends VMTemplateDBMixin(
${repeat( - this.slots, - (slot, index) => slot.typ + index.toString(), - (_slot, index) => html` + this.slots, + (slot, index) => slot.typ + index.toString(), + (_slot, index) => html` `, - )} + )}
`, ); @@ -287,11 +293,11 @@ export class VMDeviceCard extends VMTemplateDBMixin( > Connection:${index} ${vmNetworks.map( - (net) => - html` + html`Network ${net}`, - )} + )} ${conn?.typ} `; @@ -318,12 +324,12 @@ export class VMDeviceCard extends VMTemplateDBMixin( resolver?: (result: HTMLTemplateResult) => void; }; } = { - fields: {}, - slots: {}, - reagents: {}, - networks: {}, - pins: {}, - }; + fields: {}, + slots: {}, + reagents: {}, + networks: {}, + pins: {}, + }; delayRenderTab( name: CardTab, diff --git a/www/src/ts/virtual_machine/device/dbutils.ts b/www/src/ts/virtualMachine/device/dbutils.ts similarity index 100% rename from www/src/ts/virtual_machine/device/dbutils.ts rename to www/src/ts/virtualMachine/device/dbutils.ts diff --git a/www/src/ts/virtual_machine/device/device_list.ts b/www/src/ts/virtualMachine/device/deviceList.ts similarity index 98% rename from www/src/ts/virtual_machine/device/device_list.ts rename to www/src/ts/virtualMachine/device/deviceList.ts index bac5259..e9ef09f 100644 --- a/www/src/ts/virtual_machine/device/device_list.ts +++ b/www/src/ts/virtualMachine/device/deviceList.ts @@ -7,8 +7,8 @@ import { structuralEqual } from "utils"; import { repeat } from "lit/directives/repeat.js"; import { default as uFuzzy } from "@leeoniya/ufuzzy"; -import { VMSlotAddDialog } from "./slot_add_dialog"; -import "./add_device" +import { VMSlotAddDialog } from "./slotAddDialog"; +import "./addDevice" import { SlotModifyEvent } from "./slot"; @customElement("vm-device-list") diff --git a/www/src/ts/virtual_machine/device/fields.ts b/www/src/ts/virtualMachine/device/fields.ts similarity index 95% rename from www/src/ts/virtual_machine/device/fields.ts rename to www/src/ts/virtualMachine/device/fields.ts index ea2d432..7016872 100644 --- a/www/src/ts/virtual_machine/device/fields.ts +++ b/www/src/ts/virtualMachine/device/fields.ts @@ -1,7 +1,7 @@ import { html, css } from "lit"; import { customElement, property } from "lit/decorators.js"; import { BaseElement, defaultCss } from "components"; -import { VMTemplateDBMixin, VMObjectMixin } from "virtual_machine/baseDevice"; +import { VMTemplateDBMixin, VMObjectMixin } from "virtualMachine/baseDevice"; import { displayNumber, parseNumber } from "utils"; import type { LogicType } from "ic10emu_wasm"; import SlInput from "@shoelace-style/shoelace/dist/components/input/input.component.js"; diff --git a/www/src/ts/virtual_machine/device/index.ts b/www/src/ts/virtualMachine/device/index.ts similarity index 53% rename from www/src/ts/virtual_machine/device/index.ts rename to www/src/ts/virtualMachine/device/index.ts index 4b1d15a..2920e00 100644 --- a/www/src/ts/virtual_machine/device/index.ts +++ b/www/src/ts/virtualMachine/device/index.ts @@ -1,15 +1,15 @@ import "./template" import "./card" -import "./device_list" -import "./add_device" -import "./slot_add_dialog" +import "./deviceList" +import "./addDevice" +import "./slotAddDialog" import "./slot" import { VmObjectTemplate } from "./template"; import { VMDeviceCard } from "./card"; -import { VMDeviceList } from "./device_list"; -import { VMAddDeviceButton } from "./add_device"; -import { VMSlotAddDialog } from "./slot_add_dialog"; +import { VMDeviceList } from "./deviceList"; +import { VMAddDeviceButton } from "./addDevice"; +import { VMSlotAddDialog } from "./slotAddDialog"; export { VMDeviceCard, VmObjectTemplate as VmDeviceTemplate, VMDeviceList, VMAddDeviceButton, VMSlotAddDialog }; diff --git a/www/src/ts/virtual_machine/device/pins.ts b/www/src/ts/virtualMachine/device/pins.ts similarity index 95% rename from www/src/ts/virtual_machine/device/pins.ts rename to www/src/ts/virtualMachine/device/pins.ts index 86595c8..93d47e7 100644 --- a/www/src/ts/virtual_machine/device/pins.ts +++ b/www/src/ts/virtualMachine/device/pins.ts @@ -1,7 +1,7 @@ import { html, css } from "lit"; import { customElement, property } from "lit/decorators.js"; import { BaseElement, defaultCss } from "components"; -import { VMTemplateDBMixin, VMObjectMixin } from "virtual_machine/baseDevice"; +import { VMTemplateDBMixin, VMObjectMixin } from "virtualMachine/baseDevice"; import SlSelect from "@shoelace-style/shoelace/dist/components/select/select.component.js"; import { ObjectID } from "ic10emu_wasm"; diff --git a/www/src/ts/virtual_machine/device/slot.ts b/www/src/ts/virtualMachine/device/slot.ts similarity index 99% rename from www/src/ts/virtual_machine/device/slot.ts rename to www/src/ts/virtualMachine/device/slot.ts index 2ef6351..82ab084 100644 --- a/www/src/ts/virtual_machine/device/slot.ts +++ b/www/src/ts/virtualMachine/device/slot.ts @@ -1,7 +1,7 @@ import { html, css } from "lit"; import { customElement, property} from "lit/decorators.js"; import { BaseElement, defaultCss } from "components"; -import { VMTemplateDBMixin, VMObjectMixin } from "virtual_machine/baseDevice"; +import { VMTemplateDBMixin, VMObjectMixin } from "virtualMachine/baseDevice"; import { clamp, crc32, diff --git a/www/src/ts/virtual_machine/device/slot_add_dialog.ts b/www/src/ts/virtualMachine/device/slotAddDialog.ts similarity index 93% rename from www/src/ts/virtual_machine/device/slot_add_dialog.ts rename to www/src/ts/virtualMachine/device/slotAddDialog.ts index 67dacc2..de6fd41 100644 --- a/www/src/ts/virtual_machine/device/slot_add_dialog.ts +++ b/www/src/ts/virtualMachine/device/slotAddDialog.ts @@ -1,7 +1,7 @@ import { html, css } from "lit"; import { customElement, property, query, state } from "lit/decorators.js"; import { BaseElement, defaultCss } from "components"; -import { VMTemplateDBMixin } from "virtual_machine/baseDevice"; +import { 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"; @@ -62,7 +62,7 @@ export class VMSlotAddDialog extends VMTemplateDBMixin(BaseElement) { postDBSetUpdate(): void { this._items = new Map( - Array.from(this.templateDB.values()).flatMap((template) => { + Array.from(Object.values(this.templateDB)).flatMap((template) => { if ("item" in template) { return [[template.prefab.prefab_name, template]] as [ string, @@ -160,15 +160,15 @@ export class VMSlotAddDialog extends VMTemplateDBMixin(BaseElement) {
${enableNone ? none : ""} ${this._searchResults.map((result) => { - const imgSrc = `img/stationpedia/${result.entry.prefab.prefab_name}.png`; - const img = html` + const imgSrc = `img/stationpedia/${result.entry.prefab.prefab_name}.png`; + const img = html` `; - return html` + return html`
${result.entry.prefab.name}
`; - })} + })} `; } @@ -191,7 +191,7 @@ export class VMSlotAddDialog extends VMTemplateDBMixin(BaseElement) { _handleClickItem(e: Event) { const div = e.currentTarget as HTMLDivElement; const key = parseInt(div.getAttribute("key")); - const entry = this.templateDB.get(key) as SlotableItemTemplate; + const entry = this.templateDB[key] as SlotableItemTemplate; const obj = window.VM.vm.objects.get(this.objectID); const dbTemplate = obj.template; console.log("using entry", dbTemplate); @@ -231,15 +231,15 @@ export class VMSlotAddDialog extends VMTemplateDBMixin(BaseElement) { ${when( - typeof this.objectID !== "undefined" && - typeof this.slotIndex !== "undefined", - () => html` + typeof this.objectID !== "undefined" && + typeof this.slotIndex !== "undefined", + () => html`
${this.renderSearchResults()}
`, - () => html``, - )} + () => html``, + )} `; } diff --git a/www/src/ts/virtual_machine/device/template.ts b/www/src/ts/virtualMachine/device/template.ts similarity index 85% rename from www/src/ts/virtual_machine/device/template.ts rename to www/src/ts/virtualMachine/device/template.ts index eb79b41..5970b77 100644 --- a/www/src/ts/virtual_machine/device/template.ts +++ b/www/src/ts/virtualMachine/device/template.ts @@ -24,12 +24,12 @@ 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 "virtual_machine/baseDevice"; +import { VMTemplateDBMixin } from "virtualMachine/baseDevice"; export interface SlotTemplate { - typ: Class - quantity: number, - occupant?: FrozenObject, + typ: Class; + quantity: number; + occupant?: FrozenObject; } export interface ConnectionCableNetwork { @@ -42,7 +42,6 @@ export interface ConnectionCableNetwork { @customElement("vm-device-template") export class VmObjectTemplate extends VMTemplateDBMixin(BaseElement) { - static styles = [ ...defaultCss, css` @@ -91,7 +90,6 @@ export class VmObjectTemplate extends VMTemplateDBMixin(BaseElement) { private _prefabName: string; private _prefabHash: number; - get prefabName(): string { return this._prefabName; } @@ -107,7 +105,7 @@ export class VmObjectTemplate extends VMTemplateDBMixin(BaseElement) { } get dbTemplate(): ObjectTemplate { - return this.templateDB.get(this._prefabHash); + return this.templateDB[this._prefabHash]; } setupState() { @@ -117,7 +115,7 @@ export class VmObjectTemplate extends VMTemplateDBMixin(BaseElement) { ( Array.from( "logic" in dbTemplate - ? dbTemplate.logic.logic_types.entries() ?? [] + ? Object.entries(dbTemplate.logic.logic_types) : [], ) as [LogicType, MemoryAccess][] ).map(([lt, access]) => { @@ -156,14 +154,15 @@ export class VmObjectTemplate extends VMTemplateDBMixin(BaseElement) { this.connections = connections.map((conn) => conn[1]); - const numPins = "device" in dbTemplate ? dbTemplate.device.device_pins_length : 0; + const numPins = + "device" in dbTemplate ? dbTemplate.device.device_pins_length : 0; this.pins = 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` ${field.field_type} `; - })} + })} `; } @@ -209,11 +208,11 @@ export class VmObjectTemplate extends VMTemplateDBMixin(BaseElement) { return html`
${connections.map((connection, index, _conns) => { - const conn = - typeof connection === "object" && "CableNetwork" in connection - ? connection.CableNetwork - : null; - return html` + const conn = + typeof connection === "object" && "CableNetwork" in connection + ? connection.CableNetwork + : null; + return html` Connection:${index} ${vmNetworks.map( - (net) => - html`Network ${net}`, - )} + (net) => + html`Network ${net}`, + )} ${conn?.typ} `; - })} + })}
`; } @@ -270,13 +269,13 @@ export class VmObjectTemplate extends VMTemplateDBMixin(BaseElement) { > d${index} ${visibleDevices.map( - (device, _index) => html` + (device, _index) => html` Device ${device.obj_info.id} : ${device.obj_info.name ?? device.obj_info.prefab} `, - )} + )} `, ); return html`
${pinsHtml}
`; @@ -286,7 +285,7 @@ export class VmObjectTemplate extends VMTemplateDBMixin(BaseElement) { 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 + this.pins[pin] = val; } render() { @@ -342,40 +341,50 @@ export class VmObjectTemplate extends VMTemplateDBMixin(BaseElement) { const objInfo: ObjectInfo = { id: this.objectId, name: this.objectName, - prefab: this.prefabName + prefab: this.prefabName, } as ObjectInfo; if (this.slots.length > 0) { - const slotOccupants: [FrozenObject, number][] = this.slots.flatMap((slot, index) => { - return typeof slot.occupant !== "undefined" ? [[slot.occupant, index]] : []; - }) + const slotOccupants: [FrozenObject, number][] = this.slots.flatMap( + (slot, index) => { + return typeof slot.occupant !== "undefined" + ? [[slot.occupant, index]] + : []; + }, + ); let slotOccupantTemplates: FrozenObject[] | null = null; let slotOccupantObjectIds: ObjectID[] | null = null; let slotOccupantIdsMap: Map = new Map(); if (slotOccupants.length > 0) { slotOccupantTemplates = slotOccupants.map(([slot, _]) => slot); - slotOccupantObjectIds = await window.VM.vm.addObjectsFrozen(slotOccupantTemplates); - slotOccupantIdsMap = new Map(slotOccupants.map((_, index) => { - return [index, slotOccupantObjectIds[index]]; - })) + slotOccupantObjectIds = await window.VM.vm.addObjectsFrozen( + slotOccupantTemplates, + ); + slotOccupantIdsMap = new Map( + slotOccupants.map((_, index) => { + return [index, slotOccupantObjectIds[index]]; + }), + ); } - objInfo.slots = new Map(this.slots.flatMap((slot, index) => { - const occupantId = slotOccupantIdsMap.get(index); - if (typeof occupantId !== "undefined") { - const info: SlotOccupantInfo = { - id: occupantId, - quantity: slot.quantity - }; - return [[index, info]] as [number, SlotOccupantInfo][]; - } else { - return [] as [number, SlotOccupantInfo][]; - } - })) + objInfo.slots = Object.fromEntries( + this.slots.flatMap((slot, index) => { + const occupantId = slotOccupantIdsMap.get(index); + if (typeof occupantId !== "undefined") { + const info: SlotOccupantInfo = { + id: occupantId, + quantity: slot.quantity, + }; + return [[index, info]] as [number, SlotOccupantInfo][]; + } else { + return [] as [number, SlotOccupantInfo][]; + } + }), + ); } if (this.connections.length > 0) { - objInfo.connections = new Map( + objInfo.connections = Object.fromEntries( this.connections.flatMap((conn, index) => { return typeof conn === "object" && "CableNetwork" in conn && @@ -387,7 +396,10 @@ export class VmObjectTemplate extends VMTemplateDBMixin(BaseElement) { } if (this.fields.size > 0) { - objInfo.logic_values = new Map(this.fields) + objInfo.logic_values = Object.fromEntries(this.fields) as Record< + LogicType, + number + >; } const template: FrozenObject = { diff --git a/www/src/ts/virtual_machine/index.ts b/www/src/ts/virtualMachine/index.ts similarity index 97% rename from www/src/ts/virtual_machine/index.ts rename to www/src/ts/virtualMachine/index.ts index 1859292..2719f6f 100644 --- a/www/src/ts/virtual_machine/index.ts +++ b/www/src/ts/virtualMachine/index.ts @@ -83,7 +83,7 @@ class VirtualMachine extends TypedEventTarget() { return this._objects; } - get objectIds() { + get objectIds(): ObjectID[] { const ids = Array.from(this._objects.keys()); ids.sort(); return ids; @@ -93,13 +93,13 @@ class VirtualMachine extends TypedEventTarget() { return this._circuitHolders; } - get circuitHolderIds() { + get circuitHolderIds(): ObjectID[] { const ids = Array.from(this._circuitHolders.keys()); ids.sort(); return ids; } - get networks() { + get networks(): ObjectID[] { const ids = Array.from(this._networks.keys()); ids.sort(); return ids; @@ -320,7 +320,10 @@ class VirtualMachine extends TypedEventTarget() { this.updateObject(id, false); } }, this); - this.updateObject(this.activeIC.obj_info.id, false); + const activeIC = this.activeIC; + if (activeIC != null) { + this.updateObject(activeIC.obj_info.id, false); + } if (save) this.app.session.save(); } @@ -356,7 +359,7 @@ class VirtualMachine extends TypedEventTarget() { // return the data connected oject ids for a network networkDataDevices(network: ObjectID): number[] { - return this._networks.get(network)?.devices ?? [] + return this._networks.get(network)?.devices ?? []; } async changeObjectID(oldID: number, newID: number): Promise { @@ -522,14 +525,16 @@ class VirtualMachine extends TypedEventTarget() { } } - async addObjectsFrozen(frozenObjects: FrozenObject[]): Promise { + async addObjectsFrozen( + frozenObjects: FrozenObject[], + ): Promise { try { console.log("adding devices", frozenObjects); const ids = await this.ic10vm.addObjectsFrozen(frozenObjects); const refrozen = await this.ic10vm.freezeObjects(ids); ids.forEach((id, index) => { this._objects.set(id, refrozen[index]); - }) + }); const device_ids = await this.ic10vm.objects; this.dispatchCustomEvent("vm-objects-update", Array.from(device_ids)); this.app.session.save(); diff --git a/www/src/ts/virtual_machine/prefabDatabase.ts b/www/src/ts/virtualMachine/prefabDatabase.ts similarity index 99% rename from www/src/ts/virtual_machine/prefabDatabase.ts rename to www/src/ts/virtualMachine/prefabDatabase.ts index 6f67f81..68f5796 100644 --- a/www/src/ts/virtual_machine/prefabDatabase.ts +++ b/www/src/ts/virtualMachine/prefabDatabase.ts @@ -66636,4 +66636,4 @@ export default { "StructureNitrolyzer", "StructureRocketCircuitHousing" ] -} as const \ No newline at end of file +} as const diff --git a/www/src/ts/virtual_machine/registers.ts b/www/src/ts/virtualMachine/registers.ts similarity index 97% rename from www/src/ts/virtual_machine/registers.ts rename to www/src/ts/virtualMachine/registers.ts index 4c98b92..eb60df6 100644 --- a/www/src/ts/virtual_machine/registers.ts +++ b/www/src/ts/virtualMachine/registers.ts @@ -1,7 +1,7 @@ import { html, css } from "lit"; import { customElement } from "lit/decorators.js"; import { BaseElement, defaultCss } from "components"; -import { VMActiveICMixin } from "virtual_machine/baseDevice"; +import { VMActiveICMixin } from "virtualMachine/baseDevice"; import { RegisterSpec } from "ic10emu_wasm"; import SlInput from "@shoelace-style/shoelace/dist/components/input/input.js"; diff --git a/www/src/ts/virtual_machine/stack.ts b/www/src/ts/virtualMachine/stack.ts similarity index 94% rename from www/src/ts/virtual_machine/stack.ts rename to www/src/ts/virtualMachine/stack.ts index ae77740..6f96199 100644 --- a/www/src/ts/virtual_machine/stack.ts +++ b/www/src/ts/virtualMachine/stack.ts @@ -1,7 +1,7 @@ import { html, css } from "lit"; import { customElement } from "lit/decorators.js"; import { BaseElement, defaultCss } from "components"; -import { VMActiveICMixin } from "virtual_machine/baseDevice"; +import { VMActiveICMixin } from "virtualMachine/baseDevice"; import SlInput from "@shoelace-style/shoelace/dist/components/input/input.js"; import { displayNumber, parseNumber } from "utils"; @@ -41,7 +41,7 @@ export class VMICStack extends VMActiveICMixin(BaseElement) { } protected render() { - const sp = this.registers![16]; + const sp = this.registers != null ? this.registers[16] : 0; return html` diff --git a/www/src/ts/virtual_machine/ui.ts b/www/src/ts/virtualMachine/ui.ts similarity index 100% rename from www/src/ts/virtual_machine/ui.ts rename to www/src/ts/virtualMachine/ui.ts diff --git a/www/src/ts/virtualMachine/vmWorker.ts b/www/src/ts/virtualMachine/vmWorker.ts new file mode 100644 index 0000000..6f34aaa --- /dev/null +++ b/www/src/ts/virtualMachine/vmWorker.ts @@ -0,0 +1,42 @@ +import { VMRef, init } from "ic10emu_wasm"; +import type { + TemplateDatabase, +} from "ic10emu_wasm"; + +import * as Comlink from "comlink"; + +import prefabDatabase from "./prefabDatabase"; +import { parseNumber } from "utils"; + + +console.info("Processing Json prefab Database ", prefabDatabase); + +const vm: VMRef = init(); + + +const template_database = Object.fromEntries( + Object.entries(prefabDatabase.prefabsByHash).map(([hash, prefabName]) => [ + parseInt(hash), + prefabDatabase.prefabs[prefabName], + ]), +) as TemplateDatabase; + +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(); + 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()); + } + console.info(JSON.stringify(template_database)); +} +postMessage("ready"); + +Comlink.expose(vm); diff --git a/www/src/ts/virtual_machine/vmWorker.ts b/www/src/ts/virtual_machine/vmWorker.ts deleted file mode 100644 index 714633e..0000000 --- a/www/src/ts/virtual_machine/vmWorker.ts +++ /dev/null @@ -1,1158 +0,0 @@ -import { VMRef, init } from "ic10emu_wasm"; -import type { - StationpediaPrefab, - ObjectTemplate, - InternalAtmoInfo, - ThermalInfo, - LogicSlotType, - MemoryAccess, - LogicType, - MachineTier, - RecipeRange, - Instruction, - Recipe, - InstructionPart, - InstructionPartType, - GasType, - TemplateDatabase, -} from "ic10emu_wasm"; - -import * as Comlink from "comlink"; - -import prefabDatabase from "./prefabDatabase"; -import { parseNumber } from "utils"; - -export interface PrefabDatabase { - prefabs: Map; - reagents: Map< - string, - { - Hash: number; - Unit: string; - Sources?: Map; - } - >; - prefabsByHash: Map; - structures: StationpediaPrefab[]; - devices: StationpediaPrefab[]; - items: StationpediaPrefab[]; - logicableItems: StationpediaPrefab[]; - suits: StationpediaPrefab[]; - circuitHolders: StationpediaPrefab[]; -} - -type JsonDBPrefabs = typeof prefabDatabase.prefabs; - -// function buildObjectTemplate( -// template: JsonDBPrefabs[K], -// ): ObjectTemplate { -// switch (template.templateType) { -// case "Structure": -// return { -// templateType: "Structure", -// prefab: template.prefab, -// structure: template.structure, -// thermal_info: -// "thermal_info" in template ? template.thermal_info : undefined, -// internal_atmo_info: -// "internal_atmo_info" in template -// ? (template.internal_atmo_info as InternalAtmoInfo) -// : undefined, -// }; -// case "StructureSlots": -// return { -// templateType: "StructureSlots", -// prefab: template.prefab, -// structure: template.structure, -// thermal_info: -// "thermal_info" in template ? template.thermal_info : undefined, -// internal_atmo_info: -// "internal_atmo_info" in template -// ? (template.internal_atmo_info as InternalAtmoInfo) -// : undefined, -// slots: template.slots.map((slot) => slot), -// }; -// case "StructureLogic": -// return { -// templateType: "StructureLogic", -// prefab: template.prefab, -// structure: template.structure, -// thermal_info: -// "thermal_info" in template -// ? (template.thermal_info as ThermalInfo) -// : undefined, -// internal_atmo_info: -// "internal_atmo_info" in template -// ? (template.internal_atmo_info as InternalAtmoInfo) -// : undefined, -// slots: [...template.slots], -// logic: { -// logic_slot_types: new Map( -// Object.entries(template.logic.logic_slot_types).map( -// ([key, values]) => [ -// parseInt(key), -// new Map( -// Object.entries(values).map(([key, val]) => [ -// key as LogicSlotType, -// val as MemoryAccess, -// ]), -// ), -// ], -// ), -// ), -// logic_types: new Map( -// Object.entries(template.logic.logic_types).map(([key, val]) => [ -// key as LogicType, -// val as MemoryAccess, -// ]), -// ), -// modes: -// "modes" in template.logic -// ? new Map( -// Object.entries(template.logic.modes).map(([key, val]) => [ -// parseInt(key), -// val, -// ]), -// ) -// : undefined, -// transmission_receiver: template.logic.transmission_receiver, -// wireless_logic: template.logic.wireless_logic, -// circuit_holder: template.logic.circuit_holder, -// }, -// }; -// case "StructureLogicDevice": -// return { -// templateType: "StructureLogicDevice", -// prefab: template.prefab, -// structure: template.structure, -// thermal_info: -// "thermal_info" in template -// ? (template.thermal_info as ThermalInfo) -// : undefined, -// internal_atmo_info: -// "internal_atmo_info" in template -// ? (template.internal_atmo_info as InternalAtmoInfo) -// : undefined, -// slots: [...template.slots], -// logic: { -// logic_slot_types: new Map( -// Object.entries(template.logic.logic_slot_types).map( -// ([key, values]) => [ -// parseInt(key), -// new Map( -// Object.entries(values).map(([key, val]) => [ -// key as LogicSlotType, -// val as MemoryAccess, -// ]), -// ), -// ], -// ), -// ), -// logic_types: new Map( -// Object.entries(template.logic.logic_types).map(([key, val]) => [ -// key as LogicType, -// val as MemoryAccess, -// ]), -// ), -// modes: -// "modes" in template.logic -// ? new Map( -// Object.entries(template.logic.modes).map(([key, val]) => [ -// parseInt(key), -// val, -// ]), -// ) -// : undefined, -// transmission_receiver: template.logic.transmission_receiver, -// wireless_logic: template.logic.wireless_logic, -// circuit_holder: template.logic.circuit_holder, -// }, -// device: { -// connection_list: [...template.device.connection_list], -// device_pins_length: -// "device_pins_length" in template.device -// ? (template.device.device_pins_length as number) -// : undefined, -// has_activate_state: template.device.has_activate_state, -// has_atmosphere: template.device.has_atmosphere, -// has_color_state: template.device.has_color_state, -// has_lock_state: template.device.has_lock_state, -// has_mode_state: template.device.has_mode_state, -// has_on_off_state: template.device.has_on_off_state, -// has_open_state: template.device.has_open_state, -// has_reagents: template.device.has_reagents, -// }, -// }; -// case "StructureLogicDeviceConsumer": -// return { -// templateType: "StructureLogicDeviceConsumer", -// prefab: template.prefab, -// structure: template.structure, -// thermal_info: -// "thermal_info" in template -// ? (template.thermal_info as ThermalInfo) -// : undefined, -// internal_atmo_info: -// "internal_atmo_info" in template -// ? (template.internal_atmo_info as InternalAtmoInfo) -// : undefined, -// slots: [...template.slots], -// logic: { -// logic_slot_types: new Map( -// Object.entries(template.logic.logic_slot_types).map( -// ([key, values]) => [ -// parseInt(key), -// new Map( -// Object.entries(values).map(([key, val]) => [ -// key as LogicSlotType, -// val as MemoryAccess, -// ]), -// ), -// ], -// ), -// ), -// logic_types: new Map( -// Object.entries(template.logic.logic_types).map(([key, val]) => [ -// key as LogicType, -// val as MemoryAccess, -// ]), -// ), -// modes: -// "modes" in template.logic -// ? new Map( -// Object.entries(template.logic.modes).map(([key, val]) => [ -// parseInt(key), -// val, -// ]), -// ) -// : undefined, -// transmission_receiver: template.logic.transmission_receiver, -// wireless_logic: template.logic.wireless_logic, -// circuit_holder: template.logic.circuit_holder, -// }, -// device: { -// connection_list: [...template.device.connection_list], -// device_pins_length: -// "device_pins_length" in template.device -// ? (template.device.device_pins_length as number) -// : undefined, -// has_activate_state: template.device.has_activate_state, -// has_atmosphere: template.device.has_atmosphere, -// has_color_state: template.device.has_color_state, -// has_lock_state: template.device.has_lock_state, -// has_mode_state: template.device.has_mode_state, -// has_on_off_state: template.device.has_on_off_state, -// has_open_state: template.device.has_open_state, -// has_reagents: template.device.has_reagents, -// }, -// consumer_info: { -// consumed_resouces: [...template.consumer_info.consumed_resouces], -// processed_reagents: [...template.consumer_info.processed_reagents], -// }, -// fabricator_info: undefined, -// }; -// case "StructureLogicDeviceConsumerMemory": -// return { -// templateType: "StructureLogicDeviceConsumerMemory", -// prefab: template.prefab, -// structure: template.structure, -// thermal_info: -// "thermal_info" in template -// ? (template.thermal_info as ThermalInfo) -// : undefined, -// internal_atmo_info: -// "internal_atmo_info" in template -// ? (template.internal_atmo_info as InternalAtmoInfo) -// : undefined, -// slots: [...template.slots], -// logic: { -// logic_slot_types: new Map( -// Object.entries(template.logic.logic_slot_types).map( -// ([key, values]) => [ -// parseInt(key), -// new Map( -// Object.entries(values).map(([key, val]) => [ -// key as LogicSlotType, -// val as MemoryAccess, -// ]), -// ), -// ], -// ), -// ), -// logic_types: new Map( -// Object.entries(template.logic.logic_types).map(([key, val]) => [ -// key as LogicType, -// val as MemoryAccess, -// ]), -// ), -// modes: -// "modes" in template.logic -// ? new Map( -// Object.entries(template.logic.modes).map(([key, val]) => [ -// parseInt(key), -// val, -// ]), -// ) -// : undefined, -// transmission_receiver: template.logic.transmission_receiver, -// wireless_logic: template.logic.wireless_logic, -// circuit_holder: template.logic.circuit_holder, -// }, -// device: { -// connection_list: [...template.device.connection_list], -// device_pins_length: -// "device_pins_length" in template.device -// ? (template.device.device_pins_length as number) -// : undefined, -// has_activate_state: template.device.has_activate_state, -// has_atmosphere: template.device.has_atmosphere, -// has_color_state: template.device.has_color_state, -// has_lock_state: template.device.has_lock_state, -// has_mode_state: template.device.has_mode_state, -// has_on_off_state: template.device.has_on_off_state, -// has_open_state: template.device.has_open_state, -// has_reagents: template.device.has_reagents, -// }, -// consumer_info: { -// consumed_resouces: [...template.consumer_info.consumed_resouces], -// processed_reagents: [...template.consumer_info.processed_reagents], -// }, -// fabricator_info: -// "fabricator_info" in template -// ? { -// tier: template.fabricator_info.tier as MachineTier, -// recipes: new Map( -// Object.entries(template.fabricator_info.recipes).map( -// ([key, val]) => { -// const recipe: Recipe = { -// tier: val.tier as MachineTier, -// time: val.time as number, -// energy: val.energy as number, -// temperature: val.temperature as RecipeRange, -// pressure: val.pressure as RecipeRange, -// required_mix: { -// rule: val.required_mix.rule as number, -// is_any: val.required_mix.is_any as boolean, -// is_any_to_remove: val.required_mix -// .is_any_to_remove as boolean, -// reagents: new Map( -// Object.entries(val.required_mix.reagents), -// ) as Map, -// }, -// count_types: val.count_types, -// reagents: new Map(Object.entries(val.reagents)) as Map< -// string, -// number -// >, -// }; -// -// return [key, recipe]; -// }, -// ), -// ), -// } -// : undefined, -// memory: { -// memory_access: template.memory.memory_access as MemoryAccess, -// memory_size: template.memory.memory_size, -// instructions: -// "instructions" in template.memory -// ? new Map( -// Object.entries(template.memory.instructions).map( -// ([key, val]) => { -// const instruction: Instruction = { -// description: val.description, -// description_stripped: val.description_stripped, -// typ: val.typ, -// value: val.value, -// valid: [ -// val.valid[0], -// typeof val.valid[1] === "number" -// ? val.valid[1] -// : undefined, -// ], -// parts: val.parts.map((part) => { -// const instPart: InstructionPart = { -// range: [...part.range], -// name: part.name, -// typ: part.typ as InstructionPartType, -// }; -// return instPart; -// }), -// }; -// return [key, instruction]; -// }, -// ), -// ) -// : undefined, -// }, -// }; -// case "StructureLogicDeviceMemory": -// return { -// templateType: "StructureLogicDeviceMemory", -// prefab: template.prefab, -// structure: template.structure, -// thermal_info: -// "thermal_info" in template -// ? (template.thermal_info as ThermalInfo) -// : undefined, -// internal_atmo_info: -// "internal_atmo_info" in template -// ? (template.internal_atmo_info as InternalAtmoInfo) -// : undefined, -// slots: [...template.slots], -// logic: { -// logic_slot_types: new Map( -// Object.entries(template.logic.logic_slot_types).map( -// ([key, values]) => [ -// parseInt(key), -// new Map( -// Object.entries(values).map(([key, val]) => [ -// key as LogicSlotType, -// val as MemoryAccess, -// ]), -// ), -// ], -// ), -// ), -// logic_types: new Map( -// Object.entries(template.logic.logic_types).map(([key, val]) => [ -// key as LogicType, -// val as MemoryAccess, -// ]), -// ), -// modes: -// "modes" in template.logic -// ? new Map( -// Object.entries(template.logic.modes).map(([key, val]) => [ -// parseInt(key), -// val, -// ]), -// ) -// : undefined, -// transmission_receiver: template.logic.transmission_receiver, -// wireless_logic: template.logic.wireless_logic, -// circuit_holder: template.logic.circuit_holder, -// }, -// device: { -// connection_list: [...template.device.connection_list], -// device_pins_length: -// "device_pins_length" in template.device -// ? (template.device.device_pins_length as number) -// : undefined, -// has_activate_state: template.device.has_activate_state, -// has_atmosphere: template.device.has_atmosphere, -// has_color_state: template.device.has_color_state, -// has_lock_state: template.device.has_lock_state, -// has_mode_state: template.device.has_mode_state, -// has_on_off_state: template.device.has_on_off_state, -// has_open_state: template.device.has_open_state, -// has_reagents: template.device.has_reagents, -// }, -// memory: { -// memory_access: template.memory.memory_access as MemoryAccess, -// memory_size: template.memory.memory_size, -// instructions: -// "instructions" in template.memory -// ? new Map( -// Object.entries(template.memory.instructions).map( -// ([key, val]) => { -// const instruction: Instruction = { -// description: val.description, -// description_stripped: val.description_stripped, -// typ: val.typ, -// value: val.value, -// valid: [ -// val.valid[0], -// typeof val.valid[1] === "number" -// ? val.valid[1] -// : undefined, -// ], -// parts: val.parts.map( -// (part: { -// range: readonly [number, number]; -// name: string; -// typ: string; -// }) => { -// const instPart: InstructionPart = { -// range: [...part.range], -// name: part.name, -// typ: part.typ as InstructionPartType, -// }; -// return instPart; -// }, -// ), -// }; -// return [key, instruction]; -// }, -// ), -// ) -// : undefined, -// }, -// }; -// case "StructureCircuitHolder": -// return { -// templateType: "StructureCircuitHolder", -// prefab: template.prefab, -// structure: template.structure, -// thermal_info: -// "thermal_info" in template -// ? (template.thermal_info as ThermalInfo) -// : undefined, -// internal_atmo_info: -// "internal_atmo_info" in template -// ? (template.internal_atmo_info as InternalAtmoInfo) -// : undefined, -// slots: [...template.slots], -// logic: { -// logic_slot_types: new Map( -// Object.entries(template.logic.logic_slot_types).map( -// ([key, values]) => [ -// parseInt(key), -// new Map( -// Object.entries(values).map(([key, val]) => [ -// key as LogicSlotType, -// val as MemoryAccess, -// ]), -// ), -// ], -// ), -// ), -// logic_types: new Map( -// Object.entries(template.logic.logic_types).map(([key, val]) => [ -// key as LogicType, -// val as MemoryAccess, -// ]), -// ), -// modes: -// "modes" in template.logic -// ? new Map( -// Object.entries(template.logic.modes).map(([key, val]) => [ -// parseInt(key), -// val, -// ]), -// ) -// : undefined, -// transmission_receiver: template.logic.transmission_receiver, -// wireless_logic: template.logic.wireless_logic, -// circuit_holder: template.logic.circuit_holder, -// }, -// device: { -// connection_list: [...template.device.connection_list], -// device_pins_length: -// "device_pins_length" in template.device -// ? (template.device.device_pins_length as number) -// : undefined, -// has_activate_state: template.device.has_activate_state, -// has_atmosphere: template.device.has_atmosphere, -// has_color_state: template.device.has_color_state, -// has_lock_state: template.device.has_lock_state, -// has_mode_state: template.device.has_mode_state, -// has_on_off_state: template.device.has_on_off_state, -// has_open_state: template.device.has_open_state, -// has_reagents: template.device.has_reagents, -// }, -// }; -// case "Item": -// return { -// templateType: "Item", -// prefab: template.prefab, -// thermal_info: -// "thermal_info" in template -// ? (template.thermal_info as ThermalInfo) -// : undefined, -// internal_atmo_info: -// "internal_atmo_info" in template -// ? (template.internal_atmo_info as InternalAtmoInfo) -// : undefined, -// item: { -// consumable: template.item.consumable, -// ingredient: template.item.ingredient, -// max_quantity: template.item.max_quantity, -// slot_class: template.item.slot_class, -// sorting_class: template.item.sorting_class, -// filter_type: -// "filter_type" in template.item -// ? template.item.filter_type -// : undefined, -// reagents: -// "reagents" in template.item -// ? (new Map(Object.entries(template.item.reagents)) as Map< -// string, -// number -// >) -// : undefined, -// }, -// }; -// case "ItemSlots": -// return { -// templateType: "ItemSlots", -// prefab: template.prefab, -// thermal_info: -// "thermal_info" in template -// ? (template.thermal_info as ThermalInfo) -// : undefined, -// internal_atmo_info: -// "internal_atmo_info" in template -// ? (template.internal_atmo_info as InternalAtmoInfo) -// : undefined, -// item: { -// consumable: template.item.consumable, -// ingredient: template.item.ingredient, -// max_quantity: template.item.max_quantity, -// slot_class: template.item.slot_class, -// sorting_class: template.item.sorting_class, -// filter_type: -// "filter_type" in template.item -// ? (template.item.filter_type as GasType) -// : undefined, -// reagents: -// "reagents" in template.item -// ? (new Map(Object.entries(template.item.reagents)) as Map< -// string, -// number -// >) -// : undefined, -// }, -// slots: [...template.slots], -// }; -// case "ItemConsumer": -// return { -// templateType: "ItemConsumer", -// prefab: template.prefab, -// thermal_info: -// "thermal_info" in template -// ? (template.thermal_info as ThermalInfo) -// : undefined, -// internal_atmo_info: -// "internal_atmo_info" in template -// ? (template.internal_atmo_info as InternalAtmoInfo) -// : undefined, -// item: { -// consumable: template.item.consumable, -// ingredient: template.item.ingredient, -// max_quantity: template.item.max_quantity, -// slot_class: template.item.slot_class, -// sorting_class: template.item.sorting_class, -// filter_type: -// "filter_type" in template.item -// ? (template.item.filter_type as GasType) -// : undefined, -// reagents: -// "reagents" in template.item -// ? (new Map(Object.entries(template.item.reagents)) as Map< -// string, -// number -// >) -// : undefined, -// }, -// slots: [...template.slots], -// consumer_info: { -// consumed_resouces: [...template.consumer_info.consumed_resouces], -// processed_reagents: [...template.consumer_info.processed_reagents], -// }, -// }; -// case "ItemLogic": -// return { -// templateType: "ItemLogic", -// prefab: template.prefab, -// thermal_info: -// "thermal_info" in template -// ? (template.thermal_info as ThermalInfo) -// : undefined, -// internal_atmo_info: -// "internal_atmo_info" in template -// ? (template.internal_atmo_info as InternalAtmoInfo) -// : undefined, -// item: { -// consumable: template.item.consumable, -// ingredient: template.item.ingredient, -// max_quantity: template.item.max_quantity, -// slot_class: template.item.slot_class, -// sorting_class: template.item.sorting_class, -// filter_type: -// "filter_type" in template.item -// ? (template.item.filter_type as GasType) -// : undefined, -// reagents: -// "reagents" in template.item -// ? (new Map(Object.entries(template.item.reagents)) as Map< -// string, -// number -// >) -// : undefined, -// }, -// slots: [...template.slots], -// logic: { -// logic_slot_types: new Map( -// Object.entries(template.logic.logic_slot_types).map( -// ([key, values]) => [ -// parseInt(key), -// new Map( -// Object.entries(values).map(([key, val]) => [ -// key as LogicSlotType, -// val as MemoryAccess, -// ]), -// ), -// ], -// ), -// ), -// logic_types: new Map( -// Object.entries(template.logic.logic_types).map(([key, val]) => [ -// key as LogicType, -// val as MemoryAccess, -// ]), -// ), -// modes: -// "modes" in template.logic -// ? new Map( -// Object.entries(template.logic.modes).map(([key, val]) => [ -// parseInt(key), -// val, -// ]), -// ) -// : undefined, -// transmission_receiver: template.logic.transmission_receiver, -// wireless_logic: template.logic.wireless_logic, -// circuit_holder: template.logic.circuit_holder, -// }, -// }; -// case "ItemLogicMemory": -// return { -// templateType: "ItemLogicMemory", -// prefab: template.prefab, -// thermal_info: -// "thermal_info" in template -// ? (template.thermal_info as ThermalInfo) -// : undefined, -// internal_atmo_info: -// "internal_atmo_info" in template -// ? (template.internal_atmo_info as InternalAtmoInfo) -// : undefined, -// item: { -// consumable: template.item.consumable, -// ingredient: template.item.ingredient, -// max_quantity: template.item.max_quantity, -// slot_class: template.item.slot_class, -// sorting_class: template.item.sorting_class, -// filter_type: -// "filter_type" in template.item -// ? (template.item.filter_type as GasType) -// : undefined, -// reagents: -// "reagents" in template.item -// ? (new Map(Object.entries(template.item.reagents)) as Map< -// string, -// number -// >) -// : undefined, -// }, -// slots: [...template.slots], -// logic: { -// logic_slot_types: new Map( -// Object.entries(template.logic.logic_slot_types).map( -// ([key, values]) => [ -// parseInt(key), -// new Map( -// Object.entries(values).map(([key, val]) => [ -// key as LogicSlotType, -// val as MemoryAccess, -// ]), -// ), -// ], -// ), -// ), -// logic_types: new Map( -// Object.entries(template.logic.logic_types).map(([key, val]) => [ -// key as LogicType, -// val as MemoryAccess, -// ]), -// ), -// modes: -// "modes" in template.logic -// ? new Map( -// Object.entries(template.logic.modes).map(([key, val]) => [ -// parseInt(key), -// val, -// ]), -// ) -// : undefined, -// transmission_receiver: template.logic.transmission_receiver, -// wireless_logic: template.logic.wireless_logic, -// circuit_holder: template.logic.circuit_holder, -// }, -// memory: { -// memory_access: template.memory.memory_access as MemoryAccess, -// memory_size: template.memory.memory_size, -// instructions: -// "instructions" in template.memory -// ? new Map( -// Object.entries(template.memory.instructions).map( -// ([key, val]) => { -// const instruction: Instruction = { -// description: val.description, -// description_stripped: val.description_stripped, -// typ: val.typ, -// value: val.value, -// valid: [ -// val.valid[0], -// typeof val.valid[1] === "number" -// ? val.valid[1] -// : undefined, -// ], -// parts: val.parts.map( -// (part: { -// range: readonly [number, number]; -// name: string; -// typ: string; -// }) => { -// const instPart: InstructionPart = { -// range: [...part.range], -// name: part.name, -// typ: part.typ as InstructionPartType, -// }; -// return instPart; -// }, -// ), -// }; -// return [key, instruction]; -// }, -// ), -// ) -// : undefined, -// }, -// }; -// case "ItemCircuitHolder": -// return { -// templateType: "ItemCircuitHolder", -// prefab: template.prefab, -// thermal_info: -// "thermal_info" in template -// ? (template.thermal_info as ThermalInfo) -// : undefined, -// internal_atmo_info: -// "internal_atmo_info" in template -// ? (template.internal_atmo_info as InternalAtmoInfo) -// : undefined, -// item: { -// consumable: template.item.consumable, -// ingredient: template.item.ingredient, -// max_quantity: template.item.max_quantity, -// slot_class: template.item.slot_class, -// sorting_class: template.item.sorting_class, -// filter_type: -// "filter_type" in template.item -// ? (template.item.filter_type as GasType) -// : undefined, -// reagents: -// "reagents" in template.item -// ? (new Map(Object.entries(template.item.reagents)) as Map< -// string, -// number -// >) -// : undefined, -// }, -// slots: [...template.slots], -// logic: { -// logic_slot_types: new Map( -// Object.entries(template.logic.logic_slot_types).map( -// ([key, values]) => [ -// parseInt(key), -// new Map( -// Object.entries(values).map(([key, val]) => [ -// key as LogicSlotType, -// val as MemoryAccess, -// ]), -// ), -// ], -// ), -// ), -// logic_types: new Map( -// Object.entries(template.logic.logic_types).map(([key, val]) => [ -// key as LogicType, -// val as MemoryAccess, -// ]), -// ), -// modes: -// "modes" in template.logic -// ? new Map( -// Object.entries(template.logic.modes).map(([key, val]) => [ -// parseInt(key), -// val, -// ]), -// ) -// : undefined, -// transmission_receiver: template.logic.transmission_receiver, -// wireless_logic: template.logic.wireless_logic, -// circuit_holder: template.logic.circuit_holder, -// }, -// }; -// case "ItemSuit": -// return { -// templateType: "ItemSuit", -// prefab: template.prefab, -// thermal_info: -// "thermal_info" in template -// ? (template.thermal_info as ThermalInfo) -// : undefined, -// internal_atmo_info: -// "internal_atmo_info" in template -// ? (template.internal_atmo_info as InternalAtmoInfo) -// : undefined, -// item: { -// consumable: template.item.consumable, -// ingredient: template.item.ingredient, -// max_quantity: template.item.max_quantity, -// slot_class: template.item.slot_class, -// sorting_class: template.item.sorting_class, -// filter_type: -// "filter_type" in template.item -// ? (template.item.filter_type as GasType) -// : undefined, -// reagents: -// "reagents" in template.item -// ? (new Map(Object.entries(template.item.reagents)) as Map< -// string, -// number -// >) -// : undefined, -// }, -// slots: [...template.slots], -// suit_info: template.suit_info, -// }; -// // case "ItemSuitLogic": -// // return { -// // templateType: "ItemSuitLogic", -// // prefab: template.prefab, -// // thermal_info: "thermal_info" in template ? template.thermal_info as ThermalInfo : undefined, -// // internal_atmo_info: "internal_atmo_info" in template ? template.internal_atmo_info as InternalAtmoInfo : undefined, -// // item: { -// // consumable: template.item.consumable, -// // ingredient: template.item.ingredient, -// // max_quantity: template.item.max_quantity, -// // slot_class: template.item.slot_class, -// // sorting_class: template.item.sorting_class, -// // filter_type: "filter_type" in template.item ? template.item.filter_type as GasType : undefined, -// // reagents: "reagents" in template.item ? new Map(Object.entries(template.item.reagents)) as Map : undefined, -// // }, -// // slots: [...template.slots], -// // suit_info: template.suit_info, -// // logic: { -// // logic_slot_types: new Map( -// // Object.entries(template.logic.logic_slot_types) -// // .map(([key, values]) => [ -// // parseInt(key), -// // new Map( -// // Object.entries(values) -// // .map(([key, val]) => [key as LogicSlotType, val as MemoryAccess]) -// // ) -// // ]) -// // ), -// // logic_types: new Map( -// // Object.entries(template.logic.logic_types) -// // .map(([key, val]) => [key as LogicType, val as MemoryAccess]) -// // ), -// // modes: "modes" in template.logic -// // ? new Map( -// // Object.entries(template.logic.modes).map(([key, val]) => [parseInt(key), val]) -// // ) -// // : undefined, -// // transmission_receiver: template.logic.transmission_receiver, -// // wireless_logic: template.logic.wireless_logic, -// // circuit_holder: template.logic.circuit_holder -// // }, -// // } -// case "ItemSuitCircuitHolder": -// return { -// templateType: "ItemSuitCircuitHolder", -// prefab: template.prefab, -// thermal_info: -// "thermal_info" in template -// ? (template.thermal_info as ThermalInfo) -// : undefined, -// internal_atmo_info: -// "internal_atmo_info" in template -// ? (template.internal_atmo_info as InternalAtmoInfo) -// : undefined, -// item: { -// consumable: template.item.consumable, -// ingredient: template.item.ingredient, -// max_quantity: template.item.max_quantity, -// slot_class: template.item.slot_class, -// sorting_class: template.item.sorting_class, -// filter_type: -// "filter_type" in template.item -// ? (template.item.filter_type as GasType) -// : undefined, -// reagents: -// "reagents" in template.item -// ? (new Map(Object.entries(template.item.reagents)) as Map< -// string, -// number -// >) -// : undefined, -// }, -// slots: [...template.slots], -// suit_info: template.suit_info, -// logic: { -// logic_slot_types: new Map( -// Object.entries(template.logic.logic_slot_types).map( -// ([key, values]) => [ -// parseInt(key), -// new Map( -// Object.entries(values).map(([key, val]) => [ -// key as LogicSlotType, -// val as MemoryAccess, -// ]), -// ), -// ], -// ), -// ), -// logic_types: new Map( -// Object.entries(template.logic.logic_types).map(([key, val]) => [ -// key as LogicType, -// val as MemoryAccess, -// ]), -// ), -// modes: -// "modes" in template.logic -// ? new Map( -// Object.entries(template.logic.modes).map(([key, val]) => [ -// parseInt(key), -// val, -// ]), -// ) -// : undefined, -// transmission_receiver: template.logic.transmission_receiver, -// wireless_logic: template.logic.wireless_logic, -// circuit_holder: template.logic.circuit_holder, -// }, -// memory: { -// memory_access: template.memory.memory_access as MemoryAccess, -// memory_size: template.memory.memory_size, -// instructions: -// "instructions" in template.memory -// ? new Map( -// Object.entries(template.memory.instructions).map( -// ([key, val]) => { -// const instruction: Instruction = { -// description: val.description, -// description_stripped: val.description_stripped, -// typ: val.typ, -// value: val.value, -// valid: [ -// val.valid[0], -// typeof val.valid[1] === "number" -// ? val.valid[1] -// : undefined, -// ], -// parts: val.parts.map( -// (part: { -// range: readonly [number, number]; -// name: string; -// typ: string; -// }) => { -// const instPart: InstructionPart = { -// range: [...part.range], -// name: part.name, -// typ: part.typ as InstructionPartType, -// }; -// return instPart; -// }, -// ), -// }; -// return [key, instruction]; -// }, -// ), -// ) -// : undefined, -// }, -// }; -// default: -// return undefined; -// } -// } -// -// function buildPrefabDatabase(): PrefabDatabase { -// return { -// prefabs: new Map( -// Object.entries(prefabDatabase.prefabs).flatMap(([key, val]) => { -// const template = buildObjectTemplate(val); -// if (typeof template !== "undefined") { -// return [[key as StationpediaPrefab, template]]; -// } else { -// return []; -// } -// }), -// ), -// prefabsByHash: new Map( -// Object.entries(prefabDatabase.prefabsByHash).map(([key, val]) => [ -// parseInt(key), -// val as StationpediaPrefab, -// ]), -// ), -// structures: [...prefabDatabase.structures] as StationpediaPrefab[], -// devices: [...prefabDatabase.devices] as StationpediaPrefab[], -// items: [...prefabDatabase.items] as StationpediaPrefab[], -// logicableItems: [...prefabDatabase.logicableItems] as StationpediaPrefab[], -// circuitHolders: [...prefabDatabase.circuitHolders] as StationpediaPrefab[], -// suits: [...prefabDatabase.suits] as StationpediaPrefab[], -// reagents: new Map( -// Object.entries(prefabDatabase.reagents).map(([key, val]) => { -// return [ -// key, -// { -// Hash: val.Hash, -// Unit: val.Unit, -// Sources: -// "Sources" in val -// ? (new Map(Object.entries(val.Sources)) as Map< -// StationpediaPrefab, -// number -// >) -// : undefined, -// }, -// ]; -// }), -// ), -// }; -// } -// -console.info("Processing Json prefab Database ", prefabDatabase); -// -// const prefab_database = buildPrefabDatabase(); -// -// console.info("Prcessed prefab Database ", prefab_database); - -const vm: VMRef = init(); - -// const template_database = new Map( -// Array.from(prefab_database.prefabsByHash.entries()).map(([hash, name]) => { -// return [hash, prefab_database.prefabs.get(name)]; -// }), -// ); - -// console.info("Loading Prefab Template Database into VM", template_database); -try { - const start_time = performance.now(); - // vm.importTemplateDatabase(template_database); - vm.importTemplateDatabase( - Object.fromEntries( - Object.entries(prefabDatabase.prefabsByHash) - .map(([hash, prefabName]) => [parseInt(hash), prefabDatabase.prefabs[prefabName]]) - ) as TemplateDatabase - ); - 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()); - } -} - -postMessage("ready"); - -Comlink.expose(vm);