Add material registry with built-in materials

This commit is contained in:
Jared Miller 2026-03-11 13:22:07 -04:00
parent dd27634f0c
commit bc2c8fa270
Signed by: shmup
GPG key ID: 22B5C6D66A38B06C
2 changed files with 125 additions and 0 deletions

View file

@ -1,4 +1,5 @@
import { describe, expect, test } from "bun:test"; import { describe, expect, test } from "bun:test";
import { MaterialRegistry } from "../materials/registry";
import { import {
BEHAVIOR_GAS, BEHAVIOR_GAS,
BEHAVIOR_LIQUID, BEHAVIOR_LIQUID,
@ -36,3 +37,38 @@ describe("material types", () => {
expect(sand.density).toBe(1.5); expect(sand.density).toBe(1.5);
}); });
}); });
describe("MaterialRegistry", () => {
test("has air at id 0", () => {
const reg = new MaterialRegistry();
const air = reg.get(0);
expect(air.name).toBe("air");
expect(air.density).toBe(0);
});
test("has sand registered", () => {
const reg = new MaterialRegistry();
const sand = reg.getByName("sand");
expect(sand).toBeDefined();
expect(sand!.behavior).toBe(BEHAVIOR_POWDER);
});
test("all material ids are unique", () => {
const reg = new MaterialRegistry();
const ids = reg.all().map((m) => m.id);
expect(new Set(ids).size).toBe(ids.length);
});
test("all material ids are in range 0-255", () => {
const reg = new MaterialRegistry();
for (const m of reg.all()) {
expect(m.id).toBeGreaterThanOrEqual(0);
expect(m.id).toBeLessThanOrEqual(255);
}
});
test("get throws for unknown id", () => {
const reg = new MaterialRegistry();
expect(() => reg.get(254)).toThrow();
});
});

89
src/materials/registry.ts Normal file
View file

@ -0,0 +1,89 @@
import {
BEHAVIOR_GAS,
BEHAVIOR_POWDER,
BEHAVIOR_SOLID,
type Material,
} from "./types";
const BUILTIN_MATERIALS: Material[] = [
{
id: 0,
name: "air",
behavior: BEHAVIOR_GAS,
density: 0,
color: [0, 0, 0, 0],
hardness: 0,
angleOfRepose: 0,
},
{
id: 1,
name: "sand",
behavior: BEHAVIOR_POWDER,
density: 1.5,
color: [0.76, 0.7, 0.5, 1.0],
hardness: 0.1,
angleOfRepose: 34,
},
{
id: 2,
name: "dirt",
behavior: BEHAVIOR_POWDER,
density: 1.3,
color: [0.45, 0.32, 0.18, 1.0],
hardness: 0.2,
angleOfRepose: 40,
},
{
id: 3,
name: "rock",
behavior: BEHAVIOR_SOLID,
density: 2.5,
color: [0.5, 0.5, 0.5, 1.0],
hardness: 1.0,
angleOfRepose: 90,
},
{
id: 4,
name: "food",
behavior: BEHAVIOR_SOLID,
density: 1.0,
color: [0.2, 0.8, 0.2, 1.0],
hardness: 0.0,
angleOfRepose: 0,
},
{
id: 5,
name: "home",
behavior: BEHAVIOR_SOLID,
density: 0,
color: [0.3, 0.3, 1.0, 1.0],
hardness: 0.0,
angleOfRepose: 0,
},
];
export class MaterialRegistry {
private byId: Map<number, Material> = new Map();
private byName: Map<string, Material> = new Map();
constructor() {
for (const m of BUILTIN_MATERIALS) {
this.byId.set(m.id, m);
this.byName.set(m.name, m);
}
}
get(id: number): Material {
const m = this.byId.get(id);
if (!m) throw new Error(`Unknown material id: ${id}`);
return m;
}
getByName(name: string): Material | undefined {
return this.byName.get(name);
}
all(): Material[] {
return [...this.byId.values()];
}
}