blob: 2d357a8a8d79707521752a44489409be2d6370fb [file] [log] [blame] [raw]
package li.cil.oc.integration.appeng
import appeng.api.networking.crafting.ICraftingLink
import appeng.api.networking.security.MachineSource
import appeng.api.storage.data.IAEItemStack
import appeng.tile.networking.TileController
import appeng.util.item.AEItemStack
import li.cil.oc.OpenComputers
import li.cil.oc.api.driver.NamedBlock
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.ManagedEnvironment
import li.cil.oc.api.prefab.AbstractValue
import li.cil.oc.api.prefab.DriverTileEntity
import li.cil.oc.common.EventHandler
import li.cil.oc.integration.ManagedTileEntityEnvironment
import li.cil.oc.util.ResultWrapper._
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.world.World
import net.minecraftforge.common.DimensionManager
import scala.collection.convert.WrapAsScala._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
object DriverController extends DriverTileEntity {
def getTileEntityClass = classOf[TileController]
def createEnvironment(world: World, x: Int, y: Int, z: Int): ManagedEnvironment =
new Environment(world.getTileEntity(x, y, z).asInstanceOf[TileController])
class Environment(tileEntity: TileController) extends ManagedTileEntityEnvironment[TileController](tileEntity, "me_controller") with NamedBlock {
override def preferredName = "me_controller"
override def priority = 0
@Callback(doc = "function():table -- Get a list of tables representing the available CPUs in the network.")
def getCpus(context: Context, args: Arguments): Array[AnyRef] =
result(tileEntity.getProxy.getCrafting.getCpus.map(cpu => Map(
"name" -> cpu.getName,
"storage" -> cpu.getAvailableStorage,
"coprocessors" -> cpu.getCoProcessors,
"busy" -> cpu.isBusy)))
@Callback(doc = "function():table -- Get a list of known item recipes. These can be used to issue crafting requests.")
def getCraftables(context: Context, args: Arguments): Array[AnyRef] =
result(tileEntity.getProxy.getStorage.getItemInventory.getStorageList.
filter(_.isCraftable).map(new Craftable(tileEntity, _)))
@Callback(doc = "function():table -- Get a list of the stored items in the network.")
def getItemsInNetwork(context: Context, args: Arguments): Array[AnyRef] =
result(tileEntity.getProxy.getStorage.getItemInventory.getStorageList.map(_.getItemStack))
@Callback(doc = "function():table -- Get a list of the stored fluids in the network.")
def getFluidsInNetwork(context: Context, args: Arguments): Array[AnyRef] =
result(tileEntity.getProxy.getStorage.getFluidInventory.getStorageList.map(_.getFluidStack))
@Callback(doc = "function():number -- Get the average power injection into the network.")
def getAvgPowerInjection(context: Context, args: Arguments): Array[AnyRef] =
result(tileEntity.getProxy.getEnergy.getAvgPowerInjection)
@Callback(doc = "function():number -- Get the average power usage of the network.")
def getAvgPowerUsage(context: Context, args: Arguments): Array[AnyRef] =
result(tileEntity.getProxy.getEnergy.getAvgPowerUsage)
@Callback(doc = "function():number -- Get the idle power usage of the network.")
def getIdlePowerUsage(context: Context, args: Arguments): Array[AnyRef] =
result(tileEntity.getProxy.getEnergy.getIdlePowerUsage)
@Callback(doc = "function():number -- Get the maximum stored power in the network.")
def getMaxStoredPower(context: Context, args: Arguments): Array[AnyRef] =
result(tileEntity.getProxy.getEnergy.getMaxStoredPower)
@Callback(doc = "function():number -- Get the stored power in the network. ")
def getStoredPower(context: Context, args: Arguments): Array[AnyRef] =
result(tileEntity.getProxy.getEnergy.getStoredPower)
}
class Craftable(var controller: TileController, var stack: IAEItemStack) extends AbstractValue {
def this() = this(null, null)
@Callback(doc = "function():table -- Returns the item stack representation of the crafting result.")
def getItemStack(context: Context, args: Arguments): Array[AnyRef] = Array(stack.getItemStack)
@Callback(doc = "function([int amount]):userdata -- Requests the item to be crafted, returning an object that allows tracking the crafting status.")
def request(context: Context, args: Arguments): Array[AnyRef] = {
if (controller == null || controller.isInvalid) {
return result(Unit, "no controller")
}
val count = if (args.count > 0) args.checkInteger(0) else 1
val request = stack.copy
request.setStackSize(count)
val craftingGrid = controller.getProxy.getCrafting
val source = new MachineSource(controller)
val future = craftingGrid.beginCraftingJob(controller.getWorldObj, controller.getProxy.getGrid, source, request, null)
val status = new CraftingStatus()
Future {
try {
val job = future.get() // Make 100% sure we wait for this outside the scheduled closure.
EventHandler.schedule(() => status.setLink(craftingGrid.submitJob(job, null, null, true, source)))
}
catch {
case e: Exception =>
OpenComputers.log.debug("Error submitting job to AE2.", e)
status.cancel()
}
}
result(status)
}
override def load(nbt: NBTTagCompound) {
super.load(nbt)
stack = AEItemStack.loadItemStackFromNBT(nbt)
if (nbt.hasKey("dimension")) {
val dimension = nbt.getInteger("dimension")
val x = nbt.getInteger("x")
val y = nbt.getInteger("y")
val z = nbt.getInteger("z")
EventHandler.schedule(() => {
val world = DimensionManager.getWorld(dimension)
val tileEntity = world.getTileEntity(x, y, z)
if (tileEntity != null && tileEntity.isInstanceOf[TileController]) {
controller = tileEntity.asInstanceOf[TileController]
}
})
}
}
override def save(nbt: NBTTagCompound) {
super.save(nbt)
stack.writeToNBT(nbt)
if (controller != null && !controller.isInvalid) {
nbt.setInteger("dimension", controller.getWorldObj.provider.dimensionId)
nbt.setInteger("x", controller.xCoord)
nbt.setInteger("y", controller.yCoord)
nbt.setInteger("z", controller.zCoord)
}
}
}
class CraftingStatus extends AbstractValue {
private var isComputing = true
private var link: Option[ICraftingLink] = None
def setLink(value: ICraftingLink) {
link = Option(value)
isComputing = false
}
def cancel() {
isComputing = false
}
@Callback(doc = "function():boolean -- Get whether the crafting request has been canceled.")
def isCanceled(context: Context, args: Arguments): Array[AnyRef] = {
if (isComputing) return result(false, "computing")
link.fold(result(false, "no link"))(l => result(l.isCanceled))
}
@Callback(doc = "function():boolean -- Get whether the crafting request is done.")
def isDone(context: Context, args: Arguments): Array[AnyRef] = {
if (isComputing) return result(false, "computing")
link.fold(result(true, "no link"))(l => result(l.isDone))
}
override def load(nbt: NBTTagCompound) {
super.load(nbt)
isComputing = false
}
}
}