refactor(vm, frontend): memory instructions, baseObject
- parse and map meory instructions - use FrozenObjectFull to propogate data out of VM to componates (far less wasm calls)
This commit is contained in:
@@ -12,11 +12,11 @@ import { cache } from "lit/directives/cache.js";
|
||||
import { default as uFuzzy } from "@leeoniya/ufuzzy";
|
||||
import { when } from "lit/directives/when.js";
|
||||
import { unsafeHTML } from "lit/directives/unsafe-html.js";
|
||||
import { VMDeviceDBMixin } from "virtual_machine/base_device";
|
||||
import { VMTemplateDBMixin } from "virtual_machine/base_device";
|
||||
|
||||
|
||||
@customElement("vm-add-device-button")
|
||||
export class VMAddDeviceButton extends VMDeviceDBMixin(BaseElement) {
|
||||
export class VMAddDeviceButton extends VMTemplateDBMixin(BaseElement) {
|
||||
static styles = [
|
||||
...defaultCss,
|
||||
css`
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { html, css, HTMLTemplateResult } from "lit";
|
||||
import { customElement, property, query, state } from "lit/decorators.js";
|
||||
import { BaseElement, defaultCss } from "components";
|
||||
import { VMDeviceDBMixin, VMObjectMixin } from "virtual_machine/base_device";
|
||||
import { VMTemplateDBMixin, VMObjectMixin } from "virtual_machine/base_device";
|
||||
import SlSelect from "@shoelace-style/shoelace/dist/components/select/select.component.js";
|
||||
import { parseIntWithHexOrBinary, parseNumber } from "utils";
|
||||
import SlInput from "@shoelace-style/shoelace/dist/components/input/input.component.js";
|
||||
@@ -15,7 +15,9 @@ import { repeat } from "lit/directives/repeat.js";
|
||||
export type CardTab = "fields" | "slots" | "reagents" | "networks" | "pins";
|
||||
|
||||
@customElement("vm-device-card")
|
||||
export class VMDeviceCard extends VMDeviceDBMixin(VMObjectMixin(BaseElement)) {
|
||||
export class VMDeviceCard extends VMTemplateDBMixin(
|
||||
VMObjectMixin(BaseElement),
|
||||
) {
|
||||
image_err: boolean;
|
||||
|
||||
@property({ type: Boolean }) open: boolean;
|
||||
@@ -141,7 +143,17 @@ export class VMDeviceCard extends VMDeviceDBMixin(VMObjectMixin(BaseElement)) {
|
||||
badges.push(html`<sl-badge variant="primary" pill pulse>db</sl-badge>`);
|
||||
}
|
||||
const activeIc = window.VM.vm.activeIC;
|
||||
activeIc?.pins?.forEach((id, index) => {
|
||||
|
||||
const numPins =
|
||||
"device" in activeIc?.template
|
||||
? activeIc.template.device.device_pins_length
|
||||
: Math.max(
|
||||
...Array.from(activeIc?.obj_info.device_pins?.keys() ?? [0]),
|
||||
);
|
||||
const pins = new Array(numPins)
|
||||
.fill(true)
|
||||
.map((_, index) => this.pins.get(index));
|
||||
pins.forEach((id, index) => {
|
||||
if (this.objectID == id) {
|
||||
badges.push(
|
||||
html`<sl-badge variant="success" pill>d${index}</sl-badge>`,
|
||||
@@ -150,31 +162,71 @@ export class VMDeviceCard extends VMDeviceDBMixin(VMObjectMixin(BaseElement)) {
|
||||
}, this);
|
||||
return html`
|
||||
<sl-tooltip content="${this.prefabName}">
|
||||
<img class="image me-2" src="img/stationpedia/${this.prefabName}.png"
|
||||
onerror="this.src = '${VMDeviceCard.transparentImg}'" />
|
||||
<img
|
||||
class="image me-2"
|
||||
src="img/stationpedia/${this.prefabName}.png"
|
||||
onerror="this.src = '${VMDeviceCard.transparentImg}'"
|
||||
/>
|
||||
</sl-tooltip>
|
||||
<div class="header-name">
|
||||
<sl-input id="vmDeviceCard${this.objectID}Id" class="device-id me-1" size="small" pill value=${this.objectID}
|
||||
@sl-change=${this._handleChangeID}>
|
||||
<sl-input
|
||||
id="vmDeviceCard${this.objectID}Id"
|
||||
class="device-id me-1"
|
||||
size="small"
|
||||
pill
|
||||
value=${this.objectID.toString()}
|
||||
@sl-change=${this._handleChangeID}
|
||||
>
|
||||
<span slot="prefix">Id</span>
|
||||
<sl-copy-button slot="suffix" .value=${this.objectID}></sl-copy-button>
|
||||
<sl-copy-button
|
||||
slot="suffix"
|
||||
.value=${this.objectID.toString()}
|
||||
></sl-copy-button>
|
||||
</sl-input>
|
||||
<sl-input id="vmDeviceCard${this.objectID}Name" class="device-name me-1" size="small" pill
|
||||
placeholder=${this.prefabName} value=${this.name} @sl-change=${this._handleChangeName}>
|
||||
<sl-input
|
||||
id="vmDeviceCard${this.objectID}Name"
|
||||
class="device-name me-1"
|
||||
size="small"
|
||||
pill
|
||||
placeholder=${this.prefabName}
|
||||
value=${this.name}
|
||||
@sl-change=${this._handleChangeName}
|
||||
>
|
||||
<span slot="prefix">Name</span>
|
||||
<sl-copy-button slot="suffix" from="vmDeviceCard${this.objectID}Name.value"></sl-copy-button>
|
||||
<sl-copy-button
|
||||
slot="suffix"
|
||||
from="vmDeviceCard${this.objectID}Name.value"
|
||||
></sl-copy-button>
|
||||
</sl-input>
|
||||
<sl-input id="vmDeviceCard${this.objectID}NameHash" size="small" pill class="device-name-hash me-1"
|
||||
value="${this.nameHash}" readonly>
|
||||
<sl-input
|
||||
id="vmDeviceCard${this.objectID}NameHash"
|
||||
size="small"
|
||||
pill
|
||||
class="device-name-hash me-1"
|
||||
value="${this.nameHash.toString()}"
|
||||
readonly
|
||||
>
|
||||
<span slot="prefix">Hash</span>
|
||||
<sl-copy-button slot="suffix" from="vmDeviceCard${this.objectID}NameHash.value"></sl-copy-button>
|
||||
<sl-copy-button
|
||||
slot="suffix"
|
||||
from="vmDeviceCard${this.objectID}NameHash.value"
|
||||
></sl-copy-button>
|
||||
</sl-input>
|
||||
${badges.map((badge) => badge)}
|
||||
</div>
|
||||
<div class="ms-auto mt-auto mb-auto me-2">
|
||||
<sl-tooltip content=${thisIsActiveIc ? "Removing the selected Active IC is disabled" : "Remove Device" }>
|
||||
<sl-icon-button class="remove-button" name="trash" label="Remove Device" ?disabled=${thisIsActiveIc}
|
||||
@click=${this._handleDeviceRemoveButton}></sl-icon-button>
|
||||
<sl-tooltip
|
||||
content=${thisIsActiveIc
|
||||
? "Removing the selected Active IC is disabled"
|
||||
: "Remove Device"}
|
||||
>
|
||||
<sl-icon-button
|
||||
class="remove-button"
|
||||
name="trash"
|
||||
label="Remove Device"
|
||||
?disabled=${thisIsActiveIc}
|
||||
@click=${this._handleDeviceRemoveButton}
|
||||
></sl-icon-button>
|
||||
</sl-tooltip>
|
||||
</div>
|
||||
`;
|
||||
@@ -199,13 +251,14 @@ export class VMDeviceCard extends VMDeviceDBMixin(VMObjectMixin(BaseElement)) {
|
||||
"slots",
|
||||
html`
|
||||
<div class="flex flex-row flex-wrap">
|
||||
${repeat(this.slots,
|
||||
(slot, index) => slot.typ + index.toString(),
|
||||
(_slot, index) => html`
|
||||
${repeat(
|
||||
this.slots,
|
||||
(slot, index) => slot.typ + index.toString(),
|
||||
(_slot, index) => html`
|
||||
<vm-device-slot .deviceID=${this.objectID} .slotIndex=${index} class-"flex flex-row max-w-lg mr-2 mb-2">
|
||||
</vm-device-slot>
|
||||
`,
|
||||
)}
|
||||
)}
|
||||
</div>
|
||||
`,
|
||||
);
|
||||
@@ -219,15 +272,26 @@ export class VMDeviceCard extends VMDeviceDBMixin(VMObjectMixin(BaseElement)) {
|
||||
const vmNetworks = window.VM.vm.networks;
|
||||
const networks = this.connections.map((connection, index, _conns) => {
|
||||
const conn =
|
||||
typeof connection === "object" ? connection.CableNetwork : null;
|
||||
typeof connection === "object" && "CableNetwork" in connection
|
||||
? connection.CableNetwork
|
||||
: null;
|
||||
return html`
|
||||
<sl-select hoist placement="top" clearable key=${index} value=${conn?.net} ?disabled=${conn===null}
|
||||
@sl-change=${this._handleChangeConnection}>
|
||||
<sl-select
|
||||
hoist
|
||||
placement="top"
|
||||
clearable
|
||||
key=${index}
|
||||
value=${conn?.net}
|
||||
?disabled=${conn === null}
|
||||
@sl-change=${this._handleChangeConnection}
|
||||
>
|
||||
<span slot="prefix">Connection:${index} </span>
|
||||
${vmNetworks.map(
|
||||
(net) =>
|
||||
html`<sl-option value=${net.toString()}>Network ${net}</sl-option>`,
|
||||
)}
|
||||
(net) =>
|
||||
html`<sl-option value=${net.toString()}
|
||||
>Network ${net}</sl-option
|
||||
>`,
|
||||
)}
|
||||
<span slot="prefix"> ${conn?.typ} </span>
|
||||
</sl-select>
|
||||
`;
|
||||
@@ -243,7 +307,7 @@ export class VMDeviceCard extends VMDeviceDBMixin(VMObjectMixin(BaseElement)) {
|
||||
"pins",
|
||||
html`<div class="pins">
|
||||
<vm-device-pins .deviceID=${this.objectID}></vm-device-pins>
|
||||
</div>`
|
||||
</div>`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -295,7 +359,9 @@ export class VMDeviceCard extends VMDeviceDBMixin(VMObjectMixin(BaseElement)) {
|
||||
<sl-tab slot="nav" panel="slots">Slots</sl-tab>
|
||||
<sl-tab slot="nav" panel="reagents" disabled>Reagents</sl-tab>
|
||||
<sl-tab slot="nav" panel="networks">Networks</sl-tab>
|
||||
<sl-tab slot="nav" panel="pins" ?disabled=${!this.obj.pins}>Pins</sl-tab>
|
||||
<sl-tab slot="nav" panel="pins" ?disabled=${!this.numPins}
|
||||
>Pins</sl-tab
|
||||
>
|
||||
|
||||
<sl-tab-panel name="fields" active>
|
||||
${until(this.renderFields(), html`<sl-spinner></sl-spinner>`)}
|
||||
@@ -309,21 +375,37 @@ export class VMDeviceCard extends VMDeviceDBMixin(VMObjectMixin(BaseElement)) {
|
||||
<sl-tab-panel name="networks">
|
||||
${until(this.renderNetworks(), html`<sl-spinner></sl-spinner>`)}
|
||||
</sl-tab-panel>
|
||||
<sl-tab-panel name="pins">${until(this.renderPins(), html`<sl-spinner></sl-spinner>`)} </sl-tab-panel>
|
||||
<sl-tab-panel name="pins"
|
||||
>${until(this.renderPins(), html`<sl-spinner></sl-spinner>`)}
|
||||
</sl-tab-panel>
|
||||
</sl-tab-group>
|
||||
</ic10-details>
|
||||
<sl-dialog class="remove-device-dialog" no-header @sl-request-close=${this._preventOverlayClose}>
|
||||
<sl-dialog
|
||||
class="remove-device-dialog"
|
||||
no-header
|
||||
@sl-request-close=${this._preventOverlayClose}
|
||||
>
|
||||
<div class="remove-dialog-body">
|
||||
<img class="dialog-image mt-auto mb-auto me-2" src="img/stationpedia/${this.prefabName}.png"
|
||||
onerror="this.src = '${VMDeviceCard.transparentImg}'" />
|
||||
<img
|
||||
class="dialog-image mt-auto mb-auto me-2"
|
||||
src="img/stationpedia/${this.prefabName}.png"
|
||||
onerror="this.src = '${VMDeviceCard.transparentImg}'"
|
||||
/>
|
||||
<div class="flex-g">
|
||||
<p><strong>Are you sure you want to remove this device?</strong></p>
|
||||
<span>Id ${this.objectID} : ${this.name ?? this.prefabName}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div slot="footer">
|
||||
<sl-button variant="primary" autofocus @click=${this._closeRemoveDialog}>Close</sl-button>
|
||||
<sl-button variant="danger" @click=${this._removeDialogRemove}>Remove</sl-button>
|
||||
<sl-button
|
||||
variant="primary"
|
||||
autofocus
|
||||
@click=${this._closeRemoveDialog}
|
||||
>Close</sl-button
|
||||
>
|
||||
<sl-button variant="danger" @click=${this._removeDialogRemove}
|
||||
>Remove</sl-button
|
||||
>
|
||||
</div>
|
||||
</sl-dialog>
|
||||
`;
|
||||
@@ -387,5 +469,4 @@ export class VMDeviceCard extends VMDeviceDBMixin(VMObjectMixin(BaseElement)) {
|
||||
);
|
||||
this.updateDevice();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -151,11 +151,11 @@ export class VMDeviceList extends BaseElement {
|
||||
for (const device_id of this.devices) {
|
||||
const device = window.VM.vm.objects.get(device_id);
|
||||
if (device) {
|
||||
if (typeof device.name !== "undefined") {
|
||||
datapoints.push([device.name, device.id]);
|
||||
if (typeof device.obj_info.name !== "undefined") {
|
||||
datapoints.push([device.obj_info.name, device.obj_info.id]);
|
||||
}
|
||||
if (typeof device.prefabName !== "undefined") {
|
||||
datapoints.push([device.prefabName, device.id]);
|
||||
if (typeof device.obj_info.prefab !== "undefined") {
|
||||
datapoints.push([device.obj_info.prefab, device.obj_info.id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
import { html, css } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
import { BaseElement, defaultCss } from "components";
|
||||
import { VMDeviceDBMixin, VMObjectMixin } from "virtual_machine/base_device";
|
||||
import { VMTemplateDBMixin, VMObjectMixin } from "virtual_machine/base_device";
|
||||
import { displayNumber, parseNumber } from "utils";
|
||||
import type { LogicType } from "ic10emu_wasm";
|
||||
import SlInput from "@shoelace-style/shoelace/dist/components/input/input.component.js";
|
||||
|
||||
@customElement("vm-device-fields")
|
||||
export class VMDeviceSlot extends VMObjectMixin(VMDeviceDBMixin(BaseElement)) {
|
||||
export class VMDeviceSlot extends VMObjectMixin(VMTemplateDBMixin(BaseElement)) {
|
||||
constructor() {
|
||||
super();
|
||||
this.subscribe("fields");
|
||||
}
|
||||
|
||||
render() {
|
||||
const fields = Array.from(this.fields.entries());
|
||||
const fields = Array.from(this.logicFields.entries());
|
||||
const inputIdBase = `vmDeviceCard${this.objectID}Field`;
|
||||
return html`
|
||||
${fields.map(([name, field], _index, _fields) => {
|
||||
@@ -34,7 +34,7 @@ export class VMDeviceSlot extends VMObjectMixin(VMDeviceDBMixin(BaseElement)) {
|
||||
const val = parseNumber(input.value);
|
||||
window.VM.get().then((vm) => {
|
||||
if (!vm.setObjectField(this.objectID, field, val, true)) {
|
||||
input.value = this.fields.get(field).value.toString();
|
||||
input.value = this.logicFields.get(field).value.toString();
|
||||
}
|
||||
this.updateDevice();
|
||||
});
|
||||
|
||||
@@ -5,11 +5,11 @@ import "./add_device"
|
||||
import "./slot_add_dialog"
|
||||
import "./slot"
|
||||
|
||||
import { VmDeviceTemplate } from "./template";
|
||||
import { VmObjectTemplate } from "./template";
|
||||
import { VMDeviceCard } from "./card";
|
||||
import { VMDeviceList } from "./device_list";
|
||||
import { VMAddDeviceButton } from "./add_device";
|
||||
import { VMSlotAddDialog } from "./slot_add_dialog";
|
||||
|
||||
export { VMDeviceCard, VmDeviceTemplate, VMDeviceList, VMAddDeviceButton, VMSlotAddDialog };
|
||||
export { VMDeviceCard, VmObjectTemplate as VmDeviceTemplate, VMDeviceList, VMAddDeviceButton, VMSlotAddDialog };
|
||||
|
||||
|
||||
@@ -1,34 +1,42 @@
|
||||
|
||||
import { html, css } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
import { BaseElement, defaultCss } from "components";
|
||||
import { VMDeviceDBMixin, VMObjectMixin } from "virtual_machine/base_device";
|
||||
import { VMTemplateDBMixin, VMObjectMixin } from "virtual_machine/base_device";
|
||||
import SlSelect from "@shoelace-style/shoelace/dist/components/select/select.component.js";
|
||||
import { ObjectID } from "ic10emu_wasm";
|
||||
|
||||
@customElement("vm-device-pins")
|
||||
export class VMDevicePins extends VMObjectMixin(VMDeviceDBMixin(BaseElement)) {
|
||||
export class VMDevicePins extends VMObjectMixin(VMTemplateDBMixin(BaseElement)) {
|
||||
constructor() {
|
||||
super();
|
||||
this.subscribe("ic", "visible-devices");
|
||||
}
|
||||
|
||||
render() {
|
||||
const pins = this.pins;
|
||||
const visibleDevices = window.VM.vm.visibleDevices(this.objectID);
|
||||
const pins = new Array(this.numPins ?? 0)
|
||||
.fill(true)
|
||||
.map((_, index) => this.pins.get(index));
|
||||
const visibleDevices = (this.visibleDevices ?? []).map((id) => window.VM.vm.objects.get(id));
|
||||
const pinsHtml = pins?.map(
|
||||
(pin, index) =>
|
||||
html`
|
||||
<sl-select hoist placement="top" clearable key=${index} value=${pin} @sl-change=${this._handleChangePin}>
|
||||
<span slot="prefix">d${index}</span>
|
||||
${visibleDevices.map(
|
||||
(device, _index) =>
|
||||
html`
|
||||
<sl-option value=${device.id}>
|
||||
Device ${device.id} : ${device.name ?? device.prefabName}
|
||||
</sl-option>
|
||||
`,
|
||||
html` <sl-select
|
||||
hoist
|
||||
placement="top"
|
||||
clearable
|
||||
key=${index}
|
||||
value=${pin}
|
||||
@sl-change=${this._handleChangePin}
|
||||
>
|
||||
<span slot="prefix">d${index}</span>
|
||||
${visibleDevices.map(
|
||||
(device, _index) => html`
|
||||
<sl-option value=${device.obj_info.id.toString()}>
|
||||
Device ${device.obj_info.id} :
|
||||
${device.obj_info.name ?? device.obj_info.prefab}
|
||||
</sl-option>
|
||||
`,
|
||||
)}
|
||||
</sl-select>`,
|
||||
</sl-select>`,
|
||||
);
|
||||
return pinsHtml;
|
||||
}
|
||||
@@ -40,5 +48,4 @@ export class VMDevicePins extends VMObjectMixin(VMDeviceDBMixin(BaseElement)) {
|
||||
window.VM.get().then((vm) => vm.setDevicePin(this.objectID, pin, val));
|
||||
this.updateDevice();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
import { html, css } from "lit";
|
||||
import { customElement, property} from "lit/decorators.js";
|
||||
import { BaseElement, defaultCss } from "components";
|
||||
import { VMDeviceDBMixin, VMObjectMixin } from "virtual_machine/base_device";
|
||||
import { VMTemplateDBMixin, VMObjectMixin } from "virtual_machine/base_device";
|
||||
import {
|
||||
clamp,
|
||||
crc32,
|
||||
displayNumber,
|
||||
parseNumber,
|
||||
} from "utils";
|
||||
import {
|
||||
LogicField,
|
||||
LogicSlotType,
|
||||
SlotType,
|
||||
SlotInfo,
|
||||
Class as SlotType,
|
||||
TemplateDatabase,
|
||||
} from "ic10emu_wasm";
|
||||
import SlInput from "@shoelace-style/shoelace/dist/components/input/input.component.js";
|
||||
import { VMDeviceCard } from "./card";
|
||||
@@ -21,7 +25,7 @@ export interface SlotModifyEvent {
|
||||
}
|
||||
|
||||
@customElement("vm-device-slot")
|
||||
export class VMDeviceSlot extends VMObjectMixin(VMDeviceDBMixin(BaseElement)) {
|
||||
export class VMDeviceSlot extends VMObjectMixin(VMTemplateDBMixin(BaseElement)) {
|
||||
private _slotIndex: number;
|
||||
|
||||
get slotIndex() {
|
||||
@@ -72,8 +76,7 @@ export class VMDeviceSlot extends VMObjectMixin(VMDeviceDBMixin(BaseElement)) {
|
||||
slotOccupantImg(): string {
|
||||
const slot = this.slots[this.slotIndex];
|
||||
if (typeof slot.occupant !== "undefined") {
|
||||
const hashLookup = (this.templateDB ?? {}).names_by_hash ?? {};
|
||||
const prefabName = hashLookup[slot.occupant.prefab_hash] ?? "UnknownHash";
|
||||
const prefabName = slot.occupant.obj_info.prefab;
|
||||
return `img/stationpedia/${prefabName}.png`;
|
||||
} else {
|
||||
return `img/stationpedia/SlotIcon_${slot.typ}.png`;
|
||||
@@ -83,18 +86,16 @@ export class VMDeviceSlot extends VMObjectMixin(VMDeviceDBMixin(BaseElement)) {
|
||||
slotOccupantPrefabName(): string {
|
||||
const slot = this.slots[this.slotIndex];
|
||||
if (typeof slot.occupant !== "undefined") {
|
||||
const hashLookup = (this.templateDB ?? {}).names_by_hash ?? {};
|
||||
const prefabName = hashLookup[slot.occupant.prefab_hash] ?? "UnknownHash";
|
||||
const prefabName = slot.occupant.obj_info.prefab;
|
||||
return prefabName;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
slotOcccupantTemplate(): { name: string; typ: SlotType } | undefined {
|
||||
if (this.templateDB) {
|
||||
const entry = this.templateDB.db[this.prefabName];
|
||||
return entry?.slots[this.slotIndex];
|
||||
slotOcccupantTemplate(): SlotInfo | undefined {
|
||||
if ("slots" in this.obj.template) {
|
||||
return this.obj.template.slots[this.slotIndex];
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
@@ -139,10 +140,11 @@ export class VMDeviceSlot extends VMObjectMixin(VMDeviceDBMixin(BaseElement)) {
|
||||
class="absolute bottom-0 right-0 mr-1 mb-1 text-xs
|
||||
text-neutral-200/90 font-mono bg-neutral-500/40 rounded pl-1 pr-1"
|
||||
>
|
||||
<small
|
||||
>${slot.occupant.quantity}/${slot.occupant
|
||||
.max_quantity}</small
|
||||
>
|
||||
<small>
|
||||
${slot.quantity}/${"item" in slot.occupant.template
|
||||
? slot.occupant.template.item.max_quantity
|
||||
: 1}
|
||||
</small>
|
||||
</div>`,
|
||||
)}
|
||||
<div></div>
|
||||
@@ -170,13 +172,20 @@ export class VMDeviceSlot extends VMObjectMixin(VMDeviceDBMixin(BaseElement)) {
|
||||
? html` <sl-input
|
||||
type="number"
|
||||
size="small"
|
||||
.value=${slot.occupant.quantity.toString()}
|
||||
.value=${slot.quantity.toString()}
|
||||
.min=${1}
|
||||
.max=${slot.occupant.max_quantity}
|
||||
.max=${"item" in slot.occupant.template
|
||||
? slot.occupant.template.item.max_quantity
|
||||
: 1}
|
||||
@sl-change=${this._handleSlotQuantityChange}
|
||||
>
|
||||
<div slot="help-text">
|
||||
<span>Max Quantity: ${slot.occupant.max_quantity}</span>
|
||||
<span>
|
||||
Max Quantity:
|
||||
${"item" in slot.occupant.template
|
||||
? slot.occupant.template.item.max_quantity
|
||||
: 1}
|
||||
</span>
|
||||
</div>
|
||||
</sl-input>`
|
||||
: ""}
|
||||
@@ -218,7 +227,13 @@ export class VMDeviceSlot extends VMObjectMixin(VMDeviceDBMixin(BaseElement)) {
|
||||
_handleSlotQuantityChange(e: Event) {
|
||||
const input = e.currentTarget as SlInput;
|
||||
const slot = this.slots[this.slotIndex];
|
||||
const val = clamp(input.valueAsNumber, 1, slot.occupant.max_quantity);
|
||||
const val = clamp(
|
||||
input.valueAsNumber,
|
||||
1,
|
||||
"item" in slot.occupant.template
|
||||
? slot.occupant.template.item.max_quantity
|
||||
: 1,
|
||||
);
|
||||
if (
|
||||
!window.VM.vm.setObjectSlotField(
|
||||
this.objectID,
|
||||
@@ -228,15 +243,15 @@ export class VMDeviceSlot extends VMObjectMixin(VMDeviceDBMixin(BaseElement)) {
|
||||
true,
|
||||
)
|
||||
) {
|
||||
input.value = this.obj
|
||||
.getSlotField(this.slotIndex, "Quantity")
|
||||
.toString();
|
||||
input.value = this.slots[this.slotIndex].quantity.toString();
|
||||
}
|
||||
}
|
||||
|
||||
renderFields() {
|
||||
const inputIdBase = `vmDeviceSlot${this.objectID}Slot${this.slotIndex}Field`;
|
||||
const _fields = this.obj.getSlotFields(this.slotIndex);
|
||||
const _fields =
|
||||
this.slots[this.slotIndex].logicFields ??
|
||||
new Map<LogicSlotType, LogicField>();
|
||||
const fields = Array.from(_fields.entries());
|
||||
|
||||
return html`
|
||||
@@ -269,14 +284,23 @@ export class VMDeviceSlot extends VMObjectMixin(VMDeviceDBMixin(BaseElement)) {
|
||||
let val = parseNumber(input.value);
|
||||
if (field === "Quantity") {
|
||||
const slot = this.slots[this.slotIndex];
|
||||
val = clamp(input.valueAsNumber, 1, slot.occupant.max_quantity);
|
||||
val = clamp(
|
||||
input.valueAsNumber,
|
||||
1,
|
||||
"item" in slot.occupant.template
|
||||
? slot.occupant.template.item.max_quantity
|
||||
: 1,
|
||||
);
|
||||
}
|
||||
window.VM.get().then((vm) => {
|
||||
if (
|
||||
!vm.setObjectSlotField(this.objectID, this.slotIndex, field, val, true)
|
||||
) {
|
||||
input.value = this.obj
|
||||
.getSlotField(this.slotIndex, field)
|
||||
input.value = (
|
||||
this.slots[this.slotIndex].logicFields ??
|
||||
new Map<LogicSlotType, LogicField>()
|
||||
)
|
||||
.get(field)
|
||||
.toString();
|
||||
}
|
||||
this.updateDevice();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { html, css } from "lit";
|
||||
import { customElement, property, query, state } from "lit/decorators.js";
|
||||
import { BaseElement, defaultCss } from "components";
|
||||
import { VMDeviceDBMixin } from "virtual_machine/base_device";
|
||||
import { VMTemplateDBMixin } from "virtual_machine/base_device";
|
||||
import type { DeviceDB, DeviceDBEntry } from "virtual_machine/device_db";
|
||||
import SlInput from "@shoelace-style/shoelace/dist/components/input/input.component.js";
|
||||
import SlDialog from "@shoelace-style/shoelace/dist/components/dialog/dialog.component.js";
|
||||
@@ -11,7 +11,7 @@ import uFuzzy from "@leeoniya/ufuzzy";
|
||||
import { LogicField, LogicSlotType, SlotOccupantTemplate } from "ic10emu_wasm";
|
||||
|
||||
@customElement("vm-slot-add-dialog")
|
||||
export class VMSlotAddDialog extends VMDeviceDBMixin(BaseElement) {
|
||||
export class VMSlotAddDialog extends VMTemplateDBMixin(BaseElement) {
|
||||
static styles = [
|
||||
...defaultCss,
|
||||
css`
|
||||
|
||||
@@ -1,26 +1,23 @@
|
||||
import type {
|
||||
Connection,
|
||||
DeviceTemplate,
|
||||
ObjectTemplate,
|
||||
LogicField,
|
||||
LogicType,
|
||||
Slot,
|
||||
SlotTemplate,
|
||||
ConnectionCableNetwork,
|
||||
} from "ic10emu_wasm";
|
||||
import { html, css, HTMLTemplateResult } from "lit";
|
||||
import { customElement, property, query, state } from "lit/decorators.js";
|
||||
import { BaseElement, defaultCss } from "components";
|
||||
|
||||
import type { DeviceDB, DeviceDBEntry } from "virtual_machine/device_db";
|
||||
import { connectionFromDeviceDBConnection } from "./dbutils";
|
||||
import { displayNumber, parseNumber } from "utils";
|
||||
import { crc32, displayNumber, parseNumber } from "utils";
|
||||
import SlInput from "@shoelace-style/shoelace/dist/components/input/input.component.js";
|
||||
import SlSelect from "@shoelace-style/shoelace/dist/components/select/select.component.js";
|
||||
import { VMDeviceCard } from "./card";
|
||||
import { VMDeviceDBMixin } from "virtual_machine/base_device";
|
||||
import { VMTemplateDBMixin } from "virtual_machine/base_device";
|
||||
|
||||
@customElement("vm-device-template")
|
||||
export class VmDeviceTemplate extends VMDeviceDBMixin(BaseElement) {
|
||||
export class VmObjectTemplate extends VMTemplateDBMixin(BaseElement) {
|
||||
|
||||
static styles = [
|
||||
...defaultCss,
|
||||
@@ -56,14 +53,14 @@ export class VmDeviceTemplate extends VMDeviceDBMixin(BaseElement) {
|
||||
|
||||
@state() fields: { [key in LogicType]?: LogicField };
|
||||
@state() slots: SlotTemplate[];
|
||||
@state() template: DeviceTemplate;
|
||||
@state() template: ObjectTemplate;
|
||||
@state() device_id: number | undefined;
|
||||
@state() device_name: string | undefined;
|
||||
@state() connections: Connection[];
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.templateDB = window.VM.vm.db;
|
||||
this.templateDB = window.VM.vm.templateDB;
|
||||
}
|
||||
|
||||
private _prefab_name: string;
|
||||
@@ -78,27 +75,27 @@ export class VmDeviceTemplate extends VMDeviceDBMixin(BaseElement) {
|
||||
this.setupState();
|
||||
}
|
||||
|
||||
get dbDevice(): DeviceDBEntry {
|
||||
return this.templateDB.db[this.prefab_name];
|
||||
get dbTemplate(): ObjectTemplate {
|
||||
return this.templateDB.get( crc32(this.prefab_name));
|
||||
}
|
||||
|
||||
setupState() {
|
||||
|
||||
this.fields = Object.fromEntries(
|
||||
Object.entries(this.dbDevice?.logic ?? {}).map(([lt, ft]) => {
|
||||
const value = lt === "PrefabHash" ? this.dbDevice.hash : 0.0;
|
||||
Object.entries(this.dbTemplate?.logic ?? {}).map(([lt, ft]) => {
|
||||
const value = lt === "PrefabHash" ? this.dbTemplate.prefab.prefab_hash : 0.0;
|
||||
return [lt, { field_type: ft, value } as LogicField];
|
||||
}),
|
||||
);
|
||||
|
||||
this.slots = (this.dbDevice?.slots ?? []).map(
|
||||
this.slots = (this.dbTemplate?.slots ?? []).map(
|
||||
(slot, _index) =>
|
||||
({
|
||||
typ: slot.typ,
|
||||
}) as SlotTemplate,
|
||||
);
|
||||
|
||||
const connections = Object.entries(this.dbDevice?.conn ?? {}).map(
|
||||
const connections = Object.entries(this.dbTemplate?.conn ?? {}).map(
|
||||
([index, conn]) =>
|
||||
[index, connectionFromDeviceDBConnection(conn)] as const,
|
||||
);
|
||||
@@ -203,7 +200,7 @@ export class VmDeviceTemplate extends VMDeviceDBMixin(BaseElement) {
|
||||
}
|
||||
|
||||
render() {
|
||||
const device = this.dbDevice;
|
||||
const device = this.dbTemplate;
|
||||
return html`
|
||||
<sl-card class="template-card">
|
||||
<div class="header h-20 w-96" slot="header">
|
||||
|
||||
Reference in New Issue
Block a user