Merge pull request #18 from Ryex/attach_devices
Let Users Attach devices
1
Cargo.lock
generated
@@ -588,6 +588,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde-wasm-bindgen 0.6.5",
|
||||
"serde_with",
|
||||
"strum",
|
||||
"thiserror",
|
||||
"tsify",
|
||||
"wasm-bindgen",
|
||||
|
||||
1
ic10emu/data/Enums.json
Normal file
12
ic10emu/data/instruction_help_patches.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"english": {
|
||||
"bapz": "Branch to line c if abs(a) <= max(b * abs(a), float.epsilon * 8)",
|
||||
"bapzal": "Branch to line c if abs(a) <= max(b * abs(a), float.epsilon * 8) and store next line number in ra",
|
||||
"bnaz": "Branch to line c if abs(a) > max b * abs(a), float.epsilon * 8)",
|
||||
"bnazal": "Branch to line c if abs(a) > max b * abs(a), float.epsilon * 8) and store next line number in ra",
|
||||
"brapz": "Relative branch to line c if abs(a) <= max(b * abs(a), float.epsilon * 8)",
|
||||
"brnaz": "Relative branch to line c if abs(a) > max(b * abs(a), float.epsilon * 8)",
|
||||
"sapz": "Register = 1 if |a| <= max(b * abs(a), float.epsilon * 8), otherwise 0",
|
||||
"snaz": "Register = 1 if |a| > max(b * abs(a), float.epsilon), otherwise 0"
|
||||
}
|
||||
}
|
||||
@@ -8,8 +8,8 @@ atan Returns the angle (radians) whos tan is the specified value
|
||||
atan2 Returns the angle (radians) whose tangent is the quotient of two specified values: a (y) and b (x)
|
||||
bap Branch to line d if abs(a - b) <= max(c * max(abs(a), abs(b)), float.epsilon * 8)
|
||||
bapal Branch to line d if abs(a - b) <= max(c * max(abs(a), abs(b)), float.epsilon * 8) and store next line number in ra
|
||||
bapz Branch to line c if abs(a) <= float.epsilon * 8
|
||||
bapzal Branch to line c if abs(a) <= float.epsilon * 8
|
||||
bapz Branch to line c if abs(a) <= max(b * abs(a), float.epsilon * 8)
|
||||
bapzal Branch to line c if abs(a) <= max(b * abs(a), float.epsilon * 8) and store next line number in ra
|
||||
bdns Branch to line a if device d isn't set
|
||||
bdnsal Jump execution to line a and store next line number if device is not set
|
||||
bdse Branch to line a if device d is set
|
||||
@@ -37,14 +37,14 @@ bltzal Branch to line b if a < 0 and store next line number in ra
|
||||
bna Branch to line d if abs(a - b) > max(c * max(abs(a), abs(b)), float.epsilon * 8)
|
||||
bnaal Branch to line d if abs(a - b) <= max(c * max(abs(a), abs(b)), float.epsilon * 8) and store next line number in ra
|
||||
bnan Branch to line b if a is not a number (NaN)
|
||||
bnaz Branch to line c if abs(a) > float.epsilon * 8
|
||||
bnazal Branch to line c if abs(a) > float.epsilon * 8
|
||||
bnaz Branch to line c if abs(a) > max b * abs(a), float.epsilon * 8)
|
||||
bnazal Branch to line c if abs(a) > max b * abs(a), float.epsilon * 8) and store next line number in ra
|
||||
bne Branch to line c if a != b
|
||||
bneal Branch to line c if a != b and store next line number in ra
|
||||
bnez branch to line b if a != 0
|
||||
bnezal Branch to line b if a != 0 and store next line number in ra
|
||||
brap Relative branch to line d if abs(a - b) <= max(c * max(abs(a), abs(b)), float.epsilon * 8)
|
||||
brapz Relative branch to line c if abs(a) <= float.epsilon * 8
|
||||
brapz Relative branch to line c if abs(a) <= max(b * abs(a), float.epsilon * 8)
|
||||
brdns Relative jump to line a if device is not set
|
||||
brdse Relative jump to line a if device is set
|
||||
breq Relative branch to line c if a == b
|
||||
@@ -59,7 +59,7 @@ brlt Relative jump to line c if a < b
|
||||
brltz Relative branch to line b if a < 0
|
||||
brna Relative branch to line d if abs(a - b) > max(c * max(abs(a), abs(b)), float.epsilon * 8)
|
||||
brnan Relative branch to line b if a is not a number (NaN)
|
||||
brnaz Relative branch to line c if abs(a) > float.epsilon * 8
|
||||
brnaz Relative branch to line c if abs(a) > max(b * abs(a), float.epsilon * 8)
|
||||
brne Relative branch to line c if a != b
|
||||
brnez Relative branch to line b if a != 0
|
||||
ceil Register = smallest integer greater than a
|
||||
@@ -97,7 +97,7 @@ rand Register = a random value x with 0 <= x < 1
|
||||
round Register = a rounded to nearest integer
|
||||
s Stores register value to LogicType on device by housing index value.
|
||||
sap Register = 1 if abs(a - b) <= max(c * max(abs(a), abs(b)), float.epsilon * 8), otherwise 0
|
||||
sapz Register = 1 if |a| <= float.epsilon * 8, otherwise 0
|
||||
sapz Register = 1 if |a| <= max(b * abs(a), float.epsilon * 8), otherwise 0
|
||||
sb Stores register value to LogicType on all output network devices with provided type hash.
|
||||
sbn Stores register value to LogicType on all output network devices with provided type hash and name.
|
||||
sbs Stores register value to LogicSlotType on all output network devices with provided type hash in the provided slot.
|
||||
@@ -122,7 +122,7 @@ sltz Register = 1 if a < 0, otherwise 0
|
||||
sna Register = 1 if abs(a - b) > max(c * max(abs(a), abs(b)), float.epsilon * 8), otherwise 0
|
||||
snan Register = 1 if a is NaN, otherwise 0
|
||||
snanz Register = 0 if a is NaN, otherwise 1
|
||||
snaz Register = 1 if |a| > float.epsilon, otherwise 0
|
||||
snaz Register = 1 if |a| > max(b * abs(a), float.epsilon), otherwise 0
|
||||
sne Register = 1 if a != b, otherwise 0
|
||||
snez Register = 1 if a != 0, otherwise 0
|
||||
sqrt Register = square root of a
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
from collections import defaultdict
|
||||
import json
|
||||
import xml.etree.ElementTree as ET
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
import sys
|
||||
import re
|
||||
from itertools import chain
|
||||
import struct
|
||||
import binascii
|
||||
import json
|
||||
import re
|
||||
import struct
|
||||
import sys
|
||||
import xml.etree.ElementTree as ET
|
||||
from collections import defaultdict
|
||||
from itertools import chain
|
||||
from pathlib import Path
|
||||
|
||||
def intOrNone(val):
|
||||
|
||||
def intOrNone(val: str):
|
||||
try:
|
||||
return int(val)
|
||||
except ValueError:
|
||||
@@ -20,32 +21,32 @@ def main():
|
||||
description="Generate instructions, enums, and docs for lsp.\n\nWorks best when using https://github.com/Ryex/StationeersStationpediaExtractor",
|
||||
epilog="Point at the Stationeers install and go!",
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
||||
arg_parser.add_argument("path", help="Path to Stationeers installation")
|
||||
arg_parser.add_argument("--lang", help="language to extract from (ie. english)", default="english")
|
||||
_ = arg_parser.add_argument("path", help="Path to Stationeers installation")
|
||||
_ = arg_parser.add_argument("--lang", help="language to extract from (ie. english)", default="english")
|
||||
args = arg_parser.parse_args()
|
||||
install_path = Path(args.path)
|
||||
install_path = Path(args.path) # type:ignore[reportAny]
|
||||
if install_path.match("Stationeers/*.exe") or install_path.match("Stationeers/rocketstation_Data"):
|
||||
install_path = install_path.parent
|
||||
elif install_path.name == "Stationeers":
|
||||
pass
|
||||
elif (install_path / "Stationeers").is_dir():
|
||||
install_path = install_path / "Stationeers"
|
||||
|
||||
data_path = install_path / "rocketstation_Data" / "StreamingAssets" / "Language"
|
||||
|
||||
data_path = install_path / "rocketstation_Data" / "StreamingAssets" / "Language"
|
||||
if not data_path.is_dir():
|
||||
|
||||
print(f"Invalid install path. {install_path} does not point to a valid Stationeers installation")
|
||||
arg_parser.print_help()
|
||||
sys.exit(1)
|
||||
|
||||
lang = args.lang
|
||||
lang: str = args.lang # type:ignore[reportAny]
|
||||
if not (data_path / f"{lang}.xml").is_file():
|
||||
print("Language file '{lang}.xml' does not exist. can not pull help strings.")
|
||||
sys.exit(2)
|
||||
|
||||
extract_data(install_path, data_path, lang)
|
||||
|
||||
def extract_data(install_path, data_path: Path, language: str):
|
||||
def extract_data(install_path: Path, data_path: Path, language: str):
|
||||
tree = ET.parse(data_path / f"{language}.xml")
|
||||
root = tree.getroot()
|
||||
interface = root.find("Interface")
|
||||
@@ -53,7 +54,7 @@ def extract_data(install_path, data_path: Path, language: str):
|
||||
colors = root.find("Colors")
|
||||
elms = [elm for elm in (interface, strings, colors) if elm is not None ]
|
||||
|
||||
|
||||
|
||||
logic_type = re.compile(r"LogicType(\w+)")
|
||||
logic_slot_type = re.compile(r"LogicSlotType(\w+)")
|
||||
script_command = re.compile(r"ScriptCommand(\w+)")
|
||||
@@ -89,11 +90,11 @@ def extract_data(install_path, data_path: Path, language: str):
|
||||
op_help_patch_path = Path("data") / "instruction_help_patches.json"
|
||||
if op_help_patch_path.exists():
|
||||
with op_help_patch_path.open(mode="r") as f:
|
||||
patches = defaultdict(dict)
|
||||
patches.update(json.load(f))
|
||||
patches: dict[str, dict[str,str]] = defaultdict(dict)
|
||||
patches.update(json.load(f)) # type:ignore[reportAny]
|
||||
operation_help_strings.update(patches[language])
|
||||
|
||||
enums = {}
|
||||
enums: dict[str, tuple[int | None, str]] = {}
|
||||
with (Path("data") / "enums.txt").open("r") as f:
|
||||
for line in f.readlines():
|
||||
match line.strip().split(' ', maxsplit=2):
|
||||
@@ -121,7 +122,7 @@ def extract_data(install_path, data_path: Path, language: str):
|
||||
logictypes[name] = (intOrNone(val), help)
|
||||
case _:
|
||||
pass
|
||||
|
||||
|
||||
with(Path("data") / "slotlogictypes.txt").open("r") as f:
|
||||
for line in f.readlines():
|
||||
match line.strip().split(' ', maxsplit=2):
|
||||
@@ -136,8 +137,8 @@ def extract_data(install_path, data_path: Path, language: str):
|
||||
slotlogictypes[name] = (intOrNone(val), help)
|
||||
case _:
|
||||
pass
|
||||
|
||||
batchmodes = {}
|
||||
|
||||
batchmodes: dict[str, tuple[int | None, str]] = {}
|
||||
with(Path("data") / "batchmodes.txt").open("r") as f:
|
||||
for line in f.readlines():
|
||||
match line.strip().split(' ', maxsplit=2):
|
||||
@@ -148,7 +149,7 @@ def extract_data(install_path, data_path: Path, language: str):
|
||||
case _:
|
||||
pass
|
||||
|
||||
reagentmodes = {}
|
||||
reagentmodes: dict[str, tuple[int | None, str]] = {}
|
||||
with(Path("data") / "reagentmodes.txt").open("r") as f:
|
||||
for line in f.readlines():
|
||||
match line.strip().split(' ', maxsplit=2):
|
||||
@@ -162,8 +163,8 @@ def extract_data(install_path, data_path: Path, language: str):
|
||||
enum_values_path = install_path / "Stationpedia" / "Enums.json"
|
||||
if enum_values_path.exists():
|
||||
with enum_values_path.open(mode="r") as f:
|
||||
enum_values = json.load(f)
|
||||
def update_enum(enum, values):
|
||||
enum_values: dict[str, dict[str, int]] = json.load(f)
|
||||
def update_enum(enum: dict[str, tuple[int | None, str]], values: dict[str, int]):
|
||||
for name, val, in values.items():
|
||||
if name in enum:
|
||||
_, help = enum[name]
|
||||
@@ -178,13 +179,13 @@ def extract_data(install_path, data_path: Path, language: str):
|
||||
update_enum(batchmodes, enum_values["LogicBatchMethod"])
|
||||
update_enum(reagentmodes, enum_values["LogicReagentMode"])
|
||||
update_enum(enums, enum_values["Enums"])
|
||||
|
||||
|
||||
op_help_path = Path("data") / "instructions_help.txt"
|
||||
with op_help_path.open(mode="w") as f:
|
||||
for key, val in sorted(operation_help_strings.items()):
|
||||
f.write("{} {}\n".format(key, val.replace("\r", "").replace("\n", "\\n")))
|
||||
_ = f.write("{} {}\n".format(key, val.replace("\r", "").replace("\n", "\\n")))
|
||||
|
||||
stationpedia: dict[str, tuple[str, str | None]] = {}
|
||||
stationpedia: dict[int, tuple[str, str | None]] = {}
|
||||
things = root.find("Things")
|
||||
reagents = root.find("Reagents")
|
||||
hashables = [elm for elm in (things, reagents) if elm is not None]
|
||||
@@ -197,44 +198,44 @@ def extract_data(install_path, data_path: Path, language: str):
|
||||
value = value.text
|
||||
if key is None:
|
||||
continue
|
||||
crc = binascii.crc32(key.encode('utf-8'))
|
||||
crc_s = struct.unpack("i", struct.pack("I", crc))[0]
|
||||
stationpedia[crc_s] = (key, value)
|
||||
|
||||
crc_u = binascii.crc32(key.encode('utf-8'))
|
||||
crc_i: int = struct.unpack("i", struct.pack("I", crc_u))[0]
|
||||
stationpedia[crc_i] = (key, value)
|
||||
|
||||
exported_stationpedia_path = install_path / "Stationpedia" / "Stationpedia.json"
|
||||
if exported_stationpedia_path.exists():
|
||||
with exported_stationpedia_path.open(mode="r") as f:
|
||||
exported = json.load(f)
|
||||
for page in exported["pages"]:
|
||||
exported: dict[str, list[dict[str, Any]]] = json.load(f) # type:ignore[reportAny]
|
||||
for page in exported["pages"]: # type:ignore[reportUnknownVariableType]
|
||||
stationpedia[page["PrefabHash"]] = (page["PrefabName"], page["Title"])
|
||||
|
||||
|
||||
hashables_path = Path("data") / "stationpedia.txt"
|
||||
with hashables_path.open(mode="w") as f:
|
||||
for key, val in sorted(stationpedia.items(), key=lambda i: i[1][0]):
|
||||
name = val[0]
|
||||
desc = val[1] if val[1] is not None else ""
|
||||
f.write("{} {} {}\n".format(key, name, desc.replace("\r", "").replace("\n", "\\n")))
|
||||
_ = f.write("{} {} {}\n".format(key, name, desc.replace("\r", "").replace("\n", "\\n")))
|
||||
|
||||
logic_types_path = Path("data") / "logictypes.txt"
|
||||
with logic_types_path.open(mode="w") as f:
|
||||
for t, (v, help) in sorted(logictypes.items()):
|
||||
f.write(f"{t} {v} {help.replace("\r", "").replace("\n", "\\n")}\n")
|
||||
_ = f.write(f"{t} {v} {help.replace("\r", "").replace("\n", "\\n")}\n")
|
||||
slot_logic_types_path = Path("data") / "slotlogictypes.txt"
|
||||
with slot_logic_types_path.open(mode="w") as f:
|
||||
for t, (v, help) in sorted(slotlogictypes.items()):
|
||||
f.write(f"{t} {v} {help.replace("\r", "").replace("\n", "\\n")}\n")
|
||||
_ = f.write(f"{t} {v} {help.replace("\r", "").replace("\n", "\\n")}\n")
|
||||
batch_modes_path = Path("data") / "batchmodes.txt"
|
||||
with batch_modes_path.open(mode="w") as f:
|
||||
for t, (v, help) in sorted(batchmodes.items()):
|
||||
f.write(f"{t} {v} {help.replace("\r", "").replace("\n", "\\n")}\n")
|
||||
_ = f.write(f"{t} {v} {help.replace("\r", "").replace("\n", "\\n")}\n")
|
||||
reagent_modes_path = Path("data") / "reagentmodes.txt"
|
||||
with reagent_modes_path.open(mode="w") as f:
|
||||
for t, (v, help) in sorted(reagentmodes.items()):
|
||||
f.write(f"{t} {v} {help.replace("\r", "").replace("\n", "\\n")}\n")
|
||||
_ = f.write(f"{t} {v} {help.replace("\r", "").replace("\n", "\\n")}\n")
|
||||
enums_path = Path("data") / "enums.txt"
|
||||
with enums_path.open(mode="w") as f:
|
||||
for name, (val, help) in sorted(enums.items()):
|
||||
f.write(f"{name} {val} {help.replace("\r", "").replace("\n", "\\n")}\n")
|
||||
_ = f.write(f"{name} {val} {help.replace("\r", "").replace("\n", "\\n")}\n")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@@ -339,7 +339,7 @@ pub struct RegisterSpec {
|
||||
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct DeviceSpec {
|
||||
pub device: Device,
|
||||
pub connection: Option<u32>,
|
||||
pub connection: Option<usize>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
|
||||
@@ -424,7 +424,7 @@ impl Operand {
|
||||
ic: &interpreter::IC,
|
||||
inst: InstructionOp,
|
||||
index: u32,
|
||||
) -> Result<(Option<u16>, Option<u32>), interpreter::ICError> {
|
||||
) -> Result<(Option<u32>, Option<usize>), interpreter::ICError> {
|
||||
match self.translate_alias(ic) {
|
||||
Operand::DeviceSpec(DeviceSpec { device, connection }) => match device {
|
||||
Device::Db => Ok((Some(ic.device), connection)),
|
||||
@@ -615,7 +615,7 @@ impl FromStr for Operand {
|
||||
let connection_str = rest_iter
|
||||
.take_while_ref(|c| c.is_ascii_digit())
|
||||
.collect::<String>();
|
||||
let connection = connection_str.parse::<u32>().unwrap();
|
||||
let connection = connection_str.parse::<usize>().unwrap();
|
||||
if rest_iter.next().is_none() {
|
||||
Ok(Some(connection))
|
||||
} else {
|
||||
@@ -669,7 +669,7 @@ impl FromStr for Operand {
|
||||
let connection_str = rest_iter
|
||||
.take_while_ref(|c| c.is_ascii_digit())
|
||||
.collect::<String>();
|
||||
let connection = connection_str.parse::<u32>().unwrap();
|
||||
let connection = connection_str.parse::<usize>().unwrap();
|
||||
if rest_iter.next().is_none() {
|
||||
Ok(Some(connection))
|
||||
} else {
|
||||
|
||||
@@ -105,11 +105,13 @@ pub enum ICError {
|
||||
#[error("connection specifier missing")]
|
||||
MissingConnectionSpecifier,
|
||||
#[error("no data network on connection '{0}'")]
|
||||
NotDataConnection(usize),
|
||||
NotACableConnection(usize),
|
||||
#[error("network not connected on connection '{0}'")]
|
||||
NetworkNotConnected(usize),
|
||||
#[error("bad network Id '{0}'")]
|
||||
BadNetworkId(u32),
|
||||
#[error("channel index out of range '{0}'")]
|
||||
ChannelIndexOutOfRange(usize),
|
||||
}
|
||||
|
||||
impl ICError {
|
||||
@@ -169,15 +171,17 @@ impl Display for ICState {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct IC {
|
||||
pub device: u16,
|
||||
pub id: u16,
|
||||
pub device: u32,
|
||||
pub id: u32,
|
||||
pub registers: [f64; 18],
|
||||
/// Instruction Pointer
|
||||
pub ip: u32,
|
||||
/// Instruction Count since last yield
|
||||
pub ic: u16,
|
||||
pub stack: [f64; 512],
|
||||
pub aliases: HashMap<String, grammar::Operand>,
|
||||
pub defines: HashMap<String, f64>,
|
||||
pub pins: [Option<u16>; 6],
|
||||
pub pins: [Option<u32>; 6],
|
||||
pub code: String,
|
||||
pub program: Program,
|
||||
pub state: ICState,
|
||||
@@ -295,7 +299,7 @@ impl Program {
|
||||
}
|
||||
|
||||
impl IC {
|
||||
pub fn new(id: u16, device: u16) -> Self {
|
||||
pub fn new(id: u32, device: u32) -> Self {
|
||||
IC {
|
||||
device,
|
||||
id,
|
||||
@@ -2042,8 +2046,14 @@ impl IC {
|
||||
Some(device) => match device.borrow().ic.as_ref() {
|
||||
Some(ic_id) => {
|
||||
let addr = addr.as_value(this, inst, 3)?;
|
||||
let ic = vm.ics.get(ic_id).unwrap().borrow();
|
||||
let val = ic.peek_addr(addr)?;
|
||||
let val = {
|
||||
if ic_id == &this.id {
|
||||
this.peek_addr(addr)
|
||||
} else {
|
||||
let ic = vm.ics.get(ic_id).unwrap().borrow();
|
||||
ic.peek_addr(addr)
|
||||
}
|
||||
}?;
|
||||
this.set_register(indirection, target, val)?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -2069,8 +2079,14 @@ impl IC {
|
||||
Some(device) => match device.borrow().ic.as_ref() {
|
||||
Some(ic_id) => {
|
||||
let addr = addr.as_value(this, inst, 3)?;
|
||||
let ic = vm.ics.get(ic_id).unwrap().borrow();
|
||||
let val = ic.peek_addr(addr)?;
|
||||
let val = {
|
||||
if ic_id == &this.id {
|
||||
this.peek_addr(addr)
|
||||
} else {
|
||||
let ic = vm.ics.get(ic_id).unwrap().borrow();
|
||||
ic.peek_addr(addr)
|
||||
}
|
||||
}?;
|
||||
this.set_register(indirection, target, val)?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -2093,8 +2109,12 @@ impl IC {
|
||||
Some(ic_id) => {
|
||||
let addr = addr.as_value(this, inst, 2)?;
|
||||
let val = val.as_value(this, inst, 3)?;
|
||||
let mut ic = vm.ics.get(ic_id).unwrap().borrow_mut();
|
||||
ic.poke(addr, val)?;
|
||||
if ic_id == &this.id {
|
||||
this.poke(addr, val)?;
|
||||
} else {
|
||||
let mut ic = vm.ics.get(ic_id).unwrap().borrow_mut();
|
||||
ic.poke(addr, val)?;
|
||||
}
|
||||
vm.set_modified(device_id);
|
||||
Ok(())
|
||||
}
|
||||
@@ -2111,15 +2131,19 @@ impl IC {
|
||||
if device_id >= u16::MAX as f64 || device_id < u16::MIN as f64 {
|
||||
return Err(DeviceIndexOutOfRange(device_id));
|
||||
}
|
||||
let device = vm.get_device_same_network(this.device, device_id as u16);
|
||||
let device = vm.get_device_same_network(this.device, device_id as u32);
|
||||
match device {
|
||||
Some(device) => match device.borrow().ic.as_ref() {
|
||||
Some(ic_id) => {
|
||||
let addr = addr.as_value(this, inst, 2)?;
|
||||
let val = val.as_value(this, inst, 3)?;
|
||||
let mut ic = vm.ics.get(ic_id).unwrap().borrow_mut();
|
||||
ic.poke(addr, val)?;
|
||||
vm.set_modified(device_id as u16);
|
||||
if ic_id == &this.id {
|
||||
this.poke(addr, val)?;
|
||||
} else {
|
||||
let mut ic = vm.ics.get(ic_id).unwrap().borrow_mut();
|
||||
ic.poke(addr, val)?;
|
||||
}
|
||||
vm.set_modified(device_id as u32);
|
||||
Ok(())
|
||||
}
|
||||
None => Err(DeviceHasNoIC),
|
||||
@@ -2143,17 +2167,17 @@ impl IC {
|
||||
};
|
||||
let network_id = vm
|
||||
.get_device_same_network(this.device, device_id)
|
||||
.map(|device| device.borrow().get_network_id(connection as usize))
|
||||
.map(|device| device.borrow().get_network_id(connection))
|
||||
.unwrap_or(Err(UnknownDeviceID(device_id as f64)))?;
|
||||
let val = val.as_value(this, inst, 3)?;
|
||||
vm.set_network_channel(network_id as usize, channel, val)?;
|
||||
vm.set_network_channel(network_id, channel, val)?;
|
||||
return Ok(());
|
||||
}
|
||||
let device = vm.get_device_same_network(this.device, device_id);
|
||||
match device {
|
||||
Some(device) => {
|
||||
let val = val.as_value(this, inst, 1)?;
|
||||
device.borrow_mut().set_field(lt, val)?;
|
||||
device.borrow_mut().set_field(lt, val, vm)?;
|
||||
vm.set_modified(device_id);
|
||||
Ok(())
|
||||
}
|
||||
@@ -2168,13 +2192,13 @@ impl IC {
|
||||
if device_id >= u16::MAX as f64 || device_id < u16::MIN as f64 {
|
||||
return Err(DeviceIndexOutOfRange(device_id));
|
||||
}
|
||||
let device = vm.get_device_same_network(this.device, device_id as u16);
|
||||
let device = vm.get_device_same_network(this.device, device_id as u32);
|
||||
match device {
|
||||
Some(device) => {
|
||||
let lt = lt.as_logic_type(this, inst, 2)?;
|
||||
let val = val.as_value(this, inst, 3)?;
|
||||
device.borrow_mut().set_field(lt, val)?;
|
||||
vm.set_modified(device_id as u16);
|
||||
device.borrow_mut().set_field(lt, val, vm)?;
|
||||
vm.set_modified(device_id as u32);
|
||||
Ok(())
|
||||
}
|
||||
None => Err(UnknownDeviceID(device_id)),
|
||||
@@ -2193,7 +2217,7 @@ impl IC {
|
||||
let index = index.as_value(this, inst, 2)?;
|
||||
let slt = slt.as_slot_logic_type(this, inst, 3)?;
|
||||
let val = val.as_value(this, inst, 4)?;
|
||||
device.borrow_mut().set_slot_field(index, slt, val)?;
|
||||
device.borrow_mut().set_slot_field(index, slt, val, vm)?;
|
||||
vm.set_modified(device_id);
|
||||
Ok(())
|
||||
}
|
||||
@@ -2252,16 +2276,16 @@ impl IC {
|
||||
};
|
||||
let network_id = vm
|
||||
.get_device_same_network(this.device, device_id)
|
||||
.map(|device| device.borrow().get_network_id(connection as usize))
|
||||
.map(|device| device.borrow().get_network_id(connection))
|
||||
.unwrap_or(Err(UnknownDeviceID(device_id as f64)))?;
|
||||
let val = vm.get_network_channel(network_id as usize, channel)?;
|
||||
let val = vm.get_network_channel(network_id, channel)?;
|
||||
this.set_register(indirection, target, val)?;
|
||||
return Ok(());
|
||||
}
|
||||
let device = vm.get_device_same_network(this.device, device_id);
|
||||
match device {
|
||||
Some(device) => {
|
||||
let val = device.borrow().get_field(lt)?;
|
||||
let val = device.borrow().get_field(lt, vm)?;
|
||||
this.set_register(indirection, target, val)?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -2280,11 +2304,11 @@ impl IC {
|
||||
if device_id >= u16::MAX as f64 || device_id < u16::MIN as f64 {
|
||||
return Err(DeviceIndexOutOfRange(device_id));
|
||||
}
|
||||
let device = vm.get_device_same_network(this.device, device_id as u16);
|
||||
let device = vm.get_device_same_network(this.device, device_id as u32);
|
||||
match device {
|
||||
Some(device) => {
|
||||
let lt = lt.as_logic_type(this, inst, 3)?;
|
||||
let val = device.borrow().get_field(lt)?;
|
||||
let val = device.borrow().get_field(lt, vm)?;
|
||||
this.set_register(indirection, target, val)?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -2307,7 +2331,7 @@ impl IC {
|
||||
Some(device) => {
|
||||
let index = index.as_value(this, inst, 3)?;
|
||||
let slt = slt.as_slot_logic_type(this, inst, 4)?;
|
||||
let val = device.borrow().get_slot_field(index, slt)?;
|
||||
let val = device.borrow().get_slot_field(index, slt, vm)?;
|
||||
this.set_register(indirection, target, val)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
1326
ic10emu/src/lib.rs
@@ -21,6 +21,11 @@ serde_with = "3.7.0"
|
||||
tsify = { version = "0.4.5", default-features = false, features = ["js", "wasm-bindgen"] }
|
||||
thiserror = "1.0.58"
|
||||
|
||||
[build-dependencies]
|
||||
ic10emu = { path = "../ic10emu" }
|
||||
strum = { version = "0.26.2"}
|
||||
itertools = "0.12.1"
|
||||
|
||||
[features]
|
||||
default = ["console_error_panic_hook"]
|
||||
console_error_panic_hook = ["dep:console_error_panic_hook"]
|
||||
|
||||
@@ -5,18 +5,59 @@ use std::{
|
||||
path::Path,
|
||||
};
|
||||
|
||||
use itertools::Itertools;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
fn main() {
|
||||
let out_dir = env::var_os("OUT_DIR").unwrap();
|
||||
let dest_path = Path::new(&out_dir).join("ts_types.rs");
|
||||
let output_file = File::create(dest_path).unwrap();
|
||||
let mut writer = BufWriter::new(&output_file);
|
||||
|
||||
let mut ts_types: String = String::new();
|
||||
|
||||
let lt_tsunion: String = Itertools::intersperse(
|
||||
ic10emu::grammar::generated::LogicType::iter().map(|lt| format!("\"{}\"", lt.as_ref())),
|
||||
"\n | ".to_owned(),
|
||||
)
|
||||
.collect();
|
||||
let lt_tstype = format!("\nexport type LogicType = {};", lt_tsunion);
|
||||
ts_types.push_str(<_tstype);
|
||||
|
||||
let slt_tsunion: String = Itertools::intersperse(
|
||||
ic10emu::grammar::generated::SlotLogicType::iter().map(|slt| format!("\"{}\"", slt.as_ref())),
|
||||
"\n | ".to_owned(),
|
||||
)
|
||||
.collect();
|
||||
let slt_tstype = format!("\nexport type SlotLogicType = {};", slt_tsunion);
|
||||
ts_types.push_str(&slt_tstype);
|
||||
|
||||
let bm_tsunion: String = Itertools::intersperse(
|
||||
ic10emu::grammar::generated::BatchMode::iter().map(|bm| format!("\"{}\"", bm.as_ref())),
|
||||
"\n | ".to_owned(),
|
||||
)
|
||||
.collect();
|
||||
let bm_tstype = format!("\nexport type BatchMode = {};", bm_tsunion);
|
||||
ts_types.push_str(&bm_tstype);
|
||||
|
||||
let rm_tsunion: String = Itertools::intersperse(
|
||||
ic10emu::grammar::generated::ReagentMode::iter().map(|rm| format!("\"{}\"", rm.as_ref())),
|
||||
"\n | ".to_owned(),
|
||||
)
|
||||
.collect();
|
||||
let rm_tstype = format!("\nexport type ReagentMode = {};", rm_tsunion);
|
||||
ts_types.push_str(&rm_tstype);
|
||||
|
||||
let infile = Path::new("src/types.ts");
|
||||
let contents = fs::read_to_string(infile).unwrap();
|
||||
|
||||
ts_types.push('\n');
|
||||
ts_types.push_str(&contents);
|
||||
|
||||
write!(
|
||||
&mut writer,
|
||||
"#[wasm_bindgen(typescript_custom_section)]\n\
|
||||
const TYPES: &'static str = r#\"{contents}\"#;
|
||||
const TYPES: &'static str = r#\"{ts_types}\"#;
|
||||
"
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
@@ -4,7 +4,7 @@ mod types;
|
||||
|
||||
use ic10emu::{
|
||||
grammar::{LogicType, SlotLogicType},
|
||||
Connection,
|
||||
DeviceTemplate,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use types::{Registers, Stack};
|
||||
@@ -43,38 +43,59 @@ impl DeviceRef {
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter)]
|
||||
pub fn id(&self) -> u16 {
|
||||
pub fn id(&self) -> u32 {
|
||||
self.device.borrow().id
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter)]
|
||||
pub fn ic(&self) -> Option<u32> {
|
||||
self.device.borrow().ic
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter)]
|
||||
pub fn name(&self) -> Option<String> {
|
||||
self.device.borrow().name.clone()
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter, js_name = "nameHash")]
|
||||
pub fn name_hash(&self) -> Option<f64> {
|
||||
pub fn name_hash(&self) -> Option<i32> {
|
||||
self.device.borrow().name_hash
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter, js_name = "prefabName")]
|
||||
pub fn prefab_name(&self) -> Option<String> {
|
||||
self.device.borrow().prefab_name.clone()
|
||||
self.device
|
||||
.borrow()
|
||||
.prefab
|
||||
.as_ref()
|
||||
.map(|prefab| prefab.name.clone())
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter, js_name = "prefabHash")]
|
||||
pub fn prefab_hash(&self) -> Option<i32> {
|
||||
self.device.borrow().prefab_hash
|
||||
self.device
|
||||
.borrow()
|
||||
.prefab
|
||||
.as_ref()
|
||||
.map(|prefab| prefab.hash)
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter, skip_typescript)]
|
||||
pub fn fields(&self) -> JsValue {
|
||||
serde_wasm_bindgen::to_value(&self.device.borrow().fields).unwrap()
|
||||
serde_wasm_bindgen::to_value(&self.device.borrow().get_fields(&self.vm.borrow())).unwrap()
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter, skip_typescript)]
|
||||
pub fn slots(&self) -> JsValue {
|
||||
serde_wasm_bindgen::to_value(&self.device.borrow().slots).unwrap()
|
||||
pub fn slots(&self) -> Vec<JsValue> {
|
||||
self.device
|
||||
.borrow()
|
||||
.slots
|
||||
.iter()
|
||||
.map(|slot| {
|
||||
let flat_slot: types::Slot = slot.into();
|
||||
serde_wasm_bindgen::to_value(&flat_slot).unwrap()
|
||||
})
|
||||
.collect_vec()
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter, skip_typescript)]
|
||||
@@ -267,67 +288,55 @@ impl DeviceRef {
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "setField")]
|
||||
pub fn set_field(&self, field: &str, value: f64) -> Result<f64, JsError> {
|
||||
pub fn set_field(&self, field: &str, value: f64) -> Result<(), JsError> {
|
||||
let logic_typ = LogicType::from_str(field)?;
|
||||
let mut device_ref = self.device.borrow_mut();
|
||||
let logic_field = device_ref
|
||||
.fields
|
||||
.get_mut(&logic_typ)
|
||||
.ok_or_else(|| BindingError::InvalidEnumVariant(field.to_owned()))?;
|
||||
let last = logic_field.value;
|
||||
logic_field.value = value;
|
||||
Ok(last)
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "setSlotField")]
|
||||
pub fn set_slot_field(&self, slot: usize, field: &str, value: f64) -> Result<f64, JsError> {
|
||||
let logic_typ = SlotLogicType::from_str(field)?;
|
||||
let mut device_ref = self.device.borrow_mut();
|
||||
let slots_len = device_ref.slots.len();
|
||||
let slot = device_ref
|
||||
.slots
|
||||
.get_mut(slot)
|
||||
.ok_or(BindingError::OutOfBounds(slot, slots_len))?;
|
||||
let logic_field = slot
|
||||
.fields
|
||||
.get_mut(&logic_typ)
|
||||
.ok_or_else(|| BindingError::InvalidEnumVariant(field.to_owned()))?;
|
||||
let last = logic_field.value;
|
||||
logic_field.value = value;
|
||||
Ok(last)
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "setConnection")]
|
||||
pub fn set_connection(&self, conn: usize, net: Option<u16>) -> Result<(), JsError> {
|
||||
let mut device_ref = self.device.borrow_mut();
|
||||
let conn_len = device_ref.connections.len();
|
||||
let conn_ref = device_ref
|
||||
.connections
|
||||
.get_mut(conn)
|
||||
.ok_or(BindingError::OutOfBounds(conn, conn_len))?;
|
||||
match conn_ref {
|
||||
&mut Connection::CableNetwork(ref mut net_ref) => *net_ref = net,
|
||||
_ => {
|
||||
*conn_ref = Connection::CableNetwork(net);
|
||||
}
|
||||
}
|
||||
device_ref.set_field(logic_typ, value, &self.vm.borrow())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "addDeviceToNetwork")]
|
||||
pub fn add_device_to_network(&self, network_id: u16, connection: usize) -> Result<bool, JsError> {
|
||||
let id = self.device.borrow().id;
|
||||
Ok(self.vm.borrow().add_device_to_network(id, network_id, connection)?)
|
||||
#[wasm_bindgen(js_name = "setSlotField")]
|
||||
pub fn set_slot_field(&self, slot: f64, field: &str, value: f64) -> Result<(), JsError> {
|
||||
let logic_typ = SlotLogicType::from_str(field)?;
|
||||
let mut device_ref = self.device.borrow_mut();
|
||||
device_ref.set_slot_field(slot, logic_typ, value, &self.vm.borrow())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "getSlotField")]
|
||||
pub fn get_slot_field(&self, slot: f64, field: &str) -> Result<f64, JsError> {
|
||||
let logic_typ = SlotLogicType::from_str(field)?;
|
||||
let device_ref = self.device.borrow_mut();
|
||||
Ok(device_ref.get_slot_field(slot, logic_typ, &self.vm.borrow())?)
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "getSlotFields", skip_typescript)]
|
||||
pub fn get_slot_fields(&self, slot: f64) -> Result<JsValue, JsError> {
|
||||
let device_ref = self.device.borrow_mut();
|
||||
let fields = device_ref.get_slot_fields(slot, &self.vm.borrow())?;
|
||||
Ok(serde_wasm_bindgen::to_value(&fields).unwrap())
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "setConnection")]
|
||||
pub fn set_connection(&self, conn: usize, net: Option<u32>) -> Result<(), JsError> {
|
||||
let device_id = self.device.borrow().id;
|
||||
self.vm
|
||||
.borrow()
|
||||
.set_device_connection(device_id, conn, net)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "removeDeviceFromNetwork")]
|
||||
pub fn remove_device_from_network(&self, network_id: u16) -> Result<bool, JsError> {
|
||||
pub fn remove_device_from_network(&self, network_id: u32) -> Result<bool, JsError> {
|
||||
let id = self.device.borrow().id;
|
||||
Ok(self.vm.borrow().remove_device_from_network(id, network_id)?)
|
||||
Ok(self
|
||||
.vm
|
||||
.borrow()
|
||||
.remove_device_from_network(id, network_id)?)
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "setPin")]
|
||||
pub fn set_pin(&self, pin: usize, val: Option<u16>) -> Result<bool, JsError> {
|
||||
pub fn set_pin(&self, pin: usize, val: Option<u32>) -> Result<bool, JsError> {
|
||||
let id = self.device.borrow().id;
|
||||
Ok(self.vm.borrow().set_pin(id, pin, val)?)
|
||||
}
|
||||
@@ -349,89 +358,118 @@ impl VM {
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "addDevice")]
|
||||
pub fn add_device(&self, network: Option<u16>) -> Result<u16, JsError> {
|
||||
pub fn add_device(&self, network: Option<u32>) -> Result<u32, JsError> {
|
||||
Ok(self.vm.borrow_mut().add_device(network)?)
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "addDeviceFromTemplate", skip_typescript)]
|
||||
pub fn add_device_from_template(&self, template: JsValue) -> Result<u32, JsError> {
|
||||
let template: DeviceTemplate = serde_wasm_bindgen::from_value(template)?;
|
||||
web_sys::console::log_2(
|
||||
&"(wasm) adding device".into(),
|
||||
&serde_wasm_bindgen::to_value(&template).unwrap(),
|
||||
);
|
||||
Ok(self.vm.borrow_mut().add_device_from_template(template)?)
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "getDevice")]
|
||||
pub fn get_device(&self, id: u16) -> Option<DeviceRef> {
|
||||
pub fn get_device(&self, id: u32) -> Option<DeviceRef> {
|
||||
let device = self.vm.borrow().get_device(id);
|
||||
device.map(|d| DeviceRef::from_device(d.clone(), self.vm.clone()))
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "setCode")]
|
||||
/// Set program code if it's valid
|
||||
pub fn set_code(&self, id: u16, code: &str) -> Result<bool, JsError> {
|
||||
pub fn set_code(&self, id: u32, code: &str) -> Result<bool, JsError> {
|
||||
Ok(self.vm.borrow().set_code(id, code)?)
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "setCodeInvalid")]
|
||||
/// Set program code and translate invalid lines to Nop, collecting errors
|
||||
pub fn set_code_invalid(&self, id: u16, code: &str) -> Result<bool, JsError> {
|
||||
pub fn set_code_invalid(&self, id: u32, code: &str) -> Result<bool, JsError> {
|
||||
Ok(self.vm.borrow().set_code_invalid(id, code)?)
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "stepIC")]
|
||||
pub fn step_ic(&self, id: u16, advance_ip_on_err: bool) -> Result<bool, JsError> {
|
||||
pub fn step_ic(&self, id: u32, advance_ip_on_err: bool) -> Result<bool, JsError> {
|
||||
Ok(self.vm.borrow().step_ic(id, advance_ip_on_err)?)
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "runIC")]
|
||||
pub fn run_ic(&self, id: u16, ignore_errors: bool) -> Result<bool, JsError> {
|
||||
pub fn run_ic(&self, id: u32, ignore_errors: bool) -> Result<bool, JsError> {
|
||||
Ok(self.vm.borrow().run_ic(id, ignore_errors)?)
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "resetIC")]
|
||||
pub fn reset_ic(&self, id: u16) -> Result<bool, JsError> {
|
||||
pub fn reset_ic(&self, id: u32) -> Result<bool, JsError> {
|
||||
Ok(self.vm.borrow().reset_ic(id)?)
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter, js_name = "defaultNetwork")]
|
||||
pub fn default_network(&self) -> u16 {
|
||||
pub fn default_network(&self) -> u32 {
|
||||
self.vm.borrow().default_network
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter)]
|
||||
pub fn devices(&self) -> Vec<u16> {
|
||||
pub fn devices(&self) -> Vec<u32> {
|
||||
self.vm.borrow().devices.keys().copied().collect_vec()
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter)]
|
||||
pub fn networks(&self) -> Vec<u16> {
|
||||
pub fn networks(&self) -> Vec<u32> {
|
||||
self.vm.borrow().networks.keys().copied().collect_vec()
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter)]
|
||||
pub fn ics(&self) -> Vec<u16> {
|
||||
pub fn ics(&self) -> Vec<u32> {
|
||||
self.vm.borrow().ics.keys().copied().collect_vec()
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter, js_name = "lastOperationModified")]
|
||||
pub fn last_operation_modified(&self) -> Vec<u16> {
|
||||
pub fn last_operation_modified(&self) -> Vec<u32> {
|
||||
self.vm.borrow().last_operation_modified()
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "visibleDevices")]
|
||||
pub fn visible_devices(&self, source: u16) -> Vec<u16> {
|
||||
pub fn visible_devices(&self, source: u32) -> Vec<u32> {
|
||||
self.vm.borrow().visible_devices(source)
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "addDeviceToNetwork")]
|
||||
pub fn add_device_to_network(&self, id: u16, network_id: u16, connection: usize) -> Result<bool, JsError> {
|
||||
Ok(self.vm.borrow().add_device_to_network(id, network_id, connection)?)
|
||||
#[wasm_bindgen(js_name = "setDeviceConnection")]
|
||||
pub fn set_device_connection(
|
||||
&self,
|
||||
id: u32,
|
||||
connection: usize,
|
||||
network_id: Option<u32>,
|
||||
) -> Result<bool, JsError> {
|
||||
Ok(self
|
||||
.vm
|
||||
.borrow()
|
||||
.set_device_connection(id, connection, network_id)?)
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "removeDeviceFromNetwork")]
|
||||
pub fn remove_device_from_network(&self, id: u16, network_id: u16) -> Result<bool, JsError> {
|
||||
Ok(self.vm.borrow().remove_device_from_network(id, network_id)?)
|
||||
pub fn remove_device_from_network(&self, id: u32, network_id: u32) -> Result<bool, JsError> {
|
||||
Ok(self
|
||||
.vm
|
||||
.borrow()
|
||||
.remove_device_from_network(id, network_id)?)
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "setPin")]
|
||||
pub fn set_pin(&self, id: u16, pin: usize, val: Option<u16>) -> Result<bool, JsError> {
|
||||
pub fn set_pin(&self, id: u32, pin: usize, val: Option<u32>) -> Result<bool, JsError> {
|
||||
Ok(self.vm.borrow().set_pin(id, pin, val)?)
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "changeDeviceId")]
|
||||
pub fn change_device_id(&self, old_id: u32, new_id: u32) -> Result<(), JsError> {
|
||||
Ok(self.vm.borrow_mut().change_device_id(old_id, new_id)?)
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "removeDevice")]
|
||||
pub fn remove_device(&self, id: u32) -> Result<(), JsError> {
|
||||
Ok(self.vm.borrow_mut().remove_device(id)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for VM {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_with::serde_as;
|
||||
@@ -14,4 +15,45 @@ pub struct Stack(#[serde_as(as = "[_; 512]")] pub [f64; 512]);
|
||||
#[tsify(into_wasm_abi, from_wasm_abi)]
|
||||
pub struct Registers(#[serde_as(as = "[_; 18]")] pub [f64; 18]);
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/ts_types.rs"));
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct SlotOccupant {
|
||||
pub id: u32,
|
||||
pub prefab_hash: i32,
|
||||
pub quantity: u32,
|
||||
pub max_quantity: u32,
|
||||
pub damage: f64,
|
||||
pub fields: HashMap<ic10emu::grammar::SlotLogicType, ic10emu::LogicField>,
|
||||
}
|
||||
|
||||
impl From<&ic10emu::SlotOccupant> for SlotOccupant {
|
||||
fn from(value: &ic10emu::SlotOccupant) -> Self {
|
||||
SlotOccupant {
|
||||
id: value.id,
|
||||
prefab_hash: value.prefab_hash,
|
||||
quantity: value.quantity,
|
||||
max_quantity: value.max_quantity,
|
||||
damage: value.damage,
|
||||
fields: value.get_fields(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Serialize, Deserialize)]
|
||||
pub struct Slot {
|
||||
pub typ: ic10emu::SlotType,
|
||||
pub occupant: Option<SlotOccupant>,
|
||||
pub fields: HashMap<ic10emu::grammar::SlotLogicType, ic10emu::LogicField>,
|
||||
}
|
||||
|
||||
impl From<&ic10emu::Slot> for Slot {
|
||||
fn from(value: &ic10emu::Slot) -> Self {
|
||||
Slot {
|
||||
typ: value.typ,
|
||||
occupant: value.occupant.as_ref().map(|occupant| occupant.into()),
|
||||
fields: value.get_fields(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/ts_types.rs"));
|
||||
|
||||
|
||||
@@ -4,7 +4,8 @@ export interface LogicField {
|
||||
field_type: FieldType;
|
||||
value: number;
|
||||
}
|
||||
export type Fields = Map<string, LogicField>;
|
||||
export type LogicFields = Map<LogicType, LogicField>;
|
||||
export type SlotLogicFields = Map<SlotLogicType, LogicField>;
|
||||
|
||||
export type SlotType =
|
||||
| "AccessCard"
|
||||
@@ -40,39 +41,63 @@ export type SlotType =
|
||||
| "Torpedo"
|
||||
| "None";
|
||||
|
||||
export interface SlotOccupant {
|
||||
readonly id: number;
|
||||
readonly prefab_hash: number;
|
||||
readonly quantity: number;
|
||||
readonly max_quantity: number;
|
||||
readonly damage: number;
|
||||
readonly fields: SlotLogicFields;
|
||||
}
|
||||
export interface Slot {
|
||||
typ: SlotType;
|
||||
fields: Fields;
|
||||
readonly typ: SlotType;
|
||||
readonly occupant: SlotOccupant | undefined;
|
||||
readonly fields: SlotLogicFields;
|
||||
}
|
||||
|
||||
export type Reagents = Map<string, Map<number, number>>;
|
||||
|
||||
export type Connection = { CableNetwork: number } | "Other";
|
||||
export interface ConnectionCableNetwork {
|
||||
CableNetwork: {
|
||||
net: number | undefined;
|
||||
typ: string;
|
||||
};
|
||||
}
|
||||
|
||||
export type Connection = ConnectionCableNetwork | "Other";
|
||||
|
||||
export type RegisterSpec = {
|
||||
RegisterSpec: { indirection: number; target: number };
|
||||
readonly RegisterSpec: {
|
||||
readonly indirection: number;
|
||||
readonly target: number;
|
||||
};
|
||||
};
|
||||
export type DeviceSpec = {
|
||||
DeviceSpec: {
|
||||
device:
|
||||
readonly DeviceSpec: {
|
||||
readonly device:
|
||||
| "Db"
|
||||
| { Numbered: number }
|
||||
| { Indirect: { indirection: number; target: number } };
|
||||
| { readonly Numbered: number }
|
||||
| {
|
||||
readonly Indirect: {
|
||||
readonly indirection: number;
|
||||
readonly target: number;
|
||||
};
|
||||
};
|
||||
};
|
||||
connection: number | undefined;
|
||||
readonly connection: number | undefined;
|
||||
};
|
||||
export type LogicType = { LogicType: string };
|
||||
export type SlotLogicType = { SlotLogicType: string };
|
||||
export type BatchMode = { BatchMode: string };
|
||||
export type ReagentMode = { ReagentMode: string };
|
||||
export type Identifier = { Identifier: { name: string } };
|
||||
export type OperandLogicType = { readonly LogicType: string };
|
||||
export type OperandSlotLogicType = { readonly SlotLogicType: string };
|
||||
export type OperandBatchMode = { readonly BatchMode: string };
|
||||
export type OperandReagentMode = { readonly ReagentMode: string };
|
||||
export type Identifier = { readonly Identifier: { name: string } };
|
||||
|
||||
export type NumberFloat = { Float: number };
|
||||
export type NumberBinary = { Binary: number };
|
||||
export type NumberHexadecimal = { Hexadecimal: number };
|
||||
export type NumberConstant = { Constant: number };
|
||||
export type NumberString = { String: string };
|
||||
export type NumberEnum = { Enum: number };
|
||||
export type NumberFloat = { readonly Float: number };
|
||||
export type NumberBinary = { readonly Binary: number };
|
||||
export type NumberHexadecimal = { readonly Hexadecimal: number };
|
||||
export type NumberConstant = { readonly Constant: number };
|
||||
export type NumberString = { readonly String: string };
|
||||
export type NumberEnum = { readonly Enum: number };
|
||||
|
||||
export type NumberOperand = {
|
||||
Number:
|
||||
@@ -87,10 +112,10 @@ export type Operand =
|
||||
| RegisterSpec
|
||||
| DeviceSpec
|
||||
| NumberOperand
|
||||
| LogicType
|
||||
| SlotLogicType
|
||||
| BatchMode
|
||||
| ReagentMode
|
||||
| OperandLogicType
|
||||
| OperandSlotLogicType
|
||||
| OperandBatchMode
|
||||
| OperandReagentMode
|
||||
| Identifier;
|
||||
|
||||
export type Alias = RegisterSpec | DeviceSpec;
|
||||
@@ -102,22 +127,27 @@ export type Defines = Map<string, number>;
|
||||
export type Pins = (number | undefined)[];
|
||||
|
||||
export interface Instruction {
|
||||
instruction: string;
|
||||
operands: Operand[];
|
||||
readonly instruction: string;
|
||||
readonly operands: Operand[];
|
||||
}
|
||||
|
||||
export type ICError = {
|
||||
ParseError: { line: number; start: number; end: number; msg: string };
|
||||
readonly ParseError: {
|
||||
readonly line: number;
|
||||
readonly start: number;
|
||||
readonly end: number;
|
||||
readonly msg: string;
|
||||
};
|
||||
};
|
||||
|
||||
export interface Program {
|
||||
instructions: Instruction[];
|
||||
errors: ICError[];
|
||||
labels: Map<string, number>;
|
||||
readonly instructions: Instruction[];
|
||||
readonly errors: ICError[];
|
||||
readonly labels: Map<string, number>;
|
||||
}
|
||||
|
||||
export interface DeviceRef {
|
||||
readonly fields: Fields;
|
||||
readonly fields: LogicFields;
|
||||
readonly slots: Slot[];
|
||||
readonly reagents: Reagents;
|
||||
readonly connections: Connection[];
|
||||
@@ -125,4 +155,29 @@ export interface DeviceRef {
|
||||
readonly defines?: Defines | undefined;
|
||||
readonly pins?: Pins;
|
||||
readonly program?: Program;
|
||||
getSlotFields(slot: number): SlotLogicFields;
|
||||
}
|
||||
|
||||
export interface SlotOccupantTemplate {
|
||||
id?: number;
|
||||
fields: { [key in SlotLogicType]?: LogicField };
|
||||
}
|
||||
|
||||
export interface SlotTemplate {
|
||||
typ: SlotType;
|
||||
occupant?: SlotOccupantTemplate;
|
||||
}
|
||||
|
||||
export interface DeviceTemplate {
|
||||
id?: number;
|
||||
name?: string;
|
||||
prefab_name?: string;
|
||||
slots: SlotTemplate[];
|
||||
// reagents: { [key: string]: float}
|
||||
connections: Connection[];
|
||||
fields: { [key in LogicType]?: LogicField };
|
||||
}
|
||||
|
||||
export interface VM {
|
||||
addDeviceFromTemplate(template: DeviceTemplate): number;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@@ -38,7 +38,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@@ -58,7 +58,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@@ -80,7 +80,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@@ -178,8 +178,7 @@
|
||||
" candidates.append((name, entry[\"name\"].removeprefix(\"Item\"), entry[\"name\"]))\n",
|
||||
" if entry[\"name\"].removeprefix(\"Structure\") in name:\n",
|
||||
" candidates.append((name, entry[\"name\"].removeprefix(\"Structure\"), entry[\"name\"]))\n",
|
||||
" image_candidates[entry[\"name\"]] = filter_candidates(candidates)\n",
|
||||
"\n"
|
||||
" image_candidates[entry[\"name\"]] = filter_candidates(candidates)"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -191,7 +190,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"execution_count": 17,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@@ -212,30 +211,30 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"execution_count": 18,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"ItemBiomass []\n",
|
||||
"StructureBlocker []\n",
|
||||
"CartridgePlantAnalyser []\n",
|
||||
"StructureElevatorLevelIndustrial []\n",
|
||||
"ItemPlantEndothermic_Creative []\n",
|
||||
"Flag_ODA_10m []\n",
|
||||
"Flag_ODA_4m []\n",
|
||||
"Flag_ODA_6m []\n",
|
||||
"Flag_ODA_8m []\n",
|
||||
"ItemBiomass []\n",
|
||||
"ItemHorticultureBelt []\n",
|
||||
"ItemKitLiquidRegulator []\n",
|
||||
"ItemKitPortablesConnector []\n",
|
||||
"ItemMushroom ['ItemMushroom-resources.assets-3022.png', 'ItemMushroom-resources.assets-9304.png']\n",
|
||||
"ItemPlantEndothermic_Creative []\n",
|
||||
"ItemPlantThermogenic_Creative []\n",
|
||||
"Landingpad_GasConnectorInwardPiece []\n",
|
||||
"Landingpad_LiquidConnectorInwardPiece []\n",
|
||||
"ItemMushroom ['ItemMushroom-resources.assets-3022.png', 'ItemMushroom-resources.assets-9304.png']\n",
|
||||
"StructurePlinth []\n",
|
||||
"ItemPlantThermogenic_Creative []\n"
|
||||
"StructureBlocker []\n",
|
||||
"StructureElevatorLevelIndustrial []\n",
|
||||
"StructurePlinth []\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -254,14 +253,95 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"execution_count": 21,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"1223 of 1223 | 100.00% \n",
|
||||
"missing Egg\n",
|
||||
"missing Appliance\n",
|
||||
"missing Ingot\n",
|
||||
"missing Torpedo\n",
|
||||
"missing Magazine\n",
|
||||
"missing SensorProcessingUnit\n",
|
||||
"missing LiquidCanister\n",
|
||||
"missing LiquidBottle\n",
|
||||
"missing Wreckage\n",
|
||||
"missing SoundCartridge\n",
|
||||
"missing DrillHead\n",
|
||||
"missing ScanningHead\n",
|
||||
"missing Flare\n",
|
||||
"missing Blocked\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"slot_types = [\n",
|
||||
" \"Helmet\",\n",
|
||||
" \"Suit\",\n",
|
||||
" \"Back\",\n",
|
||||
" \"GasFilter\",\n",
|
||||
" \"GasCanister\",\n",
|
||||
" \"MotherBoard\",\n",
|
||||
" \"Circuitboard\",\n",
|
||||
" \"DataDisk\",\n",
|
||||
" \"Organ\",\n",
|
||||
" \"Ore\",\n",
|
||||
" \"Plant\",\n",
|
||||
" \"Uniform\",\n",
|
||||
" \"Entity\",\n",
|
||||
" \"Battery\",\n",
|
||||
" \"Egg\",\n",
|
||||
" \"Belt\",\n",
|
||||
" \"Tool\",\n",
|
||||
" \"Appliance\",\n",
|
||||
" \"Ingot\",\n",
|
||||
" \"Torpedo\",\n",
|
||||
" \"Cartridge\",\n",
|
||||
" \"AccessCard\",\n",
|
||||
" \"Magazine\",\n",
|
||||
" \"Circuit\",\n",
|
||||
" \"Bottle\",\n",
|
||||
" \"ProgrammableChip\",\n",
|
||||
" \"Glasses\",\n",
|
||||
" \"CreditCard\",\n",
|
||||
" \"DirtCanister\",\n",
|
||||
" \"SensorProcessingUnit\",\n",
|
||||
" \"LiquidCanister\",\n",
|
||||
" \"LiquidBottle\",\n",
|
||||
" \"Wreckage\",\n",
|
||||
" \"SoundCartridge\",\n",
|
||||
" \"DrillHead\",\n",
|
||||
" \"ScanningHead\",\n",
|
||||
" \"Flare\",\n",
|
||||
" \"Blocked\",\n",
|
||||
"]\n",
|
||||
"sloticons = []\n",
|
||||
"for typ in slot_types:\n",
|
||||
" try_name = f\"sloticon_{typ.lower()}\"\n",
|
||||
" found = False\n",
|
||||
" for name in names:\n",
|
||||
" if name.startswith(try_name):\n",
|
||||
" sloticons.append([f\"SlotIcon_{typ}\", name])\n",
|
||||
" found = True\n",
|
||||
" if not found:\n",
|
||||
" print(f\"missing {typ}\")\n",
|
||||
"\n",
|
||||
"to_copy.extend(sloticons)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 22,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"1266 of 1266 | 100.00% \n",
|
||||
"Done\n"
|
||||
]
|
||||
}
|
||||
@@ -284,13 +364,6 @@
|
||||
"print(\"Done\")\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
|
||||
129
www/cspell.json
@@ -1 +1,128 @@
|
||||
{"words":["Astroloy","Autolathe","bapal","bapz","bapzal","batchmode","batchmodes","bdns","bdnsal","bdse","bdseal","beqal","beqz","beqzal","bgeal","bgez","bgezal","bgtal","bgtz","bgtzal","bleal","blez","blezal","bltal","bltz","bltzal","bnaal","bnan","bnaz","bnazal","bneal","bnez","bnezal","brap","brapz","brdns","brdse","breq","breqz","brge","brgez","brgt","brgtz","brle","brlez","brlt","brltz","brna","brnan","brnaz","brne","brnez","Circuitboard","codegen","Depressurising","endpos","getd","Hardsuit","hardwrap","hashables","hstack","infile","jetpack","Keybind","lbns","logicable","logicslottypes","logictype","logictypes","lparen","Mineables","modelist","ninf","noconflict","offcanvas","overcolumn","Overlength","pedia","pinf","popperjs","preproc","Pressurising","putd","QUICKFIX","reagentmode","reagentmodes","rocketstation","rparen","sapz","sattellite","sdns","sdse","seqz","serde","sgez","sgtz","slez","slotlogic","slotlogicable","slotlogictype","slotlogictypes","slottype","sltz","snan","snanz","snaz","snez","splitn","Stationeers","stationpedia","themelist","tokentype","trunc","whos","regen","regen","tablist","tabpanel","labelledby"],"flagWords":[],"language":"en","version":"0.2"}
|
||||
{
|
||||
"words": [
|
||||
"Astroloy",
|
||||
"Autolathe",
|
||||
"bapal",
|
||||
"bapz",
|
||||
"bapzal",
|
||||
"batchmode",
|
||||
"batchmodes",
|
||||
"bdns",
|
||||
"bdnsal",
|
||||
"bdse",
|
||||
"bdseal",
|
||||
"beqal",
|
||||
"beqz",
|
||||
"beqzal",
|
||||
"bgeal",
|
||||
"bgez",
|
||||
"bgezal",
|
||||
"bgtal",
|
||||
"bgtz",
|
||||
"bgtzal",
|
||||
"bleal",
|
||||
"blez",
|
||||
"blezal",
|
||||
"bltal",
|
||||
"bltz",
|
||||
"bltzal",
|
||||
"bnaal",
|
||||
"bnan",
|
||||
"bnaz",
|
||||
"bnazal",
|
||||
"bneal",
|
||||
"bnez",
|
||||
"bnezal",
|
||||
"brap",
|
||||
"brapz",
|
||||
"brdns",
|
||||
"brdse",
|
||||
"breq",
|
||||
"breqz",
|
||||
"brge",
|
||||
"brgez",
|
||||
"brgt",
|
||||
"brgtz",
|
||||
"brle",
|
||||
"brlez",
|
||||
"brlt",
|
||||
"brltz",
|
||||
"brna",
|
||||
"brnan",
|
||||
"brnaz",
|
||||
"brne",
|
||||
"brnez",
|
||||
"Circuitboard",
|
||||
"codegen",
|
||||
"Depressurising",
|
||||
"deviceslength",
|
||||
"endpos",
|
||||
"getd",
|
||||
"Hardsuit",
|
||||
"hardwrap",
|
||||
"hashables",
|
||||
"hstack",
|
||||
"infile",
|
||||
"jetpack",
|
||||
"Keybind",
|
||||
"labelledby",
|
||||
"lbns",
|
||||
"logicable",
|
||||
"logicslottypes",
|
||||
"logictype",
|
||||
"logictypes",
|
||||
"lparen",
|
||||
"Mineables",
|
||||
"modelist",
|
||||
"ninf",
|
||||
"noconflict",
|
||||
"offcanvas",
|
||||
"overcolumn",
|
||||
"Overlength",
|
||||
"pedia",
|
||||
"pinf",
|
||||
"popperjs",
|
||||
"preproc",
|
||||
"Pressurising",
|
||||
"putd",
|
||||
"QUICKFIX",
|
||||
"reagentmode",
|
||||
"reagentmodes",
|
||||
"regen",
|
||||
"rocketstation",
|
||||
"rparen",
|
||||
"sapz",
|
||||
"sattellite",
|
||||
"sdns",
|
||||
"sdse",
|
||||
"seqz",
|
||||
"serde",
|
||||
"sgez",
|
||||
"sgtz",
|
||||
"slez",
|
||||
"slotclass",
|
||||
"slotlogic",
|
||||
"slotlogicable",
|
||||
"slotlogictype",
|
||||
"slotlogictypes",
|
||||
"slottype",
|
||||
"sltz",
|
||||
"snan",
|
||||
"snanz",
|
||||
"snaz",
|
||||
"snez",
|
||||
"sortingclass",
|
||||
"splitn",
|
||||
"Stationeers",
|
||||
"stationpedia",
|
||||
"tablist",
|
||||
"tabpanel",
|
||||
"themelist",
|
||||
"tokentype",
|
||||
"trunc",
|
||||
"whos"
|
||||
],
|
||||
"flagWords": [],
|
||||
"language": "en",
|
||||
"version": "0.2"
|
||||
}
|
||||
|
||||
38289
www/data/database.json
BIN
www/img/stationpedia/SlotIcon_AccessCard.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
www/img/stationpedia/SlotIcon_Back.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
www/img/stationpedia/SlotIcon_Battery.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
www/img/stationpedia/SlotIcon_Belt.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
www/img/stationpedia/SlotIcon_Bottle.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
www/img/stationpedia/SlotIcon_Cartridge.png
Normal file
|
After Width: | Height: | Size: 665 B |
BIN
www/img/stationpedia/SlotIcon_Circuit.png
Normal file
|
After Width: | Height: | Size: 961 B |
BIN
www/img/stationpedia/SlotIcon_Circuitboard.png
Normal file
|
After Width: | Height: | Size: 961 B |
BIN
www/img/stationpedia/SlotIcon_CreditCard.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
www/img/stationpedia/SlotIcon_DataDisk.png
Normal file
|
After Width: | Height: | Size: 483 B |
BIN
www/img/stationpedia/SlotIcon_DirtCanister.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
www/img/stationpedia/SlotIcon_Entity.png
Normal file
|
After Width: | Height: | Size: 791 B |
BIN
www/img/stationpedia/SlotIcon_GasCanister.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
www/img/stationpedia/SlotIcon_GasFilter.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
www/img/stationpedia/SlotIcon_Glasses.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
www/img/stationpedia/SlotIcon_Helmet.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
www/img/stationpedia/SlotIcon_Motherboard.png
Normal file
|
After Width: | Height: | Size: 270 B |
BIN
www/img/stationpedia/SlotIcon_Ore.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
www/img/stationpedia/SlotIcon_Organ.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
www/img/stationpedia/SlotIcon_Plant.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
www/img/stationpedia/SlotIcon_ProgrammableChip.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
www/img/stationpedia/SlotIcon_Suit.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
www/img/stationpedia/SlotIcon_Tool.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
www/img/stationpedia/SlotIcon_Uniform.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
@@ -30,7 +30,7 @@
|
||||
"@types/wicg-file-system-access": "^2023.10.5",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"copy-webpack-plugin": "^12.0.2",
|
||||
"css-loader": "^6.10.0",
|
||||
"css-loader": "^6.11.0",
|
||||
"css-minimizer-webpack-plugin": "^6.0.0",
|
||||
"esbuild": "^0.20.2",
|
||||
"esbuild-loader": "^4.1.0",
|
||||
@@ -45,15 +45,15 @@
|
||||
"imagemin-optipng": "^8.0.0",
|
||||
"imagemin-svgo": "^10.0.1",
|
||||
"lit-scss-loader": "^2.0.1",
|
||||
"mini-css-extract-plugin": "^2.8.1",
|
||||
"mini-css-extract-plugin": "^2.9.0",
|
||||
"postcss-loader": "^8.1.1",
|
||||
"sass": "^1.72.0",
|
||||
"sass-loader": "^14.1.1",
|
||||
"sass": "^1.75.0",
|
||||
"sass-loader": "^14.2.1",
|
||||
"style-loader": "^3.3.4",
|
||||
"thread-loader": "^4.0.2",
|
||||
"ts-lit-plugin": "^2.0.2",
|
||||
"ts-loader": "^9.5.1",
|
||||
"typescript": "^5.4.3",
|
||||
"typescript": "^5.4.5",
|
||||
"typescript-lit-html-plugin": "^0.9.0",
|
||||
"webpack": "^5.91.0",
|
||||
"webpack-cli": "^5.1.4",
|
||||
@@ -61,19 +61,19 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@leeoniya/ufuzzy": "^1.0.14",
|
||||
"@lit/context": "^1.1.0",
|
||||
"@lit/context": "^1.1.1",
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"@shoelace-style/shoelace": "^2.15.0",
|
||||
"ace-builds": "^1.32.9",
|
||||
"ace-linters": "^1.1.2",
|
||||
"ace-builds": "^1.33.0",
|
||||
"ace-linters": "^1.2.0",
|
||||
"bootstrap": "^5.3.3",
|
||||
"bson": "^6.5.0",
|
||||
"bson": "^6.6.0",
|
||||
"buffer": "^6.0.3",
|
||||
"crypto-browserify": "^3.12.0",
|
||||
"ic10emu_wasm": "file:..\\ic10emu_wasm\\pkg",
|
||||
"ic10lsp_wasm": "file:..\\ic10lsp_wasm\\pkg",
|
||||
"jquery": "^3.7.1",
|
||||
"lit": "^3.1.2",
|
||||
"lit": "^3.1.3",
|
||||
"lzma-web": "^3.0.1",
|
||||
"stream-browserify": "^3.0.0",
|
||||
"uuid": "^9.0.1",
|
||||
|
||||
293
www/pnpm-lock.yaml
generated
@@ -9,26 +9,26 @@ dependencies:
|
||||
specifier: ^1.0.14
|
||||
version: 1.0.14
|
||||
'@lit/context':
|
||||
specifier: ^1.1.0
|
||||
version: 1.1.0
|
||||
specifier: ^1.1.1
|
||||
version: 1.1.1
|
||||
'@popperjs/core':
|
||||
specifier: ^2.11.8
|
||||
version: 2.11.8
|
||||
'@shoelace-style/shoelace':
|
||||
specifier: ^2.15.0
|
||||
version: 2.15.0(@types/react@18.2.74)
|
||||
version: 2.15.0(@types/react@18.2.79)
|
||||
ace-builds:
|
||||
specifier: ^1.32.9
|
||||
version: 1.32.9
|
||||
specifier: ^1.33.0
|
||||
version: 1.33.0
|
||||
ace-linters:
|
||||
specifier: ^1.1.2
|
||||
version: 1.1.2
|
||||
specifier: ^1.2.0
|
||||
version: 1.2.0
|
||||
bootstrap:
|
||||
specifier: ^5.3.3
|
||||
version: 5.3.3(@popperjs/core@2.11.8)
|
||||
bson:
|
||||
specifier: ^6.5.0
|
||||
version: 6.5.0
|
||||
specifier: ^6.6.0
|
||||
version: 6.6.0
|
||||
buffer:
|
||||
specifier: ^6.0.3
|
||||
version: 6.0.3
|
||||
@@ -45,8 +45,8 @@ dependencies:
|
||||
specifier: ^3.7.1
|
||||
version: 3.7.1
|
||||
lit:
|
||||
specifier: ^3.1.2
|
||||
version: 3.1.2
|
||||
specifier: ^3.1.3
|
||||
version: 3.1.3
|
||||
lzma-web:
|
||||
specifier: ^3.0.1
|
||||
version: 3.0.1
|
||||
@@ -80,8 +80,8 @@ devDependencies:
|
||||
specifier: ^12.0.2
|
||||
version: 12.0.2(webpack@5.91.0)
|
||||
css-loader:
|
||||
specifier: ^6.10.0
|
||||
version: 6.10.0(webpack@5.91.0)
|
||||
specifier: ^6.11.0
|
||||
version: 6.11.0(webpack@5.91.0)
|
||||
css-minimizer-webpack-plugin:
|
||||
specifier: ^6.0.0
|
||||
version: 6.0.0(esbuild@0.20.2)(webpack@5.91.0)
|
||||
@@ -96,7 +96,7 @@ devDependencies:
|
||||
version: 5.1.0
|
||||
fork-ts-checker-webpack-plugin:
|
||||
specifier: ^9.0.2
|
||||
version: 9.0.2(typescript@5.4.3)(webpack@5.91.0)
|
||||
version: 9.0.2(typescript@5.4.5)(webpack@5.91.0)
|
||||
hello-wasm-pack:
|
||||
specifier: ^0.1.0
|
||||
version: 0.1.0
|
||||
@@ -125,17 +125,17 @@ devDependencies:
|
||||
specifier: ^2.0.1
|
||||
version: 2.0.1(webpack@5.91.0)
|
||||
mini-css-extract-plugin:
|
||||
specifier: ^2.8.1
|
||||
version: 2.8.1(webpack@5.91.0)
|
||||
specifier: ^2.9.0
|
||||
version: 2.9.0(webpack@5.91.0)
|
||||
postcss-loader:
|
||||
specifier: ^8.1.1
|
||||
version: 8.1.1(postcss@8.4.38)(typescript@5.4.3)(webpack@5.91.0)
|
||||
version: 8.1.1(postcss@8.4.38)(typescript@5.4.5)(webpack@5.91.0)
|
||||
sass:
|
||||
specifier: ^1.72.0
|
||||
version: 1.72.0
|
||||
specifier: ^1.75.0
|
||||
version: 1.75.0
|
||||
sass-loader:
|
||||
specifier: ^14.1.1
|
||||
version: 14.1.1(sass@1.72.0)(webpack@5.91.0)
|
||||
specifier: ^14.2.1
|
||||
version: 14.2.1(sass@1.75.0)(webpack@5.91.0)
|
||||
style-loader:
|
||||
specifier: ^3.3.4
|
||||
version: 3.3.4(webpack@5.91.0)
|
||||
@@ -147,10 +147,10 @@ devDependencies:
|
||||
version: 2.0.2
|
||||
ts-loader:
|
||||
specifier: ^9.5.1
|
||||
version: 9.5.1(typescript@5.4.3)(webpack@5.91.0)
|
||||
version: 9.5.1(typescript@5.4.5)(webpack@5.91.0)
|
||||
typescript:
|
||||
specifier: ^5.4.3
|
||||
version: 5.4.3
|
||||
specifier: ^5.4.5
|
||||
version: 5.4.5
|
||||
typescript-lit-html-plugin:
|
||||
specifier: ^0.9.0
|
||||
version: 0.9.0
|
||||
@@ -196,8 +196,8 @@ packages:
|
||||
regenerator-runtime: 0.14.1
|
||||
dev: true
|
||||
|
||||
/@ctrl/tinycolor@4.0.3:
|
||||
resolution: {integrity: sha512-e9nEVehVJwkymQpkGhdSNzLT2Lr9UTTby+JePq4Z2SxBbOQjY7pLgSouAaXvfaGQVSAaY0U4eJdwfSDmCbItcw==}
|
||||
/@ctrl/tinycolor@4.1.0:
|
||||
resolution: {integrity: sha512-WyOx8cJQ+FQus4Mm4uPIZA64gbk3Wxh0so5Lcii0aJifqwoVOlfFtorjLE0Hen4OYyHZMXDWqMmaQemBhgxFRQ==}
|
||||
engines: {node: '>=14'}
|
||||
dev: false
|
||||
|
||||
@@ -460,7 +460,7 @@ packages:
|
||||
'@jest/schemas': 29.6.3
|
||||
'@types/istanbul-lib-coverage': 2.0.6
|
||||
'@types/istanbul-reports': 3.0.4
|
||||
'@types/node': 20.12.2
|
||||
'@types/node': 20.12.7
|
||||
'@types/yargs': 17.0.32
|
||||
chalk: 4.1.2
|
||||
dev: true
|
||||
@@ -514,18 +514,18 @@ packages:
|
||||
resolution: {integrity: sha512-yWJKmpGE6lUURKAaIltoPIE/wrbY3TEkqQt+X0m+7fQNnAv0keydnYvbiJFP1PnMhizmIWRWOG5KLhYyc/xl+g==}
|
||||
dev: false
|
||||
|
||||
/@lit/context@1.1.0:
|
||||
resolution: {integrity: sha512-fCyv4dsH05wCNm3AKbB+PdYbXGJd/XT8OOwo4hVmD4COq5wOWJlQreGAMDvmHZ7osqxuu06Y4nmP6ooXpN7ErA==}
|
||||
/@lit/context@1.1.1:
|
||||
resolution: {integrity: sha512-q/Rw7oWSJidUP43f/RUPwqZ6f5VlY8HzinTWxL/gW1Hvm2S5q2hZvV+qM8WFcC+oLNNknc3JKsd5TwxLk1hbdg==}
|
||||
dependencies:
|
||||
'@lit/reactive-element': 2.0.4
|
||||
dev: false
|
||||
|
||||
/@lit/react@1.0.4(@types/react@18.2.74):
|
||||
/@lit/react@1.0.4(@types/react@18.2.79):
|
||||
resolution: {integrity: sha512-6HBvk3AwF46z17fTkZp5F7/EdCJW9xqqQgYKr3sQGgoEJv0TKV1voWydG4UQQA2RWkoD4SHjy08snSpzyoyd0w==}
|
||||
peerDependencies:
|
||||
'@types/react': 17 || 18
|
||||
dependencies:
|
||||
'@types/react': 18.2.74
|
||||
'@types/react': 18.2.79
|
||||
dev: false
|
||||
|
||||
/@lit/reactive-element@2.0.4:
|
||||
@@ -579,17 +579,17 @@ packages:
|
||||
resolution: {integrity: sha512-Hf45HeO+vdQblabpyZOTxJ4ZeZsmIUYXXPmoYrrR4OJ5OKxL+bhMz5mK8JXgl7HsoEowfz7+e248UGi861de9Q==}
|
||||
dev: false
|
||||
|
||||
/@shoelace-style/shoelace@2.15.0(@types/react@18.2.74):
|
||||
/@shoelace-style/shoelace@2.15.0(@types/react@18.2.79):
|
||||
resolution: {integrity: sha512-Lcg938Y8U2VsHqIYewzlt+H1rbrXC4GRSUkTJgXyF8/0YAOlI+srd5OSfIw+/LYmwLP2Peyh398Kae/6tg4PDA==}
|
||||
engines: {node: '>=14.17.0'}
|
||||
dependencies:
|
||||
'@ctrl/tinycolor': 4.0.3
|
||||
'@ctrl/tinycolor': 4.1.0
|
||||
'@floating-ui/dom': 1.6.3
|
||||
'@lit/react': 1.0.4(@types/react@18.2.74)
|
||||
'@lit/react': 1.0.4(@types/react@18.2.79)
|
||||
'@shoelace-style/animations': 1.1.0
|
||||
'@shoelace-style/localize': 3.1.2
|
||||
composed-offset-position: 0.0.4
|
||||
lit: 3.1.2
|
||||
lit: 3.1.3
|
||||
qr-creator: 1.0.0
|
||||
transitivePeerDependencies:
|
||||
- '@types/react'
|
||||
@@ -626,13 +626,13 @@ packages:
|
||||
resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==}
|
||||
dependencies:
|
||||
'@types/connect': 3.4.38
|
||||
'@types/node': 20.12.2
|
||||
'@types/node': 20.12.7
|
||||
dev: true
|
||||
|
||||
/@types/bonjour@3.5.13:
|
||||
resolution: {integrity: sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==}
|
||||
dependencies:
|
||||
'@types/node': 20.12.2
|
||||
'@types/node': 20.12.7
|
||||
dev: true
|
||||
|
||||
/@types/bootstrap@5.2.10:
|
||||
@@ -644,14 +644,14 @@ packages:
|
||||
/@types/connect-history-api-fallback@1.5.4:
|
||||
resolution: {integrity: sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==}
|
||||
dependencies:
|
||||
'@types/express-serve-static-core': 4.17.43
|
||||
'@types/node': 20.12.2
|
||||
'@types/express-serve-static-core': 4.19.0
|
||||
'@types/node': 20.12.7
|
||||
dev: true
|
||||
|
||||
/@types/connect@3.4.38:
|
||||
resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==}
|
||||
dependencies:
|
||||
'@types/node': 20.12.2
|
||||
'@types/node': 20.12.7
|
||||
dev: true
|
||||
|
||||
/@types/emscripten@1.39.10:
|
||||
@@ -661,12 +661,12 @@ packages:
|
||||
/@types/eslint-scope@3.7.7:
|
||||
resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==}
|
||||
dependencies:
|
||||
'@types/eslint': 8.56.6
|
||||
'@types/eslint': 8.56.9
|
||||
'@types/estree': 1.0.5
|
||||
dev: true
|
||||
|
||||
/@types/eslint@8.56.6:
|
||||
resolution: {integrity: sha512-ymwc+qb1XkjT/gfoQwxIeHZ6ixH23A+tCT2ADSA/DPVKzAjwYkTXBMCQ/f6fe4wEa85Lhp26VPeUxI7wMhAi7A==}
|
||||
/@types/eslint@8.56.9:
|
||||
resolution: {integrity: sha512-W4W3KcqzjJ0sHg2vAq9vfml6OhsJ53TcUjUqfzzZf/EChUtwspszj/S0pzMxnfRcO55/iGq47dscXw71Fxc4Zg==}
|
||||
dependencies:
|
||||
'@types/estree': 1.0.5
|
||||
'@types/json-schema': 7.0.15
|
||||
@@ -676,11 +676,11 @@ packages:
|
||||
resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
|
||||
dev: true
|
||||
|
||||
/@types/express-serve-static-core@4.17.43:
|
||||
resolution: {integrity: sha512-oaYtiBirUOPQGSWNGPWnzyAFJ0BP3cwvN4oWZQY+zUBwpVIGsKUkpBpSztp74drYcjavs7SKFZ4DX1V2QeN8rg==}
|
||||
/@types/express-serve-static-core@4.19.0:
|
||||
resolution: {integrity: sha512-bGyep3JqPCRry1wq+O5n7oiBgGWmeIJXPjXXCo8EK0u8duZGSYar7cGqd3ML2JUsLGeB7fmc06KYo9fLGWqPvQ==}
|
||||
dependencies:
|
||||
'@types/node': 20.12.2
|
||||
'@types/qs': 6.9.14
|
||||
'@types/node': 20.12.7
|
||||
'@types/qs': 6.9.15
|
||||
'@types/range-parser': 1.2.7
|
||||
'@types/send': 0.17.4
|
||||
dev: true
|
||||
@@ -689,9 +689,9 @@ packages:
|
||||
resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==}
|
||||
dependencies:
|
||||
'@types/body-parser': 1.19.5
|
||||
'@types/express-serve-static-core': 4.17.43
|
||||
'@types/qs': 6.9.14
|
||||
'@types/serve-static': 1.15.5
|
||||
'@types/express-serve-static-core': 4.19.0
|
||||
'@types/qs': 6.9.15
|
||||
'@types/serve-static': 1.15.7
|
||||
dev: true
|
||||
|
||||
/@types/html-minifier-terser@6.1.0:
|
||||
@@ -705,7 +705,7 @@ packages:
|
||||
/@types/http-proxy@1.17.14:
|
||||
resolution: {integrity: sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==}
|
||||
dependencies:
|
||||
'@types/node': 20.12.2
|
||||
'@types/node': 20.12.7
|
||||
dev: true
|
||||
|
||||
/@types/istanbul-lib-coverage@2.0.6:
|
||||
@@ -731,28 +731,21 @@ packages:
|
||||
/@types/keyv@3.1.4:
|
||||
resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==}
|
||||
dependencies:
|
||||
'@types/node': 20.12.2
|
||||
'@types/node': 20.12.7
|
||||
dev: true
|
||||
|
||||
/@types/mime@1.3.5:
|
||||
resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==}
|
||||
dev: true
|
||||
|
||||
/@types/mime@4.0.0:
|
||||
resolution: {integrity: sha512-5eEkJZ/BLvTE3vXGKkWlyTSUVZuzj23Wj8PoyOq2lt5I3CYbiLBOPb3XmCW6QcuOibIUE6emHXHt9E/F/rCa6w==}
|
||||
deprecated: This is a stub types definition. mime provides its own type definitions, so you do not need this installed.
|
||||
dependencies:
|
||||
mime: 4.0.1
|
||||
dev: true
|
||||
|
||||
/@types/node-forge@1.3.11:
|
||||
resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==}
|
||||
dependencies:
|
||||
'@types/node': 20.12.2
|
||||
'@types/node': 20.12.7
|
||||
dev: true
|
||||
|
||||
/@types/node@20.12.2:
|
||||
resolution: {integrity: sha512-zQ0NYO87hyN6Xrclcqp7f8ZbXNbRfoGWNcMvHTPQp9UUrwI0mI7XBz+cu7/W6/VClYo2g63B0cjull/srU7LgQ==}
|
||||
/@types/node@20.12.7:
|
||||
resolution: {integrity: sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==}
|
||||
dependencies:
|
||||
undici-types: 5.26.5
|
||||
dev: true
|
||||
@@ -761,16 +754,16 @@ packages:
|
||||
resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==}
|
||||
dev: false
|
||||
|
||||
/@types/qs@6.9.14:
|
||||
resolution: {integrity: sha512-5khscbd3SwWMhFqylJBLQ0zIu7c1K6Vz0uBIt915BI3zV0q1nfjRQD3RqSBcPaO6PHEF4ov/t9y89fSiyThlPA==}
|
||||
/@types/qs@6.9.15:
|
||||
resolution: {integrity: sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==}
|
||||
dev: true
|
||||
|
||||
/@types/range-parser@1.2.7:
|
||||
resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==}
|
||||
dev: true
|
||||
|
||||
/@types/react@18.2.74:
|
||||
resolution: {integrity: sha512-9AEqNZZyBx8OdZpxzQlaFEVCSFUM2YXJH46yPOiOpm078k6ZLOCcuAzGum/zK8YBwY+dbahVNbHrbgrAwIRlqw==}
|
||||
/@types/react@18.2.79:
|
||||
resolution: {integrity: sha512-RwGAGXPl9kSXwdNTafkOEuFrTBD5SA2B3iEB96xi8+xu5ddUa/cpvyVCSNn+asgLCTHkb5ZxN8gbuibYJi4s1w==}
|
||||
dependencies:
|
||||
'@types/prop-types': 15.7.12
|
||||
csstype: 3.1.3
|
||||
@@ -779,7 +772,7 @@ packages:
|
||||
/@types/responselike@1.0.3:
|
||||
resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==}
|
||||
dependencies:
|
||||
'@types/node': 20.12.2
|
||||
'@types/node': 20.12.7
|
||||
dev: true
|
||||
|
||||
/@types/retry@0.12.2:
|
||||
@@ -790,7 +783,7 @@ packages:
|
||||
resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==}
|
||||
dependencies:
|
||||
'@types/mime': 1.3.5
|
||||
'@types/node': 20.12.2
|
||||
'@types/node': 20.12.7
|
||||
dev: true
|
||||
|
||||
/@types/serve-index@1.9.4:
|
||||
@@ -799,18 +792,18 @@ packages:
|
||||
'@types/express': 4.17.21
|
||||
dev: true
|
||||
|
||||
/@types/serve-static@1.15.5:
|
||||
resolution: {integrity: sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==}
|
||||
/@types/serve-static@1.15.7:
|
||||
resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==}
|
||||
dependencies:
|
||||
'@types/http-errors': 2.0.4
|
||||
'@types/mime': 4.0.0
|
||||
'@types/node': 20.12.2
|
||||
'@types/node': 20.12.7
|
||||
'@types/send': 0.17.4
|
||||
dev: true
|
||||
|
||||
/@types/sockjs@0.3.36:
|
||||
resolution: {integrity: sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==}
|
||||
dependencies:
|
||||
'@types/node': 20.12.2
|
||||
'@types/node': 20.12.7
|
||||
dev: true
|
||||
|
||||
/@types/trusted-types@2.0.7:
|
||||
@@ -824,7 +817,7 @@ packages:
|
||||
/@types/ws@8.5.10:
|
||||
resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==}
|
||||
dependencies:
|
||||
'@types/node': 20.12.2
|
||||
'@types/node': 20.12.7
|
||||
dev: true
|
||||
|
||||
/@types/yargs-parser@21.0.3:
|
||||
@@ -1055,12 +1048,12 @@ packages:
|
||||
negotiator: 0.6.3
|
||||
dev: true
|
||||
|
||||
/ace-builds@1.32.9:
|
||||
resolution: {integrity: sha512-dqBLPj//Gq0b92YUtRIsdWsORf4J+4xW3r8/4Wr2Vqid7O1j7YBV/ZsVvWBjZFy+EnvMCRFCFOEIM1cbt4BQ/g==}
|
||||
/ace-builds@1.33.0:
|
||||
resolution: {integrity: sha512-PDvytkZNvAfuh+PaP5Oy3l3sBGd7xMk4NsB+4w/w1e3gjBqEOGeJwcX+wF/SB6mLtT3VfJLrhDNPT3eaCjtR3w==}
|
||||
dev: false
|
||||
|
||||
/ace-linters@1.1.2:
|
||||
resolution: {integrity: sha512-P7jXG8Q/TdXekVaFoso+ci+PcbuWu6+jpU6F5Djdpu3znIgsv88ZMr4TK1YHk+npmJiY8cY4cnYUfJn/XQqMdA==}
|
||||
/ace-linters@1.2.0:
|
||||
resolution: {integrity: sha512-xvayDhn3iCmB1oEloK7ZNRZHvRwDIGu+EWtlpXNL8wAwSdQjo05bTbnXEpSCy/sBlJg5tyEwsTYesNrx05DiAg==}
|
||||
dependencies:
|
||||
'@xml-tools/ast': 5.0.5
|
||||
'@xml-tools/constraints': 1.1.1
|
||||
@@ -1242,7 +1235,7 @@ packages:
|
||||
postcss: ^8.1.0
|
||||
dependencies:
|
||||
browserslist: 4.23.0
|
||||
caniuse-lite: 1.0.30001603
|
||||
caniuse-lite: 1.0.30001610
|
||||
fraction.js: 4.3.7
|
||||
normalize-range: 0.1.2
|
||||
picocolors: 1.0.0
|
||||
@@ -1964,8 +1957,8 @@ packages:
|
||||
resolution: {integrity: sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
caniuse-lite: 1.0.30001603
|
||||
electron-to-chromium: 1.4.722
|
||||
caniuse-lite: 1.0.30001610
|
||||
electron-to-chromium: 1.4.739
|
||||
dev: true
|
||||
|
||||
/browserslist@4.23.0:
|
||||
@@ -1973,14 +1966,14 @@ packages:
|
||||
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
caniuse-lite: 1.0.30001603
|
||||
electron-to-chromium: 1.4.722
|
||||
caniuse-lite: 1.0.30001610
|
||||
electron-to-chromium: 1.4.739
|
||||
node-releases: 2.0.14
|
||||
update-browserslist-db: 1.0.13(browserslist@4.23.0)
|
||||
dev: true
|
||||
|
||||
/bson@6.5.0:
|
||||
resolution: {integrity: sha512-DXf1BTAS8vKyR90BO4x5v3rKVarmkdkzwOrnYDFdjAY694ILNDkmA3uRh1xXJEl+C1DAh8XCvAQ+Gh3kzubtpg==}
|
||||
/bson@6.6.0:
|
||||
resolution: {integrity: sha512-BVINv2SgcMjL4oYbBuCQTpE3/VKOSxrOA8Cj/wQP7izSzlBGVomdm+TcUd0Pzy0ytLSSDweCKQ6X3f5veM5LQA==}
|
||||
engines: {node: '>=16.20.1'}
|
||||
dev: false
|
||||
|
||||
@@ -2100,13 +2093,13 @@ packages:
|
||||
resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==}
|
||||
dependencies:
|
||||
browserslist: 4.23.0
|
||||
caniuse-lite: 1.0.30001603
|
||||
caniuse-lite: 1.0.30001610
|
||||
lodash.memoize: 4.1.2
|
||||
lodash.uniq: 4.5.0
|
||||
dev: true
|
||||
|
||||
/caniuse-lite@1.0.30001603:
|
||||
resolution: {integrity: sha512-iL2iSS0eDILMb9n5yKQoTBim9jMZ0Yrk8g0N9K7UzYyWnfIKzXBZD5ngpM37ZcL/cv0Mli8XtVMRYMQAfFpi5Q==}
|
||||
/caniuse-lite@1.0.30001610:
|
||||
resolution: {integrity: sha512-QFutAY4NgaelojVMjY63o6XlZyORPaLfyMnsl3HgnWdJUcX6K0oaJymHjH8PT5Gk7sTm8rvC/c5COUQKXqmOMA==}
|
||||
dev: true
|
||||
|
||||
/caw@2.0.1:
|
||||
@@ -2368,7 +2361,7 @@ packages:
|
||||
/core-util-is@1.0.3:
|
||||
resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
|
||||
|
||||
/cosmiconfig@8.3.6(typescript@5.4.3):
|
||||
/cosmiconfig@8.3.6(typescript@5.4.5):
|
||||
resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==}
|
||||
engines: {node: '>=14'}
|
||||
peerDependencies:
|
||||
@@ -2381,10 +2374,10 @@ packages:
|
||||
js-yaml: 4.1.0
|
||||
parse-json: 5.2.0
|
||||
path-type: 4.0.0
|
||||
typescript: 5.4.3
|
||||
typescript: 5.4.5
|
||||
dev: true
|
||||
|
||||
/cosmiconfig@9.0.0(typescript@5.4.3):
|
||||
/cosmiconfig@9.0.0(typescript@5.4.5):
|
||||
resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==}
|
||||
engines: {node: '>=14'}
|
||||
peerDependencies:
|
||||
@@ -2397,7 +2390,7 @@ packages:
|
||||
import-fresh: 3.3.0
|
||||
js-yaml: 4.1.0
|
||||
parse-json: 5.2.0
|
||||
typescript: 5.4.3
|
||||
typescript: 5.4.5
|
||||
dev: true
|
||||
|
||||
/create-ecdh@4.0.4:
|
||||
@@ -2481,8 +2474,8 @@ packages:
|
||||
postcss: 8.4.38
|
||||
dev: true
|
||||
|
||||
/css-loader@6.10.0(webpack@5.91.0):
|
||||
resolution: {integrity: sha512-LTSA/jWbwdMlk+rhmElbDR2vbtQoTBPr7fkJE+mxrHj+7ru0hUmHafDRzWIjIHTwpitWVaqY2/UWGRca3yUgRw==}
|
||||
/css-loader@6.11.0(webpack@5.91.0):
|
||||
resolution: {integrity: sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==}
|
||||
engines: {node: '>= 12.13.0'}
|
||||
peerDependencies:
|
||||
'@rspack/core': 0.x || 1.x
|
||||
@@ -2495,9 +2488,9 @@ packages:
|
||||
dependencies:
|
||||
icss-utils: 5.1.0(postcss@8.4.38)
|
||||
postcss: 8.4.38
|
||||
postcss-modules-extract-imports: 3.0.0(postcss@8.4.38)
|
||||
postcss-modules-local-by-default: 4.0.4(postcss@8.4.38)
|
||||
postcss-modules-scope: 3.1.1(postcss@8.4.38)
|
||||
postcss-modules-extract-imports: 3.1.0(postcss@8.4.38)
|
||||
postcss-modules-local-by-default: 4.0.5(postcss@8.4.38)
|
||||
postcss-modules-scope: 3.2.0(postcss@8.4.38)
|
||||
postcss-modules-values: 4.0.0(postcss@8.4.38)
|
||||
postcss-value-parser: 4.2.0
|
||||
semver: 7.6.0
|
||||
@@ -2984,8 +2977,8 @@ packages:
|
||||
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
|
||||
dev: true
|
||||
|
||||
/electron-to-chromium@1.4.722:
|
||||
resolution: {integrity: sha512-5nLE0TWFFpZ80Crhtp4pIp8LXCztjYX41yUcV6b+bKR2PqzjskTMOOlBi1VjBHlvHwS+4gar7kNKOrsbsewEZQ==}
|
||||
/electron-to-chromium@1.4.739:
|
||||
resolution: {integrity: sha512-koRkawXOuN9w/ymhTNxGfB8ta4MRKVW0nzifU17G1UwTWlBg0vv7xnz4nxDnRFSBe9nXMGRgICcAzqXc0PmLeA==}
|
||||
dev: true
|
||||
|
||||
/elliptic@6.5.5:
|
||||
@@ -3046,8 +3039,8 @@ packages:
|
||||
engines: {node: '>=6'}
|
||||
dev: true
|
||||
|
||||
/envinfo@7.11.1:
|
||||
resolution: {integrity: sha512-8PiZgZNIB4q/Lw4AhOvAfB/ityHAd2bli3lESSWmWSzSsl5dKpy5N1d1Rfkd2teq/g9xN90lc6o98DOjMeYHpg==}
|
||||
/envinfo@7.12.0:
|
||||
resolution: {integrity: sha512-Iw9rQJBGpJRd3rwXm9ft/JiGoAZmLxxJZELYDQoPRZ4USVhkKtIcNBPw6U+/K2mBpaqM25JSV6Yl4Az9vO2wJg==}
|
||||
engines: {node: '>=4'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
@@ -3490,7 +3483,7 @@ packages:
|
||||
signal-exit: 4.1.0
|
||||
dev: true
|
||||
|
||||
/fork-ts-checker-webpack-plugin@9.0.2(typescript@5.4.3)(webpack@5.91.0):
|
||||
/fork-ts-checker-webpack-plugin@9.0.2(typescript@5.4.5)(webpack@5.91.0):
|
||||
resolution: {integrity: sha512-Uochze2R8peoN1XqlSi/rGUkDQpRogtLFocP9+PGu68zk1BDAKXfdeCdyVZpgTk8V8WFVQXdEz426VKjXLO1Gg==}
|
||||
engines: {node: '>=12.13.0', yarn: '>=1.0.0'}
|
||||
peerDependencies:
|
||||
@@ -3500,7 +3493,7 @@ packages:
|
||||
'@babel/code-frame': 7.24.2
|
||||
chalk: 4.1.2
|
||||
chokidar: 3.6.0
|
||||
cosmiconfig: 8.3.6(typescript@5.4.3)
|
||||
cosmiconfig: 8.3.6(typescript@5.4.5)
|
||||
deepmerge: 4.3.1
|
||||
fs-extra: 10.1.0
|
||||
memfs: 3.5.3
|
||||
@@ -3509,7 +3502,7 @@ packages:
|
||||
schema-utils: 3.3.0
|
||||
semver: 7.6.0
|
||||
tapable: 2.2.1
|
||||
typescript: 5.4.3
|
||||
typescript: 5.4.5
|
||||
webpack: 5.91.0(esbuild@0.20.2)(webpack-cli@5.1.4)
|
||||
dev: true
|
||||
|
||||
@@ -3893,7 +3886,7 @@ packages:
|
||||
he: 1.2.0
|
||||
param-case: 3.0.4
|
||||
relateurl: 0.2.7
|
||||
terser: 5.30.0
|
||||
terser: 5.30.3
|
||||
dev: true
|
||||
|
||||
/html-webpack-plugin@5.6.0(webpack@5.91.0):
|
||||
@@ -4357,7 +4350,7 @@ packages:
|
||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
||||
dependencies:
|
||||
'@jest/types': 29.6.3
|
||||
'@types/node': 20.12.2
|
||||
'@types/node': 20.12.7
|
||||
chalk: 4.1.2
|
||||
ci-info: 3.9.0
|
||||
graceful-fs: 4.2.11
|
||||
@@ -4368,7 +4361,7 @@ packages:
|
||||
resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==}
|
||||
engines: {node: '>= 10.13.0'}
|
||||
dependencies:
|
||||
'@types/node': 20.12.2
|
||||
'@types/node': 20.12.7
|
||||
merge-stream: 2.0.0
|
||||
supports-color: 8.1.1
|
||||
dev: true
|
||||
@@ -4377,7 +4370,7 @@ packages:
|
||||
resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==}
|
||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
||||
dependencies:
|
||||
'@types/node': 20.12.2
|
||||
'@types/node': 20.12.7
|
||||
jest-util: 29.7.0
|
||||
merge-stream: 2.0.0
|
||||
supports-color: 8.1.1
|
||||
@@ -4534,16 +4527,16 @@ packages:
|
||||
web-component-analyzer: 2.0.0
|
||||
dev: true
|
||||
|
||||
/lit-element@4.0.4:
|
||||
resolution: {integrity: sha512-98CvgulX6eCPs6TyAIQoJZBCQPo80rgXR+dVBs61cstJXqtI+USQZAbA4gFHh6L/mxBx9MrgPLHLsUgDUHAcCQ==}
|
||||
/lit-element@4.0.5:
|
||||
resolution: {integrity: sha512-iTWskWZEtn9SyEf4aBG6rKT8GABZMrTWop1+jopsEOgEcugcXJGKuX5bEbkq9qfzY+XB4MAgCaSPwnNpdsNQ3Q==}
|
||||
dependencies:
|
||||
'@lit-labs/ssr-dom-shim': 1.2.0
|
||||
'@lit/reactive-element': 2.0.4
|
||||
lit-html: 3.1.2
|
||||
lit-html: 3.1.3
|
||||
dev: false
|
||||
|
||||
/lit-html@3.1.2:
|
||||
resolution: {integrity: sha512-3OBZSUrPnAHoKJ9AMjRL/m01YJxQMf+TMHanNtTHG68ubjnZxK0RFl102DPzsw4mWnHibfZIBJm3LWCZ/LmMvg==}
|
||||
/lit-html@3.1.3:
|
||||
resolution: {integrity: sha512-FwIbqDD8O/8lM4vUZ4KvQZjPPNx7V1VhT7vmRB8RBAO0AU6wuTVdoXiu2CivVjEGdugvcbPNBLtPE1y0ifplHA==}
|
||||
dependencies:
|
||||
'@types/trusted-types': 2.0.7
|
||||
dev: false
|
||||
@@ -4557,12 +4550,12 @@ packages:
|
||||
webpack: 5.91.0(esbuild@0.20.2)(webpack-cli@5.1.4)
|
||||
dev: true
|
||||
|
||||
/lit@3.1.2:
|
||||
resolution: {integrity: sha512-VZx5iAyMtX7CV4K8iTLdCkMaYZ7ipjJZ0JcSdJ0zIdGxxyurjIn7yuuSxNBD7QmjvcNJwr0JS4cAdAtsy7gZ6w==}
|
||||
/lit@3.1.3:
|
||||
resolution: {integrity: sha512-l4slfspEsnCcHVRTvaP7YnkTZEZggNFywLEIhQaGhYDczG+tu/vlgm/KaWIEjIp+ZyV20r2JnZctMb8LeLCG7Q==}
|
||||
dependencies:
|
||||
'@lit/reactive-element': 2.0.4
|
||||
lit-element: 4.0.4
|
||||
lit-html: 3.1.2
|
||||
lit-element: 4.0.5
|
||||
lit-html: 3.1.3
|
||||
dev: false
|
||||
|
||||
/load-json-file@1.1.0:
|
||||
@@ -4748,8 +4741,8 @@ packages:
|
||||
fs-monkey: 1.0.5
|
||||
dev: true
|
||||
|
||||
/memfs@4.8.1:
|
||||
resolution: {integrity: sha512-7q/AdPzf2WpwPlPL4v1kE2KsJsHl7EF4+hAeVzlyanr2+YnR21NVn9mDqo+7DEaKDRsQy8nvxPlKH4WqMtiO0w==}
|
||||
/memfs@4.8.2:
|
||||
resolution: {integrity: sha512-j4WKth315edViMBGkHW6NTF0QBjsTrcRDmYNcGsPq+ozMEyCCCIlX2d2mJ5wuh6iHvJ3FevUrr48v58YRqVdYg==}
|
||||
engines: {node: '>= 4.0.0'}
|
||||
dependencies:
|
||||
tslib: 2.6.2
|
||||
@@ -4823,12 +4816,6 @@ packages:
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/mime@4.0.1:
|
||||
resolution: {integrity: sha512-5lZ5tyrIfliMXzFtkYyekWbtRXObT9OWa8IwQ5uxTBDHucNNwniRqo0yInflj+iYi5CBa6qxadGzGarDfuEOxA==}
|
||||
engines: {node: '>=16'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/mimic-fn@2.1.0:
|
||||
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
|
||||
engines: {node: '>=6'}
|
||||
@@ -4839,8 +4826,8 @@ packages:
|
||||
engines: {node: '>=4'}
|
||||
dev: true
|
||||
|
||||
/mini-css-extract-plugin@2.8.1(webpack@5.91.0):
|
||||
resolution: {integrity: sha512-/1HDlyFRxWIZPI1ZpgqlZ8jMw/1Dp/dl3P0L1jtZ+zVcHqwPhGwaJwKL00WVgfnBy6PWCde9W65or7IIETImuA==}
|
||||
/mini-css-extract-plugin@2.9.0(webpack@5.91.0):
|
||||
resolution: {integrity: sha512-Zs1YsZVfemekSZG+44vBsYTLQORkPMwnlv+aehcxK/NLKC+EGhDB39/YePYYqx/sTk6NnYpuqikhSn7+JIevTA==}
|
||||
engines: {node: '>= 12.13.0'}
|
||||
peerDependencies:
|
||||
webpack: ^5.0.0
|
||||
@@ -5434,7 +5421,7 @@ packages:
|
||||
postcss: 8.4.38
|
||||
dev: true
|
||||
|
||||
/postcss-loader@8.1.1(postcss@8.4.38)(typescript@5.4.3)(webpack@5.91.0):
|
||||
/postcss-loader@8.1.1(postcss@8.4.38)(typescript@5.4.5)(webpack@5.91.0):
|
||||
resolution: {integrity: sha512-0IeqyAsG6tYiDRCYKQJLAmgQr47DX6N7sFSWvQxt6AcupX8DIdmykuk/o/tx0Lze3ErGHJEp5OSRxrelC6+NdQ==}
|
||||
engines: {node: '>= 18.12.0'}
|
||||
peerDependencies:
|
||||
@@ -5447,7 +5434,7 @@ packages:
|
||||
webpack:
|
||||
optional: true
|
||||
dependencies:
|
||||
cosmiconfig: 9.0.0(typescript@5.4.3)
|
||||
cosmiconfig: 9.0.0(typescript@5.4.5)
|
||||
jiti: 1.21.0
|
||||
postcss: 8.4.38
|
||||
semver: 7.6.0
|
||||
@@ -5524,8 +5511,8 @@ packages:
|
||||
postcss-selector-parser: 6.0.16
|
||||
dev: true
|
||||
|
||||
/postcss-modules-extract-imports@3.0.0(postcss@8.4.38):
|
||||
resolution: {integrity: sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==}
|
||||
/postcss-modules-extract-imports@3.1.0(postcss@8.4.38):
|
||||
resolution: {integrity: sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==}
|
||||
engines: {node: ^10 || ^12 || >= 14}
|
||||
peerDependencies:
|
||||
postcss: ^8.1.0
|
||||
@@ -5533,8 +5520,8 @@ packages:
|
||||
postcss: 8.4.38
|
||||
dev: true
|
||||
|
||||
/postcss-modules-local-by-default@4.0.4(postcss@8.4.38):
|
||||
resolution: {integrity: sha512-L4QzMnOdVwRm1Qb8m4x8jsZzKAaPAgrUF1r/hjDR2Xj7R+8Zsf97jAlSQzWtKx5YNiNGN8QxmPFIc/sh+RQl+Q==}
|
||||
/postcss-modules-local-by-default@4.0.5(postcss@8.4.38):
|
||||
resolution: {integrity: sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==}
|
||||
engines: {node: ^10 || ^12 || >= 14}
|
||||
peerDependencies:
|
||||
postcss: ^8.1.0
|
||||
@@ -5545,8 +5532,8 @@ packages:
|
||||
postcss-value-parser: 4.2.0
|
||||
dev: true
|
||||
|
||||
/postcss-modules-scope@3.1.1(postcss@8.4.38):
|
||||
resolution: {integrity: sha512-uZgqzdTleelWjzJY+Fhti6F3C9iF1JR/dODLs/JDefozYcKTBCdD8BIl6nNPbTbcLnGrk56hzwZC2DaGNvYjzA==}
|
||||
/postcss-modules-scope@3.2.0(postcss@8.4.38):
|
||||
resolution: {integrity: sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==}
|
||||
engines: {node: ^10 || ^12 || >= 14}
|
||||
peerDependencies:
|
||||
postcss: ^8.1.0
|
||||
@@ -6083,8 +6070,8 @@ packages:
|
||||
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
|
||||
dev: true
|
||||
|
||||
/sass-loader@14.1.1(sass@1.72.0)(webpack@5.91.0):
|
||||
resolution: {integrity: sha512-QX8AasDg75monlybel38BZ49JP5Z+uSKfKwF2rO7S74BywaRmGQMUBw9dtkS+ekyM/QnP+NOrRYq8ABMZ9G8jw==}
|
||||
/sass-loader@14.2.1(sass@1.75.0)(webpack@5.91.0):
|
||||
resolution: {integrity: sha512-G0VcnMYU18a4N7VoNDegg2OuMjYtxnqzQWARVWCIVSZwJeiL9kg8QMsuIZOplsJgTzZLF6jGxI3AClj8I9nRdQ==}
|
||||
engines: {node: '>= 18.12.0'}
|
||||
peerDependencies:
|
||||
'@rspack/core': 0.x || 1.x
|
||||
@@ -6105,12 +6092,12 @@ packages:
|
||||
optional: true
|
||||
dependencies:
|
||||
neo-async: 2.6.2
|
||||
sass: 1.72.0
|
||||
sass: 1.75.0
|
||||
webpack: 5.91.0(esbuild@0.20.2)(webpack-cli@5.1.4)
|
||||
dev: true
|
||||
|
||||
/sass@1.72.0:
|
||||
resolution: {integrity: sha512-Gpczt3WA56Ly0Mn8Sl21Vj94s1axi9hDIzDFn9Ph9x3C3p4nNyvsqJoQyVXKou6cBlfFWEgRW4rT8Tb4i3XnVA==}
|
||||
/sass@1.75.0:
|
||||
resolution: {integrity: sha512-ShMYi3WkrDWxExyxSZPst4/okE9ts46xZmJDSawJQrnte7M1V9fScVB+uNXOVKRBt0PggHOwoZcn8mYX4trnBw==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
@@ -6729,12 +6716,12 @@ packages:
|
||||
jest-worker: 27.5.1
|
||||
schema-utils: 3.3.0
|
||||
serialize-javascript: 6.0.2
|
||||
terser: 5.30.0
|
||||
terser: 5.30.3
|
||||
webpack: 5.91.0(esbuild@0.20.2)(webpack-cli@5.1.4)
|
||||
dev: true
|
||||
|
||||
/terser@5.30.0:
|
||||
resolution: {integrity: sha512-Y/SblUl5kEyEFzhMAQdsxVHh+utAxd4IuRNJzKywY/4uzSogh3G219jqbDDxYu4MXO9CzY3tSEqmZvW6AoEDJw==}
|
||||
/terser@5.30.3:
|
||||
resolution: {integrity: sha512-STdUgOUx8rLbMGO9IOwHLpCqolkDITFFQSMYYwKE1N2lY6MVSaeoi10z/EhWxRc6ybqoVmKSkhKYH/XUpl7vSA==}
|
||||
engines: {node: '>=10'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
@@ -6828,7 +6815,7 @@ packages:
|
||||
web-component-analyzer: 2.0.0
|
||||
dev: true
|
||||
|
||||
/ts-loader@9.5.1(typescript@5.4.3)(webpack@5.91.0):
|
||||
/ts-loader@9.5.1(typescript@5.4.5)(webpack@5.91.0):
|
||||
resolution: {integrity: sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
peerDependencies:
|
||||
@@ -6840,7 +6827,7 @@ packages:
|
||||
micromatch: 4.0.5
|
||||
semver: 7.6.0
|
||||
source-map: 0.7.4
|
||||
typescript: 5.4.3
|
||||
typescript: 5.4.5
|
||||
webpack: 5.91.0(esbuild@0.20.2)(webpack-cli@5.1.4)
|
||||
dev: true
|
||||
|
||||
@@ -6895,8 +6882,8 @@ packages:
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/typescript@5.4.3:
|
||||
resolution: {integrity: sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==}
|
||||
/typescript@5.4.5:
|
||||
resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==}
|
||||
engines: {node: '>=14.17'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
@@ -7179,7 +7166,7 @@ packages:
|
||||
colorette: 2.0.20
|
||||
commander: 10.0.1
|
||||
cross-spawn: 7.0.3
|
||||
envinfo: 7.11.1
|
||||
envinfo: 7.12.0
|
||||
fastest-levenshtein: 1.0.16
|
||||
import-local: 3.1.0
|
||||
interpret: 3.1.1
|
||||
@@ -7189,8 +7176,8 @@ packages:
|
||||
webpack-merge: 5.10.0
|
||||
dev: true
|
||||
|
||||
/webpack-dev-middleware@7.2.0(webpack@5.91.0):
|
||||
resolution: {integrity: sha512-VLzmsjJrf+3UVf3QsT3E7xZ9F9bdhUhQFGRxyl6bmYR+W519UWnK6/teZeqAFFjWEtpVs+JqNPCVqB/s7P4tGg==}
|
||||
/webpack-dev-middleware@7.2.1(webpack@5.91.0):
|
||||
resolution: {integrity: sha512-hRLz+jPQXo999Nx9fXVdKlg/aehsw1ajA9skAneGmT03xwmyuhvF93p6HUKKbWhXdcERtGTzUCtIQr+2IQegrA==}
|
||||
engines: {node: '>= 18.12.0'}
|
||||
peerDependencies:
|
||||
webpack: ^5.0.0
|
||||
@@ -7199,7 +7186,7 @@ packages:
|
||||
optional: true
|
||||
dependencies:
|
||||
colorette: 2.0.20
|
||||
memfs: 4.8.1
|
||||
memfs: 4.8.2
|
||||
mime-types: 2.1.35
|
||||
on-finished: 2.4.1
|
||||
range-parser: 1.2.1
|
||||
@@ -7224,7 +7211,7 @@ packages:
|
||||
'@types/connect-history-api-fallback': 1.5.4
|
||||
'@types/express': 4.17.21
|
||||
'@types/serve-index': 1.9.4
|
||||
'@types/serve-static': 1.15.5
|
||||
'@types/serve-static': 1.15.7
|
||||
'@types/sockjs': 0.3.36
|
||||
'@types/ws': 8.5.10
|
||||
ansi-html-community: 0.0.8
|
||||
@@ -7250,7 +7237,7 @@ packages:
|
||||
spdy: 4.0.2
|
||||
webpack: 5.91.0(esbuild@0.20.2)(webpack-cli@5.1.4)
|
||||
webpack-cli: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.91.0)
|
||||
webpack-dev-middleware: 7.2.0(webpack@5.91.0)
|
||||
webpack-dev-middleware: 7.2.1(webpack@5.91.0)
|
||||
ws: 8.16.0
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html data-bs-theme="dark">
|
||||
<html data-bs-theme="dark" class="sl-theme-dark">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
@@ -65,6 +65,9 @@ $accordion-button-padding-y: 0.5rem;
|
||||
// Utilities
|
||||
@import "bootstrap/scss/utilities/api";
|
||||
|
||||
// Sholace theme
|
||||
@import "@shoelace-style/shoelace/dist/themes/dark.css";
|
||||
|
||||
|
||||
//
|
||||
// Custom styles
|
||||
|
||||
@@ -28,6 +28,9 @@ export const defaultCss = [
|
||||
.mt-auto {
|
||||
margin-top: auto !important;
|
||||
}
|
||||
.me-2 {
|
||||
margin-right: 2rem !important;
|
||||
}
|
||||
.hstack {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@@ -36,6 +39,9 @@ export const defaultCss = [
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.flex-g {
|
||||
flex-grow: 1;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
import { html, css, HTMLTemplateResult, PropertyValueMap } from "lit";
|
||||
import {
|
||||
html,
|
||||
css,
|
||||
HTMLTemplateResult,
|
||||
PropertyValueMap,
|
||||
CSSResultGroup,
|
||||
} from "lit";
|
||||
import { customElement, query, state } from "lit/decorators.js";
|
||||
import { classMap } from "lit/directives/class-map.js";
|
||||
import SlDetails from "@shoelace-style/shoelace/dist/components/details/details.js";
|
||||
@@ -7,6 +13,21 @@ import SlDetails from "@shoelace-style/shoelace/dist/components/details/details.
|
||||
export class IC10Details extends SlDetails {
|
||||
@query(".details__summary-icon") accessor summaryIcon: HTMLSpanElement;
|
||||
|
||||
static styles = [
|
||||
SlDetails.styles,
|
||||
css`
|
||||
.details__header {
|
||||
cursor: auto;
|
||||
}
|
||||
.details__summary-icon {
|
||||
cursor: pointer;
|
||||
}
|
||||
.details__content {
|
||||
padding-top: 0;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
@@ -48,34 +69,16 @@ export class IC10Details extends SlDetails {
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<details
|
||||
part="base"
|
||||
class=${classMap({
|
||||
details: true,
|
||||
"details--open": this.open,
|
||||
"details--disabled": this.disabled,
|
||||
})}
|
||||
>
|
||||
<summary
|
||||
part="header"
|
||||
id="header"
|
||||
class="details__header"
|
||||
role="button"
|
||||
aria-expanded=${this.open ? "true" : "false"}
|
||||
aria-controls="content"
|
||||
aria-disabled=${this.disabled ? "true" : "false"}
|
||||
tabindex=${this.disabled ? "-1" : "0"}
|
||||
>
|
||||
<slot name="summary" part="summary" class="details__summary"
|
||||
>${this.summary}</slot
|
||||
<details part="base" class=${classMap({ details: true, "details--open" : this.open, "details--disabled" : this.disabled,
|
||||
})}>
|
||||
<summary part="header" id="header" class="details__header" role="button" aria-expanded=${this.open ? "true" : "false"
|
||||
} aria-controls="content" aria-disabled=${this.disabled ? "true" : "false" } tabindex=${this.disabled ? "-1" : "0" }
|
||||
@click=${(e: Event)=> e.preventDefault()}
|
||||
>
|
||||
<slot name="summary" part="summary" class="details__summary">${this.summary}</slot>
|
||||
|
||||
<span
|
||||
part="summary-icon"
|
||||
class="details__summary-icon"
|
||||
@click=${this.handleSummaryIconClick}
|
||||
@keydown=${this.handleSummaryIconKeyDown}
|
||||
>
|
||||
<span part="summary-icon" class="details__summary-icon" @click=${this.handleSummaryIconClick}
|
||||
@keydown=${this.handleSummaryIconKeyDown}>
|
||||
<slot name="expand-icon">
|
||||
<sl-icon library="system" name="chevron-right"></sl-icon>
|
||||
</slot>
|
||||
|
||||
@@ -28,11 +28,11 @@ declare global {
|
||||
|
||||
import { BaseElement, defaultCss } from "../components";
|
||||
import { html } from "lit";
|
||||
import { Ref, createRef, ref } from "lit/directives/ref.js";
|
||||
import { customElement, property, query } from "lit/decorators.js";
|
||||
import { customElement, state, query } from "lit/decorators.js";
|
||||
import { editorStyles } from "./styles";
|
||||
import "./shortcuts_ui";
|
||||
import { AceKeyboardShortcuts } from "./shortcuts_ui";
|
||||
import { LanguageClientConfig, ProviderOptions } from "ace-linters/types/types/language-service";
|
||||
|
||||
@customElement("ace-ic10")
|
||||
export class IC10Editor extends BaseElement {
|
||||
@@ -45,8 +45,7 @@ export class IC10Editor extends BaseElement {
|
||||
};
|
||||
sessions: Map<number, Ace.EditSession>;
|
||||
|
||||
@property({ type: Number })
|
||||
accessor active_session: number = 0;
|
||||
@state() active_session: number = 1;
|
||||
|
||||
active_line_markers: Map<number, number | null> = new Map();
|
||||
languageProvider?: LanguageProvider;
|
||||
@@ -291,7 +290,7 @@ export class IC10Editor extends BaseElement {
|
||||
|
||||
window.App!.session.onActiveLine(((e: CustomEvent) => {
|
||||
const session = window.App?.session!;
|
||||
const id = e.detail;
|
||||
const id: number = e.detail;
|
||||
const active_line = session.getActiveLine(id);
|
||||
if (typeof active_line !== "undefined") {
|
||||
const marker = that.active_line_markers.get(id);
|
||||
@@ -485,14 +484,14 @@ export class IC10Editor extends BaseElement {
|
||||
}
|
||||
|
||||
createOrSetSession(session_id: number, content: any) {
|
||||
if (!this.sessions.hasOwnProperty(session_id)) {
|
||||
if (!this.sessions.has(session_id)) {
|
||||
this.newSession(session_id);
|
||||
}
|
||||
this.sessions.get(session_id)?.setValue(content);
|
||||
}
|
||||
|
||||
newSession(session_id: number) {
|
||||
if (this.sessions.hasOwnProperty(session_id)) {
|
||||
if (this.sessions.has(session_id)) {
|
||||
return false;
|
||||
}
|
||||
const session = ace.createEditSession("", this.mode as any);
|
||||
@@ -504,14 +503,19 @@ export class IC10Editor extends BaseElement {
|
||||
}
|
||||
|
||||
setupLsp(lsp_worker: Worker) {
|
||||
const serverData = {
|
||||
const serverData: LanguageClientConfig = {
|
||||
module: () => import("ace-linters/build/language-client"),
|
||||
modes: "ic10",
|
||||
type: "webworker",
|
||||
worker: lsp_worker,
|
||||
};
|
||||
const options: ProviderOptions = {
|
||||
functionality: {
|
||||
semanticTokens: true
|
||||
}
|
||||
}
|
||||
// Create a language provider for web worker
|
||||
this.languageProvider = AceLanguageClient.for(serverData as any);
|
||||
this.languageProvider = AceLanguageClient.for(serverData, options);
|
||||
this.languageProvider.registerEditor(this.editor);
|
||||
}
|
||||
|
||||
@@ -564,7 +568,7 @@ export class IC10Editor extends BaseElement {
|
||||
}
|
||||
|
||||
destroySession(session_id: number) {
|
||||
if (!this.sessions.hasOwnProperty(session_id)) {
|
||||
if (!this.sessions.has(session_id)) {
|
||||
return false;
|
||||
}
|
||||
if (!(Object.keys(this.sessions).length > 1)) {
|
||||
|
||||
@@ -74,7 +74,7 @@ export class Session extends EventTarget {
|
||||
this._programs = new Map();
|
||||
this._errors = new Map();
|
||||
this._save_timeout = undefined;
|
||||
this._activeIC = 0;
|
||||
this._activeIC = 1;
|
||||
this._activeLines = new Map();
|
||||
this.loadFromFragment();
|
||||
|
||||
@@ -117,8 +117,11 @@ export class Session extends EventTarget {
|
||||
}
|
||||
|
||||
setActiveLine(id: number, line: number) {
|
||||
this._activeLines.set(id, line);
|
||||
this._fireOnActiveLine(id);
|
||||
const last = this._activeLines.get(id);
|
||||
if (last !== line) {
|
||||
this._activeLines.set(id, line);
|
||||
this._fireOnActiveLine(id);
|
||||
}
|
||||
}
|
||||
|
||||
set activeLine(line: number) {
|
||||
@@ -198,7 +201,7 @@ export class Session extends EventTarget {
|
||||
async loadFromFragment() {
|
||||
const fragment = window.location.hash.slice(1);
|
||||
if (fragment === "demo") {
|
||||
this._programs = new Map([[0, demoCode]]);
|
||||
this._programs = new Map([[1, demoCode]]);
|
||||
this._fireOnLoad();
|
||||
return;
|
||||
}
|
||||
@@ -210,7 +213,7 @@ export class Session extends EventTarget {
|
||||
const data = getJson(txt);
|
||||
if (data === null) {
|
||||
// backwards compatible
|
||||
this._programs = new Map([[0, txt]]);
|
||||
this._programs = new Map([[1, txt]]);
|
||||
this, this._fireOnLoad();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -175,5 +175,42 @@ export function parseNumber(s: string): number {
|
||||
case 'epsilon':
|
||||
return Number.EPSILON;
|
||||
}
|
||||
if (/^%[01]+$/.test(s)) {
|
||||
return parseInt(s.slice(1), 2)
|
||||
}
|
||||
if (/^\$[0-9A-Fa-f]+$/.test(s)) {
|
||||
return parseInt(s.slice(1), 16)
|
||||
}
|
||||
if (/[a-fA-F]/.test(s)) {
|
||||
const hex = parseHex(s);
|
||||
if (!isNaN(hex)) {
|
||||
return hex;
|
||||
}
|
||||
}
|
||||
return parseFloat(s);
|
||||
}
|
||||
|
||||
export function parseHex(h: string) : number {
|
||||
var val = parseInt(h, 16);
|
||||
if (val.toString(16) === h.toLowerCase()) {
|
||||
return val;
|
||||
} else {
|
||||
return NaN;
|
||||
}
|
||||
}
|
||||
|
||||
export function parseIntWithHexOrBinary(s: string): number {
|
||||
if (/^%[01]+$/.test(s)) {
|
||||
return parseInt(s.slice(1), 2)
|
||||
}
|
||||
if (/^\$[0-9A-Fa-f]+$/.test(s)) {
|
||||
return parseInt(s.slice(1), 16)
|
||||
}
|
||||
if (/[a-fA-F]/.test(s)) {
|
||||
const hex = parseHex(s);
|
||||
if (!isNaN(hex)) {
|
||||
return hex;
|
||||
}
|
||||
}
|
||||
return parseInt(s);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { property, state } from "lit/decorators.js";
|
||||
|
||||
import {
|
||||
DeviceRef,
|
||||
Fields,
|
||||
LogicFields,
|
||||
Reagents,
|
||||
Slot,
|
||||
Connection,
|
||||
@@ -25,7 +25,7 @@ export declare class VMDeviceMixinInterface {
|
||||
name: string | null;
|
||||
nameHash: number | null;
|
||||
prefabName: string | null;
|
||||
fields: Fields;
|
||||
fields: LogicFields;
|
||||
slots: Slot[];
|
||||
reagents: Reagents;
|
||||
connections: Connection[];
|
||||
@@ -47,13 +47,23 @@ export const VMDeviceMixin = <T extends Constructor<LitElement>>(
|
||||
superClass: T,
|
||||
) => {
|
||||
class VMDeviceMixinClass extends superClass {
|
||||
@property({ type: Number }) accessor deviceID: number;
|
||||
@state() accessor device: DeviceRef;
|
||||
|
||||
_deviceID: number;
|
||||
get deviceID() {
|
||||
return this._deviceID;
|
||||
}
|
||||
@property({ type: Number })
|
||||
set deviceID(val: number) {
|
||||
this._deviceID = val;
|
||||
this.updateDevice();
|
||||
}
|
||||
|
||||
device: DeviceRef;
|
||||
|
||||
@state() accessor name: string | null = null;
|
||||
@state() accessor nameHash: number | null = null;
|
||||
@state() accessor prefabName: string | null;
|
||||
@state() accessor fields: Fields;
|
||||
@state() accessor fields: LogicFields;
|
||||
@state() accessor slots: Slot[];
|
||||
@state() accessor reagents: Reagents;
|
||||
@state() accessor connections: Connection[];
|
||||
@@ -69,11 +79,14 @@ export const VMDeviceMixin = <T extends Constructor<LitElement>>(
|
||||
|
||||
connectedCallback(): void {
|
||||
const root = super.connectedCallback();
|
||||
this.device = window.VM!.devices.get(this.deviceID)!;
|
||||
window.VM?.addEventListener(
|
||||
"vm-device-modified",
|
||||
this._handleDeviceModified.bind(this),
|
||||
);
|
||||
window.VM?.addEventListener(
|
||||
"vm-devices-update",
|
||||
this._handleDevicesModified.bind(this),
|
||||
);
|
||||
this.updateDevice();
|
||||
return root;
|
||||
}
|
||||
@@ -82,10 +95,19 @@ export const VMDeviceMixin = <T extends Constructor<LitElement>>(
|
||||
const id = e.detail;
|
||||
if (this.deviceID === id) {
|
||||
this.updateDevice();
|
||||
} else {
|
||||
this.requestUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
_handleDevicesModified(e: CustomEvent) {
|
||||
const ids = e.detail;
|
||||
this.requestUpdate();
|
||||
}
|
||||
|
||||
updateDevice() {
|
||||
this.device = window.VM!.devices.get(this.deviceID)!;
|
||||
|
||||
const name = this.device.name ?? null;
|
||||
if (this.name !== name) {
|
||||
this.name = name;
|
||||
@@ -114,7 +136,9 @@ export const VMDeviceMixin = <T extends Constructor<LitElement>>(
|
||||
if (!structuralEqual(this.connections, connections)) {
|
||||
this.connections = connections;
|
||||
}
|
||||
this.updateIC();
|
||||
if (typeof this.device.ic !== "undefined") {
|
||||
this.updateIC();
|
||||
}
|
||||
}
|
||||
|
||||
updateIC() {
|
||||
@@ -130,7 +154,7 @@ export const VMDeviceMixin = <T extends Constructor<LitElement>>(
|
||||
if (this.icState !== state) {
|
||||
this.icState = state;
|
||||
}
|
||||
const errors = this.device.program!.errors ?? null;
|
||||
const errors = this.device.program?.errors ?? null;
|
||||
if (!structuralEqual(this.errors, errors)) {
|
||||
this.errors = errors;
|
||||
}
|
||||
@@ -159,7 +183,9 @@ export const VMDeviceMixin = <T extends Constructor<LitElement>>(
|
||||
return VMDeviceMixinClass as Constructor<VMDeviceMixinInterface> & T;
|
||||
};
|
||||
|
||||
export const VMActiveICMixin = <T extends Constructor<LitElement>>(superClass: T) => {
|
||||
export const VMActiveICMixin = <T extends Constructor<LitElement>>(
|
||||
superClass: T,
|
||||
) => {
|
||||
class VMActiveICMixinClass extends VMDeviceMixin(superClass) {
|
||||
constructor() {
|
||||
super();
|
||||
@@ -187,6 +213,6 @@ export const VMActiveICMixin = <T extends Constructor<LitElement>>(superClass: T
|
||||
}
|
||||
this.updateDevice();
|
||||
}
|
||||
};
|
||||
}
|
||||
return VMActiveICMixinClass as Constructor<VMDeviceMixinInterface> & T;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -52,6 +52,7 @@ export class VMICControls extends VMActiveICMixin(BaseElement) {
|
||||
sl-button[variant="success"] {
|
||||
/* Changes the success theme color to purple using primitives */
|
||||
--sl-color-success-600: var(--sl-color-purple-700);
|
||||
--sl-color-success-500: var(--sl-color-purple-600);
|
||||
}
|
||||
sl-button[variant="primary"] {
|
||||
/* Changes the success theme color to purple using primitives */
|
||||
|
||||
@@ -1,20 +1,139 @@
|
||||
export type DeviceDBEntry = {
|
||||
import { LogicType, SlotLogicType } from "ic10emu_wasm";
|
||||
|
||||
export type SortingClass =
|
||||
| "Default"
|
||||
| "Kits"
|
||||
| "Tools"
|
||||
| "Resources"
|
||||
| "Food"
|
||||
| "Clothing"
|
||||
| "Appliances"
|
||||
| "Atmospherics"
|
||||
| "Storage"
|
||||
| "Ores"
|
||||
| "Ices";
|
||||
export type SlotClass =
|
||||
| "None"
|
||||
| "Helmet"
|
||||
| "Suit"
|
||||
| "Back"
|
||||
| "GasFilter"
|
||||
| "GasCanister"
|
||||
| "Motherboard"
|
||||
| "Circuitboard"
|
||||
| "DataDisk"
|
||||
| "Organ"
|
||||
| "Ore"
|
||||
| "Plant"
|
||||
| "Uniform"
|
||||
| "Entity"
|
||||
| "Battery"
|
||||
| "Egg"
|
||||
| "Belt"
|
||||
| "Tool"
|
||||
| "Appliance"
|
||||
| "Ingot"
|
||||
| "Torpedo"
|
||||
| "Cartridge"
|
||||
| "AccessCard"
|
||||
| "Magazine"
|
||||
| "Circuit"
|
||||
| "Bottle"
|
||||
| "ProgrammableChip"
|
||||
| "Glasses"
|
||||
| "CreditCard"
|
||||
| "DirtCanister"
|
||||
| "SensorProcessingUnit"
|
||||
| "LiquidCanister"
|
||||
| "LiquidBottle"
|
||||
| "Wreckage"
|
||||
| "SoundCartridge"
|
||||
| "DrillHead"
|
||||
| "ScanningHead"
|
||||
| "Flare"
|
||||
| "Blocked";
|
||||
export type NetworkType =
|
||||
| "None"
|
||||
| "Pipe"
|
||||
| "Power"
|
||||
| "Data"
|
||||
| "Chute"
|
||||
| "Elevator"
|
||||
| "PipeLiquid"
|
||||
| "LandingPad"
|
||||
| "LaunchPad"
|
||||
| "PowerAndData"
|
||||
| "All";
|
||||
export type ConnectionRole =
|
||||
| "None"
|
||||
| "Input"
|
||||
| "Input2"
|
||||
| "Output"
|
||||
| "Output2"
|
||||
| "Waste";
|
||||
|
||||
export type FieldType = "Read" | "Write" | "ReadWrite";
|
||||
|
||||
export type ReagentMode = "Contents" | "Recipe" | "Required" | "TotalContents";
|
||||
|
||||
export type BatchMode = "Average" | "Maximum" | "Minimum" | "Sum";
|
||||
|
||||
export interface DeviceDBItem {
|
||||
slotclass: SlotClass;
|
||||
sorting: SortingClass;
|
||||
maxquantity?: number;
|
||||
filtertype?: string;
|
||||
consumable?: boolean;
|
||||
ingredient?: boolean;
|
||||
reagents?: { [key: string]: number};
|
||||
}
|
||||
|
||||
export interface DeviceDBDevice {
|
||||
states: DBStates;
|
||||
reagents: boolean;
|
||||
atmosphere: boolean;
|
||||
pins?: number;
|
||||
}
|
||||
|
||||
export interface DeviceDBConnection {
|
||||
typ: NetworkType;
|
||||
role: ConnectionRole;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface DeviceDBEntry {
|
||||
name: string;
|
||||
hash: number;
|
||||
title: string;
|
||||
desc: string;
|
||||
logic?: { [key: string]: string };
|
||||
slots?: { name: string; typ: string }[];
|
||||
modes?: { [key: string]: string };
|
||||
conn?: { [key: string]: string[] };
|
||||
slots?: { name: string; typ: SlotClass }[];
|
||||
logic?: { [key in LogicType]?: FieldType };
|
||||
slotlogic?: { [key in SlotLogicType]?: number[] };
|
||||
modes?: { [key: number]: string };
|
||||
conn?: { [key: number]: DeviceDBConnection };
|
||||
item?: DeviceDBItem;
|
||||
device?: DeviceDBDevice;
|
||||
};
|
||||
|
||||
export type DeviceDB = {
|
||||
export interface DBStates {
|
||||
activate: boolean;
|
||||
color: boolean;
|
||||
lock: boolean;
|
||||
mode: boolean;
|
||||
onoff: boolean;
|
||||
open: boolean;
|
||||
}
|
||||
|
||||
export interface DeviceDB {
|
||||
logic_enabled: string[];
|
||||
slot_logic_enabled: string[];
|
||||
devices: string[];
|
||||
items: string[];
|
||||
strutures: string[];
|
||||
structures: string[];
|
||||
db: {
|
||||
[key: string]: DeviceDBEntry;
|
||||
};
|
||||
names_by_hash: { [key: number]: string };
|
||||
reagent_hashes: { [key: string]: number}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { DeviceRef, VM, init } from "ic10emu_wasm";
|
||||
import { DeviceDB } from "./device_db"
|
||||
import { DeviceRef, DeviceTemplate, VM, init } from "ic10emu_wasm";
|
||||
import { DeviceDB } from "./device_db";
|
||||
import "./base_device";
|
||||
|
||||
declare global {
|
||||
@@ -8,6 +8,13 @@ declare global {
|
||||
}
|
||||
}
|
||||
|
||||
export interface ToastMessage {
|
||||
variant: "warning" | "danger" | "success" | "primary" | "neutral";
|
||||
icon: string;
|
||||
title: string;
|
||||
msg: string;
|
||||
id: string;
|
||||
}
|
||||
|
||||
class VirtualMachine extends EventTarget {
|
||||
ic10vm: VM;
|
||||
@@ -15,7 +22,7 @@ class VirtualMachine extends EventTarget {
|
||||
_ics: Map<number, DeviceRef>;
|
||||
|
||||
accessor db: DeviceDB;
|
||||
dbPromise: Promise<{ default: DeviceDB }>
|
||||
dbPromise: Promise<{ default: DeviceDB }>;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
@@ -28,8 +35,13 @@ class VirtualMachine extends EventTarget {
|
||||
this._devices = new Map();
|
||||
this._ics = new Map();
|
||||
|
||||
this.dbPromise = import("../../../data/database.json");
|
||||
this.dbPromise.then((module) => this.setupDeviceDatabase(module.default))
|
||||
this.dbPromise = import("../../../data/database.json", {
|
||||
assert: { type: "json" },
|
||||
}) as Promise<{ default: DeviceDB }>;
|
||||
|
||||
this.dbPromise.then((module) =>
|
||||
this.setupDeviceDatabase(module.default as DeviceDB),
|
||||
);
|
||||
|
||||
this.updateDevices();
|
||||
this.updateCode();
|
||||
@@ -40,7 +52,9 @@ class VirtualMachine extends EventTarget {
|
||||
}
|
||||
|
||||
get deviceIds() {
|
||||
return Array.from(this.ic10vm.devices);
|
||||
const ids = Array.from(this.ic10vm.devices);
|
||||
ids.sort();
|
||||
return ids;
|
||||
}
|
||||
|
||||
get ics() {
|
||||
@@ -79,29 +93,34 @@ class VirtualMachine extends EventTarget {
|
||||
}
|
||||
for (const id of this._devices.keys()) {
|
||||
if (!device_ids.includes(id)) {
|
||||
this._devices.get(id)!.free();
|
||||
this._devices.delete(id);
|
||||
update_flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
const ics = this.ic10vm.ics;
|
||||
for (const id of ics) {
|
||||
if (!this._ics.has(id)) {
|
||||
this._ics.set(id, this._devices.get(id)!);
|
||||
update_flag = true;
|
||||
for (const [id, device] of this._devices) {
|
||||
if (typeof device.ic !== "undefined") {
|
||||
if (!this._ics.has(id)) {
|
||||
this._ics.set(id, device);
|
||||
update_flag = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const id of this._ics.keys()) {
|
||||
if (!ics.includes(id)) {
|
||||
this._ics.get(id)!.free();
|
||||
if (!this._devices.has(id)) {
|
||||
this._ics.delete(id);
|
||||
update_flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (update_flag) {
|
||||
const ids = Array.from(device_ids);
|
||||
ids.sort();
|
||||
this.dispatchEvent(
|
||||
new CustomEvent("vm-devices-update", { detail: device_ids }),
|
||||
new CustomEvent("vm-devices-update", {
|
||||
detail: ids,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -113,18 +132,19 @@ class VirtualMachine extends EventTarget {
|
||||
const ic = this._ics.get(id);
|
||||
const prog = progs.get(id);
|
||||
if (ic && prog) {
|
||||
console.time(`CompileProgram_${id}_${attempt}`);
|
||||
try {
|
||||
console.time(`CompileProgram_${id}_${attempt}`);
|
||||
this.ics.get(id)!.setCodeInvalid(progs.get(id)!);
|
||||
const compiled = this.ics.get(id)?.program!;
|
||||
window.App?.session.setProgramErrors(id, compiled.errors);
|
||||
this.dispatchEvent(
|
||||
new CustomEvent("vm-device-modified", { detail: id }),
|
||||
);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
} catch (err) {
|
||||
this.handleVmError(err);
|
||||
} finally{
|
||||
console.timeEnd(`CompileProgram_${id}_${attempt}`);
|
||||
}
|
||||
console.timeEnd(`CompileProgram_${id}_${attempt}`);
|
||||
}
|
||||
}
|
||||
this.update();
|
||||
@@ -135,8 +155,8 @@ class VirtualMachine extends EventTarget {
|
||||
if (ic) {
|
||||
try {
|
||||
ic.step(false);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
} catch (err) {
|
||||
this.handleVmError(err);
|
||||
}
|
||||
this.update();
|
||||
this.dispatchEvent(
|
||||
@@ -150,8 +170,8 @@ class VirtualMachine extends EventTarget {
|
||||
if (ic) {
|
||||
try {
|
||||
ic.run(false);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
} catch (err) {
|
||||
this.handleVmError(err);
|
||||
}
|
||||
this.update();
|
||||
this.dispatchEvent(
|
||||
@@ -177,71 +197,133 @@ class VirtualMachine extends EventTarget {
|
||||
);
|
||||
}
|
||||
}, this);
|
||||
const ic = this.activeIC!;
|
||||
window.App!.session.setActiveLine(window.App!.session.activeIC, ic.ip!);
|
||||
this.updateDevice(this.activeIC);
|
||||
}
|
||||
|
||||
setRegister(index: number, val: number) {
|
||||
const ic = this.activeIC!;
|
||||
try {
|
||||
ic.setRegister(index, val);
|
||||
this.dispatchEvent(
|
||||
new CustomEvent("vm-device-modified", { detail: ic.id }),
|
||||
);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
updateDevice(device: DeviceRef) {
|
||||
this.dispatchEvent(
|
||||
new CustomEvent("vm-device-modified", { detail: device.id }),
|
||||
);
|
||||
if (typeof device.ic !== "undefined") {
|
||||
window.App!.session.setActiveLine(device.id, device.ip!);
|
||||
}
|
||||
}
|
||||
|
||||
setStack(addr: number, val: number) {
|
||||
handleVmError(err: Error) {
|
||||
console.log("Error in Virtual Machine", err);
|
||||
const message: ToastMessage = {
|
||||
variant: "danger",
|
||||
icon: "bug",
|
||||
title: `Error in Virtual Machine ${err.name}`,
|
||||
msg: err.message,
|
||||
id: Date.now().toString(16),
|
||||
};
|
||||
this.dispatchEvent(new CustomEvent("vm-message", { detail: message }));
|
||||
}
|
||||
|
||||
changeDeviceId(old_id: number, new_id: number): boolean {
|
||||
try {
|
||||
this.ic10vm.changeDeviceId(old_id, new_id);
|
||||
this.updateDevices();
|
||||
if (window.App.session.activeIC === old_id) {
|
||||
window.App.session.activeIC = new_id;
|
||||
}
|
||||
return true;
|
||||
} catch (err) {
|
||||
this.handleVmError(err);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
setRegister(index: number, val: number): boolean {
|
||||
const ic = this.activeIC!;
|
||||
try {
|
||||
ic.setRegister(index, val);
|
||||
this.updateDevice(ic);
|
||||
return true;
|
||||
} catch (err) {
|
||||
this.handleVmError(err);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
setStack(addr: number, val: number): boolean {
|
||||
const ic = this.activeIC!;
|
||||
try {
|
||||
ic!.setStack(addr, val);
|
||||
this.dispatchEvent(
|
||||
new CustomEvent("vm-device-modified", { detail: ic.id }),
|
||||
);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
this.updateDevice(ic);
|
||||
return true;
|
||||
} catch (err) {
|
||||
this.handleVmError(err);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
setDeviceName(id: number, name: string): boolean {
|
||||
const device = this._devices.get(id);
|
||||
if (device) {
|
||||
device.setName(name);
|
||||
this.dispatchEvent(new CustomEvent("vm-device-modified", { detail: id }));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
setDeviceField(id: number, field: string, val: number) {
|
||||
const device = this._devices.get(id);
|
||||
if (device) {
|
||||
try {
|
||||
device.setField(field, val);
|
||||
this.dispatchEvent(
|
||||
new CustomEvent("vm-device-modified", { detail: id }),
|
||||
);
|
||||
device.setName(name);
|
||||
this.dispatchEvent(new CustomEvent("vm-device-modified", { detail: id }));
|
||||
return true;
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
} catch(e) {
|
||||
this.handleVmError(e);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
setDeviceSlotField(id: number, slot: number, field: string, val: number) {
|
||||
setDeviceField(id: number, field: string, val: number): boolean {
|
||||
const device = this._devices.get(id);
|
||||
if (device) {
|
||||
try {
|
||||
device.setField(field, val);
|
||||
this.updateDevice(device);
|
||||
return true;
|
||||
} catch (err) {
|
||||
this.handleVmError(err);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
setDeviceSlotField(id: number, slot: number, field: string, val: number): boolean {
|
||||
const device = this._devices.get(id);
|
||||
if (device) {
|
||||
try {
|
||||
device.setSlotField(slot, field, val);
|
||||
this.dispatchEvent(
|
||||
new CustomEvent("vm-device-modified", { detail: id }),
|
||||
);
|
||||
this.updateDevice(device);
|
||||
return true;
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
} catch (err) {
|
||||
this.handleVmError(err);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
setDeviceConnection(id: number, conn: number, val: number | undefined): boolean {
|
||||
const device = this._devices.get(id);
|
||||
if (typeof device !== "undefined") {
|
||||
try {
|
||||
this.ic10vm.setDeviceConnection(id, conn, val);
|
||||
this.updateDevice(device);
|
||||
return true
|
||||
} catch (err) {
|
||||
this.handleVmError(err);
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
setDevicePin(id: number, pin: number, val: number | undefined): boolean {
|
||||
const device = this._devices.get(id);
|
||||
if (typeof device !== "undefined") {
|
||||
try {
|
||||
this.ic10vm.setPin(id, pin, val);
|
||||
this.updateDevice(device);
|
||||
return true;
|
||||
} catch (err) {
|
||||
this.handleVmError(err);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@@ -254,6 +336,35 @@ class VirtualMachine extends EventTarget {
|
||||
new CustomEvent("vm-device-db-loaded", { detail: this.db }),
|
||||
);
|
||||
}
|
||||
|
||||
addDeviceFromTemplate(template: DeviceTemplate): boolean {
|
||||
try {
|
||||
console.log("adding device", template);
|
||||
const id = this.ic10vm.addDeviceFromTemplate(template);
|
||||
this._devices.set(id, this.ic10vm.getDevice(id)!);
|
||||
const device_ids = this.ic10vm.devices;
|
||||
this.dispatchEvent(
|
||||
new CustomEvent("vm-devices-update", {
|
||||
detail: Array.from(device_ids),
|
||||
}),
|
||||
);
|
||||
return true;
|
||||
} catch (err) {
|
||||
this.handleVmError(err);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
removeDevice(id: number): boolean {
|
||||
try {
|
||||
this.ic10vm.removeDevice(id);
|
||||
this.updateDevices();
|
||||
return true;
|
||||
} catch (err) {
|
||||
this.handleVmError(err);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { VirtualMachine };
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
import { HTMLTemplateResult, html, css } from "lit";
|
||||
import { customElement, property, query } from "lit/decorators.js";
|
||||
import { customElement, property, query, state } from "lit/decorators.js";
|
||||
import { BaseElement, defaultCss } from "../components";
|
||||
import "@shoelace-style/shoelace/dist/components/details/details.js";
|
||||
import "@shoelace-style/shoelace/dist/components/tab/tab.js";
|
||||
import "@shoelace-style/shoelace/dist/components/tab-panel/tab-panel.js";
|
||||
import "@shoelace-style/shoelace/dist/components/tab-group/tab-group.js";
|
||||
import "@shoelace-style/shoelace/dist/components/alert/alert.js";
|
||||
|
||||
import "./controls";
|
||||
import "./registers";
|
||||
import "./stack";
|
||||
import "./device";
|
||||
import { ToastMessage } from ".";
|
||||
|
||||
@customElement("vm-ui")
|
||||
export class VMUI extends BaseElement {
|
||||
@@ -32,11 +34,29 @@ export class VMUI extends BaseElement {
|
||||
margin-left: 1rem;
|
||||
margin-right: 1rem;
|
||||
margin-top: 0.5rem;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
.side-container {
|
||||
height: 100%
|
||||
height: calc(100vh - 3.8rem);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
vm-device-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1 1 auto;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.tab-panel {
|
||||
height: calc(100vh - 19rem);
|
||||
overflow-y: auto;
|
||||
}
|
||||
.tab-group {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
sl-tab::part(base) {
|
||||
padding: var(--sl-spacing-small) var(--sl-spacing-medium);
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
@@ -44,14 +64,36 @@ export class VMUI extends BaseElement {
|
||||
super();
|
||||
}
|
||||
|
||||
connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
window.VM.addEventListener("vm-message", this._handleVMMessage.bind(this));
|
||||
}
|
||||
|
||||
_handleVMMessage(e: CustomEvent) {
|
||||
const msg: ToastMessage = e.detail;
|
||||
const alert = Object.assign(document.createElement("sl-alert"), {
|
||||
variant: msg.variant,
|
||||
closable: true,
|
||||
// duration: 5000,
|
||||
innerHTML: `
|
||||
<sl-icon slot="icon" name="${msg.icon}"></sl-icon>
|
||||
<strong>${msg.title}</strong><br />
|
||||
${msg.msg}
|
||||
`,
|
||||
});
|
||||
|
||||
document.body.append(alert);
|
||||
alert.toast();
|
||||
}
|
||||
|
||||
protected render() {
|
||||
return html`
|
||||
<div class="side-container">
|
||||
<vm-ic-controls></vm-ic-controls>
|
||||
<sl-tab-group>
|
||||
<sl-tab-group class="tab-group">
|
||||
<sl-tab slot="nav" panel="active-ic">Active IC</sl-tab>
|
||||
<sl-tab slot="nav" panel="devices">Devices</sl-tab>
|
||||
<sl-tab-panel name="active-ic">
|
||||
<sl-tab-panel name="active-ic" class="tab-panel">
|
||||
<sl-details summary="Registers" open>
|
||||
<vm-ic-registers></vm-ic-registers>
|
||||
</sl-details>
|
||||
@@ -59,7 +101,7 @@ export class VMUI extends BaseElement {
|
||||
<vm-ic-stack></vm-ic-stack>
|
||||
</sl-details>
|
||||
</sl-tab-panel>
|
||||
<sl-tab-panel name="devices">
|
||||
<sl-tab-panel name="devices" class="tab-panel">
|
||||
<vm-device-list></vm-device-list>
|
||||
</sl-tab-panel>
|
||||
</sl-tab-group>
|
||||
|
||||
16
www/src/ts/virtual_machine/utils.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { Connection } from "ic10emu_wasm";
|
||||
import { DeviceDBConnection } from "./device_db";
|
||||
|
||||
const CableNetworkTypes: readonly string[] = Object.freeze(["Power", "Data", "PowerAndData"]);
|
||||
export function connectionFromDeviceDBConnection(conn: DeviceDBConnection): Connection {
|
||||
if (CableNetworkTypes.includes(conn.typ)) {
|
||||
return {
|
||||
CableNetwork: {
|
||||
net: window.VM?.ic10vm.defaultNetwork,
|
||||
typ: conn.typ
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return "Other";
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,7 @@ import re
|
||||
from collections import defaultdict
|
||||
from pathlib import Path
|
||||
from pprint import pprint
|
||||
from typing import Any # type: ignore[Any]
|
||||
from typing import TypedDict
|
||||
from typing import Any, NotRequired, TypedDict # type: ignore[Any]
|
||||
|
||||
|
||||
class SlotInsert(TypedDict):
|
||||
@@ -18,6 +17,29 @@ class LInsert(TypedDict):
|
||||
LogicAccessTypes: str
|
||||
|
||||
|
||||
class PediaPageItem(TypedDict):
|
||||
SlotClass: str
|
||||
SortingClass: str
|
||||
MaxQuantity: NotRequired[float]
|
||||
FilterType: NotRequired[str]
|
||||
Consumable: NotRequired[bool]
|
||||
Ingredient: NotRequired[bool]
|
||||
Reagents: NotRequired[dict[str, float]]
|
||||
|
||||
|
||||
class PediaPageDevice(TypedDict):
|
||||
ConnectionList: list[list[str]]
|
||||
HasReagents: bool
|
||||
HasAtmosphere: bool
|
||||
HasLockState: bool
|
||||
HasOpenState: bool
|
||||
HasOnOffState: bool
|
||||
HasActivateState: bool
|
||||
HasModeState: bool
|
||||
HasColorState: bool
|
||||
DevicesLength: NotRequired[int]
|
||||
|
||||
|
||||
class PediaPage(TypedDict):
|
||||
Key: str
|
||||
Title: str
|
||||
@@ -29,42 +51,78 @@ class PediaPage(TypedDict):
|
||||
LogicSlotInsert: list[LInsert]
|
||||
ModeInsert: list[LInsert]
|
||||
ConnectionInsert: list[LInsert]
|
||||
ConnectionList: list[list[str]]
|
||||
Device: NotRequired[PediaPageDevice]
|
||||
Item: NotRequired[PediaPageItem]
|
||||
|
||||
|
||||
class Pedia(TypedDict):
|
||||
pages: list[PediaPage]
|
||||
|
||||
reagents: dict[str, int]
|
||||
|
||||
class DBSlot(TypedDict):
|
||||
name: str
|
||||
typ: str
|
||||
|
||||
|
||||
class DBPageStates(TypedDict):
|
||||
lock: NotRequired[bool]
|
||||
open: NotRequired[bool]
|
||||
mode: NotRequired[bool]
|
||||
onoff: NotRequired[bool]
|
||||
color: NotRequired[bool]
|
||||
activate: NotRequired[bool]
|
||||
|
||||
|
||||
class DBPageConnection(TypedDict):
|
||||
typ: str
|
||||
role: str
|
||||
name: str
|
||||
|
||||
|
||||
class DBPageDevice(TypedDict):
|
||||
states: DBPageStates
|
||||
reagents: bool
|
||||
atmosphere: bool
|
||||
pins: NotRequired[int]
|
||||
|
||||
|
||||
class DBPageItem(TypedDict):
|
||||
slotclass: str | None
|
||||
sorting: str | None
|
||||
filtertype: NotRequired[str]
|
||||
maxquantity: NotRequired[int]
|
||||
consumable: NotRequired[bool]
|
||||
ingredient: NotRequired[bool]
|
||||
reagents: NotRequired[dict[str, float]]
|
||||
|
||||
|
||||
class DBPage(TypedDict):
|
||||
name: str
|
||||
hash: int
|
||||
title: str
|
||||
desc: str
|
||||
slots: list[DBSlot] | None
|
||||
logic: dict[str, str] | None
|
||||
slotlogic: dict[str, list[int]] | None
|
||||
modes: dict[int, str] | None
|
||||
conn: dict[int, list[str]] | None
|
||||
conn: dict[int, DBPageConnection] | None
|
||||
item: NotRequired[DBPageItem]
|
||||
device: NotRequired[DBPageDevice]
|
||||
|
||||
|
||||
def extract_all() -> None:
|
||||
db: dict[str, DBPage] = {}
|
||||
pedia: Pedia = {"pages": []}
|
||||
pedia: Pedia = {"pages": [], "reagents": {}}
|
||||
linkPat = re.compile(r"<link=\w+><color=[\w#]+>(.+?)</color></link>")
|
||||
with (Path("data") / "Stationpedia.json").open("r") as f:
|
||||
pedia = json.load(f)
|
||||
for page in pedia["pages"]:
|
||||
item: DBPage = defaultdict(list) # type: ignore[reportAssignmenType]
|
||||
item: DBPage = defaultdict(list) # type: ignore[reportAssignmentType]
|
||||
|
||||
match page:
|
||||
case {
|
||||
"Key": _,
|
||||
"Title": _,
|
||||
"Title": title,
|
||||
"Description": desc,
|
||||
"PrefabName": name,
|
||||
"PrefabHash": name_hash,
|
||||
@@ -72,17 +130,25 @@ def extract_all() -> None:
|
||||
"LogicInsert": logic,
|
||||
"LogicSlotInsert": slotlogic,
|
||||
"ModeInsert": modes,
|
||||
"ConnectionInsert": _,
|
||||
"ConnectionList": connections,
|
||||
"ConnectionInsert": conninsert,
|
||||
}:
|
||||
|
||||
connNames = {
|
||||
int(insert["LogicAccessTypes"]): insert["LogicName"]
|
||||
for insert in conninsert
|
||||
}
|
||||
|
||||
device = page.get("Device", None)
|
||||
item_props = page.get("Item", None)
|
||||
item["name"] = name
|
||||
item["hash"] = name_hash
|
||||
item["title"] = title
|
||||
item["desc"] = re.sub(linkPat, r"\1", desc)
|
||||
match slots:
|
||||
case []:
|
||||
item["slots"] = None
|
||||
case _:
|
||||
item["slots"] = [{}] * len(slots) # type: ignore[reportAssignmenType]
|
||||
item["slots"] = [{}] * len(slots) # type: ignore[reportAssignmentType]
|
||||
for slot in slots:
|
||||
item["slots"][int(slot["SlotIndex"])] = {
|
||||
"name": slot["SlotName"],
|
||||
@@ -119,13 +185,112 @@ def extract_all() -> None:
|
||||
"LogicName"
|
||||
]
|
||||
|
||||
match connections:
|
||||
case []:
|
||||
item["conn"] = None
|
||||
match device:
|
||||
case None:
|
||||
pass
|
||||
case {
|
||||
"ConnectionList": connections,
|
||||
"HasReagents": hasReagents,
|
||||
"HasAtmosphere": hasAtmosphere,
|
||||
"HasLockState": hasLockState,
|
||||
"HasOpenState": hasOpenState,
|
||||
"HasModeState": hasModeState,
|
||||
"HasOnOffState": hasOnOffState,
|
||||
"HasActivateState": hasActivateState,
|
||||
"HasColorState": hasColorState,
|
||||
}:
|
||||
|
||||
match connections:
|
||||
case []:
|
||||
item["conn"] = None
|
||||
case _:
|
||||
item["conn"] = {}
|
||||
for index, [conn_typ, conn_role] in enumerate(
|
||||
connections
|
||||
):
|
||||
item["conn"][index] = {
|
||||
"typ": conn_typ,
|
||||
"role": conn_role,
|
||||
"name": connNames.get(index, "Connection"),
|
||||
}
|
||||
|
||||
states: DBPageStates = {}
|
||||
|
||||
states["lock"] = hasLockState
|
||||
states["open"] = hasOpenState
|
||||
states["mode"] = hasModeState
|
||||
states["activate"] = hasActivateState
|
||||
states["onoff"] = hasOnOffState
|
||||
states["color"] = hasColorState
|
||||
|
||||
deviceslength = device.get("DevicesLength", None)
|
||||
dbdevice: DBPageDevice = {
|
||||
"states": states,
|
||||
"reagents": hasReagents,
|
||||
"atmosphere": hasAtmosphere,
|
||||
}
|
||||
|
||||
match deviceslength:
|
||||
case None:
|
||||
pass
|
||||
case _:
|
||||
dbdevice["pins"] = deviceslength
|
||||
|
||||
item["device"] = dbdevice
|
||||
|
||||
case _:
|
||||
item["conn"] = {}
|
||||
for index, [conn_typ, conn_role] in enumerate(connections):
|
||||
item["conn"][index] = [conn_typ, conn_role]
|
||||
print(f"NON-CONFORMING: ")
|
||||
pprint(device)
|
||||
return
|
||||
|
||||
match item_props:
|
||||
case None:
|
||||
pass
|
||||
case {"SlotClass": slotclass, "SortingClass": sortingclass}:
|
||||
maxquantity = item_props.get("MaxQuantity", None)
|
||||
filtertype = item_props.get("FilterType", None)
|
||||
dbitem: DBPageItem = {
|
||||
"sorting": sortingclass,
|
||||
"slotclass": slotclass,
|
||||
}
|
||||
match maxquantity:
|
||||
case None:
|
||||
pass
|
||||
case _:
|
||||
dbitem["maxquantity"] = int(maxquantity)
|
||||
|
||||
match filtertype:
|
||||
case None:
|
||||
pass
|
||||
case _:
|
||||
dbitem["filtertype"] = filtertype
|
||||
|
||||
consumable = item_props.get("Consumable", None)
|
||||
match consumable:
|
||||
case None:
|
||||
pass
|
||||
case _:
|
||||
dbitem["consumable"] = consumable
|
||||
|
||||
ingredient = item_props.get("Ingredient", None)
|
||||
match ingredient:
|
||||
case None:
|
||||
pass
|
||||
case _:
|
||||
dbitem["ingredient"] = ingredient
|
||||
|
||||
reagents = item_props.get("Reagents", None)
|
||||
match reagents:
|
||||
case None:
|
||||
pass
|
||||
case _:
|
||||
dbitem["reagents"] = reagents
|
||||
|
||||
item["item"] = dbitem
|
||||
case _:
|
||||
print(f"NON-CONFORMING: ")
|
||||
pprint(item_props)
|
||||
return
|
||||
|
||||
case _:
|
||||
print(f"NON-CONFORMING: ")
|
||||
@@ -139,17 +304,13 @@ def extract_all() -> None:
|
||||
item["name"] for item in db.values() if item["slotlogic"] is not None
|
||||
]
|
||||
|
||||
devices = [
|
||||
item["name"]
|
||||
for item in db.values()
|
||||
if item["logic"] is not None and item["conn"] is not None
|
||||
]
|
||||
devices = [item["name"] for item in db.values() if "device" in item]
|
||||
|
||||
strutures = [
|
||||
structures = [
|
||||
item["name"] for item in db.values() if item["name"].startswith("Structure")
|
||||
]
|
||||
|
||||
items = [item["name"] for item in db.values() if item["name"] not in strutures]
|
||||
items = [item["name"] for item in db.values() if "item" in item]
|
||||
|
||||
def clean_nones(value: Any) -> Any: # type: ignore[Any]
|
||||
if isinstance(value, list):
|
||||
@@ -168,14 +329,21 @@ def extract_all() -> None:
|
||||
"logic_enabled": logicable,
|
||||
"slot_logic_enabled": slotlogicable,
|
||||
"devices": devices,
|
||||
"strutures": strutures,
|
||||
"structures": structures,
|
||||
"items": items,
|
||||
"db": db,
|
||||
"names_by_hash": {
|
||||
page["hash"]: page["name"] for page in db.values()
|
||||
},
|
||||
"reagent_hashes": pedia["reagents"]
|
||||
}
|
||||
),
|
||||
f,
|
||||
indent=1,
|
||||
sort_keys=True,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# extract_logicable()
|
||||
extract_all()
|
||||
|
||||
@@ -3,13 +3,15 @@
|
||||
"outDir": "./dist/",
|
||||
"sourceMap": true,
|
||||
"noImplicitAny": true,
|
||||
"module": "es2022",
|
||||
"module": "esnext",
|
||||
"target": "es2021",
|
||||
"allowJs": true,
|
||||
"moduleResolution": "bundler",
|
||||
"resolveJsonModule": true,
|
||||
"esModuleInterop": true,
|
||||
"isolatedModules": true,
|
||||
"experimentalDecorators": true,
|
||||
"useDefineForClassFields": false,
|
||||
"types": ["@types/wicg-file-system-access", "@types/ace"],
|
||||
"plugins": [
|
||||
{
|
||||
|
||||
@@ -26,7 +26,7 @@ module.exports = {
|
||||
patterns: [
|
||||
"img/*.png",
|
||||
"img/*/*.png",
|
||||
{ from: "data/database.json", to: "data" },
|
||||
// { from: "data/database.json", to: "data" },
|
||||
// Copy Shoelace assets to dist/shoelace
|
||||
{
|
||||
from: path.resolve(
|
||||
|
||||
@@ -23,7 +23,7 @@ module.exports = {
|
||||
patterns: [
|
||||
"img/*.png",
|
||||
"img/*/*.png",
|
||||
{ from: "data/database.json", to: "data" },
|
||||
// { from: "data/database.json", to: "data" },
|
||||
// Copy Shoelace assets to dist/shoelace
|
||||
{
|
||||
from: path.resolve(
|
||||
|
||||