/* Copyright (c) 2023 ByteBit/xtreme8000 This file is part of CavEX. CavEX is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. CavEX is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with CavEX. If not, see . */ #include #include "recipe.h" array_recipe_t recipes_crafting; void recipe_init() { array_recipe_init(recipes_crafting); recipe_add( recipes_crafting, (struct item_data) {.id = BLOCK_PLANKS, .durability = 0, .count = 4}, 1, 1, (uint8_t[]) {1}, (struct item_data) {.id = BLOCK_LOG}, false); recipe_add( recipes_crafting, (struct item_data) {.id = ITEM_STICK, .durability = 0, .count = 4}, 1, 2, (uint8_t[]) {1, 1}, (struct item_data) {.id = BLOCK_PLANKS}, false); recipe_add( recipes_crafting, (struct item_data) {.id = BLOCK_WORKBENCH, .durability = 0, .count = 1}, 2, 2, (uint8_t[]) {1, 1, 1, 1}, (struct item_data) {.id = BLOCK_PLANKS}, false); recipe_add(recipes_crafting, (struct item_data) { .id = ITEM_DIAMOND_PICKAXE, .durability = 0, .count = 1}, 3, 3, (uint8_t[]) {1, 1, 1, 0, 2, 0, 0, 2, 0}, (struct item_data) {.id = ITEM_DIAMOND}, false, (struct item_data) {.id = ITEM_STICK}, false); } void recipe_add(array_recipe_t recipes, struct item_data result, size_t width, size_t height, uint8_t* shape, ...) { assert(recipes && width > 0 && height > 0 && width * height <= 9 && shape); size_t count = 0; for(size_t k = 0; k < width * height; k++) { if(shape[k] > count) count = shape[k]; } assert(count > 0 && count <= 9); struct recipe_ingredients ingredients[9]; va_list inputs; va_start(inputs, shape); for(size_t k = 0; k < count; k++) { ingredients[k].item = va_arg(inputs, struct item_data); ingredients[k].match_durability = (bool)va_arg(inputs, int); } va_end(inputs); struct recipe r = (struct recipe) { .result = result, .width = width, .height = height, }; for(size_t k = 0; k < width * height; k++) { if(shape[k] > 0) { r.shape[k] = ingredients[shape[k] - 1]; } else { r.shape[k].item.id = 0; } } array_recipe_push_back(recipes, r); } bool recipe_match(array_recipe_t recipes, struct item_data slots[9], bool slot_empty[9], struct item_data* result) { assert(recipes && slots && slot_empty && result); array_recipe_it_t it; array_recipe_it(it, recipes); while(!array_recipe_end_p(it)) { struct recipe* current = array_recipe_ref(it); for(size_t y = 0; y <= 3 - current->height; y++) { for(size_t x = 0; x <= 3 - current->width; x++) { bool match = true; // check that outside of pattern is empty for(size_t py = 0; py < 3 && match; py++) { for(size_t px = 0; px < 3 && match; px++) { if((px < x || px >= x + current->width || py < y || py >= y + current->height) && !slot_empty[px + py * 3]) match = false; } } // check pattern itself for(size_t py = 0; py < current->height && match; py++) { for(size_t px = 0; px < current->width && match; px++) { size_t slots_idx = (px + x) + (py + y) * 3; size_t shape_idx = px + py * current->width; if(current->shape[shape_idx].item.id == 0) { if(!slot_empty[slots_idx]) match = false; } else { if(slot_empty[slots_idx] || current->shape[shape_idx].item.id != slots[slots_idx].id || (current->shape->match_durability && current->shape[shape_idx].item.durability != slots[slots_idx].durability)) match = false; } } } if(match) { *result = current->result; return true; } } } array_recipe_next(it); } return false; }