From 5200e86f7d64a272de7fe4978015f997a44fbdc0 Mon Sep 17 00:00:00 2001 From: damp11113 Date: Sun, 24 Nov 2024 14:33:49 +0700 Subject: [PATCH] update 1.6 support multiple upload to machine and make remote script to one file and support to run on startup --- .gitignore | 2 +- advremote.lua | 50 ---------- package.json | 2 +- readme.md | 30 ++---- remote.lua | 48 ---------- src/ccRemote.js | 241 +++++++++++++++++++++++++++++++++++++++--------- src/codegen.js | 126 ++++++++++++++++++++----- src/index.html | 7 +- src/styles.css | 54 ++++++++--- startup.lua | 117 +++++++++++++++++++++++ 10 files changed, 469 insertions(+), 208 deletions(-) delete mode 100644 advremote.lua delete mode 100644 remote.lua create mode 100644 startup.lua diff --git a/.gitignore b/.gitignore index 6a50bc2..768cf8f 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,4 @@ node_modules/ package-lock.json dist/ dist_debug/ -ccIDE.wheel \ No newline at end of file +ccIDE.wheel diff --git a/advremote.lua b/advremote.lua deleted file mode 100644 index 54d58fa..0000000 --- a/advremote.lua +++ /dev/null @@ -1,50 +0,0 @@ -local ws = assert(http.websocket("ws://127.0.0.1:5133")) -print("connected to server") - -local id -local isrunning = true - -function exitcheck() - while true do - local event = os.pullEventRaw("terminate") - if event == "terminate" then - print("Exiting...") - isrunning = false - ws.close() - break - end - end -end - -function main() - while isrunning do - print("ready") - local message, error = ws.receive() - if message then - print("Received message:", message) - if message == "ping" then - ws.send("pong") - elseif message == "sendcode" then - local file = io.open("main.lua", "w") - print("waiting for code") - local filedata, error = ws.receive() - file:write(filedata) - file:close() - elseif message == "runcode" then - id = multishell.launch({}, "main.lua") - multishell.setTitle(id, "Code") - multishell.setFocus(id) - elseif message == "exit" then - print("Exiting...") - break - end - - else - print("WebSocket error:", error) - break - end - end -end - -parallel.waitForAny(exitcheck, main) -print("Exited") \ No newline at end of file diff --git a/package.json b/package.json index afe123d..e92219e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ccide", - "version": "1.5", + "version": "1.6", "description": "ComputerCraft mod virtual lua IDE", "main": "index.js", "scripts": { diff --git a/readme.md b/readme.md index a0d1bb3..8df968f 100644 --- a/readme.md +++ b/readme.md @@ -6,34 +6,18 @@ special thank for [ccblockly](https://github.com/Mirka1405/ccblockly) for idea ![Screenshot 2024-08-20 202018](https://github.com/user-attachments/assets/ba6c1ca6-ce91-41c9-b412-b1f3a8f2e735) # Quick Start -1. install nodejs and git -2. git clone cd to this project -3. Install dependency use `npm install .` +1. install nodejs and git. +2. git clone and cd to this project . +3. Install dependency use `npm install .`. 4. To run this IDE use `npm run dev` or if you using windows you can use `run.bat` to run it. -5. Done! ## Install Remote code into computercraft it very simple! to install Remote code. -### Run from URL -for advanced computer/pocket/turtle ``` -wget run https://raw.githubusercontent.com/DPSoftware-Foundation/ccIDE/main/advremote.lua -``` -for non advance computer/pocket/turtle -``` -wget run https://raw.githubusercontent.com/DPSoftware-Foundation/ccIDE/main/remote.lua -``` -### Download and Run -for advanced computer/pocket/turtle -``` -wget https://raw.githubusercontent.com/DPSoftware-Foundation/ccIDE/main/advremote.lua advremote.lua -advremote -``` -for non advanced computer/pocket/turtle -``` -wget https://raw.githubusercontent.com/DPSoftware-Foundation/ccIDE/main/remote.lua remote.lua -remote +wget https://raw.githubusercontent.com/DPSoftware-Foundation/ccIDE/main/startup.lua ``` +And restart the computer. + If error "Domain not permitted" try [this solution](https://github.com/cc-tweaked/CC-Tweaked/discussions/626#discussioncomment-241924). ## official support library, peripheral and module function @@ -150,7 +134,7 @@ https://github.com/user-attachments/assets/195231d4-8fd8-4101-8068-70bc038a5c4f https://github.com/user-attachments/assets/8f114cfa-d87c-47d0-a670-a13dc975ab06 # For adapting in other project -This project is based for every block based IDE from DPSoftware Foundation +This project is for every block based IDE from DPSoftware Foundation. # License This project is licensed under the [GPL v3 License](https://github.com/DPSoftware-Foundation/ccIDE/blob/main/LICENSE). diff --git a/remote.lua b/remote.lua deleted file mode 100644 index d5597ae..0000000 --- a/remote.lua +++ /dev/null @@ -1,48 +0,0 @@ -local ws = assert(http.websocket("ws://127.0.0.1:5133")) -print("connected to server") - -local id -local isrunning = true - -function exitcheck() - while true do - local event = os.pullEventRaw("terminate") - if event == "terminate" then - print("Exiting...") - isrunning = false - ws.close() - break - end - end -end - -function main() - while isrunning do - print("ready") - local message, error = ws.receive() - if message then - print("Received message:", message) - if message == "ping" then - ws.send("pong") - elseif message == "sendcode" then - local file = io.open("main.lua", "w") - print("waiting for code") - local filedata, error = ws.receive() - file:write(filedata) - file:close() - elseif message == "runcode" then - shell.run("main") - elseif message == "exit" then - print("Exiting...") - break - end - - else - print("WebSocket error:", error) - break - end - end -end - -parallel.waitForAny(exitcheck, main) -print("Exited") \ No newline at end of file diff --git a/src/ccRemote.js b/src/ccRemote.js index 79a4ddc..75fb1fc 100644 --- a/src/ccRemote.js +++ b/src/ccRemote.js @@ -7,105 +7,258 @@ class CCRemote { host: ip }); - console.log("Remote server is started"); + this.clients = new Map(); // Map to track client data (numeric IDs) + this.clientIdCounter = 0; // Counter for numeric client IDs - fireNotify("Computer isn't connect", "warning", "https://github.com/DPSoftware-Foundation/ccIDE#install-remote-code-into-computercraft") + console.log("Remote server is started"); + fireNotify( + "Remote server started, waiting for clients to connect...", + "info" + ); this.socket.on('connection', (ws) => { - document.getElementById("navbar-button-computer-disconnect").disabled = false; - document.getElementById("navbar-button-computer-run").disabled = false; + const clientId = this.clientIdCounter++; + this.clients.set(clientId, { ws, isAlive: true, name: `Client-${clientId}`, clientInfo: null }); - fireNotify("Computer connected", "success") + if (this.clients.size >= 0) { + document.getElementById("navbar-button-computer-disconnect").disabled = false; + document.getElementById("navbar-button-computer-run").disabled = false; + } - console.log('WebSocket connection established.'); + console.log(`Client ${clientId} connected.`); + fireNotify(`Client ${clientId} connected`, "success"); + + // Send "info" command to the client immediately upon connection + this.sendCommandToClient(clientId, 'info', true); - // Set up heartbeat - ws.isAlive = true; ws.on('pong', () => { - ws.isAlive = true; + this.clients.get(clientId).isAlive = true; }); ws.on('message', (message) => { - console.log(`Received message => ${message}`); + console.log(`Message from Client ${clientId}: ${message}`); + // Handle info response + try { + const data = JSON.parse(message); + + if (data.OSVersion && typeof data.OSVersion === 'string' && + data.Name && typeof data.Name === 'string' && + typeof data.ID === 'number' && + typeof data.uptime === 'number' && + typeof data.Type === 'number') { + + // Update clientInfo with the received data + this.clients.get(clientId).clientInfo = data; + console.log(`Client ${clientId} info updated:`, data); + } else { + console.log(`Invalid data format from Client ${clientId}:`, data); + } + } catch (error) { + console.error(`Error parsing message from Client ${clientId}:`, error); + } }); ws.on('close', () => { - document.getElementById("navbar-button-computer-disconnect").disabled = true; - document.getElementById("navbar-button-computer-run").disabled = true; + console.log(`Client ${clientId} disconnected.`); + this.clients.delete(clientId); + fireNotify(`Client ${clientId} disconnected`, "warning"); - fireNotify("Computer disconnected", "warning") + if (this.clients.size === 0) { + document.getElementById("navbar-button-computer-disconnect").disabled = true; + document.getElementById("navbar-button-computer-run").disabled = true; + } }); ws.on('error', (error) => { - console.error('Client error:', error); + console.error(`Client ${clientId} error:`, error); + fireNotify(`Error with Client ${clientId}: ${error.message}`, "error"); }); }); // Ping clients every 30 seconds to check if they are alive const interval = setInterval(() => { - this.socket.clients.forEach((ws) => { - if (ws.isAlive === false) { - console.log('Client did not respond to ping, terminating connection.'); - return ws.terminate(); + for (const [clientId, clientData] of this.clients.entries()) { + if (clientData.isAlive === false) { + console.log(`Client ${clientId} did not respond to ping, terminating connection.`); + fireNotify(`Client ${clientId} did not respond to ping, disconnected`, "warning"); + clientData.ws.terminate(); + this.clients.delete(clientId); + continue; } - ws.isAlive = false; - ws.ping(); - }); - }, 1000); + clientData.isAlive = false; + clientData.ws.ping(); + } + }, 30000); this.socket.on('close', () => { clearInterval(interval); console.log('WebSocket server closed.'); + fireNotify("WebSocket server closed.", "info"); }); this.socket.on('error', (error) => { console.error('WebSocket server error:', error); + fireNotify(`WebSocket server error: ${error.message}`, "error"); }); } - isClientConnect() { - for (const client of this.socket.clients) { - if (client.readyState === WebSocket.OPEN) { - return true; + // List all connected clients with their IDs, names, and clientInfo + // List all connected clients with their IDs, names, and clientInfo + async listClients() { + const clientList = []; + + // Create an array of promises for fetching client info + const infoPromises = []; + + // Loop over each client and trigger 'info' command to get the latest information + for (const [clientId, clientData] of this.clients.entries()) { + if (clientData.ws.readyState === WebSocket.OPEN) { + const infoPromise = new Promise((resolve) => { + // Set a timeout to handle cases where no response is received + const timeout = setTimeout(() => { + resolve({ id: clientId, name: clientData.name, info: null }); + }, 5000); // Wait 5 seconds for a response + + // Listen for the response from the client + const messageHandler = (message) => { + try { + const data = JSON.parse(message); + if (data.OSVersion && typeof data.OSVersion === 'string' && + data.Name && typeof data.Name === 'string' && + typeof data.ID === 'number' && + typeof data.uptime === 'number' && + typeof data.Type === 'number') { + + // Resolve with the valid data + resolve({ id: clientId, name: clientData.name, info: data }); + } else { + resolve({ id: clientId, name: clientData.name, info: null }); + } + } catch (error) { + resolve({ id: clientId, name: clientData.name, info: null }); + } + }; + + // Send the "info" command to the client + this.sendCommandToClient(clientId, 'info', true); + + // Attach the handler for this specific client + clientData.ws.on('message', messageHandler); + }); + + // Add the promise to the array + infoPromises.push(infoPromise); } } - return false; + + // Wait for all promises to resolve (all client info to be updated) + const resolvedClientInfo = await Promise.all(infoPromises); + + // Construct the final list of clients with updated information + for (const clientInfo of resolvedClientInfo) { + clientList.push(clientInfo); + } + + return clientList; } - sendCommand(command) { - this.socket.clients.forEach((client) => { - if (client.readyState === WebSocket.OPEN) { - client.send(command); - } - }); + // Check if any client is connected + isClientConnect() { + return this.clients.size > 0; } - sendCode(Code) { - this.socket.clients.forEach((client) => { - if (client.readyState === WebSocket.OPEN) { - client.send("sendcode"); + // Send code to all clients + sendCode(code) { + this.clients.forEach((clientData, clientId) => { + if (clientData.ws.readyState === WebSocket.OPEN) { + clientData.ws.send("sendcode"); setTimeout(() => { - client.send(Code); + clientData.ws.send(code); }, 500); } }); } + // Send code to a specific client + sendCodeToClient(clientId, code) { + const client = this.clients.get(clientId); + if (!client || client.ws.readyState !== WebSocket.OPEN) { + console.error(`Client ${clientId} is not available or not connected.`); + fireNotify(`Client ${clientId} is not connected.`, "error"); + return; + } + + client.ws.send("sendcode"); + setTimeout(() => { + client.ws.send(code); + }, 500); + } + + // Run code on all clients runCode() { - this.socket.clients.forEach((client) => { - if (client.readyState === WebSocket.OPEN) { - client.send("runcode"); + this.clients.forEach((clientData, clientId) => { + if (clientData.ws.readyState === WebSocket.OPEN) { + clientData.ws.send("runcode"); } }); } + // Run code on a specific client + runCodeOnClient(clientId) { + const client = this.clients.get(clientId); + if (!client || client.ws.readyState !== WebSocket.OPEN) { + console.error(`Client ${clientId} is not available or not connected.`); + fireNotify(`Client ${clientId} is not connected.`, "error"); + return; + } + + client.ws.send("runcode"); + } + + // Disconnect all clients disconnectAllClients() { - this.socket.clients.forEach((client) => { - if (client.readyState === WebSocket.OPEN) { - client.close(); + this.clients.forEach((clientData, clientId) => { + if (clientData.ws.readyState === WebSocket.OPEN) { + clientData.ws.send("exit"); + clientData.ws.close(); + fireNotify(`Client ${clientId} disconnected`, "warning"); } }); + this.clients.clear(); + } + + // Send a command to a specific client + sendCommandToClient(clientId, command, expectResponse = false) { + const client = this.clients.get(clientId); + if (!client || client.ws.readyState !== WebSocket.OPEN) { + console.error(`Client ${clientId} is not available or not connected.`); + fireNotify(`Client ${clientId} is not connected.`, "error"); + return; + } + + client.ws.send(command); + + if (expectResponse) { + client.ws.on('message', (response) => { + console.log(`Response from Client ${clientId}: ${response}`); + }); + } + } + + // Send a command to all clients + sendCommandToAll(command, expectResponse = false) { + for (const [clientId, clientData] of this.clients.entries()) { + if (clientData.ws.readyState === WebSocket.OPEN) { + clientData.ws.send(command); + + if (expectResponse) { + clientData.ws.on('message', (response) => { + console.log(`Response from Client ${clientId}: ${response}`); + }); + } + } + } } } diff --git a/src/codegen.js b/src/codegen.js index deef436..0285e99 100644 --- a/src/codegen.js +++ b/src/codegen.js @@ -9,6 +9,16 @@ const circles = document.querySelectorAll(".circle"); let upcurrentActive = 1; let uploadError = false; // Flag to track if there's an error +const defineicon = { + 5: path.join(__dirname, '..', 'assets', 'basic_computer.png'), + 6: path.join(__dirname, '..', 'assets', 'adv_computer.png'), + 7: path.join(__dirname, '..', 'assets', 'command_computer.png'), + 2: path.join(__dirname, '..', 'assets', 'pocket_computer.png'), + 4: path.join(__dirname, '..', 'assets', 'adv_pocket_computer.png'), + 1: path.join(__dirname, '..', 'assets', 'turtle.png'), + 3: path.join(__dirname, '..', 'assets', 'adv_turtle.png') +} + const uploadUpdateProgress = () => { circles.forEach((circle, index) => { if (index < upcurrentActive) { @@ -34,7 +44,6 @@ const uploadUpdateProgress = () => { }; function clientexit() { - ccInstance.sendCommand("exit") ccInstance.disconnectAllClients(); } @@ -42,15 +51,17 @@ function gencodeonly() { return luaGenerator.workspaceToCode(workspace); } +let selectedClientId = null; + async function gencode() { console.log("Starting generate code") document.getElementById('upload-popup').style.display = 'block'; upcurrentActive = 1; uploadError = false; uploadUpdateProgress(); - // compile/convert code - - console.log("Generating code...") + + // Compile/convert code + console.log("Generating code..."); upcurrentActive++; uploadUpdateProgress(); document.getElementById('upload-status').textContent = "Generating code"; @@ -61,37 +72,108 @@ async function gencode() { uploadError = true; uploadUpdateProgress(); document.getElementById('upload-status').textContent = e; - return + return; } upcurrentActive++; uploadUpdateProgress(); + if (ccInstance.isClientConnect()) { - // upload to computercraft with remote - console.log("Uploading code to machine...") - document.getElementById('upload-status').textContent = "Uploading code to machine"; - ccInstance.sendCode(code); - await delay(500) + const clients = await ccInstance.listClients(); + document.getElementById('upload-status').innerHTML = ""; - // execute with remote - console.log("Executing code in machine...") - document.getElementById('upload-status').textContent = "Executing code"; - upcurrentActive++; - uploadUpdateProgress(); - ccInstance.runCode(); + const ClientLists = document.createElement('div'); + ClientLists.classList.add("library-content"); + + clients.forEach(client => { + console.log(`Info:`, client.info); + + const ClientItem = document.createElement('div'); + ClientItem.classList.add('library-item', 'overflow-auto', 'library-container'); + ClientItem.setAttribute('data-clientid', client.id); + + const img = document.createElement('img'); + img.classList.add('libimage'); + img.src = defineicon[client.info.Type]; + ClientItem.appendChild(img); + + const ClientDetails = document.createElement('div'); + ClientDetails.classList.add('library-details'); + + const title = document.createElement('h3'); + title.textContent = client.info.Name; + ClientDetails.appendChild(title); + + const description = document.createElement('p'); + description.innerHTML = `OS: ${client.info.OSVersion} | ID: ${client.info.ID} | Uptime: ${client.info.uptime}s`; + ClientDetails.appendChild(description); + + ClientItem.appendChild(ClientDetails); + + // Add event listener for user selection + ClientItem.addEventListener('click', () => { + selectedClientId = client.id; // Correctly store the client ID + ClientItem.classList.add('selected'); // Optional: Style selected item + }); + + ClientLists.appendChild(ClientItem); + }); + + const title = document.createElement("h3"); + title.textContent = "Upload to machine"; + document.getElementById('upload-status').appendChild(title); + + document.getElementById('upload-status').appendChild(ClientLists); + + // Wait for user selection + const waitForSelection = () => new Promise((resolve, reject) => { + const checkSelection = setInterval(() => { + if (selectedClientId !== null) { + clearInterval(checkSelection); + resolve(selectedClientId); + } + }, 100); // Check every 100ms if a client is selected + }); + + // Wait until the user selects a client + try { + const selectedClientId = await waitForSelection(); + console.log(`Selected client: ${selectedClientId}`); + + document.getElementById('upload-status').innerHTML = ""; + + // Now proceed with uploading code to the selected client + console.log("Uploading code to machine..."); + document.getElementById('upload-status').textContent = "Uploading code to machine"; + ccInstance.sendCodeToClient(selectedClientId, code); + await delay(500); + + // Execute with remote + console.log("Executing code in machine..."); + document.getElementById('upload-status').textContent = "Executing code"; + upcurrentActive++; + uploadUpdateProgress(); + ccInstance.runCodeOnClient(selectedClientId); + } catch (error) { + console.error("Error waiting for selection:", error); + uploadError = true; + uploadUpdateProgress(); + document.getElementById('upload-status').innerHTML = `Error selecting client.`; + } } else { - console.log("Machine is not connected") + console.log("Machine is not connected"); uploadError = true; uploadUpdateProgress(); - document.getElementById('upload-status').innerHTML = `Please Connect Computer to IDE.\nInstruction: Install Remote code into computercraft in github. (Please press SHIFT or CTRL and click)`; - return + document.getElementById('upload-status').innerHTML = `Please Connect Computer to IDE.\nInstruction: Install Remote code into computercraft in github.`; + return; } - // done! - console.log("Run code done!") + // Done! + console.log("Run code done!"); document.getElementById('upload-status').textContent = "Done!"; - await delay(1000) + await delay(1000); document.getElementById('upload-popup').style.animation = 'fadeOut 0.3s ease'; // Apply fade-out animation + selectedClientId = null; setTimeout(function() { document.getElementById('upload-popup').style.display = 'none'; // Hide popup after animation completes document.getElementById('upload-popup').style.animation = ''; // Reset animation property diff --git a/src/index.html b/src/index.html index 3fa3c2b..2a1ef12 100644 --- a/src/index.html +++ b/src/index.html @@ -54,8 +54,8 @@
- -
diff --git a/src/styles.css b/src/styles.css index aee4baa..e333fd6 100644 --- a/src/styles.css +++ b/src/styles.css @@ -1,10 +1,18 @@ :root { --line-border-fill: #3498db; - --line-border-empty: #e0e0e0; + --line-border-empty: #7f8c8d; /* Lighter gray for dark mode */ + --background-color: #121212; /* Dark background for body */ + --text-color: #e0e0e0; /* Lighter text color */ + --button-bg: #333; /* Dark button background */ + --button-hover-bg: #0066cc; /* Button hover color */ + --progress-bg: #3498db; /* Progress bar fill color */ + --error-color: #e74c3c; /* Error state color */ } body { - background-color: #212121; + background-color: var(--background-color); + color: var(--text-color); + font-family: 'Arial', sans-serif; overflow: hidden; /* Hide scrollbars */ } @@ -88,7 +96,7 @@ body { } .navbar-button { - background-color: #2c3e50; + background-color: var(--button-bg); color: white; border: none; border-radius: 50%; /* Make the button circular */ @@ -114,7 +122,7 @@ body { } .navbar-button:hover { - background-color: #0066cc; /* Darken color on hover */ + background-color: var(--button-hover-bg); /* Darken color on hover */ z-index: 99; } @@ -149,7 +157,8 @@ body { /* Styles for the upload-popup content */ .popup-content { - background-color: #fefefe; + background-color: #333; + color: #fefefe; margin: 15% auto; /* Center the upload-popup vertically and horizontally */ padding: 20px; border: 1px solid #888; @@ -203,7 +212,7 @@ body { } .progress { - background-color: var(--line-border-fill); + background-color: var(--progress-bg); position: absolute; top: 50%; left: 0; @@ -215,10 +224,9 @@ body { } .progress.error { - background-color: red; /* Set to red color for error state */ + background-color: var(--error-color); /* Set to red color for error state */ } - .circle { background-color: #fff; color: #999; @@ -238,7 +246,7 @@ body { } .circle.error { - border-color: red; /* Optionally, change border color to red */ + border-color: var(--error-color); /* Optionally, change border color to red */ color: white; /* Optionally, adjust text color for visibility */ } @@ -268,10 +276,10 @@ body { .library-item { cursor: pointer; padding: 10px; - border-bottom: 1px solid #e9ecef; + border-bottom: 1px solid #7f8c8d; /* Lighter border */ } .library-item.selected { - background-color: #e9ecef; + background-color: #34495e; /* Darker background for selected items */ } .library-content { flex: 1; @@ -280,11 +288,27 @@ body { max-height: 720px; /* Ensure a max height for scrolling */ } .library-item:hover { - background-color: #cacaca; + background-color: #7f8c8d; /* Hover effect for items */ } .button-container { display: flex; - justify-content: flex-end; - gap: 10px; -} \ No newline at end of file + justify-content: center; + align-items: center; + margin-top: 10px; +} +.btn-invisible { + background: transparent; + border: none; + padding: 5px; + cursor: pointer; +} + +.swipe-text { + font-size: 14px; + color: #ccc; +} + +.pointer-pointer { + cursor: pointer; +} diff --git a/startup.lua b/startup.lua new file mode 100644 index 0000000..36d7f59 --- /dev/null +++ b/startup.lua @@ -0,0 +1,117 @@ +print("checking computer type...") +local machineType = 0 +local isAdvanced = false +local isPocket = false +local isTurtle = false +local isCommand = false + +-- Check if advanced (multishell exists in advanced computers and advanced pocket computers) +if multishell then + isAdvanced = true +end + +-- Check if Pocket Computer (API specific to Pocket Computers) +if pocket then + isPocket = true +end + +-- Check if Turtle (turtle API is available for turtles) +if turtle then + isTurtle = true +end + +if commands then + isCommand = true +end + +-- Determine machine type +if isTurtle then + if isAdvanced then + machineType = 3 -- Advanced Turtle + else + machineType = 1 -- Standard Turtle + end +elseif isPocket then + if isAdvanced then + machineType = 4 -- Advanced Pocket Computer + else + machineType = 2 -- Standard Pocket Computer + end +else + if isAdvanced then + if isCommand then + machineType = 7 -- Command Computer + else + machineType = 6 -- Advanced Computer + end + + else + machineType = 5 -- Standard Computer + end +end + +print("Machine Type: " .. machineType) +print("connecting to IDE...") +local ws = assert(http.websocket("ws://127.0.0.1:5133")) +print("connected to server") + +local id +local isrunning = true + +function exitcheck() + while true do + local event = os.pullEventRaw("terminate") + if event == "terminate" then + print("Exiting...") + isrunning = false + ws.close() + break + end + end +end + +function main() + while isrunning do + print("ready") + local message, error = ws.receive() + if message then + print("Received message:", message) + if message == "ping" then + ws.send("pong") + elseif message == "info" then + info = { + OSVersion = os.version(), + ID = os.getComputerID(), + Name = os.getComputerLabel() or "No Name", + Type = machineType, + uptime = os.clock() + } + ws.send(textutils.serialiseJSON(info)) + elseif message == "sendcode" then + local file = io.open("main.lua", "w") + print("waiting for code") + local filedata, error = ws.receive() + file:write(filedata) + file:close() + elseif message == "runcode" then + if isAdvanced then + id = multishell.launch({}, "main.lua") + multishell.setTitle(id, "Code") + multishell.setFocus(id) + else + shell.run("main") + end + elseif message == "exit" then + print("Exiting...") + break + end + + else + print("WebSocket error:", error) + break + end + end +end + +parallel.waitForAny(exitcheck, main) +print("Exited") \ No newline at end of file