From fe7e743f55a05d82cff88bfd6c65ae9d8d3933a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Tue, 26 Aug 2014 18:29:26 +0200 Subject: [PATCH] Made cables dyeable and made them not connect when of different colors (except for light gray, the default color, which connects to all other colors). Closes #517. --- .../textures/blocks/CablePart.png | Bin 295 -> 304 bytes .../li/cil/oc/client/PacketHandler.scala | 2 +- .../scala/li/cil/oc/common/block/Cable.scala | 31 +++++++- .../li/cil/oc/common/block/Delegator.scala | 16 +++- .../cil/oc/common/multipart/CablePart.scala | 75 +++++++++++++++++- .../cil/oc/common/multipart/MultiPart.scala | 2 +- .../li/cil/oc/common/tileentity/Cable.scala | 12 ++- .../oc/common/tileentity/traits/Colored.scala | 2 +- .../li/cil/oc/server/network/Network.scala | 32 ++++++-- 9 files changed, 153 insertions(+), 19 deletions(-) diff --git a/src/main/resources/assets/opencomputers/textures/blocks/CablePart.png b/src/main/resources/assets/opencomputers/textures/blocks/CablePart.png index e80dde348ed37e905ca6c4a92b57b14cdb9ab4a5..c9a9df32161c5f3e62718c0876d2fc4471e468a0 100644 GIT binary patch delta 239 zcmV!ma&mHcd3kVfaC&-r zdwY9tZ*OjHZhU-vRpg}-0001)Nkln6>P;$o>>5bXT zJL0~7J2(}6nqxT&DdRkYSrX1NG@6^6h!*Y7YkMXQ-oOQKFU7}d84uV2t0V7&^hv<) pxJIS@`C9PM*Mi-7J;zso0RRc$1J;}+R=ofK002ovPDHLkV1lM^X?g$v delta 230 zcmV false } - private def canConnectFromSide(tileEntity: TileEntity, side: ForgeDirection) = + private def cableColor(tileEntity: TileEntity) = + tileEntity match { + case cable: tileentity.Cable => cable.color + case _ => + if (Mods.ForgeMultipart.isAvailable) cableColorFMP(tileEntity) + else Color.LightGray + } + + private def cableColorFMP(tileEntity: TileEntity) = + tileEntity match { + case host: TileMultipart => (host.partList collect { + case cable: CablePart => cable.color + }).headOption.getOrElse(Color.LightGray) + case _ => Color.LightGray + } + + private def canConnectBasedOnColor(te1: TileEntity, te2: TileEntity) = { + val (c1, c2) = (cableColor(te1), cableColor(te2)) + c1 == c2 || c1 == Color.LightGray || c2 == Color.LightGray + } + + private def canConnectFromSideFMP(tileEntity: TileEntity, side: ForgeDirection) = tileEntity match { case host: TileMultipart => host.partList.forall { diff --git a/src/main/scala/li/cil/oc/common/block/Delegator.scala b/src/main/scala/li/cil/oc/common/block/Delegator.scala index 1f7147a7e..1d0b19384 100644 --- a/src/main/scala/li/cil/oc/common/block/Delegator.scala +++ b/src/main/scala/li/cil/oc/common/block/Delegator.scala @@ -33,6 +33,9 @@ class Delegator[Child <: Delegate](id: Int) extends Block(id, Material.iron) { // For Immibis Microblock support. val ImmibisMicroblocks_TransformableBlockMarker = null + // For FMP part coloring. + var colorMultiplierOverride: Option[Int] = None + // ----------------------------------------------------------------------- // // SubBlock // ----------------------------------------------------------------------- // @@ -214,6 +217,15 @@ class Delegator[Child <: Delegate](id: Int) extends Block(id, Material.iron) { case _ => false } + override def recolourBlock(world: World, x: Int, y: Int, z: Int, side: ForgeDirection, colour: Int) = + world.getBlockTileEntity(x, y, z) match { + case colored: Colored if colored.color != colour => + colored.color = colour + world.markBlockForUpdate(x, y, z) + false // Don't consume items. + case _ => super.recolourBlock(world, x, y, z, side, colour) + } + // ----------------------------------------------------------------------- // override def canConnectRedstone(world: IBlockAccess, x: Int, y: Int, z: Int, side: Int) = @@ -393,10 +405,10 @@ class Delegator[Child <: Delegate](id: Int) extends Block(id, Material.iron) { @SideOnly(Side.CLIENT) override def colorMultiplier(world: IBlockAccess, x: Int, y: Int, z: Int) = - subBlock(world, x, y, z) match { + colorMultiplierOverride.getOrElse(subBlock(world, x, y, z) match { case Some(subBlock) => subBlock.color(world, x, y, z) case _ => super.colorMultiplier(world, x, y, z) - } + }) @SideOnly(Side.CLIENT) override def getIcon(side: Int, metadata: Int) = diff --git a/src/main/scala/li/cil/oc/common/multipart/CablePart.scala b/src/main/scala/li/cil/oc/common/multipart/CablePart.scala index 921365b75..8208dbe9d 100644 --- a/src/main/scala/li/cil/oc/common/multipart/CablePart.scala +++ b/src/main/scala/li/cil/oc/common/multipart/CablePart.scala @@ -1,5 +1,6 @@ package li.cil.oc.common.multipart +import codechicken.lib.data.{MCDataInput, MCDataOutput} import codechicken.lib.lighting.LazyLightMatrix import codechicken.lib.vec.{Cuboid6, Vector3} import codechicken.multipart._ @@ -8,18 +9,44 @@ import li.cil.oc.api.network.{Message, Node, Visibility} import li.cil.oc.api.{Items, network} import li.cil.oc.client.renderer.block.BlockRenderer import li.cil.oc.common.block.{Cable, Delegator} +import li.cil.oc.common.tileentity +import li.cil.oc.util.Color import li.cil.oc.util.ExtendedNBT._ import li.cil.oc.{Settings, api, common} import net.minecraft.client.Minecraft +import net.minecraft.entity.player.EntityPlayer +import net.minecraft.item.ItemStack import net.minecraft.nbt.NBTTagCompound -import net.minecraft.util.AxisAlignedBB +import net.minecraft.util.{MovingObjectPosition, AxisAlignedBB} import scala.collection.convert.WrapAsJava import scala.collection.convert.WrapAsScala._ -class CablePart(val original: Option[Node] = None) extends DelegatePart with TCuboidPart with TNormalOcclusion with network.Environment { +class CablePart(val original: Option[tileentity.Cable] = None) extends DelegatePart with TCuboidPart with TNormalOcclusion with network.Environment { val node = api.Network.newNode(this, Visibility.None).create() + private var _color = 0 + + original.foreach(cable => _color = cable.color) + + // ----------------------------------------------------------------------- // + + def color = _color + + def color_=(value: Int) = if (value != _color) { + _color = value + onColorChanged() + } + + protected def onColorChanged() { + if (world != null && !world.isRemote) { + sendDescUpdate() + api.Network.joinOrCreateNetwork(tile) + } + } + + // ----------------------------------------------------------------------- // + override def delegate = Delegator.subBlock(Items.get("cable").createItemStack(1)).get def getType = Settings.namespace + "cable" @@ -32,9 +59,22 @@ class CablePart(val original: Option[Node] = None) extends DelegatePart with TCu override def getRenderBounds = new Cuboid6(Cable.bounds(world, x, y, z).offset(x, y, z)) + // ----------------------------------------------------------------------- // + + override def activate(player: EntityPlayer, hit: MovingObjectPosition, item: ItemStack) = { + if (Color.isDye(player.getHeldItem)) { + color = Color.dyeColor(player.getHeldItem) + tile.markDirty() + true + } + else super.activate(player, hit, item) + } + + // ----------------------------------------------------------------------- // + override def invalidateConvertedTile() { super.invalidateConvertedTile() - original.foreach(_.neighbors.foreach(_.connect(this.node))) + original.foreach(_.node.neighbors.foreach(_.connect(this.node))) } override def onPartChanged(part: TMultiPart) { @@ -52,9 +92,14 @@ class CablePart(val original: Option[Node] = None) extends DelegatePart with TCu Option(node).foreach(_.remove) } + // ----------------------------------------------------------------------- // + override def load(nbt: NBTTagCompound) { super.load(nbt) node.load(nbt.getCompoundTag(Settings.namespace + "node")) + if (nbt.hasKey(Settings.namespace + "renderColor")) { + _color = nbt.getInteger(Settings.namespace + "renderColor") + } } override def save(nbt: NBTTagCompound) { @@ -63,17 +108,39 @@ class CablePart(val original: Option[Node] = None) extends DelegatePart with TCu if (node != null) { nbt.setNewCompoundTag(Settings.namespace + "node", node.save) } + nbt.setInteger(Settings.namespace + "renderColor", _color) } + override def readDesc(packet: MCDataInput) { + super.readDesc(packet) + _color = packet.readInt() + } + + override def writeDesc(packet: MCDataOutput) { + super.writeDesc(packet) + packet.writeInt(_color) + } + + // ----------------------------------------------------------------------- // + @SideOnly(Side.CLIENT) override def renderStatic(pos: Vector3, olm: LazyLightMatrix, pass: Int) { val (x, y, z) = (pos.x.toInt, pos.y.toInt, pos.z.toInt) val block = api.Items.get("cable").block() val metadata = world.getBlockMetadata(x, y, z) val renderer = Minecraft.getMinecraft.renderGlobal.globalRenderBlocks - BlockRenderer.renderCable(Cable.neighbors(world, x, y, z), block, metadata, x, y, z, renderer) + block match { + case delegator: Delegator[_] => + delegator.colorMultiplierOverride = Some(_color) + BlockRenderer.renderCable(Cable.neighbors(world, x, y, z), block, metadata, x, y, z, renderer) + delegator.colorMultiplierOverride = None + case _ => + BlockRenderer.renderCable(Cable.neighbors(world, x, y, z), block, metadata, x, y, z, renderer) + } } + // ----------------------------------------------------------------------- // + override def onMessage(message: Message) {} override def onDisconnect(node: Node) {} diff --git a/src/main/scala/li/cil/oc/common/multipart/MultiPart.scala b/src/main/scala/li/cil/oc/common/multipart/MultiPart.scala index 610275c84..47904cd97 100644 --- a/src/main/scala/li/cil/oc/common/multipart/MultiPart.scala +++ b/src/main/scala/li/cil/oc/common/multipart/MultiPart.scala @@ -28,7 +28,7 @@ object MultiPart extends IPartFactory with IPartConverter { override def convert(world: World, pos: BlockCoord) = { world.getBlockTileEntity(pos.x, pos.y, pos.z) match { - case cable: Cable => new CablePart(Some(cable.node)) + case cable: Cable => new CablePart(Some(cable)) case _ => null } } diff --git a/src/main/scala/li/cil/oc/common/tileentity/Cable.scala b/src/main/scala/li/cil/oc/common/tileentity/Cable.scala index 7896eac14..302aa5653 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Cable.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Cable.scala @@ -1,11 +1,21 @@ package li.cil.oc.common.tileentity import li.cil.oc.api.network.Visibility +import li.cil.oc.util.Color import li.cil.oc.{api, common} -class Cable extends traits.Environment with traits.NotAnalyzable with traits.ImmibisMicroblock { +class Cable extends traits.Environment with traits.NotAnalyzable with traits.ImmibisMicroblock with traits.Colored { val node = api.Network.newNode(this, Visibility.None).create() + color = Color.LightGray + + override protected def onColorChanged() { + super.onColorChanged() + if (world != null && isServer) { + api.Network.joinOrCreateNetwork(this) + } + } + override def canUpdate = false override def getRenderBoundingBox = common.block.Cable.bounds(world, x, y, z).offset(x, y, z) diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/Colored.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/Colored.scala index 380b9a44c..81727d4f7 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/traits/Colored.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/traits/Colored.scala @@ -6,7 +6,7 @@ import li.cil.oc.server.PacketSender import net.minecraft.nbt.NBTTagCompound trait Colored extends TileEntity { - var _color = 0 + private var _color = 0 def color = _color diff --git a/src/main/scala/li/cil/oc/server/network/Network.scala b/src/main/scala/li/cil/oc/server/network/Network.scala index b26da6cbf..ec32e7a62 100644 --- a/src/main/scala/li/cil/oc/server/network/Network.scala +++ b/src/main/scala/li/cil/oc/server/network/Network.scala @@ -8,7 +8,7 @@ import li.cil.oc.common.block.Cable import li.cil.oc.common.multipart.CablePart import li.cil.oc.common.tileentity import li.cil.oc.server.network.{Node => MutableNode} -import li.cil.oc.util.SideTracker +import li.cil.oc.util.{Color, SideTracker} import li.cil.oc.util.mods.Mods import li.cil.oc.{OpenComputers, Settings, api} import net.minecraft.nbt._ @@ -385,10 +385,11 @@ object Network extends api.detail.NetworkAPI { case Some(node: MutableNode) => neighborNode match { case Some(neighbor: MutableNode) if neighbor != node && neighbor.network != null => - val canConnect = !Mods.ForgeMultipart.isAvailable || - (canConnectFromSide(tileEntity, side) && canConnectFromSide(neighborTileEntity, side.getOpposite)) + val canConnectColor = canConnectBasedOnColor(tileEntity, neighborTileEntity) + val canConnectFMP = !Mods.ForgeMultipart.isAvailable || + (canConnectFromSideFMP(tileEntity, side) && canConnectFromSideFMP(neighborTileEntity, side.getOpposite)) val canConnectIM = canConnectFromSideIM(tileEntity, side) && canConnectFromSideIM(neighborTileEntity, side.getOpposite) - if (canConnect && canConnectIM) neighbor.connect(node) + if (canConnectColor && canConnectFMP && canConnectIM) neighbor.connect(node) else node.disconnect(neighbor) case _ => } @@ -423,7 +424,28 @@ object Network extends api.detail.NetworkAPI { case _ => None } - private def canConnectFromSide(tileEntity: TileEntity, side: ForgeDirection) = + private def cableColor(tileEntity: TileEntity) = + tileEntity match { + case cable: tileentity.Cable => cable.color + case _ => + if (Mods.ForgeMultipart.isAvailable) cableColorFMP(tileEntity) + else Color.LightGray + } + + private def cableColorFMP(tileEntity: TileEntity) = + tileEntity match { + case host: TileMultipart => (host.partList collect { + case cable: CablePart => cable.color + }).headOption.getOrElse(Color.LightGray) + case _ => Color.LightGray + } + + private def canConnectBasedOnColor(te1: TileEntity, te2: TileEntity) = { + val (c1, c2) = (cableColor(te1), cableColor(te2)) + c1 == c2 || c1 == Color.LightGray || c2 == Color.LightGray + } + + private def canConnectFromSideFMP(tileEntity: TileEntity, side: ForgeDirection) = tileEntity match { case host: TileMultipart => host.partList.forall {