mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-16 05:53:41 +01:00
Workstation transfer, Part II
- Intermediate changes, probably doesn't even compile
This commit is contained in:
parent
d9d5e60606
commit
2d6d360da4
6 changed files with 473 additions and 114 deletions
|
@ -3,9 +3,9 @@ package com.simibubi.create.content.contraptions.fluids.actors;
|
|||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import com.simibubi.create.AllBlockPartials;
|
||||
import com.simibubi.create.foundation.fluid.FluidRenderer;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour.TankSegment;
|
||||
import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer;
|
||||
import com.simibubi.create.foundation.utility.LerpedFloat;
|
||||
import com.simibubi.create.foundation.utility.Pair;
|
||||
|
||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
|
@ -27,9 +27,13 @@ public class SpoutRenderer extends SafeTileEntityRenderer<SpoutTileEntity> {
|
|||
protected void renderSafe(SpoutTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer,
|
||||
int light, int overlay) {
|
||||
|
||||
Pair<FluidStack, LerpedFloat> fluid = te.getFluid();
|
||||
FluidStack fluidStack = fluid.getFirst();
|
||||
float level = fluid.getSecond()
|
||||
SmartFluidTankBehaviour tank = te.tank;
|
||||
if (tank == null)
|
||||
return;
|
||||
|
||||
TankSegment primaryTank = tank.getPrimaryTank();
|
||||
FluidStack fluidStack = primaryTank.getRenderedFluid();
|
||||
float level = primaryTank.getFluidLevel()
|
||||
.getValue(partialTicks);
|
||||
|
||||
if (!fluidStack.isEmpty() && level != 0) {
|
||||
|
|
|
@ -7,16 +7,13 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack;
|
||||
import com.simibubi.create.foundation.fluid.SmartFluidTank;
|
||||
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour.ProcessingResult;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour.TransportedResult;
|
||||
import com.simibubi.create.foundation.utility.LerpedFloat;
|
||||
import com.simibubi.create.foundation.utility.LerpedFloat.Chaser;
|
||||
import com.simibubi.create.foundation.utility.Pair;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
@ -32,58 +29,22 @@ import net.minecraftforge.common.capabilities.Capability;
|
|||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler;
|
||||
import net.minecraftforge.fluids.capability.templates.FluidTank;
|
||||
|
||||
// FIXME: Quite similar to FluidTankTileEntity, create a behaviour
|
||||
|
||||
public class SpoutTileEntity extends SmartTileEntity {
|
||||
|
||||
protected FluidTank tank;
|
||||
protected LazyOptional<IFluidHandler> capability;
|
||||
protected LerpedFloat fluidLevel;
|
||||
protected FluidStack renderedFluid;
|
||||
|
||||
public static final int FILLING_TIME = 20;
|
||||
protected int processingTicks;
|
||||
|
||||
private static final int SYNC_RATE = 8;
|
||||
protected int syncCooldown;
|
||||
protected boolean queuedSync;
|
||||
|
||||
protected boolean sendSplash;
|
||||
protected BeltProcessingBehaviour beltProcessing;
|
||||
protected int processingTicks;
|
||||
protected boolean sendSplash;
|
||||
|
||||
SmartFluidTankBehaviour tank;
|
||||
|
||||
public SpoutTileEntity(TileEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
tank = new SmartFluidTank(1000, this::onFluidStackChanged);
|
||||
capability = LazyOptional.of(() -> tank);
|
||||
fluidLevel = LerpedFloat.linear()
|
||||
.startWithValue(0)
|
||||
.chase(0, .25, Chaser.EXP);
|
||||
renderedFluid = FluidStack.EMPTY;
|
||||
processingTicks = -1;
|
||||
}
|
||||
|
||||
protected void onFluidStackChanged(FluidStack newFluidStack) {
|
||||
if (!hasWorld())
|
||||
return;
|
||||
fluidLevel.chase(tank.getFluidAmount() / (float) tank.getCapacity(), .25, Chaser.EXP);
|
||||
if (!world.isRemote) {
|
||||
markDirty();
|
||||
sendData();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
if (!world.isRemote) {
|
||||
fluidLevel.forceNextSync();
|
||||
onFluidStackChanged(tank.getFluid());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AxisAlignedBB getRenderBoundingBox() {
|
||||
return super.getRenderBoundingBox().expand(0, -2, 0);
|
||||
|
@ -91,9 +52,13 @@ public class SpoutTileEntity extends SmartTileEntity {
|
|||
|
||||
@Override
|
||||
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
|
||||
tank = SmartFluidTankBehaviour.single(this, 1000);
|
||||
behaviours.add(tank);
|
||||
|
||||
beltProcessing = new BeltProcessingBehaviour(this).whenItemEnters(this::onItemReceived)
|
||||
.whileItemHeld(this::whenItemHeld);
|
||||
behaviours.add(beltProcessing);
|
||||
|
||||
}
|
||||
|
||||
protected ProcessingResult onItemReceived(TransportedItemStack transported,
|
||||
|
@ -102,7 +67,7 @@ public class SpoutTileEntity extends SmartTileEntity {
|
|||
return PASS;
|
||||
if (tank.isEmpty())
|
||||
return HOLD;
|
||||
if (FillingBySpout.getRequiredAmountForItem(world, transported.stack, tank.getFluid()) == -1)
|
||||
if (FillingBySpout.getRequiredAmountForItem(world, transported.stack, getCurrentFluidInTank()) == -1)
|
||||
return PASS;
|
||||
return HOLD;
|
||||
}
|
||||
|
@ -115,7 +80,7 @@ public class SpoutTileEntity extends SmartTileEntity {
|
|||
return PASS;
|
||||
if (tank.isEmpty())
|
||||
return HOLD;
|
||||
FluidStack fluid = tank.getFluid();
|
||||
FluidStack fluid = getCurrentFluidInTank();
|
||||
int requiredAmountForItem = FillingBySpout.getRequiredAmountForItem(world, transported.stack, fluid.copy());
|
||||
if (requiredAmountForItem == -1)
|
||||
return PASS;
|
||||
|
@ -142,24 +107,21 @@ public class SpoutTileEntity extends SmartTileEntity {
|
|||
handler.handleProcessingOnItem(transported, TransportedResult.convertToAndLeaveHeld(outList, held));
|
||||
}
|
||||
|
||||
tank.setFluid(fluid);
|
||||
tank.getPrimaryHandler().setFluid(fluid);
|
||||
sendSplash = true;
|
||||
markDirty();
|
||||
sendData();
|
||||
return PASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
capability.invalidate();
|
||||
super.remove();
|
||||
private FluidStack getCurrentFluidInTank() {
|
||||
return tank.getPrimaryHandler().getFluid();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void write(CompoundNBT compound, boolean clientPacket) {
|
||||
super.write(compound, clientPacket);
|
||||
compound.put("TankContent", tank.writeToNBT(new CompoundNBT()));
|
||||
compound.put("Level", fluidLevel.writeNBT());
|
||||
|
||||
compound.putInt("ProcessingTicks", processingTicks);
|
||||
if (sendSplash && clientPacket) {
|
||||
compound.putBoolean("Splash", true);
|
||||
|
@ -170,61 +132,27 @@ public class SpoutTileEntity extends SmartTileEntity {
|
|||
@Override
|
||||
protected void read(CompoundNBT compound, boolean clientPacket) {
|
||||
super.read(compound, clientPacket);
|
||||
tank.readFromNBT(compound.getCompound("TankContent"));
|
||||
fluidLevel.readNBT(compound.getCompound("Level"), clientPacket);
|
||||
processingTicks = compound.getInt("ProcessingTicks");
|
||||
if (!tank.getFluid()
|
||||
.isEmpty())
|
||||
renderedFluid = tank.getFluid();
|
||||
|
||||
if (!clientPacket)
|
||||
return;
|
||||
if (compound.contains("Splash"))
|
||||
spawnSplash(renderedFluid);
|
||||
spawnSplash(tank.getPrimaryTank().getRenderedFluid());
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) {
|
||||
if (cap == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY && side != Direction.DOWN)
|
||||
return capability.cast();
|
||||
return tank.getCapability().cast();
|
||||
return super.getCapability(cap, side);
|
||||
}
|
||||
|
||||
public Pair<FluidStack, LerpedFloat> getFluid() {
|
||||
return Pair.of(renderedFluid, fluidLevel);
|
||||
}
|
||||
|
||||
public void sendDataImmediately() {
|
||||
syncCooldown = 0;
|
||||
queuedSync = false;
|
||||
sendData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
if (processingTicks >= 0)
|
||||
processingTicks--;
|
||||
if (processingTicks >= 8 && world.isRemote)
|
||||
spawnProcessingParticles(renderedFluid);
|
||||
if (syncCooldown > 0) {
|
||||
syncCooldown--;
|
||||
if (syncCooldown == 0 && queuedSync)
|
||||
sendData();
|
||||
}
|
||||
if (fluidLevel != null)
|
||||
fluidLevel.tickChaser();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendData() {
|
||||
if (syncCooldown > 0) {
|
||||
queuedSync = true;
|
||||
return;
|
||||
}
|
||||
super.sendData();
|
||||
queuedSync = false;
|
||||
syncCooldown = SYNC_RATE;
|
||||
spawnProcessingParticles(tank.getPrimaryTank().getRenderedFluid());
|
||||
}
|
||||
|
||||
protected void spawnProcessingParticles(FluidStack fluid) {
|
||||
|
|
|
@ -5,18 +5,18 @@ import java.util.Optional;
|
|||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import com.simibubi.create.content.contraptions.fluids.CombinedFluidHandler;
|
||||
import com.simibubi.create.foundation.fluid.CombinedTankWrapper;
|
||||
import com.simibubi.create.foundation.item.SmartInventory;
|
||||
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.nbt.ListNBT;
|
||||
import net.minecraft.tileentity.ITickableTileEntity;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.tileentity.TileEntityType;
|
||||
|
@ -27,6 +27,7 @@ import net.minecraftforge.api.distmarker.OnlyIn;
|
|||
import net.minecraftforge.common.capabilities.Capability;
|
||||
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.IItemHandlerModifiable;
|
||||
import net.minecraftforge.items.wrapper.CombinedInvWrapper;
|
||||
|
@ -34,20 +35,25 @@ import net.minecraftforge.items.wrapper.CombinedInvWrapper;
|
|||
public class BasinTileEntity extends SmartTileEntity implements ITickableTileEntity {
|
||||
|
||||
public BasinInputInventory inputInventory;
|
||||
protected SmartInventory outputInventory;
|
||||
protected LazyOptional<IItemHandlerModifiable> itemCapability;
|
||||
protected LazyOptional<CombinedFluidHandler> fluidCapability;
|
||||
public SmartFluidTankBehaviour inputTank;
|
||||
|
||||
protected SmartInventory outputInventory;
|
||||
protected SmartFluidTankBehaviour outputTank;
|
||||
|
||||
protected LazyOptional<IItemHandlerModifiable> itemCapability;
|
||||
protected LazyOptional<IFluidHandler> fluidCapability;
|
||||
|
||||
private boolean contentsChanged;
|
||||
private FilteringBehaviour filtering;
|
||||
private boolean contentsChanged;
|
||||
|
||||
public BasinTileEntity(TileEntityType<? extends BasinTileEntity> type) {
|
||||
super(type);
|
||||
inputInventory = new BasinInputInventory(9, this);
|
||||
inputInventory.withMaxStackSize(8).forbidExtraction();
|
||||
inputInventory.withMaxStackSize(8)
|
||||
.forbidExtraction();
|
||||
outputInventory = new SmartInventory(9, this).forbidInsertion();
|
||||
itemCapability = LazyOptional.of(() -> new CombinedInvWrapper(inputInventory, outputInventory));
|
||||
fluidCapability = LazyOptional.of(() -> new CombinedFluidHandler(9, 1000));
|
||||
|
||||
contentsChanged = true;
|
||||
}
|
||||
|
||||
|
@ -58,6 +64,16 @@ public class BasinTileEntity extends SmartTileEntity implements ITickableTileEnt
|
|||
.withCallback(newFilter -> contentsChanged = true)
|
||||
.forRecipes();
|
||||
behaviours.add(filtering);
|
||||
|
||||
inputTank = new SmartFluidTankBehaviour(SmartFluidTankBehaviour.INPUT, this, 2, 1000, true).forbidExtraction();
|
||||
outputTank = new SmartFluidTankBehaviour(SmartFluidTankBehaviour.OUTPUT, this, 2, 1000, true).forbidInsertion();
|
||||
behaviours.add(inputTank);
|
||||
behaviours.add(outputTank);
|
||||
fluidCapability = LazyOptional.of(() -> {
|
||||
LazyOptional<? extends IFluidHandler> inputCap = inputTank.getCapability();
|
||||
LazyOptional<? extends IFluidHandler> outputCap = outputTank.getCapability();
|
||||
return new CombinedTankWrapper(inputCap.orElse(null), outputCap.orElse(null));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -65,9 +81,6 @@ public class BasinTileEntity extends SmartTileEntity implements ITickableTileEnt
|
|||
super.read(compound, clientPacket);
|
||||
inputInventory.deserializeNBT(compound.getCompound("InputItems"));
|
||||
outputInventory.deserializeNBT(compound.getCompound("OutputItems"));
|
||||
if (compound.contains("fluids"))
|
||||
fluidCapability
|
||||
.ifPresent(combinedFluidHandler -> combinedFluidHandler.readFromNBT(compound.getList("fluids", 10)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -75,10 +88,6 @@ public class BasinTileEntity extends SmartTileEntity implements ITickableTileEnt
|
|||
super.write(compound, clientPacket);
|
||||
compound.put("InputItems", inputInventory.serializeNBT());
|
||||
compound.put("OutputItems", outputInventory.serializeNBT());
|
||||
fluidCapability.ifPresent(combinedFuidHandler -> {
|
||||
ListNBT nbt = combinedFuidHandler.getListNBT();
|
||||
compound.put("fluids", nbt);
|
||||
});
|
||||
}
|
||||
|
||||
public void onEmptied() {
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
package com.simibubi.create.foundation.fluid;
|
||||
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler;
|
||||
import net.minecraftforge.items.wrapper.EmptyHandler;
|
||||
|
||||
/**
|
||||
* Combines multiple IFluidHandlers into one interface (See CombinedInvWrapper
|
||||
* for items)
|
||||
*/
|
||||
public class CombinedTankWrapper implements IFluidHandler {
|
||||
|
||||
protected final IFluidHandler[] itemHandler;
|
||||
protected final int[] baseIndex;
|
||||
protected final int tankCount;
|
||||
protected boolean enforceVariety;
|
||||
|
||||
public CombinedTankWrapper(IFluidHandler... fluidHandlers) {
|
||||
this.itemHandler = fluidHandlers;
|
||||
this.baseIndex = new int[fluidHandlers.length];
|
||||
int index = 0;
|
||||
for (int i = 0; i < fluidHandlers.length; i++) {
|
||||
index += fluidHandlers[i].getTanks();
|
||||
baseIndex[i] = index;
|
||||
}
|
||||
this.tankCount = index;
|
||||
}
|
||||
|
||||
public CombinedTankWrapper enforceVariety() {
|
||||
enforceVariety = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTanks() {
|
||||
return tankCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FluidStack getFluidInTank(int tank) {
|
||||
int index = getIndexForSlot(tank);
|
||||
IFluidHandler handler = getHandlerFromIndex(index);
|
||||
tank = getSlotFromIndex(tank, index);
|
||||
return handler.getFluidInTank(tank);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTankCapacity(int tank) {
|
||||
int index = getIndexForSlot(tank);
|
||||
IFluidHandler handler = getHandlerFromIndex(index);
|
||||
int localSlot = getSlotFromIndex(tank, index);
|
||||
return handler.getTankCapacity(localSlot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFluidValid(int tank, FluidStack stack) {
|
||||
int index = getIndexForSlot(tank);
|
||||
IFluidHandler handler = getHandlerFromIndex(index);
|
||||
int localSlot = getSlotFromIndex(tank, index);
|
||||
return handler.isFluidValid(localSlot, stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int fill(FluidStack resource, FluidAction action) {
|
||||
int filled = 0;
|
||||
resource = resource.copy();
|
||||
|
||||
for (IFluidHandler iFluidHandler : itemHandler) {
|
||||
boolean skipRest = false;
|
||||
int filledIntoCurrent = iFluidHandler.fill(resource, action);
|
||||
|
||||
for (int i = 0; i < iFluidHandler.getTanks(); i++)
|
||||
if (iFluidHandler.getFluidInTank(i).isFluidEqual(resource) && enforceVariety)
|
||||
skipRest = true;
|
||||
|
||||
resource.shrink(filledIntoCurrent);
|
||||
filled += filledIntoCurrent;
|
||||
|
||||
if (resource.isEmpty() || skipRest)
|
||||
break;
|
||||
}
|
||||
|
||||
return filled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FluidStack drain(FluidStack resource, FluidAction action) {
|
||||
FluidStack drained = FluidStack.EMPTY;
|
||||
resource = resource.copy();
|
||||
|
||||
for (IFluidHandler iFluidHandler : itemHandler) {
|
||||
FluidStack drainedFromCurrent = iFluidHandler.drain(resource, action);
|
||||
int amount = drainedFromCurrent.getAmount();
|
||||
resource.shrink(amount);
|
||||
|
||||
if (!drainedFromCurrent.isEmpty())
|
||||
drained = new FluidStack(drainedFromCurrent.getFluid(), amount + drained.getAmount());
|
||||
if (resource.isEmpty())
|
||||
break;
|
||||
}
|
||||
|
||||
return drained;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FluidStack drain(int maxDrain, FluidAction action) {
|
||||
FluidStack drained = FluidStack.EMPTY;
|
||||
|
||||
for (IFluidHandler iFluidHandler : itemHandler) {
|
||||
FluidStack drainedFromCurrent = iFluidHandler.drain(maxDrain, action);
|
||||
int amount = drainedFromCurrent.getAmount();
|
||||
maxDrain -= amount;
|
||||
|
||||
if (!drainedFromCurrent.isEmpty())
|
||||
drained = new FluidStack(drainedFromCurrent.getFluid(), amount + drained.getAmount());
|
||||
if (maxDrain == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return drained;
|
||||
}
|
||||
|
||||
protected int getIndexForSlot(int slot) {
|
||||
if (slot < 0)
|
||||
return -1;
|
||||
for (int i = 0; i < baseIndex.length; i++)
|
||||
if (slot - baseIndex[i] < 0)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
protected IFluidHandler getHandlerFromIndex(int index) {
|
||||
if (index < 0 || index >= itemHandler.length)
|
||||
return (IFluidHandler) EmptyHandler.INSTANCE;
|
||||
return itemHandler[index];
|
||||
}
|
||||
|
||||
protected int getSlotFromIndex(int slot, int index) {
|
||||
if (index <= 0 || index >= baseIndex.length)
|
||||
return slot;
|
||||
return slot - baseIndex[index - 1];
|
||||
}
|
||||
}
|
|
@ -4,4 +4,18 @@ import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
|||
|
||||
public class BehaviourType<T extends TileEntityBehaviour> {
|
||||
|
||||
private String name;
|
||||
|
||||
public BehaviourType(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public BehaviourType() {
|
||||
this("");
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,261 @@
|
|||
package com.simibubi.create.foundation.tileEntity.behaviour.fluid;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.apache.commons.lang3.mutable.MutableInt;
|
||||
|
||||
import com.simibubi.create.foundation.fluid.CombinedTankWrapper;
|
||||
import com.simibubi.create.foundation.fluid.SmartFluidTank;
|
||||
import com.simibubi.create.foundation.item.SmartInventory;
|
||||
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType;
|
||||
import com.simibubi.create.foundation.utility.LerpedFloat;
|
||||
import com.simibubi.create.foundation.utility.LerpedFloat.Chaser;
|
||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.nbt.ListNBT;
|
||||
import net.minecraftforge.common.util.Constants.NBT;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler;
|
||||
|
||||
public class SmartFluidTankBehaviour extends TileEntityBehaviour {
|
||||
|
||||
public static BehaviourType<SmartFluidTankBehaviour>
|
||||
|
||||
TYPE = new BehaviourType<>(), INPUT = new BehaviourType<>("Input"), OUTPUT = new BehaviourType<>("Output");
|
||||
|
||||
private static final int SYNC_RATE = 8;
|
||||
|
||||
protected int syncCooldown;
|
||||
protected boolean queuedSync;
|
||||
protected TankSegment[] tanks;
|
||||
protected LazyOptional<? extends IFluidHandler> capability;
|
||||
protected boolean extractionAllowed;
|
||||
protected boolean insertionAllowed;
|
||||
|
||||
private BehaviourType<SmartFluidTankBehaviour> behaviourType;
|
||||
|
||||
public static SmartFluidTankBehaviour single(SmartTileEntity te, int capacity) {
|
||||
return new SmartFluidTankBehaviour(TYPE, te, 1, capacity, false);
|
||||
}
|
||||
|
||||
public SmartFluidTankBehaviour(BehaviourType<SmartFluidTankBehaviour> type, SmartTileEntity te, int tanks,
|
||||
int tankCapacity, boolean enforceVariety) {
|
||||
super(te);
|
||||
insertionAllowed = true;
|
||||
extractionAllowed = true;
|
||||
behaviourType = type;
|
||||
this.tanks = new TankSegment[tanks];
|
||||
IFluidHandler[] handlers = new IFluidHandler[tanks];
|
||||
for (int i = 0; i < tanks; i++) {
|
||||
TankSegment tankSegment = new TankSegment(tankCapacity);
|
||||
this.tanks[i] = tankSegment;
|
||||
handlers[i] = tankSegment.tank;
|
||||
}
|
||||
capability = LazyOptional.of(() -> new InternalFluidHandler(handlers));
|
||||
}
|
||||
|
||||
public SmartFluidTankBehaviour allowInsertion() {
|
||||
insertionAllowed = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SmartFluidTankBehaviour allowExtraction() {
|
||||
extractionAllowed = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SmartFluidTankBehaviour forbidInsertion() {
|
||||
insertionAllowed = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SmartFluidTankBehaviour forbidExtraction() {
|
||||
extractionAllowed = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
if (getWorld().isRemote)
|
||||
return;
|
||||
foreach(ts -> {
|
||||
ts.fluidLevel.forceNextSync();
|
||||
ts.onFluidStackChanged(ts.tank.getFluid());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
|
||||
if (syncCooldown > 0) {
|
||||
syncCooldown--;
|
||||
if (syncCooldown == 0 && queuedSync)
|
||||
tileEntity.sendData();
|
||||
}
|
||||
|
||||
foreach(te -> {
|
||||
LerpedFloat fluidLevel = te.getFluidLevel();
|
||||
if (fluidLevel != null)
|
||||
fluidLevel.tickChaser();
|
||||
});
|
||||
}
|
||||
|
||||
public void sendDataImmediately() {
|
||||
syncCooldown = 0;
|
||||
queuedSync = false;
|
||||
tileEntity.sendData();
|
||||
}
|
||||
|
||||
public void sendDataLazily() {
|
||||
if (syncCooldown > 0) {
|
||||
queuedSync = true;
|
||||
return;
|
||||
}
|
||||
tileEntity.sendData();
|
||||
queuedSync = false;
|
||||
syncCooldown = SYNC_RATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
super.remove();
|
||||
capability.invalidate();
|
||||
}
|
||||
|
||||
public SmartFluidTank getPrimaryHandler() {
|
||||
return getPrimaryTank().tank;
|
||||
}
|
||||
|
||||
public TankSegment getPrimaryTank() {
|
||||
return tanks[0];
|
||||
}
|
||||
|
||||
public TankSegment[] getTanks() {
|
||||
return tanks;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
for (TankSegment tankSegment : tanks)
|
||||
if (!tankSegment.tank.isEmpty())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void foreach(Consumer<TankSegment> action) {
|
||||
for (TankSegment tankSegment : tanks)
|
||||
action.accept(tankSegment);
|
||||
}
|
||||
|
||||
public LazyOptional<? extends IFluidHandler> getCapability() {
|
||||
return capability;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(CompoundNBT nbt, boolean clientPacket) {
|
||||
super.write(nbt, clientPacket);
|
||||
ListNBT tanksNBT = new ListNBT();
|
||||
foreach(ts -> tanksNBT.add(ts.writeNBT()));
|
||||
nbt.put(getType().getName() + "Tanks", tanksNBT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(CompoundNBT nbt, boolean clientPacket) {
|
||||
super.read(nbt, clientPacket);
|
||||
MutableInt index = new MutableInt(0);
|
||||
NBTHelper.iterateCompoundList(nbt.getList(getType().getName() + "Tanks", NBT.TAG_COMPOUND), c -> {
|
||||
if (index.intValue() >= tanks.length)
|
||||
return;
|
||||
tanks[index.intValue()].readNBT(c, clientPacket);
|
||||
index.increment();
|
||||
});
|
||||
}
|
||||
|
||||
class InternalFluidHandler extends CombinedTankWrapper {
|
||||
|
||||
public InternalFluidHandler(IFluidHandler[] handlers) {
|
||||
super(handlers);
|
||||
if (enforceVariety)
|
||||
enforceVariety();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int fill(FluidStack resource, FluidAction action) {
|
||||
if (!insertionAllowed)
|
||||
return 0;
|
||||
return super.fill(resource, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FluidStack drain(FluidStack resource, FluidAction action) {
|
||||
if (!extractionAllowed)
|
||||
return FluidStack.EMPTY;
|
||||
return super.drain(resource, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FluidStack drain(int maxDrain, FluidAction action) {
|
||||
if (!extractionAllowed)
|
||||
return FluidStack.EMPTY;
|
||||
return super.drain(maxDrain, action);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class TankSegment {
|
||||
|
||||
protected SmartFluidTank tank;
|
||||
protected LerpedFloat fluidLevel;
|
||||
protected FluidStack renderedFluid;
|
||||
|
||||
public TankSegment(int capacity) {
|
||||
tank = new SmartFluidTank(1000, f -> onFluidStackChanged(f));
|
||||
fluidLevel = LerpedFloat.linear()
|
||||
.startWithValue(0)
|
||||
.chase(0, .25, Chaser.EXP);
|
||||
renderedFluid = FluidStack.EMPTY;
|
||||
}
|
||||
|
||||
protected void onFluidStackChanged(FluidStack newFluidStack) {
|
||||
if (!tileEntity.hasWorld())
|
||||
return;
|
||||
fluidLevel.chase(tank.getFluidAmount() / (float) tank.getCapacity(), .25, Chaser.EXP);
|
||||
if (!getWorld().isRemote)
|
||||
sendDataLazily();
|
||||
}
|
||||
|
||||
public FluidStack getRenderedFluid() {
|
||||
return renderedFluid;
|
||||
}
|
||||
|
||||
public LerpedFloat getFluidLevel() {
|
||||
return fluidLevel;
|
||||
}
|
||||
|
||||
public CompoundNBT writeNBT() {
|
||||
CompoundNBT compound = new CompoundNBT();
|
||||
compound.put("TankContent", tank.writeToNBT(new CompoundNBT()));
|
||||
compound.put("Level", fluidLevel.writeNBT());
|
||||
return compound;
|
||||
}
|
||||
|
||||
public void readNBT(CompoundNBT compound, boolean clientPacket) {
|
||||
tank.readFromNBT(compound.getCompound("TankContent"));
|
||||
fluidLevel.readNBT(compound.getCompound("Level"), clientPacket);
|
||||
if (!tank.getFluid()
|
||||
.isEmpty())
|
||||
renderedFluid = tank.getFluid();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public BehaviourType<?> getType() {
|
||||
return behaviourType;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue