a7b69bd038
Adds worker/src/models.rs (parent-chain blockstate/model resolution, texture-variable substitution reusing Phase 12's atlas keys), routes non-cube blocks through new per-element mesh emission in mesh.rs while leaving full-cube blocks on the existing cube mesher, and threads a per-server ModelContext (vanilla worker-wide + modded per-job) through main.rs. Modded model JSON is stored in a new block_models Postgres table and read alongside the existing (previously write-only) block_registry table. Fixes a pre-existing face-culling bug as a side effect of excluding non-cube voxels from the cube mesher's input. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015tKdPZt78zbPUZMXWzKEKt
63 lines
2.4 KiB
TypeScript
63 lines
2.4 KiB
TypeScript
import { describe, test, expect, beforeAll, afterAll } from "bun:test";
|
|
import { and, eq } from "drizzle-orm";
|
|
import { db } from "./db/client";
|
|
import { blockModels } from "./db/schema";
|
|
import { storeBlockModels } from "./models";
|
|
import { createTestServer, deleteTestServer } from "./test-helpers";
|
|
|
|
describe("storeBlockModels", () => {
|
|
let server: { id: string };
|
|
|
|
beforeAll(async () => {
|
|
server = await createTestServer("block-models");
|
|
});
|
|
|
|
afterAll(async () => {
|
|
await deleteTestServer(server.id);
|
|
});
|
|
|
|
test("upserts blockstate and model entries, keyed by (serverId, kind, name)", async () => {
|
|
await storeBlockModels(server.id, [
|
|
{ kind: "blockstate", name: "thaumcraft:blockcustomplant", json: '{"variants":{}}' },
|
|
{ kind: "model", name: "thaumcraft:block/customplant", json: '{"elements":[]}' },
|
|
]);
|
|
const rows = await db.select().from(blockModels).where(eq(blockModels.serverId, server.id));
|
|
expect(rows.length).toBe(2);
|
|
expect(rows.find((r) => r.kind === "blockstate")?.name).toBe("thaumcraft:blockcustomplant");
|
|
expect(rows.find((r) => r.kind === "model")?.json).toBe('{"elements":[]}');
|
|
});
|
|
|
|
test("a blockstate and a model can share the same name without colliding (kind is part of the key)", async () => {
|
|
await storeBlockModels(server.id, [
|
|
{ kind: "blockstate", name: "thaumcraft:foo", json: '{"a":1}' },
|
|
{ kind: "model", name: "thaumcraft:foo", json: '{"b":2}' },
|
|
]);
|
|
const rows = await db
|
|
.select()
|
|
.from(blockModels)
|
|
.where(and(eq(blockModels.serverId, server.id), eq(blockModels.name, "thaumcraft:foo")));
|
|
expect(rows.length).toBe(2);
|
|
});
|
|
|
|
test("re-sending the same (kind, name) with new JSON overwrites, not duplicates", async () => {
|
|
await storeBlockModels(server.id, [{ kind: "model", name: "thaumcraft:block/customplant", json: '{"v":1}' }]);
|
|
await storeBlockModels(server.id, [{ kind: "model", name: "thaumcraft:block/customplant", json: '{"v":2}' }]);
|
|
const rows = await db
|
|
.select()
|
|
.from(blockModels)
|
|
.where(
|
|
and(
|
|
eq(blockModels.serverId, server.id),
|
|
eq(blockModels.kind, "model"),
|
|
eq(blockModels.name, "thaumcraft:block/customplant"),
|
|
),
|
|
);
|
|
expect(rows.length).toBe(1);
|
|
expect(rows[0]!.json).toBe('{"v":2}');
|
|
});
|
|
|
|
test("an empty list is a no-op, not an error", async () => {
|
|
await expect(storeBlockModels(server.id, [])).resolves.toBeUndefined();
|
|
});
|
|
});
|