mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-28 16:06:48 +01:00
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:
parent
6511cbcd7b
commit
3bcdac6080
7 changed files with 306 additions and 110 deletions
|
@ -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())
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue