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
import com.bluepowermod.api.BPApi
import com.bluepowermod.api.wire.redstone.IBundledDevice
import cpw.mods.fml.common.Optional
import li.cil.oc.Settings
import li.cil.oc.integration.Mods
import li.cil.oc.integration.util.BundledRedstone
import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ExtendedWorld._
import mods.immibis.redlogic.api.wiring.IBundledEmitter
import mods.immibis.redlogic.api.wiring.IBundledUpdatable
import mods.immibis.redlogic.api.wiring.IInsulatedRedstoneWire
import mrtjp.projectred.api.IBundledTile
import mrtjp.projectred.api.ProjectRedAPI
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.nbt.NBTTagIntArray
import net.minecraftforge.common.util.Constants.NBT
@ -102,7 +99,7 @@ trait BundledRedstoneAware extends RedstoneAware with IBundledEmitter with IBund
override def updateRedstoneInput(side: ForgeDirection) {
super.updateRedstoneInput(side)
bundledInput(side, computeBundledInput(side))
bundledInput(side, BundledRedstone.computeBundledInput(position, side))
}
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() {
if (Mods.MineFactoryReloaded.isAvailable) {
for (side <- ForgeDirection.VALID_DIRECTIONS) {

View File

@ -1,20 +1,17 @@
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.relauncher.Side
import cpw.mods.fml.relauncher.SideOnly
import li.cil.oc.Settings
import li.cil.oc.integration.Mods
import li.cil.oc.integration.util.BundledRedstone
import li.cil.oc.server.{PacketSender => ServerPacketSender}
import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedWorld._
import mods.immibis.redlogic.api.wiring.IConnectable
import mods.immibis.redlogic.api.wiring.IRedstoneEmitter
import mods.immibis.redlogic.api.wiring.IRedstoneUpdatable
import mods.immibis.redlogic.api.wiring.IWire
import net.minecraft.init.Blocks
import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.common.util.ForgeDirection
@ -86,7 +83,7 @@ trait RedstoneAware extends RotationAware with IConnectable with IRedstoneEmitte
}
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 onRedstoneOutputEnabledChanged() {

View File

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

View File

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

View File

@ -1,12 +1,39 @@
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.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 initialize(): Unit = {
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
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 {
def isAvailable = Mods.RedLogic.isAvailable ||
Mods.MineFactoryReloaded.isAvailable ||
Mods.ProjectRedTransmission.isAvailable
val providers = mutable.Buffer.empty[RedstoneProvider]
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.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 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 initialize() {
@ -36,5 +42,16 @@ object ModVanilla extends ModProxy {
Driver.add(ConverterWorldProvider)
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
}