bit the bullet and make the ts move
(I want types sooo bad...)
This commit is contained in:
@@ -65,24 +65,50 @@ pub struct DeviceTemplate {
|
||||
pub logic: HashMap<grammar::LogicType, LogicField>,
|
||||
pub slots: Vec<SlotTemplate>,
|
||||
pub slotlogic: HashMap<grammar::LogicType, usize>,
|
||||
pub conn: HashMap<u32, Connection>,
|
||||
pub conn: Vec<(ConnectionType, ConnectionRole)>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum ConnectionType {
|
||||
Chute,
|
||||
Pipe,
|
||||
Power,
|
||||
PowerData,
|
||||
#[default]
|
||||
Data,
|
||||
Chute,
|
||||
Elevator,
|
||||
PipeLiquid,
|
||||
LandingPad,
|
||||
LaunchPad,
|
||||
PowerAndData,
|
||||
#[serde(other)]
|
||||
#[default]
|
||||
None,
|
||||
}
|
||||
|
||||
impl From<ConnectionType> for Connection {
|
||||
fn from(value: ConnectionType) -> Self {
|
||||
match value {
|
||||
ConnectionType::Chute | ConnectionType::Pipe | ConnectionType::Power => Self::Other,
|
||||
_ => Self::CableNetwork(None),
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum ConnectionRole {
|
||||
Input,
|
||||
Input2,
|
||||
Output,
|
||||
Output2,
|
||||
Waste,
|
||||
#[serde(other)]
|
||||
#[default]
|
||||
None,
|
||||
}
|
||||
|
||||
impl Connection {
|
||||
fn from(typ: ConnectionType, _role: ConnectionRole) -> Self {
|
||||
match typ {
|
||||
ConnectionType::None
|
||||
| ConnectionType::Chute
|
||||
| ConnectionType::Pipe
|
||||
| ConnectionType::Elevator
|
||||
| ConnectionType::LandingPad
|
||||
| ConnectionType::LaunchPad
|
||||
| ConnectionType::PipeLiquid => Self::Other,
|
||||
ConnectionType::Data | ConnectionType::Power | ConnectionType::PowerAndData => {
|
||||
Self::CableNetwork(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -145,7 +145,7 @@
|
||||
<a class="navbar-brand active" aria-current="page" href="">Stationeers IC10 Emulator</a>
|
||||
</div>
|
||||
<div class="nav navbar-nav ms-2">
|
||||
|
||||
|
||||
</div>
|
||||
<div class="nav navbar-nav ms-auto navbar-right d-flex flex-row">
|
||||
<a class="navbar-text mt-auto mb-auto align-self-center" href="https://github.com/ryex/ic10emu">View on Github
|
||||
@@ -192,7 +192,8 @@
|
||||
<div id="vmActiveIC" class="container ">
|
||||
<div class="ms-1 me-2 pb-2 row border border-secondary rounded bg-secondary bg-opacity-10">
|
||||
<div class="mt-2 col">
|
||||
<div id="vmControls" class="btn-group-vertical btn-group-sm " role="group" aria-label="Virtual Machine Controls">
|
||||
<div id="vmControls" class="btn-group-vertical btn-group-sm " role="group"
|
||||
aria-label="Virtual Machine Controls">
|
||||
<button id="vmControlRun" type="button" class="btn btn-primary">Run</button>
|
||||
<button id="vmControlStep" type="button" class="btn btn-secondary">Step</button>
|
||||
<button id="vmControlReset" type="button" class="btn btn-warning">Reset</button>
|
||||
@@ -217,6 +218,10 @@
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-2 p2">
|
||||
<button type="button" class="btn btn-outline-secondary">View Devices <span
|
||||
id="vmViewDeviceCount"></span></button>
|
||||
</div>
|
||||
<div class="row mt-2">
|
||||
<div class="accordion" id="vmActiveIC">
|
||||
<div class="accordion-item">
|
||||
@@ -249,9 +254,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -264,6 +266,18 @@
|
||||
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.32.7/ace.js" type="text/javascript" charset="utf-8"></script> -->
|
||||
<script>
|
||||
</script>
|
||||
|
||||
|
||||
<div class="offcanvas offcanvas-start" tabindex="-1" id="vmDevices" aria-labelledby="vmDevicesLabel"
|
||||
data-bs-scroll="true" data-bs-backdrop="false">
|
||||
<div class="offcanvas-header">
|
||||
<h5 class="offcanvas-title" id="vmDevicesLabel">Devices</h5>
|
||||
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body">
|
||||
<div class="p-2" id="vmDevicesOCBody"></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -57,17 +57,17 @@ class IC10Editor {
|
||||
|
||||
this.ui = new IC10EditorUI(this);
|
||||
|
||||
const self = this;
|
||||
const that = this;
|
||||
|
||||
App.session.onLoad((session) => {
|
||||
const updated_ids = [];
|
||||
for (const id in session.programs) {
|
||||
updated_ids.push(id);
|
||||
self.createOrSetSession(id, session.programs[id]);
|
||||
that.createOrSetSession(id, session.programs[id]);
|
||||
}
|
||||
for (const id in self.sessions) {
|
||||
for (const id in that.sessions) {
|
||||
if (!updated_ids.includes(id)) {
|
||||
self.destroySession(id);
|
||||
that.destroySession(id);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -77,17 +77,17 @@ class IC10Editor {
|
||||
for (const id in Object.keys(session.programs)) {
|
||||
const active_line = session.getActiveLine(id);
|
||||
if (typeof active_line !== "undefined") {
|
||||
const marker = self.active_line_markers[id];
|
||||
const marker = that.active_line_markers[id];
|
||||
if (marker) {
|
||||
self.sessions[id].removeMarker(marker);
|
||||
self.active_line_markers[id] = null;
|
||||
that.sessions[id].removeMarker(marker);
|
||||
that.active_line_markers[id] = null;
|
||||
}
|
||||
const session = self.sessions[id];
|
||||
const session = that.sessions[id];
|
||||
if (session) {
|
||||
self.active_line_markers[id] = session.addMarker(new Range(active_line, 0, active_line, 1), "vm_ic_active_line", "fullLine", true);
|
||||
if (self.active_session == id) {
|
||||
that.active_line_markers[id] = session.addMarker(new Range(active_line, 0, active_line, 1), "vm_ic_active_line", "fullLine", true);
|
||||
if (that.active_session == id) {
|
||||
// editor.resize(true);
|
||||
self.aceEditor.scrollToLine(active_line, true, true)
|
||||
that.aceEditor.scrollToLine(active_line, true, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,11 +5,11 @@ class IC10EditorUI {
|
||||
|
||||
constructor(ic10editor) {
|
||||
|
||||
const self = this;
|
||||
const that = this;
|
||||
|
||||
self.ic10editor = ic10editor;
|
||||
that.ic10editor = ic10editor;
|
||||
|
||||
self.ic10editor.aceEditor.commands.addCommand({
|
||||
that.ic10editor.aceEditor.commands.addCommand({
|
||||
name: "showSettingsMenu",
|
||||
description: "Show settings menu",
|
||||
bindKey: { win: "Ctrl-,", mac: "Command-," },
|
||||
@@ -21,50 +21,50 @@ class IC10EditorUI {
|
||||
|
||||
ace.config.loadModule("ace/ext/keyboard_menu", function (module) {
|
||||
console.log("keybinding_menu loaded");
|
||||
module.init(self.ic10editor.aceEditor);
|
||||
module.init(that.ic10editor.aceEditor);
|
||||
});
|
||||
|
||||
self.ic10editor.loadEditorSettings();
|
||||
self.displayEditorSettings();
|
||||
self.updateEditorSettings();
|
||||
self.reCalcEditorSize();
|
||||
window.addEventListener('resize', (e) => { self.reCalcEditorSize(); });
|
||||
that.ic10editor.loadEditorSettings();
|
||||
that.displayEditorSettings();
|
||||
that.updateEditorSettings();
|
||||
that.reCalcEditorSize();
|
||||
window.addEventListener('resize', (e) => { that.reCalcEditorSize(); });
|
||||
|
||||
document.getElementsByName("editorKeybindRadio").forEach((el) => {
|
||||
el.addEventListener('change', (e) => {
|
||||
self.ic10editor.settings.keyboard = e.target.value;
|
||||
self.ic10editor.saveEditorSettings();
|
||||
self.updateEditorSettings();
|
||||
that.ic10editor.settings.keyboard = e.target.value;
|
||||
that.ic10editor.saveEditorSettings();
|
||||
that.updateEditorSettings();
|
||||
});
|
||||
});
|
||||
|
||||
document.getElementsByName("editorCursorRadio").forEach((el) => {
|
||||
el.addEventListener('change', (e) => {
|
||||
self.ic10editor.settings.cursor = e.target.value;
|
||||
self.ic10editor.saveEditorSettings();
|
||||
self.updateEditorSettings();
|
||||
that.ic10editor.settings.cursor = e.target.value;
|
||||
that.ic10editor.saveEditorSettings();
|
||||
that.updateEditorSettings();
|
||||
});
|
||||
});
|
||||
document.getElementById("editorSettingsFontSize").addEventListener('change', (e) => {
|
||||
window.App.editorSettings.fontSize = e.target.value;
|
||||
self.ic10editor.saveEditorSettings();
|
||||
self.updateEditorSettings();
|
||||
that.ic10editor.saveEditorSettings();
|
||||
that.updateEditorSettings();
|
||||
});
|
||||
document.getElementById("editorSettingsRelativeLineNumbers").addEventListener('change', (e) => {
|
||||
window.App.editorSettings.relativeLineNumbers = e.target.checked;
|
||||
self.ic10editor.saveEditorSettings();
|
||||
self.updateEditorSettings();
|
||||
that.ic10editor.saveEditorSettings();
|
||||
that.updateEditorSettings();
|
||||
});
|
||||
|
||||
console.log(self.ic10editor.aceEditor.getOption('keyboardHandler'));
|
||||
console.log(that.ic10editor.aceEditor.getOption('keyboardHandler'));
|
||||
|
||||
self.ic10editor.aceEditor.setTheme("ace/theme/one_dark");
|
||||
that.ic10editor.aceEditor.setTheme("ace/theme/one_dark");
|
||||
ace.config.loadModule("ace/ext/statusbar", function (module) {
|
||||
const statusBar = new module.StatusBar(self.ic10editor.aceEditor, document.getElementById("statusBar"));
|
||||
statusBar.updateStatus(self.ic10editor.aceEditor);
|
||||
const statusBar = new module.StatusBar(that.ic10editor.aceEditor, document.getElementById("statusBar"));
|
||||
statusBar.updateStatus(that.ic10editor.aceEditor);
|
||||
});
|
||||
|
||||
self.ic10editor.aceEditor.setAutoScrollEditorIntoView(true);
|
||||
that.ic10editor.aceEditor.setAutoScrollEditorIntoView(true);
|
||||
|
||||
}
|
||||
|
||||
61
www/src/js/index.ts
Normal file
61
www/src/js/index.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import { IC10Editor, setupLspWorker } from "./editor";
|
||||
import { Session } from './session';
|
||||
import { VirtualMachine } from "./virtual_machine";
|
||||
import { docReady, openFile, saveFile } from "./utils";
|
||||
// import { makeRequest } from "./utils";
|
||||
|
||||
const App = {
|
||||
editor: null,
|
||||
vm: null,
|
||||
session: new Session()
|
||||
};
|
||||
|
||||
window.App = App;
|
||||
|
||||
// const dbPromise = makeRequest({ method: "GET", url: "/data/database.json"});
|
||||
const dbPromise = fetch("/data/database.json").then(resp => resp.json());
|
||||
|
||||
docReady(() => {
|
||||
|
||||
App.vm = new VirtualMachine();
|
||||
|
||||
dbPromise.then(db => App.vm.setupDeviceDatabase(db))
|
||||
|
||||
const init_session_id = App.vm.devices[0];
|
||||
|
||||
App.editor = new IC10Editor(init_session_id);
|
||||
|
||||
setupLspWorker().then((worker) => {
|
||||
App.editor.setupLsp(worker);
|
||||
})
|
||||
|
||||
|
||||
// Menu
|
||||
document.getElementById("mainMenuShare").addEventListener('click', (_event) => {
|
||||
const link = document.getElementById("shareLinkText");
|
||||
link.setAttribute('value', window.location);
|
||||
link.setSelectionRange(0, 0);
|
||||
}, { capture: true });
|
||||
document.getElementById("shareLinkCopyButton").addEventListener('click', (event) => {
|
||||
event.preventDefault();
|
||||
const link = document.getElementById("shareLinkText");
|
||||
link.select();
|
||||
link.setSelectionRange(0, 99999);
|
||||
navigator.clipboard.writeText(link.value);
|
||||
}, { capture: true });
|
||||
document.getElementById("mainMenuOpenFile").addEventListener('click', (_event) => {
|
||||
openFile(editor);
|
||||
}, { capture: true });
|
||||
document.getElementById("mainMenuSaveAs").addEventListener('click', (_event) => {
|
||||
saveFile(editor.getSession().getValue())
|
||||
|
||||
}, { capture: true });
|
||||
document.getElementById("mainMenuKeyboardShortcuts").addEventListener('click', (_event) => {
|
||||
App.editor.editor.execCommand("showKeyboardShortcuts");
|
||||
}, { capture: true });
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -63,17 +63,17 @@ j ra
|
||||
|
||||
class Session {
|
||||
constructor() {
|
||||
this._programs = {};
|
||||
this._programs = new Map();
|
||||
this._save_timeout = 0;
|
||||
this._onLoadCallbacks = [];
|
||||
this._activeSession = 0;
|
||||
this._activeLines = {};
|
||||
this._activeLines = new Map();
|
||||
this._onActiveLineCallbacks = [];
|
||||
this.loadFromFragment();
|
||||
|
||||
const self = this;
|
||||
const that = this;
|
||||
window.addEventListener('hashchange', (_event) => {
|
||||
self.loadFromFragment();
|
||||
that.loadFromFragment();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ class Session {
|
||||
}
|
||||
|
||||
set programs(programs) {
|
||||
Object.assign(this._programs, programs);
|
||||
this._programs = new Map([...programs]);
|
||||
}
|
||||
|
||||
get activeSession() {
|
||||
@@ -90,11 +90,11 @@ class Session {
|
||||
}
|
||||
|
||||
getActiveLine(id) {
|
||||
return this._activeLines[id];
|
||||
return this._activeLines.get(id);
|
||||
}
|
||||
|
||||
setActiveLine(id, line) {
|
||||
this._activeLines[id] = line;
|
||||
this._activeLines.set(id, line);
|
||||
this._fireOnActiveLine();
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ class Session {
|
||||
}
|
||||
|
||||
setProgramCode(id, code) {
|
||||
this._programs[id] = code;
|
||||
this._programs.set(id, code);
|
||||
this.save();
|
||||
}
|
||||
|
||||
@@ -112,8 +112,7 @@ class Session {
|
||||
}
|
||||
|
||||
_fireOnLoad() {
|
||||
for (const i in this._onLoadCallbacks) {
|
||||
const callback = this._onLoadCallbacks[i];
|
||||
for (const callback of this._onLoadCallbacks) {
|
||||
callback(this);
|
||||
}
|
||||
}
|
||||
@@ -123,8 +122,7 @@ class Session {
|
||||
}
|
||||
|
||||
_fireOnActiveLine() {
|
||||
for (const i in this._onActiveLineCallbacks) {
|
||||
const callback = this._onActiveLineCallbacks[i];
|
||||
for (const callback of this._onActiveLineCallbacks) {
|
||||
callback(this);
|
||||
}
|
||||
}
|
||||
@@ -141,7 +139,7 @@ class Session {
|
||||
}
|
||||
|
||||
async saveToFragment() {
|
||||
const toSave = { programs: this._programs };
|
||||
const toSave = { programs: Array.from(this._programs) };
|
||||
const bytes = new TextEncoder().encode(JSON.stringify(toSave));
|
||||
try {
|
||||
const c_bytes = await compress(bytes);
|
||||
@@ -157,7 +155,7 @@ class Session {
|
||||
async loadFromFragment() {
|
||||
const fragment = window.location.hash.slice(1);
|
||||
if (fragment === "demo") {
|
||||
this._programs = { 0: demoCode };
|
||||
this._programs = new Map([[0, demoCode]]);
|
||||
this._fireOnLoad();
|
||||
return;
|
||||
}
|
||||
@@ -168,12 +166,12 @@ class Session {
|
||||
const txt = new TextDecoder().decode(bytes);
|
||||
const data = getJson(txt);
|
||||
if (data === null) { // backwards compatible
|
||||
this._programs = { 0: txt };
|
||||
this._programs = new Map([[0, txt]]);
|
||||
this, this._fireOnLoad();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
this._programs = Object.assign({}, data.programs);
|
||||
this._programs = new Map(data.programs);
|
||||
this._fireOnLoad();
|
||||
return;
|
||||
} catch (e) {
|
||||
@@ -1,14 +1,3 @@
|
||||
import { IC10Editor, setupLspWorker } from "./editor";
|
||||
import { Session } from './session';
|
||||
import { VirtualMachine } from "./virtual_machine";
|
||||
|
||||
const App = {
|
||||
editor: null,
|
||||
vm: null,
|
||||
session: new Session()
|
||||
};
|
||||
|
||||
window.App = App;
|
||||
|
||||
|
||||
function docReady(fn) {
|
||||
@@ -20,44 +9,42 @@ function docReady(fn) {
|
||||
}
|
||||
}
|
||||
|
||||
docReady(() => {
|
||||
|
||||
App.vm = new VirtualMachine();
|
||||
|
||||
const init_session_id = App.vm.devices[0];
|
||||
|
||||
App.editor = new IC10Editor(init_session_id);
|
||||
|
||||
setupLspWorker().then((worker) => {
|
||||
App.editor.setupLsp(worker);
|
||||
})
|
||||
|
||||
|
||||
// Menu
|
||||
document.getElementById("mainMenuShare").addEventListener('click', (_event) => {
|
||||
const link = document.getElementById("shareLinkText");
|
||||
link.setAttribute('value', window.location);
|
||||
link.setSelectionRange(0, 0);
|
||||
}, { capture: true });
|
||||
document.getElementById("shareLinkCopyButton").addEventListener('click', (event) => {
|
||||
event.preventDefault();
|
||||
const link = document.getElementById("shareLinkText");
|
||||
link.select();
|
||||
link.setSelectionRange(0, 99999);
|
||||
navigator.clipboard.writeText(link.value);
|
||||
}, { capture: true });
|
||||
document.getElementById("mainMenuOpenFile").addEventListener('click', (_event) => {
|
||||
openFile(editor);
|
||||
}, { capture: true });
|
||||
document.getElementById("mainMenuSaveAs").addEventListener('click', (_event) => {
|
||||
saveFile(editor.getSession().getValue())
|
||||
|
||||
}, { capture: true });
|
||||
document.getElementById("mainMenuKeyboardShortcuts").addEventListener('click', (_event) => {
|
||||
App.editor.editor.execCommand("showKeyboardShortcuts");
|
||||
}, { capture: true });
|
||||
|
||||
});
|
||||
// probably not needed, fetch() exists now
|
||||
function makeRequest (opts) {
|
||||
const req = new Request()
|
||||
return new Promise(function (resolve, reject) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open(opts.method, opts.url);
|
||||
xhr.onload = function () {
|
||||
if (xhr.status >= 200 && xhr.status < 300) {
|
||||
resolve(xhr.response);
|
||||
} else {
|
||||
reject({
|
||||
status: xhr.status,
|
||||
statusText: xhr.statusText
|
||||
});
|
||||
}
|
||||
};
|
||||
xhr.onerror = function () {
|
||||
reject({
|
||||
status: xhr.status,
|
||||
statusText: xhr.statusText
|
||||
});
|
||||
};
|
||||
if (opts.headers) {
|
||||
Object.keys(opts.headers).forEach(function (key) {
|
||||
xhr.setRequestHeader(key, opts.headers[key]);
|
||||
});
|
||||
}
|
||||
var params = opts.params;
|
||||
if (params && typeof params === 'object') {
|
||||
params = Object.keys(params).map(function (key) {
|
||||
return encodeURIComponent(key) + '=' + encodeURIComponent(params[key]);
|
||||
}).join('&');
|
||||
}
|
||||
xhr.send(params);
|
||||
});
|
||||
}
|
||||
|
||||
async function saveFile(content) {
|
||||
const blob = new Blob([content], { type: "text/plain" });
|
||||
@@ -116,6 +103,4 @@ async function openFile(editor) {
|
||||
input.click();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
export { docReady, makeRequest, saveFile, openFile }
|
||||
44
www/src/js/virtual_machine/device.ts
Normal file
44
www/src/js/virtual_machine/device.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { Offcanvas } from 'bootstrap';
|
||||
|
||||
|
||||
class VMDeviceUI {
|
||||
|
||||
constructor(ui) {
|
||||
const that = this;
|
||||
that.ui = ui;
|
||||
this.root = document.createElement('div');
|
||||
this.canvasEl = document.getElementById('vmDevicesOCBody');
|
||||
this.deviceCountEl = document.getElementById('vmDViewDeviceCount');
|
||||
this.canvas = new Offcanvas(this.canvasEl)
|
||||
|
||||
}
|
||||
|
||||
update(active_ic) {
|
||||
const devices = window.VM.devices;
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class VMDeviceCard {
|
||||
constructor(deviceUI, device) {
|
||||
const that = this;
|
||||
this.deviceUI = deviceUI;
|
||||
this.device = device;
|
||||
this.root = document.createElement('div');
|
||||
this.root.classList.add("hstack", "gap-2");
|
||||
this.viewBtn = document.createElement('button');
|
||||
this.viewBtn.type = "button";
|
||||
this.viewBtn.classList.add("btn", "btn-secondary");
|
||||
const btnTxt = document.createTextNode(device.name)
|
||||
this.deviceUI.root.appendChild(this.root);
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.root.remove();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { VMDeviceUI }
|
||||
@@ -1,4 +1,5 @@
|
||||
import { init } from "ic10emu_wasm";
|
||||
import { VMDeviceUI } from "./device";
|
||||
// import { Card } from 'bootstrap';
|
||||
|
||||
class VirtualMachine {
|
||||
@@ -11,40 +12,76 @@ class VirtualMachine {
|
||||
this.ic10vm = vm;
|
||||
this.ui = new VirtualMachineUI(this);
|
||||
|
||||
this.ics = {}
|
||||
const ics = this.ic10vm.ics;
|
||||
for (const id of Object.keys(ics)) {
|
||||
this.ics[id] = this.ic10vm.getDevice(parseInt(id));
|
||||
}
|
||||
this.updateCode()
|
||||
this._devices = new Map();
|
||||
this._ics = new Map();
|
||||
|
||||
this.updateDevices();
|
||||
|
||||
this.updateCode()
|
||||
|
||||
}
|
||||
|
||||
get devices () {
|
||||
return this.ic10vm.devices;
|
||||
return this._devices;
|
||||
}
|
||||
|
||||
get ics () {
|
||||
return this._ics;
|
||||
}
|
||||
|
||||
get activeIC () {
|
||||
return this._ics.get(window.App.session.activeSession);
|
||||
}
|
||||
|
||||
updateDevices() {
|
||||
|
||||
const device_ids = this.ic10vm.devices;
|
||||
for (const id of device_ids) {
|
||||
if (!this._devices.has(id)){
|
||||
this._devices.set(id, this.ic10vm.getDevice(id));
|
||||
}
|
||||
}
|
||||
for(const id of this._devices) {
|
||||
if (!device_ids.includes(id)) {
|
||||
this._devices.delete(id);
|
||||
}
|
||||
}
|
||||
|
||||
const ics = this.ic10vm.ics;
|
||||
for (const id of ics) {
|
||||
if (!this._ics.has(id)){
|
||||
this._ics.set(id, this._devices.get(id));
|
||||
}
|
||||
}
|
||||
for(const id of this._ics) {
|
||||
if (!ics.includes(id)) {
|
||||
this._ics.delete(id);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
updateCode() {
|
||||
const progs = window.App.session.programs;
|
||||
for (const id of Object.keys(progs)) {
|
||||
const ic = this.ics[id];
|
||||
const attempt = Date.now().toString(16)
|
||||
const ic = this._ics.get(id);
|
||||
const prog = progs[id];
|
||||
if (ic && prog) {
|
||||
console.time(`CompileProgram_${id}`);
|
||||
console.time(`CompileProgram_${id}_${attempt}`);
|
||||
try {
|
||||
this.ics[id].setCode(progs[id]);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
console.timeEnd(`CompileProgram_${id}`);
|
||||
console.timeEnd(`CompileProgram_${id}_${attempt}`);
|
||||
}
|
||||
}
|
||||
this.update();
|
||||
}
|
||||
|
||||
step() {
|
||||
const ic = this.ics[window.App.session.activeSession];
|
||||
const ic = this.activeIC;
|
||||
if (ic) {
|
||||
try {
|
||||
ic.step();
|
||||
@@ -56,7 +93,7 @@ class VirtualMachine {
|
||||
}
|
||||
|
||||
run() {
|
||||
const ic = this.ics[window.App.session.activeSession];
|
||||
const ic = this.activeIC;
|
||||
if (ic) {
|
||||
try {
|
||||
ic.run(false);
|
||||
@@ -68,7 +105,7 @@ class VirtualMachine {
|
||||
}
|
||||
|
||||
reset() {
|
||||
const ic = this.ics[window.App.session.activeSession];
|
||||
const ic = this.activeIC;
|
||||
if (ic) {
|
||||
ic.reset();
|
||||
this.update();
|
||||
@@ -76,13 +113,14 @@ class VirtualMachine {
|
||||
}
|
||||
|
||||
update() {
|
||||
const ic = this.ics[window.App.session.activeSession];
|
||||
this.updateDevices();
|
||||
const ic = this.activeIC;
|
||||
window.App.session.setActiveLine(window.App.session.activeSession, ic.ip);
|
||||
this.ui.update(ic);
|
||||
}
|
||||
|
||||
setRegister(index, val) {
|
||||
const ic = this.ics[window.App.session.activeSession];
|
||||
const ic = this.activeIC;
|
||||
try {
|
||||
ic.setRegister(index, val);
|
||||
} catch (e) {
|
||||
@@ -91,13 +129,18 @@ class VirtualMachine {
|
||||
}
|
||||
|
||||
setStack(addr, val) {
|
||||
const ic = this.ics[window.App.session.activeSession];
|
||||
const ic = this.activeIC;
|
||||
try {
|
||||
ic.setStack(addr, val);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
setupDeviceDatabase(db) {
|
||||
this.db = db;
|
||||
console.log("Loaded Device Database", this.db);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -107,17 +150,18 @@ class VirtualMachineUI {
|
||||
this.state = new VMStateUI(this);
|
||||
this.registers = new VMRegistersUI(this);
|
||||
this.stack = new VMStackUI(this);
|
||||
this.devices = new VMDeviceUI(this);
|
||||
|
||||
const self = this;
|
||||
const that = this;
|
||||
|
||||
document.getElementById("vmControlRun").addEventListener('click', (_event) => {
|
||||
self.vm.run();
|
||||
that.vm.run();
|
||||
}, { capture: true });
|
||||
document.getElementById("vmControlStep").addEventListener('click', (_event) => {
|
||||
self.vm.step();
|
||||
that.vm.step();
|
||||
}, { capture: true });
|
||||
document.getElementById("vmControlReset").addEventListener('click', (_event) => {
|
||||
self.vm.reset();
|
||||
that.vm.reset();
|
||||
}, { capture: true });
|
||||
|
||||
}
|
||||
@@ -126,6 +170,7 @@ class VirtualMachineUI {
|
||||
this.state.update(ic);
|
||||
this.registers.update(ic);
|
||||
this.stack.update(ic);
|
||||
this.devices.update(ic);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -154,10 +199,10 @@ class VMRegistersUI {
|
||||
const regDom = document.getElementById("vmActiveRegisters");
|
||||
this.tbl = document.createElement("div");
|
||||
this.tbl.classList.add("d-flex", "flex-wrap", "justify-content-start", "align-items-end",);
|
||||
this.regCels = [];
|
||||
this.regCells = [];
|
||||
for (var i = 0; i < 18; i++) {
|
||||
const container = document.createElement("div");
|
||||
container.classList.add("vm_reg_cel", "align-self-stretch");
|
||||
container.classList.add("vm_reg_cel", "align-that-stretch");
|
||||
const cell = document.createElement("div");
|
||||
cell.classList.add("input-group", "input-group-sm")
|
||||
// cell.style.width = "30%";
|
||||
@@ -173,7 +218,7 @@ class VMRegistersUI {
|
||||
const aliasesLabel = document.createElement("span");
|
||||
aliasesLabel.classList.add("input-group-text", "reg_label")
|
||||
cell.appendChild(aliasesLabel);
|
||||
this.regCels.push({
|
||||
this.regCells.push({
|
||||
cell,
|
||||
nameLabel,
|
||||
aliasesLabel,
|
||||
@@ -182,7 +227,7 @@ class VMRegistersUI {
|
||||
container.appendChild(cell);
|
||||
this.tbl.appendChild(container);
|
||||
}
|
||||
this.regCels.forEach(cell => {
|
||||
this.regCells.forEach(cell => {
|
||||
cell.input.addEventListener('change', this.onCellUpdate);
|
||||
});
|
||||
this.default_aliases = { "sp": 16, "ra": 17 }
|
||||
@@ -206,12 +251,12 @@ class VMRegistersUI {
|
||||
}
|
||||
|
||||
update(ic) {
|
||||
const self = this;
|
||||
const that = this;
|
||||
if (ic) {
|
||||
const registers = ic.registers;
|
||||
if (registers) {
|
||||
for (var i = 0; i < registers.length; i++) {
|
||||
this.regCels[i].input.value = registers[i];
|
||||
this.regCells[i].input.value = registers[i];
|
||||
}
|
||||
}
|
||||
const aliases = ic.aliases;
|
||||
@@ -242,7 +287,7 @@ class VMRegistersUI {
|
||||
}
|
||||
|
||||
for(const [index, label] of Object.entries(labels)) {
|
||||
this.regCels[index].aliasesLabel.innerText = label.join(", ")
|
||||
this.regCells[index].aliasesLabel.innerText = label.join(", ")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -253,10 +298,10 @@ class VMStackUI {
|
||||
const stackDom = document.getElementById("vmActiveStack");
|
||||
this.tbl = document.createElement("div");
|
||||
this.tbl.classList.add("d-flex", "flex-wrap", "justify-content-start", "align-items-end",);
|
||||
this.stackCels = [];
|
||||
this.stackCells = [];
|
||||
for (var i = 0; i < 512; i++) {
|
||||
const container = document.createElement("div");
|
||||
container.classList.add("vm_stack_cel", "align-self-stretch");
|
||||
container.classList.add("vm_stack_cel", "align-that-stretch");
|
||||
const cell = document.createElement("div");
|
||||
cell.classList.add("input-group", "input-group-sm")
|
||||
const nameLabel = document.createElement("span");
|
||||
@@ -269,7 +314,7 @@ class VMStackUI {
|
||||
input.dataset.index = i;
|
||||
cell.appendChild(input);
|
||||
|
||||
this.stackCels.push({
|
||||
this.stackCells.push({
|
||||
cell,
|
||||
nameLabel,
|
||||
input,
|
||||
@@ -277,7 +322,7 @@ class VMStackUI {
|
||||
container.appendChild(cell);
|
||||
this.tbl.appendChild(container);
|
||||
}
|
||||
this.stackCels.forEach(cell => {
|
||||
this.stackCells.forEach(cell => {
|
||||
cell.input.addEventListener('change', this.onCellUpdate);
|
||||
});
|
||||
stackDom.appendChild(this.tbl);
|
||||
@@ -299,17 +344,17 @@ class VMStackUI {
|
||||
}
|
||||
|
||||
update(ic) {
|
||||
const self = this;
|
||||
const that = this;
|
||||
if (ic) {
|
||||
const stack = ic.stack;
|
||||
const sp = ic.registers[16];
|
||||
if (stack) {
|
||||
for (var i = 0; i < stack.length; i++) {
|
||||
this.stackCels[i].input.value = stack[i];
|
||||
this.stackCells[i].input.value = stack[i];
|
||||
if (i == sp) {
|
||||
this.stackCels[i].nameLabel.classList.add("stack_pointer");
|
||||
this.stackCells[i].nameLabel.classList.add("stack_pointer");
|
||||
} else {
|
||||
this.stackCels[i].nameLabel.classList.remove("stack_pointer");
|
||||
this.stackCells[i].nameLabel.classList.remove("stack_pointer");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ from collections import defaultdict
|
||||
import re
|
||||
import json
|
||||
|
||||
|
||||
def extract_all():
|
||||
items = {}
|
||||
pedia = {}
|
||||
@@ -19,15 +20,16 @@ def extract_all():
|
||||
"Title": _,
|
||||
"Description": desc,
|
||||
"PrefabName": name,
|
||||
"PrefabHash": hash,
|
||||
"PrefabHash": name_hash,
|
||||
"SlotInserts": slots,
|
||||
"LogicInsert": logic,
|
||||
"LogicSlotInsert": slotlogic,
|
||||
"ModeInsert": modes,
|
||||
"ConnectionInsert": connections,
|
||||
"ConnectionInsert": _,
|
||||
"ConnectionList": connections, # type: List[Tuple[str, str]]
|
||||
}:
|
||||
item["name"] = name
|
||||
item["hash"] = hash
|
||||
item["hash"] = name_hash
|
||||
item["desc"] = re.sub(linkPat, r"\1", desc)
|
||||
match slots:
|
||||
case []:
|
||||
@@ -47,7 +49,7 @@ def extract_all():
|
||||
item["logic"] = {}
|
||||
for lat in logic:
|
||||
item["logic"][re.sub(linkPat, r"\1", lat["LogicName"])] = (
|
||||
lat["LogicAccessTypes"]
|
||||
lat["LogicAccessTypes"].replace(" ", "")
|
||||
)
|
||||
|
||||
match slotlogic:
|
||||
@@ -75,10 +77,8 @@ def extract_all():
|
||||
item["conn"] = None
|
||||
case _:
|
||||
item["conn"] = {}
|
||||
for conn in connections:
|
||||
item["conn"][int(conn["LogicAccessTypes"])] = conn[
|
||||
"LogicName"
|
||||
]
|
||||
for index, [conn_typ, conn_role] in enumerate(connections):
|
||||
item["conn"][index] = [conn_typ, conn_role]
|
||||
|
||||
case _:
|
||||
print(f"NON-CONFORMING: ")
|
||||
@@ -91,21 +91,34 @@ def extract_all():
|
||||
slotlogicable = [
|
||||
item["name"] for item in items.values() if item["slotlogic"] is not None
|
||||
]
|
||||
|
||||
devices = [
|
||||
item["name"]
|
||||
for item in items.values()
|
||||
if item["logic"] is not None and item["conn"] is not None
|
||||
]
|
||||
|
||||
def clean_nones(value):
|
||||
if isinstance(value, list):
|
||||
return [clean_nones(x) for x in value if x is not None]
|
||||
elif isinstance(value, dict):
|
||||
return {
|
||||
key: clean_nones(val) for key, val in value.items() if val is not None
|
||||
}
|
||||
else:
|
||||
return value
|
||||
|
||||
with open("data/database.json", "w") as f:
|
||||
json.encoder
|
||||
json.dump(
|
||||
{
|
||||
"logic_enabled": logicable,
|
||||
"slot_logic_enabled": slotlogicable,
|
||||
"devices": devices,
|
||||
"items": items,
|
||||
},
|
||||
clean_nones(
|
||||
{
|
||||
"logic_enabled": logicable,
|
||||
"slot_logic_enabled": slotlogicable,
|
||||
"devices": devices,
|
||||
"items": items,
|
||||
}
|
||||
),
|
||||
f,
|
||||
)
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ module.exports = {
|
||||
mode: "development",
|
||||
devtool: "eval-source-map",
|
||||
plugins: [
|
||||
new CopyWebpackPlugin({ patterns: ['img/*.png', 'img/*/*.png'] }),
|
||||
new CopyWebpackPlugin({ patterns: ['img/*.png', 'img/*/*.png', { from: 'data/database.json', to: 'data' }] }),
|
||||
new HtmlWebpackPlugin({ template: './src/index.html' }),
|
||||
new miniCssExtractPlugin()
|
||||
],
|
||||
@@ -67,7 +67,7 @@ module.exports = {
|
||||
},],
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.tsx', '.ts', '.js'],
|
||||
extensions: ['.tsx', '.ts', '.js', '.json'],
|
||||
fallback: {
|
||||
"crypto": require.resolve("crypto-browserify"),
|
||||
"buffer": require.resolve("buffer"),
|
||||
@@ -79,8 +79,9 @@ module.exports = {
|
||||
asyncWebAssembly: true,
|
||||
syncWebAssembly: true,
|
||||
},
|
||||
// output: {
|
||||
// filename: 'bundle.js',
|
||||
// path: path.resolve(__dirname, 'dist'),
|
||||
// },
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
|
||||
clean: true,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -19,7 +19,7 @@ module.exports = {
|
||||
mode: "production",
|
||||
devtool: "source-map",
|
||||
plugins: [
|
||||
new CopyWebpackPlugin({ patterns: ['img/*.png', 'img/*/*.png'] }),
|
||||
new CopyWebpackPlugin({ patterns: ['img/*.png', 'img/*/*.png', { from: 'data/database.json', to: 'data' }] }),
|
||||
new HtmlWebpackPlugin({ template: './src/index.html' }),
|
||||
new miniCssExtractPlugin()
|
||||
],
|
||||
@@ -119,9 +119,10 @@ module.exports = {
|
||||
},
|
||||
})
|
||||
]
|
||||
}
|
||||
// output: {
|
||||
// filename: 'bundle.js',
|
||||
// path: path.resolve(__dirname, 'dist'),
|
||||
// },
|
||||
},
|
||||
output: {
|
||||
filename: 'bundle.js',
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
clean: true
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user