figura-protogen/script.lua

1711 lines
66 KiB
Lua

-- 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",
--[[<ROOT> | color ]] root = "white",
--[[<DUPE> | 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<string, fun(x: table, detail: boolean, inHover: boolean, options: {indent?:number|"false", DONE?: table, length?: number, max?: boolean}): string>
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":" <ROOT>","color":"%s"}'):format(rtt.root)
elseif DONE[x] then
str = str .. (',{"text":" <DUPE>","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 "<NAME ERROR>"):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 <category> - View all settings in the category.\n" ..
" $$#set <category.setting> - View the current value for this setting.\n" ..
" $$#set <category.setting> <value> - Sets the setting to the given value.\n" ..
" <value> 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 <name> - 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 <name> - 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] <INTERNAL USE>", "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
-- }}}