From 43980d550d3cc03f1a3f049a83962669433276af Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Sat, 14 Dec 2019 16:29:48 +0100 Subject: [PATCH] Plenty to process - The Mechanical Mixer now supports custom mixing recipes - The Mechanical Press now interacts with the basin to apply compressing recipes - Added JEI integration for Mixing, Compressing, Sawing and Block Cutting recipes --- .../create/compat/jei/AnimatedMixer.java | 86 +++++++ .../create/compat/jei/AnimatedPress.java | 17 ++ .../create/compat/jei/AnimatedSaw.java | 59 +++++ .../compat/jei/BlockCuttingCategory.java | 136 +++++++++++ .../simibubi/create/compat/jei/CreateJEI.java | 55 ++++- .../create/compat/jei/CrushingCategory.java | 10 +- .../create/compat/jei/MixingCategory.java | 113 +++++++++ .../create/compat/jei/PackingCategory.java | 100 ++++++++ .../create/compat/jei/PressingCategory.java | 7 +- .../create/compat/jei/SawingCategory.java | 98 ++++++++ .../create/compat/jei/SplashingCategory.java | 10 +- .../create/foundation/item/ItemHelper.java | 41 +++- .../utility/recipe/RecipeFinder.java | 43 +--- .../mixer/MechanicalMixerTileEntity.java | 186 +++++---------- .../press/MechanicalPressBlock.java | 10 +- .../press/MechanicalPressTileEntity.java | 216 +++++++++++++++--- .../components/saw/SawTileEntity.java | 12 +- .../processing/BasinOperatingTileEntity.java | 166 ++++++++++++++ .../processing/BasinTileEntity.java | 15 +- .../ProcessingRecipeSerializer.java | 4 +- .../resources/assets/create/lang/en_us.json | 8 +- .../create/recipes/mixing/andesite_alloy.json | 18 ++ 22 files changed, 1167 insertions(+), 243 deletions(-) create mode 100644 src/main/java/com/simibubi/create/compat/jei/AnimatedMixer.java create mode 100644 src/main/java/com/simibubi/create/compat/jei/AnimatedSaw.java create mode 100644 src/main/java/com/simibubi/create/compat/jei/BlockCuttingCategory.java create mode 100644 src/main/java/com/simibubi/create/compat/jei/MixingCategory.java create mode 100644 src/main/java/com/simibubi/create/compat/jei/PackingCategory.java create mode 100644 src/main/java/com/simibubi/create/compat/jei/SawingCategory.java create mode 100644 src/main/java/com/simibubi/create/modules/contraptions/processing/BasinOperatingTileEntity.java create mode 100644 src/main/resources/data/create/recipes/mixing/andesite_alloy.json diff --git a/src/main/java/com/simibubi/create/compat/jei/AnimatedMixer.java b/src/main/java/com/simibubi/create/compat/jei/AnimatedMixer.java new file mode 100644 index 000000000..df92a644f --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/jei/AnimatedMixer.java @@ -0,0 +1,86 @@ +package com.simibubi.create.compat.jei; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.foundation.gui.ScreenElementRenderer; + +import net.minecraft.block.BlockState; +import net.minecraft.state.properties.BlockStateProperties; +import net.minecraft.util.Direction.Axis; + +public class AnimatedMixer extends AnimatedKinetics { + + @Override + public int getWidth() { + return 50; + } + + @Override + public int getHeight() { + return 150; + } + + @Override + public void draw(int xOffset, int yOffset) { + GlStateManager.pushMatrix(); + GlStateManager.enableDepthTest(); + GlStateManager.translatef(xOffset, yOffset, 0); + GlStateManager.rotatef(-15.5f, 1, 0, 0); + GlStateManager.rotatef(22.5f, 0, 1, 0); + GlStateManager.translatef(-45, -5, 0); + GlStateManager.scaled(.45f, .45f, .45f); + + GlStateManager.pushMatrix(); + ScreenElementRenderer.renderBlock(this::cogwheel); + GlStateManager.popMatrix(); + + GlStateManager.pushMatrix(); + ScreenElementRenderer.renderBlock(this::body); + GlStateManager.popMatrix(); + + GlStateManager.pushMatrix(); + ScreenElementRenderer.renderBlock(this::pole); + GlStateManager.popMatrix(); + + GlStateManager.pushMatrix(); + ScreenElementRenderer.renderBlock(this::head); + GlStateManager.popMatrix(); + + GlStateManager.pushMatrix(); + ScreenElementRenderer.renderBlock(this::basin); + GlStateManager.popMatrix(); + + GlStateManager.popMatrix(); + } + + private BlockState cogwheel() { + float t = 25; + GlStateManager.translatef(t, -t, -t); + GlStateManager.rotated(getCurrentAngle() * 2, 0, 1, 0); + GlStateManager.translatef(-t, t, t); + return AllBlocks.SHAFTLESS_COGWHEEL.get().getDefaultState().with(BlockStateProperties.AXIS, Axis.Y); + } + + private BlockState body() { + return AllBlocks.MECHANICAL_MIXER.get().getDefaultState(); + } + + private BlockState pole() { + GlStateManager.translatef(0, 51, 0); + return AllBlocks.MECHANICAL_MIXER_POLE.get().getDefaultState(); + } + + private BlockState head() { + float t = 25; + GlStateManager.translatef(0, 51, 0); + GlStateManager.translatef(t, -t, -t); + GlStateManager.rotated(getCurrentAngle() * 4, 0, 1, 0); + GlStateManager.translatef(-t, t, t); + return AllBlocks.MECHANICAL_MIXER_HEAD.get().getDefaultState(); + } + + private BlockState basin() { + GlStateManager.translatef(0, 85, 0); + return AllBlocks.BASIN.get().getDefaultState(); + } +} diff --git a/src/main/java/com/simibubi/create/compat/jei/AnimatedPress.java b/src/main/java/com/simibubi/create/compat/jei/AnimatedPress.java index d6425d3f9..a131624e3 100644 --- a/src/main/java/com/simibubi/create/compat/jei/AnimatedPress.java +++ b/src/main/java/com/simibubi/create/compat/jei/AnimatedPress.java @@ -14,6 +14,12 @@ import net.minecraft.util.Direction.Axis; public class AnimatedPress extends AnimatedKinetics { + private boolean basin; + + public AnimatedPress(boolean basin) { + this.basin = basin; + } + @Override public int getWidth() { return 50; @@ -45,6 +51,12 @@ public class AnimatedPress extends AnimatedKinetics { GlStateManager.pushMatrix(); ScreenElementRenderer.renderBlock(this::head); GlStateManager.popMatrix(); + + if (basin) { + GlStateManager.pushMatrix(); + ScreenElementRenderer.renderBlock(this::basin); + GlStateManager.popMatrix(); + } GlStateManager.popMatrix(); } @@ -79,5 +91,10 @@ public class AnimatedPress extends AnimatedKinetics { return AllBlocks.MECHANICAL_PRESS_HEAD.get().getDefaultState().with(BlockStateProperties.HORIZONTAL_FACING, Direction.EAST); } + + private BlockState basin() { + GlStateManager.translatef(0, 85, 0); + return AllBlocks.BASIN.get().getDefaultState(); + } } diff --git a/src/main/java/com/simibubi/create/compat/jei/AnimatedSaw.java b/src/main/java/com/simibubi/create/compat/jei/AnimatedSaw.java new file mode 100644 index 000000000..8f2fd7b71 --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/jei/AnimatedSaw.java @@ -0,0 +1,59 @@ +package com.simibubi.create.compat.jei; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.foundation.gui.ScreenElementRenderer; +import com.simibubi.create.modules.contraptions.components.saw.SawBlock; + +import net.minecraft.block.BlockState; +import net.minecraft.state.properties.BlockStateProperties; +import net.minecraft.util.Direction; +import net.minecraft.util.Direction.Axis; + +public class AnimatedSaw extends AnimatedKinetics { + + @Override + public int getWidth() { + return 50; + } + + @Override + public int getHeight() { + return 50; + } + + @Override + public void draw(int xOffset, int yOffset) { + GlStateManager.pushMatrix(); + GlStateManager.enableDepthTest(); + GlStateManager.translatef(xOffset, yOffset, 0); + GlStateManager.rotatef(-15.5f, 1, 0, 0); + GlStateManager.rotatef(22.5f, 0, 1, 0); + GlStateManager.translatef(-45, -5, 0); + GlStateManager.scaled(.6f, .6f, .6f); + + GlStateManager.pushMatrix(); + ScreenElementRenderer.renderBlock(this::shaft); + GlStateManager.popMatrix(); + + GlStateManager.pushMatrix(); + ScreenElementRenderer.renderBlock(this::block); + GlStateManager.popMatrix(); + + GlStateManager.popMatrix(); + } + + private BlockState shaft() { + float t = 25; + GlStateManager.translatef(t, -t, t); + GlStateManager.rotated(-getCurrentAngle() * 2, 0, 0, 1); + GlStateManager.translatef(-t, t, -t); + return AllBlocks.SHAFT.get().getDefaultState().with(BlockStateProperties.AXIS, Axis.X); + } + + private BlockState block() { + return AllBlocks.SAW.get().getDefaultState().with(BlockStateProperties.FACING, Direction.UP) + .with(SawBlock.RUNNING, true).with(SawBlock.AXIS_ALONG_FIRST_COORDINATE, true); + } + +} diff --git a/src/main/java/com/simibubi/create/compat/jei/BlockCuttingCategory.java b/src/main/java/com/simibubi/create/compat/jei/BlockCuttingCategory.java new file mode 100644 index 000000000..2e366ecd1 --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/jei/BlockCuttingCategory.java @@ -0,0 +1,136 @@ +package com.simibubi.create.compat.jei; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.Create; +import com.simibubi.create.ScreenResources; +import com.simibubi.create.compat.jei.BlockCuttingCategory.CondensedBlockCuttingRecipe; +import com.simibubi.create.foundation.item.ItemHelper; +import com.simibubi.create.foundation.utility.Lang; + +import mezz.jei.api.constants.VanillaTypes; +import mezz.jei.api.gui.IRecipeLayout; +import mezz.jei.api.gui.drawable.IDrawable; +import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; +import mezz.jei.api.ingredients.IIngredients; +import mezz.jei.api.recipe.category.IRecipeCategory; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.item.crafting.StonecuttingRecipe; +import net.minecraft.util.ResourceLocation; + +public class BlockCuttingCategory implements IRecipeCategory { + + private AnimatedSaw saw; + private static ResourceLocation ID = new ResourceLocation(Create.ID, "block_cutting"); + private IDrawable icon; + private IDrawable background = new EmptyBackground(177, 70); + + public BlockCuttingCategory() { + icon = new DoubleItemIcon(() -> new ItemStack(AllBlocks.SAW.get()), + () -> new ItemStack(Items.STONE_BRICK_STAIRS)); + saw = new AnimatedSaw(); + } + + @Override + public IDrawable getIcon() { + return icon; + } + + @Override + public ResourceLocation getUid() { + return ID; + } + + @Override + public Class getRecipeClass() { + return CondensedBlockCuttingRecipe.class; + } + + @Override + public String getTitle() { + return Lang.translate("recipe.block_cutting"); + } + + @Override + public IDrawable getBackground() { + return background; + } + + @Override + public void setIngredients(CondensedBlockCuttingRecipe recipe, IIngredients ingredients) { + ingredients.setInputIngredients(recipe.getIngredients()); + ingredients.setOutputs(VanillaTypes.ITEM, recipe.getOutputs()); + } + + @Override + public void setRecipe(IRecipeLayout recipeLayout, CondensedBlockCuttingRecipe recipe, IIngredients ingredients) { + IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks(); + itemStacks.init(0, true, 4, 4); + itemStacks.set(0, Arrays.asList(recipe.getIngredients().get(0).getMatchingStacks())); + + List results = recipe.getOutputs(); + for (int outputIndex = 0; outputIndex < results.size(); outputIndex++) { + int xOffset = (outputIndex % 5) * 19; + int yOffset = (outputIndex / 5) * -19; + + itemStacks.init(outputIndex + 1, false, 77 + xOffset, 47 + yOffset); + itemStacks.set(outputIndex + 1, results.get(outputIndex).getStack()); + } + } + + @Override + public void draw(CondensedBlockCuttingRecipe recipe, double mouseX, double mouseY) { + ScreenResources.JEI_SLOT.draw(4, 4); + int size = recipe.getOutputs().size(); + for (int i = 0; i < size; i++) { + int xOffset = (i % 5) * 19; + int yOffset = (i / 5) * -19; + ScreenResources.JEI_SLOT.draw(77 + xOffset, 47 + yOffset); + } + ScreenResources.JEI_DOWN_ARROW.draw(31, 6); + ScreenResources.JEI_SHADOW.draw(19, 55); + saw.draw(33, 35); + } + + public static class CondensedBlockCuttingRecipe extends StonecuttingRecipe { + + List outputs = new ArrayList<>(); + + public CondensedBlockCuttingRecipe(Ingredient ingredient) { + super(new ResourceLocation(""), "", ingredient, ItemStack.EMPTY); + } + + public void addOutput(ItemStack stack) { + outputs.add(stack); + } + + public List getOutputs() { + return outputs; + } + + public static List condenseRecipes(List> stoneCuttingRecipes) { + List condensed = new ArrayList<>(); + Recipes: for (IRecipe recipe : stoneCuttingRecipes) { + Ingredient i1 = recipe.getIngredients().get(0); + for (CondensedBlockCuttingRecipe condensedRecipe : condensed) { + if (ItemHelper.matchIngredients(i1, condensedRecipe.getIngredients().get(0))) { + condensedRecipe.addOutput(recipe.getRecipeOutput()); + continue Recipes; + } + } + CondensedBlockCuttingRecipe cr = new CondensedBlockCuttingRecipe(i1); + cr.addOutput(recipe.getRecipeOutput()); + condensed.add(cr); + } + return condensed; + } + + } + +} diff --git a/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java b/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java index 093ed2493..a7e8e263c 100644 --- a/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java +++ b/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java @@ -3,24 +3,32 @@ package com.simibubi.create.compat.jei; import java.util.List; import java.util.stream.Collectors; +import com.google.common.base.Predicate; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; import com.simibubi.create.AllRecipes; import com.simibubi.create.Create; +import com.simibubi.create.compat.jei.BlockCuttingCategory.CondensedBlockCuttingRecipe; import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.modules.contraptions.components.press.MechanicalPressTileEntity; +import com.simibubi.create.modules.contraptions.processing.StochasticOutput; import com.simibubi.create.modules.logistics.block.inventories.FlexcrateScreen; import com.simibubi.create.modules.schematics.block.SchematicannonScreen; import mezz.jei.api.IModPlugin; import mezz.jei.api.JeiPlugin; +import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; import mezz.jei.api.registration.IGuiHandlerRegistration; import mezz.jei.api.registration.IRecipeCatalystRegistration; import mezz.jei.api.registration.IRecipeCategoryRegistration; import mezz.jei.api.registration.IRecipeRegistration; import mezz.jei.api.registration.ISubtypeRegistration; +import net.minecraft.block.Blocks; import net.minecraft.client.Minecraft; import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.ICraftingRecipe; import net.minecraft.item.crafting.IRecipe; +import net.minecraft.item.crafting.IRecipeSerializer; import net.minecraft.item.crafting.IRecipeType; import net.minecraft.util.ResourceLocation; import net.minecraft.util.text.StringTextComponent; @@ -36,6 +44,10 @@ public class CreateJEI implements IModPlugin { private PressingCategory pressingCategory; private BlastingViaFanCategory blastingCategory; private BlockzapperUpgradeCategory blockzapperCategory; + private MixingCategory mixingCategory; + private SawingCategory sawingCategory; + private BlockCuttingCategory blockCuttingCategory; + private PackingCategory packingCategory; @Override public ResourceLocation getPluginUid() { @@ -49,6 +61,10 @@ public class CreateJEI implements IModPlugin { smokingCategory = new SmokingViaFanCategory(); blastingCategory = new BlastingViaFanCategory(); blockzapperCategory = new BlockzapperUpgradeCategory(); + mixingCategory = new MixingCategory(); + sawingCategory = new SawingCategory(); + blockCuttingCategory = new BlockCuttingCategory(); + packingCategory = new PackingCategory(); } @Override @@ -59,7 +75,8 @@ public class CreateJEI implements IModPlugin { @Override public void registerCategories(IRecipeCategoryRegistration registration) { registration.addRecipeCategories(crushingCategory, splashingCategory, pressingCategory, smokingCategory, - blastingCategory, blockzapperCategory); + blastingCategory, blockzapperCategory, mixingCategory, sawingCategory, blockCuttingCategory, + packingCategory); } @Override @@ -72,6 +89,19 @@ public class CreateJEI implements IModPlugin { registration.addRecipes(findRecipesByType(IRecipeType.SMOKING), smokingCategory.getUid()); registration.addRecipes(findRecipesByTypeExcluding(IRecipeType.SMELTING, IRecipeType.SMOKING), blastingCategory.getUid()); + registration.addRecipes(findRecipes(AllRecipes.MIXING), mixingCategory.getUid()); + registration + .addRecipes( + findRecipes(r -> r.getSerializer() == IRecipeSerializer.CRAFTING_SHAPELESS + && !MechanicalPressTileEntity.canCompress(r.getIngredients())), + mixingCategory.getUid()); + registration.addRecipes(findRecipes(AllRecipes.CUTTING), sawingCategory.getUid()); + registration.addRecipes( + CondensedBlockCuttingRecipe.condenseRecipes(findRecipesByType(IRecipeType.STONECUTTING)), + blockCuttingCategory.getUid()); + registration.addRecipes(findRecipes( + r -> (r instanceof ICraftingRecipe) && MechanicalPressTileEntity.canCompress(r.getIngredients())), + packingCategory.getUid()); } @Override @@ -91,6 +121,13 @@ public class CreateJEI implements IModPlugin { registration.addRecipeCatalyst(blastingFan, blastingCategory.getUid()); registration.addRecipeCatalyst(new ItemStack(AllBlocks.MECHANICAL_PRESS.get()), pressingCategory.getUid()); registration.addRecipeCatalyst(new ItemStack(AllItems.PLACEMENT_HANDGUN.get()), blockzapperCategory.getUid()); + registration.addRecipeCatalyst(new ItemStack(AllBlocks.MECHANICAL_MIXER.get()), mixingCategory.getUid()); + registration.addRecipeCatalyst(new ItemStack(AllBlocks.BASIN.get()), mixingCategory.getUid()); + registration.addRecipeCatalyst(new ItemStack(AllBlocks.SAW.get()), sawingCategory.getUid()); + registration.addRecipeCatalyst(new ItemStack(AllBlocks.SAW.get()), blockCuttingCategory.getUid()); + registration.addRecipeCatalyst(new ItemStack(Blocks.STONECUTTER), blockCuttingCategory.getUid()); + registration.addRecipeCatalyst(new ItemStack(AllBlocks.MECHANICAL_PRESS.get()), packingCategory.getUid()); + registration.addRecipeCatalyst(new ItemStack(AllBlocks.BASIN.get()), packingCategory.getUid()); } @Override @@ -103,6 +140,11 @@ public class CreateJEI implements IModPlugin { return findRecipesByType(recipe.type); } + private static List> findRecipes(Predicate> pred) { + return Minecraft.getInstance().world.getRecipeManager().getRecipes().stream().filter(pred) + .collect(Collectors.toList()); + } + private static List> findRecipesByType(IRecipeType type) { return Minecraft.getInstance().world.getRecipeManager().getRecipes().stream().filter(r -> r.getType() == type) .collect(Collectors.toList()); @@ -129,4 +171,15 @@ public class CreateJEI implements IModPlugin { return byType; } + static void addStochasticTooltip(IGuiItemStackGroup itemStacks, List results) { + itemStacks.addTooltipCallback((slotIndex, input, ingredient, tooltip) -> { + if (input) + return; + StochasticOutput output = results.get(slotIndex - 1); + if (output.getChance() != 1) + tooltip.add(1, TextFormatting.GOLD + + Lang.translate("recipe.processing.chance", (int) (output.getChance() * 100))); + }); + } + } diff --git a/src/main/java/com/simibubi/create/compat/jei/CrushingCategory.java b/src/main/java/com/simibubi/create/compat/jei/CrushingCategory.java index ec3d0b3b8..e074a3905 100644 --- a/src/main/java/com/simibubi/create/compat/jei/CrushingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/CrushingCategory.java @@ -19,7 +19,6 @@ import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.recipe.category.IRecipeCategory; import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; -import net.minecraft.util.text.TextFormatting; public class CrushingCategory implements IRecipeCategory { @@ -78,14 +77,7 @@ public class CrushingCategory implements IRecipeCategory { itemStacks.set(outputIndex + 1, results.get(outputIndex).getStack()); } - itemStacks.addTooltipCallback((slotIndex, input, ingredient, tooltip) -> { - if (input) - return; - StochasticOutput output = results.get(slotIndex - 1); - if (output.getChance() != 1) - tooltip.add(1, TextFormatting.GOLD - + Lang.translate("recipe.processing.chance", (int) (output.getChance() * 100))); - }); + CreateJEI.addStochasticTooltip(itemStacks, results); } @Override diff --git a/src/main/java/com/simibubi/create/compat/jei/MixingCategory.java b/src/main/java/com/simibubi/create/compat/jei/MixingCategory.java new file mode 100644 index 000000000..6711a5988 --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/jei/MixingCategory.java @@ -0,0 +1,113 @@ +package com.simibubi.create.compat.jei; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.mutable.MutableInt; +import org.apache.commons.lang3.tuple.Pair; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.Create; +import com.simibubi.create.ScreenResources; +import com.simibubi.create.foundation.item.ItemHelper; +import com.simibubi.create.foundation.utility.Lang; + +import mezz.jei.api.constants.VanillaTypes; +import mezz.jei.api.gui.IRecipeLayout; +import mezz.jei.api.gui.drawable.IDrawable; +import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; +import mezz.jei.api.ingredients.IIngredients; +import mezz.jei.api.recipe.category.IRecipeCategory; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.util.NonNullList; +import net.minecraft.util.ResourceLocation; + +public class MixingCategory implements IRecipeCategory> { + + private AnimatedMixer mixer; + private static ResourceLocation ID = new ResourceLocation(Create.ID, "mixing"); + private IDrawable icon; + private IDrawable background = new EmptyBackground(177, 70); + + public MixingCategory() { + icon = new DoubleItemIcon(() -> new ItemStack(AllBlocks.MECHANICAL_MIXER.get()), + () -> new ItemStack(AllBlocks.BASIN.get())); + mixer = new AnimatedMixer(); + } + + @Override + public IDrawable getIcon() { + return icon; + } + + @Override + public ResourceLocation getUid() { + return ID; + } + + @Override + public String getTitle() { + return Lang.translate("recipe.mixing"); + } + + @Override + public IDrawable getBackground() { + return background; + } + + @Override + public void setIngredients(IRecipe recipe, IIngredients ingredients) { + ingredients.setInputIngredients(recipe.getIngredients()); + ingredients.setOutput(VanillaTypes.ITEM, recipe.getRecipeOutput()); + } + + @Override + public void setRecipe(IRecipeLayout recipeLayout, IRecipe recipe, IIngredients ingredients) { + IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks(); + + NonNullList recipeIngredients = recipe.getIngredients(); + List> actualIngredients = ItemHelper.condenseIngredients(recipeIngredients); + + int size = actualIngredients.size(); + int xOffset = size < 3 ? (3 - size) * 19 / 2 : 0; + int i = 0; + while (i < size) { + Pair ingredient = actualIngredients.get(i); + itemStacks.init(i, true, 16 + xOffset + (i % 3) * 19, 50 - (i / 3) * 19); + List asList = Arrays.asList(ingredient.getKey().getMatchingStacks()); + itemStacks.set(i, asList.stream().map(stack -> { + stack = stack.copy(); + stack.setCount(ingredient.getRight().getValue()); + return stack; + }).collect(Collectors.toList())); + i++; + } + + itemStacks.init(i, false, 141, 50); + itemStacks.set(i, recipe.getRecipeOutput().getStack()); + } + + @Override + public void draw(IRecipe recipe, double mouseX, double mouseY) { + List> actualIngredients = ItemHelper.condenseIngredients(recipe.getIngredients()); + + int size = actualIngredients.size(); + int xOffset = size < 3 ? (3 - size) * 19 / 2 : 0; + for (int i = 0; i < size; i++) + ScreenResources.JEI_SLOT.draw(16 + xOffset + (i % 3) * 19, 50 - (i / 3) * 19); + ScreenResources.JEI_SLOT.draw(141, 50); + ScreenResources.JEI_DOWN_ARROW.draw(136, 32); + ScreenResources.JEI_SHADOW.draw(81, 57); + mixer.draw(getBackground().getWidth() / 2 + 20, 8); + } + + @SuppressWarnings("unchecked") + @Override + public Class> getRecipeClass() { + return (Class>) IRecipe.class; + } + +} diff --git a/src/main/java/com/simibubi/create/compat/jei/PackingCategory.java b/src/main/java/com/simibubi/create/compat/jei/PackingCategory.java new file mode 100644 index 000000000..03e3d2a5f --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/jei/PackingCategory.java @@ -0,0 +1,100 @@ +package com.simibubi.create.compat.jei; + +import java.util.Arrays; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.Create; +import com.simibubi.create.ScreenResources; +import com.simibubi.create.foundation.utility.Lang; + +import mezz.jei.api.constants.VanillaTypes; +import mezz.jei.api.gui.IRecipeLayout; +import mezz.jei.api.gui.drawable.IDrawable; +import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; +import mezz.jei.api.ingredients.IIngredients; +import mezz.jei.api.recipe.category.IRecipeCategory; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.util.NonNullList; +import net.minecraft.util.ResourceLocation; + +public class PackingCategory implements IRecipeCategory> { + + private AnimatedPress press; + private static ResourceLocation ID = new ResourceLocation(Create.ID, "packing"); + private IDrawable icon; + private IDrawable background = new EmptyBackground(177, 70); + + public PackingCategory() { + icon = new DoubleItemIcon(() -> new ItemStack(AllBlocks.MECHANICAL_PRESS.get()), + () -> new ItemStack(AllBlocks.BASIN.get())); + press = new AnimatedPress(true); + } + + @Override + public IDrawable getIcon() { + return icon; + } + + @Override + public ResourceLocation getUid() { + return ID; + } + + @SuppressWarnings("unchecked") + @Override + public Class> getRecipeClass() { + return (Class>) IRecipe.class; + } + + @Override + public String getTitle() { + return Lang.translate("recipe.packing"); + } + + @Override + public IDrawable getBackground() { + return background; + } + + @Override + public void setIngredients(IRecipe recipe, IIngredients ingredients) { + ingredients.setInputIngredients(recipe.getIngredients()); + ingredients.setOutput(VanillaTypes.ITEM, recipe.getRecipeOutput()); + } + + @Override + public void setRecipe(IRecipeLayout recipeLayout, IRecipe recipe, IIngredients ingredients) { + IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks(); + int i = 0; + + NonNullList ingredients2 = recipe.getIngredients(); + int size = ingredients2.size(); + int rows = size == 4 ? 2 : 3; + while (i < size) { + Ingredient ingredient = ingredients2.get(i); + itemStacks.init(i, true, (rows == 2 ? 26 : 17) + (i % rows) * 19, 50 - (i / rows) * 19); + itemStacks.set(i, Arrays.asList(ingredient.getMatchingStacks())); + i++; + } + + itemStacks.init(i, false, 141, 50); + itemStacks.set(i, recipe.getRecipeOutput()); + } + + @Override + public void draw(IRecipe recipe, double mouseX, double mouseY) { + NonNullList ingredients2 = recipe.getIngredients(); + int size = ingredients2.size(); + int rows = size == 4 ? 2 : 3; + for (int i = 0; i < size; i++) { + ScreenResources.JEI_SLOT.draw((rows == 2 ? 26 : 17) + (i % rows) * 19, 50 - (i / rows) * 19); + } + ScreenResources.JEI_SLOT.draw(141, 50); + ScreenResources.JEI_DOWN_ARROW.draw(136, 32); + ScreenResources.JEI_SHADOW.draw(81, 57); + press.draw(getBackground().getWidth() / 2 + 20, 8); + } + +} diff --git a/src/main/java/com/simibubi/create/compat/jei/PressingCategory.java b/src/main/java/com/simibubi/create/compat/jei/PressingCategory.java index 8ec9aa309..d3b5c9524 100644 --- a/src/main/java/com/simibubi/create/compat/jei/PressingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/PressingCategory.java @@ -30,7 +30,7 @@ public class PressingCategory implements IRecipeCategory { public PressingCategory() { icon = new DoubleItemIcon(() -> new ItemStack(AllBlocks.MECHANICAL_PRESS.get()), () -> new ItemStack(AllItems.IRON_SHEET.get())); - press = new AnimatedPress(); + press = new AnimatedPress(false); } @Override @@ -75,6 +75,8 @@ public class PressingCategory implements IRecipeCategory { itemStacks.init(outputIndex + 1, false, 131 + 19 * outputIndex, 50); itemStacks.set(outputIndex + 1, results.get(outputIndex).getStack()); } + + CreateJEI.addStochasticTooltip(itemStacks, results); } @Override @@ -83,8 +85,9 @@ public class PressingCategory implements IRecipeCategory { ScreenResources.JEI_SLOT.draw(131, 50); if (recipe.getRollableResults().size() > 1) ScreenResources.JEI_SLOT.draw(131 + 19, 50); + ScreenResources.JEI_SHADOW.draw(61, 41); ScreenResources.JEI_LONG_ARROW.draw(52, 54); - press.draw(getBackground().getWidth() / 2, 20); + press.draw(getBackground().getWidth() / 2, 8); } } diff --git a/src/main/java/com/simibubi/create/compat/jei/SawingCategory.java b/src/main/java/com/simibubi/create/compat/jei/SawingCategory.java new file mode 100644 index 000000000..858a24c72 --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/jei/SawingCategory.java @@ -0,0 +1,98 @@ +package com.simibubi.create.compat.jei; + +import java.util.Arrays; +import java.util.List; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.Create; +import com.simibubi.create.ScreenResources; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.modules.contraptions.components.saw.CuttingRecipe; +import com.simibubi.create.modules.contraptions.processing.StochasticOutput; + +import mezz.jei.api.constants.VanillaTypes; +import mezz.jei.api.gui.IRecipeLayout; +import mezz.jei.api.gui.drawable.IDrawable; +import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; +import mezz.jei.api.ingredients.IIngredients; +import mezz.jei.api.recipe.category.IRecipeCategory; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.util.ResourceLocation; + +public class SawingCategory implements IRecipeCategory { + + private AnimatedSaw saw; + private static ResourceLocation ID = new ResourceLocation(Create.ID, "sawing"); + private IDrawable icon; + private IDrawable background = new EmptyBackground(177, 70); + + public SawingCategory() { + icon = new DoubleItemIcon(() -> new ItemStack(AllBlocks.SAW.get()), () -> new ItemStack(Items.OAK_LOG)); + saw = new AnimatedSaw(); + } + + @Override + public IDrawable getIcon() { + return icon; + } + + @Override + public ResourceLocation getUid() { + return ID; + } + + @Override + public Class getRecipeClass() { + return CuttingRecipe.class; + } + + @Override + public String getTitle() { + return Lang.translate("recipe.sawing"); + } + + @Override + public IDrawable getBackground() { + return background; + } + + @Override + public void setIngredients(CuttingRecipe recipe, IIngredients ingredients) { + ingredients.setInputIngredients(recipe.getIngredients()); + ingredients.setOutputs(VanillaTypes.ITEM, recipe.getPossibleOutputs()); + } + + @Override + public void setRecipe(IRecipeLayout recipeLayout, CuttingRecipe recipe, IIngredients ingredients) { + IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks(); + itemStacks.init(0, true, 43, 4); + itemStacks.set(0, Arrays.asList(recipe.getIngredients().get(0).getMatchingStacks())); + + List results = recipe.getRollableResults(); + for (int outputIndex = 0; outputIndex < results.size(); outputIndex++) { + int xOffset = outputIndex % 2 == 0 ? 0 : 19; + int yOffset = (outputIndex / 2) * -19; + + itemStacks.init(outputIndex + 1, false, 117 + xOffset, 47 + yOffset); + itemStacks.set(outputIndex + 1, results.get(outputIndex).getStack()); + } + + CreateJEI.addStochasticTooltip(itemStacks, results); + } + + @Override + public void draw(CuttingRecipe recipe, double mouseX, double mouseY) { + ScreenResources.JEI_SLOT.draw(43, 4); + int size = recipe.getRollableResults().size(); + for (int i = 0; i < size; i++) { + int xOffset = i % 2 == 0 ? 0 : 19; + int yOffset = (i / 2) * -19; + ScreenResources.JEI_SLOT.draw(117 + xOffset, 47 + yOffset); + } + ScreenResources.JEI_DOWN_ARROW.draw(70, 6); + ScreenResources.JEI_SHADOW.draw(58, 55); + saw.draw(72, 35); + } + +} diff --git a/src/main/java/com/simibubi/create/compat/jei/SplashingCategory.java b/src/main/java/com/simibubi/create/compat/jei/SplashingCategory.java index e9a600e2f..e9ccd4f27 100644 --- a/src/main/java/com/simibubi/create/compat/jei/SplashingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/SplashingCategory.java @@ -23,7 +23,6 @@ import net.minecraft.block.FlowingFluidBlock; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.util.ResourceLocation; -import net.minecraft.util.text.TextFormatting; public class SplashingCategory extends ProcessingViaFanCategory { @@ -83,14 +82,7 @@ public class SplashingCategory extends ProcessingViaFanCategory itemStacks.set(outputIndex + 1, results.get(outputIndex).getStack()); } - itemStacks.addTooltipCallback((slotIndex, input, ingredient, tooltip) -> { - if (input) - return; - StochasticOutput output = results.get(slotIndex - 1); - if (output.getChance() != 1) - tooltip.add(1, TextFormatting.GOLD - + Lang.translate("recipe.processing.chance", (int) (output.getChance() * 100))); - }); + CreateJEI.addStochasticTooltip(itemStacks, results); } @Override diff --git a/src/main/java/com/simibubi/create/foundation/item/ItemHelper.java b/src/main/java/com/simibubi/create/foundation/item/ItemHelper.java index 93fb54d8f..74926ea3b 100644 --- a/src/main/java/com/simibubi/create/foundation/item/ItemHelper.java +++ b/src/main/java/com/simibubi/create/foundation/item/ItemHelper.java @@ -3,7 +3,12 @@ package com.simibubi.create.foundation.item; import java.util.ArrayList; import java.util.List; +import org.apache.commons.lang3.mutable.MutableInt; +import org.apache.commons.lang3.tuple.Pair; + import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.util.NonNullList; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.ItemHandlerHelper; @@ -33,7 +38,7 @@ public class ItemHelper { if (stack.getCount() > 0) stacks.add(stack); } - + public static boolean isSameInventory(IItemHandler h1, IItemHandler h2) { if (h1 == null || h2 == null) return false; @@ -46,4 +51,38 @@ public class ItemHelper { return true; } + public static List> condenseIngredients(NonNullList recipeIngredients) { + List> actualIngredients = new ArrayList<>(); + Ingredients: for (Ingredient igd : recipeIngredients) { + for (Pair pair : actualIngredients) { + ItemStack[] stacks1 = pair.getKey().getMatchingStacks(); + ItemStack[] stacks2 = igd.getMatchingStacks(); + if (stacks1.length == stacks2.length) { + for (int i = 0; i <= stacks1.length; i++) { + if (i == stacks1.length) { + pair.getValue().increment(); + continue Ingredients; + } + if (!ItemStack.areItemsEqual(stacks1[i], stacks2[i])) + break; + } + } + } + actualIngredients.add(Pair.of(igd, new MutableInt(1))); + } + return actualIngredients; + } + + public static boolean matchIngredients(Ingredient i1, Ingredient i2) { + ItemStack[] stacks1 = i1.getMatchingStacks(); + ItemStack[] stacks2 = i2.getMatchingStacks(); + if (stacks1.length == stacks2.length) { + for (int i = 0; i < stacks1.length; i++) + if (!ItemStack.areItemsEqual(stacks1[i], stacks2[i])) + return false; + return true; + } + return false; + } + } diff --git a/src/main/java/com/simibubi/create/foundation/utility/recipe/RecipeFinder.java b/src/main/java/com/simibubi/create/foundation/utility/recipe/RecipeFinder.java index 6f4804bae..fa3b06eea 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/recipe/RecipeFinder.java +++ b/src/main/java/com/simibubi/create/foundation/utility/recipe/RecipeFinder.java @@ -5,7 +5,6 @@ import java.util.List; import java.util.concurrent.ExecutionException; import java.util.function.Predicate; import java.util.stream.Collectors; -import java.util.stream.Stream; import javax.annotation.Nullable; @@ -13,7 +12,6 @@ import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import net.minecraft.item.crafting.IRecipe; -import net.minecraft.item.crafting.IRecipeType; import net.minecraft.world.World; /** @@ -26,38 +24,7 @@ import net.minecraft.world.World; */ public class RecipeFinder { - private static Cache cachedSearches = CacheBuilder.newBuilder().build(); - - public static class StartedSearch { - List> findings; - - public StartedSearch(List> findings) { - this.findings = findings; - } - - public RecipeStream> search() { - return new RecipeStream<>(findings.stream()); - } - - public static class RecipeStream> { - Stream stream; - - public RecipeStream(Stream stream) { - this.stream = stream; - } - - @SuppressWarnings("unchecked") - public > RecipeStream assumeType(IRecipeType type) { - return (RecipeStream) this; - } - - public List filter(Predicate condition) { - return stream.filter(condition).collect(Collectors.toList()); - } - - } - - } + private static Cache>> cachedSearches = CacheBuilder.newBuilder().build(); /** * Find all IRecipes matching the condition predicate. If this search is made @@ -69,7 +36,7 @@ public class RecipeFinder { * @param conditions * @return A started search to continue with more specific conditions. */ - public static StartedSearch get(@Nullable Object cacheKey, World world, Predicate> conditions) { + public static List> get(@Nullable Object cacheKey, World world, Predicate> conditions) { if (cacheKey == null) return startSearch(world, conditions); @@ -79,13 +46,13 @@ public class RecipeFinder { e.printStackTrace(); } - return new StartedSearch(Collections.emptyList()); + return Collections.emptyList(); } - private static StartedSearch startSearch(World world, Predicate> conditions) { + private static List> startSearch(World world, Predicate> conditions) { List> list = world.getRecipeManager().getRecipes().stream().filter(conditions) .collect(Collectors.toList()); - return new StartedSearch(list); + return list; } } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/mixer/MechanicalMixerTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/components/mixer/MechanicalMixerTileEntity.java index 3142b852a..7adff8303 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/mixer/MechanicalMixerTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/mixer/MechanicalMixerTileEntity.java @@ -3,68 +3,49 @@ package com.simibubi.create.modules.contraptions.components.mixer; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; -import java.util.stream.Collectors; import com.simibubi.create.AllPackets; +import com.simibubi.create.AllRecipes; import com.simibubi.create.AllTileEntities; import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.modules.contraptions.base.KineticTileEntity; -import com.simibubi.create.modules.contraptions.processing.BasinTileEntity; +import com.simibubi.create.modules.contraptions.components.press.MechanicalPressTileEntity; +import com.simibubi.create.modules.contraptions.processing.BasinOperatingTileEntity; import com.simibubi.create.modules.contraptions.processing.BasinTileEntity.BasinInventory; import net.minecraft.inventory.IInventory; -import net.minecraft.item.BucketItem; import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; import net.minecraft.item.crafting.IRecipe; import net.minecraft.item.crafting.IRecipeSerializer; import net.minecraft.item.crafting.Ingredient; -import net.minecraft.item.crafting.ShapelessRecipe; import net.minecraft.nbt.CompoundNBT; import net.minecraft.particles.ItemParticleData; import net.minecraft.particles.ParticleTypes; -import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Direction.Axis; import net.minecraft.util.NonNullList; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.ItemHandlerHelper; -public class MechanicalMixerTileEntity extends KineticTileEntity { +public class MechanicalMixerTileEntity extends BasinOperatingTileEntity { + + private static Object shapelessOrMixingRecipesKey = new Object(); public int runningTicks; public int processingTicks; public boolean running; - public boolean checkBasin; - public boolean basinRemoved; public int minIngredients; public int currentValue; public int lastModified; - private ShapelessRecipe lastRecipe; - private LazyOptional basinInv = LazyOptional.empty(); - private List inputs; - public MechanicalMixerTileEntity() { super(AllTileEntities.MECHANICAL_MIXER.type); - checkBasin = true; minIngredients = currentValue = 1; lastModified = -1; processingTicks = -1; } - @Override - public void onSpeedChanged(float prevSpeed) { - super.onSpeedChanged(prevSpeed); - checkBasin = true; - } - public float getRenderedHeadOffset(float partialTicks) { int localTick = 0; float offset = 0; @@ -132,7 +113,6 @@ public class MechanicalMixerTileEntity extends KineticTileEntity { @Override public void tick() { - super.tick(); if (world.isRemote && lastModified != -1) { if (lastModified++ > 10) { @@ -141,20 +121,14 @@ public class MechanicalMixerTileEntity extends KineticTileEntity { } } - if (runningTicks == 40) { + super.tick(); + + if (runningTicks >= 40) { running = false; runningTicks = 0; return; } - if (basinRemoved) { - basinRemoved = false; - if (running) { - runningTicks = 40; - return; - } - } - float speed = Math.abs(getSpeed()); if (running) { if (world.isRemote && runningTicks == 20) @@ -163,58 +137,21 @@ public class MechanicalMixerTileEntity extends KineticTileEntity { if (!world.isRemote && runningTicks == 20) { if (processingTicks < 0) { processingTicks = (MathHelper.log2((int) (8000 / speed))) * 15 + 1; - return; - } - processingTicks--; - if (processingTicks == 0) { - runningTicks++; - processingTicks = -1; - applyRecipe(); - sendData(); + } else { + processingTicks--; + if (processingTicks == 0) { + runningTicks++; + processingTicks = -1; + applyBasinRecipe(); + sendData(); + } } } if (runningTicks != 20) runningTicks++; - - return; } - if (!isSpeedRequirementFulfilled()) - return; - if (!checkBasin) - return; - checkBasin = false; - TileEntity basinTE = world.getTileEntity(pos.down(2)); - if (basinTE == null || !(basinTE instanceof BasinTileEntity)) - return; - if (!basinInv.isPresent()) - basinInv = basinTE.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY); - if (!basinInv.isPresent()) - return; - - if (world.isRemote) - return; - - gatherInputs(); - if (matchRecipe(lastRecipe)) { - running = true; - runningTicks = 0; - sendData(); - return; - } - - List> shapelessRecipe = world.getRecipeManager().getRecipes().parallelStream() - .filter(recipe -> recipe.getSerializer() == IRecipeSerializer.CRAFTING_SHAPELESS) - .filter(this::matchRecipe).sorted((r1, r2) -> r1.getIngredients().size() - r2.getIngredients().size()) - .collect(Collectors.toList()); - if (shapelessRecipe.isEmpty()) - return; - - running = true; - runningTicks = 0; - lastRecipe = (ShapelessRecipe) shapelessRecipe.get(0); - sendData(); } public void renderParticles() { @@ -240,64 +177,20 @@ public class MechanicalMixerTileEntity extends KineticTileEntity { } } - public void gatherInputs() { - BasinInventory inv = (BasinInventory) basinInv.orElse(null); - inputs = new ArrayList<>(); - IItemHandlerModifiable inputHandler = inv.getInputHandler(); - for (int slot = 0; slot < inputHandler.getSlots(); ++slot) { - ItemStack itemstack = inputHandler.extractItem(slot, inputHandler.getSlotLimit(slot), true); - if (!itemstack.isEmpty()) { - inputs.add(itemstack); - } - } + @Override + protected boolean matchStaticFilters(IRecipe r) { + return (r.getSerializer() == IRecipeSerializer.CRAFTING_SHAPELESS || r.getType() == AllRecipes.MIXING.type) + && !MechanicalPressTileEntity.canCompress(r.getIngredients()); } - public void applyRecipe() { - if (lastRecipe == null) - return; - if (!basinInv.isPresent()) - return; - - BasinInventory inv = (BasinInventory) basinInv.orElse(null); - if (inv == null) - return; - - IItemHandlerModifiable inputs = inv.getInputHandler(); - IItemHandlerModifiable outputs = inv.getOutputHandler(); - int buckets = 0; - Ingredients: for (Ingredient ingredient : lastRecipe.getIngredients()) { - for (int slot = 0; slot < inputs.getSlots(); slot++) { - if (!ingredient.test(inputs.extractItem(slot, 1, true))) - continue; - ItemStack extracted = inputs.extractItem(slot, 1, false); - if (extracted.getItem() instanceof BucketItem) - buckets++; - continue Ingredients; - } - // something wasn't found - return; - } - - ItemHandlerHelper.insertItemStacked(outputs, lastRecipe.getRecipeOutput().copy(), false); - if (buckets > 0) - ItemHandlerHelper.insertItemStacked(outputs, new ItemStack(Items.BUCKET, buckets), false); - - // Continue mixing - gatherInputs(); - if (matchRecipe(lastRecipe)) { - runningTicks = 20; - sendData(); - } - } - - public boolean matchRecipe(IRecipe recipe) { - if (!(recipe instanceof ShapelessRecipe)) + @Override + protected boolean matchBasinRecipe(IRecipe recipe) { + if (recipe == null) return false; if (recipe.getIngredients().size() < minIngredients) return false; - ShapelessRecipe shapelessRecipe = (ShapelessRecipe) recipe; - NonNullList ingredients = shapelessRecipe.getIngredients(); + NonNullList ingredients = recipe.getIngredients(); if (!ingredients.stream().allMatch(Ingredient::isSimple)) return false; @@ -321,4 +214,33 @@ public class MechanicalMixerTileEntity extends KineticTileEntity { return true; } + @Override + public void startProcessingBasin() { + if (running) + return; + super.startProcessingBasin(); + running = true; + runningTicks = 0; + } + + @Override + public boolean continueWithPreviousRecipe() { + runningTicks = 20; + return true; + } + + @Override + protected void basinRemoved() { + super.basinRemoved(); + if (running) { + runningTicks = 40; + running = false; + } + } + + @Override + protected Object getRecipeCacheKey() { + return shapelessOrMixingRecipesKey; + } + } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/press/MechanicalPressBlock.java b/src/main/java/com/simibubi/create/modules/contraptions/components/press/MechanicalPressBlock.java index 82ffacefc..476c1235f 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/press/MechanicalPressBlock.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/press/MechanicalPressBlock.java @@ -11,6 +11,7 @@ import com.simibubi.create.foundation.block.SyncedTileEntity; import com.simibubi.create.foundation.item.ItemHelper; import com.simibubi.create.foundation.utility.AllShapes; import com.simibubi.create.modules.contraptions.base.HorizontalKineticBlock; +import com.simibubi.create.modules.contraptions.components.press.MechanicalPressTileEntity.Mode; import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState; import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.IBeltAttachment; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock; @@ -62,7 +63,7 @@ public class MechanicalPressBlock extends HorizontalKineticBlock if (worldIn.isBlockPowered(pos)) { if (!te.finished && !te.running && te.getSpeed() != 0) - te.start(false); + te.start(Mode.WORLD); } else { te.finished = false; } @@ -139,7 +140,7 @@ public class MechanicalPressBlock extends HorizontalKineticBlock return false; state.processingDuration = 1; - pressTe.start(true); + pressTe.start(Mode.BELT); return true; } @@ -156,6 +157,10 @@ public class MechanicalPressBlock extends HorizontalKineticBlock if (pressTe.running) { if (pressTe.runningTicks == 30) { Optional recipe = pressTe.getRecipe(transportedStack.stack); + + pressTe.pressedItems.clear(); + pressTe.pressedItems.add(transportedStack.stack); + if (!recipe.isPresent()) return false; ItemStack out = recipe.get().getRecipeOutput().copy(); @@ -167,6 +172,7 @@ public class MechanicalPressBlock extends HorizontalKineticBlock TileEntity controllerTE = te.getWorld().getTileEntity(te.getController()); if (controllerTE != null && controllerTE instanceof BeltTileEntity) ((SyncedTileEntity) controllerTE).sendData(); + pressTe.sendData(); } return true; } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/press/MechanicalPressTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/components/press/MechanicalPressTileEntity.java index 0f51edba6..204cfe759 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/press/MechanicalPressTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/press/MechanicalPressTileEntity.java @@ -1,31 +1,43 @@ package com.simibubi.create.modules.contraptions.components.press; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; import com.simibubi.create.AllRecipes; import com.simibubi.create.AllTileEntities; +import com.simibubi.create.foundation.item.ItemHelper; import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.modules.contraptions.base.KineticTileEntity; -import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity; -import com.simibubi.create.modules.contraptions.relays.belt.TransportedItemStack; +import com.simibubi.create.modules.contraptions.processing.BasinOperatingTileEntity; +import com.simibubi.create.modules.contraptions.processing.BasinTileEntity.BasinInventory; import com.simibubi.create.modules.logistics.InWorldProcessing; import net.minecraft.entity.Entity; import net.minecraft.entity.item.ItemEntity; +import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.ICraftingRecipe; +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.item.crafting.Ingredient; import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.ListNBT; import net.minecraft.particles.ItemParticleData; import net.minecraft.particles.ParticleTypes; -import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.NonNullList; import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundEvents; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; +import net.minecraftforge.common.util.Constants.NBT; +import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.items.wrapper.RecipeWrapper; -public class MechanicalPressTileEntity extends KineticTileEntity { +public class MechanicalPressTileEntity extends BasinOperatingTileEntity { + + private static Object compressingRecipesKey = new Object(); + public List pressedItems = new ArrayList<>(); public static class PressingInv extends RecipeWrapper { public PressingInv() { @@ -33,20 +45,33 @@ public class MechanicalPressTileEntity extends KineticTileEntity { } } + enum Mode { + WORLD(1), BELT(19f / 16f), BASIN(22f / 16f) + + ; + + float headOffset; + + private Mode(float headOffset) { + this.headOffset = headOffset; + } + } + private static PressingInv pressingInv = new PressingInv(); public int runningTicks; public boolean running; - public boolean beltMode; + public Mode mode; public boolean finished; public MechanicalPressTileEntity() { super(AllTileEntities.MECHANICAL_PRESS.type); + mode = Mode.WORLD; } @Override public void read(CompoundNBT compound) { running = compound.getBoolean("Running"); - beltMode = compound.getBoolean("OnBelt"); + mode = Mode.values()[compound.getInt("Mode")]; finished = compound.getBoolean("Finished"); runningTicks = compound.getInt("Ticks"); super.read(compound); @@ -55,37 +80,67 @@ public class MechanicalPressTileEntity extends KineticTileEntity { @Override public CompoundNBT write(CompoundNBT compound) { compound.putBoolean("Running", running); - compound.putBoolean("OnBelt", beltMode); + compound.putInt("Mode", mode.ordinal()); compound.putBoolean("Finished", finished); compound.putInt("Ticks", runningTicks); return super.write(compound); } + @Override + public CompoundNBT writeToClient(CompoundNBT tag) { + ListNBT particleItems = new ListNBT(); + pressedItems.forEach(stack -> particleItems.add(stack.serializeNBT())); + tag.put("ParticleItems", particleItems); + return super.writeToClient(tag); + } + + @Override + public void readClientUpdate(CompoundNBT tag) { + super.readClientUpdate(tag); + ListNBT particleItems = tag.getList("ParticleItems", NBT.TAG_COMPOUND); + particleItems.forEach(nbt -> pressedItems.add(ItemStack.read((CompoundNBT) nbt))); + spawnParticles(); + } + @Override public AxisAlignedBB getRenderBoundingBox() { - return new AxisAlignedBB(pos).expand(0, -1.5, 0); + return new AxisAlignedBB(pos).expand(0, -1.5, 0).expand(0, 1, 0); } public float getRenderedHeadOffset(float partialTicks) { if (running) { if (runningTicks < 40) { float num = (runningTicks - 1 + partialTicks) / 30f; - return MathHelper.clamp(num * num * num, 0, beltMode ? 1 + 3 / 16f : 1); + return MathHelper.clamp(num * num * num, 0, mode.headOffset); } if (runningTicks >= 40) { - return MathHelper.clamp(((60 - runningTicks) + 1 - partialTicks) / 20f, 0, beltMode ? 1 + 3 / 16f : 1); + return MathHelper.clamp(((60 - runningTicks) + 1 - partialTicks) / 20f * mode.headOffset, 0, + mode.headOffset); } } return 0; } - public void start(boolean onBelt) { - beltMode = onBelt; + public void start(Mode mode) { + this.mode = mode; running = true; runningTicks = 0; + pressedItems.clear(); sendData(); } + public boolean inWorld() { + return mode == Mode.WORLD; + } + + public boolean onBelt() { + return mode == Mode.BELT; + } + + public boolean onBasin() { + return mode == Mode.BASIN; + } + @Override public void tick() { super.tick(); @@ -95,16 +150,18 @@ public class MechanicalPressTileEntity extends KineticTileEntity { if (runningTicks == 30) { - if (!beltMode) { - AxisAlignedBB bb = new AxisAlignedBB(pos.down(beltMode ? 2 : 1)); + if (inWorld()) { + AxisAlignedBB bb = new AxisAlignedBB(pos.down(1)); + pressedItems.clear(); for (Entity entity : world.getEntitiesWithinAABBExcludingEntity(null, bb)) { if (!(entity instanceof ItemEntity)) continue; ItemEntity itemEntity = (ItemEntity) entity; - makeParticleEffect(entity.getPositionVec(), itemEntity.getItem()); if (!world.isRemote) { + pressedItems.add(itemEntity.getItem()); + sendData(); Optional recipe = getRecipe(itemEntity.getItem()); if (recipe.isPresent()) InWorldProcessing.applyRecipeOn(itemEntity, recipe.get()); @@ -112,18 +169,22 @@ public class MechanicalPressTileEntity extends KineticTileEntity { } } - if (beltMode && world.isRemote) { - TileEntity te = world.getTileEntity(pos.down(2)); - if (te != null && te instanceof BeltTileEntity) { - BeltTileEntity beltTE = (BeltTileEntity) te; - TileEntity controller = world.getTileEntity(beltTE.getController()); - if (controller != null && controller instanceof BeltTileEntity) { - TransportedItemStack stackAtOffset = ((BeltTileEntity) controller).getInventory() - .getStackAtOffset(beltTE.index); - if (stackAtOffset != null) - makeParticleEffect(VecHelper.getCenterOf(pos.down(2)).add(0, 5 / 16f, 0), - stackAtOffset.stack); + if (onBasin()) { + if (!world.isRemote) { + pressedItems.clear(); + applyBasinRecipe(); + IItemHandler orElse = basinInv.orElse(null); + if (basinInv.isPresent() && orElse instanceof BasinInventory) { + BasinInventory inv = (BasinInventory) orElse; + + for (int slot = 0; slot < inv.getInputHandler().getSlots(); slot++) { + ItemStack stackInSlot = inv.getStackInSlot(slot); + if (stackInSlot.isEmpty()) + continue; + pressedItems.add(stackInSlot); + } } + sendData(); } } @@ -136,9 +197,18 @@ public class MechanicalPressTileEntity extends KineticTileEntity { if (!world.isRemote && runningTicks > 60) { finished = true; - if (!beltMode) + if (inWorld()) finished = world.isBlockPowered(pos); running = false; + + if (onBasin()) { + gatherInputs(); + if (matchBasinRecipe(lastRecipe)) { + startProcessingBasin(); + } + } + + pressedItems.clear(); sendData(); return; } @@ -146,12 +216,41 @@ public class MechanicalPressTileEntity extends KineticTileEntity { runningTicks++; } - public void makeParticleEffect(Vec3d pos, ItemStack stack) { + protected void spawnParticles() { + if (pressedItems.isEmpty()) + return; + + if (mode == Mode.BASIN) { + pressedItems.forEach(stack -> makeCompactingParticleEffect(VecHelper.getCenterOf(pos.down(2)), stack)); + } + if (mode == Mode.BELT) { + pressedItems.forEach( + stack -> makePressingParticleEffect(VecHelper.getCenterOf(pos.down(2)).add(0, 8 / 16f, 0), stack)); + } + if (mode == Mode.WORLD) { + pressedItems.forEach( + stack -> makePressingParticleEffect(VecHelper.getCenterOf(pos.down(1)).add(0, -1 / 4f, 0), stack)); + } + + pressedItems.clear(); + } + + public void makePressingParticleEffect(Vec3d pos, ItemStack stack) { if (world.isRemote) { for (int i = 0; i < 20; i++) { - Vec3d motion = VecHelper.offsetRandomly(Vec3d.ZERO, world.rand, .25f).mul(1, 0, 1); + Vec3d motion = VecHelper.offsetRandomly(Vec3d.ZERO, world.rand, .125f).mul(1, 0, 1); + world.addParticle(new ItemParticleData(ParticleTypes.ITEM, stack), pos.x, pos.y - .25f, pos.z, motion.x, + motion.y + .125f, motion.z); + } + } + } + + public void makeCompactingParticleEffect(Vec3d pos, ItemStack stack) { + if (world.isRemote) { + for (int i = 0; i < 20; i++) { + Vec3d motion = VecHelper.offsetRandomly(Vec3d.ZERO, world.rand, .175f).mul(1, 0, 1); world.addParticle(new ItemParticleData(ParticleTypes.ITEM, stack), pos.x, pos.y, pos.z, motion.x, - motion.y, motion.z); + motion.y + .25f, motion.z); } } } @@ -163,4 +262,59 @@ public class MechanicalPressTileEntity extends KineticTileEntity { return recipe; } + public static boolean canCompress(NonNullList ingredients) { + return (ingredients.size() == 4 || ingredients.size() == 9) + && ItemHelper.condenseIngredients(ingredients).size() == 1; + } + + @Override + protected boolean matchStaticFilters(IRecipe recipe) { + return recipe instanceof ICraftingRecipe && canCompress(recipe.getIngredients()); + } + + @Override + protected boolean matchBasinRecipe(IRecipe recipe) { + if (recipe == null) + return false; + + NonNullList ingredients = recipe.getIngredients(); + if (!ingredients.stream().allMatch(Ingredient::isSimple)) + return false; + + List remaining = new ArrayList<>(); + inputs.forEach(stack -> remaining.add(stack.copy())); + + Ingredients: for (Ingredient ingredient : ingredients) { + for (ItemStack stack : remaining) { + if (stack.isEmpty()) + continue; + if (ingredient.test(stack)) { + stack.shrink(1); + continue Ingredients; + } + } + return false; + } + return true; + } + + @Override + protected Object getRecipeCacheKey() { + return compressingRecipesKey; + } + + @Override + public void startProcessingBasin() { + if (running) + return; + super.startProcessingBasin(); + start(Mode.BASIN); + } + + @Override + protected void basinRemoved() { + pressedItems.clear(); + super.basinRemoved(); + } + } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/saw/SawTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/components/saw/SawTileEntity.java index 416014972..fec1150ea 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/saw/SawTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/saw/SawTileEntity.java @@ -5,8 +5,8 @@ import static com.simibubi.create.modules.contraptions.components.saw.SawBlock.R import java.util.LinkedList; import java.util.List; import java.util.Random; +import java.util.stream.Collectors; -import com.google.common.base.Predicates; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllRecipes; import com.simibubi.create.AllTileEntities; @@ -16,8 +16,6 @@ import com.simibubi.create.foundation.utility.TreeCutter.Tree; import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.recipe.RecipeConditions; import com.simibubi.create.foundation.utility.recipe.RecipeFinder; -import com.simibubi.create.foundation.utility.recipe.RecipeFinder.StartedSearch; -import com.simibubi.create.foundation.utility.recipe.RecipeFinder.StartedSearch.RecipeStream; import com.simibubi.create.modules.contraptions.components.actors.BlockBreakingKineticTileEntity; import com.simibubi.create.modules.contraptions.processing.ProcessingInventory; import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity; @@ -283,11 +281,11 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity implements IHa } private List> getRecipes() { - StartedSearch startedSearch = RecipeFinder.get(cuttingRecipesKey, world, + List> startedSearch = RecipeFinder.get(cuttingRecipesKey, world, RecipeConditions.isOfType(IRecipeType.STONECUTTING, AllRecipes.Types.CUTTING)); - RecipeStream> search = startedSearch.search(); - return search.filter(Predicates.and(RecipeConditions.outputMatchesFilter(filter), - RecipeConditions.firstIngredientMatches(inventory.getStackInSlot(0)))); + return startedSearch.stream().filter(RecipeConditions.outputMatchesFilter(filter)) + .filter(RecipeConditions.firstIngredientMatches(inventory.getStackInSlot(0))) + .collect(Collectors.toList()); } public void insertItem(ItemEntity entity) { diff --git a/src/main/java/com/simibubi/create/modules/contraptions/processing/BasinOperatingTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/processing/BasinOperatingTileEntity.java new file mode 100644 index 000000000..c2d89dc3e --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/contraptions/processing/BasinOperatingTileEntity.java @@ -0,0 +1,166 @@ +package com.simibubi.create.modules.contraptions.processing; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import com.simibubi.create.foundation.utility.recipe.RecipeFinder; +import com.simibubi.create.modules.contraptions.base.KineticTileEntity; +import com.simibubi.create.modules.contraptions.processing.BasinTileEntity.BasinInventory; + +import net.minecraft.inventory.IInventory; +import net.minecraft.item.BucketItem; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.tileentity.TileEntityType; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.ItemHandlerHelper; + +public abstract class BasinOperatingTileEntity extends KineticTileEntity { + + public boolean checkBasin; + public boolean basinRemoved; + protected IRecipe lastRecipe; + protected LazyOptional basinInv = LazyOptional.empty(); + protected List inputs; + + public BasinOperatingTileEntity(TileEntityType typeIn) { + super(typeIn); + checkBasin = true; + } + + @Override + public void onSpeedChanged(float prevSpeed) { + super.onSpeedChanged(prevSpeed); + checkBasin = true; + } + + public void gatherInputs() { + BasinInventory inv = (BasinInventory) basinInv.orElse(null); + inputs = new ArrayList<>(); + IItemHandlerModifiable inputHandler = inv.getInputHandler(); + for (int slot = 0; slot < inputHandler.getSlots(); ++slot) { + ItemStack itemstack = inputHandler.extractItem(slot, inputHandler.getSlotLimit(slot), true); + if (!itemstack.isEmpty()) { + inputs.add(itemstack); + } + } + } + + @Override + public void tick() { + super.tick(); + + if (basinRemoved) { + basinRemoved = false; + basinRemoved(); + sendData(); + return; + } + + if (!isSpeedRequirementFulfilled()) + return; + if (!isCheckingBasin()) + return; + if (!checkBasin) + return; + checkBasin = false; + TileEntity basinTE = world.getTileEntity(pos.down(2)); + if (basinTE == null || !(basinTE instanceof BasinTileEntity)) + return; + if (!basinInv.isPresent()) + basinInv = basinTE.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY); + if (!basinInv.isPresent()) + return; + + if (world.isRemote) + return; + + gatherInputs(); +// if (matchBasinRecipe(lastRecipe)) { +// startProcessingBasin(); +// sendData(); +// return; +// } + List> recipes = getMatchingRecipes(); + if (recipes.isEmpty()) + return; + + lastRecipe = recipes.get(0); + startProcessingBasin(); + sendData(); + } + + protected boolean isCheckingBasin() { + return true; + } + + public void startProcessingBasin() { + } + + public boolean continueWithPreviousRecipe() { + return true; + } + + public void applyBasinRecipe() { + if (lastRecipe == null) + return; + if (!basinInv.isPresent()) + return; + + BasinInventory inv = (BasinInventory) basinInv.orElse(null); + if (inv == null) + return; + + IItemHandlerModifiable inputs = inv.getInputHandler(); + IItemHandlerModifiable outputs = inv.getOutputHandler(); + int buckets = 0; + Ingredients: for (Ingredient ingredient : lastRecipe.getIngredients()) { + for (int slot = 0; slot < inputs.getSlots(); slot++) { + if (!ingredient.test(inputs.extractItem(slot, 1, true))) + continue; + ItemStack extracted = inputs.extractItem(slot, 1, false); + if (extracted.getItem() instanceof BucketItem) + buckets++; + continue Ingredients; + } + // something wasn't found + return; + } + + ItemHandlerHelper.insertItemStacked(outputs, lastRecipe.getRecipeOutput().copy(), false); + if (buckets > 0) + ItemHandlerHelper.insertItemStacked(outputs, new ItemStack(Items.BUCKET, buckets), false); + + // Continue mixing + gatherInputs(); + if (matchBasinRecipe(lastRecipe)) { + continueWithPreviousRecipe(); + sendData(); + } + } + + protected List> getMatchingRecipes() { + List> list = RecipeFinder.get(getRecipeCacheKey(), world, this::matchStaticFilters); + return list.stream().filter(this::matchBasinRecipe) + .sorted((r1, r2) -> -r1.getIngredients().size() + r2.getIngredients().size()) + .collect(Collectors.toList()); + } + + protected void basinRemoved() { + + } + + protected abstract boolean matchStaticFilters(IRecipe recipe); + + protected abstract boolean matchBasinRecipe(IRecipe recipe); + + protected abstract Object getRecipeCacheKey(); + +} diff --git a/src/main/java/com/simibubi/create/modules/contraptions/processing/BasinTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/processing/BasinTileEntity.java index 3c49a1ae9..5fdbf9476 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/processing/BasinTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/processing/BasinTileEntity.java @@ -2,7 +2,6 @@ package com.simibubi.create.modules.contraptions.processing; import com.simibubi.create.AllTileEntities; import com.simibubi.create.foundation.block.SyncedTileEntity; -import com.simibubi.create.modules.contraptions.components.mixer.MechanicalMixerTileEntity; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; @@ -27,7 +26,7 @@ public class BasinTileEntity extends SyncedTileEntity implements ITickableTileEn markDirty(); } }; - + public class BasinInputInventory extends RecipeWrapper { public BasinInputInventory() { super(inputInventory); @@ -99,15 +98,15 @@ public class BasinTileEntity extends SyncedTileEntity implements ITickableTileEn compound.put("OutputItems", outputInventory.serializeNBT()); return compound; } - + public void onEmptied() { TileEntity te = world.getTileEntity(pos.up(2)); if (te == null) return; - if (te instanceof MechanicalMixerTileEntity) - ((MechanicalMixerTileEntity) te).basinRemoved = true; + if (te instanceof BasinOperatingTileEntity) + ((BasinOperatingTileEntity) te).basinRemoved = true; } - + @Override public void remove() { onEmptied(); @@ -131,8 +130,8 @@ public class BasinTileEntity extends SyncedTileEntity implements ITickableTileEn TileEntity te = world.getTileEntity(pos.up(2)); if (te == null) return; - if (te instanceof MechanicalMixerTileEntity) - ((MechanicalMixerTileEntity) te).checkBasin = true; + if (te instanceof BasinOperatingTileEntity) + ((BasinOperatingTileEntity) te).checkBasin = true; } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/processing/ProcessingRecipeSerializer.java b/src/main/java/com/simibubi/create/modules/contraptions/processing/ProcessingRecipeSerializer.java index 6ba2bd8db..e69725df8 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/processing/ProcessingRecipeSerializer.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/processing/ProcessingRecipeSerializer.java @@ -43,7 +43,9 @@ public class ProcessingRecipeSerializer> results.add(new StochasticOutput(itemstack, chance)); } - int duration = JSONUtils.getInt(json, "processingTime"); + int duration = -1; + if (JSONUtils.hasField(json, "processingTime")) + duration = JSONUtils.getInt(json, "processingTime"); return this.factory.create(recipeId, s, ingredients, results, duration); } diff --git a/src/main/resources/assets/create/lang/en_us.json b/src/main/resources/assets/create/lang/en_us.json index 9bf9d1c55..8f7afcfdd 100644 --- a/src/main/resources/assets/create/lang/en_us.json +++ b/src/main/resources/assets/create/lang/en_us.json @@ -184,7 +184,11 @@ "create.recipe.smokingViaFan.fan": "Fan behind Fire", "create.recipe.blastingViaFan": "Bulk Smelting", "create.recipe.blastingViaFan.fan": "Fan behind Lava", - "create.recipe.pressing": "Mechanical Press", + "create.recipe.pressing": "Pressing", + "create.recipe.mixing": "Mixing", + "create.recipe.packing": "Compressing", + "create.recipe.sawing": "Sawing", + "create.recipe.block_cutting": "Block Cutting", "create.recipe.blockzapperUpgrade": "Handheld Blockzapper", "create.recipe.processing.chance": "%1$s%% Chance", @@ -571,7 +575,7 @@ "block.create.mechanical_mixer.tooltip.condition1": "When above Basin", "block.create.mechanical_mixer.tooltip.behaviour1": "Starts to mix items in the basin whenever all necessary ingredients are present.", "block.create.mechanical_mixer.tooltip.condition2": "When used with Wrench", - "block.create.mechanical_mixer.tooltip.behaviour2": "_Configures_ the minimum amount of _different_ _ingredients_ required before the mixer should begin. Use this option to rule out unwanted recipes with similar but less ingredients.", + "block.create.mechanical_mixer.tooltip.behaviour2": "_Configures_ the minimum amount of _total_ _ingredients_ for applied recipes. Use this option to _rule_ _out_ _unwanted_ _recipes_ with similar but less ingredients.", "block.create.mechanical_piston.tooltip": "MECHANICAL PISTON", "block.create.mechanical_piston.tooltip.summary": "A more advanced version of the _Piston,_ using _Rotational_ _Force_ to precisely move attached structures. _Piston_ _Extension_ _Poles_ at the rear define the _Range_ of this Device. Without extensions, the piston will not move. Use _Translation_ _Chassis_ to move more than a single line of blocks.", diff --git a/src/main/resources/data/create/recipes/mixing/andesite_alloy.json b/src/main/resources/data/create/recipes/mixing/andesite_alloy.json new file mode 100644 index 000000000..4b257d05d --- /dev/null +++ b/src/main/resources/data/create/recipes/mixing/andesite_alloy.json @@ -0,0 +1,18 @@ +{ + "type": "create:mixing", + "group": "minecraft:misc", + "ingredients": [ + { + "item": "minecraft:andesite" + }, + { + "item": "minecraft:iron_nugget" + } + ], + "results": [ + { + "item": "create:andesite_alloy_cube", + "count": 1 + } + ] +} \ No newline at end of file