mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-18 19:56:17 -04:00
Assigning 3D prints to multipart "slots" where they intersect with those areas. Makes them properly block Project Red bundled cables, for example. Closes #1015.
There are some... interesting cases with multi-state prints and redstone logic (e.g. the printed trapdoor cutting of the power that triggers it), but it shouldn't be a real problem.
This commit is contained in:
parent
e98866473a
commit
6f02abad8c
@ -5,11 +5,18 @@ import java.lang
|
|||||||
import codechicken.lib.data.MCDataInput
|
import codechicken.lib.data.MCDataInput
|
||||||
import codechicken.lib.data.MCDataOutput
|
import codechicken.lib.data.MCDataOutput
|
||||||
import codechicken.lib.raytracer.ExtendedMOP
|
import codechicken.lib.raytracer.ExtendedMOP
|
||||||
|
import codechicken.lib.raytracer.IndexedCuboid6
|
||||||
import codechicken.lib.vec.Cuboid6
|
import codechicken.lib.vec.Cuboid6
|
||||||
import codechicken.lib.vec.Vector3
|
import codechicken.lib.vec.Vector3
|
||||||
import codechicken.multipart.IRedstonePart
|
import codechicken.multipart.IRedstonePart
|
||||||
|
import codechicken.multipart.PartMap
|
||||||
import codechicken.multipart.TCuboidPart
|
import codechicken.multipart.TCuboidPart
|
||||||
|
import codechicken.multipart.TEdgePart
|
||||||
|
import codechicken.multipart.TFacePart
|
||||||
|
import codechicken.multipart.TMultiPart
|
||||||
import codechicken.multipart.TNormalOcclusion
|
import codechicken.multipart.TNormalOcclusion
|
||||||
|
import codechicken.multipart.TSlottedPart
|
||||||
|
import codechicken.multipart.scalatraits.TSlottedTile
|
||||||
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
|
||||||
@ -38,14 +45,55 @@ import net.minecraftforge.common.util.ForgeDirection
|
|||||||
import org.lwjgl.opengl.GL11
|
import org.lwjgl.opengl.GL11
|
||||||
|
|
||||||
import scala.collection.convert.WrapAsJava._
|
import scala.collection.convert.WrapAsJava._
|
||||||
|
import scala.collection.convert.WrapAsScala._
|
||||||
|
|
||||||
class PrintPart(val original: Option[tileentity.Print] = None) extends SimpleBlockPart with TCuboidPart with TNormalOcclusion with IRedstonePart {
|
object PrintPart {
|
||||||
|
private val q0 = 0 / 16f
|
||||||
|
private val q1 = 4 / 16f
|
||||||
|
private val q2 = 12 / 16f
|
||||||
|
private val q3 = 16 / 16f
|
||||||
|
|
||||||
|
val slotBounds = Array(
|
||||||
|
new Cuboid6(q1, q0, q1, q2, q1, q2),
|
||||||
|
new Cuboid6(q1, q2, q1, q2, q3, q2),
|
||||||
|
new Cuboid6(q1, q1, q0, q2, q2, q1),
|
||||||
|
new Cuboid6(q1, q1, q2, q2, q2, q3),
|
||||||
|
new Cuboid6(q0, q1, q1, q1, q2, q2),
|
||||||
|
new Cuboid6(q2, q1, q1, q3, q2, q2),
|
||||||
|
new Cuboid6(q1, q1, q1, q2, q2, q2),
|
||||||
|
|
||||||
|
new Cuboid6(q0, q0, q0, q1, q1, q1),
|
||||||
|
new Cuboid6(q0, q2, q0, q1, q3, q1),
|
||||||
|
new Cuboid6(q0, q0, q2, q1, q1, q3),
|
||||||
|
new Cuboid6(q0, q2, q2, q1, q3, q3),
|
||||||
|
new Cuboid6(q2, q0, q0, q3, q1, q1),
|
||||||
|
new Cuboid6(q2, q2, q0, q3, q3, q1),
|
||||||
|
new Cuboid6(q2, q0, q2, q3, q1, q3),
|
||||||
|
new Cuboid6(q2, q2, q2, q3, q3, q3),
|
||||||
|
|
||||||
|
new Cuboid6(q0, q1, q0, q1, q2, q1),
|
||||||
|
new Cuboid6(q0, q1, q2, q1, q2, q3),
|
||||||
|
new Cuboid6(q2, q1, q0, q3, q2, q1),
|
||||||
|
new Cuboid6(q2, q1, q2, q3, q2, q3),
|
||||||
|
new Cuboid6(q0, q0, q1, q1, q1, q2),
|
||||||
|
new Cuboid6(q2, q0, q1, q3, q1, q2),
|
||||||
|
new Cuboid6(q0, q2, q1, q1, q3, q2),
|
||||||
|
new Cuboid6(q2, q2, q1, q3, q3, q2),
|
||||||
|
new Cuboid6(q1, q0, q0, q2, q1, q1),
|
||||||
|
new Cuboid6(q1, q2, q0, q2, q3, q1),
|
||||||
|
new Cuboid6(q1, q0, q2, q2, q1, q3),
|
||||||
|
new Cuboid6(q1, q2, q2, q2, q3, q3)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
class PrintPart(val original: Option[tileentity.Print] = None) extends SimpleBlockPart with TCuboidPart with TNormalOcclusion with IRedstonePart with TSlottedPart with TEdgePart with TFacePart {
|
||||||
var facing = ForgeDirection.SOUTH
|
var facing = ForgeDirection.SOUTH
|
||||||
var data = new PrintData()
|
var data = new PrintData()
|
||||||
|
|
||||||
var boundsOff = ExtendedAABB.unitBounds
|
var boundsOff = ExtendedAABB.unitBounds
|
||||||
var boundsOn = ExtendedAABB.unitBounds
|
var boundsOn = ExtendedAABB.unitBounds
|
||||||
var state = false
|
var state = false
|
||||||
|
var toggling = false // avoid infinite loops when updating neighbors
|
||||||
|
|
||||||
original.foreach(print => {
|
original.foreach(print => {
|
||||||
facing = print.facing
|
facing = print.facing
|
||||||
@ -74,8 +122,24 @@ class PrintPart(val original: Option[tileentity.Print] = None) extends SimpleBlo
|
|||||||
|
|
||||||
override def getRenderBounds = getBounds
|
override def getRenderBounds = getBounds
|
||||||
|
|
||||||
|
override def getSlotMask: Int = {
|
||||||
|
var mask = 0
|
||||||
|
val boxes = getOcclusionBoxes
|
||||||
|
for (slot <- PartMap.values) {
|
||||||
|
val bounds = PrintPart.slotBounds(slot.i)
|
||||||
|
if (boxes.exists(_.intersects(bounds))) {
|
||||||
|
mask |= slot.mask
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mask
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------- //
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
|
override def conductsRedstone: Boolean = data.emitRedstone && state
|
||||||
|
|
||||||
|
override def redstoneConductionMap: Int = if (data.emitRedstone && state) 0xFF else 0
|
||||||
|
|
||||||
override def canConnectRedstone(side: Int): Boolean = true
|
override def canConnectRedstone(side: Int): Boolean = true
|
||||||
|
|
||||||
override def strongPowerLevel(side: Int): Int = weakPowerLevel(side)
|
override def strongPowerLevel(side: Int): Int = weakPowerLevel(side)
|
||||||
@ -96,22 +160,29 @@ class PrintPart(val original: Option[tileentity.Print] = None) extends SimpleBlo
|
|||||||
|
|
||||||
def toggleState(): Unit = {
|
def toggleState(): Unit = {
|
||||||
if (canToggle) {
|
if (canToggle) {
|
||||||
|
toggling = true
|
||||||
state = !state
|
state = !state
|
||||||
world.playSoundEffect(x + 0.5, y + 0.5, z + 0.5, "random.click", 0.3F, if (state) 0.6F else 0.5F)
|
// Update slot info in tile... kinda meh, but works.
|
||||||
world.notifyBlocksOfNeighborChange(x, y, z, tile.getBlockType)
|
tile match {
|
||||||
world.markBlockForUpdate(x, y, z)
|
case slotted: TSlottedTile =>
|
||||||
if (!world.isRemote) sendDescUpdate()
|
for (i <- 0 until slotted.v_partMap.length) {
|
||||||
tile.partList.foreach {
|
if (slotted.v_partMap(i) == this)
|
||||||
case print: PrintPart if print != this => print.onNeighborChanged()
|
slotted.v_partMap(i) = null
|
||||||
|
}
|
||||||
|
tile.bindPart(this)
|
||||||
case _ =>
|
case _ =>
|
||||||
}
|
}
|
||||||
|
world.playSoundEffect(x + 0.5, y + 0.5, z + 0.5, "random.click", 0.3F, if (state) 0.6F else 0.5F)
|
||||||
|
tile.notifyPartChange(this)
|
||||||
|
sendDescUpdate()
|
||||||
if (state && data.isButtonMode) {
|
if (state && data.isButtonMode) {
|
||||||
scheduleTick(simpleBlock.tickRate(world))
|
scheduleTick(simpleBlock.tickRate(world))
|
||||||
}
|
}
|
||||||
|
toggling = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def canToggle = {
|
def canToggle = !toggling && world != null && !world.isRemote && {
|
||||||
val toggled = new PrintPart()
|
val toggled = new PrintPart()
|
||||||
toggled.facing = facing
|
toggled.facing = facing
|
||||||
toggled.data = data
|
toggled.data = data
|
||||||
@ -177,22 +248,33 @@ class PrintPart(val original: Option[tileentity.Print] = None) extends SimpleBlo
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override def onPartChanged(part: TMultiPart): Unit = {
|
||||||
|
super.onPartChanged(part)
|
||||||
|
checkRedstone()
|
||||||
|
}
|
||||||
|
|
||||||
override def onNeighborChanged(): Unit = {
|
override def onNeighborChanged(): Unit = {
|
||||||
super.onNeighborChanged()
|
super.onNeighborChanged()
|
||||||
|
checkRedstone()
|
||||||
|
}
|
||||||
|
|
||||||
|
protected def checkRedstone(): Unit = {
|
||||||
|
val newMaxValue = computeInput()
|
||||||
|
val newState = newMaxValue > 1 // Fixes oddities in cycling updates.
|
||||||
|
if (!data.emitRedstone && data.stateOn.size > 0 && state != newState) {
|
||||||
|
toggleState()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected def computeInput(): Int = {
|
||||||
val inner = tile.partList.foldLeft(false)((powered, part) => part match {
|
val inner = tile.partList.foldLeft(false)((powered, part) => part match {
|
||||||
case print: PrintPart => powered || (print.state && print.data.emitRedstone)
|
case print: PrintPart => powered || (print.state && print.data.emitRedstone)
|
||||||
case _ => powered
|
case _ => powered
|
||||||
})
|
})
|
||||||
val newMaxValue = if (inner) 15 else ForgeDirection.VALID_DIRECTIONS.map(computeInput).max
|
if (inner) 15 else ForgeDirection.VALID_DIRECTIONS.map(computeInput).max
|
||||||
if (!data.emitRedstone && data.stateOn.size > 0) {
|
|
||||||
val newState = newMaxValue > 0
|
|
||||||
if (state != newState) {
|
|
||||||
toggleState()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected def computeInput(side: ForgeDirection) = {
|
protected def computeInput(side: ForgeDirection): Int = {
|
||||||
val blockPos = BlockPosition(x, y, z).offset(side)
|
val blockPos = BlockPosition(x, y, z).offset(side)
|
||||||
if (!world.blockExists(blockPos)) 0
|
if (!world.blockExists(blockPos)) 0
|
||||||
else {
|
else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user