diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf
index 44c4915e7..76361606e 100644
--- a/src/main/resources/application.conf
+++ b/src/main/resources/application.conf
@@ -1403,6 +1403,12 @@ opencomputers {
# Radius the MFU is able to operate in
mfuRange: 3
+
+ # Transposer fluid transfer rate specified in millibuckets per second.
+ # While the transposer can transfer an unlimited amount in a single
+ # operation, it will block the computer for a duration matching the
+ # limit set in this config option.
+ transposerFluidTransferRate=4000
}
# Settings for mod integration (the mod previously known as OpenComponents).
diff --git a/src/main/scala/li/cil/oc/Settings.scala b/src/main/scala/li/cil/oc/Settings.scala
index da166a236..85eb7d4d7 100644
--- a/src/main/scala/li/cil/oc/Settings.scala
+++ b/src/main/scala/li/cil/oc/Settings.scala
@@ -51,6 +51,7 @@ class Settings(val config: Config) {
(-1.0, -1.0)
}
val enableNanomachinePfx = config.getBoolean("client.enableNanomachinePfx")
+ val transposerFluidTransferRate = config.getInt("misc.transposerFluidTransferRate")
// ----------------------------------------------------------------------- //
// computer
diff --git a/src/main/scala/li/cil/oc/server/component/traits/InventoryTransfer.scala b/src/main/scala/li/cil/oc/server/component/traits/InventoryTransfer.scala
index e2b5ac91d..be3cc69b4 100644
--- a/src/main/scala/li/cil/oc/server/component/traits/InventoryTransfer.scala
+++ b/src/main/scala/li/cil/oc/server/component/traits/InventoryTransfer.scala
@@ -1,5 +1,6 @@
package li.cil.oc.server.component.traits
+import li.cil.oc.Settings
import li.cil.oc.api.machine.Arguments
import li.cil.oc.api.machine.Callback
import li.cil.oc.api.machine.Context
@@ -40,20 +41,21 @@ trait InventoryTransfer extends traits.WorldAware with traits.SideRestricted {
}
}
- @Callback(doc = """function(sourceSide:number, sinkSide:number[, count:number]):number -- Transfer some items between two inventories.""")
+ @Callback(doc = """function(sourceSide:number, sinkSide:number[, count:number [, sourceTank:number]]):boolean, number -- Transfer some fluid between two tanks. Returns operation result and filled amount""")
def transferFluid(context: Context, args: Arguments): Array[AnyRef] = {
val sourceSide = checkSideForAction(args, 0)
val sourcePos = position.offset(sourceSide)
val sinkSide = checkSideForAction(args, 1)
val sinkPos = position.offset(sinkSide)
val count = args.optFluidCount(2)
+ val sourceTank = args.optInteger(3, -1)
onTransferContents() match {
case Some(reason) =>
result(Unit, reason)
case _ =>
- val moved = FluidUtils.transferBetweenFluidHandlersAt(sourcePos, sourceSide.getOpposite, sinkPos, sinkSide.getOpposite, count)
- if (moved > 0) context.pause(moved / 1000 * 0.25) // Allow up to 4 buckets per second.
+ val moved = FluidUtils.transferBetweenFluidHandlersAt(sourcePos, sourceSide.getOpposite, sinkPos, sinkSide.getOpposite, count, sourceTank)
+ if (moved > 0) context.pause(moved / Settings.get.transposerFluidTransferRate) // Allow up to 16 buckets per second.
result(moved > 0, moved)
}
}
diff --git a/src/main/scala/li/cil/oc/util/FluidUtils.scala b/src/main/scala/li/cil/oc/util/FluidUtils.scala
index 0dfdb739e..7fc24381b 100644
--- a/src/main/scala/li/cil/oc/util/FluidUtils.scala
+++ b/src/main/scala/li/cil/oc/util/FluidUtils.scala
@@ -40,13 +40,26 @@ object FluidUtils {
*
* This returns true if some fluid was transferred.
*/
- def transferBetweenFluidHandlers(source: IFluidHandler, sourceSide: ForgeDirection, sink: IFluidHandler, sinkSide: ForgeDirection, limit: Int = FluidContainerRegistry.BUCKET_VOLUME) : Int = {
- val drained = source.drain(sourceSide, limit, false)
- if (drained == null) {
- return 0
+ def transferBetweenFluidHandlers(source: IFluidHandler, sourceSide: ForgeDirection, sink: IFluidHandler, sinkSide: ForgeDirection, limit: Int = FluidContainerRegistry.BUCKET_VOLUME, sourceTank: Int = -1) : Int = {
+ val ti = source.getTankInfo(sourceSide)
+ val srcFluid = if (sourceTank < 0 || ti == null || ti.length <= sourceTank) null else ti(sourceTank).fluid.copy()
+
+ val nullFluid = srcFluid == null;
+ val drained = if (nullFluid)
+ source.drain(sourceSide, limit, false)
+ else {
+ srcFluid.amount = limit
+ source.drain(sourceSide, srcFluid, false)
}
- val filled = sink.fill(sinkSide, drained, false)
- sink.fill(sinkSide, source.drain(sourceSide, filled, true), true)
+ if (drained != null) {
+ val filled = sink.fill(sinkSide, drained, false)
+ if (nullFluid) {
+ sink.fill(sinkSide, source.drain(sourceSide, filled, true), true)
+ } else {
+ srcFluid.amount = filled
+ sink.fill(sinkSide, source.drain(sourceSide, srcFluid, true), true)
+ }
+ } else 0
}
/**
@@ -56,10 +69,10 @@ object FluidUtils {
* This uses the fluidHandlerAt method, and therefore handles special
* cases such as fluid blocks.
*/
- def transferBetweenFluidHandlersAt(sourcePos: BlockPosition, sourceSide: ForgeDirection, sinkPos: BlockPosition, sinkSide: ForgeDirection, limit: Int = FluidContainerRegistry.BUCKET_VOLUME) =
+ def transferBetweenFluidHandlersAt(sourcePos: BlockPosition, sourceSide: ForgeDirection, sinkPos: BlockPosition, sinkSide: ForgeDirection, limit: Int = FluidContainerRegistry.BUCKET_VOLUME, sourceTank: Int = -1) =
fluidHandlerAt(sourcePos).fold(0)(source =>
fluidHandlerAt(sinkPos).fold(0)(sink =>
- transferBetweenFluidHandlers(source, sourceSide, sink, sinkSide, limit)))
+ transferBetweenFluidHandlers(source, sourceSide, sink, sinkSide, limit, sourceTank)))
/**
* Lookup fluid taking into account flowing liquid blocks...