import { Make } from "@rbxts/altmake"; import type { Entity } from "@rbxts/jecs"; import { pair, world } from "@rbxts/jecs"; import { beforeEach, describe, expect, it, jest } from "@rbxts/jest-globals"; import { useDeltaTime } from "@rbxts/planck-matter-hooks"; import { Workspace } from "@rbxts/services"; import { Trove } from "@rbxts/trove"; import { Handle } from "common/shared/constants/world"; import components from "common/shared/ecs/components"; import { startReplication, startSnapshots } from "common/shared/ecs/replication"; import { wrapSystem } from "common/shared/utils"; import stepMotion from "../ecs/systems/reconcile/step-motion"; import updateMotion from "../ecs/systems/reconcile/update-motion"; import createMotion from "../ecs/systems/update/spawn-motion"; const func = jest.fn(); const useDeltaTimeMock = jest.mock< typeof import("@rbxts/planck-matter-hooks/out/hooks/useDeltaTime") >(getModuleByTree(...$getModuleTree("@rbxts/planck-matter-hooks/out/hooks/useDeltaTime")), () => { return { useDeltaTime: func(), }; }); func.mockReturnValue(0); describe("update motion", () => { const UpdateMotionSystem = wrapSystem(updateMotion); const SpawnMotionSystem = wrapSystem(createMotion); const StepMotionSystem = wrapSystem(stepMotion); let serverHandle: Handle; let clientHandle: Handle; const trove = new Trove(); function spawnTestEntity(handle: Handle): Entity { const entity = handle.entity(); const part = Make("Part", { Anchored: true, CFrame: new CFrame(0, 100, 0), Parent: Workspace, }); handle.set(entity, components.NetworkedPart, part); handle.set( entity, pair(components.NetworkedStartPair, components.Transform), new CFrame(0, 100, 0), ); handle.set( entity, pair(components.NetworkedGoalPair, components.Transform), new CFrame(0, 10, 0), ); handle.set(entity, components.NetworkedTweenOptions, {}); return entity; } beforeEach(() => { serverHandle = new Handle(world()); clientHandle = new Handle(world()); trove.clean(); jest.restoreAllMocks(); jest.resetModules() }); it("should spawn target component if entity doesn't have it", () => { const { disconnect, drain } = startReplication(serverHandle); const patch = startSnapshots(clientHandle); trove.add(disconnect); const mockMovableEntity = spawnTestEntity(serverHandle); serverHandle.set(mockMovableEntity, components.NetworkedSpringOptions, {}); patch(drain()); SpawnMotionSystem(clientHandle); UpdateMotionSystem(clientHandle); const spyMotionObjectQuery = jest.fn(); const spyTransformQuery = jest.fn(); for (const [_, motion] of clientHandle.query(components.MotionObject)) { spyMotionObjectQuery(); expect(typeIs(motion.get(), "CFrame")).toBe(true); expect(motion.get()).never.toStrictEqual(new CFrame(0, 100, 0)); } for (const _ of clientHandle.each(components.Transform)) spyTransformQuery(); expect(spyMotionObjectQuery).toHaveBeenCalledTimes(1); expect(spyTransformQuery).toHaveBeenCalledTimes(1); }); it("should finish motion with correct target position", (_, done) => { const { disconnect, drain } = startReplication(serverHandle); const patch = startSnapshots(clientHandle); trove.add(disconnect); const mockMovableEntity = spawnTestEntity(serverHandle); serverHandle.set(mockMovableEntity, components.NetworkedSpringOptions, {}); patch(drain()); print(useDeltaTime()); print($getModuleTree("@rbxts/planck-matter-hooks/out")); SpawnMotionSystem(clientHandle); UpdateMotionSystem(clientHandle); StepMotionSystem(clientHandle); // print(os.clock()); SpawnMotionSystem(clientHandle); UpdateMotionSystem(clientHandle); StepMotionSystem(clientHandle); // const servicesModule = getModuleByTree(...$getModuleTree("@rbxts/planck-matter-hooks")); // print(type(servicesModule)); for (const [, motion] of clientHandle.query(components.MotionObject)) { // print(motion.get()); // motion.onComplete(() => { // expect(motion.get()).toStrictEqual(new CFrame(0, 10, 0)); // expect(clientHandle.get(mockMovableEntity, components.Transform)).toStrictEqual( // new CFrame(0, 10, 0), // ); // done(); // }); } }); }); function getModuleByTree(root: Instance, tree: Array): ModuleScript { let result = root; for (const child of tree) { result = result.WaitForChild(child)!; } return result as ModuleScript; }