132 lines
2.8 KiB
TypeScript
132 lines
2.8 KiB
TypeScript
import { Container, ItemStack } from "$/common/inventory.ts";
|
|
import { CRAFTING_RESULT_SLOT } from "$/common/protocol.ts";
|
|
|
|
export interface CraftingRecipe {
|
|
width: number;
|
|
height: number;
|
|
pattern: (string | undefined)[];
|
|
result: { id: string; count: number };
|
|
}
|
|
|
|
export const CRAFTING_RECIPES: CraftingRecipe[] = [
|
|
{
|
|
width: 3,
|
|
height: 3,
|
|
pattern: [
|
|
"bworld:planks",
|
|
"bworld:planks",
|
|
"bworld:planks",
|
|
"bworld:planks",
|
|
undefined,
|
|
"bworld:planks",
|
|
"bworld:planks",
|
|
"bworld:planks",
|
|
"bworld:planks",
|
|
],
|
|
result: { id: "bworld:chest", count: 1 },
|
|
},
|
|
{
|
|
width: 3,
|
|
height: 3,
|
|
pattern: [
|
|
"bworld:stone",
|
|
"bworld:stone",
|
|
"bworld:stone",
|
|
"bworld:stone",
|
|
undefined,
|
|
"bworld:stone",
|
|
"bworld:stone",
|
|
"bworld:stone",
|
|
"bworld:stone",
|
|
],
|
|
result: { id: "bworld:furnace", count: 1 },
|
|
},
|
|
{
|
|
width: 1,
|
|
height: 1,
|
|
pattern: [
|
|
"bworld:log",
|
|
],
|
|
result: { id: "bworld:planks", count: 2 },
|
|
},
|
|
{
|
|
width: 1,
|
|
height: 2,
|
|
pattern: [
|
|
"bworld:planks",
|
|
"bworld:planks",
|
|
],
|
|
result: { id: "bworld:stick", count: 2 },
|
|
},
|
|
{
|
|
width: 3,
|
|
height: 3,
|
|
pattern: [
|
|
"bworld:planks",
|
|
"bworld:planks",
|
|
"bworld:planks",
|
|
undefined,
|
|
"bworld:stick",
|
|
undefined,
|
|
undefined,
|
|
"bworld:stick",
|
|
undefined,
|
|
],
|
|
result: { id: "bworld:wood_pickaxe", count: 1 },
|
|
},
|
|
];
|
|
|
|
function get_crafting_grid(crafting: Container): (string | undefined)[] {
|
|
const grid: (string | undefined)[] = [];
|
|
for (let i = 0; i < 9; i++) {
|
|
grid.push(crafting.get_item(i)?.type_id);
|
|
}
|
|
return grid;
|
|
}
|
|
|
|
function matches_recipe(grid: (string | undefined)[], recipe: CraftingRecipe): boolean {
|
|
for (let y = 0; y <= 3 - recipe.height; y++) {
|
|
for (let x = 0; x <= 3 - recipe.width; x++) {
|
|
let match = true;
|
|
|
|
for (let gy = 0; gy < 3; gy++) {
|
|
for (let gx = 0; gx < 3; gx++) {
|
|
const grid_index = gy * 3 + gx;
|
|
|
|
if (gx >= x && gx < x + recipe.width && gy >= y && gy < y + recipe.height) {
|
|
const recipe_index = (gy - y) * recipe.width + (gx - x);
|
|
if (grid[grid_index] !== recipe.pattern[recipe_index]) {
|
|
match = false;
|
|
break;
|
|
}
|
|
} else if (grid[grid_index] !== undefined) {
|
|
match = false;
|
|
break;
|
|
}
|
|
}
|
|
if (!match) break;
|
|
}
|
|
|
|
if (match) return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// puts what the grid makes in the result slot
|
|
export function update_crafting_result(crafting: Container) {
|
|
const grid = get_crafting_grid(crafting);
|
|
const recipe = CRAFTING_RECIPES.find((recipe) => matches_recipe(grid, recipe));
|
|
crafting.set_item(CRAFTING_RESULT_SLOT, recipe ? new ItemStack(recipe.result.id, recipe.result.count) : undefined);
|
|
}
|
|
|
|
export function consume_recipe_items(crafting: Container) {
|
|
for (let i = 0; i < 9; i++) {
|
|
const slot = crafting.get_slot(i);
|
|
if (slot.has_item()) {
|
|
slot.amount = slot.amount! - 1;
|
|
}
|
|
}
|
|
}
|