Reworked redstone logic to make it more modular.

This commit is contained in:
Florian Nücke 2015-04-27 21:16:41 +02:00
parent 4956271d62
commit 2886fdcd4d
9 changed files with 162 additions and 94 deletions

View File

@ -1,18 +1,15 @@
package li.cil.oc.common.tileentity.traits package li.cil.oc.common.tileentity.traits
import com.bluepowermod.api.BPApi
import com.bluepowermod.api.wire.redstone.IBundledDevice
import cpw.mods.fml.common.Optional import cpw.mods.fml.common.Optional
import li.cil.oc.Settings import li.cil.oc.Settings
import li.cil.oc.integration.Mods import li.cil.oc.integration.Mods
import li.cil.oc.integration.util.BundledRedstone
import li.cil.oc.util.BlockPosition import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedNBT._ import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ExtendedWorld._ import li.cil.oc.util.ExtendedWorld._
import mods.immibis.redlogic.api.wiring.IBundledEmitter import mods.immibis.redlogic.api.wiring.IBundledEmitter
import mods.immibis.redlogic.api.wiring.IBundledUpdatable import mods.immibis.redlogic.api.wiring.IBundledUpdatable
import mods.immibis.redlogic.api.wiring.IInsulatedRedstoneWire
import mrtjp.projectred.api.IBundledTile import mrtjp.projectred.api.IBundledTile
import mrtjp.projectred.api.ProjectRedAPI
import net.minecraft.nbt.NBTTagCompound import net.minecraft.nbt.NBTTagCompound
import net.minecraft.nbt.NBTTagIntArray import net.minecraft.nbt.NBTTagIntArray
import net.minecraftforge.common.util.Constants.NBT import net.minecraftforge.common.util.Constants.NBT
@ -102,7 +99,7 @@ trait BundledRedstoneAware extends RedstoneAware with IBundledEmitter with IBund
override def updateRedstoneInput(side: ForgeDirection) { override def updateRedstoneInput(side: ForgeDirection) {
super.updateRedstoneInput(side) super.updateRedstoneInput(side)
bundledInput(side, computeBundledInput(side)) bundledInput(side, BundledRedstone.computeBundledInput(position, side))
} }
override def readFromNBTForServer(nbt: NBTTagCompound) { override def readFromNBTForServer(nbt: NBTTagCompound) {
@ -143,55 +140,6 @@ trait BundledRedstoneAware extends RedstoneAware with IBundledEmitter with IBund
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
protected def computeBundledInput(side: ForgeDirection): Array[Int] = {
val redLogic = if (Mods.RedLogic.isAvailable) {
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 wire: IInsulatedRedstoneWire =>
var strength: Array[Int] = null
for (face <- -1 to 5 if wire.wireConnectsInDirection(face, side.ordinal())) {
if (strength == null) strength = Array.fill(16)(0)
strength(wire.getInsulatedWireColour) = math.max(strength(wire.getInsulatedWireColour), wire.getEmittedSignalStrength(face, side.ordinal()))
}
strength
case emitter: IBundledEmitter =>
var strength: Array[Int] = null
for (i <- -1 to 5 if strength == null) {
strength = Option(emitter.getBundledCableStrength(i, side.getOpposite.ordinal())).fold(null: Array[Int])(_.map(_ & 0xFF))
}
strength
case _ => null
}
else null
}
else null
val projectRed = if (Mods.ProjectRedTransmission.isAvailable) {
Option(ProjectRedAPI.transmissionAPI.getBundledInput(world, x, y, z, side.ordinal)).fold(null: Array[Int])(_.map(_ & 0xFF))
}
else null
val bluePower = if (Mods.BluePower.isAvailable) {
var strength: Array[Int] = null
ForgeDirection.values.map(BPApi.getInstance.getRedstoneApi.getBundledDevice(world, x + side.offsetX, y + side.offsetY, z + side.offsetY, _, ForgeDirection.UNKNOWN)).collect {
case device: IBundledDevice => Option(device.getBundledOutput(side.getOpposite)).foreach(inputs => {
if (strength == null) strength = Array.fill(16)(0)
for (color <- 0 until strength.length) {
strength(color) = math.max(strength(color), inputs(color) & 0xFF)
}
})
}
strength
}
else null
var result: Array[Int] = null
for (inputs <- Iterable(redLogic, projectRed, bluePower) if inputs != null) {
if (result == null) result = Array.fill(16)(0)
for (color <- 0 until result.length) {
result(color) = math.max(result(color), inputs(color))
}
}
result
}
override protected def onRedstoneOutputEnabledChanged() { override protected def onRedstoneOutputEnabledChanged() {
if (Mods.MineFactoryReloaded.isAvailable) { if (Mods.MineFactoryReloaded.isAvailable) {
for (side <- ForgeDirection.VALID_DIRECTIONS) { for (side <- ForgeDirection.VALID_DIRECTIONS) {

View File

@ -1,20 +1,17 @@
package li.cil.oc.common.tileentity.traits package li.cil.oc.common.tileentity.traits
import com.bluepowermod.api.BPApi
import com.bluepowermod.api.wire.redstone.IRedstoneDevice
import cpw.mods.fml.common.Optional import cpw.mods.fml.common.Optional
import cpw.mods.fml.relauncher.Side import cpw.mods.fml.relauncher.Side
import cpw.mods.fml.relauncher.SideOnly import cpw.mods.fml.relauncher.SideOnly
import li.cil.oc.Settings import li.cil.oc.Settings
import li.cil.oc.integration.Mods import li.cil.oc.integration.Mods
import li.cil.oc.integration.util.BundledRedstone
import li.cil.oc.server.{PacketSender => ServerPacketSender} import li.cil.oc.server.{PacketSender => ServerPacketSender}
import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedWorld._ import li.cil.oc.util.ExtendedWorld._
import mods.immibis.redlogic.api.wiring.IConnectable import mods.immibis.redlogic.api.wiring.IConnectable
import mods.immibis.redlogic.api.wiring.IRedstoneEmitter import mods.immibis.redlogic.api.wiring.IRedstoneEmitter
import mods.immibis.redlogic.api.wiring.IRedstoneUpdatable import mods.immibis.redlogic.api.wiring.IRedstoneUpdatable
import mods.immibis.redlogic.api.wiring.IWire import mods.immibis.redlogic.api.wiring.IWire
import net.minecraft.init.Blocks
import net.minecraft.nbt.NBTTagCompound import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.common.util.ForgeDirection import net.minecraftforge.common.util.ForgeDirection
@ -86,7 +83,7 @@ trait RedstoneAware extends RotationAware with IConnectable with IRedstoneEmitte
} }
def updateRedstoneInput(side: ForgeDirection) { def updateRedstoneInput(side: ForgeDirection) {
input(side, computeInput(side)) input(side, BundledRedstone.computeInput(position, side))
} }
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
@ -122,35 +119,6 @@ trait RedstoneAware extends RotationAware with IConnectable with IRedstoneEmitte
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
protected def computeInput(side: ForgeDirection) = {
val blockPos = BlockPosition(x, y, z).offset(side)
if (!world.blockExists(blockPos)) 0
else {
// See BlockRedstoneLogic.getInputStrength() for reference.
val vanilla = math.max(world.getIndirectPowerLevelTo(blockPos, side),
if (world.getBlock(blockPos) == Blocks.redstone_wire) world.getBlockMetadata(blockPos) else 0)
val redLogic = if (Mods.RedLogic.isAvailable) {
world.getTileEntity(blockPos) match {
case emitter: IRedstoneEmitter =>
var strength = 0
for (i <- -1 to 5) {
strength = math.max(strength, emitter.getEmittedSignalStrength(i, side.getOpposite.ordinal()))
}
strength
case _ => 0
}
}
else 0
val bluePower = if (Mods.BluePower.isAvailable) {
ForgeDirection.values.map(BPApi.getInstance.getRedstoneApi.getRedstoneDevice(world, x + side.offsetX, y + side.offsetY, z + side.offsetY, _, ForgeDirection.UNKNOWN)).collect {
case device: IRedstoneDevice => device.getRedstonePower(side.getOpposite) & 0xFF
}.padTo(1, 0).max
}
else 0
vanilla max redLogic max bluePower
}
}
protected def onRedstoneInputChanged(side: ForgeDirection, oldMaxValue: Int, newMaxValue: Int) {} protected def onRedstoneInputChanged(side: ForgeDirection, oldMaxValue: Int, newMaxValue: Int) {}
protected def onRedstoneOutputEnabledChanged() { protected def onRedstoneOutputEnabledChanged() {

View File

@ -20,7 +20,7 @@ trait TileEntity extends net.minecraft.tileentity.TileEntity {
def z = zCoord def z = zCoord
def position = BlockPosition(x, y, z) def position = BlockPosition(x, y, z, world)
def block = getBlockType def block = getBlockType

View File

@ -96,7 +96,9 @@ object Mods {
integration.ic2.ModIndustrialCraft2, integration.ic2.ModIndustrialCraft2,
integration.mfr.ModMineFactoryReloaded, integration.mfr.ModMineFactoryReloaded,
integration.mystcraft.ModMystcraft, integration.mystcraft.ModMystcraft,
integration.projectred.ModProjectRed,
integration.railcraft.ModRailcraft, integration.railcraft.ModRailcraft,
integration.redlogic.ModRedLogic,
integration.stargatetech2.ModStargateTech2, integration.stargatetech2.ModStargateTech2,
integration.thaumcraft.ModThaumcraft, integration.thaumcraft.ModThaumcraft,
integration.thermalexpansion.ModThermalExpansion, integration.thermalexpansion.ModThermalExpansion,

View File

@ -1,12 +1,39 @@
package li.cil.oc.integration.bluepower package li.cil.oc.integration.bluepower
import com.bluepowermod.api.BPApi
import com.bluepowermod.api.wire.redstone.IBundledDevice
import com.bluepowermod.api.wire.redstone.IRedstoneDevice
import li.cil.oc.integration.ModProxy import li.cil.oc.integration.ModProxy
import li.cil.oc.integration.Mods import li.cil.oc.integration.Mods
import li.cil.oc.integration.util.BundledRedstone
import li.cil.oc.integration.util.BundledRedstone.RedstoneProvider
import li.cil.oc.util.BlockPosition
import net.minecraftforge.common.util.ForgeDirection
object ModBluePower extends ModProxy { object ModBluePower extends ModProxy with RedstoneProvider {
override def getMod = Mods.BluePower override def getMod = Mods.BluePower
override def initialize(): Unit = { override def initialize(): Unit = {
RedstoneProvider.init() RedstoneProvider.init()
BundledRedstone.addProvider(this)
}
override def computeInput(pos: BlockPosition, side: ForgeDirection): Int = {
val world = pos.world.get
val (nx, ny, nz) = (pos.x + side.offsetX, pos.y + side.offsetY, pos.z + side.offsetZ)
ForgeDirection.values.map(BPApi.getInstance.getRedstoneApi.getRedstoneDevice(world, nx, ny, nz, _, ForgeDirection.UNKNOWN)).collect {
case device: IRedstoneDevice => device.getRedstonePower(side.getOpposite) & 0xFF
}.padTo(1, 0).max
}
def computeBundledInput(pos: BlockPosition, side: ForgeDirection): Array[Int] = {
val world = pos.world.get
val (nx, ny, nz) = (pos.x + side.offsetX, pos.y + side.offsetY, pos.z + side.offsetZ)
val inputs = ForgeDirection.values.map(BPApi.getInstance.getRedstoneApi.getBundledDevice(world, nx, ny, nz, _, ForgeDirection.UNKNOWN)).collect {
case device: IBundledDevice => Option(device.getBundledOutput(side.getOpposite)).fold(null: Array[Int])(_.map(_ & 0xFF))
}.filter(_ != null)
if (inputs.isEmpty) null
else inputs.reduce((a, b) => (a, b).zipped.map((l, r) => math.max(l, r)))
} }
} }

View File

@ -0,0 +1,24 @@
package li.cil.oc.integration.projectred
import li.cil.oc.integration.ModProxy
import li.cil.oc.integration.Mods
import li.cil.oc.integration.util.BundledRedstone
import li.cil.oc.integration.util.BundledRedstone.RedstoneProvider
import li.cil.oc.util.BlockPosition
import mrtjp.projectred.api.ProjectRedAPI
import net.minecraftforge.common.util.ForgeDirection
object ModProjectRed extends ModProxy with RedstoneProvider {
override def getMod = Mods.ProjectRedTransmission
override def initialize(): Unit = {
BundledRedstone.addProvider(this)
}
override def computeInput(pos: BlockPosition, side: ForgeDirection): Int = 0
def computeBundledInput(pos: BlockPosition, side: ForgeDirection): Array[Int] = {
Option(ProjectRedAPI.transmissionAPI.getBundledInput(pos.world.get, pos.x, pos.y, pos.z, side.ordinal)).
fold(null: Array[Int])(_.map(_ & 0xFF))
}
}

View File

@ -0,0 +1,53 @@
package li.cil.oc.integration.redlogic
import li.cil.oc.integration.ModProxy
import li.cil.oc.integration.Mods
import li.cil.oc.integration.util.BundledRedstone
import li.cil.oc.integration.util.BundledRedstone.RedstoneProvider
import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedWorld._
import mods.immibis.redlogic.api.wiring.IBundledEmitter
import mods.immibis.redlogic.api.wiring.IInsulatedRedstoneWire
import mods.immibis.redlogic.api.wiring.IRedstoneEmitter
import net.minecraftforge.common.util.ForgeDirection
object ModRedLogic extends ModProxy with RedstoneProvider {
override def getMod = Mods.RedLogic
override def initialize(): Unit = {
BundledRedstone.addProvider(this)
}
override def computeInput(pos: BlockPosition, side: ForgeDirection): Int = {
pos.world.get.getTileEntity(pos) match {
case emitter: IRedstoneEmitter =>
var strength = 0
for (i <- -1 to 5) {
strength = math.max(strength, emitter.getEmittedSignalStrength(i, side.getOpposite.ordinal()))
}
strength
case _ => 0
}
}
def computeBundledInput(pos: BlockPosition, side: ForgeDirection): Array[Int] = {
val world = pos.world.get
val npos = pos.offset(side)
world.getTileEntity(npos) match {
case wire: IInsulatedRedstoneWire =>
var strength: Array[Int] = null
for (face <- -1 to 5 if wire.wireConnectsInDirection(face, side.ordinal())) {
if (strength == null) strength = Array.fill(16)(0)
strength(wire.getInsulatedWireColour) = math.max(strength(wire.getInsulatedWireColour), wire.getEmittedSignalStrength(face, side.ordinal()))
}
strength
case emitter: IBundledEmitter =>
var strength: Array[Int] = null
for (i <- -1 to 5 if strength == null) {
strength = Option(emitter.getBundledCableStrength(i, side.getOpposite.ordinal())).fold(null: Array[Int])(_.map(_ & 0xFF))
}
strength
case _ => null
}
}
}

View File

@ -1,9 +1,38 @@
package li.cil.oc.integration.util package li.cil.oc.integration.util
import li.cil.oc.integration.Mods import li.cil.oc.integration.Mods
import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedWorld._
import net.minecraftforge.common.util.ForgeDirection
import scala.collection.mutable
object BundledRedstone { object BundledRedstone {
def isAvailable = Mods.RedLogic.isAvailable || val providers = mutable.Buffer.empty[RedstoneProvider]
Mods.MineFactoryReloaded.isAvailable ||
Mods.ProjectRedTransmission.isAvailable def addProvider(provider: RedstoneProvider): Unit = providers += provider
def isAvailable = Mods.MineFactoryReloaded.isAvailable || providers.length > 0
def computeInput(pos: BlockPosition, side: ForgeDirection): Int = {
if (pos.world.get.blockExists(pos.offset(side)))
providers.map(_.computeInput(pos, side)).padTo(1, 0).max
else 0
}
def computeBundledInput(pos: BlockPosition, side: ForgeDirection): Array[Int] = {
if (pos.world.get.blockExists(pos.offset(side))) {
val inputs = providers.map(_.computeBundledInput(pos, side)).filter(_ != null)
if (inputs.isEmpty) null
else inputs.reduce((a, b) => (a, b).zipped.map((l, r) => math.max(l, r)))
}
else null
}
trait RedstoneProvider {
def computeInput(pos: BlockPosition, side: ForgeDirection): Int
def computeBundledInput(pos: BlockPosition, side: ForgeDirection): Array[Int]
}
} }

View File

@ -4,8 +4,14 @@ import li.cil.oc.Settings
import li.cil.oc.api.Driver import li.cil.oc.api.Driver
import li.cil.oc.integration.ModProxy import li.cil.oc.integration.ModProxy
import li.cil.oc.integration.Mods import li.cil.oc.integration.Mods
import li.cil.oc.integration.util.BundledRedstone
import li.cil.oc.integration.util.BundledRedstone.RedstoneProvider
import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedWorld._
import net.minecraft.init.Blocks
import net.minecraftforge.common.util.ForgeDirection
object ModVanilla extends ModProxy { object ModVanilla extends ModProxy with RedstoneProvider {
def getMod = Mods.Minecraft def getMod = Mods.Minecraft
def initialize() { def initialize() {
@ -36,5 +42,16 @@ object ModVanilla extends ModProxy {
Driver.add(ConverterWorldProvider) Driver.add(ConverterWorldProvider)
RecipeHandler.init() RecipeHandler.init()
BundledRedstone.addProvider(this)
} }
override def computeInput(pos: BlockPosition, side: ForgeDirection): Int = {
val world = pos.world.get
// See BlockRedstoneLogic.getInputStrength() for reference.
math.max(world.getIndirectPowerLevelTo(pos, side),
if (world.getBlock(pos) == Blocks.redstone_wire) world.getBlockMetadata(pos) else 0)
}
override def computeBundledInput(pos: BlockPosition, side: ForgeDirection): Array[Int] = null
} }