package codechicken.microblock import codechicken.core.vec.Cuboid6 import codechicken.core.vec.Scale import codechicken.core.vec.Vector3 import codechicken.core.raytracer.SelectionBox import codechicken.core.vec.TransformationList import codechicken.core.vec.AxisCycle import codechicken.core.vec.Rotation import codechicken.multipart.TMultiPart import codechicken.multipart.TNormalOcclusion import codechicken.multipart.JPartialOcclusion import codechicken.multipart.NormalOcclusionTest import codechicken.multipart.TileMultipart import codechicken.multipart.MultiPartRegistry import codechicken.core.lighting.LazyLightMatrix import codechicken.microblock.MicroMaterialRegistry.IMicroMaterial import cpw.mods.fml.relauncher.SideOnly import cpw.mods.fml.relauncher.Side import codechicken.scala.ScalaBridge._ import codechicken.core.raytracer.ExtendedMOP object EdgePlacement extends PlacementProperties { import codechicken.multipart.PartMap._ def microClass = EdgeMicroClass def placementGrid = EdgePlacementGrid def opposite(slot:Int, side:Int):Int = { if(slot < 0)//custom placement return slot val e = slot-15 return 15+(packEdgeBits(e, unpackEdgeBits(e)^(1<<(side>>1)))) } override def customPlacement(pmt:MicroblockPlacement):ExecutablePlacement = { if(pmt.size%2 == 1) return null val part = PostMicroClass.create(pmt.size, pmt.hit.sideHit>>1, pmt.material, pmt.world.isRemote) if(pmt.doExpand) { val hpart = pmt.htile.partList(ExtendedMOP.getData[(Int, _)](pmt.hit)._1) if(hpart.getType == PostMicroClass.getName) { val mpart = hpart.asInstanceOf[Microblock] if(mpart.material == pmt.material && mpart.getSize + pmt.size < 8) { part.shape = ((mpart.getSize+pmt.size)<<4|mpart.getShape).toByte return pmt.expand(mpart, part) } } } if(pmt.slot >= 0) return null if(pmt.internal && !pmt.oppMod) return pmt.internalPlacement(pmt.htile.asInstanceOf[TileMultipart], part) return pmt.externalPlacement(part) } } object EdgeMicroClass extends MicroblockClass { var aBounds:Array[Cuboid6] = new Array(256) for(s <- 0 until 12) { val rx = if((s&2) != 0) -1 else 1 val rz = if((s&1) != 0) -1 else 1 val transform = new TransformationList(new Scale(new Vector3(rx, 1, rz)), AxisCycle.cycles(s>>2)).at(Vector3.center) for(t <- 1 until 8) { val d = t/8D aBounds(t<<4|s) = new SelectionBox(new Cuboid6(0, 0, 0, d, 1, d)) .transform(transform).bound } } override def itemSlot = 15 def getName = "mcr_edge" def create(client:Boolean) = if(client) new EdgeMicroblockClient else new EdgeMicroblock def create(size:Int, slot:Int, material:Int, client:Boolean) = if(client) new EdgeMicroblockClient(size, slot, material) else new EdgeMicroblock(size, slot, material) def placementProperties = EdgePlacement override def sizeToVolume(size:Int) = size*size def getDisplayName(size:Int):String = size match { case 1 => "Strip" case 2 => "Post" case 4 => "Pillar" } } class EdgeMicroblockClient(shape$:Byte = 0, material$:Int = 0) extends EdgeMicroblock(shape$, material$) with CommonMicroblockClient { def this(size:Int, slot:Int, material:Int) = this((size<<4|(slot-15)).toByte, material) } class EdgeMicroblock(shape$:Byte = 0, material$:Int = 0) extends CommonMicroblock(shape$, material$) { def this(size:Int, slot:Int, material:Int) = this((size<<4|(slot-15)).toByte, material) def microClass = EdgeMicroClass def getBounds = EdgeMicroClass.aBounds(shape) override def getSlot = getShape+15 } object PostMicroClass { var aBounds:Array[Cuboid6] = new Array(256) for(s <- 0 until 3) { val transform = Rotation.sideRotations(s<<1).at(Vector3.center) for(t <- 2 until 8 by 2) { val d1 = 0.5-t/16D val d2 = 0.5+t/16D aBounds(t<<4|s) = new SelectionBox(new Cuboid6(d1, 0, d1, d2, 1, d2)) .transform(transform).bound } } def getName = "mcr_post" def create(client:Boolean) = if(client) new PostMicroblockClient else new PostMicroblock def create(size:Int, slot:Int, material:Int, client:Boolean) = if(client) new PostMicroblockClient(size, slot, material) else new PostMicroblock(size, slot, material) def register() = MultiPartRegistry.registerParts((_, c:Boolean) => create(c), getName) } class PostMicroblockClient(shape$:Byte = 0, material$:Int = 0) extends PostMicroblock(shape$, material$) with MicroblockClient { var renderBounds1:Cuboid6 = _ var renderBounds2:Cuboid6 = _ def this(size:Int, orient:Int, material:Int) = this((size<<4|orient).toByte, material) override def renderStatic(pos:Vector3, olm:LazyLightMatrix, pass:Int) { val mat = MicroMaterialRegistry.getMaterial(material) if(mat != null && pass == mat.getRenderPass) render(pos, olm, mat) } def render(pos:Vector3, olm:LazyLightMatrix, mat:IMicroMaterial) { renderCuboid(pos, olm, mat, renderBounds1, 0) if(renderBounds2 != null) renderCuboid(pos, olm, mat, renderBounds2, 0) } override def onPartChanged() { if(tile.worldObj.isRemote) recalcBounds() } def recalcBounds() { renderBounds1 = getBounds.copy renderBounds2 = null shrinkFace(getShape<<1) shrinkFace(getShape<<1|1) tile.partList.foreach(p => if(p.isInstanceOf[PostMicroblock] && p != this) shrinkPost(p.asInstanceOf[PostMicroblock]) ) } def shrinkFace(fside:Int) { val part = tile.partMap(fside) if(part != null && part.getType.equals("mcr_face")) MicroOcclusion.shrink(renderBounds1, part.asInstanceOf[CommonMicroblock].getBounds, fside) } def shrinkPost(post:PostMicroblock) { if(post == this) return if(thisShrinks(post)) { if(renderBounds2 == null) { renderBounds2 = renderBounds1.copy getShape match { case 0 => renderBounds2.min.y = 0.5; renderBounds1.max.y = 0.5 case 1 => renderBounds2.min.z = 0.5; renderBounds1.max.z = 0.5 case 2 => renderBounds2.min.x = 0.5; renderBounds1.max.x = 0.5 } } MicroOcclusion.shrink(renderBounds1, post.getBounds, getShape<<1|1) MicroOcclusion.shrink(renderBounds2, post.getBounds, getShape<<1) } } def thisShrinks(other:PostMicroblock):Boolean = { if(getSize != other.getSize) return getSize < other.getSize if(isTransparent != other.isTransparent) return isTransparent return getShape > other.getShape } } class PostMicroblock(shape$:Byte = 0, material$:Int = 0) extends Microblock(shape$, material$) with JPartialOcclusion with TNormalOcclusion { def this(size:Int, orient:Int, material:Int) = this((size<<4|orient).toByte, material) override def getType = PostMicroClass.getName def getBounds = PostMicroClass.aBounds(shape) def getOcclusionBoxes = Seq(getBounds) def getPartialOcclusionBoxes = getOcclusionBoxes override def itemSizes = EdgeMicroClass.itemSizes override def itemClassID = EdgeMicroClass.classID override def sizeToVolume(size:Int) = EdgeMicroClass.sizeToVolume(size) override def occlusionTest(npart:TMultiPart): Boolean = { if(npart.isInstanceOf[PostMicroblock]) return npart.asInstanceOf[PostMicroblock].getShape != getShape if(npart.getType.equals("mcr_face")) if(npart.asInstanceOf[CommonMicroblock].getSlot>>1 == getShape) return true return super.occlusionTest(npart) } }