Files
ForgeMultipart/codechicken/multipart/BlockMultipart.scala
T
Chicken-Bones 3fd8ff6d03 Added packet scheduler for managing part updates
Fixed improper AABB culling of multipart tiles
Fixed some bounding box highlight issues
Added ability for parts to override harvesting
2013-11-12 11:38:57 +10:00

329 lines
10 KiB
Scala

package codechicken.multipart
import java.util.List
import java.lang.Iterable
import net.minecraft.block.Block
import net.minecraft.block.material.Material
import net.minecraft.entity.Entity
import net.minecraft.util.AxisAlignedBB
import net.minecraft.world.World
import net.minecraftforge.common.ForgeDirection
import net.minecraft.util.Vec3
import net.minecraft.util.MovingObjectPosition
import java.util.LinkedList
import codechicken.lib.raytracer.IndexedCuboid6
import codechicken.lib.vec.Cuboid6
import codechicken.lib.raytracer.RayTracer
import codechicken.lib.vec.Vector3
import codechicken.lib.vec.BlockCoord
import net.minecraft.entity.player.EntityPlayer
import java.util.Random
import java.util.ArrayList
import net.minecraft.item.ItemStack
import net.minecraft.client.particle.EffectRenderer
import net.minecraft.client.Minecraft
import net.minecraft.util.Icon
import net.minecraft.client.renderer.texture.IconRegister
import codechicken.lib.render.TextureSpecial
import codechicken.lib.render.TextureUtils
import net.minecraft.world.IBlockAccess
import codechicken.lib.raytracer.ExtendedMOP
import scala.collection.JavaConversions._
import java.util.Collections
import codechicken.multipart.scalatraits.TTileChangeTile
object BlockMultipart
{
def getTile(world:IBlockAccess, x:Int, y:Int, z:Int):TileMultipart =
{
val tile = world.getBlockTileEntity(x, y, z)
if(tile.isInstanceOf[TileMultipart])
tile.asInstanceOf[TileMultipart]
else
null
}
def getClientTile(world:IBlockAccess, x:Int, y:Int, z:Int):TileMultipartClient =
{
val tile = world.getBlockTileEntity(x, y, z)
if(tile.isInstanceOf[TileMultipartClient])
tile.asInstanceOf[TileMultipartClient]
else
null
}
def reduceMOP(hit:MovingObjectPosition):(Int, ExtendedMOP) = {
val ehit = hit.asInstanceOf[ExtendedMOP]
val data:(Int, _) = ExtendedMOP.getData(hit)
return (data._1, new ExtendedMOP(ehit, data._2, ehit.dist))
}
def drawHighlight(world:World, player:EntityPlayer, hit:MovingObjectPosition, frame:Float):Boolean =
{
val tile = getTile(world, hit.blockX, hit.blockY, hit.blockZ)
if(tile == null)
return false
val (index, mop) = reduceMOP(hit)
if(tile.partList(index).drawHighlight(mop, player, frame))
return true
tile.partList(index).collisionRayTrace(RayTracer.getStartVec(player), RayTracer.getEndVec(player))
return false
}
}
/**
* Block class for all multiparts, should be internal use only.
*/
class BlockMultipart(id:Int) extends Block(id, Material.rock)
{
import BlockMultipart._
override def hasTileEntity(meta:Int = 0) = true
override def isBlockSolidOnSide(world:World, x:Int, y:Int, z:Int, side:ForgeDirection):Boolean =
{
return getTile(world, x, y, z) match {
case null => false
case tile => tile.isSolid(side.ordinal())
}
}
override def onNeighborBlockChange(world:World, x:Int, y:Int, z:Int, id:Int)
{
val tile = getTile(world, x, y, z)
if(tile != null)
tile.onNeighborBlockChange()
}
override def collisionRayTrace(world:World, x:Int, y:Int, z:Int, start:Vec3, end:Vec3):ExtendedMOP =
{
getTile(world, x, y, z) match {
case null => null
case tile => tile.collisionRayTrace(start, end)
}
}
def rayTraceAll(world:World, x:Int, y:Int, z:Int, start:Vec3, end:Vec3):Iterable[ExtendedMOP] =
{
getTile(world, x, y, z) match {
case null => Seq()
case tile => tile.rayTraceAll(start, end)
}
}
override def removeBlockByPlayer(world:World, player:EntityPlayer, x:Int, y:Int, z:Int):Boolean =
{
val hit = RayTracer.retraceBlock(world, player, x, y, z)
val tile = getTile(world, x, y, z)
if(hit == null || tile == null)
{
dropAndDestroy(world, x, y, z)
return true
}
val (index, mop) = reduceMOP(hit)
if(world.isRemote)
{
tile.partList(index).addDestroyEffects(mop, Minecraft.getMinecraft().effectRenderer)
return true
}
return tile.harvestPart(index, mop, player)
}
def dropAndDestroy(world:World, x:Int, y:Int, z:Int)
{
val tile = getTile(world, x, y, z)
if(tile != null && !world.isRemote)
tile.dropItems(getBlockDropped(world, x, y, z, 0, 0))
world.setBlockToAir(x, y, z)
}
override def quantityDropped(meta:Int, fortune:Int, random:Random) = 0
override def getBlockDropped(world:World, x:Int, y:Int, z:Int, meta:Int, fortune:Int):ArrayList[ItemStack] =
{
val ai = new ArrayList[ItemStack]()
if(world.isRemote)
return ai
val tile = getTile(world, x, y, z)
if(tile != null)
tile.partList.foreach(part => part.getDrops.foreach(item => ai.add(item)))
return ai
}
override def addCollisionBoxesToList(world:World, x:Int, y:Int, z:Int, ebb:AxisAlignedBB, list$:List[_], entity:Entity)
{
val list = list$.asInstanceOf[List[AxisAlignedBB]]
val tile = getTile(world, x, y, z)
if(tile != null)
tile.partList.foreach(part =>
part.getCollisionBoxes.foreach{c =>
val aabb = c.toAABB().offset(x, y, z)
if(aabb.intersectsWith(ebb))
list.add(aabb)
})
}
override def addBlockHitEffects(world:World, hit:MovingObjectPosition, effectRenderer:EffectRenderer):Boolean =
{
val tile = getClientTile(world, hit.blockX, hit.blockY, hit.blockZ)
if(tile != null) {
val (index, mop) = reduceMOP(hit)
tile.partList(index).addHitEffects(mop, effectRenderer)
}
return true
}
override def addBlockDestroyEffects(world:World, x:Int, y:Int, z:Int, s:Int, effectRenderer:EffectRenderer) = true
override def renderAsNormalBlock() = false
override def isOpaqueCube() = false
override def getRenderType() = TileMultipart.renderID
override def isAirBlock(world:World, x:Int, y:Int, z:Int):Boolean =
{
return getTile(world, x, y, z) match {
case null => true
case tile => tile.partList.isEmpty
}
}
override def isBlockReplaceable(world:World, x:Int, y:Int, z:Int) = isAirBlock(world, x, y, z)
override def getRenderBlockPass = 1
override def canRenderInPass(pass:Int):Boolean =
{
MultipartRenderer.pass = pass
return true
}
override def getPickBlock(hit:MovingObjectPosition, world:World, x:Int, y:Int, z:Int):ItemStack =
{
val tile = getTile(world, x, y, z)
if(tile != null)
{
val (index, mop) = reduceMOP(hit)
return tile.partList(index).pickItem(mop)
}
return null
}
override def getPlayerRelativeBlockHardness(player:EntityPlayer, world:World, x:Int, y:Int, z:Int):Float =
{
val hit = RayTracer.retraceBlock(world, player, x, y, z)
val tile = getTile(world, x, y, z)
if(hit != null && tile != null) {
val (index, mop) = reduceMOP(hit)
return tile.partList(index).getStrength(mop, player)/30F;
}
return 1/100F
}
/**
* Kludge to set PROTECTED blockIcon to a blank icon
*/
override def registerIcons(register:IconRegister)
{
val n = getUnlocalizedName();
val icon = TextureUtils.getBlankIcon(16, register);
setTextureName(icon.getIconName)
super.registerIcons(register)
}
override def getLightValue(world:IBlockAccess, x:Int, y:Int, z:Int):Int =
{
return getTile(world, x, y, z) match {
case null => 0
case tile => tile.getLightValue
}
}
override def randomDisplayTick(world:World, x:Int, y:Int, z:Int, random:Random)
{
val tile = getClientTile(world, x, y, z)
if(tile != null) tile.randomDisplayTick(random)
}
override def onBlockActivated(world:World, x:Int, y:Int, z:Int, player:EntityPlayer, side:Int, hitX:Float, hitY:Float, hitZ:Float):Boolean =
{
val hit = RayTracer.retraceBlock(world, player, x, y, z);
if(hit == null)
return false
val tile = getTile(world, x, y, z)
if(tile == null)
return false
val (index, mop) = reduceMOP(hit)
return tile.partList(index).activate(player, mop, player.getHeldItem)
}
override def onBlockClicked(world:World, x:Int, y:Int, z:Int, player:EntityPlayer)
{
val hit = RayTracer.retraceBlock(world, player, x, y, z);
if(hit == null)
return
val tile = getTile(world, x, y, z)
if(tile == null)
return
val (index, mop) = reduceMOP(hit)
tile.partList(index).click(player, mop, player.getHeldItem)
}
override def isProvidingStrongPower(world:IBlockAccess, x:Int, y:Int, z:Int, side:Int):Int =
{
return getTile(world, x, y, z) match {
case null => 0
case tile => tile.strongPowerLevel(side^1)
}
}
override def isProvidingWeakPower(world:IBlockAccess, x:Int, y:Int, z:Int, side:Int):Int =
{
return getTile(world, x, y, z) match {
case null => 0
case tile => tile.weakPowerLevel(side^1)
}
}
override def canConnectRedstone(world:IBlockAccess, x:Int, y:Int, z:Int, side:Int):Boolean =
{
return getTile(world, x, y, z) match {
case null => false
case tile => tile.canConnectRedstone(side)
}
}
override def onEntityCollidedWithBlock(world:World, x:Int, y:Int, z:Int, entity:Entity)
{
val tile = getTile(world, x, y, z)
if(tile != null)
tile.onEntityCollision(entity)
}
override def onNeighborTileChange(world:World, x:Int, y:Int, z:Int, tileX:Int, tileY:Int, tileZ:Int)
{
getTile(world, x, y, z) match {
case null => world.setBlockToAir(x, y, z)
case tile => tile.onNeighborTileChange(tileX, tileY, tileZ)
}
}
override def weakTileChanges() = true
override def canProvidePower = true
}