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

View File

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

View File

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

View File

@ -465,8 +465,14 @@ class Drone(val world: World) extends Entity(world) with MachineHost with intern
override def interactFirst(player: EntityPlayer) = { override def interactFirst(player: EntityPlayer) = {
if (player.isSneaking) { if (player.isSneaking) {
if (api.Items.get(player.getCurrentEquippedItem) == api.Items.get(Constants.ItemName.Wrench)) {
kill() kill()
} }
else if (!world.isRemote && !machine.isRunning) {
preparePowerUp()
start()
}
}
else if (!world.isRemote) { else if (!world.isRemote) {
player.openGui(OpenComputers, GuiType.Drone.id, world, getEntityId, 0, 0) 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.item.ItemStack
import net.minecraft.util.EnumFacing import net.minecraft.util.EnumFacing
import net.minecraft.world.World import net.minecraft.world.World
import net.minecraftforge.common.util.FakePlayer
import net.minecraftforge.event.entity.player.EntityInteractEvent import net.minecraftforge.event.entity.player.EntityInteractEvent
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent 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) { private def analyzeNodes(nodes: Array[Node], player: EntityPlayer) = if (nodes != null) for (node <- nodes if node != null) {
player match { player match {
case _: FakePlayer => // Nope
case playerMP: EntityPlayerMP => case playerMP: EntityPlayerMP =>
if (node != null) node.host match { if (node != null) node.host match {
case machine: Machine => case machine: Machine =>

View File

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

View File

@ -1,6 +1,5 @@
package li.cil.oc.common.nanomachines.provider package li.cil.oc.common.nanomachines.provider
import li.cil.oc.Settings
import li.cil.oc.Settings import li.cil.oc.Settings
import li.cil.oc.api import li.cil.oc.api
import li.cil.oc.api.nanomachines.DisableReason 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.item.ItemStack
import net.minecraft.nbt.NBTTagCompound import net.minecraft.nbt.NBTTagCompound
import net.minecraft.world.World import net.minecraft.world.World
import net.minecraftforge.common.util.FakePlayer
import net.minecraftforge.event.ForgeEventFactory import net.minecraftforge.event.ForgeEventFactory
import net.minecraftforge.event.entity.player.PlayerInteractEvent.Action import net.minecraftforge.event.entity.player.PlayerInteractEvent.Action
import net.minecraftforge.fml.common.eventhandler.Event import net.minecraftforge.fml.common.eventhandler.Event
@ -42,6 +42,7 @@ object DisintegrationProvider extends ScalaProvider("c4e7e3c2-8069-4fbb-b08e-74b
override def update(): Unit = { override def update(): Unit = {
val world = player.getEntityWorld val world = player.getEntityWorld
if (!world.isRemote) player match { if (!world.isRemote) player match {
case _: FakePlayer => // Nope
case playerMP: EntityPlayerMP => case playerMP: EntityPlayerMP =>
val now = world.getTotalWorldTime 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 { 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. // 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) 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.""") @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) 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) = { 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.""") @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] = { def addShape(context: Context, args: Arguments): Array[Object] = {
if (data.stateOff.size > Settings.get.maxPrintComplexity || data.stateOn.size > Settings.get.maxPrintComplexity) { 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 minX = (args.checkInteger(0) max 0 min 16) / 16f
val minY = (args.checkInteger(1) 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.""") @Callback(doc = """function([count:number]):boolean -- Commit and begin printing the current configuration.""")
def commit(context: Context, args: Arguments): Array[Object] = { def commit(context: Context, args: Arguments): Array[Object] = {
if (!canPrint) { if (!canPrint) {
return result(null, "model invalid") return result(Unit, "model invalid")
} }
limit = (args.optDouble(0, 1) max 0 min Integer.MAX_VALUE).toInt limit = (args.optDouble(0, 1) max 0 min Integer.MAX_VALUE).toInt
isActive = limit > 0 isActive = limit > 0

View File

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

View File

@ -1,7 +1,5 @@
package li.cil.oc.integration.appeng 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.internal.Database
import li.cil.oc.api.machine.Arguments import li.cil.oc.api.machine.Arguments
import li.cil.oc.api.machine.Context 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.api.network.ManagedEnvironment
import li.cil.oc.util.ExtendedArguments._ import li.cil.oc.util.ExtendedArguments._
import li.cil.oc.util.ResultWrapper.result import li.cil.oc.util.ResultWrapper.result
import net.minecraftforge.common.util.ForgeDirection
import scala.reflect.ClassTag import scala.reflect.ClassTag
@ -25,7 +22,7 @@ trait PartEnvironmentBase extends ManagedEnvironment {
val slot = args.optSlot(config, 1, 0) val slot = args.optSlot(config, 1, 0)
val stack = config.getStackInSlot(slot) val stack = config.getStackInSlot(slot)
result(stack) 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 li.cil.oc.util.ResultWrapper._
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.world.World import net.minecraft.world.World
import powercrystals.minefactoryreloaded.api.IDeepStorageUnit
object DriverDeepStorageUnit extends DriverTileEntity with EnvironmentAware { object DriverDeepStorageUnit extends DriverTileEntity with EnvironmentAware {
override def getTileEntityClass: Class[_] = classOf[IDeepStorageUnit] 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.") @Callback(doc = "function():int -- Get the maximum number of stored items.")
def getStoredItemType(context: Context, args: Arguments): Array[AnyRef] = { def getStoredItemType(context: Context, args: Arguments): Array[AnyRef] = {
if (Settings.get.allowItemStackInspection) result(tileEntity.getStoredItemType) 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(DriverDebugCard)
api.Driver.add(DriverEEPROM) api.Driver.add(DriverEEPROM)
api.Driver.add(DriverFileSystem) api.Driver.add(DriverFileSystem)
api.Driver.add(DriverGeolyzer)
api.Driver.add(DriverGraphicsCard) api.Driver.add(DriverGraphicsCard)
api.Driver.add(DriverInternetCard) api.Driver.add(DriverInternetCard)
api.Driver.add(DriverLinkedCard) api.Driver.add(DriverLinkedCard)
@ -114,7 +113,6 @@ object ModOpenComputers extends ModProxy {
api.Driver.add(DriverNetworkCard) api.Driver.add(DriverNetworkCard)
api.Driver.add(DriverKeyboard) api.Driver.add(DriverKeyboard)
api.Driver.add(DriverRedstoneCard) api.Driver.add(DriverRedstoneCard)
api.Driver.add(DriverScreen)
api.Driver.add(DriverTablet) api.Driver.add(DriverTablet)
api.Driver.add(DriverWirelessNetworkCard) api.Driver.add(DriverWirelessNetworkCard)
@ -122,6 +120,10 @@ object ModOpenComputers extends ModProxy {
api.Driver.add(DriverContainerFloppy) api.Driver.add(DriverContainerFloppy)
api.Driver.add(DriverContainerUpgrade) api.Driver.add(DriverContainerUpgrade)
api.Driver.add(DriverGeolyzer)
api.Driver.add(DriverScreen)
api.Driver.add(DriverTransposer)
api.Driver.add(DriverUpgradeAngel) api.Driver.add(DriverUpgradeAngel)
api.Driver.add(DriverUpgradeBattery) api.Driver.add(DriverUpgradeBattery)
api.Driver.add(DriverUpgradeChunkloader) api.Driver.add(DriverUpgradeChunkloader)
@ -145,6 +147,7 @@ object ModOpenComputers extends ModProxy {
Constants.BlockName.Geolyzer, Constants.BlockName.Geolyzer,
Constants.BlockName.Keyboard, Constants.BlockName.Keyboard,
Constants.BlockName.ScreenTier1, Constants.BlockName.ScreenTier1,
Constants.BlockName.Transposer,
Constants.ItemName.AngelUpgrade, Constants.ItemName.AngelUpgrade,
Constants.ItemName.BatteryUpgradeTier1, Constants.ItemName.BatteryUpgradeTier1,
Constants.ItemName.BatteryUpgradeTier2, Constants.ItemName.BatteryUpgradeTier2,
@ -163,27 +166,28 @@ object ModOpenComputers extends ModProxy {
Constants.ItemName.TractorBeamUpgrade, Constants.ItemName.TractorBeamUpgrade,
Constants.ItemName.LeashUpgrade) Constants.ItemName.LeashUpgrade)
blacklistHost(classOf[internal.Drone], blacklistHost(classOf[internal.Drone],
Constants.BlockName.Keyboard,
Constants.BlockName.ScreenTier1,
Constants.BlockName.Transposer,
Constants.ItemName.APUTier1, Constants.ItemName.APUTier1,
Constants.ItemName.APUTier2, Constants.ItemName.APUTier2,
Constants.ItemName.GraphicsCardTier1, Constants.ItemName.GraphicsCardTier1,
Constants.ItemName.GraphicsCardTier2, Constants.ItemName.GraphicsCardTier2,
Constants.ItemName.GraphicsCardTier3, Constants.ItemName.GraphicsCardTier3,
Constants.BlockName.Keyboard,
Constants.ItemName.NetworkCard, Constants.ItemName.NetworkCard,
Constants.ItemName.RedstoneCardTier1, Constants.ItemName.RedstoneCardTier1,
Constants.BlockName.ScreenTier1,
Constants.ItemName.AngelUpgrade, Constants.ItemName.AngelUpgrade,
Constants.ItemName.CraftingUpgrade, Constants.ItemName.CraftingUpgrade,
Constants.ItemName.HoverUpgradeTier1, Constants.ItemName.HoverUpgradeTier1,
Constants.ItemName.HoverUpgradeTier2) Constants.ItemName.HoverUpgradeTier2)
blacklistHost(classOf[internal.Microcontroller], blacklistHost(classOf[internal.Microcontroller],
Constants.BlockName.Keyboard,
Constants.BlockName.ScreenTier1,
Constants.ItemName.APUTier1, Constants.ItemName.APUTier1,
Constants.ItemName.APUTier2, Constants.ItemName.APUTier2,
Constants.ItemName.GraphicsCardTier1, Constants.ItemName.GraphicsCardTier1,
Constants.ItemName.GraphicsCardTier2, Constants.ItemName.GraphicsCardTier2,
Constants.ItemName.GraphicsCardTier3, Constants.ItemName.GraphicsCardTier3,
Constants.BlockName.Keyboard,
Constants.BlockName.ScreenTier1,
Constants.ItemName.AngelUpgrade, Constants.ItemName.AngelUpgrade,
Constants.ItemName.ChunkloaderUpgrade, Constants.ItemName.ChunkloaderUpgrade,
Constants.ItemName.CraftingUpgrade, Constants.ItemName.CraftingUpgrade,
@ -202,11 +206,13 @@ object ModOpenComputers extends ModProxy {
Constants.ItemName.TractorBeamUpgrade, Constants.ItemName.TractorBeamUpgrade,
Constants.ItemName.LeashUpgrade) Constants.ItemName.LeashUpgrade)
blacklistHost(classOf[internal.Robot], blacklistHost(classOf[internal.Robot],
Constants.BlockName.Transposer,
Constants.ItemName.LeashUpgrade) Constants.ItemName.LeashUpgrade)
blacklistHost(classOf[internal.Tablet], blacklistHost(classOf[internal.Tablet],
Constants.BlockName.ScreenTier1,
Constants.BlockName.Transposer,
Constants.ItemName.NetworkCard, Constants.ItemName.NetworkCard,
Constants.ItemName.RedstoneCardTier1, Constants.ItemName.RedstoneCardTier1,
Constants.BlockName.ScreenTier1,
Constants.ItemName.AngelUpgrade, Constants.ItemName.AngelUpgrade,
Constants.ItemName.ChunkloaderUpgrade, Constants.ItemName.ChunkloaderUpgrade,
Constants.ItemName.CraftingUpgrade, 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.Arguments
import li.cil.oc.api.machine.Callback import li.cil.oc.api.machine.Callback
import li.cil.oc.api.machine.Context 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.ActivationType
import li.cil.oc.server.agent.Player import li.cil.oc.server.agent.Player
import li.cil.oc.util.BlockPosition import li.cil.oc.util.BlockPosition
@ -303,7 +304,7 @@ trait Agent extends traits.WorldControl with traits.InventoryControl with traits
player.side.getFrontOffsetZ * range) player.side.getFrontOffsetZ * range)
val hit = world.rayTraceBlocks(origin, target) val hit = world.rayTraceBlocks(origin, target)
player.closestEntity[Entity]() match { 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 case _ => hit
} }
} }

View File

@ -440,9 +440,9 @@ object DebugCard {
tileEntity.markDirty() tileEntity.markDirty()
world.markBlockForUpdate(blockPos) world.markBlockForUpdate(blockPos)
result(true) 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) val removed = inventory.decrStackSize(slot, count)
if (removed == null) result(0) if (removed == null) result(0)
else result(removed.stackSize) 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: _*) val side = args.checkSide(5, EnumFacing.values: _*)
world.getTileEntity(position) match { world.getTileEntity(position) match {
case handler: IFluidHandler => result(handler.fill(side, new FluidStack(fluid, amount), true)) 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: _*) val side = args.checkSide(4, EnumFacing.values: _*)
world.getTileEntity(position) match { world.getTileEntity(position) match {
case handler: IFluidHandler => result(handler.drain(side, amount, true)) 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 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.net._
import java.nio.ByteBuffer import java.nio.ByteBuffer
import java.nio.channels.SocketChannel 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.OpenComputers
import li.cil.oc.api.machine.{Arguments, Callback, Context} 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._
import li.cil.oc.api.{Network, prefab} import li.cil.oc.api.prefab
import li.cil.oc.api.prefab.AbstractValue import li.cil.oc.api.prefab.AbstractValue
import li.cil.oc.util.ExtendedNBT._ import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ThreadPoolFactory import li.cil.oc.util.ThreadPoolFactory
@ -190,7 +202,7 @@ object InternetCard {
if (checkConnected()) { if (checkConnected()) {
val buffer = ByteBuffer.allocate(n) val buffer = ByteBuffer.allocate(n)
val read = channel.read(buffer) 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(buffer.array.view(0, read).toArray)
} }
else result(Array.empty[Byte]) else result(Array.empty[Byte])
@ -297,7 +309,7 @@ object InternetCard {
def response(context: Context, args: Arguments): Array[AnyRef] = this.synchronized { def response(context: Context, args: Arguments): Array[AnyRef] = this.synchronized {
response match { response match {
case Some((code, message, headers)) => result(code, message, headers) 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 { 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))) val n = math.min(Settings.get.maxReadBuffer, math.max(0, args.optInteger(1, Int.MaxValue)))
if (checkResponse()) { if (checkResponse()) {
if (eof && queue.isEmpty) result(null) if (eof && queue.isEmpty) result(Unit)
else { else {
val buffer = ByteBuffer.allocate(n) val buffer = ByteBuffer.allocate(n)
var read = 0 var read = 0

View File

@ -2,68 +2,49 @@ package li.cil.oc.server.component
import li.cil.oc.Settings import li.cil.oc.Settings
import li.cil.oc.api 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.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.network.Visibility
import li.cil.oc.api.prefab import li.cil.oc.api.prefab
import li.cil.oc.common.tileentity import li.cil.oc.common.tileentity
import li.cil.oc.server.{PacketSender => ServerPacketSender} import li.cil.oc.server.{PacketSender => ServerPacketSender}
import li.cil.oc.util.BlockPosition import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedArguments._ import li.cil.oc.util.ExtendedArguments._
import li.cil.oc.util.FluidUtils
import li.cil.oc.util.InventoryUtils
import net.minecraft.util.EnumFacing import net.minecraft.util.EnumFacing
import scala.language.existentials import scala.language.existentials
class Transposer(val host: tileentity.Transposer) extends prefab.ManagedEnvironment with traits.WorldInventoryAnalytics with traits.WorldTankAnalytics { object Transposer {
abstract class Common extends prefab.ManagedEnvironment with traits.WorldInventoryAnalytics with traits.WorldTankAnalytics with traits.InventoryTransfer {
override val node = api.Network.newNode(this, Visibility.Network). override val node = api.Network.newNode(this, Visibility.Network).
withComponent("transposer"). withComponent("transposer").
withConnector(). withConnector().
create() create()
override protected def checkSideForAction(args: Arguments, n: Int) =
args.checkSide(n, EnumFacing.values: _*)
override def onTransferContents(): Option[String] = {
if (node.tryChangeBuffer(-Settings.get.transposerCost)) None
else Option("not enough energy")
}
}
class Block(val host: tileentity.Transposer) extends Common {
override def position = BlockPosition(host) override def position = BlockPosition(host)
override protected def checkSideForAction(args: Arguments, n: Int) = args.checkSide(n, EnumFacing.values: _*) override def onTransferContents(): Option[String] = {
val result = super.onTransferContents()
@Callback(doc = """function(sourceSide:number, sinkSide:number[, count:number[, sourceSlot:number, sinkSlot:number]]):number -- Transfer some items between two inventories.""") if (result.isEmpty) ServerPacketSender.sendTransposerActivity(host)
def transferItem(context: Context, args: Arguments): Array[AnyRef] = { result
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))
}
else result(Unit, "not enough energy")
} }
@Callback(doc = """function(sourceSide:number, sinkSide:number[, count:number]):number -- Transfer some items between two inventories.""") class Upgrade(val host: EnvironmentHost) extends Common {
def transferFluid(context: Context, args: Arguments): Array[AnyRef] = { node.setVisibility(Visibility.Neighbors)
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)) { override def position = BlockPosition(host)
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")
}
} }

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) val facing = checkSideForAction(args, 0)
withInventory(facing, inventory => result(inventory.getStackInSlot(args.checkSlot(inventory, 1)))) 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.""") @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] = { 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]) = private def withInventory(side: EnumFacing, f: IInventory => Array[AnyRef]) =
InventoryUtils.inventoryAt(position.offset(side)) match { InventoryUtils.inventoryAt(position.offset(side)) match {
case Some(inventory) if inventory.isUseableByPlayer(fakePlayer) && mayInteract(position.offset(side), side.getOpposite) => f(inventory) 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. * 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) = 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( extractFromInventorySlot(
insertIntoInventorySlot(_, sink, sinkSide, sinkSlot, limit), source, sourceSide, sourceSlot, limit) 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 * Utility method for calling <tt>transferBetweenInventories</tt> on inventories
@ -266,7 +272,7 @@ object InventoryUtils {
* Utility method for calling <tt>transferBetweenInventoriesSlots</tt> on inventories * Utility method for calling <tt>transferBetweenInventoriesSlots</tt> on inventories
* in the world. * 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(sourcePos).exists(sourceInventory =>
inventoryAt(sinkPos).exists(sinkInventory => inventoryAt(sinkPos).exists(sinkInventory =>
transferBetweenInventoriesSlots(sourceInventory, sourceSide, sourceSlot, sinkInventory, sinkSide, sinkSlot, limit))) transferBetweenInventoriesSlots(sourceInventory, sourceSide, sourceSlot, sinkInventory, sinkSide, sinkSlot, limit)))