electrodynamics/src/main/scala/edx/mechanical/mech/process/grinder/TileGrindingWheel.scala

212 lines
6.8 KiB
Scala

package edx.mechanical.mech.process.grinder
import cpw.mods.fml.relauncher.{Side, SideOnly}
import edx.core.{Electrodynamics, Reference}
import edx.mechanical.mech.TileMechanical
import net.minecraft.block.material.Material
import net.minecraft.entity.Entity
import net.minecraft.entity.item.EntityItem
import net.minecraft.item.{ItemBlock, ItemStack}
import net.minecraft.util.{DamageSource, ResourceLocation}
import net.minecraftforge.client.model.AdvancedModelLoader
import net.minecraftforge.common.util.ForgeDirection
import org.lwjgl.opengl.GL11._
import resonantengine.api.edx.recipe.{MachineRecipes, RecipeType}
import resonantengine.lib.render.RenderUtility
import resonantengine.lib.transform.region.Cuboid
import resonantengine.lib.transform.rotation.AngleAxis
import resonantengine.lib.transform.vector.Vector3
import resonantengine.prefab.misc.Timer
/**
* The grinding wheel. This block will face the direction in which it can rotate.
* @author Calclavia
*/
object TileGrindingWheel
{
final val processTime = 20 * 20
/**
* A map of ItemStacks and their remaining grind-time left.
*/
final val grindingTimer = new Timer[EntityItem]
@SideOnly(Side.CLIENT)
final val model = AdvancedModelLoader.loadModel(new ResourceLocation(Reference.domain, Reference.modelPath + "grinder.obj"))
}
class TileGrindingWheel extends TileMechanical(Material.rock)
{
private final val requiredTorque: Long = 250
private var grindingItem: EntityItem = null
private var counter = 0d
mechanicalNode = new NodeGrinder(this)
bounds = new Cuboid(0.05f, 0.05f, 0.05f, 0.95f, 0.95f, 0.95f)
isOpaqueCube = false
normalRender = false
textureName = "material_steel_dark"
rotationMask = 0x3F
override def update()
{
super.update()
counter = Math.max(counter + Math.abs(mechanicalNode.torque), 0)
doWork()
}
def doWork()
{
if (canWork)
{
var didWork = false
if (grindingItem != null)
{
if (TileGrindingWheel.grindingTimer.containsKey(grindingItem) && !grindingItem.isDead && toVectorWorld.add(0.5).distance(new Vector3(grindingItem)) < 1)
{
val timeLeft: Int = TileGrindingWheel.grindingTimer.decrease(grindingItem)
if (timeLeft <= 0)
{
if (this.doGrind(grindingItem))
{
grindingItem.getEntityItem.stackSize -= 1;
if (grindingItem.getEntityItem.stackSize <= 0)
{
grindingItem.setDead()
TileGrindingWheel.grindingTimer.remove(grindingItem)
grindingItem = null
}
else
{
grindingItem.setEntityItemStack(grindingItem.getEntityItem)
TileGrindingWheel.grindingTimer.put(grindingItem, TileGrindingWheel.processTime)
}
}
}
else
{
grindingItem.delayBeforeCanPickup = 20
if (grindingItem.getEntityItem.getItem.isInstanceOf[ItemBlock])
{
Electrodynamics.proxy.renderBlockParticle(worldObj, new Vector3(grindingItem), new Vector3((Math.random - 0.5f) * 3, (Math.random - 0.5f) * 3, (Math.random - 0.5f) * 3), 3, 1)
}
else
{
worldObj.spawnParticle("crit", grindingItem.posX, grindingItem.posY, grindingItem.posZ, (Math.random - 0.5f) * 3, (Math.random - 0.5f) * 3, (Math.random - 0.5f) * 3)
}
}
didWork = true
}
else
{
TileGrindingWheel.grindingTimer.remove(grindingItem)
grindingItem = null
}
}
if (didWork)
{
if (this.ticks % 8 == 0)
{
worldObj.playSoundEffect(this.xCoord + 0.5, this.yCoord + 0.5, this.zCoord + 0.5, Reference.prefix + "grinder", 0.5f, 1)
}
counter -= requiredTorque
}
}
}
private def doGrind(entity: EntityItem): Boolean =
{
val itemStack: ItemStack = entity.getEntityItem
val results = MachineRecipes.instance.getOutput(RecipeType.SIFTER.name, itemStack)
for (resource <- results)
{
val outputStack: ItemStack = resource.getItemStack
if (!world.isRemote)
{
val entityItem: EntityItem = new EntityItem(this.worldObj, entity.posX, entity.posY - 1.2, entity.posZ, outputStack)
entityItem.delayBeforeCanPickup = 20
entityItem.motionX = 0
entityItem.motionY = 0
entityItem.motionZ = 0
world.spawnEntityInWorld(entityItem)
}
}
return results.length > 0
}
/**
* Can this machine work this tick?
*/
def canWork: Boolean = counter >= requiredTorque
override def collide(entity: Entity)
{
if (entity.isInstanceOf[EntityItem])
{
entity.asInstanceOf[EntityItem].age -= 1
}
if (canWork)
{
if (entity.isInstanceOf[EntityItem])
{
if (canGrind(entity.asInstanceOf[EntityItem].getEntityItem))
{
if (grindingItem == null)
{
grindingItem = entity.asInstanceOf[EntityItem]
}
if (!TileGrindingWheel.grindingTimer.containsKey(entity.asInstanceOf[EntityItem]))
{
TileGrindingWheel.grindingTimer.put(entity.asInstanceOf[EntityItem], TileGrindingWheel.processTime)
}
}
}
else
{
entity.attackEntityFrom(new DamageSource("grinder"), 2)
}
}
if (mechanicalNode.angularVelocity != 0)
{
//The velocity added should be tangent to the circle
val deltaVector = new Vector3(entity) - center
val deltaAngle = Math.toDegrees(mechanicalNode.angularVelocity / 20)
var dir = getDirection
dir = ForgeDirection.getOrientation(if (dir.ordinal() % 2 != 0) dir.ordinal() - 1 else dir.ordinal()).getOpposite
val rotation = new AngleAxis(deltaAngle, new Vector3(dir))
val deltaPos = deltaVector.transform(rotation) - deltaVector
val velocity = deltaPos / 20
entity.addVelocity(velocity.x, velocity.y, velocity.z)
}
}
def canGrind(itemStack: ItemStack): Boolean = MachineRecipes.instance.getOutput(RecipeType.SIFTER.name, itemStack).length > 0
override def renderDynamic(pos: Vector3, frame: Float, pass: Int): Unit =
{
glPushMatrix()
glTranslated(pos.x + 0.5, pos.y + 0.5, pos.z + 0.5)
glScalef(0.51f, 0.5f, 0.5f)
var dir = getDirection
dir = ForgeDirection.getOrientation(if (dir.ordinal() % 2 != 0) dir.ordinal() - 1 else dir.ordinal())
if (dir.offsetY == 0)
glRotated(90, 0, 1, 0)
else
glRotated(90, 0, 1, 0)
RenderUtility.rotateBlockBasedOnDirection(dir)
glRotated(Math.toDegrees(mechanicalNode.angle), 0, 0, 1)
RenderUtility.bind(Reference.blockTextureDirectory + "planks_oak.png")
TileGrindingWheel.model.renderAllExcept("teeth")
RenderUtility.bind(Reference.blockTextureDirectory + "cobblestone.png")
TileGrindingWheel.model.renderOnly("teeth")
glPopMatrix()
}
}