Merge branch 'master-MC1.7.10' of github.com:MightyPirates/OpenComputers into master-MC1.8

Conflicts:
	src/main/scala/li/cil/oc/common/item/Analyzer.scala
	src/main/scala/li/cil/oc/common/item/Debugger.scala
	src/main/scala/li/cil/oc/server/component/Agent.scala
	src/main/scala/li/cil/oc/server/component/DebugCard.scala
	src/main/scala/li/cil/oc/server/component/Transposer.scala
	src/main/scala/li/cil/oc/util/InventoryUtils.scala
This commit is contained in:
Florian Nücke 2015-09-19 13:16:41 +02:00
commit c427dcc195
22 changed files with 178 additions and 87 deletions

View File

@ -465,8 +465,8 @@ opencomputers {
# screens. This also controls how frequent distributors revalidate their
# global state and secondary distributors, as well as how often the power
# converter queries sources for energy (for now: only BuildCraft). If set
# to 1, this would query every tick. The default queries every 20 ticks,
# or in other words once per second.
# to 1, this would query every tick. The default queries every 10 ticks,
# or in other words twice per second.
# Higher values mean more responsive power consumption, but slightly more
# work per tick (shouldn't be that noticeable, though). Note that this
# has no influence on the actual amount of energy required by computers

View File

@ -118,6 +118,7 @@ object EventHandler {
@SubscribeEvent
def playerLoggedIn(e: PlayerLoggedInEvent) {
if (SideTracker.isServer) e.player match {
case _: FakePlayer => // Nope
case player: EntityPlayerMP =>
if (!LuaStateFactory.isAvailable) {
player.addChatMessage(Localization.Chat.WarningLuaFallback)

View File

@ -15,6 +15,7 @@ import net.minecraft.inventory.Slot
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTBase
import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.common.util.FakePlayer
import scala.collection.convert.WrapAsScala._
@ -155,6 +156,7 @@ abstract class Player(val playerInventory: InventoryPlayer, val otherInventory:
val nbt = new NBTTagCompound()
detectCustomDataChanges(nbt)
for (entry <- crafters) entry match {
case _: FakePlayer => // Nope
case player: EntityPlayerMP => ServerPacketSender.sendContainerUpdate(this, nbt, player)
case _ =>
}

View File

@ -465,7 +465,13 @@ class Drone(val world: World) extends Entity(world) with MachineHost with intern
override def interactFirst(player: EntityPlayer) = {
if (player.isSneaking) {
kill()
if (api.Items.get(player.getCurrentEquippedItem) == api.Items.get(Constants.ItemName.Wrench)) {
kill()
}
else if (!world.isRemote && !machine.isRunning) {
preparePowerUp()
start()
}
}
else if (!world.isRemote) {
player.openGui(OpenComputers, GuiType.Drone.id, world, getEntityId, 0, 0)

View File

@ -16,6 +16,7 @@ import net.minecraft.entity.player.EntityPlayerMP
import net.minecraft.item.ItemStack
import net.minecraft.util.EnumFacing
import net.minecraft.world.World
import net.minecraftforge.common.util.FakePlayer
import net.minecraftforge.event.entity.player.EntityInteractEvent
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
@ -59,6 +60,7 @@ object Analyzer {
private def analyzeNodes(nodes: Array[Node], player: EntityPlayer) = if (nodes != null) for (node <- nodes if node != null) {
player match {
case _: FakePlayer => // Nope
case playerMP: EntityPlayerMP =>
if (node != null) node.host match {
case machine: Machine =>

View File

@ -9,11 +9,13 @@ import net.minecraft.entity.player.EntityPlayer
import net.minecraft.entity.player.EntityPlayerMP
import net.minecraft.item.ItemStack
import net.minecraft.util.EnumFacing
import net.minecraftforge.common.util.FakePlayer
class Debugger(val parent: Delegator) extends traits.Delegate {
override def onItemUse(stack: ItemStack, player: EntityPlayer, position: BlockPosition, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float) = {
val world = position.world.get
player match {
case _: FakePlayer => false // Nope
case realPlayer: EntityPlayerMP =>
world.getTileEntity(position) match {
case host: SidedEnvironment =>

View File

@ -1,6 +1,5 @@
package li.cil.oc.common.nanomachines.provider
import li.cil.oc.Settings
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.nanomachines.DisableReason
@ -14,6 +13,7 @@ import net.minecraft.entity.player.EntityPlayerMP
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.world.World
import net.minecraftforge.common.util.FakePlayer
import net.minecraftforge.event.ForgeEventFactory
import net.minecraftforge.event.entity.player.PlayerInteractEvent.Action
import net.minecraftforge.fml.common.eventhandler.Event
@ -42,6 +42,7 @@ object DisintegrationProvider extends ScalaProvider("c4e7e3c2-8069-4fbb-b08e-74b
override def update(): Unit = {
val world = player.getEntityWorld
if (!world.isRemote) player match {
case _: FakePlayer => // Nope
case playerMP: EntityPlayerMP =>
val now = world.getTotalWorldTime

View File

@ -205,7 +205,7 @@ class Charger extends traits.Environment with traits.PowerAcceptor with traits.R
}
val players = world.getEntitiesWithinAABB(classOf[EntityPlayer], bounds).collect {
case player: EntityPlayer => new PlayerChargeable(player)
case player: EntityPlayer if api.Nanomachines.hasController(player) => new PlayerChargeable(player)
}
// Only update list when we have to, keeps pointless block updates to a minimum.

View File

@ -319,7 +319,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.""")
@ -338,7 +338,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) = {

View File

@ -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

View File

@ -4,7 +4,7 @@ import li.cil.oc.server.component
import net.minecraft.nbt.NBTTagCompound
class Transposer extends traits.Environment {
val transposer = new component.Transposer(this)
val transposer = new component.Transposer.Block(this)
def node = transposer.node

View File

@ -1,7 +1,5 @@
package li.cil.oc.integration.appeng
import appeng.api.implementations.tiles.ISegmentedInventory
import appeng.api.parts.IPartHost
import li.cil.oc.api.internal.Database
import li.cil.oc.api.machine.Arguments
import li.cil.oc.api.machine.Context
@ -9,7 +7,6 @@ import li.cil.oc.api.network.Component
import li.cil.oc.api.network.ManagedEnvironment
import li.cil.oc.util.ExtendedArguments._
import li.cil.oc.util.ResultWrapper.result
import net.minecraftforge.common.util.ForgeDirection
import scala.reflect.ClassTag
@ -25,7 +22,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")
}
}

View File

@ -11,7 +11,6 @@ import li.cil.oc.integration.ManagedTileEntityEnvironment
import li.cil.oc.util.ResultWrapper._
import net.minecraft.item.ItemStack
import net.minecraft.world.World
import powercrystals.minefactoryreloaded.api.IDeepStorageUnit
object DriverDeepStorageUnit extends DriverTileEntity with EnvironmentAware {
override def getTileEntityClass: Class[_] = classOf[IDeepStorageUnit]
@ -31,7 +30,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")
}
}

View File

@ -0,0 +1,21 @@
package li.cil.oc.integration.opencomputers
import li.cil.oc.Constants
import li.cil.oc.api
import li.cil.oc.api.driver.EnvironmentAware
import li.cil.oc.api.driver.EnvironmentHost
import li.cil.oc.api.driver.item.HostAware
import li.cil.oc.common.Slot
import li.cil.oc.server.component
import net.minecraft.item.ItemStack
object DriverTransposer extends Item with HostAware with EnvironmentAware {
override def worksWith(stack: ItemStack) = isOneOf(stack,
api.Items.get(Constants.BlockName.Transposer))
override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = new component.Transposer.Upgrade(host)
override def slot(stack: ItemStack) = Slot.Upgrade
override def providedEnvironment(stack: ItemStack) = classOf[component.Transposer.Upgrade]
}

View File

@ -105,7 +105,6 @@ object ModOpenComputers extends ModProxy {
api.Driver.add(DriverDebugCard)
api.Driver.add(DriverEEPROM)
api.Driver.add(DriverFileSystem)
api.Driver.add(DriverGeolyzer)
api.Driver.add(DriverGraphicsCard)
api.Driver.add(DriverInternetCard)
api.Driver.add(DriverLinkedCard)
@ -114,7 +113,6 @@ object ModOpenComputers extends ModProxy {
api.Driver.add(DriverNetworkCard)
api.Driver.add(DriverKeyboard)
api.Driver.add(DriverRedstoneCard)
api.Driver.add(DriverScreen)
api.Driver.add(DriverTablet)
api.Driver.add(DriverWirelessNetworkCard)
@ -122,6 +120,10 @@ object ModOpenComputers extends ModProxy {
api.Driver.add(DriverContainerFloppy)
api.Driver.add(DriverContainerUpgrade)
api.Driver.add(DriverGeolyzer)
api.Driver.add(DriverScreen)
api.Driver.add(DriverTransposer)
api.Driver.add(DriverUpgradeAngel)
api.Driver.add(DriverUpgradeBattery)
api.Driver.add(DriverUpgradeChunkloader)
@ -145,6 +147,7 @@ object ModOpenComputers extends ModProxy {
Constants.BlockName.Geolyzer,
Constants.BlockName.Keyboard,
Constants.BlockName.ScreenTier1,
Constants.BlockName.Transposer,
Constants.ItemName.AngelUpgrade,
Constants.ItemName.BatteryUpgradeTier1,
Constants.ItemName.BatteryUpgradeTier2,
@ -163,27 +166,28 @@ object ModOpenComputers extends ModProxy {
Constants.ItemName.TractorBeamUpgrade,
Constants.ItemName.LeashUpgrade)
blacklistHost(classOf[internal.Drone],
Constants.BlockName.Keyboard,
Constants.BlockName.ScreenTier1,
Constants.BlockName.Transposer,
Constants.ItemName.APUTier1,
Constants.ItemName.APUTier2,
Constants.ItemName.GraphicsCardTier1,
Constants.ItemName.GraphicsCardTier2,
Constants.ItemName.GraphicsCardTier3,
Constants.BlockName.Keyboard,
Constants.ItemName.NetworkCard,
Constants.ItemName.RedstoneCardTier1,
Constants.BlockName.ScreenTier1,
Constants.ItemName.AngelUpgrade,
Constants.ItemName.CraftingUpgrade,
Constants.ItemName.HoverUpgradeTier1,
Constants.ItemName.HoverUpgradeTier2)
blacklistHost(classOf[internal.Microcontroller],
Constants.BlockName.Keyboard,
Constants.BlockName.ScreenTier1,
Constants.ItemName.APUTier1,
Constants.ItemName.APUTier2,
Constants.ItemName.GraphicsCardTier1,
Constants.ItemName.GraphicsCardTier2,
Constants.ItemName.GraphicsCardTier3,
Constants.BlockName.Keyboard,
Constants.BlockName.ScreenTier1,
Constants.ItemName.AngelUpgrade,
Constants.ItemName.ChunkloaderUpgrade,
Constants.ItemName.CraftingUpgrade,
@ -202,11 +206,13 @@ object ModOpenComputers extends ModProxy {
Constants.ItemName.TractorBeamUpgrade,
Constants.ItemName.LeashUpgrade)
blacklistHost(classOf[internal.Robot],
Constants.BlockName.Transposer,
Constants.ItemName.LeashUpgrade)
blacklistHost(classOf[internal.Tablet],
Constants.BlockName.ScreenTier1,
Constants.BlockName.Transposer,
Constants.ItemName.NetworkCard,
Constants.ItemName.RedstoneCardTier1,
Constants.BlockName.ScreenTier1,
Constants.ItemName.AngelUpgrade,
Constants.ItemName.ChunkloaderUpgrade,
Constants.ItemName.CraftingUpgrade,

View File

@ -6,6 +6,7 @@ import li.cil.oc.api.internal
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.common.entity
import li.cil.oc.server.agent.ActivationType
import li.cil.oc.server.agent.Player
import li.cil.oc.util.BlockPosition
@ -303,7 +304,7 @@ trait Agent extends traits.WorldControl with traits.InventoryControl with traits
player.side.getFrontOffsetZ * range)
val hit = world.rayTraceBlocks(origin, target)
player.closestEntity[Entity]() match {
case Some(entity@(_: EntityLivingBase | _: EntityMinecart)) if hit == null || new Vec3(player.posX, player.posY, player.posZ).distanceTo(hit.hitVec) > player.getDistanceToEntity(entity) => new MovingObjectPosition(entity)
case Some(entity@(_: EntityLivingBase | _: EntityMinecart | _: entity.Drone)) if hit == null || new Vec3(player.posX, player.posY, player.posZ).distanceTo(hit.hitVec) > player.getDistanceToEntity(entity) => new MovingObjectPosition(entity)
case _ => hit
}
}

View File

@ -440,9 +440,9 @@ object DebugCard {
tileEntity.markDirty()
world.markBlockForUpdate(blockPos)
result(true)
case nbt => result(null, s"nbt tag compound expected, got '${NBTBase.NBT_TYPES(nbt.getId)}'")
case nbt => result(Unit, s"nbt tag compound expected, got '${NBTBase.NBT_TYPES(nbt.getId)}'")
}
case _ => result(null, "no tile entity")
case _ => result(Unit, "no tile entity")
}
}
@ -524,7 +524,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")
}
}
@ -540,7 +540,7 @@ object DebugCard {
val side = args.checkSide(5, EnumFacing.values: _*)
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")
}
}
@ -552,7 +552,7 @@ object DebugCard {
val side = args.checkSide(4, EnumFacing.values: _*)
world.getTileEntity(position) match {
case handler: IFluidHandler => result(handler.drain(side, amount, true))
case _ => result(null, "no tank")
case _ => result(Unit, "no tank")
}
}

View File

@ -1,15 +1,27 @@
package li.cil.oc.server.component
import java.io.{BufferedWriter, FileNotFoundException, IOException, InputStream, OutputStreamWriter}
import java.io.BufferedWriter
import java.io.FileNotFoundException
import java.io.IOException
import java.io.InputStream
import java.io.OutputStreamWriter
import java.net._
import java.nio.ByteBuffer
import java.nio.channels.SocketChannel
import java.util.concurrent.{Callable, ConcurrentLinkedQueue, ExecutionException, Future}
import java.util.concurrent.Callable
import java.util.concurrent.ConcurrentLinkedQueue
import java.util.concurrent.ExecutionException
import java.util.concurrent.Future
import li.cil.oc.{OpenComputers, Settings, api}
import li.cil.oc.api.machine.{Arguments, Callback, Context}
import li.cil.oc.OpenComputers
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.Network
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._
import li.cil.oc.api.{Network, prefab}
import li.cil.oc.api.prefab
import li.cil.oc.api.prefab.AbstractValue
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ThreadPoolFactory
@ -190,7 +202,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])
@ -297,7 +309,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)
}
}
@ -305,7 +317,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

View File

@ -2,68 +2,49 @@ package li.cil.oc.server.component
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.driver.EnvironmentHost
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.minecraft.util.EnumFacing
import scala.language.existentials
class Transposer(val host: tileentity.Transposer) extends prefab.ManagedEnvironment with traits.WorldInventoryAnalytics with traits.WorldTankAnalytics {
override val node = api.Network.newNode(this, Visibility.Network).
withComponent("transposer").
withConnector().
create()
object Transposer {
override def position = BlockPosition(host)
abstract class Common extends prefab.ManagedEnvironment with traits.WorldInventoryAnalytics with traits.WorldTankAnalytics with traits.InventoryTransfer {
override val node = api.Network.newNode(this, Visibility.Network).
withComponent("transposer").
withConnector().
create()
override protected def checkSideForAction(args: Arguments, n: Int) = args.checkSide(n, EnumFacing.values: _*)
override protected def checkSideForAction(args: Arguments, n: Int) =
args.checkSide(n, EnumFacing.values: _*)
@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)
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))
override def onTransferContents(): Option[String] = {
if (node.tryChangeBuffer(-Settings.get.transposerCost)) None
else Option("not enough energy")
}
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)
class Block(val host: tileentity.Transposer) extends Common {
override def position = BlockPosition(host)
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)
override def onTransferContents(): Option[String] = {
val result = super.onTransferContents()
if (result.isEmpty) ServerPacketSender.sendTransposerActivity(host)
result
}
else result(Unit, "not enough energy")
}
class Upgrade(val host: EnvironmentHost) extends Common {
node.setVisibility(Visibility.Neighbors)
override def position = BlockPosition(host)
}
}

View File

@ -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.optSlot(InventoryUtils.inventoryAt(sinkPos).getOrElse(throw new IllegalArgumentException("no inventory")), 4, -1)
result(InventoryUtils.transferBetweenInventoriesSlotsAt(sourcePos, sourceSide.getOpposite, sourceSlot, sinkPos, Option(sinkSide.getOpposite), if (sinkSlot < 0) None else Option(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)
}
}
}

View File

@ -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: EnumFacing, 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")
}
}

View File

@ -249,9 +249,15 @@ object InventoryUtils {
/**
* Like <tt>transferBetweenInventories</tt> but moving between specific slots.
*/
def transferBetweenInventoriesSlots(source: IInventory, sourceSide: EnumFacing, sourceSlot: Int, sink: IInventory, sinkSide: Option[EnumFacing], sinkSlot: Int, limit: Int = 64) =
extractFromInventorySlot(
insertIntoInventorySlot(_, sink, sinkSide, sinkSlot, limit), source, sourceSide, sourceSlot, limit)
def transferBetweenInventoriesSlots(source: IInventory, sourceSide: EnumFacing, sourceSlot: Int, sink: IInventory, sinkSide: Option[EnumFacing], sinkSlot: Option[Int], limit: Int = 64) =
sinkSlot match {
case Some(explicitSinkSlot) =>
extractFromInventorySlot(
insertIntoInventorySlot(_, sink, sinkSide, explicitSinkSlot, limit), source, sourceSide, sourceSlot, limit)
case _ =>
extractFromInventorySlot(
insertIntoInventory(_, sink, sinkSide, limit), source, sourceSide, sourceSlot, limit)
}
/**
* Utility method for calling <tt>transferBetweenInventories</tt> on inventories
@ -266,7 +272,7 @@ object InventoryUtils {
* Utility method for calling <tt>transferBetweenInventoriesSlots</tt> on inventories
* in the world.
*/
def transferBetweenInventoriesSlotsAt(sourcePos: BlockPosition, sourceSide: EnumFacing, sourceSlot: Int, sinkPos: BlockPosition, sinkSide: Option[EnumFacing], sinkSlot: Int, limit: Int = 64) =
def transferBetweenInventoriesSlotsAt(sourcePos: BlockPosition, sourceSide: EnumFacing, sourceSlot: Int, sinkPos: BlockPosition, sinkSide: Option[EnumFacing], sinkSlot: Option[Int], limit: Int = 64) =
inventoryAt(sourcePos).exists(sourceInventory =>
inventoryAt(sinkPos).exists(sinkInventory =>
transferBetweenInventoriesSlots(sourceInventory, sourceSide, sourceSlot, sinkInventory, sinkSide, sinkSlot, limit)))