mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-13 01:10:19 -04:00
Added FMP compatibility to 3D prints \o/
This commit is contained in:
parent
2af6242086
commit
ff2ca21edb
@ -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")
|
||||||
|
|
||||||
|
@ -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(
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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))
|
||||||
|
@ -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) {
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
275
src/main/scala/li/cil/oc/integration/fmp/PrintPart.scala
Normal file
275
src/main/scala/li/cil/oc/integration/fmp/PrintPart.scala
Normal 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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user