refactor(vm, frontend): turns out that the serde_wasm_bindgen facilities of TSify are borken...
This commit is contained in:
17
Cargo.lock
generated
17
Cargo.lock
generated
@@ -645,13 +645,16 @@ dependencies = [
|
||||
name = "ic10emu_wasm"
|
||||
version = "0.2.3"
|
||||
dependencies = [
|
||||
"color-eyre",
|
||||
"console_error_panic_hook",
|
||||
"ic10emu",
|
||||
"itertools",
|
||||
"js-sys",
|
||||
"serde",
|
||||
"serde-wasm-bindgen 0.6.5",
|
||||
"serde-wasm-bindgen",
|
||||
"serde_derive",
|
||||
"serde_ignored",
|
||||
"serde_path_to_error",
|
||||
"serde_with",
|
||||
"stationeers_data",
|
||||
"strum",
|
||||
@@ -1276,17 +1279,6 @@ dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde-wasm-bindgen"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3b143e2833c57ab9ad3ea280d21fd34e285a42837aeb0ee301f4f41890fa00e"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde-wasm-bindgen"
|
||||
version = "0.6.5"
|
||||
@@ -1802,7 +1794,6 @@ checksum = "d6b26cf145f2f3b9ff84e182c448eaf05468e247f148cf3d2a7d67d78ff023a0"
|
||||
dependencies = [
|
||||
"gloo-utils",
|
||||
"serde",
|
||||
"serde-wasm-bindgen 0.5.0",
|
||||
"serde_json",
|
||||
"tsify-macros",
|
||||
"wasm-bindgen",
|
||||
|
||||
@@ -29,7 +29,7 @@ time = { version = "0.3.36", features = [
|
||||
"serde",
|
||||
"local-offset",
|
||||
] }
|
||||
tsify = { version = "0.4.5", optional = true, features = ["js"] }
|
||||
tsify = { version = "0.4.5", optional = true, features = ["json"] }
|
||||
wasm-bindgen = { version = "0.2.92", optional = true }
|
||||
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
|
||||
@@ -16,10 +16,13 @@ wasm-bindgen-futures = { version = "0.4.42", features = [
|
||||
] }
|
||||
wasm-streams = "0.4"
|
||||
serde-wasm-bindgen = "0.6.5"
|
||||
serde_path_to_error = "0.1.16"
|
||||
serde_ignored = "0.1.10"
|
||||
color-eyre = "0.6.3"
|
||||
itertools = "0.13.0"
|
||||
serde = { version = "1.0.202", features = ["derive"] }
|
||||
serde_with = "3.8.1"
|
||||
tsify = { version = "0.4.5", features = ["js"] }
|
||||
tsify = { version = "0.4.5", features = ["json"] }
|
||||
thiserror = "1.0.61"
|
||||
serde_derive = "1.0.203"
|
||||
|
||||
|
||||
@@ -108,6 +108,23 @@ impl IntoIterator for CompileErrors {
|
||||
}
|
||||
}
|
||||
|
||||
use color_eyre::eyre;
|
||||
pub fn parse_value<'a, T: serde::Deserialize<'a>>(
|
||||
jd: impl serde::Deserializer<'a>,
|
||||
) -> Result<T, color_eyre::Report> {
|
||||
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}");
|
||||
};
|
||||
serde_ignored::deserialize(path, &mut fun).map_err(|e| {
|
||||
eyre::eyre!(
|
||||
"path: {track} | error = {e}",
|
||||
track = track.path().to_string(),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl VMRef {
|
||||
#[wasm_bindgen(constructor)]
|
||||
@@ -120,6 +137,18 @@ impl VMRef {
|
||||
self.vm.import_template_database(db);
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "importTemplateDatabaseSerde")]
|
||||
pub fn import_template_database_serde(&self, db: JsValue) -> Result<(), JsError> {
|
||||
let parsed_db: BTreeMap<i32, ObjectTemplate> =
|
||||
parse_value(serde_wasm_bindgen::Deserializer::from(db)).map_err(|err| {
|
||||
<&dyn std::error::Error as std::convert::Into<JsError>>::into(
|
||||
std::convert::AsRef::<dyn std::error::Error>::as_ref(&err),
|
||||
)
|
||||
})?;
|
||||
self.vm.import_template_database(parsed_db);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "getTemplateDatabase")]
|
||||
pub fn get_template_database(&self) -> TemplateDatabase {
|
||||
TemplateDatabase(self.vm.get_template_database())
|
||||
|
||||
@@ -16,5 +16,5 @@ phf = "0.11.2"
|
||||
serde = "1.0.202"
|
||||
serde_derive = "1.0.202"
|
||||
strum = { version = "0.26.2", features = ["derive", "phf", "strum_macros"] }
|
||||
tsify = { version = "0.4.5", optional = true, features = ["js"] }
|
||||
tsify = { version = "0.4.5", optional = true, features = ["json"] }
|
||||
wasm-bindgen = { version = "0.2.92", optional = true }
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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/base_device";
|
||||
import { VMActiveICMixin } from "virtual_machine/baseDevice";
|
||||
|
||||
import SlSelect from "@shoelace-style/shoelace/dist/components/select/select.js";
|
||||
|
||||
|
||||
@@ -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/base_device";
|
||||
import { VMTemplateDBMixin } from "virtual_machine/baseDevice";
|
||||
import { LogicInfo, ObjectTemplate, StructureInfo } from "ic10emu_wasm";
|
||||
|
||||
type LogicableStrucutureTemplate = Extract<
|
||||
|
||||
@@ -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/base_device";
|
||||
import { VMTemplateDBMixin, VMObjectMixin } from "virtual_machine/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";
|
||||
|
||||
@@ -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/base_device";
|
||||
import { VMTemplateDBMixin, VMObjectMixin } from "virtual_machine/baseDevice";
|
||||
import { displayNumber, parseNumber } from "utils";
|
||||
import type { LogicType } from "ic10emu_wasm";
|
||||
import SlInput from "@shoelace-style/shoelace/dist/components/input/input.component.js";
|
||||
|
||||
@@ -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/base_device";
|
||||
import { VMTemplateDBMixin, VMObjectMixin } from "virtual_machine/baseDevice";
|
||||
import SlSelect from "@shoelace-style/shoelace/dist/components/select/select.component.js";
|
||||
import { ObjectID } from "ic10emu_wasm";
|
||||
|
||||
|
||||
@@ -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/base_device";
|
||||
import { VMTemplateDBMixin, VMObjectMixin } from "virtual_machine/baseDevice";
|
||||
import {
|
||||
clamp,
|
||||
crc32,
|
||||
|
||||
@@ -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/base_device";
|
||||
import { VMTemplateDBMixin } from "virtual_machine/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";
|
||||
|
||||
@@ -24,7 +24,7 @@ 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/base_device";
|
||||
import { VMTemplateDBMixin } from "virtual_machine/baseDevice";
|
||||
|
||||
export interface SlotTemplate {
|
||||
typ: Class
|
||||
|
||||
@@ -11,7 +11,7 @@ import type {
|
||||
ObjectID,
|
||||
} from "ic10emu_wasm";
|
||||
import * as Comlink from "comlink";
|
||||
import "./base_device";
|
||||
import "./baseDevice";
|
||||
import "./device";
|
||||
import { App } from "app";
|
||||
import { structuralEqual, TypedEventTarget } from "utils";
|
||||
@@ -52,15 +52,24 @@ class VirtualMachine extends TypedEventTarget<VirtualMachineEventMap>() {
|
||||
constructor(app: App) {
|
||||
super();
|
||||
this.app = app;
|
||||
this.vm_worker = new Worker( new URL("./vm_worker.ts", import.meta.url));
|
||||
const vm = Comlink.wrap<VMRef>(this.vm_worker);
|
||||
this.ic10vm = vm;
|
||||
window.VM.set(this);
|
||||
|
||||
this._objects = new Map();
|
||||
this._circuitHolders = new Map();
|
||||
this._networks = new Map();
|
||||
|
||||
this.setupVM();
|
||||
}
|
||||
|
||||
async setupVM() {
|
||||
this.vm_worker = new Worker(new URL("./vmWorker.ts", import.meta.url));
|
||||
const loaded = (w: Worker) =>
|
||||
new Promise((r) => w.addEventListener("message", r, { once: true }));
|
||||
await Promise.all([loaded(this.vm_worker)]);
|
||||
console.info("VM Worker loaded");
|
||||
const vm = Comlink.wrap<VMRef>(this.vm_worker);
|
||||
this.ic10vm = vm;
|
||||
window.VM.set(this);
|
||||
|
||||
this.templateDBPromise = this.ic10vm.getTemplateDatabase();
|
||||
|
||||
this.templateDBPromise.then((db) => this.setupTemplateDatabase(db));
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{
|
||||
export default {
|
||||
"prefabs": {
|
||||
"AccessCardBlack": {
|
||||
"templateType": "Item",
|
||||
@@ -66636,4 +66636,4 @@
|
||||
"StructureNitrolyzer",
|
||||
"StructureRocketCircuitHousing"
|
||||
]
|
||||
}
|
||||
} as const
|
||||
@@ -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/base_device";
|
||||
import { VMActiveICMixin } from "virtual_machine/baseDevice";
|
||||
|
||||
import { RegisterSpec } from "ic10emu_wasm";
|
||||
import SlInput from "@shoelace-style/shoelace/dist/components/input/input.js";
|
||||
|
||||
@@ -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/base_device";
|
||||
import { VMActiveICMixin } from "virtual_machine/baseDevice";
|
||||
|
||||
import SlInput from "@shoelace-style/shoelace/dist/components/input/input.js";
|
||||
import { displayNumber, parseNumber } from "utils";
|
||||
|
||||
1158
www/src/ts/virtual_machine/vmWorker.ts
Normal file
1158
www/src/ts/virtual_machine/vmWorker.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,47 +0,0 @@
|
||||
import { VMRef, init } from "ic10emu_wasm";
|
||||
import type { StationpediaPrefab, ObjectTemplate } from "ic10emu_wasm";
|
||||
|
||||
import * as Comlink from "comlink";
|
||||
|
||||
import * as json_database from "../../../data/database.json" with { type: "json" };
|
||||
|
||||
export interface PrefabDatabase {
|
||||
prefabs: { [key in StationpediaPrefab]: ObjectTemplate};
|
||||
reagents: {
|
||||
[key: string]: {
|
||||
Hash: number;
|
||||
Unit: string;
|
||||
Sources?: {
|
||||
[key in StationpediaPrefab]: number;
|
||||
};
|
||||
};
|
||||
};
|
||||
prefabsByHash: {
|
||||
[key: number]: StationpediaPrefab;
|
||||
};
|
||||
structures: StationpediaPrefab[];
|
||||
devices: StationpediaPrefab[];
|
||||
items: StationpediaPrefab[];
|
||||
logicableItems: StationpediaPrefab[];
|
||||
suits: StationpediaPrefab[];
|
||||
circuitHolders: StationpediaPrefab[];
|
||||
}
|
||||
|
||||
const prefab_database = json_database as unknown as PrefabDatabase;
|
||||
|
||||
const vm: VMRef = init();
|
||||
|
||||
const template_database = new Map(
|
||||
Object.entries(prefab_database.prefabsByHash).map(([hash, name]) => {
|
||||
return [parseInt(hash), prefab_database.prefabs[name]];
|
||||
}),
|
||||
);
|
||||
|
||||
console.info("Loading Prefab Template Database into VM", template_database);
|
||||
const start_time = performance.now();
|
||||
vm.importTemplateDatabase(template_database);
|
||||
const now = performance.now();
|
||||
const time_elapsed = (now - start_time) / 1000;
|
||||
console.log(`Prefab Templat Database loaded in ${time_elapsed} seconds`);
|
||||
|
||||
Comlink.expose(vm);
|
||||
@@ -187,12 +187,16 @@ pub fn generate_database(
|
||||
circuit_holders,
|
||||
};
|
||||
|
||||
let data_path = workspace.join("www").join("data");
|
||||
let data_path = workspace
|
||||
.join("www")
|
||||
.join("src")
|
||||
.join("ts")
|
||||
.join("virtual_machine");
|
||||
if !data_path.exists() {
|
||||
std::fs::create_dir(&data_path)?;
|
||||
}
|
||||
{
|
||||
let database_path = data_path.join("database.json");
|
||||
let database_path = data_path.join("prefabDatabase.ts");
|
||||
let mut database_file = std::io::BufWriter::new(std::fs::File::create(database_path)?);
|
||||
let json = serde_json::to_string_pretty(&db)?;
|
||||
// this may seem anathema but I don't want to write a separate struct set to skip Nones
|
||||
@@ -205,9 +209,11 @@ pub fn generate_database(
|
||||
//
|
||||
// https://regex101.com/r/WFpjHV/1
|
||||
//
|
||||
let null_matcher = regex::Regex::new(r#"(?:,\n\s*"\w+":\snull)+(,?)|(?:(?:\n)?\s*"\w+":\snull),"#).unwrap();
|
||||
let null_matcher =
|
||||
regex::Regex::new(r#"(?:,\n\s*"\w+":\snull)+(,?)|(?:(?:\n)?\s*"\w+":\snull),"#)
|
||||
.unwrap();
|
||||
let json = null_matcher.replace_all(&json, "$1");
|
||||
write!(&mut database_file, "{json}")?;
|
||||
write!(&mut database_file, "export default {json} as const")?;
|
||||
database_file.flush()?;
|
||||
}
|
||||
|
||||
@@ -236,11 +242,13 @@ fn write_prefab_map<T: std::io::Write>(
|
||||
use crate::templates::*;
|
||||
}
|
||||
)?;
|
||||
let enum_tag_regex = regex::Regex::new(r#"templateType:\s"\w+"\.into\(\),"#).unwrap();
|
||||
let entries = prefabs
|
||||
.values()
|
||||
.map(|prefab| {
|
||||
let hash = prefab.prefab().prefab_hash;
|
||||
let obj = syn::parse_str::<syn::Expr>(&uneval::to_string(prefab)?)?;
|
||||
let uneval_src = &uneval::to_string(prefab)?;
|
||||
let obj = syn::parse_str::<syn::Expr>(&enum_tag_regex.replace_all(&uneval_src, ""))?;
|
||||
let entry = quote! {
|
||||
map.insert(#hash, #obj.into());
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user