From 2886fdcd4dee60ffdb79a115a1db48e9e6a985bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Mon, 27 Apr 2015 21:16:41 +0200 Subject: [PATCH] Reworked redstone logic to make it more modular. --- .../traits/BundledRedstoneAware.scala | 56 +------------------ .../tileentity/traits/RedstoneAware.scala | 36 +----------- .../common/tileentity/traits/TileEntity.scala | 2 +- .../scala/li/cil/oc/integration/Mods.scala | 2 + .../integration/bluepower/ModBluePower.scala | 29 +++++++++- .../projectred/ModProjectRed.scala | 24 ++++++++ .../oc/integration/redlogic/ModRedLogic.scala | 53 ++++++++++++++++++ .../oc/integration/util/BundledRedstone.scala | 35 +++++++++++- .../oc/integration/vanilla/ModVanilla.scala | 19 ++++++- 9 files changed, 162 insertions(+), 94 deletions(-) create mode 100644 src/main/scala/li/cil/oc/integration/projectred/ModProjectRed.scala create mode 100644 src/main/scala/li/cil/oc/integration/redlogic/ModRedLogic.scala diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/BundledRedstoneAware.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/BundledRedstoneAware.scala index 7f451a55c..d8c7f030f 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/traits/BundledRedstoneAware.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/traits/BundledRedstoneAware.scala @@ -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) { diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/RedstoneAware.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/RedstoneAware.scala index ac403a1f0..3ba0f4cd5 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/traits/RedstoneAware.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/traits/RedstoneAware.scala @@ -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() { diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/TileEntity.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/TileEntity.scala index e01b6d788..9b6dfd2fc 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/traits/TileEntity.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/traits/TileEntity.scala @@ -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 diff --git a/src/main/scala/li/cil/oc/integration/Mods.scala b/src/main/scala/li/cil/oc/integration/Mods.scala index d6bb28040..9b50bf26f 100644 --- a/src/main/scala/li/cil/oc/integration/Mods.scala +++ b/src/main/scala/li/cil/oc/integration/Mods.scala @@ -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, diff --git a/src/main/scala/li/cil/oc/integration/bluepower/ModBluePower.scala b/src/main/scala/li/cil/oc/integration/bluepower/ModBluePower.scala index b24297d65..c97251e24 100644 --- a/src/main/scala/li/cil/oc/integration/bluepower/ModBluePower.scala +++ b/src/main/scala/li/cil/oc/integration/bluepower/ModBluePower.scala @@ -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))) } } diff --git a/src/main/scala/li/cil/oc/integration/projectred/ModProjectRed.scala b/src/main/scala/li/cil/oc/integration/projectred/ModProjectRed.scala new file mode 100644 index 000000000..b2982427a --- /dev/null +++ b/src/main/scala/li/cil/oc/integration/projectred/ModProjectRed.scala @@ -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)) + } +} diff --git a/src/main/scala/li/cil/oc/integration/redlogic/ModRedLogic.scala b/src/main/scala/li/cil/oc/integration/redlogic/ModRedLogic.scala new file mode 100644 index 000000000..a762a2f5b --- /dev/null +++ b/src/main/scala/li/cil/oc/integration/redlogic/ModRedLogic.scala @@ -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 + } + } +} diff --git a/src/main/scala/li/cil/oc/integration/util/BundledRedstone.scala b/src/main/scala/li/cil/oc/integration/util/BundledRedstone.scala index 2502881dc..de3983539 100644 --- a/src/main/scala/li/cil/oc/integration/util/BundledRedstone.scala +++ b/src/main/scala/li/cil/oc/integration/util/BundledRedstone.scala @@ -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] + } + } diff --git a/src/main/scala/li/cil/oc/integration/vanilla/ModVanilla.scala b/src/main/scala/li/cil/oc/integration/vanilla/ModVanilla.scala index a1916d1be..93dddf5a8 100644 --- a/src/main/scala/li/cil/oc/integration/vanilla/ModVanilla.scala +++ b/src/main/scala/li/cil/oc/integration/vanilla/ModVanilla.scala @@ -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 }