mirror of
https://github.com/damp11113-software/ccIDE.git
synced 2025-04-26 22:18:13 +00:00
update 1.6
support multiple upload to machine and make remote script to one file and support to run on startup
This commit is contained in:
parent
a5ac8c99c8
commit
5200e86f7d
2
.gitignore
vendored
2
.gitignore
vendored
@ -3,4 +3,4 @@ node_modules/
|
||||
package-lock.json
|
||||
dist/
|
||||
dist_debug/
|
||||
ccIDE.wheel
|
||||
ccIDE.wheel
|
||||
|
@ -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")
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ccide",
|
||||
"version": "1.5",
|
||||
"version": "1.6",
|
||||
"description": "ComputerCraft mod virtual lua IDE",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
30
readme.md
30
readme.md
@ -6,34 +6,18 @@ special thank for [ccblockly](https://github.com/Mirka1405/ccblockly) for idea
|
||||

|
||||
|
||||
# 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).
|
||||
|
48
remote.lua
48
remote.lua
@ -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")
|
241
src/ccRemote.js
241
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}`);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
126
src/codegen.js
126
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: <a href="https://github.com/DPSoftware-Foundation/ccIDE#install-remote-code-into-computercraft">Install Remote code into computercraft</a> in github. (Please press SHIFT or CTRL and click)`;
|
||||
return
|
||||
document.getElementById('upload-status').innerHTML = `Please Connect Computer to IDE.\nInstruction: <a href="https://github.com/DPSoftware-Foundation/ccIDE#install-remote-code-into-computercraft">Install Remote code into computercraft</a> 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
|
||||
|
@ -54,8 +54,8 @@
|
||||
<div id="blocklyDiv"></div>
|
||||
</section>
|
||||
|
||||
<div class="popup" id="upload-popup">
|
||||
<div class="popup-content">
|
||||
<div class="popup" id="upload-popup" style="overflow-y:hidden;">
|
||||
<div class="popup-content p-3" style="max-width: 720px; position: relative; margin-top: 100px;">
|
||||
<button type="button" class="btn-close float-end" aria-label="Close" id="uploadCloseBtn"></button>
|
||||
<div class="upload-progress-container" style="text-align: center;">
|
||||
<div class="progress-container">
|
||||
@ -73,7 +73,7 @@
|
||||
<svg viewBox="0 0 24 24"><path d="m20 22-3.86-1.55c.7-1.53 1.2-3.11 1.51-4.72L20 22M7.86 20.45 4 22l2.35-6.27c.31 1.61.81 3.19 1.51 4.72M12 2s5 2 5 10c0 3.1-.75 5.75-1.67 7.83A2 2 0 0 1 13.5 21h-3a2 2 0 0 1-1.83-1.17C7.76 17.75 7 15.1 7 12c0-8 5-10 5-10m0 10c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2z" /></svg>
|
||||
</div>
|
||||
</div>
|
||||
<p id="upload-status"></p>
|
||||
<div id="upload-status"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -132,7 +132,6 @@
|
||||
<img src="../assets/network-require.png" class="libimageicon" data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-title="Network Require">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="button-container">
|
||||
|
@ -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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
117
startup.lua
Normal file
117
startup.lua
Normal file
@ -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")
|
Loading…
x
Reference in New Issue
Block a user