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

Conflicts:
	src/main/scala/li/cil/oc/common/recipe/ExtendedRecipe.scala
	src/main/scala/li/cil/oc/common/tileentity/Robot.scala
	src/main/scala/li/cil/oc/common/tileentity/RobotProxy.scala
	src/main/scala/li/cil/oc/server/PacketHandler.scala
	src/main/scala/li/cil/oc/server/driver/converter/FluidTankInfo.scala
	src/main/scala/li/cil/oc/server/driver/converter/ItemStack.scala
This commit is contained in:
Florian Nücke 2014-10-01 18:11:57 +02:00
commit 8f79419788
27 changed files with 693 additions and 35 deletions

Binary file not shown.

View File

@ -891,8 +891,9 @@ opencomputers {
# Allow robots to get a table representation of item stacks using the # Allow robots to get a table representation of item stacks using the
# inventory controller upgrade? (i.e. whether the getStackInSlot method # inventory controller upgrade? (i.e. whether the getStackInSlot method
# of said upgrade is enabled or not). # of said upgrade is enabled or not). Also applies to tank controller
allowItemStackInspection: false # upgrade and it's fluid getter method.
allowItemStackInspection: true
} }
# Settings that are intended for debugging issues, not for normal use. # Settings that are intended for debugging issues, not for normal use.
@ -987,5 +988,9 @@ opencomputers {
# not have an overly noticeable impact on performance, but it's disabled # not have an overly noticeable impact on performance, but it's disabled
# by default because it is unnecessary in *most* cases. # by default because it is unnecessary in *most* cases.
periodicallyForceLightUpdate: false periodicallyForceLightUpdate: false
# Pass along IDs of items and fluids when converting them to a table
# representation for Lua.
insertIdsInConverters: false
} }
} }

View File

@ -104,6 +104,8 @@ oc:item.UpgradeNavigation.name=Navigations-Upgrade
oc:item.UpgradePiston.name=Kolben-Upgrade oc:item.UpgradePiston.name=Kolben-Upgrade
oc:item.UpgradeSign.name=Schild-I/O-Upgrade oc:item.UpgradeSign.name=Schild-I/O-Upgrade
oc:item.UpgradeSolarGenerator.name=Solargenerator-Upgrade oc:item.UpgradeSolarGenerator.name=Solargenerator-Upgrade
oc:item.UpgradeTank.name=Tank-Upgrade
oc:item.UpgradeTankController.name=Tankbedienungs-Upgrade
oc:item.UpgradeTractorBeam.name=Traktorstrahl-Upgrade oc:item.UpgradeTractorBeam.name=Traktorstrahl-Upgrade
oc:item.WirelessNetworkCard.name=Drahtlosnetzwerkkarte oc:item.WirelessNetworkCard.name=Drahtlosnetzwerkkarte
@ -262,5 +264,7 @@ oc:tooltip.UpgradeNavigation=Erlaubt es Robotern, ihre Position und Ausrichtung
oc:tooltip.UpgradePiston=Dieses Upgrade erlaubt es zu drängeln. Es macht es möglich Blöcke zu verschieben, ähnlich dem Kolben. Es kann jedoch §lkeine§7 Entities bewegen. oc:tooltip.UpgradePiston=Dieses Upgrade erlaubt es zu drängeln. Es macht es möglich Blöcke zu verschieben, ähnlich dem Kolben. Es kann jedoch §lkeine§7 Entities bewegen.
oc:tooltip.UpgradeSign=Erlaubt das Lesen und Schreiben von Text auf Schildern. oc:tooltip.UpgradeSign=Erlaubt das Lesen und Schreiben von Text auf Schildern.
oc:tooltip.UpgradeSolarGenerator=Kann verwendet werden, um unterwegs Energie aus Sonnenlicht zu generieren. Benötigt eine ungehinderte Sicht zum Himmel über dem Roboter. Generiert Energie mit %s%% der Geschwindigkeit eines Stirlingmotors. oc:tooltip.UpgradeSolarGenerator=Kann verwendet werden, um unterwegs Energie aus Sonnenlicht zu generieren. Benötigt eine ungehinderte Sicht zum Himmel über dem Roboter. Generiert Energie mit %s%% der Geschwindigkeit eines Stirlingmotors.
oc:tooltip.UpgradeTank=Dieses Upgrade gibt Robotern einen internen Tank. Ohne ein solches Upgrade können Roboter keine Flüssigkeiten verwahren.
oc:tooltip.UpgradeTankController=Dieses Upgrade erlaubt es dem Roboter, präziser mit externen Tanks zu interagieren, und erlaubt es ihm, Flüssigkeiten in und aus sich im Inventar befindlichen Tank-Gegenständen zu pumpen.
oc:tooltip.UpgradeTractorBeam=Stattet den Roboter mit unglaublich fortschrittlicher Technologie - Kosename: "Gegenstandsmagnet" - aus. Erlaubt es dem Roboter, Gegenstände, innerhalb von 3 Blöcken um sich herum, einzusammeln. oc:tooltip.UpgradeTractorBeam=Stattet den Roboter mit unglaublich fortschrittlicher Technologie - Kosename: "Gegenstandsmagnet" - aus. Erlaubt es dem Roboter, Gegenstände, innerhalb von 3 Blöcken um sich herum, einzusammeln.
oc:tooltip.WirelessNetworkCard=Erlaubt das drahtlose Senden von Netzwerknachrichten, zusätzlich zu normalen. Drahtlose Nachrichten werden nur gesendet, wenn eine §fSignalstärke§7 festgelegt wurde! oc:tooltip.WirelessNetworkCard=Erlaubt das drahtlose Senden von Netzwerknachrichten, zusätzlich zu normalen. Drahtlose Nachrichten werden nur gesendet, wenn eine §fSignalstärke§7 festgelegt wurde!

View File

@ -104,6 +104,8 @@ oc:item.UpgradeNavigation.name=Navigation Upgrade
oc:item.UpgradePiston.name=Piston Upgrade oc:item.UpgradePiston.name=Piston Upgrade
oc:item.UpgradeSign.name=Sign I/O Upgrade oc:item.UpgradeSign.name=Sign I/O Upgrade
oc:item.UpgradeSolarGenerator.name=Solar Generator Upgrade oc:item.UpgradeSolarGenerator.name=Solar Generator Upgrade
oc:item.UpgradeTank.name=Tank Upgrade
oc:item.UpgradeTankController.name=Tank Controller Upgrade
oc:item.UpgradeTractorBeam.name=Tractor Beam Upgrade oc:item.UpgradeTractorBeam.name=Tractor Beam Upgrade
oc:item.WirelessNetworkCard.name=Wireless Network Card oc:item.WirelessNetworkCard.name=Wireless Network Card
@ -262,5 +264,7 @@ oc:tooltip.UpgradeNavigation=Can be used to determine the position and orientati
oc:tooltip.UpgradePiston=This upgrade is very pushy. It allows moving blocks, similar to when using a piston. It does §lnot§7 move entities, however. oc:tooltip.UpgradePiston=This upgrade is very pushy. It allows moving blocks, similar to when using a piston. It does §lnot§7 move entities, however.
oc:tooltip.UpgradeSign=Allows reading text on and writing text to signs. oc:tooltip.UpgradeSign=Allows reading text on and writing text to signs.
oc:tooltip.UpgradeSolarGenerator=Can be used to generate energy from sunlight on the go. Requires a clear line of sight to the sky above the robot. Generates energy at %s%% of the speed of a Stirling Engine. oc:tooltip.UpgradeSolarGenerator=Can be used to generate energy from sunlight on the go. Requires a clear line of sight to the sky above the robot. Generates energy at %s%% of the speed of a Stirling Engine.
oc:tooltip.UpgradeTank=This upgrade provides a tank for fluid storage to the robot. Without one of these, robots will not be able to store fluids internally.
oc:tooltip.UpgradeTankController=This upgrade allows the robot more control in how it interacts with external tanks, and allows it to transfer fluids into and out of fluid tank items in its inventory.
oc:tooltip.UpgradeTractorBeam=Equips the robot with extremely advanced technology, nicknamed the "Item Magnet". Allows it to pick up items anywhere within 3 blocks of its location. oc:tooltip.UpgradeTractorBeam=Equips the robot with extremely advanced technology, nicknamed the "Item Magnet". Allows it to pick up items anywhere within 3 blocks of its location.
oc:tooltip.WirelessNetworkCard=Allows wireless sending of network messages in addition to normal ones. You can adjust the §fsignal strength§7 to control how far messages are sent. Higher signal strength results in higher energy consumption. oc:tooltip.WirelessNetworkCard=Allows wireless sending of network messages in addition to normal ones. You can adjust the §fsignal strength§7 to control how far messages are sent. Higher signal strength results in higher energy consumption.

View File

@ -41,24 +41,24 @@ function robot.inventorySize()
end end
function robot.select(slot) function robot.select(...)
return component.robot.select(slot) return component.robot.select(...)
end end
function robot.count(slot) function robot.count(...)
return component.robot.count(slot) return component.robot.count(...)
end end
function robot.space(slot) function robot.space(...)
return component.robot.space(slot) return component.robot.space(...)
end end
function robot.compareTo(slot) function robot.compareTo(...)
return component.robot.compareTo(slot) return component.robot.compareTo(...)
end end
function robot.transferTo(slot, count) function robot.transferTo(...)
return component.robot.transferTo(slot, count) return component.robot.transferTo(...)
end end
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@ -195,6 +195,79 @@ function robot.turnAround()
return turn() and turn() return turn() and turn()
end end
-------------------------------------------------------------------------------
-- Tank
function robot.tankCount()
return component.robot.tankCount()
end
function robot.selectTank(tank)
return component.robot.selectTank(tank)
end
function robot.tankLevel()
return component.robot.tankLevel()
end
function robot.tankSpace()
return component.robot.tankSpace()
end
function robot.compareFluidTo(...)
return component.robot.compareFluidTo(...)
end
function robot.transferFluidTo(...)
return component.robot.transferFluidTo(...)
end
-------------------------------------------------------------------------------
-- Tank + World
function robot.compareFluid()
return component.robot.compareFluid(sides.front)
end
function robot.compareFluidUp()
return component.robot.compareFluid(sides.up)
end
function robot.compareFluidDown()
return component.robot.compareFluid(sides.down)
end
function robot.drain(count)
checkArg(1, count, "nil", "number")
return component.robot.drain(sides.front, count)
end
function robot.drainUp(count)
checkArg(1, count, "nil", "number")
return component.robot.drain(sides.up, count)
end
function robot.drainDown(count)
checkArg(1, count, "nil", "number")
return component.robot.drain(sides.down, count)
end
function robot.fill(count)
checkArg(1, count, "nil", "number")
return component.robot.fill(sides.front, count)
end
function robot.fillUp(count)
checkArg(1, count, "nil", "number")
return component.robot.fill(sides.up, count)
end
function robot.fillDown(count)
checkArg(1, count, "nil", "number")
return component.robot.fill(sides.down, count)
end
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
return robot return robot

View File

@ -196,6 +196,16 @@ solarGeneratorUpgrade {
["oc:circuitChip3", blockLapis, "oc:circuitChip3"] ["oc:circuitChip3", blockLapis, "oc:circuitChip3"]
[ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]] [ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
} }
tankUpgrade {
input: [[plankWood, fenceIron, plankWood]
[dispenser, cauldron, craftingPiston]
[plankWood, "oc:circuitChip1", plankWood]]
}
tankControllerUpgrade {
input: [[ingotGold, glassBottle, ingotGold]
[dispenser, "oc:circuitChip2", craftingPiston]
[ingotGold, "oc:materialCircuitBoardPrinted", ingotGold]]
}
tractorBeamUpgrade { tractorBeamUpgrade {
input: [[ingotGold, craftingPiston, ingotGold] input: [[ingotGold, craftingPiston, ingotGold]
[ingotIron, "oc:capacitor", ingotIron] [ingotIron, "oc:capacitor", ingotIron]

Binary file not shown.

After

Width:  |  Height:  |  Size: 693 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 631 B

View File

@ -261,5 +261,7 @@ object Items extends ItemAPI {
// 1.3.5 // 1.3.5
Recipes.addItem(new item.TabletCase(multi), "tabletCase", "oc:tabletCase") Recipes.addItem(new item.TabletCase(multi), "tabletCase", "oc:tabletCase")
Recipes.addItem(new item.UpgradePiston(multi), "pistonUpgrade", "oc:pistonUpgrade") Recipes.addItem(new item.UpgradePiston(multi), "pistonUpgrade", "oc:pistonUpgrade")
Recipes.addItem(new item.UpgradeTank(multi), "tankUpgrade", "oc:tankUpgrade")
Recipes.addItem(new item.UpgradeTankController(multi), "tankControllerUpgrade", "oc:tankControllerUpgrade")
} }
} }

View File

@ -248,6 +248,7 @@ class Settings(config: Config) {
val disassembleAllTheThings = config.getBoolean("misc.disassembleAllTheThings") val disassembleAllTheThings = config.getBoolean("misc.disassembleAllTheThings")
val disassemblerBreakChance = config.getDouble("misc.disassemblerBreakChance") max 0 min 1 val disassemblerBreakChance = config.getDouble("misc.disassemblerBreakChance") max 0 min 1
val hideOwnPet = config.getBoolean("misc.hideOwnSpecial") val hideOwnPet = config.getBoolean("misc.hideOwnSpecial")
val allowItemStackInspection = config.getBoolean("misc.allowItemStackInspection")
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
// debug // debug
@ -265,6 +266,7 @@ class Settings(config: Config) {
val debugPersistence = config.getBoolean("debug.verbosePersistenceErrors") val debugPersistence = config.getBoolean("debug.verbosePersistenceErrors")
val nativeInTmpDir = config.getBoolean("debug.nativeInTmpDir") val nativeInTmpDir = config.getBoolean("debug.nativeInTmpDir")
val periodicallyForceLightUpdate = config.getBoolean("debug.periodicallyForceLightUpdate") val periodicallyForceLightUpdate = config.getBoolean("debug.periodicallyForceLightUpdate")
val insertIdsInConverters = config.getBoolean("debug.insertIdsInConverters")
} }
object Settings { object Settings {
@ -352,6 +354,11 @@ object Settings {
"computer.debug", "computer.debug",
"misc.alwaysTryNative", "misc.alwaysTryNative",
"misc.verbosePersistenceErrors" "misc.verbosePersistenceErrors"
),
// Upgrading to version 1.3.5, added forgotten check for item stack,
// inspection, patch to true to avoid stuff suddenly breaking.
VersionRange.createFromVersionSpec("1.3.4") -> Array(
"misc.allowItemStackInspection"
) )
) )

View File

@ -102,6 +102,8 @@ class Proxy {
api.Driver.add(driver.item.UpgradePiston) api.Driver.add(driver.item.UpgradePiston)
api.Driver.add(driver.item.UpgradeSign) api.Driver.add(driver.item.UpgradeSign)
api.Driver.add(driver.item.UpgradeSolarGenerator) api.Driver.add(driver.item.UpgradeSolarGenerator)
api.Driver.add(driver.item.UpgradeTank)
api.Driver.add(driver.item.UpgradeTankController)
api.Driver.add(driver.item.UpgradeTractorBeam) api.Driver.add(driver.item.UpgradeTractorBeam)
api.Driver.add(driver.item.WirelessNetworkCard) api.Driver.add(driver.item.WirelessNetworkCard)
@ -116,6 +118,7 @@ class Proxy {
} }
OpenComputers.log.info("Initializing vanilla converters.") OpenComputers.log.info("Initializing vanilla converters.")
api.Driver.add(driver.converter.FluidStack)
api.Driver.add(driver.converter.FluidTankInfo) api.Driver.add(driver.converter.FluidTankInfo)
api.Driver.add(driver.converter.ItemStack) api.Driver.add(driver.converter.ItemStack)

View File

@ -17,7 +17,7 @@ import li.cil.oc.server.component
import li.cil.oc.util.ExtendedNBT._ import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ItemUtils.TabletData import li.cil.oc.util.ItemUtils.TabletData
import li.cil.oc.util.{ItemUtils, RotationHelper} import li.cil.oc.util.{ItemUtils, RotationHelper}
import li.cil.oc.{OpenComputers, Settings, api} import li.cil.oc.{Localization, OpenComputers, Settings, api}
import net.minecraft.entity.Entity import net.minecraft.entity.Entity
import net.minecraft.entity.player.EntityPlayer import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
@ -251,7 +251,14 @@ class TabletWrapper(var stack: ItemStack, var holder: EntityPlayer) extends Comp
override def isPaused = computer.isPaused override def isPaused = computer.isPaused
override def start() = computer.start() override def start() = {
val result = computer.start()
computer.lastError match {
case message if message != null => holder.addChatMessage(Localization.Analyzer.LastError(message))
case _ =>
}
result
}
override def pause(seconds: Double) = computer.pause(seconds) override def pause(seconds: Double) = computer.pause(seconds)

View File

@ -0,0 +1,23 @@
package li.cil.oc.common.item
import java.util
import cpw.mods.fml.relauncher.{Side, SideOnly}
import li.cil.oc.Settings
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.ItemStack
import net.minecraftforge.fluids.FluidStack
class UpgradeTank(val parent: Delegator) extends Delegate with ItemTier {
@SideOnly(Side.CLIENT) override
def tooltipLines(stack: ItemStack, player: EntityPlayer, tooltip: util.List[String], advanced: Boolean) = {
if (stack.hasTagCompound) {
FluidStack.loadFluidStackFromNBT(stack.getTagCompound.getCompoundTag(Settings.namespace + "data")) match {
case stack: FluidStack =>
tooltip.add(stack.getFluid.getLocalizedName(stack) + ": " + stack.amount + "/16000")
case _ =>
}
}
super.tooltipLines(stack, player, tooltip, advanced)
}
}

View File

@ -0,0 +1,3 @@
package li.cil.oc.common.item
class UpgradeTankController(val parent: Delegator) extends Delegate with ItemTier

View File

@ -7,7 +7,9 @@ import li.cil.oc.util.{Color, SideTracker}
import li.cil.oc.{Settings, api} import li.cil.oc.{Settings, api}
import net.minecraft.inventory.InventoryCrafting import net.minecraft.inventory.InventoryCrafting
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound import net.minecraft.nbt.{NBTBase, NBTTagCompound}
import scala.collection.convert.WrapAsScala._
object ExtendedRecipe { object ExtendedRecipe {
private lazy val navigationUpgrade = api.Items.get("navigationUpgrade") private lazy val navigationUpgrade = api.Items.get("navigationUpgrade")
@ -41,10 +43,18 @@ object ExtendedRecipe {
val nbt = craftedStack.getTagCompound val nbt = craftedStack.getTagCompound
for (i <- 0 until inventory.getSizeInventory) { for (i <- 0 until inventory.getSizeInventory) {
val stack = inventory.getStackInSlot(i) val stack = inventory.getStackInSlot(i)
if (stack != null) Color.findDye(stack) match { if (stack != null) {
case Some(oreDictName) => Color.findDye(stack) match {
nbt.setInteger(Settings.namespace + "color", Color.dyes.indexOf(oreDictName)) case Some(oreDictName) =>
case _ => nbt.setInteger(Settings.namespace + "color", Color.dyes.indexOf(oreDictName))
case _ =>
}
if (api.Items.get(stack) == floppy && stack.hasTagCompound) {
val oldData = stack.getTagCompound
for (oldTagName <- oldData.func_150296_c().map(_.asInstanceOf[String])) {
nbt.setTag(oldTagName, oldData.getTag(oldTagName).copy())
}
}
} }
} }
} }

View File

@ -22,7 +22,7 @@ import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.common.MinecraftForge import net.minecraftforge.common.MinecraftForge
import net.minecraftforge.common.util.ForgeDirection import net.minecraftforge.common.util.ForgeDirection
import net.minecraftforge.fluids.{BlockFluidBase, FluidRegistry} import net.minecraftforge.fluids._
import scala.collection.mutable import scala.collection.mutable
@ -32,7 +32,7 @@ import scala.collection.mutable
// robot moves we only create a new proxy tile entity, hook the instance of this // robot moves we only create a new proxy tile entity, hook the instance of this
// class that was held by the old proxy to it and can then safely forget the // class that was held by the old proxy to it and can then safely forget the
// old proxy, which will be cleaned up by Minecraft like any other tile entity. // old proxy, which will be cleaned up by Minecraft like any other tile entity.
class Robot extends traits.Computer with traits.PowerInformation with api.machine.Robot { class Robot extends traits.Computer with traits.PowerInformation with api.machine.Robot with IFluidHandler {
var proxy: RobotProxy = _ var proxy: RobotProxy = _
val info = new ItemUtils.RobotData() val info = new ItemUtils.RobotData()
@ -55,6 +55,8 @@ class Robot extends traits.Computer with traits.PowerInformation with api.machin
var selectedSlot = actualSlot(0) var selectedSlot = actualSlot(0)
var selectedTank = 0
// For client. // For client.
var renderingErrored = false var renderingErrored = false
@ -336,6 +338,7 @@ class Robot extends traits.Computer with traits.PowerInformation with api.machin
if (inventorySize > 0) { if (inventorySize > 0) {
selectedSlot = nbt.getInteger(Settings.namespace + "selectedSlot") max inventorySlots.min min inventorySlots.max selectedSlot = nbt.getInteger(Settings.namespace + "selectedSlot") max inventorySlots.min min inventorySlots.max
} }
selectedTank = nbt.getInteger(Settings.namespace + "selectedTank")
animationTicksTotal = nbt.getInteger(Settings.namespace + "animationTicksTotal") animationTicksTotal = nbt.getInteger(Settings.namespace + "animationTicksTotal")
animationTicksLeft = nbt.getInteger(Settings.namespace + "animationTicksLeft") animationTicksLeft = nbt.getInteger(Settings.namespace + "animationTicksLeft")
if (animationTicksLeft > 0) { if (animationTicksLeft > 0) {
@ -357,6 +360,7 @@ class Robot extends traits.Computer with traits.PowerInformation with api.machin
nbt.setString(Settings.namespace + "owner", owner) nbt.setString(Settings.namespace + "owner", owner)
ownerUuid.foreach(uuid => nbt.setString(Settings.namespace + "ownerUuid", uuid.toString)) ownerUuid.foreach(uuid => nbt.setString(Settings.namespace + "ownerUuid", uuid.toString))
nbt.setInteger(Settings.namespace + "selectedSlot", selectedSlot) nbt.setInteger(Settings.namespace + "selectedSlot", selectedSlot)
nbt.setInteger(Settings.namespace + "selectedTank", selectedTank)
if (isAnimatingMove || isAnimatingSwing || isAnimatingTurn) { if (isAnimatingMove || isAnimatingSwing || isAnimatingTurn) {
nbt.setInteger(Settings.namespace + "animationTicksTotal", animationTicksTotal) nbt.setInteger(Settings.namespace + "animationTicksTotal", animationTicksTotal)
nbt.setInteger(Settings.namespace + "animationTicksLeft", animationTicksLeft) nbt.setInteger(Settings.namespace + "animationTicksLeft", animationTicksLeft)
@ -443,6 +447,7 @@ class Robot extends traits.Computer with traits.PowerInformation with api.machin
} }
if (isComponentSlot(slot)) { if (isComponentSlot(slot)) {
super.onItemAdded(slot, stack) super.onItemAdded(slot, stack)
world.notifyBlocksOfNeighborChange(x, y, z, getBlockType)
} }
if (isInventorySlot(slot)) { if (isInventorySlot(slot)) {
computer.signal("inventory_changed", Int.box(slot - actualSlot(0) + 1)) computer.signal("inventory_changed", Int.box(slot - actualSlot(0) + 1))
@ -466,6 +471,9 @@ class Robot extends traits.Computer with traits.PowerInformation with api.machin
if (isInventorySlot(slot)) { if (isInventorySlot(slot)) {
computer.signal("inventory_changed", Int.box(slot - actualSlot(0) + 1)) computer.signal("inventory_changed", Int.box(slot - actualSlot(0) + 1))
} }
if (isComponentSlot(slot)) {
world.notifyBlocksOfNeighborChange(x, y, z, getBlockType)
}
} }
} }
@ -652,4 +660,62 @@ class Robot extends traits.Computer with traits.PowerInformation with api.machin
case ForgeDirection.EAST => containerSlots.toArray case ForgeDirection.EAST => containerSlots.toArray
case _ => inventorySlots.toArray case _ => inventorySlots.toArray
} }
}
// ----------------------------------------------------------------------- //
def getFluidTank(tank: Int) = {
val tanks = components.collect {
case Some(tank: IFluidTank) => tank
}
if (tank < 0 || tank >= tanks.length) None
else Option(tanks(tank))
}
def tankCount = components.count {
case Some(tank: IFluidTank) => true
case _ => false
}
// ----------------------------------------------------------------------- //
override def fill(from: ForgeDirection, resource: FluidStack, doFill: Boolean) =
getFluidTank(selectedTank) match {
case Some(tank) =>
tank.fill(resource, doFill)
case _ => 0
}
override def drain(from: ForgeDirection, resource: FluidStack, doDrain: Boolean) =
getFluidTank(selectedTank) match {
case Some(tank) if tank.getFluid != null && tank.getFluid.isFluidEqual(resource) =>
tank.drain(resource.amount, doDrain)
case _ => null
}
override def drain(from: ForgeDirection, maxDrain: Int, doDrain: Boolean) = {
getFluidTank(selectedTank) match {
case Some(tank) =>
tank.drain(maxDrain, doDrain)
case _ => null
}
}
override def canFill(from: ForgeDirection, fluid: Fluid) = {
getFluidTank(selectedTank) match {
case Some(tank) => tank.getFluid == null || tank.getFluid.getFluid == fluid
case _ => false
}
}
override def canDrain(from: ForgeDirection, fluid: Fluid): Boolean = {
getFluidTank(selectedTank) match {
case Some(tank) => tank.getFluid != null && tank.getFluid.getFluid == fluid
case _ => false
}
}
override def getTankInfo(from: ForgeDirection) =
components.collect {
case Some(tank: IFluidTank) => tank.getInfo
}.toArray
}

View File

@ -12,8 +12,9 @@ import net.minecraft.inventory.ISidedInventory
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.common.util.ForgeDirection import net.minecraftforge.common.util.ForgeDirection
import net.minecraftforge.fluids.{Fluid, FluidStack, IFluidHandler}
class RobotProxy(val robot: Robot) extends traits.Computer with traits.PowerInformation with api.machine.Robot with ISidedInventory { class RobotProxy(val robot: Robot) extends traits.Computer with traits.PowerInformation with api.machine.Robot with ISidedInventory with IFluidHandler {
def this() = this(new Robot()) def this() = this(new Robot())
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
@ -250,4 +251,18 @@ class RobotProxy(val robot: Robot) extends traits.Computer with traits.PowerInfo
override def globalBufferSize = robot.globalBufferSize override def globalBufferSize = robot.globalBufferSize
override def globalBufferSize_=(value: Double) = robot.globalBufferSize = value override def globalBufferSize_=(value: Double) = robot.globalBufferSize = value
// ----------------------------------------------------------------------- //
override def fill(from: ForgeDirection, resource: FluidStack, doFill: Boolean) = robot.fill(from, resource, doFill)
override def drain(from: ForgeDirection, resource: FluidStack, doDrain: Boolean) = robot.drain(from, resource, doDrain)
override def drain(from: ForgeDirection, maxDrain: Int, doDrain: Boolean) = robot.drain(from, maxDrain, doDrain)
override def canFill(from: ForgeDirection, fluid: Fluid) = robot.canFill(from, fluid)
override def canDrain(from: ForgeDirection, fluid: Fluid) = robot.canDrain(from, fluid)
override def getTankInfo(from: ForgeDirection) = robot.getTankInfo(from)
} }

View File

@ -29,7 +29,7 @@ class UpgradeInventoryController(val owner: Container with Robot) extends compon
} }
@Callback(doc = """function():table -- Get a description of the stack in the the inventory on the specified side of the robot. Back refers to the robot's own inventory.""") @Callback(doc = """function():table -- Get a description of the stack in the the inventory on the specified side of the robot. Back refers to the robot's own inventory.""")
def getStackInSlot(context: Context, args: Arguments): Array[AnyRef] = { def getStackInSlot(context: Context, args: Arguments): Array[AnyRef] = if (Settings.get.allowItemStackInspection) {
val facing = checkSideForInventory(args, 0) val facing = checkSideForInventory(args, 0)
val slot = args.checkInteger(1) - 1 val slot = args.checkInteger(1) - 1
if (facing == owner.facing.getOpposite) { if (facing == owner.facing.getOpposite) {
@ -43,6 +43,7 @@ class UpgradeInventoryController(val owner: Container with Robot) extends compon
case _ => result(Unit, "no inventory") case _ => result(Unit, "no inventory")
} }
} }
else result(Unit, "not enabled in config")
@Callback(doc = """function(facing:number, slot:number[, count:number]):boolean -- Drops the selected item stack into the specified slot of an inventory.""") @Callback(doc = """function(facing:number, slot:number[, count:number]):boolean -- Drops the selected item stack into the specified slot of an inventory.""")
def dropIntoSlot(context: Context, args: Arguments): Array[AnyRef] = { def dropIntoSlot(context: Context, args: Arguments): Array[AnyRef] = {

View File

@ -0,0 +1,38 @@
package li.cil.oc.server.component
import li.cil.oc.api.Network
import li.cil.oc.api.driver.Container
import li.cil.oc.api.network.Visibility
import li.cil.oc.common.component.ManagedComponent
import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.fluids.{FluidStack, FluidTank, IFluidTank}
class UpgradeTank(val owner: Container, val capacity: Int) extends ManagedComponent with IFluidTank {
val node = Network.newNode(this, Visibility.None).create()
val tank = new FluidTank(capacity)
override def load(nbt: NBTTagCompound) {
super.load(nbt)
tank.readFromNBT(nbt)
}
override def save(nbt: NBTTagCompound) {
super.save(nbt)
tank.writeToNBT(nbt)
}
// ----------------------------------------------------------------------- //
override def getFluid = tank.getFluid
override def getFluidAmount = tank.getFluidAmount
override def getCapacity = tank.getCapacity
override def getInfo = tank.getInfo
override def fill(stack: FluidStack, doFill: Boolean) = tank.fill(stack, doFill)
override def drain(maxDrain: Int, doDrain: Boolean) = tank.drain(maxDrain, doDrain)
}

View File

@ -0,0 +1,125 @@
package li.cil.oc.server.component
import li.cil.oc.Settings
import li.cil.oc.api.Network
import li.cil.oc.api.driver.Container
import li.cil.oc.api.network._
import li.cil.oc.common.component
import li.cil.oc.common.tileentity.Robot
import li.cil.oc.util.ExtendedArguments._
import net.minecraft.item.ItemStack
import net.minecraftforge.common.util.ForgeDirection
import net.minecraftforge.fluids.{FluidContainerRegistry, IFluidContainerItem, IFluidHandler}
class UpgradeTankController(val owner: Container with Robot) extends component.ManagedComponent {
val node = Network.newNode(this, Visibility.Network).
withComponent("tank_controller", Visibility.Neighbors).
withConnector().
create()
// ----------------------------------------------------------------------- //
@Callback(doc = """function(side:number):number -- Get the capacity of the tank on the specified side of the robot. Back refers to the robot's own selected tank.""")
def getTankCapacity(context: Context, args: Arguments): Array[AnyRef] = {
val facing = checkSideForTank(args, 0)
if (facing == owner.facing.getOpposite) result(owner.getFluidTank(owner.selectedTank).fold(0)(_.getCapacity))
else owner.world.getTileEntity(math.floor(owner.xPosition).toInt + facing.offsetX, math.floor(owner.yPosition).toInt + facing.offsetY, math.floor(owner.zPosition).toInt + facing.offsetZ) match {
case handler: IFluidHandler =>
result((owner.getFluidTank(owner.selectedTank) match {
case Some(tank) => handler.getTankInfo(facing.getOpposite).filter(info => info.fluid == null || info.fluid.isFluidEqual(tank.getFluid))
case _ => handler.getTankInfo(facing.getOpposite)
}).map(_.capacity).foldLeft(0)((max, capacity) => math.max(max, capacity)))
case _ => result(Unit, "no tank")
}
}
@Callback(doc = """function(side:number):table -- Get a description of the fluid in the the tank on the specified side of the robot. Back refers to the robot's own selected tank.""")
def getFluidInTank(context: Context, args: Arguments): Array[AnyRef] = if (Settings.get.allowItemStackInspection) {
val facing = checkSideForTank(args, 0)
if (facing == owner.facing.getOpposite) result(owner.getFluidTank(owner.selectedTank).map(_.getFluid).orNull)
else owner.world.getTileEntity(math.floor(owner.xPosition).toInt + facing.offsetX, math.floor(owner.yPosition).toInt + facing.offsetY, math.floor(owner.zPosition).toInt + facing.offsetZ) match {
case handler: IFluidHandler => result(Option(handler.getTankInfo(facing.getOpposite)).map(_.map(_.fluid)).orNull)
case _ => result(Unit, "no tank")
}
}
else result(Unit, "not enabled in config")
@Callback(doc = """function([amount:number]):boolean -- Transfers fluid from a tank in the selected inventory slot to the selected tank.""")
def drain(context: Context, args: Arguments): Array[AnyRef] = {
val amount = args.optionalFluidCount(0)
owner.getFluidTank(owner.selectedTank) match {
case Some(tank) =>
owner.getStackInSlot(owner.selectedSlot) match {
case stack: ItemStack =>
if (FluidContainerRegistry.isFilledContainer(stack)) {
val contents = FluidContainerRegistry.getFluidForFilledItem(stack)
val container = stack.getItem.getContainerItem(stack)
if (tank.getCapacity - tank.getFluidAmount < contents.amount) {
result(Unit, "tank is full")
}
else if (tank.fill(contents, false) < contents.amount) {
result(Unit, "incompatible fluid")
}
else {
tank.fill(contents, true)
owner.decrStackSize(owner.selectedSlot, 1)
owner.player().inventory.addItemStackToInventory(container)
result(true)
}
}
else stack.getItem match {
case container: IFluidContainerItem =>
val drained = container.drain(stack, amount, false)
val transferred = tank.fill(drained, true)
if (transferred > 0) {
container.drain(stack, transferred, true)
result(true)
}
else result(Unit, "incompatible or no fluid")
case _ => result(Unit, "item is empty or not a fluid container")
}
case _ => result(Unit, "nothing selected")
}
case _ => result(Unit, "no tank")
}
}
@Callback(doc = """function([amount:number]):boolean -- Transfers fluid from the selected tank to a tank in the selected inventory slot.""")
def fill(context: Context, args: Arguments): Array[AnyRef] = {
val amount = args.optionalFluidCount(0)
owner.getFluidTank(owner.selectedTank) match {
case Some(tank) =>
owner.getStackInSlot(owner.selectedSlot) match {
case stack: ItemStack =>
if (FluidContainerRegistry.isEmptyContainer(stack)) {
val drained = tank.drain(amount, false)
val filled = FluidContainerRegistry.fillFluidContainer(drained, stack)
if (filled == null) {
result(Unit, "tank is empty")
}
else {
tank.drain(FluidContainerRegistry.getFluidForFilledItem(filled).amount, true)
owner.decrStackSize(owner.selectedSlot, 1)
owner.player().inventory.addItemStackToInventory(filled)
result(true)
}
}
else stack.getItem match {
case container: IFluidContainerItem =>
val drained = tank.drain(amount, false)
val transferred = container.fill(stack, drained, true)
if (transferred > 0) {
tank.drain(transferred, true)
result(true)
}
else result(Unit, "incompatible or no fluid")
case _ => result(Unit, "item is full or not a fluid container")
}
case _ => result(Unit, "nothing selected")
}
case _ => result(Unit, "no tank")
}
}
private def checkSideForTank(args: Arguments, n: Int) = owner.toGlobal(args.checkSide(n, ForgeDirection.SOUTH, ForgeDirection.NORTH, ForgeDirection.UP, ForgeDirection.DOWN))
}

View File

@ -18,7 +18,7 @@ import net.minecraft.util.{MovingObjectPosition, Vec3}
import net.minecraftforge.common.MinecraftForge import net.minecraftforge.common.MinecraftForge
import net.minecraftforge.common.util.ForgeDirection import net.minecraftforge.common.util.ForgeDirection
import net.minecraftforge.event.world.BlockEvent import net.minecraftforge.event.world.BlockEvent
import net.minecraftforge.fluids.FluidRegistry import net.minecraftforge.fluids._
import scala.collection.convert.WrapAsScala._ import scala.collection.convert.WrapAsScala._
@ -45,6 +45,8 @@ class Robot(val robot: tileentity.Robot) extends ManagedComponent {
def selectedSlot = robot.selectedSlot def selectedSlot = robot.selectedSlot
def selectedTank = robot.selectedTank
def player = robot.player() def player = robot.player()
def canPlaceInAir = { def canPlaceInAir = {
@ -493,6 +495,185 @@ class Robot(val robot: tileentity.Robot) extends ManagedComponent {
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
@Callback
def tankCount(context: Context, args: Arguments): Array[AnyRef] = result(robot.tankCount)
@Callback
def selectTank(context: Context, args: Arguments): Array[AnyRef] = {
if (args.count > 0 && args.checkAny(0) != null) {
robot.selectedTank = checkTank(args, 0)
}
result(selectedTank + 1)
}
@Callback(direct = true)
def tankLevel(context: Context, args: Arguments): Array[AnyRef] = {
val index =
if (args.count > 0 && args.checkAny(0) != null) checkTank(args, 0)
else selectedTank
result(fluidInTank(index) match {
case Some(fluid) => fluid.amount
case _ => 0
})
}
@Callback(direct = true)
def tankSpace(context: Context, args: Arguments): Array[AnyRef] = {
val index =
if (args.count > 0 && args.checkAny(0) != null) checkTank(args, 0)
else selectedTank
result(getTank(index) match {
case Some(tank) => tank.getCapacity - tank.getFluidAmount
case _ => 0
})
}
@Callback
def compareFluidTo(context: Context, args: Arguments): Array[AnyRef] = {
val index = checkTank(args, 0)
result((fluidInTank(selectedTank), fluidInTank(index)) match {
case (Some(stackA), Some(stackB)) => haveSameFluidType(stackA, stackB)
case (None, None) => true
case _ => false
})
}
@Callback
def transferFluidTo(context: Context, args: Arguments): Array[AnyRef] = {
val index = checkTank(args, 0)
val count = args.optionalFluidCount(1)
if (index == selectedTank || count == 0) {
result(true)
}
else (getTank(selectedTank), getTank(index)) match {
case (Some(from), Some(to)) =>
val drained = from.drain(count, false)
val transferred = to.fill(drained, true)
if (transferred > 0) {
from.drain(transferred, true)
robot.markDirty()
result(true)
}
else if (count >= from.getFluidAmount && to.getCapacity >= from.getFluidAmount && from.getCapacity >= to.getFluidAmount) {
// Swap.
val tmp = to.drain(to.getFluidAmount, true)
to.fill(from.drain(from.getFluidAmount, true), true)
from.fill(tmp, true)
robot.markDirty()
result(true)
}
else result(Unit, "incompatible or no fluid")
case _ => result(Unit, "invalid index")
}
}
@Callback
def compareFluid(context: Context, args: Arguments): Array[AnyRef] = {
val side = checkSideForAction(args, 0)
fluidInTank(selectedTank) match {
case Some(stack) =>
world.getTileEntity(x + side.offsetX, y + side.offsetY, z + side.offsetZ) match {
case handler: IFluidHandler =>
result(Option(handler.getTankInfo(side.getOpposite)).exists(_.exists(other => stack.isFluidEqual(other.fluid))))
case _ =>
val block = world.getBlock(x + side.offsetX, y + side.offsetY, z + side.offsetZ)
val fluid = FluidRegistry.lookupFluidForBlock(block)
result(stack.getFluid == fluid)
}
case _ => result(false)
}
}
@Callback
def drain(context: Context, args: Arguments): Array[AnyRef] = {
val facing = checkSideForAction(args, 0)
val count = args.optionalFluidCount(1)
getTank(selectedTank) match {
case Some(tank) =>
val space = tank.getCapacity - tank.getFluidAmount
val amount = math.min(count, space)
if (count > 0 && amount == 0) {
result(Unit, "tank is full")
}
else world.getTileEntity(x + facing.offsetX, y + facing.offsetY, z + facing.offsetZ) match {
case handler: IFluidHandler =>
tank.getFluid match {
case stack: FluidStack =>
val drained = handler.drain(facing.getOpposite, new FluidStack(stack, amount), true)
if ((drained != null && drained.amount > 0) || amount == 0) {
tank.fill(drained, true)
result(true)
}
else result(Unit, "incompatible or no fluid")
case _ =>
tank.fill(handler.drain(facing.getOpposite, amount, true), true)
result(true)
}
case _ =>
val block = world.getBlock(x + facing.offsetX, y + facing.offsetY, z + facing.offsetZ)
val fluid = FluidRegistry.lookupFluidForBlock(block)
if (tank.fill(new FluidStack(fluid, 1000), false) == 1000) {
tank.fill(new FluidStack(fluid, 1000), true)
world.setBlockToAir(x + facing.offsetX, y + facing.offsetY, z + facing.offsetZ)
result(true)
}
else result(Unit, "tank is full")
}
case _ => result(Unit, "no tank selected")
}
}
@Callback
def fill(context: Context, args: Arguments): Array[AnyRef] = {
val facing = checkSideForAction(args, 0)
val count = args.optionalFluidCount(1)
getTank(selectedTank) match {
case Some(tank) =>
val amount = math.min(count, tank.getFluidAmount)
if (count > 0 && amount == 0) {
result(Unit, "tank is empty")
}
val (bx, by, bz) = (x + facing.offsetX, y + facing.offsetY, z + facing.offsetZ)
world.getTileEntity(bx, by, bz) match {
case handler: IFluidHandler =>
tank.getFluid match {
case stack: FluidStack =>
val filled = handler.fill(facing.getOpposite, new FluidStack(stack, amount), true)
if (filled > 0 || amount == 0) {
tank.drain(filled, true)
result(true)
}
else result(Unit, "incompatible or no fluid")
case _ =>
result(Unit, "tank is empty")
}
case _ =>
val block = world.getBlock(bx, by, bz)
if (block != null && !block.isAir(world, x, y, z) && !block.isReplaceable(world, x, y, z)) {
result(Unit, "no space")
}
else if (tank.getFluidAmount < 1000) {
result(Unit, "tank is empty")
}
else if (!tank.getFluid.getFluid.canBePlacedInWorld) {
result(Unit, "incompatible fluid")
}
else {
val fluidBlock = tank.getFluid.getFluid.getBlock
tank.drain(1000, true)
world.func_147480_a(bx, by, bz, true)
world.setBlock(bx, by, bz, fluidBlock)
// This fake neighbor update is required to get stills to start flowing.
world.notifyBlockOfNeighborChange(bx, by, bz, robot.block)
result(true)
}
}
case _ => result(Unit, "no tank selected")
}
}
// ----------------------------------------------------------------------- //
override def onConnect(node: Node) { override def onConnect(node: Node) {
super.onConnect(node) super.onConnect(node)
if (node == this.node) { if (node == this.node) {
@ -619,12 +800,23 @@ class Robot(val robot: tileentity.Robot) extends ManagedComponent {
stackA.getItem == stackB.getItem && stackA.getItem == stackB.getItem &&
(!stackA.getHasSubtypes || stackA.getItemDamage == stackB.getItemDamage) (!stackA.getHasSubtypes || stackA.getItemDamage == stackB.getItemDamage)
private def haveSameFluidType(stackA: FluidStack, stackB: FluidStack) = stackA.isFluidEqual(stackB)
private def stackInSlot(slot: Int) = Option(robot.getStackInSlot(slot)) private def stackInSlot(slot: Int) = Option(robot.getStackInSlot(slot))
private def getTank(index: Int) = robot.getFluidTank(index)
private def fluidInTank(index: Int) = getTank(index) match {
case Some(tank) => Option(tank.getFluid)
case _ => None
}
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
private def checkSlot(args: Arguments, n: Int) = args.checkSlot(robot, n) private def checkSlot(args: Arguments, n: Int) = args.checkSlot(robot, n)
private def checkTank(args: Arguments, n: Int) = args.checkTank(robot, n)
private def checkSideForAction(args: Arguments, n: Int) = robot.toGlobal(args.checkSideForAction(n)) private def checkSideForAction(args: Arguments, n: Int) = robot.toGlobal(args.checkSideForAction(n))
private def checkSideForFace(args: Arguments, n: Int, facing: ForgeDirection) = robot.toGlobal(args.checkSideForFace(n, robot.toLocal(facing))) private def checkSideForFace(args: Arguments, n: Int, facing: ForgeDirection) = robot.toGlobal(args.checkSideForFace(n, robot.toLocal(facing)))

View File

@ -0,0 +1,25 @@
package li.cil.oc.server.driver.converter
import java.util
import li.cil.oc.{Settings, api}
import scala.collection.convert.WrapAsScala._
object FluidStack extends api.driver.Converter {
override def convert(value: scala.Any, output: util.Map[AnyRef, AnyRef]) =
value match {
case stack: net.minecraftforge.fluids.FluidStack =>
if (Settings.get.insertIdsInConverters) {
output += "id" -> Int.box(stack.fluidID)
}
output += "amount" -> Int.box(stack.amount)
output += "hasTag" -> Boolean.box(stack.tag != null)
val fluid = stack.getFluid
if (fluid != null) {
output += "name" -> fluid.getName
output += "label" -> fluid.getLocalizedName(stack)
}
case _ =>
}
}

View File

@ -13,13 +13,7 @@ object FluidTankInfo extends api.driver.Converter {
case tankInfo: fluids.FluidTankInfo => case tankInfo: fluids.FluidTankInfo =>
output += "capacity" -> Int.box(tankInfo.capacity) output += "capacity" -> Int.box(tankInfo.capacity)
if (tankInfo.fluid != null) { if (tankInfo.fluid != null) {
output += "amount" -> Int.box(tankInfo.fluid.amount) FluidStack.convert(tankInfo.fluid, output)
output += "id" -> Int.box(tankInfo.fluid.fluidID)
val fluid = tankInfo.fluid.getFluid
if (fluid != null) {
output += "name" -> fluid.getName
output += "label" -> fluid.getLocalizedName(tankInfo.fluid)
}
} }
else output += "amount" -> Int.box(0) else output += "amount" -> Int.box(0)
case _ => case _ =>

View File

@ -2,7 +2,7 @@ package li.cil.oc.server.driver.converter
import java.util import java.util
import li.cil.oc.api import li.cil.oc.{Settings, api}
import net.minecraft.item import net.minecraft.item
import net.minecraft.item.Item import net.minecraft.item.Item
@ -12,7 +12,9 @@ object ItemStack extends api.driver.Converter {
override def convert(value: AnyRef, output: util.Map[AnyRef, AnyRef]) = override def convert(value: AnyRef, output: util.Map[AnyRef, AnyRef]) =
value match { value match {
case stack: item.ItemStack => case stack: item.ItemStack =>
output += "id" -> Int.box(Item.getIdFromItem(stack.getItem)) if (Settings.get.insertIdsInConverters) {
output += "id" -> Int.box(Item.getIdFromItem(stack.getItem))
}
output += "damage" -> Int.box(stack.getItemDamage) output += "damage" -> Int.box(stack.getItemDamage)
output += "maxDamage" -> Int.box(stack.getMaxDamage) output += "maxDamage" -> Int.box(stack.getMaxDamage)
output += "size" -> Int.box(stack.stackSize) output += "size" -> Int.box(stack.stackSize)

View File

@ -0,0 +1,14 @@
package li.cil.oc.server.driver.item
import li.cil.oc.api
import li.cil.oc.api.driver.{Container, Slot}
import li.cil.oc.server.component
import net.minecraft.item.ItemStack
object UpgradeTank extends Item {
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("tankUpgrade"))
override def createEnvironment(stack: ItemStack, container: Container) = new component.UpgradeTank(container, 16000)
override def slot(stack: ItemStack) = Slot.Upgrade
}

View File

@ -0,0 +1,21 @@
package li.cil.oc.server.driver.item
import li.cil.oc.api
import li.cil.oc.api.driver.{Container, Slot}
import li.cil.oc.common.Tier
import li.cil.oc.common.tileentity.Robot
import li.cil.oc.server.component
import net.minecraft.item.ItemStack
object UpgradeTankController extends Item {
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("tankControllerUpgrade"))
override def createEnvironment(stack: ItemStack, container: Container) = container match {
case robot: Container with Robot => new component.UpgradeTankController(robot)
case _ => null
}
override def slot(stack: ItemStack) = Slot.Upgrade
override def tier(stack: ItemStack) = Tier.Two
}

View File

@ -1,7 +1,7 @@
package li.cil.oc.util package li.cil.oc.util
import li.cil.oc.api.machine.Robot
import li.cil.oc.api.network.Arguments import li.cil.oc.api.network.Arguments
import li.cil.oc.common.tileentity.Robot
import net.minecraft.inventory.IInventory import net.minecraft.inventory.IInventory
import net.minecraftforge.common.util.ForgeDirection import net.minecraftforge.common.util.ForgeDirection
@ -18,6 +18,12 @@ object ExtendedArguments {
} }
else 64 else 64
def optionalFluidCount(n: Int) =
if (args.count > n && args.checkAny(n) != null) {
math.max(0, args.checkInteger(n))
}
else 1000
def checkSlot(inventory: IInventory, n: Int) = { def checkSlot(inventory: IInventory, n: Int) = {
val slot = args.checkInteger(n) - 1 val slot = args.checkInteger(n) - 1
if (slot < 0 || slot >= inventory.getSizeInventory) { if (slot < 0 || slot >= inventory.getSizeInventory) {
@ -34,6 +40,14 @@ object ExtendedArguments {
slot + 1 + robot.containerCount slot + 1 + robot.containerCount
} }
def checkTank(robot: Robot, n: Int) = {
val tank = args.checkInteger(n) - 1
if (tank < 0 || tank >= robot.tankCount) {
throw new IllegalArgumentException("invalid tank index")
}
tank
}
def checkSideForAction(n: Int) = checkSide(n, ForgeDirection.SOUTH, ForgeDirection.UP, ForgeDirection.DOWN) def checkSideForAction(n: Int) = checkSide(n, ForgeDirection.SOUTH, ForgeDirection.UP, ForgeDirection.DOWN)
def checkSideForMovement(n: Int) = checkSide(n, ForgeDirection.SOUTH, ForgeDirection.NORTH, ForgeDirection.UP, ForgeDirection.DOWN) def checkSideForMovement(n: Int) = checkSide(n, ForgeDirection.SOUTH, ForgeDirection.NORTH, ForgeDirection.UP, ForgeDirection.DOWN)