feat(rbxl): XML-������ ������ .rbxl + Day/Night + Tool/Mouse/Backpack flow #38
@ -25,6 +25,11 @@ const SCHEDULER = {
|
||||
const HEARTBEAT_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() {
|
||||
const sig = {
|
||||
__isSignal: true,
|
||||
@ -45,9 +50,16 @@ function makeSignal() {
|
||||
sig.connect = sig.Connect;
|
||||
sig.Fire = function (...args) {
|
||||
for (const fn of [...sig.connections]) {
|
||||
try { fn(...args); } catch (e) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('[Signal handler]', e);
|
||||
// Запускаем handler в его собственной coroutine — это позволяет
|
||||
// делать wait() внутри без yield-across-C-boundary ошибки.
|
||||
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
|
||||
return 0
|
||||
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 для лога
|
||||
global.set('__log', (level, text) => {
|
||||
send('log', { level: String(level || 'info'), text: String(text || '') });
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user