From a4b11f5201f00cbf995ea5d41ebf7fa5288ea923 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Sat, 19 Sep 2015 11:42:24 +0200 Subject: [PATCH] Pulled core transposer logic out into trait. More homogenous use of result(Unit, ...) vs. the occasiona result(null, ...) --- .../cil/oc/common/tileentity/Hologram.scala | 4 +- .../li/cil/oc/common/tileentity/Printer.scala | 4 +- .../appeng/PartEnvironmentBase.scala | 2 +- .../dsu/DriverDeepStorageUnit.scala | 2 +- .../scala/li/cil/oc/server/agent/Player.scala | 2 + .../cil/oc/server/component/DebugCard.scala | 10 ++-- .../oc/server/component/InternetCard.scala | 6 +-- .../cil/oc/server/component/Transposer.scala | 44 ++------------- .../component/traits/InventoryTransfer.scala | 54 +++++++++++++++++++ .../traits/WorldInventoryAnalytics.scala | 4 +- 10 files changed, 76 insertions(+), 56 deletions(-) create mode 100644 src/main/scala/li/cil/oc/server/component/traits/InventoryTransfer.scala diff --git a/src/main/scala/li/cil/oc/common/tileentity/Hologram.scala b/src/main/scala/li/cil/oc/common/tileentity/Hologram.scala index c396642cc..6e664dde6 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Hologram.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Hologram.scala @@ -321,7 +321,7 @@ class Hologram(var tier: Int) extends traits.Environment with SidedEnvironment w result(true) } - else result(null, "not supported") + else result(Unit, "not supported") } @Callback(doc = """function(speed:number, x:number, y:number, z:number):boolean -- Set the rotation speed of the displayed hologram.""") @@ -340,7 +340,7 @@ class Hologram(var tier: Int) extends traits.Environment with SidedEnvironment w result(true) } - else result(null, "not supported") + else result(Unit, "not supported") } private def checkCoordinates(args: Arguments, idxX: Int = 0, idxY: Int = 1, idxZ: Int = 2) = { diff --git a/src/main/scala/li/cil/oc/common/tileentity/Printer.scala b/src/main/scala/li/cil/oc/common/tileentity/Printer.scala index ed34fd0dd..2996ed30e 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Printer.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Printer.scala @@ -152,7 +152,7 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat @Callback(doc = """function(minX:number, minY:number, minZ:number, maxX:number, maxY:number, maxZ:number, texture:string[, state:boolean=false][,tint:number]) -- Adds a shape to the printers configuration, optionally specifying whether it is for the off or on state.""") def addShape(context: Context, args: Arguments): Array[Object] = { if (data.stateOff.size > Settings.get.maxPrintComplexity || data.stateOn.size > Settings.get.maxPrintComplexity) { - return result(null, "model too complex") + return result(Unit, "model too complex") } val minX = (args.checkInteger(0) max 0 min 16) / 16f val minY = (args.checkInteger(1) max 0 min 16) / 16f @@ -193,7 +193,7 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat @Callback(doc = """function([count:number]):boolean -- Commit and begin printing the current configuration.""") def commit(context: Context, args: Arguments): Array[Object] = { if (!canPrint) { - return result(null, "model invalid") + return result(Unit, "model invalid") } limit = (args.optDouble(0, 1) max 0 min Integer.MAX_VALUE).toInt isActive = limit > 0 diff --git a/src/main/scala/li/cil/oc/integration/appeng/PartEnvironmentBase.scala b/src/main/scala/li/cil/oc/integration/appeng/PartEnvironmentBase.scala index 1dbd70cef..fe75b5ffc 100644 --- a/src/main/scala/li/cil/oc/integration/appeng/PartEnvironmentBase.scala +++ b/src/main/scala/li/cil/oc/integration/appeng/PartEnvironmentBase.scala @@ -25,7 +25,7 @@ trait PartEnvironmentBase extends ManagedEnvironment { val slot = args.optSlot(config, 1, 0) val stack = config.getStackInSlot(slot) result(stack) - case _ => result(null, "no matching part") + case _ => result(Unit, "no matching part") } } diff --git a/src/main/scala/li/cil/oc/integration/dsu/DriverDeepStorageUnit.scala b/src/main/scala/li/cil/oc/integration/dsu/DriverDeepStorageUnit.scala index cbc5510f9..05b15f7a5 100644 --- a/src/main/scala/li/cil/oc/integration/dsu/DriverDeepStorageUnit.scala +++ b/src/main/scala/li/cil/oc/integration/dsu/DriverDeepStorageUnit.scala @@ -31,7 +31,7 @@ object DriverDeepStorageUnit extends DriverTileEntity with EnvironmentAware { @Callback(doc = "function():int -- Get the maximum number of stored items.") def getStoredItemType(context: Context, args: Arguments): Array[AnyRef] = { if (Settings.get.allowItemStackInspection) result(tileEntity.getStoredItemType) - else result(null, "not enabled in config") + else result(Unit, "not enabled in config") } } diff --git a/src/main/scala/li/cil/oc/server/agent/Player.scala b/src/main/scala/li/cil/oc/server/agent/Player.scala index d268cb4dc..06230da6e 100644 --- a/src/main/scala/li/cil/oc/server/agent/Player.scala +++ b/src/main/scala/li/cil/oc/server/agent/Player.scala @@ -11,6 +11,7 @@ import li.cil.oc.api.event._ import li.cil.oc.api.internal import li.cil.oc.api.network.Connector import li.cil.oc.common.EventHandler +import li.cil.oc.common.entity.Drone import li.cil.oc.integration.Mods import li.cil.oc.integration.util.PortalGun import li.cil.oc.integration.util.TinkersConstruct @@ -177,6 +178,7 @@ class Player(val agent: internal.Agent) extends FakePlayer(agent.world.asInstanc !cancel && callUsingItemInSlot(agent.equipmentInventory, 0, stack => { val result = isItemUseAllowed(stack) && (entity.interactFirst(this) || (entity match { case living: EntityLivingBase if getCurrentEquippedItem != null => getCurrentEquippedItem.interactWithEntity(this, living) + case drone: Drone => drone.start() case _ => false })) if (getCurrentEquippedItem != null && getCurrentEquippedItem.stackSize <= 0) { diff --git a/src/main/scala/li/cil/oc/server/component/DebugCard.scala b/src/main/scala/li/cil/oc/server/component/DebugCard.scala index 8795f4643..1fe7d5bb2 100644 --- a/src/main/scala/li/cil/oc/server/component/DebugCard.scala +++ b/src/main/scala/li/cil/oc/server/component/DebugCard.scala @@ -438,9 +438,9 @@ object DebugCard { tileEntity.markDirty() world.markBlockForUpdate(x, y, z) result(true) - case nbt => result(null, s"nbt tag compound expected, got '${NBTBase.NBTTypes(nbt.getId)}'") + case nbt => result(Unit, s"nbt tag compound expected, got '${NBTBase.NBTTypes(nbt.getId)}'") } - case _ => result(null, "no tile entity") + case _ => result(Unit, "no tile entity") } } @@ -522,7 +522,7 @@ object DebugCard { val removed = inventory.decrStackSize(slot, count) if (removed == null) result(0) else result(removed.stackSize) - case _ => result(null, "no inventory") + case _ => result(Unit, "no inventory") } } @@ -538,7 +538,7 @@ object DebugCard { val side = args.checkSide(5, ForgeDirection.VALID_DIRECTIONS: _*) world.getTileEntity(position) match { case handler: IFluidHandler => result(handler.fill(side, new FluidStack(fluid, amount), true)) - case _ => result(null, "no tank") + case _ => result(Unit, "no tank") } } @@ -550,7 +550,7 @@ object DebugCard { val side = args.checkSide(4, ForgeDirection.VALID_DIRECTIONS: _*) world.getTileEntity(position) match { case handler: IFluidHandler => result(handler.drain(side, amount, true)) - case _ => result(null, "no tank") + case _ => result(Unit, "no tank") } } diff --git a/src/main/scala/li/cil/oc/server/component/InternetCard.scala b/src/main/scala/li/cil/oc/server/component/InternetCard.scala index 74d5d1d0e..64c3fb7b1 100644 --- a/src/main/scala/li/cil/oc/server/component/InternetCard.scala +++ b/src/main/scala/li/cil/oc/server/component/InternetCard.scala @@ -190,7 +190,7 @@ object InternetCard { if (checkConnected()) { val buffer = ByteBuffer.allocate(n) val read = channel.read(buffer) - if (read == -1) result(null) + if (read == -1) result(Unit) else result(buffer.array.view(0, read).toArray) } else result(Array.empty[Byte]) @@ -296,7 +296,7 @@ object InternetCard { def response(context: Context, args: Arguments): Array[AnyRef] = this.synchronized { response match { case Some((code, message, headers)) => result(code, message, headers) - case _ => result(null) + case _ => result(Unit) } } @@ -304,7 +304,7 @@ object InternetCard { def read(context: Context, args: Arguments): Array[AnyRef] = this.synchronized { val n = math.min(Settings.get.maxReadBuffer, math.max(0, args.optInteger(1, Int.MaxValue))) if (checkResponse()) { - if (eof && queue.isEmpty) result(null) + if (eof && queue.isEmpty) result(Unit) else { val buffer = ByteBuffer.allocate(n) var read = 0 diff --git a/src/main/scala/li/cil/oc/server/component/Transposer.scala b/src/main/scala/li/cil/oc/server/component/Transposer.scala index f3d4efb82..cc68a1368 100644 --- a/src/main/scala/li/cil/oc/server/component/Transposer.scala +++ b/src/main/scala/li/cil/oc/server/component/Transposer.scala @@ -3,21 +3,17 @@ package li.cil.oc.server.component import li.cil.oc.Settings import li.cil.oc.api import li.cil.oc.api.machine.Arguments -import li.cil.oc.api.machine.Callback -import li.cil.oc.api.machine.Context import li.cil.oc.api.network.Visibility import li.cil.oc.api.prefab import li.cil.oc.common.tileentity import li.cil.oc.server.{PacketSender => ServerPacketSender} import li.cil.oc.util.BlockPosition import li.cil.oc.util.ExtendedArguments._ -import li.cil.oc.util.FluidUtils -import li.cil.oc.util.InventoryUtils import net.minecraftforge.common.util.ForgeDirection import scala.language.existentials -class Transposer(val host: tileentity.Transposer) extends prefab.ManagedEnvironment with traits.WorldInventoryAnalytics with traits.WorldTankAnalytics { +class Transposer(val host: tileentity.Transposer) extends prefab.ManagedEnvironment with traits.WorldInventoryAnalytics with traits.WorldTankAnalytics with traits.InventoryTransfer { override val node = api.Network.newNode(this, Visibility.Network). withComponent("transposer"). withConnector(). @@ -28,43 +24,11 @@ class Transposer(val host: tileentity.Transposer) extends prefab.ManagedEnvironm override protected def checkSideForAction(args: Arguments, n: Int) = args.checkSide(n, ForgeDirection.VALID_DIRECTIONS: _*) - @Callback(doc = """function(sourceSide:number, sinkSide:number[, count:number[, sourceSlot:number, sinkSlot:number]]):number -- Transfer some items between two inventories.""") - def transferItem(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.optItemCount(2) - + override def onTransferContents(): Option[String] = { if (node.tryChangeBuffer(-Settings.get.transposerCost)) { ServerPacketSender.sendTransposerActivity(host) - - if (args.count > 3) { - val sourceSlot = args.checkSlot(InventoryUtils.inventoryAt(sourcePos).getOrElse(throw new IllegalArgumentException("no inventory")), 3) - val sinkSlot = args.checkSlot(InventoryUtils.inventoryAt(sinkPos).getOrElse(throw new IllegalArgumentException("no inventory")), 4) - - result(InventoryUtils.transferBetweenInventoriesSlotsAt(sourcePos, sourceSide.getOpposite, sourceSlot, sinkPos, Option(sinkSide.getOpposite), sinkSlot, count)) - } - else result(InventoryUtils.transferBetweenInventoriesAt(sourcePos, sourceSide.getOpposite, sinkPos, Option(sinkSide.getOpposite), count)) + None } - else result(Unit, "not enough energy") - } - - @Callback(doc = """function(sourceSide:number, sinkSide:number[, count:number]):number -- Transfer some items between two inventories.""") - 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) - - if (node.tryChangeBuffer(-Settings.get.transposerCost)) { - ServerPacketSender.sendTransposerActivity(host) - - 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. - result(moved > 0, moved) - } - else result(Unit, "not enough energy") + else Option("not enough energy") } } 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 new file mode 100644 index 000000000..1989021bd --- /dev/null +++ b/src/main/scala/li/cil/oc/server/component/traits/InventoryTransfer.scala @@ -0,0 +1,54 @@ +package li.cil.oc.server.component.traits + +import li.cil.oc.api.machine.Arguments +import li.cil.oc.api.machine.Callback +import li.cil.oc.api.machine.Context +import li.cil.oc.server.component._ +import li.cil.oc.util.ExtendedArguments._ +import li.cil.oc.util.FluidUtils +import li.cil.oc.util.InventoryUtils + +trait InventoryTransfer extends traits.WorldAware with traits.SideRestricted { + // Return None on success, else Some("failure reason") + def onTransferContents(): Option[String] + + @Callback(doc = """function(sourceSide:number, sinkSide:number[, count:number[, sourceSlot:number, sinkSlot:number]]):number -- Transfer some items between two inventories.""") + def transferItem(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.optItemCount(2) + + onTransferContents() match { + case Some(reason) => + result(Unit, reason) + case _ => + if (args.count > 3) { + val sourceSlot = args.checkSlot(InventoryUtils.inventoryAt(sourcePos).getOrElse(throw new IllegalArgumentException("no inventory")), 3) + val sinkSlot = args.checkSlot(InventoryUtils.inventoryAt(sinkPos).getOrElse(throw new IllegalArgumentException("no inventory")), 4) + + result(InventoryUtils.transferBetweenInventoriesSlotsAt(sourcePos, sourceSide.getOpposite, sourceSlot, sinkPos, Option(sinkSide.getOpposite), sinkSlot, count)) + } + else result(InventoryUtils.transferBetweenInventoriesAt(sourcePos, sourceSide.getOpposite, sinkPos, Option(sinkSide.getOpposite), count)) + } + } + + @Callback(doc = """function(sourceSide:number, sinkSide:number[, count:number]):number -- Transfer some items between two inventories.""") + 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) + + 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. + result(moved > 0, moved) + } + } +} diff --git a/src/main/scala/li/cil/oc/server/component/traits/WorldInventoryAnalytics.scala b/src/main/scala/li/cil/oc/server/component/traits/WorldInventoryAnalytics.scala index 7351920bb..5eb50d0a3 100644 --- a/src/main/scala/li/cil/oc/server/component/traits/WorldInventoryAnalytics.scala +++ b/src/main/scala/li/cil/oc/server/component/traits/WorldInventoryAnalytics.scala @@ -62,7 +62,7 @@ trait WorldInventoryAnalytics extends WorldAware with SideRestricted with Networ val facing = checkSideForAction(args, 0) withInventory(facing, inventory => result(inventory.getStackInSlot(args.checkSlot(inventory, 1)))) } - else result(null, "not enabled in config") + else result(Unit, "not enabled in config") @Callback(doc = """function(side:number, slot:number, dbAddress:string, dbSlot:number):boolean -- Store an item stack description in the specified slot of the database with the specified address.""") def store(context: Context, args: Arguments): Array[AnyRef] = { @@ -80,6 +80,6 @@ trait WorldInventoryAnalytics extends WorldAware with SideRestricted with Networ private def withInventory(side: ForgeDirection, f: IInventory => Array[AnyRef]) = InventoryUtils.inventoryAt(position.offset(side)) match { case Some(inventory) if inventory.isUseableByPlayer(fakePlayer) && mayInteract(position.offset(side), side.getOpposite) => f(inventory) - case _ => result(null, "no inventory") + case _ => result(Unit, "no inventory") } }