make slots account for having occupents. return logic fields that are deived form the device or slot occupant
This commit is contained in:
@@ -43,10 +43,15 @@ 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()
|
||||
@@ -69,12 +74,20 @@ impl DeviceRef {
|
||||
|
||||
#[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,38 +280,37 @@ 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)
|
||||
device_ref.set_field(logic_typ, value, &self.vm.borrow())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "setSlotField")]
|
||||
pub fn set_slot_field(&self, slot: usize, field: &str, value: f64) -> Result<f64, JsError> {
|
||||
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();
|
||||
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)
|
||||
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<u16>) -> Result<(), JsError> {
|
||||
pub fn set_connection(&self, conn: usize, net: Option<u32>) -> Result<(), JsError> {
|
||||
let mut device_ref = self.device.borrow_mut();
|
||||
let conn_len = device_ref.connections.len();
|
||||
let conn_ref = device_ref
|
||||
@@ -315,19 +327,29 @@ impl DeviceRef {
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "addDeviceToNetwork")]
|
||||
pub fn add_device_to_network(&self, network_id: u16, connection: usize) -> Result<bool, JsError> {
|
||||
pub fn add_device_to_network(
|
||||
&self,
|
||||
network_id: u32,
|
||||
connection: usize,
|
||||
) -> Result<bool, JsError> {
|
||||
let id = self.device.borrow().id;
|
||||
Ok(self.vm.borrow().add_device_to_network(id, network_id, connection)?)
|
||||
Ok(self
|
||||
.vm
|
||||
.borrow()
|
||||
.add_device_to_network(id, network_id, connection)?)
|
||||
}
|
||||
|
||||
#[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 +371,98 @@ 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 = "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)?)
|
||||
pub fn add_device_to_network(
|
||||
&self,
|
||||
id: u32,
|
||||
network_id: u32,
|
||||
connection: usize,
|
||||
) -> Result<bool, JsError> {
|
||||
Ok(self
|
||||
.vm
|
||||
.borrow()
|
||||
.add_device_to_network(id, network_id, connection)?)
|
||||
}
|
||||
|
||||
#[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)?)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
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"));
|
||||
|
||||
|
||||
@@ -40,9 +40,18 @@ 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: Fields;
|
||||
}
|
||||
export interface Slot {
|
||||
typ: SlotType;
|
||||
fields: Fields;
|
||||
readonly typ: SlotType;
|
||||
readonly occupant: SlotOccupant | undefined;
|
||||
readonly fields: Fields;
|
||||
}
|
||||
|
||||
export type Reagents = Map<string, Map<number, number>>;
|
||||
@@ -50,29 +59,37 @@ export type Reagents = Map<string, Map<number, number>>;
|
||||
export type Connection = { CableNetwork: number } | "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 LogicType = { readonly LogicType: string };
|
||||
export type SlotLogicType = { readonly SlotLogicType: string };
|
||||
export type BatchMode = { readonly BatchMode: string };
|
||||
export type ReagentMode = { 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:
|
||||
@@ -102,18 +119,23 @@ 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 {
|
||||
@@ -125,4 +147,5 @@ export interface DeviceRef {
|
||||
readonly defines?: Defines | undefined;
|
||||
readonly pins?: Pins;
|
||||
readonly program?: Program;
|
||||
getSlotFields(slot: number): Fields;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user