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.

This commit is contained in:
Florian Nücke 2014-08-26 18:29:26 +02:00
parent cc9c38c16d
commit fe7e743f55
9 changed files with 153 additions and 19 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 295 B

After

Width:  |  Height:  |  Size: 304 B

View File

@ -3,7 +3,7 @@ package li.cil.oc.client
import java.io.EOFException
import cpw.mods.fml.common.network.Player
import li.cil.oc.{OpenComputers, Localization}
import li.cil.oc.Localization
import li.cil.oc.api.component
import li.cil.oc.api.network.ManagedEnvironment
import li.cil.oc.client.renderer.PetRenderer

View File

@ -8,6 +8,7 @@ import li.cil.oc.api.network.{Environment, SidedEnvironment}
import li.cil.oc.client.Textures
import li.cil.oc.common.multipart.CablePart
import li.cil.oc.common.tileentity
import li.cil.oc.util.Color
import li.cil.oc.util.mods.Mods
import net.minecraft.tileentity.TileEntity
import net.minecraft.util.AxisAlignedBB
@ -87,10 +88,11 @@ object Cable {
if (!world.isAirBlock(tx, ty, tz)) {
val neighborTileEntity = world.getBlockTileEntity(tx, ty, tz)
val neighborHasNode = hasNetworkNode(neighborTileEntity, side.getOpposite)
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 (neighborHasNode && canConnect && canConnectIM) {
if (neighborHasNode && canConnectColor && canConnectFMP && canConnectIM) {
result |= side.flag
}
}
@ -117,7 +119,28 @@ object Cable {
case _ => 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 {

View File

@ -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) =

View File

@ -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) {}

View File

@ -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
}
}

View File

@ -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)

View File

@ -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

View File

@ -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 {