Skip to content

Instantly share code, notes, and snippets.

Created January 30, 2016 22:54
package temportalist.ropes.common.block
import javax.vecmath.{AxisAngle4f, Quat4f, Vector3f}
import com.google.common.collect.Lists
import net.minecraft.block.material.Material
import net.minecraft.block.properties.IProperty
import net.minecraft.block.state.{BlockState, IBlockState}
import net.minecraft.block.{Block, BlockFence}
import net.minecraft.entity.{EntityLeashKnot, EntityLivingBase}
import net.minecraft.item.{ItemStack, ItemBlock}
import net.minecraft.util.EnumFacing.{Axis, AxisDirection}
import net.minecraft.util.{BlockPos, EnumFacing}
import net.minecraft.world.{IBlockAccess, World}
import net.minecraftforge.client.model.TRSRTransformation
import net.minecraftforge.client.model.obj.OBJModel
import net.minecraftforge.client.model.obj.OBJModel.OBJState
import net.minecraftforge.common.property.{IExtendedBlockState, IUnlistedProperty}
import temportalist.origin.api.common.block.StateProperties._
import temportalist.origin.api.common.block.{BlockBase, StateProperties}
import temportalist.origin.api.common.lib.V3O
import temportalist.origin.api.common.utility.Cursor
import temportalist.ropes.common.entity.EntityRopeKnot
import temportalist.ropes.common.init.ModBlocks
/**
* Created by TheTemportalist on 1/18/2016.
*/
class BlockRope(mat: Material, itemBlock: Class[_ <: ItemBlock] = classOf[ItemBlockRope])
extends BlockBase(ModBlocks, mat, itemBlock = itemBlock) {
var BRIDGE_LENGTH: IProperty[Integer] = null
var BRIDGE_INDEX: IProperty[Integer] = null
this.setDefaultState(this.getBlockState.getBaseState.withProperty(AXIS, Axis.X))
override def setBlockBoundsBasedOnState(worldIn: IBlockAccess, pos: BlockPos): Unit = {
val axis = worldIn.getBlockState(pos).getValue(AXIS)
axis match {
case Axis.X => this.setBlockBounds(0.4375F, 0, 0, 0.5625F, 0.125F, 1F)
case Axis.Z => this.setBlockBounds(0, 0, 0.4275F, 0.5625F, 1, 0.5625F)
case Axis.Y => this.setBlockBounds(0.4375F, 0F, 0.4375F, 0.5625F, 1F, 0.5625F)
}
}
override def onBlockPlaced(worldIn: World, pos: BlockPos, facing: EnumFacing, hitX: Float,
hitY: Float, hitZ: Float, meta: Int, placer: EntityLivingBase): IBlockState = {
var state = this.getStateFromMeta(meta)
facing.getAxis match {
case Axis.Y =>
state = state.withProperty(AXIS, placer.getHorizontalFacing.getAxis)
case _ => state = state.withProperty(AXIS, Axis.Y)
}
state
}
override def createBlockState(): BlockState = {
val MAX_BRIDGE_LENGTH = 1
this.BRIDGE_LENGTH = StateProperties.createPropInt("bridge_length", 0, MAX_BRIDGE_LENGTH)
this.BRIDGE_INDEX = StateProperties.createPropInt("bridge_index", 0, MAX_BRIDGE_LENGTH)
this.createState(this,
Seq[IProperty[_]](AXIS, BRIDGE_LENGTH, BRIDGE_INDEX),
Seq[IUnlistedProperty[_]](OBJModel.OBJProperty.instance))
}
override def getExtendedState(state: IBlockState, world: IBlockAccess,
pos: BlockPos): IBlockState = {
//println(state.isInstanceOf[IExtendedBlockState])
state match {
case extended: IExtendedBlockState =>
val rot = new V3O(0, 0, 0)
//println(state.getValue(AXIS))
extended.getValue(AXIS) match {
case Axis.X => //rot.y += 90
case Axis.Y => rot.x += 90
case Axis.Z =>
}
//rot.x += 90
val offsetRot = this.updateSagLogic(state, world, pos)
if (offsetRot != null) {
}
println(rot)
extended.withProperty(OBJModel.OBJProperty.instance,
new OBJState(Lists.newArrayList(OBJModel.Group.ALL), true,
new TRSRTransformation(
new Vector3f(0, 0, 0), {
val quat = new Quat4f()
rot.x = 90
quat.mul({
val q = new Quat4f()
q.set(new AxisAngle4f(1, 0, 0, rot.x_f() / 180 * 3.14F))
q
})
/*
quat.mul({
val q = new Quat4f()
q.set(new AxisAngle4f(0, 1, 0, rot.y_f()))
q
})
quat.mul({
val q = new Quat4f()
q.set(new AxisAngle4f(0, 0, 1, rot.z_f()))
q
})
*/
quat
},
null, null)))
case _ => state
}
}
def updateSagLogic(state: IBlockState, worldIn: IBlockAccess, pos: BlockPos): (Float, V3O) = {
if (!worldIn.isInstanceOf[World]) return null
// https://www.desmos.com/calculator/rv0kzpd0n3
// m = 0.08xa^(-2)
// y = 0.04((x/a)^(2)-b)
// p1 = (l/2)^(2)
// a = p1 <= 25 ? 1 : l/10
// b = p1 <= 25 ? p1 : 25
val l = state.getValue(BRIDGE_LENGTH)
val x = state.getValue(BRIDGE_INDEX)
val p1 = Math.pow(l / 2, 2)
val a = if (p1 <= 25) 1 else l / 10
val b = Math.min(p1, 25)
val y = 0.04 * (Math.pow(x / a, 2) - b)
val m = 0.08 * x * Math.pow(a, -2)
state.getValue(AXIS) match {
case Axis.X => // rotate around Z
(y.toFloat, new V3O(0, 0, m))
case Axis.Z => // rotate around X
(y.toFloat, new V3O(m, 0, 0))
case _ => null
}
}
override def isOpaqueCube: Boolean = false
override def isFullCube: Boolean = false
override def isVisuallyOpaque: Boolean = false
override def getRenderType: Int = 3
override def getMetaFromState(state: IBlockState): Int = {
state.getValue(AXIS).ordinal()
}
override def getStateFromMeta(meta: Int): IBlockState = {
this.getBaseExtState.withProperty(AXIS, Axis.values()(meta))
}
override def usesOBJ: Boolean = true
override def hasCustomItemModel: Boolean = true
override def onNeighborBlockChange(worldIn: World, pos: BlockPos, state: IBlockState,
neighborBlock: Block): Unit = {
if (neighborBlock == this) {
println("notify min please")
this.notifyMinToUpdateLine(worldIn, pos, state)
}
}
def notifyMinToUpdateLine(world: World, pos: BlockPos, state: IBlockState): Unit = {
println("notifying something")
val axis = state.getValue(AXIS)
println(this.isEndRope(world, pos, state))
if (this.isEndRope(world, pos, state)) {
println("update")
this.updateLine(world, pos, state)
}
else {
val axisOffset = new V3O(axis, -1)
println("AxisOff: " + axisOffset)
val nextPos = new V3O(pos) + axisOffset
val nextState = nextPos.getBlockState(world)
println("try to notify " + nextPos)
val nextIsRope = nextState.getBlock == this && nextState.getValue(AXIS) == axis
println(nextIsRope)
if (nextIsRope) {
}
/*
if (nextState.getBlock == this && nextState.getValue(AXIS) == axis) {
println("notifying next")
this.notifyMinToUpdateLine(world, nextPos.toBlockPos, nextState)
}
else println("didnt notify")
*/
}
}
def updateLine(world: World, pos: BlockPos, state: IBlockState): Unit = {
println("updating from " + pos)
val axis = state.getValue(AXIS)
//return
def getLastPos(dir: AxisDirection): BlockPos = {
var currentPos = pos
var currentState = state
do {
currentPos = V3O.offset(currentPos, axis, dir)
currentState = world.getBlockState(currentPos)
} while (currentState.getBlock == this && currentState.getValue(AXIS) == axis)
currentPos
}
val posMin = new V3O(pos)
val posMax = new V3O(getLastPos(AxisDirection.POSITIVE))
val posMin_2D = posMin.copy().packAxis(axis)
val posMax_2D = posMax.copy().packAxis(axis)
val lengthOfBridge = (posMax_2D.x - posMin_2D.x).toInt
println(lengthOfBridge)
/*
for (i <- -lengthOfBridge / 2 until lengthOfBridge / 2) {
val blockPos = posMin + (axis, scale = i)
blockPos.getBlockState(world).
withProperty(BRIDGE_LENGTH, Int.box(lengthOfBridge)).
withProperty(BRIDGE_INDEX, Int.box(i))
blockPos.markBlockForUpdate(world)
}
*/
}
def shouldCheckForKnot: Boolean = true
def isEndRope(world: World, pos: BlockPos, state: IBlockState): Boolean = {
return !world.isAirBlock(pos.down())
val axis = state.getValue(AXIS)
def isRope(world: World, pos: BlockPos, doCheckKnot: Boolean = true): Boolean = {
if (world.getBlockState(pos).getBlock == this) return true
val checkDatKnot = if (!this.shouldCheckForKnot) doCheckKnot else false
if (checkDatKnot && world.getBlockState(pos).getBlock.isInstanceOf[BlockFence]) {
EntityLeashKnot.getKnotForPosition(world, pos) match {
case knot: EntityRopeKnot => return true
case _ =>
}
}
false
}
axis match {
case Axis.X =>
if (!(isRope(world, pos.add(1, 0, 0)) && isRope(world, pos.add(-1, 0, 0))))
return true
case Axis.Z =>
if (!(isRope(world, pos.add(0, 0, 1)) && isRope(world, pos.add(0, 0, -1))))
return true
case Axis.Y =>
if (!(isRope(world, pos.add(0, 1, 0), doCheckKnot = false) &&
isRope(world, pos.add(0, -1, 0), doCheckKnot = false)))
return true
case _ =>
}
false
}
def isValidAxis(axis: Axis): Boolean = true
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment