diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf
index 67c82af2e..85a11cbd9 100644
--- a/src/main/resources/application.conf
+++ b/src/main/resources/application.conf
@@ -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
diff --git a/src/main/scala/li/cil/oc/common/EventHandler.scala b/src/main/scala/li/cil/oc/common/EventHandler.scala
index 65b51bcb2..2970924d8 100644
--- a/src/main/scala/li/cil/oc/common/EventHandler.scala
+++ b/src/main/scala/li/cil/oc/common/EventHandler.scala
@@ -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)
diff --git a/src/main/scala/li/cil/oc/common/container/Player.scala b/src/main/scala/li/cil/oc/common/container/Player.scala
index 23067a191..e392003dc 100644
--- a/src/main/scala/li/cil/oc/common/container/Player.scala
+++ b/src/main/scala/li/cil/oc/common/container/Player.scala
@@ -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 _ =>
}
diff --git a/src/main/scala/li/cil/oc/common/entity/Drone.scala b/src/main/scala/li/cil/oc/common/entity/Drone.scala
index 659dd09df..b14c09106 100644
--- a/src/main/scala/li/cil/oc/common/entity/Drone.scala
+++ b/src/main/scala/li/cil/oc/common/entity/Drone.scala
@@ -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)
diff --git a/src/main/scala/li/cil/oc/common/item/Analyzer.scala b/src/main/scala/li/cil/oc/common/item/Analyzer.scala
index bc15ef557..228366e75 100644
--- a/src/main/scala/li/cil/oc/common/item/Analyzer.scala
+++ b/src/main/scala/li/cil/oc/common/item/Analyzer.scala
@@ -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 =>
diff --git a/src/main/scala/li/cil/oc/common/item/Debugger.scala b/src/main/scala/li/cil/oc/common/item/Debugger.scala
index 7f96c6eb4..7b20cdba6 100644
--- a/src/main/scala/li/cil/oc/common/item/Debugger.scala
+++ b/src/main/scala/li/cil/oc/common/item/Debugger.scala
@@ -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 =>
diff --git a/src/main/scala/li/cil/oc/common/nanomachines/provider/DisintegrationProvider.scala b/src/main/scala/li/cil/oc/common/nanomachines/provider/DisintegrationProvider.scala
index d02111685..52e254ef2 100644
--- a/src/main/scala/li/cil/oc/common/nanomachines/provider/DisintegrationProvider.scala
+++ b/src/main/scala/li/cil/oc/common/nanomachines/provider/DisintegrationProvider.scala
@@ -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
diff --git a/src/main/scala/li/cil/oc/common/tileentity/Charger.scala b/src/main/scala/li/cil/oc/common/tileentity/Charger.scala
index 9dcdd85dc..2eba3cf7e 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/Charger.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/Charger.scala
@@ -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.
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 10666c101..36028eb0b 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/Hologram.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/Hologram.scala
@@ -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) = {
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 34918b455..d177e02f8 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/common/tileentity/Transposer.scala b/src/main/scala/li/cil/oc/common/tileentity/Transposer.scala
index b3e43b9f4..4860a866f 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/Transposer.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/Transposer.scala
@@ -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
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..fd1ccde4c 100644
--- a/src/main/scala/li/cil/oc/integration/appeng/PartEnvironmentBase.scala
+++ b/src/main/scala/li/cil/oc/integration/appeng/PartEnvironmentBase.scala
@@ -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")
}
}
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..ba0cbd53d 100644
--- a/src/main/scala/li/cil/oc/integration/dsu/DriverDeepStorageUnit.scala
+++ b/src/main/scala/li/cil/oc/integration/dsu/DriverDeepStorageUnit.scala
@@ -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")
}
}
diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/DriverTransposer.scala b/src/main/scala/li/cil/oc/integration/opencomputers/DriverTransposer.scala
new file mode 100644
index 000000000..bce4d0253
--- /dev/null
+++ b/src/main/scala/li/cil/oc/integration/opencomputers/DriverTransposer.scala
@@ -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]
+}
diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/ModOpenComputers.scala b/src/main/scala/li/cil/oc/integration/opencomputers/ModOpenComputers.scala
index 9c46309b0..27b43b4f2 100644
--- a/src/main/scala/li/cil/oc/integration/opencomputers/ModOpenComputers.scala
+++ b/src/main/scala/li/cil/oc/integration/opencomputers/ModOpenComputers.scala
@@ -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,
diff --git a/src/main/scala/li/cil/oc/server/component/Agent.scala b/src/main/scala/li/cil/oc/server/component/Agent.scala
index 5c062486a..0a7bd6f8e 100644
--- a/src/main/scala/li/cil/oc/server/component/Agent.scala
+++ b/src/main/scala/li/cil/oc/server/component/Agent.scala
@@ -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
}
}
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 31562f7bd..be87b9741 100644
--- a/src/main/scala/li/cil/oc/server/component/DebugCard.scala
+++ b/src/main/scala/li/cil/oc/server/component/DebugCard.scala
@@ -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")
}
}
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 eae05568e..bd6fe8abe 100644
--- a/src/main/scala/li/cil/oc/server/component/InternetCard.scala
+++ b/src/main/scala/li/cil/oc/server/component/InternetCard.scala
@@ -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
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 c51faeaf2..3d1f4c162 100644
--- a/src/main/scala/li/cil/oc/server/component/Transposer.scala
+++ b/src/main/scala/li/cil/oc/server/component/Transposer.scala
@@ -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)
+ }
+
}
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..704ddcdbc
--- /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.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)
+ }
+ }
+}
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 8cd75dfdd..887e81ba1 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: 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")
}
}
diff --git a/src/main/scala/li/cil/oc/util/InventoryUtils.scala b/src/main/scala/li/cil/oc/util/InventoryUtils.scala
index ff2936839..97c75ae2c 100644
--- a/src/main/scala/li/cil/oc/util/InventoryUtils.scala
+++ b/src/main/scala/li/cil/oc/util/InventoryUtils.scala
@@ -249,9 +249,15 @@ object InventoryUtils {
/**
* Like transferBetweenInventories 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 transferBetweenInventories on inventories
@@ -266,7 +272,7 @@ object InventoryUtils {
* Utility method for calling transferBetweenInventoriesSlots 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)))