Added FMP compatibility to 3D prints \o/

This commit is contained in:
Florian Nücke 2015-03-26 07:09:45 +01:00
parent 2af6242086
commit ff2ca21edb
9 changed files with 343 additions and 22 deletions

View File

@ -102,7 +102,7 @@ object BlockRenderer extends ISimpleBlockRenderingHandler {
result result
case print: tileentity.Print => case print: tileentity.Print =>
Print.render(print, x, y, z, block, renderer) Print.render(print.data, print.state, print.facing, x, y, z, block, renderer)
RenderState.checkError(getClass.getName + ".renderWorldBlock: print") RenderState.checkError(getClass.getName + ".renderWorldBlock: print")

View File

@ -2,20 +2,27 @@ package li.cil.oc.client.renderer.block
import li.cil.oc.api.Items import li.cil.oc.api.Items
import li.cil.oc.common.block import li.cil.oc.common.block
import li.cil.oc.common.tileentity import li.cil.oc.common.item.data.PrintData
import li.cil.oc.util.ExtendedAABB._ import li.cil.oc.util.ExtendedAABB._
import net.minecraft.block.Block import net.minecraft.block.Block
import net.minecraft.client.Minecraft import net.minecraft.client.Minecraft
import net.minecraft.client.renderer.RenderBlocks import net.minecraft.client.renderer.RenderBlocks
import net.minecraft.client.renderer.texture.TextureMap import net.minecraft.client.renderer.texture.TextureMap
import net.minecraft.util.IIcon import net.minecraft.util.IIcon
import net.minecraftforge.common.util.ForgeDirection
object Print { object Print {
lazy val printBlock = Items.get("print").block().asInstanceOf[block.Print] lazy val printBlock = Items.get("print").block().asInstanceOf[block.Print]
def render(print: tileentity.Print, x: Int, y: Int, z: Int, block: Block, renderer: RenderBlocks): Unit = { def render(data: PrintData, state: Boolean, facing: ForgeDirection, x: Int, y: Int, z: Int, block: Block, renderer: RenderBlocks): Unit = {
for (shape <- if (print.state) print.data.stateOn else print.data.stateOff) { val shapes = if (state) data.stateOn else data.stateOff
val bounds = shape.bounds.rotateTowards(print.facing) if (shapes.size == 0) {
printBlock.textureOverride = Option(resolveTexture("missingno"))
renderer.setRenderBounds(0, 0, 0, 1, 1, 1)
renderer.renderStandardBlock(block, x, y, z)
}
else for (shape <- shapes) {
val bounds = shape.bounds.rotateTowards(facing)
printBlock.colorMultiplierOverride = shape.tint printBlock.colorMultiplierOverride = shape.tint
printBlock.textureOverride = Option(resolveTexture(shape.texture)) printBlock.textureOverride = Option(resolveTexture(shape.texture))
renderer.setRenderBounds( renderer.setRenderBounds(

View File

@ -102,16 +102,16 @@ class Print(protected implicit val tileTag: ClassTag[tileentity.Print]) extends
} }
} }
override protected def intersect(world: World, x: Int, y: Int, z: Int, origin: Vec3, direction: Vec3): MovingObjectPosition = { override protected def intersect(world: World, x: Int, y: Int, z: Int, start: Vec3, end: Vec3): MovingObjectPosition = {
world.getTileEntity(x, y, z) match { world.getTileEntity(x, y, z) match {
case print: tileentity.Print => case print: tileentity.Print =>
var closestDistance = Double.PositiveInfinity var closestDistance = Double.PositiveInfinity
var closest: Option[MovingObjectPosition] = None var closest: Option[MovingObjectPosition] = None
for (shape <- if (print.state) print.data.stateOn else print.data.stateOff) { for (shape <- if (print.state) print.data.stateOn else print.data.stateOff) {
val bounds = shape.bounds.rotateTowards(print.facing).offset(x, y, z) val bounds = shape.bounds.rotateTowards(print.facing).offset(x, y, z)
val hit = bounds.calculateIntercept(origin, direction) val hit = bounds.calculateIntercept(start, end)
if (hit != null) { if (hit != null) {
val distance = hit.hitVec.distanceTo(origin) val distance = hit.hitVec.distanceTo(start)
if (distance < closestDistance) { if (distance < closestDistance) {
closestDistance = distance closestDistance = distance
closest = Option(hit) closest = Option(hit)
@ -119,7 +119,7 @@ class Print(protected implicit val tileTag: ClassTag[tileentity.Print]) extends
} }
} }
closest.map(hit => new MovingObjectPosition(x, y, z, hit.sideHit, hit.hitVec)).orNull closest.map(hit => new MovingObjectPosition(x, y, z, hit.sideHit, hit.hitVec)).orNull
case _ => super.intersect(world, x, y, z, origin, direction) case _ => super.intersect(world, x, y, z, start, end)
} }
} }

View File

@ -166,11 +166,11 @@ class RobotProxy extends RedstoneAware with traits.SpecialBlock with traits.Stat
private def gettingDropsForActualDrop = new Exception().getStackTrace.exists(element => getDropForRealDropCallers.contains(element.getClassName + "." + element.getMethodName)) private def gettingDropsForActualDrop = new Exception().getStackTrace.exists(element => getDropForRealDropCallers.contains(element.getClassName + "." + element.getMethodName))
override def intersect(world: World, x: Int, y: Int, z: Int, origin: Vec3, direction: Vec3) = { override def intersect(world: World, x: Int, y: Int, z: Int, start: Vec3, end: Vec3) = {
val bounds = getCollisionBoundingBoxFromPool(world, x, y, z) val bounds = getCollisionBoundingBoxFromPool(world, x, y, z)
world.getTileEntity(x, y, z) match { world.getTileEntity(x, y, z) match {
case proxy: tileentity.RobotProxy if proxy.robot.animationTicksLeft <= 0 && bounds.isVecInside(origin) => null case proxy: tileentity.RobotProxy if proxy.robot.animationTicksLeft <= 0 && bounds.isVecInside(start) => null
case _ => super.intersect(world, x, y, z, origin, direction) case _ => super.intersect(world, x, y, z, start, end)
} }
} }

View File

@ -207,16 +207,16 @@ class SimpleBlock(material: Material = Material.iron) extends Block(material) {
} }
// NOTE: must not be final for immibis microblocks to work. // NOTE: must not be final for immibis microblocks to work.
override def collisionRayTrace(world: World, x: Int, y: Int, z: Int, origin: Vec3, direction: Vec3) = override def collisionRayTrace(world: World, x: Int, y: Int, z: Int, start: Vec3, end: Vec3) =
this.synchronized(intersect(world, x, y, z, origin, direction)) this.synchronized(intersect(world, x, y, z, start, end))
override def getCollisionBoundingBoxFromPool(world: World, x: Int, y: Int, z: Int) = this.synchronized { override def getCollisionBoundingBoxFromPool(world: World, x: Int, y: Int, z: Int) = this.synchronized {
doSetBlockBoundsBasedOnState(world, x, y, z) doSetBlockBoundsBasedOnState(world, x, y, z)
super.getCollisionBoundingBoxFromPool(world, x, y, z) super.getCollisionBoundingBoxFromPool(world, x, y, z)
} }
protected def intersect(world: World, x: Int, y: Int, z: Int, origin: Vec3, direction: Vec3) = protected def intersect(world: World, x: Int, y: Int, z: Int, start: Vec3, end: Vec3) =
super.collisionRayTrace(world, x, y, z, origin, direction) super.collisionRayTrace(world, x, y, z, start, end)
final override def canPlaceBlockOnSide(world: World, x: Int, y: Int, z: Int, side: Int) = final override def canPlaceBlockOnSide(world: World, x: Int, y: Int, z: Int, side: Int) =
canPlaceBlockOnSide(world, x, y, z, toLocal(world, x, y, z, ForgeDirection.getOrientation(side).getOpposite)) canPlaceBlockOnSide(world, x, y, z, toLocal(world, x, y, z, ForgeDirection.getOrientation(side).getOpposite))

View File

@ -6,6 +6,7 @@ import codechicken.lib.vec.BlockCoord
import codechicken.lib.vec.Vector3 import codechicken.lib.vec.Vector3
import codechicken.multipart.TileMultipart import codechicken.multipart.TileMultipart
import cpw.mods.fml.common.eventhandler.SubscribeEvent import cpw.mods.fml.common.eventhandler.SubscribeEvent
import li.cil.oc.Settings
import li.cil.oc.api.Items import li.cil.oc.api.Items
import li.cil.oc.client.PacketSender import li.cil.oc.client.PacketSender
import li.cil.oc.common.block.SimpleBlock import li.cil.oc.common.block.SimpleBlock
@ -14,6 +15,7 @@ import net.minecraft.item.ItemBlock
import net.minecraft.network.play.client.C08PacketPlayerBlockPlacement import net.minecraft.network.play.client.C08PacketPlayerBlockPlacement
import net.minecraft.util.MovingObjectPosition import net.minecraft.util.MovingObjectPosition
import net.minecraftforge.common.MinecraftForge import net.minecraftforge.common.MinecraftForge
import net.minecraftforge.common.util.ForgeDirection
import net.minecraftforge.event.entity.player.PlayerDestroyItemEvent import net.minecraftforge.event.entity.player.PlayerDestroyItemEvent
import net.minecraftforge.event.entity.player.PlayerInteractEvent import net.minecraftforge.event.entity.player.PlayerInteractEvent
import net.minecraftforge.event.entity.player.PlayerInteractEvent.Action import net.minecraftforge.event.entity.player.PlayerInteractEvent.Action
@ -21,6 +23,8 @@ import net.minecraftforge.event.entity.player.PlayerInteractEvent.Action
object EventHandler { object EventHandler {
private var currentlyPlacing = false private var currentlyPlacing = false
private val yaw2Direction = Array(ForgeDirection.SOUTH, ForgeDirection.WEST, ForgeDirection.NORTH, ForgeDirection.EAST)
@SubscribeEvent @SubscribeEvent
def playerInteract(event: PlayerInteractEvent) { def playerInteract(event: PlayerInteractEvent) {
this.synchronized { this.synchronized {
@ -46,7 +50,17 @@ object EventHandler {
if (hit != null && player.getHeldItem != null) player.getHeldItem.getItem match { if (hit != null && player.getHeldItem != null) player.getHeldItem.getItem match {
case itemBlock: ItemBlock => case itemBlock: ItemBlock =>
itemBlock.field_150939_a match { itemBlock.field_150939_a match {
case simpleBlock: SimpleBlock if simpleBlock == Items.get("cable").block() => placeDelegatePart(player, hit, new CablePart()) case simpleBlock: SimpleBlock =>
if (simpleBlock == Items.get("cable").block()) {
placeDelegatePart(player, hit, new CablePart())
}
else if (simpleBlock == Items.get("print").block()) {
val part = new PrintPart()
part.data.load(player.getHeldItem)
part.facing = yaw2Direction((player.rotationYaw / 360 * 4).round & 3).getOpposite
placeDelegatePart(player, hit, part)
}
else false
case _ => false case _ => false
} }
case _ => false case _ => false
@ -54,6 +68,7 @@ object EventHandler {
else false else false
} }
protected def placeDelegatePart(player: EntityPlayer, hit: MovingObjectPosition, part: SimpleBlockPart): Boolean = { protected def placeDelegatePart(player: EntityPlayer, hit: MovingObjectPosition, part: SimpleBlockPart): Boolean = {
val world = player.getEntityWorld val world = player.getEntityWorld
if (world.isRemote && !player.isSneaking) { if (world.isRemote && !player.isSneaking) {
@ -66,7 +81,7 @@ object EventHandler {
hit.blockX, hit.blockY, hit.blockZ, hit.sideHit, hit.blockX, hit.blockY, hit.blockZ, hit.sideHit,
player.inventory.getCurrentItem, player.inventory.getCurrentItem,
f.x.toFloat, f.y.toFloat, f.z.toFloat)) f.x.toFloat, f.y.toFloat, f.z.toFloat))
return false return true
} }
} }
@ -75,14 +90,28 @@ object EventHandler {
val inside = Option(TileMultipart.getOrConvertTile(world, pos)) val inside = Option(TileMultipart.getOrConvertTile(world, pos))
val outside = Option(TileMultipart.getOrConvertTile(world, posOutside)) val outside = Option(TileMultipart.getOrConvertTile(world, posOutside))
inside match { inside match {
case Some(t) if t.canAddPart(part) => placeMultiPart(player, part, pos) case Some(t) if t.canAddPart(part) && canAddPrint(t, part) => placeMultiPart(player, part, pos)
case _ => outside match { case _ => outside match {
case Some(t) if t.canAddPart(part) => placeMultiPart(player, part, posOutside) case Some(t) if t.canAddPart(part) && canAddPrint(t, part) => placeMultiPart(player, part, posOutside)
case _ => false case _ => false
} }
} }
} }
protected def canAddPrint(t: TileMultipart, p: SimpleBlockPart): Boolean = p match {
case print: PrintPart =>
val (offSum, onSum) = t.partList.foldLeft((print.data.stateOff.size, print.data.stateOn.size))((acc, part) => {
val (offAcc, onAcc) = acc
val (offCount, onCount) = part match {
case innerPrint: PrintPart => (innerPrint.data.stateOff.size, innerPrint.data.stateOn.size)
case _ => (0, 0)
}
(offAcc + offCount, onAcc + onCount)
})
offSum <= Settings.get.maxPrintComplexity && onSum <= Settings.get.maxPrintComplexity
case _ => true
}
protected def placeMultiPart(player: EntityPlayer, part: SimpleBlockPart, pos: BlockCoord) = { protected def placeMultiPart(player: EntityPlayer, part: SimpleBlockPart, pos: BlockCoord) = {
val world = player.getEntityWorld val world = player.getEntityWorld
if (world.isRemote) { if (world.isRemote) {

View File

@ -7,6 +7,7 @@ import codechicken.multipart.MultiPartRegistry
import codechicken.multipart.MultiPartRegistry.IPartConverter import codechicken.multipart.MultiPartRegistry.IPartConverter
import li.cil.oc.api.Items import li.cil.oc.api.Items
import li.cil.oc.common.tileentity.Cable import li.cil.oc.common.tileentity.Cable
import li.cil.oc.common.tileentity.Print
import net.minecraft.world.World import net.minecraft.world.World
object MultipartConverter extends IPartConverter { object MultipartConverter extends IPartConverter {
@ -14,11 +15,15 @@ object MultipartConverter extends IPartConverter {
MultiPartRegistry.registerConverter(this) MultiPartRegistry.registerConverter(this)
} }
override def blockTypes = util.Arrays.asList(Items.get("cable").block) override def blockTypes = util.Arrays.asList(
Items.get("cable").block,
Items.get("print").block
)
override def convert(world: World, pos: BlockCoord) = { override def convert(world: World, pos: BlockCoord) = {
world.getTileEntity(pos.x, pos.y, pos.z) match { world.getTileEntity(pos.x, pos.y, pos.z) match {
case cable: Cable => new CablePart(Some(cable)) case cable: Cable => new CablePart(Some(cable))
case print: Print => new PrintPart(Some(print))
case _ => null case _ => null
} }
} }

View File

@ -7,12 +7,17 @@ import li.cil.oc.Settings
object MultipartFactory extends IPartFactory { object MultipartFactory extends IPartFactory {
def init() { def init() {
MultiPartRegistry.registerParts(MultipartFactory, Array(Settings.namespace + "cable")) MultiPartRegistry.registerParts(MultipartFactory, Array(
Settings.namespace + "cable",
Settings.namespace + "print"
))
} }
override def createPart(name: String, client: Boolean): TMultiPart = { override def createPart(name: String, client: Boolean): TMultiPart = {
if (name.equals(Settings.namespace + "cable")) if (name.equals(Settings.namespace + "cable"))
return new CablePart() return new CablePart()
if (name.equals(Settings.namespace + "print"))
return new PrintPart()
null null
} }
} }

View File

@ -0,0 +1,275 @@
package li.cil.oc.integration.fmp
import java.lang
import codechicken.lib.data.MCDataInput
import codechicken.lib.data.MCDataOutput
import codechicken.lib.raytracer.ExtendedMOP
import codechicken.lib.vec.Cuboid6
import codechicken.lib.vec.Vector3
import codechicken.multipart.IRedstonePart
import codechicken.multipart.TCuboidPart
import codechicken.multipart.TNormalOcclusion
import cpw.mods.fml.relauncher.Side
import cpw.mods.fml.relauncher.SideOnly
import li.cil.oc.Settings
import li.cil.oc.api.Items
import li.cil.oc.client.renderer.block.Print
import li.cil.oc.common.block.Print
import li.cil.oc.common.item.data.PrintData
import li.cil.oc.common.tileentity
import li.cil.oc.integration.Mods
import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedAABB
import li.cil.oc.util.ExtendedAABB._
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ExtendedWorld._
import mods.immibis.redlogic.api.wiring.IRedstoneEmitter
import net.minecraft.client.renderer.OpenGlHelper
import net.minecraft.client.renderer.RenderBlocks
import net.minecraft.client.renderer.RenderGlobal
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.init.Blocks
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.util.MovingObjectPosition
import net.minecraft.util.Vec3
import net.minecraftforge.common.util.ForgeDirection
import org.lwjgl.opengl.GL11
import scala.collection.convert.WrapAsJava._
class PrintPart(val original: Option[tileentity.Print] = None) extends SimpleBlockPart with TCuboidPart with TNormalOcclusion with IRedstonePart {
var facing = ForgeDirection.SOUTH
var data = new PrintData()
var boundsOff = ExtendedAABB.unitBounds
var boundsOn = ExtendedAABB.unitBounds
var state = false
original.foreach(print => {
facing = print.facing
data = print.data
boundsOff = print.boundsOff
boundsOn = print.boundsOn
state = print.state
})
// ----------------------------------------------------------------------- //
override def simpleBlock = Items.get("print").block().asInstanceOf[Print]
def getType = Settings.namespace + "print"
override def doesTick = false
override def getBounds = new Cuboid6(if (state) boundsOn else boundsOff)
override def getOcclusionBoxes = {
val shapes = if (state) data.stateOn else data.stateOff
asJavaIterable(shapes.map(shape => new Cuboid6(shape.bounds.rotateTowards(facing))))
}
override def getCollisionBoxes = getOcclusionBoxes
override def getRenderBounds = getBounds
// ----------------------------------------------------------------------- //
override def canConnectRedstone(side: Int): Boolean = true
override def strongPowerLevel(side: Int): Int = weakPowerLevel(side)
override def weakPowerLevel(side: Int): Int = if (data.emitRedstone && state) 15 else 0
// ----------------------------------------------------------------------- //
override def activate(player: EntityPlayer, hit: MovingObjectPosition, item: ItemStack): Boolean = {
if (data.stateOn.size > 0) {
if (!state || !data.isButtonMode) {
toggleState()
return true
}
}
false
}
def toggleState(): Unit = {
if (canToggle) {
state = !state
world.playSoundEffect(x + 0.5, y + 0.5, z + 0.5, "random.click", 0.3F, if (state) 0.6F else 0.5F)
world.notifyBlocksOfNeighborChange(x, y, z, tile.getBlockType)
world.markBlockForUpdate(x, y, z)
if (!world.isRemote) sendDescUpdate()
tile.partList.foreach {
case print: PrintPart if print != this => print.onNeighborChanged()
case _ =>
}
if (state && data.isButtonMode) {
scheduleTick(simpleBlock.tickRate(world))
}
}
}
def canToggle = {
val toggled = new PrintPart()
toggled.facing = facing
toggled.data = data
toggled.state = !state
toggled.boundsOff = boundsOff
toggled.boundsOn = boundsOn
tile.canReplacePart(this, toggled)
}
// ----------------------------------------------------------------------- //
override def scheduledTick(): Unit = if (state) toggleState()
override def pickItem(hit: MovingObjectPosition): ItemStack = data.createItemStack()
override def getDrops: lang.Iterable[ItemStack] = asJavaIterable(Iterable(data.createItemStack()))
override def collisionRayTrace(start: Vec3, end: Vec3): ExtendedMOP = {
val shapes = if (state) data.stateOn else data.stateOff
var closestDistance = Double.PositiveInfinity
var closest: Option[MovingObjectPosition] = None
for (shape <- shapes) {
val bounds = shape.bounds.rotateTowards(facing).offset(x, y, z)
val hit = bounds.calculateIntercept(start, end)
if (hit != null) {
val distance = hit.hitVec.distanceTo(start)
if (distance < closestDistance) {
closestDistance = distance
hit.blockX = x
hit.blockY = y
hit.blockZ = z
closest = Option(hit)
}
}
}
closest.fold(if (shapes.isEmpty) new ExtendedMOP(x, y, z, 0, Vec3.createVectorHelper(0.5, 0.5, 0.5), null) else null)(hit => new ExtendedMOP(hit, null, closestDistance))
}
@SideOnly(Side.CLIENT)
override def drawHighlight(hit: MovingObjectPosition, player: EntityPlayer, frame: Float): Boolean = {
val pos = player.getPosition(frame)
val expansion = 0.002f
// See RenderGlobal.drawSelectionBox.
GL11.glEnable(GL11.GL_BLEND)
OpenGlHelper.glBlendFunc(770, 771, 1, 0)
GL11.glColor4f(0, 0, 0, 0.4f)
GL11.glLineWidth(2)
GL11.glDisable(GL11.GL_TEXTURE_2D)
GL11.glDepthMask(false)
for (shape <- if (state) data.stateOn else data.stateOff) {
val bounds = shape.bounds.rotateTowards(facing)
RenderGlobal.drawOutlinedBoundingBox(bounds.copy().expand(expansion, expansion, expansion)
.offset(hit.blockX, hit.blockY, hit.blockZ)
.offset(-pos.xCoord, -pos.yCoord, -pos.zCoord), -1)
}
GL11.glDepthMask(true)
GL11.glEnable(GL11.GL_TEXTURE_2D)
GL11.glDisable(GL11.GL_BLEND)
true
}
override def onNeighborChanged(): Unit = {
super.onNeighborChanged()
val inner = tile.partList.foldLeft(false)((powered, part) => part match {
case print: PrintPart => powered || (print.state && print.data.emitRedstone)
case _ => powered
})
val newMaxValue = 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) = {
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
math.max(vanilla, redLogic)
}
}
// ----------------------------------------------------------------------- //
override def load(nbt: NBTTagCompound) {
super.load(nbt)
facing = nbt.getDirection("facing").getOrElse(facing)
data.load(nbt.getCompoundTag("data"))
state = nbt.getBoolean("state")
updateBounds()
}
override def save(nbt: NBTTagCompound) {
super.save(nbt)
nbt.setDirection("facing", Option(facing))
nbt.setNewCompoundTag("data", data.save)
nbt.setBoolean("state", state)
}
override def readDesc(packet: MCDataInput) {
super.readDesc(packet)
facing = ForgeDirection.getOrientation(packet.readUByte())
data.load(packet.readNBTTagCompound())
state = packet.readBoolean()
updateBounds()
if (world != null) {
world.markBlockForUpdate(x, y, z)
}
}
override def writeDesc(packet: MCDataOutput) {
super.writeDesc(packet)
packet.writeByte(facing.ordinal().toByte)
val nbt = new NBTTagCompound()
data.save(nbt)
packet.writeNBTTagCompound(nbt)
packet.writeBoolean(state)
}
def updateBounds(): Unit = {
boundsOff = data.stateOff.drop(1).foldLeft(data.stateOff.headOption.fold(ExtendedAABB.unitBounds)(_.bounds))((a, b) => a.func_111270_a(b.bounds))
if (boundsOff.volume == 0) boundsOff = ExtendedAABB.unitBounds
else boundsOff = boundsOff.rotateTowards(facing)
boundsOn = data.stateOn.drop(1).foldLeft(data.stateOn.headOption.fold(ExtendedAABB.unitBounds)(_.bounds))((a, b) => a.func_111270_a(b.bounds))
if (boundsOn.volume == 0) boundsOn = ExtendedAABB.unitBounds
else boundsOn = boundsOn.rotateTowards(facing)
}
// ----------------------------------------------------------------------- //
@SideOnly(Side.CLIENT)
override def renderStatic(pos: Vector3, pass: Int) = {
val (x, y, z) = (pos.x.toInt, pos.y.toInt, pos.z.toInt)
val renderer = RenderBlocks.getInstance
renderer.blockAccess = world
Print.render(data, state, facing, x, y, z, simpleBlock, renderer)
true
}
}