/* * Copyright (c) 2015 NOVA, All rights reserved. * This library is free software, licensed under GNU Lesser General Public License version 3 * * This file is part of NOVA. * * NOVA 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. * * NOVA 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 NOVA. If not, see <http://www.gnu.org/licenses/>. */ package nova.core.recipes.crafting; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; import nova.core.event.RecipeEvent; import nova.core.item.Item; import nova.core.recipes.RecipeManager; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Optional; /** * Manages crafting recipes and has functions to efficiently lookup a crafting * recipe. * * @author Stan Hebben */ public class CraftingRecipeManager { private final RecipeManager recipeManager; private final List<CraftingRecipe> dynamicRecipes; private final Multimap<String, CraftingRecipe> staticRecipes; public CraftingRecipeManager(RecipeManager recipeManager) { this.recipeManager = recipeManager; this.dynamicRecipes = new ArrayList<>(); this.staticRecipes = ArrayListMultimap.create(); recipeManager.whenRecipeAdded(CraftingRecipe.class, this::onCraftingRecipeAdded); recipeManager.whenRecipeRemoved(CraftingRecipe.class, this::onCraftingRecipeRemoved); } /** * Adds a recipe. Adds it to the global recipe list as CraftingRecipe. * * @param recipe {@link CraftingRecipe} */ public void addRecipe(CraftingRecipe recipe) { recipeManager.addRecipe(recipe); } /** * Removes a recipe. Removes it from the global recipe list. * * @param recipe {@link CraftingRecipe} */ public void removeRecipe(CraftingRecipe recipe) { recipeManager.removeRecipe(recipe); } /** * Gets the recipe that matches the given crafting grid. * * @param grid crafting grid * @return matching crafting recipe, if any */ public Optional<CraftingRecipe> getRecipe(CraftingGrid grid) { for (CraftingRecipe dynamicRecipe : dynamicRecipes) { if (dynamicRecipe.matches(grid)) { return Optional.of(dynamicRecipe); } } Optional<Item> firstItem = grid.getFirstNonEmptyItem(); if (!firstItem.isPresent()) { return Optional.empty(); } String firstItemId = firstItem.get().getID(); if (!staticRecipes.containsKey(firstItemId)) { return Optional.empty(); } for (CraftingRecipe staticRecipe : staticRecipes.get(firstItemId)) { if (staticRecipe.matches(grid)) { return Optional.of(staticRecipe); } } return Optional.empty(); } // ####################### // ### Private Methods ### // ####################### private <T extends CraftingRecipe> void onCraftingRecipeAdded(RecipeEvent.Add<T> evt) { Collection<String> possibleFirstItemIds = evt.recipe.getPossibleItemsInFirstSlot(); if (!possibleFirstItemIds.isEmpty()) { for (String itemId : possibleFirstItemIds) { staticRecipes.put(itemId, evt.recipe); } } else { dynamicRecipes.add(evt.recipe); } } private <T extends CraftingRecipe> void onCraftingRecipeRemoved(RecipeEvent.Remove<T> evt) { Collection<String> possibleFirstItemIds = evt.recipe.getPossibleItemsInFirstSlot(); if (!possibleFirstItemIds.isEmpty()) { for (String itemId : possibleFirstItemIds) { staticRecipes.remove(itemId, evt.recipe); } } else { dynamicRecipes.remove(evt.recipe); } } }