Update Healer Man server
This commit is contained in:
1 parent
69809f7228
commit
ff20ab8779
101 files changed
+16713
-945
No files matched your search
@@ -0,0 +1,88 @@
|
||||
import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
import {
|
||||
countSurfaceBucketReferences,
|
||||
selectDetourAnchorComponents,
|
||||
} from "./detour-component-selection.mjs";
|
||||
|
||||
function topologyFixture() {
|
||||
const polygons = [
|
||||
[0, 0, 0, 0, 0, 0, 0, 2, 4],
|
||||
[1, 0, 0, 0, 0, 1, 2, 1, 3],
|
||||
[2, 1, 1, 0, 0, 0, 3, 3, 4],
|
||||
[3, 2, 2, 0, 0, 0, 6, 1, 3],
|
||||
];
|
||||
const link = (from, to, edge) => [from, to, edge, 0, 0, 255, 0, 1, from, 0, 0, to, 0, 0];
|
||||
return {
|
||||
schemaVersion: 1,
|
||||
polygonCount: 4,
|
||||
tileCount: 3,
|
||||
detailTriangleCount: 7,
|
||||
geometryTriangleCount: 7,
|
||||
polygonFanTriangleCount: 5,
|
||||
directedLinkCount: 2,
|
||||
unrepresentedLinkCount: 0,
|
||||
offMeshPolygonCount: 0,
|
||||
weakComponents: { count: 3, largestPolygonCount: 2, polygonCounts: [2, 1, 1] },
|
||||
polygons,
|
||||
links: [link(0, 2, 0), link(2, 0, 1)],
|
||||
};
|
||||
}
|
||||
|
||||
test("source anchors retain complete weak Detour components and remap only exact source links", () => {
|
||||
const selected = selectDetourAnchorComponents(topologyFixture(), [
|
||||
{ id: "entry", kind: "entry", position: [0, 0, 0], polygonId: 0, distance: 0.2, maximumDistance: 0.5, required: true },
|
||||
{ id: "boss", kind: "boss", position: [100, 0, 0], polygonId: 3, distance: 0.1, maximumDistance: 0.25, required: true },
|
||||
{ id: "far-combat", kind: "combat", position: [50, 0, 0], polygonId: 1, distance: 7, maximumDistance: 4 },
|
||||
]);
|
||||
|
||||
assert.deepEqual([...selected.selectedSourcePolygonIds], [0, 2, 3]);
|
||||
assert.deepEqual([...selected.sourceToSelectedPolygonId], [[0, 0], [2, 1], [3, 2]]);
|
||||
assert.equal(selected.topology.polygonCount, 3);
|
||||
assert.equal(selected.topology.directedLinkCount, 2);
|
||||
assert.equal(selected.topology.detailTriangleCount, 6);
|
||||
assert.deepEqual(selected.topology.polygons.map((row) => row.slice(0, 8)), [
|
||||
[0, 0, 0, 0, 0, 0, 0, 2],
|
||||
[1, 1, 1, 0, 0, 0, 2, 3],
|
||||
[2, 2, 2, 0, 0, 0, 5, 1],
|
||||
]);
|
||||
assert.deepEqual(selected.topology.links.map((row) => row.slice(0, 2)), [[0, 1], [1, 0]]);
|
||||
assert.equal(selected.summary.retainedAnchorIds.includes("entry"), true);
|
||||
assert.equal(selected.summary.retainedAnchorIds.includes("boss"), true);
|
||||
assert.equal(selected.summary.unmatchedAnchors[0].id, "far-combat");
|
||||
assert.equal(selected.summary.excluded.polygonCount, 1);
|
||||
assert.equal(selected.summary.excluded.disposition, "unanchored-components-excluded; not individually proven decorative");
|
||||
});
|
||||
|
||||
test("selection fails closed when an anchored component exceeds any runtime budget", () => {
|
||||
const source = topologyFixture();
|
||||
assert.throws(() => selectDetourAnchorComponents(source, [
|
||||
{ id: "entry", polygonId: 0, distance: 0, maximumDistance: 1 },
|
||||
], { limits: { polygons: 1 } }), /polygons budget/);
|
||||
assert.throws(() => selectDetourAnchorComponents(source, [
|
||||
{ id: "entry", polygonId: 0, distance: 0, maximumDistance: 1 },
|
||||
], { limits: { directedLinks: 1 } }), /directedLinks budget/);
|
||||
assert.throws(() => selectDetourAnchorComponents(source, [
|
||||
{ id: "entry", polygonId: 0, distance: 0, maximumDistance: 1 },
|
||||
], { limits: { detailTriangles: 1 } }), /detailTriangles budget/);
|
||||
assert.throws(() => selectDetourAnchorComponents(source, [
|
||||
{ id: "entry", polygonId: 0, distance: 0, maximumDistance: 1 },
|
||||
], { limits: { surfaceBucketReferences: 3 }, surfaceBucketReferenceCount: 4 }), /surfaceBucketReferences budget/);
|
||||
});
|
||||
|
||||
test("source anchors outside their explicit projection limit do not select components", () => {
|
||||
assert.throws(() => selectDetourAnchorComponents(topologyFixture(), [
|
||||
{ id: "unprojected", polygonId: 2, distance: 4.001, maximumDistance: 4 },
|
||||
]), /No source anchors map/);
|
||||
});
|
||||
|
||||
test("surface bucket references match runtime's XZ cell coverage rule", () => {
|
||||
const positions = new Float32Array([
|
||||
0, 0, 0,
|
||||
8, 0, 0,
|
||||
0, 0, 8,
|
||||
-0.1, 0, -0.1,
|
||||
]);
|
||||
const indices = new Uint32Array([0, 1, 2, 0, 2, 3]);
|
||||
assert.equal(countSurfaceBucketReferences(positions, indices, 8), 10);
|
||||
});
|
||||
Reference in new issue
Block a user