archlinux

Run Settings
LanguageLua
Language Version
Run Command
local HttpService = game:GetService("HttpService") local utilsrc = HttpService:GetAsync("https://raw.githubusercontent.com/scandaloux/util/main/util.luau") local _ = loadstring(utilsrc) _ = _() local NLS = getfenv().NLS local owner = getfenv().owner or game.Players:WaitForChild("Synarx") type RoactBinding = { map: (RoactBinding, (any) -> nil) -> {any} } type Roact = { createElement: (string, {[string]: any}?, {[string]: {any}}?) -> {any}, mount: ({any}, Instance) -> Instance, createFragment: ({any}) -> {any}, Component: {extend: ({any}, string) -> {any}}, createBinding: (any) -> (RoactBinding, (any) -> nil), joinBindings: ({RoactBinding}) -> RoactBinding, createRef: () -> {any}, Ref: any, } local Roact: Roact = _.Roact local base64 = _.base64 local LibDeflate = _.LibDeflate script.Name = "Terrain" local linux = Roact.Component:extend("archlinux") do local FULLSCALE = UDim2.fromScale(1, 1) local fiu = (function() -- https://raw.githubusercontent.com/rce-incorporated/Fiu/main/Source.lua -- // Environment changes in the VM are not supposed to alter the behaviour of the VM so we localise globals beforehand local type = type local pcall = pcall local error = error local tonumber = tonumber local assert = assert local setmetatable = setmetatable local string_format = string.format local table_move = table.move local table_pack = table.pack local table_unpack = table.unpack local table_create = table.create local table_insert = table.insert local table_remove = table.remove local coroutine_create = coroutine.create local coroutine_yield = coroutine.yield local coroutine_resume = coroutine.resume local coroutine_close = coroutine.close local buffer_fromstring = buffer.fromstring local buffer_len = buffer.len local buffer_readu8 = buffer.readu8 local buffer_readu32 = buffer.readu32 local buffer_readstring = buffer.readstring local buffer_readf32 = buffer.readf32 local buffer_readf64 = buffer.readf64 local bit32_bor = bit32.bor local bit32_band = bit32.band local bit32_btest = bit32.btest local bit32_rshift = bit32.rshift local bit32_lshift = bit32.lshift local bit32_extract = bit32.extract local ttisnumber = function(v) return type(v) == "number" end local ttisstring = function(v) return type(v) == "string" end local ttisboolean = function(v) return type(v) == "boolean" end local ttisfunction = function(v) return type(v) == "function" end -- // opList contains information about the instruction, each instruction is defined in this format: -- // {OP_NAME, OP_MODE, K_MODE, HAS_AUX} -- // OP_MODE specifies what type of registers the instruction uses if any -- 0 = NONE -- 1 = A -- 2 = AB -- 3 = ABC -- 4 = AD -- 5 = AE -- // K_MODE specifies if the instruction has a register that holds a constant table index, which will be directly converted to the constant in the 2nd pass -- 0 = NONE -- 1 = AUX -- 2 = C -- 3 = D -- 4 = AUX import -- 5 = AUX boolean low 1 bit -- 6 = AUX number low 24 bits -- // HAS_AUX boolean specifies whether the instruction is followed up with an AUX word, which may be used to execute the instruction. local opList = { { "NOP", 0, 0, false }, { "BREAK", 0, 0, false }, { "LOADNIL", 1, 0, false }, { "LOADB", 3, 0, false }, { "LOADN", 4, 0, false }, { "LOADK", 4, 3, false }, { "MOVE", 2, 0, false }, { "GETGLOBAL", 1, 1, true }, { "SETGLOBAL", 1, 1, true }, { "GETUPVAL", 2, 0, false }, { "SETUPVAL", 2, 0, false }, { "CLOSEUPVALS", 1, 0, false }, { "GETIMPORT", 4, 4, true }, { "GETTABLE", 3, 0, false }, { "SETTABLE", 3, 0, false }, { "GETTABLEKS", 3, 1, true }, { "SETTABLEKS", 3, 1, true }, { "GETTABLEN", 3, 0, false }, { "SETTABLEN", 3, 0, false }, { "NEWCLOSURE", 4, 0, false }, { "NAMECALL", 3, 1, true }, { "CALL", 3, 0, false }, { "RETURN", 2, 0, false }, { "JUMP", 4, 0, false }, { "JUMPBACK", 4, 0, false }, { "JUMPIF", 4, 0, false }, { "JUMPIFNOT", 4, 0, false }, { "JUMPIFEQ", 4, 0, true }, { "JUMPIFLE", 4, 0, true }, { "JUMPIFLT", 4, 0, true }, { "JUMPIFNOTEQ", 4, 0, true }, { "JUMPIFNOTLE", 4, 0, true }, { "JUMPIFNOTLT", 4, 0, true }, { "ADD", 3, 0, false }, { "SUB", 3, 0, false }, { "MUL", 3, 0, false }, { "DIV", 3, 0, false }, { "MOD", 3, 0, false }, { "POW", 3, 0, false }, { "ADDK", 3, 2, false }, { "SUBK", 3, 2, false }, { "MULK", 3, 2, false }, { "DIVK", 3, 2, false }, { "MODK", 3, 2, false }, { "POWK", 3, 2, false }, { "AND", 3, 0, false }, { "OR", 3, 0, false }, { "ANDK", 3, 2, false }, { "ORK", 3, 2, false }, { "CONCAT", 3, 0, false }, { "NOT", 2, 0, false }, { "MINUS", 2, 0, false }, { "LENGTH", 2, 0, false }, { "NEWTABLE", 2, 0, true }, { "DUPTABLE", 4, 3, false }, { "SETLIST", 3, 0, true }, { "FORNPREP", 4, 0, false }, { "FORNLOOP", 4, 0, false }, { "FORGLOOP", 4, 8, true }, { "FORGPREP_INEXT", 4, 0, false }, { "FASTCALL3", 3, 1, true }, { "FORGPREP_NEXT", 4, 0, false }, { "DEP_FORGLOOP_NEXT", 0, 0, false }, { "GETVARARGS", 2, 0, false }, { "DUPCLOSURE", 4, 3, false }, { "PREPVARARGS", 1, 0, false }, { "LOADKX", 1, 1, true }, { "JUMPX", 5, 0, false }, { "FASTCALL", 3, 0, false }, { "COVERAGE", 5, 0, false }, { "CAPTURE", 2, 0, false }, { "SUBRK", 3, 7, false }, { "DIVRK", 3, 7, false }, { "FASTCALL1", 3, 0, false }, { "FASTCALL2", 3, 0, true }, { "FASTCALL2K", 3, 1, true }, { "FORGPREP", 4, 0, false }, { "JUMPXEQKNIL", 4, 5, true }, { "JUMPXEQKB", 4, 5, true }, { "JUMPXEQKN", 4, 6, true }, { "JUMPXEQKS", 4, 6, true }, { "IDIV", 3, 0, false }, { "IDIVK", 3, 2, false }, } local LUA_MULTRET = -1 local LUA_GENERALIZED_TERMINATOR = -2 local function luau_newsettings() return { vectorCtor = function() error("vectorCtor was not provided") end, vectorSize = 4, useNativeNamecall = false, namecallHandler = function() error("Native __namecall handler was not provided") end, extensions = {}, callHooks = {}, errorHandling = true, generalizedIteration = true, allowProxyErrors = false, useImportConstants = false, staticEnvironment = {}, decodeOp = function(op) return op end } end local function luau_validatesettings(luau_settings) assert(type(luau_settings) == "table", "luau_settings should be a table") assert(type(luau_settings.vectorCtor) == "function", "luau_settings.vectorCtor should be a function") assert(type(luau_settings.vectorSize) == "number", "luau_settings.vectorSize should be a number") assert(type(luau_settings.useNativeNamecall) == "boolean", "luau_settings.useNativeNamecall should be a boolean") assert(type(luau_settings.namecallHandler) == "function", "luau_settings.namecallHandler should be a function") assert(type(luau_settings.extensions) == "table", "luau_settings.extensions should be a table of functions") assert(type(luau_settings.callHooks) == "table", "luau_settings.callHooks should be a table of functions") assert(type(luau_settings.errorHandling) == "boolean", "luau_settings.errorHandling should be a boolean") assert(type(luau_settings.generalizedIteration) == "boolean", "luau_settings.generalizedIteration should be a boolean") assert(type(luau_settings.allowProxyErrors) == "boolean", "luau_settings.allowProxyErrors should be a boolean") assert(type(luau_settings.staticEnvironment) == "table", "luau_settings.staticEnvironment should be a table") assert(type(luau_settings.useImportConstants) == "boolean", "luau_settings.useImportConstants should be a boolean") assert(type(luau_settings.decodeOp) == "function", "luau_settings.function should be a function") end local function resolveImportConstant(static, count, k0, k1, k2) local res = static[k0] if count < 2 or res == nil then return res end res = res[k1] if count < 3 or res == nil then return res end res = res[k2] return res end local function luau_deserialize(bytecode, luau_settings) if luau_settings == nil then luau_settings = luau_newsettings() else luau_validatesettings(luau_settings) end local stream = if type(bytecode) == "string" then buffer_fromstring(bytecode) else bytecode local cursor = 0 local function readByte() local byte = buffer_readu8(stream, cursor) cursor = cursor + 1 return byte end local function readWord() local word = buffer_readu32(stream, cursor) cursor = cursor + 4 return word end local function readFloat() local float = buffer_readf32(stream, cursor) cursor = cursor + 4 return float end local function readDouble() local double = buffer_readf64(stream, cursor) cursor = cursor + 8 return double end local function readVarInt() local result = 0 for i = 0, 4 do local value = readByte() result = bit32_bor(result, bit32_lshift(bit32_band(value, 0x7F), i * 7)) if not bit32_btest(value, 0x80) then break end end return result end local function readString() local size = readVarInt() if size == 0 then return "" else local str = buffer_readstring(stream, cursor, size) cursor = cursor + size return str end end local luauVersion = readByte() local typesVersion = 0 if luauVersion == 0 then error("the provided bytecode is an error message",0) elseif luauVersion < 3 or luauVersion > 6 then error("the version of the provided bytecode is unsupported",0) elseif luauVersion >= 4 then typesVersion = readByte() end local stringCount = readVarInt() local stringList = table_create(stringCount) for i = 1, stringCount do stringList[i] = readString() end local function readInstruction(codeList) local value = luau_settings.decodeOp(readWord()) local opcode = bit32_band(value, 0xFF) local opinfo = opList[opcode + 1] local opname = opinfo[1] local opmode = opinfo[2] local kmode = opinfo[3] local usesAux = opinfo[4] local inst = { opcode = opcode; opname = opname; opmode = opmode; kmode = kmode; usesAux = usesAux; } table_insert(codeList, inst) if opmode == 1 then --[[ A ]] inst.A = bit32_band(bit32_rshift(value, 8), 0xFF) elseif opmode == 2 then --[[ AB ]] inst.A = bit32_band(bit32_rshift(value, 8), 0xFF) inst.B = bit32_band(bit32_rshift(value, 16), 0xFF) elseif opmode == 3 then --[[ ABC ]] inst.A = bit32_band(bit32_rshift(value, 8), 0xFF) inst.B = bit32_band(bit32_rshift(value, 16), 0xFF) inst.C = bit32_band(bit32_rshift(value, 24), 0xFF) elseif opmode == 4 then --[[ AD ]] inst.A = bit32_band(bit32_rshift(value, 8), 0xFF) local temp = bit32_band(bit32_rshift(value, 16), 0xFFFF) inst.D = if temp < 0x8000 then temp else temp - 0x10000 elseif opmode == 5 then --[[ AE ]] local temp = bit32_band(bit32_rshift(value, 8), 0xFFFFFF) inst.E = if temp < 0x800000 then temp else temp - 0x1000000 end if usesAux then local aux = readWord() inst.aux = aux table_insert(codeList, {value = aux, opname = "auxvalue" }) end return usesAux end local function checkkmode(inst, k) local kmode = inst.kmode if kmode == 1 then --// AUX inst.K = k[inst.aux + 1] elseif kmode == 2 then --// C inst.K = k[inst.C + 1] elseif kmode == 3 then--// D inst.K = k[inst.D + 1] elseif kmode == 4 then --// AUX import local extend = inst.aux local count = bit32_rshift(extend, 30) local id0 = bit32_band(bit32_rshift(extend, 20), 0x3FF) inst.K0 = k[id0 + 1] inst.KC = count if count == 2 then local id1 = bit32_band(bit32_rshift(extend, 10), 0x3FF) inst.K1 = k[id1 + 1] elseif count == 3 then local id1 = bit32_band(bit32_rshift(extend, 10), 0x3FF) local id2 = bit32_band(bit32_rshift(extend, 0), 0x3FF) inst.K1 = k[id1 + 1] inst.K2 = k[id2 + 1] end if luau_settings.useImportConstants then inst.K = resolveImportConstant( luau_settings.staticEnvironment, count, inst.K0, inst.K1, inst.K2 ) end elseif kmode == 5 then --// AUX boolean low 1 bit inst.K = bit32_extract(inst.aux, 0, 1) == 1 inst.KN = bit32_extract(inst.aux, 31, 1) == 1 elseif kmode == 6 then --// AUX number low 24 bits inst.K = k[bit32_extract(inst.aux, 0, 24) + 1] inst.KN = bit32_extract(inst.aux, 31, 1) == 1 elseif kmode == 7 then --// B inst.K = k[inst.B + 1] elseif kmode == 8 then --// AUX number low 16 bits inst.K = bit32_band(inst.aux, 0xf) end end local function readProto(bytecodeid) local maxstacksize = readByte() local numparams = readByte() local nups = readByte() local isvararg = readByte() ~= 0 if luauVersion >= 4 then readByte() --// flags local typesize = readVarInt(); cursor = cursor + typesize; end local sizecode = readVarInt() local codelist = table_create(sizecode) local skipnext = false for i = 1, sizecode do if skipnext then skipnext = false continue end skipnext = readInstruction(codelist) end local debugcodelist = table_create(sizecode) for i = 1, sizecode do debugcodelist[i] = codelist[i].opcode end local sizek = readVarInt() local klist = table_create(sizek) for i = 1, sizek do local kt = readByte() local k if kt == 0 then --// Nil k = nil elseif kt == 1 then --// Bool k = readByte() ~= 0 elseif kt == 2 then --// Number k = readDouble() elseif kt == 3 then --// String k = stringList[readVarInt()] elseif kt == 4 then --// Import k = readWord() elseif kt == 5 then --// Table local dataLength = readVarInt() k = table_create(dataLength) for i = 1, dataLength do k[i] = readVarInt() end elseif kt == 6 then --// Closure k = readVarInt() elseif kt == 7 then --// Vector local x,y,z,w = readFloat(), readFloat(), readFloat(), readFloat() if luau_settings.vectorSize == 4 then k = luau_settings.vectorCtor(x,y,z,w) else k = luau_settings.vectorCtor(x,y,z) end end klist[i] = k end -- // 2nd pass to replace constant references in the instruction for i = 1, sizecode do checkkmode(codelist[i], klist) end local sizep = readVarInt() local protolist = table_create(sizep) for i = 1, sizep do protolist[i] = readVarInt() + 1 end local linedefined = readVarInt() local debugnameindex = readVarInt() local debugname if debugnameindex ~= 0 then debugname = stringList[debugnameindex] else debugname = "(??)" end -- // lineinfo local lineinfoenabled = readByte() ~= 0 local instructionlineinfo = nil if lineinfoenabled then local linegaplog2 = readByte() local intervals = bit32_rshift((sizecode - 1), linegaplog2) + 1 local lineinfo = table_create(sizecode) local abslineinfo = table_create(intervals) local lastoffset = 0 for j = 1, sizecode do lastoffset += readByte() lineinfo[j] = lastoffset end local lastline = 0 for j = 1, intervals do lastline += readWord() abslineinfo[j] = lastline % (2 ^ 32) end instructionlineinfo = table_create(sizecode) for i = 1, sizecode do --// p->abslineinfo[pc >> p->linegaplog2] + p->lineinfo[pc]; table_insert(instructionlineinfo, abslineinfo[bit32_rshift(i - 1, linegaplog2) + 1] + lineinfo[i]) end end -- // debuginfo if readByte() ~= 0 then local sizel = readVarInt() for i = 1, sizel do readVarInt() readVarInt() readVarInt() readByte() end local sizeupvalues = readVarInt() for i = 1, sizeupvalues do readVarInt() end end return { maxstacksize = maxstacksize; numparams = numparams; nups = nups; isvararg = isvararg; linedefined = linedefined; debugname = debugname; sizecode = sizecode; code = codelist; debugcode = debugcodelist; sizek = sizek; k = klist; sizep = sizep; protos = protolist; lineinfoenabled = lineinfoenabled; instructionlineinfo = instructionlineinfo; bytecodeid = bytecodeid; } end -- userdataRemapping (not used in VM, left unused) if typesVersion == 3 then local index = readByte() while index ~= 0 do readVarInt() index = readByte() end end local protoCount = readVarInt() local protoList = table_create(protoCount) for i = 1, protoCount do protoList[i] = readProto(i - 1) end local mainProto = protoList[readVarInt() + 1] assert(cursor == buffer_len(stream), "deserializer cursor position mismatch") mainProto.debugname = "(main)" return { stringList = stringList; protoList = protoList; mainProto = mainProto; typesVersion = typesVersion; } end local function luau_load(module, env, luau_settings) if luau_settings == nil then luau_settings = luau_newsettings() else luau_validatesettings(luau_settings) end if type(module) ~= "table" then module = luau_deserialize(module, luau_settings) end local protolist = module.protoList local mainProto = module.mainProto local breakHook = luau_settings.callHooks.breakHook local stepHook = luau_settings.callHooks.stepHook local interruptHook = luau_settings.callHooks.interruptHook local panicHook = luau_settings.callHooks.panicHook local alive = true local function luau_close() alive = false end local function luau_wrapclosure(module, proto, upvals) local function luau_execute(...) local debugging, stack, protos, code, varargs if luau_settings.errorHandling then debugging, stack, protos, code, varargs = ... else --// Copied from error handling wrapper local passed = table_pack(...) stack = table_create(proto.maxstacksize) varargs = { len = 0, list = {}, } table_move(passed, 1, proto.numparams, 0, stack) if proto.numparams < passed.n then local start = proto.numparams + 1 local len = passed.n - proto.numparams varargs.len = len table_move(passed, start, start + len - 1, 1, varargs.list) end passed = nil debugging = {pc = 0, name = "NONE"} protos = proto.protos code = proto.code end local top, pc, open_upvalues, generalized_iterators = -1, 1, setmetatable({}, {__mode = "vs"}), setmetatable({}, {__mode = "ks"}) local constants = proto.k local debugopcodes = proto.debugcode local extensions = luau_settings.extensions local handlingBreak = false local inst, op while alive do if not handlingBreak then inst = code[pc] op = inst.opcode end handlingBreak = false debugging.pc = pc debugging.top = top debugging.name = inst.opname pc += 1 if stepHook then stepHook(stack, debugging, proto, module, upvals) end if op == 0 then --[[ NOP ]] --// Do nothing elseif op == 1 then --[[ BREAK ]] if breakHook then local results = table.pack(breakHook(stack, debugging, proto, module, upvals)) if results[1] then return table_unpack(results, 2, #results) end end pc -= 1 op = debugopcodes[pc] handlingBreak = true elseif op == 2 then --[[ LOADNIL ]] stack[inst.A] = nil elseif op == 3 then --[[ LOADB ]] stack[inst.A] = inst.B == 1 pc += inst.C elseif op == 4 then --[[ LOADN ]] stack[inst.A] = inst.D elseif op == 5 then --[[ LOADK ]] stack[inst.A] = inst.K elseif op == 6 then --[[ MOVE ]] stack[inst.A] = stack[inst.B] elseif op == 7 then --[[ GETGLOBAL ]] local kv = inst.K stack[inst.A] = extensions[kv] or env[kv] pc += 1 --// adjust for aux elseif op == 8 then --[[ SETGLOBAL ]] local kv = inst.K env[kv] = stack[inst.A] pc += 1 --// adjust for aux elseif op == 9 then --[[ GETUPVAL ]] local uv = upvals[inst.B + 1] stack[inst.A] = uv.store[uv.index] elseif op == 10 then --[[ SETUPVAL ]] local uv = upvals[inst.B + 1] uv.store[uv.index] = stack[inst.A] elseif op == 11 then --[[ CLOSEUPVALS ]] for i, uv in open_upvalues do if uv.index >= inst.A then uv.value = uv.store[uv.index] uv.store = uv uv.index = "value" --// self reference open_upvalues[i] = nil end end elseif op == 12 then --[[ GETIMPORT ]] if luau_settings.useImportConstants then stack[inst.A] = inst.K else local count = inst.KC local k0 = inst.K0 local import = extensions[k0] or env[k0] if count == 1 then stack[inst.A] = import elseif count == 2 then stack[inst.A] = import[inst.K1] elseif count == 3 then stack[inst.A] = import[inst.K1][inst.K2] end end pc += 1 --// adjust for aux elseif op == 13 then --[[ GETTABLE ]] stack[inst.A] = stack[inst.B][stack[inst.C]] elseif op == 14 then --[[ SETTABLE ]] stack[inst.B][stack[inst.C]] = stack[inst.A] elseif op == 15 then --[[ GETTABLEKS ]] local index = inst.K stack[inst.A] = stack[inst.B][index] pc += 1 --// adjust for aux elseif op == 16 then --[[ SETTABLEKS ]] local index = inst.K stack[inst.B][index] = stack[inst.A] pc += 1 --// adjust for aux elseif op == 17 then --[[ GETTABLEN ]] stack[inst.A] = stack[inst.B][inst.C + 1] elseif op == 18 then --[[ SETTABLEN ]] stack[inst.B][inst.C + 1] = stack[inst.A] elseif op == 19 then --[[ NEWCLOSURE ]] local newPrototype = protolist[protos[inst.D + 1]] local nups = newPrototype.nups local upvalues = table_create(nups) stack[inst.A] = luau_wrapclosure(module, newPrototype, upvalues) for i = 1, nups do local pseudo = code[pc] pc += 1 local type = pseudo.A if type == 0 then --// value local upvalue = { value = stack[pseudo.B], index = "value",--// self reference } upvalue.store = upvalue upvalues[i] = upvalue elseif type == 1 then --// reference local index = pseudo.B local prev = open_upvalues[index] if prev == nil then prev = { index = index, store = stack, } open_upvalues[index] = prev end upvalues[i] = prev elseif type == 2 then --// upvalue upvalues[i] = upvals[pseudo.B + 1] end end elseif op == 20 then --[[ NAMECALL ]] local A = inst.A local B = inst.B local kv = inst.K local sb = stack[B] stack[A + 1] = sb pc += 1 --// adjust for aux local useFallback = true --// Special handling for native namecall behaviour local useNativeHandler = luau_settings.useNativeNamecall if useNativeHandler then local nativeNamecall = luau_settings.namecallHandler local callInst = code[pc] local callOp = callInst.opcode --// Copied from the CALL handler under local callA, callB, callC = callInst.A, callInst.B, callInst.C if stepHook then stepHook(stack, debugging, proto, module, upvals) end if interruptHook then interruptHook(stack, debugging, proto, module, upvals) end local params = if callB == 0 then top - callA else callB - 1 local ret_list = table_pack( nativeNamecall(kv, table_unpack(stack, callA + 1, callA + params)) ) if ret_list[1] == true then useFallback = false pc += 1 --// Skip next CALL instruction inst = callInst op = callOp debugging.pc = pc debugging.name = inst.opname table_remove(ret_list, 1) local ret_num = ret_list.n - 1 if callC == 0 then top = callA + ret_num - 1 else ret_num = callC - 1 end table_move(ret_list, 1, ret_num, callA, stack) end end if useFallback then stack[A] = sb[kv] end elseif op == 21 then --[[ CALL ]] if interruptHook then interruptHook(stack, debugging, proto, module, upvals) end local A, B, C = inst.A, inst.B, inst.C local params = if B == 0 then top - A else B - 1 local func = stack[A] local ret_list = table_pack( func(table_unpack(stack, A + 1, A + params)) ) local ret_num = ret_list.n if C == 0 then top = A + ret_num - 1 else ret_num = C - 1 end table_move(ret_list, 1, ret_num, A, stack) elseif op == 22 then --[[ RETURN ]] if interruptHook then interruptHook(stack, debugging, proto, module, upvals) end local A = inst.A local B = inst.B local b = B - 1 local nresults if b == LUA_MULTRET then nresults = top - A + 1 else nresults = B - 1 end return table_unpack(stack, A, A + nresults - 1) elseif op == 23 then --[[ JUMP ]] pc += inst.D elseif op == 24 then --[[ JUMPBACK ]] if interruptHook then interruptHook(stack, debugging, proto, module, upvals) end pc += inst.D elseif op == 25 then --[[ JUMPIF ]] if stack[inst.A] then pc += inst.D end elseif op == 26 then --[[ JUMPIFNOT ]] if not stack[inst.A] then pc += inst.D end elseif op == 27 then --[[ JUMPIFEQ ]] if stack[inst.A] == stack[inst.aux] then pc += inst.D else pc += 1 end elseif op == 28 then --[[ JUMPIFLE ]] if stack[inst.A] <= stack[inst.aux] then pc += inst.D else pc += 1 end elseif op == 29 then --[[ JUMPIFLT ]] if stack[inst.A] < stack[inst.aux] then pc += inst.D else pc += 1 end elseif op == 30 then --[[ JUMPIFNOTEQ ]] if stack[inst.A] == stack[inst.aux] then pc += 1 else pc += inst.D end elseif op == 31 then --[[ JUMPIFNOTLE ]] if stack[inst.A] <= stack[inst.aux] then pc += 1 else pc += inst.D end elseif op == 32 then --[[ JUMPIFNOTLT ]] if stack[inst.A] < stack[inst.aux] then pc += 1 else pc += inst.D end elseif op == 33 then --[[ ADD ]] stack[inst.A] = stack[inst.B] + stack[inst.C] elseif op == 34 then --[[ SUB ]] stack[inst.A] = stack[inst.B] - stack[inst.C] elseif op == 35 then --[[ MUL ]] stack[inst.A] = stack[inst.B] * stack[inst.C] elseif op == 36 then --[[ DIV ]] stack[inst.A] = stack[inst.B] / stack[inst.C] elseif op == 37 then --[[ MOD ]] stack[inst.A] = stack[inst.B] % stack[inst.C] elseif op == 38 then --[[ POW ]] stack[inst.A] = stack[inst.B] ^ stack[inst.C] elseif op == 39 then --[[ ADDK ]] stack[inst.A] = stack[inst.B] + inst.K elseif op == 40 then --[[ SUBK ]] stack[inst.A] = stack[inst.B] - inst.K elseif op == 41 then --[[ MULK ]] stack[inst.A] = stack[inst.B] * inst.K elseif op == 42 then --[[ DIVK ]] stack[inst.A] = stack[inst.B] / inst.K elseif op == 43 then --[[ MODK ]] stack[inst.A] = stack[inst.B] % inst.K elseif op == 44 then --[[ POWK ]] stack[inst.A] = stack[inst.B] ^ inst.K elseif op == 45 then --[[ AND ]] local value = stack[inst.B] stack[inst.A] = if value then stack[inst.C] or false else value elseif op == 46 then --[[ OR ]] local value = stack[inst.B] stack[inst.A] = if value then value else stack[inst.C] or false elseif op == 47 then --[[ ANDK ]] local value = stack[inst.B] stack[inst.A] = if value then inst.K or false else value elseif op == 48 then --[[ ORK ]] local value = stack[inst.B] stack[inst.A] = if value then value else inst.K or false elseif op == 49 then --[[ CONCAT ]] local s = "" for i = inst.B, inst.C do s ..= stack[i] end stack[inst.A] = s elseif op == 50 then --[[ NOT ]] stack[inst.A] = not stack[inst.B] elseif op == 51 then --[[ MINUS ]] stack[inst.A] = -stack[inst.B] elseif op == 52 then --[[ LENGTH ]] stack[inst.A] = #stack[inst.B] elseif op == 53 then --[[ NEWTABLE ]] stack[inst.A] = table_create(inst.aux) pc += 1 --// adjust for aux elseif op == 54 then --[[ DUPTABLE ]] local template = inst.K local serialized = {} for _, id in template do serialized[constants[id + 1]] = nil end stack[inst.A] = serialized elseif op == 55 then --[[ SETLIST ]] local A = inst.A local B = inst.B local c = inst.C - 1 if c == LUA_MULTRET then c = top - B + 1 end table_move(stack, B, B + c - 1, inst.aux, stack[A]) pc += 1 --// adjust for aux elseif op == 56 then --[[ FORNPREP ]] local A = inst.A local limit = stack[A] if not ttisnumber(limit) then local number = tonumber(limit) if number == nil then error("invalid 'for' limit (number expected)") end stack[A] = number limit = number end local step = stack[A + 1] if not ttisnumber(step) then local number = tonumber(step) if number == nil then error("invalid 'for' step (number expected)") end stack[A + 1] = number step = number end local index = stack[A + 2] if not ttisnumber(index) then local number = tonumber(index) if number == nil then error("invalid 'for' index (number expected)") end stack[A + 2] = number index = number end if step > 0 then if not (index <= limit) then pc += inst.D end else if not (limit <= index) then pc += inst.D end end elseif op == 57 then --[[ FORNLOOP ]] if interruptHook then interruptHook(stack, debugging, proto, module, upvals) end local A = inst.A local limit = stack[A] local step = stack[A + 1] local index = stack[A + 2] + step stack[A + 2] = index if step > 0 then if index <= limit then pc += inst.D end else if limit <= index then pc += inst.D end end elseif op == 58 then --[[ FORGLOOP ]] if interruptHook then interruptHook(stack, debugging, proto, module, upvals) end local A = inst.A local res = inst.K top = A + 6 local it = stack[A] if (luau_settings.generalizedIteration == false) or ttisfunction(it) then local vals = { it(stack[A + 1], stack[A + 2]) } table_move(vals, 1, res, A + 3, stack) if stack[A + 3] ~= nil then stack[A + 2] = stack[A + 3] pc += inst.D else pc += 1 end else local ok, vals = coroutine_resume(generalized_iterators[inst], it, stack[A + 1], stack[A + 2]) if not ok then error(vals) end if vals == LUA_GENERALIZED_TERMINATOR then generalized_iterators[inst] = nil pc += 1 else table_move(vals, 1, res, A + 3, stack) stack[A + 2] = stack[A + 3] pc += inst.D end end elseif op == 59 then --[[ FORGPREP_INEXT ]] if not ttisfunction(stack[inst.A]) then error(string_format("attempt to iterate over a %s value", type(stack[inst.A]))) -- FORGPREP_INEXT encountered non-function value end pc += inst.D elseif op == 60 then --[[ FASTCALL3 ]] --[[ Skipped ]] pc += 1 --// adjust for aux elseif op == 61 then --[[ FORGPREP_NEXT ]] if not ttisfunction(stack[inst.A]) then error(string_format("attempt to iterate over a %s value", type(stack[inst.A]))) -- FORGPREP_NEXT encountered non-function value end pc += inst.D elseif op == 63 then --[[ GETVARARGS ]] local A = inst.A local b = inst.B - 1 if b == LUA_MULTRET then b = varargs.len top = A + b - 1 end table_move(varargs.list, 1, b, A, stack) elseif op == 64 then --[[ DUPCLOSURE ]] local newPrototype = protolist[inst.K + 1] --// correct behavior would be to reuse the prototype if possible but it would not be useful here local nups = newPrototype.nups local upvalues = table_create(nups) stack[inst.A] = luau_wrapclosure(module, newPrototype, upvalues) for i = 1, nups do local pseudo = code[pc] pc += 1 local type = pseudo.A if type == 0 then --// value local upvalue = { value = stack[pseudo.B], index = "value",--// self reference } upvalue.store = upvalue upvalues[i] = upvalue --// references dont get handled by DUPCLOSURE elseif type == 2 then --// upvalue upvalues[i] = upvals[pseudo.B + 1] end end elseif op == 65 then --[[ PREPVARARGS ]] --[[ Handled by wrapper ]] elseif op == 66 then --[[ LOADKX ]] local kv = inst.K stack[inst.A] = kv pc += 1 --// adjust for aux elseif op == 67 then --[[ JUMPX ]] if interruptHook then interruptHook(stack, debugging, proto, module, upvals) end pc += inst.E elseif op == 68 then --[[ FASTCALL ]] --[[ Skipped ]] elseif op == 69 then --[[ COVERAGE ]] inst.E += 1 elseif op == 70 then --[[ CAPTURE ]] --[[ Handled by CLOSURE ]] error("encountered unhandled CAPTURE") elseif op == 71 then --[[ SUBRK ]] stack[inst.A] = inst.K - stack[inst.C] elseif op == 72 then --[[ DIVRK ]] stack[inst.A] = inst.K / stack[inst.C] elseif op == 73 then --[[ FASTCALL1 ]] --[[ Skipped ]] elseif op == 74 then --[[ FASTCALL2 ]] --[[ Skipped ]] pc += 1 --// adjust for aux elseif op == 75 then --[[ FASTCALL2K ]] --[[ Skipped ]] pc += 1 --// adjust for aux elseif op == 76 then --[[ FORGPREP ]] local iterator = stack[inst.A] if luau_settings.generalizedIteration and not ttisfunction(iterator) then local loopInstruction = code[pc + inst.D] if generalized_iterators[loopInstruction] == nil then local function gen_iterator(...) for r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, r20, r21, r22, r23, r24, r25, r26, r27, r28, r29, r30, r31, r32, r33, r34, r35, r36, r37, r38, r39, r40, r41, r42, r43, r44, r45, r46, r47, r48, r49, r50, r51, r52, r53, r54, r55, r56, r57, r58, r59, r60, r61, r62, r63, r64, r65, r66, r67, r68, r69, r70, r71, r72, r73, r74, r75, r76, r77, r78, r79, r80, r81, r82, r83, r84, r85, r86, r87, r88, r89, r90, r91, r92, r93, r94, r95, r96, r97, r98, r99, r100, r101, r102, r103, r104, r105, r106, r107, r108, r109, r110, r111, r112, r113, r114, r115, r116, r117, r118, r119, r120, r121, r122, r123, r124, r125, r126, r127, r128, r129, r130, r131, r132, r133, r134, r135, r136, r137, r138, r139, r140, r141, r142, r143, r144, r145, r146, r147, r148, r149, r150, r151, r152, r153, r154, r155, r156, r157, r158, r159, r160, r161, r162, r163, r164, r165, r166, r167, r168, r169, r170, r171, r172, r173, r174, r175, r176, r177, r178, r179, r180, r181, r182, r183, r184, r185, r186, r187, r188, r189, r190, r191, r192, r193, r194, r195, r196, r197, r198, r199, r200 in ... do coroutine_yield({r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, r20, r21, r22, r23, r24, r25, r26, r27, r28, r29, r30, r31, r32, r33, r34, r35, r36, r37, r38, r39, r40, r41, r42, r43, r44, r45, r46, r47, r48, r49, r50, r51, r52, r53, r54, r55, r56, r57, r58, r59, r60, r61, r62, r63, r64, r65, r66, r67, r68, r69, r70, r71, r72, r73, r74, r75, r76, r77, r78, r79, r80, r81, r82, r83, r84, r85, r86, r87, r88, r89, r90, r91, r92, r93, r94, r95, r96, r97, r98, r99, r100, r101, r102, r103, r104, r105, r106, r107, r108, r109, r110, r111, r112, r113, r114, r115, r116, r117, r118, r119, r120, r121, r122, r123, r124, r125, r126, r127, r128, r129, r130, r131, r132, r133, r134, r135, r136, r137, r138, r139, r140, r141, r142, r143, r144, r145, r146, r147, r148, r149, r150, r151, r152, r153, r154, r155, r156, r157, r158, r159, r160, r161, r162, r163, r164, r165, r166, r167, r168, r169, r170, r171, r172, r173, r174, r175, r176, r177, r178, r179, r180, r181, r182, r183, r184, r185, r186, r187, r188, r189, r190, r191, r192, r193, r194, r195, r196, r197, r198, r199, r200}) end coroutine_yield(LUA_GENERALIZED_TERMINATOR) end generalized_iterators[loopInstruction] = coroutine_create(gen_iterator) end end pc += inst.D elseif op == 77 then --[[ JUMPXEQKNIL ]] local kn = inst.KN if (stack[inst.A] == nil) ~= kn then pc += inst.D else pc += 1 end elseif op == 78 then --[[ JUMPXEQKB ]] local kv = inst.K local kn = inst.KN local ra = stack[inst.A] if (ttisboolean(ra) and (ra == kv)) ~= kn then pc += inst.D else pc += 1 end elseif op == 79 then --[[ JUMPXEQKN ]] local kv = inst.K local kn = inst.KN local ra = stack[inst.A] if (ra == kv) ~= kn then pc += inst.D else pc += 1 end elseif op == 80 then --[[ JUMPXEQKS ]] local kv = inst.K local kn = inst.KN local ra = stack[inst.A] if (ra == kv) ~= kn then pc += inst.D else pc += 1 end elseif op == 81 then --[[ IDIV ]] stack[inst.A] = stack[inst.B] // stack[inst.C] elseif op == 82 then --[[ IDIVK ]] stack[inst.A] = stack[inst.B] // inst.K else error("Unsupported Opcode: " .. inst.opname .. " op: " .. op) end end for i, uv in open_upvalues do uv.value = uv.store[uv.index] uv.store = uv uv.index = "value" --// self reference open_upvalues[i] = nil end for i, iter in generalized_iterators do coroutine_close(iter) generalized_iterators[i] = nil end end local function wrapped(...) local passed = table_pack(...) local stack = table_create(proto.maxstacksize) local varargs = { len = 0, list = {}, } table_move(passed, 1, proto.numparams, 0, stack) if proto.numparams < passed.n then local start = proto.numparams + 1 local len = passed.n - proto.numparams varargs.len = len table_move(passed, start, start + len - 1, 1, varargs.list) end passed = nil local debugging = {pc = 0, name = "NONE"} local result if luau_settings.errorHandling then result = table_pack(pcall(luau_execute, debugging, stack, proto.protos, proto.code, varargs)) else result = table_pack(true, luau_execute(debugging, stack, proto.protos, proto.code, varargs)) end if result[1] then return table_unpack(result, 2, result.n) else local message = result[2] if panicHook then panicHook(message, stack, debugging, proto, module, upvals) end if ttisstring(message) == false then if luau_settings.allowProxyErrors then error(message) else message = type(message) end end if proto.lineinfoenabled then return error(string_format("Fiu VM Error { Name: %s Line: %s PC: %s Opcode: %s }: %s", proto.debugname, proto.instructionlineinfo[debugging.pc], debugging.pc, debugging.name, message), 0) else return error(string_format("Fiu VM Error { Name: %s PC: %s Opcode: %s }: %s", proto.debugname, debugging.pc, debugging.name, message), 0) end end end if luau_settings.errorHandling then return wrapped else return luau_execute end end return luau_wrapclosure(module, mainProto), luau_close end return { luau_newsettings = luau_newsettings, luau_validatesettings = luau_validatesettings, luau_deserialize = luau_deserialize, luau_load = luau_load, } end)() local base64 = (function() -- @original: https://gist.github.com/Reselim/40d62b17d138cc74335a1b0709e19ce2 local Alphabet = {} local Indexes = {} -- A-Z for Index = 65, 90 do table.insert(Alphabet, Index) end -- a-z for Index = 97, 122 do table.insert(Alphabet, Index) end -- 0-9 for Index = 48, 57 do table.insert(Alphabet, Index) end table.insert(Alphabet, 43) -- + table.insert(Alphabet, 47) -- / for Index, Character in ipairs(Alphabet) do Indexes[Character] = Index end local Base64 = {} local bit32_rshift = bit32.rshift local bit32_lshift = bit32.lshift local bit32_band = bit32.band --[[** Encodes a string in Base64. @param [t:string] Input The input string to encode. @returns [t:string] The string encoded in Base64. **--]] function Base64.encode(Input) local Output = {} local Length = 0 for Index = 1, #Input, 3 do local C1, C2, C3 = string.byte(Input, Index, Index + 2) local A = bit32_rshift(C1, 2) local B = bit32_lshift(bit32_band(C1, 3), 4) + bit32_rshift(C2 or 0, 4) local C = bit32_lshift(bit32_band(C2 or 0, 15), 2) + bit32_rshift(C3 or 0, 6) local D = bit32_band(C3 or 0, 63) Length = Length + 1 Output[Length] = Alphabet[A + 1] Length = Length + 1 Output[Length] = Alphabet[B + 1] Length = Length + 1 Output[Length] = C2 and Alphabet[C + 1] or 61 Length = Length + 1 Output[Length] = C3 and Alphabet[D + 1] or 61 end local NewOutput = {} local NewLength = 0 local IndexAdd4096Sub1 for Index = 1, Length, 4096 do NewLength = NewLength + 1 IndexAdd4096Sub1 = Index + 4096 - 1 NewOutput[NewLength] = string.char(table.unpack( Output, Index, IndexAdd4096Sub1 > Length and Length or IndexAdd4096Sub1 )) end return table.concat(NewOutput) end --[[** Decodes a string from Base64. @param [t:string] Input The input string to decode. @returns [t:string] The newly decoded string. **--]] function Base64.decode(Input) local Output = {} local Length = 0 for Index = 1, #Input, 4 do local C1, C2, C3, C4 = string.byte(Input, Index, Index + 3) local I1 = Indexes[C1] - 1 local I2 = Indexes[C2] - 1 local I3 = (Indexes[C3] or 1) - 1 local I4 = (Indexes[C4] or 1) - 1 local A = bit32_lshift(I1, 2) + bit32_rshift(I2, 4) local B = bit32_lshift(bit32_band(I2, 15), 4) + bit32_rshift(I3, 2) local C = bit32_lshift(bit32_band(I3, 3), 6) + I4 Length = Length + 1 Output[Length] = A if C3 ~= 61 then Length = Length + 1 Output[Length] = B end if C4 ~= 61 then Length = Length + 1 Output[Length] = C end end local NewOutput = {} local NewLength = 0 local IndexAdd4096Sub1 for Index = 1, Length, 4096 do NewLength = NewLength + 1 IndexAdd4096Sub1 = Index + 4096 - 1 NewOutput[NewLength] = string.char(table.unpack( Output, Index, IndexAdd4096Sub1 > Length and Length or IndexAdd4096Sub1 )) end return table.concat(NewOutput) end return Base64 end)() local env = {} local filesystem = {} do filesystem.__index = filesystem -- setmetatable(filesystem, cfilesystem) for filesystem wrappers local currentTime = tick local DEBUG = false filesystem.umask = 022 filesystem.types = { dir = "di", link = "ln", socket = "so", pipe = "pi", exe = "ex", file = "fl" } function filesystem.extname(path) local dot_index = path:match(".*()%.") if not dot_index or dot_index == 1 then return "" end return path:sub(dot_index) end function filesystem.join(...) local parts = {...} local result = {} for _, path in ipairs(parts) do path = path:gsub("^/+", "") path = path:gsub("/+$", "") if path and path ~= "" then table.insert(result, path) end end return "/" .. table.concat(result, "/") .. "/" end function filesystem.basename(path) path = path:gsub("^/+", "") path = path:gsub("/+$", "") local base = path:match("([^/]+)$") return base or "" end local function createNode(type, content) return { type = type, metadata = { created = currentTime(), modified = currentTime(), permissions = type == "file" and 666 - filesystem.umask or 777 - filesystem.umask, }, content = type == filesystem.types.file and content or nil, contents = type == filesystem.types.dir and (content or {}) or nil } end function filesystem.splitpath(path) local dirs = {} local stack = {} for dir in path:gmatch("[^/]+") do if dir == ".." then if #stack > 0 then table.remove(stack) end elseif dir ~= "." and dir ~= "" then table.insert(stack, dir) end end for i, dir in ipairs(stack) do table.insert(dirs, dir) end return dirs end function filesystem.prefix(path, prefix, dir) if path:sub(1, #prefix) == prefix then path = filesystem.join(dir, path:sub(#prefix + 1)) end if path:sub(1, #prefix + 1) == "/" .. prefix or path:sub(1, #prefix + 1) == prefix .. "/" then path = filesystem.join(dir, path:sub(#prefix + 2)) end return path end function filesystem.parsecontext(path, home, dir) path = filesystem.prefix(path, "~") path = filesystem.prefix(path, ".") path = table.concat(filesystem.splitpath(path), "/") if #path == 0 then path = "/" end return path end local function getNode(currentNode, path) local dirs = filesystem.splitpath(path) for _, dir in ipairs(dirs) do currentNode = currentNode.contents and currentNode.contents[dir] if not currentNode then return nil end end return currentNode end local function getDir(fs, path) local dirs = filesystem.splitpath(path) local parentPath = table.concat(dirs, "/", 1, #dirs - 1) local parentDir = getNode(fs, parentPath) if not parentDir or parentDir.type ~= filesystem.types.dir then return false, "No such directory: " .. parentPath end return true, parentDir, dirs end function filesystem.mkdir(fs, path) if DEBUG then print("mkdir", debug.traceback()) end local success, result, dirs = getDir(fs, path) if not success then return success, result end local name = dirs[#dirs] if result.contents[name] then return false, "Directory already exists: " .. path end result.contents[name] = createNode(filesystem.types.dir) return true end function filesystem.rmdir(fs, path) if DEBUG then print("rmdir", debug.traceback()) end local success, result, dirs = getDir(fs, path) if not success then return success, result end local name = dirs[#dirs] if not result.contents[name] then return false, "No such directory: " .. path end result.contents[name] = nil return true end function filesystem.create(fs, path, content, metadata) if DEBUG then print("create", debug.traceback()) end local success, result, dirs = getDir(fs, path) if not success then return success, result end local name = dirs[#dirs] if result.contents[name] then return false, "File already exists: " .. path end local node = createNode(filesystem.types.file, content) if metadata then for index, value in metadata do node.metadata[index] = value end end result.contents[name] = node return true end function filesystem.rm(fs, path) if DEBUG then print("rm", debug.traceback()) end local success, result, dirs = getDir(fs, path) if not success then return success, result end local name = dirs[#dirs] if not result.contents[name] then return false, "No such file: " .. path end result.contents[name] = nil return true end function filesystem.readdir(fs, path) if DEBUG then print("readdir", debug.traceback()) end local success, result, dirs = getDir(fs, path) if not success then return success, result end local contents = {} if path == "/" then contents = result.contents else local name = dirs[#dirs] if not result.contents[name] or result.contents[name].type ~= filesystem.types.dir then return false, "No such directory: " .. path end contents = result.contents[name].contents end local paths = {} for node in contents do table.insert(paths, filesystem.join(path, node)) end return true, paths end function filesystem.read(fs, path) if DEBUG then print("read", debug.traceback()) end local file = getNode(fs, path) if file and file.type == filesystem.types.file then return true, file.content else return false, "No such file: " .. path end end function filesystem.write(fs, path, content, metadata) if DEBUG then print("write", debug.traceback()) end local file = getNode(fs, path) if file and file.type == filesystem.types.file then file.content = content file.metadata.modified = currentTime() if metadata then for index, value in metadata do file.metadata[index] = value end end return true else return filesystem.create(fs, path, content, metadata) end end function filesystem.metadata(fs, path) if DEBUG then print("metadata", debug.traceback()) end local node = getNode(fs, path) if node then local metadata = node.metadata metadata.type = node.type metadata.subtype = node.subtype return true, metadata end return false, "No such file or directory: " .. path end function filesystem.symlink(fs, path1, path2) local node1 = getNode(fs, path1) if not node1 then return false, "No such file or directory: " .. path1 end local node2 = getNode(fs, path2) if not node2 then return false, "No such file or directory: " .. path2 end node1.content = nil node1.contents = nil node1.subtype = filesystem.types.link setmetatable(node1, { __index = function(_, index) if index == "metadata" or index == "subtype" then return node1[index] end return node2[index] end, __newindex = function(_, index, value) node2[index] = value end, }) return true end function filesystem.exists(fs, path) local node = getNode(fs, path) return node ~= nil and true or false end function filesystem.new() if DEBUG then print("new", debug.traceback()) end return createNode(filesystem.types.dir) end end local fs = filesystem.new() do local rootfs = { "/bin", "/boot", "/dev", "/etc", "/etc/default", "/etc/network", "/etc/profile", "/etc/rc.d", "/etc/xdg", "/home", "/lib", "/lib64", "/media", "/mnt", "/opt", "/proc", "/root", "/run", "/sbin", "/srv", "/sys", "/tmp", "/usr", "/usr/bin", "/usr/lib", "/usr/lib64", "/usr/local", "/usr/local/bin", "/usr/local/etc", "/usr/local/games", "/usr/local/lib", "/usr/local/sbin", "/usr/local/share", "/usr/local/src", "/usr/sbin", "/usr/share", "/usr/share/doc", "/usr/share/man", "/usr/src", "/var", "/var/cache", "/var/lib", "/var/lib/machines", "/var/lib/pacman", "/var/lib/systemd", "/var/lib/dbus", "/var/lib/logrotate", "/var/local", "/var/lock", "/var/log", "/var/mail", "/var/opt", "/var/run", "/var/spool", "/var/tmp" } local failed = false local function safe(func, ...) local success, result = func(...) if not success then failed = true warn(result) end return success, result end for _, path in rootfs do safe(filesystem.mkdir, fs, path) end safe(filesystem.symlink, fs, "/bin", "/usr/bin") safe(filesystem.symlink, fs, "/lib", "/usr/lib") safe(filesystem.symlink, fs, "/lib64", "/usr/lib64") safe(filesystem.symlink, fs, "/sbin", "/usr/sbin") safe(filesystem.write, fs, "/etc/machine-id", HttpService:GenerateGUID(false)) safe(filesystem.write, fs, "/etc/os-release", `NAME="Arch Linux"\nPRETTY_NAME="Arch Linux"\nID=arch\nBUILD_ID=rolling\nANSI_COLOR="38;2;23;147;209"\nHOME_URL="https://archlinux.org/"\nDOCUMENTATION_URL="https://wiki.archlinux.org/"\nSUPPORT_URL="https://bbs.archlinux.org/"\nBUG_REPORT_URL="https://gitlab.archlinux.org/groups/archlinux/-/issues"\nPRIVACY_POLICY_URL="https://terms.archlinux.org/docs/privacy-policy/"\nLOGO=archlinux-logo`) safe(filesystem.write, fs, "/etc/issue", "Arch Linux \r (\l)") safe(filesystem.write, fs, "/usr/bin/ls", base64.decode("BQENBGFyZ3MEc2VsZgNkaXIKZmlsZXN5c3RlbQhtZXRhZGF0YQR0eXBlBXR5cGVzB3JlYWRkaXIIYmFzZW5hbWUFdGFibGUGaW5zZXJ0BmNvbmNhdAEgAQ8AAAEAADpBAAAADAEBAAAAAEARAAEAGQACAAwABAAADCCADAEHAAAYUIAGAgAAFQECAxkBAwADAwAABgQCABYDAwAPAwJxCAAAAAwECgADJFDAHgMfAAQAAAAMAwwAACxQgAYEAAAVAwIDGgMfADUFAAAAAAAABgYEAAIHAAACCAAATAYJAAYMBQAMDQ4AADRQgAYOCgAVDQIARDQAAgwLEQAAQPCAFQsAAToG9v8CAAAAAwYBAAwHEwAASPCABggFAAUJFAAVBwMAFgYAABYAAQADAwEADAQOAAA0UIAGBQAAFQQCABYDAAAWAAEAFQMBBAAAAEADAgMDBAAMIIADBAMFBAAYUIADBgMHBAMkUMADCAQALFCAAwkEADRQgAMKAwsEAEDwgAMMBABI8IADDQABAAEYAAAAAAAAAAEAAAABAQAAAgAAAAAAAQAAAAEBAAEAAAABAAAAAAAAAAD/AAMAAAAAAAAE/wAAAAAAAQEAAAAAAA==")) safe(filesystem.write, fs, "/usr/bin/cat", base64.decode("BQEIBGFyZ3MKZmlsZXN5c3RlbQhtZXRhZGF0YQR0eXBlBXR5cGVzA2RpchA6IElzIGEgZGlyZWN0b3J5BHJlYWQBBwAAAQIAHEEAAAAMAQEAAAAAQBEAAQAMAQQAAAwggAYCAAAVAQIDGQEBABYCAgAPAwJxBQAAAAwECAAHGCDAHgMGAAQAAAADAwAABgUAAAUGCQAxBAUGFgMDAAwDCwAAKCCABgQAABUDAgMDBQEABgYEABYFAwAMAwEEAAAAQAMCAwMEAAwggAMEAwUDBgQHGCDAAwcDCAQAKCCAAAEAARgAAAAAAQAAAAEBAgAAAAAAAQAAAAACAAAAAQAAAQAAAAAA")) safe(filesystem.write, fs, "/usr/bin/clear", base64.decode("BQEDBHNlbGYFY2xlYXIpY2xlYXI6IHRlcm1pbmFsIGRvZXMgbm90IHN1cHBvcnQgY2xlYXJpbmcBAgAAAQIADkEAAAAMAAIAAAQAgBoABwAMAAMAAAAAQBQAALABAAAAFQACAQMAAQAWAAIAAwAAAAUBBAAWAAMABQMBAwIEAAQAgAQAAABAAwMAAQABGAAAAAABAAAAAAEAAgAAAQAAAAAA")) safe(filesystem.write, fs, "/usr/bin/cd", base64.decode("BQEHAX4EYXJncwpmaWxlc3lzdGVtBmV4aXN0cxs6IE5vIHN1Y2ggZmlsZSBvciBkaXJlY3RvcnkCY2QeZmFpbGVkOiBhcmUgeW91IGluIGEgdGVybWluYWw/AQYAAAECABxBAAAADAICAAAAEEARAQIAMAABAAwBBQAAEDCABgIAABUBAgIZAQUAAwIAAAYEAAAFBQYAMQMEBRYCAwAMAggAAABwQBoCBQAMAggAAABwQAYDAAAVAgIBFwADAAMCAAAFAwkAFgIDAAMCAQAWAgIACgMBAwIEAAAQQAMDAwQEABAwgAMFAwYEAABwQAMHAAEAARgAAAAAAAEAAAABAQAAAAACAAABAAAAAAIAAAIAAQAAAAAA")) safe(filesystem.write, fs, "/usr/bin/touch", base64.decode("BQEKBGFyZ3MHb3B0aW9ucwF0CG1vZGlmaWVkCmZpbGVzeXN0ZW0GZXhpc3RzBHJlYWQFd3JpdGUHY3JlYXRlZAABCQAAAQIALUEAAAAMAQEAAAAAQBEAAQAMAQQAAAwggAICAAAaAQQANgMGABABA6QFAAAABgIDAAwDCQAAIHCABgQAABUDAgIaAw0ADAMLAAAocIAGBAAAFQMCAxoDFgAMBQ0AADBwgAYGAAAGBwQABggCABUFBAAWBQAAFgABAA8DAqQFAAAAEAMC0A4AAAACAwAAEAMCpAUAAAAMAw0AADBwgAYEAAAFBQ8ABgYCABUDBAAWAwAAFgABABADAQQAAABAAwIDAwQADCCAAwQFAQUDBQMGBAAgcIADBwQAKHCAAwgEADBwgAMJAwoAAQABGAAAAAABAAEBAQEAAAMAAAAAAQAAAAEBAAAAAAAAB/wAAAABAAABAAAAAAAAAgEAAAAAAA==")) safe(filesystem.write, fs, "/usr/bin/fastfetch-icon", base64.decode("BQETBlteDQpdKwZnbWF0Y2gMXiVzKiguLSklcyokBW1hdGNoAAJeIw5eKFsld19dKyk9KC4qKQheIiguKikiJAheJyguKiknJBNwYXJzZUtleVZhbHVlU3RyaW5nCmZpbGVzeXN0ZW0EcmVhZA8vZXRjL29zLXJlbGVhc2UCaWQFcGNhbGwEaHR0cAhHZXRBc3luY0xodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vZmFzdGZldGNoLWNsaS9mYXN0ZmV0Y2gvZGV2L3NyYy9sb2dvL2FzY2lpBC50eHQCDAEAAAAAKTUBAAAAAAAABQQAABQCAIgBAAAAFQIDBEwCHwAFCQIAFAcF5wMAAAAVBwMCBgUHAFAFGQAEAAAABQkFABQHBecDAAAAFQcDAhkHEwAFCQYAFAcF5wMAAAAVBwMDGgcOABoIDQAFCwcAFAkI5wMAAAAVCQMCGQkGAAULCAAUCQjnAwAAABUJAwIZCQEABgkIAAYICQAOCAEHOgLg/wEAAAAWAQIACQMBAwIDAwMEAwUDBgMHAwgDCQABCgEYAAACAAAAAAEAAAAAAQAAAAAAAAEAAAACAAEAAAAAAAAAAAAAAAH5AAwCAAAAAAsAAAECACJBAAAAQAAAAAwBAwAACBCABQIEABUBAgMaARgABgMAAAYEAgAVAwICBgIDAA8DAvQFAAAADAQHAAAAYEAMBQoAACSAgAwGCwAAAIBABQgMAAYJAwAFCg0AMQcIChUEBAMaBAMAAwYBAAYHBQAWBgMAAwYAAAYHBQAWBgMAAwMAAAYEAgAWAwMADgYAAwsDDAQACBCAAw0DDgMPBAAAYEADEAMRBAAkgIAEAACAQAMSAxMBAAEAARgAABIAAAABAQAAAAEAAQAAAAAAAAAAAAABAQAAAgAAAwAAAQAAAAAB")) safe(filesystem.write, fs, "/usr/bin/fastfetch-icon.luau", [[local function parseKeyValueString(str) local result = {} for line in str:gmatch("[^\r\n]+") do line = line:match("^%s*(.-)%s*$") if line ~= "" and not line:match("^#") then local key, value = line:match("^([%w_]+)=(.*)") if key and value then value = value:match('^"(.*)"$') or value:match("^'(.*)'$") or value result[key] = value end end end return result end local gotosrelease, osrelease = filesystem.read("/etc/os-release") if gotosrelease then osrelease = parseKeyValueString(osrelease) local id = osrelease.ID if not id then return false, "invalid os-release parameters, missing ID" end local goticon, iconresponse = pcall(http.GetAsync, http, "https://raw.githubusercontent.com/fastfetch-cli/fastfetch/dev/src/logo/ascii/"..id..".txt") if goticon then return true, iconresponse else return false, iconresponse end else return false, osrelease end]]) if failed then error("failed creating rootfs") end end local term = Roact.Component:extend("term") do local function parseCommand(commandString) local command, argsString = commandString:match("^(%S+)%s*(.*)") local args = {} local pos = 1 local inQuotes = false local currentArg = "" while pos <= #argsString do local char = argsString:sub(pos, pos) if char == '"' then inQuotes = not inQuotes elseif char == ' ' and not inQuotes then if #currentArg > 0 then table.insert(args, currentArg) currentArg = "" end else currentArg = currentArg .. char end pos = pos + 1 end if #currentArg > 0 then table.insert(args, currentArg) end return command, args end local function parseOptions(args) local parsedArgs = { options = {}, positional = {} } local function handleArg(arg) if arg:match("^%-%-") then local key, value = arg:match("^%-%-(%S+)%s*(.*)") parsedArgs.options[key] = value == "" and true or value elseif arg:match("^%-%S") then local key = arg:sub(2) parsedArgs.options[key] = true else table.insert(parsedArgs.positional, arg) end end for i = 1, #args do handleArg(args[i]) end return parsedArgs end term.colors = { --basic [0] = "#000000", -- Black [1] = "#ff0000", -- Red [2] = "#00ff00", -- Green [3] = "#ffff00", -- Yellow [4] = "#0000ff", -- Blue [5] = "#ff00ff", -- Magenta [6] = "#00ffff", -- Cyan [7] = "#ffffff", -- White [8] = "#808080", -- Bright Black (Gray) [9] = "#ff6666", -- Bright Red [10] = "#66ff66", -- Bright Green [11] = "#ffff66", -- Bright Yellow [12] = "#6666ff", -- Bright Blue [13] = "#ff66ff", -- Bright Magenta [14] = "#66ffff", -- Bright Cyan [15] = "#ffffff", -- Bright White --extended [16] = "#000000", [17] = "#800000", [18] = "#008000", [19] = "#808000", [20] = "#000080", [21] = "#800080", [22] = "#008080", [23] = "#c0c0c0", [24] = "#808080", [25] = "#ff0000", [26] = "#00ff00", [27] = "#ffff00", [28] = "#0000ff", [29] = "#ff00ff", [30] = "#00ffff", [31] = "#ffffff", [32] = "#000000", [33] = "#00005f", [34] = "#000087", [35] = "#0000af", [36] = "#0000d7", [37] = "#0000ff", [38] = "#005f00", [39] = "#005f5f", [40] = "#005f87", [41] = "#005faf", [42] = "#007f00", [43] = "#007f5f", [44] = "#007f87", [45] = "#007faf", [46] = "#007fd7", [47] = "#007fff", [48] = "#00af00", [49] = "#00af5f", [50] = "#00af87", [51] = "#00afaf", [52] = "#00afd7", [53] = "#00afff", [54] = "#00d700", [55] = "#00d75f", [56] = "#00d787", [57] = "#00d7af", [58] = "#00d7d7", [59] = "#00d7ff", [60] = "#00ff00", [61] = "#00ff5f", [62] = "#00ff87", [63] = "#00ffaf", [64] = "#00ffd7", [65] = "#00ffff", [66] = "#5f0000", [67] = "#5f005f", [68] = "#5f0087", [69] = "#5f00af", [70] = "#5f00d7", [71] = "#5f00ff", [72] = "#5f5f00", [73] = "#5f5f5f", [74] = "#5f5f87", [75] = "#5f5faf", [76] = "#5f5fd7", [77] = "#5f5fff", [78] = "#5f8700", [79] = "#5f875f", [80] = "#5f8787", [81] = "#5f87af", [82] = "#5f87d7", [83] = "#5f87ff", [84] = "#5faf00", [85] = "#5faf5f", [86] = "#5faf87", [87] = "#5fafaf", [88] = "#5fafd7", [89] = "#5fafff", [90] = "#5fd700", [91] = "#5fd75f", [92] = "#5fd787", [93] = "#5fd7af", [94] = "#5fd7d7", [95] = "#5fd7ff", [96] = "#5fff00", [97] = "#5fff5f", [98] = "#5fff87", [99] = "#5fffaf", [100] = "#5fffd7", [101] = "#5fffff", [102] = "#870000", [103] = "#87005f", [104] = "#870087", [105] = "#8700af", [106] = "#8700d7", [107] = "#8700ff", [108] = "#875f00", [109] = "#875f5f", [110] = "#875f87", [111] = "#875faf", [112] = "#875fd7", [113] = "#875fff", [114] = "#878700", [115] = "#87875f", [116] = "#878787", [117] = "#8787af", [118] = "#8787d7", [119] = "#8787ff", [120] = "#87af00", [121] = "#87af5f", [122] = "#87af87", [123] = "#87afaf", [124] = "#87afd7", [125] = "#87afff", [126] = "#87d700", [127] = "#87d75f", [128] = "#87d787", [129] = "#87d7af", [130] = "#87d7d7", [131] = "#87d7ff", [132] = "#87ff00", [133] = "#87ff5f", [134] = "#87ff87", [135] = "#87ffaf", [136] = "#87ffd7", [137] = "#87ffff", [138] = "#af0000", [139] = "#af005f", [140] = "#af0087", [141] = "#af00af", [142] = "#af00d7", [143] = "#af00ff", [144] = "#af5f00", [145] = "#af5f5f", [146] = "#af5f87", [147] = "#af5faf", [148] = "#af5fd7", [149] = "#af5fff", [150] = "#af8700", [151] = "#af875f", [152] = "#af8787", [153] = "#af87af", [154] = "#af87d7", [155] = "#af87ff", [156] = "#afaf00", [157] = "#afaf5f", [158] = "#afaf87", [159] = "#afafaf", [160] = "#afafd7", [161] = "#afafff", [162] = "#afd700", [163] = "#afd75f", [164] = "#afd787", [165] = "#afd7af", [166] = "#afd7d7", [167] = "#afd7ff", [168] = "#afff00", [169] = "#afff5f", [170] = "#afff87", [171] = "#afffaf", [172] = "#afffd7", [173] = "#afffff", [174] = "#d70000", [175] = "#d7005f", [176] = "#d70087", [177] = "#d700af", [178] = "#d700d7", [179] = "#d700ff", [180] = "#d75f00", [181] = "#d75f5f", [182] = "#d75f87", [183] = "#d75faf", [184] = "#d75fd7", [185] = "#d75fff", [186] = "#d78700", [187] = "#d7875f", [188] = "#d78787", [189] = "#d787af", [190] = "#d787d7", [191] = "#d787ff", [192] = "#d7af00", [193] = "#d7af5f", [194] = "#d7af87", [195] = "#d7afaf", [196] = "#d7afd7", [197] = "#d7afff", [198] = "#d7d700", [199] = "#d7d75f", [200] = "#d7d787", [201] = "#d7d7af", [202] = "#d7d7d7", [203] = "#d7d7ff", [204] = "#d7ff00", [205] = "#d7ff5f", [206] = "#d7ff87", [207] = "#d7ffaf", [208] = "#d7ffd7", [209] = "#d7ffff", [210] = "#ff0000", [211] = "#ff005f", [212] = "#ff0087", [213] = "#ff00af", [214] = "#ff00d7", [215] = "#ff00ff", [216] = "#ff5f00", [217] = "#ff5f5f", [218] = "#ff5f87", [219] = "#ff5faf", [220] = "#ff5fd7", [221] = "#ff5fff", [222] = "#ff8700", [223] = "#ff875f", [224] = "#ff8787", [225] = "#ff87af", [226] = "#ff87d7", [227] = "#ff87ff", [228] = "#ffaf00", [229] = "#ffaf5f", [230] = "#ffaf87", [231] = "#ffafaf", [232] = "#ffafd7", [233] = "#ffafff", [234] = "#ffd700", [235] = "#ffd75f", [236] = "#ffd787", [237] = "#ffd7af", [238] = "#ffd7d7", [239] = "#ffd7ff", [240] = "#ffff00", [241] = "#ffff5f", [242] = "#ffff87", [243] = "#ffffaf", [244] = "#ffffd7", [245] = "#ffffff", [246] = "#000000", [247] = "#00005f", [248] = "#000087", [249] = "#0000af", [250] = "#0000d7", [251] = "#0000ff", [252] = "#005f00", [253] = "#005f5f", [254] = "#005f87", [255] = "#005faf", } local function sanitizeRichText(text) local replace = { ['<'] = '&lt;', ['>'] = '&gt;', ['"'] = '&quot;', ["'"] = '&apos;', ['&'] = '&amp;' } local res = string.gsub(text, "([<>'\"\&])", replace) return res end function term.parsecolors(text) local richText = "" local i = 1 while i <= #text do if text:sub(i, i) == "\27" then local codeStart = i + 1 local codeEnd = text:find("m", codeStart) if codeEnd then local code = tonumber(text:sub(codeStart, codeEnd - 1)) if code then if code >= 0 then richText = richText .. string.format("<font color=\"%s\">", term.colors[code]) elseif code == 0 then richText = richText .. "</font>" end i = codeEnd end end else richText = richText .. text:sub(i, i) end i = i + 1 end return richText end function term.parse(commandString, cfilesystem, self) local command, args = parseCommand(commandString) if not command then return end local parsedArgs = parseOptions(args) local path = filesystem.join("/usr/bin", command) local exists, content = filesystem.read(fs, path) if exists then local lenv = getfenv() lenv.args = args lenv.options = parsedArgs lenv.filesystem = cfilesystem lenv.http = HttpService lenv.env = setmetatable({}, { __index = function(_, index) return env[index] end, __newindex = function(_, index, value) env[index] = value end, __tostring = "env" }) if self then lenv.self = self lenv.cd = function(path) path = filesystem.join(self.dir, path) path = filesystem.parsecontext(path, self.home, self.dir) self.dir = path end end local extname = filesystem.basename(path):split(".") extname = extname[#extname] local success, commandsuccess, commandresponse = pcall(function() local func if extname == "luau" or extname == "lua" then func = loadstring(content) func = setfenv(func, lenv) else func = fiu.luau_load(content, lenv) end return func() end) if not success then return commandsuccess end if commandsuccess then return commandresponse else return command .. ": ".. (commandresponse or "") end else return command..": command not found" end end local function getHostname() local success, hostname = filesystem.read(fs, "/etc/hostname") if not success then hostname = "archlinux" end return hostname end function term:init() self.textSize, self.updateTextSize = Roact.createBinding(28) self.root = Roact.createRef() self.prefix = "[%s@%s %s]$" self.user = "root" self.home = "/root/" self.dir = self.home self.lines = 0 local function parsepath(path) return filesystem.parsecontext(path, self.home, self.dir) end local termfilesystem = {} function termfilesystem.symlink(path1, path2) return filesystem.symlink(fs, parsepath(path1), parsepath(path2)) end function termfilesystem.metadata(path) return filesystem.metadata(fs, parsepath(path)) end function termfilesystem.rm(path) return filesystem.rm(fs, parsepath(path)) end function termfilesystem.rmdir(path) return filesystem.rmdir(fs, parsepath(path)) end function termfilesystem.read(path) return filesystem.read(fs, parsepath(path)) end function termfilesystem.mkdir(path) return filesystem.mkdir(fs, parsepath(path)) end function termfilesystem.write(path, ...) return filesystem.write(fs, parsepath(path), ...) end function termfilesystem.exists(path) return filesystem.exists(fs, parsepath(path)) end function termfilesystem.readdir(path) return filesystem.readdir(fs, parsepath(path)) end setmetatable(termfilesystem, filesystem) self.filesystem = termfilesystem end function term:clear() self.lines = 0 for _, object in self.root:getValue():GetChildren() do if object:IsA("TextBox") then object:Destroy() end end end function term:print(content) local content, update = Roact.createBinding(content) local ref = Roact.createRef() local text = Roact.createElement("TextBox", { Size = Roact.joinBindings({self.textSize, content}):map(function(values) local size, content = unpack(values) local _, lineCount = content:gsub("\n", "\n") lineCount += 1 return UDim2.new(1, 0, 0, size * lineCount) end), TextSize = self.textSize, BackgroundTransparency = 1, Font = Enum.Font.Code, TextColor3 = Color3.new(1, 1, 1), TextXAlignment = Enum.TextXAlignment.Left, TextYAlignment = Enum.TextYAlignment.Top, Text = content, TextEditable = false, ClearTextOnFocus = false, MultiLine = false, [Roact.Ref] = ref }) self.lines += 1 Roact.mount(text, self.root:getValue()) local object = ref:getValue() object:SetAttribute("line", self.lines) return { content = content, update = update, object = object } end function term:newline(initial, prefix) local dirname = filesystem.basename(self.dir) if filesystem.join(self.dir) == filesystem.join(self.home) then dirname = "~" end if #dirname == 0 then dirname = "/" end local prefix = self.prefix:format(self.user, getHostname(), dirname) local line = self:print(prefix .. " " .. (initial or "")) line.object:SetAttribute("start", #prefix + 2) local update = line.update line.update = function(content) return update(prefix .. " " .. content) end return line end function term:didMount() local sg = Instance.new("ScreenGui") sg.ResetOnSpawn = false sg.Parent = owner.PlayerGui local remote = Instance.new("RemoteEvent") remote.Parent = sg NLS([[local remote, root = ... local sub = string.sub local uis = game:GetService("UserInputService") local lines = {} local currentline local text = "" local focused = false uis.InputBegan:Connect(function(input, gp) if input.KeyCode == Enum.KeyCode.Return and focused then focused = false lines[currentline]:ReleaseFocus() remote:FireServer("return", text) end end) local inputs = {} function killinputs() for _, connection in pairs(inputs) do if typeof(connection) == "function" then connection() else connection:Disconnect() end end inputs = {} end function inputlisten(line) killinputs() local fake = line:Clone() fake.TextTransparency = 0.5 fake:SetAttribute("line", nil) fake:SetAttribute("start", nil) fake.Size = UDim2.fromScale(1, 1) fake.ZIndex = 2 fake.Name = "input" fake.TextEditable = true fake.Parent = line local start = line:GetAttribute("start") local prefix = sub(line.Text, 1, start - 2) text = sub(line.Text, start) table.insert(inputs, fake:GetPropertyChangedSignal("Text"):Connect(function() local new = fake.Text if sub(new, 1, start - 1) ~= prefix .. " " then fake.Text = prefix .. " " end text = sub(fake.Text, start) remote:FireServer("update", text) end)) table.insert(inputs, fake.Focused:Connect(function() focused = true end)) table.insert(inputs, fake.FocusLost:Connect(function() task.wait() focused = false end)) table.insert(inputs, function() fake:Destroy() focused = false text = "" end) end function addline(line) local lineValue = line:GetAttribute("line") if lineValue and line:GetAttribute("start") then lines[lineValue] = line if lineValue > (currentline or 0) then currentline = lineValue inputlisten(line) end line:GetPropertyChangedSignal("Parent"):Connect(function() if line.Parent == nil then lines[lineValue] = nil if currentline == lineValue then currentline = nil killinputs() end end end) end end for _, line in pairs(root:GetChildren()) do addline(line) end root.ChildAdded:Connect(addline) root.InputBegan:Connect(function(input) if input.UserInputType == Enum.UserInputType.Touch or input.UserInputType == Enum.UserInputType.MouseButton1 then if currentline then lines[currentline].input:CaptureFocus() end end end)]], sg, remote, self.root:getValue()) local current = self:newline() remote.OnServerEvent:Connect(function(sender, action, data) if sender ~= owner then return end if action == "update" then current.update(data) elseif action == "return" then local result = term.parse(data, self.filesystem, self) if result then self:print(term.parsecolors(sanitizeRichText(tostring(result)))) end current.update(data) current = self:newline() end end) end function term:render() local root = Roact.createElement("Frame", { Size = FULLSCALE, BackgroundColor3 = Color3.new(), BorderSizePixel = 0, ZIndex = 0, [Roact.Ref] = self.root }, { list = Roact.createElement("UIListLayout") }) return root end end function linux:init() end function linux:render() local root = Roact.createElement("Frame", { Size = FULLSCALE, BackgroundColor3 = Color3.new(), BorderSizePixel = 0, ZIndex = 0, }, { term = Roact.createElement(term) }) return root end end local gui, screen do local resolution = Vector2.new(1920, 1080) local screenSize = 7 screen = Instance.new("Part") screen.CanCollide = false screen.CanTouch = false screen.Locked = true screen.Name = "Base" screen.Size = Vector3.new(screenSize * (resolution.X / resolution.Y), screenSize, 0) screen.Anchored = true screen.Parent = script task.spawn(function() while true do task.wait() local char = owner.Character if char then local hrp = char:FindFirstChild("HumanoidRootPart") if hrp then screen.CFrame = hrp.CFrame * CFrame.new(0, screen.Size.Y / 2, -5) end end end end) gui = Roact.createElement("SurfaceGui", { Face = Enum.NormalId.Back, SizingMode = Enum.SurfaceGuiSizingMode.FixedSize, CanvasSize = resolution, ClipsDescendants = true, ZIndexBehavior = Enum.ZIndexBehavior.Sibling, LightInfluence = 0, }, { content = Roact.createElement(linux) }) end Roact.mount(gui, screen)
Editor Settings
Theme
Key bindings
Full width
Lines