Smithing table

This commit is contained in:
2026-09-25 23:48:29 -03:00
parent 9237152aa1
commit 8f32a59bd6
15 changed files with 279 additions and 13 deletions
+67
View File
@@ -195,3 +195,70 @@ Deno.test("chests and furnaces from a world saved before they were mod code keep
assert(saved.tiles.every((tile: Msg) => tile.data === undefined && tile.containers === undefined));
assertEquals(Object.keys(saved.containers).length, 2);
});
Deno.test("a smithing table upgrades a wooden pickaxe with 5 stone, using up exactly that", async () => {
const t = await setup([["bworld:wood_pickaxe", 1], ["bworld:stone", 7]]);
t.game.set_block(1, 100, 0, "bworld:smithing_table");
let messages = t.take(1);
const pickaxe = slot_of(messages, "bworld:wood_pickaxe");
const stone = slot_of(messages, "bworld:stone");
t.send(1, { type: "use_block", x: 1, y: 100, z: 0, face: "top" });
const opened = t.take(1).find((m) => m.type === "open_screen");
assertEquals(opened.layout.slots.map((s: Msg) => [s.index, s.output ?? false]), [
[0, false],
[1, false],
[2, false],
[3, true],
]);
// with only the tool there's nothing to take
move_to_screen(t, pickaxe, 0);
t.game.tick();
t.send(1, { type: "click", container: "screen", index: 3, button: 0 });
assertEquals(t.take(1).filter((m) => m.type === "cursor").at(-1)?.item ?? null, null);
// the result shows up once there's enough stone, and taking it uses up the pickaxe and 5 stone
move_to_screen(t, stone, 1);
t.game.tick();
assertEquals(last_container(t.take(1), "screen")[3], { id: "bworld:stone_pickaxe", count: 1 });
t.send(1, { type: "click", container: "screen", index: 3, button: 0 });
messages = t.take(1);
assertEquals(messages.filter((m) => m.type === "cursor").at(-1).item, { id: "bworld:stone_pickaxe", count: 1 });
assertEquals(last_container(messages, "screen"), [null, { id: "bworld:stone", count: 2 }, null, null]);
// closing gives back the leftover stone, and the cursor's pickaxe goes into the inventory
t.send(1, { type: "close_screen" });
const inventory = last_container(t.take(1), "inventory").filter((i: Msg) => i);
assertEquals(
inventory.sort((a: Msg, b: Msg) => a.id.localeCompare(b.id)),
[{ id: "bworld:stone", count: 2 }, { id: "bworld:stone_pickaxe", count: 1 }],
);
assertEquals(t.game.containers.size, 0);
});
Deno.test("a smithing result can't be taken once its inputs are gone, even before it updates", async () => {
const t = await setup([["bworld:wood_pickaxe", 1], ["bworld:stone", 5]]);
t.game.set_block(1, 100, 0, "bworld:smithing_table");
const messages = t.take(1);
t.send(1, { type: "use_block", x: 1, y: 100, z: 0, face: "top" });
move_to_screen(t, slot_of(messages, "bworld:wood_pickaxe"), 0);
move_to_screen(t, slot_of(messages, "bworld:stone"), 1);
t.game.tick();
// take the pickaxe back out and try the result in the same tick
t.send(1, { type: "click", container: "screen", index: 0, button: 0 });
t.send(1, { type: "click", container: "inventory", index: 20, button: 0 });
t.send(1, { type: "click", container: "screen", index: 3, button: 0 });
const cursor = t.take(1).filter((m) => m.type === "cursor").at(-1).item;
assertEquals(cursor, null);
// and an extra item in the third slot doesn't match a recipe without one
t.send(1, { type: "click", container: "inventory", index: 20, button: 0 });
t.send(1, { type: "click", container: "screen", index: 0, button: 0 });
t.send(1, { type: "chat", text: "/give bworld:coal 1" });
const coal = slot_of(t.take(1), "bworld:coal");
move_to_screen(t, coal, 2);
t.game.tick();
assertEquals(last_container(t.take(1), "screen")[3], null);
});