-- vim: set foldmethod=marker : -- Texture dimensions -- size = 128 factor = size / 64 -- Values for UV mappings -- face_damage=0 face_expr=0 step_u_face=32 step_v_face=16 offset_u_face=64 offset_v_face=0 armor_enabled=true -- initialize values -- function player_init() old_health=player.getHealth() end expr_cooldown=0 -- Parts -- HEAD=model.Head.Head -- Initial configuration -- for key, value in pairs(vanilla_model) do value.setEnabled(false) end vanilla_model.CAPE.setEnabled(true) -- Expression change -- function getExprUV(damage, expression) local u=offset_u_face+(damage*step_u_face) local v=offset_v_face+(expression*step_v_face) return {u/size,v/size} end function changeExpression(_damage, _expression, ticks) -- u is damage, v is expression local damage = _damage local expression = _expression if damage == nil then damage = face_damage end if expression == nil then expression = face_expr end HEAD.setUV(getExprUV(damage,expression)) expr_cooldown=ticks end function setExpression(damage, expression) face_damage=damage face_expr=expression HEAD.setUV(getExprUV(damage, expression)) end function resetExpression() HEAD.setUV(getExprUV(face_damage,face_expr)) end -- Action Wheel -- action_wheel.SLOT_1.setTitle('test expression') action_wheel.SLOT_1.setFunction(function() ping.expressionTest() end) function ping.expressionTest() setExpression(1,0) changeExpression(nil, 1, 10) end action_wheel.SLOT_2.setTitle('log health') action_wheel.SLOT_2.setFunction(function() print(player.getHealth()) end) action_wheel.SLOT_3.setTitle('Toggle Armor') action_wheel.SLOT_3.setFunction(function() ping.setArmor() end) -- Pings -- --- Damage function -- function ping.oof(health) if health <= 5 then setExpression(1,0) end changeExpression(nil,1,10) end --- Heal function (revert expression) -- function ping.healed(health) setExpression(0,0) end --- Toggle Armor --- function ping.setArmor(enabled) if enabled == nil then armor_enabled=not armor_enabled else armor_enabled=enabled end for key, value in pairs(armor_model) do value.setEnabled(armor_enabled) end end -- does not work on multiplayer, use ping.oof() function onDamage(amount, source) end -- Tick function -- function tick() -- expression reset spaghetti code -- if expr_cooldown > 0 then expr_cooldown = expr_cooldown-1 if expr_cooldown <= 0 then resetExpression() end end -- optimization, only execute these once a second -- if world.getTimeOfDay() % 20 then -- if face is cracked if face_damage==1 and player.getHealth() > 5 then ping.healed() end end -- Damage ping (onDamage doesn't work in multiplayer) -- if old_health>player.getHealth() then -- debug -- print(string.format('old_health=%03.2f, player.getHealth=%03.2f', old_health,player.getHealth())) ping.oof(player.getHealth()) end -- End of tick -- old_health=player.getHealth() end -- REPL CODE {{{ if client.isHost() then local loadSecrets = false --Disable this if the REPL is slow to load. --[[>========================================<< INFO >>========================================<[]-- FIGURA REPL By: GrandpaScout [STEAM_1:0:55009667] Version: 4.1.1 Compatibility: >= Figura 0.0.8 Description: A REPL for use in Figura 0.0.8 or later. Contains formatting for types, table printing, hover data, and many other useful tools. Is also themeable! --[]>======================================<< END INFO >>======================================<]]-- --Create a completely seperated string table. local string = {} for k,v in pairs(_G.string) do string[k] = v end local function checkSMT() return pcall(function() ---@diagnostic disable: unused-local local str = "%s" local str2 = "I" local a, b a = str:byte(1,3) a = str:find("h", 1, true) a = str:format("hello") for _ in str:gmatch("h") do end a = str:gsub("h", "i", 2) a = str:len() a = str:lower() a = str:match("h", 2) a = str:rep(5, "//") a = str:reverse() a = str:sub(1, 4) a = str:upper() ---@diagnostic enable: unused-local end) end --The REPL *requires* a functional string metatable. --This will replace a missing one with a substitute. if not checkSMT() then local t = {} for k,f in pairs(string) do t[k] = f end getmetatable("").__index = t end ---@type any #Shut up type hints for this value. local Infinity = math.huge --An infinite value, for convenience. --[=========================================[ CONFIG ]=========================================]-- local repl_theme = { repl = { --Generic REPL text --[[Normal text. | color ]] default = "white", --[[INPUT: | color ]] input = "white", --[[RETURNS: | color ]] returns = "white", --[[REPL: Notice | color ]] notice = "white", --[[REPL: Error | color ]] error = "red", --[[return | color ]] repl_return = "light_purple", --[[User Code. | color ]] user_input = "white", }, any = { -- Any values --[[Prop: | color ]] h_property = "dark_gray", --[[Metatable: {} | number ]] meta_len = 16 }, null = { -- Nil values --[[nil | color ]] default = "gray", --[[(no value?) | color ]] no_value = "dark_gray" }, boolean = { -- Booleans --[[true false | color ]] default = "yellow", --[[true color | color ]] t = "dark_green", --[[false color | color ]] f = "dark_red", --[[true symbol | string ]] true_char = "☑", --[[false symbol | string ]] false_char = "☒" }, number = { -- Numbers --[[123 | color ]] default = "blue", --[[(0x7B) | color ]] hex = "dark_blue", --[[0b10 | color ]] bin = "dark_blue", --[[0o71 | color ]] oct = "dark_blue", --[[0x, 0X, #, etc. | string ]] hex_prefix = "0x", --[[0b, 0B, etc. | string ]] bin_prefix = "0b", --[[0o, 0O, 0, etc. | string ]] oct_prefix = "0o" }, string = { -- Strings --[["abc" | color ]] default = "red", --[[\r\n§ | color ]] escaped = "dark_red", --[[\ | color ]] slash = "dark_gray", --[[(# bytes) | color ]] bytes = "dark_red", --[[# characters | color ]] characters = "dark_red", --[[... | color ]] len_limit = "gray", --[[= "hello wo..." | number ]] value_size = 256, --[["hello worl..." | number ]] max_size = Infinity, --[["Hover Da..." | number ]] max_h_size = 4096, --[[\0 -> ∅ | boolean]] use_symbols = true }, table = { -- Tables --[[table: 1234abcd | color ]] default = "aqua", --[[(# indexes) | color ]] indexes = "dark_aqua", --[[{ } | color ]] bracket = "dark_gray", --[[[ ] | color ]] key_bracket = "dark_gray", --[[= | color ]] equals = "dark_gray", --[[ · · · (# more) | color ]] line_limit = "gray", --[[ | color ]] root = "white", --[[ | color ]] duplicate = "aqua", --[[["string"] = | number ]] skey_len = 16, --[[max table depth | number ]] max_indent = 1, --[[max table len | number ]] max_length = Infinity, --[[ · · · } | number ]] more_len = 48, --[[Contents: {} | number ]] content_len = 32 }, func = { -- Functions --[[function: | color ]] default = "light_purple", --[[avatar | color ]] script = "dark_purple", --[[:123-167 | color ]] lines = "dark_gray", --[[builtin: | color ]] builtin = "dark_gray", --[[figura: | color ]] figura = "dark_gray", --[[unknown: | color ]] unknown = "dark_gray", --[[(# bytes) | color ]] bytes = "dark_purple", --[[Lua | color ]] lua = "blue", --[[(JAVA) | color ]] java = "gold" }, userdata = { --[[userdata: | color ]] default = "gray", --[[1 stick | color ]] value = "gray" }, thread = { -- Threads --[[thread: 1234abc | color ]] default = "green", --[[(status) | color ]] parentheses = "dark_green", --[[Running | color ]] running = "green", --[[Suspended | color ]] suspended = "gold", --[[Normal | color ]] normal = "dark_aqua", --[[Dead | color ]] dead = "dark_red" }, vector = { -- Vectors --[[1.23 | color ]] default = "white", --[[< > | color ]] bracket = "dark_gray", --[[, | color ]] seperator = "dark_gray", --[[(#/6 indexes) | color ]] indexes = "gray", --[[123.45 | color ]] length = "gray", }, other = { -- Unknown types. --[[stringified val | color ]] default = "white", --[[(type) | color ]] type = "gray" } } --[=======================================[ END CONFIG ]=======================================]-- local replcatmt = { __metatable = false, __newindex = function(self, key, value) if self[key] == nil then error("cannot change non-existent Theme Setting") end if type(value) == "string" then rawset(self, key, value:gsub("([\\\"])", "\\%1")) else rawset(self, key, value) end end, __index = { NewSetting = function(self, name, value) if self[name] ~= nil then rawset(self, name, value or false) end end } } for _,c in pairs(repl_theme) do setmetatable(c, replcatmt) end setmetatable(repl_theme, { __metatable = false, __newindex = function(self, key) if not self[key] then error("cannot add new Theme Setting category") else error("cannot replace Theme Setting category") end end, __index = { NewCategory = function(self, name) if not self[name] then rawset(self, name, setmetatable({}, replcatmt)) end end } }) local rtr, rta, rtx, rtb, rtn, rts, rtt, rtf, rtu, rtc, rtv, rto = repl_theme.repl, repl_theme.any, repl_theme.null, repl_theme.boolean, repl_theme.number, repl_theme.string, repl_theme.table, repl_theme.func, repl_theme.userdata, repl_theme.thread, repl_theme.vector, repl_theme.other local strrep = { all = '([\0\a\b\f\n\r\t\v\\"])', --∅♪←⊻↓⏮⇄⇵ ["\0"] = {"0", "∅"}, ["\a"] = {"a", "♪"}, ["\b"] = {"b", "←"}, ["\f"] = {"f", "⊻"}, ["\n"] = {"n", "↓"}, ["\r"] = {"r", "⏮"}, ["\t"] = {"t", "⇄"}, ["\v"] = {"v", "⇵"}, ["\\"] = {"\\\\", "\\\\"}, ["\""] = {'\\"', '\\"'} } function strrep.toStr(x) return ('",{"text":"\\\\","color":"%s"},{"text":"%s","color":"%s"},"'):format( rts.slash, strrep[x][1], rts.escaped ) end function strrep.toSym(x) return ('",{"text":"%s","color":"%s"},"'):format( strrep[x][2], rts.escaped ) end local keyrank = { boolean = 0, number = 1, string = 2, table = 3, ["function"] = 4, thread = 5, vector = 6, userdata = 7, other = 99 } local function tblsort(a, b) local ar, br = keyrank[type(a)] or keyrank.other, keyrank[type(b)] or keyrank.other if ar == br then if ar == 1 then return a < b else return tostring(a) < tostring(b) end else return ar < br end end local figuraFIDs = { PingFunction = true } H = {} local H = H setmetatable(H, { __pow = function(self, ind) if self ~= H then error("index from the right side of the history list") elseif type(ind) ~= "number" then error("quick-history only works with a number") else local x,y = tostring(ind):match("^(%-?%d*)%.?(%d-)$") x,y = tonumber(x) or 1, tonumber(y) local res = self[x == 0 and 1 or #self-x+1] return res and (y and res[y] or res) or nil end end }) O = {} local O = O local Otypes = {number = true, ["function"] = true, table = true, userdata = true, thread = true, vector = true} local Omt = { __type = "PointersList", __index = { N = {}, Nindex = {} } } local Oindex, OindexN, OindexNi = Omt.__index, Omt.__index.N, Omt.__index.Nindex function Omt:__newindex(key) local t = type(key) if Otypes[t] then if t == "number" then if not OindexNi[key] then OindexN[#Oindex.N+1] = key OindexNi[key] = #Oindex.N end elseif not Oindex[key] then Oindex[#Oindex+1] = key Oindex[key] = #Oindex end end end function Omt:__len() return #Oindex end setmetatable(O, Omt) local JSON = {} do local function PointersListHover(x, hasContents) local xmt = getmetatable(x).__index local str = ('{"text":"PointerList","color":"%s"},{"text":" (table)\n","color":"%s"},[{"text":"Pointers: ","color":"%s"},{"text":"%d","color":"%s"}'):format( rtt.default, rtt.indexes, rta.h_property, #xmt, rtt.indexes ) if not hasContents then str = str .. ',"\n\nContents: "' .. JSON.stringify.custom.PointersList(x, true, true, { length = rtt.content_len, indent = "single" }) end return ('{"action":"show_text","value":[%s]]}'):format(str) end local function PointersListMoreHover(x, tbl, i) local strs = { ('{"text":" · · ·","color":"%s"}'):format(rtt.line_limit) } for j = i+1, #tbl do local v = x[j] strs[#strs+1] = (',"\n "%s,{"text":" = ","color":"%s"}%s'):format( JSON.stringify.number(j, false, true), rtt.equals, JSON.stringify.any(v, true, true, {indent = false}) ) if j >= (i+rtt.more_len) and j ~= #tbl then strs[#strs+1] = (',{"text":"\n · · · (%d more)","color":"%s"}'):format( #tbl - j, rtt.line_limit ) break end end return ('{"action":"show_text","value":[%s,{"text":"\n]","color":"%s"}]}'):format( table.concat(strs), rtt.bracket ) end local function HistoryHover(x, hasContents) --Not yet. end JSON.stringify = { ---@type table custom={ ---@param x table ---@param detail? string ---@param inHover? boolean ---@param options? {indent?:number|"false", DONE?: table, length?: number, max?: boolean} PointersList = function(x, detail, inHover, options) local xmt = getmetatable(x).__index local indent if options.indent == false then indent = rtt.max_indent + 1 else indent = tonumber(options.indent) and math.max(options.indent, 0) or 1 end local contents = indent <= rtt.max_indent local str = (',[{"text":"PointerList: %s","color":"%s"%s}'):format( tostring(x):match("^table: (%x%x?%x?%x?%x?%x?%x?%x?)$") or "???", rtt.default, not inHover and (',"insertion":"O","hoverEvent":' .. PointersListHover(x, contents)) or "" ) if contents then str = str .. (',[{"text":" [","color":"%s"}'):format(rtt.bracket) end if detail then str = str .. (',{"text":" (%d pointers)","color":"%s"}'):format( #xmt, rtt.indexes ) end if contents then local strs = {} for i,v in ipairs(xmt) do strs[#strs+1] = (',"\n%s"%s,{"text":" = ","color":"%s"}%s'):format( (" "):rep(indent), JSON.stringify.number(i, false, inHover), rtt.equals, JSON.stringify.any(v, true, inHover, {indent = false}) ) if options.length and (i >= options.length) and ((#xmt - i) ~= 0) then if inHover then strs[#strs+1] = (',{"text":"\n%s · · · (%d more)","color":"%s"}'):format( (" "):rep(indent), #xmt - i, rtt.line_limit ) else strs[#strs+1] = (',{"text":"\n%s · · · (%d more)","color":"%s","hoverEvent":%s}'):format( (" "):rep(indent), #xmt - i, rtt.line_limit, PointersListMoreHover(x, Oindex, i) ) end break end end str = str .. ('%s,"\n%s]"]'):format( table.concat(strs), (" "):rep(math.max(indent-1, 0)) ) end return str .. "]" end }, ---@param x any ---@param detail? string ---@param inHover? boolean ---@param options? {indent?:number|"false", DONE?: table, length?: number, max?: boolean} ---@return string any = function(x, detail, inHover, options) options = options or {} local t = type(x) if t == "string" then return JSON.stringify.string(x, detail, inHover, options.length) elseif t == "table" then local mt = getmetatable(x) local mtt = type(mt) == "table" and mt.__type or nil if mtt and JSON.stringify.custom[mtt] then return JSON.stringify.custom[mtt](x, detail, inHover, options) else return JSON.stringify.table(x, detail, inHover, options.indent, options.length, options.DONE) end elseif t == "vector" then return JSON.stringify.vector(x, detail, inHover, options.max) else return (JSON.stringify[t] or JSON.stringify.other)(x, detail, inHover) end end, ---@param inHover? boolean ---@return string ["nil"] = function(_, _, inHover) return (',{"text":"nil","color":"%s"%s}'):format( rtx.default, not inHover and (',"insertion":"nil","hoverEvent":%s'):format(JSON.hoverData["nil"]()) or "" ) end, ---@param x boolean ---@param detail? boolean ---@param inHover? boolean ---@return string boolean = function(x, detail, inHover) local str = (',[{"text":"%s","color":"%s"%s}'):format( tostring(x), rtb.default, not inHover and (',"insertion":"%s","hoverEvent":%s'):format( tostring(x), JSON.hoverData.boolean(x) ) or "" ) if detail then str = str .. (',{"text":" %s","color":"%s"}'):format( x and rtb.true_char or rtb.false_char, x and rtb.t or rtb.f ) end return str .. "]" end, ---@param x number ---@param detail? boolean ---@param inHover? boolean ---@return string number = function(x, detail, inHover) local unsafenum = tonumber(tostring(x)) ~= x local insert = x if unsafenum and not O.Nindex[x] then O[x] = true if not inHover then insert = "O.N[" .. O.Nindex[x] .. "]" end end local str = (',[{"text":"%s","color":"%s"%s}'):format( tostring(x), rtn.default, not inHover and (',"insertion":"%s","hoverEvent":%s'):format( insert, JSON.hoverData.number(x) ) or "" ) if detail and math.floor(x) == x and x-1 ~= x then str = str .. (',{"text":" (%s%X)","color":"%s"}'):format( rtn.hex_prefix, x, rtn.hex ) end return str .. "]" end, ---@param x string ---@param detail? boolean ---@param inHover? boolean ---@param length? number ---@return string string = function(x, detail, inHover, length) length = tonumber(length) local xstr if not length or (length <= 0) or (length >= #x) then xstr = x length = false else xstr = x:sub(1, length-4) end local firstmatch = xstr:find(strrep.all) or xstr:find("§") local str if firstmatch then str = xstr :gsub( strrep.all, rts.use_symbols and strrep.toSym or strrep.toStr ) :gsub( "§(.)", ('",{"text":"ƒ","color":"%s"},"§%%1%%1§r'):format(rts.escaped) ) str = (',[{"text":"\\"%s","color":"%s"%s}'):format( str:sub(1, firstmatch-1), rts.default, not inHover and (',"insertion":"\\"%s\\"","hoverEvent":%s'):format( x :gsub(strrep.all, function(c) return "\\\\" .. strrep[c][1] end) :gsub("§", "\\\\xC2\\\\xA7") :gsub("([\1\2\3\4\5\6\14\15\16\17\18\19\20\21\22\23\24\25\26\27\28\29\30\31\127])", function(c) return "\\\\" .. string.byte(c) end), JSON.hoverData.string(x) ) or "" ) .. str:sub(firstmatch+1) if str:find(',"$') then str = str:sub(1, -3) .. (length and (',{"text":" · · · ","color":"%s"},"\\""'):format(rts.len_limit) or ',"\\""') else str = str .. (length and ('",{"text":" · · · ","color":"%s"},"\\""'):format(rts.len_limit) or '\\""') end else str = (',[{"text":"\\"%s","color":"%s"%s}%s,"\\""'):format( xstr, rts.default, not inHover and (',"insertion":"\\"%s\\"","hoverEvent":%s'):format( x :gsub(strrep.all, function(c) return "\\\\" .. strrep[c][1] end) :gsub("§", "\\\\xC2\\\\xA7") :gsub("([\1\2\3\4\5\6\14\15\16\17\18\19\20\21\22\23\24\25\26\27\28\29\30\31\127])", function(c) return "\\\\" .. string.byte(c) end), JSON.hoverData.string(x) ) or "", length and (',{"text":" · · · ","color":"%s"}'):format(rts.len_limit) or "" ) end if detail then str = str .. (',{"text":" (%d byte%s)","color":"%s"}'):format( #x, #x ~= 1 and "s" or "", rts.bytes ) end return str .. "]" end, ---@param x table ---@param detail? boolean ---@param inHover? boolean ---@param indent? "false"|number|'"single"' ---@param length? number ---@param DONE? table ---@return string table = function(x, detail, inHover, indent, length, DONE) local noindent if indent == false then indent = rtt.max_indent + 1 elseif indent == "single" then noindent = true indent = 1 end indent = indent == nil and 1 or math.max(indent, 0) if not O[x] then O[x] = true end local insert = "O[" .. O[x] .. "]" local contents = indent <= rtt.max_indent local xlen = 0 if not inHover or detail then for _ in pairs(x) do --Iterate the table for *every* key to get the real size. xlen = xlen + 1 end if xlen == 0 then xlen = tonumber(#x) or 0 end --If a table cannot be iterated, try getting the length. If that fails, use 0. end local str = (',[{"text":"%s","color":"%s"%s}'):format( tostring(x), rtt.default, not inHover and (',"insertion":"%s","hoverEvent":%s'):format( insert, JSON.hoverData.table(x, contents, xlen) ) or "" ) if contents then str = str .. (',{"text":" {","color":"%s"}'):format(rtt.bracket) end if detail then str = str .. (',{"text":" (%d index%s)","color":"%s"}'):format( xlen, xlen ~= 1 and "es" or "", rtt.indexes ) end if contents and not next(x) then str = str .. (',{"text":"%s}","color":"%s"}'):format( detail and " " or "", rtt.bracket ) contents = false end str = str .. "]" if not DONE then --DONE handles recursion. DONE = {} DONE.root = x DONE[x] = true elseif DONE.root == x then str = str .. (',{"text":" ","color":"%s"}'):format(rtt.root) elseif DONE[x] then str = str .. (',{"text":" ","color":"%s"}'):format(rtt.duplicate) else DONE[x] = true end if contents then local keys = {} for k in pairs(x) do --Get all keys and sort them. keys[#keys+1] = k end table.sort(keys, tblsort) local strs = {} for i,k in ipairs(keys) do local v = x[k] strs[#strs+1] = (',[{"text":"\n%s[","color":"%s"}%s,"]"],{"text":" = ","color":"%s"}%s'):format( noindent and " " or (" "):rep(indent*2), rtt.key_bracket, JSON.stringify.any(k, false, inHover, { length = rtt.skey_len, indent = false, max = false }), rtt.equals, JSON.stringify.any(v, true, inHover, { indent = ((not DONE[v] and not noindent) and (indent + 1) or false), length = rts.value_size, DONE = DONE }) ) if length and (i >= length) and ((#keys - i) ~= 0) then --If the line limit is hit, stop the table early. if inHover then strs[#strs+1] = (',{"text":"\n%s · · · (%d more)","color":"%s"}'):format( (" "):rep(indent), #keys - i, rtt.line_limit ) else strs[#strs+1] = (',{"text":"\n%s · · · (%d more)","color":"%s","hoverEvent":%s}'):format( (" "):rep(indent), #keys - i, rtt.line_limit, JSON.hoverData.tableMore(x, keys, i) ) end break end end str = str .. ('%s,{"text":"\n%s}","color":"%s"}'):format( table.concat(strs), (" "):rep(math.max(indent-1, 0)), rtt.bracket ) end return str end, ---@param x function ---@param detail? boolean ---@param inHover? boolean ---@return string ["function"] = function(x, detail, inHover) local s, dump = pcall(string.dump, x) local insert if not inHover then if not O[x] then O[x] = true end insert = "O[" .. O[x] .. "]" end local str if s then local fname, flines = tostring(x):match("^function: ([^:]+)(:%d+%-%d+)$") str = (',[{"text":"function:","color":"%s"%s},{"text":" %s","color":"%s"},{"text":"%s","color":"%s"}'):format( rtf.default, not inHover and (',"insertion":"%s","hoverEvent":%s'):format( insert, JSON.hoverData["function"](x, #dump) ) or "", fname:gsub("([\\\"])", "\\%1"), rtf.script, flines, rtf.lines ) else local fid = tostring(x):match(" ?([%w_]+)$") local ftype = fid and ( (tonumber(fid) or figuraFIDs[fid]) and "figura" or "builtin" ) or "unknown" str = (',[{"text":""%s},[{"text":"function: ","color":"%s"},{"text":"%s:","color":"%s"},"%s"]'):format( not inHover and (',"insertion":"%s","hoverEvent":%s'):format( insert, JSON.hoverData["function"](x) ) or "", rtf.default, ftype, rtf[ftype], (fid or ""):gsub("([\\\"])", "\\%1") ) end if detail then if s then str = str .. (',{"text":" (%d byte%s)","color":"%s"}'):format( #dump, #dump ~= 1 and "s" or "", rtf.bytes ) else str = str .. (',{"text":" (JAVA)","color":"%s"}'):format(rtf.java) end end return str .. "]" end, ---@param x userdata ---@param inHover? boolean ---@return string userdata = function(x, _, inHover) local ustr = tostring(x):gsub("([\\\"])", "\\%1") local insert if not inHover then if not O[x] then O[x] = true end insert = "O[" .. O[x] .. "]" end if ustr:match("^userdata: ") then ustr = ustr:sub(11) end return (',[{"text":"userdata: ","color":"%s"%s},{"text":"%s","color":"%s"}]'):format( rtu.default, not inHover and (',"insertion":"%s","hoverEvent":%s'):format( insert, JSON.hoverData.userdata(x) ) or "", ustr, rtu.value ) end, ---@param x thread ---@param detail? boolean ---@param inHover? boolean ---@return string thread = function(x, detail, inHover) local insert local status if detail or not inHover then status = coroutine.status(x) end if not inHover then if not O[x] then O[x] = true end insert = "O[" .. O[x] .. "]" end local str = (',[{"text":"%s","color":"%s"%s}'):format( tostring(x), rtc.default, not inHover and (',"insertion":"%s","hoverEvent":%s'):format( insert, JSON.hoverData.thread(x, status) ) or "" ) if detail then str = str .. (',[{"text":" (","color":"%s"},{"text":"%s","color":"%s"},")"]'):format( rtc.parentheses, status:gsub("^.", string.upper), rtc[status] ) end return str .. "]" end, ---@param x Vector ---@param detail? boolean ---@param inHover? boolean ---@param max? boolean ---@return string vector = function(x, detail, inHover, max) max = max == nil or max local insert if not inHover then if not O[x] then O[x] = true end insert = "O[" .. O[x] .. "]" end local i = 1 for j=6,1,-1 do if x[j] ~= 0 then i = j break end end local strs = {} if max then for j = 1, i do strs[#strs+1] = (',"%f"'):format(x[j]) end else for j = 1, i do local fstr = tostring(x[j]) local fsub = fstr:sub(1, (fstr:find("%..*$") or #fstr) + 5) strs[#strs+1] = (',"%s%s"'):format( fsub, (#fstr > #fsub) and "..." or "" ) end end strs[1] = (',[{"text":""%s},[{"text":"<","color":"%s"},[{"text":%s,"color":"%s"}'):format( not inHover and (',"insertion":"%s","hoverEvent":%s'):format( insert, JSON.hoverData.vector(x) ) or "", rtv.bracket, strs[1]:sub(2), rtv.default ) strs[#strs] = strs[#strs] .. '],">"]' local sep = (',{"text":",","color":"%s"}'):format(rtv.seperator) local str = table.concat(strs, sep) if detail then str = str .. (',{"text":" (%d/6 indexes)","color":"%s"}'):format( i, rtv.indexes ) end return str .. "]" end, ---@param x any ---@param detail? boolean ---@param inHover? boolean ---@return string other = function(x, detail, inHover) local str = (',[{"text":"%s","color":"%s"%s}'):format( tostring(x):gsub("([\\\"])", "\\%1"), rto.default, not inHover and (',"hoverEvent":' .. JSON.hoverData.other(x)) or "" ) if detail then str = str .. (',{"text":" (%s)","color":"%s"}'):format( type(x), rto.type ) end return str .. "]" end } local o2b = { ["0"] = "000", ["1"] = "001", ["2"] = "010", ["3"] = "011", ["4"] = "100", ["5"] = "101", ["6"] = "110", ["7"] = "111" } local vectorObj = { asTable = 1, toDeg = 2, toRad = 3, angleTo = 4, cross = 5, dot = 6, normalized = 7, getLength = 8, distanceTo = 9 } function JSON.stringify.vectorMethods() local str = (',{"text":"table: LuaVector","color":"%s"},{"text":" {","color":"%s"},{"text":" (9 indexes)","color":"%s"}'):format( rtt.default, rtt.bracket, rtt.indexes ) local keys = {} for k in pairs(vectorObj) do keys[#keys+1] = k end table.sort(keys) local strs = {} for _, k in ipairs(keys) do local v = vectorObj[k] strs[#strs+1] = (',[{"text":"\n [","color":"%s"}%s,"]"],{"text":" = ","color":"%s"},[{"text":"function: ","color":"%s"},{"text":"figura:","color":"%s"},"%s"],{"text":" (JAVA)","color":"%s"}'):format( rtt.key_bracket, JSON.stringify.any(k, false, false, {length = rtt.skey_len, indent = false, max = false}), rtt.equals, rtf.default, rtf.figura, v, rtf.java ) end return str .. ('%s,{"text":"\n}","color":"%s"}'):format( table.concat(strs), rtt.bracket ) end JSON.hoverData = { ["nil"] = function() return ('{"action":"show_text","value":[{"text":"Nil\nnil","color":"%s"}]}'):format(rtx.default) end, boolean = function(x) return ('{"action":"show_text","value":[{"text":"Boolean\n","color":"%s"},{"text":"%s","color":"%s"}]}'):format( rtb.default, tostring(x), x and rtb.t or rtb.f ) end, number = function(x) local str = ('{"text":"Number\n%s","color":"%s"}'):format( tostring(x), rtn.default ) if math.floor(x) == x and math.abs(x) <= 0x7FFFFFFFFFFFFFFF then local sign = x < 0 and "-" or "" x = math.abs(x) local ostr = ("%o"):format(x) str = str .. (',[{"text":"\nHex: ","color":"%s"},{"text":"%s%s%x\n","color":"%s"},"Oct: ",{"text":"%s%s%s\n","color":"%s"},"Bin: ",{"text":"%s%s%s","color":"%s"}]'):format( rta.h_property, sign, rtn.hex_prefix, x, rtn.hex, sign, rtn.oct_prefix, ostr, rtn.oct, sign, rtn.bin_prefix, ostr:gsub(".", o2b):gsub("^0+", "", 1), rtn.bin ) end return ('{"action":"show_text","value":[%s]}'):format(str) end, string = function(x) local chars = 0 for i = 1, #x do if math.floor(x:byte(i) * 0.015625) ~= 2 then chars = chars + 1 end end local mt = getmetatable("") return ('{"action":"show_text","value":[{"text":"String\n","color":"%s"}%s,[{"text":"\nBytes: ","color":"%s"},{"text":"%d\n","color":"%s"},"Characters: ",{"text":"%d\n\n","color":"%s"},"Metatable: "%s]]}'):format( rts.default, JSON.stringify.string(x, false, true, rts.max_h_size), rta.h_property, #x, rts.bytes, chars, rts.characters, JSON.stringify.any(mt, true, true, { indent = "single", length = type(mt) == "string" and rts.value_size or rta.meta_len }) ) end, table = function(x, contentVisible, size) local mt = getmetatable(x) local str = ('{"text":"Table\n%s\n","color":"%s"},[{"text":"Indexes: ","color":"%s"},{"text":"%d\n\n","color":"%s"},"Metatable: "%s'):format( tostring(x), rtt.default, rta.h_property, size, rtt.indexes, JSON.stringify.any(mt, true, true, { indent = "single", length = type(mt) == "string" and rts.value_size or rta.meta_len }) ) if not contentVisible then str = str .. (',"\n\nContents: "' .. JSON.stringify.table(x, false, true, "single", rtt.content_len)) end return ('{"action":"show_text","value":[%s]]}'):format(str) end, tableMore = function(x, keys, i) local strs = { ('{"text":" · · ·","color":"%s"}'):format(rtt.line_limit) } for j = i+1, #keys do local k = keys[j] local v = x[k] strs[#strs+1] = (',[{"text":"\n [","color":"%s"}%s,"]"],{"text":" = ","color":"%s"}%s'):format( rtt.key_bracket, JSON.stringify.any(k, false, true, { indent = false, length = rtt.skey_len, max = false }), rtt.equals, JSON.stringify.any(v, true, true, { indent = false, length = rts.value_size }) ) if j >= (i+rtt.more_len) and j ~= #keys then strs[#strs+1] = (',{"text":"\n · · · (%d more)","color":"%s"}'):format( #keys - j, rtt.line_limit ) break end end return ('{"action":"show_text","value":[%s,{"text":"\n}","color":"%s"}]}'):format( table.concat(strs), rtt.bracket ) end, ["function"] = function(x, size) local str = ('{"text":"Function\n","color":"%s"}%s,[{"text":"\nSource: ","color":"%s"},{"text":"%s","color":"%s"}'):format( rtf.default, JSON.stringify["function"](x, false, true), rta.h_property, size and "Lua" or "Java", size and rtf.lua or rtf.java ) if size then str = str .. (',"\nBytes: ",{"text":"%d","color":"%s"}'):format( size, rtf.bytes ) end return ('{"action":"show_text","value":[%s]]}'):format(str) end, userdata = function(x) return ('{"action":"show_text","value":[{"text":"Userdata\n","color":"%s"},{"text":"%s","color":"%s"}]}'):format( rtu.default, tostring(x):gsub("([\\\"])", "\\%1"), rtu.value ) end, thread = function(x, status) return ('{"action":"show_text","value":[{"text":"Thread\n%s\n","color":"%s"},{"text":"Status: ","color":"%s"},{"text":"%s","color":"%s"}]'):format( tostring(x), rtc.default, rta.h_property, status, rtc[status] ) end, vector = function(x) local str = ('{"text":"Vector\n","color":"%s"}%s,[{"text":"\nLength: ","color":"%s"},{"text":"%f\n","color":"%s"}'):format( rtv.default, JSON.stringify.vector(x, false, true, true), rta.h_property, x.getLength(), rtv.length ) if (x[1] >= 0 and x[1] <= 1) and (x[2] >= 0 and x[2] <= 1) and (x[3] >= 0 and x[3] <= 1) then local rgb_r,rgb_g,rgb_b = math.floor(x[1]*255), math.floor(x[2]*255), math.floor(x[3]*255) local rgb_hsv = vectors.rgbToHSV(x) local rgb_h,rgb_s,rgb_v = math.floor(rgb_hsv[1]*360)%360, math.floor(rgb_hsv[2]*10000)*0.01, math.floor(rgb_hsv[3]*10000)*0.01 local hsv_h, hsv_s, hsv_v = math.floor(x[1]*360)%360, math.floor(x[2]*10000)*0.01, math.floor(x[3]*10000)*0.01 local hsv_rgb = vectors.hsvToRGB(x) local hsv_r, hsv_g, hsv_b = math.floor(hsv_rgb[1]*255), math.floor(hsv_rgb[2]*255), math.floor(hsv_rgb[3]*255) str = str .. (',"\n[RGB]:\n Color: ",{"text":"Lorem_Ipsum █ ⏹⏺◆\n","color":"#%06X"}," RGB: ",{"text":"⏺ %d","color":"#%02X0000"},", ",{"text":"⏺ %d","color":"#00%02X00"},", ",{"text":"⏺ %d\n","color":"#0000%02X"}," HSV: ",{"text":"⏺ %d°","color":"#%06X"},", ",{"text":"⏺ %s%%","color":"#%06X"},", ",{"text":"⏺ %s%%\n","color":"#%06X"},"[HSV]:\n Color: ",{"text":"Lorem_Ipsum █ ⏹⏺◆\n","color":"#%06X"}," HSV: ",{"text":"⏺ %d°","color":"#%06X"},", ",{"text":"⏺ %s%%","color":"#%06X"},", ",{"text":"⏺ %s%%\n","color":"#%06X"}," RGB: ",{"text":"⏺ %d","color":"#%02X0000"},", ",{"text":"⏺ %d","color":"#00%02X00"},", ",{"text":"⏺ %d\n","color":"#0000%02X"}'):format( vectors.rgbToINT(x), rgb_r, rgb_r, rgb_g, rgb_g, rgb_b, rgb_b, rgb_h, vectors.rgbToINT(vectors.hsvToRGB(vectors.of{rgb_hsv[1], 1, 1})), tostring(rgb_s), vectors.rgbToINT(vectors.hsvToRGB(vectors.of{0, rgb_hsv[2], 1})), tostring(rgb_v), vectors.rgbToINT(vectors.hsvToRGB(vectors.of{0, 0, rgb_hsv[3]})), vectors.rgbToINT(vectors.hsvToRGB(x)), hsv_h, vectors.rgbToINT(vectors.hsvToRGB(vectors.of{x[1], 1, 1})), tostring(hsv_s), vectors.rgbToINT(vectors.hsvToRGB(vectors.of{0, x[2], 1})), tostring(hsv_v), vectors.rgbToINT(vectors.hsvToRGB(vectors.of{0, 0, x[3]})), hsv_r, hsv_r, hsv_g, hsv_g, hsv_b, hsv_b ) end return ('{"action":"show_text","value":[%s,"\nMethods: "%s]]}'):format( str, JSON.stringify.vectorMethods() ) end, other = function(x) return ('{"action":"show_text","value":[{"text":"%s\n","color":"%s"},{"text":"%s","color":"%s"}]}'):format( type(x):gsub("^.", string.upper), rto.type, tostring(x):gsub("\\\"", "\\%1"), rto.default ) end } end local rotbl = { __metatable = false, __newindex = function() error("attempt to modify read-only table") end } REPL = { currentcommand = "", stringify = JSON.stringify, theme = repl_theme, bound = false, key = keybind.newKey("[REPL] Bind to Chat", "GRAVE_ACCENT"), keyWP = false, log = function(x, detail, inHover, options) options = type(options) == "table" and options or {} log(('[{"text":"","italic":false}%s]'):format( JSON.stringify.any(x, detail, inHover, { indent = options.indent, length = options.length, max = options.max }) ), true) end, ---@type {boolean: number, number: string, string: table, table: Vector, Vector: userdata, userdata: boolean} testtable = setmetatable({ [true] = 123.456, [123.456] = "\abcxyz", ["qwer\ty"] = setmetatable({"hello", "world", setmetatable({"!"}, rotbl)}, rotbl), [setmetatable({"foo","bar","baz",yalike="jazz?"}, rotbl)] = vectors.of{1,2,3,4,5,math.sqrt(2)}, [vectors.of{1,2,3,4,5,math.sqrt(2)}] = item_stack.createItem("minecraft:stick")["figura$item_stack"], [item_stack.createItem("minecraft:stone")["figura$item_stack"]] = false }, rotbl), RegisterStringifier = function(name, stringify) end } local REPL = REPL local REPLSuperActions = { fixstringmt = { func = function() local t = {} for k,f in pairs(string) do t[k] = f end getmetatable("").__index = t log("Set string metatable index to " .. tostring(string)) end, desc = "Repairs the string metatable.", help = "Repairs the string metatable.\n" .. "This is useful if you somehow broke string methods.\n" .. "The string metatable is required to be functional for the REPL to run.\n" .. "Usage:\n" .. " $$#fixstringmt" }, error = { func = function() error("forced critical REPL error.") end, desc = "Force a critical error in the REPL.", help = "Force a critical error in the REPL.\n" .. "Used to emulate a Lua error in the REPL itself instead of an error with REPL input.\n" .. "Usage:\n" .. " $$#error" }, avatarerror = { func = function(yes) if yes == "yes" then return "\0\9\0\70\79\82\67\69\0\9\0" else log("Please use \"$$#avatarerror yes\" to confirm.") end end, desc = "Force your avatar to error.", help = "Force your avatar to error.\n" .. "The only way to reverse this action is to reload the avatar.\n" .. "Usage:\n" .. " $$#avatarerror - Does nothing.\n" .. " $$#avatarerror yes - Causes an avatar error." }, mlcancel = { func = function() if REPL.currentcommand == "" then log("There is no current Multi-line input!") else REPL.currentcommand = "" end end, desc = "Cancels the current multi-line input.", help = "Cancels the current multi-line input.\n" .. "Useful if you want to cancel an entire chunk of multi-line Lua without causing issues.\n" .. "Usage:\n" .. " $$#mlcancel" }, mlback = { func = function() local lastline = REPL.currentcommand:find("[^\n]*\n$") if lastline then REPL.currentcommand = REPL.currentcommand:sub(1, lastline-1) else log("There is no current Multi-line input!") end end, desc = "Deletes the last line of a multi-line input.", help = "Deletes the last line of a multi-line input.\n" .. "Useful if you make an error and you want to try again.\n" .. "Usage:\n" .. " $$#mlback" }, mlrun = { func = function() if REPL.currentcommand == "" then log("There is no current Multi-line input!") else REPL() end end, desc = "Run the current Multi-line input as is.", help = "Run the current Multi-line input as is.\n" .. "Useful if you accidentally start a new line instead of running the input.\n" .. "Usage:\n" .. " $$#mlrun" }, mlprint = { func = function() if REPL.currentcommand == "" then log("There is no current Multi-line input!") else log(('[{"text":"Current input:\n","italic":false},{"text":"%s","color":"%s"}]'):format( REPL.currentcommand:gsub("([\\\"])", "\\%1"), rtr.user_input ), true) end end, desc = "Prints the current Multi-line input to chat.", help = "Prints the current Multi-line input to chat.\n" .. "Useful if you forgot where you were in your multi-line input.\n" .. "Usage:\n" .. " $$#mlprint" }, set = { func = function(args) local cat, set, val = args:match("^([^.]*)%.?(%S*) ?(.*)$") if cat == "" then local options = {} for k in pairs(repl_theme) do if k ~= "" then options[#options+1] = k end end table.sort(options) local strs = {} for _,k in ipairs(options) do strs[#strs+1] = k end log("Categories:\n" .. table.concat(strs, ", ")) elseif not repl_theme[cat] then log(("Theme category [%s] not found.\nUse \"$$#set\" to list all categories."):format(cat)) elseif set == "" then local tcat = repl_theme[cat] local options = {} for k in pairs(tcat) do if k ~= "" then options[#options+1] = k end end table.sort(options) local strs = {} for _,k in ipairs(options) do local v = tcat[k] strs[#strs+1] = ("[%s] - %s"):format( k, (type(v) == "string" and not v:match("^#%x%x%x%x%x%x$")) and ('"' .. tostring(v):gsub("([\\\"])", "\\%1") .. '"') or tostring(v) ) end log("Settings for category:\n[" .. cat .. "]:\n " .. table.concat(strs, "\n ")) elseif repl_theme[cat][set] == nil then log(("Theme setting [%s.%s] not found.\nUse \"$$#set %s\" to list all settings in this category."):format( cat, set, cat )) elseif val == "" then local tset = repl_theme[cat][set] local tsett = type(tset) log(("Value for setting:\n[%s.%s]:\n %s"):format( cat, set, (tsett == "string" and not tset:match("^#%x%x%x%x%x%x$")) and ('"' .. tostring(tset):gsub("([\\\"])", "\\%1") .. '"') or (tsett == "number" and math.abs(tset) == math.huge) and (tset < 0 and "-Infinity" or "Infinity") or tostring(tset) )) else ---@type string|number|boolean local value if val:match("^\".+\"$") then value = val:sub(2,-2) elseif val:match("^#%x%x%x%x%x%x$") then value = val elseif tonumber(val) then value = tonumber(val) elseif val == "true" or val == "false" then value = val == "true" elseif val:match("^%-?[Ii]nfinity$") or val:match("^%-?[Ii]nf$") then local m = val:sub(1,1) == "-" value = m and -math.huge or math.huge else log("Invalid value. Please do \"$$#help set\" to see what values can be used.") return end repl_theme[cat][set] = value end end, desc = "Quickly set REPL theme settings.", help = "Quickly set REPL theme settings.\n" .. "Please make sure you are using sane values. The resulting value is not checked.\n" .. "Usage:\n" .. " $$#set - View all categories.\n" .. " $$#set - View all settings in the category.\n" .. " $$#set - View the current value for this setting.\n" .. " $$#set - Sets the setting to the given value.\n" .. " can be:\n" .. " {string} (\"string\"),\n" .. " {number} (123.45),\n" .. " {boolean} (true/false)" } } local RSABlCSt, RSABlCStT, RSABlCStH = false, "", "" if loadSecrets then --[[ I see you are poking around... Everything in this block is part of the "REPL Secret" and is for fun. If you ruin the fun and cheat to view these then I will be disappointed in you :( If you *really* want a hint to one of them, mention GrandpaScout with the message "I need a REPL moment." in Blancworks' general chat. You will get a reply as soon as the message is recieved. The reply will have a warning and will be spoilered to avoid spoiling it for others. ]]-- local function RSASt2Sc(a) ---@diagnostic disable-next-line: deprecated return loadstring("return ".. loadstring(([[return(%s):gsub("(%%d%%d%%d)",function(a)return _G["\115\116\114\105\110\103"]["\99\104\97\114"](_G["\116\111\110\117\109\98\101\114"](a))end)]]):format(a))())() end RSABlCSt = RSASt2Sc[[(0 ..0x1EF6BAD164A9 ..0x9EB5E76D48F ..0x3BE5BEF1E60 ..0x931D9C4F0FF ..0x24F8D26F541A ..0x3DF25A8612EC ..0x98F37246B83 ..0x6C7D92)]] RSABlCStT = RSASt2Sc[[(0 ..0x1EFD07B8A344 ..0x93226C12A77 ..0x40AF269AE82A ..0x5A25443C9646 ..0xA76E7ABBE7B ..0x4)]] RSABlCStH = RSASt2Sc[[(0 ..0x319C4710DF4 ..0x4998C482275A ..0x630D54ECBA1 ..0x12A095FD6C98 ..0xBBA2)]] local a = RSASt2Sc[[( 0x0B3231CBD021 ..0x526905BAC99C ..0x00E6C5CD67E7 ..0x0921A115728F ..0x095F167E326F ..0x256F8B738488 ..0x1EF9C105B2BE ..0x0AA6D8708B36 ..0x37FFC3C02FD8 ..0x1F0351679E0F ..0x0A5F0FF3BF8B ..0x2E1CAD3F0564 ..0x3C13A2D6FE82 ..0x098F6CC348DA ..0x2E601D23269C ..0x08D4F9787560 ..0x2DD4705871B5 ..0x0F8DA57AE936 ..0x091955403431 ..0x12A095FD6C98 ..0x045F43E24636 ..0x496349555AA0 ..0x085F29620443 ..0x2539E689E835 ..0x00000104F145 )]] REPLSuperActions[RSASt2Sc[[(0 ..0x1F0315CCDFC6 ..0x643B6EA)]]] = a REPLSuperActions[RSASt2Sc[[(0 ..0x1F0315BDB4FD ..0x1D8CA)]]] = a REPLSuperActions[RSASt2Sc[[(0 ..0x1F047A97F46A ..0xAA6C6738BDF ..0xFC2)]]] = a REPLSuperActions[RSASt2Sc[[(0 ..0x1F047AD4F98C ..0x1B5A2)]]] = RSASt2Sc[[( 0x0B3231CBD021 ..0x526905BAC99C ..0x00E6C5CD67E7 ..0x0921A115728F ..0x095F167E326F ..0x256F8B738488 ..0x0318F9B3C707 ..0x096309D1B6DE ..0x1D2BD5A43A75 ..0x0B01FF8B9727 ..0x03AACC21F4F4 ..0x09D52E028E0C ..0x24B09E71EFA9 ..0x0102C4CE21EB ..0x24B2D7A235E2 ..0x04A4A5F8F2EC ..0x03AB436705C1 ..0x09D5049A462D ..0x075E6A9EBC93 ..0x09328033F89B ..0x058F8DC725F1 ..0x09322728DDB9 ..0x0967AEE45498 ..0x045FBAF1B627 ..0x1BE76712F45C ..0x085F29620449 ..0x12A073723033 ..0x0EA7DC39C645 )]] REPLSuperActions[RSASt2Sc[[(0 ..0x1F0351C34AC9 ..0x18AAA)]]] = RSASt2Sc[[( 0x0B3231CBD021 ..0x526905BAC99C ..0x00E6C5CD67E7 ..0x0921A115728F ..0x095F167E326F ..0x256F8B738488 ..0x0318F9B3C76A ..0x2DE00D6584B4 ..0x08D4DB95B5F6 ..0x401553900D14 ..0x09039C3D3DE7 ..0x24B085F6127E ..0x045EBABED2C9 ..0x0669EDFBF082 ..0x098F6CC348DA ..0x2E601D23269C ..0x08D4F9787560 ..0x2DD4705871B5 ..0x0F8DA57AE936 ..0x091955403431 ..0x12A095FD6C98 ..0x045F43E24636 ..0x496349555AA0 ..0x085F29620443 ..0x2539E689E835 ..0x00000104F145 )]] a = RSASt2Sc[[( 0x0B3231CBD021 ..0x526905BAC99C ..0x00E6C5CD67E7 ..0x0921A115728F ..0x095F167E326F ..0x256F8B738488 ..0x1EF9C1060C97 ..0x0AA4DDBC283F ..0x49ADE03DDEFC ..0x58510B785A74 ..0x0A192ADEE53F ..0x06789D11CEAD ..0x09309D5D23C3 ..0x492DA202AD14 ..0x09039C3D3DE7 ..0x24B085F6127E ..0x04BC4DDD3629 ..0x03AFE7425482 ..0x098F6CC348DA ..0x2E601D23269C ..0x08D4F9787560 ..0x2DD4705871B5 ..0x0F8DA57AE936 ..0x091955403431 ..0x12A095FD6C98 ..0x045F43E24636 ..0x496349555AA0 ..0x085F29620443 ..0x2539E689E835 ..0x00000104F145 )]] REPLSuperActions[RSASt2Sc[[(0 ..0x1F065843EBC8 ..0xA77F9EE04FB ..0x16BA79CB2)]]] = a REPLSuperActions[RSASt2Sc[[(0 ..0x1F065843EBC8 ..0xA77F9EE04FB ..0x58C86BD53DA)]]] = a a = RSASt2Sc[[( (0x0B3231CBD021 ..0x526905BAC99C ..0x00E6C5CD67E7 ..0x0921A115728F ..0x095F167E326F ..0x256F8B738488 ..0x004F4C2B94B9 ..0x0927B29E72B8 ..0x0A8F4258B5A2 ..0x40B5F99E5396 ..0x1D359CF9FCA8 ..0x093227415F8F ..0x03BAD88F4BD9 ..0x0960E1E54627 ..0x1312B7069280 ..0x3C1FFDA52053 ..0x0AD545908417 ..0x0493A07AE0C5 ..0x09EC94A89ECF ..0x37ABA370E8B7 ..0x0CC31A671095 ..0x0A6116DBD22A ..0x2E79E2C4ADF9 ..0x09294F8018A1 ..0x0ABDC101B39E ..0x0103D8B25B08 ..0x09D528777C0B ..0x0100963B66CA ..0x0931D9C4D60B ..0x01E933FB41AC ..0x09309D5D2DE7 ..0x132C54246601 ..0x0A18E4AE4540 ..0x098F0779E887 ..0x02C1F75E606D ..0x001927372A29 ..0x091AA8A55EE7 ..0x01EAD46133EC ..0x098F49090CEA ..0x2E77941DDCEF ..0x0E94C449A790 ..0x00FE054A7CF9 ..0x092DC0A2F420 ..0x0A1B259F98E7 ..0x40B87F163209 ..0x0101775D7E7B ..0x01D9210E2115 ..0x09ECAC09112A ..0x01020063F0A0 ..0x094975AAFEC9 ..0x40A5E123574B ..0x0DABEFF0F2C9 ..0x098F49090CEB ..0x378437C7CA84 ..0x1D32D14DE7F4 ..0x0932450EA80B ..0x058ED5E5D4A5 ..0x09D5168FBE8B ..0x0A26A1E281C5 ..0x015E45C6D07B ..0x01D920B2B6B1 ..0x0960827C8BAF ..0x131E5BDCBFE0 ..0x09039C404CB7 ..0x3773F0D38679 ..0x1320EADB2301 ..0x0A0389363985 ..0x4090E5927D03 ..0x00034460CF56 ..0x09190DE47A4D ..0x52D421A51444 ..0x1D359CFA0C96 ..0x0960D57C6D86 ..0x04A72F903F46 ..0x098F1F6562B1 ..0x4010CE147020 ..0x1D2AE766AA55 ..0x093244C6FE4F ..0x131E5BDCBFE1 ..0x0EA3E659D556 ..0x095EE744A18E ..0x52C5FDDC5883 ..0x0E94C4498850 ..0x0A8F425ECE2F ..0x24ABF6F09BCA ..0x1D359D63BF30 ..0x001A918D7B19 ..0x091AA8A560E3 ..0x0103617D1188 ..0x093056460A3F ..0x01EC3AD79B15 ..0x09190DE47D6E ..0x409EB84AD00C ..0x1D220C37D0B1 ..0x09EC4D20890F ..0x377D43F1357D ..0x0A1BAFEF6754 ..0x0AD4F228E78F ..0x01E8809231D6 ..0x095EE727872B).. (0x2E6E418DA17A ..0x02EB51AF40D3 ..0x1317634C9DBB ..0x0A1C67B14229 ..0x0A0377C3F9C2 ..0x2E62A2ADC9C8 ..0x1D3130D88840 ..0x094975AAFECB ..0x0677EA332C5C ..0x098F49090CEB ..0x378437BCA5DC ..0x078E0E18161B ..0x09FF139C4BCE ..0x03BBA1DA607B ..0x127B495C1D83 ..0x0CD57F94E666 ..0x0A1B133DC452 ..0x0A0D08F387B0 ..0x08D3346EFC8E ..0x075C131CAD33 ..0x00F2637C0F00 ..0x008BD13625D9 ..0x091FC3B55529 ..0x0A03DD11CC59 ..0x2DC446968B64 ..0x1D33FB53BEA1 ..0x0A038936385A ..0x03BAD88F4BD9 ..0x0960E1E54627 ..0x131C0D2E7733 ..0x00178D128D67 ..0x000255F5A756 ..0x09190D939F79 ..0x40AA7D457155 ..0x0019E1ADB859 ..0x091FC3B568B1 ..0x09EC2365DCFF ..0x2DC446968B64 ..0x1D3130BA4E39 ..0x0B03EDD8BB91 ..0x40A828AC8FDB ..0x001785E05BD7 ..0x000255F5A756 ..0x09190DD84A5C ..0x2537AFA5FE41 ..0x0EA58738B0B0 ..0x09322D31273A ..0x096316ECF856 ..0x1D356225BB30 ..0x0A1B13BDD70B ..0x52CD20BEFB00 ..0x06A4693D09E0 ..0x2537AFA5FE41 ..0x0EA58738B0B0 ..0x09322D31273A ..0x096316ECF856 ..0x1D3561D944F6 ..0x09190DDFE92A ..0x01014DEDE7F4 ..0x098F43101EAA ..0x03BADD178B50 ..0x098F49090CEB ..0x0A26A1E281C5 ..0x015E45C6D07B ..0x127B6395D472 ..0x1D34AE613548 ..0x09D4EC5CA786 ..0x2563BE16E3B5 ..0x1320EBCF46B8 ..0x09EC1D6E7557 ..0x133353413073 ..0x0CD669798C41 ..0x0AA684E45139 ..0x01EB47B5B174 ..0x0977CA8104CA ..0x0A1B026CD2B2 ..0x02EBC2E5CAEF ..0x057C75B85093 ..0x09305656D12A ..0x0962F7566B8B ..0x092F62683BCA ..0x09BDF7580BF6 ..0x0A220222F4C4 ..0x1D312C325135 ..0x0A8F89E55DAB ..0x01EBC373EE4B ..0x09309DB8C07B ..0x127B6395D472 ..0x1D3130401531 ..0x010061AC794B ..0x092F98D37A37 ..0x091AA9227E2F ..0x37948BDC2E71 ..0x0A18E4AE3988 ..0x0930560A8779 ..0x40AA7D52B847 ..0x0CD491948E33 ..0x09323F1BEF3F ..0x24C7E2BC9020 ..0x1D3130D88840).. (0x0A1ACBB738B7 ..0x0A28FBE66922 ..0x1D2F8ED6CC54 ..0x0109A7234680 ..0x06607895CF9C ..0x24ABD7F58B7C ..0x2D85A64E0844 ..0x093256E7447E ..0x075FCD15984F ..0x09EC70D924FB ..0x0A1D2DE523CB ..0x092F98D34B56 ..0x0B01FF8B997F ..0x37A284216390 ..0x3C1FFDA52053 ..0x0AD545908417 ..0x0493A089FBFE ..0x09321B4DFF2A ..0x0A22004EA97D ..0x0A1BAFEFBD47 ..0x0A60C358BDA2 ..0x1B93AF0E6BA1 ..0x0EA58738B086 ..0x098F1F6562B1 ..0x3FF4E7A7E858 ..0x006B5109DA79 ..0x00EA58BB390F ..0x52BCE2B9B468 ..0x004AC87A57F3 ..0x091FC898EB7F ..0x0A60B77DC0FA ..0x1B982F2B39FF ..0x0102A1806FEB ..0x24E858C57E42 ..0x05EAF5D4245E ..0x36E11A831A3B ..0x0176CA3DB58D ..0x083767D2F551 ..0x09D5403840F7 ..0x0839BF540AC5 ..0x00178684D936 ..0x091955403431 ..0x12A095FD6C98 ..0x045F43E24636 ..0x496349555AA0 ..0x085F29620443 ..0x2539E689E835 ..0x00000104F145) )]] REPLSuperActions[RSASt2Sc[[(0 ..0x1F0403DC5B0D ..0x6CCFB8A)]]] = a REPLSuperActions[RSASt2Sc[[(0 ..0x31A0062D5E7 ..0x6C4ACA)]]] = a REPLSuperActions[RSASt2Sc[[(0 ..0x4F640E638B ..0x92F62683BCA ..0x662721A)]]] = a end REPLSuperActions.help = { func = function(arg) local SA = REPLSuperActions[arg] if SA and not v[RSABlCStH] then log(string.format('{"text":"Help for [%s]:\n%s\n","italic":false}', arg == "" and "help" or arg, SA.help and string.gsub(SA.help, "([\\\"])", "\\%1") or string.format("No help found for this SuperAction.\nAssumed usage:\n $$#%s - Run SuperAction", arg) ), true) else log("No SuperAction with that name found.") end end, desc = "Provides help about SuperActions.", help = "Provides help about SuperActions.\n" .. "Usage:\n" .. " $$#help - Get help about the help SuperAction.\n" .. " $$#help - Get help about the named SuperAction." } REPLSuperActions[""] = { func = function(arg) local a = arg == RSABlCSt local topics = {} for k in pairs(REPLSuperActions) do topics[#topics+1] = k end table.sort(topics) local strs = {} for _,k in ipairs(topics) do v = REPLSuperActions[k] if not v[RSABlCStH] then strs[#strs+1] = string.format("[$$#%s]: %s", k, v.desc or "No description provided...") end end log("All SuperActions:\n" .. table.concat(strs, "\n") .. "\n") if a then local astrs = {} for _,k in ipairs(topics) do if REPLSuperActions[k][RSABlCStH] then astrs[#astrs+1] = string.format("@ [$$#%s]", k) end end log(RSABlCStT .. table.concat(astrs, "\n") .. "\n") end end, desc = "List all SuperActions.", --"What? That's not what this SA does!" --If this were to be typed out in chat, it would look like this "$$#help". --Therefore, this is actually the help topic for the help SA. help = "Provides help about SuperActions.\n" .. "Usage:\n" .. " $$#help - Get help about the help SuperAction.\n" .. " $$#help - Get help about the named SuperAction.\n\n" .. "If you were looking for a list of SuperActions, try \"$$#\"." } local REPLmt = setmetatable({ __newindex = function() error("The REPL table is immutable to avoid self-destruction of the REPL.") end, __call = function(self, cmd) local str, nl if cmd ~= nil then cmd = tostring(cmd) if string.sub(cmd, 1, 3) == "$$#" then --Assume the worst, the code in this block should *all* run even if the string metatable is fucked. local SAcmd, SAarg = string.match(cmd, "^$$#(%S*) ?(.*)$") SAcmd = string.lower(SAcmd) if REPLSuperActions[SAcmd] then log(string.format('{"text":"REPL: Running SuperAction.","color":"%s","italic":false}', rtr.notice), true) local ret = REPLSuperActions[SAcmd].func(SAarg) if ret == "\0\9\0\70\79\82\67\69\0\9\0" then return "\0\9\0\70\79\82\67\69\0\9\0" end else log(string.format('{"text":"REPL: SuperAction not found!\nUse $$# to list all valid SuperActions.","color":"%s","italic":false}', rtr.error), true) end return end str, nl = cmd:match("^(.-)(;?)$") if not str then error "Command error." end if #REPL.currentcommand == 0 and str:sub(1,1) == "/" then log(('{"text":"REPL: Ignoring Minecraft command.","color":"%s","italic":false}'):format(rtr.notice), true) chat.setFiguraCommandPrefix() chat.sendMessage(str) chat.setFiguraCommandPrefix("") return end REPL.currentcommand = REPL.currentcommand .. str .. "\n" else str = "" end if nl ~= ";" then chat.setFiguraCommandPrefix() local ccmd = REPL.currentcommand:sub(1, -2) REPL.currentcommand = "" local f = loadstring("return " .. ccmd) if type(f) == "function" then log(('[{"text":"INPUT:\n","color":"%s","italic":false},{"text":"return ","color":"%s"},{"text":"%s\n","color":"%s"}]'):format( rtr.input, rtr.repl_return, ccmd:gsub("([\\\"])", "\\%1"), rtr.user_input ), true) else f = loadstring(ccmd) if type(f) == "function" then log(('[{"text":"INPUT:\n","color":"%s","italic":false},{"text":"%s\n","color":"%s"}]'):format( rtr.input, ccmd:gsub("([\\\"])", "\\%1"), rtr.user_input ), true) else log(('{"text":"REPL: Compile Error!\n%s","color":"%s","italic":false}'):format( f:gsub("\t", " "):gsub("([\\\"])", "\\%1"), rtr.error ), true) chat.setFiguraCommandPrefix("") return end end local r = {pcall(f)} if not r[1] then log(('{"text":"REPL: Runtime Error!\n%s","color":"%s","italic":false}'):format( r[2]:gsub("\t", " "):gsub("([\\\"])", "\\%1"):gsub("§.", ""), rtr.error ), true) chat.setFiguraCommandPrefix("") return end table.remove(r, 1) local _H = {} H[#H+1] = _H local rh = 0 for i in pairs(r) do if i > rh then rh = i end end for i=1,rh do local v = r[i] _H[i] = v r[i] = JSON.stringify.any(v, true, false, { indent = rtt.max_indent < 0 and rtt.max_indent or nil, length = type(v) == "string" and rts.max_size or rtt.max_length }) end if rh == 0 then r[1] = ('%s,{"text":" (no value?)","color":"%s"}'):format( JSON.stringify["nil"](), rtx.no_value ) end log(('[{"text":"RETURNS:\n","color":"%s","italic":false}%s,"\n"]'):format( rtr.returns, table.concat(r, ',"\n"') ), true) chat.setFiguraCommandPrefix("") end end }, { __newindex = function() error("The REPL metatable is immutable to avoid self-destruction of the REPL.") end, __metatable = false }) --Store pointer to the Environment. --[[ O[1] ]] O[_ENV] = true --Store pointers to REPL values. --[[ O[2] ]] O[REPL] = true --[[ O[3] ]] O[REPL.key] = true --[[ O[4] ]] O[REPL.log] = true --[[ O[5] ]] O[REPL.stringify] = true --[[ O[6] ]] O[REPL.theme] = true --Store pointer to REPL metatable. --[[ O[7] ]] O[REPLmt] = true --Store pointers to O values. --[[ O[8] ]] O[O] = true --[[ O[9] ]] O[O.N] = true --[[ O[10] ]] O[O.Nindex] = true --Store pointers to instances. INSTANCE_Biome = biome.getBiome("minecraft:plains", {}) --[[ O[11] ]] O[INSTANCE_Biome] = true INSTANCE_BlockState = block_state.createBlock("minecraft:stone") --[[ O[12] ]] O[INSTANCE_BlockState] = true INSTANCE_ItemStack = item_stack.createItem("minecraft:shield") --[[ O[13] ]] O[INSTANCE_ItemStack] = true INSTANCE_FiguraKeybind = keybind.newKey("[REPL] ", "UNKNOWN") --[[ O[14] ]] O[INSTANCE_FiguraKeybind] = true INSTANCE_RegisteredKeybind = keybind.getRegisteredKeybind("key.jump") --[[ O[15] ]] O[INSTANCE_RegisteredKeybind] = true INSTANCE_Vector = vectors.of{1,2,3,4,5,6} --[[ O[16] ]] O[INSTANCE_Vector] = true setmetatable(REPL, REPLmt) onCommand = function(cmd) if REPL.bound then local s, e = pcall(REPLmt.__call, nil, cmd) if not s then --Again, we have to assume the worst. log( string.format( '{"text":"REPL: Critical REPL error!\n%s","color":"%s","italic":"false"}', string.gsub(string.gsub(string.gsub(e, "\t", " "), "([\\\"])", "\\%1"), "§.", ""), rtr.error ), true ) if not checkSMT() then log('{"text":"\nThe string metatable has been tampered with!\nCore REPL functions cannot run without a valid string metatable!\nYou can use \\"$$#fixstringmt\\" to attempt to fix the issue.","color":"dark_red","italic":false}', true) end chat.setFiguraCommandPrefix("") elseif e == "\0\9\0\70\79\82\67\69\0\9\0" then error("FORCED AVATAR ERROR.\nRELOAD AVATAR TO REGAIN CONTROL.\n") end end end function tick() local REPLkeyIP = REPL.key.isPressed() if REPLkeyIP and not REPL.keyWP then if REPL.bound then REPL.bound = false chat.setFiguraCommandPrefix() log(string.format('{"text":"REPL: Unbound from chat.","color":"%s","italic":false}', rtr.notice), true) else REPL.bound = true chat.setFiguraCommandPrefix("") log(string.format('{"text":"REPL: Bound to chat.","color":"%s","italic":false}', rtr.notice), true) end end REPL.keyWP = REPLkeyIP end end -- }}}