From ea52a9ad2df042371d3e497aa336d807cc602ed7 Mon Sep 17 00:00:00 2001 From: ExE Boss Date: Fri, 24 Feb 2017 19:39:05 +0100 Subject: [PATCH] Implement Smelting (#254) * Implement Smelting * Fix Stan Hebben's weirdness --- .../v17/recipes/MinecraftItemIngredient.java | 2 +- .../v17/recipes/MinecraftRecipeRegistry.java | 32 ++++++++ .../mc/forge/v17/recipes/RecipeConverter.java | 8 +- .../v18/recipes/MinecraftItemIngredient.java | 2 +- .../v18/recipes/MinecraftRecipeRegistry.java | 32 ++++++++ .../mc/forge/v18/recipes/RecipeConverter.java | 44 ++++++----- .../core/recipes/crafting/CraftingRecipe.java | 5 +- .../crafting/CraftingRecipeManager.java | 12 +-- .../crafting/ShapedCraftingRecipe.java | 26 ++++--- .../crafting/ShapelessCraftingRecipe.java | 5 +- .../ItemIngredient.java | 7 +- .../OreItemIngredient.java | 16 ++-- .../SpecificItemIngredient.java | 13 ++-- .../recipes/smelting/BasicSmeltingRecipe.java | 60 ++++++++++++++ .../core/recipes/smelting/SmeltingRecipe.java | 78 +++++++++++++++++++ .../smelting/SmeltingRecipeManager.java | 72 +++++++++++++++++ 16 files changed, 349 insertions(+), 65 deletions(-) rename src/main/java/nova/core/recipes/{crafting => ingredient}/ItemIngredient.java (95%) rename src/main/java/nova/core/recipes/{crafting => ingredient}/OreItemIngredient.java (79%) rename src/main/java/nova/core/recipes/{crafting => ingredient}/SpecificItemIngredient.java (89%) create mode 100644 src/main/java/nova/core/recipes/smelting/BasicSmeltingRecipe.java create mode 100644 src/main/java/nova/core/recipes/smelting/SmeltingRecipe.java create mode 100644 src/main/java/nova/core/recipes/smelting/SmeltingRecipeManager.java diff --git a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/recipes/MinecraftItemIngredient.java b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/recipes/MinecraftItemIngredient.java index 97582befa..46f2e9c77 100644 --- a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/recipes/MinecraftItemIngredient.java +++ b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/recipes/MinecraftItemIngredient.java @@ -21,7 +21,7 @@ package nova.core.wrapper.mc.forge.v17.recipes; import nova.core.item.Item; -import nova.core.recipes.crafting.SpecificItemIngredient; +import nova.core.recipes.ingredient.SpecificItemIngredient; import nova.internal.core.Game; /** diff --git a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/recipes/MinecraftRecipeRegistry.java b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/recipes/MinecraftRecipeRegistry.java index e076aa23d..86d2f2583 100644 --- a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/recipes/MinecraftRecipeRegistry.java +++ b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/recipes/MinecraftRecipeRegistry.java @@ -20,22 +20,30 @@ package nova.core.wrapper.mc.forge.v17.recipes; +import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.CraftingManager; +import net.minecraft.item.crafting.FurnaceRecipes; import net.minecraft.item.crafting.IRecipe; import nova.core.event.RecipeEvent; +import nova.core.item.Item; +import nova.core.recipes.ingredient.ItemIngredient; import nova.core.recipes.RecipeManager; import nova.core.recipes.crafting.CraftingRecipe; +import nova.core.recipes.smelting.SmeltingRecipe; import nova.core.wrapper.mc.forge.v17.util.ReflectionUtil; +import nova.core.wrapper.mc.forge.v17.wrapper.item.ItemConverter; import nova.internal.core.Game; import java.util.AbstractList; import java.util.Collection; +import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Map; +import java.util.Optional; import java.util.Spliterator; import java.util.function.Consumer; import java.util.stream.Stream; @@ -73,6 +81,9 @@ public void registerRecipes() { recipeManager.whenRecipeAdded(CraftingRecipe.class, this::onNOVARecipeAdded); recipeManager.whenRecipeRemoved(CraftingRecipe.class, this::onNOVARecipeRemoved); + + recipeManager.whenRecipeAdded(SmeltingRecipe.class, this::onNOVASmeltingAdded); + recipeManager.whenRecipeRemoved(SmeltingRecipe.class, this::onNOVASmeltingRemoved); } private CraftingRecipe convert(IRecipe recipe) { @@ -128,6 +139,27 @@ private void onMinecraftRecipeRemoved(IRecipe recipe) { Game.recipes().removeRecipe(novaRecipe); } + private void onNOVASmeltingAdded(RecipeEvent.Add evt) { + SmeltingRecipe recipe = evt.recipe; + + Collection inputs = recipe.getInput().map(ItemIngredient::getExampleItems).orElse(Collections.emptyList()); + + final Optional output = recipe.getExampleOutput().map(ItemConverter.instance()::toNative); + if (!output.isPresent()) + return; + + inputs.stream().map(ItemConverter.instance()::toNative).forEach(input -> FurnaceRecipes.smelting().func_151394_a(input, output.get(), 0)); + } + + private void onNOVASmeltingRemoved(RecipeEvent.Remove evt) { + SmeltingRecipe recipe = evt.recipe; + + Collection inputs = recipe.getInput().map(ItemIngredient::getExampleItems).orElse(Collections.emptyList()); + @SuppressWarnings("unchecked") + Map smeltingList = FurnaceRecipes.smelting().getSmeltingList(); + inputs.stream().map(ItemConverter.instance()::toNative).forEach(input -> smeltingList.remove(input)); + } + private class RecipeListWrapper extends AbstractList { private final List original; diff --git a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/recipes/RecipeConverter.java b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/recipes/RecipeConverter.java index 298f3d266..18501e684 100644 --- a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/recipes/RecipeConverter.java +++ b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/recipes/RecipeConverter.java @@ -28,11 +28,11 @@ import net.minecraftforge.oredict.ShapelessOreRecipe; import nova.core.item.Item; import nova.core.recipes.crafting.CraftingRecipe; -import nova.core.recipes.crafting.ItemIngredient; -import nova.core.recipes.crafting.OreItemIngredient; +import nova.core.recipes.ingredient.ItemIngredient; +import nova.core.recipes.ingredient.OreItemIngredient; import nova.core.recipes.crafting.ShapedCraftingRecipe; import nova.core.recipes.crafting.ShapelessCraftingRecipe; -import nova.core.recipes.crafting.SpecificItemIngredient; +import nova.core.recipes.ingredient.SpecificItemIngredient; import nova.core.wrapper.mc.forge.v17.util.ReflectionUtil; import nova.internal.core.Game; @@ -110,7 +110,7 @@ private static String findOreDictEntryFor(List ingredient) { } private static ItemStack wrapSpecific(SpecificItemIngredient ingredient) { - for (Item item : ingredient.getExampleItems().get()) { + for (Item item : ingredient.getExampleItems()) { return Game.natives().toNative(item.getFactory().build()); } diff --git a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/recipes/MinecraftItemIngredient.java b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/recipes/MinecraftItemIngredient.java index 72116bf5e..fa8c25553 100644 --- a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/recipes/MinecraftItemIngredient.java +++ b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/recipes/MinecraftItemIngredient.java @@ -21,7 +21,7 @@ package nova.core.wrapper.mc.forge.v18.recipes; import nova.core.item.Item; -import nova.core.recipes.crafting.SpecificItemIngredient; +import nova.core.recipes.ingredient.SpecificItemIngredient; import nova.internal.core.Game; /** diff --git a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/recipes/MinecraftRecipeRegistry.java b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/recipes/MinecraftRecipeRegistry.java index 6bf591619..5944a20c5 100644 --- a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/recipes/MinecraftRecipeRegistry.java +++ b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/recipes/MinecraftRecipeRegistry.java @@ -20,22 +20,30 @@ package nova.core.wrapper.mc.forge.v18.recipes; +import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.CraftingManager; +import net.minecraft.item.crafting.FurnaceRecipes; import net.minecraft.item.crafting.IRecipe; import nova.core.event.RecipeEvent; +import nova.core.item.Item; +import nova.core.recipes.ingredient.ItemIngredient; import nova.core.recipes.RecipeManager; import nova.core.recipes.crafting.CraftingRecipe; +import nova.core.recipes.smelting.SmeltingRecipe; import nova.core.wrapper.mc.forge.v18.util.ReflectionUtil; +import nova.core.wrapper.mc.forge.v18.wrapper.item.ItemConverter; import nova.internal.core.Game; import java.util.AbstractList; import java.util.Collection; +import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Map; +import java.util.Optional; import java.util.Spliterator; import java.util.function.Consumer; import java.util.stream.Stream; @@ -73,6 +81,9 @@ public void registerRecipes() { recipeManager.whenRecipeAdded(CraftingRecipe.class, this::onNOVARecipeAdded); recipeManager.whenRecipeRemoved(CraftingRecipe.class, this::onNOVARecipeRemoved); + + recipeManager.whenRecipeAdded(SmeltingRecipe.class, this::onNOVASmeltingAdded); + recipeManager.whenRecipeRemoved(SmeltingRecipe.class, this::onNOVASmeltingRemoved); } private CraftingRecipe convert(IRecipe recipe) { @@ -128,6 +139,27 @@ private void onMinecraftRecipeRemoved(IRecipe recipe) { Game.recipes().removeRecipe(novaRecipe); } + private void onNOVASmeltingAdded(RecipeEvent.Add evt) { + SmeltingRecipe recipe = evt.recipe; + + Collection inputs = recipe.getInput().map(ItemIngredient::getExampleItems).orElse(Collections.emptyList()); + + final Optional output = recipe.getExampleOutput().map(ItemConverter.instance()::toNative); + if (!output.isPresent()) + return; + + inputs.stream().map(ItemConverter.instance()::toNative).forEach(input -> FurnaceRecipes.instance().addSmeltingRecipe(input, output.get(), 0)); + } + + private void onNOVASmeltingRemoved(RecipeEvent.Remove evt) { + SmeltingRecipe recipe = evt.recipe; + + Collection inputs = recipe.getInput().map(ItemIngredient::getExampleItems).orElse(Collections.emptyList()); + @SuppressWarnings("unchecked") + Map smeltingList = FurnaceRecipes.instance().getSmeltingList(); + inputs.stream().map(ItemConverter.instance()::toNative).forEach(input -> smeltingList.remove(input)); + } + private class RecipeListWrapper extends AbstractList { private final List original; diff --git a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/recipes/RecipeConverter.java b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/recipes/RecipeConverter.java index cd616f714..51a8fac8e 100644 --- a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/recipes/RecipeConverter.java +++ b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/recipes/RecipeConverter.java @@ -28,11 +28,12 @@ import net.minecraftforge.oredict.ShapelessOreRecipe; import nova.core.item.Item; import nova.core.recipes.crafting.CraftingRecipe; -import nova.core.recipes.crafting.ItemIngredient; -import nova.core.recipes.crafting.OreItemIngredient; +import nova.core.recipes.ingredient.ItemIngredient; +import nova.core.recipes.ingredient.OreItemIngredient; import nova.core.recipes.crafting.ShapedCraftingRecipe; import nova.core.recipes.crafting.ShapelessCraftingRecipe; -import nova.core.recipes.crafting.SpecificItemIngredient; +import nova.core.recipes.ingredient.SpecificItemIngredient; +import nova.core.util.Identifiable; import nova.core.wrapper.mc.forge.v18.util.ReflectionUtil; import nova.internal.core.Game; @@ -84,11 +85,11 @@ private static ItemIngredient getIngredient(Object ingredient) { if (ingredient == null) { return null; } else if (ingredient instanceof ItemStack) { - return new SpecificItemIngredient(((Item) Game.natives().toNova(ingredient)).getID()); + return new SpecificItemIngredient(((Identifiable) Game.natives().toNova(ingredient)).getID()); } else if (ingredient instanceof String) { return new OreItemIngredient((String) ingredient); } else if (ingredient instanceof List) { - String oreDictEntry = findOreDictEntryFor((List) ingredient); + String oreDictEntry = findOreDictEntryFor((List) ingredient); if (oreDictEntry == null) { return null; } @@ -99,7 +100,7 @@ private static ItemIngredient getIngredient(Object ingredient) { } } - private static String findOreDictEntryFor(List ingredient) { + private static String findOreDictEntryFor(List ingredient) { for (String key : net.minecraftforge.oredict.OreDictionary.getOreNames()) { if (net.minecraftforge.oredict.OreDictionary.getOres(key).equals(ingredient)) { return key; @@ -110,7 +111,7 @@ private static String findOreDictEntryFor(List ingredient) { } private static ItemStack wrapSpecific(SpecificItemIngredient ingredient) { - for (Item item : ingredient.getExampleItems().get()) { + for (Item item : ingredient.getExampleItems()) { return Game.natives().toNative(item.getFactory().build()); } @@ -139,20 +140,21 @@ public static IRecipe convert(ShapelessCraftingRecipe recipe) { ItemIngredient[] ingredients = recipe.getIngredients(); int type = getRecipeType(ingredients); - if (type == TYPE_BASIC) { - ItemStack[] items = new ItemStack[ingredients.length]; - for (int i = 0; i < ingredients.length; i++) { - items[i] = wrapSpecific((SpecificItemIngredient) ingredients[i]); - } - return new ShapelessRecipeBasic(items, recipe); - } else if (type == TYPE_ORE) { - Object[] items = new Object[ingredients.length]; - for (int i = 0; i < ingredients.length; i++) { - items[i] = getInternal(ingredients[i]); - } - return new ShapelessRecipeOre(items, recipe); - } else { - return new NovaCraftingRecipe(recipe); + switch (type) { + case TYPE_BASIC: { + ItemStack[] items = new ItemStack[ingredients.length]; + for (int i = 0; i < ingredients.length; i++) { + items[i] = wrapSpecific((SpecificItemIngredient) ingredients[i]); + } + return new ShapelessRecipeBasic(items, recipe); + } case TYPE_ORE: { + Object[] items = new Object[ingredients.length]; + for (int i = 0; i < ingredients.length; i++) { + items[i] = getInternal(ingredients[i]); + } + return new ShapelessRecipeOre(items, recipe); + } default: + return new NovaCraftingRecipe(recipe); } } diff --git a/src/main/java/nova/core/recipes/crafting/CraftingRecipe.java b/src/main/java/nova/core/recipes/crafting/CraftingRecipe.java index 5703176f4..6d8b68a98 100755 --- a/src/main/java/nova/core/recipes/crafting/CraftingRecipe.java +++ b/src/main/java/nova/core/recipes/crafting/CraftingRecipe.java @@ -24,6 +24,7 @@ import nova.core.recipes.Recipe; import java.util.Collection; +import java.util.Collections; import java.util.Optional; /** @@ -73,7 +74,7 @@ public interface CraftingRecipe extends Recipe { * * @return The items */ - default Optional> getPossibleItemsInFirstSlot() { - return Optional.empty(); + default Collection getPossibleItemsInFirstSlot() { + return Collections.emptyList(); } } diff --git a/src/main/java/nova/core/recipes/crafting/CraftingRecipeManager.java b/src/main/java/nova/core/recipes/crafting/CraftingRecipeManager.java index 15b0b6a91..520fb7987 100644 --- a/src/main/java/nova/core/recipes/crafting/CraftingRecipeManager.java +++ b/src/main/java/nova/core/recipes/crafting/CraftingRecipeManager.java @@ -106,9 +106,9 @@ public Optional getRecipe(CraftingGrid grid) { // ####################### private void onCraftingRecipeAdded(RecipeEvent.Add evt) { - Optional> possibleFirstItemIds = evt.recipe.getPossibleItemsInFirstSlot(); - if (possibleFirstItemIds.isPresent()) { - for (String itemId : possibleFirstItemIds.get()) { + Collection possibleFirstItemIds = evt.recipe.getPossibleItemsInFirstSlot(); + if (!possibleFirstItemIds.isEmpty()) { + for (String itemId : possibleFirstItemIds) { staticRecipes.put(itemId, evt.recipe); } } else { @@ -117,9 +117,9 @@ private void onCraftingRecipeAdded(RecipeEvent.Add } private void onCraftingRecipeRemoved(RecipeEvent.Remove evt) { - Optional> possibleFirstItemIds = evt.recipe.getPossibleItemsInFirstSlot(); - if (possibleFirstItemIds.isPresent()) { - for (String itemId : possibleFirstItemIds.get()) { + Collection possibleFirstItemIds = evt.recipe.getPossibleItemsInFirstSlot(); + if (!possibleFirstItemIds.isEmpty()) { + for (String itemId : possibleFirstItemIds) { staticRecipes.remove(itemId, evt.recipe); } } else { diff --git a/src/main/java/nova/core/recipes/crafting/ShapedCraftingRecipe.java b/src/main/java/nova/core/recipes/crafting/ShapedCraftingRecipe.java index b79e4ea65..c5f2b9e42 100755 --- a/src/main/java/nova/core/recipes/crafting/ShapedCraftingRecipe.java +++ b/src/main/java/nova/core/recipes/crafting/ShapedCraftingRecipe.java @@ -20,10 +20,12 @@ package nova.core.recipes.crafting; +import nova.core.recipes.ingredient.ItemIngredient; import nova.core.item.Item; import org.apache.commons.math3.geometry.euclidean.twod.Vector2D; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -272,22 +274,22 @@ public void consumeItems(CraftingGrid craftingGrid) { } @Override - public Optional> getPossibleItemsInFirstSlot() { + public Collection getPossibleItemsInFirstSlot() { if (isMirrored()) { - Optional> optionsForFirstItem = ingredients[0].getPossibleItemIds(); - if (!optionsForFirstItem.isPresent()) { - return Optional.empty(); + Collection optionsForFirstItem = ingredients[0].getPossibleItemIds(); + if (optionsForFirstItem.isEmpty()) { + return Collections.emptyList(); } - Optional> optionsForSecondItem = ingredients[lastIngredientIndexOnFirstLine].getPossibleItemIds(); - if (!optionsForSecondItem.isPresent()) { - return Optional.empty(); + Collection optionsForSecondItem = ingredients[lastIngredientIndexOnFirstLine].getPossibleItemIds(); + if (optionsForFirstItem.isEmpty()) { + return Collections.emptyList(); } Set result = new HashSet<>(); - result.addAll(optionsForFirstItem.get()); - result.addAll(optionsForSecondItem.get()); - return Optional.of(result); + result.addAll(optionsForFirstItem); + result.addAll(optionsForSecondItem); + return result; } else { return ingredients[0].getPossibleItemIds(); } @@ -403,12 +405,14 @@ private NonMirroredMapping(Vector2D firstItemOffset) { firstItemOffset.getY() - posy[0])); } + @Override public Optional getStack(CraftingGrid craftingGrid, int ingredient) { return craftingGrid.getStack( offsetX + posx[ingredient], offsetY + posy[ingredient]); } + @Override public void setStack(CraftingGrid craftingGrid, int ingredient, Optional value) { craftingGrid.setStack( offsetX + posx[ingredient], @@ -426,12 +430,14 @@ private MirroredMapping(Vector2D firstItemOffset, int craftingGridWidth) { firstItemOffset.getY() - posy[0])); } + @Override public Optional getStack(CraftingGrid craftingGrid, int ingredient) { return craftingGrid.getStack( craftingGrid.getWidth() - (offsetX + posx[ingredient]) - 1, offsetY + posy[ingredient]); } + @Override public void setStack(CraftingGrid craftingGrid, int ingredient, Optional value) { craftingGrid.setStack( craftingGrid.getWidth() - (offsetX + posx[ingredient]) - 1, diff --git a/src/main/java/nova/core/recipes/crafting/ShapelessCraftingRecipe.java b/src/main/java/nova/core/recipes/crafting/ShapelessCraftingRecipe.java index e19f8d5ed..1f4c253fb 100755 --- a/src/main/java/nova/core/recipes/crafting/ShapelessCraftingRecipe.java +++ b/src/main/java/nova/core/recipes/crafting/ShapelessCraftingRecipe.java @@ -20,6 +20,7 @@ package nova.core.recipes.crafting; +import nova.core.recipes.ingredient.ItemIngredient; import nova.core.item.Item; import java.util.HashMap; @@ -35,11 +36,11 @@ public class ShapelessCraftingRecipe implements CraftingRecipe { private final RecipeFunction recipeFunction; private final ItemIngredient[] ingredients; - public ShapelessCraftingRecipe(Item output, ItemIngredient[] ingredients) { + public ShapelessCraftingRecipe(Item output, ItemIngredient... ingredients) { this(output, (crafting, tagged) -> Optional.of(output), ingredients); } - public ShapelessCraftingRecipe(Item nominalOutput, RecipeFunction recipeFunction, ItemIngredient[] ingredients) { + public ShapelessCraftingRecipe(Item nominalOutput, RecipeFunction recipeFunction, ItemIngredient... ingredients) { this.nominalOutput = nominalOutput; this.recipeFunction = recipeFunction; this.ingredients = ingredients; diff --git a/src/main/java/nova/core/recipes/crafting/ItemIngredient.java b/src/main/java/nova/core/recipes/ingredient/ItemIngredient.java similarity index 95% rename from src/main/java/nova/core/recipes/crafting/ItemIngredient.java rename to src/main/java/nova/core/recipes/ingredient/ItemIngredient.java index d9a580bc8..39cf39b7a 100755 --- a/src/main/java/nova/core/recipes/crafting/ItemIngredient.java +++ b/src/main/java/nova/core/recipes/ingredient/ItemIngredient.java @@ -18,11 +18,12 @@ * along with NOVA. If not, see . */ -package nova.core.recipes.crafting; +package nova.core.recipes.ingredient; import nova.core.block.BlockFactory; import nova.core.item.Item; import nova.core.item.ItemFactory; +import nova.core.recipes.crafting.CraftingGrid; import java.util.Collection; import java.util.Optional; @@ -81,7 +82,7 @@ static ItemIngredient forDictionary(String id) { * * @return possible items */ - Optional> getPossibleItemIds(); + Collection getPossibleItemIds(); /** * Returns a list of example items. This list could be used to render @@ -89,7 +90,7 @@ static ItemIngredient forDictionary(String id) { * * @return example items */ - Optional> getExampleItems(); + Collection getExampleItems(); /** * Checks if this ingredient is a subset of another ingredient. An diff --git a/src/main/java/nova/core/recipes/crafting/OreItemIngredient.java b/src/main/java/nova/core/recipes/ingredient/OreItemIngredient.java similarity index 79% rename from src/main/java/nova/core/recipes/crafting/OreItemIngredient.java rename to src/main/java/nova/core/recipes/ingredient/OreItemIngredient.java index 648455ec2..1b2b05e33 100644 --- a/src/main/java/nova/core/recipes/crafting/OreItemIngredient.java +++ b/src/main/java/nova/core/recipes/ingredient/OreItemIngredient.java @@ -18,14 +18,13 @@ * along with NOVA. If not, see . */ -package nova.core.recipes.crafting; +package nova.core.recipes.ingredient; import nova.core.item.Item; +import nova.core.recipes.crafting.CraftingGrid; import nova.internal.core.Game; -import java.util.ArrayList; import java.util.Collection; -import java.util.List; import java.util.Optional; import java.util.stream.Collectors; @@ -45,16 +44,13 @@ public String getName() { } @Override - public Optional> getPossibleItemIds() { - return Optional.of(Game.itemDictionary().get(name).stream().map(Item::getID).collect(Collectors.toList())); + public Collection getPossibleItemIds() { + return Game.itemDictionary().get(name).stream().map(Item::getID).collect(Collectors.toList()); } @Override - public Optional> getExampleItems() { - List result = new ArrayList(); - - - return Optional.of(Game.itemDictionary().get(name)); + public Collection getExampleItems() { + return Game.itemDictionary().get(name); } @Override diff --git a/src/main/java/nova/core/recipes/crafting/SpecificItemIngredient.java b/src/main/java/nova/core/recipes/ingredient/SpecificItemIngredient.java similarity index 89% rename from src/main/java/nova/core/recipes/crafting/SpecificItemIngredient.java rename to src/main/java/nova/core/recipes/ingredient/SpecificItemIngredient.java index 074928720..b517a1732 100644 --- a/src/main/java/nova/core/recipes/crafting/SpecificItemIngredient.java +++ b/src/main/java/nova/core/recipes/ingredient/SpecificItemIngredient.java @@ -16,10 +16,13 @@ * * You should have received a copy of the GNU General Public License * along with NOVA. If not, see . - */package nova.core.recipes.crafting; + */ + +package nova.core.recipes.ingredient; import nova.core.item.Item; import nova.core.item.ItemFactory; +import nova.core.recipes.crafting.CraftingGrid; import nova.core.util.exception.RegistrationException; import nova.internal.core.Game; @@ -43,13 +46,13 @@ public String getItemId() { } @Override - public Optional> getPossibleItemIds() { - return Optional.of(Collections.singleton(itemId)); + public Collection getPossibleItemIds() { + return Collections.singleton(itemId); } @Override - public Optional> getExampleItems() { - return Optional.of(Collections.singleton(getItem(itemId))); + public Collection getExampleItems() { + return Collections.singleton(getItem(itemId)); } @Override diff --git a/src/main/java/nova/core/recipes/smelting/BasicSmeltingRecipe.java b/src/main/java/nova/core/recipes/smelting/BasicSmeltingRecipe.java new file mode 100644 index 000000000..46e0b7d76 --- /dev/null +++ b/src/main/java/nova/core/recipes/smelting/BasicSmeltingRecipe.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2017 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 . + */ +package nova.core.recipes.smelting; + +import nova.core.item.Item; +import nova.core.item.ItemFactory; +import nova.core.recipes.ingredient.ItemIngredient; + +import java.util.Optional; + +/** + * @author ExE Boss + */ +public class BasicSmeltingRecipe implements SmeltingRecipe { + + private final ItemFactory output; + private final ItemIngredient ingredient; + + /** + * Defines a basic structured crafting recipe, using a format string. + * @param output Output {@link Item} of the recipe + * @param ingredient {@link ItemIngredient} + */ + public BasicSmeltingRecipe(ItemFactory output, ItemIngredient ingredient) { + this.output = output; + this.ingredient = ingredient; + } + + @Override + public boolean matches(Item input) { + return this.ingredient.matches(input); + } + + @Override + public Optional getCraftingResult(Item input) { + return matches(input) ? Optional.of(output.build()) : Optional.empty(); + } + + @Override + public Optional getInput() { + return Optional.of(this.ingredient); + } +} diff --git a/src/main/java/nova/core/recipes/smelting/SmeltingRecipe.java b/src/main/java/nova/core/recipes/smelting/SmeltingRecipe.java new file mode 100644 index 000000000..9103dbc63 --- /dev/null +++ b/src/main/java/nova/core/recipes/smelting/SmeltingRecipe.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2017 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 . + */ + +package nova.core.recipes.smelting; + +import nova.core.item.Item; +import nova.core.recipes.Recipe; +import nova.core.recipes.ingredient.ItemIngredient; + +import java.util.Collection; +import java.util.Collections; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * @author ExE Boss + */ +public interface SmeltingRecipe extends Recipe { + /** + * Checks if this crafting recipe matches the content of the given smelting input. + * + * @param input smelting input to read from + * @return true if a smelting operation would return a valid result + */ + boolean matches(Item input); + + /** + * Calculates the crafting result for the given crafting grid. Does not + * modify the contents of the crafting grid. + * + * @param input crafting grid + * @return crafting result, empty if the recipe doesn't match + */ + Optional getCraftingResult(Item input); + + /** + * Gets an example input for this recipe. Used in recipe display. + * + * @return example input + */ + default Collection getExampleInput() { + return getInput().map(ItemIngredient::getExampleItems).orElseGet(() -> Collections.emptyList()); + } + + /** + * Gets an example output for this recipe. Used in recipe display. + * + * @return example output + */ + default Optional getExampleOutput() { + return getInput().map(ItemIngredient::getExampleItems).orElseGet(() -> Collections.emptyList()).stream() + .map(item -> this.getCraftingResult(item)).filter(Optional::isPresent).map(Optional::get).findFirst(); + } + + /** + * Gets the input for this recipe. Used during registration. + * + * @return the input + */ + Optional getInput(); +} diff --git a/src/main/java/nova/core/recipes/smelting/SmeltingRecipeManager.java b/src/main/java/nova/core/recipes/smelting/SmeltingRecipeManager.java new file mode 100644 index 000000000..e5d69ac8d --- /dev/null +++ b/src/main/java/nova/core/recipes/smelting/SmeltingRecipeManager.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2017 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 . + */ +package nova.core.recipes.smelting; + +import nova.core.event.RecipeEvent; +import nova.core.recipes.RecipeManager; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author ExE Boss + */ +public class SmeltingRecipeManager { + private final RecipeManager recipeManager; + private final List recipes; + + public SmeltingRecipeManager(RecipeManager recipeManager) { + this.recipeManager = recipeManager; + this.recipes = new ArrayList<>(); + + this.recipeManager.whenRecipeAdded(SmeltingRecipe.class, this::onSmeltingRecipeAdded); + this.recipeManager.whenRecipeRemoved(SmeltingRecipe.class, this::onSmeltingRecipeRemoved); + } + + /** + * Adds a recipe. Adds it to the global recipe list as SmeltingRecipe. + * + * @param recipe {@link SmeltingRecipe} + */ + public void addRecipe(SmeltingRecipe recipe) { + recipeManager.addRecipe(recipe); + } + + /** + * Removes a recipe. Removes it from the global recipe list. + * + * @param recipe {@link SmeltingRecipe} + */ + public void removeRecipe(SmeltingRecipe recipe) { + recipeManager.removeRecipe(recipe); + } + + // ####################### + // ### Private Methods ### + // ####################### + + private void onSmeltingRecipeAdded(RecipeEvent.Add e) { + recipes.add(e.recipe); + } + + private void onSmeltingRecipeRemoved(RecipeEvent.Remove e) { + recipes.remove(e.recipe); + } +}