fix(lua): Signal Fire запускает Lua-handler в собственной coroutine
Roblox-скрипты делают:
Tool.Equipped:connect(function(mouse)
wait(0.15) -- yield внутри handler!
mouse.Icon = ...
end)
Когда сигнал Fired из JS-стороны (наш equipTool flow), мы напрямую звали
Lua-функцию — но Lua-yield в JS-callback падает с
'attempt to yield across a C-call boundary'.
Фикс: новая Lua-функция __rbxl_run_in_coroutine(fn, ...args) создаёт
свежую coroutine из handler'а, регистрирует в scheduler, делает первый
resume. Если handler уйдёт в wait — это yield в свою coroutine, не через
C-boundary. Scheduler tickScheduler потом возобновит её через delay.
Это закрывает RayGun.onEquippedLocal с wait(0.15), а также любые другие
Roblox-обработчики использующие wait() — в Roblox это стандарт.
This commit is contained in:
parent
52724ab9c8
commit
d750c94a78
@ -25,6 +25,11 @@ const SCHEDULER = {
|
|||||||
const HEARTBEAT_SIGNAL = makeSignal();
|
const HEARTBEAT_SIGNAL = makeSignal();
|
||||||
const STEPPED_SIGNAL = makeSignal();
|
const STEPPED_SIGNAL = makeSignal();
|
||||||
|
|
||||||
|
// Глобальный helper для запуска Lua-handler'ов в собственной coroutine.
|
||||||
|
// Без этого Roblox-обработчики которые внутри делают wait() падают с
|
||||||
|
// "attempt to yield across a C-call boundary".
|
||||||
|
let _runHandlerInCoroutine = null;
|
||||||
|
|
||||||
function makeSignal() {
|
function makeSignal() {
|
||||||
const sig = {
|
const sig = {
|
||||||
__isSignal: true,
|
__isSignal: true,
|
||||||
@ -45,9 +50,16 @@ function makeSignal() {
|
|||||||
sig.connect = sig.Connect;
|
sig.connect = sig.Connect;
|
||||||
sig.Fire = function (...args) {
|
sig.Fire = function (...args) {
|
||||||
for (const fn of [...sig.connections]) {
|
for (const fn of [...sig.connections]) {
|
||||||
try { fn(...args); } catch (e) {
|
// Запускаем handler в его собственной coroutine — это позволяет
|
||||||
// eslint-disable-next-line no-console
|
// делать wait() внутри без yield-across-C-boundary ошибки.
|
||||||
console.error('[Signal handler]', e);
|
if (_runHandlerInCoroutine) {
|
||||||
|
try { _runHandlerInCoroutine(fn, args); } catch (e) {
|
||||||
|
console.error('[Signal handler]', e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try { fn(...args); } catch (e) {
|
||||||
|
console.error('[Signal handler]', e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1389,7 +1401,29 @@ export function registerRobloxShim(lua, opts) {
|
|||||||
if type(ret) == 'number' then return ret end
|
if type(ret) == 'number' then return ret end
|
||||||
return 0
|
return 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Запуск Lua-handler'а в собственной coroutine.
|
||||||
|
-- Используется при Fire сигнала из JS — иначе wait() внутри handler'а
|
||||||
|
-- падает с 'attempt to yield across a C-call boundary'.
|
||||||
|
__rbxl_next_handler_id = 0
|
||||||
|
function __rbxl_run_in_coroutine(fn, a1, a2, a3, a4)
|
||||||
|
__rbxl_next_handler_id = __rbxl_next_handler_id + 1
|
||||||
|
local handlerId = "handler_" .. __rbxl_next_handler_id
|
||||||
|
local co = coroutine.create(function() fn(a1, a2, a3, a4) end)
|
||||||
|
__rbxl_register_coroutine(handlerId, co)
|
||||||
|
local ok, ret = coroutine.resume(co)
|
||||||
|
if not ok then
|
||||||
|
__rbxl_send_error(handlerId, tostring(ret))
|
||||||
|
__rbxl_unregister_coroutine(handlerId)
|
||||||
|
elseif type(ret) == 'number' then
|
||||||
|
__rbxl_schedule_resume(handlerId, ret)
|
||||||
|
elseif coroutine.status(co) == 'dead' then
|
||||||
|
__rbxl_unregister_coroutine(handlerId)
|
||||||
|
end
|
||||||
|
end
|
||||||
`);
|
`);
|
||||||
|
// Кешируем ссылку на функцию для использования из makeSignal
|
||||||
|
_runHandlerInCoroutine = lua.global.get('__rbxl_run_in_coroutine');
|
||||||
// Добавим Lua-side helper для лога
|
// Добавим Lua-side helper для лога
|
||||||
global.set('__log', (level, text) => {
|
global.set('__log', (level, text) => {
|
||||||
send('log', { level: String(level || 'info'), text: String(text || '') });
|
send('log', { level: String(level || 'info'), text: String(text || '') });
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user