341 lines
9.9 KiB
Scala
341 lines
9.9 KiB
Scala
package edx.basic.fluid.gutter
|
|
|
|
import java.util.{ArrayList, List}
|
|
|
|
import cpw.mods.fml.relauncher.{Side, SideOnly}
|
|
import edx.basic.fluid.tank.TileTank
|
|
import edx.core.Reference
|
|
import edx.core.prefab.node.{NodeFluid, NodeFluidPressure, TileFluidProvider}
|
|
import net.minecraft.block.Block
|
|
import net.minecraft.block.material.Material
|
|
import net.minecraft.entity.Entity
|
|
import net.minecraft.entity.item.EntityItem
|
|
import net.minecraft.entity.player.EntityPlayer
|
|
import net.minecraft.item.ItemStack
|
|
import net.minecraft.tileentity.TileEntity
|
|
import net.minecraft.util.ResourceLocation
|
|
import net.minecraftforge.client.model.AdvancedModelLoader
|
|
import net.minecraftforge.common.util.ForgeDirection
|
|
import net.minecraftforge.fluids._
|
|
import org.lwjgl.opengl.GL11
|
|
import resonantengine.api.edx.recipe.{MachineRecipes, RecipeType}
|
|
import resonantengine.lib.render.{FluidRenderUtility, RenderUtility}
|
|
import resonantengine.lib.transform.region.Cuboid
|
|
import resonantengine.lib.transform.vector.Vector3
|
|
import resonantengine.lib.utility.FluidUtility
|
|
import resonantengine.lib.utility.inventory.InventoryUtility
|
|
import resonantengine.lib.wrapper.BitmaskWrapper._
|
|
|
|
import scala.collection.convert.wrapAll._
|
|
|
|
object TileGutter
|
|
{
|
|
@SideOnly(Side.CLIENT)
|
|
private val model = AdvancedModelLoader.loadModel(new ResourceLocation(Reference.domain, Reference.modelPath + "gutter.tcn"))
|
|
@SideOnly(Side.CLIENT)
|
|
private val texture = new ResourceLocation(Reference.domain, Reference.modelPath + "gutter.png")
|
|
}
|
|
|
|
/**
|
|
* The gutter, used for fluid transfer.
|
|
*
|
|
* @author Calclavia
|
|
*/
|
|
class TileGutter extends TileFluidProvider(Material.rock)
|
|
{
|
|
fluidNode = new NodeGutter(this)
|
|
fluidNode.asInstanceOf[NodeGutter].doPressureUpdate = false
|
|
|
|
fluidNode.onConnectionChanged = () =>
|
|
{
|
|
sendPacket(0)
|
|
}
|
|
|
|
fluidNode.onFluidChanged = () =>
|
|
{
|
|
if (!world.isRemote)
|
|
{
|
|
//TODO: Check if this is very costly
|
|
// UpdateTicker.world.enqueue(checkFluidAbove)
|
|
sendPacket(1)
|
|
}
|
|
}
|
|
|
|
textureName = "material_wood_surface"
|
|
isOpaqueCube = false
|
|
normalRender = false
|
|
bounds = new Cuboid(0, 0, 0, 1, 0.99, 1)
|
|
|
|
override def getCollisionBoxes: java.lang.Iterable[Cuboid] =
|
|
{
|
|
val list: List[Cuboid] = new ArrayList[Cuboid]
|
|
val thickness = 0.1f
|
|
|
|
if (!clientRenderMask.mask(ForgeDirection.DOWN))
|
|
{
|
|
list.add(new Cuboid(0.0F, 0.0F, 0.0F, 1.0F, thickness, 1.0F))
|
|
}
|
|
if (!clientRenderMask.mask(ForgeDirection.WEST))
|
|
{
|
|
list.add(new Cuboid(0.0F, 0.0F, 0.0F, thickness, 1.0F, 1.0F))
|
|
}
|
|
if (!clientRenderMask.mask(ForgeDirection.NORTH))
|
|
{
|
|
list.add(new Cuboid(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, thickness))
|
|
}
|
|
if (!clientRenderMask.mask(ForgeDirection.EAST))
|
|
{
|
|
list.add(new Cuboid(1.0F - thickness, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F))
|
|
}
|
|
if (!clientRenderMask.mask(ForgeDirection.SOUTH))
|
|
{
|
|
list.add(new Cuboid(0.0F, 0.0F, 1.0F - thickness, 1.0F, 1.0F, 1.0F))
|
|
}
|
|
return list
|
|
}
|
|
|
|
override def collide(entity: Entity)
|
|
{
|
|
if (fluidNode.getFluidAmount > 0)
|
|
{
|
|
for (i <- 2 to 6)
|
|
{
|
|
val dir: ForgeDirection = ForgeDirection.getOrientation(i)
|
|
val pressure: Int = fluidNode.asInstanceOf[NodeFluidPressure].pressure(dir)
|
|
val pos: Vector3 = toVectorWorld.add(dir)
|
|
val checkTile: TileEntity = pos.getTileEntity(world)
|
|
|
|
if (checkTile.isInstanceOf[TileGutter])
|
|
{
|
|
val deltaPressure: Int = pressure - checkTile.asInstanceOf[TileGutter].fluidNode.asInstanceOf[NodeFluidPressure].pressure(dir.getOpposite)
|
|
entity.motionX += 0.01 * dir.offsetX * deltaPressure
|
|
entity.motionY += 0.01 * dir.offsetY * deltaPressure
|
|
entity.motionZ += 0.01 * dir.offsetZ * deltaPressure
|
|
}
|
|
}
|
|
if (fluidNode.getFluid.getFluid.getTemperature >= 373)
|
|
{
|
|
entity.setFire(5)
|
|
}
|
|
else
|
|
{
|
|
entity.extinguish()
|
|
}
|
|
}
|
|
if (entity.isInstanceOf[EntityItem])
|
|
{
|
|
entity.noClip = true
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Called when the block is first added to the world
|
|
*/
|
|
override def onWorldJoin()
|
|
{
|
|
super.onWorldJoin()
|
|
checkFluidAbove()
|
|
}
|
|
|
|
override def onNeighborChanged(block: Block)
|
|
{
|
|
super.onNeighborChanged(block)
|
|
checkFluidAbove()
|
|
}
|
|
|
|
def checkFluidAbove()
|
|
{
|
|
if (!world.isRemote)
|
|
{
|
|
val posAbove = toVectorWorld + new Vector3(0, 1, 0)
|
|
val blockAbove = posAbove.getBlock
|
|
val tanks = findAllTanks
|
|
|
|
def drainAbove(doDrain: Boolean) =
|
|
{
|
|
val stack = FluidUtility.drainBlock(posAbove.world, posAbove, doDrain)
|
|
|
|
if (stack != null)
|
|
FluidUtility.fillAllTanks(tanks, stack, doDrain)
|
|
else
|
|
0
|
|
}
|
|
|
|
if (drainAbove(false) == FluidContainerRegistry.BUCKET_VOLUME)
|
|
drainAbove(true)
|
|
}
|
|
}
|
|
|
|
override def use(player: EntityPlayer, side: Int, vector3: Vector3): Boolean =
|
|
{
|
|
if (player.getCurrentEquippedItem != null)
|
|
{
|
|
val itemStack = player.getCurrentEquippedItem
|
|
val outputs = MachineRecipes.instance.getOutput(RecipeType.MIXER.name, itemStack)
|
|
|
|
if (outputs.length > 0)
|
|
{
|
|
if (!world.isRemote)
|
|
{
|
|
val drainAmount = 25
|
|
val drain = fluidNode.drain(ForgeDirection.UP, drainAmount, false)
|
|
|
|
if (drain != null && drain.amount > 0 && world.rand.nextFloat < 0.05)
|
|
{
|
|
outputs.map(_.getItemStack.copy).foreach(s => InventoryUtility.dropItemStack(world, new Vector3(player), s, 0))
|
|
itemStack.stackSize -= 1
|
|
if (itemStack.stackSize <= 0)
|
|
player.inventory.setInventorySlotContents(player.inventory.currentItem, null)
|
|
}
|
|
player.addExhaustion(0.1f)
|
|
fluidNode.drain(ForgeDirection.UP, drainAmount, true)
|
|
}
|
|
|
|
world.playSoundEffect(x + 0.5, y + 0.5, z + 0.5, "liquid.water", 0.5f, 1)
|
|
return true
|
|
}
|
|
|
|
return FluidUtility.playerActivatedFluidItem(findAllTanks, player, side)
|
|
}
|
|
return true
|
|
}
|
|
|
|
override def onFillRain()
|
|
{
|
|
if (!world.isRemote)
|
|
{
|
|
fill(ForgeDirection.UP, new FluidStack(FluidRegistry.WATER, 10), true)
|
|
}
|
|
}
|
|
|
|
@SideOnly(Side.CLIENT)
|
|
override def renderInventory(itemStack: ItemStack)
|
|
{
|
|
render(0, 0x0)
|
|
}
|
|
|
|
def render(meta: Int, sides: Int)
|
|
{
|
|
RenderUtility.bind(TileGutter.texture)
|
|
|
|
for (dir <- ForgeDirection.VALID_DIRECTIONS)
|
|
{
|
|
if (dir != ForgeDirection.UP && dir != ForgeDirection.DOWN)
|
|
{
|
|
GL11.glPushMatrix()
|
|
RenderUtility.rotateBlockBasedOnDirection(dir)
|
|
|
|
if (sides.mask(ForgeDirection.DOWN))
|
|
{
|
|
GL11.glTranslatef(0, -0.075f, 0)
|
|
GL11.glScalef(1, 1.15f, 1)
|
|
}
|
|
if (!sides.mask(dir))
|
|
{
|
|
TileGutter.model.renderOnly("left")
|
|
}
|
|
if (!sides.mask(dir) || !sides.mask(dir.getRotation(ForgeDirection.UP)))
|
|
{
|
|
TileGutter.model.renderOnly("backCornerL")
|
|
}
|
|
GL11.glPopMatrix()
|
|
}
|
|
}
|
|
|
|
if (!sides.mask(ForgeDirection.DOWN))
|
|
{
|
|
TileGutter.model.renderOnly("base")
|
|
}
|
|
}
|
|
|
|
override def renderDynamic(pos: Vector3, frame: Float, pass: Int)
|
|
{
|
|
GL11.glPushMatrix()
|
|
GL11.glTranslated(pos.x + 0.5, pos.y + 0.5, pos.z + 0.5)
|
|
|
|
render(0, clientRenderMask)
|
|
|
|
if (world != null)
|
|
{
|
|
val tank: IFluidTank = fluidNode
|
|
val percentageFilled = tank.getFluidAmount / tank.getCapacity.toDouble
|
|
|
|
if (percentageFilled > 0.1)
|
|
{
|
|
GL11.glPushMatrix()
|
|
GL11.glScaled(0.99, 0.99, 0.99)
|
|
val ySouthEast = FluidUtility.getAveragePercentageFilledForSides(classOf[TileGutter], percentageFilled, world, toVectorWorld, ForgeDirection.SOUTH, ForgeDirection.EAST)
|
|
val yNorthEast = FluidUtility.getAveragePercentageFilledForSides(classOf[TileGutter], percentageFilled, world, toVectorWorld, ForgeDirection.NORTH, ForgeDirection.EAST)
|
|
val ySouthWest = FluidUtility.getAveragePercentageFilledForSides(classOf[TileGutter], percentageFilled, world, toVectorWorld, ForgeDirection.SOUTH, ForgeDirection.WEST)
|
|
val yNorthWest = FluidUtility.getAveragePercentageFilledForSides(classOf[TileGutter], percentageFilled, world, toVectorWorld, ForgeDirection.NORTH, ForgeDirection.WEST)
|
|
FluidRenderUtility.renderFluidTesselation(tank, ySouthEast, yNorthEast, ySouthWest, yNorthWest)
|
|
GL11.glPopMatrix()
|
|
}
|
|
}
|
|
|
|
GL11.glPopMatrix()
|
|
}
|
|
|
|
//Recurse through all gutter blocks
|
|
private def findGutters(traverse: Set[NodeGutter] = Set(fluidNode.asInstanceOf[NodeGutter])): Set[NodeGutter] =
|
|
{
|
|
val current = traverse.last
|
|
var foundGutters = traverse
|
|
|
|
current.connections
|
|
.filter(g => g.isInstanceOf[NodeGutter] && !traverse.contains(g))
|
|
.map(_.asInstanceOf[NodeGutter])
|
|
.foreach(g => foundGutters ++= findGutters(traverse + g))
|
|
|
|
return foundGutters
|
|
}
|
|
|
|
private def findAllTanks = findGutters().map(_.getTank).toList
|
|
|
|
class NodeGutter(parent: TileFluidProvider) extends NodeFluidGravity(parent)
|
|
{
|
|
|
|
override def connect[B <: IFluidHandler](obj: B, dir: ForgeDirection) =
|
|
{
|
|
super.connect(obj, dir)
|
|
|
|
if (obj.isInstanceOf[NodeGutter])
|
|
clientRenderMask = clientRenderMask.openMask(dir)
|
|
}
|
|
|
|
override def clearConnections()
|
|
{
|
|
super.clearConnections()
|
|
clientRenderMask = 0x00
|
|
}
|
|
|
|
override def canConnect[B <: IFluidHandler](other: B, from: ForgeDirection): Boolean =
|
|
{
|
|
if (other.isInstanceOf[NodeFluid] && other.asInstanceOf[NodeFluid].parent.isInstanceOf[TileTank])
|
|
return false
|
|
|
|
return super.canConnect(other, from)
|
|
}
|
|
|
|
override def canFill(from: ForgeDirection, fluid: Fluid): Boolean =
|
|
{
|
|
return from != ForgeDirection.UP && !fluid.isGaseous
|
|
}
|
|
|
|
override def canDrain(from: ForgeDirection, fluid: Fluid): Boolean =
|
|
{
|
|
return from != ForgeDirection.UP && !fluid.isGaseous
|
|
}
|
|
|
|
override def fill(from: ForgeDirection, resource: FluidStack, doFill: Boolean): Int =
|
|
{
|
|
if (!resource.getFluid.isGaseous)
|
|
{
|
|
return super.fill(from, resource, doFill)
|
|
}
|
|
return 0
|
|
}
|
|
}
|
|
|
|
}
|