From 872dc5b8880fb34d5b2b4fdb763be600394e46db Mon Sep 17 00:00:00 2001 From: repo_alt Date: Fri, 7 Jan 2022 03:58:03 +0300 Subject: [PATCH] Extended AE crafting CPU API Fixed NEI valid items highlight after API update Some AE integration code cleanup --- .../oc/client/gui/DynamicGuiContainer.scala | 4 +- .../integration/appeng/NetworkControl.scala | 226 ++++++++++++------ 2 files changed, 155 insertions(+), 75 deletions(-) diff --git a/src/main/scala/li/cil/oc/client/gui/DynamicGuiContainer.scala b/src/main/scala/li/cil/oc/client/gui/DynamicGuiContainer.scala index 09d9b4dc9..84147e247 100644 --- a/src/main/scala/li/cil/oc/client/gui/DynamicGuiContainer.scala +++ b/src/main/scala/li/cil/oc/client/gui/DynamicGuiContainer.scala @@ -180,9 +180,9 @@ abstract class DynamicGuiContainer[C <: Container](container: C) extends CustomG val panel = LayoutManager.itemPanel if (panel == null) return zLevel += 350 - val itemsPerPage = ReflectionHelper.getPrivateValue(classOf[ItemPanel], LayoutManager.itemPanel, "itemsPerPage").asInstanceOf[Int] + val itemsPerPage = panel.getGrid.getPerPage for (index <- 0 until itemsPerPage) { - val rect = panel.getSlotRect(index) + val rect = panel.getGrid.getSlotRect(index) val slot = panel.getSlotMouseOver(rect.x, rect.y) if (slot != null) hoveredSlot match { case Some(hovered) => diff --git a/src/main/scala/li/cil/oc/integration/appeng/NetworkControl.scala b/src/main/scala/li/cil/oc/integration/appeng/NetworkControl.scala index 3c72f0b1f..ba5d28874 100644 --- a/src/main/scala/li/cil/oc/integration/appeng/NetworkControl.scala +++ b/src/main/scala/li/cil/oc/integration/appeng/NetworkControl.scala @@ -4,12 +4,14 @@ import java.lang import appeng.api.AEApi import appeng.api.config.Actionable -import appeng.api.networking.crafting.ICraftingLink -import appeng.api.networking.crafting.ICraftingRequester +import appeng.api.networking.IGridNode +import appeng.api.networking.crafting.{CraftingItemList, ICraftingLink, ICraftingRequester} import appeng.api.networking.security.{BaseActionSource, IActionHost, MachineSource} import appeng.api.networking.storage.IBaseMonitor import appeng.api.storage.IMEMonitorHandlerReceiver import appeng.api.storage.data.{IAEItemStack, IItemList} +import appeng.api.util.AECableType +import appeng.me.cluster.implementations.CraftingCPUCluster import appeng.me.helpers.IGridProxyable import appeng.util.item.AEItemStack import com.google.common.collect.ImmutableSet @@ -28,7 +30,6 @@ import li.cil.oc.util.DatabaseAccess import li.cil.oc.util.ExtendedArguments._ import li.cil.oc.util.ExtendedNBT._ import li.cil.oc.util.ResultWrapper._ -import net.minecraft.item.Item import net.minecraft.nbt.NBTTagCompound import net.minecraft.tileentity.TileEntity import net.minecraftforge.common.DimensionManager @@ -42,6 +43,7 @@ import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future import scala.language.existentials +//noinspection ScalaUnusedSymbol // Note to self: this class is used by ExtraCells (and potentially others), do not rename / drastically change it. trait NetworkControl[AETile >: Null <: TileEntity with IGridProxyable with IActionHost] { def tile: AETile @@ -54,12 +56,16 @@ trait NetworkControl[AETile >: Null <: TileEntity with IGridProxyable with IActi @Callback(doc = "function():table -- Get a list of tables representing the available CPUs in the network.") def getCpus(context: Context, args: Arguments): Array[AnyRef] = { val buffer = new mutable.ListBuffer[Map[String, Any]] + var index = 0 tile.getProxy.getCrafting.getCpus.foreach(cpu => { buffer.append(Map( "name" -> cpu.getName, "storage" -> cpu.getAvailableStorage, "coprocessors" -> cpu.getCoProcessors, - "busy" -> cpu.isBusy)) + "busy" -> cpu.isBusy, + "cpu" -> new Cpu(tile, index, cpu.asInstanceOf[CraftingCPUCluster]) + )) + index += 1 }) result(buffer.toArray) } @@ -141,7 +147,7 @@ trait NetworkControl[AETile >: Null <: TileEntity with IGridProxyable with IActi private def matches(stack: java.util.HashMap[String, AnyRef], filter: scala.collection.mutable.Map[String, AnyRef]): Boolean = { if (stack == null) return false filter.forall { - case (key: String, value: AnyRef) => { + case (key: String, value: AnyRef) => val stack_value = stack.get(key) value match { case number: Number => stack_value match { @@ -150,13 +156,13 @@ trait NetworkControl[AETile >: Null <: TileEntity with IGridProxyable with IActi } case any => any.toString.equals(stack_value.toString) } - } } } } object NetworkControl { + //noinspection ScalaUnusedSymbol class Craftable(var controller: TileEntity with IGridProxyable with IActionHost, var stack: IAEItemStack) extends AbstractValue with ICraftingRequester { def this() = this(null, null) @@ -164,25 +170,22 @@ object NetworkControl { // ----------------------------------------------------------------------- // - override def getRequestedJobs = ImmutableSet.copyOf(links.toIterable) + //noinspection RedundantCollectionConversion + override def getRequestedJobs: ImmutableSet[ICraftingLink] = ImmutableSet.copyOf(links.toIterable) override def jobStateChange(link: ICraftingLink) { links -= link } - // rv1 - def injectCratedItems(link: ICraftingLink, stack: IAEItemStack, p3: Actionable) = stack + override def injectCraftedItems(link: ICraftingLink, stack: IAEItemStack, p3: Actionable): IAEItemStack = stack - // rv2 - def injectCraftedItems(link: ICraftingLink, stack: IAEItemStack, p3: Actionable) = stack + override def getActionableNode: IGridNode = controller.getActionableNode - override def getActionableNode = controller.getActionableNode + override def getCableConnectionType(side: ForgeDirection): AECableType = controller.getCableConnectionType(side) - override def getCableConnectionType(side: ForgeDirection) = controller.getCableConnectionType(side) + override def securityBreak(): Unit = controller.securityBreak() - override def securityBreak() = controller.securityBreak() - - override def getGridNode(side: ForgeDirection) = controller.getGridNode(side) + override def getGridNode(side: ForgeDirection): IGridNode = controller.getGridNode(side) // ----------------------------------------------------------------------- // @@ -204,9 +207,9 @@ object NetworkControl { val future = craftingGrid.beginCraftingJob(controller.getWorldObj, controller.getProxy.getGrid, source, request, null) val prioritizePower = args.optBoolean(1, true) val cpuName = args.optString(2, "") - val cpu = if (!cpuName.isEmpty()) { + val cpu = if (!cpuName.isEmpty) { controller.getProxy.getCrafting.getCpus.collectFirst({ - case c if cpuName.equals(c.getName()) => c + case c if cpuName.equals(c.getName) => c }).orNull } else null @@ -240,19 +243,7 @@ object NetworkControl { 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.scheduleServer(() => { - val world = DimensionManager.getWorld(dimension) - val tileEntity = world.getTileEntity(x, y, z) - if (tileEntity != null && tileEntity.isInstanceOf[TileEntity with IGridProxyable with IActionHost]) { - controller = tileEntity.asInstanceOf[TileEntity with IGridProxyable with IActionHost] - } - }) - } + loadController(nbt, c => controller = c) links ++= nbt.getTagList("links", NBT.TAG_COMPOUND).map( (nbt: NBTTagCompound) => AEApi.instance.storage.loadCraftingLink(nbt, this)) } @@ -260,16 +251,83 @@ object NetworkControl { 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) - } + saveController(controller, nbt) nbt.setNewTagList("links", links.map(_.writeToNBT _)) } } + //noinspection ScalaUnusedSymbol + class Cpu(var controller: TileEntity with IGridProxyable, var index : Int, var cpu : CraftingCPUCluster) extends AbstractValue { + def this() = this(null, 0, null) + + @Callback(doc = "function():boolean -- Cancel this CPU current crafting job.") + def cancel(context: Context, args: Arguments): Array[AnyRef] = { + if (!getCpu.isBusy) + result(false) + else { + getCpu.cancel() + result(true) + } + } + + @Callback(doc = "function():boolean -- Is cpu active?") + def isActive(context: Context, args: Arguments): Array[AnyRef] = { + result(getCpu.isActive) + } + + @Callback(doc = "function():boolean -- Is cpu busy?") + def isBusy(context: Context, args: Arguments): Array[AnyRef] = { + result(getCpu.isBusy) + } + + @Callback(doc = "function():table -- Get currently crafted items.") + def activeItems(context: Context, args: Arguments): Array[AnyRef] = { + val list = AEApi.instance.storage.createItemList + getCpu.getListOfItem(list, CraftingItemList.ACTIVE) + result(list.map(item => convert(item, controller)).toArray) + } + + @Callback(doc = "function():table -- Get pending items.") + def pendingItems(context: Context, args: Arguments): Array[AnyRef] = { + val list = AEApi.instance.storage.createItemList + getCpu.getListOfItem(list, CraftingItemList.PENDING) + result(list.map(item => convert(item, controller)).toArray) + } + + @Callback(doc = "function():table -- Get stored items.") + def storedItems(context: Context, args: Arguments): Array[AnyRef] = { + val list = AEApi.instance.storage.createItemList + getCpu.getListOfItem(list, CraftingItemList.STORAGE) + result(list.map(item => convert(item, controller)).toArray) + } + private def getCpu = { + if (cpu == null && controller != null) { + var i = 0 + for (c <- controller.getProxy.getCrafting.getCpus) { + if (i == index) { + cpu = c.asInstanceOf[CraftingCPUCluster] + } + i += 1 + } + } + if (cpu == null) + throw new Exception("Broken CPU cluster") + cpu + } + + override def save(nbt: NBTTagCompound) { + super.save(nbt) + nbt.setInteger("index", index) + saveController(controller, nbt) + } + override def load(nbt: NBTTagCompound) { + super.load(nbt) + index = nbt.getInteger("index") + loadController(nbt, c => controller = c) + } + } + + //noinspection ScalaUnusedSymbol class CraftingStatus extends AbstractValue { private var isComputing = true private var link: Option[ICraftingLink] = None @@ -318,67 +376,62 @@ object NetworkControl { } } - class NetworkContents(var controller: TileEntity with IGridProxyable) extends AbstractValue with IMEMonitorHandlerReceiver[IAEItemStack] + //noinspection ConvertNullInitializerToUnderscore + class NetworkContents(var controller: TileEntity with IGridProxyable with IActionHost) extends AbstractValue with IMEMonitorHandlerReceiver[IAEItemStack] { def this() = this(null) if (controller != null) controller.getProxy.getStorage.getItemInventory.addListener(this, null) - var items : IItemList[IAEItemStack] = null - var i : java.util.Iterator[IAEItemStack] = null - var index = 0 + private var addedListener = true + private var items : IItemList[IAEItemStack] = null + private var itemIterator : java.util.Iterator[IAEItemStack] = null + private var index = 0 override def call(context: Context, arguments: Arguments): Array[AnyRef] = { - if (controller == null) return null + if (controller == null) + return null + if (!addedListener) { + controller.getProxy.getStorage.getItemInventory.addListener(this, null) + addedListener = true + } if (items == null) { items = controller.getProxy.getStorage.getItemInventory.getStorageList if (items != null) - i = items.iterator - if (i != null) + itemIterator = items.iterator + if (itemIterator != null) for (_ <- 1 to index) { - if (i.hasNext) - i.next + if (itemIterator.hasNext) + itemIterator.next } } - if (this.i == null && this.items != null) - this.i = items.iterator - if (!this.i.hasNext()) return null + if (this.itemIterator == null && this.items != null) + this.itemIterator = items.iterator + if (!this.itemIterator.hasNext) + return null index += 1 - Array[AnyRef](convert(i.next(), controller)) + Array[AnyRef](convert(itemIterator.next(), controller)) } + override def load(nbt: NBTTagCompound) { super.load(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") - index = nbt.getInteger("index") - EventHandler.scheduleServer(() => { - val tileEntity = DimensionManager.getWorld(dimension).getTileEntity(x, y, z) - if (tileEntity != null && tileEntity.isInstanceOf[TileEntity with IGridProxyable]) { - controller = tileEntity.asInstanceOf[TileEntity with IGridProxyable] - if (controller!= null) - controller.getProxy.getStorage.getItemInventory.addListener(this, null) - } - }) - } + addedListener = false + loadController(nbt, c => controller = c) } + override def save(nbt: NBTTagCompound) { super.save(nbt) nbt.setInteger("index", index) - 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) - } + saveController(controller, nbt) } - var valid = true - def dispose(context: Nothing): Unit = { + + private var valid = true + + override def dispose(context: Context): Unit = { valid = false } override def isValid(verificationToken: Any): Boolean = valid + override def onListUpdate(): Unit = { this.items = null } @@ -386,6 +439,7 @@ object NetworkControl { this.items = null } } + def aeCraftItem(aeItem: IAEItemStack, tile: TileEntity with IGridProxyable): IAEItemStack = { val patterns = tile.getProxy.getCrafting.getCraftingFor(aeItem, null, 0, tile.getWorldObj) patterns.find(pattern => pattern.getOutputs.exists(_.isSameType(aeItem))) match { @@ -400,6 +454,7 @@ object NetworkControl { else aeCraftItem(aeItem, tile) } + def convert(aeItem: IAEItemStack, tile: TileEntity with IGridProxyable): java.util.HashMap[String, AnyRef] = { def hashConvert(value: java.util.HashMap[_, _]) = { val hash = new java.util.HashMap[String, AnyRef] @@ -419,4 +474,29 @@ object NetworkControl { } null } + + private def loadController(nbt: NBTTagCompound, f : TileEntity with IGridProxyable with IActionHost => Unit ) : Unit = { + 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.scheduleServer(() => { + val world = DimensionManager.getWorld(dimension) + val tileEntity = world.getTileEntity(x, y, z) + if (tileEntity != null && tileEntity.isInstanceOf[TileEntity with IGridProxyable with IActionHost]) { + f(tileEntity.asInstanceOf[TileEntity with IGridProxyable with IActionHost]) + } + }) + } + } + + private def saveController(controller: TileEntity, nbt: NBTTagCompound): Unit = { + 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) + } + } } \ No newline at end of file