All checks were successful
Часть тест-фичи импорта Roblox-карт (см. rublox/studio rbxl-importer/). Что добавлено: - wasmoon (Lua 5.4 WASM) как dep. - RobloxLuaWorker.js — Worker-хост Lua-VM. - RobloxLuaSandbox.js — main-side обёртка (по аналогии с ScriptSandbox). - roblox-shim.js — math (Vector3/Color3/CFrame/UDim2), Instance прокси (game/workspace/script/GetService/IsA), Part свойства (Position/Color/Material/Anchored/CanCollide), RBXScriptSignal (Touched/Heartbeat/Stepped/Connect/Wait). - roblox-scheduler.js — корутины + wait/task.wait/task.delay/task.spawn, автоматический fire Heartbeat/Stepped/RenderStepped на tick. - roblox-tween.js — TweenService с 10 easing-функциями (Linear, Quad, Cubic, Quart, Quint, Sine, Bounce, Elastic, Back, Exponential). - roblox-services.js — Players/LocalPlayer/Character/Humanoid (Health, WalkSpeed, JumpPower, TakeDamage, Died, LoadAnimation), UserInputService, RemoteEvent (FireServer/FireClient), RemoteFunction, DataStoreService, HttpService. - roblox-physics.js — BodyVelocity/BodyGyro/BodyPosition/BodyForce/ BodyAngularVelocity/AlignPosition/LinearVelocity. Интеграция в GameRuntime: - В start() проверяется script.kind === 'roblox-lua' → _startRobloxLuaScript() запускает RobloxLuaSandbox. - _handleRobloxLuaCommand() мапит IPC команды (partSet/partVel/playerCmd) на PrimitiveManager и game.player API. - _buildRobloxLuaSceneSnap() готовит snap для workspace:GetChildren. Тесты: **36/36 passed**. - mvp (9): math, Instance proxy, Part, IsA. - wait (5): корутины, wait/task.wait/task.delay. - tween (2): TweenInfo + Linear easing. - services (8): Humanoid, DataStore, HttpService, RemoteEvent. - integration (12): KillBrick, WalkSpeed, Tween-door, BodyVelocity конвейер, leaderstats, Checkpoint, циклы с wait, task.spawn, Color/Material, RemoteEvent client→server, Heartbeat, Vector3. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
105 lines
2.9 KiB
JavaScript
105 lines
2.9 KiB
JavaScript
/**
|
|
* rbxl-lua-wait.test.js — тесты wait/task.wait через шедулер.
|
|
*/
|
|
import { LuaFactory } from 'wasmoon';
|
|
import { registerRobloxApi } from '../src/engine/roblox-shim.js';
|
|
import { RobloxScheduler } from '../src/engine/roblox-scheduler.js';
|
|
|
|
const SCENE = { primitives: {} };
|
|
|
|
async function run(luaSource, ticks = [0.5, 0.5, 0.5, 0.5, 0.5]) {
|
|
const factory = new LuaFactory();
|
|
const lua = await factory.createEngine();
|
|
const sent = [];
|
|
const send = (cmd, payload) => sent.push({ cmd, payload });
|
|
registerRobloxApi(lua, { getSceneSnap: () => SCENE, targetPrimitiveId: null, send });
|
|
const sched = new RobloxScheduler(lua);
|
|
sched.install();
|
|
|
|
await sched.spawnMain(luaSource);
|
|
for (const dt of ticks) {
|
|
await sched.tick(dt);
|
|
}
|
|
lua.global.close();
|
|
return sent.filter(s => s.cmd === 'log').map(s => s.payload);
|
|
}
|
|
|
|
const TESTS = [
|
|
{
|
|
name: 'wait(0) — мгновенный',
|
|
lua: `
|
|
print("before")
|
|
wait(0)
|
|
print("after")
|
|
`,
|
|
expect: ['before', 'after'],
|
|
},
|
|
{
|
|
name: 'wait(1) — резюм после tick',
|
|
lua: `
|
|
print("step1")
|
|
wait(1)
|
|
print("step2")
|
|
`,
|
|
ticks: [0.5, 0.5, 0.5], // 1.5 сек суммарно
|
|
expect: ['step1', 'step2'],
|
|
},
|
|
{
|
|
name: 'task.wait(0.5)',
|
|
lua: `
|
|
print("a")
|
|
task.wait(0.5)
|
|
print("b")
|
|
`,
|
|
ticks: [0.5, 0.5],
|
|
expect: ['a', 'b'],
|
|
},
|
|
{
|
|
name: 'несколько wait подряд',
|
|
lua: `
|
|
print("p1")
|
|
wait(0.5)
|
|
print("p2")
|
|
wait(0.5)
|
|
print("p3")
|
|
`,
|
|
ticks: [0.5, 0.5, 0.5, 0.5], // 2 сек
|
|
expect: ['p1', 'p2', 'p3'],
|
|
},
|
|
{
|
|
name: 'task.delay (не блокирует)',
|
|
lua: `
|
|
print("immediate")
|
|
task.delay(0.3, function() print("delayed") end)
|
|
print("after delay-call")
|
|
`,
|
|
ticks: [0.5],
|
|
expect: ['immediate', 'after delay-call', 'delayed'],
|
|
},
|
|
];
|
|
|
|
(async () => {
|
|
let passed = 0, failed = 0;
|
|
for (const t of TESTS) {
|
|
try {
|
|
const logs = await run(t.lua, t.ticks);
|
|
const texts = logs.map(l => l.text);
|
|
const ok = JSON.stringify(texts) === JSON.stringify(t.expect);
|
|
if (ok) {
|
|
console.log(`✓ ${t.name}`);
|
|
passed++;
|
|
} else {
|
|
console.log(`✗ ${t.name}`);
|
|
console.log(` expected: ${JSON.stringify(t.expect)}`);
|
|
console.log(` got: ${JSON.stringify(texts)}`);
|
|
failed++;
|
|
}
|
|
} catch (e) {
|
|
console.log(`✗ ${t.name} — exception: ${e}`);
|
|
failed++;
|
|
}
|
|
}
|
|
console.log(`\n${passed} passed, ${failed} failed`);
|
|
process.exit(failed > 0 ? 1 : 0);
|
|
})();
|