From 84e6295f27c44e1aacc0f76bd8c5144a5789477e Mon Sep 17 00:00:00 2001 From: mezz Date: Fri, 27 Nov 2015 16:28:09 -0800 Subject: [PATCH 1/6] Make mod name tooltip italic --- src/main/java/mezz/jei/TooltipEventHandler.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/mezz/jei/TooltipEventHandler.java b/src/main/java/mezz/jei/TooltipEventHandler.java index e57273c7a..7b0f8a691 100644 --- a/src/main/java/mezz/jei/TooltipEventHandler.java +++ b/src/main/java/mezz/jei/TooltipEventHandler.java @@ -13,6 +13,8 @@ import mezz.jei.config.Config; public class TooltipEventHandler { + private static final String chatFormatting = EnumChatFormatting.BLUE.toString() + EnumChatFormatting.ITALIC.toString(); + @SubscribeEvent public void onToolTip(@Nonnull ItemTooltipEvent event) { if (!Config.tooltipModNameEnabled) { @@ -30,6 +32,6 @@ public void onToolTip(@Nonnull ItemTooltipEvent event) { } String modName = JEIManager.itemRegistry.getModNameForItem(item); - event.toolTip.add(EnumChatFormatting.BLUE + modName); + event.toolTip.add(chatFormatting + modName); } } From 566578559939cb0400dcc961b4c5d38c74a27049 Mon Sep 17 00:00:00 2001 From: mezz Date: Fri, 27 Nov 2015 17:05:35 -0800 Subject: [PATCH 2/6] modularize widgets, rename things with "ingredient" as a concept --- src/main/java/mezz/jei/RecipeRegistry.java | 20 ++--- .../mezz/jei/api/gui/ICraftingGridHelper.java | 8 +- ...uidTanks.java => IGuiFluidStackGroup.java} | 6 +- .../mezz/jei/api/gui/IGuiIngredientGroup.java | 15 ++++ ...temStacks.java => IGuiItemStackGroup.java} | 6 +- src/main/java/mezz/jei/api/package-info.java | 2 +- .../mezz/jei/api/recipe/IRecipeCategory.java | 19 +++-- .../jei/api/recipe/IRecipeCategoryUid.java | 7 ++ .../mezz/jei/api/recipe/IRecipeHandler.java | 4 +- .../api/recipe/VanillaRecipeCategoryUid.java | 5 ++ .../java/mezz/jei/gui/CraftingGridHelper.java | 13 ++-- src/main/java/mezz/jei/gui/GuiFluidTank.java | 53 ------------- src/main/java/mezz/jei/gui/GuiFluidTanks.java | 13 ---- src/main/java/mezz/jei/gui/GuiItemStack.java | 78 ------------------- src/main/java/mezz/jei/gui/GuiItemStacks.java | 17 ---- .../java/mezz/jei/gui/ItemListOverlay.java | 18 +++-- src/main/java/mezz/jei/gui/RecipeWidget.java | 22 +++--- .../java/mezz/jei/gui/TooltipRenderer.java | 2 +- .../jei/gui/ingredients/FluidStackHelper.java | 28 +++++++ .../gui/ingredients/FluidStackRenderer.java | 33 ++++++++ .../gui/ingredients/GuiFluidStackGroup.java | 16 ++++ .../GuiIngredient.java} | 55 ++++++------- .../GuiIngredientGroup.java} | 29 ++++--- .../gui/ingredients/GuiItemStackGroup.java | 34 ++++++++ .../IGuiIngredient.java} | 6 +- .../gui/ingredients/IIngredientHelper.java | 12 +++ .../gui/ingredients/IIngredientRenderer.java | 15 ++++ .../jei/gui/ingredients/ItemStackHelper.java | 21 +++++ .../gui/ingredients/ItemStackRenderer.java | 47 +++++++++++ .../crafting/CraftingRecipeCategory.java | 18 +++-- .../crafting/ShapedOreRecipeHandler.java | 9 ++- .../crafting/ShapedRecipesHandler.java | 9 ++- .../crafting/ShapelessOreRecipeHandler.java | 9 ++- .../crafting/ShapelessRecipesHandler.java | 9 ++- .../vanilla/furnace/FuelRecipeHandler.java | 9 ++- .../furnace/FurnaceRecipeCategory.java | 17 +++- .../furnace/SmeltingRecipeHandler.java | 9 ++- 37 files changed, 407 insertions(+), 286 deletions(-) rename src/main/java/mezz/jei/api/gui/{IGuiFluidTanks.java => IGuiFluidStackGroup.java} (74%) create mode 100644 src/main/java/mezz/jei/api/gui/IGuiIngredientGroup.java rename src/main/java/mezz/jei/api/gui/{IGuiItemStacks.java => IGuiItemStackGroup.java} (75%) create mode 100644 src/main/java/mezz/jei/api/recipe/IRecipeCategoryUid.java create mode 100644 src/main/java/mezz/jei/api/recipe/VanillaRecipeCategoryUid.java delete mode 100644 src/main/java/mezz/jei/gui/GuiFluidTank.java delete mode 100644 src/main/java/mezz/jei/gui/GuiFluidTanks.java delete mode 100644 src/main/java/mezz/jei/gui/GuiItemStack.java delete mode 100644 src/main/java/mezz/jei/gui/GuiItemStacks.java create mode 100644 src/main/java/mezz/jei/gui/ingredients/FluidStackHelper.java create mode 100644 src/main/java/mezz/jei/gui/ingredients/FluidStackRenderer.java create mode 100644 src/main/java/mezz/jei/gui/ingredients/GuiFluidStackGroup.java rename src/main/java/mezz/jei/gui/{GuiWidget.java => ingredients/GuiIngredient.java} (63%) rename src/main/java/mezz/jei/gui/{GuiWidgets.java => ingredients/GuiIngredientGroup.java} (54%) create mode 100644 src/main/java/mezz/jei/gui/ingredients/GuiItemStackGroup.java rename src/main/java/mezz/jei/gui/{IGuiWidget.java => ingredients/IGuiIngredient.java} (78%) create mode 100644 src/main/java/mezz/jei/gui/ingredients/IIngredientHelper.java create mode 100644 src/main/java/mezz/jei/gui/ingredients/IIngredientRenderer.java create mode 100644 src/main/java/mezz/jei/gui/ingredients/ItemStackHelper.java create mode 100644 src/main/java/mezz/jei/gui/ingredients/ItemStackRenderer.java diff --git a/src/main/java/mezz/jei/RecipeRegistry.java b/src/main/java/mezz/jei/RecipeRegistry.java index 2123d9630..6ae2be027 100644 --- a/src/main/java/mezz/jei/RecipeRegistry.java +++ b/src/main/java/mezz/jei/RecipeRegistry.java @@ -1,11 +1,9 @@ package mezz.jei; -import com.google.common.collect.ImmutableClassToInstanceMap; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; -import com.google.common.collect.MutableClassToInstanceMap; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -13,6 +11,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import net.minecraft.item.ItemStack; @@ -22,6 +21,7 @@ import mezz.jei.api.IRecipeRegistry; import mezz.jei.api.recipe.IRecipeCategory; +import mezz.jei.api.recipe.IRecipeCategoryUid; import mezz.jei.api.recipe.IRecipeHandler; import mezz.jei.api.recipe.IRecipeWrapper; import mezz.jei.util.Log; @@ -31,7 +31,7 @@ public class RecipeRegistry implements IRecipeRegistry { private final ImmutableMap recipeHandlers; - private final ImmutableClassToInstanceMap recipeCategoriesMap; + private final ImmutableMap recipeCategoriesMap; private final RecipeMap recipeInputMap; private final RecipeMap recipeOutputMap; private final Set unhandledRecipeClasses = new HashSet<>(); @@ -48,12 +48,12 @@ public class RecipeRegistry implements IRecipeRegistry { addRecipes(recipes); } - private static ImmutableClassToInstanceMap buildRecipeCategoriesMap(@Nonnull ImmutableList recipeCategories) { - MutableClassToInstanceMap mutableRecipeCategoriesMap = MutableClassToInstanceMap.create(); + private static ImmutableMap buildRecipeCategoriesMap(@Nonnull ImmutableList recipeCategories) { + Map mutableRecipeCategoriesMap = new HashMap<>(); for (IRecipeCategory recipeCategory : recipeCategories) { - mutableRecipeCategoriesMap.put(recipeCategory.getClass(), recipeCategory); + mutableRecipeCategoriesMap.put(recipeCategory.getUid(), recipeCategory); } - return ImmutableClassToInstanceMap.copyOf(mutableRecipeCategoriesMap); + return ImmutableMap.copyOf(mutableRecipeCategoriesMap); } private static ImmutableMap buildRecipeHandlersMap(@Nonnull List recipeHandlers) { @@ -103,10 +103,10 @@ private void addRecipe(@Nullable Object recipe) { return; } - Class recipeCategoryClass = recipeHandler.getRecipeCategoryClass(); - IRecipeCategory recipeCategory = recipeCategoriesMap.getInstance(recipeCategoryClass); + IRecipeCategoryUid recipeCategoryUid = recipeHandler.getRecipeCategoryUid(); + IRecipeCategory recipeCategory = recipeCategoriesMap.get(recipeCategoryUid); if (recipeCategory == null) { - Log.error("No recipe category registered for recipeCategoryClass: {}", recipeCategoryClass); + Log.error("No recipe category registered for recipeCategoryUid: {}", recipeCategoryUid); return; } diff --git a/src/main/java/mezz/jei/api/gui/ICraftingGridHelper.java b/src/main/java/mezz/jei/api/gui/ICraftingGridHelper.java index 4121a6599..1ff4a1cfa 100644 --- a/src/main/java/mezz/jei/api/gui/ICraftingGridHelper.java +++ b/src/main/java/mezz/jei/api/gui/ICraftingGridHelper.java @@ -6,15 +6,15 @@ import net.minecraft.item.ItemStack; /** - * Helps set crafting-grid-style GuiItemStacks. + * Helps set crafting-grid-style GuiItemStackGroup. * Get an instance from IGuiHelper. */ public interface ICraftingGridHelper { - void setInput(@Nonnull IGuiItemStacks guiItemStacks, @Nonnull List input); + void setInput(@Nonnull IGuiItemStackGroup guiItemStacks, @Nonnull List input); - void setInput(@Nonnull IGuiItemStacks guiItemStacks, @Nonnull List input, int width, int height); + void setInput(@Nonnull IGuiItemStackGroup guiItemStacks, @Nonnull List input, int width, int height); - void setOutput(@Nonnull IGuiItemStacks guiItemStacks, @Nonnull List output); + void setOutput(@Nonnull IGuiItemStackGroup guiItemStacks, @Nonnull List output); } diff --git a/src/main/java/mezz/jei/api/gui/IGuiFluidTanks.java b/src/main/java/mezz/jei/api/gui/IGuiFluidStackGroup.java similarity index 74% rename from src/main/java/mezz/jei/api/gui/IGuiFluidTanks.java rename to src/main/java/mezz/jei/api/gui/IGuiFluidStackGroup.java index c7ad2af9f..bebd12fcb 100644 --- a/src/main/java/mezz/jei/api/gui/IGuiFluidTanks.java +++ b/src/main/java/mezz/jei/api/gui/IGuiFluidStackGroup.java @@ -6,19 +6,21 @@ import net.minecraftforge.fluids.FluidStack; /** - * IGuiFluidTanks displays FluidStack Tanks in a gui. + * IGuiFluidStackGroup displays FluidStacks in a gui. * * If multiple FluidStacks are set, they will be displayed in rotation. */ -public interface IGuiFluidTanks { +public interface IGuiFluidStackGroup extends IGuiIngredientGroup { /** * Fluid tanks must be initialized once, and then can be set many times. */ void init(int index, int xPosition, int yPosition, int width, int height, int capacityMb); + @Override void set(int index, @Nonnull Collection fluidStacks); + @Override void set(int index, @Nonnull FluidStack fluidStack); } diff --git a/src/main/java/mezz/jei/api/gui/IGuiIngredientGroup.java b/src/main/java/mezz/jei/api/gui/IGuiIngredientGroup.java new file mode 100644 index 000000000..30120e81a --- /dev/null +++ b/src/main/java/mezz/jei/api/gui/IGuiIngredientGroup.java @@ -0,0 +1,15 @@ +package mezz.jei.api.gui; + +import javax.annotation.Nonnull; +import java.util.Collection; + +/** + * IGuiIngredientGroup displays recipe ingredients in a gui. + * + * If multiple ingredients are set for one index, they will be displayed in rotation. + */ +public interface IGuiIngredientGroup { + void set(int index, @Nonnull Collection ingredients); + + void set(int index, @Nonnull T ingredient); +} diff --git a/src/main/java/mezz/jei/api/gui/IGuiItemStacks.java b/src/main/java/mezz/jei/api/gui/IGuiItemStackGroup.java similarity index 75% rename from src/main/java/mezz/jei/api/gui/IGuiItemStacks.java rename to src/main/java/mezz/jei/api/gui/IGuiItemStackGroup.java index 831e5372c..e9c7c2fe9 100644 --- a/src/main/java/mezz/jei/api/gui/IGuiItemStacks.java +++ b/src/main/java/mezz/jei/api/gui/IGuiItemStackGroup.java @@ -6,20 +6,22 @@ import net.minecraft.item.ItemStack; /** - * IGuiItemStacks displays ItemStacks in a gui. + * IGuiItemStackGroup displays ItemStacks in a gui. * * If multiple ItemStacks are set, they will be displayed in rotation. * ItemStacks with subtypes and wildcard metadata will be displayed as multiple ItemStacks. */ -public interface IGuiItemStacks { +public interface IGuiItemStackGroup extends IGuiIngredientGroup { /** * ItemStacks must be initialized once, and then can be set many times. */ void init(int index, int xPosition, int yPosition); + @Override void set(int index, @Nonnull Collection itemStacks); + @Override void set(int index, @Nonnull ItemStack itemStack); } diff --git a/src/main/java/mezz/jei/api/package-info.java b/src/main/java/mezz/jei/api/package-info.java index 9df2753a1..49ce9858d 100644 --- a/src/main/java/mezz/jei/api/package-info.java +++ b/src/main/java/mezz/jei/api/package-info.java @@ -1,4 +1,4 @@ -@API(apiVersion = "24.0.0", owner = "JEI", provides = "JustEnoughItemsAPI") +@API(apiVersion = "25.0.0", owner = "JEI", provides = "JustEnoughItemsAPI") package mezz.jei.api; import net.minecraftforge.fml.common.API; diff --git a/src/main/java/mezz/jei/api/recipe/IRecipeCategory.java b/src/main/java/mezz/jei/api/recipe/IRecipeCategory.java index 45025cb29..c4656671f 100644 --- a/src/main/java/mezz/jei/api/recipe/IRecipeCategory.java +++ b/src/main/java/mezz/jei/api/recipe/IRecipeCategory.java @@ -3,8 +3,8 @@ import javax.annotation.Nonnull; import mezz.jei.api.gui.IDrawable; -import mezz.jei.api.gui.IGuiFluidTanks; -import mezz.jei.api.gui.IGuiItemStacks; +import mezz.jei.api.gui.IGuiFluidStackGroup; +import mezz.jei.api.gui.IGuiItemStackGroup; /** * Defines a category of recipe, (i.e. Crafting Table Recipe, Furnace Recipe) @@ -12,6 +12,13 @@ */ public interface IRecipeCategory { + /** + * Returns a unique ID for this recipe category. + * Referenced from recipes to identify which recipe category they belong to. + */ + @Nonnull + IRecipeCategoryUid getUid(); + /** * Returns the localized name for this recipe type. * Drawn at the top of the recipe GUI pages for this category. @@ -28,13 +35,13 @@ public interface IRecipeCategory { IDrawable getBackground(); /** - * Initialize the IGuiItemStacks and IGuiFluidTanks with this recipe's layout. + * Initialize the IGuiItemStackGroup and IGuiFluidStackGroup with this recipe's layout. */ - void init(@Nonnull IGuiItemStacks guiItemStacks, @Nonnull IGuiFluidTanks guiFluidTanks); + void init(@Nonnull IGuiItemStackGroup guiItemStacks, @Nonnull IGuiFluidStackGroup guiFluidTanks); /** - * Set the IGuiItemStacks and IGuiFluidTanks properties from the RecipeWrapper. + * Set the IGuiItemStackGroup and IGuiFluidStackGroup properties from the RecipeWrapper. */ - void setRecipe(@Nonnull IGuiItemStacks guiItemStacks, @Nonnull IGuiFluidTanks guiFluidTanks, @Nonnull IRecipeWrapper recipeWrapper); + void setRecipe(@Nonnull IGuiItemStackGroup guiItemStacks, @Nonnull IGuiFluidStackGroup guiFluidTanks, @Nonnull IRecipeWrapper recipeWrapper); } diff --git a/src/main/java/mezz/jei/api/recipe/IRecipeCategoryUid.java b/src/main/java/mezz/jei/api/recipe/IRecipeCategoryUid.java new file mode 100644 index 000000000..ccc04e7ed --- /dev/null +++ b/src/main/java/mezz/jei/api/recipe/IRecipeCategoryUid.java @@ -0,0 +1,7 @@ +package mezz.jei.api.recipe; + +/** + * Unique identifier for a recipe category. + */ +public interface IRecipeCategoryUid { +} diff --git a/src/main/java/mezz/jei/api/recipe/IRecipeHandler.java b/src/main/java/mezz/jei/api/recipe/IRecipeHandler.java index 3caf1a18f..b480d8651 100644 --- a/src/main/java/mezz/jei/api/recipe/IRecipeHandler.java +++ b/src/main/java/mezz/jei/api/recipe/IRecipeHandler.java @@ -11,9 +11,9 @@ public interface IRecipeHandler { @Nonnull Class getRecipeClass(); - /** Returns the category of this recipe. */ + /** Returns this recipe's category unique id. */ @Nonnull - Class getRecipeCategoryClass(); + IRecipeCategoryUid getRecipeCategoryUid(); /** Returns a recipe wrapper for the given recipe. */ @Nonnull diff --git a/src/main/java/mezz/jei/api/recipe/VanillaRecipeCategoryUid.java b/src/main/java/mezz/jei/api/recipe/VanillaRecipeCategoryUid.java new file mode 100644 index 000000000..6cf7eac2a --- /dev/null +++ b/src/main/java/mezz/jei/api/recipe/VanillaRecipeCategoryUid.java @@ -0,0 +1,5 @@ +package mezz.jei.api.recipe; + +public enum VanillaRecipeCategoryUid implements IRecipeCategoryUid { + CRAFTING, FURNACE +} diff --git a/src/main/java/mezz/jei/gui/CraftingGridHelper.java b/src/main/java/mezz/jei/gui/CraftingGridHelper.java index 40ddd33e4..0d295fe0b 100644 --- a/src/main/java/mezz/jei/gui/CraftingGridHelper.java +++ b/src/main/java/mezz/jei/gui/CraftingGridHelper.java @@ -8,7 +8,7 @@ import net.minecraft.item.ItemStack; import mezz.jei.api.gui.ICraftingGridHelper; -import mezz.jei.api.gui.IGuiItemStacks; +import mezz.jei.api.gui.IGuiItemStackGroup; import mezz.jei.util.StackUtil; public class CraftingGridHelper implements ICraftingGridHelper { @@ -21,7 +21,8 @@ public CraftingGridHelper(int craftInputSlot1, int craftOutputSlot) { this.craftOutputSlot = craftOutputSlot; } - public void setInput(@Nonnull IGuiItemStacks guiItemStacks, @Nonnull List input) { + @Override + public void setInput(@Nonnull IGuiItemStackGroup guiItemStacks, @Nonnull List input) { int width, height; if (input.size() > 4) { width = height = 3; @@ -34,7 +35,8 @@ public void setInput(@Nonnull IGuiItemStacks guiItemStacks, @Nonnull List input) setInput(guiItemStacks, input, width, height); } - public void setInput(@Nonnull IGuiItemStacks guiItemStacks, @Nonnull List input, int width, int height) { + @Override + public void setInput(@Nonnull IGuiItemStackGroup guiItemStacks, @Nonnull List input, int width, int height) { for (int i = 0; i < input.size(); i++) { Object recipeItem = input.get(i); int index; @@ -72,11 +74,12 @@ public void setInput(@Nonnull IGuiItemStacks guiItemStacks, @Nonnull List input, } } - public void setOutput(@Nonnull IGuiItemStacks guiItemStacks, @Nonnull List output) { + @Override + public void setOutput(@Nonnull IGuiItemStackGroup guiItemStacks, @Nonnull List output) { guiItemStacks.set(craftOutputSlot, output); } - private void setInput(@Nonnull IGuiItemStacks guiItemStacks, int inputIndex, @Nonnull Collection input) { + private void setInput(@Nonnull IGuiItemStackGroup guiItemStacks, int inputIndex, @Nonnull Collection input) { guiItemStacks.set(craftInputSlot1 + inputIndex, input); } diff --git a/src/main/java/mezz/jei/gui/GuiFluidTank.java b/src/main/java/mezz/jei/gui/GuiFluidTank.java deleted file mode 100644 index dd9aa83b1..000000000 --- a/src/main/java/mezz/jei/gui/GuiFluidTank.java +++ /dev/null @@ -1,53 +0,0 @@ -package mezz.jei.gui; - -import javax.annotation.Nonnull; -import java.util.Collection; -import java.util.List; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.FontRenderer; - -import net.minecraftforge.fluids.FluidStack; - -public class GuiFluidTank extends GuiWidget { - private final int capacityMb; - - public GuiFluidTank(int xPosition, int yPosition, int width, int height, int capacityMb) { - super(xPosition, yPosition, width, height); - this.capacityMb = capacityMb; - } - - @Override - protected Collection expandSubtypes(Collection contained) { - return contained; - } - - @Override - protected FluidStack getMatch(Iterable contained, @Nonnull Focus toMatch) { - if (toMatch.getFluid() == null) { - return null; - } - for (FluidStack fluidStack : contained) { - if (toMatch.getFluid() == fluidStack.getFluid()) { - return fluidStack; - } - } - return null; - } - - @Override - protected void draw(@Nonnull Minecraft minecraft, int xPosition, int yPosition, @Nonnull FluidStack contents) { - // TODO - } - - @Override - protected List getTooltip(@Nonnull Minecraft minecraft, @Nonnull FluidStack value) { - // TODO - return null; - } - - @Override - protected FontRenderer getFontRenderer(@Nonnull Minecraft minecraft, @Nonnull FluidStack value) { - return minecraft.fontRendererObj; - } -} diff --git a/src/main/java/mezz/jei/gui/GuiFluidTanks.java b/src/main/java/mezz/jei/gui/GuiFluidTanks.java deleted file mode 100644 index 535ec09fd..000000000 --- a/src/main/java/mezz/jei/gui/GuiFluidTanks.java +++ /dev/null @@ -1,13 +0,0 @@ -package mezz.jei.gui; - -import net.minecraftforge.fluids.FluidStack; - -import mezz.jei.api.gui.IGuiFluidTanks; - -public class GuiFluidTanks extends GuiWidgets implements IGuiFluidTanks { - @Override - public void init(int index, int xPosition, int yPosition, int width, int height, int capacityMb) { - GuiFluidTank guiFluidTank = new GuiFluidTank(xPosition, yPosition, width, height, capacityMb); - guiWidgets.put(index, guiFluidTank); - } -} diff --git a/src/main/java/mezz/jei/gui/GuiItemStack.java b/src/main/java/mezz/jei/gui/GuiItemStack.java deleted file mode 100644 index 52a8e9f99..000000000 --- a/src/main/java/mezz/jei/gui/GuiItemStack.java +++ /dev/null @@ -1,78 +0,0 @@ -package mezz.jei.gui; - -import javax.annotation.Nonnull; -import java.util.Collection; -import java.util.List; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.FontRenderer; -import net.minecraft.client.renderer.RenderHelper; -import net.minecraft.item.ItemStack; -import net.minecraft.util.EnumChatFormatting; - -import mezz.jei.util.StackUtil; - -public class GuiItemStack extends GuiWidget { - private static final int baseWidth = 16; - private static final int baseHeight = 16; - - public static int getWidth(int padding) { - return baseWidth + (2 * padding); - } - - public static int getHeight(int padding) { - return baseHeight + (2 * padding); - } - - private final int padding; - - public GuiItemStack(int xPosition, int yPosition, int padding) { - super(xPosition, yPosition, getWidth(padding), getHeight(padding)); - this.padding = padding; - } - - @Override - protected Collection expandSubtypes(Collection contained) { - return StackUtil.getAllSubtypes(contained); - } - - @Override - protected ItemStack getMatch(Iterable contained, @Nonnull Focus toMatch) { - return StackUtil.containsStack(contained, toMatch.getStack()); - } - - @Override - protected void draw(@Nonnull Minecraft minecraft, int xPosition, int yPosition, @Nonnull ItemStack itemStack) { - FontRenderer font = getFontRenderer(minecraft, itemStack); - - RenderHelper.enableGUIStandardItemLighting(); - - minecraft.getRenderItem().renderItemAndEffectIntoGUI(itemStack, xPosition + padding, yPosition + padding); - minecraft.getRenderItem().renderItemOverlayIntoGUI(font, itemStack, xPosition + padding, yPosition + padding, null); - - RenderHelper.disableStandardItemLighting(); - } - - @SuppressWarnings("unchecked") - @Override - protected List getTooltip(@Nonnull Minecraft minecraft, @Nonnull ItemStack itemStack) { - List list = itemStack.getTooltip(minecraft.thePlayer, minecraft.gameSettings.advancedItemTooltips); - for (int k = 0; k < list.size(); ++k) { - if (k == 0) { - list.set(k, itemStack.getRarity().rarityColor + (String) list.get(k)); - } else { - list.set(k, EnumChatFormatting.GRAY + (String) list.get(k)); - } - } - return list; - } - - @Override - protected FontRenderer getFontRenderer(@Nonnull Minecraft minecraft, @Nonnull ItemStack itemStack) { - FontRenderer fontRenderer = itemStack.getItem().getFontRenderer(itemStack); - if (fontRenderer == null) { - fontRenderer = minecraft.fontRendererObj; - } - return fontRenderer; - } -} diff --git a/src/main/java/mezz/jei/gui/GuiItemStacks.java b/src/main/java/mezz/jei/gui/GuiItemStacks.java deleted file mode 100644 index ae89013ac..000000000 --- a/src/main/java/mezz/jei/gui/GuiItemStacks.java +++ /dev/null @@ -1,17 +0,0 @@ -package mezz.jei.gui; - -import net.minecraft.item.ItemStack; - -import mezz.jei.api.gui.IGuiItemStacks; - -public class GuiItemStacks extends GuiWidgets implements IGuiItemStacks { - @Override - public void init(int index, int xPosition, int yPosition) { - init(index, xPosition, yPosition, 1); - } - - public void init(int index, int xPosition, int yPosition, int padding) { - GuiItemStack guiItemStack = new GuiItemStack(xPosition, yPosition, padding); - guiWidgets.put(index, guiItemStack); - } -} diff --git a/src/main/java/mezz/jei/gui/ItemListOverlay.java b/src/main/java/mezz/jei/gui/ItemListOverlay.java index c5a169cb5..d42f42b11 100644 --- a/src/main/java/mezz/jei/gui/ItemListOverlay.java +++ b/src/main/java/mezz/jei/gui/ItemListOverlay.java @@ -21,6 +21,8 @@ import org.lwjgl.input.Keyboard; import mezz.jei.ItemFilter; +import mezz.jei.gui.ingredients.GuiIngredient; +import mezz.jei.gui.ingredients.GuiItemStackGroup; import mezz.jei.input.IKeyable; import mezz.jei.input.IMouseHandler; import mezz.jei.input.IShowsRecipeFocuses; @@ -32,15 +34,15 @@ public class ItemListOverlay implements IShowsRecipeFocuses, IMouseHandler, IKey private static final int borderPadding = 1; private static final int searchHeight = 16; private static final int itemStackPadding = 1; - private static final int itemStackWidth = GuiItemStack.getWidth(itemStackPadding); - private static final int itemStackHeight = GuiItemStack.getHeight(itemStackPadding); + private static final int itemStackWidth = GuiItemStackGroup.getWidth(itemStackPadding); + private static final int itemStackHeight = GuiItemStackGroup.getHeight(itemStackPadding); private static final int maxSearchLength = 32; private static int pageNum = 0; private final ItemFilter itemFilter; private int buttonHeight; - private final ArrayList guiItemStacks = new ArrayList<>(); + private final ArrayList> guiItemStacks = new ArrayList<>(); private GuiButton nextButton; private GuiButton backButton; private GuiTextField searchField; @@ -50,7 +52,7 @@ public class ItemListOverlay implements IShowsRecipeFocuses, IMouseHandler, IKey private int pageNumDisplayX; private int pageNumDisplayY; - private GuiItemStack hovered = null; + private GuiIngredient hovered = null; // properties of the gui we're beside private int guiLeft; @@ -110,7 +112,7 @@ private int createItemButtons() { maxX = x; } - guiItemStacks.add(new GuiItemStack(x, y, itemStackPadding)); + guiItemStacks.add(GuiItemStackGroup.createGuiItemStack(x, y, itemStackPadding)); x += itemStackWidth; if (x + itemStackWidth + borderPadding > width) { @@ -130,7 +132,7 @@ private void updateLayout() { int i = pageNum * getCountPerPage(); ImmutableList itemList = itemFilter.getItemList(); - for (GuiItemStack itemButton : guiItemStacks) { + for (GuiIngredient itemButton : guiItemStacks) { if (i >= itemList.size()) { itemButton.clear(); } else { @@ -185,7 +187,7 @@ public void drawScreen(@Nonnull Minecraft minecraft, int mouseX, int mouseY) { nextButton.drawButton(minecraft, mouseX, mouseY); backButton.drawButton(minecraft, mouseX, mouseY); - for (GuiItemStack guiItemStack : guiItemStacks) { + for (GuiIngredient guiItemStack : guiItemStacks) { if (hovered == null && guiItemStack.isMouseOver(mouseX, mouseY)) { hovered = guiItemStack; } else { @@ -216,7 +218,7 @@ public Focus getFocusUnderMouse(int mouseX, int mouseY) { if (!isMouseOver(mouseX, mouseY)) { return null; } - for (GuiItemStack guiItemStack : guiItemStacks) { + for (GuiIngredient guiItemStack : guiItemStacks) { if (guiItemStack.isMouseOver(mouseX, mouseY)) { setKeyboardFocus(false); return new Focus(guiItemStack.get()); diff --git a/src/main/java/mezz/jei/gui/RecipeWidget.java b/src/main/java/mezz/jei/gui/RecipeWidget.java index ec4ec33f0..655efed8b 100644 --- a/src/main/java/mezz/jei/gui/RecipeWidget.java +++ b/src/main/java/mezz/jei/gui/RecipeWidget.java @@ -8,13 +8,15 @@ import mezz.jei.api.recipe.IRecipeCategory; import mezz.jei.api.recipe.IRecipeWrapper; +import mezz.jei.gui.ingredients.GuiFluidStackGroup; +import mezz.jei.gui.ingredients.GuiItemStackGroup; public class RecipeWidget { @Nonnull private final IRecipeCategory recipeCategory; - private final GuiItemStacks guiItemStacks; - private final GuiFluidTanks guiFluidTanks; + private final GuiItemStackGroup guiItemStackGroup; + private final GuiFluidStackGroup guiFluidStackGroup; private IRecipeWrapper recipeWrapper; private int posX; @@ -22,9 +24,9 @@ public class RecipeWidget { public RecipeWidget(@Nonnull IRecipeCategory recipeCategory) { this.recipeCategory = recipeCategory; - this.guiItemStacks = new GuiItemStacks(); - this.guiFluidTanks = new GuiFluidTanks(); - this.recipeCategory.init(guiItemStacks, guiFluidTanks); + this.guiItemStackGroup = new GuiItemStackGroup(); + this.guiFluidStackGroup = new GuiFluidStackGroup(); + this.recipeCategory.init(guiItemStackGroup, guiFluidStackGroup); } public void setPosition(int posX, int posY) { @@ -35,9 +37,9 @@ public void setPosition(int posX, int posY) { public void setRecipe(@Nonnull IRecipeWrapper recipeWrapper, @Nonnull Focus focus) { this.recipeWrapper = recipeWrapper; - guiItemStacks.clear(); - guiItemStacks.setFocus(focus); - recipeCategory.setRecipe(guiItemStacks, guiFluidTanks, recipeWrapper); + guiItemStackGroup.clear(); + guiItemStackGroup.setFocus(focus); + recipeCategory.setRecipe(guiItemStackGroup, guiFluidStackGroup, recipeWrapper); } public void draw(@Nonnull Minecraft minecraft, int mouseX, int mouseY) { @@ -52,12 +54,12 @@ public void draw(@Nonnull Minecraft minecraft, int mouseX, int mouseY) { recipeCategory.getBackground().draw(minecraft); recipeWrapper.drawInfo(minecraft); - guiItemStacks.draw(minecraft, mouseX - posX, mouseY - posY); + guiItemStackGroup.draw(minecraft, mouseX - posX, mouseY - posY); GL11.glPopMatrix(); } public Focus getFocusUnderMouse(int mouseX, int mouseY) { - return guiItemStacks.getFocusUnderMouse(mouseX - posX, mouseY - posY); + return guiItemStackGroup.getFocusUnderMouse(mouseX - posX, mouseY - posY); } } diff --git a/src/main/java/mezz/jei/gui/TooltipRenderer.java b/src/main/java/mezz/jei/gui/TooltipRenderer.java index 14235dfdf..27e282485 100644 --- a/src/main/java/mezz/jei/gui/TooltipRenderer.java +++ b/src/main/java/mezz/jei/gui/TooltipRenderer.java @@ -13,7 +13,7 @@ public class TooltipRenderer { private static final TooltipGuiScreen tooltipScreen = new TooltipGuiScreen(); - public static void drawHoveringText(Minecraft minecraft, List textLines, int x, int y, FontRenderer font) { + public static void drawHoveringText(Minecraft minecraft, List textLines, int x, int y, FontRenderer font) { tooltipScreen.set(minecraft); tooltipScreen.drawHoveringText(textLines, x, y, font); } diff --git a/src/main/java/mezz/jei/gui/ingredients/FluidStackHelper.java b/src/main/java/mezz/jei/gui/ingredients/FluidStackHelper.java new file mode 100644 index 000000000..2d2bcd8a7 --- /dev/null +++ b/src/main/java/mezz/jei/gui/ingredients/FluidStackHelper.java @@ -0,0 +1,28 @@ +package mezz.jei.gui.ingredients; + +import javax.annotation.Nonnull; +import java.util.Collection; + +import net.minecraftforge.fluids.FluidStack; + +import mezz.jei.gui.Focus; + +public class FluidStackHelper implements IIngredientHelper { + @Override + public Collection expandSubtypes(Collection contained) { + return contained; + } + + @Override + public FluidStack getMatch(Iterable contained, @Nonnull Focus toMatch) { + if (toMatch.getFluid() == null) { + return null; + } + for (FluidStack fluidStack : contained) { + if (toMatch.getFluid() == fluidStack.getFluid()) { + return fluidStack; + } + } + return null; + } +} diff --git a/src/main/java/mezz/jei/gui/ingredients/FluidStackRenderer.java b/src/main/java/mezz/jei/gui/ingredients/FluidStackRenderer.java new file mode 100644 index 000000000..1ca844135 --- /dev/null +++ b/src/main/java/mezz/jei/gui/ingredients/FluidStackRenderer.java @@ -0,0 +1,33 @@ +package mezz.jei.gui.ingredients; + +import javax.annotation.Nonnull; +import java.util.List; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; + +import net.minecraftforge.fluids.FluidStack; + +public class FluidStackRenderer implements IIngredientRenderer { + private final int capacityMb; + + public FluidStackRenderer(int capacityMb) { + this.capacityMb = capacityMb; + } + + @Override + public void draw(@Nonnull Minecraft minecraft, int xPosition, int yPosition, @Nonnull FluidStack value) { + // TODO + } + + @Override + public List getTooltip(@Nonnull Minecraft minecraft, @Nonnull FluidStack value) { + // TODO + return null; + } + + @Override + public FontRenderer getFontRenderer(@Nonnull Minecraft minecraft, @Nonnull FluidStack value) { + return minecraft.fontRendererObj; + } +} diff --git a/src/main/java/mezz/jei/gui/ingredients/GuiFluidStackGroup.java b/src/main/java/mezz/jei/gui/ingredients/GuiFluidStackGroup.java new file mode 100644 index 000000000..1f554411a --- /dev/null +++ b/src/main/java/mezz/jei/gui/ingredients/GuiFluidStackGroup.java @@ -0,0 +1,16 @@ +package mezz.jei.gui.ingredients; + +import net.minecraftforge.fluids.FluidStack; + +import mezz.jei.api.gui.IGuiFluidStackGroup; + +public class GuiFluidStackGroup extends GuiIngredientGroup> implements IGuiFluidStackGroup { + private static final FluidStackHelper helper = new FluidStackHelper(); + + @Override + public void init(int index, int xPosition, int yPosition, int width, int height, int capacityMb) { + FluidStackRenderer renderer = new FluidStackRenderer(capacityMb); + GuiIngredient guiIngredient = new GuiIngredient<>(renderer, helper, xPosition, yPosition, width, height, 0); + guiIngredients.put(index, guiIngredient); + } +} diff --git a/src/main/java/mezz/jei/gui/GuiWidget.java b/src/main/java/mezz/jei/gui/ingredients/GuiIngredient.java similarity index 63% rename from src/main/java/mezz/jei/gui/GuiWidget.java rename to src/main/java/mezz/jei/gui/ingredients/GuiIngredient.java index 00d86cd51..32acc9acc 100644 --- a/src/main/java/mezz/jei/gui/GuiWidget.java +++ b/src/main/java/mezz/jei/gui/ingredients/GuiIngredient.java @@ -1,4 +1,4 @@ -package mezz.jei.gui; +package mezz.jei.gui.ingredients; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -15,28 +15,39 @@ import org.lwjgl.opengl.GL11; +import mezz.jei.gui.Focus; +import mezz.jei.gui.TooltipRenderer; import mezz.jei.util.CycleTimer; import mezz.jei.util.Log; -public abstract class GuiWidget extends Gui implements IGuiWidget { - protected final int xPosition; - protected final int yPosition; - protected final int width; - protected final int height; +public class GuiIngredient extends Gui implements IGuiIngredient { + private final int xPosition; + private final int yPosition; + private final int width; + private final int height; + private final int padding; - protected boolean enabled; - protected boolean visible; + @Nonnull + private final CycleTimer cycleTimer = new CycleTimer(); + @Nonnull + private final List contained = new ArrayList<>(); + @Nonnull + private final IIngredientRenderer ingredientRenderer; + @Nonnull + private final IIngredientHelper ingredientHelper; - protected final CycleTimer cycleTimer = new CycleTimer(); + private boolean enabled; + private boolean visible; - @Nonnull - protected final List contained = new ArrayList<>(); + public GuiIngredient(@Nonnull IIngredientRenderer ingredientRenderer, @Nonnull IIngredientHelper ingredientHelper, int xPosition, int yPosition, int width, int height, int padding) { + this.ingredientRenderer = ingredientRenderer; + this.ingredientHelper = ingredientHelper; - public GuiWidget(int xPosition, int yPosition, int width, int height) { this.xPosition = xPosition; this.yPosition = yPosition; this.width = width; this.height = height; + this.padding = padding; } @Override @@ -64,8 +75,8 @@ public void set(@Nonnull T contained, @Nonnull Focus focus) { @Override public void set(@Nonnull Collection contained, @Nonnull Focus focus) { this.contained.clear(); - contained = expandSubtypes(contained); - T match = getMatch(contained, focus); + contained = ingredientHelper.expandSubtypes(contained); + T match = ingredientHelper.getMatch(contained, focus); if (match != null) { this.contained.add(match); } else { @@ -74,10 +85,6 @@ public void set(@Nonnull Collection contained, @Nonnull Focus focus) { visible = enabled = !this.contained.isEmpty(); } - protected abstract Collection expandSubtypes(Collection contained); - - protected abstract T getMatch(Iterable contained, @Nonnull Focus toMatch); - @Override public void draw(@Nonnull Minecraft minecraft) { draw(minecraft, true); @@ -105,7 +112,7 @@ private void draw(Minecraft minecraft, boolean cycleIcons) { return; } - draw(minecraft, xPosition, yPosition, value); + ingredientRenderer.draw(minecraft, xPosition + padding, yPosition + padding, value); } private void drawTooltip(@Nonnull Minecraft minecraft, int mouseX, int mouseY, @Nonnull T value) { @@ -118,8 +125,8 @@ private void drawTooltip(@Nonnull Minecraft minecraft, int mouseX, int mouseY, @ drawRect(xPosition, yPosition, xPosition + width, yPosition + width, 0x7FFFFFFF); this.zLevel = 0; - List tooltip = getTooltip(minecraft, value); - FontRenderer fontRenderer = getFontRenderer(minecraft, value); + List tooltip = ingredientRenderer.getTooltip(minecraft, value); + FontRenderer fontRenderer = ingredientRenderer.getFontRenderer(minecraft, value); TooltipRenderer.drawHoveringText(minecraft, tooltip, mouseX, mouseY, fontRenderer); GlStateManager.enableDepth(); @@ -127,10 +134,4 @@ private void drawTooltip(@Nonnull Minecraft minecraft, int mouseX, int mouseY, @ Log.error("Exception when rendering tooltip on {}.\n{}", value, e); } } - - protected abstract void draw(@Nonnull Minecraft minecraft, int xPosition, int yPosition, @Nonnull T value); - - protected abstract List getTooltip(@Nonnull Minecraft minecraft, @Nonnull T value); - - protected abstract FontRenderer getFontRenderer(@Nonnull Minecraft minecraft, @Nonnull T value); } diff --git a/src/main/java/mezz/jei/gui/GuiWidgets.java b/src/main/java/mezz/jei/gui/ingredients/GuiIngredientGroup.java similarity index 54% rename from src/main/java/mezz/jei/gui/GuiWidgets.java rename to src/main/java/mezz/jei/gui/ingredients/GuiIngredientGroup.java index 2632d76fa..bc2e98b73 100644 --- a/src/main/java/mezz/jei/gui/GuiWidgets.java +++ b/src/main/java/mezz/jei/gui/ingredients/GuiIngredientGroup.java @@ -1,4 +1,4 @@ -package mezz.jei.gui; +package mezz.jei.gui.ingredients; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -8,37 +8,42 @@ import net.minecraft.client.Minecraft; -public abstract class GuiWidgets> { +import mezz.jei.api.gui.IGuiIngredientGroup; +import mezz.jei.gui.Focus; + +public abstract class GuiIngredientGroup> implements IGuiIngredientGroup { @Nonnull - protected final Map guiWidgets = new HashMap<>(); + protected final Map guiIngredients = new HashMap<>(); @Nonnull protected Focus focus = new Focus(); /** - * If focus is set and any of the guiWidgets contains focus + * If focus is set and any of the guiIngredients contains focus * they will only display focus instead of rotating through all their values. */ public void setFocus(@Nonnull Focus focus) { this.focus = focus; } + @Override public void set(int index, @Nonnull Collection values) { - guiWidgets.get(index).set(values, focus); + guiIngredients.get(index).set(values, focus); } + @Override public void set(int index, @Nonnull V value) { - guiWidgets.get(index).set(value, focus); + guiIngredients.get(index).set(value, focus); } public void clear() { - for (T guiWidget : guiWidgets.values()) { + for (T guiWidget : guiIngredients.values()) { guiWidget.clear(); } } @Nullable public Focus getFocusUnderMouse(int mouseX, int mouseY) { - for (T widget : guiWidgets.values()) { + for (T widget : guiIngredients.values()) { if (widget != null && widget.isMouseOver(mouseX, mouseY)) { return new Focus(widget.get()); } @@ -48,11 +53,11 @@ public Focus getFocusUnderMouse(int mouseX, int mouseY) { public void draw(@Nonnull Minecraft minecraft, int mouseX, int mouseY) { T hovered = null; - for (T widget : guiWidgets.values()) { - if (hovered == null && widget.isMouseOver(mouseX, mouseY)) { - hovered = widget; + for (T ingredient : guiIngredients.values()) { + if (hovered == null && ingredient.isMouseOver(mouseX, mouseY)) { + hovered = ingredient; } else { - widget.draw(minecraft); + ingredient.draw(minecraft); } } if (hovered != null) { diff --git a/src/main/java/mezz/jei/gui/ingredients/GuiItemStackGroup.java b/src/main/java/mezz/jei/gui/ingredients/GuiItemStackGroup.java new file mode 100644 index 000000000..7140dcc29 --- /dev/null +++ b/src/main/java/mezz/jei/gui/ingredients/GuiItemStackGroup.java @@ -0,0 +1,34 @@ +package mezz.jei.gui.ingredients; + +import net.minecraft.item.ItemStack; + +import mezz.jei.api.gui.IGuiItemStackGroup; + +public class GuiItemStackGroup extends GuiIngredientGroup> implements IGuiItemStackGroup { + private static final int baseWidth = 16; + private static final int baseHeight = 16; + private static final ItemStackRenderer renderer = new ItemStackRenderer(); + private static final ItemStackHelper helper = new ItemStackHelper(); + + public static int getWidth(int padding) { + return baseWidth + (2 * padding); + } + + public static int getHeight(int padding) { + return baseHeight + (2 * padding); + } + + public static GuiIngredient createGuiItemStack(int xPosition, int yPosition, int padding) { + return new GuiIngredient<>(renderer, helper, xPosition, yPosition, getWidth(padding), getHeight(padding), padding); + } + + @Override + public void init(int index, int xPosition, int yPosition) { + init(index, xPosition, yPosition, 1); + } + + public void init(int index, int xPosition, int yPosition, int padding) { + GuiIngredient guiIngredient = createGuiItemStack(xPosition, yPosition, padding); + guiIngredients.put(index, guiIngredient); + } +} diff --git a/src/main/java/mezz/jei/gui/IGuiWidget.java b/src/main/java/mezz/jei/gui/ingredients/IGuiIngredient.java similarity index 78% rename from src/main/java/mezz/jei/gui/IGuiWidget.java rename to src/main/java/mezz/jei/gui/ingredients/IGuiIngredient.java index f9c12dd34..66020a57b 100644 --- a/src/main/java/mezz/jei/gui/IGuiWidget.java +++ b/src/main/java/mezz/jei/gui/ingredients/IGuiIngredient.java @@ -1,4 +1,4 @@ -package mezz.jei.gui; +package mezz.jei.gui.ingredients; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -6,7 +6,9 @@ import net.minecraft.client.Minecraft; -public interface IGuiWidget { +import mezz.jei.gui.Focus; + +public interface IGuiIngredient { void set(@Nonnull T contained, @Nonnull Focus focus); void set(@Nonnull Collection contained, @Nonnull Focus focus); diff --git a/src/main/java/mezz/jei/gui/ingredients/IIngredientHelper.java b/src/main/java/mezz/jei/gui/ingredients/IIngredientHelper.java new file mode 100644 index 000000000..b27b99a18 --- /dev/null +++ b/src/main/java/mezz/jei/gui/ingredients/IIngredientHelper.java @@ -0,0 +1,12 @@ +package mezz.jei.gui.ingredients; + +import javax.annotation.Nonnull; +import java.util.Collection; + +import mezz.jei.gui.Focus; + +public interface IIngredientHelper { + Collection expandSubtypes(Collection contained); + + T getMatch(Iterable contained, @Nonnull Focus toMatch); +} diff --git a/src/main/java/mezz/jei/gui/ingredients/IIngredientRenderer.java b/src/main/java/mezz/jei/gui/ingredients/IIngredientRenderer.java new file mode 100644 index 000000000..41be09f8b --- /dev/null +++ b/src/main/java/mezz/jei/gui/ingredients/IIngredientRenderer.java @@ -0,0 +1,15 @@ +package mezz.jei.gui.ingredients; + +import javax.annotation.Nonnull; +import java.util.List; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; + +public interface IIngredientRenderer { + void draw(@Nonnull Minecraft minecraft, int xPosition, int yPosition, @Nonnull T value); + + List getTooltip(@Nonnull Minecraft minecraft, @Nonnull T value); + + FontRenderer getFontRenderer(@Nonnull Minecraft minecraft, @Nonnull T value); +} diff --git a/src/main/java/mezz/jei/gui/ingredients/ItemStackHelper.java b/src/main/java/mezz/jei/gui/ingredients/ItemStackHelper.java new file mode 100644 index 000000000..5258e1afb --- /dev/null +++ b/src/main/java/mezz/jei/gui/ingredients/ItemStackHelper.java @@ -0,0 +1,21 @@ +package mezz.jei.gui.ingredients; + +import javax.annotation.Nonnull; +import java.util.Collection; + +import net.minecraft.item.ItemStack; + +import mezz.jei.gui.Focus; +import mezz.jei.util.StackUtil; + +public class ItemStackHelper implements IIngredientHelper { + @Override + public Collection expandSubtypes(Collection contained) { + return StackUtil.getAllSubtypes(contained); + } + + @Override + public ItemStack getMatch(Iterable contained, @Nonnull Focus toMatch) { + return StackUtil.containsStack(contained, toMatch.getStack()); + } +} diff --git a/src/main/java/mezz/jei/gui/ingredients/ItemStackRenderer.java b/src/main/java/mezz/jei/gui/ingredients/ItemStackRenderer.java new file mode 100644 index 000000000..0be7b094c --- /dev/null +++ b/src/main/java/mezz/jei/gui/ingredients/ItemStackRenderer.java @@ -0,0 +1,47 @@ +package mezz.jei.gui.ingredients; + +import javax.annotation.Nonnull; +import java.util.List; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumChatFormatting; + +public class ItemStackRenderer implements IIngredientRenderer { + @Override + public void draw(@Nonnull Minecraft minecraft, int xPosition, int yPosition, @Nonnull ItemStack itemStack) { + FontRenderer font = getFontRenderer(minecraft, itemStack); + + RenderHelper.enableGUIStandardItemLighting(); + + minecraft.getRenderItem().renderItemAndEffectIntoGUI(itemStack, xPosition, yPosition); + minecraft.getRenderItem().renderItemOverlayIntoGUI(font, itemStack, xPosition, yPosition, null); + + RenderHelper.disableStandardItemLighting(); + } + + @SuppressWarnings("unchecked") + @Override + public List getTooltip(@Nonnull Minecraft minecraft, @Nonnull ItemStack itemStack) { + List list = itemStack.getTooltip(minecraft.thePlayer, minecraft.gameSettings.advancedItemTooltips); + for (int k = 0; k < list.size(); ++k) { + if (k == 0) { + list.set(k, itemStack.getRarity().rarityColor + list.get(k)); + } else { + list.set(k, EnumChatFormatting.GRAY + list.get(k)); + } + } + return list; + } + + @Override + public FontRenderer getFontRenderer(@Nonnull Minecraft minecraft, @Nonnull ItemStack itemStack) { + FontRenderer fontRenderer = itemStack.getItem().getFontRenderer(itemStack); + if (fontRenderer == null) { + fontRenderer = minecraft.fontRendererObj; + } + return fontRenderer; + } +} diff --git a/src/main/java/mezz/jei/plugins/vanilla/crafting/CraftingRecipeCategory.java b/src/main/java/mezz/jei/plugins/vanilla/crafting/CraftingRecipeCategory.java index 6dc8555d4..1f5b8d1a4 100644 --- a/src/main/java/mezz/jei/plugins/vanilla/crafting/CraftingRecipeCategory.java +++ b/src/main/java/mezz/jei/plugins/vanilla/crafting/CraftingRecipeCategory.java @@ -8,10 +8,12 @@ import mezz.jei.api.JEIManager; import mezz.jei.api.gui.ICraftingGridHelper; import mezz.jei.api.gui.IDrawable; -import mezz.jei.api.gui.IGuiFluidTanks; -import mezz.jei.api.gui.IGuiItemStacks; +import mezz.jei.api.gui.IGuiFluidStackGroup; +import mezz.jei.api.gui.IGuiItemStackGroup; import mezz.jei.api.recipe.IRecipeCategory; +import mezz.jei.api.recipe.IRecipeCategoryUid; import mezz.jei.api.recipe.IRecipeWrapper; +import mezz.jei.api.recipe.VanillaRecipeCategoryUid; import mezz.jei.api.recipe.wrapper.ICraftingRecipeWrapper; import mezz.jei.api.recipe.wrapper.IShapedCraftingRecipeWrapper; import mezz.jei.util.Log; @@ -35,6 +37,12 @@ public CraftingRecipeCategory() { craftingGridHelper = JEIManager.guiHelper.createCraftingGridHelper(craftInputSlot1, craftOutputSlot); } + @Override + @Nonnull + public IRecipeCategoryUid getUid() { + return VanillaRecipeCategoryUid.CRAFTING; + } + @Nonnull @Override public String getTitle() { @@ -48,7 +56,7 @@ public IDrawable getBackground() { } @Override - public void init(@Nonnull IGuiItemStacks guiItemStacks, @Nonnull IGuiFluidTanks guiFluidTanks) { + public void init(@Nonnull IGuiItemStackGroup guiItemStacks, @Nonnull IGuiFluidStackGroup guiFluidTanks) { guiItemStacks.init(craftOutputSlot, 94, 18); for (int y = 0; y < 3; ++y) { @@ -60,7 +68,7 @@ public void init(@Nonnull IGuiItemStacks guiItemStacks, @Nonnull IGuiFluidTanks } @Override - public void setRecipe(@Nonnull IGuiItemStacks guiItemStacks, @Nonnull IGuiFluidTanks guiFluidTanks, @Nonnull IRecipeWrapper recipeWrapper) { + public void setRecipe(@Nonnull IGuiItemStackGroup guiItemStacks, @Nonnull IGuiFluidStackGroup guiFluidTanks, @Nonnull IRecipeWrapper recipeWrapper) { if (recipeWrapper instanceof IShapedCraftingRecipeWrapper) { IShapedCraftingRecipeWrapper wrapper = (IShapedCraftingRecipeWrapper) recipeWrapper; craftingGridHelper.setInput(guiItemStacks, wrapper.getInputs(), wrapper.getWidth(), wrapper.getHeight()); @@ -70,7 +78,7 @@ public void setRecipe(@Nonnull IGuiItemStacks guiItemStacks, @Nonnull IGuiFluidT craftingGridHelper.setInput(guiItemStacks, wrapper.getInputs()); craftingGridHelper.setOutput(guiItemStacks, wrapper.getOutputs()); } else { - Log.error("RecipeWrapper is not a know crafting wrapper type: {}", recipeWrapper); + Log.error("RecipeWrapper is not a known crafting wrapper type: {}", recipeWrapper); } } diff --git a/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapedOreRecipeHandler.java b/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapedOreRecipeHandler.java index 46bc90d7c..744a5b5e7 100644 --- a/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapedOreRecipeHandler.java +++ b/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapedOreRecipeHandler.java @@ -5,9 +5,10 @@ import net.minecraftforge.oredict.ShapedOreRecipe; -import mezz.jei.api.recipe.IRecipeCategory; +import mezz.jei.api.recipe.IRecipeCategoryUid; import mezz.jei.api.recipe.IRecipeHandler; import mezz.jei.api.recipe.IRecipeWrapper; +import mezz.jei.api.recipe.VanillaRecipeCategoryUid; public class ShapedOreRecipeHandler implements IRecipeHandler { @@ -17,10 +18,10 @@ public Class getRecipeClass() { return ShapedOreRecipe.class; } - @Override @Nonnull - public Class getRecipeCategoryClass() { - return CraftingRecipeCategory.class; + @Override + public IRecipeCategoryUid getRecipeCategoryUid() { + return VanillaRecipeCategoryUid.CRAFTING; } @Override diff --git a/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapedRecipesHandler.java b/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapedRecipesHandler.java index ad01c3cd7..458ef3bb0 100644 --- a/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapedRecipesHandler.java +++ b/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapedRecipesHandler.java @@ -5,9 +5,10 @@ import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.ShapedRecipes; -import mezz.jei.api.recipe.IRecipeCategory; +import mezz.jei.api.recipe.IRecipeCategoryUid; import mezz.jei.api.recipe.IRecipeHandler; import mezz.jei.api.recipe.IRecipeWrapper; +import mezz.jei.api.recipe.VanillaRecipeCategoryUid; public class ShapedRecipesHandler implements IRecipeHandler { @@ -17,10 +18,10 @@ public Class getRecipeClass() { return ShapedRecipes.class; } - @Override @Nonnull - public Class getRecipeCategoryClass() { - return CraftingRecipeCategory.class; + @Override + public IRecipeCategoryUid getRecipeCategoryUid() { + return VanillaRecipeCategoryUid.CRAFTING; } @Override diff --git a/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapelessOreRecipeHandler.java b/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapelessOreRecipeHandler.java index b7a4c1974..54bc21e2d 100644 --- a/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapelessOreRecipeHandler.java +++ b/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapelessOreRecipeHandler.java @@ -5,9 +5,10 @@ import net.minecraftforge.oredict.ShapelessOreRecipe; -import mezz.jei.api.recipe.IRecipeCategory; +import mezz.jei.api.recipe.IRecipeCategoryUid; import mezz.jei.api.recipe.IRecipeHandler; import mezz.jei.api.recipe.IRecipeWrapper; +import mezz.jei.api.recipe.VanillaRecipeCategoryUid; public class ShapelessOreRecipeHandler implements IRecipeHandler { @@ -17,10 +18,10 @@ public Class getRecipeClass() { return ShapelessOreRecipe.class; } - @Override @Nonnull - public Class getRecipeCategoryClass() { - return CraftingRecipeCategory.class; + @Override + public IRecipeCategoryUid getRecipeCategoryUid() { + return VanillaRecipeCategoryUid.CRAFTING; } @Override diff --git a/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapelessRecipesHandler.java b/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapelessRecipesHandler.java index 38ef702d0..b8e8e4a38 100644 --- a/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapelessRecipesHandler.java +++ b/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapelessRecipesHandler.java @@ -5,9 +5,10 @@ import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.ShapelessRecipes; -import mezz.jei.api.recipe.IRecipeCategory; +import mezz.jei.api.recipe.IRecipeCategoryUid; import mezz.jei.api.recipe.IRecipeHandler; import mezz.jei.api.recipe.IRecipeWrapper; +import mezz.jei.api.recipe.VanillaRecipeCategoryUid; public class ShapelessRecipesHandler implements IRecipeHandler { @@ -17,10 +18,10 @@ public Class getRecipeClass() { return ShapelessRecipes.class; } - @Override @Nonnull - public Class getRecipeCategoryClass() { - return CraftingRecipeCategory.class; + @Override + public IRecipeCategoryUid getRecipeCategoryUid() { + return VanillaRecipeCategoryUid.CRAFTING; } @Override diff --git a/src/main/java/mezz/jei/plugins/vanilla/furnace/FuelRecipeHandler.java b/src/main/java/mezz/jei/plugins/vanilla/furnace/FuelRecipeHandler.java index 57e4269d5..e2ef8eb6f 100644 --- a/src/main/java/mezz/jei/plugins/vanilla/furnace/FuelRecipeHandler.java +++ b/src/main/java/mezz/jei/plugins/vanilla/furnace/FuelRecipeHandler.java @@ -2,9 +2,10 @@ import javax.annotation.Nonnull; -import mezz.jei.api.recipe.IRecipeCategory; +import mezz.jei.api.recipe.IRecipeCategoryUid; import mezz.jei.api.recipe.IRecipeHandler; import mezz.jei.api.recipe.IRecipeWrapper; +import mezz.jei.api.recipe.VanillaRecipeCategoryUid; public class FuelRecipeHandler implements IRecipeHandler { @Override @@ -13,10 +14,10 @@ public Class getRecipeClass() { return FuelRecipe.class; } - @Override @Nonnull - public Class getRecipeCategoryClass() { - return FurnaceRecipeCategory.class; + @Override + public IRecipeCategoryUid getRecipeCategoryUid() { + return VanillaRecipeCategoryUid.FURNACE; } @Override diff --git a/src/main/java/mezz/jei/plugins/vanilla/furnace/FurnaceRecipeCategory.java b/src/main/java/mezz/jei/plugins/vanilla/furnace/FurnaceRecipeCategory.java index 83d198c34..8e757b909 100644 --- a/src/main/java/mezz/jei/plugins/vanilla/furnace/FurnaceRecipeCategory.java +++ b/src/main/java/mezz/jei/plugins/vanilla/furnace/FurnaceRecipeCategory.java @@ -7,10 +7,12 @@ import mezz.jei.api.JEIManager; import mezz.jei.api.gui.IDrawable; -import mezz.jei.api.gui.IGuiFluidTanks; -import mezz.jei.api.gui.IGuiItemStacks; +import mezz.jei.api.gui.IGuiFluidStackGroup; +import mezz.jei.api.gui.IGuiItemStackGroup; import mezz.jei.api.recipe.IRecipeCategory; +import mezz.jei.api.recipe.IRecipeCategoryUid; import mezz.jei.api.recipe.IRecipeWrapper; +import mezz.jei.api.recipe.VanillaRecipeCategoryUid; public class FurnaceRecipeCategory implements IRecipeCategory { @@ -30,19 +32,26 @@ public FurnaceRecipeCategory() { } @Nonnull + @Override + public IRecipeCategoryUid getUid() { + return VanillaRecipeCategoryUid.FURNACE; + } + + @Nonnull + @Override public IDrawable getBackground() { return background; } @Override - public void init(@Nonnull IGuiItemStacks guiItemStacks, @Nonnull IGuiFluidTanks guiFluidTanks) { + public void init(@Nonnull IGuiItemStackGroup guiItemStacks, @Nonnull IGuiFluidStackGroup guiFluidTanks) { guiItemStacks.init(inputSlot, 0, 0); guiItemStacks.init(fuelSlot, 0, 36); guiItemStacks.init(outputSlot, 60, 18); } @Override - public void setRecipe(@Nonnull IGuiItemStacks guiItemStacks, @Nonnull IGuiFluidTanks guiFluidTanks, @Nonnull IRecipeWrapper recipeWrapper) { + public void setRecipe(@Nonnull IGuiItemStackGroup guiItemStacks, @Nonnull IGuiFluidStackGroup guiFluidTanks, @Nonnull IRecipeWrapper recipeWrapper) { if (recipeWrapper instanceof FuelRecipe) { FuelRecipe fuelRecipeWrapper = (FuelRecipe) recipeWrapper; guiItemStacks.set(fuelSlot, fuelRecipeWrapper.getInputs()); diff --git a/src/main/java/mezz/jei/plugins/vanilla/furnace/SmeltingRecipeHandler.java b/src/main/java/mezz/jei/plugins/vanilla/furnace/SmeltingRecipeHandler.java index a4115da05..2fe5c1f7a 100644 --- a/src/main/java/mezz/jei/plugins/vanilla/furnace/SmeltingRecipeHandler.java +++ b/src/main/java/mezz/jei/plugins/vanilla/furnace/SmeltingRecipeHandler.java @@ -2,9 +2,10 @@ import javax.annotation.Nonnull; -import mezz.jei.api.recipe.IRecipeCategory; +import mezz.jei.api.recipe.IRecipeCategoryUid; import mezz.jei.api.recipe.IRecipeHandler; import mezz.jei.api.recipe.IRecipeWrapper; +import mezz.jei.api.recipe.VanillaRecipeCategoryUid; public class SmeltingRecipeHandler implements IRecipeHandler { @@ -14,10 +15,10 @@ public Class getRecipeClass() { return SmeltingRecipe.class; } - @Override @Nonnull - public Class getRecipeCategoryClass() { - return FurnaceRecipeCategory.class; + @Override + public IRecipeCategoryUid getRecipeCategoryUid() { + return VanillaRecipeCategoryUid.FURNACE; } @Override From bea74269d7c82bb72c640bbacd92e085471748cc Mon Sep 17 00:00:00 2001 From: mezz Date: Fri, 27 Nov 2015 17:51:20 -0800 Subject: [PATCH 3/6] improve doc --- src/main/java/mezz/jei/api/gui/IGuiIngredientGroup.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/mezz/jei/api/gui/IGuiIngredientGroup.java b/src/main/java/mezz/jei/api/gui/IGuiIngredientGroup.java index 30120e81a..0a6ecc0d5 100644 --- a/src/main/java/mezz/jei/api/gui/IGuiIngredientGroup.java +++ b/src/main/java/mezz/jei/api/gui/IGuiIngredientGroup.java @@ -7,6 +7,7 @@ * IGuiIngredientGroup displays recipe ingredients in a gui. * * If multiple ingredients are set for one index, they will be displayed in rotation. + * @see IGuiItemStackGroup and IGuiFluidStackGroup */ public interface IGuiIngredientGroup { void set(int index, @Nonnull Collection ingredients); From 6b10b77f4521f9ee08bdfe2db0b0b94737ad128b Mon Sep 17 00:00:00 2001 From: mezz Date: Sat, 28 Nov 2015 12:31:09 -0800 Subject: [PATCH 4/6] tidy ItemStackElement --- src/main/java/mezz/jei/util/ItemStackElement.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/mezz/jei/util/ItemStackElement.java b/src/main/java/mezz/jei/util/ItemStackElement.java index 0ac0d5f67..0c534443a 100644 --- a/src/main/java/mezz/jei/util/ItemStackElement.java +++ b/src/main/java/mezz/jei/util/ItemStackElement.java @@ -32,14 +32,14 @@ public static ItemStackElement create(@Nonnull ItemStack itemStack) { } } - public ItemStackElement(@Nonnull ItemStack itemStack) { + private ItemStackElement(@Nonnull ItemStack itemStack) { this.itemStack = itemStack; this.localizedName = itemStack.getDisplayName().toLowerCase(); String modId = GameRegistry.findUniqueIdentifierFor(itemStack.getItem()).modId; String modName = JEIManager.itemRegistry.getModNameForItem(itemStack.getItem()); - this.modName = modId.toLowerCase(Locale.ENGLISH) + " " + modName.toLowerCase(Locale.ENGLISH); + this.modName = modId.toLowerCase(Locale.ENGLISH) + ' ' + modName.toLowerCase(Locale.ENGLISH); } @Nonnull From a16a862eb183a98a5b8149a31de5e081750df6b4 Mon Sep 17 00:00:00 2001 From: mezz Date: Tue, 1 Dec 2015 22:57:04 -0800 Subject: [PATCH 5/6] Fix #4 Fix #43 Add support for recipe transfer-to-crafting-area feature --- README.md | 5 +- src/main/java/mezz/jei/ItemFilter.java | 2 +- src/main/java/mezz/jei/ItemRegistry.java | 6 +- src/main/java/mezz/jei/JustEnoughItems.java | 101 ++----- src/main/java/mezz/jei/PluginRegistry.java | 50 ++++ src/main/java/mezz/jei/ProxyCommon.java | 42 +++ src/main/java/mezz/jei/ProxyCommonClient.java | 62 +++++ src/main/java/mezz/jei/RecipeRegistry.java | 36 ++- src/main/java/mezz/jei/api/IGuiHelper.java | 4 + src/main/java/mezz/jei/api/IItemRegistry.java | 3 + src/main/java/mezz/jei/api/IModPlugin.java | 19 +- .../java/mezz/jei/api/IPluginRegistry.java | 6 + .../java/mezz/jei/api/IRecipeRegistry.java | 4 + .../mezz/jei/api/gui/IGuiFluidStackGroup.java | 13 +- .../mezz/jei/api/gui/IGuiIngredientGroup.java | 4 +- .../mezz/jei/api/gui/IGuiItemStackGroup.java | 16 +- .../java/mezz/jei/api/gui/IRecipeLayout.java | 17 ++ src/main/java/mezz/jei/api/package-info.java | 2 +- .../mezz/jei/api/recipe/IRecipeCategory.java | 13 +- .../jei/api/recipe/IRecipeCategoryUid.java | 7 - .../mezz/jei/api/recipe/IRecipeHandler.java | 2 +- .../jei/api/recipe/IRecipeTransferHelper.java | 33 +++ .../mezz/jei/api/recipe/IRecipeWrapper.java | 23 +- .../api/recipe/VanillaRecipeCategoryUid.java | 9 +- .../jei/gui/BasicRecipeTransferHelper.java | 57 ++++ .../java/mezz/jei/gui/CraftingGridHelper.java | 57 ++-- src/main/java/mezz/jei/gui/GuiHelper.java | 7 + .../java/mezz/jei/gui/IRecipeGuiLogic.java | 2 +- .../java/mezz/jei/gui/ItemListOverlay.java | 2 +- .../java/mezz/jei/gui/RecipeGuiLogic.java | 12 +- src/main/java/mezz/jei/gui/RecipeLayout.java | 106 ++++++++ src/main/java/mezz/jei/gui/RecipeWidget.java | 65 ----- src/main/java/mezz/jei/gui/RecipesGui.java | 65 +++-- .../gui/ingredients/GuiFluidStackGroup.java | 6 +- .../jei/gui/ingredients/GuiIngredient.java | 16 +- .../gui/ingredients/GuiIngredientGroup.java | 15 +- .../gui/ingredients/GuiItemStackGroup.java | 21 +- .../jei/gui/ingredients/IGuiIngredient.java | 4 + src/main/java/mezz/jei/input/IKeyable.java | 2 +- .../java/mezz/jei/input/InputHandler.java | 2 +- src/main/java/mezz/jei/network/IPacketId.java | 5 + .../java/mezz/jei/network/PacketHandler.java | 95 +++++++ .../java/mezz/jei/network/PacketIdClient.java | 7 + .../java/mezz/jei/network/PacketIdServer.java | 7 + .../mezz/jei/network/packets/PacketJEI.java | 36 +++ .../network/packets/PacketRecipeTransfer.java | 84 ++++++ .../jei/plugins/vanilla/VanillaPlugin.java | 28 +- .../crafting/CraftingRecipeCategory.java | 19 +- .../crafting/ShapedOreRecipeHandler.java | 3 +- .../crafting/ShapedOreRecipeWrapper.java | 5 + .../crafting/ShapedRecipesHandler.java | 3 +- .../crafting/ShapedRecipesWrapper.java | 4 + .../crafting/ShapelessOreRecipeHandler.java | 3 +- .../crafting/ShapelessOreRecipeWrapper.java | 5 + .../crafting/ShapelessRecipesHandler.java | 3 +- .../crafting/ShapelessRecipesWrapper.java | 5 + .../plugins/vanilla/furnace/FuelRecipe.java | 4 + .../vanilla/furnace/FuelRecipeHandler.java | 5 +- .../vanilla/furnace/FurnaceFuelCategory.java | 26 ++ .../furnace/FurnaceRecipeCategory.java | 36 +-- .../furnace/FurnaceSmeltingCategory.java | 25 ++ .../vanilla/furnace/SmeltingRecipe.java | 16 +- .../furnace/SmeltingRecipeHandler.java | 5 +- .../mezz/jei/util/RecipeTransferUtil.java | 249 ++++++++++++++++++ src/main/java/mezz/jei/util/StackUtil.java | 218 +++++++++++++-- 65 files changed, 1479 insertions(+), 335 deletions(-) create mode 100644 src/main/java/mezz/jei/PluginRegistry.java create mode 100644 src/main/java/mezz/jei/ProxyCommon.java create mode 100644 src/main/java/mezz/jei/ProxyCommonClient.java create mode 100644 src/main/java/mezz/jei/api/gui/IRecipeLayout.java delete mode 100644 src/main/java/mezz/jei/api/recipe/IRecipeCategoryUid.java create mode 100644 src/main/java/mezz/jei/api/recipe/IRecipeTransferHelper.java create mode 100644 src/main/java/mezz/jei/gui/BasicRecipeTransferHelper.java create mode 100644 src/main/java/mezz/jei/gui/RecipeLayout.java delete mode 100644 src/main/java/mezz/jei/gui/RecipeWidget.java create mode 100644 src/main/java/mezz/jei/network/IPacketId.java create mode 100644 src/main/java/mezz/jei/network/PacketHandler.java create mode 100644 src/main/java/mezz/jei/network/PacketIdClient.java create mode 100644 src/main/java/mezz/jei/network/PacketIdServer.java create mode 100644 src/main/java/mezz/jei/network/packets/PacketJEI.java create mode 100644 src/main/java/mezz/jei/network/packets/PacketRecipeTransfer.java create mode 100644 src/main/java/mezz/jei/plugins/vanilla/furnace/FurnaceFuelCategory.java create mode 100644 src/main/java/mezz/jei/plugins/vanilla/furnace/FurnaceSmeltingCategory.java create mode 100644 src/main/java/mezz/jei/util/RecipeTransferUtil.java diff --git a/README.md b/README.md index aa62539e5..94b4dcc26 100644 --- a/README.md +++ b/README.md @@ -28,9 +28,6 @@ dependencies { ``` `` can be `1.8` or `1.8.8`. -See the curseforge link above for a available JEI versions. - -There is a bug in ForgeGradle with dependency ATs, to work around it run: -`gradlew cleanDeobfMcSRG && gradlew setupDecompWorkspace` +See the list of github tags for available JEI versions. Join [#JEI on esper.net IRC](http://webchat.esper.net/?nick=JEIGithub...&channels=JEI&prompt=1) for questions or anything else. diff --git a/src/main/java/mezz/jei/ItemFilter.java b/src/main/java/mezz/jei/ItemFilter.java index 907672987..01e0cfd12 100644 --- a/src/main/java/mezz/jei/ItemFilter.java +++ b/src/main/java/mezz/jei/ItemFilter.java @@ -91,7 +91,7 @@ public ImmutableList load(@Nonnull final String filterText) th } } catch (RuntimeException e) { try { - Log.error("Couldn't find ItemModelMesher for itemstack {}. Exception: {}", itemStack, e); + Log.error("Couldn't find ItemModelMesher for itemStack {}. Exception: {}", itemStack, e); } catch (RuntimeException ignored) { } diff --git a/src/main/java/mezz/jei/ItemRegistry.java b/src/main/java/mezz/jei/ItemRegistry.java index 44be1fc47..ec52d84eb 100644 --- a/src/main/java/mezz/jei/ItemRegistry.java +++ b/src/main/java/mezz/jei/ItemRegistry.java @@ -34,8 +34,8 @@ class ItemRegistry implements IItemRegistry { @Nonnull private final ModList modList; - public ItemRegistry(@Nonnull ModList modList) { - this.modList = modList; + public ItemRegistry() { + this.modList = new ModList(); List itemList = new ArrayList<>(); List fuels = new ArrayList<>(); @@ -144,7 +144,7 @@ private void addItemStack(@Nonnull ItemStack stack, @Nonnull List ite } } catch (RuntimeException e) { try { - Log.error("Couldn't create unique name for itemstack {}. Exception: {}", stack, e); + Log.error("Couldn't create unique name for itemStack {}. Exception: {}", stack, e); } catch (RuntimeException ignored) { } diff --git a/src/main/java/mezz/jei/JustEnoughItems.java b/src/main/java/mezz/jei/JustEnoughItems.java index 8f67cacc5..d6f443769 100644 --- a/src/main/java/mezz/jei/JustEnoughItems.java +++ b/src/main/java/mezz/jei/JustEnoughItems.java @@ -1,115 +1,52 @@ package mezz.jei; -import com.google.common.collect.ImmutableList; - import javax.annotation.Nonnull; -import java.util.ArrayList; -import java.util.List; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.fml.client.event.ConfigChangedEvent; -import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.SidedProxy; import net.minecraftforge.fml.common.event.FMLInitializationEvent; +import net.minecraftforge.fml.common.event.FMLLoadCompleteEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; -import net.minecraftforge.fml.common.event.FMLServerAboutToStartEvent; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import mezz.jei.api.IModPlugin; -import mezz.jei.api.IPluginRegistry; import mezz.jei.api.JEIManager; -import mezz.jei.api.recipe.IRecipeCategory; -import mezz.jei.api.recipe.IRecipeHandler; -import mezz.jei.config.Config; import mezz.jei.config.Constants; -import mezz.jei.config.KeyBindings; import mezz.jei.gui.GuiHelper; -import mezz.jei.gui.ItemListOverlay; -import mezz.jei.plugins.vanilla.VanillaPlugin; -import mezz.jei.util.ModList; +import mezz.jei.network.PacketHandler; @Mod(modid = Constants.MOD_ID, name = Constants.NAME, version = Constants.VERSION, guiFactory = "mezz.jei.config.JEIModGuiFactory", dependencies = "required-after:Forge@[11.14.0.1269,);") -public class JustEnoughItems implements IPluginRegistry { +public class JustEnoughItems { + + @SidedProxy(clientSide = "mezz.jei.ProxyCommonClient", serverSide = "mezz.jei.ProxyCommon") + public static ProxyCommon common; @Mod.Instance(Constants.MOD_ID) public static JustEnoughItems instance; - @Nonnull - private final List plugins = new ArrayList<>(); - private boolean pluginsCanRegister = true; - private boolean jeiStarted = false; + public static PacketHandler packetHandler; - public JustEnoughItems() { - JEIManager.guiHelper = new GuiHelper(); - JEIManager.pluginRegistry = this; - } + private PluginRegistry pluginRegistry; @Mod.EventHandler public void preInit(@Nonnull FMLPreInitializationEvent event) { - Config.preInit(event); - - JEIManager.pluginRegistry.registerPlugin(new VanillaPlugin()); - } - - @Override - public void registerPlugin(IModPlugin plugin) { - if (!pluginsCanRegister) { - throw new IllegalStateException("Plugins must be registered during FMLPreInitializationEvent."); - } - - if (plugin.isModLoaded()) { - plugins.add(plugin); - } + packetHandler = new PacketHandler(); + JEIManager.pluginRegistry = pluginRegistry = new PluginRegistry(); + JEIManager.guiHelper = new GuiHelper(); + common.preInit(event); } @Mod.EventHandler - public void init(FMLInitializationEvent event) { - pluginsCanRegister = false; - KeyBindings.init(); - - FMLCommonHandler.instance().bus().register(instance); + public void init(@Nonnull FMLInitializationEvent event) { + pluginRegistry.init(); + common.init(event); } @Mod.EventHandler - public void aboutToStart(FMLServerAboutToStartEvent event) { - if (jeiStarted) { - return; - } - jeiStarted = true; - - ModList modList = new ModList(); - - JEIManager.itemRegistry = new ItemRegistry(modList); - - ImmutableList.Builder recipeCategories = ImmutableList.builder(); - ImmutableList.Builder recipeHandlers = ImmutableList.builder(); - ImmutableList.Builder recipes = ImmutableList.builder(); - - for (IModPlugin plugin : plugins) { - recipeCategories.addAll(plugin.getRecipeCategories()); - recipeHandlers.addAll(plugin.getRecipeHandlers()); - recipes.addAll(plugin.getRecipes()); - } - - JEIManager.recipeRegistry = new RecipeRegistry(recipeCategories.build(), recipeHandlers.build(), recipes.build()); - - ItemFilter itemFilter = new ItemFilter(JEIManager.itemRegistry.getItemList()); - ItemListOverlay itemListOverlay = new ItemListOverlay(itemFilter); - GuiEventHandler guiEventHandler = new GuiEventHandler(itemListOverlay); - MinecraftForge.EVENT_BUS.register(guiEventHandler); - FMLCommonHandler.instance().bus().register(guiEventHandler); - - TooltipEventHandler tooltipEventHandler = new TooltipEventHandler(); - MinecraftForge.EVENT_BUS.register(tooltipEventHandler); + public void loadComplete(@Nonnull FMLLoadCompleteEvent event) { + JEIManager.recipeRegistry = pluginRegistry.createRecipeRegistry(); + common.loadComplete(event); } - - @SubscribeEvent - public void onConfigChanged(@Nonnull ConfigChangedEvent.OnConfigChangedEvent eventArgs) { - Config.onConfigChanged(eventArgs); - } - } diff --git a/src/main/java/mezz/jei/PluginRegistry.java b/src/main/java/mezz/jei/PluginRegistry.java new file mode 100644 index 000000000..10f1e46dc --- /dev/null +++ b/src/main/java/mezz/jei/PluginRegistry.java @@ -0,0 +1,50 @@ +package mezz.jei; + +import com.google.common.collect.ImmutableList; + +import javax.annotation.Nonnull; +import java.util.ArrayList; +import java.util.List; + +import mezz.jei.api.IModPlugin; +import mezz.jei.api.IPluginRegistry; +import mezz.jei.api.recipe.IRecipeCategory; +import mezz.jei.api.recipe.IRecipeHandler; +import mezz.jei.api.recipe.IRecipeTransferHelper; + +public class PluginRegistry implements IPluginRegistry { + private boolean pluginsCanRegister = true; + @Nonnull + private final List plugins = new ArrayList<>(); + + @Override + public void registerPlugin(IModPlugin plugin) { + if (!pluginsCanRegister) { + throw new IllegalStateException("Plugins must be registered during FMLPreInitializationEvent."); + } + + if (plugin.isModLoaded()) { + plugins.add(plugin); + } + } + + public void init() { + pluginsCanRegister = false; + } + + public RecipeRegistry createRecipeRegistry() { + ImmutableList.Builder recipeCategories = ImmutableList.builder(); + ImmutableList.Builder recipeHandlers = ImmutableList.builder(); + ImmutableList.Builder recipeTransferHelpers = ImmutableList.builder(); + ImmutableList.Builder recipes = ImmutableList.builder(); + + for (IModPlugin plugin : plugins) { + recipeCategories.addAll(plugin.getRecipeCategories()); + recipeHandlers.addAll(plugin.getRecipeHandlers()); + recipeTransferHelpers.addAll(plugin.getRecipeTransferHelpers()); + recipes.addAll(plugin.getRecipes()); + } + + return new RecipeRegistry(recipeCategories.build(), recipeHandlers.build(), recipeTransferHelpers.build(), recipes.build()); + } +} diff --git a/src/main/java/mezz/jei/ProxyCommon.java b/src/main/java/mezz/jei/ProxyCommon.java new file mode 100644 index 000000000..c61b8d95b --- /dev/null +++ b/src/main/java/mezz/jei/ProxyCommon.java @@ -0,0 +1,42 @@ +package mezz.jei; + +import javax.annotation.Nonnull; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; + +import net.minecraftforge.common.util.FakePlayer; +import net.minecraftforge.fml.common.event.FMLInitializationEvent; +import net.minecraftforge.fml.common.event.FMLLoadCompleteEvent; +import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; + +import mezz.jei.network.packets.PacketJEI; +import mezz.jei.util.Log; + +public class ProxyCommon { + + public void preInit(@Nonnull FMLPreInitializationEvent event) { + + } + + public void init(@Nonnull FMLInitializationEvent event) { + + } + + public void loadComplete(@Nonnull FMLLoadCompleteEvent event) { + + } + + public void sendPacketToServer(PacketJEI packet) { + Log.error("Tried to send packet to the server from the server: {}", packet); + } + + public void sendPacketToPlayer(PacketJEI packet, EntityPlayer entityplayer) { + if (!(entityplayer instanceof EntityPlayerMP) || (entityplayer instanceof FakePlayer)) { + return; + } + + EntityPlayerMP player = (EntityPlayerMP) entityplayer; + JustEnoughItems.packetHandler.sendPacket(packet.getPacket(), player); + } +} diff --git a/src/main/java/mezz/jei/ProxyCommonClient.java b/src/main/java/mezz/jei/ProxyCommonClient.java new file mode 100644 index 000000000..b4312838a --- /dev/null +++ b/src/main/java/mezz/jei/ProxyCommonClient.java @@ -0,0 +1,62 @@ +package mezz.jei; + +import javax.annotation.Nonnull; + +import net.minecraft.client.network.NetHandlerPlayClient; + +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.client.FMLClientHandler; +import net.minecraftforge.fml.client.event.ConfigChangedEvent; +import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.common.event.FMLInitializationEvent; +import net.minecraftforge.fml.common.event.FMLLoadCompleteEvent; +import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +import mezz.jei.api.JEIManager; +import mezz.jei.config.Config; +import mezz.jei.config.KeyBindings; +import mezz.jei.gui.ItemListOverlay; +import mezz.jei.network.packets.PacketJEI; +import mezz.jei.plugins.vanilla.VanillaPlugin; + +public class ProxyCommonClient extends ProxyCommon { + @Override + public void preInit(@Nonnull FMLPreInitializationEvent event) { + Config.preInit(event); + JEIManager.pluginRegistry.registerPlugin(new VanillaPlugin()); + } + + @Override + public void init(@Nonnull FMLInitializationEvent event) { + KeyBindings.init(); + FMLCommonHandler.instance().bus().register(this); + } + + @Override + public void loadComplete(@Nonnull FMLLoadCompleteEvent event) { + JEIManager.itemRegistry = new ItemRegistry(); + + ItemFilter itemFilter = new ItemFilter(JEIManager.itemRegistry.getItemList()); + ItemListOverlay itemListOverlay = new ItemListOverlay(itemFilter); + GuiEventHandler guiEventHandler = new GuiEventHandler(itemListOverlay); + MinecraftForge.EVENT_BUS.register(guiEventHandler); + FMLCommonHandler.instance().bus().register(guiEventHandler); + + TooltipEventHandler tooltipEventHandler = new TooltipEventHandler(); + MinecraftForge.EVENT_BUS.register(tooltipEventHandler); + } + + @Override + public void sendPacketToServer(PacketJEI packet) { + NetHandlerPlayClient netHandler = FMLClientHandler.instance().getClient().getNetHandler(); + if (netHandler != null) { + netHandler.addToSendQueue(packet.getPacket()); + } + } + + @SubscribeEvent + public void onConfigChanged(@Nonnull ConfigChangedEvent.OnConfigChangedEvent eventArgs) { + Config.onConfigChanged(eventArgs); + } +} diff --git a/src/main/java/mezz/jei/RecipeRegistry.java b/src/main/java/mezz/jei/RecipeRegistry.java index 6ae2be027..0c07aaef7 100644 --- a/src/main/java/mezz/jei/RecipeRegistry.java +++ b/src/main/java/mezz/jei/RecipeRegistry.java @@ -3,6 +3,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableTable; import com.google.common.collect.Maps; import javax.annotation.Nonnull; @@ -14,6 +15,7 @@ import java.util.Map; import java.util.Set; +import net.minecraft.inventory.Container; import net.minecraft.item.ItemStack; import net.minecraftforge.fluids.Fluid; @@ -21,8 +23,8 @@ import mezz.jei.api.IRecipeRegistry; import mezz.jei.api.recipe.IRecipeCategory; -import mezz.jei.api.recipe.IRecipeCategoryUid; import mezz.jei.api.recipe.IRecipeHandler; +import mezz.jei.api.recipe.IRecipeTransferHelper; import mezz.jei.api.recipe.IRecipeWrapper; import mezz.jei.util.Log; import mezz.jei.util.RecipeCategoryComparator; @@ -31,14 +33,16 @@ public class RecipeRegistry implements IRecipeRegistry { private final ImmutableMap recipeHandlers; - private final ImmutableMap recipeCategoriesMap; + private final ImmutableTable recipeTransferHelpers; + private final ImmutableMap recipeCategoriesMap; private final RecipeMap recipeInputMap; private final RecipeMap recipeOutputMap; private final Set unhandledRecipeClasses = new HashSet<>(); - RecipeRegistry(@Nonnull ImmutableList recipeCategories, @Nonnull ImmutableList recipeHandlers, @Nonnull ImmutableList recipes) { + RecipeRegistry(@Nonnull ImmutableList recipeCategories, @Nonnull ImmutableList recipeHandlers, @Nonnull ImmutableList recipeTransferHelpers, @Nonnull ImmutableList recipes) { recipeCategories = ImmutableSet.copyOf(recipeCategories).asList(); //remove duplicates this.recipeCategoriesMap = buildRecipeCategoriesMap(recipeCategories); + this.recipeTransferHelpers = buildRecipeTransferHelperTable(recipeTransferHelpers); this.recipeHandlers = buildRecipeHandlersMap(recipeHandlers); RecipeCategoryComparator recipeCategoryComparator = new RecipeCategoryComparator(recipeCategories); @@ -48,8 +52,8 @@ public class RecipeRegistry implements IRecipeRegistry { addRecipes(recipes); } - private static ImmutableMap buildRecipeCategoriesMap(@Nonnull ImmutableList recipeCategories) { - Map mutableRecipeCategoriesMap = new HashMap<>(); + private static ImmutableMap buildRecipeCategoriesMap(@Nonnull ImmutableList recipeCategories) { + Map mutableRecipeCategoriesMap = new HashMap<>(); for (IRecipeCategory recipeCategory : recipeCategories) { mutableRecipeCategoriesMap.put(recipeCategory.getUid(), recipeCategory); } @@ -74,6 +78,14 @@ private static ImmutableMap buildRecipeHandlersMap(@Nonnu return ImmutableMap.copyOf(mutableRecipeHandlers); } + private static ImmutableTable buildRecipeTransferHelperTable(@Nonnull List recipeTransferHelpers) { + ImmutableTable.Builder builder = ImmutableTable.builder(); + for (IRecipeTransferHelper recipeTransferHelper : recipeTransferHelpers) { + builder.put(recipeTransferHelper.getContainerClass(), recipeTransferHelper.getRecipeCategoryUid(), recipeTransferHelper); + } + return builder.build(); + } + private void addRecipes(@Nullable ImmutableList recipes) { if (recipes == null) { return; @@ -103,7 +115,7 @@ private void addRecipe(@Nullable Object recipe) { return; } - IRecipeCategoryUid recipeCategoryUid = recipeHandler.getRecipeCategoryUid(); + String recipeCategoryUid = recipeHandler.getRecipeCategoryUid(); IRecipeCategory recipeCategory = recipeCategoriesMap.get(recipeCategoryUid); if (recipeCategory == null) { Log.error("No recipe category registered for recipeCategoryUid: {}", recipeCategoryUid); @@ -121,6 +133,9 @@ private void addRecipe(@Nullable Object recipe) { List inputs = recipeWrapper.getInputs(); List fluidInputs = recipeWrapper.getFluidInputs(); if (inputs != null || fluidInputs != null) { + if (recipeWrapper.usesOreDictionaryComparison()) { + inputs = StackUtil.expandRecipeInputs(inputs, true); + } List inputStacks = StackUtil.toItemStackList(inputs); if (fluidInputs == null) { fluidInputs = Collections.emptyList(); @@ -221,4 +236,13 @@ public ImmutableList getRecipesWithOutput(@Nullable IRecipeCategory reci } return recipeOutputMap.getRecipes(recipeCategory, output); } + + @Nullable + @Override + public IRecipeTransferHelper getRecipeTransferHelper(@Nullable Container container, @Nullable IRecipeCategory recipeCategory) { + if (container == null || recipeCategory == null) { + return null; + } + return recipeTransferHelpers.get(container.getClass(), recipeCategory.getUid()); + } } diff --git a/src/main/java/mezz/jei/api/IGuiHelper.java b/src/main/java/mezz/jei/api/IGuiHelper.java index 6ba0c37b0..79fae4529 100644 --- a/src/main/java/mezz/jei/api/IGuiHelper.java +++ b/src/main/java/mezz/jei/api/IGuiHelper.java @@ -2,10 +2,12 @@ import javax.annotation.Nonnull; +import net.minecraft.inventory.Container; import net.minecraft.util.ResourceLocation; import mezz.jei.api.gui.ICraftingGridHelper; import mezz.jei.api.gui.IDrawable; +import mezz.jei.api.recipe.IRecipeTransferHelper; /** * Helps with the implementation of GUIs. @@ -18,4 +20,6 @@ public interface IGuiHelper { @Nonnull ICraftingGridHelper createCraftingGridHelper(int craftInputSlot1, int craftOutputSlot); + @Nonnull + IRecipeTransferHelper createRecipeTransferHelper(Class containerClass, String recipeCategoryUid, int recipeSlotStart, int recipeSlotCount, int inventorySlotStart, int inventorySlotCount); } diff --git a/src/main/java/mezz/jei/api/IItemRegistry.java b/src/main/java/mezz/jei/api/IItemRegistry.java index 4b4cafb66..95a063faa 100644 --- a/src/main/java/mezz/jei/api/IItemRegistry.java +++ b/src/main/java/mezz/jei/api/IItemRegistry.java @@ -7,6 +7,9 @@ import net.minecraft.item.Item; import net.minecraft.item.ItemStack; +/** + * The IItemRegistry is provided by JEI and has some useful functions related to items. + */ public interface IItemRegistry { /** Returns a list of all the Items registered. */ diff --git a/src/main/java/mezz/jei/api/IModPlugin.java b/src/main/java/mezz/jei/api/IModPlugin.java index 839f12f48..5618fea60 100644 --- a/src/main/java/mezz/jei/api/IModPlugin.java +++ b/src/main/java/mezz/jei/api/IModPlugin.java @@ -1,10 +1,13 @@ package mezz.jei.api; +import javax.annotation.Nonnull; + import mezz.jei.api.recipe.IRecipeCategory; import mezz.jei.api.recipe.IRecipeHandler; +import mezz.jei.api.recipe.IRecipeTransferHelper; /** - * The main class for a plugin. + * The main class for a plugin. Everything passed from a mod into JEI is through this class. * This class must not import anything that could be missing at runtime (i.e. code from any mod). */ public interface IModPlugin { @@ -12,10 +15,22 @@ public interface IModPlugin { /** Returns true if this plugin's mod is loaded. */ boolean isModLoaded(); + /** Return the recipe categories provided by this plugin. */ + @Nonnull Iterable getRecipeCategories(); + /** Return the recipe handlers provided by this plugin. */ + @Nonnull Iterable getRecipeHandlers(); - Iterable getRecipes(); + /** Return the recipe transfer helpers provided by this plugin. */ + @Nonnull + Iterable getRecipeTransferHelpers(); + /** + * Return the recipes provided by this plugin. + * These can be regular recipes, they will get wrapped by the provided recipe handlers. + */ + @Nonnull + Iterable getRecipes(); } diff --git a/src/main/java/mezz/jei/api/IPluginRegistry.java b/src/main/java/mezz/jei/api/IPluginRegistry.java index f478dde1b..1f9c82470 100644 --- a/src/main/java/mezz/jei/api/IPluginRegistry.java +++ b/src/main/java/mezz/jei/api/IPluginRegistry.java @@ -1,7 +1,13 @@ package mezz.jei.api; +/** + * The main entry point for mod plugins. All plugins must register here. + */ public interface IPluginRegistry { + /** + * Register your mod plugin. + */ void registerPlugin(IModPlugin plugin); } diff --git a/src/main/java/mezz/jei/api/IRecipeRegistry.java b/src/main/java/mezz/jei/api/IRecipeRegistry.java index c8f80ba3f..65d10381c 100644 --- a/src/main/java/mezz/jei/api/IRecipeRegistry.java +++ b/src/main/java/mezz/jei/api/IRecipeRegistry.java @@ -5,12 +5,14 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; +import net.minecraft.inventory.Container; import net.minecraft.item.ItemStack; import net.minecraftforge.fluids.Fluid; import mezz.jei.api.recipe.IRecipeCategory; import mezz.jei.api.recipe.IRecipeHandler; +import mezz.jei.api.recipe.IRecipeTransferHelper; /** * The IRecipeManager offers several functions for retrieving and handling recipes. @@ -55,4 +57,6 @@ public interface IRecipeRegistry { @Nonnull ImmutableList getRecipesWithOutput(IRecipeCategory recipeCategory, Fluid output); + @Nullable + IRecipeTransferHelper getRecipeTransferHelper(Container container, IRecipeCategory recipeCategory); } diff --git a/src/main/java/mezz/jei/api/gui/IGuiFluidStackGroup.java b/src/main/java/mezz/jei/api/gui/IGuiFluidStackGroup.java index bebd12fcb..1d182f6b9 100644 --- a/src/main/java/mezz/jei/api/gui/IGuiFluidStackGroup.java +++ b/src/main/java/mezz/jei/api/gui/IGuiFluidStackGroup.java @@ -14,13 +14,20 @@ public interface IGuiFluidStackGroup extends IGuiIngredientGroup { /** * Fluid tanks must be initialized once, and then can be set many times. + * @param slotIndex the slot index of this fluid + * @param input whether this slot is an input + * @param xPosition x position relative to the recipe background + * @param yPosition y position relative to the recipe background + * @param width width of this tank + * @param height height of this tank + * @param capacityMb maximum amount of fluid that this tank can hold */ - void init(int index, int xPosition, int yPosition, int width, int height, int capacityMb); + void init(int slotIndex, boolean input, int xPosition, int yPosition, int width, int height, int capacityMb); @Override - void set(int index, @Nonnull Collection fluidStacks); + void set(int slotIndex, @Nonnull Collection fluidStacks); @Override - void set(int index, @Nonnull FluidStack fluidStack); + void set(int slotIndex, @Nonnull FluidStack fluidStack); } diff --git a/src/main/java/mezz/jei/api/gui/IGuiIngredientGroup.java b/src/main/java/mezz/jei/api/gui/IGuiIngredientGroup.java index 0a6ecc0d5..841299565 100644 --- a/src/main/java/mezz/jei/api/gui/IGuiIngredientGroup.java +++ b/src/main/java/mezz/jei/api/gui/IGuiIngredientGroup.java @@ -10,7 +10,7 @@ * @see IGuiItemStackGroup and IGuiFluidStackGroup */ public interface IGuiIngredientGroup { - void set(int index, @Nonnull Collection ingredients); + void set(int slotIndex, @Nonnull Collection ingredients); - void set(int index, @Nonnull T ingredient); + void set(int slotIndex, @Nonnull T ingredient); } diff --git a/src/main/java/mezz/jei/api/gui/IGuiItemStackGroup.java b/src/main/java/mezz/jei/api/gui/IGuiItemStackGroup.java index e9c7c2fe9..c83c211ca 100644 --- a/src/main/java/mezz/jei/api/gui/IGuiItemStackGroup.java +++ b/src/main/java/mezz/jei/api/gui/IGuiItemStackGroup.java @@ -2,6 +2,7 @@ import javax.annotation.Nonnull; import java.util.Collection; +import java.util.List; import net.minecraft.item.ItemStack; @@ -15,13 +16,22 @@ public interface IGuiItemStackGroup extends IGuiIngredientGroup { /** * ItemStacks must be initialized once, and then can be set many times. + * @param slotIndex the slot index of this itemStack + * @param input whether this slot is an input. Used for the recipe-fill feature. + * @param xPosition x position of the slot relative to the recipe background + * @param yPosition y position of the slot relative to the recipe background */ - void init(int index, int xPosition, int yPosition); + void init(int slotIndex, boolean input, int xPosition, int yPosition); + + /** + * Takes a list of ingredients from IRecipeWrapper getInputs or getOutputs + */ + void setFromRecipe(int slotIndex, @Nonnull List ingredients); @Override - void set(int index, @Nonnull Collection itemStacks); + void set(int slotIndex, @Nonnull Collection itemStacks); @Override - void set(int index, @Nonnull ItemStack itemStack); + void set(int slotIndex, @Nonnull ItemStack itemStack); } diff --git a/src/main/java/mezz/jei/api/gui/IRecipeLayout.java b/src/main/java/mezz/jei/api/gui/IRecipeLayout.java new file mode 100644 index 000000000..17a286d34 --- /dev/null +++ b/src/main/java/mezz/jei/api/gui/IRecipeLayout.java @@ -0,0 +1,17 @@ +package mezz.jei.api.gui; + +import javax.annotation.Nonnull; + +public interface IRecipeLayout { + @Nonnull + IGuiItemStackGroup getItemStacks(); + + @Nonnull + IGuiFluidStackGroup getFluidStacks(); + + /** + * Enables the recipe transfer button and sets its position relative to the recipe layout. + * The button transfers items in the user's inventory into the crafting area to set a recipe. + */ + void setRecipeTransferButton(int posX, int posY); +} diff --git a/src/main/java/mezz/jei/api/package-info.java b/src/main/java/mezz/jei/api/package-info.java index 49ce9858d..e246defe3 100644 --- a/src/main/java/mezz/jei/api/package-info.java +++ b/src/main/java/mezz/jei/api/package-info.java @@ -1,4 +1,4 @@ -@API(apiVersion = "25.0.0", owner = "JEI", provides = "JustEnoughItemsAPI") +@API(apiVersion = "26.0.0", owner = "JEI", provides = "JustEnoughItemsAPI") package mezz.jei.api; import net.minecraftforge.fml.common.API; diff --git a/src/main/java/mezz/jei/api/recipe/IRecipeCategory.java b/src/main/java/mezz/jei/api/recipe/IRecipeCategory.java index c4656671f..bd657f6cc 100644 --- a/src/main/java/mezz/jei/api/recipe/IRecipeCategory.java +++ b/src/main/java/mezz/jei/api/recipe/IRecipeCategory.java @@ -3,8 +3,7 @@ import javax.annotation.Nonnull; import mezz.jei.api.gui.IDrawable; -import mezz.jei.api.gui.IGuiFluidStackGroup; -import mezz.jei.api.gui.IGuiItemStackGroup; +import mezz.jei.api.gui.IRecipeLayout; /** * Defines a category of recipe, (i.e. Crafting Table Recipe, Furnace Recipe) @@ -17,7 +16,7 @@ public interface IRecipeCategory { * Referenced from recipes to identify which recipe category they belong to. */ @Nonnull - IRecipeCategoryUid getUid(); + String getUid(); /** * Returns the localized name for this recipe type. @@ -35,13 +34,13 @@ public interface IRecipeCategory { IDrawable getBackground(); /** - * Initialize the IGuiItemStackGroup and IGuiFluidStackGroup with this recipe's layout. + * Initialize the IRecipeLayout. */ - void init(@Nonnull IGuiItemStackGroup guiItemStacks, @Nonnull IGuiFluidStackGroup guiFluidTanks); + void init(@Nonnull IRecipeLayout recipeLayout); /** - * Set the IGuiItemStackGroup and IGuiFluidStackGroup properties from the RecipeWrapper. + * Set the IRecipeLayout properties from the RecipeWrapper. */ - void setRecipe(@Nonnull IGuiItemStackGroup guiItemStacks, @Nonnull IGuiFluidStackGroup guiFluidTanks, @Nonnull IRecipeWrapper recipeWrapper); + void setRecipe(@Nonnull IRecipeLayout recipeLayout, @Nonnull IRecipeWrapper recipeWrapper); } diff --git a/src/main/java/mezz/jei/api/recipe/IRecipeCategoryUid.java b/src/main/java/mezz/jei/api/recipe/IRecipeCategoryUid.java deleted file mode 100644 index ccc04e7ed..000000000 --- a/src/main/java/mezz/jei/api/recipe/IRecipeCategoryUid.java +++ /dev/null @@ -1,7 +0,0 @@ -package mezz.jei.api.recipe; - -/** - * Unique identifier for a recipe category. - */ -public interface IRecipeCategoryUid { -} diff --git a/src/main/java/mezz/jei/api/recipe/IRecipeHandler.java b/src/main/java/mezz/jei/api/recipe/IRecipeHandler.java index b480d8651..a64241642 100644 --- a/src/main/java/mezz/jei/api/recipe/IRecipeHandler.java +++ b/src/main/java/mezz/jei/api/recipe/IRecipeHandler.java @@ -13,7 +13,7 @@ public interface IRecipeHandler { /** Returns this recipe's category unique id. */ @Nonnull - IRecipeCategoryUid getRecipeCategoryUid(); + String getRecipeCategoryUid(); /** Returns a recipe wrapper for the given recipe. */ @Nonnull diff --git a/src/main/java/mezz/jei/api/recipe/IRecipeTransferHelper.java b/src/main/java/mezz/jei/api/recipe/IRecipeTransferHelper.java new file mode 100644 index 000000000..b692b5419 --- /dev/null +++ b/src/main/java/mezz/jei/api/recipe/IRecipeTransferHelper.java @@ -0,0 +1,33 @@ +package mezz.jei.api.recipe; + +import java.util.List; + +import net.minecraft.inventory.Container; +import net.minecraft.inventory.Slot; + +/** + * Gives JEI the information it needs to transfer recipes from the player's inventory into the crafting area. + * Most plugins should create new IRecipeTransferHelper instances with IGuiHelper.createRecipeTransferHelper. + * Complicated containers can implement this interface directly if necessary. + */ +public interface IRecipeTransferHelper { + /** + * Return the container class that this recipe transfer helper supports + */ + Class getContainerClass(); + + /** + * Return the recipe category that this container can handle. + */ + String getRecipeCategoryUid(); + + /** + * Return a list of slots for the recipe area. + */ + List getRecipeSlots(Container container); + + /** + * Return a list of slots that the transfer can use to get items for crafting, or place leftover items. + */ + List getInventorySlots(Container container); +} diff --git a/src/main/java/mezz/jei/api/recipe/IRecipeWrapper.java b/src/main/java/mezz/jei/api/recipe/IRecipeWrapper.java index 972e1f3e1..f4056169e 100644 --- a/src/main/java/mezz/jei/api/recipe/IRecipeWrapper.java +++ b/src/main/java/mezz/jei/api/recipe/IRecipeWrapper.java @@ -7,16 +7,33 @@ import net.minecraftforge.fluids.FluidStack; +/** + * A wrapper around a normal recipe with methods that allow JEI can make sense of it. + * Implementers will have to create a wrapper for each type of recipe they have. + */ public interface IRecipeWrapper { + /** + * Return a list of recipe inputs. + * Each element can be an ItemStack, null, or a List of ItemStacks. + */ List getInputs(); - List getFluidInputs(); - + /** + * Return a list of recipe inputs. + * Each element can be an ItemStack, null, or a List of ItemStacks. + */ List getOutputs(); + /** Return a list of recipe fluid inputs. */ + List getFluidInputs(); + + /** Return a list of recipe fluid outputs. */ List getFluidOutputs(); - /* Draw additional info about the recipe. */ + /** Draw additional info about the recipe. */ void drawInfo(@Nonnull Minecraft minecraft); + + /** Return true if this recipe uses the ore dictionary to compare itemStacks with its inputs. */ + boolean usesOreDictionaryComparison(); } diff --git a/src/main/java/mezz/jei/api/recipe/VanillaRecipeCategoryUid.java b/src/main/java/mezz/jei/api/recipe/VanillaRecipeCategoryUid.java index 6cf7eac2a..c938dd218 100644 --- a/src/main/java/mezz/jei/api/recipe/VanillaRecipeCategoryUid.java +++ b/src/main/java/mezz/jei/api/recipe/VanillaRecipeCategoryUid.java @@ -1,5 +1,10 @@ package mezz.jei.api.recipe; -public enum VanillaRecipeCategoryUid implements IRecipeCategoryUid { - CRAFTING, FURNACE +/** + * List of vanilla recipe category UIDs, so that addons with their own vanilla recipe handlers can use them. + */ +public class VanillaRecipeCategoryUid { + public static final String CRAFTING = "crafting"; + public static final String SMELTING = "smelting"; + public static final String FUEL = "fuel"; } diff --git a/src/main/java/mezz/jei/gui/BasicRecipeTransferHelper.java b/src/main/java/mezz/jei/gui/BasicRecipeTransferHelper.java new file mode 100644 index 000000000..e3154ad65 --- /dev/null +++ b/src/main/java/mezz/jei/gui/BasicRecipeTransferHelper.java @@ -0,0 +1,57 @@ +package mezz.jei.gui; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.inventory.Container; +import net.minecraft.inventory.Slot; + +import mezz.jei.api.recipe.IRecipeTransferHelper; + +public class BasicRecipeTransferHelper implements IRecipeTransferHelper { + private final Class containerClass; + private final String recipeCategoryUid; + private final int recipeSlotStart; + private final int recipeSlotCount; + private final int inventorySlotStart; + private final int inventorySlotCount; + + public BasicRecipeTransferHelper(Class containerClass, String recipeCategoryUid, int recipeSlotStart, int recipeSlotCount, int inventorySlotStart, int inventorySlotCount) { + this.containerClass = containerClass; + this.recipeCategoryUid = recipeCategoryUid; + this.recipeSlotStart = recipeSlotStart; + this.recipeSlotCount = recipeSlotCount; + this.inventorySlotStart = inventorySlotStart; + this.inventorySlotCount = inventorySlotCount; + } + + @Override + public Class getContainerClass() { + return containerClass; + } + + @Override + public String getRecipeCategoryUid() { + return recipeCategoryUid; + } + + @Override + public List getRecipeSlots(Container container) { + List slots = new ArrayList<>(); + for (int i = recipeSlotStart; i < recipeSlotStart + recipeSlotCount; i++) { + Slot slot = container.getSlot(i); + slots.add(slot); + } + return slots; + } + + @Override + public List getInventorySlots(Container container) { + List slots = new ArrayList<>(); + for (int i = inventorySlotStart; i < inventorySlotStart + inventorySlotCount; i++) { + Slot slot = container.getSlot(i); + slots.add(slot); + } + return slots; + } +} diff --git a/src/main/java/mezz/jei/gui/CraftingGridHelper.java b/src/main/java/mezz/jei/gui/CraftingGridHelper.java index 0d295fe0b..305a92197 100644 --- a/src/main/java/mezz/jei/gui/CraftingGridHelper.java +++ b/src/main/java/mezz/jei/gui/CraftingGridHelper.java @@ -2,7 +2,6 @@ import javax.annotation.Nonnull; import java.util.Collection; -import java.util.Collections; import java.util.List; import net.minecraft.item.ItemStack; @@ -39,39 +38,39 @@ public void setInput(@Nonnull IGuiItemStackGroup guiItemStacks, @Nonnull List in public void setInput(@Nonnull IGuiItemStackGroup guiItemStacks, @Nonnull List input, int width, int height) { for (int i = 0; i < input.size(); i++) { Object recipeItem = input.get(i); - int index; - if (width == 1) { - if (height == 3) { - index = (i * 3) + 1; - } else if (height == 2) { - index = (i * 3) + 4; - } else { - index = 4; - } - } else if (height == 1) { - index = i + 6; - } else if (width == 2) { - index = i; - if (i > 1) { - index++; - if (i > 3) { - index++; - } - } + int index = getCraftingIndex(i, width, height); + + List itemStacks = StackUtil.toItemStackList(recipeItem); + setInput(guiItemStacks, index, itemStacks); + } + } + + private int getCraftingIndex(int i, int width, int height) { + int index; + if (width == 1) { + if (height == 3) { + index = (i * 3) + 1; } else if (height == 2) { - index = i + 3; + index = (i * 3) + 4; } else { - index = i; + index = 4; } - - if (recipeItem instanceof ItemStack) { - List itemStacks = Collections.singletonList((ItemStack) recipeItem); - setInput(guiItemStacks, index, itemStacks); - } else if (recipeItem instanceof Iterable) { - List itemStacks = StackUtil.toItemStackList((Iterable) recipeItem); - setInput(guiItemStacks, index, itemStacks); + } else if (height == 1) { + index = i + 6; + } else if (width == 2) { + index = i; + if (i > 1) { + index++; + if (i > 3) { + index++; + } } + } else if (height == 2) { + index = i + 3; + } else { + index = i; } + return index; } @Override diff --git a/src/main/java/mezz/jei/gui/GuiHelper.java b/src/main/java/mezz/jei/gui/GuiHelper.java index 0715af179..b14fb2e22 100644 --- a/src/main/java/mezz/jei/gui/GuiHelper.java +++ b/src/main/java/mezz/jei/gui/GuiHelper.java @@ -2,11 +2,13 @@ import javax.annotation.Nonnull; +import net.minecraft.inventory.Container; import net.minecraft.util.ResourceLocation; import mezz.jei.api.IGuiHelper; import mezz.jei.api.gui.ICraftingGridHelper; import mezz.jei.api.gui.IDrawable; +import mezz.jei.api.recipe.IRecipeTransferHelper; public class GuiHelper implements IGuiHelper { @@ -22,4 +24,9 @@ public ICraftingGridHelper createCraftingGridHelper(int craftInputSlot1, int cra return new CraftingGridHelper(craftInputSlot1, craftOutputSlot); } + @Nonnull + @Override + public IRecipeTransferHelper createRecipeTransferHelper(Class containerClass, String recipeCategoryUid, int recipeSlotStart, int recipeSlotCount, int inventorySlotStart, int inventorySlotCount) { + return new BasicRecipeTransferHelper(containerClass, recipeCategoryUid, recipeSlotStart, recipeSlotCount, inventorySlotStart, inventorySlotCount); + } } diff --git a/src/main/java/mezz/jei/gui/IRecipeGuiLogic.java b/src/main/java/mezz/jei/gui/IRecipeGuiLogic.java index 21e9b9ab9..e398c0ef8 100644 --- a/src/main/java/mezz/jei/gui/IRecipeGuiLogic.java +++ b/src/main/java/mezz/jei/gui/IRecipeGuiLogic.java @@ -34,5 +34,5 @@ enum Mode { IRecipeCategory getRecipeCategory(); @Nonnull - List getRecipeWidgets(); + List getRecipeWidgets(int posX, int posY, int spacingY); } diff --git a/src/main/java/mezz/jei/gui/ItemListOverlay.java b/src/main/java/mezz/jei/gui/ItemListOverlay.java index d42f42b11..bfd5876dd 100644 --- a/src/main/java/mezz/jei/gui/ItemListOverlay.java +++ b/src/main/java/mezz/jei/gui/ItemListOverlay.java @@ -112,7 +112,7 @@ private int createItemButtons() { maxX = x; } - guiItemStacks.add(GuiItemStackGroup.createGuiItemStack(x, y, itemStackPadding)); + guiItemStacks.add(GuiItemStackGroup.createGuiItemStack(false, x, y, itemStackPadding)); x += itemStackWidth; if (x + itemStackWidth + borderPadding > width) { diff --git a/src/main/java/mezz/jei/gui/RecipeGuiLogic.java b/src/main/java/mezz/jei/gui/RecipeGuiLogic.java index b7e55e790..46561cbb8 100644 --- a/src/main/java/mezz/jei/gui/RecipeGuiLogic.java +++ b/src/main/java/mezz/jei/gui/RecipeGuiLogic.java @@ -97,14 +97,15 @@ public IRecipeCategory getRecipeCategory() { @Override @Nonnull - public List getRecipeWidgets() { - List recipeWidgets = new ArrayList<>(); + public List getRecipeWidgets(int posX, int posY, int spacingY) { + List recipeWidgets = new ArrayList<>(); IRecipeCategory recipeCategory = getRecipeCategory(); if (recipeCategory == null) { return recipeWidgets; } + int recipeWidgetIndex = 0; for (int recipeIndex = pageIndex * recipesPerPage; recipeIndex < recipes.size() && recipeWidgets.size() < recipesPerPage; recipeIndex++) { Object recipe = recipes.get(recipeIndex); IRecipeHandler recipeHandler = JEIManager.recipeRegistry.getRecipeHandler(recipe.getClass()); @@ -113,12 +114,13 @@ public List getRecipeWidgets() { continue; } - RecipeWidget recipeWidget = new RecipeWidget(recipeCategory); - @SuppressWarnings("unchecked") IRecipeWrapper recipeWrapper = recipeHandler.getRecipeWrapper(recipe); - recipeWidget.setRecipe(recipeWrapper, focus); + + RecipeLayout recipeWidget = new RecipeLayout(recipeWidgetIndex++, posX, posY, recipeCategory, recipeWrapper, focus); recipeWidgets.add(recipeWidget); + + posY += spacingY; } return recipeWidgets; diff --git a/src/main/java/mezz/jei/gui/RecipeLayout.java b/src/main/java/mezz/jei/gui/RecipeLayout.java new file mode 100644 index 000000000..342f3d477 --- /dev/null +++ b/src/main/java/mezz/jei/gui/RecipeLayout.java @@ -0,0 +1,106 @@ +package mezz.jei.gui; + +import javax.annotation.Nonnull; + +import net.minecraft.client.Minecraft; + +import net.minecraftforge.fml.client.config.GuiButtonExt; + +import org.lwjgl.opengl.GL11; + +import mezz.jei.api.gui.IGuiFluidStackGroup; +import mezz.jei.api.gui.IRecipeLayout; +import mezz.jei.api.recipe.IRecipeCategory; +import mezz.jei.api.recipe.IRecipeWrapper; +import mezz.jei.gui.ingredients.GuiFluidStackGroup; +import mezz.jei.gui.ingredients.GuiItemStackGroup; + +public class RecipeLayout implements IRecipeLayout { + public static final int recipeTransferButtonIndex = 100; + + @Nonnull + private final IRecipeCategory recipeCategory; + @Nonnull + private final GuiItemStackGroup guiItemStackGroup; + @Nonnull + private final GuiFluidStackGroup guiFluidStackGroup; + @Nonnull + private final GuiButtonExt recipeTransferButton; + @Nonnull + private final IRecipeWrapper recipeWrapper; + + private final int posX; + private final int posY; + + public RecipeLayout(int index, int posX, int posY, @Nonnull IRecipeCategory recipeCategory, @Nonnull IRecipeWrapper recipeWrapper, @Nonnull Focus focus) { + this.recipeCategory = recipeCategory; + this.guiItemStackGroup = new GuiItemStackGroup(); + this.guiFluidStackGroup = new GuiFluidStackGroup(); + this.recipeTransferButton = new GuiButtonExt(recipeTransferButtonIndex + index, 0, 0, 12, 12, "+"); + this.recipeTransferButton.visible = false; + this.posX = posX; + this.posY = posY; + + this.recipeCategory.init(this); + + this.recipeWrapper = recipeWrapper; + this.guiItemStackGroup.setFocus(focus); + this.recipeCategory.setRecipe(this, recipeWrapper); + } + + public void draw(@Nonnull Minecraft minecraft, int mouseX, int mouseY) { + GL11.glPushMatrix(); + GL11.glTranslatef(posX, posY, 0.0F); + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + GL11.glDisable(GL11.GL_LIGHTING); + + recipeCategory.getBackground().draw(minecraft); + + GL11.glTranslatef(-posX, -posY, 0.0F); + recipeTransferButton.drawButton(minecraft, mouseX, mouseY); + GL11.glTranslatef(posX, posY, 0.0F); + + recipeWrapper.drawInfo(minecraft); + guiItemStackGroup.draw(minecraft, mouseX - posX, mouseY - posY); + + GL11.glPopMatrix(); + } + + public Focus getFocusUnderMouse(int mouseX, int mouseY) { + return guiItemStackGroup.getFocusUnderMouse(mouseX - posX, mouseY - posY); + } + + @Override + @Nonnull + public GuiItemStackGroup getItemStacks() { + return guiItemStackGroup; + } + + @Override + @Nonnull + public IGuiFluidStackGroup getFluidStacks() { + return guiFluidStackGroup; + } + + @Override + public void setRecipeTransferButton(int posX, int posY) { + recipeTransferButton.xPosition = posX + this.posX; + recipeTransferButton.yPosition = posY + this.posY; + recipeTransferButton.visible = true; + } + + @Nonnull + public GuiButtonExt getRecipeTransferButton() { + return recipeTransferButton; + } + + @Nonnull + public IRecipeWrapper getRecipeWrapper() { + return recipeWrapper; + } + + @Nonnull + public IRecipeCategory getRecipeCategory() { + return recipeCategory; + } +} diff --git a/src/main/java/mezz/jei/gui/RecipeWidget.java b/src/main/java/mezz/jei/gui/RecipeWidget.java deleted file mode 100644 index 655efed8b..000000000 --- a/src/main/java/mezz/jei/gui/RecipeWidget.java +++ /dev/null @@ -1,65 +0,0 @@ -package mezz.jei.gui; - -import javax.annotation.Nonnull; - -import net.minecraft.client.Minecraft; - -import org.lwjgl.opengl.GL11; - -import mezz.jei.api.recipe.IRecipeCategory; -import mezz.jei.api.recipe.IRecipeWrapper; -import mezz.jei.gui.ingredients.GuiFluidStackGroup; -import mezz.jei.gui.ingredients.GuiItemStackGroup; - -public class RecipeWidget { - - @Nonnull - private final IRecipeCategory recipeCategory; - private final GuiItemStackGroup guiItemStackGroup; - private final GuiFluidStackGroup guiFluidStackGroup; - - private IRecipeWrapper recipeWrapper; - private int posX; - private int posY; - - public RecipeWidget(@Nonnull IRecipeCategory recipeCategory) { - this.recipeCategory = recipeCategory; - this.guiItemStackGroup = new GuiItemStackGroup(); - this.guiFluidStackGroup = new GuiFluidStackGroup(); - this.recipeCategory.init(guiItemStackGroup, guiFluidStackGroup); - } - - public void setPosition(int posX, int posY) { - this.posX = posX; - this.posY = posY; - } - - public void setRecipe(@Nonnull IRecipeWrapper recipeWrapper, @Nonnull Focus focus) { - this.recipeWrapper = recipeWrapper; - - guiItemStackGroup.clear(); - guiItemStackGroup.setFocus(focus); - recipeCategory.setRecipe(guiItemStackGroup, guiFluidStackGroup, recipeWrapper); - } - - public void draw(@Nonnull Minecraft minecraft, int mouseX, int mouseY) { - if (recipeWrapper == null) { - return; - } - - GL11.glPushMatrix(); - GL11.glTranslatef(posX, posY, 0.0F); - GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); - GL11.glDisable(GL11.GL_LIGHTING); - - recipeCategory.getBackground().draw(minecraft); - recipeWrapper.drawInfo(minecraft); - guiItemStackGroup.draw(minecraft, mouseX - posX, mouseY - posY); - - GL11.glPopMatrix(); - } - - public Focus getFocusUnderMouse(int mouseX, int mouseY) { - return guiItemStackGroup.getFocusUnderMouse(mouseX - posX, mouseY - posY); - } -} diff --git a/src/main/java/mezz/jei/gui/RecipesGui.java b/src/main/java/mezz/jei/gui/RecipesGui.java index a6cfb9396..e67e0adcb 100644 --- a/src/main/java/mezz/jei/gui/RecipesGui.java +++ b/src/main/java/mezz/jei/gui/RecipesGui.java @@ -10,6 +10,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiScreen; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.ResourceLocation; import net.minecraftforge.fml.client.FMLClientHandler; @@ -23,6 +24,7 @@ import mezz.jei.input.IMouseHandler; import mezz.jei.input.IShowsRecipeFocuses; import mezz.jei.util.Log; +import mezz.jei.util.RecipeTransferUtil; import mezz.jei.util.StringUtil; public class RecipesGui extends GuiScreen implements IShowsRecipeFocuses, IMouseHandler { @@ -36,9 +38,9 @@ public class RecipesGui extends GuiScreen implements IShowsRecipeFocuses, IMouse /* Internal logic for the gui, handles finding recipes */ private final IRecipeGuiLogic logic = new RecipeGuiLogic(); - /* List of RecipeWidget to display */ + /* List of RecipeLayout to display */ @Nonnull - private final List recipeWidgets = new ArrayList<>(); + private final List recipeLayouts = new ArrayList<>(); private String pageString; private String title; @@ -126,7 +128,7 @@ public Focus getFocusUnderMouse(int mouseX, int mouseY) { if (!isMouseOver(mouseX, mouseY)) { return null; } - for (RecipeWidget recipeWidget : recipeWidgets) { + for (RecipeLayout recipeWidget : recipeLayouts) { Focus focus = recipeWidget.getFocusUnderMouse(mouseX, mouseY); if (focus != null) { return focus; @@ -135,18 +137,23 @@ public Focus getFocusUnderMouse(int mouseX, int mouseY) { return null; } + // workaround to see if a button was clicked + private boolean guiActionPerformed = false; + @Override public boolean handleMouseClicked(int mouseX, int mouseY, int mouseButton) { if (!isMouseOver(mouseX, mouseY)) { return false; } + guiActionPerformed = false; + try { handleMouseInput(); } catch (IOException e) { Log.error("IOException on mouse click.", e); } - return false; + return guiActionPerformed; } @Override @@ -198,18 +205,31 @@ public void showUses(@Nonnull Focus focus) { @Override protected void actionPerformed(@Nonnull GuiButton guibutton) { + boolean updateLayout = true; + if (guibutton.id == nextPage.id) { logic.nextPage(); - updateLayout(); } else if (guibutton.id == previousPage.id) { logic.previousPage(); - updateLayout(); } else if (guibutton.id == nextRecipeCategory.id) { logic.nextRecipeCategory(); - updateLayout(); } else if (guibutton.id == previousRecipeCategory.id) { logic.previousRecipeCategory(); + } else if (guibutton.id >= RecipeLayout.recipeTransferButtonIndex) { + int recipeIndex = guibutton.id - RecipeLayout.recipeTransferButtonIndex; + RecipeLayout recipeLayout = recipeLayouts.get(recipeIndex); + if (RecipeTransferUtil.transferRecipe(recipeLayout, Minecraft.getMinecraft().thePlayer)) { + close(); + guiActionPerformed = true; + updateLayout = false; + } + } else { + updateLayout = false; + } + + if (updateLayout) { updateLayout(); + guiActionPerformed = true; } } @@ -229,15 +249,13 @@ private void updateLayout() { title = recipeCategory.getTitle(); - final int posX = guiLeft + recipeXOffset; + int posX = guiLeft + recipeXOffset; int posY = guiTop + headerHeight + recipeSpacing; + int spacingY = recipeBackground.getHeight() + recipeSpacing; - recipeWidgets.clear(); - recipeWidgets.addAll(logic.getRecipeWidgets()); - for (RecipeWidget recipeWidget : recipeWidgets) { - recipeWidget.setPosition(posX, posY); - posY += recipeBackground.getHeight() + recipeSpacing; - } + recipeLayouts.clear(); + recipeLayouts.addAll(logic.getRecipeWidgets(posX, posY, spacingY)); + addRecipeTransferButtons(recipeLayouts); nextPage.enabled = previousPage.enabled = logic.hasMultiplePages(); nextRecipeCategory.enabled = previousRecipeCategory.enabled = logic.hasMultipleCategories(); @@ -245,6 +263,21 @@ private void updateLayout() { pageString = logic.getPageString(); } + @SuppressWarnings("unchecked") + private void addRecipeTransferButtons(List recipeLayouts) { + buttonList.clear(); + addButtons(); + + EntityPlayer player = Minecraft.getMinecraft().thePlayer; + + for (RecipeLayout recipeLayout : recipeLayouts) { + GuiButtonExt button = recipeLayout.getRecipeTransferButton(); + button.visible = RecipeTransferUtil.hasTransferHelper(recipeLayout, player); + button.enabled = RecipeTransferUtil.canTransferRecipe(recipeLayout, player); + buttonList.add(button); + } + } + public void draw(int mouseX, int mouseY) { Minecraft minecraft = Minecraft.getMinecraft(); @@ -268,8 +301,8 @@ public void draw(int mouseX, int mouseY) { } GL11.glPopMatrix(); - RecipeWidget hovered = null; - for (RecipeWidget recipeWidget : recipeWidgets) { + RecipeLayout hovered = null; + for (RecipeLayout recipeWidget : recipeLayouts) { if (recipeWidget.getFocusUnderMouse(mouseX, mouseY) != null) { hovered = recipeWidget; } else { diff --git a/src/main/java/mezz/jei/gui/ingredients/GuiFluidStackGroup.java b/src/main/java/mezz/jei/gui/ingredients/GuiFluidStackGroup.java index 1f554411a..3c31b3320 100644 --- a/src/main/java/mezz/jei/gui/ingredients/GuiFluidStackGroup.java +++ b/src/main/java/mezz/jei/gui/ingredients/GuiFluidStackGroup.java @@ -8,9 +8,9 @@ public class GuiFluidStackGroup extends GuiIngredientGroup guiIngredient = new GuiIngredient<>(renderer, helper, xPosition, yPosition, width, height, 0); - guiIngredients.put(index, guiIngredient); + GuiIngredient guiIngredient = new GuiIngredient<>(renderer, helper, input, xPosition, yPosition, width, height, 0); + guiIngredients.put(slotIndex, guiIngredient); } } diff --git a/src/main/java/mezz/jei/gui/ingredients/GuiIngredient.java b/src/main/java/mezz/jei/gui/ingredients/GuiIngredient.java index 32acc9acc..248eff9c9 100644 --- a/src/main/java/mezz/jei/gui/ingredients/GuiIngredient.java +++ b/src/main/java/mezz/jei/gui/ingredients/GuiIngredient.java @@ -21,6 +21,8 @@ import mezz.jei.util.Log; public class GuiIngredient extends Gui implements IGuiIngredient { + private final boolean input; + private final int xPosition; private final int yPosition; private final int width; @@ -39,10 +41,12 @@ public class GuiIngredient extends Gui implements IGuiIngredient { private boolean enabled; private boolean visible; - public GuiIngredient(@Nonnull IIngredientRenderer ingredientRenderer, @Nonnull IIngredientHelper ingredientHelper, int xPosition, int yPosition, int width, int height, int padding) { + public GuiIngredient(@Nonnull IIngredientRenderer ingredientRenderer, @Nonnull IIngredientHelper ingredientHelper, boolean input, int xPosition, int yPosition, int width, int height, int padding) { this.ingredientRenderer = ingredientRenderer; this.ingredientHelper = ingredientHelper; + this.input = input; + this.xPosition = xPosition; this.yPosition = yPosition; this.width = width; @@ -67,6 +71,12 @@ public T get() { return cycleTimer.getCycledItem(contained); } + @Nonnull + @Override + public List getAll() { + return contained; + } + @Override public void set(@Nonnull T contained, @Nonnull Focus focus) { set(Collections.singleton(contained), focus); @@ -134,4 +144,8 @@ private void drawTooltip(@Nonnull Minecraft minecraft, int mouseX, int mouseY, @ Log.error("Exception when rendering tooltip on {}.\n{}", value, e); } } + + public boolean isInput() { + return input; + } } diff --git a/src/main/java/mezz/jei/gui/ingredients/GuiIngredientGroup.java b/src/main/java/mezz/jei/gui/ingredients/GuiIngredientGroup.java index bc2e98b73..c7762beb5 100644 --- a/src/main/java/mezz/jei/gui/ingredients/GuiIngredientGroup.java +++ b/src/main/java/mezz/jei/gui/ingredients/GuiIngredientGroup.java @@ -26,19 +26,18 @@ public void setFocus(@Nonnull Focus focus) { } @Override - public void set(int index, @Nonnull Collection values) { - guiIngredients.get(index).set(values, focus); + public void set(int slotIndex, @Nonnull Collection values) { + guiIngredients.get(slotIndex).set(values, focus); } @Override - public void set(int index, @Nonnull V value) { - guiIngredients.get(index).set(value, focus); + public void set(int slotIndex, @Nonnull V value) { + guiIngredients.get(slotIndex).set(value, focus); } - public void clear() { - for (T guiWidget : guiIngredients.values()) { - guiWidget.clear(); - } + @Nonnull + public Map getGuiIngredients() { + return guiIngredients; } @Nullable diff --git a/src/main/java/mezz/jei/gui/ingredients/GuiItemStackGroup.java b/src/main/java/mezz/jei/gui/ingredients/GuiItemStackGroup.java index 7140dcc29..6fe05c290 100644 --- a/src/main/java/mezz/jei/gui/ingredients/GuiItemStackGroup.java +++ b/src/main/java/mezz/jei/gui/ingredients/GuiItemStackGroup.java @@ -1,8 +1,12 @@ package mezz.jei.gui.ingredients; +import javax.annotation.Nonnull; +import java.util.List; + import net.minecraft.item.ItemStack; import mezz.jei.api.gui.IGuiItemStackGroup; +import mezz.jei.util.StackUtil; public class GuiItemStackGroup extends GuiIngredientGroup> implements IGuiItemStackGroup { private static final int baseWidth = 16; @@ -18,17 +22,22 @@ public static int getHeight(int padding) { return baseHeight + (2 * padding); } - public static GuiIngredient createGuiItemStack(int xPosition, int yPosition, int padding) { - return new GuiIngredient<>(renderer, helper, xPosition, yPosition, getWidth(padding), getHeight(padding), padding); + public static GuiIngredient createGuiItemStack(boolean input, int xPosition, int yPosition, int padding) { + return new GuiIngredient<>(renderer, helper, input, xPosition, yPosition, getWidth(padding), getHeight(padding), padding); + } + + @Override + public void setFromRecipe(int slotIndex, @Nonnull List ingredients) { + set(slotIndex, StackUtil.toItemStackList(ingredients)); } @Override - public void init(int index, int xPosition, int yPosition) { - init(index, xPosition, yPosition, 1); + public void init(int slotIndex, boolean input, int xPosition, int yPosition) { + init(slotIndex, input, xPosition, yPosition, 1); } - public void init(int index, int xPosition, int yPosition, int padding) { - GuiIngredient guiIngredient = createGuiItemStack(xPosition, yPosition, padding); + public void init(int index, boolean input, int xPosition, int yPosition, int padding) { + GuiIngredient guiIngredient = createGuiItemStack(input, xPosition, yPosition, padding); guiIngredients.put(index, guiIngredient); } } diff --git a/src/main/java/mezz/jei/gui/ingredients/IGuiIngredient.java b/src/main/java/mezz/jei/gui/ingredients/IGuiIngredient.java index 66020a57b..03f79374b 100644 --- a/src/main/java/mezz/jei/gui/ingredients/IGuiIngredient.java +++ b/src/main/java/mezz/jei/gui/ingredients/IGuiIngredient.java @@ -3,6 +3,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collection; +import java.util.List; import net.minecraft.client.Minecraft; @@ -18,6 +19,9 @@ public interface IGuiIngredient { @Nullable T get(); + @Nonnull + List getAll(); + boolean isMouseOver(int mouseX, int mouseY); void draw(@Nonnull Minecraft minecraft); diff --git a/src/main/java/mezz/jei/input/IKeyable.java b/src/main/java/mezz/jei/input/IKeyable.java index 54cc891b3..0a90a0998 100644 --- a/src/main/java/mezz/jei/input/IKeyable.java +++ b/src/main/java/mezz/jei/input/IKeyable.java @@ -3,7 +3,7 @@ public interface IKeyable extends ICloseable { /** - * Returns true if all keyboard input should go to this IKeyboardable. + * Returns true if all keyboard input should go to this IKeyable. */ boolean hasKeyboardFocus(); diff --git a/src/main/java/mezz/jei/input/InputHandler.java b/src/main/java/mezz/jei/input/InputHandler.java index aca7862db..da090cbc9 100644 --- a/src/main/java/mezz/jei/input/InputHandler.java +++ b/src/main/java/mezz/jei/input/InputHandler.java @@ -99,7 +99,7 @@ private boolean handleMouseClick(int mouseButton, int mouseX, int mouseY) { } } - return recipesGui.isOpen(); + return false; } @Nullable diff --git a/src/main/java/mezz/jei/network/IPacketId.java b/src/main/java/mezz/jei/network/IPacketId.java new file mode 100644 index 000000000..caf7a31f4 --- /dev/null +++ b/src/main/java/mezz/jei/network/IPacketId.java @@ -0,0 +1,5 @@ +package mezz.jei.network; + +public interface IPacketId { + int ordinal(); +} diff --git a/src/main/java/mezz/jei/network/PacketHandler.java b/src/main/java/mezz/jei/network/PacketHandler.java new file mode 100644 index 000000000..e97baa7a3 --- /dev/null +++ b/src/main/java/mezz/jei/network/PacketHandler.java @@ -0,0 +1,95 @@ +package mezz.jei.network; + +import java.io.IOException; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.network.NetHandlerPlayServer; +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.IThreadListener; + +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.network.FMLEventChannel; +import net.minecraftforge.fml.common.network.FMLNetworkEvent; +import net.minecraftforge.fml.common.network.NetworkRegistry; +import net.minecraftforge.fml.common.network.internal.FMLProxyPacket; + +import mezz.jei.network.packets.PacketJEI; +import mezz.jei.network.packets.PacketRecipeTransfer; +import mezz.jei.util.Log; + +public class PacketHandler { + public static final String channelId = "JEI"; + private final FMLEventChannel channel; + + public PacketHandler() { + channel = NetworkRegistry.INSTANCE.newEventDrivenChannel(channelId); + channel.register(this); + } + + @SubscribeEvent + public void onPacket(FMLNetworkEvent.ServerCustomPacketEvent event) { + PacketBuffer packetBuffer = new PacketBuffer(event.packet.payload()); + EntityPlayerMP player = ((NetHandlerPlayServer) event.handler).playerEntity; + + try { + byte packetIdOrdinal = packetBuffer.readByte(); + PacketIdServer packetId = PacketIdServer.VALUES[packetIdOrdinal]; + PacketJEI packet; + + switch (packetId) { + case RECIPE_TRANSFER: { + packet = new PacketRecipeTransfer(); + break; + } + default: { + return; + } + } + + checkThreadAndEnqueue(packet, packetBuffer, player, player.getServerForPlayer()); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + /* + @SubscribeEvent + public void onPacket(FMLNetworkEvent.ClientCustomPacketEvent event) { + PacketBuffer packetBuffer = new PacketBuffer(event.packet.payload()); + Minecraft minecraft = Minecraft.getMinecraft(); + EntityPlayer player = minecraft.thePlayer; + PacketJEI packet; + + try { + byte packetIdOrdinal = packetBuffer.readByte(); + PacketIdClient packetId = PacketIdClient.VALUES[packetIdOrdinal]; + switch (packetId) { + default: { + return; + } + } + + checkThreadAndEnqueue(packet, packetBuffer, player, minecraft); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + */ + + public void sendPacket(FMLProxyPacket packet, EntityPlayerMP player) { + channel.sendTo(packet, player); + } + + private static void checkThreadAndEnqueue(final PacketJEI packet, final PacketBuffer packetBuffer, final EntityPlayer player, IThreadListener threadListener) { + if (!threadListener.isCallingFromMinecraftThread()) { + threadListener.addScheduledTask(() -> { + try { + packet.readPacketData(packetBuffer, player); + } catch (IOException e) { + Log.error("Network Error: {}", e); + } + }); + } + } +} diff --git a/src/main/java/mezz/jei/network/PacketIdClient.java b/src/main/java/mezz/jei/network/PacketIdClient.java new file mode 100644 index 000000000..0b1c3fb9b --- /dev/null +++ b/src/main/java/mezz/jei/network/PacketIdClient.java @@ -0,0 +1,7 @@ +package mezz.jei.network; + +public enum PacketIdClient implements IPacketId { + INVALID; + + public static final PacketIdClient[] VALUES = values(); +} diff --git a/src/main/java/mezz/jei/network/PacketIdServer.java b/src/main/java/mezz/jei/network/PacketIdServer.java new file mode 100644 index 000000000..704538540 --- /dev/null +++ b/src/main/java/mezz/jei/network/PacketIdServer.java @@ -0,0 +1,7 @@ +package mezz.jei.network; + +public enum PacketIdServer implements IPacketId { + RECIPE_TRANSFER; + + public static final PacketIdServer[] VALUES = values(); +} diff --git a/src/main/java/mezz/jei/network/packets/PacketJEI.java b/src/main/java/mezz/jei/network/packets/PacketJEI.java new file mode 100644 index 000000000..90c2fa6bd --- /dev/null +++ b/src/main/java/mezz/jei/network/packets/PacketJEI.java @@ -0,0 +1,36 @@ +package mezz.jei.network.packets; + +import java.io.IOException; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.network.PacketBuffer; + +import net.minecraftforge.fml.common.network.internal.FMLProxyPacket; + +import io.netty.buffer.Unpooled; +import mezz.jei.network.IPacketId; +import mezz.jei.network.PacketHandler; +import mezz.jei.util.Log; + +public abstract class PacketJEI { + private final IPacketId id = getPacketId(); + + public final FMLProxyPacket getPacket() { + PacketBuffer packetBuffer = new PacketBuffer(Unpooled.buffer()); + + packetBuffer.writeByte(id.ordinal()); + try { + writePacketData(packetBuffer); + } catch (IOException e) { + Log.error("Network Error: {}", e); + } + + return new FMLProxyPacket(packetBuffer, PacketHandler.channelId); + } + + public abstract IPacketId getPacketId(); + + public abstract void readPacketData(PacketBuffer buf, EntityPlayer player) throws IOException; + + public abstract void writePacketData(PacketBuffer buf) throws IOException; +} diff --git a/src/main/java/mezz/jei/network/packets/PacketRecipeTransfer.java b/src/main/java/mezz/jei/network/packets/PacketRecipeTransfer.java new file mode 100644 index 000000000..7273ca978 --- /dev/null +++ b/src/main/java/mezz/jei/network/packets/PacketRecipeTransfer.java @@ -0,0 +1,84 @@ +package mezz.jei.network.packets; + +import javax.annotation.Nonnull; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketBuffer; + +import mezz.jei.network.IPacketId; +import mezz.jei.network.PacketIdServer; +import mezz.jei.util.RecipeTransferUtil; + +public class PacketRecipeTransfer extends PacketJEI { + + private Map recipeMap; + private Collection craftingSlots; + private Collection inventorySlots; + + public PacketRecipeTransfer() { + + } + + public PacketRecipeTransfer(@Nonnull Map recipeMap, @Nonnull Collection craftingSlots, @Nonnull Collection inventorySlots) { + this.recipeMap = recipeMap; + this.craftingSlots = craftingSlots; + this.inventorySlots = inventorySlots; + } + + @Override + public IPacketId getPacketId() { + return PacketIdServer.RECIPE_TRANSFER; + } + + @Override + public void readPacketData(PacketBuffer buf, EntityPlayer player) throws IOException { + int recipeMapSize = buf.readVarIntFromBuffer(); + recipeMap = new HashMap<>(recipeMapSize); + for (int i = 0; i < recipeMapSize; i++) { + int slotIndex = buf.readVarIntFromBuffer(); + ItemStack recipeItem = buf.readItemStackFromBuffer(); + recipeMap.put(slotIndex, recipeItem); + } + + int craftingSlotsSize = buf.readVarIntFromBuffer(); + craftingSlots = new ArrayList<>(craftingSlotsSize); + for (int i = 0; i < craftingSlotsSize; i++) { + int slotIndex = buf.readVarIntFromBuffer(); + craftingSlots.add(slotIndex); + } + + int inventorySlotsSize = buf.readVarIntFromBuffer(); + inventorySlots = new ArrayList<>(inventorySlotsSize); + for (int i = 0; i < inventorySlotsSize; i++) { + int slotIndex = buf.readVarIntFromBuffer(); + inventorySlots.add(slotIndex); + } + + RecipeTransferUtil.setItems(player, recipeMap, craftingSlots, inventorySlots); + } + + @Override + public void writePacketData(PacketBuffer buf) throws IOException { + buf.writeVarIntToBuffer(recipeMap.size()); + for (Map.Entry recipeMapEntry : recipeMap.entrySet()) { + buf.writeVarIntToBuffer(recipeMapEntry.getKey()); + buf.writeItemStackToBuffer(recipeMapEntry.getValue()); + } + + buf.writeVarIntToBuffer(craftingSlots.size()); + for (Integer craftingSlot : craftingSlots) { + buf.writeVarIntToBuffer(craftingSlot); + } + + buf.writeVarIntToBuffer(inventorySlots.size()); + for (Integer inventorySlot : inventorySlots) { + buf.writeVarIntToBuffer(inventorySlot); + } + } +} diff --git a/src/main/java/mezz/jei/plugins/vanilla/VanillaPlugin.java b/src/main/java/mezz/jei/plugins/vanilla/VanillaPlugin.java index 700035227..271158efd 100644 --- a/src/main/java/mezz/jei/plugins/vanilla/VanillaPlugin.java +++ b/src/main/java/mezz/jei/plugins/vanilla/VanillaPlugin.java @@ -1,12 +1,20 @@ package mezz.jei.plugins.vanilla; +import javax.annotation.Nonnull; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import net.minecraft.inventory.ContainerFurnace; +import net.minecraft.inventory.ContainerWorkbench; + +import mezz.jei.api.IGuiHelper; import mezz.jei.api.IModPlugin; +import mezz.jei.api.JEIManager; import mezz.jei.api.recipe.IRecipeCategory; import mezz.jei.api.recipe.IRecipeHandler; +import mezz.jei.api.recipe.IRecipeTransferHelper; +import mezz.jei.api.recipe.VanillaRecipeCategoryUid; import mezz.jei.plugins.vanilla.crafting.CraftingRecipeCategory; import mezz.jei.plugins.vanilla.crafting.CraftingRecipeMaker; import mezz.jei.plugins.vanilla.crafting.ShapedOreRecipeHandler; @@ -15,7 +23,8 @@ import mezz.jei.plugins.vanilla.crafting.ShapelessRecipesHandler; import mezz.jei.plugins.vanilla.furnace.FuelRecipeHandler; import mezz.jei.plugins.vanilla.furnace.FuelRecipeMaker; -import mezz.jei.plugins.vanilla.furnace.FurnaceRecipeCategory; +import mezz.jei.plugins.vanilla.furnace.FurnaceFuelCategory; +import mezz.jei.plugins.vanilla.furnace.FurnaceSmeltingCategory; import mezz.jei.plugins.vanilla.furnace.SmeltingRecipeHandler; import mezz.jei.plugins.vanilla.furnace.SmeltingRecipeMaker; @@ -27,14 +36,17 @@ public boolean isModLoaded() { } @Override + @Nonnull public Iterable getRecipeCategories() { return Arrays.asList( new CraftingRecipeCategory(), - new FurnaceRecipeCategory() + new FurnaceFuelCategory(), + new FurnaceSmeltingCategory() ); } @Override + @Nonnull public Iterable getRecipeHandlers() { return Arrays.asList( new ShapedOreRecipeHandler(), @@ -47,6 +59,18 @@ public Iterable getRecipeHandlers() { } @Override + @Nonnull + public Iterable getRecipeTransferHelpers() { + IGuiHelper guiHelper = JEIManager.guiHelper; + return Arrays.asList( + guiHelper.createRecipeTransferHelper(ContainerWorkbench.class, VanillaRecipeCategoryUid.CRAFTING, 1, 9, 10, 36), + guiHelper.createRecipeTransferHelper(ContainerFurnace.class, VanillaRecipeCategoryUid.SMELTING, 0, 1, 1, 36), + guiHelper.createRecipeTransferHelper(ContainerFurnace.class, VanillaRecipeCategoryUid.FUEL, 1, 1, 1, 36) + ); + } + + @Override + @Nonnull public Iterable getRecipes() { List recipes = new ArrayList<>(); diff --git a/src/main/java/mezz/jei/plugins/vanilla/crafting/CraftingRecipeCategory.java b/src/main/java/mezz/jei/plugins/vanilla/crafting/CraftingRecipeCategory.java index 1f5b8d1a4..4aad35fcf 100644 --- a/src/main/java/mezz/jei/plugins/vanilla/crafting/CraftingRecipeCategory.java +++ b/src/main/java/mezz/jei/plugins/vanilla/crafting/CraftingRecipeCategory.java @@ -8,10 +8,9 @@ import mezz.jei.api.JEIManager; import mezz.jei.api.gui.ICraftingGridHelper; import mezz.jei.api.gui.IDrawable; -import mezz.jei.api.gui.IGuiFluidStackGroup; import mezz.jei.api.gui.IGuiItemStackGroup; +import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.recipe.IRecipeCategory; -import mezz.jei.api.recipe.IRecipeCategoryUid; import mezz.jei.api.recipe.IRecipeWrapper; import mezz.jei.api.recipe.VanillaRecipeCategoryUid; import mezz.jei.api.recipe.wrapper.ICraftingRecipeWrapper; @@ -39,7 +38,7 @@ public CraftingRecipeCategory() { @Override @Nonnull - public IRecipeCategoryUid getUid() { + public String getUid() { return VanillaRecipeCategoryUid.CRAFTING; } @@ -56,19 +55,25 @@ public IDrawable getBackground() { } @Override - public void init(@Nonnull IGuiItemStackGroup guiItemStacks, @Nonnull IGuiFluidStackGroup guiFluidTanks) { - guiItemStacks.init(craftOutputSlot, 94, 18); + public void init(@Nonnull IRecipeLayout recipeLayout) { + recipeLayout.setRecipeTransferButton(56, 0); + + IGuiItemStackGroup guiItemStacks = recipeLayout.getItemStacks(); + + guiItemStacks.init(craftOutputSlot, false, 94, 18); for (int y = 0; y < 3; ++y) { for (int x = 0; x < 3; ++x) { int index = craftInputSlot1 + x + (y * 3); - guiItemStacks.init(index, x * 18, y * 18); + guiItemStacks.init(index, true, x * 18, y * 18); } } } @Override - public void setRecipe(@Nonnull IGuiItemStackGroup guiItemStacks, @Nonnull IGuiFluidStackGroup guiFluidTanks, @Nonnull IRecipeWrapper recipeWrapper) { + public void setRecipe(@Nonnull IRecipeLayout recipeLayout, @Nonnull IRecipeWrapper recipeWrapper) { + IGuiItemStackGroup guiItemStacks = recipeLayout.getItemStacks(); + if (recipeWrapper instanceof IShapedCraftingRecipeWrapper) { IShapedCraftingRecipeWrapper wrapper = (IShapedCraftingRecipeWrapper) recipeWrapper; craftingGridHelper.setInput(guiItemStacks, wrapper.getInputs(), wrapper.getWidth(), wrapper.getHeight()); diff --git a/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapedOreRecipeHandler.java b/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapedOreRecipeHandler.java index 744a5b5e7..dff329c43 100644 --- a/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapedOreRecipeHandler.java +++ b/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapedOreRecipeHandler.java @@ -5,7 +5,6 @@ import net.minecraftforge.oredict.ShapedOreRecipe; -import mezz.jei.api.recipe.IRecipeCategoryUid; import mezz.jei.api.recipe.IRecipeHandler; import mezz.jei.api.recipe.IRecipeWrapper; import mezz.jei.api.recipe.VanillaRecipeCategoryUid; @@ -20,7 +19,7 @@ public Class getRecipeClass() { @Nonnull @Override - public IRecipeCategoryUid getRecipeCategoryUid() { + public String getRecipeCategoryUid() { return VanillaRecipeCategoryUid.CRAFTING; } diff --git a/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapedOreRecipeWrapper.java b/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapedOreRecipeWrapper.java index f29aec282..d7a24ad06 100644 --- a/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapedOreRecipeWrapper.java +++ b/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapedOreRecipeWrapper.java @@ -52,6 +52,11 @@ public void drawInfo(@Nonnull Minecraft minecraft) { } + @Override + public boolean usesOreDictionaryComparison() { + return true; + } + @Override public int getWidth() { return width; diff --git a/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapedRecipesHandler.java b/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapedRecipesHandler.java index 458ef3bb0..a4b293450 100644 --- a/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapedRecipesHandler.java +++ b/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapedRecipesHandler.java @@ -5,7 +5,6 @@ import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.ShapedRecipes; -import mezz.jei.api.recipe.IRecipeCategoryUid; import mezz.jei.api.recipe.IRecipeHandler; import mezz.jei.api.recipe.IRecipeWrapper; import mezz.jei.api.recipe.VanillaRecipeCategoryUid; @@ -20,7 +19,7 @@ public Class getRecipeClass() { @Nonnull @Override - public IRecipeCategoryUid getRecipeCategoryUid() { + public String getRecipeCategoryUid() { return VanillaRecipeCategoryUid.CRAFTING; } diff --git a/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapedRecipesWrapper.java b/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapedRecipesWrapper.java index 048782dab..5d491c1b8 100644 --- a/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapedRecipesWrapper.java +++ b/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapedRecipesWrapper.java @@ -53,4 +53,8 @@ public int getHeight() { return recipe.recipeHeight; } + @Override + public boolean usesOreDictionaryComparison() { + return false; + } } diff --git a/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapelessOreRecipeHandler.java b/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapelessOreRecipeHandler.java index 54bc21e2d..62c1def7f 100644 --- a/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapelessOreRecipeHandler.java +++ b/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapelessOreRecipeHandler.java @@ -5,7 +5,6 @@ import net.minecraftforge.oredict.ShapelessOreRecipe; -import mezz.jei.api.recipe.IRecipeCategoryUid; import mezz.jei.api.recipe.IRecipeHandler; import mezz.jei.api.recipe.IRecipeWrapper; import mezz.jei.api.recipe.VanillaRecipeCategoryUid; @@ -20,7 +19,7 @@ public Class getRecipeClass() { @Nonnull @Override - public IRecipeCategoryUid getRecipeCategoryUid() { + public String getRecipeCategoryUid() { return VanillaRecipeCategoryUid.CRAFTING; } diff --git a/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapelessOreRecipeWrapper.java b/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapelessOreRecipeWrapper.java index 3f8539707..a04597ca7 100644 --- a/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapelessOreRecipeWrapper.java +++ b/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapelessOreRecipeWrapper.java @@ -46,4 +46,9 @@ public void drawInfo(@Nonnull Minecraft minecraft) { } + @Override + public boolean usesOreDictionaryComparison() { + return true; + } + } diff --git a/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapelessRecipesHandler.java b/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapelessRecipesHandler.java index b8e8e4a38..34fd1af45 100644 --- a/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapelessRecipesHandler.java +++ b/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapelessRecipesHandler.java @@ -5,7 +5,6 @@ import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.ShapelessRecipes; -import mezz.jei.api.recipe.IRecipeCategoryUid; import mezz.jei.api.recipe.IRecipeHandler; import mezz.jei.api.recipe.IRecipeWrapper; import mezz.jei.api.recipe.VanillaRecipeCategoryUid; @@ -20,7 +19,7 @@ public Class getRecipeClass() { @Nonnull @Override - public IRecipeCategoryUid getRecipeCategoryUid() { + public String getRecipeCategoryUid() { return VanillaRecipeCategoryUid.CRAFTING; } diff --git a/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapelessRecipesWrapper.java b/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapelessRecipesWrapper.java index 557445dbe..a5a5d9f41 100644 --- a/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapelessRecipesWrapper.java +++ b/src/main/java/mezz/jei/plugins/vanilla/crafting/ShapelessRecipesWrapper.java @@ -44,4 +44,9 @@ public List getOutputs() { public void drawInfo(@Nonnull Minecraft minecraft) { } + + @Override + public boolean usesOreDictionaryComparison() { + return false; + } } diff --git a/src/main/java/mezz/jei/plugins/vanilla/furnace/FuelRecipe.java b/src/main/java/mezz/jei/plugins/vanilla/furnace/FuelRecipe.java index a8c1dda39..ea409df36 100644 --- a/src/main/java/mezz/jei/plugins/vanilla/furnace/FuelRecipe.java +++ b/src/main/java/mezz/jei/plugins/vanilla/furnace/FuelRecipe.java @@ -42,4 +42,8 @@ public void drawInfo(@Nonnull Minecraft minecraft) { minecraft.fontRendererObj.drawString(burnTimeString, 20, 45, Color.gray.getRGB()); } + @Override + public boolean usesOreDictionaryComparison() { + return false; + } } diff --git a/src/main/java/mezz/jei/plugins/vanilla/furnace/FuelRecipeHandler.java b/src/main/java/mezz/jei/plugins/vanilla/furnace/FuelRecipeHandler.java index e2ef8eb6f..ab73fb29f 100644 --- a/src/main/java/mezz/jei/plugins/vanilla/furnace/FuelRecipeHandler.java +++ b/src/main/java/mezz/jei/plugins/vanilla/furnace/FuelRecipeHandler.java @@ -2,7 +2,6 @@ import javax.annotation.Nonnull; -import mezz.jei.api.recipe.IRecipeCategoryUid; import mezz.jei.api.recipe.IRecipeHandler; import mezz.jei.api.recipe.IRecipeWrapper; import mezz.jei.api.recipe.VanillaRecipeCategoryUid; @@ -16,8 +15,8 @@ public Class getRecipeClass() { @Nonnull @Override - public IRecipeCategoryUid getRecipeCategoryUid() { - return VanillaRecipeCategoryUid.FURNACE; + public String getRecipeCategoryUid() { + return VanillaRecipeCategoryUid.FUEL; } @Override diff --git a/src/main/java/mezz/jei/plugins/vanilla/furnace/FurnaceFuelCategory.java b/src/main/java/mezz/jei/plugins/vanilla/furnace/FurnaceFuelCategory.java new file mode 100644 index 000000000..691b5986f --- /dev/null +++ b/src/main/java/mezz/jei/plugins/vanilla/furnace/FurnaceFuelCategory.java @@ -0,0 +1,26 @@ +package mezz.jei.plugins.vanilla.furnace; + +import javax.annotation.Nonnull; + +import mezz.jei.api.gui.IGuiItemStackGroup; +import mezz.jei.api.gui.IRecipeLayout; +import mezz.jei.api.recipe.VanillaRecipeCategoryUid; + +public class FurnaceFuelCategory extends FurnaceRecipeCategory { + + @Nonnull + @Override + public String getUid() { + return VanillaRecipeCategoryUid.FUEL; + } + + @Override + public void init(@Nonnull IRecipeLayout recipeLayout) { + recipeLayout.setRecipeTransferButton(-14, 36); + + IGuiItemStackGroup guiItemStacks = recipeLayout.getItemStacks(); + guiItemStacks.init(inputSlot, false, 0, 0); + guiItemStacks.init(fuelSlot, true, 0, 36); + guiItemStacks.init(outputSlot, false, 60, 18); + } +} diff --git a/src/main/java/mezz/jei/plugins/vanilla/furnace/FurnaceRecipeCategory.java b/src/main/java/mezz/jei/plugins/vanilla/furnace/FurnaceRecipeCategory.java index 8e757b909..51c1ab5ef 100644 --- a/src/main/java/mezz/jei/plugins/vanilla/furnace/FurnaceRecipeCategory.java +++ b/src/main/java/mezz/jei/plugins/vanilla/furnace/FurnaceRecipeCategory.java @@ -7,18 +7,16 @@ import mezz.jei.api.JEIManager; import mezz.jei.api.gui.IDrawable; -import mezz.jei.api.gui.IGuiFluidStackGroup; import mezz.jei.api.gui.IGuiItemStackGroup; +import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.recipe.IRecipeCategory; -import mezz.jei.api.recipe.IRecipeCategoryUid; import mezz.jei.api.recipe.IRecipeWrapper; -import mezz.jei.api.recipe.VanillaRecipeCategoryUid; -public class FurnaceRecipeCategory implements IRecipeCategory { +public abstract class FurnaceRecipeCategory implements IRecipeCategory { - private static final int inputSlot = 0; - private static final int fuelSlot = 1; - private static final int outputSlot = 2; + protected static final int inputSlot = 0; + protected static final int fuelSlot = 1; + protected static final int outputSlot = 2; @Nonnull private final IDrawable background; @@ -31,12 +29,6 @@ public FurnaceRecipeCategory() { localizedName = StatCollector.translateToLocal("gui.jei.furnaceRecipes"); } - @Nonnull - @Override - public IRecipeCategoryUid getUid() { - return VanillaRecipeCategoryUid.FURNACE; - } - @Nonnull @Override public IDrawable getBackground() { @@ -44,21 +36,13 @@ public IDrawable getBackground() { } @Override - public void init(@Nonnull IGuiItemStackGroup guiItemStacks, @Nonnull IGuiFluidStackGroup guiFluidTanks) { - guiItemStacks.init(inputSlot, 0, 0); - guiItemStacks.init(fuelSlot, 0, 36); - guiItemStacks.init(outputSlot, 60, 18); - } - - @Override - public void setRecipe(@Nonnull IGuiItemStackGroup guiItemStacks, @Nonnull IGuiFluidStackGroup guiFluidTanks, @Nonnull IRecipeWrapper recipeWrapper) { + public void setRecipe(@Nonnull IRecipeLayout recipeLayout, @Nonnull IRecipeWrapper recipeWrapper) { + IGuiItemStackGroup guiItemStacks = recipeLayout.getItemStacks(); if (recipeWrapper instanceof FuelRecipe) { - FuelRecipe fuelRecipeWrapper = (FuelRecipe) recipeWrapper; - guiItemStacks.set(fuelSlot, fuelRecipeWrapper.getInputs()); + guiItemStacks.setFromRecipe(fuelSlot, recipeWrapper.getInputs()); } else if (recipeWrapper instanceof SmeltingRecipe) { - SmeltingRecipe smeltingRecipeWrapper = (SmeltingRecipe) recipeWrapper; - guiItemStacks.set(inputSlot, smeltingRecipeWrapper.getInputs()); - guiItemStacks.set(outputSlot, smeltingRecipeWrapper.getOutputs()); + guiItemStacks.setFromRecipe(inputSlot, recipeWrapper.getInputs()); + guiItemStacks.setFromRecipe(outputSlot, recipeWrapper.getOutputs()); } } diff --git a/src/main/java/mezz/jei/plugins/vanilla/furnace/FurnaceSmeltingCategory.java b/src/main/java/mezz/jei/plugins/vanilla/furnace/FurnaceSmeltingCategory.java new file mode 100644 index 000000000..f1e0ea554 --- /dev/null +++ b/src/main/java/mezz/jei/plugins/vanilla/furnace/FurnaceSmeltingCategory.java @@ -0,0 +1,25 @@ +package mezz.jei.plugins.vanilla.furnace; + +import javax.annotation.Nonnull; + +import mezz.jei.api.gui.IGuiItemStackGroup; +import mezz.jei.api.gui.IRecipeLayout; +import mezz.jei.api.recipe.VanillaRecipeCategoryUid; + +public class FurnaceSmeltingCategory extends FurnaceRecipeCategory { + @Nonnull + @Override + public String getUid() { + return VanillaRecipeCategoryUid.SMELTING; + } + + @Override + public void init(@Nonnull IRecipeLayout recipeLayout) { + recipeLayout.setRecipeTransferButton(-14, 0); + + IGuiItemStackGroup guiItemStacks = recipeLayout.getItemStacks(); + guiItemStacks.init(inputSlot, true, 0, 0); + guiItemStacks.init(fuelSlot, false, 0, 36); + guiItemStacks.init(outputSlot, false, 60, 18); + } +} diff --git a/src/main/java/mezz/jei/plugins/vanilla/furnace/SmeltingRecipe.java b/src/main/java/mezz/jei/plugins/vanilla/furnace/SmeltingRecipe.java index 55efcb5cd..b1de7d395 100644 --- a/src/main/java/mezz/jei/plugins/vanilla/furnace/SmeltingRecipe.java +++ b/src/main/java/mezz/jei/plugins/vanilla/furnace/SmeltingRecipe.java @@ -15,16 +15,16 @@ public class SmeltingRecipe extends VanillaRecipeWrapper { @Nonnull - private final List input; + private final List> input; @Nonnull - private final ItemStack output; + private final List outputs; @Nullable private final String experienceString; public SmeltingRecipe(@Nonnull List input, @Nonnull ItemStack output, float experience) { - this.input = input; - this.output = output; + this.input = Collections.singletonList(input); + this.outputs = Collections.singletonList(output); if (experience > 0.0) { experienceString = StatCollector.translateToLocalFormatted("gui.jei.furnaceExperience", experience); @@ -34,13 +34,13 @@ public SmeltingRecipe(@Nonnull List input, @Nonnull ItemStack output, } @Nonnull - public List getInputs() { + public List> getInputs() { return input; } @Nonnull public List getOutputs() { - return Collections.singletonList(output); + return outputs; } @Override @@ -51,4 +51,8 @@ public void drawInfo(@Nonnull Minecraft minecraft) { } } + @Override + public boolean usesOreDictionaryComparison() { + return false; + } } diff --git a/src/main/java/mezz/jei/plugins/vanilla/furnace/SmeltingRecipeHandler.java b/src/main/java/mezz/jei/plugins/vanilla/furnace/SmeltingRecipeHandler.java index 2fe5c1f7a..1644dbd45 100644 --- a/src/main/java/mezz/jei/plugins/vanilla/furnace/SmeltingRecipeHandler.java +++ b/src/main/java/mezz/jei/plugins/vanilla/furnace/SmeltingRecipeHandler.java @@ -2,7 +2,6 @@ import javax.annotation.Nonnull; -import mezz.jei.api.recipe.IRecipeCategoryUid; import mezz.jei.api.recipe.IRecipeHandler; import mezz.jei.api.recipe.IRecipeWrapper; import mezz.jei.api.recipe.VanillaRecipeCategoryUid; @@ -17,8 +16,8 @@ public Class getRecipeClass() { @Nonnull @Override - public IRecipeCategoryUid getRecipeCategoryUid() { - return VanillaRecipeCategoryUid.FURNACE; + public String getRecipeCategoryUid() { + return VanillaRecipeCategoryUid.SMELTING; } @Override diff --git a/src/main/java/mezz/jei/util/RecipeTransferUtil.java b/src/main/java/mezz/jei/util/RecipeTransferUtil.java new file mode 100644 index 000000000..a742f8ef1 --- /dev/null +++ b/src/main/java/mezz/jei/util/RecipeTransferUtil.java @@ -0,0 +1,249 @@ +package mezz.jei.util; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; + +import mezz.jei.JustEnoughItems; +import mezz.jei.api.JEIManager; +import mezz.jei.api.recipe.IRecipeTransferHelper; +import mezz.jei.api.recipe.IRecipeWrapper; +import mezz.jei.gui.RecipeLayout; +import mezz.jei.gui.ingredients.GuiIngredient; +import mezz.jei.gui.ingredients.GuiItemStackGroup; +import mezz.jei.network.packets.PacketRecipeTransfer; + +public class RecipeTransferUtil { + public static boolean hasTransferHelper(@Nonnull RecipeLayout recipeLayout, @Nonnull EntityPlayer player) { + Container container = player.openContainer; + + IRecipeTransferHelper transferHelper = JEIManager.recipeRegistry.getRecipeTransferHelper(container, recipeLayout.getRecipeCategory()); + return transferHelper != null; + } + + public static boolean canTransferRecipe(@Nonnull RecipeLayout recipeLayout, @Nonnull EntityPlayer player) { + return transferRecipe(recipeLayout, player, false); + } + + public static boolean transferRecipe(@Nonnull RecipeLayout recipeLayout, @Nonnull EntityPlayer player) { + return transferRecipe(recipeLayout, player, true); + } + + private static boolean transferRecipe(@Nonnull RecipeLayout recipeLayout, @Nonnull EntityPlayer player, boolean doTransfer) { + Container container = player.openContainer; + + IRecipeTransferHelper transferHelper = JEIManager.recipeRegistry.getRecipeTransferHelper(container, recipeLayout.getRecipeCategory()); + if (transferHelper == null) { + return false; + } + + Map inventorySlots = new HashMap<>(); + for (Slot slot : transferHelper.getInventorySlots(container)) { + inventorySlots.put(slot.slotNumber, slot); + } + + Map craftingSlots = new HashMap<>(); + for (Slot slot : transferHelper.getRecipeSlots(container)) { + craftingSlots.put(slot.slotNumber, slot); + } + + IRecipeWrapper recipeWrapper = recipeLayout.getRecipeWrapper(); + if (recipeWrapper.getInputs().size() > craftingSlots.size()) { + return false; + } + + GuiItemStackGroup itemStackGroup = recipeLayout.getItemStacks(); + List> requiredStackLists = getInputStacks(itemStackGroup.getGuiIngredients()); + + List availableItemStacks = new ArrayList<>(); + int filledCraftSlotCount = 0; + int emptySlotCount = 0; + + for (Slot slot : craftingSlots.values()) { + if (slot.getHasStack()) { + filledCraftSlotCount++; + availableItemStacks.add(slot.getStack()); + } + } + + for (Slot slot : inventorySlots.values()) { + if (slot.getHasStack()) { + availableItemStacks.add(slot.getStack()); + } else { + emptySlotCount++; + } + } + + // check if we have enough inventory space to shuffle items around to their final locations + if (filledCraftSlotCount - recipeWrapper.getInputs().size() > emptySlotCount) { + return false; + } + + List matchingStacks = getMatchingItems(availableItemStacks, requiredStackLists); + if (matchingStacks == null) { + return false; + } + + Map slotMap = buildSlotMap(itemStackGroup, matchingStacks); + if (slotMap == null || StackUtil.containsSets(slotMap.values(), availableItemStacks) == null) { + return false; + } + + if (doTransfer) { + PacketRecipeTransfer packet = new PacketRecipeTransfer(slotMap, craftingSlots.keySet(), inventorySlots.keySet()); + JustEnoughItems.common.sendPacketToServer(packet); + } + + return true; + } + + /** + * Build slot map (Crafting Slot Index -> ItemStack) for the recipe. + * Based on slot position info from itemStackGroup the ingredients from the player's inventory in matchingStacks. + */ + @Nullable + private static Map buildSlotMap(@Nonnull GuiItemStackGroup itemStackGroup, @Nonnull List matchingStacks) { + Map slotMap = new HashMap<>(); + + for (Map.Entry> entry : itemStackGroup.getGuiIngredients().entrySet()) { + GuiIngredient guiIngredient = entry.getValue(); + if (!guiIngredient.isInput()) { + continue; + } + + List requiredStacks = guiIngredient.getAll(); + if (requiredStacks.isEmpty()) { + continue; + } + + ItemStack matchingStack = StackUtil.containsStack(matchingStacks, requiredStacks); + if (matchingStack != null) { + slotMap.put(entry.getKey(), matchingStack); + matchingStacks.remove(matchingStack); + } else { + return null; + } + } + + return slotMap; + } + + public static void setItems(@Nonnull EntityPlayer player, @Nonnull Map slotMap, @Nonnull Collection craftingSlots, @Nonnull Collection inventorySlots) { + Container container = player.openContainer; + + // remove required recipe items + List removeRecipeItems = new ArrayList<>(); + for (ItemStack matchingStack : slotMap.values()) { + ItemStack requiredStack = matchingStack.copy(); + while (requiredStack.stackSize > 0) { + Slot inventorySlot = getSlotWithStack(container, craftingSlots, requiredStack); + if (inventorySlot == null) { + inventorySlot = getSlotWithStack(container, inventorySlots, requiredStack); + if (inventorySlot == null) { + Log.error("Couldn't find required items in inventory, even though they should be there."); + // abort! put removed items back into the player's inventory somewhere so they're not lost + List allSlots = new ArrayList<>(); + allSlots.addAll(inventorySlots); + allSlots.addAll(craftingSlots); + for (ItemStack removedRecipeItem : removeRecipeItems) { + StackUtil.addStack(container, allSlots, removedRecipeItem, true); + } + return; + } + } + ItemStack removed = inventorySlot.decrStackSize(requiredStack.stackSize); + removeRecipeItems.add(removed); + requiredStack.stackSize -= removed.stackSize; + } + } + + // clear the crafting grid + List clearedCraftingItems = new ArrayList<>(); + for (Integer craftingSlotIndex : craftingSlots) { + Slot craftingSlot = container.getSlot(craftingSlotIndex); + if (craftingSlot != null && craftingSlot.getHasStack()) { + ItemStack craftingItem = craftingSlot.decrStackSize(Integer.MAX_VALUE); + clearedCraftingItems.add(craftingItem); + } + } + + // put items into the crafting grid + for (Map.Entry entry : slotMap.entrySet()) { + ItemStack stack = entry.getValue(); + Integer slotIndex = entry.getKey(); + Slot slot = container.getSlot(slotIndex); + slot.putStack(stack); + } + + // put cleared items back into the player's inventory + for (ItemStack oldCraftingItem : clearedCraftingItems) { + StackUtil.addStack(container, inventorySlots, oldCraftingItem, true); + } + + container.detectAndSendChanges(); + } + + private static List> getInputStacks(@Nonnull Map> guiItemStacks) { + List> inputStacks = new ArrayList<>(); + + for (Map.Entry> entry : guiItemStacks.entrySet()) { + if (entry.getValue().isInput()) { + inputStacks.add(entry.getValue().getAll()); + } + } + return inputStacks; + } + + /** + * Returns a list of items in slots that complete the recipe defined by requiredStacksList. + * Returns null if there are not enough items in slots. + */ + @Nullable + private static List getMatchingItems(@Nonnull List availableItemStacks, @Nonnull List> requiredStacksList) { + List matchingItems = new ArrayList<>(); + + for (List requiredStacks : requiredStacksList) { + if (requiredStacks.isEmpty()) { + continue; + } + + ItemStack matching = null; + for (ItemStack requiredStack : requiredStacks) { + if (StackUtil.containsStack(availableItemStacks, requiredStack) != null) { + matching = requiredStack.copy(); + break; + } + } + if (matching == null) { + return null; + } else { + matchingItems.add(matching); + } + } + + return matchingItems; + } + + @Nullable + private static Slot getSlotWithStack(@Nonnull Container container, @Nonnull Iterable slotIndexes, @Nonnull ItemStack stack) { + for (Integer slotIndex : slotIndexes) { + Slot slot = container.getSlot(slotIndex); + if (slot != null) { + ItemStack slotStack = slot.getStack(); + if (StackUtil.isIdentical(stack, slotStack)) { + return slot; + } + } + } + return null; + } +} diff --git a/src/main/java/mezz/jei/util/StackUtil.java b/src/main/java/mezz/jei/util/StackUtil.java index f78356e9f..44b30b71e 100644 --- a/src/main/java/mezz/jei/util/StackUtil.java +++ b/src/main/java/mezz/jei/util/StackUtil.java @@ -3,10 +3,13 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.Slot; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -16,12 +19,8 @@ public class StackUtil { @Nonnull - public static List removeDuplicateItemStacks(Iterable stacks) { + public static List removeDuplicateItemStacks(@Nonnull Iterable stacks) { List newStacks = new ArrayList<>(); - if (stacks == null) { - return newStacks; - } - for (ItemStack stack : stacks) { if (stack != null && containsStack(newStacks, stack) == null) { newStacks.add(stack); @@ -30,6 +29,23 @@ public static List removeDuplicateItemStacks(Iterable stac return newStacks; } + /* Returns an ItemStack from "stacks" if it isIdentical to an ItemStack from "contains" */ + @Nullable + public static ItemStack containsStack(@Nullable Iterable stacks, @Nullable Iterable contains) { + if (stacks == null || contains == null) { + return null; + } + + for (ItemStack containStack : contains) { + ItemStack matchingStack = containsStack(stacks, containStack); + if (matchingStack != null) { + return matchingStack; + } + } + + return null; + } + /* Returns an ItemStack from "stacks" if it isIdentical to "contains" */ @Nullable public static ItemStack containsStack(@Nullable Iterable stacks, @Nullable ItemStack contains) { @@ -45,6 +61,70 @@ public static ItemStack containsStack(@Nullable Iterable stacks, @Nul return null; } + @Nonnull + public static List condenseStacks(Collection stacks) { + List condensed = new ArrayList<>(); + + for (ItemStack stack : stacks) { + if (stack == null) { + continue; + } + if (stack.stackSize <= 0) { + continue; + } + + boolean matched = false; + for (ItemStack cached : condensed) { + if ((cached.isItemEqual(stack) && ItemStack.areItemStackTagsEqual(cached, stack))) { + cached.stackSize += stack.stackSize; + matched = true; + } + } + + if (!matched) { + ItemStack cached = stack.copy(); + condensed.add(cached); + } + } + + return condensed; + } + + /** + * Counts how many full sets are contained in the passed stock. + * Returns a list of matching stacks from set, or null if there aren't enough for a complete match. + */ + @Nullable + public static List containsSets(Collection required, Collection offered) { + int totalSets = 0; + + List matching = new ArrayList<>(); + List condensedRequired = condenseStacks(required); + List condensedOffered = condenseStacks(offered); + + for (ItemStack req : condensedRequired) { + int reqCount = 0; + for (ItemStack offer : condensedOffered) { + if (isIdentical(req, offer)) { + int stackCount = (int) Math.floor(offer.stackSize / req.stackSize); + reqCount = Math.max(reqCount, stackCount); + } + } + + if (reqCount == 0) { + return null; + } else { + matching.add(req); + + if (totalSets == 0 || totalSets > reqCount) { + totalSets = reqCount; + } + } + } + + return matching; + } + public static boolean isIdentical(@Nullable ItemStack lhs, @Nullable ItemStack rhs) { if (lhs == rhs) { return true; @@ -125,24 +205,63 @@ private static void getAllSubtypes(List subtypesList, Iterable stacks } @Nonnull - public static List toItemStackList(@Nullable Iterable stacks) { - if (stacks == null) { - return Collections.emptyList(); + public static List getOreNames(@Nonnull ItemStack stack) { + List oreNames = new ArrayList<>(); + int[] oreIds = OreDictionary.getOreIDs(stack); + for (int oreId : oreIds) { + String oreName = OreDictionary.getOreName(oreId); + oreNames.add(oreName); + } + return oreNames; + } + + public static List> expandRecipeInputs(@Nullable List recipeInputs, boolean oreDict) { + List> expandedRecipeInputs = new ArrayList<>(); + if (recipeInputs == null) { + return expandedRecipeInputs; } + + for (Object recipeInput : recipeInputs) { + List inputStacks = toItemStackList(recipeInput); + List inputExpanded = new ArrayList<>(); + for (ItemStack stack : inputStacks) { + if (oreDict) { + List inputOres = getOreNames(stack); + if (inputOres.size() > 0) { + for (String inputOre : inputOres) { + List ores = OreDictionary.getOres(inputOre); + inputExpanded.addAll(ores); + } + } + } + List subtypes = getSubtypes(stack); + inputExpanded.addAll(subtypes); + } + removeDuplicateItemStacks(inputExpanded); + expandedRecipeInputs.add(inputExpanded); + } + return expandedRecipeInputs; + } + + @Nonnull + public static List toItemStackList(@Nullable Object stacks) { List itemStacksList = new ArrayList<>(); toItemStackList(itemStacksList, stacks); return removeDuplicateItemStacks(itemStacksList); } - private static void toItemStackList(@Nonnull List itemStackList, @Nonnull Iterable input) { - for (Object obj : input) { - if (obj instanceof Iterable) { - toItemStackList(itemStackList, (Iterable) obj); - } else if (obj instanceof ItemStack) { - itemStackList.add((ItemStack) obj); - } else if (obj != null) { - Log.error("Unknown object found: {}", obj); + private static void toItemStackList(@Nonnull List itemStackList, @Nullable Object input) { + if (input instanceof ItemStack) { + itemStackList.add((ItemStack) input); + } else if (input instanceof String) { + List stacks = OreDictionary.getOres((String) input); + itemStackList.addAll(stacks); + } else if (input instanceof Iterable) { + for (Object obj : (Iterable) input) { + toItemStackList(itemStackList, obj); } + } else if (input != null) { + Log.error("Unknown object found: {}", input); } } @@ -166,4 +285,71 @@ public static String uniqueIdentifierForStack(@Nonnull ItemStack stack, boolean return itemKey.toString(); } + + public static int addStack(Container container, Collection slotIndexes, ItemStack stack, boolean doAdd) { + int added = 0; + // Add to existing stacks first + for (Integer slotIndex : slotIndexes) { + Slot slot = container.getSlot(slotIndex); + if (slot == null) { + continue; + } + + ItemStack inventoryStack = slot.getStack(); + if (inventoryStack == null || inventoryStack.getItem() == null) { + continue; + } + + // Already occupied by different item, skip this slot. + if (!inventoryStack.isStackable() || !inventoryStack.isItemEqual(stack) || !ItemStack.areItemStackTagsEqual(inventoryStack, stack)) { + continue; + } + + int remain = stack.stackSize - added; + int space = inventoryStack.getMaxStackSize() - inventoryStack.stackSize; + if (space <= 0) { + continue; + } + + // Enough space + if (space >= remain) { + if (doAdd) { + inventoryStack.stackSize += remain; + } + return stack.stackSize; + } + + // Not enough space + if (doAdd) { + inventoryStack.stackSize = inventoryStack.getMaxStackSize(); + } + + added += space; + } + + if (added >= stack.stackSize) { + return added; + } + + for (Integer slotIndex : slotIndexes) { + Slot slot = container.getSlot(slotIndex); + if (slot == null) { + continue; + } + + ItemStack inventoryStack = slot.getStack(); + if (inventoryStack != null) { + continue; + } + + if (doAdd) { + ItemStack stackToAdd = stack.copy(); + stackToAdd.stackSize = stack.stackSize - added; + slot.putStack(stackToAdd); + } + return stack.stackSize; + } + + return added; + } } From 28e075a00db8652cc3932c0e89c5afbe58a696ec Mon Sep 17 00:00:00 2001 From: mezz Date: Tue, 1 Dec 2015 23:07:13 -0800 Subject: [PATCH 6/6] Fix client crash --- src/main/java/mezz/jei/JustEnoughItems.java | 3 +-- src/main/java/mezz/jei/ProxyCommonClient.java | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/mezz/jei/JustEnoughItems.java b/src/main/java/mezz/jei/JustEnoughItems.java index d6f443769..d2e79a8b6 100644 --- a/src/main/java/mezz/jei/JustEnoughItems.java +++ b/src/main/java/mezz/jei/JustEnoughItems.java @@ -28,7 +28,7 @@ public class JustEnoughItems { public static PacketHandler packetHandler; - private PluginRegistry pluginRegistry; + public static PluginRegistry pluginRegistry; @Mod.EventHandler public void preInit(@Nonnull FMLPreInitializationEvent event) { @@ -46,7 +46,6 @@ public void init(@Nonnull FMLInitializationEvent event) { @Mod.EventHandler public void loadComplete(@Nonnull FMLLoadCompleteEvent event) { - JEIManager.recipeRegistry = pluginRegistry.createRecipeRegistry(); common.loadComplete(event); } } diff --git a/src/main/java/mezz/jei/ProxyCommonClient.java b/src/main/java/mezz/jei/ProxyCommonClient.java index b4312838a..eecbabda0 100644 --- a/src/main/java/mezz/jei/ProxyCommonClient.java +++ b/src/main/java/mezz/jei/ProxyCommonClient.java @@ -36,6 +36,7 @@ public void init(@Nonnull FMLInitializationEvent event) { @Override public void loadComplete(@Nonnull FMLLoadCompleteEvent event) { JEIManager.itemRegistry = new ItemRegistry(); + JEIManager.recipeRegistry = JustEnoughItems.pluginRegistry.createRecipeRegistry(); ItemFilter itemFilter = new ItemFilter(JEIManager.itemRegistry.getItemList()); ItemListOverlay itemListOverlay = new ItemListOverlay(itemFilter);