feat(rbxl): XML-������ ������ .rbxl + Day/Night + Tool/Mouse/Backpack flow #38
@ -274,23 +274,48 @@ function isProbablySignalName(prop) {
|
|||||||
|| /(Changed|Added|Removed|Began|Ended|Clicked|Activated|Touched|Died|Loaded|Hover|Connect|Event|Signal|Reached)$/.test(prop);
|
|| /(Changed|Added|Removed|Began|Ended|Clicked|Activated|Touched|Died|Loaded|Hover|Connect|Event|Signal|Reached)$/.test(prop);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Callable stub: функция которая ничего не делает + поля Connect/Wait/Fire,
|
// Универсальный object-stub: ведёт себя как сигнал, как Instance, как Tool/Folder.
|
||||||
// чтобы выглядеть и как метод (`obj:Method()`), и как сигнал (`sig:Connect()`),
|
// НЕ function — иначе wasmoon мапит в Lua-function и Lua-индексация `.field`
|
||||||
// и как объект (`obj.Property`).
|
// падает с "attempt to index a function value".
|
||||||
function makeCallableStub(name) {
|
function makeObjectStub(name) {
|
||||||
// Используем function чтобы Proxy мог иметь apply trap
|
const target = {
|
||||||
const fnTarget = function () { return fnTarget; };
|
__stubName: name || 'stub',
|
||||||
fnTarget.__stubName = name || 'stub';
|
// Signal API
|
||||||
fnTarget.Connect = function () { return { Disconnect: () => {}, disconnect: () => {}, Connected: false }; };
|
Connect() { return { Disconnect() {}, disconnect() {}, Connected: false }; },
|
||||||
fnTarget.connect = fnTarget.Connect;
|
connect() { return this.Connect(); },
|
||||||
fnTarget.Wait = function () { return undefined; };
|
Wait() { return undefined; },
|
||||||
fnTarget.wait = fnTarget.Wait;
|
wait() { return undefined; },
|
||||||
fnTarget.Fire = function () { return undefined; };
|
Fire() {},
|
||||||
fnTarget.fire = fnTarget.Fire;
|
fire() {},
|
||||||
fnTarget.Disconnect = function () {};
|
Disconnect() {},
|
||||||
fnTarget.disconnect = fnTarget.Disconnect;
|
disconnect() {},
|
||||||
// Proxy чтобы любое доступ к unknown полю/индексу возвращал тот же stub
|
// Instance read-API
|
||||||
return new Proxy(fnTarget, {
|
FindFirstChild() { return undefined; },
|
||||||
|
FindFirstChildOfClass() { return undefined; },
|
||||||
|
FindFirstAncestor() { return undefined; },
|
||||||
|
FindFirstAncestorOfClass() { return undefined; },
|
||||||
|
GetChildren() { return []; },
|
||||||
|
GetDescendants() { return []; },
|
||||||
|
IsA() { return false; },
|
||||||
|
GetFullName() { return name || 'stub'; },
|
||||||
|
Destroy() {},
|
||||||
|
Clone() { return makeObjectStub(name); },
|
||||||
|
GetAttribute() { return undefined; },
|
||||||
|
SetAttribute() {},
|
||||||
|
GetPropertyChangedSignal() { return makeObjectStub('Changed'); },
|
||||||
|
// Tool/Animation/Sound — частые no-op методы
|
||||||
|
Activate() {}, Deactivate() {}, Equip() {}, Unequip() {},
|
||||||
|
Play() {}, Stop() {}, Pause() {}, Resume() {},
|
||||||
|
AdjustSpeed() {}, LoadAnimation() { return makeObjectStub('Animation'); },
|
||||||
|
TakeDamage() {}, MoveTo() {},
|
||||||
|
// Базовые поля
|
||||||
|
Parent: undefined,
|
||||||
|
Name: name || 'stub',
|
||||||
|
ClassName: 'Folder',
|
||||||
|
Children: [],
|
||||||
|
};
|
||||||
|
target.WaitForChild = function (childName) { return makeObjectStub(childName); };
|
||||||
|
return new Proxy(target, {
|
||||||
get(t, prop) {
|
get(t, prop) {
|
||||||
if (Object.prototype.hasOwnProperty.call(t, prop) || prop in t) {
|
if (Object.prototype.hasOwnProperty.call(t, prop) || prop in t) {
|
||||||
return t[prop];
|
return t[prop];
|
||||||
@ -301,12 +326,11 @@ function makeCallableStub(name) {
|
|||||||
prop.startsWith('__') || prop.startsWith('Symbol')) {
|
prop.startsWith('__') || prop.startsWith('Symbol')) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
const child = makeCallableStub(prop);
|
const child = makeObjectStub(prop);
|
||||||
t[prop] = child;
|
t[prop] = child;
|
||||||
return child;
|
return child;
|
||||||
},
|
},
|
||||||
set(t, prop, value) { t[prop] = value; return true; },
|
set(t, prop, value) { t[prop] = value; return true; },
|
||||||
apply() { return fnTarget; }, // obj() возвращает себя
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -354,10 +378,10 @@ function newInstance(className, name) {
|
|||||||
prop.startsWith('__') || prop.startsWith('Symbol')) {
|
prop.startsWith('__') || prop.startsWith('Symbol')) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
// Callable-stub: можно вызвать как функцию, как сигнал (:Connect),
|
// Object-stub: ведёт себя как сигнал (Connect), как Instance
|
||||||
// как объект (.Property), как child Instance (.WaitForChild). Не падает
|
// (WaitForChild, GetChildren), как Tool (Activate). НЕ function —
|
||||||
// на любом обращении со стороны импортированных скриптов.
|
// иначе Lua упадёт с "attempt to index a function value".
|
||||||
const stub = makeCallableStub(prop);
|
const stub = makeObjectStub(prop);
|
||||||
t[prop] = stub;
|
t[prop] = stub;
|
||||||
return stub;
|
return stub;
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user