mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-14 17:56:34 -04:00
Extracted tank logic from robot component and some minor bugfixing.
This commit is contained in:
parent
006935ba06
commit
c5e79df8b5
@ -79,6 +79,7 @@ public interface MachineHost extends EnvironmentHost {
|
||||
* <p/>
|
||||
* This method is called from executor threads, so it must be thread-safe.
|
||||
*/
|
||||
// TODO Merge with {@link EnvironmentHost#markChanged} in 1.5
|
||||
void markForSaving();
|
||||
|
||||
/**
|
||||
|
10
src/main/scala/li/cil/oc/common/inventory/MultiTank.scala
Normal file
10
src/main/scala/li/cil/oc/common/inventory/MultiTank.scala
Normal file
@ -0,0 +1,10 @@
|
||||
package li.cil.oc.common.inventory
|
||||
|
||||
import net.minecraftforge.fluids.IFluidTank
|
||||
|
||||
// TODO Move to api.internal in 1.5, make internal.Robot extend this.
|
||||
trait MultiTank {
|
||||
def tankCount: Int
|
||||
|
||||
def getFluidTank(index: Int): IFluidTank
|
||||
}
|
@ -17,6 +17,7 @@ import li.cil.oc.api.network._
|
||||
import li.cil.oc.client.gui
|
||||
import li.cil.oc.common.Slot
|
||||
import li.cil.oc.common.Tier
|
||||
import li.cil.oc.common.inventory.MultiTank
|
||||
import li.cil.oc.integration.opencomputers.DriverKeyboard
|
||||
import li.cil.oc.integration.opencomputers.DriverRedstoneCard
|
||||
import li.cil.oc.integration.opencomputers.DriverScreen
|
||||
@ -43,7 +44,7 @@ import scala.collection.mutable
|
||||
// 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
|
||||
// old proxy, which will be cleaned up by Minecraft like any other tile entity.
|
||||
class Robot extends traits.Computer with traits.PowerInformation with IFluidHandler with internal.Robot {
|
||||
class Robot extends traits.Computer with traits.PowerInformation with IFluidHandler with internal.Robot with MultiTank {
|
||||
var proxy: RobotProxy = _
|
||||
|
||||
val info = new ItemUtils.RobotData()
|
||||
@ -651,7 +652,7 @@ class Robot extends traits.Computer with traits.PowerInformation with IFluidHand
|
||||
}
|
||||
|
||||
override def setInventorySlotContents(slot: Int, stack: ItemStack) {
|
||||
if (slot < getSizeInventory - componentCount && isItemValidForSlot(slot, stack)) {
|
||||
if (slot < getSizeInventory - componentCount && (isItemValidForSlot(slot, stack) || stack == null)) {
|
||||
if (stack != null && stack.stackSize > 1 && isComponentSlot(slot)) {
|
||||
super.setInventorySlotContents(slot, stack.splitStack(1))
|
||||
if (stack.stackSize > 0 && isServer) {
|
||||
|
@ -9,6 +9,7 @@ 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.common.inventory.MultiTank
|
||||
import li.cil.oc.integration.Mods
|
||||
import mods.immibis.redlogic.api.wiring.IWire
|
||||
import net.minecraft.entity.Entity
|
||||
@ -21,7 +22,7 @@ import net.minecraftforge.fluids.Fluid
|
||||
import net.minecraftforge.fluids.FluidStack
|
||||
import net.minecraftforge.fluids.IFluidHandler
|
||||
|
||||
class RobotProxy(val robot: Robot) extends traits.Computer with traits.PowerInformation with ISidedInventory with IFluidHandler with internal.Robot {
|
||||
class RobotProxy(val robot: Robot) extends traits.Computer with traits.PowerInformation with ISidedInventory with IFluidHandler with internal.Robot with MultiTank {
|
||||
def this() = this(new Robot())
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
@ -118,8 +118,7 @@ trait Computer extends Environment with ComponentInventory with Rotatable with B
|
||||
|
||||
if (_isRunning != machine.isRunning) {
|
||||
_isRunning = machine.isRunning
|
||||
isOutputEnabled = hasRedstoneCard
|
||||
isAbstractBusAvailable = hasAbstractBusCard
|
||||
markDirty()
|
||||
ServerPacketSender.sendComputerState(this)
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ trait Environment extends TileEntity with network.Environment with driver.Enviro
|
||||
|
||||
override def zPosition = z + 0.5
|
||||
|
||||
override def markChanged() = if (canUpdate) isChangeScheduled = true else markDirty()
|
||||
override def markChanged() = if (canUpdate) isChangeScheduled = true else world.markTileEntityChunkModified(x, y, z, this)
|
||||
|
||||
protected def isConnected = node.address != null && node.network != null
|
||||
|
||||
|
@ -105,7 +105,7 @@ object ModOpenComputers extends ModProxy {
|
||||
|
||||
blacklistHost(classOf[internal.Adapter], "geolyzer", "keyboard", "screen1", "angelUpgrade", "batteryUpgrade1", "batteryUpgrade2", "batteryUpgrade3", "chunkloaderUpgrade", "craftingUpgrade", "experienceUpgrade", "generatorUpgrade", "inventoryUpgrade", "navigationUpgrade", "pistonUpgrade", "solarGeneratorUpgrade", "tankUpgrade", "tractorBeamUpgrade")
|
||||
blacklistHost(classOf[internal.Microcontroller], "graphicsCard1", "graphicsCard2", "graphicsCard3", "keyboard", "screen1", "angelUpgrade", "chunkloaderUpgrade", "craftingUpgrade", "databaseUpgrade1", "databaseUpgrade2", "databaseUpgrade3", "experienceUpgrade", "generatorUpgrade", "inventoryUpgrade", "inventoryControllerUpgrade", "navigationUpgrade", "tankUpgrade", "tankControllerUpgrade", "tractorBeamUpgrade")
|
||||
blacklistHost(classOf[internal.Drone], "graphicsCard1", "graphicsCard2", "graphicsCard3", "keyboard", "lanCard", "redstoneCard1", "screen1", "angelUpgrade", "craftingUpgrade", "experienceUpgrade", "generatorUpgrade", "tankUpgrade", "tankControllerUpgrade")
|
||||
blacklistHost(classOf[internal.Drone], "graphicsCard1", "graphicsCard2", "graphicsCard3", "keyboard", "lanCard", "redstoneCard1", "screen1", "angelUpgrade", "craftingUpgrade", "experienceUpgrade")
|
||||
blacklistHost(classOf[internal.Tablet], "lanCard", "redstoneCard1", "screen1", "angelUpgrade", "chunkloaderUpgrade", "craftingUpgrade", "databaseUpgrade1", "databaseUpgrade2", "databaseUpgrade3", "experienceUpgrade", "generatorUpgrade", "inventoryUpgrade", "inventoryControllerUpgrade", "tankUpgrade", "tankControllerUpgrade")
|
||||
|
||||
if (!WirelessRedstone.isAvailable) {
|
||||
|
@ -16,7 +16,7 @@ import net.minecraft.world.WorldServer
|
||||
import net.minecraftforge.common.util.FakePlayerFactory
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
|
||||
class Drone(val host: entity.Drone) extends prefab.ManagedEnvironment with traits.WorldInspectable with traits.InventoryInspectable with traits.InventoryWorldInterop {
|
||||
class Drone(val host: entity.Drone) extends prefab.ManagedEnvironment with traits.WorldControl with traits.InventoryControl with traits.InventoryWorldControl {
|
||||
override val node = Network.newNode(this, Visibility.Network).
|
||||
withComponent("drone").
|
||||
create()
|
||||
|
@ -10,6 +10,7 @@ import li.cil.oc.api.machine.Context
|
||||
import li.cil.oc.api.network._
|
||||
import li.cil.oc.api.prefab
|
||||
import li.cil.oc.common.ToolDurabilityProviders
|
||||
import li.cil.oc.common.inventory.MultiTank
|
||||
import li.cil.oc.common.tileentity
|
||||
import li.cil.oc.server.component.traits
|
||||
import li.cil.oc.server.{PacketSender => ServerPacketSender}
|
||||
@ -28,11 +29,10 @@ import net.minecraft.util.MovingObjectPosition.MovingObjectType
|
||||
import net.minecraft.util.Vec3
|
||||
import net.minecraftforge.common.MinecraftForge
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
import net.minecraftforge.fluids._
|
||||
|
||||
import scala.collection.convert.WrapAsScala._
|
||||
|
||||
class Robot(val robot: tileentity.Robot) extends prefab.ManagedEnvironment with traits.WorldInspectable with traits.InventoryInspectable with traits.InventoryWorldInterop {
|
||||
class Robot(val robot: tileentity.Robot) extends prefab.ManagedEnvironment with traits.WorldControl with traits.InventoryControl with traits.InventoryWorldControl with traits.TankControl with traits.TankWorldControl {
|
||||
override val node = api.Network.newNode(this, Visibility.Network).
|
||||
withComponent("robot").
|
||||
withConnector(Settings.get.bufferRobot).
|
||||
@ -90,13 +90,25 @@ class Robot(val robot: tileentity.Robot) extends prefab.ManagedEnvironment with
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
val tank = new MultiTank {
|
||||
override def tankCount = robot.tankCount
|
||||
|
||||
override def getFluidTank(index: Int) = robot.getFluidTank(index)
|
||||
}
|
||||
|
||||
def selectedTank = robot.selectedTank
|
||||
|
||||
override def selectedTank_=(value: Int) = robot.selectedTank = value
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override protected def fakePlayer = robot.player()
|
||||
|
||||
override protected 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)))
|
||||
|
||||
def selectedTank = robot.selectedTank
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
def canPlaceInAir = {
|
||||
val event = new RobotPlaceInAirEvent(robot)
|
||||
@ -378,195 +390,6 @@ class Robot(val robot: tileentity.Robot) extends prefab.ManagedEnvironment with
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
@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) =>
|
||||
val (nx, ny, nz) = (x + side.offsetX, y + side.offsetY, z + side.offsetZ)
|
||||
if (world.blockExists(nx, ny, nz)) world.getTileEntity(nx, ny, nz) 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)
|
||||
}
|
||||
else result(false)
|
||||
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 {
|
||||
val (nx, ny, nz) = (x + facing.offsetX, y + facing.offsetY, z + facing.offsetZ)
|
||||
if (world.blockExists(nx, ny, nz)) world.getTileEntity(nx, ny, nz) 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 (fluid == null) {
|
||||
result(Unit, "incompatible or no fluid")
|
||||
}
|
||||
else 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")
|
||||
}
|
||||
else result(Unit, "incompatible or no fluid")
|
||||
}
|
||||
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)
|
||||
if (world.blockExists(bx, by, bz)) 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)
|
||||
}
|
||||
}
|
||||
else result(Unit, "no space")
|
||||
case _ => result(Unit, "no tank selected")
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def onConnect(node: Node) {
|
||||
super.onConnect(node)
|
||||
if (node == this.node) {
|
||||
@ -659,21 +482,4 @@ class Robot(val robot: tileentity.Robot) extends prefab.ManagedEnvironment with
|
||||
(hit.hitVec.yCoord - hit.blockY).toFloat,
|
||||
(hit.hitVec.zCoord - hit.blockZ).toFloat)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
private def haveSameFluidType(stackA: FluidStack, stackB: FluidStack) = stackA.isFluidEqual(stackB)
|
||||
|
||||
private def getTank(index: Int) = robot.tryGetTank(index)
|
||||
|
||||
private def fluidInTank(index: Int) = getTank(index) match {
|
||||
case Some(tank) => Option(tank.getFluid)
|
||||
case _ => None
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
private def checkTank(args: Arguments, n: Int) = args.checkTank(robot, n)
|
||||
|
||||
private def checkSideForFace(args: Arguments, n: Int, facing: ForgeDirection) = robot.toGlobal(args.checkSideForFace(n, robot.toLocal(facing)))
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ trait InventoryAware {
|
||||
|
||||
def selectedSlot_=(value: Int): Unit
|
||||
|
||||
def insertionSlots = {
|
||||
protected def insertionSlots = {
|
||||
val slots = (0 until inventory.getSizeInventory).toIterable
|
||||
slots.drop(selectedSlot) ++ slots.take(selectedSlot)
|
||||
}
|
||||
|
@ -6,11 +6,11 @@ import li.cil.oc.api.machine.Context
|
||||
import li.cil.oc.util.ExtendedArguments._
|
||||
import li.cil.oc.util.ResultWrapper.result
|
||||
|
||||
trait InventoryInspectable extends InventoryAware {
|
||||
@Callback
|
||||
trait InventoryControl extends InventoryAware {
|
||||
@Callback(doc = "function():number -- The size of this device's internal inventory.")
|
||||
def inventorySize(context: Context, args: Arguments): Array[AnyRef] = result(inventory.getSizeInventory)
|
||||
|
||||
@Callback
|
||||
@Callback(doc = "function([slot:number]):number -- Get the currently selected slot; set the selected slot if specified.")
|
||||
def select(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
if (args.count > 0 && args.checkAny(0) != null) {
|
||||
val slot = args.checkSlot(inventory, 0)
|
||||
@ -21,7 +21,7 @@ trait InventoryInspectable extends InventoryAware {
|
||||
result(selectedSlot + 1)
|
||||
}
|
||||
|
||||
@Callback(direct = true)
|
||||
@Callback(direct = true, doc = "function([slot:number]):number -- Get the number of items in the specified slot, otherwise in the selected slot.")
|
||||
def count(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val slot =
|
||||
if (args.count > 0 && args.checkAny(0) != null) args.checkSlot(inventory, 0)
|
||||
@ -32,7 +32,7 @@ trait InventoryInspectable extends InventoryAware {
|
||||
})
|
||||
}
|
||||
|
||||
@Callback(direct = true)
|
||||
@Callback(direct = true, doc = "function([slot:number]):number -- Get the remaining space in the specified slot, otherwise in the selected slot.")
|
||||
def space(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val slot =
|
||||
if (args.count > 0 && args.checkAny(0) != null) args.checkSlot(inventory, 0)
|
||||
@ -43,7 +43,7 @@ trait InventoryInspectable extends InventoryAware {
|
||||
})
|
||||
}
|
||||
|
||||
@Callback
|
||||
@Callback(doc = "function(otherSlot:number):boolean -- Compare the contents of the selected slot to the contents of the specified slot.")
|
||||
def compareTo(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val slot = args.checkSlot(inventory, 0)
|
||||
result((stackInSlot(selectedSlot), stackInSlot(slot)) match {
|
||||
@ -53,7 +53,7 @@ trait InventoryInspectable extends InventoryAware {
|
||||
})
|
||||
}
|
||||
|
||||
@Callback
|
||||
@Callback(doc = "function(toSlot:number[, amount:number]):boolean -- Move up to the specified amount of items from the selected slot into the specified slot.")
|
||||
def transferTo(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val slot = args.checkSlot(inventory, 0)
|
||||
val count = args.optionalItemCount(1)
|
@ -13,7 +13,7 @@ import net.minecraft.entity.item.EntityItem
|
||||
import net.minecraft.item.ItemBlock
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
|
||||
trait InventoryWorldInterop extends InventoryAware with WorldAware with SideRestricted {
|
||||
trait InventoryWorldControl extends InventoryAware with WorldAware with SideRestricted {
|
||||
@Callback
|
||||
def compare(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val side = checkSideForAction(args, 0)
|
@ -0,0 +1,23 @@
|
||||
package li.cil.oc.server.component.traits
|
||||
|
||||
import li.cil.oc.common.inventory.MultiTank
|
||||
import net.minecraftforge.fluids.FluidStack
|
||||
|
||||
trait TankAware {
|
||||
def tank: MultiTank
|
||||
|
||||
def selectedTank: Int
|
||||
|
||||
def selectedTank_=(value: Int): Unit
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
protected def getTank(index: Int) = Option(tank.getFluidTank(index))
|
||||
|
||||
protected def fluidInTank(index: Int) = getTank(index) match {
|
||||
case Some(tank) => Option(tank.getFluid)
|
||||
case _ => None
|
||||
}
|
||||
|
||||
protected def haveSameFluidType(stackA: FluidStack, stackB: FluidStack) = stackA.isFluidEqual(stackB)
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
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.util.ExtendedArguments._
|
||||
import li.cil.oc.util.ResultWrapper.result
|
||||
|
||||
trait TankControl extends TankAware {
|
||||
@Callback
|
||||
def tankCount(context: Context, args: Arguments): Array[AnyRef] = result(tank.tankCount)
|
||||
|
||||
@Callback
|
||||
def selectTank(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
if (args.count > 0 && args.checkAny(0) != null) {
|
||||
selectedTank = args.checkTank(tank, 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) args.checkTank(tank, 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) args.checkTank(tank, 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 = args.checkTank(tank, 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 = args.checkTank(tank, 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)
|
||||
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)
|
||||
result(true)
|
||||
}
|
||||
else result(Unit, "incompatible or no fluid")
|
||||
case _ => result(Unit, "invalid index")
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,130 @@
|
||||
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.util.BlockPosition
|
||||
import li.cil.oc.util.ExtendedBlock._
|
||||
import li.cil.oc.util.ExtendedWorld._
|
||||
import li.cil.oc.util.ExtendedArguments._
|
||||
import li.cil.oc.util.ResultWrapper.result
|
||||
import net.minecraftforge.fluids.FluidRegistry
|
||||
import net.minecraftforge.fluids.FluidStack
|
||||
import net.minecraftforge.fluids.IFluidHandler
|
||||
|
||||
trait TankWorldControl extends TankAware with WorldAware with SideRestricted {
|
||||
@Callback
|
||||
def compareFluid(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val side = checkSideForAction(args, 0)
|
||||
fluidInTank(selectedTank) match {
|
||||
case Some(stack) =>
|
||||
val blockPos = BlockPosition(x, y, z).offset(side)
|
||||
if (world.blockExists(blockPos)) world.getTileEntity(blockPos) match {
|
||||
case handler: IFluidHandler =>
|
||||
result(Option(handler.getTankInfo(side.getOpposite)).exists(_.exists(other => stack.isFluidEqual(other.fluid))))
|
||||
case _ =>
|
||||
val block = world.getBlock(blockPos)
|
||||
val fluid = FluidRegistry.lookupFluidForBlock(block)
|
||||
result(stack.getFluid == fluid)
|
||||
}
|
||||
else result(false)
|
||||
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 {
|
||||
val blockPos = BlockPosition(x, y, z).offset(facing)
|
||||
if (world.blockExists(blockPos)) world.getTileEntity(blockPos) 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 _ =>
|
||||
val transferred = tank.fill(handler.drain(facing.getOpposite, amount, true), true)
|
||||
result(transferred > 0, transferred)
|
||||
}
|
||||
case _ =>
|
||||
val block = world.getBlock(blockPos)
|
||||
val fluid = FluidRegistry.lookupFluidForBlock(block)
|
||||
if (fluid == null) {
|
||||
result(Unit, "incompatible or no fluid")
|
||||
}
|
||||
else if (tank.fill(new FluidStack(fluid, 1000), false) == 1000) {
|
||||
tank.fill(new FluidStack(fluid, 1000), true)
|
||||
world.setBlockToAir(blockPos)
|
||||
result(true)
|
||||
}
|
||||
else result(Unit, "tank is full")
|
||||
}
|
||||
else result(Unit, "incompatible or no fluid")
|
||||
}
|
||||
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 blockPos = BlockPosition(x, y, z).offset(facing)
|
||||
if (world.blockExists(blockPos)) world.getTileEntity(blockPos) 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(blockPos)
|
||||
if (!block.isAir(blockPos) && !block.isReplaceable(blockPos)) {
|
||||
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.breakBlock(blockPos)
|
||||
world.setBlock(blockPos, fluidBlock)
|
||||
// This fake neighbor update is required to get stills to start flowing.
|
||||
world.notifyBlockOfNeighborChange(blockPos, world.getBlock(x, y, z))
|
||||
result(true)
|
||||
}
|
||||
}
|
||||
else result(Unit, "no space")
|
||||
case _ => result(Unit, "no tank selected")
|
||||
}
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@ import li.cil.oc.api.machine.Callback
|
||||
import li.cil.oc.api.machine.Context
|
||||
import li.cil.oc.util.ResultWrapper.result
|
||||
|
||||
trait WorldInspectable extends WorldAware with SideRestricted {
|
||||
trait WorldControl extends WorldAware with SideRestricted {
|
||||
@Callback
|
||||
def detect(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val side = checkSideForAction(args, 0)
|
@ -2,6 +2,7 @@ package li.cil.oc.util
|
||||
|
||||
import li.cil.oc.api.internal.Robot
|
||||
import li.cil.oc.api.machine.Arguments
|
||||
import li.cil.oc.common.inventory.MultiTank
|
||||
import net.minecraft.inventory.IInventory
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
|
||||
@ -45,9 +46,9 @@ object ExtendedArguments {
|
||||
slot + 1 + robot.containerCount
|
||||
}
|
||||
|
||||
def checkTank(robot: Robot, n: Int) = {
|
||||
def checkTank(multi: MultiTank, n: Int) = {
|
||||
val tank = args.checkInteger(n) - 1
|
||||
if (tank < 0 || tank >= robot.tankCount) {
|
||||
if (tank < 0 || tank >= multi.tankCount) {
|
||||
throw new IllegalArgumentException("invalid tank index")
|
||||
}
|
||||
tank
|
||||
|
@ -1,6 +1,7 @@
|
||||
package li.cil.oc.util
|
||||
|
||||
import li.cil.oc.api.driver.EnvironmentHost
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
import net.minecraft.world.IBlockAccess
|
||||
import net.minecraft.world.World
|
||||
@ -28,6 +29,8 @@ object ExtendedWorld {
|
||||
}
|
||||
|
||||
class ExtendedWorld(override val world: World) extends ExtendedBlockAccess(world) {
|
||||
def blockExists(position: BlockPosition) = world.blockExists(position.x, position.y, position.z)
|
||||
|
||||
def getBlockHardness(position: BlockPosition) = getBlock(position).getBlockHardness(world, position.x, position.y, position.z)
|
||||
|
||||
def getBlockHarvestLevel(position: BlockPosition) = getBlock(position).getHarvestLevel(getBlockMetadata(position))
|
||||
@ -35,6 +38,12 @@ object ExtendedWorld {
|
||||
def getBlockHarvestTool(position: BlockPosition) = getBlock(position).getHarvestTool(getBlockMetadata(position))
|
||||
|
||||
def setBlockToAir(position: BlockPosition) = world.setBlockToAir(position.x, position.y, position.z)
|
||||
|
||||
def notifyBlockOfNeighborChange(position: BlockPosition, block: Block) = world.notifyBlockOfNeighborChange(position.x, position.y, position.z, block)
|
||||
|
||||
def breakBlock(position: BlockPosition, drops: Boolean = true) = world.func_147480_a(position.x, position.y, position.z, drops)
|
||||
|
||||
def setBlock(position: BlockPosition, block: Block) = world.setBlock(position.x, position.y, position.z, block)
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user