mta-resources/[admin]/runcode/client.lua
2025-05-10 22:29:17 +00:00

141 lines
3.1 KiB
Lua

me = localPlayer
-- Primary functionality
local function runString (commandstring)
outputChatBoxR("Executing client-side command: "..commandstring)
local notReturned
--First we test with return
local commandFunction,errorMsg = loadstring("return "..commandstring)
if errorMsg then
--It failed. Lets try without "return"
commandFunction, errorMsg = loadstring(commandstring)
end
if errorMsg then
--It still failed. Print the error message and stop the function
outputChatBoxR("Error: "..errorMsg)
return
end
--Finally, lets execute our function
local results = { pcall(commandFunction) }
if not results[1] then
--It failed.
outputChatBoxR("Error: "..results[2])
return
end
local resultsString = ""
local first = true
for i = 2, #results do
if first then
first = false
else
resultsString = resultsString..", "
end
local resultType = type(results[i])
if isElement(results[i]) then
resultType = "element:"..getElementType(results[i])
end
resultsString = resultsString..tostring(results[i]).." ["..resultType.."]"
end
if #results > 1 then
outputChatBoxR("Command results: " ..resultsString)
return
end
outputChatBoxR("Command executed!")
end
addEvent("doCrun", true)
addEventHandler("doCrun", root, runString)
-- Variable watching feature
local watchFuncs = {}
local watchKeys = {}
local watchFunc_G = function(k)
return _G[k]
end
local function watchRender()
local sw, y = guiGetScreenSize()
local strings = {}
local maxWidth = 0
-- Offset bottom by some more
y = y - 20
for _, key in ipairs(watchKeys) do
local results = { pcall(watchFuncs[key], key) }
for i, v in ipairs(results) do
results[i] = tostring(v)
end
local text = table.concat(results, ", ")
table.insert(strings, key .. ": " .. text)
local textWidth = dxGetTextWidth(text)
if textWidth > maxWidth then
maxWidth = textWidth
end
end
for _, text in ipairs(strings) do
y = y - 20
dxDrawText(text, sw - 100 - maxWidth, y)
end
end
local function watch(key, v)
-- Error checking
if type(v) ~= "string" and type(v) ~= "function" and type(v) ~= "nil" then
error("Unexpected watch value of type " .. type(v) .. " for key " .. key)
return
end
-- Remove if missing value
if not v then
-- Don't do anything if key doesn't exist
if not watchFuncs[key] then
return false
end
watchFuncs[key] = nil
table.remove(watchKeys, table.find(watchKeys, key))
table.sort(watchKeys)
-- Remove event handler if we have no keys left
if #watchKeys == 0 then
removeEventHandler("onClientRender", root, watchRender)
end
return true
end
-- Only insert key if it doesn't already exist
if not watchFuncs[key] then
table.insert(watchKeys, key)
table.sort(watchKeys)
-- Add event handler if this is our first key
if #watchKeys == 1 then
addEventHandler("onClientRender", root, watchRender)
end
end
-- Set watchFunc as global watcher, if v is string
if type(v) == "string" then
watchFuncs[key] = watchFunc_G
elseif type(v) == "function" then
watchFuncs[key] = v
else
assert(false, "never reached")
end
return true
end
runcode = {
me = localPlayer,
watch = watch
}