From b13456c9c848a0eee187179356dc55540099f793 Mon Sep 17 00:00:00 2001 From: ChomeNS <95471003+ChomeNS@users.noreply.github.com> Date: Fri, 18 Aug 2023 08:58:54 +0700 Subject: [PATCH] use worker threads getPlayerList will temporailly not work for now because i am too lazy to fix the output thing --- index.js | 90 +++++++++++++++++--------------------------------------- vm.js | 76 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+), 63 deletions(-) create mode 100644 vm.js diff --git a/index.js b/index.js index 76b28fe..d203fc7 100644 --- a/index.js +++ b/index.js @@ -2,84 +2,48 @@ const { VM } = require('vm2') const { Server } = require('socket.io') const util = require('util') const { stylize } = require('./colors') -const randomstring = require('randomstring') -const ChatMessage = require('prismarine-chat')('1.20.1') -const mc = require('minecraft-protocol') -const moment = require('moment-timezone') -const crypto = require('crypto') -const nbt = require('prismarine-nbt') - -const BRIDGE_PREFIX = 'function:' +const { Worker } = require('worker_threads') +const path = require('path') const io = new Server(3069) io.on('connection', (socket) => { - let functions + let worker - let proxy + function reset () { + worker = new Worker(path.join(__dirname, 'vm.js')) - const handler = { - get (target, prop) { - if (!target[prop]) throw new Error(`Function "${prop}" not available`) + worker.on('message', (msg) => { + switch (msg.type) { + case 'socketEmit': + socket.emit(...msg.data) - return (...args) => target[prop](...args) - } - } + break + case 'socketOnce': + socket.once(...msg.data) - socket.on('setFunctions', (jsonArray) => { - const parsed = JSON.parse(jsonArray) - - functions = {} - - for (const eachFuntion of parsed) { - functions[eachFuntion] = (...args) => { - socket.emit(BRIDGE_PREFIX + eachFuntion, ...args) - - return new Promise((resolve) => { - socket.once(`functionOutput:${eachFuntion}`, (message, parseJSON) => { - if (parseJSON) resolve(JSON.parse(message)) - else resolve(message) - }) - }) - } - } - - proxy = new Proxy(functions, handler) - - resetVM() - }) - - let vm - function resetVM () { - vm = new VM({ - timeout: 3000, - sandbox: { - get bridge () { return proxy }, - randomstring, - ChatMessage, - mc, - moment, - crypto, - nbt + break } }) } - resetVM() + reset() - socket.on('runCode', (transactionId, code) => { - (async () => { - try { - const output = vm.run(code) - - socket.emit('codeOutput', transactionId, false, util.inspect(output, { stylize })) - } catch (e) { - socket.emit('codeOutput', transactionId, true, e.toString()) - } - })() + socket.on('setFunctions', (jsonArray) => { + worker.postMessage({ type: 'setFunctions', jsonArray }) }) - socket.on('reset', resetVM) + socket.on('runCode', (transactionId, code) => { + worker.postMessage({ type: 'runCode', code }) + + worker.on('message', ({ type, error, output }) => { + if (type !== 'codeOutput') return + + socket.emit('codeOutput', transactionId, error, output) + }) + }) + + socket.on('reset', reset) }) process.on('uncaughtException', (e) => { diff --git a/vm.js b/vm.js new file mode 100644 index 0000000..451c64f --- /dev/null +++ b/vm.js @@ -0,0 +1,76 @@ +const { parentPort } = require('worker_threads') +const { VM } = require('vm2') +const randomstring = require('randomstring') +const ChatMessage = require('prismarine-chat')('1.20.1') +const mc = require('minecraft-protocol') +const moment = require('moment-timezone') +const crypto = require('crypto') +const nbt = require('prismarine-nbt') +const util = require('util') +const { stylize } = require('./colors') + +const BRIDGE_PREFIX = 'function:' + +let proxy + +let vm + +const handler = { + get (target, prop) { + if (!target[prop]) throw new Error(`Function "${prop}" not available`) + + return (...args) => target[prop](...args) + } +} + +let functions + +parentPort.on('message', (msg) => { + switch (msg.type) { + case 'setFunctions': + const parsed = JSON.parse(msg.jsonArray) + + functions = {} + + for (const eachFuntion of parsed) { + functions[eachFuntion] = (...args) => { + parentPort.postMessage({ type: 'socketEmit', data: [BRIDGE_PREFIX + eachFuntion, ...args] }) + + // how do i make thjis work + // return new Promise((resolve) => { + // parentPort.postMessage({ type: 'socketOnce', data: [`functionOutput:${eachFuntion}`, (message, parseJSON) => { + // if (parseJSON) resolve(JSON.parse(message)) + // else resolve(message) + // }]}) + // }) + } + } + + proxy = new Proxy(functions, handler) + + vm = new VM({ + timeout: 100, + sandbox: { + get bridge () { return proxy }, + randomstring, + ChatMessage, + mc, + moment, + crypto, + nbt + } + }) + + break + case 'runCode': + try { + const output = vm.run(msg.code) + + parentPort.postMessage({ type: 'codeOutput', output: util.inspect(output, { stylize }), error: false }) + } catch (e) { + parentPort.postMessage({ type: 'codeOutput', output: e.toString(), error: true }) + } + + break + } +})