electrodynamics/src/main/scala/edx/electrical/circuit/component/laser/focus/TileMirror.scala

166 lines
4.7 KiB
Scala

package edx.electrical.circuit.component.laser.focus
import cpw.mods.fml.client.FMLClientHandler
import cpw.mods.fml.relauncher.{Side, SideOnly}
import edx.core.{Electrodynamics, Reference}
import edx.electrical.circuit.component.laser.{ILaserHandler, Laser}
import net.minecraft.block.material.Material
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.network.play.server.S35PacketUpdateTileEntity
import net.minecraft.network.{NetworkManager, Packet}
import net.minecraft.util.{MovingObjectPosition, ResourceLocation}
import net.minecraftforge.client.model.AdvancedModelLoader
import net.minecraftforge.common.util.ForgeDirection
import org.lwjgl.opengl.GL11._
import resonantengine.lib.transform.rotation.Quaternion
import resonantengine.lib.transform.vector.Vector3
import scala.collection.convert.wrapAsJava._
object TileMirror
{
@SideOnly(Side.CLIENT) val model = AdvancedModelLoader.loadModel(new ResourceLocation(Reference.domain, Reference.modelPath + "mirror.tcn"))
@SideOnly(Side.CLIENT) val texture = new ResourceLocation(Reference.domain, Reference.modelPath + "mirror.png")
}
/**
* A mirror reflects lasers.
*
* TODO: Make it actually reflect light (render reflection)
*
* @author Calclavia
*/
class TileMirror extends TileFocus(Material.glass) with ILaserHandler with IFocus
{
private var normal = new Vector3(0, 1, 0)
private var cachedHits = List[Vector3]()
domain = ""
textureName = "stone"
normalRender = false
isOpaqueCube = false
override def update()
{
if (isPowered)
{
for (a <- 0 to 5)
{
val dir = ForgeDirection.getOrientation(a)
val axis = new Vector3(dir)
val rotateAngle = world.getIndirectPowerLevelTo((x.toInt + axis.x).toInt, (y + axis.y).toInt, (z + axis.z).toInt, a) * 15
if (rotateAngle > 0)
{
normal = normal.transform(new Quaternion(Math.toRadians(rotateAngle), axis)).normalize
}
}
world.markBlockForUpdate(x.toInt, y.toInt, z.toInt)
}
if (world.getTotalWorldTime % 20 == 0)
cachedHits = List()
}
override def focus(newPosition: Vector3)
{
normal = ((newPosition - toVectorWorld) - 0.5).normalize
world.markBlockForUpdate(x.toInt, y.toInt, z.toInt)
}
override def getFocus: Vector3 = normal
def setFocus(focus: Vector3)
{
normal = focus
}
override def getCacheDirections: java.util.List[Vector3] = cachedHits.toList
override def onLaserHit(renderStart: Vector3, incidentDirection: Vector3, hit: MovingObjectPosition, color: Vector3, energy: Double): Boolean =
{
/**
* Cache hits
*/
cachedHits = incidentDirection :: cachedHits
/**
* Render incoming laser
*/
Electrodynamics.proxy.renderLaser(worldObj, renderStart, toVectorWorld + 0.5, color, energy)
/**
* Calculate Reflection
*/
val angle = Math.acos(incidentDirection $ normal)
val axisOfReflection = incidentDirection.cross(normal)
val rotateAngle = 2 * angle - Math.PI
if (rotateAngle < Math.PI)
{
val newDirection = (incidentDirection.clone.transform(new Quaternion(rotateAngle, axisOfReflection))).normalize
Laser.spawn(worldObj, toVectorWorld+ 0.5 + newDirection * 0.9, toVectorWorld + 0.5, newDirection, color, energy / 1.2)
}
return true
}
override def getDescriptionPacket: Packet =
{
val nbt = new NBTTagCompound()
writeToNBT(nbt)
return new S35PacketUpdateTileEntity(x.toInt, y.toInt, z.toInt, 0, nbt)
}
override def writeToNBT(nbt: NBTTagCompound)
{
super.writeToNBT(nbt)
val normalNBT = new NBTTagCompound()
normal.writeNBT(normalNBT)
nbt.setTag("normal", normalNBT)
}
override def onDataPacket(net: NetworkManager, pkt: S35PacketUpdateTileEntity)
{
val receive = pkt.func_148857_g
readFromNBT(receive)
}
override def readFromNBT(nbt: NBTTagCompound)
{
super.readFromNBT(nbt)
normal = new Vector3(nbt.getCompoundTag("normal"))
}
@SideOnly(Side.CLIENT)
override def renderDynamic(pos: Vector3, frame: Float, pass: Int)
{
glPushMatrix()
glTranslated(pos.x + 0.5, pos.y + 0.5, pos.z + 0.5)
FMLClientHandler.instance.getClient.renderEngine.bindTexture(TileMirror.texture)
val angle = normal.toEulerAngle
glRotated(angle.yaw, 0, 1, 0)
glRotated(angle.pitch, 1, 0, 0)
glRotated(90, 1, 0, 0)
TileMirror.model.renderOnly("mirror", "mirrorBacking", "standConnector")
glPopMatrix()
}
@SideOnly(Side.CLIENT)
override def renderInventory(itemStack: ItemStack)
{
glPushMatrix()
FMLClientHandler.instance.getClient.renderEngine.bindTexture(TileMirror.texture)
TileMirror.model.renderAll()
glPopMatrix()
}
}