Skip to content

Commit

Permalink
implement FluidHandlers
Browse files Browse the repository at this point in the history
  • Loading branch information
dphaldes committed Nov 13, 2023
1 parent 6cbe6b8 commit 215d205
Show file tree
Hide file tree
Showing 3 changed files with 181 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,41 @@

import java.util.EnumMap;
import java.util.List;
import java.util.function.IntConsumer;

/**
* MachineFluidStorage takes a list of fluid tanks and handles IO for them all.
*/
public class MachineFluidHandler implements IFluidHandler, IEnderCapabilityProvider<IFluidHandler> {
private final IIOConfig config;

private final List<IFluidTank> tanks;
private final MachineTankLayout layout;
private final List<MachineTank> tanks;

private final EnumMap<Direction, LazyOptional<Sided>> sideCache = new EnumMap<>(Direction.class);
private LazyOptional<MachineFluidHandler> selfCache = LazyOptional.empty();

public MachineFluidHandler(IIOConfig config, IFluidTank... tanks) {
// Not sure if we need this but might be useful to update recipe/task if tank is filled.
private IntConsumer changeListener = i -> {};

public MachineFluidHandler(IIOConfig config, MachineTankLayout layout) {
this.config = config;
this.tanks = List.of(tanks);
this.layout = layout;
this.tanks = layout.createTanks();
}

public void addSlotChangedCallback(IntConsumer callback) {
changeListener = changeListener.andThen(callback);
}

public final IIOConfig getConfig() {
return config;
}

public MachineTankLayout getLayout() {
return layout;
}

//Not a good idea to use this method. Tank Access should be the way to access tanks
public final IFluidTank getTank(int tank) {
return tanks.get(tank);
}
Expand All @@ -58,6 +72,49 @@ public boolean isFluidValid(int tank, FluidStack stack) {
return tanks.get(tank).isFluidValid(stack);
}

@Override
public Capability<IFluidHandler> getCapabilityType() {
return ForgeCapabilities.FLUID_HANDLER;
}

@Override
public LazyOptional<IFluidHandler> getCapability(@Nullable Direction side) {
if (side == null) {
// Create own cache if its been invalidated or not created yet.
if (!selfCache.isPresent()) {
selfCache = LazyOptional.of(() -> this);
}

return selfCache.cast();
}

if (!config.getMode(side).canConnect()) {
return LazyOptional.empty();
}

return sideCache.computeIfAbsent(side, dir -> LazyOptional.of(() -> new Sided(this, dir))).cast();
}

@Override
public void invalidateSide(@Nullable Direction side) {
if (side != null) {
if (sideCache.containsKey(side)) {
sideCache.get(side).invalidate();
sideCache.remove(side);
}
} else {
selfCache.invalidate();
}
}

@Override
public void invalidateCaps() {
for (LazyOptional<Sided> side : sideCache.values()) {
side.invalidate();
}
selfCache.invalidate();
}

@Override
public int fill(FluidStack resource, FluidAction action) {
// Don't waste any time.
Expand Down Expand Up @@ -106,49 +163,6 @@ public FluidStack drain(int maxDrain, FluidAction action) {
return FluidStack.EMPTY;
}

@Override
public Capability<IFluidHandler> getCapabilityType() {
return ForgeCapabilities.FLUID_HANDLER;
}

@Override
public LazyOptional<IFluidHandler> getCapability(@Nullable Direction side) {
if (side == null) {
// Create own cache if its been invalidated or not created yet.
if (!selfCache.isPresent()) {
selfCache = LazyOptional.of(() -> this);
}

return selfCache.cast();
}

if (!config.getMode(side).canConnect()) {
return LazyOptional.empty();
}

return sideCache.computeIfAbsent(side, dir -> LazyOptional.of(() -> new Sided(this, dir))).cast();
}

@Override
public void invalidateSide(@Nullable Direction side) {
if (side != null) {
if (sideCache.containsKey(side)) {
sideCache.get(side).invalidate();
sideCache.remove(side);
}
} else {
selfCache.invalidate();
}
}

@Override
public void invalidateCaps() {
for (LazyOptional<Sided> side : sideCache.values()) {
side.invalidate();
}
selfCache.invalidate();
}

// Sided capability access
private static class Sided implements IFluidHandler {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package com.enderio.machines.common.io.fluid;

import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.IFluidTank;
import net.minecraftforge.fluids.capability.IFluidHandler;
import org.jetbrains.annotations.NotNull;

import java.util.function.Predicate;

//Replace MachineFluidTank
public class MachineTank implements IFluidTank {

private final int capacity;
private final Predicate<FluidStack> validator;

private boolean canInsert;

private boolean canExtract;
@NotNull private FluidStack fluid = FluidStack.EMPTY;

public MachineTank(int capacity, Predicate<FluidStack> validator, boolean canInsert, boolean canExtract) {
this.capacity = capacity;
this.validator = validator;
this.canInsert = canInsert;
this.canExtract = canExtract;
}

@Override
public int getCapacity() {
return capacity;
}

@Override
public @NotNull FluidStack getFluid() {
return fluid;
}

@Override
public int getFluidAmount() {
return fluid.getAmount();
}

@Override
public boolean isFluidValid(FluidStack stack) {
return validator.test(stack);
}

public int fill(FluidStack resource, IFluidHandler.FluidAction action) {
if (!canInsert || resource.isEmpty() || !isFluidValid(resource)) {
return 0;
}
if (action.simulate()) {
if (fluid.isEmpty()) {
return Math.min(capacity, resource.getAmount());
}
if (!fluid.isFluidEqual(resource)) {
return 0;
}
return Math.min(capacity - fluid.getAmount(), resource.getAmount());
}
if (fluid.isEmpty()) {
fluid = new FluidStack(resource, Math.min(capacity, resource.getAmount()));
onContentsChanged();
return fluid.getAmount();
}
if (!fluid.isFluidEqual(resource)) {
return 0;
}
int filled = capacity - fluid.getAmount();

if (resource.getAmount() < filled) {
fluid.grow(resource.getAmount());
filled = resource.getAmount();
} else {
fluid.setAmount(capacity);
}
if (filled > 0)
onContentsChanged();
return filled;
}

@NotNull
@Override
public FluidStack drain(FluidStack resource, IFluidHandler.FluidAction action) {
if (!canExtract || resource.isEmpty() || !resource.isFluidEqual(fluid)) {
return FluidStack.EMPTY;
}
return drain(resource.getAmount(), action);
}

@NotNull
@Override
public FluidStack drain(int maxDrain, IFluidHandler.FluidAction action) {
int drained = maxDrain;
if (fluid.getAmount() < drained) {
drained = fluid.getAmount();
}
FluidStack stack = new FluidStack(fluid, drained);
if (action.execute() && drained > 0) {
fluid.shrink(drained);
onContentsChanged();
}
return stack;
}

protected void onContentsChanged() {

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,19 @@ public boolean isFluidValid(int slot, FluidStack stack) {
return tanks.get(slot).filter().test(stack);
}

public List<MachineTank> createTanks() {
List<MachineTank> tankList = new ArrayList<>();
tanks.forEach((config -> {
tankList.add(new MachineTank(config.capacity, config.filter, config.insert, config.extract));
}));
return tankList;
}

public static class Builder {
private final ArrayList<TankConfig> tanks = new ArrayList<>();

public Builder tank(TankAccess access, int capacity, boolean canInsert, boolean canRemove, Predicate<FluidStack> filter) {
tanks.add(new TankConfig(capacity, canInsert, canRemove, filter));
public Builder tank(TankAccess access, int capacity, boolean canInsert, boolean canExtract, Predicate<FluidStack> filter) {
tanks.add(new TankConfig(capacity, canInsert, canExtract, filter));
access.init(tanks.size() - 1);
return this;
}
Expand Down

0 comments on commit 215d205

Please sign in to comment.