|
| 1 | +import { system} from "@minecraft/server"; |
| 2 | +const AsyncFunctionConstructor = (async function () { }).constructor; |
| 3 | +const GeneratorFunctionConstructor = (function* () { }).constructor; |
| 4 | +const AsyncGeneratorFunctionConstructor = (async function* () { }).constructor; |
| 5 | +const runInterval = system.runInterval.bind(system); |
| 6 | +const runTimeout = system.runTimeout.bind(system); |
| 7 | +const clearRun = system.clearRun.bind(system); |
| 8 | +const nativeFunction = "{\n [native code]\n}"; |
| 9 | +const safePrototypes = [ |
| 10 | + Object.prototype, |
| 11 | + Array.prototype, |
| 12 | + Map.prototype, |
| 13 | + Set.prototype, |
| 14 | + Function.prototype, |
| 15 | + AsyncFunctionConstructor.prototype, |
| 16 | + GeneratorFunctionConstructor.prototype, |
| 17 | + AsyncGeneratorFunctionConstructor.prototype |
| 18 | +]; |
| 19 | +const MinecraftModules = [ |
| 20 | + { module_name: "@minecraft/server", tag: "mc" }, |
| 21 | + { module_name: "@minecraft/server-ui", tag: "ui" }, |
| 22 | + { module_name: "@minecraft/server-gametest", tag: "gametest" }, |
| 23 | + { module_name: "@minecraft/server-net", tag: "net" }, |
| 24 | + { module_name: "@minecraft/server-admin", tag: "admin" }, |
| 25 | + { module_name: "@minecraft/server-editor", tag: "editor" }, |
| 26 | + { module_name: "@minecraft/server-editor-bindings", tag: "bindings" } |
| 27 | +]; |
| 28 | +var OutputType; |
| 29 | +(function (OutputType) { |
| 30 | + OutputType[OutputType["SyntaxError"] = 0] = "SyntaxError"; |
| 31 | + OutputType[OutputType["Error"] = 1] = "Error"; |
| 32 | + OutputType[OutputType["Successfull"] = 2] = "Successfull"; |
| 33 | +})(OutputType || (OutputType = {})); |
| 34 | +var LogTypes; |
| 35 | +(function (LogTypes) { |
| 36 | + LogTypes[LogTypes["log"] = 0] = "log"; |
| 37 | + LogTypes[LogTypes["error"] = 1] = "error"; |
| 38 | + LogTypes[LogTypes["warn"] = 2] = "warn"; |
| 39 | +})(LogTypes || (LogTypes = {})); |
| 40 | +const setInterval = (callBack, interval = 0, ...params) => runInterval(() => callBack(...params), interval); |
| 41 | +const setTimeout = (callBack, interval = 0, ...params) => runTimeout(() => callBack(...params), interval); |
| 42 | +function consoleLike(type, ...texts) { |
| 43 | + console.warn(`[Terminal-${LogTypes[type]}]: `, ...texts.map(a => getView[typeof a](ViewStyle.Short, a))); |
| 44 | +} |
| 45 | +function formatView(type, object) { |
| 46 | + return getView[typeof object](ViewStyle.Full, object); |
| 47 | +} |
| 48 | +export async function TerminalInput(source, message, o = consoleLike) { |
| 49 | + const a = await RunCode(message, true, { console: { log: o.bind(source, LogTypes.log), warn: o.bind(source, LogTypes.warn), error: o.bind(source, LogTypes.error) }, print: o.bind(source, LogTypes.log), self: source, setTimeout, setInterval, clearInterval: clearRun, clearTimeout: clearRun }); |
| 50 | + const multicommand = a.multicommand; |
| 51 | + if (a.syntaxError) |
| 52 | + return { type: OutputType.SyntaxError, value: a.syntaxError, formatView: formatView(OutputType.SyntaxError, a.syntaxError), multicommand }; |
| 53 | + try { |
| 54 | + const output = await a.promise; |
| 55 | + return { type: OutputType.Successfull, value: output, formatView: formatView(OutputType.Successfull, output), multicommand }; |
| 56 | + } |
| 57 | + catch (error) { |
| 58 | + console.warn("It was handled xd, but after the promise returns"); |
| 59 | + return { type: OutputType.Error, value: error, formatView: formatView(OutputType.Error, error), multicommand }; |
| 60 | + } |
| 61 | +} |
| 62 | +async function RunCode(code, useModules = true, ...scopes) { |
| 63 | + let func, output = { syntaxError: undefined, promise: undefined, multicommand: false }; |
| 64 | + const modules = useModules ? (await BuildAPIScope(...MinecraftModules)) : []; |
| 65 | + try { |
| 66 | + //@ts-ignore |
| 67 | + func = BuildNewFunction(this, code, ...modules, ...scopes); |
| 68 | + } |
| 69 | + catch (error) { |
| 70 | + output.syntaxError = error; |
| 71 | + return output; |
| 72 | + } |
| 73 | + output.multicommand = func.multicommand ?? false; |
| 74 | + output.promise = func(); |
| 75 | + return output; |
| 76 | +} |
| 77 | +async function BuildAPIScope(...modules) { |
| 78 | + let promises = []; |
| 79 | + modules.forEach(m => promises.push(import(m.module_name).catch(() => ({})))); |
| 80 | + const dlls = await Promise.all(promises); |
| 81 | + return dlls.map((m, i) => ({ [modules[i].tag]: m })); |
| 82 | +} |
| 83 | +function BuildNewFunction(thisArg = globalThis, code, ...scopes) { |
| 84 | + let scope = {}, func; |
| 85 | + for (const s of scopes) |
| 86 | + Object.assign(scope, s); |
| 87 | + let keys = Object.getOwnPropertyNames(scope); |
| 88 | + try { |
| 89 | + if (code.endsWith(";")) |
| 90 | + code = code.substring(0, code.length - 1); |
| 91 | + func = AsyncFunctionConstructor.apply(AsyncFunctionConstructor, [...keys, "return (" + code + ")"]); |
| 92 | + } |
| 93 | + catch (error) { |
| 94 | + func = AsyncFunctionConstructor.apply(AsyncFunctionConstructor, [...keys, code]); |
| 95 | + func.multicommand = true; |
| 96 | + } |
| 97 | + const a = Function.prototype.bind.apply(func, [thisArg, ...keys.map(k => scope[k])]); |
| 98 | + a.multicommand = !!func.multicommand; |
| 99 | + return a; |
| 100 | +} |
| 101 | +var ViewStyle; |
| 102 | +(function (ViewStyle) { |
| 103 | + ViewStyle[ViewStyle["Primitive"] = 0] = "Primitive"; |
| 104 | + ViewStyle[ViewStyle["Short"] = 1] = "Short"; |
| 105 | + ViewStyle[ViewStyle["Full"] = 2] = "Full"; |
| 106 | +})(ViewStyle || (ViewStyle = {})); |
| 107 | +const getView = { |
| 108 | + "object"(style, any) { |
| 109 | + if (any === null) |
| 110 | + return "§7§onull"; |
| 111 | + if (style === ViewStyle.Primitive) { |
| 112 | + const typeOf = getTypeOfObject(any); |
| 113 | + return `§7${(typeOf == "Object" || typeOf == '') ? "" : typeOf + " "}{...}`; |
| 114 | + } |
| 115 | + else if (style === ViewStyle.Short) { |
| 116 | + const names = Object.getOwnPropertyNames(any), symbols = Object.getOwnPropertySymbols(any); |
| 117 | + //@ts-ignore |
| 118 | + const keys = names.map(k => `§7${k}§r§7: ${getView[typeof any[k]](ViewStyle.Primitive, any[k])}§r`).concat(symbols.map(s => `§r${getView["symbol"](ViewStyle.Primitive, s)}§r§7: ${getView[typeof any[s]](ViewStyle.Primitive, any[s])}`)); |
| 119 | + const realKeys = keys.slice(0, 5), typeOf = getTypeOfObject(any); |
| 120 | + return `§7${(typeOf == "Object" || typeOf == '') ? "" : typeOf + " "}{${realKeys.join("§7, ")}${keys.length > 5 ? "§r§7, ..." : "§r§7"}}`; |
| 121 | + } |
| 122 | + else { |
| 123 | + return getView["object"](ViewStyle.Short, any) + "\n" + buildCompoudView([], any, any).join('\n'); |
| 124 | + } |
| 125 | + }, |
| 126 | + "function"(n, any) { |
| 127 | + if (n === ViewStyle.Short) { |
| 128 | + const n = any.toString() ?? "", ctor = Object.getPrototypeOf(any).constructor; |
| 129 | + if (n.startsWith('class')) { |
| 130 | + return `§5§oclass §r§3${any.name}`; |
| 131 | + } |
| 132 | + else { |
| 133 | + return `§5§o${(ctor == AsyncFunctionConstructor ? "async ƒ " : (ctor == GeneratorFunctionConstructor ? "ƒ * " : (ctor == AsyncGeneratorFunctionConstructor ? "async ƒ * " : "ƒ ")))}§r§g${any.name}§7(${(n.match(/(?<=(^[^\(]+\()|\()(.*)(?=(\)([ ]+|)\{([^]+|)\}$)|(\)(([ ]+|)(\=\>)([ ]+|))))/) ?? ["error"])[0].replace(/ +/g, " ")})`; |
| 134 | + } |
| 135 | + } |
| 136 | + else if (n === ViewStyle.Primitive) |
| 137 | + return "§5§oƒ§r"; |
| 138 | + else |
| 139 | + return getView["object"](ViewStyle.Short, any) + "\n" + buildCompoudView([], any, any, " ", true).join('\n'); |
| 140 | + }, |
| 141 | + "number"(n, any) { return `§3${any.toString()}§r`; }, |
| 142 | + "bigint"(n, any) { return `§3${any.toString()}§r`; }, |
| 143 | + "boolean"(n, any) { return `§3${any.toString()}§r`; }, |
| 144 | + "symbol"(n, any) { return `§7Symbol(${any.description})§r`; }, |
| 145 | + "undefined"() { return "§7§oundefined§r"; }, |
| 146 | + "string"(n, any) { |
| 147 | + if (n === ViewStyle.Full) |
| 148 | + return `§3"${any}"§r`; |
| 149 | + else if (n === ViewStyle.Short) |
| 150 | + return `§3"${any.split('\n')[0]}"§r`; |
| 151 | + else { |
| 152 | + const v = any.split('\n')[0]; |
| 153 | + return `§3"${v.length > 20 ? (v.substring(0, 20) + "...") : v}"§r`; |
| 154 | + } |
| 155 | + } |
| 156 | +}; |
| 157 | +function buildCompoudView(array, base, object, offSet = " ", func = false, deepth = 1) { |
| 158 | + const off = offSet.repeat(deepth); |
| 159 | + const prototype = Object.getPrototypeOf(object); |
| 160 | + const descriptors = Object.getOwnPropertyDescriptors(object); |
| 161 | + for (const key of [...Object.getOwnPropertyNames(descriptors), ...Object.getOwnPropertySymbols(descriptors)]) { |
| 162 | + const { value, set, get } = descriptors[key]; |
| 163 | + if (value) { |
| 164 | + array.push(`${off}§r${typeof key == "string" ? key : getView["symbol"](ViewStyle.Primitive, key)}§7: §r${getView[typeof value](ViewStyle.Short, value)}§r`); |
| 165 | + } |
| 166 | + else { |
| 167 | + if (get != undefined) { |
| 168 | + const v = get.call(base); |
| 169 | + array.push(`${off}§r§7get§r ${typeof key == "string" ? key : getView["symbol"](ViewStyle.Primitive, key)}§7: §r${getView[typeof v](ViewStyle.Short, v)}§r`); |
| 170 | + } |
| 171 | + if (set != undefined) |
| 172 | + array.push(`${off}§r§7set§r ${typeof key == "string" ? key : getView["symbol"](ViewStyle.Primitive, key)}§7: (...)§r`); |
| 173 | + } |
| 174 | + } |
| 175 | + if (func) |
| 176 | + array.push(`${off}§7[[Native Function]]: §7${getView["boolean"](ViewStyle.Primitive, object.toString().endsWith(nativeFunction))}§r`); |
| 177 | + if (prototype == null) |
| 178 | + return array; |
| 179 | + const typOf = getTypeOfObject(prototype); |
| 180 | + array.push(`${off}§7[[Prototype]]: ${(typOf == "" ? "Object" : typOf)}§r`); |
| 181 | + if (!safePrototypes.includes(prototype)) |
| 182 | + buildCompoudView(array, base, prototype, offSet, typeof prototype === 'function', deepth + 1); |
| 183 | + return array; |
| 184 | +} |
| 185 | +function getTypeOfObject(obj) { return (obj[Symbol.toStringTag] ?? ((typeof obj === "function" ? obj.name : undefined) ?? ((obj.constructor?.prototype == obj ? obj.constructor?.name : obj.__proto__?.constructor?.name) ?? ""))); } |
| 186 | +//@ts-ignore |
| 187 | +globalThis[Symbol.toStringTag] = 'GlobalThis'; |
| 188 | +//@ts-ignore |
| 189 | +globalThis.console[Symbol.toStringTag] = "Console"; |
0 commit comments