rUNC Executor Test
rUNC — это комплексный, открытый набор тестов для глубокой проверки функциональности среды исполнения Luau. Он оценивает корректность реализации десятков функций, выявляя потенциальные проблемы, уязвимости и несоответствия стандарту.
Запуск теста
Чтобы запустить тест, выполните следующую команду в вашей среде исполнения:
loadstring(game:HttpGet("https://raw.githubusercontent.com/TesterTD/rUNC/main/rUNC.lua"))()
FAQ
Что такое rUNC?
rUNC — инструмент для комплексного тестирования окружения, который проверяет наличие и корректную работу десятков ключевых функций: от базовых (например, newcclosure
) до продвинутых, связанных с отладкой, метатаблицами и взаимодействием с движком Roblox.
В отличие от оригинального UNC, созданного как единый стандарт именования и API, rUNC имитирует реальные сценарии использования функций, чтобы убедиться, что они действительно работают так, как должны, а не просто существуют для прохождения базовых проверок.
Что означает "Skid Rate"?
Это условный показатель, который отражает процент неудачных тестов для критически важных или базовых функций. Высокий Skid Rate может указывать на низкое качество, эмуляцию или неполную реализацию среды исполнения.
В чем цель этого проекта?
Тест был создан, чтобы доказать, что надежная проверка среды исполнения может и должна быть с открытым исходным кодом. Он служит альтернативой закрытым системам, которые анализируют среду анонимно, не позволяя пользователям изучить сам механизм проверки.
Почему нет тестов для WebSocket?
Тесты для WebSocket
намеренно исключены, так как его реализация часто приводит к нестабильной работе или вылетам в различных средах исполнения. Вместо этого предоставляется общая документация по его API.
Где большинство примеров?
Остаточные примеры можно посмотреть в самом открытом коде для проверки функций. Я не вижу смысла оставлять их везде, к тому же на разных инжекторах они реагируют по‑разному, хоть и проходят тест они одинаково хорошо или плохо.
newcclosure
Создает "C-замыкание" из функции Luau. Это позволяет маскировать Luau-функции под встроенные C-функции, что изменяет их поведение при обработке ошибок и для таких проверок, как iscclosure
.
Синтаксис
Примеры
local my_func = function() return "Hello from Luau!" end
local c_func = newcclosure(my_func)
print(iscclosure(my_func)) --> false
print(iscclosure(c_func)) --> true
print(c_func()) --> Hello from Luau!
local error_func = newcclosure(function()
error("This is a custom error")
end)
-- pcall вернет ошибку без информации о скрипте и строке, как будто она из C-кода
local success, message = pcall(error_func)
print(success, message) --> false, This is a custom error
Как проверяется в rUNC
Тест проверяет несколько ключевых аспектов:
- Создание и тип: Убеждается, что
newcclosure
успешно создает функцию и чтоiscclosure
правильно идентифицирует её как C-замыкание. - Сохранение семантики: Проверяет, что обернутая функция возвращает те же значения (включая множественные возвраты), что и оригинал.
- Обработка yield: Тестирует, может ли
newcclosure
оборачивать "yielding" функции (например, сtask.wait
) и корректно возобновлять их выполнение. - Маскировка ошибок: Удостоверяется, что ошибки, возникающие внутри C-замыкания, выглядят как ошибки из C-кода (без stack trace).
- Вложенность: Проверяет возможность создавать
newcclosure
из функции, которая уже является C-замыканием.
hookfunction
Позволяет перехватить вызовы одной функции и заменить их другой. Возвращает оригинальную функцию, чтобы её можно было вызвать внутри перехватчика для сохранения исходной логики. Это мощный инструмент для логирования, модификации поведения или блокировки функций.
Синтаксис
Примеры
local original_warn
original_warn = hookfunction(warn, function(...)
print("[WARN CALLED]:", ...)
return original_warn(...)
end)
warn("Test message")
local old_print
old_print = hookfunction(print, function(...)
local args = {...}
table.insert(args, 1, "[HOOKED]")
return old_print(table.unpack(args))
end)
print("Hello", "world") -- Выведет: [HOOKED] Hello world
Как проверяется в rUNC
Тест проводит комплексную проверку:
- Базовый перехват: Удостоверяется, что вызов оригинальной функции теперь выполняет код хука.
- Возврат оригинала: Проверяет, что
hookfunction
возвращает рабочую копию оригинальной функции. - Обработка ошибок: Тестирует, что ошибки в оригинальной функции могут быть перехвачены и обработаны внутри хука.
- Работа с C-функциями: Убеждается, что можно перехватывать глобальные C-функции, такие как
warn
. - Восстановление: Проверяет, что хук можно снять, вызвав
hookfunction
повторно с оригинальной функцией. - Совместимость с `newcclosure`: Тест запускается дважды: с обычной Luau-функцией и с C-замыканием в качестве хука.
restorefunction
Полностью восстанавливает оригинальное состояние функции, которая была ранее изменена с помощью hookfunction
. Удаляет все установленные хуки, включая вложенные, возвращая функцию к её первоначальному состоянию.
Синтаксис
Примеры
hookfunction(print, function(...) end) -- Блокируем print
print("This will not appear")
restorefunction(print)
print("This will appear now") --> This will appear now
local function my_func() return "original" end
local old1 = hookfunction(my_func, function() return "hooked 1" end)
local old2 = hookfunction(my_func, function() return "hooked 2" end)
print(my_func()) --> "hooked 2"
restorefunction(my_func)
print(my_func()) --> "original"
Как проверяется в rUNC
- Ошибка на не-хукнутой функции: Убеждается, что вызов
restorefunction
на обычной функции вызывает ошибку. - Полное восстановление: После установки нескольких хуков на одну функцию, проверяет, что
restorefunction
возвращает её к самому первому, оригинальному состоянию. - Изоляция: Проверяет, что восстановление одной функции не затрагивает хуки, установленные на другие функции.
- Повторное восстановление: Убеждается, что повторный вызов
restorefunction
на уже восстановленной функции вызывает ошибку.
cloneref
Создает "легкую" копию (ссылку) на Instance
. Клон и оригинал указывают на один и тот же объект в памяти. Это означает, что изменение свойства у клона изменит его и у оригинала. Уничтожение оригинала делает клон невалидным. Защищает от __mode атак, то есть детекты с помощью weak tables.
Синтаксис
Примеры
local part_original = Instance.new("Part", workspace)
local part_clone = cloneref(part_original)
print(part_original == part_clone) --> false (ссылки разные)
part_clone.Name = "NewName"
print(part_original.Name) --> "NewName" (объект один)
local part_original = Instance.new("Part", workspace)
local part_clone = cloneref(part_original)
part_original:Destroy()
task.wait(0.1)
local success, result = pcall(function()
return part_clone.Parent
end)
print(success, result) --> true nil
Как проверяется в rUNC
- Создание и неравенство: Убеждается, что клон успешно создается, но при этом
original ~= clone
возвращаетtrue
. - Общие сигналы: Проверяет, что подключение к сигналу на клоне влияет на оригинал.
- Совместное уничтожение: После вызова
:Destroy()
на оригинале, тест проверяет, что и оригинал, и клон удалены из игрового дерева. - Невалидность: Убеждается, что после уничтожения оригинала, доступ к свойствам или методам клона вызывает ошибку или возвращает `nil`.
compareinstances
Сравнивает два `Instance`, чтобы определить, указывают ли они на один и тот же базовый объект. Это особенно полезно при работе с `cloneref`, так как обычное сравнение `==` вернет `false` для оригинала и его клона.
Синтаксис
Примеры
local original = Instance.new("Part")
local ref = cloneref(original)
print(original == ref) --> false
print(compareinstances(original, ref)) --> true
local part1 = Instance.new("Part")
local part2 = Instance.new("Part")
print(compareinstances(part1, part2)) --> false
print(compareinstances(part1, part1)) --> true
Как проверяется в rUNC
- Идентичность: Проверяет, что
compareinstances(inst, inst)
возвращает `true`. - Сравнение с клоном: Убеждается, что
compareinstances(inst, cloneref(inst))
возвращает `true`. - Различие: Проверяет, что
compareinstances(inst1, inst2)
для разных объектов возвращает `false`.
loadstring
Компилирует строку кода Luau в функцию без её немедленного выполнения. Если в коде есть синтаксическая ошибка, возвращает `nil` и сообщение об ошибке.
Синтаксис
Примеры
local code = "getgenv().a = 10; return a + 5"
local func, err = loadstring(code)
if func then
print("Result:", func()) --> Result: 15
print("Global var:", getgenv().a) --> Global var: 10
else
warn("Failed to compile code:", err)
end
local invalid_code = "local a =="
local func, err = loadstring(invalid_code, "MyChunk")
if not func then
print("Error:", err) --> Error: [MyChunk]:1: Expected identifier...
end
Как проверяется в rUNC
- Компиляция и исполнение: Проверяет, что `loadstring` для корректного кода возвращает функцию, которая выполняется и возвращает правильное значение.
- Доступ к окружению: Убеждается, что код может изменять глобальное окружение (
getgenv
). - Обработка невалидного кода: Проверяет, что для кода с ошибкой `loadstring` возвращает `nil` и строку с сообщением об ошибке.
- Имя чанка: Удостоверяется, что имя чанка (`chunkName`) появляется в сообщении об ошибке.
firesignal
Вызывает сигнал (`RBXScriptSignal`) с указанными аргументами. По сути, это способ программно имитировать срабатывание сигнала.
Синтаксис
Примеры
local button = Instance.new("TextButton")
button.MouseButton1Click:Connect(function()
print("Button was clicked programmatically!")
end)
firesignal(button.MouseButton1Click)
local bindable = Instance.new("BindableEvent")
bindable.Event:Connect(function(player, score)
print(player.Name .. " scored " .. score)
end)
local player = game:GetService("Players").LocalPlayer
firesignal(bindable.Event, player, 100)
Как проверяется в rUNC
- Вызов с аргументами и без: Проверяет, что вызовы `firesignal` корректно активируют подключенную функцию и передают ей аргументы (или `nil`).
- Отключенные соединения: Проверяет, что `firesignal` не вызывает соединения, которые были отключены через `:Disconnect()`.
identifyexecutor
Возвращает имя и версию текущей среды исполнения (эксплойта).
Синтаксис
Примеры
local name, version = identifyexecutor()
print(`Executor: {name} v{version}`)
Как проверяется в rUNC
- Успешное выполнение: Проверяет, что функция выполняется без ошибок.
- Тип и содержимое: Убеждается, что оба возвращаемых значения — это непустые строки, соответствующие имени и версии.
isrbxactive
Проверяет, активно ли окно Roblox. Возвращает `true`, если окно находится в фокусе, и `false` в противном случае. Полезно для скриптов, которые должны приостанавливать свою работу, когда игрок сворачивает игру.
Синтаксис
Примеры
task.spawn(function()
while true do
if isrbxactive() then
-- Выполняем действия, только если игра в фокусе
print("Окно удерживается")
end
task.wait(1)
end
end)
Как проверяется в rUNC
- Возвращаемое значение: Тест просто вызывает функцию и проверяет, что она выполняется без ошибок и возвращает `true`, так как во время выполнения теста окно по определению активно.
gethui
Возвращает скрытый контейнер интерфейса (`Instance`), предназначенный для безопасного размещения UI-элементов. Объекты в `gethui` Если так подумать, это CoreGui parent на максималках, cloneref с CoreGui будет в разы лучше.
Синтаксис
Примеры
local permanentGui = Instance.new("ScreenGui")
permanentGui.ResetOnSpawn = false
permanentGui.Parent = gethui()
Как проверяется в rUNC
- Тип объекта: Проверяет, что `gethui` возвращает объект типа `Instance`.
- Функциональность родителя: Убеждается, что в возвращенный объект можно помещать другие `Instance` (например, `ScreenGui`).
islclosure / iscclosure / isexecutorclosure
Эти функции проверяют тип замыкания (closure). Они используются для определения, является ли функция обычной Luau-функцией, C-функцией или специфичной для эксплойта.
islclosure(func)
: Возвращает `true`, если `func` — это стандартная функция, написанная на Luau.iscclosure(func)
: Возвращает `true`, если `func` — это C-функция, включаяnewcclosure
.isexecutorclosure(func)
: Возвращает `true`, если функция принадлежит среде исполнения.
Примеры
local lua_func = function() end
local c_func_wrapped = newcclosure(lua_func)
local c_func_native = print
local exploit_func = getgenv
print("lua_func is lclosure:", islclosure(lua_func)) --> true
print("c_func_native is cclosure:", iscclosure(c_func_native)) --> true
print("exploit_func is executorclosure:", isexecutorclosure(exploit_func)) --> true
Как проверяется в rUNC
Тест проверяет все три функции на разных типах целей: Luau-функция, стандартная C-функция (`print`), обернутая C-функция (`newcclosure`) и функция среды исполнения (`getgenv`).
isnewcclosure
Определяет, была ли C-функция создана с помощью newcclosure
. Это позволяет отличить "настоящие" встроенные C-функции от Luau-функций, замаскированных под C.
Синтаксис
Примеры
local wrapped = newcclosure(function() end)
print("For wrapped function:", isnewcclosure(wrapped)) --> true
print("For native 'print':", isnewcclosure(print)) --> false
Как проверяется в rUNC
Тест проверяет, что функция возвращает true
для результата newcclosure
и false
для обычной Luau-функции.
isfunctionhooked
Проверяет, была ли функция перехвачена (захукана) с помощью hookfunction
.
Синтаксис
Примеры
local function my_func() end
print("Before hook:", isfunctionhooked(my_func)) -- false
local old = hookfunction(my_func, function() end)
print("After hook:", isfunctionhooked(my_func)) -- true
hookfunction(my_func, old) -- restore original
print("After restore:", isfunctionhooked(my_func)) -- false (Но, скорее будет true, на что можно надеяться, когда ты восстанавливаешь функцию не через restorefunction💀)
Как проверяется в rUNC
Тест проверяет, что функция возвращает false
для обычной функции, true
после применения `hookfunction`, и снова false
после восстановления.
replaceclosure
Заменяет код одной Luau-функции кодом другой. При этом новая функция получает доступ к upvalue'ам (внешним локальным переменным) оригинальной функции.
Внимание: Эта функция может легко привести к сбою, если новая функция неправильно работает с upvalue'ами старой.
Синтаксис
Примеры
local counter = 10
local function original()
counter = counter + 1
return "Original was called"
end
local function replacement()
return "Replacement was called, counter is: " .. counter
end
replaceclosure(original, replacement)
print(original()) --> Replacement was called, counter is: 10
Как проверяется в rUNC
- Подмена: Убеждается, что после замены вызов оригинальной функции теперь выполняет код новой.
- Доступ к upvalue: Проверяет, что замененная функция может корректно читать upvalue'ы оригинала.
- Защита C-функций: Удостоверяется, что попытка заменить C-функцию вызывает ошибку.
clonefunction
Создает полную копию (клон) Luau-функции. Клон имеет то же самое тело и upvalue'ы, но является отдельным объектом. Хуки, примененные к оригиналу после клонирования, не влияют на клон.
Синтаксис
Примеры
local function original()
print("Original function")
end
local cloned = clonefunction(original)
hookfunction(original, function() print("Hooked!") end)
original() --> Hooked!
cloned() --> Original function
Как проверяется в rUNC
- Общее окружение: Убеждается, что `getfenv(original)` и `getfenv(cloned)` совпадают.
- Изоляция от `hookfunction`: После клонирования хукает оригинал и проверяет, что клон остался неизменным.
- Работа с C-функциями: Убеждается, что попытка клонировать C-функцию не вызывает ошибку (проверка эмуляции).
newlclosure
Создает новое Luau-замыкание из существующей Luau-функции. Это похоже на clonefunction
, но является более низкоуровневой операцией. Новый lclosure
разделяет код и upvalue'ы с оригиналом.
Синтаксис
Примеры
local count = 0
local function increment()
count = count + 1
return count
end
local lclosure_copy = newlclosure(increment)
print(increment()) --> 1
print(lclosure_copy()) --> 2
print(islclosure(lclosure_copy)) --> true
Как проверяется в rUNC
- Успешное создание: Проверяет, что функция создает новое замыкание и что
islclosure
возвращаетtrue
. - Общие upvalues: Убеждается, что вызов оригинала и нового замыкания влияет на один и тот же upvalue.
- Ошибка на C-функциях: Проверяет, что попытка использовать на C-функции вызывает ошибку.
checkcaller
Проверяет контекст вызова. Возвращает `true`, если вызов происходит из среды инжектора. Возвращает `false`, если вызов инициирован из самого клиента, следственно игрой, а не Executor.
Синтаксис
Примеры
local Players = cloneref(game:GetService("Players")) --> Получаем сервис Players через cloneref (Зачем? Прочти мой документационный пост про cloneref :D)
local lp = Players.LocalPlayer
local old --> Переменная для хранения оригинальной функции __namecall
old = hookmetamethod(game, "__namecall", newcclosure(function(self, ...)
local method = getnamecallmethod() --> Получаем имя вызываемого метода ("Kick")
if self == lp and method and method:lower() == "kick" then --> Проверяем, что метод вызывается на LocalPlayer и это Kick
if checkcaller() then --> Если вызов из кода Executor, значит...
warn("Попытка кика со стороны Executor была заблокирована!!! Нахуя себя кикать?") --> Логируем, что кик был от executor и посылаем нахер
return --> Блокируем выполнение
else --> Если вызов из игры (Клиент попытался кикнуть)
warn("хахаахахахаха лошок ебаный захотел кикнуть со стороны клиента") --> Логируем, что кик был от клиента, а не от Executor
return --> Блокируем выполнение
end
end
return old(self, ...) --> Если условия не совпали — вызываем оригинальный __namecall
end))
task.delay(2, function() --> Ждём 2 секунды, чтобы хук успел установиться (На всякий, вдруг твой инжектор Velocity :D)
warn(">>> TEST: вызываем Kick от инжектора")
lp:Kick("Если ты видишь это сообщение то это значит одно: A - твой инжектор не обладает hookmetamethod или функция крайне плохо сделана...") --> Этот вызов должен быть перехвачен хуком и заблокирован
end)
Как проверяется в rUNC
Тест проводит множество проверок: базовый вызов, вызов из C-кода через `__namecall`, вызов из `newcclosure` и стабильность.
getrawmetatable
Возвращает метатаблицу объекта, даже если она защищена свойством __metatable
.
Синтаксис
Примеры
local t = {}
local mt = { __metatable = "LOCKED" }
setmetatable(t, mt)
print(getmetatable(t)) --> LOCKED
print(getrawmetatable(t) == mt) --> true
Как проверяется в rUNC
Проверяет работу с обычной таблицей, `Instance` и сервисами. Создает таблицу с защитой `__metatable` и проверяет, что `getrawmetatable` успешно ее получает.
setrawmetatable
Устанавливает метатаблицу для объекта, обходя защиту `__metatable`.
Синтаксис
Примеры
local t = {}
setmetatable(t, { __metatable = "LOCKED" })
local new_mt = { __index = function() return "bypassed!" end }
setrawmetatable(t, new_mt)
print(t.anything) --> bypassed!
Как проверяется в rUNC
Проверяет, что `setrawmetatable` успешно устанавливает новую метатаблицу на защищенный объект и что она действительно работает.
hookmetamethod
Перехватывает вызовы метаметодов (`__index`, `__namecall`, и др.) для заданного объекта. Это один из самых мощных способов изменения поведения Roblox API.
Синтаксис
Примеры
local old_namecall
old_namecall = hookmetamethod(game, "__namecall", function(self, ...)
if getnamecallmethod():lower() == "getservice" then
print("GetService вызван для:", ...)
end
return old_namecall(self, ...)
end)
game:GetService("Players")
Как проверяется в rUNC
Тест проверяет хуки на несколько ключевых метаметодов: __newindex
, __tostring
, __index
, и __namecall
, а также возможность их восстановления.
getgenv / getrenv / getsenv
Предоставляют доступ к различным таблицам окружения.
getgenv()
: Глобальное окружение Executor среды.getrenv()
: Глобальное окружение Roblox, врата getrenv() к getfenv().getsenv(script)
: Локальное окружение конкретного скрипта.
Примеры
getsenv
local animate = game.Players.LocalPlayer.Character:FindFirstChild("Animate")
if animate then
local env = getsenv(animate)
print(typeof(env.onSwimming)) --> function
end
getgenv
local g = getgenv()
g.testValue = 123
print(getgenv().testValue) --> 123
getrenv
local r = getrenv()
print(r.game) --> Ugc
r._customFlag = true
print(getrenv()._customFlag) --> true
Как проверяется в rUNC
- getgenv / getrenv: Проверяет, возвращается ли таблица и сохраняются ли в ней изменения.
- getsenv: Проверяет получение окружения для активного
LocalScript
, ошибку на неактивном иnil
дляModuleScript
.
getthreadidentity / setthreadidentity
Функции для управления уровнем "идентичности" (контекста безопасности) текущего потока. Уровень идентичности — это число от 0 до 8.
Примеры
print("Уровень потока сейчас:", getthreadidentity())
task.spawn(function()
print("Новый поток (Уровень на данный момент):", getthreadidentity())
setthreadidentity(6)
print("Новый поток (После изменения):", getthreadidentity()) --> 6
end)
task.wait(0.1)
print("Основной поток уровня не был нарушен:", getthreadidentity())
Как проверяется в rUNC
Тест проводит исчерпывающую проверку: стабильность, диапазон, изоляцию потоков, работу в `pcall` и быстрое переключение.
getscripts
Возвращает таблицу всех существующих в игре скриптовых объектов (LocalScript
, Script
, ModuleScript
), независимо от того, запущены они или нет.
Синтаксис
Примеры
local scripts_list = getscripts()
print("Всего скриптов:", #scripts_list)
local foundAnimate = false
for _, script_obj in ipairs(scripts_list) do
if typeof(script_obj) == "Instance" and script_obj:IsA("LocalScript") and script_obj.Name:find("Animate") then
print("Нашёл Animate script:", script_obj:GetFullName())
foundAnimate = true
end
end
local player = game.Players.LocalPlayer
local charAnimate = player.Character and player.Character:FindFirstChild("Animate")
if not charAnimate or not charAnimate:IsA("LocalScript") then
warn("Эмуляция getscripts: Animate не найден в персонаже")
elseif not foundAnimate then
warn("Фальшивый getscripts: Animate есть в персонаже, но отсутствует в списке getscripts")
else
print("Animate найден и в персонаже, и в списке getscripts")
end
Как проверяется в rUNC
Создает новый LocalScript
и затем проверяет, что getscripts
находит этот свежесозданный скрипт в возвращенном списке.
getrunningscripts
Возвращает таблицу всех скриптов, которые в данный момент исполняются. В отличие от getscripts
, эта функция не включает скрипты, которые отключены (Disabled = true
) или еще не были запущены.
Синтаксис
Примеры
local running_scripts = getrunningscripts()
print("Всего запущенных скриптов:", #running_scripts)
for _, s in ipairs(running_scripts) do
print("- " .. s:GetFullName())
end
local player = game.Players.LocalPlayer
local vehicleCameraPath = player:FindFirstChild("PlayerScripts")
and player.PlayerScripts:FindFirstChild("PlayerModule")
and player.PlayerScripts.PlayerModule:FindFirstChild("CameraModule")
and player.PlayerScripts.PlayerModule.CameraModule:FindFirstChild("VehicleCamera")
if not vehicleCameraPath or not vehicleCameraPath:IsA("ModuleScript") then
warn("Тупорылая эмуляция getrunningscripts: VehicleCamera не найден")
else
print("VehicleCamera найден:", vehicleCameraPath:GetFullName())
end
Как проверяется в rUNC
Находит известный работающий скрипт (Animate), проверяет, что не включает неактивные скрипты, и что общее число скриптов больше нуля.
getloadedmodules
Возвращает таблицу всех ModuleScript
, которые были загружены хотя бы раз через require()
.
Синтаксис
Примеры
local ok, modules = pcall(getloadedmodules)
if not ok or type(modules) ~= "table" then
warn("getloadedmodules отсутствует или эмулирован")
return
end
local count = 0
print("=== Список загруженных ModuleScript ===")
for _, module in ipairs(modules) do
if typeof(module) == "Instance" and module:IsA("ModuleScript") then
count += 1
print(count .. ".", module.Name, "→", module:GetFullName())
end
end
print("Всего загруженных модулей:", count)
local player = game.Players.LocalPlayer
local cameraUIPath = player:FindFirstChild("PlayerScripts")
and player.PlayerScripts:FindFirstChild("PlayerModule")
and player.PlayerScripts.PlayerModule:FindFirstChild("CameraModule")
and player.PlayerScripts.PlayerModule.CameraModule:FindFirstChild("CameraUI")
if not cameraUIPath or not cameraUIPath:IsA("ModuleScript") then
warn("Примитивная эмуляция getloadedmodules: CameraUI не найден")
else
local okReq, result = pcall(require, cameraUIPath)
if not okReq then
warn("Примитивная эмуляция getloadedmodules: require(CameraUI) не сработал")
else
print("CameraUI найден и успешно загружен через require")
end
end
Как проверяется в rUNC
Проверяет, что известный загруженный модуль присутствует в списке, а свежесозданный, незагруженный — отсутствует.
getscriptbytecode
Возвращает скомпилированный байт-код скрипта в виде строки.
Синтаксис
Примеры
local Players = game:GetService("Players")
local lp = Players.LocalPlayer
local char = lp.Character or lp.CharacterAdded:Wait()
local animate = char:WaitForChild("Animate")
local bytecode = getscriptbytecode(animate)
if bytecode then
print("Bytecode length:", #bytecode) --> 12365
else
warn("Не удалось получить байткод Animate")
end
Как проверяется в rUNC
Убеждается, что для скрипта с кодом (Animate) возвращается непустая строка, а для скрипта без байт-кода — nil
или пустая строка.
getscriptclosure
Возвращает главное замыкание (функцию) скрипта. По сути, это "скомпилированный" результат, который можно выполнить.
Синтаксис
Примеры
local animate = game.Players.LocalPlayer.Character:WaitForChild("Animate")
local func = getscriptclosure(animate)
print("Closure доступен:", func ~= nil) --> true
Как проверяется в rUNC
Проверяет, что для скрипта с кодом (Animate) возвращается function
, а для пустого — nil
.
getscripthash
Возвращает хэш (SHA-384) байт-кода скрипта. Это надежный способ проверить, был ли скрипт изменен.
Синтаксис
Примеры
local Players = game:GetService("Players")
local lp = Players.LocalPlayer
local char = lp.Character or lp.CharacterAdded:Wait()
local animate = char:WaitForChild("Animate")
local current_hash = getscripthash(animate)
print("→ Текущий хэш Animate:", current_hash)
local known_hash = current_hash
if current_hash ~= known_hash then
warn("Animate script изменил хеш!!")
else
print("Animate script hash имеет один и тот же хеш, всё нормально.")
end
Как проверяется в rUNC
Проверяет, что возвращаемое значение является валидным хэшем SHA-384. Тестирует, что для скрипта без байт-кода возвращается nil
.
getfunctionhash
Возвращает хэш (SHA-384) байт-кода Luau-функции. Работает напрямую с функциями в памяти.
Синтаксис
Примеры
local function a() return 1 end
local function b() return 1 end -- Другая функция, но с тем же кодом
print(getfunctionhash(a) == getfunctionhash(b)) --> true
Как проверяется в rUNC
Проверяет, что возвращается корректный хэш. Убеждается, что разные функции имеют разные хэши, а идентичные — одинаковые. Проверяет ошибку на C-функциях.
getcallingscript
Возвращает script
, из которого была вызвана текущая функция. Если вызов был инициирован C-кодом, возвращает nil
.
Синтаксис
Примеры
local old
old = hookmetamethod(game, "__newindex", function(self, key, value)
if not checkcaller() then
local caller = getcallingscript()
warn("__newindex доступ из скрипта:", caller and caller:GetFullName() or "Unknown") --> Как правило это будет PlayerScripts.RbxCharacterSounds
hookmetamethod(game, "__newindex", old)
return old(self, key, value)
end
return old(self, key, value)
end)
print(getcallingscript())
Как проверяется в rUNC
Проверяет, что прямой вызов из C-потока возвращает nil
, а вызов из Luau-функции возвращает текущий скрипт.
queue_on_teleport
Регистрирует строку с Lua-кодом, которая будет выполнена после того, как игрок телепортируется в другое место (place) внутри той же игры (universe).
Синтаксис
Примеры
local TeleportService = game:GetService("TeleportService")
local Players = game:GetService("Players")
local lp = Players.LocalPlayer
queue_on_teleport([[
print("→ Код из очереди выполнился после телепорта в ту же игру!")
]])
TeleportService:Teleport(game.PlaceId, lp)
Как проверяется в rUNC
Проверяет, что вызов с валидной строкой кода не вызывает ошибок.
getgc
Возвращает таблицу со всеми объектами (функции, таблицы, userdata и т.д.), которые в данный момент находятся в памяти и отслеживаются сборщиком мусора (Garbage Collector). Может включать или не включать функции в зависимости от аргумента.
Синтаксис
Примеры
local marker = Instance.new("Folder")
marker.Name = "Иван Золо"
local gcObjects = {}
local foundMarker = false
local markerIndex
for i, v in ipairs(getgc(true)) do
if v == marker then
foundMarker = true
markerIndex = i
end
if typeof(v) == "Instance" and v.ClassName == "Part" then
table.insert(gcObjects, v)
end
end
marker:Destroy()
if not foundMarker then
print("Эмуляция getgc")
else
print("Маркер найден в getgc под индексом", markerIndex)
print("Нашёл", #gcObjects, "объектов Part в памяти")
end
local function SecretAdminFunction()
print("→ Запущена функция 1")
end
local function HiddenDebugTool()
print("→ Запущена фунция 2")
end
local function UltraSecureRoutine()
print("→ Запущена функция 3")
end
local markerFunc = function() end
local foundMarker = false
local foundTargets = {}
for _, v in ipairs(getgc(false)) do
if v == markerFunc then
foundMarker = true
end
if type(v) == "function" then
local info = debug.getinfo(v)
if info and info.name == "SecretAdminFunction" then
table.insert(foundTargets, "SecretAdminFunction")
v()
elseif info and info.name == "HiddenDebugTool" then
table.insert(foundTargets, "HiddenDebugTool")
v()
elseif info and info.name == "UltraSecureRoutine" then
table.insert(foundTargets, "UltraSecureRoutine")
v()
end
end
end
if not foundMarker then
print("Эмуляция getgc")
else
if #foundTargets > 0 then
print("Найдены и вызваны функции:", table.concat(foundTargets, ", "))
else
print("Маркер найден, но целевые функции отсутствуют")
end
end
Как проверяется в rUNC
- getgc(false): Проверяет, что находит функции, но не таблицы.
- getgc(true): Проверяет, что находит все тестовые объекты: функцию, таблицу и userdata.
getnilinstances
Возвращает таблицу всех объектов Instance
, у которых нет родителя (Parent == nil
). Это подмножество того, что вернет getinstances
.
Синтаксис
Примеры
local marker = Instance.new("Folder")
marker.Name = "Коржик"
marker.Parent = nil
local cleaned_count = 0
local foundMarker = false
local markerIndex
for i, inst in ipairs(getnilinstances()) do
if inst == marker then
foundMarker = true
markerIndex = i
end
if not inst:IsDescendantOf(game) and inst.ClassName ~= "GameSettings" then
local ok = pcall(function()
inst:Destroy()
end)
if ok then
cleaned_count += 1
end
end
end
marker:Destroy()
if not foundMarker then
print("Эмуляция getnilinstances")
else
print("Маркер найден в getnilinstances под индексом", markerIndex)
print("Очищено nil-объектов:", cleaned_count)
end
Как проверяется в rUNC
Убеждается, что объект без родителя присутствует в списке, а объект с родителем — нет.
getinstances
Возвращает таблицу всех Instance
, существующих в памяти, независимо от того, есть у них родитель или нет.
Синтаксис
Примеры
local part = Instance.new("Part")
part.Size = Vector3.new(4, 1, 4)
part.Position = Vector3.new(0, 5, 0)
part.Anchored = true
part.Parent = workspace
local prompt = Instance.new("ProximityPrompt")
prompt.ActionText = "Нажми меня"
prompt.ObjectText = "Тестовый объект"
prompt.Enabled = true
prompt.Parent = part
local marker = Instance.new("Folder")
marker.Name = "Печенье"
marker.Parent = workspace
local foundMarker = false
local markerIndex
for i, inst in ipairs(getinstances()) do
if inst == marker then
foundMarker = true
markerIndex = i
end
if inst:IsA("ProximityPrompt") and inst.Enabled then
print("Найден активный prompt:", inst:GetFullName())
end
end
marker:Destroy()
if not foundMarker then
print("Эмуляция getinstances")
else
print("Маркер найден в getinstances под индексом", markerIndex)
end
Как проверяется в rUNC
Убеждается, что свежесозданный Instance
без родителя находится в списке.
getreg
Возвращает таблицу реестра Lua. Это низкоуровневая структура, в которой хранятся все "живые" объекты, включая потоки (thread
), функции, таблицы и userdata.
Синтаксис
Примеры
local my_thread1 = task.spawn(function() -- PS: Найдёт множество лишних потоков, это нормально!
while true do
task.wait(1)
end
end)
local my_thread2 = coroutine.create(function()
while true do
task.wait(2)
end
end)
coroutine.resume(my_thread2)
local my_thread3 = task.spawn(function()
for i = 1, 5 do
task.wait(0.5)
end
end)
local function isRealGetReg()
local ok, reg = pcall(getreg)
if not ok or type(reg) ~= "table" then
return false, "getreg вернул не таблицу"
end
local hasThreadType, hasFunctionType = false, false
for _, v in pairs(reg) do
local t = type(v)
if t == "thread" then hasThreadType = true end
if t == "function" then hasFunctionType = true end
if hasThreadType and hasFunctionType then
return true
end
end
return false, "В реестре нет ожидаемых типов"
end
local okReg, reason = isRealGetReg()
if not okReg then
print("Эмуляция getreg:", reason)
else
for _, value in pairs(getreg()) do
if type(value) == "thread" and coroutine.status(value) == "suspended" then
print("Найден зависший поток:", tostring(value), "статус:", coroutine.status(value))
if value == my_thread1 then
print("→ Это my_thread1 (бесконечный цикл с ожиданием 1 сек)")
elseif value == my_thread2 then
print("→ Это my_thread2 (корутина с ожиданием 2 сек)")
elseif value == my_thread3 then
print("→ Это my_thread3 (короткий цикл на 5 итераций)")
else
print("→ Это неизвестный поток")
end
coroutine.close(value)
print("Поток закрыт")
end
end
end
Как проверяется в rUNC
Проверяет, что находит созданный поток, и что его можно закрыть через coroutine.close
.
cache.* (invalidate, iscached, replace)
Набор функций для управления внутренним кэшем ссылок на Instance
Roblox.
cache.iscached(inst)
: Проверяет, находится ли объект в кэше.cache.invalidate(inst)
: Удаляет объект из кэша. Следующее обращение к нему (например,workspace.Part
) создаст новую ссылку.cache.replace(old_inst, new_inst)
: Заменяет один объект в кэше другим.
Примеры
local part1 = workspace.Part
cache.invalidate(workspace.Part)
local part2 = workspace.Part
print(part1 == part2) --> false (ссылки теперь разные)
local part = workspace.Part
print("Кэширован ли Part:", cache.iscached(part)) --> true
cache.invalidate(part)
print("Кэширован ли Part после invalidate:", cache.iscached(part)) --> false
local oldPart = workspace.Part
local newFire = Instance.new("Fire")
newFire.Parent = workspace
cache.replace(oldPart, newFire)
local replaced = workspace.Part
print("После replace ссылка на Part изменилась:", replaced ~= oldPart) --> true
Как проверяется в rUNC
- invalidate: Создает
Part
и получает на него ссылку. После вызоваcache.invalidate
снова получает ссылку и проверяет, что новая ссылка не равна старой. - iscached: Проверяет, что свежесозданный
Part
кэширован. Затем инвалидирует его и проверяет, что он больше не в кэше. - replace: Заменяет
Part
наFire
и проверяет, что ссылки на объекты стали разными.
getconnections
Возвращает таблицу всех объектов соединений (RBXScriptConnection
), подключенных к данному сигналу.
Синтаксис
Примеры
local event = Instance.new("BindableEvent")
event.Event:Connect(function(arg)
return "Сработало с аргументом: " .. tostring(arg)
end)
local connection = getconnections(event.Event)[1]
print(connection.Function("тест")) -- Сработало с аргументом: тест
connection:Fire("ещё тест")
print("Тип потока подключения:", typeof(connection.Thread)) -- thread
local remote = Instance.new("RemoteEvent")
remote.Name = "RemoteEvent"
remote.Parent = workspace
remote.OnClientEvent:Connect(function(arg1, arg2)
print("Событие получено! Аргументы:", arg1, arg2)
end)
for _, conn in ipairs(getconnections(remote.OnClientEvent)) do
if conn.Function then
print("Вызываем функцию подключения напрямую...")
conn.Function("arg1", 123)
end
end
Как проверяется в rUNC
Проверяет возврат таблицы, валидность соединений, доступ к .Function
, вызов .Fire()
, и обработку C-соединений.
getcallbackvalue
Получает функцию обратного вызова (callback), назначенную свойству объекта, например, BindableFunction.OnInvoke
или RemoteFunction.OnClientInvoke
.
Синтаксис
Примеры
OnInvoke
с доп. проверкойlocal getcallbackvalue = getcallbackvalue
local bf = Instance.new("BindableFunction")
bf.OnInvoke = function(a, b) return a + b end
local function safeGetCallback(obj, prop)
if typeof(obj) ~= "Instance" or type(prop) ~= "string" then
return nil
end
local cb = getcallbackvalue(obj, prop)
if type(cb) ~= "function" then
return nil
end
local ok, upv = pcall(debug.getupvalue, cb, 1)
if ok and upv ~= nil and upv ~= obj then
return nil
end
return cb
end
local callback = safeGetCallback(bf, "OnInvoke")
if callback then
local result = callback(534, -4)
print(result) --> 530
else
print("Callback вероятно спуфнут или просто отсутствует")
end
Как проверяется в rUNC
Проверяет успешное извлечение callback, его работоспособность, и корректную обработку nil
для неустановленных или несуществующих свойств.
setreadonly / isreadonly
Функции для управления состоянием "только для чтения" у таблиц.
setreadonly(tbl, state)
: Устанавливает или снимает с таблицыtbl
флаг "только для чтения".isreadonly(tbl)
: Проверяет, является ли таблицаtbl
"только для чтения".
Примеры
local config = {
version = "1.0",
enabled = true
}
setreadonly(config, true)
print(isreadonly(config)) --> true
local success, err = pcall(function()
config.version = "1.1" -- Это вызовет ошибку
end)
print(success) --> false
print(config.version) --> 1.0
local config = config or {
enabled = true
}
setreadonly(config, false)
config.enabled = false
setreadonly(config, true)
print("config.enabled =", config.enabled) -- false
Как проверяется в rUNC
Устанавливает флаг и проверяет блокировку записи. Затем снимает флаг и проверяет, что запись снова возможна.
setscriptable / isscriptable
Функции для управления "скриптуемостью" (доступностью из скриптов) скрытых или защищенных свойств Instance
.
setscriptable(inst, prop, state)
: Делает свойствоprop
объектаinst
доступным или недоступным для скриптов.isscriptable(inst, prop)
: Проверяет, является ли свойствоprop
доступным.
Примеры
InternalHeadScale
local humanoid = game.Players.LocalPlayer.Character:WaitForChild("Humanoid")
print("До снятия защиты — scriptable?:", isscriptable(humanoid, "InternalHeadScale"))
setscriptable(humanoid, "InternalHeadScale", true)
print("После снятия защиты — scriptable?:", isscriptable(humanoid, "InternalHeadScale"))
print("InternalHeadScale до:", humanoid.InternalHeadScale)
humanoid.InternalHeadScale = humanoid.InternalHeadScale + 0.1
print("InternalHeadScale после:", humanoid.InternalHeadScale)
setscriptable(humanoid, "InternalHeadScale", false)
print("После возврата защиты — scriptable?:", isscriptable(humanoid, "InternalHeadScale"))
Как проверяется в rUNC
Проверяет для Humanoid.InternalHeadScale
, что оно изначально нескриптуемо, становится скриптуемым после setscriptable(true)
(и его можно изменить), и снова становится нескриптуемым после setscriptable(false)
.
get/setsimulationradius
Функции для чтения и изменения радиуса симуляции физики для игрока.
Примеры
local originalRadius = getsimulationradius()
print("Original radius:", originalRadius)
setsimulationradius(1024)
print("New radius:", getsimulationradius()) --> 1024
Как проверяется в rUNC
Читает исходный радиус, устанавливает новое значение, а затем снова читает его, чтобы убедиться, что оно изменилось.
firetouchinterest
Искусственно вызывает событие касания (.Touched
или .TouchEnded
) между двумя объектами. Позволяет симулировать физический контакт без реального перемещения объектов.
Синтаксис
toggle
: 0
или true
для Touched
, 1
или false
для TouchEnded
.
Примеры
-- Создаём персонажа (берём уже существующего у LocalPlayer)
local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
-- По последней информации разные Executors не хотят работать с этим тестом
-- и отдают что-то по типу: Primitives belong to different or invalid worlds
-- Создаём триггер
local trap_trigger = Instance.new("Part")
trap_trigger.Name = "TrapTrigger"
trap_trigger.Size = Vector3.new(5, 1, 5)
trap_trigger.Position = Vector3.new(0, 5, 0)
trap_trigger.Anchored = true
trap_trigger.Transparency = 0.5
trap_trigger.BrickColor = BrickColor.new("Bright red")
trap_trigger.Parent = workspace
-- Подключаем обработчик касания
trap_trigger.Touched:Connect(function(hit)
if hit and hit.Parent == character then
print("Trap activated!")
end
end)
-- Имитируем, что персонаж коснулся триггера
firetouchinterest(trap_trigger, character:WaitForChild("HumanoidRootPart"), 0)
Как проверяется в rUNC
Тест создает две части и подписывается на события Touched
и TouchEnded
у одной из них.
- Учет
CanTouch
: УстанавливаетCanTouch = false
и проверяет, чтоfiretouchinterest
не вызывает событие. - Вызов
Touched
: УстанавливаетCanTouch = true
и проверяет, что вызов сtoggle=0
илиtoggle=true
инкрементирует счетчикTouched
. - Вызов
TouchEnded
: Проверяет, что вызов сtoggle=1
илиtoggle=false
инкрементирует счетчикTouchEnded
. - Обработка ошибок: Убеждается, что вызов с неверными типами аргументов (например,
nil
или{}
) вызывает ошибку.
fireclickdetector
Программно симулирует клик мыши или наведение на объект с ClickDetector
.
Синтаксис
event
: Может быть "MouseClick"
(по умолчанию), "RightMouseClick"
, "MouseHoverEnter"
, "MouseHoverLeave"
.
Примеры
-- Создаём новый ClickDetector (детектор кликов)
local click_detector = Instance.new("ClickDetector")
-- Обработчик клика левой кнопкой мыши
click_detector.MouseClick:Connect(function(player)
print(`{player.Name} Fired M1`)
end)
-- Обработчик клика правой кнопкой мыши
click_detector.RightMouseClick:Connect(function(player)
print(`{player.Name} Fired M2`)
end)
-- Обработчик наведения курсора на объект
click_detector.MouseHoverEnter:Connect(function(player)
print(`{player.Name} Fired HoverEnter`)
end)
-- Обработчик ухода курсора с объекта
click_detector.MouseHoverLeave:Connect(function(player)
print(`{player} Fired HoverLeave`)
end)
-- Симулируем клик ЛКМ по ClickDetector
fireclickdetector(click_detector, 0, "MouseClick")
-- Симулируем клик ПКМ по ClickDetector
fireclickdetector(click_detector, 0, "RightMouseClick")
-- Симулируем наведение курсора на объект
fireclickdetector(click_detector, 0, "MouseHoverEnter")
-- Симулируем уход курсора с объекта
fireclickdetector(click_detector, 0, "MouseHoverLeave")
local info_object = workspace:FindFirstChild("InfoObject")
if not info_object then
info_object = Instance.new("Part")
info_object.Name = "InfoObject"
info_object.Size = Vector3.new(2, 1, 2)
info_object.Position = Vector3.new(0, 3, 0)
info_object.Anchored = true
info_object.Parent = workspace
end
local info_detector = info_object:FindFirstChildOfClass("ClickDetector")
if not info_detector then
info_detector = Instance.new("ClickDetector")
info_detector.Parent = info_object
end
print("Наводим курсор на объект, чтобы показать подсказку")
fireclickdetector(info_detector, 0, "MouseHoverEnter")
task.wait(2)
print("Убираем курсор с объекта")
fireclickdetector(info_detector, 0, "MouseHoverLeave")
Как проверяется в rUNC
Последовательно вызывает fireclickdetector
для MouseClick
, RightMouseClick
, MouseHoverEnter
, MouseHoverLeave
и проверяет, что соответствующие события сработали.
fireproximityprompt
Симулирует срабатывание ProximityPrompt
от лица LocalPlayer
.
Синтаксис
Примеры
local part = Instance.new("Part")
part.Size = Vector3.new(2, 1, 2)
part.Position = Vector3.new(0, 3, 0)
part.Anchored = true
part.Name = "CollectableItem"
part.Parent = workspace
local item_prompt = Instance.new("ProximityPrompt")
item_prompt.ActionText = "Collect"
item_prompt.ObjectText = "Item"
item_prompt.HoldDuration = 0
item_prompt.Parent = part
print("Активируем ProximityPrompt для объекта:", part.Name)
fireproximityprompt(item_prompt)
print("ProximityPrompt был успешно вызван")
Как проверяется в rUNC
Проверяет, что вызов не вызывает ошибок и что событие Triggered
срабатывает с LocalPlayer
в качестве аргумента.
replicatesignal
Используется для удаленной репликации событий ввода, таких как MouseWheelForward
/Backward
. Реплицирует сигнал на сервер с переданными аргументами, если это возможно. Аргументы должны соответствовать сигнатуре самого сигнала — при неверных аргументах будет выброшена ошибка.
Синтаксис
Примеры
-- Создаём тестовый Part с ClickDetector
local test_part = Instance.new("Part")
test_part.Name = "TestClickPart"
test_part.Size = Vector3.new(4, 1, 4)
test_part.Position = Vector3.new(0, 5, 0)
test_part.Anchored = true
test_part.Parent = workspace
local detector = Instance.new("ClickDetector")
detector.Parent = test_part
-- Реплицируем событие MouseActionReplicated с корректными аргументами
replicatesignal(detector.MouseActionReplicated, game.Players.LocalPlayer, 0)
task.wait(0.1)
print("MouseClickReplicated =", game.Players.LocalPlayer:GetAttribute("MouseClickReplicated"))
-- Создаём тестовый UI с Frame
local player = game.Players.LocalPlayer
local gui = Instance.new("ScreenGui")
gui.Name = "TestGui"
gui.Parent = player:WaitForChild("PlayerGui")
local frame = Instance.new("Frame")
frame.Size = UDim2.new(0, 200, 0, 100)
frame.Position = UDim2.new(0.5, -100, 0.5, -50)
frame.BackgroundColor3 = Color3.fromRGB(255, 200, 200)
frame.Parent = gui
-- Эти вызовы вызовут ошибку, так как аргументы не соответствуют сигнатуре события
pcall(function() replicatesignal(frame.MouseWheelForward) end)
pcall(function() replicatesignal(frame.MouseWheelForward, 121) end)
-- Корректный вызов с нужными аргументами
replicatesignal(frame.MouseWheelForward, 121, 214)
task.wait(0.1)
print("MouseWheelForwardReplicated =", player:GetAttribute("MouseWheelForwardReplicated"))
Как проверяется в rUNC
Проверяет, что вызов с корректными аргументами не вызывает ошибок, а с неполными — вызывает.
getfpscap / setfpscap
Функции для чтения и установки ограничения кадров в секунду (FPS) в Roblox.
setfpscap(fps)
: Устанавливает ограничение FPS на указанное значениеfps
(число).getfpscap()
: Возвращает текущее ограничение FPS как число.
Синтаксис
Примеры
local currentFpsCap = getfpscap()
print("Current FPS Cap:", currentFpsCap)
-- Сохраняем текущее значение
local oldCap = getfpscap()
-- Устанавливаем новый cap
setfpscap(60)
print("New FPS Cap:", getfpscap())
-- Возвращаем старое значение
setfpscap(oldCap)
print("Restored FPS Cap:", getfpscap())
Как проверяется в rUNC
Читает cap, сверяет его с реальным FPS, устанавливает новый cap, проверяет что реальный FPS изменился, затем восстанавливает исходное значение.
messagebox
Отображает системное диалоговое окно (message box).
messagebox(text, caption, type)
: Показывает системное окно с сообщениемtext
, заголовкомcaption
и типом окнаtype
(целое число, определяющее иконку и кнопки).- Возвращает: Целое число, представляющее ответ пользователя (например, код нажатой кнопки).
Синтаксис
Примеры
local response = messagebox("Do you want to continue?", "Confirmation", 4)
if response == 6 then -- 6 обычно соответствует кнопке "Yes"
print("Пользователь выбрал: Да")
elseif response == 7 then -- 7 обычно соответствует кнопке "No"
print("Пользователь выбрал: Нет")
else
print("Пользователь закрыл окно или выбрал другой вариант")
end
messagebox("Operation completed successfully.", "Info", 0)
Как проверяется в rUNC
Проверяет, что вызов не вызывает ошибок, и определяет, является ли вызов синхронным (блокирующим) или асинхронным.
setclipboard
Функция для записи текста в буфер обмена пользователя.
setclipboard(text)
: Устанавливает содержимое буфера обмена в указанный текстtext
(строка).
Синтаксис
Примеры
-- Записываем текст в буфер обмена
setclipboard("Copied text")
print("Текст был скопирован в буфер обмена.")
-- Генерируем случайный текст и копируем его
local random_text = "Hello from rUNC! " .. math.random()
setclipboard(random_text)
print("В буфер обмена записано:", random_text)
Как проверяется в rUNC
Записывает случайное число в буфер обмена через setclipboard
и проверяет, что вызов не вызывает ошибок.
Эмуляция мыши
Набор функций для программной симуляции движений и кликов мыши.
mouse1/2press/release/click()
mousemoveabs(x, y)
,mousemoverel(dx, dy)
mousescroll(dx, dy)
Как проверяется в rUNC
Создает UI-кнопку под курсором и проверяет, что вызовы `mouse1click`, `mouse1press`/`release`, `mouse2click` и `mouse2press`/`release` действительно вызывают соответствующие события `MouseButton1Click`, `MouseButton1Down`/`Up` и т.д. Остальные функции проверяются на отсутствие ошибок при вызове.
Actors API
Набор функций для работы с параллельными вычислениями в Roblox с использованием Actor
.
API позволяет выполнять код в отдельных глобальных состояниях (Lua VM), что полезно для распределения нагрузки, изоляции задач и обхода некоторых ограничений движка.
Передача данных между актором и основным потоком осуществляется через каналы связи.
getactors()
: Возвращает список всехActor
в игре, в которых можно выполнить код.isparallel()
: Проверяет, выполняется ли текущий код в параллельном режиме.run_on_actor(actor, code, [channel_data])
: Выполняет указанный код в контексте актора. Третий аргумент может быть любым значением, кроме таблиц и функций (они принадлежат другой Lua VM).create_comm_channel()
: Создаёт канал связи между основным потоком и актором, возвращает ID канала иBindableEvent
для передачи данных.getactorthreads()
: Возвращает список потоков акторов, доступных для выполнения кода.run_on_thread(actor_thread, code, [channel_data])
: Выполняет код в указанном потоке актора.
Синтаксис
Примеры
for index, actor in getactors() do
print(index, actor)
end
local actors = getactors()
if #actors > 0 then
run_on_actor(actors[1], 'print("Hello World from Actor!")')
else
warn("Акторы не найдены в этой игре")
end
local actors = getactors()
if #actors > 0 then
local comm_id, event = create_comm_channel()
event.Event:Connect(function(data)
print("Сообщение от актора:", data)
end)
run_on_actor(actors[1], [=[
local channel = get_comm_channel(...)
channel:Fire("Hello World!")
]=], comm_id)
end
print(isparallel() and "В параллельном режиме" or "В обычном режиме")
for index, thread in getactorthreads() do
print(index, thread)
end
local threads = getactorthreads()
if #threads > 0 then
run_on_thread(threads[1], "print('Hello from Actor Thread!')")
end
Как проверяется в rUNC
Тест проверяет базовую работоспособность: getactors
возвращает таблицу, isparallel
возвращает boolean, а create_comm_channel
возвращает ID и BindableEvent
. Проверка выполнения кода на акторах (run_on_actor
) тестируется на отсутствие ошибок.
Drawing
Библиотека для рендеринга 2D‑примитивов (линий, кругов, текста и т.д.) прямо на экране. Позволяет создавать и управлять графическими объектами поверх окна Roblox, изменять их свойства и удалять при необходимости.
Синтаксис
type
: Тип создаваемого объекта ("Line"
, "Circle"
, "Square"
, "Triangle"
, "Quad"
, "Text"
, "Image"
)
collect
: (необязательно) Автоматически ли удалять объект при очистке.
Примеры
-- Создаём линию
local line = Drawing.new("Line")
line.From = Vector2.new(100, 100)
line.To = Vector2.new(200, 200)
line.Color = Color3.new(1, 0, 0) -- красный
line.Thickness = 2
line.Visible = true
-- Создаём текст
local text = Drawing.new("Text")
text.Text = "Hello, World!"
text.Position = Vector2.new(150, 150)
text.Color = Color3.new(0, 1, 0) -- зелёный
text.Size = 18
text.Font = Drawing.Fonts.UI
text.Visible = true
-- Удаляем объекты через 5 секунд
task.delay(5, function()
line:Remove()
text:Remove()
end)
local circle = Drawing.new("Circle")
circle.Position = Vector2.new(300, 300)
circle.Radius = 50
circle.Filled = false
circle.Color = Color3.new(0, 0, 1) -- синий
circle.Thickness = 3
circle.Visible = true
-- Удаляет все объекты, созданные через Drawing
Drawing.clear()
-- Также можно очистить внутренний кэш
cleardrawcache()
Как проверяется в rUNC
- Создание объекта: Проверяет, что
Drawing.new("Circle")
успешно выполняется и что результат проходит проверкуisrenderobj
.
debug.(get/set)upvalue(s)
Функции для интроспекции и модификации "upvalues" (внешних локальных переменных) Luau‑функции.
debug.getupvalues(func)
: Возвращает таблицу всех upvalue'ов функции.debug.getupvalue(func, index)
: Возвращает upvalue по его индексу.debug.setupvalue(func, index, value)
: Устанавливает новое значение для upvalue.
Примеры
-- Функция, создающая замыкание с upvalue
local function makeDummy()
local UpFunction = function()
print("Мурзик 555")
end
local function DummyFunction()
UpFunction()
end
return DummyFunction
end
local DummyFunction = makeDummy()
print("До подмены:")
DummyFunction() -- Мурзик 555
-- Читаем первый upvalue
local Retrieved = debug.getupvalue(DummyFunction, 1)
if type(Retrieved) == "function" then
print("Upvalue найден, подменяем...")
debug.setupvalue(DummyFunction, 1, function()
print("Барсик 52")
end)
else
print("Upvalue не найден или это не функция")
end
print("После подмены:")
DummyFunction() -- Барсик 52
local function outer()
local a, b = 10, "test"
return function()
return a, b
end
end
local fn = outer()
local upvalues = debug.getupvalues(fn)
for i, v in ipairs(upvalues) do
print("Upvalue #" .. i, v)
end
Как проверяется в rUNC
- Чтение:
getupvalues
иgetupvalue
вызываются для тестовой функции, и проверяется, что они возвращают правильные значения. - Запись:
setupvalue
используется для изменения upvalue. Затем тестовая функция вызывается снова, чтобы убедиться, что изменение вступило в силу. Также проверяется смена типа upvalue. - Граничные случаи: Тестируется поведение с функциями без upvalue'ов и с некорректными индексами.
- C‑функции: Проверяется, что все три функции вызывают ошибку при попытке использовать их на C‑функциях.
debug.(get/set)constant(s)
Функции для интроспекции и модификации таблицы констант Luau‑функции. Константы — это литералы (числа, строки и т.д.), которые "зашиты" в байт‑код функции.
debug.getconstants(func)
: Возвращает таблицу всех констант.debug.getconstant(func, index)
: Возвращает константу по индексу.debug.setconstant(func, index, value)
: Заменяет константу новым значением.
Примеры
local function getFuncType(func)
if islclosure(func) then
return "Lua"
else
return "C"
end
end
-- Функция с константами
local function demo()
local a = "Hello"
local b = "force_const"
local c = (true or false)
local d = ("nil_marker")
return a, b, c, d
end
print("Тип функции demo:", getFuncType(demo))
print("\n=== До подмены ===")
print(demo())
-- Получаем константы
local constants = debug.getconstants(demo)
print("\nКонстанты в функции:")
for i, v in ipairs(constants) do
if type(v) == "function" then
print("["..i.."]", v, "(function, "..getFuncType(v)..")")
else
print("["..i.."]", v, "("..type(v)..")")
end
end
-- Подменяем: все строки → "Павел Дуров"
for i, v in ipairs(constants) do
if type(v) == "string" then
debug.setconstant(demo, i, "Павел Дуров")
end
end
print("\n=== После подмены ===")
print(demo())
-- Проверка на [C] или [Lua]
print("\nТип функции print:", getFuncType(print))
print("Тип функции math.sin:", getFuncType(math.sin))
Как проверяется в rUNC
Проверяет, что getconstants
находит все типы констант (строки, числа, функции). Проверяет, что setconstant
успешно меняет константу и это отражается на поведении функции.
debug.(get/set)stack
Функции для низкоуровневой работы со стеком вызовов.
debug.getstack(level, index)
: Получает локальную переменную со стека.level
— уровень вложенности вызова (1 — текущая функция, 2 — та, что её вызвала, и т.д.),index
— номер переменной.debug.setstack(level, index, value)
: Устанавливает новое значение для локальной переменной на стеке. Тип нового значения должен совпадать с типом старого.
Примеры
local function parent(a, b)
print("[parent] До подмены:", a, b)
local function child()
-- level = 2 → стек родителя
-- index = 1 → первый аргумент (a)
debug.setstack(2, 1, 666)
-- index = 2 → второй аргумент (b)
debug.setstack(2, 2, "кошка")
end
child()
print("[parent] После подмены:", a, b)
end
-- Вызов: до подмены → 10, собака; после подмены → 666, кошка
parent(10, "собака")
Как проверяется в rUNC
- Запись в родительский стек: Проверяет, что вызов
debug.setstack
сlevel=2
успешно изменяет локальную переменную в вызывающей функции. - Запись в текущий стек: Проверяет, что
level=1
корректно изменяет переменную в текущей функции. - Несовпадение типов: Удостоверяется, что попытка установить значение другого типа вызывает ошибку.
- C‑функции: Проверяет, что вызов на C‑фрейме стека вызывает ошибку.
debug.getproto(s)
Функции для работы с "прототипами" функций (шаблонами вложенных функций).
debug.getprotos(func)
: Возвращает таблицу всех прототипов (шаблонов) внутренних функций.debug.getproto(func, index, active)
: Получает конкретный прототип. Еслиactive
=false, возвращается неактивный прототип, который нельзя вызвать. Еслиactive
=true, возвращается таблица активных экземпляров этого прототипа.
Примеры
local function container()
local function innerOne()
return "Привет из innerOne"
end
local function innerTwo()
return "Привет из innerTwo"
end
return innerOne
end
-- Получаем все прототипы функции container
local protos = debug.getprotos(container)
print("Всего прототипов:", #protos)
for i, proto in ipairs(protos) do
print(string.format("[%d] Прототип: %s", i, tostring(proto)))
local consts = debug.getconstants(proto)
if #consts > 0 then
print(" Константы:", table.concat(consts, ", "))
else
print(" Констант нет")
end
end
-- Получаем конкретный прототип по индексу (неактивный!!!)
local proto1 = debug.getproto(container, 1)
print("\nПрототип #1 (неактивный):", proto1)
-- Получаем активную функцию из прототипа
local activeFuncs = debug.getproto(container, 1, true)
print("Активные функции из прототипа #1:", #activeFuncs)
for i, f in ipairs(activeFuncs) do
print(" Активная функция #" .. i .. " вызов ->", f())
end
Как проверяется в rUNC
Проверяет получение неактивных и активных прототипов, их вызов, а также ошибку на C‑функциях.
debug.setmetatable
Версия setmetatable
из библиотеки debug
, которая игнорирует защиту __metatable
. Функционально идентична setrawmetatable
.
Синтаксис
Примеры
-- Создаём таблицы с заблокированной метатаблицей
local pot = {}
local asus = {}
setmetatable(pot, { __metatable = "LOCKED", __tostring = function() return "Горшок" end })
setmetatable(asus, { __metatable = "LOCKED", __tostring = function() return "Асус" end })
print("До обхода защиты:")
print("pot:", pot) -- Горшок
print("asus:", asus) -- Асус
-- Попытка обычной замены метатаблицы — не сработает
local ok, err = pcall(setmetatable, pot, { __tostring = function() return "Хакнутый горшок" end })
print("Обычная замена метатаблицы:", ok, err)
-- Обход защиты через debug.setmetatable
debug.setmetatable(pot, {
__tostring = function() return "Горшок взломан" end,
speak = function() return "Горшок 666" end
})
debug.setmetatable(asus, {
__tostring = function() return "Асус взломан" end,
speak = function() return "Асус легенда" end
})
print("\nПосле обхода защиты:")
print("pot:", pot)
print("asus:", asus)
-- Вызываем «методы» из новых метатаблиц
print("pot говорит:", getmetatable(pot).speak())
print("asus говорит:", getmetatable(asus).speak())
-- Проверим, что __metatable больше не LOCKED
print("\nТекущая метатаблица pot:", getmetatable(pot))
print("Текущая метатаблица asus:", getmetatable(asus))
Как проверяется в rUNC
Тест аналогичен test_setrawmetatable
:
- Подтверждение защиты: Убеждается, что обычная
setmetatable
не работает. - Обход защиты: Проверяет, что
debug.setmetatable
успешно устанавливает новую метатаблицу. - Проверка эффекта: Убеждается, что новая метатаблица активна и работает.
debug.getinfo
Возвращает таблицу с информацией о функции или уровне стека вызовов (имя, количество upvalue'ов, строка определения и т.д.).
Синтаксис
Примеры
local function my_func(a, b, ...)
local x = 123
return a + b + x
end
local ok, info = pcall(debug.getinfo, my_func, "nSluaf")
if ok and info then
print("Имя:", info.name) --> my_func
print("Источник:", info.source) --> "", то есть пусто
print("Строка определения:", info.linedefined) --> nil
print("Последняя строка:", info.lastlinedefined) --> nil
print("Upvalues:", info.nups) --> 0
print("Параметров:", info.nparams) --> nil
print("Vararg:", info.isvararg) -- true/false или nil
print("Функция:", info.func) --> function: 0x...
else
print("Ошибка при получении информации:", info)
end
local function get_caller_info()
-- "nf" → n = имя, f = сама функция
local info = debug.getinfo(2, "nf") -- 2 = вызывающая функция
return info.name, info.func
end
local function LadaGranta()
local caller_name, caller_func = get_caller_info()
print("Я вызвана функцией:", caller_name) --> LadaGranta
print("Userdata функции:", caller_func) --> function: 0x...
end
LadaGranta()
Как проверяется в rUNC
- Информация о функции: Вызывает
getinfo
для тестовой функции с разными флагами и проверяет, что поля (what
,source
,linedefined
,nups
,name
) содержат корректные значения. - Информация по уровню стека: Вызывает
getinfo
с числовым аргументом (уровнем стека) и проверяет, что получает корректную информацию о текущей (level=1
) и вызывающей (level=2
) функциях. - C‑функции: Убеждается, что вызов
getinfo
для C‑функции вызывает ошибку.
Другие debug-функции
Набор дополнительных отладочных функций.
debug.setname(func, name)
: Устанавливает имя для функции, видимое вdebug.getinfo
.debug.isvalidlevel(level)
: Проверяет, существует ли указанный уровень в стеке вызовов.
Синтаксис
Примеры
local function my_function()
return "Привет!"
end
print("Имя до:", debug.getinfo(my_function).name) -- my_function или nil
debug.setname(my_function, "Горшок")
print("Имя после:", debug.getinfo(my_function).name) -- Горшок
print(debug.isvalidlevel(1)) -- true, текущий уровень стека существует
print(debug.isvalidlevel(100)) -- false, такого уровня нет
Как проверяется в rUNC
- debug.setname: Устанавливает имя и проверяет через
debug.getinfo
, что оно изменилось. - debug.isvalidlevel: Проверяет, что возвращает
true
для валидного уровня иfalse
для невалидного.
crypt.base64encode / crypt.base64decode
Функции для кодирования и декодирования строк в формат Base64.
crypt.base64encode(data)
: Кодирует строку.crypt.base64decode(encoded_data)
: Декодирует строку.
Примеры
local original = "Hello, Roblox!"
local encoded = crypt.base64encode(original)
print("Encoded:", encoded) --> SGVsbG8sIFJvYmxveCE=
local decoded = crypt.base64decode(encoded)
print("Decoded:", decoded) --> Hello, Roblox!
Как проверяется в rUNC
- Round-trip: Кодирует строку, затем декодирует результат и проверяет, что он совпадает с оригиналом.
- Известные значения: Кодирует и декодирует заранее известные строки и сверяет результат с ожидаемым, чтобы проверить корректность самого алгоритма.
crypt.encrypt / crypt.decrypt
Функции для симметричного шифрования и дешифрования данных с использованием AES.
crypt.encrypt(data, key, iv?, mode?)
: Шифрует данные. Возвращает зашифрованную строку (в Base64) и использованный IV (в Base64).crypt.decrypt(ciphertext, key, iv, mode?)
: Расшифровывает данные, зашифрованные с помощьюcrypt.encrypt
.
Синтаксис
Примеры
-- Генерируем ключ и IV нужной длины
local key = crypt.generatekey(32) -- 32 байта для AES-256
local iv = crypt.generatekey(12) -- 12 байт для GCM
local plaintext = "Это секретное сообщение."
-- Шифруем
local ciphertext = crypt.encrypt(plaintext, key, iv, "aes-gcm")
print("Encrypted (base64):", crypt.base64encode(ciphertext))
-- Расшифровываем
local decrypted = crypt.decrypt(ciphertext, key, iv, "aes-gcm")
print("Decrypted:", decrypted)
-- Генерируем ключ (Base64)
local key = crypt.generatekey(32)
-- Шифруем, IV сгенерируется автоматически
local encrypted, iv = crypt.encrypt("Секретное сообщение", key)
print("Encrypted:", encrypted)
print("IV:", iv)
-- Расшифровываем
local decrypted = crypt.decrypt(encrypted, key, iv)
print("Decrypted:", decrypted)
Как проверяется в rUNC
- Round-trip: Генерирует ключ, шифрует строку, расшифровывает её тем же ключом и проверяет, что результат совпадает с оригиналом.
- Неверный ключ: Пытается расшифровать данные с другим ключом и убеждается, что результат не совпадает с оригиналом.
crypt.generatekey / crypt.generatebytes
Функции для генерации криптографически стойких случайных данных.
crypt.generatekey()
: Генерирует ключ для использования вcrypt.encrypt/decrypt
.crypt.generatebytes(length)
: Генерирует случайную строку байт указанной длины.
Примеры
-- Генерируем новый ключ
local new_key = crypt.generatekey()
print("Сгенерированный ключ (base64):", crypt.base64encode(new_key))
-- Генерируем 32-байтный вектор инициализации (IV)
local random_iv = crypt.generatebytes(32)
print("Длина сгенерированного IV:", #random_iv) --> 44 (в base64)
Как проверяется в rUNC
- generatekey: Проверяет, что функция возвращает непустую строку.
- generatebytes: Проверяет, что функция возвращает строку, и что её длина в точности равна запрошенной.
crypt.hash
Вычисляет хэш строки, используя указанный алгоритм.
Синтаксис
Примеры
local password = "password123"
local hashed_password = crypt.hash(password, "sha512")
print("Hashed:", crypt.base64encode(hashed_password))
Как проверяется в rUNC
- Успешное выполнение: Проверяет, что функция возвращает строку.
- Детерминированность: Хэширует одну и ту же строку дважды и убеждается, что результаты полностью совпадают.
lz4compress / lz4decompress
Функции для быстрого сжатия и распаковки данных с использованием алгоритма LZ4.
lz4compress(data)
: Сжимает строку.lz4decompress(compressed_data, original_size)
: Распаковывает строку. Требует знания исходного размера данных.
Примеры
local original_text = table.concat({string.rep("roblox ", 100)}, "")
local original_size = #original_text
local compressed = lz4compress(original_text)
print(string.format("Original: %d bytes, Compressed: %d bytes", original_size, #compressed))
-- Пример вывода: Original: 700 bytes, Compressed: 19 bytes
local decompressed = lz4decompress(compressed, original_size)
print("Round-trip successful:", original_text == decompressed) --> true
Как проверяется в rUNC
- Round-trip: Сжимает строку, затем распаковывает её, и проверяет, что результат в точности совпадает с исходной строкой.
request / http_request
Отправляет HTTP(S) запрос и возвращает ответ.
httpget(url)
: Выполняет HTTP GET-запрос и возвращает тело ответа в виде строки.httppost(url, data, content_type?)
: Выполняет HTTP POST-запрос с указанными данными и типом содержимого.request(options)
: Выполняет HTTP-запрос с расширенными параметрами (метод, заголовки, тело, куки и т.д.).http.request(options)
: Альтернативный способ вызоваrequest
через таблицуhttp
.
Примеры
local body = httpget("https://httpbin.org/get")
print("GET response body:", body)
local body = httppost(
"https://httpbin.org/post",
"key=value&test=123",
"application/x-www-form-urlencoded"
)
print("POST response body:", body)
local response = request({
Url = "https://httpbin.org/post",
Method = "POST",
Headers = {["Content-Type"] = "application/json"},
Body = '{"name": "Горшок"}',
Cookies = {session = "abc123"}
})
print("Success:", response.Success)
print("Status:", response.StatusCode, response.StatusMessage)
print("Body:", response.Body)
local response = request({
Url = "https://httpbin.org/status/404",
Method = "GET"
})
print("Success:", response.Success) -- false
print("Status:", response.StatusCode) -- 404
print("Body:", response.Body)
local ok, err = pcall(function()
return httpget("ht!tp://invalid-url")
end)
print("OK:", ok)
print("Error:", err)
Как проверяется в rUNC
- GET-запрос: Отправляется запрос на
https://httpbin.org/get
и проверяется, что ответ содержит ожидаемые данные. - POST-запрос: Отправляется запрос на
https://httpbin.org/post
с телом и заголовками, затем проверяется, что сервер получил корректные данные. - Расширенные параметры: Проверяется, что
request
корректно передаёт метод, заголовки, тело и куки. - Ошибка 404: Проверяется, что
Success
= false иStatusCode
= 404. - Невалидный URL: Проверяется, что функция выбрасывает ошибку при передаче некорректного адреса.
Файловые операции
Набор функций для работы с файлами: writefile
, readfile
, appendfile
, delfile
, isfile
.
Примеры
-- Записываем текст в файл
writefile("test.txt", "Привет, мир!")
-- Читаем содержимое файла
local content = readfile("test.txt")
print("Содержимое файла:", content)
-- Добавляем строку в конец файла
appendfile("test.txt", "\nНовая строка")
-- Проверяем результат
print(readfile("test.txt"))
if isfile("test.txt") then
print("Файл существует")
else
print("Файл не найден")
end
-- Удаляем файл
delfile("test.txt")
-- Проверяем, что файл удалён
print("Файл существует после удаления:", isfile("test.txt"))
Как проверяется в rUNC
Тест последовательно выполняет все операции, проверяя создание, чтение, добавление, перезапись и удаление файла.
Операции с папками
Набор функций для управления папками: makefolder
, isfolder
, listfiles
, delfolder
.
Примеры
-- Создаём папку
makefolder("MyFolder")
-- Проверяем, что папка существует
if isfolder("MyFolder") then
print("Папка успешно создана")
else
print("Папка не найдена")
end
-- Создаём тестовые файлы
writefile("MyFolder/file1.txt", "Содержимое 1")
writefile("MyFolder/file2.txt", "Содержимое 2")
-- Получаем список файлов
local files = listfiles("MyFolder")
print("Файлы в папке:")
for _, file in ipairs(files) do
print(file)
end
-- Удаляем папку
delfolder("MyFolder")
-- Проверяем, что папка удалена
print("Папка существует после удаления:", isfolder("MyFolder"))
Как проверяется в rUNC
Тест проверяет создание, листинг содержимого и удаление папки.
loadfile
Читает файл, содержащий Lua‑код, и компилирует его в функцию.
Синтаксис
filename
— путь к файлу с Lua‑кодом.
Возвращает скомпилированную функцию или nil
и сообщение об ошибке, если файл не удалось загрузить или скомпилировать.
Примеры
-- Создаём файл с корректным Lua‑кодом
writefile("test_script.lua", [[
return function(name)
return "Привет, " .. name .. "!"
end
]])
-- Загружаем файл
local chunk, err = loadfile("test_script.lua")
if not chunk then
error("Ошибка загрузки: " .. err)
end
-- Выполняем загруженный код, получаем функцию
local greet = chunk()
print(greet("Горшок")) -- Привет, Горшок!
-- Перезаписываем файл с ошибочным Lua‑кодом
writefile("test_script.lua", [[
return function()
local a = 10 +
end
]])
-- Пытаемся загрузить файл
local chunk, err = loadfile("test_script.lua")
if not chunk then
print("Ошибка при компиляции:", err)
else
print("Неожиданно удалось загрузить файл")
end
Как проверяется в rUNC
- Корректный код: Создаёт файл с рабочим Lua‑кодом, загружает его через
loadfile
, выполняет и проверяет результат. - Некорректный код: Перезаписывает файл с синтаксической ошибкой, вызывает
loadfile
и убеждается, что возвращаетсяnil
и сообщение об ошибке.
getcustomasset
Преобразует локальный путь к файлу в формат rbxasset://
, который можно использовать в Roblox API для загрузки аудио, моделей, изображений интерфейса и других типов ассетов.
Внутренне файл копируется в директорию контента игры и становится доступен по сгенерированному URL.
Синтаксис
Примеры
-- Скачиваем и сохраняем mp3-файл
local encoded = game:HttpGet("https://example.com/sound_base64.txt")
writefile("ExampleSound.mp3", crypt.base64decode(encoded))
-- Получаем asset ID
local asset_id = getcustomasset("ExampleSound.mp3")
print("Asset ID:", asset_id) -- rbxasset://...
-- Создаём и воспроизводим звук
local sound = Instance.new("Sound")
sound.Parent = workspace
sound.SoundId = asset_id
sound.Volume = 0.35
sound:Play()
-- Сохраняем локальный PNG
writefile("Icon.png", game:HttpGet("https://example.com/icon.png"))
-- Получаем asset ID
local icon_asset = getcustomasset("Icon.png")
-- Создаём ImageLabel с этим изображением
local image = Instance.new("ImageLabel")
image.Size = UDim2.new(0, 100, 0, 100)
image.Image = icon_asset
image.Parent = game.Players.LocalPlayer:WaitForChild("PlayerGui")
Как проверяется в rUNC
- Создаёт временный файл с тестовыми данными.
- Вызывает
getcustomasset
для этого файла. - Проверяет, что возвращаемая строка начинается с
rbxasset://
и является корректным asset ID.
WebSocket
Клиентский класс для работы с WebSocket‑соединениями в Lua.
Конструктор, события и методы
WebSocket.New(url)
/WebSocket.new(url)
/WebSocket.connect(url)
/WebSocket.Connect(url)
— создаёт новое WebSocket‑соединение и возвращает объектWebSocketClient
.ws:Send(message)
/ws:send(message)
— отправляет сообщение на сервер.ws:Close()
/ws:close()
— закрывает соединение.ws.OnMessage
— событие, вызываемое при получении сообщения от сервера.ws.OnClose
— событие, вызываемое при закрытии соединения.
Примеры
-- Создаём новое соединение
local ws = WebSocket.New("ws://echo.websocket.org")
-- Обработчик входящих сообщений
ws.OnMessage:Connect(function(message)
print("Получено:", message)
end)
-- Обработчик закрытия соединения
ws.OnClose:Connect(function()
print("Соединение закрыто")
end)
-- Отправляем сообщение
ws:Send("Привет, сервер!")
-- Закрываем соединение через 5 секунд
task.delay(5, function()
ws:Close()
end)
local ws = WebSocket.connect("ws://example.com/socket")
ws.OnMessage:Connect(function(message)
print("Получено:", message)
ws:Send("Эхо: " .. message)
end)
ws.OnClose:Connect(function()
print("Соединение закрыто сервером")
end)
ws:Send("Первое сообщение")
Как проверяется в rUNC
Тесты для WebSocket
исключены из rUNC
из‑за проблем со стабильностью. Раздел носит информационный характер.