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
+21
View File
@@ -0,0 +1,21 @@
{
"format_version": 1,
"block": {
"id": "bworld:smithing_table",
"textures": {
"top": "bworld:smithing_table_top",
"bottom": "bworld:smithing_table_bottom",
"front": "bworld:smithing_table_front",
"side": "bworld:smithing_table_side"
},
"mining": {
"toughness": 5,
"tool": "axe"
},
"drops": "bworld:smithing_table",
"interactive": true,
"components": {
"bworld:smithing_table": {}
}
}
}
+8
View File
@@ -0,0 +1,8 @@
{
"format_version": 1,
"item": {
"id": "bworld:stone_pickaxe",
"texture": "bworld:stone_pickaxe",
"tool": "pickaxe"
}
}
@@ -0,0 +1,12 @@
{
"format_version": 1,
"recipe": {
"type": "smithing",
"tool": "bworld:wood_pickaxe",
"material": {
"id": "bworld:stone",
"count": 5
},
"result": "bworld:stone_pickaxe"
}
}
+76
View File
@@ -5,6 +5,7 @@ export function setup(ctx: ServerContext) {
register_hoeable(ctx);
register_storage(ctx);
register_furnace(ctx);
register_smithing_table(ctx);
register_crop(ctx);
register_watering_can(ctx);
}
@@ -196,6 +197,81 @@ function register_furnace(ctx: ServerContext) {
});
}
// smithing table: a tool, some of a material and maybe a third item make a better tool, see the smithing recipes.
// every player gets their own slots, and what's left in them goes back to the player when they close it
const TOOL = 0;
const MATERIAL = 1;
const ADDITION = 2;
const RESULT = 3;
function register_smithing_table(ctx: ServerContext) {
ctx.components.register_block("bworld:smithing_table", {
on_interact(_block, _params, player) {
const container = ctx.containers.create(4);
// the recipe the inputs make, with enough material
const match = () => {
const tool = container.get(TOOL);
const material = container.get(MATERIAL);
const addition = container.get(ADDITION);
if (!tool || !material) return undefined;
const recipe = ctx.recipes.smithing(tool.id, material.id, addition?.id);
if (!recipe || material.count < recipe.material_count) return undefined;
return { ...recipe, tool, material, addition };
};
// the result slot shows what taking it would give, the upgraded tool keeps the old one's data
const show_result = () => {
const recipe = match();
const shown = container.get(RESULT);
if (!recipe) {
if (shown) container.set(RESULT, undefined);
} else if (shown?.id !== recipe.result) {
container.set(RESULT, { id: recipe.result, count: 1, data: recipe.tool.data });
}
};
const stop = container.on_change((slot) => {
if (slot !== RESULT) show_result();
});
const screen = ctx.ui.open_container(player, {
container,
layout: [
{ slot: TOOL, x: 1.5, y: 0.5 },
{ slot: MATERIAL, x: 2.5, y: 0.5 },
{ slot: ADDITION, x: 3.5, y: 0.5 },
{
slot: RESULT,
x: 5.5,
y: 0.5,
output_only: true,
// the inputs are used up in the same step, so they can't be taken out after
on_take(item) {
const recipe = match();
if (!recipe || recipe.result !== item.id) return false;
recipe.tool.count -= 1;
recipe.material.count -= recipe.material_count;
if (recipe.addition) recipe.addition.count -= 1;
return true;
},
},
],
rows: 2,
});
screen.on_close(() => {
stop();
for (const slot of [TOOL, MATERIAL, ADDITION]) {
const item = container.get(slot);
if (item) player.give_item(item.id, item.count, item.data);
}
ctx.containers.delete(container.id);
});
return true;
},
});
}
// grows one stage each time it's right clicked with the fertilizer, like bone meal on wheat
function register_crop(ctx: ServerContext) {
ctx.components.register_block<{ fertilizer: string; max_age: number }>("bworld:crop", {