mirror of
https://github.com/GTNewHorizons/ForgeMultipart.git
synced 2026-11-13 00:47:52 +00:00
Fixed improper AABB culling of multipart tiles Fixed some bounding box highlight issues Added ability for parts to override harvesting
329 lines
10 KiB
Scala
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
|
|
} |