Preventing pipe feed back loop

This commit is contained in:
Calclavia 2014-01-25 20:37:25 +08:00
parent 676af2e409
commit dcc1a0caf5
3 changed files with 134 additions and 105 deletions

View file

@ -16,4 +16,6 @@ public interface IFluidConnector extends IConnector<IFluidNetwork>, IFluidHandle
public FluidTank getInternalTank(); public FluidTank getInternalTank();
public void onFluidChanged(); public void onFluidChanged();
public boolean canFlow();
} }

View file

@ -14,125 +14,140 @@ import resonantinduction.api.fluid.IFluidPipe;
import universalelectricity.api.vector.Vector3; import universalelectricity.api.vector.Vector3;
import calclavia.lib.utility.FluidUtility; import calclavia.lib.utility.FluidUtility;
/** The network for pipe fluid transfer. getNodes() is NOT used. /**
* The network for pipe fluid transfer. getNodes() is NOT used.
* *
* @author DarkGuardsman */ * @author DarkGuardsman
*/
public class PipeNetwork extends FluidNetwork public class PipeNetwork extends FluidNetwork
{ {
public HashMap<IFluidHandler, EnumSet<ForgeDirection>> connectionMap = new HashMap<IFluidHandler, EnumSet<ForgeDirection>>(); public HashMap<IFluidHandler, EnumSet<ForgeDirection>> sideMap = new HashMap<IFluidHandler, EnumSet<ForgeDirection>>();
public int maxFlowRate = 0; public HashMap<IFluidHandler, IFluidConnector> connectionMap = new HashMap<IFluidHandler, IFluidConnector>();
public int maxPressure = 0; public int maxFlowRate = 0;
public int maxPressure = 0;
@Override @Override
public void update() public void update()
{ {
/* /*
* Slight delay to allow visual effect to take place before draining the pipe's internal * Slight delay to allow visual effect to take place before draining the pipe's internal
* tank * tank
*/ */
FluidStack stack = this.getTank().getFluid().copy(); FluidStack stack = this.getTank().getFluid().copy();
int count = this.connectionMap.size(); int count = this.sideMap.size();
for (Entry<IFluidHandler, EnumSet<ForgeDirection>> entry : this.connectionMap.entrySet()) for (Entry<IFluidHandler, EnumSet<ForgeDirection>> entry : this.sideMap.entrySet())
{ {
int sideCount = entry.getValue().size(); int sideCount = entry.getValue().size();
for (ForgeDirection dir : entry.getValue())
{
int volPer = (stack.amount / count);
int volPerSide = (volPer / sideCount);
stack.amount -= entry.getKey().fill(dir, FluidUtility.getStack(stack, Math.min(volPerSide, this.maxFlowRate)), true); for (ForgeDirection dir : entry.getValue())
{
int volPer = (stack.amount / count);
int volPerSide = (volPer / sideCount);
IFluidHandler handler = entry.getKey();
if (sideCount > 1) /*
--sideCount; * Don't input to tanks from the sides where the pipe is extraction mode. This
if (volPer <= 0) * prevents feed-back loops.
break; */
} if (connectionMap.get(handler).canFlow())
{
stack.amount -= handler.fill(dir, FluidUtility.getStack(stack, Math.min(volPerSide, this.maxFlowRate)), true);
}
if (sideCount > 1)
--sideCount;
if (volPer <= 0)
break;
}
if (count > 1) if (count > 1)
count--; count--;
if (stack == null || stack.amount <= 0) if (stack == null || stack.amount <= 0)
{ {
stack = null; stack = null;
break; break;
} }
} }
this.getTank().setFluid(stack); this.getTank().setFluid(stack);
// TODO check for change before rebuilding // TODO check for change before rebuilding
this.reconstructTankInfo(); this.reconstructTankInfo();
} }
@Override @Override
public boolean canUpdate() public boolean canUpdate()
{ {
return getTank().getFluidAmount() > 0 && connectionMap.size() > 0 && getConnectors().size() > 0; return getTank().getFluidAmount() > 0 && sideMap.size() > 0 && getConnectors().size() > 0;
} }
@Override @Override
public boolean continueUpdate() public boolean continueUpdate()
{ {
return canUpdate(); return canUpdate();
} }
@Override @Override
public void reconstruct() public void reconstruct()
{ {
this.connectionMap.clear(); this.sideMap.clear();
this.maxFlowRate = Integer.MAX_VALUE; this.maxFlowRate = Integer.MAX_VALUE;
this.maxPressure = Integer.MAX_VALUE; this.maxPressure = Integer.MAX_VALUE;
super.reconstruct(); super.reconstruct();
} }
@Override @Override
public void reconstructConnector(IFluidConnector part) public void reconstructConnector(IFluidConnector connector)
{ {
super.reconstructConnector(part); super.reconstructConnector(connector);
if (part instanceof IFluidPipe)
{
if (((IFluidPipe) part).getMaxFlowRate() < this.maxFlowRate)
this.maxFlowRate = ((IFluidPipe) part).getMaxFlowRate();
if (((IFluidPipe) part).getMaxPressure() < this.maxPressure) if (connector instanceof IFluidPipe)
this.maxPressure = ((IFluidPipe) part).getMaxPressure(); {
} if (((IFluidPipe) connector).getMaxFlowRate() < this.maxFlowRate)
for (int i = 0; i < 6; i++) this.maxFlowRate = ((IFluidPipe) connector).getMaxFlowRate();
{
if (part.getConnections()[i] instanceof IFluidHandler && !(part.getConnections()[i] instanceof IFluidPipe))
{
EnumSet<ForgeDirection> set = this.connectionMap.get(part.getConnections()[i]);
if (set == null)
{
set = EnumSet.noneOf(ForgeDirection.class);
}
set.add(ForgeDirection.getOrientation(i).getOpposite());
this.connectionMap.put((IFluidHandler) part.getConnections()[i], set);
}
}
}
@Override if (((IFluidPipe) connector).getMaxPressure() < this.maxPressure)
public FluidStack drain(IFluidConnector source, ForgeDirection from, FluidStack resource, boolean doDrain) this.maxPressure = ((IFluidPipe) connector).getMaxPressure();
{ }
return null; for (int i = 0; i < 6; i++)
} {
if (connector.getConnections()[i] instanceof IFluidHandler && !(connector.getConnections()[i] instanceof IFluidPipe))
{
EnumSet<ForgeDirection> set = this.sideMap.get(connector.getConnections()[i]);
if (set == null)
{
set = EnumSet.noneOf(ForgeDirection.class);
}
@Override set.add(ForgeDirection.getOrientation(i).getOpposite());
public FluidStack drain(IFluidConnector source, ForgeDirection from, int resource, boolean doDrain) sideMap.put((IFluidHandler) connector.getConnections()[i], set);
{ connectionMap.put((IFluidHandler) connector.getConnections()[i], connector);
return null; }
} }
}
@Override @Override
public Class getConnectorClass() public FluidStack drain(IFluidConnector source, ForgeDirection from, FluidStack resource, boolean doDrain)
{ {
return IFluidPipe.class; return null;
} }
@Override @Override
public IFluidNetwork newInstance() public FluidStack drain(IFluidConnector source, ForgeDirection from, int resource, boolean doDrain)
{ {
return new PipeNetwork(); return null;
} }
@Override
public Class getConnectorClass()
{
return IFluidPipe.class;
}
@Override
public IFluidNetwork newInstance()
{
return new PipeNetwork();
}
} }

View file

@ -1,5 +1,6 @@
package resonantinduction.mechanical.fluid.pipe; package resonantinduction.mechanical.fluid.pipe;
import calclavia.lib.prefab.block.BlockAdvanced;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagCompound;
@ -70,10 +71,15 @@ public class PartPipe extends PartFramedConnection<EnumPipeMaterial, IFluidPipe,
@Override @Override
public boolean activate(EntityPlayer player, MovingObjectPosition part, ItemStack item) public boolean activate(EntityPlayer player, MovingObjectPosition part, ItemStack item)
{ {
if (!world().isRemote && player.isSneaking()) if (!world().isRemote)
{ {
isExtracting = !isExtracting; if (BlockAdvanced.isUsableWrench(player, player.getCurrentEquippedItem(), x(), y(), z()))
player.addChatMessage("Pipe extraction mode: " + isExtracting); {
isExtracting = !isExtracting;
player.addChatMessage("Pipe extraction mode: " + isExtracting);
BlockAdvanced.damageWrench(player, player.getCurrentEquippedItem(), x(), y(), z());
return true;
}
} }
return super.activate(player, part, item); return super.activate(player, part, item);
@ -213,4 +219,10 @@ public class PartPipe extends PartFramedConnection<EnumPipeMaterial, IFluidPipe,
isExtracting = nbt.getBoolean("isExtracting"); isExtracting = nbt.getBoolean("isExtracting");
} }
@Override
public boolean canFlow()
{
return !isExtracting;
}
} }