Crude basin fluid support

- basin can now store fluid
- fluid stored in basin will be bundled together with item in a MultiIngredientTypeList supporting both items and fluids
This commit is contained in:
LordGrimmauld 2020-07-08 18:20:49 +02:00
parent 6511cbcd7b
commit 3bcdac6080
7 changed files with 306 additions and 110 deletions

View file

@ -1,6 +1,7 @@
package com.simibubi.create.content.contraptions.components.mixer;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
@ -32,7 +33,7 @@ import net.minecraftforge.items.IItemHandler;
public class MechanicalMixerTileEntity extends BasinOperatingTileEntity {
private static Object shapelessOrMixingRecipesKey = new Object();
private static final Object shapelessOrMixingRecipesKey = new Object();
public int runningTicks;
public int processingTicks;
@ -47,15 +48,15 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity {
@Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
super.addBehaviours(behaviours);
CenteredSideValueBoxTransform slot =
new CenteredSideValueBoxTransform((state, direction) -> direction.getAxis().isHorizontal()) {
CenteredSideValueBoxTransform slot = new CenteredSideValueBoxTransform((state, direction) -> direction.getAxis()
.isHorizontal()) {
@Override
protected Vec3d getSouthLocation() {
return super.getSouthLocation().add(0, 4 / 16f, 0);
}
@Override
protected Vec3d getSouthLocation() {
return super.getSouthLocation().add(0, 4 / 16f, 0);
}
};
};
minIngredients = new ScrollValueBehaviour(Lang.translate("mechanical_mixer.min_ingredients"), this, slot);
minIngredients.between(1, 9);
minIngredients.withCallback(i -> basinChecker.scheduleUpdate());
@ -74,7 +75,7 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity {
offset = num - .5f;
} else if (runningTicks <= 20) {
offset = 1;
} else if (runningTicks > 20) {
} else {
localTick = 40 - runningTicks;
float num = (localTick - partialTicks) / 20f;
num = ((2 - MathHelper.cos((float) (num * Math.PI))) / 2);
@ -93,9 +94,7 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity {
if (runningTicks <= 20) {
return speed * 2;
}
if (runningTicks > 20) {
return speed;
}
return speed;
}
return speed / 2;
}
@ -130,7 +129,7 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity {
}
float speed = Math.abs(getSpeed());
if (running) {
if (running && world != null) {
if (world.isRemote && runningTicks == 20)
renderParticles();
@ -155,52 +154,53 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity {
}
public void renderParticles() {
IItemHandler itemHandler = basinInv.orElse(null);
if (itemHandler != null) {
BasinInventory inv = (BasinInventory) itemHandler;
IItemHandler itemHandler = basinItemInv.orElse(null);
BasinInventory inv = (BasinInventory) itemHandler;
for (int slot = 0; slot < inv.getInputHandler().getSlots(); slot++) {
ItemStack stackInSlot = itemHandler.getStackInSlot(slot);
if (stackInSlot.isEmpty())
continue;
for (int slot = 0; slot < inv.getInputHandler()
.getSlots(); slot++) {
ItemStack stackInSlot = itemHandler.getStackInSlot(slot);
if (stackInSlot.isEmpty())
continue;
ItemParticleData data = new ItemParticleData(ParticleTypes.ITEM, stackInSlot);
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);
ItemParticleData data = new ItemParticleData(ParticleTypes.ITEM, stackInSlot);
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);
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
protected <C extends IInventory> boolean matchStaticFilters(IRecipe<C> r) {
return (r.getSerializer() == IRecipeSerializer.CRAFTING_SHAPELESS || r.getType() == AllRecipeTypes.MIXING.type)
&& !MechanicalPressTileEntity.canCompress(r.getIngredients());
&& !MechanicalPressTileEntity.canCompress(r.getIngredients());
}
@Override
protected <C extends IInventory> boolean matchBasinRecipe(IRecipe<C> recipe) {
if (recipe == null)
return false;
if (recipe.getIngredients().size() < minIngredients.getValue())
if (recipe.getIngredients()
.size() < minIngredients.getValue())
return false;
NonNullList<Ingredient> ingredients = recipe.getIngredients();
if (!ingredients.stream()
.allMatch(ingredient -> (ingredient.isSimple() || ingredient.getMatchingStacks().length == 1)))
.allMatch(ingredient -> (ingredient.isSimple() || ingredient.getMatchingStacks().length == 1)))
return false;
List<ItemStack> remaining = new ArrayList<>();
inputs.forEach(stack -> remaining.add(stack.copy()));
inputs.forEachItemStack(stack -> remaining.add(stack.copy()));
// sort by leniency
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) {
for (ItemStack stack : remaining) {
if (stack.isEmpty())

View file

@ -39,7 +39,7 @@ import net.minecraftforge.items.wrapper.RecipeWrapper;
public class MechanicalPressTileEntity extends BasinOperatingTileEntity {
private static Object compressingRecipesKey = new Object();
private static final Object compressingRecipesKey = new Object();
public List<ItemStack> pressedItems = new ArrayList<>();
public static class PressingInv extends RecipeWrapper {
@ -55,12 +55,12 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity {
float headOffset;
private Mode(float headOffset) {
Mode(float headOffset) {
this.headOffset = headOffset;
}
}
private static PressingInv pressingInv = new PressingInv();
private static final PressingInv pressingInv = new PressingInv();
public BeltProcessingBehaviour processingBehaviour;
public int runningTicks;
@ -128,10 +128,8 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity {
float num = (runningTicks - 1 + partialTicks) / 30f;
return MathHelper.clamp(num * num * num, 0, mode.headOffset);
}
if (runningTicks >= 40) {
return MathHelper.clamp(((60 - runningTicks) + 1 - partialTicks) / 20f * mode.headOffset, 0,
mode.headOffset);
}
return MathHelper.clamp(((60 - runningTicks) + 1 - partialTicks) / 20f * mode.headOffset, 0,
mode.headOffset);
}
return 0;
}
@ -148,10 +146,6 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity {
return mode == Mode.WORLD;
}
public boolean onBelt() {
return mode == Mode.BELT;
}
public boolean onBasin() {
return mode == Mode.BASIN;
}
@ -160,7 +154,7 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity {
public void tick() {
super.tick();
if (!running)
if (!running || world == null)
return;
if (runningTicks == 30) {
@ -190,8 +184,8 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity {
if (!world.isRemote) {
pressedItems.clear();
applyBasinRecipe();
IItemHandler orElse = basinInv.orElse(null);
if (basinInv.isPresent() && orElse instanceof BasinInventory) {
IItemHandler orElse = basinItemInv.orElse(null);
if (basinItemInv.isPresent() && orElse instanceof BasinInventory) {
BasinInventory inv = (BasinInventory) orElse;
for (int slot = 0; slot < inv.getInputHandler()
@ -256,7 +250,7 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity {
}
public void makePressingParticleEffect(Vec3d pos, ItemStack stack) {
if (world.isRemote) {
if (world != null && world.isRemote) {
for (int i = 0; i < 20; i++) {
Vec3d motion = VecHelper.offsetRandomly(Vec3d.ZERO, world.rand, .125f)
.mul(1, 0, 1);
@ -267,7 +261,7 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity {
}
public void makeCompactingParticleEffect(Vec3d pos, ItemStack stack) {
if (world.isRemote) {
if (world != null && world.isRemote) {
for (int i = 0; i < 20; i++) {
Vec3d motion = VecHelper.offsetRandomly(Vec3d.ZERO, world.rand, .175f)
.mul(1, 0, 1);
@ -279,9 +273,8 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity {
public Optional<PressingRecipe> getRecipe(ItemStack item) {
pressingInv.setInventorySlotContents(0, item);
Optional<PressingRecipe> recipe = world.getRecipeManager()
return world.getRecipeManager()
.getRecipe(AllRecipeTypes.PRESSING.getType(), pressingInv, world);
return recipe;
}
public static boolean canCompress(NonNullList<Ingredient> ingredients) {
@ -305,7 +298,7 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity {
return false;
List<ItemStack> remaining = new ArrayList<>();
inputs.forEach(stack -> remaining.add(stack.copy()));
inputs.forEachItemStack(stack -> remaining.add(stack.copy()));
Ingredients: for (Ingredient ingredient : ingredients) {
for (ItemStack stack : remaining) {

View file

@ -0,0 +1,135 @@
package com.simibubi.create.content.contraptions.fluids;
import net.minecraft.fluid.Fluid;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT;
import net.minecraft.util.math.MathHelper;
import net.minecraftforge.common.util.NonNullConsumer;
import net.minecraftforge.fluids.FluidStack;
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 {
private final int capacity;
private final FluidStack[] tanks;
public CombinedFluidHandler(int tankNumber, int capacity) {
this.capacity = capacity;
this.tanks = new FluidStack[tankNumber];
Arrays.fill(tanks, FluidStack.EMPTY);
}
@Override
public int getTanks() {
return tanks.length;
}
@Nonnull
@Override
public FluidStack getFluidInTank(int tank) {
if (tank < 0 || tank >= tanks.length)
return FluidStack.EMPTY;
return tanks[tank];
}
@Override
public int getTankCapacity(int tank) {
return capacity;
}
@Override
public boolean isFluidValid(int tank, @Nonnull FluidStack stack) {
return (!stack.isEmpty()) && (tanks[tank].isEmpty() || tanks[tank].isFluidEqual(stack))
&& tanks[tank].getAmount() < capacity;
}
@Override
public int fill(FluidStack resource, FluidAction action) {
int tankIndex;
int amount = resource.getAmount();
while ((tankIndex = getFittingFluidSlot(resource)) != -1) {
int newAmount = MathHelper.clamp(amount - capacity - tanks[tankIndex].getAmount(), 0, Integer.MAX_VALUE);
if (action == FluidAction.EXECUTE)
if (tanks[tankIndex].isEmpty())
tanks[tankIndex] = new FluidStack(resource.getFluid(), amount - newAmount);
else
tanks[tankIndex].grow(amount - newAmount);
amount = newAmount;
if (amount == 0)
return 0;
}
return amount;
}
@Nonnull
@Override
public FluidStack drain(FluidStack resource, FluidAction action) {
if (resource.isEmpty())
return FluidStack.EMPTY;
FluidStack stack = new FluidStack(resource, 0);
for (int i = 0; i < tanks.length; i++) {
if (tanks[i].isFluidEqual(resource)) {
stack.grow(tanks[i].getAmount());
if (action == FluidAction.EXECUTE)
tanks[i] = FluidStack.EMPTY;
}
}
return stack.isEmpty() ? FluidStack.EMPTY : stack;
}
@Nonnull
@Override
public FluidStack drain(int maxDrain, FluidAction action) {
FluidStack stack = new FluidStack(tanks[0].getFluid(), 0);
for (int i = 0; i < tanks.length; i++) {
if (tanks[i].isFluidEqual(stack)) {
int newDrainAmount = MathHelper.clamp(stack.getAmount() + tanks[i].getAmount(), 0, maxDrain);
if (action == FluidAction.EXECUTE) {
tanks[i].shrink(newDrainAmount - stack.getAmount());
if (tanks[i].isEmpty())
tanks[i] = FluidStack.EMPTY;
}
stack.setAmount(newDrainAmount);
}
}
return stack.isEmpty() ? FluidStack.EMPTY : stack;
}
private int getFittingFluidSlot(FluidStack fluidStack) {
return IntStream.range(0, tanks.length)
.filter(i -> isFluidValid(i, fluidStack))
.findFirst()
.orElse(-1);
}
private void setFluid(FluidStack fluid, int tank) {
tanks[tank] = fluid;
}
public CombinedFluidHandler readFromNBT(ListNBT fluidNBTs) {
for (int i = 0; i < Math.min(tanks.length, fluidNBTs.size()); i++)
setFluid(FluidStack.loadFluidStackFromNBT(fluidNBTs.getCompound(i)), i);
return this;
}
public ListNBT getListNBT() {
return Arrays.stream(tanks)
.map(fluid -> fluid.writeToNBT(new CompoundNBT()))
.collect(Collectors.toCollection(ListNBT::new));
}
public void forEachTank(NonNullConsumer<FluidStack> fluidStackConsumer) {
Arrays.stream(tanks)
.forEach(fluidStackConsumer::accept);
}
}

View file

@ -43,7 +43,7 @@ public class BasinBlock extends Block implements ITE<BasinTileEntity>, IWrenchab
public TileEntity createTileEntity(BlockState state, IBlockReader world) {
return AllTileEntities.BASIN.create();
}
@Override
public ActionResultType onWrenched(BlockState state, ItemUseContext context) {
return ActionResultType.FAIL;
@ -51,8 +51,9 @@ public class BasinBlock extends Block implements ITE<BasinTileEntity>, IWrenchab
@Override
public ActionResultType onUse(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn,
BlockRayTraceResult hit) {
if (!player.getHeldItem(handIn).isEmpty())
BlockRayTraceResult hit) {
if (!player.getHeldItem(handIn)
.isEmpty())
return ActionResultType.PASS;
try {
@ -63,7 +64,8 @@ public class BasinBlock extends Block implements ITE<BasinTileEntity>, IWrenchab
inv.setStackInSlot(slot, ItemStack.EMPTY);
}
te.onEmptied();
} catch (TileEntityException e) {}
} catch (TileEntityException e) {
}
return ActionResultType.SUCCESS;
}
@ -79,15 +81,15 @@ public class BasinBlock extends Block implements ITE<BasinTileEntity>, IWrenchab
return;
ItemEntity itemEntity = (ItemEntity) entityIn;
withTileEntityDo(worldIn, entityIn.getPosition(), te -> {
ItemStack insertItem = ItemHandlerHelper.insertItem(te.inputInventory, itemEntity.getItem().copy(), false);
ItemStack insertItem = ItemHandlerHelper.insertItem(te.inputItemInventory, itemEntity.getItem()
.copy(), false);
if (insertItem.isEmpty()) {
itemEntity.remove();
if (!itemEntity.world.isRemote)
AllTriggers
.triggerForNearbyPlayers(AllTriggers.BASIN_THROW, itemEntity.world,
itemEntity.getPosition(), 3);
AllTriggers.triggerForNearbyPlayers(AllTriggers.BASIN_THROW, itemEntity.world,
itemEntity.getPosition(), 3);
return;
}
@ -107,8 +109,8 @@ public class BasinBlock extends Block implements ITE<BasinTileEntity>, IWrenchab
}
withTileEntityDo(worldIn, pos, te -> {
ItemHelper.dropContents(worldIn, pos, te.inputInventory);
ItemHelper.dropContents(worldIn, pos, te.outputInventory);
ItemHelper.dropContents(worldIn, pos, te.inputItemInventory);
ItemHelper.dropContents(worldIn, pos, te.outputItemInventory);
});
worldIn.removeTileEntity(pos);
}
@ -121,8 +123,9 @@ public class BasinBlock extends Block implements ITE<BasinTileEntity>, IWrenchab
@Override
public int getComparatorInputOverride(BlockState blockState, World worldIn, BlockPos pos) {
try {
return ItemHelper.calcRedstoneFromInventory(getTileEntity(worldIn, pos).inputInventory);
} catch (TileEntityException e) {}
return ItemHelper.calcRedstoneFromInventory(getTileEntity(worldIn, pos).inputItemInventory);
} catch (TileEntityException e) {
}
return 0;
}

View file

@ -7,6 +7,7 @@ import java.util.stream.Collectors;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.fluids.CombinedFluidHandler;
import com.simibubi.create.content.contraptions.processing.BasinTileEntity.BasinInventory;
import com.simibubi.create.foundation.advancement.AllTriggers;
import com.simibubi.create.foundation.advancement.SimpleTrigger;
@ -22,6 +23,8 @@ import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.NonNullList;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.IItemHandlerModifiable;
@ -32,8 +35,9 @@ public abstract class BasinOperatingTileEntity extends KineticTileEntity {
public DeferralBehaviour basinChecker;
public boolean basinRemoved;
protected IRecipe<?> lastRecipe;
protected LazyOptional<IItemHandler> basinInv = LazyOptional.empty();
protected List<ItemStack> inputs;
protected LazyOptional<IItemHandler> basinItemInv = LazyOptional.empty();
protected LazyOptional<IFluidHandler> basinFluidInv = LazyOptional.empty();
protected MultiIngredientTypeList inputs;
public BasinOperatingTileEntity(TileEntityType<?> typeIn) {
super(typeIn);
@ -55,17 +59,19 @@ public abstract class BasinOperatingTileEntity extends KineticTileEntity {
}
public void gatherInputs() {
if (!basinInv.isPresent())
return;
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);
inputs = new MultiIngredientTypeList();
basinItemInv.ifPresent(inv -> {
IItemHandlerModifiable inputHandler = ((BasinInventory) 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);
}
}
}
});
basinFluidInv.ifPresent(iFluidHandler -> ((CombinedFluidHandler) iFluidHandler).forEachTank(inputs::add));
}
@Override
@ -91,12 +97,16 @@ public abstract class BasinOperatingTileEntity extends KineticTileEntity {
Optional<BasinTileEntity> basinTe = getBasin();
if (!basinTe.isPresent())
return true;
if (!basinInv.isPresent())
basinInv = basinTe.get().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY);
if (!basinInv.isPresent())
if (!basinItemInv.isPresent())
basinItemInv = basinTe.get()
.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY);
if (!basinFluidInv.isPresent())
basinFluidInv = basinTe.get()
.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY);
if (!basinFluidInv.isPresent() || !basinItemInv.isPresent())
return true;
if (world.isRemote)
if (world == null || world.isRemote)
return true;
gatherInputs();
@ -112,8 +122,7 @@ public abstract class BasinOperatingTileEntity extends KineticTileEntity {
protected abstract boolean isRunning();
public void startProcessingBasin() {
}
public void startProcessingBasin() {}
public boolean continueWithPreviousRecipe() {
return true;
@ -122,12 +131,10 @@ public abstract class BasinOperatingTileEntity extends KineticTileEntity {
public void applyBasinRecipe() {
if (lastRecipe == null)
return;
if (!basinInv.isPresent())
if (!basinItemInv.isPresent() || !basinFluidInv.isPresent())
return;
BasinInventory inv = (BasinInventory) basinInv.orElse(null);
if (inv == null)
return;
BasinInventory inv = (BasinInventory) basinItemInv.orElse(null);
IItemHandlerModifiable inputs = inv.getInputHandler();
IItemHandlerModifiable outputs = inv.getOutputHandler();
@ -142,25 +149,29 @@ public abstract class BasinOperatingTileEntity extends KineticTileEntity {
continue;
ItemStack extracted = inputs.extractItem(slot, 1, false);
if ((lastRecipe instanceof ProcessingRecipe)
&& ((ProcessingRecipe<?>) lastRecipe).getRollableIngredients().get(i).remains()) {
&& ((ProcessingRecipe<?>) lastRecipe).getRollableIngredients()
.get(i)
.remains()) {
catalysts.add(extracted.copy());
} else if (extracted.hasContainerItem()) {
containers.add(extracted.getContainerItem().copy());
containers.add(extracted.getContainerItem()
.copy());
}
continue Ingredients;
}
// something wasn't found
return;
}
if (!world.isRemote) {
if (world != null && !world.isRemote) {
SimpleTrigger trigger = AllTriggers.MIXER_MIX;
if (AllTileEntities.MECHANICAL_PRESS.is(this))
trigger = AllTriggers.PRESS_COMPACT;
AllTriggers.triggerForNearbyPlayers(trigger, world, pos, 4);
}
ItemHandlerHelper.insertItemStacked(outputs, lastRecipe.getRecipeOutput().copy(), false);
ItemHandlerHelper.insertItemStacked(outputs, lastRecipe.getRecipeOutput()
.copy(), false);
containers.forEach(stack -> ItemHandlerHelper.insertItemStacked(outputs, stack, false));
catalysts.forEach(c -> ItemHandlerHelper.insertItemStacked(outputs, c, false));
@ -176,9 +187,12 @@ public abstract class BasinOperatingTileEntity extends KineticTileEntity {
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());
return list.stream()
.filter(this::matchBasinRecipe)
.sorted((r1, r2) -> -r1.getIngredients()
.size() + r2.getIngredients()
.size())
.collect(Collectors.toList());
}
protected void basinRemoved() {
@ -186,6 +200,8 @@ public abstract class BasinOperatingTileEntity extends KineticTileEntity {
}
protected Optional<BasinTileEntity> getBasin() {
if (world == null)
return Optional.empty();
TileEntity basinTE = world.getTileEntity(pos.down(2));
if (!(basinTE instanceof BasinTileEntity))
return Optional.empty();

View file

@ -3,6 +3,7 @@ package com.simibubi.create.content.contraptions.processing;
import java.util.List;
import java.util.Optional;
import com.simibubi.create.content.contraptions.fluids.CombinedFluidHandler;
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour;
@ -15,6 +16,7 @@ import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.ItemHandlerHelper;
@ -22,11 +24,13 @@ import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.items.wrapper.CombinedInvWrapper;
import net.minecraftforge.items.wrapper.RecipeWrapper;
import javax.annotation.Nonnull;
public class BasinTileEntity extends SmartTileEntity implements ITickableTileEntity {
public boolean contentsChanged;
protected ItemStackHandler outputInventory = new ItemStackHandler(9) {
protected ItemStackHandler outputItemInventory = new ItemStackHandler(9) {
protected void onContentsChanged(int slot) {
sendData();
markDirty();
@ -35,18 +39,19 @@ public class BasinTileEntity extends SmartTileEntity implements ITickableTileEnt
public class BasinInputInventory extends RecipeWrapper {
public BasinInputInventory() {
super(inputInventory);
super(inputItemInventory);
}
}
protected ItemStackHandler inputInventory = new ItemStackHandler(9) {
protected ItemStackHandler inputItemInventory = new ItemStackHandler(9) {
protected void onContentsChanged(int slot) {
contentsChanged = true;
sendData();
markDirty();
};
}
public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) {
@Nonnull
public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) {
for (int i = 0; i < getSlots(); i++) {
ItemStack stackInSlot = getStackInSlot(i);
if (ItemHandlerHelper.canItemStacksStack(stack, stackInSlot))
@ -54,7 +59,7 @@ public class BasinTileEntity extends SmartTileEntity implements ITickableTileEnt
return stack;
}
return super.insertItem(slot, stack, simulate);
};
}
};
public static class BasinInventory extends CombinedInvWrapper {
@ -62,6 +67,7 @@ public class BasinTileEntity extends SmartTileEntity implements ITickableTileEnt
super(input, output);
}
@Nonnull
@Override
public ItemStack extractItem(int slot, int amount, boolean simulate) {
if (isInput(slot))
@ -69,8 +75,9 @@ public class BasinTileEntity extends SmartTileEntity implements ITickableTileEnt
return super.extractItem(slot, amount, simulate);
}
@Nonnull
@Override
public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) {
public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) {
if (!isInput(slot))
return stack;
return super.insertItem(slot, stack, simulate);
@ -91,7 +98,11 @@ public class BasinTileEntity extends SmartTileEntity implements ITickableTileEnt
}
protected LazyOptional<IItemHandlerModifiable> inventory =
LazyOptional.of(() -> new BasinInventory(inputInventory, outputInventory));
LazyOptional.of(() -> new BasinInventory(inputItemInventory, outputItemInventory));
protected LazyOptional<CombinedFluidHandler> fluidInventory =
LazyOptional.of(() -> new CombinedFluidHandler(9, 1000));
public BasinInputInventory recipeInventory;
public BasinTileEntity(TileEntityType<? extends BasinTileEntity> type) {
@ -99,24 +110,28 @@ public class BasinTileEntity extends SmartTileEntity implements ITickableTileEnt
contentsChanged = true;
recipeInventory = new BasinInputInventory();
}
@Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
behaviours.add(new DirectBeltInputBehaviour(this));
}
@Override
public void read(CompoundNBT compound) {
super.read(compound);
inputInventory.deserializeNBT(compound.getCompound("InputItems"));
outputInventory.deserializeNBT(compound.getCompound("OutputItems"));
inputItemInventory.deserializeNBT(compound.getCompound("InputItems"));
outputItemInventory.deserializeNBT(compound.getCompound("OutputItems"));
if (compound.hasUniqueId("fluids"))
fluidInventory
.ifPresent(combinedFluidHandler -> combinedFluidHandler.readFromNBT(compound.getList("fluids", 10)));
}
@Override
public CompoundNBT write(CompoundNBT compound) {
super.write(compound);
compound.put("InputItems", inputInventory.serializeNBT());
compound.put("OutputItems", outputInventory.serializeNBT());
compound.put("InputItems", inputItemInventory.serializeNBT());
compound.put("OutputItems", outputItemInventory.serializeNBT());
fluidInventory.ifPresent(combinedFuidHandler -> compound.put("fluids", combinedFuidHandler.getListNBT()));
return compound;
}
@ -128,13 +143,17 @@ public class BasinTileEntity extends SmartTileEntity implements ITickableTileEnt
public void remove() {
onEmptied();
inventory.invalidate();
fluidInventory.invalidate();
super.remove();
}
@Nonnull
@Override
public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) {
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, Direction side) {
if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
return inventory.cast();
if (cap == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY)
return fluidInventory.cast();
return super.getCapability(cap, side);
}
@ -147,6 +166,8 @@ public class BasinTileEntity extends SmartTileEntity implements ITickableTileEnt
}
private Optional<BasinOperatingTileEntity> getOperator() {
if (world == null)
return Optional.empty();
TileEntity te = world.getTileEntity(pos.up(2));
if (te instanceof BasinOperatingTileEntity)
return Optional.of((BasinOperatingTileEntity) te);

View file

@ -0,0 +1,28 @@
package com.simibubi.create.content.contraptions.processing;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fluids.FluidStack;
import java.util.ArrayList;
import java.util.function.Consumer;
public class MultiIngredientTypeList {
private final ArrayList<ItemStack> itemIngredients = new ArrayList<>();
private final ArrayList<FluidStack> fluidIngredients = new ArrayList<>();
public void add(ItemStack itemstack) {
itemIngredients.add(itemstack);
}
public void add(FluidStack fluidStack) {
fluidIngredients.add(fluidStack);
}
public void forEachItemStack(Consumer<? super ItemStack> itemStackConsumer) {
itemIngredients.forEach(itemStackConsumer);
}
public void forEachFluidStack(Consumer<? super FluidStack> fluidStackConsumer) {
fluidIngredients.forEach(fluidStackConsumer);
}
}