fluid reading for the processing recipes and its serializer

This commit is contained in:
LordGrimmauld 2020-07-10 13:48:59 +02:00
parent f9fe47eea5
commit a73919357b
32 changed files with 349 additions and 150 deletions

View file

@ -49,30 +49,31 @@ public enum AllRecipeTypes {
public <T extends IRecipeType<?>> T getType() { public <T extends IRecipeType<?>> T getType() {
return (T) type; return (T) type;
} }
private AllRecipeTypes(Supplier<IRecipeSerializer<?>> supplier) { AllRecipeTypes(Supplier<IRecipeSerializer<?>> supplier) {
this(supplier, null); this(supplier, null);
} }
private AllRecipeTypes(Supplier<IRecipeSerializer<?>> supplier, AllRecipeTypes(Supplier<IRecipeSerializer<?>> supplier,
IRecipeType<? extends IRecipe<? extends IInventory>> existingType) { IRecipeType<? extends IRecipe<? extends IInventory>> existingType) {
this.supplier = supplier; this.supplier = supplier;
this.type = existingType; this.type = existingType;
} }
public static void register(RegistryEvent.Register<IRecipeSerializer<?>> event) { public static void register(RegistryEvent.Register<IRecipeSerializer<?>> event) {
ShapedRecipe.setCraftingSize(9, 9); ShapedRecipe.setCraftingSize(9, 9);
for (AllRecipeTypes r : AllRecipeTypes.values()) { for (AllRecipeTypes r : AllRecipeTypes.values()) {
if (r.type == null) if (r.type == null)
r.type = customType(Lang.asId(r.name())); r.type = customType(Lang.asId(r.name()));
r.serializer = r.supplier.get(); r.serializer = r.supplier.get();
ResourceLocation location = new ResourceLocation(Create.ID, Lang.asId(r.name())); ResourceLocation location = new ResourceLocation(Create.ID, Lang.asId(r.name()));
event.getRegistry().register(r.serializer.setRegistryName(location)); event.getRegistry()
.register(r.serializer.setRegistryName(location));
} }
} }
private static <T extends IRecipe<?>> IRecipeType<T> customType(String id) { private static <T extends IRecipe<?>> IRecipeType<T> customType(String id) {
return Registry.register(Registry.RECIPE_TYPE, new ResourceLocation(Create.ID, id), new IRecipeType<T>() { return Registry.register(Registry.RECIPE_TYPE, new ResourceLocation(Create.ID, id), new IRecipeType<T>() {
public String toString() { public String toString() {
@ -80,10 +81,10 @@ public enum AllRecipeTypes {
} }
}); });
} }
private static Supplier<IRecipeSerializer<?>> processingSerializer(IRecipeFactory<? extends ProcessingRecipe<?>> factory) { private static Supplier<IRecipeSerializer<?>> processingSerializer(
IRecipeFactory<? extends ProcessingRecipe<?>> factory) {
return () -> new ProcessingRecipeSerializer<>(factory); return () -> new ProcessingRecipeSerializer<>(factory);
} }
} }

View file

@ -1,8 +1,11 @@
package com.simibubi.create.compat.jei; package com.simibubi.create.compat.jei;
import java.util.Arrays; import java.util.Collections;
import java.util.List; import java.util.List;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import com.simibubi.create.AllRecipeTypes; import com.simibubi.create.AllRecipeTypes;
import com.simibubi.create.Create; import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.processing.ProcessingIngredient; import com.simibubi.create.content.contraptions.processing.ProcessingIngredient;
@ -13,6 +16,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.Ingredient; import net.minecraft.item.crafting.Ingredient;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.items.wrapper.RecipeWrapper; import net.minecraftforge.items.wrapper.RecipeWrapper;
/** /**
@ -21,24 +25,27 @@ import net.minecraftforge.items.wrapper.RecipeWrapper;
* @author simibubi * @author simibubi
* *
*/ */
@ParametersAreNonnullByDefault
public class ConversionRecipe extends ProcessingRecipe<RecipeWrapper> { public class ConversionRecipe extends ProcessingRecipe<RecipeWrapper> {
public ConversionRecipe(ResourceLocation id, String group, List<ProcessingIngredient> ingredients, public ConversionRecipe(ResourceLocation id, String group, List<ProcessingIngredient> ingredients,
List<ProcessingOutput> results, int processingDuration) { List<ProcessingOutput> results, int processingDuration, @Nullable List<FluidStack> fluidIngredients,
@Nullable List<FluidStack> fluidResults) {
super(AllRecipeTypes.CONVERSION, id, group, ingredients, results, processingDuration); super(AllRecipeTypes.CONVERSION, id, group, ingredients, results, processingDuration);
} }
static int counter = 0; static int counter = 0;
public static ConversionRecipe create(ItemStack from, ItemStack to) { public static ConversionRecipe create(ItemStack from, ItemStack to) {
List<ProcessingIngredient> ingredients = Arrays.asList(new ProcessingIngredient(Ingredient.fromStacks(from))); List<ProcessingIngredient> ingredients =
List<ProcessingOutput> outputs = Arrays.asList(new ProcessingOutput(to, 1)); Collections.singletonList(new ProcessingIngredient(Ingredient.fromStacks(from)));
List<ProcessingOutput> outputs = Collections.singletonList(new ProcessingOutput(to, 1));
return new ConversionRecipe(new ResourceLocation(Create.ID, "conversion_" + counter++), ingredients, outputs); return new ConversionRecipe(new ResourceLocation(Create.ID, "conversion_" + counter++), ingredients, outputs);
} }
public ConversionRecipe(ResourceLocation id, List<ProcessingIngredient> ingredients, public ConversionRecipe(ResourceLocation id, List<ProcessingIngredient> ingredients,
List<ProcessingOutput> results) { List<ProcessingOutput> results) {
this(id, "conversions", ingredients, results, -1); this(id, "conversions", ingredients, results, -1, null, null);
} }
@Override @Override

View file

@ -59,10 +59,10 @@ public abstract class CreateRecipeCategory<T extends IRecipe<?>> implements IRec
if (!(recipe instanceof ProcessingRecipe)) if (!(recipe instanceof ProcessingRecipe))
return jeiSlot; return jeiSlot;
ProcessingRecipe<?> processingRecipe = (ProcessingRecipe<?>) recipe; ProcessingRecipe<?> processingRecipe = (ProcessingRecipe<?>) recipe;
List<ProcessingOutput> rollableResults = processingRecipe.getRollableResults(); List<ProcessingOutput> rollableResults = processingRecipe.getRollableItemResults();
if (rollableResults.size() <= index) if (rollableResults.size() <= index)
return jeiSlot; return jeiSlot;
if (processingRecipe.getRollableResults().get(index).getChance() == 1) if (processingRecipe.getRollableItemResults().get(index).getChance() == 1)
return jeiSlot; return jeiSlot;
return AllGuiTextures.JEI_CHANCE_SLOT; return AllGuiTextures.JEI_CHANCE_SLOT;
} }

View file

@ -41,7 +41,7 @@ public class CrushingCategory extends CreateRecipeCategory<AbstractCrushingRecip
itemStacks.init(0, true, 50, 2); itemStacks.init(0, true, 50, 2);
itemStacks.set(0, Arrays.asList(recipe.getIngredients().get(0).getMatchingStacks())); itemStacks.set(0, Arrays.asList(recipe.getIngredients().get(0).getMatchingStacks()));
List<ProcessingOutput> results = recipe.getRollableResults(); List<ProcessingOutput> results = recipe.getRollableItemResults();
int size = results.size(); int size = results.size();
int offset = -size * 19 / 2; int offset = -size * 19 / 2;
for (int outputIndex = 0; outputIndex < size; outputIndex++) { for (int outputIndex = 0; outputIndex < size; outputIndex++) {
@ -54,7 +54,7 @@ public class CrushingCategory extends CreateRecipeCategory<AbstractCrushingRecip
@Override @Override
public void draw(AbstractCrushingRecipe recipe, double mouseX, double mouseY) { public void draw(AbstractCrushingRecipe recipe, double mouseX, double mouseY) {
List<ProcessingOutput> results = recipe.getRollableResults(); List<ProcessingOutput> results = recipe.getRollableItemResults();
AllGuiTextures.JEI_SLOT.draw(50, 2); AllGuiTextures.JEI_SLOT.draw(50, 2);
AllGuiTextures.JEI_DOWN_ARROW.draw(72, 7); AllGuiTextures.JEI_DOWN_ARROW.draw(72, 7);

View file

@ -43,7 +43,7 @@ public class MillingCategory extends CreateRecipeCategory<AbstractCrushingRecipe
.get(0) .get(0)
.getMatchingStacks())); .getMatchingStacks()));
List<ProcessingOutput> results = recipe.getRollableResults(); List<ProcessingOutput> results = recipe.getRollableItemResults();
boolean single = results.size() == 1; boolean single = results.size() == 1;
for (int outputIndex = 0; outputIndex < results.size(); outputIndex++) { for (int outputIndex = 0; outputIndex < results.size(); outputIndex++) {
int xOffset = outputIndex % 2 == 0 ? 0 : 19; int xOffset = outputIndex % 2 == 0 ? 0 : 19;

View file

@ -41,7 +41,7 @@ public class MysteriousItemConversionCategory extends CreateRecipeCategory<Conve
@Override @Override
public void setRecipe(IRecipeLayout recipeLayout, ConversionRecipe recipe, IIngredients ingredients) { public void setRecipe(IRecipeLayout recipeLayout, ConversionRecipe recipe, IIngredients ingredients) {
IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks(); IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks();
List<ProcessingOutput> results = recipe.getRollableResults(); List<ProcessingOutput> results = recipe.getRollableItemResults();
itemStacks.init(0, true, 26, 16); itemStacks.init(0, true, 26, 16);
itemStacks.set(0, Arrays.asList(recipe.getIngredients().get(0).getMatchingStacks())); itemStacks.set(0, Arrays.asList(recipe.getIngredients().get(0).getMatchingStacks()));
itemStacks.init(1, false, 131, 16); itemStacks.init(1, false, 131, 16);

View file

@ -43,7 +43,7 @@ public class PolishingCategory extends CreateRecipeCategory<SandPaperPolishingRe
@Override @Override
public void setRecipe(IRecipeLayout recipeLayout, SandPaperPolishingRecipe recipe, IIngredients ingredients) { public void setRecipe(IRecipeLayout recipeLayout, SandPaperPolishingRecipe recipe, IIngredients ingredients) {
IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks(); IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks();
List<ProcessingOutput> results = recipe.getRollableResults(); List<ProcessingOutput> results = recipe.getRollableItemResults();
itemStacks.init(0, true, 26, 28); itemStacks.init(0, true, 26, 28);
itemStacks.set(0, Arrays.asList(recipe.getIngredients().get(0).getMatchingStacks())); itemStacks.set(0, Arrays.asList(recipe.getIngredients().get(0).getMatchingStacks()));

View file

@ -41,7 +41,7 @@ public class PressingCategory extends CreateRecipeCategory<PressingRecipe> {
itemStacks.init(0, true, 26, 50); itemStacks.init(0, true, 26, 50);
itemStacks.set(0, Arrays.asList(recipe.getIngredients().get(0).getMatchingStacks())); itemStacks.set(0, Arrays.asList(recipe.getIngredients().get(0).getMatchingStacks()));
List<ProcessingOutput> results = recipe.getRollableResults(); List<ProcessingOutput> results = recipe.getRollableItemResults();
for (int outputIndex = 0; outputIndex < results.size(); outputIndex++) { for (int outputIndex = 0; outputIndex < results.size(); outputIndex++) {
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());
@ -54,7 +54,7 @@ public class PressingCategory extends CreateRecipeCategory<PressingRecipe> {
public void draw(PressingRecipe recipe, double mouseX, double mouseY) { public void draw(PressingRecipe recipe, double mouseX, double mouseY) {
AllGuiTextures.JEI_SLOT.draw(26, 50); AllGuiTextures.JEI_SLOT.draw(26, 50);
getRenderedSlot(recipe, 0).draw(131, 50); getRenderedSlot(recipe, 0).draw(131, 50);
if (recipe.getRollableResults().size() > 1) if (recipe.getRollableItemResults().size() > 1)
getRenderedSlot(recipe, 1).draw(131 + 19, 50); getRenderedSlot(recipe, 1).draw(131 + 19, 50);
AllGuiTextures.JEI_SHADOW.draw(61, 41); AllGuiTextures.JEI_SHADOW.draw(61, 41);
AllGuiTextures.JEI_LONG_ARROW.draw(52, 54); AllGuiTextures.JEI_LONG_ARROW.draw(52, 54);

View file

@ -40,7 +40,7 @@ public class SawingCategory extends CreateRecipeCategory<CuttingRecipe> {
itemStacks.init(0, true, 43, 4); itemStacks.init(0, true, 43, 4);
itemStacks.set(0, Arrays.asList(recipe.getIngredients().get(0).getMatchingStacks())); itemStacks.set(0, Arrays.asList(recipe.getIngredients().get(0).getMatchingStacks()));
List<ProcessingOutput> results = recipe.getRollableResults(); List<ProcessingOutput> results = recipe.getRollableItemResults();
for (int outputIndex = 0; outputIndex < results.size(); outputIndex++) { for (int outputIndex = 0; outputIndex < results.size(); outputIndex++) {
int xOffset = outputIndex % 2 == 0 ? 0 : 19; int xOffset = outputIndex % 2 == 0 ? 0 : 19;
int yOffset = (outputIndex / 2) * -19; int yOffset = (outputIndex / 2) * -19;
@ -55,7 +55,7 @@ public class SawingCategory extends CreateRecipeCategory<CuttingRecipe> {
@Override @Override
public void draw(CuttingRecipe recipe, double mouseX, double mouseY) { public void draw(CuttingRecipe recipe, double mouseX, double mouseY) {
AllGuiTextures.JEI_SLOT.draw(43, 4); AllGuiTextures.JEI_SLOT.draw(43, 4);
int size = recipe.getRollableResults().size(); int size = recipe.getRollableItemResults().size();
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
int xOffset = i % 2 == 0 ? 0 : 19; int xOffset = i % 2 == 0 ? 0 : 19;
int yOffset = (i / 2) * -19; int yOffset = (i / 2) * -19;

View file

@ -42,7 +42,7 @@ public class SplashingCategory extends ProcessingViaFanCategory<SplashingRecipe>
.get(0) .get(0)
.getMatchingStacks())); .getMatchingStacks()));
List<ProcessingOutput> results = recipe.getRollableResults(); List<ProcessingOutput> results = recipe.getRollableItemResults();
boolean single = results.size() == 1; boolean single = results.size() == 1;
for (int outputIndex = 0; outputIndex < results.size(); outputIndex++) { for (int outputIndex = 0; outputIndex < results.size(); outputIndex++) {
int xOffset = outputIndex % 2 == 0 ? 0 : 19; int xOffset = outputIndex % 2 == 0 ? 0 : 19;

View file

@ -13,7 +13,7 @@ import net.minecraftforge.items.wrapper.RecipeWrapper;
public abstract class AbstractCrushingRecipe extends ProcessingRecipe<RecipeWrapper> { public abstract class AbstractCrushingRecipe extends ProcessingRecipe<RecipeWrapper> {
public AbstractCrushingRecipe(AllRecipeTypes recipeType, ResourceLocation id, String group, public AbstractCrushingRecipe(AllRecipeTypes recipeType, ResourceLocation id, String group,
List<ProcessingIngredient> ingredients, List<ProcessingOutput> results, int processingDuration) { List<ProcessingIngredient> ingredients, List<ProcessingOutput> results, int processingDuration) {
super(recipeType, id, group, ingredients, results, processingDuration); super(recipeType, id, group, ingredients, results, processingDuration);
} }

View file

@ -8,12 +8,14 @@ import com.simibubi.create.content.contraptions.processing.ProcessingOutput;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.items.wrapper.RecipeWrapper; import net.minecraftforge.items.wrapper.RecipeWrapper;
public class CrushingRecipe extends AbstractCrushingRecipe { public class CrushingRecipe extends AbstractCrushingRecipe {
public CrushingRecipe(ResourceLocation id, String group, List<ProcessingIngredient> ingredients, public CrushingRecipe(ResourceLocation id, String group, List<ProcessingIngredient> ingredients,
List<ProcessingOutput> results, int processingDuration) { List<ProcessingOutput> results, int processingDuration, List<FluidStack> fluidIngredients,
List<FluidStack> fluidResults) {
super(AllRecipeTypes.CRUSHING, id, group, ingredients, results, processingDuration); super(AllRecipeTypes.CRUSHING, id, group, ingredients, results, processingDuration);
} }
@ -21,9 +23,10 @@ public class CrushingRecipe extends AbstractCrushingRecipe {
public boolean matches(RecipeWrapper inv, World worldIn) { public boolean matches(RecipeWrapper inv, World worldIn) {
if (inv.isEmpty()) if (inv.isEmpty())
return false; return false;
return ingredients.get(0).test(inv.getStackInSlot(0)); return ingredients.get(0)
.test(inv.getStackInSlot(0));
} }
@Override @Override
protected int getMaxOutputCount() { protected int getMaxOutputCount() {
return 7; return 7;

View file

@ -191,7 +191,7 @@ public class CrushingWheelControllerTileEntity extends SmartTileEntity {
inventory.clear(); inventory.clear();
for (int roll = 0; roll < rolls; roll++) { for (int roll = 0; roll < rolls; roll++) {
List<ItemStack> rolledResults = recipe.get() List<ItemStack> rolledResults = recipe.get()
.rollResults(); .rollResults().getItemStacks();
for (int i = 0; i < rolledResults.size(); i++) { for (int i = 0; i < rolledResults.size(); i++) {
ItemStack stack = rolledResults.get(i); ItemStack stack = rolledResults.get(i);
ItemHelper.addToList(stack, list); ItemHelper.addToList(stack, list);

View file

@ -11,11 +11,16 @@ import com.simibubi.create.content.logistics.InWorldProcessing.SplashingInv;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.fluids.FluidStack;
import javax.annotation.ParametersAreNonnullByDefault;
@ParametersAreNonnullByDefault
public class SplashingRecipe extends ProcessingRecipe<InWorldProcessing.SplashingInv> { public class SplashingRecipe extends ProcessingRecipe<InWorldProcessing.SplashingInv> {
public SplashingRecipe(ResourceLocation id, String group, List<ProcessingIngredient> ingredients, public SplashingRecipe(ResourceLocation id, String group, List<ProcessingIngredient> ingredients,
List<ProcessingOutput> results, int processingDuration) { List<ProcessingOutput> results, int processingDuration, List<FluidStack> fluidIngredients,
List<FluidStack> fluidResults) {
super(AllRecipeTypes.SPLASHING, id, group, ingredients, results, processingDuration); super(AllRecipeTypes.SPLASHING, id, group, ingredients, results, processingDuration);
} }
@ -23,9 +28,10 @@ public class SplashingRecipe extends ProcessingRecipe<InWorldProcessing.Splashin
public boolean matches(SplashingInv inv, World worldIn) { public boolean matches(SplashingInv inv, World worldIn) {
if (inv.isEmpty()) if (inv.isEmpty())
return false; return false;
return ingredients.get(0).test(inv.getStackInSlot(0)); return ingredients.get(0)
.test(inv.getStackInSlot(0));
} }
@Override @Override
protected int getMaxOutputCount() { protected int getMaxOutputCount() {
return 6; return 6;

View file

@ -9,12 +9,17 @@ import com.simibubi.create.content.contraptions.processing.ProcessingOutput;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.items.wrapper.RecipeWrapper; import net.minecraftforge.items.wrapper.RecipeWrapper;
import javax.annotation.ParametersAreNonnullByDefault;
@ParametersAreNonnullByDefault
public class MillingRecipe extends AbstractCrushingRecipe { public class MillingRecipe extends AbstractCrushingRecipe {
public MillingRecipe(ResourceLocation id, String group, List<ProcessingIngredient> ingredients, public MillingRecipe(ResourceLocation id, String group, List<ProcessingIngredient> ingredients,
List<ProcessingOutput> results, int processingDuration) { List<ProcessingOutput> results, int processingDuration, List<FluidStack> fluidIngredients,
List<FluidStack> fluidResults) {
super(AllRecipeTypes.MILLING, id, group, ingredients, results, processingDuration); super(AllRecipeTypes.MILLING, id, group, ingredients, results, processingDuration);
} }
@ -22,9 +27,10 @@ public class MillingRecipe extends AbstractCrushingRecipe {
public boolean matches(RecipeWrapper inv, World worldIn) { public boolean matches(RecipeWrapper inv, World worldIn) {
if (inv.isEmpty()) if (inv.isEmpty())
return false; return false;
return ingredients.get(0).test(inv.getStackInSlot(0)); return ingredients.get(0)
.test(inv.getStackInSlot(0));
} }
@Override @Override
protected int getMaxOutputCount() { protected int getMaxOutputCount() {
return 4; return 4;

View file

@ -94,7 +94,7 @@ public class MillstoneTileEntity extends KineticTileEntity {
ItemStack stackInSlot = inputInv.getStackInSlot(0); ItemStack stackInSlot = inputInv.getStackInSlot(0);
stackInSlot.shrink(1); stackInSlot.shrink(1);
inputInv.setStackInSlot(0, stackInSlot); inputInv.setStackInSlot(0, stackInSlot);
lastRecipe.rollResults().forEach(stack -> ItemHandlerHelper.insertItemStacked(outputInv, stack, false)); lastRecipe.rollResults().forEachItemStack(stack -> ItemHandlerHelper.insertItemStacked(outputInv, stack, false));
sendData(); sendData();
markDirty(); markDirty();
} }

View file

@ -1,14 +1,15 @@
package com.simibubi.create.content.contraptions.components.mixer; package com.simibubi.create.content.contraptions.components.mixer;
import java.util.ArrayList;
import java.util.Comparator; import java.util.Comparator;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import com.simibubi.create.AllRecipeTypes; import com.simibubi.create.AllRecipeTypes;
import com.simibubi.create.content.contraptions.components.press.MechanicalPressTileEntity; import com.simibubi.create.content.contraptions.components.press.MechanicalPressTileEntity;
import com.simibubi.create.content.contraptions.fluids.CombinedFluidHandler;
import com.simibubi.create.content.contraptions.processing.BasinOperatingTileEntity; import com.simibubi.create.content.contraptions.processing.BasinOperatingTileEntity;
import com.simibubi.create.content.contraptions.processing.BasinTileEntity.BasinInventory; import com.simibubi.create.content.contraptions.processing.BasinTileEntity.BasinInventory;
import com.simibubi.create.content.contraptions.processing.CombinedItemFluidList;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.CenteredSideValueBoxTransform; import com.simibubi.create.foundation.tileEntity.behaviour.CenteredSideValueBoxTransform;
import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueBehaviour;
@ -29,7 +30,6 @@ 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.items.IItemHandler;
public class MechanicalMixerTileEntity extends BasinOperatingTileEntity { public class MechanicalMixerTileEntity extends BasinOperatingTileEntity {
@ -65,7 +65,7 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity {
} }
public float getRenderedHeadOffset(float partialTicks) { public float getRenderedHeadOffset(float partialTicks) {
int localTick = 0; int localTick;
float offset = 0; float offset = 0;
if (running) { if (running) {
if (runningTicks < 20) { if (runningTicks < 20) {
@ -154,26 +154,45 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity {
} }
public void renderParticles() { public void renderParticles() {
IItemHandler itemHandler = basinItemInv.orElse(null); if (world == null)
BasinInventory inv = (BasinInventory) itemHandler; return;
basinItemInv.ifPresent(inv -> {
for (int slot = 0; slot < ((BasinInventory) inv).getInputHandler()
.getSlots(); slot++) {
ItemStack stackInSlot = inv.getStackInSlot(slot);
if (stackInSlot.isEmpty())
continue;
for (int slot = 0; slot < inv.getInputHandler() ItemParticleData data = new ItemParticleData(ParticleTypes.ITEM, stackInSlot);
.getSlots(); slot++) { float angle = world.rand.nextFloat() * 360;
ItemStack stackInSlot = itemHandler.getStackInSlot(slot); Vec3d offset = new Vec3d(0, 0, 0.25f);
if (stackInSlot.isEmpty()) offset = VecHelper.rotate(offset, angle, Axis.Y);
continue; Vec3d target = VecHelper.rotate(offset, getSpeed() > 0 ? 25 : -25, Axis.Y)
.add(0, .25f, 0);
ItemParticleData data = new ItemParticleData(ParticleTypes.ITEM, stackInSlot); Vec3d center = offset.add(VecHelper.getCenterOf(pos));
float angle = world.rand.nextFloat() * 360; target = VecHelper.offsetRandomly(target.subtract(offset), world.rand, 1 / 128f);
Vec3d offset = new Vec3d(0, 0, 0.25f); world.addParticle(data, center.x, center.y - 2, center.z, target.x, target.y, target.z);
offset = VecHelper.rotate(offset, angle, Axis.Y); }
Vec3d target = VecHelper.rotate(offset, getSpeed() > 0 ? 25 : -25, Axis.Y) });
.add(0, .25f, 0);
// Fluid Particles
/*
* basinFluidInv.ifPresent(fluidInv -> ((CombinedFluidHandler)
* fluidInv).forEachTank(fluidStack -> { if(fluidStack.isEmpty()) return; float
* angle = world.rand.nextFloat() * 360; Vec3d offset = new Vec3d(0, 0, 0.25f);
* offset = VecHelper.rotate(offset, angle, Axis.Y); Vec3d target =
* VecHelper.rotate(offset, getSpeed() > 0 ? 25 : -25, Axis.Y) .add(0, .25f, 0);
*
* Vec3d center = offset.add(VecHelper.getCenterOf(pos)); target =
* VecHelper.offsetRandomly(target.subtract(offset), world.rand, 1 / 128f);
* IParticleData data = new AirFlowParticleData(this.pos.down(2));
* world.addParticle(data, center.x, center.y - 2, center.z, target.x, target.y,
* target.z);
*
* }));
*/
Vec3d center = offset.add(VecHelper.getCenterOf(pos));
target = VecHelper.offsetRandomly(target.subtract(offset), world.rand, 1 / 128f);
world.addParticle(data, center.x, center.y - 2, center.z, target.x, target.y, target.z);
}
} }
@Override @Override
@ -195,14 +214,16 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity {
.allMatch(ingredient -> (ingredient.isSimple() || ingredient.getMatchingStacks().length == 1))) .allMatch(ingredient -> (ingredient.isSimple() || ingredient.getMatchingStacks().length == 1)))
return false; return false;
List<ItemStack> remaining = new ArrayList<>(); CombinedItemFluidList remaining = new CombinedItemFluidList();
inputs.forEachItemStack(stack -> remaining.add(stack.copy())); inputs.forEachItemStack(stack -> remaining.add(stack.copy()));
basinFluidInv.ifPresent(
fluidInv -> ((CombinedFluidHandler) fluidInv).forEachTank(fluidStack -> remaining.add(fluidStack.copy())));
// sort by leniency // sort by leniency
List<Ingredient> sortedIngredients = new LinkedList<>(ingredients); List<Ingredient> sortedIngredients = new LinkedList<>(ingredients);
sortedIngredients.sort(Comparator.comparingInt(i -> i.getMatchingStacks().length)); sortedIngredients.sort(Comparator.comparingInt(i -> i.getMatchingStacks().length));
Ingredients: for (Ingredient ingredient : sortedIngredients) { Ingredients: for (Ingredient ingredient : sortedIngredients) {
for (ItemStack stack : remaining) { for (ItemStack stack : remaining.getItemStacks()) {
if (stack.isEmpty()) if (stack.isEmpty())
continue; continue;
if (ingredient.test(stack)) { if (ingredient.test(stack)) {
@ -212,6 +233,9 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity {
} }
return false; return false;
} }
if (!(recipe instanceof MixingRecipe))
return true;
return true; return true;
} }

View file

@ -1,10 +1,14 @@
package com.simibubi.create.content.contraptions.components.mixer; package com.simibubi.create.content.contraptions.components.mixer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import javax.annotation.Nonnull;
import com.simibubi.create.AllRecipeTypes; import com.simibubi.create.AllRecipeTypes;
import com.simibubi.create.content.contraptions.processing.BasinTileEntity.BasinInputInventory; import com.simibubi.create.content.contraptions.processing.BasinTileEntity.BasinInputInventory;
import com.simibubi.create.content.contraptions.processing.ProcessingIngredient; import com.simibubi.create.content.contraptions.processing.ProcessingIngredient;
@ -17,36 +21,45 @@ import net.minecraft.item.crafting.Ingredient;
import net.minecraft.util.NonNullList; import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.fluids.FluidStack;
public class MixingRecipe extends ProcessingRecipe<BasinInputInventory> { public class MixingRecipe extends ProcessingRecipe<BasinInputInventory> {
public MixingRecipe(ResourceLocation id, String group, List<ProcessingIngredient> ingredients, public MixingRecipe(ResourceLocation id, String group, List<ProcessingIngredient> ingredients,
List<ProcessingOutput> results, int processingDuration) { List<ProcessingOutput> results, int processingDuration) {
super(AllRecipeTypes.MIXING, id, group, ingredients, results, processingDuration); super(AllRecipeTypes.MIXING, id, group, ingredients, results, processingDuration);
} }
public MixingRecipe(ResourceLocation id, String group, List<ProcessingIngredient> ingredients,
List<ProcessingOutput> results, int processingDuration, List<FluidStack> fluidIngredients,
List<FluidStack> fluidResults) {
super(AllRecipeTypes.MIXING, id, group, ingredients, results, processingDuration, fluidIngredients,
fluidResults);
}
@Override @Override
protected int getMaxInputCount() { protected int getMaxInputCount() {
return 9; return 9;
} }
@Override @Override
protected int getMaxOutputCount() { protected int getMaxOutputCount() {
return 1; return 1;
} }
@Override @Override
protected boolean canHaveCatalysts() { protected boolean canHaveCatalysts() {
return true; return true;
} }
@Override @Override
public boolean matches(BasinInputInventory inv, World worldIn) { public boolean matches(BasinInputInventory inv, @Nonnull World worldIn) {
if (inv.isEmpty()) if (inv.isEmpty())
return false; return false;
NonNullList<Ingredient> ingredients = getIngredients(); NonNullList<Ingredient> ingredients = this.getIngredients();
if (!ingredients.stream().allMatch(Ingredient::isSimple)) if (!ingredients.stream()
.allMatch(Ingredient::isSimple))
return false; return false;
List<ItemStack> remaining = new ArrayList<>(); List<ItemStack> remaining = new ArrayList<>();
@ -59,7 +72,7 @@ public class MixingRecipe extends ProcessingRecipe<BasinInputInventory> {
// sort by leniency // sort by leniency
List<Ingredient> sortedIngredients = new LinkedList<>(ingredients); List<Ingredient> sortedIngredients = new LinkedList<>(ingredients);
sortedIngredients.sort((i1, i2) -> i1.getMatchingStacks().length - i2.getMatchingStacks().length); sortedIngredients.sort(Comparator.comparingInt(i -> i.getMatchingStacks().length));
Ingredients: for (Ingredient ingredient : sortedIngredients) { Ingredients: for (Ingredient ingredient : sortedIngredients) {
for (ItemStack stack : remaining) { for (ItemStack stack : remaining) {
if (stack.isEmpty()) if (stack.isEmpty())
@ -76,7 +89,16 @@ public class MixingRecipe extends ProcessingRecipe<BasinInputInventory> {
public static MixingRecipe of(IRecipe<?> recipe) { public static MixingRecipe of(IRecipe<?> recipe) {
return new MixingRecipe(recipe.getId(), recipe.getGroup(), ProcessingIngredient.list(recipe.getIngredients()), return new MixingRecipe(recipe.getId(), recipe.getGroup(), ProcessingIngredient.list(recipe.getIngredients()),
Arrays.asList(new ProcessingOutput(recipe.getRecipeOutput(), 1)), -1); Collections.singletonList(new ProcessingOutput(recipe.getRecipeOutput(), 1)), -1);
} }
@Override
protected boolean canHaveFluidIngredient() {
return true;
}
@Override
protected boolean canHaveFluidOutput() {
return true;
}
} }

View file

@ -6,8 +6,10 @@ import java.util.Optional;
import com.simibubi.create.AllRecipeTypes; import com.simibubi.create.AllRecipeTypes;
import com.simibubi.create.AllSoundEvents; import com.simibubi.create.AllSoundEvents;
import com.simibubi.create.content.contraptions.fluids.CombinedFluidHandler;
import com.simibubi.create.content.contraptions.processing.BasinOperatingTileEntity; import com.simibubi.create.content.contraptions.processing.BasinOperatingTileEntity;
import com.simibubi.create.content.contraptions.processing.BasinTileEntity.BasinInventory; import com.simibubi.create.content.contraptions.processing.BasinTileEntity.BasinInventory;
import com.simibubi.create.content.contraptions.processing.CombinedItemFluidList;
import com.simibubi.create.content.logistics.InWorldProcessing; import com.simibubi.create.content.logistics.InWorldProcessing;
import com.simibubi.create.foundation.advancement.AllTriggers; import com.simibubi.create.foundation.advancement.AllTriggers;
import com.simibubi.create.foundation.item.ItemHelper; import com.simibubi.create.foundation.item.ItemHelper;
@ -297,11 +299,12 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity {
.allMatch(Ingredient::isSimple)) .allMatch(Ingredient::isSimple))
return false; return false;
List<ItemStack> remaining = new ArrayList<>(); CombinedItemFluidList remaining = new CombinedItemFluidList();
inputs.forEachItemStack(stack -> remaining.add(stack.copy())); inputs.forEachItemStack(stack -> remaining.add(stack.copy()));
basinFluidInv.ifPresent(fluidInv -> ((CombinedFluidHandler) fluidInv).forEachTank(fluidStack -> remaining.add(fluidStack.copy())));
Ingredients: for (Ingredient ingredient : ingredients) { Ingredients: for (Ingredient ingredient : ingredients) {
for (ItemStack stack : remaining) { for (ItemStack stack : remaining.getItemStacks()) {
if (stack.isEmpty()) if (stack.isEmpty())
continue; continue;
if (ingredient.test(stack)) { if (ingredient.test(stack)) {

View file

@ -10,11 +10,16 @@ import com.simibubi.create.content.contraptions.processing.ProcessingRecipe;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.fluids.FluidStack;
import javax.annotation.ParametersAreNonnullByDefault;
@ParametersAreNonnullByDefault
public class PressingRecipe extends ProcessingRecipe<MechanicalPressTileEntity.PressingInv> { public class PressingRecipe extends ProcessingRecipe<MechanicalPressTileEntity.PressingInv> {
public PressingRecipe(ResourceLocation id, String group, List<ProcessingIngredient> ingredients, public PressingRecipe(ResourceLocation id, String group, List<ProcessingIngredient> ingredients,
List<ProcessingOutput> results, int processingDuration) { List<ProcessingOutput> results, int processingDuration, List<FluidStack> fluidIngredients,
List<FluidStack> fluidResults) {
super(AllRecipeTypes.PRESSING, id, group, ingredients, results, processingDuration); super(AllRecipeTypes.PRESSING, id, group, ingredients, results, processingDuration);
} }
@ -22,12 +27,12 @@ public class PressingRecipe extends ProcessingRecipe<MechanicalPressTileEntity.P
public boolean matches(PressingInv inv, World worldIn) { public boolean matches(PressingInv inv, World worldIn) {
if (inv.isEmpty()) if (inv.isEmpty())
return false; return false;
return ingredients.get(0).test(inv.getStackInSlot(0)); return ingredients.get(0)
.test(inv.getStackInSlot(0));
} }
@Override @Override
protected int getMaxOutputCount() { protected int getMaxOutputCount() {
return 2; return 2;
} }
} }

View file

@ -9,12 +9,17 @@ import com.simibubi.create.content.contraptions.processing.ProcessingRecipe;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.items.wrapper.RecipeWrapper; import net.minecraftforge.items.wrapper.RecipeWrapper;
import javax.annotation.ParametersAreNonnullByDefault;
@ParametersAreNonnullByDefault
public class CuttingRecipe extends ProcessingRecipe<RecipeWrapper> { public class CuttingRecipe extends ProcessingRecipe<RecipeWrapper> {
public CuttingRecipe(ResourceLocation id, String group, List<ProcessingIngredient> ingredients, public CuttingRecipe(ResourceLocation id, String group, List<ProcessingIngredient> ingredients,
List<ProcessingOutput> results, int processingDuration) { List<ProcessingOutput> results, int processingDuration, List<FluidStack> fluidIngredients,
List<FluidStack> fluidResults) {
super(AllRecipeTypes.CUTTING, id, group, ingredients, results, processingDuration); super(AllRecipeTypes.CUTTING, id, group, ingredients, results, processingDuration);
} }
@ -22,9 +27,10 @@ public class CuttingRecipe extends ProcessingRecipe<RecipeWrapper> {
public boolean matches(RecipeWrapper inv, World worldIn) { public boolean matches(RecipeWrapper inv, World worldIn) {
if (inv.isEmpty()) if (inv.isEmpty())
return false; return false;
return ingredients.get(0).test(inv.getStackInSlot(0)); return ingredients.get(0)
.test(inv.getStackInSlot(0));
} }
@Override @Override
protected int getMaxOutputCount() { protected int getMaxOutputCount() {
return 4; return 4;

View file

@ -248,7 +248,7 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity {
for (int roll = 0; roll < rolls; roll++) { for (int roll = 0; roll < rolls; roll++) {
List<ItemStack> results = new LinkedList<ItemStack>(); List<ItemStack> results = new LinkedList<ItemStack>();
if (recipe instanceof CuttingRecipe) if (recipe instanceof CuttingRecipe)
results = ((CuttingRecipe) recipe).rollResults(); results = ((CuttingRecipe) recipe).rollResults().getItemStacks();
else if (recipe instanceof StonecuttingRecipe) else if (recipe instanceof StonecuttingRecipe)
results.add(recipe.getRecipeOutput() results.add(recipe.getRecipeOutput()
.copy()); .copy());

View file

@ -1,6 +1,11 @@
package com.simibubi.create.content.contraptions.fluids; package com.simibubi.create.content.contraptions.fluids;
import net.minecraft.fluid.Fluid; import java.util.Arrays;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javax.annotation.Nonnull;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT; import net.minecraft.nbt.ListNBT;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
@ -8,11 +13,6 @@ import net.minecraftforge.common.util.NonNullConsumer;
import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler;
import javax.annotation.Nonnull;
import java.util.Arrays;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class CombinedFluidHandler implements IFluidHandler { public class CombinedFluidHandler implements IFluidHandler {
private final int capacity; private final int capacity;
private final FluidStack[] tanks; private final FluidStack[] tanks;

View file

@ -37,7 +37,7 @@ public abstract class BasinOperatingTileEntity extends KineticTileEntity {
protected IRecipe<?> lastRecipe; protected IRecipe<?> lastRecipe;
protected LazyOptional<IItemHandler> basinItemInv = LazyOptional.empty(); protected LazyOptional<IItemHandler> basinItemInv = LazyOptional.empty();
protected LazyOptional<IFluidHandler> basinFluidInv = LazyOptional.empty(); protected LazyOptional<IFluidHandler> basinFluidInv = LazyOptional.empty();
protected MultiIngredientTypeList inputs; protected CombinedItemFluidList inputs;
public BasinOperatingTileEntity(TileEntityType<?> typeIn) { public BasinOperatingTileEntity(TileEntityType<?> typeIn) {
super(typeIn); super(typeIn);
@ -59,7 +59,7 @@ public abstract class BasinOperatingTileEntity extends KineticTileEntity {
} }
public void gatherInputs() { public void gatherInputs() {
inputs = new MultiIngredientTypeList(); inputs = new CombinedItemFluidList();
basinItemInv.ifPresent(inv -> { basinItemInv.ifPresent(inv -> {
IItemHandlerModifiable inputHandler = ((BasinInventory) inv).getInputHandler(); IItemHandlerModifiable inputHandler = ((BasinInventory) inv).getInputHandler();

View file

@ -3,6 +3,8 @@ package com.simibubi.create.content.contraptions.processing;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import javax.annotation.Nonnull;
import com.simibubi.create.content.contraptions.fluids.CombinedFluidHandler; import com.simibubi.create.content.contraptions.fluids.CombinedFluidHandler;
import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
@ -10,6 +12,7 @@ import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputB
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT;
import net.minecraft.tileentity.ITickableTileEntity; import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityType; import net.minecraft.tileentity.TileEntityType;
@ -24,8 +27,6 @@ import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.items.wrapper.CombinedInvWrapper; import net.minecraftforge.items.wrapper.CombinedInvWrapper;
import net.minecraftforge.items.wrapper.RecipeWrapper; import net.minecraftforge.items.wrapper.RecipeWrapper;
import javax.annotation.Nonnull;
public class BasinTileEntity extends SmartTileEntity implements ITickableTileEntity { public class BasinTileEntity extends SmartTileEntity implements ITickableTileEntity {
public boolean contentsChanged; public boolean contentsChanged;
@ -121,7 +122,7 @@ public class BasinTileEntity extends SmartTileEntity implements ITickableTileEnt
super.read(compound); super.read(compound);
inputItemInventory.deserializeNBT(compound.getCompound("InputItems")); inputItemInventory.deserializeNBT(compound.getCompound("InputItems"));
outputItemInventory.deserializeNBT(compound.getCompound("OutputItems")); outputItemInventory.deserializeNBT(compound.getCompound("OutputItems"));
if (compound.hasUniqueId("fluids")) if (compound.contains("fluids"))
fluidInventory fluidInventory
.ifPresent(combinedFluidHandler -> combinedFluidHandler.readFromNBT(compound.getList("fluids", 10))); .ifPresent(combinedFluidHandler -> combinedFluidHandler.readFromNBT(compound.getList("fluids", 10)));
} }
@ -131,7 +132,10 @@ public class BasinTileEntity extends SmartTileEntity implements ITickableTileEnt
super.write(compound); super.write(compound);
compound.put("InputItems", inputItemInventory.serializeNBT()); compound.put("InputItems", inputItemInventory.serializeNBT());
compound.put("OutputItems", outputItemInventory.serializeNBT()); compound.put("OutputItems", outputItemInventory.serializeNBT());
fluidInventory.ifPresent(combinedFuidHandler -> compound.put("fluids", combinedFuidHandler.getListNBT())); fluidInventory.ifPresent(combinedFuidHandler -> {
ListNBT nbt = combinedFuidHandler.getListNBT();
compound.put("fluids", nbt);
});
return compound; return compound;
} }

View file

@ -6,23 +6,31 @@ import net.minecraftforge.fluids.FluidStack;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.function.Consumer; import java.util.function.Consumer;
public class MultiIngredientTypeList { public class CombinedItemFluidList {
private final ArrayList<ItemStack> itemIngredients = new ArrayList<>(); private final ArrayList<ItemStack> itemStacks = new ArrayList<>();
private final ArrayList<FluidStack> fluidIngredients = new ArrayList<>(); private final ArrayList<FluidStack> fluidStacks = new ArrayList<>();
public void add(ItemStack itemstack) { public void add(ItemStack itemstack) {
itemIngredients.add(itemstack); itemStacks.add(itemstack);
} }
public void add(FluidStack fluidStack) { public void add(FluidStack fluidStack) {
fluidIngredients.add(fluidStack); fluidStacks.add(fluidStack);
} }
public void forEachItemStack(Consumer<? super ItemStack> itemStackConsumer) { public void forEachItemStack(Consumer<? super ItemStack> itemStackConsumer) {
itemIngredients.forEach(itemStackConsumer); itemStacks.forEach(itemStackConsumer);
} }
public void forEachFluidStack(Consumer<? super FluidStack> fluidStackConsumer) { public void forEachFluidStack(Consumer<? super FluidStack> fluidStackConsumer) {
fluidIngredients.forEach(fluidStackConsumer); fluidStacks.forEach(fluidStackConsumer);
}
public ArrayList<ItemStack> getItemStacks() {
return itemStacks;
}
public ArrayList<FluidStack> getFluidStacks() {
return fluidStacks;
} }
} }

View file

@ -7,9 +7,9 @@ import net.minecraft.network.PacketBuffer;
public class ProcessingOutput { public class ProcessingOutput {
private static Random r = new Random(); private static final Random r = new Random();
private ItemStack stack; private final ItemStack stack;
private float chance; private final float chance;
public ProcessingOutput(ItemStack stack, float chance) { public ProcessingOutput(ItemStack stack, float chance) {
this.stack = stack; this.stack = stack;

View file

@ -1,12 +1,12 @@
package com.simibubi.create.content.contraptions.processing; package com.simibubi.create.content.contraptions.processing;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.simibubi.create.AllRecipeTypes; import com.simibubi.create.AllRecipeTypes;
import com.simibubi.create.Create; import com.simibubi.create.Create;
import mcp.MethodsReturnNonnullByDefault;
import net.minecraft.inventory.IInventory; import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipe; import net.minecraft.item.crafting.IRecipe;
@ -15,7 +15,13 @@ import net.minecraft.item.crafting.IRecipeType;
import net.minecraft.item.crafting.Ingredient; import net.minecraft.item.crafting.Ingredient;
import net.minecraft.util.NonNullList; import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fluids.FluidStack;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
public abstract class ProcessingRecipe<T extends IInventory> implements IRecipe<T> { public abstract class ProcessingRecipe<T extends IInventory> implements IRecipe<T> {
protected final List<ProcessingIngredient> ingredients; protected final List<ProcessingIngredient> ingredients;
private final List<ProcessingOutput> results; private final List<ProcessingOutput> results;
@ -24,9 +30,11 @@ public abstract class ProcessingRecipe<T extends IInventory> implements IRecipe<
protected final ResourceLocation id; protected final ResourceLocation id;
protected final String group; protected final String group;
protected final int processingDuration; protected final int processingDuration;
protected final List<FluidStack> fluidIngredients;
protected final List<FluidStack> fluidResults;
public ProcessingRecipe(AllRecipeTypes recipeType, ResourceLocation id, String group, public ProcessingRecipe(AllRecipeTypes recipeType, ResourceLocation id, String group,
List<ProcessingIngredient> ingredients, List<ProcessingOutput> results, int processingDuration) { List<ProcessingIngredient> ingredients, List<ProcessingOutput> results, int processingDuration) {
this.type = recipeType.type; this.type = recipeType.type;
this.serializer = recipeType.serializer; this.serializer = recipeType.serializer;
this.id = id; this.id = id;
@ -34,20 +42,37 @@ public abstract class ProcessingRecipe<T extends IInventory> implements IRecipe<
this.ingredients = ingredients; this.ingredients = ingredients;
this.results = results; this.results = results;
this.processingDuration = processingDuration; this.processingDuration = processingDuration;
this.fluidIngredients = null;
this.fluidResults = null;
validate(recipeType);
}
public ProcessingRecipe(AllRecipeTypes recipeType, ResourceLocation id, String group,
List<ProcessingIngredient> ingredients, List<ProcessingOutput> results, int processingDuration,
@Nullable List<FluidStack> fluidIngredients, @Nullable List<FluidStack> fluidResults) {
this.type = recipeType.type;
this.serializer = recipeType.serializer;
this.id = id;
this.group = group;
this.ingredients = ingredients;
this.results = results;
this.processingDuration = processingDuration;
this.fluidIngredients = fluidIngredients;
this.fluidResults = fluidResults;
validate(recipeType); validate(recipeType);
} }
private void validate(AllRecipeTypes recipeType) { private void validate(AllRecipeTypes recipeType) {
if (ingredients.size() > getMaxInputCount()) if (ingredients.size() > getMaxInputCount())
Create.logger.warn("Your custom " + recipeType.name() + " recipe (" + id.toString() + ") has more inputs (" Create.logger.warn("Your custom " + recipeType.name() + " recipe (" + id.toString() + ") has more inputs ("
+ ingredients.size() + ") than supported (" + getMaxInputCount() + ")."); + ingredients.size() + ") than supported (" + getMaxInputCount() + ").");
if (results.size() > getMaxOutputCount()) if (results.size() > getMaxOutputCount())
Create.logger.warn("Your custom " + recipeType.name() + " recipe (" + id.toString() + ") has more outputs (" Create.logger.warn("Your custom " + recipeType.name() + " recipe (" + id.toString() + ") has more outputs ("
+ results.size() + ") than supported (" + getMaxOutputCount() + ")."); + results.size() + ") than supported (" + getMaxOutputCount() + ").");
ingredients.forEach(i -> { ingredients.forEach(i -> {
if (i.isCatalyst() && !canHaveCatalysts()) if (i.isCatalyst() && !canHaveCatalysts())
Create.logger.warn("Your custom " + recipeType.name() + " recipe (" + id.toString() Create.logger.warn("Your custom " + recipeType.name() + " recipe (" + id.toString()
+ ") has a catalyst ingredient, which act like a regular ingredient in this type."); + ") has a catalyst ingredient, which act like a regular ingredient in this type.");
}); });
} }
@ -62,14 +87,14 @@ public abstract class ProcessingRecipe<T extends IInventory> implements IRecipe<
return processingDuration; return processingDuration;
} }
public List<ItemStack> rollResults() { public CombinedItemFluidList rollResults() {
List<ItemStack> stacks = new ArrayList<>(); CombinedItemFluidList results = new CombinedItemFluidList();
for (ProcessingOutput output : getRollableResults()) { for (ProcessingOutput output : getRollableItemResults()) {
ItemStack stack = output.rollOutput(); ItemStack stack = output.rollOutput();
if (!stack.isEmpty()) if (!stack.isEmpty())
stacks.add(stack); results.add(stack);
} }
return stacks; return results;
} }
@Override @Override
@ -84,7 +109,9 @@ public abstract class ProcessingRecipe<T extends IInventory> implements IRecipe<
@Override @Override
public ItemStack getRecipeOutput() { public ItemStack getRecipeOutput() {
return getRollableResults().isEmpty() ? ItemStack.EMPTY : getRollableResults().get(0).getStack(); return getRollableItemResults().isEmpty() ? ItemStack.EMPTY
: getRollableItemResults().get(0)
.getStack();
} }
@Override @Override
@ -119,15 +146,25 @@ public abstract class ProcessingRecipe<T extends IInventory> implements IRecipe<
return false; return false;
} }
public List<ProcessingOutput> getRollableResults() { public List<ProcessingOutput> getRollableItemResults() {
return results; return results;
} }
public List<ProcessingIngredient> getRollableIngredients() { public List<ProcessingIngredient> getRollableIngredients() {
return ingredients; return ingredients;
} }
public List<ItemStack> getPossibleOutputs() { public List<ItemStack> getPossibleOutputs() {
return getRollableResults().stream().map(output -> output.getStack()).collect(Collectors.toList()); return getRollableItemResults().stream()
.map(ProcessingOutput::getStack)
.collect(Collectors.toList());
}
protected boolean canHaveFluidIngredient() {
return false;
}
protected boolean canHaveFluidOutput() {
return false;
} }
} }

View file

@ -6,15 +6,23 @@ import java.util.List;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import mcp.MethodsReturnNonnullByDefault;
import net.minecraft.fluid.Fluid;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipeSerializer; import net.minecraft.item.crafting.IRecipeSerializer;
import net.minecraft.network.PacketBuffer; import net.minecraft.network.PacketBuffer;
import net.minecraft.util.JSONUtils; import net.minecraft.util.JSONUtils;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.Registry;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.registries.ForgeRegistries;
import javax.annotation.ParametersAreNonnullByDefault;
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
public class ProcessingRecipeSerializer<T extends ProcessingRecipe<?>> public class ProcessingRecipeSerializer<T extends ProcessingRecipe<?>>
extends net.minecraftforge.registries.ForgeRegistryEntry<IRecipeSerializer<?>> implements IRecipeSerializer<T> { extends net.minecraftforge.registries.ForgeRegistryEntry<IRecipeSerializer<?>> implements IRecipeSerializer<T> {
protected final IRecipeFactory<T> factory; protected final IRecipeFactory<T> factory;
@ -27,32 +35,58 @@ public class ProcessingRecipeSerializer<T extends ProcessingRecipe<?>>
String s = JSONUtils.getString(json, "group", ""); String s = JSONUtils.getString(json, "group", "");
List<ProcessingIngredient> ingredients = new ArrayList<>(); List<ProcessingIngredient> ingredients = new ArrayList<>();
List<FluidStack> fluidIngredients = new ArrayList<>();
for (JsonElement e : JSONUtils.getJsonArray(json, "ingredients")) { for (JsonElement e : JSONUtils.getJsonArray(json, "ingredients")) {
int count = 1; JsonObject entry = e.getAsJsonObject();
if (JSONUtils.hasField((JsonObject) e, "count")) { if (JSONUtils.hasField(entry, "fluid")) {
count = JSONUtils.getInt(e.getAsJsonObject().get("count"), "count"); Fluid fluid = ForgeRegistries.FLUIDS
} .getValue(ResourceLocation.tryCreate(JSONUtils.getString(entry.get("fluid"), "fluid")));
for(int i = 0; i < count; i++) { int amount = 1;
ingredients.add(ProcessingIngredient.parse(e.getAsJsonObject())); if (JSONUtils.hasField((JsonObject) e, "amount")) {
amount = JSONUtils.getInt(entry.get("amount"), "amount");
}
if (fluid != null && amount > 0)
fluidIngredients.add(new FluidStack(fluid, amount));
} else {
int count = 1;
if (JSONUtils.hasField((JsonObject) e, "count")) {
count = JSONUtils.getInt(entry.get("count"), "count");
}
for (int i = 0; i < count; i++) {
ingredients.add(ProcessingIngredient.parse(entry));
}
} }
} }
List<ProcessingOutput> results = new ArrayList<>(); List<ProcessingOutput> results = new ArrayList<>();
List<FluidStack> fluidResults = new ArrayList<>();
for (JsonElement e : JSONUtils.getJsonArray(json, "results")) { for (JsonElement e : JSONUtils.getJsonArray(json, "results")) {
String s1 = JSONUtils.getString(e.getAsJsonObject().get("item"), "item"); JsonObject entry = e.getAsJsonObject();
int i = JSONUtils.getInt(e.getAsJsonObject().get("count"), "count"); if (JSONUtils.hasField(entry, "fluid")) {
float chance = 1; Fluid fluid = ForgeRegistries.FLUIDS
if (JSONUtils.hasField((JsonObject) e, "chance")) .getValue(ResourceLocation.tryCreate(JSONUtils.getString(entry.get("fluid"), "fluid")));
chance = JSONUtils.getFloat(e.getAsJsonObject().get("chance"), "chance"); int amount = 1;
ItemStack itemstack = new ItemStack(Registry.ITEM.getOrDefault(new ResourceLocation(s1)), i); if (JSONUtils.hasField((JsonObject) e, "amount")) {
results.add(new ProcessingOutput(itemstack, chance)); amount = JSONUtils.getInt(entry.get("amount"), "amount");
}
if (fluid != null && amount > 0)
fluidResults.add(new FluidStack(fluid, amount));
} else {
String s1 = JSONUtils.getString(entry.get("item"), "item");
int i = JSONUtils.getInt(entry.get("count"), "count");
float chance = 1;
if (JSONUtils.hasField((JsonObject) e, "chance"))
chance = JSONUtils.getFloat(entry.get("chance"), "chance");
ItemStack itemstack = new ItemStack(Registry.ITEM.getOrDefault(new ResourceLocation(s1)), i);
results.add(new ProcessingOutput(itemstack, chance));
}
} }
int duration = -1; int duration = -1;
if (JSONUtils.hasField(json, "processingTime")) if (JSONUtils.hasField(json, "processingTime"))
duration = JSONUtils.getInt(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, fluidIngredients, fluidResults);
} }
public T read(ResourceLocation recipeId, PacketBuffer buffer) { public T read(ResourceLocation recipeId, PacketBuffer buffer) {
@ -63,14 +97,24 @@ public class ProcessingRecipeSerializer<T extends ProcessingRecipe<?>>
for (int i = 0; i < ingredientCount; i++) for (int i = 0; i < ingredientCount; i++)
ingredients.add(ProcessingIngredient.parse(buffer)); ingredients.add(ProcessingIngredient.parse(buffer));
int fluidInputCount = buffer.readInt();
List<FluidStack> fluidIngredients = new ArrayList<>();
for (int i = 0; i < fluidInputCount; i++)
fluidIngredients.add(FluidStack.readFromPacket(buffer));
List<ProcessingOutput> results = new ArrayList<>(); List<ProcessingOutput> results = new ArrayList<>();
int outputCount = buffer.readInt(); int outputCount = buffer.readInt();
for (int i = 0; i < outputCount; i++) for (int i = 0; i < outputCount; i++)
results.add(ProcessingOutput.read(buffer)); results.add(ProcessingOutput.read(buffer));
int fluidOutputCount = buffer.readInt();
List<FluidStack> fluidResults = new ArrayList<>();
for (int i = 0; i < fluidOutputCount; i++)
fluidResults.add(FluidStack.readFromPacket(buffer));
int duration = buffer.readInt(); int duration = buffer.readInt();
return this.factory.create(recipeId, s, ingredients, results, duration); return this.factory.create(recipeId, s, ingredients, results, duration, fluidIngredients, fluidResults);
} }
public void write(PacketBuffer buffer, T recipe) { public void write(PacketBuffer buffer, T recipe) {
@ -78,16 +122,31 @@ public class ProcessingRecipeSerializer<T extends ProcessingRecipe<?>>
buffer.writeInt(recipe.ingredients.size()); buffer.writeInt(recipe.ingredients.size());
recipe.ingredients.forEach(i -> i.write(buffer)); recipe.ingredients.forEach(i -> i.write(buffer));
if (recipe.canHaveFluidIngredient() && recipe.fluidIngredients != null) {
buffer.writeInt(recipe.fluidIngredients.size());
recipe.fluidIngredients.forEach(fluidStack -> fluidStack.writeToPacket(buffer));
} else {
buffer.writeInt(0);
}
buffer.writeInt(recipe.getRollableResults().size()); buffer.writeInt(recipe.getRollableItemResults()
recipe.getRollableResults().forEach(i -> i.write(buffer)); .size());
recipe.getRollableItemResults()
.forEach(i -> i.write(buffer));
if (recipe.canHaveFluidOutput() && recipe.fluidResults != null) {
buffer.writeInt(recipe.fluidResults.size());
recipe.fluidResults.forEach(fluidStack -> fluidStack.writeToPacket(buffer));
} else {
buffer.writeInt(0);
}
buffer.writeInt(recipe.processingDuration); buffer.writeInt(recipe.processingDuration);
} }
public interface IRecipeFactory<T extends ProcessingRecipe<?>> { public interface IRecipeFactory<T extends ProcessingRecipe<?>> {
T create(ResourceLocation id, String group, List<ProcessingIngredient> ingredients, List<ProcessingOutput> results, T create(ResourceLocation recipeId, String s, List<ProcessingIngredient> ingredients,
int duration); List<ProcessingOutput> results, int duration, List<FluidStack> fluidIngredients,
List<FluidStack> fluidResults);
} }
} }

View file

@ -2,6 +2,7 @@ package com.simibubi.create.content.curiosities.tools;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import mcp.MethodsReturnNonnullByDefault;
import net.minecraft.enchantment.Enchantment; import net.minecraft.enchantment.Enchantment;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.item.ItemEntity; import net.minecraft.entity.item.ItemEntity;
@ -24,6 +25,10 @@ import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.common.util.FakePlayer; import net.minecraftforge.common.util.FakePlayer;
import javax.annotation.ParametersAreNonnullByDefault;
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
public class SandPaperItem extends Item { public class SandPaperItem extends Item {
public SandPaperItem(Properties properties) { public SandPaperItem(Properties properties) {
@ -68,8 +73,6 @@ public class SandPaperItem extends Item {
return FAIL; return FAIL;
BlockRayTraceResult ray = (BlockRayTraceResult) raytraceresult; BlockRayTraceResult ray = (BlockRayTraceResult) raytraceresult;
Vec3d hitVec = ray.getHitVec(); Vec3d hitVec = ray.getHitVec();
if (hitVec == null)
return FAIL;
AxisAlignedBB bb = new AxisAlignedBB(hitVec, hitVec).grow(1f); AxisAlignedBB bb = new AxisAlignedBB(hitVec, hitVec).grow(1f);
ItemEntity pickUp = null; ItemEntity pickUp = null;

View file

@ -10,19 +10,21 @@ import com.simibubi.create.content.curiosities.tools.SandPaperPolishingRecipe.Sa
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipe; import net.minecraft.item.crafting.IRecipe;
import net.minecraft.util.DamageSource;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.items.wrapper.RecipeWrapper; import net.minecraftforge.items.wrapper.RecipeWrapper;
import javax.annotation.ParametersAreNonnullByDefault;
@ParametersAreNonnullByDefault
public class SandPaperPolishingRecipe extends ProcessingRecipe<SandPaperInv> { public class SandPaperPolishingRecipe extends ProcessingRecipe<SandPaperInv> {
public static DamageSource CURSED_POLISHING = new DamageSource("create.curse_polish").setExplosion();
public SandPaperPolishingRecipe(ResourceLocation id, String group, List<ProcessingIngredient> ingredients, public SandPaperPolishingRecipe(ResourceLocation id, String group, List<ProcessingIngredient> ingredients,
List<ProcessingOutput> results, int processingDuration) { List<ProcessingOutput> results, int processingDuration, List<FluidStack> fluidIngredients,
List<FluidStack> fluidResults) {
super(AllRecipeTypes.SANDPAPER_POLISHING, id, group, ingredients, results, processingDuration); super(AllRecipeTypes.SANDPAPER_POLISHING, id, group, ingredients, results, processingDuration);
} }
@ -33,18 +35,21 @@ public class SandPaperPolishingRecipe extends ProcessingRecipe<SandPaperInv> {
public static ItemStack applyPolish(World world, Vec3d position, ItemStack stack, ItemStack sandPaperStack) { public static ItemStack applyPolish(World world, Vec3d position, ItemStack stack, ItemStack sandPaperStack) {
List<IRecipe<SandPaperInv>> matchingRecipes = getMatchingRecipes(world, stack); List<IRecipe<SandPaperInv>> matchingRecipes = getMatchingRecipes(world, stack);
if (!matchingRecipes.isEmpty()) if (!matchingRecipes.isEmpty())
return matchingRecipes.get(0).getCraftingResult(new SandPaperInv(stack)).copy(); return matchingRecipes.get(0)
.getCraftingResult(new SandPaperInv(stack))
.copy();
return stack; return stack;
} }
@Override @Override
public boolean matches(SandPaperInv inv, World worldIn) { public boolean matches(SandPaperInv inv, World worldIn) {
return ingredients.get(0).test(inv.getStackInSlot(0)); return ingredients.get(0)
.test(inv.getStackInSlot(0));
} }
public static List<IRecipe<SandPaperInv>> getMatchingRecipes(World world, ItemStack stack) { public static List<IRecipe<SandPaperInv>> getMatchingRecipes(World world, ItemStack stack) {
return world.getRecipeManager().getRecipes(AllRecipeTypes.SANDPAPER_POLISHING.getType(), new SandPaperInv(stack), return world.getRecipeManager()
world); .getRecipes(AllRecipeTypes.SANDPAPER_POLISHING.getType(), new SandPaperInv(stack), world);
} }
@Override @Override

View file

@ -263,7 +263,7 @@ public class InWorldProcessing {
if (recipe instanceof ProcessingRecipe) { if (recipe instanceof ProcessingRecipe) {
stacks = new ArrayList<>(); stacks = new ArrayList<>();
for (int i = 0; i < stackIn.getCount(); i++) { for (int i = 0; i < stackIn.getCount(); i++) {
List<ItemStack> rollResults = ((ProcessingRecipe<?>) recipe).rollResults(); List<ItemStack> rollResults = ((ProcessingRecipe<?>) recipe).rollResults().getItemStacks();
for (ItemStack stack : rollResults) { for (ItemStack stack : rollResults) {
for (ItemStack previouslyRolled : stacks) { for (ItemStack previouslyRolled : stacks) {
if (stack.isEmpty()) if (stack.isEmpty())