Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ dependencies {
shadowImplementation name: 'OC-JNLua-Natives', version: '20220928.1', ext: 'jar'

api("com.github.GTNewHorizons:AE2FluidCraft-Rework:1.5.95-gtnh:dev")
api("com.github.GTNewHorizons:Applied-Energistics-2-Unofficial:rv3-beta-999-GTNH:dev")
api("com.github.GTNewHorizons:Applied-Energistics-2-Unofficial:rv3-beta-1006-GTNH:dev")
implementation("com.github.GTNewHorizons:GTNHLib:0.11.24:dev") {transitive = false}

compileOnly("com.github.GTNewHorizons:Angelica:2.1.52:api") {transitive = false}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ object ConverterPattern extends Converter {
output += "inputs" -> inputs
output += "outputs" -> outputs
output += "isCraftable" -> Boolean.box(encodedValue.getBoolean("crafting"))
output += "substitute" -> Boolean.box(encodedValue.getBoolean("substitute"))
output += "beSubstitute" -> Boolean.box(encodedValue.getBoolean("beSubstitute"))
}
} catch {
case ignored: Throwable =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import appeng.api.parts.IPartHost
import appeng.api.util.{DimensionalCoord, IInterfaceViewable}
import appeng.parts.AEBasePart
import appeng.parts.p2p.PartP2PTunnel
import appeng.parts.reporting.PartInterfaceTerminal
import appeng.parts.reporting.{PartInterfaceTerminal, PartPatternTerminal}
import appeng.util.inv.WrapperInvSlot
import li.cil.oc.api.driver
import li.cil.oc.api.driver.{EnvironmentProvider, NamedBlock}
import li.cil.oc.api.machine.{Arguments, Callback, Context}
Expand All @@ -20,7 +21,7 @@ import net.minecraftforge.common.util.Constants.NBT
import net.minecraftforge.common.util.ForgeDirection

import java.util
import scala.collection.JavaConversions.asScalaSet
import scala.collection.JavaConversions.asScalaIterator
import scala.collection.JavaConverters._
import scala.collection.mutable

Expand Down Expand Up @@ -111,7 +112,7 @@ object DriverPartInterfaceTerminal extends driver.SidedBlock {
case _ => ForgeDirection.UNKNOWN
}
val slot: Integer = args.get("slot") match {
case value: java.lang.Number => value.intValue
case value: java.lang.Number => value.intValue - 1
case _ => -1
}
TransferData(location, side)(slot)
Expand All @@ -121,16 +122,13 @@ object DriverPartInterfaceTerminal extends driver.SidedBlock {
private case class TransferTask(source: TransferData, target: TransferData)

private def findMachines(targets: Array[TransferData]) = {
val result = mutable.Map[TransferData, IInterfaceViewable]()
val it = allMachines.iterator
val result = mutable.Map[TransferData, PatternContainer]()
val it = allMachines

while (it.hasNext && result.size < targets.length) {
val machine = it.next()
val location = machine.getLocation
val side = machine match {
case part: AEBasePart => part.getSide
case _ => ForgeDirection.UNKNOWN
}
val side = machine.getSide
targets.find(t => t.location == location && t.side == side).foreach { matchedData =>
result(matchedData) = machine
}
Expand Down Expand Up @@ -177,18 +175,28 @@ object DriverPartInterfaceTerminal extends driver.SidedBlock {
}.toArray
}

private def allMachines: Iterable[IInterfaceViewable] = {
private def allMachines: Iterator[PatternContainer] = {
val grid = getGrid
if (grid == null) return Array.empty[IInterfaceViewable]
AEApi.instance().registries().interfaceTerminal().getSupportedClasses.view
.flatMap(c => grid.getMachines(c).asScala)
.map(_.getMachine.asInstanceOf[IInterfaceViewable])
.filter { m =>
m.shouldDisplay && (m match {
case p: PartP2PTunnel[_] => !p.isOutput
case _ => true
})
}
if (grid == null) {
Iterator.empty
}
else {
val interfaces = AEApi.instance().registries().interfaceTerminal().getSupportedClasses.iterator
.flatMap(c => grid.getMachines(c).asScala)
.map(_.getMachine)
.collect {
case m: IInterfaceViewable if m.shouldDisplay && (m match {
case p: PartP2PTunnel[_] => !p.isOutput
case _ => true
}) => new InterfaceAdapter(m)
}
val patternTerminals = grid.getMachines(classOf[PartPatternTerminal]).asScala.iterator
.map(_.getMachine)
.collect {
case t: PartPatternTerminal => new PatternTerminalAdapter(t)
}
interfaces ++ patternTerminals
}
}

private def getGrid = part.getActionableNode.getGrid
Expand All @@ -201,8 +209,47 @@ object DriverPartInterfaceTerminal extends driver.SidedBlock {
else null
}

class InterfaceViewableArrayValue(it: Iterable[IInterfaceViewable]) extends AbstractValue {
def this() = this(Iterable.empty)
trait PatternContainer {
def getName: String

def getPatterns: IInventory

def numSlots: Int

def getLocation: DimensionalCoord

def getSide: ForgeDirection
}

private class InterfaceAdapter(val machine: IInterfaceViewable) extends PatternContainer {
override def getName: String = machine.getName

override def getPatterns: IInventory = machine.getPatterns

override def numSlots: Int = machine.numSlots

override def getLocation: DimensionalCoord = machine.getLocation

override def getSide: ForgeDirection = machine match {
case part: AEBasePart => part.getSide
case _ => ForgeDirection.UNKNOWN
}
}

private class PatternTerminalAdapter(val terminal: PartPatternTerminal) extends PatternContainer {
override def getName: String = terminal.getCustomName

override def getPatterns: IInventory = new WrapperInvSlot(terminal.getInventoryByName("pattern")).getWrapper(1)

override def numSlots: Int = 1

override def getLocation: DimensionalCoord = terminal.getLocation

override def getSide: ForgeDirection = terminal.getSide
}

private class InterfaceViewableArrayValue(it: Iterator[PatternContainer]) extends AbstractValue {
def this() = this(Iterator.empty)

private case class InterfaceViewableInfo(name: String, location: DimensionalCoord, side: ForgeDirection, patterns: Array[ItemStack])

Expand All @@ -212,7 +259,7 @@ object DriverPartInterfaceTerminal extends driver.SidedBlock {
"name" -> info.name,
"location" -> info.location,
"side" -> info.side,
"patterns" -> info.patterns.zipWithIndex.map(_.swap).toMap
"patterns" -> info.patterns.zipWithIndex.map { case (pattern, id) => (id + 1, pattern) }.toMap
)
} else {
Map(
Expand All @@ -226,12 +273,9 @@ object DriverPartInterfaceTerminal extends driver.SidedBlock {
private var array = it.map { machine =>
val name = machine.getName
val location = machine.getLocation
val side = machine match {
case part: AEBasePart => part.getSide
case _ => ForgeDirection.UNKNOWN
}
val side = machine.getSide
val patterns = machine.getPatterns
val patternsArray = Array.tabulate(machine.rows() * machine.rowSize()) { index =>
val patternsArray = Array.tabulate(machine.numSlots) { index =>
val stack = patterns.getStackInSlot(index)
if (stack == null) null else stack.copy()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
package li.cil.oc.integration.appeng

import appeng.api.parts.IPatternTerminal.PatternEncodeListener
import appeng.api.parts.{IPartHost, IPatternTerminal}
import appeng.api.storage.StorageName
import appeng.parts.reporting.PartPatternTerminal
import li.cil.oc.api.driver
import li.cil.oc.api.driver.NamedBlock
import li.cil.oc.api.machine.{Arguments, Callback, Context}
import li.cil.oc.api.network.{ManagedEnvironment, Node}
import li.cil.oc.integration.ManagedTileEntityEnvironment
import li.cil.oc.integration.appeng.internal.PartTerminalPatternEnvironment
import li.cil.oc.server.driver.Registry
import li.cil.oc.util.ExtendedArguments.extendedArguments
import li.cil.oc.util.ResultWrapper.result
import net.minecraft.item.ItemStack
import net.minecraft.world.World
import net.minecraftforge.common.util.ForgeDirection

import scala.collection.mutable
import scala.reflect.ClassTag

object DriverPartPatternTerminal extends driver.SidedBlock {
override def worksWith(world: World, x: Int, y: Int, z: Int, side: ForgeDirection): Boolean =
world.getTileEntity(x, y, z) match {
case container: IPartHost => ForgeDirection.VALID_DIRECTIONS.map(container.getPart).exists(_.isInstanceOf[PartPatternTerminal])
case _ => false
}

override def createEnvironment(world: World, x: Int, y: Int, z: Int, side: ForgeDirection): ManagedEnvironment = {
val host = world.getTileEntity(x, y, z).asInstanceOf[IPartHost]
new Environment(host)
}

final class Environment(val host: IPartHost)(implicit val tag: ClassTag[PartPatternTerminal]) extends ManagedTileEntityEnvironment[IPartHost](host, "me_pattern_terminal") with NamedBlock with PartTerminalPatternEnvironment[PartPatternTerminal] {
override def preferredName = "me_pattern_terminal"

override def priority = 0

private val listeners = mutable.ArrayBuffer[(PartPatternTerminal, PatternEncodeListener)]()
private def bindListeners(): Unit = {
unbindListeners()
val location = Registry.convert(result(host.getLocation))
ForgeDirection.VALID_DIRECTIONS.foreach { side =>
host.getPart(side) match {
case part: PartPatternTerminal =>
val listener = new PatternEncodeListener {
override def onEncoded(terminal: IPatternTerminal, pattern: ItemStack): Unit = {
val args: Array[AnyRef] = Array.concat(result("me_pattern_encoded"), location, result(side.ordinal))
node.sendToReachable("computer.signal", args: _*)
}
}
part.addPatternEncodeListeners(listener)
listeners += ((part, listener))
case _ =>
}
}
}
private def unbindListeners(): Unit = {
listeners.foreach { case (part, listener) =>
part.removePatternEncodeListeners(listener)
}
listeners.clear()
}
override def onConnect(node: Node): Unit = {
super.onConnect(node)
if (node == this.node) {
bindListeners()
}
}

override def onDisconnect(node: Node): Unit = {
super.onDisconnect(node)
if (node == this.node) {
unbindListeners()
}
}

@Callback(doc = "function(side:number):boolean -- Return crafting mode.")
def isCraftingMode(context: Context, args: Arguments): Array[AnyRef] = {
val part = getPart(args.checkSideAny(0))
result(part.isCraftingRecipe)
}

@Callback(doc = "function(side:number, mode:boolean) -- Set crafting mode.")
def setCraftingMode(context: Context, args: Arguments): Array[AnyRef] = {
val part = getPart(args.checkSideAny(0))
part.setCraftingRecipe(args.checkBoolean(1))
result(null)
}

@Callback(doc = "function(side:number):boolean -- Return substitution state.")
def isSubstitution(context: Context, args: Arguments): Array[AnyRef] = {
val part = getPart(args.checkSideAny(0))
result(part.isSubstitution)
}

@Callback(doc = "function(side:number, mode:boolean) -- Set if substitution.")
def setSubstitution(context: Context, args: Arguments): Array[AnyRef] = {
val part = getPart(args.checkSideAny(0))
part.setSubstitution(args.checkBoolean(1))
result(null)
}

@Callback(doc = "function(side:number):boolean -- Return canBeSubstitution state.")
def isCanBeSubstitution(context: Context, args: Arguments): Array[AnyRef] = {
val part = getPart(args.checkSideAny(0))
result(part.canBeSubstitution)
}

@Callback(doc = "function(side:number, mode:boolean) -- Set if canBeSubstitution.")
def setCanBeSubstitution(context: Context, args: Arguments): Array[AnyRef] = {
val part = getPart(args.checkSideAny(0))
part.setCanBeSubstitution(args.checkBoolean(1))
result(null)
}

@Callback(doc = "function(side:number, index:number[, detail:table, type:string]):boolean -- Set the pattern input.")
def setInterfacePatternInput(context: Context, args: Arguments): Array[AnyRef] =
setPatternSlot(context, args, "in")

@Callback(doc = "function(side:number, index:number[, detail:table, type:string]):boolean -- Set the pattern input.")
def setInterfacePatternOutput(context: Context, args: Arguments): Array[AnyRef] =
setPatternSlot(context, args, "out")

@Callback(doc = "function(side:number, index:number):boolean -- Get the terminal pattern input stack.")
def getTerminalPatternInput(context: Context, args: Arguments): Array[AnyRef] = {
val part = getPart(args.checkSideAny(0))
val index = args.checkInteger(1)
val inv = part.getAEInventoryByName(StorageName.CRAFTING_INPUT)
result(inv.getAEStackInSlot(index))
}

@Callback(doc = "function(side:number, index:number[, detail:table, type:string]):boolean -- Set the terminal pattern input stack.")
def setTerminalPatternInput(context: Context, args: Arguments): Array[AnyRef] = {
val part = getPart(args.checkSideAny(0))
val index = args.checkInteger(1) - 1
val stack = getAEStack(context, args, 0)
val inv = part.getAEInventoryByName(StorageName.CRAFTING_INPUT)
inv.putAEStackInSlot(index, stack)
result(null)
}

@Callback(doc = "function(side:number, index:number):boolean -- Get the terminal pattern output stack.")
def getTerminalPatternOutput(context: Context, args: Arguments): Array[AnyRef] = {
val part = getPart(args.checkSideAny(0))
val index = args.checkInteger(1)
val inv = part.getAEInventoryByName(StorageName.CRAFTING_OUTPUT)
result(inv.getAEStackInSlot(index))
}

@Callback(doc = "function(side:number):table -- Get the pattern in the terminal.")
def getTerminalPattern(context: Context, args: Arguments): Array[AnyRef] = {
val inv = getPatternInventory(context, args)
val stack = inv.getStackInSlot(1)
result(stack)
}

@Callback(doc = "function(side:number, index:number[, detail:table, type:string]):boolean -- Set the terminal pattern input stack.")
def setTerminalPatternOutput(context: Context, args: Arguments): Array[AnyRef] = {
val part = getPart(args.checkSideAny(0))
val index = args.checkInteger(1) - 1
val stack = getAEStack(context, args, 0)
val inv = part.getAEInventoryByName(StorageName.CRAFTING_OUTPUT)
inv.putAEStackInSlot(index, stack)
result(null)
}

@Callback(doc = "function(side:number):boolean -- Encode pattern.")
def encode(context: Context, args: Arguments): Array[AnyRef] = {
val part = getPart(args.checkSideAny(0))
result(part.encode(part.getCustomName, host.getTile.getWorldObj))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ object ModAppEng extends ModProxy {
Driver.add(DriverStorageBus)
Driver.add(DriverPartInterface)
Driver.add(DriverPartInterfaceTerminal)
Driver.add(DriverPartPatternTerminal)
Driver.add(DriverBlockInterface)
Driver.add(DriverUpgradeAE)

Expand Down
Loading