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
This commit is contained in:
parent
9bd07d4ed0
commit
43980d550d
22 changed files with 1167 additions and 243 deletions
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,6 +14,12 @@ import net.minecraft.util.Direction.Axis;
|
||||||
|
|
||||||
public class AnimatedPress extends AnimatedKinetics {
|
public class AnimatedPress extends AnimatedKinetics {
|
||||||
|
|
||||||
|
private boolean basin;
|
||||||
|
|
||||||
|
public AnimatedPress(boolean basin) {
|
||||||
|
this.basin = basin;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getWidth() {
|
public int getWidth() {
|
||||||
return 50;
|
return 50;
|
||||||
|
@ -45,6 +51,12 @@ public class AnimatedPress extends AnimatedKinetics {
|
||||||
GlStateManager.pushMatrix();
|
GlStateManager.pushMatrix();
|
||||||
ScreenElementRenderer.renderBlock(this::head);
|
ScreenElementRenderer.renderBlock(this::head);
|
||||||
GlStateManager.popMatrix();
|
GlStateManager.popMatrix();
|
||||||
|
|
||||||
|
if (basin) {
|
||||||
|
GlStateManager.pushMatrix();
|
||||||
|
ScreenElementRenderer.renderBlock(this::basin);
|
||||||
|
GlStateManager.popMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
GlStateManager.popMatrix();
|
GlStateManager.popMatrix();
|
||||||
}
|
}
|
||||||
|
@ -79,5 +91,10 @@ public class AnimatedPress extends AnimatedKinetics {
|
||||||
return AllBlocks.MECHANICAL_PRESS_HEAD.get().getDefaultState().with(BlockStateProperties.HORIZONTAL_FACING,
|
return AllBlocks.MECHANICAL_PRESS_HEAD.get().getDefaultState().with(BlockStateProperties.HORIZONTAL_FACING,
|
||||||
Direction.EAST);
|
Direction.EAST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private BlockState basin() {
|
||||||
|
GlStateManager.translatef(0, 85, 0);
|
||||||
|
return AllBlocks.BASIN.get().getDefaultState();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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<CondensedBlockCuttingRecipe> {
|
||||||
|
|
||||||
|
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<? extends CondensedBlockCuttingRecipe> 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<ItemStack> 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<ItemStack> outputs = new ArrayList<>();
|
||||||
|
|
||||||
|
public CondensedBlockCuttingRecipe(Ingredient ingredient) {
|
||||||
|
super(new ResourceLocation(""), "", ingredient, ItemStack.EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addOutput(ItemStack stack) {
|
||||||
|
outputs.add(stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ItemStack> getOutputs() {
|
||||||
|
return outputs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<CondensedBlockCuttingRecipe> condenseRecipes(List<IRecipe<?>> stoneCuttingRecipes) {
|
||||||
|
List<CondensedBlockCuttingRecipe> 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -3,24 +3,32 @@ package com.simibubi.create.compat.jei;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.AllItems;
|
import com.simibubi.create.AllItems;
|
||||||
import com.simibubi.create.AllRecipes;
|
import com.simibubi.create.AllRecipes;
|
||||||
import com.simibubi.create.Create;
|
import com.simibubi.create.Create;
|
||||||
|
import com.simibubi.create.compat.jei.BlockCuttingCategory.CondensedBlockCuttingRecipe;
|
||||||
import com.simibubi.create.foundation.utility.Lang;
|
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.logistics.block.inventories.FlexcrateScreen;
|
||||||
import com.simibubi.create.modules.schematics.block.SchematicannonScreen;
|
import com.simibubi.create.modules.schematics.block.SchematicannonScreen;
|
||||||
|
|
||||||
import mezz.jei.api.IModPlugin;
|
import mezz.jei.api.IModPlugin;
|
||||||
import mezz.jei.api.JeiPlugin;
|
import mezz.jei.api.JeiPlugin;
|
||||||
|
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup;
|
||||||
import mezz.jei.api.registration.IGuiHandlerRegistration;
|
import mezz.jei.api.registration.IGuiHandlerRegistration;
|
||||||
import mezz.jei.api.registration.IRecipeCatalystRegistration;
|
import mezz.jei.api.registration.IRecipeCatalystRegistration;
|
||||||
import mezz.jei.api.registration.IRecipeCategoryRegistration;
|
import mezz.jei.api.registration.IRecipeCategoryRegistration;
|
||||||
import mezz.jei.api.registration.IRecipeRegistration;
|
import mezz.jei.api.registration.IRecipeRegistration;
|
||||||
import mezz.jei.api.registration.ISubtypeRegistration;
|
import mezz.jei.api.registration.ISubtypeRegistration;
|
||||||
|
import net.minecraft.block.Blocks;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.item.crafting.ICraftingRecipe;
|
||||||
import net.minecraft.item.crafting.IRecipe;
|
import net.minecraft.item.crafting.IRecipe;
|
||||||
|
import net.minecraft.item.crafting.IRecipeSerializer;
|
||||||
import net.minecraft.item.crafting.IRecipeType;
|
import net.minecraft.item.crafting.IRecipeType;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraft.util.text.StringTextComponent;
|
import net.minecraft.util.text.StringTextComponent;
|
||||||
|
@ -36,6 +44,10 @@ public class CreateJEI implements IModPlugin {
|
||||||
private PressingCategory pressingCategory;
|
private PressingCategory pressingCategory;
|
||||||
private BlastingViaFanCategory blastingCategory;
|
private BlastingViaFanCategory blastingCategory;
|
||||||
private BlockzapperUpgradeCategory blockzapperCategory;
|
private BlockzapperUpgradeCategory blockzapperCategory;
|
||||||
|
private MixingCategory mixingCategory;
|
||||||
|
private SawingCategory sawingCategory;
|
||||||
|
private BlockCuttingCategory blockCuttingCategory;
|
||||||
|
private PackingCategory packingCategory;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResourceLocation getPluginUid() {
|
public ResourceLocation getPluginUid() {
|
||||||
|
@ -49,6 +61,10 @@ public class CreateJEI implements IModPlugin {
|
||||||
smokingCategory = new SmokingViaFanCategory();
|
smokingCategory = new SmokingViaFanCategory();
|
||||||
blastingCategory = new BlastingViaFanCategory();
|
blastingCategory = new BlastingViaFanCategory();
|
||||||
blockzapperCategory = new BlockzapperUpgradeCategory();
|
blockzapperCategory = new BlockzapperUpgradeCategory();
|
||||||
|
mixingCategory = new MixingCategory();
|
||||||
|
sawingCategory = new SawingCategory();
|
||||||
|
blockCuttingCategory = new BlockCuttingCategory();
|
||||||
|
packingCategory = new PackingCategory();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -59,7 +75,8 @@ public class CreateJEI implements IModPlugin {
|
||||||
@Override
|
@Override
|
||||||
public void registerCategories(IRecipeCategoryRegistration registration) {
|
public void registerCategories(IRecipeCategoryRegistration registration) {
|
||||||
registration.addRecipeCategories(crushingCategory, splashingCategory, pressingCategory, smokingCategory,
|
registration.addRecipeCategories(crushingCategory, splashingCategory, pressingCategory, smokingCategory,
|
||||||
blastingCategory, blockzapperCategory);
|
blastingCategory, blockzapperCategory, mixingCategory, sawingCategory, blockCuttingCategory,
|
||||||
|
packingCategory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -72,6 +89,19 @@ public class CreateJEI implements IModPlugin {
|
||||||
registration.addRecipes(findRecipesByType(IRecipeType.SMOKING), smokingCategory.getUid());
|
registration.addRecipes(findRecipesByType(IRecipeType.SMOKING), smokingCategory.getUid());
|
||||||
registration.addRecipes(findRecipesByTypeExcluding(IRecipeType.SMELTING, IRecipeType.SMOKING),
|
registration.addRecipes(findRecipesByTypeExcluding(IRecipeType.SMELTING, IRecipeType.SMOKING),
|
||||||
blastingCategory.getUid());
|
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
|
@Override
|
||||||
|
@ -91,6 +121,13 @@ public class CreateJEI implements IModPlugin {
|
||||||
registration.addRecipeCatalyst(blastingFan, blastingCategory.getUid());
|
registration.addRecipeCatalyst(blastingFan, blastingCategory.getUid());
|
||||||
registration.addRecipeCatalyst(new ItemStack(AllBlocks.MECHANICAL_PRESS.get()), pressingCategory.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(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
|
@Override
|
||||||
|
@ -103,6 +140,11 @@ public class CreateJEI implements IModPlugin {
|
||||||
return findRecipesByType(recipe.type);
|
return findRecipesByType(recipe.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static List<IRecipe<?>> findRecipes(Predicate<IRecipe<?>> pred) {
|
||||||
|
return Minecraft.getInstance().world.getRecipeManager().getRecipes().stream().filter(pred)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
private static List<IRecipe<?>> findRecipesByType(IRecipeType<?> type) {
|
private static List<IRecipe<?>> findRecipesByType(IRecipeType<?> type) {
|
||||||
return Minecraft.getInstance().world.getRecipeManager().getRecipes().stream().filter(r -> r.getType() == type)
|
return Minecraft.getInstance().world.getRecipeManager().getRecipes().stream().filter(r -> r.getType() == type)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
@ -129,4 +171,15 @@ public class CreateJEI implements IModPlugin {
|
||||||
return byType;
|
return byType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void addStochasticTooltip(IGuiItemStackGroup itemStacks, List<StochasticOutput> 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)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@ import mezz.jei.api.ingredients.IIngredients;
|
||||||
import mezz.jei.api.recipe.category.IRecipeCategory;
|
import mezz.jei.api.recipe.category.IRecipeCategory;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraft.util.text.TextFormatting;
|
|
||||||
|
|
||||||
public class CrushingCategory implements IRecipeCategory<CrushingRecipe> {
|
public class CrushingCategory implements IRecipeCategory<CrushingRecipe> {
|
||||||
|
|
||||||
|
@ -78,14 +77,7 @@ public class CrushingCategory implements IRecipeCategory<CrushingRecipe> {
|
||||||
itemStacks.set(outputIndex + 1, results.get(outputIndex).getStack());
|
itemStacks.set(outputIndex + 1, results.get(outputIndex).getStack());
|
||||||
}
|
}
|
||||||
|
|
||||||
itemStacks.addTooltipCallback((slotIndex, input, ingredient, tooltip) -> {
|
CreateJEI.addStochasticTooltip(itemStacks, results);
|
||||||
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)));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
113
src/main/java/com/simibubi/create/compat/jei/MixingCategory.java
Normal file
113
src/main/java/com/simibubi/create/compat/jei/MixingCategory.java
Normal file
|
@ -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<IRecipe<?>> {
|
||||||
|
|
||||||
|
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<Ingredient> recipeIngredients = recipe.getIngredients();
|
||||||
|
List<Pair<Ingredient, MutableInt>> 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, MutableInt> ingredient = actualIngredients.get(i);
|
||||||
|
itemStacks.init(i, true, 16 + xOffset + (i % 3) * 19, 50 - (i / 3) * 19);
|
||||||
|
List<ItemStack> 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<Pair<Ingredient, MutableInt>> 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<? extends IRecipe<?>> getRecipeClass() {
|
||||||
|
return (Class<? extends IRecipe<?>>) IRecipe.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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<IRecipe<?>> {
|
||||||
|
|
||||||
|
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<? extends IRecipe<?>> getRecipeClass() {
|
||||||
|
return (Class<? extends IRecipe<?>>) 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<Ingredient> 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<Ingredient> 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -30,7 +30,7 @@ public class PressingCategory implements IRecipeCategory<PressingRecipe> {
|
||||||
public PressingCategory() {
|
public PressingCategory() {
|
||||||
icon = new DoubleItemIcon(() -> new ItemStack(AllBlocks.MECHANICAL_PRESS.get()),
|
icon = new DoubleItemIcon(() -> new ItemStack(AllBlocks.MECHANICAL_PRESS.get()),
|
||||||
() -> new ItemStack(AllItems.IRON_SHEET.get()));
|
() -> new ItemStack(AllItems.IRON_SHEET.get()));
|
||||||
press = new AnimatedPress();
|
press = new AnimatedPress(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -75,6 +75,8 @@ public class PressingCategory implements IRecipeCategory<PressingRecipe> {
|
||||||
itemStacks.init(outputIndex + 1, false, 131 + 19 * outputIndex, 50);
|
itemStacks.init(outputIndex + 1, false, 131 + 19 * outputIndex, 50);
|
||||||
itemStacks.set(outputIndex + 1, results.get(outputIndex).getStack());
|
itemStacks.set(outputIndex + 1, results.get(outputIndex).getStack());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CreateJEI.addStochasticTooltip(itemStacks, results);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -83,8 +85,9 @@ public class PressingCategory implements IRecipeCategory<PressingRecipe> {
|
||||||
ScreenResources.JEI_SLOT.draw(131, 50);
|
ScreenResources.JEI_SLOT.draw(131, 50);
|
||||||
if (recipe.getRollableResults().size() > 1)
|
if (recipe.getRollableResults().size() > 1)
|
||||||
ScreenResources.JEI_SLOT.draw(131 + 19, 50);
|
ScreenResources.JEI_SLOT.draw(131 + 19, 50);
|
||||||
|
ScreenResources.JEI_SHADOW.draw(61, 41);
|
||||||
ScreenResources.JEI_LONG_ARROW.draw(52, 54);
|
ScreenResources.JEI_LONG_ARROW.draw(52, 54);
|
||||||
press.draw(getBackground().getWidth() / 2, 20);
|
press.draw(getBackground().getWidth() / 2, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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<CuttingRecipe> {
|
||||||
|
|
||||||
|
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<? extends CuttingRecipe> 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<StochasticOutput> 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -23,7 +23,6 @@ import net.minecraft.block.FlowingFluidBlock;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.item.Items;
|
import net.minecraft.item.Items;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraft.util.text.TextFormatting;
|
|
||||||
|
|
||||||
public class SplashingCategory extends ProcessingViaFanCategory<SplashingRecipe> {
|
public class SplashingCategory extends ProcessingViaFanCategory<SplashingRecipe> {
|
||||||
|
|
||||||
|
@ -83,14 +82,7 @@ public class SplashingCategory extends ProcessingViaFanCategory<SplashingRecipe>
|
||||||
itemStacks.set(outputIndex + 1, results.get(outputIndex).getStack());
|
itemStacks.set(outputIndex + 1, results.get(outputIndex).getStack());
|
||||||
}
|
}
|
||||||
|
|
||||||
itemStacks.addTooltipCallback((slotIndex, input, ingredient, tooltip) -> {
|
CreateJEI.addStochasticTooltip(itemStacks, results);
|
||||||
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)));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -3,7 +3,12 @@ package com.simibubi.create.foundation.item;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
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.ItemStack;
|
||||||
|
import net.minecraft.item.crafting.Ingredient;
|
||||||
|
import net.minecraft.util.NonNullList;
|
||||||
import net.minecraftforge.items.IItemHandler;
|
import net.minecraftforge.items.IItemHandler;
|
||||||
import net.minecraftforge.items.ItemHandlerHelper;
|
import net.minecraftforge.items.ItemHandlerHelper;
|
||||||
|
|
||||||
|
@ -33,7 +38,7 @@ public class ItemHelper {
|
||||||
if (stack.getCount() > 0)
|
if (stack.getCount() > 0)
|
||||||
stacks.add(stack);
|
stacks.add(stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isSameInventory(IItemHandler h1, IItemHandler h2) {
|
public static boolean isSameInventory(IItemHandler h1, IItemHandler h2) {
|
||||||
if (h1 == null || h2 == null)
|
if (h1 == null || h2 == null)
|
||||||
return false;
|
return false;
|
||||||
|
@ -46,4 +51,38 @@ public class ItemHelper {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<Pair<Ingredient, MutableInt>> condenseIngredients(NonNullList<Ingredient> recipeIngredients) {
|
||||||
|
List<Pair<Ingredient, MutableInt>> actualIngredients = new ArrayList<>();
|
||||||
|
Ingredients: for (Ingredient igd : recipeIngredients) {
|
||||||
|
for (Pair<Ingredient, MutableInt> 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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import java.util.List;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
@ -13,7 +12,6 @@ import com.google.common.cache.Cache;
|
||||||
import com.google.common.cache.CacheBuilder;
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
|
||||||
import net.minecraft.item.crafting.IRecipe;
|
import net.minecraft.item.crafting.IRecipe;
|
||||||
import net.minecraft.item.crafting.IRecipeType;
|
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,38 +24,7 @@ import net.minecraft.world.World;
|
||||||
*/
|
*/
|
||||||
public class RecipeFinder {
|
public class RecipeFinder {
|
||||||
|
|
||||||
private static Cache<Object, StartedSearch> cachedSearches = CacheBuilder.newBuilder().build();
|
private static Cache<Object, List<IRecipe<?>>> cachedSearches = CacheBuilder.newBuilder().build();
|
||||||
|
|
||||||
public static class StartedSearch {
|
|
||||||
List<IRecipe<?>> findings;
|
|
||||||
|
|
||||||
public StartedSearch(List<IRecipe<?>> findings) {
|
|
||||||
this.findings = findings;
|
|
||||||
}
|
|
||||||
|
|
||||||
public RecipeStream<IRecipe<?>> search() {
|
|
||||||
return new RecipeStream<>(findings.stream());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class RecipeStream<R extends IRecipe<?>> {
|
|
||||||
Stream<R> stream;
|
|
||||||
|
|
||||||
public RecipeStream(Stream<R> stream) {
|
|
||||||
this.stream = stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <X extends IRecipe<?>> RecipeStream<X> assumeType(IRecipeType<X> type) {
|
|
||||||
return (RecipeStream<X>) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<R> filter(Predicate<R> condition) {
|
|
||||||
return stream.filter(condition).collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find all IRecipes matching the condition predicate. If this search is made
|
* Find all IRecipes matching the condition predicate. If this search is made
|
||||||
|
@ -69,7 +36,7 @@ public class RecipeFinder {
|
||||||
* @param conditions
|
* @param conditions
|
||||||
* @return A started search to continue with more specific conditions.
|
* @return A started search to continue with more specific conditions.
|
||||||
*/
|
*/
|
||||||
public static StartedSearch get(@Nullable Object cacheKey, World world, Predicate<IRecipe<?>> conditions) {
|
public static List<IRecipe<?>> get(@Nullable Object cacheKey, World world, Predicate<IRecipe<?>> conditions) {
|
||||||
if (cacheKey == null)
|
if (cacheKey == null)
|
||||||
return startSearch(world, conditions);
|
return startSearch(world, conditions);
|
||||||
|
|
||||||
|
@ -79,13 +46,13 @@ public class RecipeFinder {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new StartedSearch(Collections.emptyList());
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static StartedSearch startSearch(World world, Predicate<? super IRecipe<?>> conditions) {
|
private static List<IRecipe<?>> startSearch(World world, Predicate<? super IRecipe<?>> conditions) {
|
||||||
List<IRecipe<?>> list = world.getRecipeManager().getRecipes().stream().filter(conditions)
|
List<IRecipe<?>> list = world.getRecipeManager().getRecipes().stream().filter(conditions)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
return new StartedSearch(list);
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,68 +3,49 @@ package com.simibubi.create.modules.contraptions.components.mixer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import com.simibubi.create.AllPackets;
|
import com.simibubi.create.AllPackets;
|
||||||
|
import com.simibubi.create.AllRecipes;
|
||||||
import com.simibubi.create.AllTileEntities;
|
import com.simibubi.create.AllTileEntities;
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
|
import com.simibubi.create.modules.contraptions.components.press.MechanicalPressTileEntity;
|
||||||
import com.simibubi.create.modules.contraptions.processing.BasinTileEntity;
|
import com.simibubi.create.modules.contraptions.processing.BasinOperatingTileEntity;
|
||||||
import com.simibubi.create.modules.contraptions.processing.BasinTileEntity.BasinInventory;
|
import com.simibubi.create.modules.contraptions.processing.BasinTileEntity.BasinInventory;
|
||||||
|
|
||||||
import net.minecraft.inventory.IInventory;
|
import net.minecraft.inventory.IInventory;
|
||||||
import net.minecraft.item.BucketItem;
|
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.item.Items;
|
|
||||||
import net.minecraft.item.crafting.IRecipe;
|
import net.minecraft.item.crafting.IRecipe;
|
||||||
import net.minecraft.item.crafting.IRecipeSerializer;
|
import net.minecraft.item.crafting.IRecipeSerializer;
|
||||||
import net.minecraft.item.crafting.Ingredient;
|
import net.minecraft.item.crafting.Ingredient;
|
||||||
import net.minecraft.item.crafting.ShapelessRecipe;
|
|
||||||
import net.minecraft.nbt.CompoundNBT;
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
import net.minecraft.particles.ItemParticleData;
|
import net.minecraft.particles.ItemParticleData;
|
||||||
import net.minecraft.particles.ParticleTypes;
|
import net.minecraft.particles.ParticleTypes;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
|
||||||
import net.minecraft.util.Direction.Axis;
|
import net.minecraft.util.Direction.Axis;
|
||||||
import net.minecraft.util.NonNullList;
|
import net.minecraft.util.NonNullList;
|
||||||
import net.minecraft.util.math.AxisAlignedBB;
|
import net.minecraft.util.math.AxisAlignedBB;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import net.minecraft.util.math.Vec3d;
|
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.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 runningTicks;
|
||||||
public int processingTicks;
|
public int processingTicks;
|
||||||
public boolean running;
|
public boolean running;
|
||||||
public boolean checkBasin;
|
|
||||||
public boolean basinRemoved;
|
|
||||||
|
|
||||||
public int minIngredients;
|
public int minIngredients;
|
||||||
public int currentValue;
|
public int currentValue;
|
||||||
public int lastModified;
|
public int lastModified;
|
||||||
|
|
||||||
private ShapelessRecipe lastRecipe;
|
|
||||||
private LazyOptional<IItemHandler> basinInv = LazyOptional.empty();
|
|
||||||
private List<ItemStack> inputs;
|
|
||||||
|
|
||||||
public MechanicalMixerTileEntity() {
|
public MechanicalMixerTileEntity() {
|
||||||
super(AllTileEntities.MECHANICAL_MIXER.type);
|
super(AllTileEntities.MECHANICAL_MIXER.type);
|
||||||
checkBasin = true;
|
|
||||||
minIngredients = currentValue = 1;
|
minIngredients = currentValue = 1;
|
||||||
lastModified = -1;
|
lastModified = -1;
|
||||||
processingTicks = -1;
|
processingTicks = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSpeedChanged(float prevSpeed) {
|
|
||||||
super.onSpeedChanged(prevSpeed);
|
|
||||||
checkBasin = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getRenderedHeadOffset(float partialTicks) {
|
public float getRenderedHeadOffset(float partialTicks) {
|
||||||
int localTick = 0;
|
int localTick = 0;
|
||||||
float offset = 0;
|
float offset = 0;
|
||||||
|
@ -132,7 +113,6 @@ public class MechanicalMixerTileEntity extends KineticTileEntity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
super.tick();
|
|
||||||
|
|
||||||
if (world.isRemote && lastModified != -1) {
|
if (world.isRemote && lastModified != -1) {
|
||||||
if (lastModified++ > 10) {
|
if (lastModified++ > 10) {
|
||||||
|
@ -141,20 +121,14 @@ public class MechanicalMixerTileEntity extends KineticTileEntity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (runningTicks == 40) {
|
super.tick();
|
||||||
|
|
||||||
|
if (runningTicks >= 40) {
|
||||||
running = false;
|
running = false;
|
||||||
runningTicks = 0;
|
runningTicks = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (basinRemoved) {
|
|
||||||
basinRemoved = false;
|
|
||||||
if (running) {
|
|
||||||
runningTicks = 40;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float speed = Math.abs(getSpeed());
|
float speed = Math.abs(getSpeed());
|
||||||
if (running) {
|
if (running) {
|
||||||
if (world.isRemote && runningTicks == 20)
|
if (world.isRemote && runningTicks == 20)
|
||||||
|
@ -163,58 +137,21 @@ public class MechanicalMixerTileEntity extends KineticTileEntity {
|
||||||
if (!world.isRemote && runningTicks == 20) {
|
if (!world.isRemote && runningTicks == 20) {
|
||||||
if (processingTicks < 0) {
|
if (processingTicks < 0) {
|
||||||
processingTicks = (MathHelper.log2((int) (8000 / speed))) * 15 + 1;
|
processingTicks = (MathHelper.log2((int) (8000 / speed))) * 15 + 1;
|
||||||
return;
|
} else {
|
||||||
}
|
processingTicks--;
|
||||||
processingTicks--;
|
if (processingTicks == 0) {
|
||||||
if (processingTicks == 0) {
|
runningTicks++;
|
||||||
runningTicks++;
|
processingTicks = -1;
|
||||||
processingTicks = -1;
|
applyBasinRecipe();
|
||||||
applyRecipe();
|
sendData();
|
||||||
sendData();
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (runningTicks != 20)
|
if (runningTicks != 20)
|
||||||
runningTicks++;
|
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<IRecipe<?>> 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() {
|
public void renderParticles() {
|
||||||
|
@ -240,64 +177,20 @@ public class MechanicalMixerTileEntity extends KineticTileEntity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void gatherInputs() {
|
@Override
|
||||||
BasinInventory inv = (BasinInventory) basinInv.orElse(null);
|
protected <C extends IInventory> boolean matchStaticFilters(IRecipe<C> r) {
|
||||||
inputs = new ArrayList<>();
|
return (r.getSerializer() == IRecipeSerializer.CRAFTING_SHAPELESS || r.getType() == AllRecipes.MIXING.type)
|
||||||
IItemHandlerModifiable inputHandler = inv.getInputHandler();
|
&& !MechanicalPressTileEntity.canCompress(r.getIngredients());
|
||||||
for (int slot = 0; slot < inputHandler.getSlots(); ++slot) {
|
|
||||||
ItemStack itemstack = inputHandler.extractItem(slot, inputHandler.getSlotLimit(slot), true);
|
|
||||||
if (!itemstack.isEmpty()) {
|
|
||||||
inputs.add(itemstack);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void applyRecipe() {
|
@Override
|
||||||
if (lastRecipe == null)
|
protected <C extends IInventory> boolean matchBasinRecipe(IRecipe<C> recipe) {
|
||||||
return;
|
if (recipe == null)
|
||||||
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 <C extends IInventory> boolean matchRecipe(IRecipe<C> recipe) {
|
|
||||||
if (!(recipe instanceof ShapelessRecipe))
|
|
||||||
return false;
|
return false;
|
||||||
if (recipe.getIngredients().size() < minIngredients)
|
if (recipe.getIngredients().size() < minIngredients)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
ShapelessRecipe shapelessRecipe = (ShapelessRecipe) recipe;
|
NonNullList<Ingredient> ingredients = recipe.getIngredients();
|
||||||
NonNullList<Ingredient> ingredients = shapelessRecipe.getIngredients();
|
|
||||||
if (!ingredients.stream().allMatch(Ingredient::isSimple))
|
if (!ingredients.stream().allMatch(Ingredient::isSimple))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -321,4 +214,33 @@ public class MechanicalMixerTileEntity extends KineticTileEntity {
|
||||||
return true;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import com.simibubi.create.foundation.block.SyncedTileEntity;
|
||||||
import com.simibubi.create.foundation.item.ItemHelper;
|
import com.simibubi.create.foundation.item.ItemHelper;
|
||||||
import com.simibubi.create.foundation.utility.AllShapes;
|
import com.simibubi.create.foundation.utility.AllShapes;
|
||||||
import com.simibubi.create.modules.contraptions.base.HorizontalKineticBlock;
|
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.BeltAttachmentState;
|
||||||
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.IBeltAttachment;
|
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.IBeltAttachment;
|
||||||
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock;
|
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock;
|
||||||
|
@ -62,7 +63,7 @@ public class MechanicalPressBlock extends HorizontalKineticBlock
|
||||||
|
|
||||||
if (worldIn.isBlockPowered(pos)) {
|
if (worldIn.isBlockPowered(pos)) {
|
||||||
if (!te.finished && !te.running && te.getSpeed() != 0)
|
if (!te.finished && !te.running && te.getSpeed() != 0)
|
||||||
te.start(false);
|
te.start(Mode.WORLD);
|
||||||
} else {
|
} else {
|
||||||
te.finished = false;
|
te.finished = false;
|
||||||
}
|
}
|
||||||
|
@ -139,7 +140,7 @@ public class MechanicalPressBlock extends HorizontalKineticBlock
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
state.processingDuration = 1;
|
state.processingDuration = 1;
|
||||||
pressTe.start(true);
|
pressTe.start(Mode.BELT);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,6 +157,10 @@ public class MechanicalPressBlock extends HorizontalKineticBlock
|
||||||
if (pressTe.running) {
|
if (pressTe.running) {
|
||||||
if (pressTe.runningTicks == 30) {
|
if (pressTe.runningTicks == 30) {
|
||||||
Optional<PressingRecipe> recipe = pressTe.getRecipe(transportedStack.stack);
|
Optional<PressingRecipe> recipe = pressTe.getRecipe(transportedStack.stack);
|
||||||
|
|
||||||
|
pressTe.pressedItems.clear();
|
||||||
|
pressTe.pressedItems.add(transportedStack.stack);
|
||||||
|
|
||||||
if (!recipe.isPresent())
|
if (!recipe.isPresent())
|
||||||
return false;
|
return false;
|
||||||
ItemStack out = recipe.get().getRecipeOutput().copy();
|
ItemStack out = recipe.get().getRecipeOutput().copy();
|
||||||
|
@ -167,6 +172,7 @@ public class MechanicalPressBlock extends HorizontalKineticBlock
|
||||||
TileEntity controllerTE = te.getWorld().getTileEntity(te.getController());
|
TileEntity controllerTE = te.getWorld().getTileEntity(te.getController());
|
||||||
if (controllerTE != null && controllerTE instanceof BeltTileEntity)
|
if (controllerTE != null && controllerTE instanceof BeltTileEntity)
|
||||||
((SyncedTileEntity) controllerTE).sendData();
|
((SyncedTileEntity) controllerTE).sendData();
|
||||||
|
pressTe.sendData();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,31 +1,43 @@
|
||||||
package com.simibubi.create.modules.contraptions.components.press;
|
package com.simibubi.create.modules.contraptions.components.press;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import com.simibubi.create.AllRecipes;
|
import com.simibubi.create.AllRecipes;
|
||||||
import com.simibubi.create.AllTileEntities;
|
import com.simibubi.create.AllTileEntities;
|
||||||
|
import com.simibubi.create.foundation.item.ItemHelper;
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
|
import com.simibubi.create.modules.contraptions.processing.BasinOperatingTileEntity;
|
||||||
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
|
import com.simibubi.create.modules.contraptions.processing.BasinTileEntity.BasinInventory;
|
||||||
import com.simibubi.create.modules.contraptions.relays.belt.TransportedItemStack;
|
|
||||||
import com.simibubi.create.modules.logistics.InWorldProcessing;
|
import com.simibubi.create.modules.logistics.InWorldProcessing;
|
||||||
|
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.item.ItemEntity;
|
import net.minecraft.entity.item.ItemEntity;
|
||||||
|
import net.minecraft.inventory.IInventory;
|
||||||
import net.minecraft.item.ItemStack;
|
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.CompoundNBT;
|
||||||
|
import net.minecraft.nbt.ListNBT;
|
||||||
import net.minecraft.particles.ItemParticleData;
|
import net.minecraft.particles.ItemParticleData;
|
||||||
import net.minecraft.particles.ParticleTypes;
|
import net.minecraft.particles.ParticleTypes;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.util.NonNullList;
|
||||||
import net.minecraft.util.SoundCategory;
|
import net.minecraft.util.SoundCategory;
|
||||||
import net.minecraft.util.SoundEvents;
|
import net.minecraft.util.SoundEvents;
|
||||||
import net.minecraft.util.math.AxisAlignedBB;
|
import net.minecraft.util.math.AxisAlignedBB;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import net.minecraft.util.math.Vec3d;
|
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.ItemStackHandler;
|
||||||
import net.minecraftforge.items.wrapper.RecipeWrapper;
|
import net.minecraftforge.items.wrapper.RecipeWrapper;
|
||||||
|
|
||||||
public class MechanicalPressTileEntity extends KineticTileEntity {
|
public class MechanicalPressTileEntity extends BasinOperatingTileEntity {
|
||||||
|
|
||||||
|
private static Object compressingRecipesKey = new Object();
|
||||||
|
public List<ItemStack> pressedItems = new ArrayList<>();
|
||||||
|
|
||||||
public static class PressingInv extends RecipeWrapper {
|
public static class PressingInv extends RecipeWrapper {
|
||||||
public PressingInv() {
|
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();
|
private static PressingInv pressingInv = new PressingInv();
|
||||||
public int runningTicks;
|
public int runningTicks;
|
||||||
public boolean running;
|
public boolean running;
|
||||||
public boolean beltMode;
|
public Mode mode;
|
||||||
public boolean finished;
|
public boolean finished;
|
||||||
|
|
||||||
public MechanicalPressTileEntity() {
|
public MechanicalPressTileEntity() {
|
||||||
super(AllTileEntities.MECHANICAL_PRESS.type);
|
super(AllTileEntities.MECHANICAL_PRESS.type);
|
||||||
|
mode = Mode.WORLD;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void read(CompoundNBT compound) {
|
public void read(CompoundNBT compound) {
|
||||||
running = compound.getBoolean("Running");
|
running = compound.getBoolean("Running");
|
||||||
beltMode = compound.getBoolean("OnBelt");
|
mode = Mode.values()[compound.getInt("Mode")];
|
||||||
finished = compound.getBoolean("Finished");
|
finished = compound.getBoolean("Finished");
|
||||||
runningTicks = compound.getInt("Ticks");
|
runningTicks = compound.getInt("Ticks");
|
||||||
super.read(compound);
|
super.read(compound);
|
||||||
|
@ -55,37 +80,67 @@ public class MechanicalPressTileEntity extends KineticTileEntity {
|
||||||
@Override
|
@Override
|
||||||
public CompoundNBT write(CompoundNBT compound) {
|
public CompoundNBT write(CompoundNBT compound) {
|
||||||
compound.putBoolean("Running", running);
|
compound.putBoolean("Running", running);
|
||||||
compound.putBoolean("OnBelt", beltMode);
|
compound.putInt("Mode", mode.ordinal());
|
||||||
compound.putBoolean("Finished", finished);
|
compound.putBoolean("Finished", finished);
|
||||||
compound.putInt("Ticks", runningTicks);
|
compound.putInt("Ticks", runningTicks);
|
||||||
return super.write(compound);
|
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
|
@Override
|
||||||
public AxisAlignedBB getRenderBoundingBox() {
|
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) {
|
public float getRenderedHeadOffset(float partialTicks) {
|
||||||
if (running) {
|
if (running) {
|
||||||
if (runningTicks < 40) {
|
if (runningTicks < 40) {
|
||||||
float num = (runningTicks - 1 + partialTicks) / 30f;
|
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) {
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start(boolean onBelt) {
|
public void start(Mode mode) {
|
||||||
beltMode = onBelt;
|
this.mode = mode;
|
||||||
running = true;
|
running = true;
|
||||||
runningTicks = 0;
|
runningTicks = 0;
|
||||||
|
pressedItems.clear();
|
||||||
sendData();
|
sendData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean inWorld() {
|
||||||
|
return mode == Mode.WORLD;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean onBelt() {
|
||||||
|
return mode == Mode.BELT;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean onBasin() {
|
||||||
|
return mode == Mode.BASIN;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
super.tick();
|
super.tick();
|
||||||
|
@ -95,16 +150,18 @@ public class MechanicalPressTileEntity extends KineticTileEntity {
|
||||||
|
|
||||||
if (runningTicks == 30) {
|
if (runningTicks == 30) {
|
||||||
|
|
||||||
if (!beltMode) {
|
if (inWorld()) {
|
||||||
AxisAlignedBB bb = new AxisAlignedBB(pos.down(beltMode ? 2 : 1));
|
AxisAlignedBB bb = new AxisAlignedBB(pos.down(1));
|
||||||
|
pressedItems.clear();
|
||||||
for (Entity entity : world.getEntitiesWithinAABBExcludingEntity(null, bb)) {
|
for (Entity entity : world.getEntitiesWithinAABBExcludingEntity(null, bb)) {
|
||||||
if (!(entity instanceof ItemEntity))
|
if (!(entity instanceof ItemEntity))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ItemEntity itemEntity = (ItemEntity) entity;
|
ItemEntity itemEntity = (ItemEntity) entity;
|
||||||
makeParticleEffect(entity.getPositionVec(), itemEntity.getItem());
|
|
||||||
|
|
||||||
if (!world.isRemote) {
|
if (!world.isRemote) {
|
||||||
|
pressedItems.add(itemEntity.getItem());
|
||||||
|
sendData();
|
||||||
Optional<PressingRecipe> recipe = getRecipe(itemEntity.getItem());
|
Optional<PressingRecipe> recipe = getRecipe(itemEntity.getItem());
|
||||||
if (recipe.isPresent())
|
if (recipe.isPresent())
|
||||||
InWorldProcessing.applyRecipeOn(itemEntity, recipe.get());
|
InWorldProcessing.applyRecipeOn(itemEntity, recipe.get());
|
||||||
|
@ -112,18 +169,22 @@ public class MechanicalPressTileEntity extends KineticTileEntity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (beltMode && world.isRemote) {
|
if (onBasin()) {
|
||||||
TileEntity te = world.getTileEntity(pos.down(2));
|
if (!world.isRemote) {
|
||||||
if (te != null && te instanceof BeltTileEntity) {
|
pressedItems.clear();
|
||||||
BeltTileEntity beltTE = (BeltTileEntity) te;
|
applyBasinRecipe();
|
||||||
TileEntity controller = world.getTileEntity(beltTE.getController());
|
IItemHandler orElse = basinInv.orElse(null);
|
||||||
if (controller != null && controller instanceof BeltTileEntity) {
|
if (basinInv.isPresent() && orElse instanceof BasinInventory) {
|
||||||
TransportedItemStack stackAtOffset = ((BeltTileEntity) controller).getInventory()
|
BasinInventory inv = (BasinInventory) orElse;
|
||||||
.getStackAtOffset(beltTE.index);
|
|
||||||
if (stackAtOffset != null)
|
for (int slot = 0; slot < inv.getInputHandler().getSlots(); slot++) {
|
||||||
makeParticleEffect(VecHelper.getCenterOf(pos.down(2)).add(0, 5 / 16f, 0),
|
ItemStack stackInSlot = inv.getStackInSlot(slot);
|
||||||
stackAtOffset.stack);
|
if (stackInSlot.isEmpty())
|
||||||
|
continue;
|
||||||
|
pressedItems.add(stackInSlot);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
sendData();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -136,9 +197,18 @@ public class MechanicalPressTileEntity extends KineticTileEntity {
|
||||||
|
|
||||||
if (!world.isRemote && runningTicks > 60) {
|
if (!world.isRemote && runningTicks > 60) {
|
||||||
finished = true;
|
finished = true;
|
||||||
if (!beltMode)
|
if (inWorld())
|
||||||
finished = world.isBlockPowered(pos);
|
finished = world.isBlockPowered(pos);
|
||||||
running = false;
|
running = false;
|
||||||
|
|
||||||
|
if (onBasin()) {
|
||||||
|
gatherInputs();
|
||||||
|
if (matchBasinRecipe(lastRecipe)) {
|
||||||
|
startProcessingBasin();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pressedItems.clear();
|
||||||
sendData();
|
sendData();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -146,12 +216,41 @@ public class MechanicalPressTileEntity extends KineticTileEntity {
|
||||||
runningTicks++;
|
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) {
|
if (world.isRemote) {
|
||||||
for (int i = 0; i < 20; i++) {
|
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,
|
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;
|
return recipe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean canCompress(NonNullList<Ingredient> ingredients) {
|
||||||
|
return (ingredients.size() == 4 || ingredients.size() == 9)
|
||||||
|
&& ItemHelper.condenseIngredients(ingredients).size() == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected <C extends IInventory> boolean matchStaticFilters(IRecipe<C> recipe) {
|
||||||
|
return recipe instanceof ICraftingRecipe && canCompress(recipe.getIngredients());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected <C extends IInventory> boolean matchBasinRecipe(IRecipe<C> recipe) {
|
||||||
|
if (recipe == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
NonNullList<Ingredient> ingredients = recipe.getIngredients();
|
||||||
|
if (!ingredients.stream().allMatch(Ingredient::isSimple))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
List<ItemStack> 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();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,8 @@ import static com.simibubi.create.modules.contraptions.components.saw.SawBlock.R
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import com.google.common.base.Predicates;
|
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.AllRecipes;
|
import com.simibubi.create.AllRecipes;
|
||||||
import com.simibubi.create.AllTileEntities;
|
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.VecHelper;
|
||||||
import com.simibubi.create.foundation.utility.recipe.RecipeConditions;
|
import com.simibubi.create.foundation.utility.recipe.RecipeConditions;
|
||||||
import com.simibubi.create.foundation.utility.recipe.RecipeFinder;
|
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.components.actors.BlockBreakingKineticTileEntity;
|
||||||
import com.simibubi.create.modules.contraptions.processing.ProcessingInventory;
|
import com.simibubi.create.modules.contraptions.processing.ProcessingInventory;
|
||||||
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
|
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
|
||||||
|
@ -283,11 +281,11 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity implements IHa
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<? extends IRecipe<?>> getRecipes() {
|
private List<? extends IRecipe<?>> getRecipes() {
|
||||||
StartedSearch startedSearch = RecipeFinder.get(cuttingRecipesKey, world,
|
List<IRecipe<?>> startedSearch = RecipeFinder.get(cuttingRecipesKey, world,
|
||||||
RecipeConditions.isOfType(IRecipeType.STONECUTTING, AllRecipes.Types.CUTTING));
|
RecipeConditions.isOfType(IRecipeType.STONECUTTING, AllRecipes.Types.CUTTING));
|
||||||
RecipeStream<IRecipe<?>> search = startedSearch.search();
|
return startedSearch.stream().filter(RecipeConditions.outputMatchesFilter(filter))
|
||||||
return search.filter(Predicates.and(RecipeConditions.outputMatchesFilter(filter),
|
.filter(RecipeConditions.firstIngredientMatches(inventory.getStackInSlot(0)))
|
||||||
RecipeConditions.firstIngredientMatches(inventory.getStackInSlot(0))));
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void insertItem(ItemEntity entity) {
|
public void insertItem(ItemEntity entity) {
|
||||||
|
|
|
@ -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<IItemHandler> basinInv = LazyOptional.empty();
|
||||||
|
protected List<ItemStack> 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<IRecipe<?>> 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<IRecipe<?>> getMatchingRecipes() {
|
||||||
|
List<IRecipe<?>> 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 <C extends IInventory> boolean matchStaticFilters(IRecipe<C> recipe);
|
||||||
|
|
||||||
|
protected abstract <C extends IInventory> boolean matchBasinRecipe(IRecipe<C> recipe);
|
||||||
|
|
||||||
|
protected abstract Object getRecipeCacheKey();
|
||||||
|
|
||||||
|
}
|
|
@ -2,7 +2,6 @@ package com.simibubi.create.modules.contraptions.processing;
|
||||||
|
|
||||||
import com.simibubi.create.AllTileEntities;
|
import com.simibubi.create.AllTileEntities;
|
||||||
import com.simibubi.create.foundation.block.SyncedTileEntity;
|
import com.simibubi.create.foundation.block.SyncedTileEntity;
|
||||||
import com.simibubi.create.modules.contraptions.components.mixer.MechanicalMixerTileEntity;
|
|
||||||
|
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.nbt.CompoundNBT;
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
|
@ -27,7 +26,7 @@ public class BasinTileEntity extends SyncedTileEntity implements ITickableTileEn
|
||||||
markDirty();
|
markDirty();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public class BasinInputInventory extends RecipeWrapper {
|
public class BasinInputInventory extends RecipeWrapper {
|
||||||
public BasinInputInventory() {
|
public BasinInputInventory() {
|
||||||
super(inputInventory);
|
super(inputInventory);
|
||||||
|
@ -99,15 +98,15 @@ public class BasinTileEntity extends SyncedTileEntity implements ITickableTileEn
|
||||||
compound.put("OutputItems", outputInventory.serializeNBT());
|
compound.put("OutputItems", outputInventory.serializeNBT());
|
||||||
return compound;
|
return compound;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onEmptied() {
|
public void onEmptied() {
|
||||||
TileEntity te = world.getTileEntity(pos.up(2));
|
TileEntity te = world.getTileEntity(pos.up(2));
|
||||||
if (te == null)
|
if (te == null)
|
||||||
return;
|
return;
|
||||||
if (te instanceof MechanicalMixerTileEntity)
|
if (te instanceof BasinOperatingTileEntity)
|
||||||
((MechanicalMixerTileEntity) te).basinRemoved = true;
|
((BasinOperatingTileEntity) te).basinRemoved = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void remove() {
|
public void remove() {
|
||||||
onEmptied();
|
onEmptied();
|
||||||
|
@ -131,8 +130,8 @@ public class BasinTileEntity extends SyncedTileEntity implements ITickableTileEn
|
||||||
TileEntity te = world.getTileEntity(pos.up(2));
|
TileEntity te = world.getTileEntity(pos.up(2));
|
||||||
if (te == null)
|
if (te == null)
|
||||||
return;
|
return;
|
||||||
if (te instanceof MechanicalMixerTileEntity)
|
if (te instanceof BasinOperatingTileEntity)
|
||||||
((MechanicalMixerTileEntity) te).checkBasin = true;
|
((BasinOperatingTileEntity) te).checkBasin = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,9 @@ public class ProcessingRecipeSerializer<T extends ProcessingRecipe<?>>
|
||||||
results.add(new StochasticOutput(itemstack, chance));
|
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);
|
return this.factory.create(recipeId, s, ingredients, results, duration);
|
||||||
}
|
}
|
||||||
|
|
|
@ -184,7 +184,11 @@
|
||||||
"create.recipe.smokingViaFan.fan": "Fan behind Fire",
|
"create.recipe.smokingViaFan.fan": "Fan behind Fire",
|
||||||
"create.recipe.blastingViaFan": "Bulk Smelting",
|
"create.recipe.blastingViaFan": "Bulk Smelting",
|
||||||
"create.recipe.blastingViaFan.fan": "Fan behind Lava",
|
"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.blockzapperUpgrade": "Handheld Blockzapper",
|
||||||
"create.recipe.processing.chance": "%1$s%% Chance",
|
"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.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.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.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": "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.",
|
"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.",
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in a new issue