Fixed cables and keyboards trying to push the player out of their blockspace.

This commit is contained in:
Florian Nücke 2015-01-13 17:45:49 +01:00
parent 5aa042d3e1
commit e5ff144a1c
10 changed files with 136 additions and 110 deletions

View File

@ -11,9 +11,13 @@ import net.minecraft.util.EnumFacing
import net.minecraft.world.IBlockAccess import net.minecraft.world.IBlockAccess
import net.minecraft.world.World import net.minecraft.world.World
class Assembler extends SimpleBlock with traits.SpecialBlock with traits.PowerAcceptor with traits.StateAware { class Assembler extends SimpleBlock with traits.PowerAcceptor with traits.StateAware {
setLightLevel(0.34f) setLightLevel(0.34f)
override def isOpaqueCube = false
override def isVisuallyOpaque = super.isVisuallyOpaque
override def isBlockSolid(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = side == EnumFacing.DOWN || side == EnumFacing.UP override def isBlockSolid(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = side == EnumFacing.DOWN || side == EnumFacing.UP
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //

View File

@ -29,8 +29,8 @@ import net.minecraftforge.fml.relauncher.SideOnly
import scala.collection.mutable.ArrayBuffer import scala.collection.mutable.ArrayBuffer
class Cable extends SimpleBlock with traits.Extended with traits.SpecialBlock { class Cable extends SimpleBlock with traits.Extended {
setLightOpacity(0) setLightOpacity(2)
// For Immibis Microblock support. // For Immibis Microblock support.
val ImmibisMicroblocks_TransformableBlockMarker = null val ImmibisMicroblocks_TransformableBlockMarker = null
@ -38,6 +38,8 @@ class Cable extends SimpleBlock with traits.Extended with traits.SpecialBlock {
// For FMP part coloring. // For FMP part coloring.
var colorMultiplierOverride: Option[Int] = None var colorMultiplierOverride: Option[Int] = None
// ----------------------------------------------------------------------- //
override protected def setDefaultExtendedState(state: IBlockState) = setDefaultState(state) override protected def setDefaultExtendedState(state: IBlockState) = setDefaultState(state)
override protected def addExtendedState(state: IBlockState, world: IBlockAccess, pos: BlockPos) = override protected def addExtendedState(state: IBlockState, world: IBlockAccess, pos: BlockPos) =
@ -54,6 +56,10 @@ class Cable extends SimpleBlock with traits.Extended with traits.SpecialBlock {
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
override def isOpaqueCube = false
override def isFullCube = false
@SideOnly(Side.CLIENT) override @SideOnly(Side.CLIENT) override
def colorMultiplier(world: IBlockAccess, pos: BlockPos, renderPass: Int) = colorMultiplierOverride.getOrElse(super.colorMultiplier(world, pos, renderPass)) def colorMultiplier(world: IBlockAccess, pos: BlockPos, renderPass: Int) = colorMultiplierOverride.getOrElse(super.colorMultiplier(world, pos, renderPass))
@ -72,7 +78,7 @@ class Cable extends SimpleBlock with traits.Extended with traits.SpecialBlock {
super.onNeighborBlockChange(world, pos, state, neighborBlock) super.onNeighborBlockChange(world, pos, state, neighborBlock)
} }
override protected def doSetBlockBoundsBasedOnState(world: IBlockAccess, pos: BlockPos): Unit = { override def setBlockBoundsBasedOnState(world: IBlockAccess, pos: BlockPos): Unit = {
setBlockBounds(Cable.bounds(world, pos)) setBlockBounds(Cable.bounds(world, pos))
} }
} }

View File

@ -15,12 +15,16 @@ import net.minecraft.world.World
import net.minecraftforge.fml.relauncher.Side import net.minecraftforge.fml.relauncher.Side
import net.minecraftforge.fml.relauncher.SideOnly import net.minecraftforge.fml.relauncher.SideOnly
class Hologram(val tier: Int) extends SimpleBlock with traits.SpecialBlock { class Hologram(val tier: Int) extends SimpleBlock {
setLightLevel(1) setLightLevel(1)
setBlockBounds(0, 0, 0, 1, 0.5f, 1) setBlockBounds(0, 0, 0, 1, 0.5f, 1)
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
override def isOpaqueCube = false
override def isFullCube = false
override def isBlockSolid(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = side == EnumFacing.DOWN override def isBlockSolid(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = side == EnumFacing.DOWN
@SideOnly(Side.CLIENT) @SideOnly(Side.CLIENT)

View File

@ -7,18 +7,27 @@ import li.cil.oc.common.tileentity
import net.minecraft.block.Block import net.minecraft.block.Block
import net.minecraft.block.state.IBlockState import net.minecraft.block.state.IBlockState
import net.minecraft.entity.player.EntityPlayer import net.minecraft.entity.player.EntityPlayer
import net.minecraft.util.AxisAlignedBB
import net.minecraft.util.BlockPos import net.minecraft.util.BlockPos
import net.minecraft.util.EnumFacing import net.minecraft.util.EnumFacing
import net.minecraft.world.IBlockAccess import net.minecraft.world.IBlockAccess
import net.minecraft.world.World import net.minecraft.world.World
import org.lwjgl.opengl.GL11 import org.lwjgl.opengl.GL11
class Keyboard extends SimpleBlock with traits.SpecialBlock with traits.OmniRotatable { class Keyboard extends SimpleBlock with traits.OmniRotatable {
setLightOpacity(0) setLightOpacity(0)
// For Immibis Microblock support. // For Immibis Microblock support.
val ImmibisMicroblocks_TransformableBlockMarker = null val ImmibisMicroblocks_TransformableBlockMarker = null
// ----------------------------------------------------------------------- //
override def isOpaqueCube = false
override def isFullCube = false
// ----------------------------------------------------------------------- //
override protected def setDefaultExtendedState(state: IBlockState) = setDefaultState(state) override protected def setDefaultExtendedState(state: IBlockState) = setDefaultState(state)
override def shouldSideBeRendered(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = true override def shouldSideBeRendered(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = true
@ -52,7 +61,7 @@ class Keyboard extends SimpleBlock with traits.SpecialBlock with traits.OmniRota
}) })
} }
override protected def doSetBlockBoundsBasedOnState(world: IBlockAccess, pos: BlockPos) = override def setBlockBoundsBasedOnState(world: IBlockAccess, pos: BlockPos) =
world.getTileEntity(pos) match { world.getTileEntity(pos) match {
case keyboard: tileentity.Keyboard => setBlockBounds(keyboard.pitch, keyboard.yaw) case keyboard: tileentity.Keyboard => setBlockBounds(keyboard.pitch, keyboard.yaw)
case _ => case _ =>
@ -71,9 +80,7 @@ class Keyboard extends SimpleBlock with traits.SpecialBlock with traits.OmniRota
val y1 = up.getFrontOffsetY * sizes(1) + side.getFrontOffsetY * sizes(2) - forward.getFrontOffsetY * 0.5f val y1 = up.getFrontOffsetY * sizes(1) + side.getFrontOffsetY * sizes(2) - forward.getFrontOffsetY * 0.5f
val z0 = -up.getFrontOffsetZ * sizes(1) - side.getFrontOffsetZ * sizes(2) - forward.getFrontOffsetZ * sizes(0) val z0 = -up.getFrontOffsetZ * sizes(1) - side.getFrontOffsetZ * sizes(2) - forward.getFrontOffsetZ * sizes(0)
val z1 = up.getFrontOffsetZ * sizes(1) + side.getFrontOffsetZ * sizes(2) - forward.getFrontOffsetZ * 0.5f val z1 = up.getFrontOffsetZ * sizes(1) + side.getFrontOffsetZ * sizes(2) - forward.getFrontOffsetZ * 0.5f
setBlockBounds( setBlockBounds(new AxisAlignedBB(x0, y0, z0, x1, y1, z1).offset(0.5, 0.5, 0.5))
math.min(x0, x1) + 0.5f, math.min(y0, y1) + 0.5f, math.min(z0, z1) + 0.5f,
math.max(x0, x1) + 0.5f, math.max(y0, y1) + 0.5f, math.max(z0, z1) + 0.5f)
} }
override def onNeighborBlockChange(world: World, pos: BlockPos, state: IBlockState, neighborBlock: Block) = override def onNeighborBlockChange(world: World, pos: BlockPos, state: IBlockState, neighborBlock: Block) =

View File

@ -11,18 +11,21 @@ import li.cil.oc.util.Rarity
import net.minecraft.block.state.IBlockState import net.minecraft.block.state.IBlockState
import net.minecraft.entity.player.EntityPlayer import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.util.BlockPos import net.minecraft.util._
import net.minecraft.util.EnumFacing
import net.minecraft.util.MovingObjectPosition
import net.minecraft.util.Vec3i
import net.minecraft.world.IBlockAccess import net.minecraft.world.IBlockAccess
import net.minecraft.world.World import net.minecraft.world.World
class RobotAfterimage extends SimpleBlock with traits.SpecialBlock { class RobotAfterimage extends SimpleBlock {
setLightOpacity(0) setLightOpacity(0)
setCreativeTab(null) setCreativeTab(null)
NEI.hide(this) NEI.hide(this)
// ----------------------------------------------------------------------- //
override def isOpaqueCube = false
override def isFullCube = false
override def shouldSideBeRendered(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = false override def shouldSideBeRendered(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = false
override def isBlockSolid(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = false override def isBlockSolid(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = false
@ -64,19 +67,16 @@ class RobotAfterimage extends SimpleBlock with traits.SpecialBlock {
} }
} }
override protected def doSetBlockBoundsBasedOnState(world: IBlockAccess, pos: BlockPos) { override def setBlockBoundsBasedOnState(world: IBlockAccess, pos: BlockPos) {
findMovingRobot(world, pos) match { findMovingRobot(world, pos) match {
case Some(robot) => case Some(robot) =>
val block = robot.getBlockType val block = robot.getBlockType
block.setBlockBoundsBasedOnState(world, robot.getPos) block.setBlockBoundsBasedOnState(world, robot.getPos)
val delta = robot.moveFrom.fold(Vec3i.NULL_VECTOR)(robot.getPos.subtract(_)) val delta = robot.moveFrom.fold(Vec3i.NULL_VECTOR)(robot.getPos.subtract(_))
setBlockBounds( setBlockBounds(new AxisAlignedBB(
block.getBlockBoundsMinX.toFloat + delta.getX, block.getBlockBoundsMinX, block.getBlockBoundsMinY, block.getBlockBoundsMinZ,
block.getBlockBoundsMinY.toFloat + delta.getY, block.getBlockBoundsMaxX, block.getBlockBoundsMaxY, block.getBlockBoundsMaxZ).
block.getBlockBoundsMinZ.toFloat + delta.getZ, offset(delta.getX, delta.getY, delta.getZ))
block.getBlockBoundsMaxX.toFloat + delta.getX,
block.getBlockBoundsMaxY.toFloat + delta.getY,
block.getBlockBoundsMaxZ.toFloat + delta.getZ)
case _ => // throw new Exception("Robot afterimage without a robot found. This is a bug!") case _ => // throw new Exception("Robot afterimage without a robot found. This is a bug!")
} }
} }

View File

@ -26,7 +26,7 @@ import net.minecraft.util._
import net.minecraft.world.IBlockAccess import net.minecraft.world.IBlockAccess
import net.minecraft.world.World import net.minecraft.world.World
class RobotProxy extends RedstoneAware with traits.SpecialBlock with traits.StateAware { class RobotProxy extends RedstoneAware with traits.StateAware {
setLightOpacity(0) setLightOpacity(0)
setCreativeTab(null) setCreativeTab(null)
NEI.hide(this) NEI.hide(this)
@ -39,6 +39,10 @@ class RobotProxy extends RedstoneAware with traits.SpecialBlock with traits.Stat
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
override def isOpaqueCube = false
override def isFullCube = false
override def shouldSideBeRendered(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = false override def shouldSideBeRendered(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = false
override def isBlockSolid(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = false override def isBlockSolid(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = false
@ -150,15 +154,15 @@ class RobotProxy extends RedstoneAware with traits.SpecialBlock with traits.Stat
private def gettingDropsForActualDrop = new Exception().getStackTrace.exists(element => getDropForRealDropCallers.contains(element.getClassName + "." + element.getMethodName)) private def gettingDropsForActualDrop = new Exception().getStackTrace.exists(element => getDropForRealDropCallers.contains(element.getClassName + "." + element.getMethodName))
protected override def intersect(world: World, pos: BlockPos, origin: Vec3, direction: Vec3) = { override def collisionRayTrace(world: World, pos: BlockPos, origin: Vec3, direction: Vec3) = {
val bounds = getCollisionBoundingBox(world, pos, world.getBlockState(pos)) val bounds = getCollisionBoundingBox(world, pos, world.getBlockState(pos))
world.getTileEntity(pos) match { world.getTileEntity(pos) match {
case proxy: tileentity.RobotProxy if proxy.robot.animationTicksLeft <= 0 && bounds.isVecInside(origin) => null case proxy: tileentity.RobotProxy if proxy.robot.animationTicksLeft <= 0 && bounds.isVecInside(origin) => null
case _ => super.intersect(world, pos, origin, direction) case _ => super.collisionRayTrace(world, pos, origin, direction)
} }
} }
protected override def doSetBlockBoundsBasedOnState(world: IBlockAccess, pos: BlockPos) { override def setBlockBoundsBasedOnState(world: IBlockAccess, pos: BlockPos) {
world.getTileEntity(pos) match { world.getTileEntity(pos) match {
case proxy: tileentity.RobotProxy => case proxy: tileentity.RobotProxy =>
val robot = proxy.robot val robot = proxy.robot
@ -169,7 +173,7 @@ class RobotProxy extends RedstoneAware with traits.SpecialBlock with traits.Stat
bounds.offset(delta.getX * remaining, delta.getY * remaining, delta.getZ * remaining) bounds.offset(delta.getX * remaining, delta.getY * remaining, delta.getZ * remaining)
} }
setBlockBounds(bounds) setBlockBounds(bounds)
case _ => super.doSetBlockBoundsBasedOnState(world, pos) case _ => super.setBlockBoundsBasedOnState(world, pos)
} }
} }

View File

@ -13,7 +13,7 @@ import net.minecraft.world.World
import net.minecraftforge.fml.relauncher.Side import net.minecraftforge.fml.relauncher.Side
import net.minecraftforge.fml.relauncher.SideOnly import net.minecraftforge.fml.relauncher.SideOnly
class ServerRack extends RedstoneAware with traits.SpecialBlock with traits.PowerAcceptor with traits.Rotatable with traits.StateAware { class ServerRack extends RedstoneAware with traits.PowerAcceptor with traits.Rotatable with traits.StateAware {
override protected def setDefaultExtendedState(state: IBlockState) = setDefaultState(state) override protected def setDefaultExtendedState(state: IBlockState) = setDefaultState(state)
@SideOnly(Side.CLIENT) @SideOnly(Side.CLIENT)

View File

@ -30,8 +30,57 @@ abstract class SimpleBlock(material: Material = Material.iron) extends BlockCont
protected val validRotations_ = Array(EnumFacing.UP, EnumFacing.DOWN) protected val validRotations_ = Array(EnumFacing.UP, EnumFacing.DOWN)
protected val bounds = new ThreadLocal[AxisAlignedBB]() {
override def initialValue() = new AxisAlignedBB(minX, minY, minZ, maxX, maxY, maxZ)
}
def createItemStack(amount: Int = 1) = new ItemStack(this, amount) def createItemStack(amount: Int = 1) = new ItemStack(this, amount)
// ----------------------------------------------------------------------- //
// Synchronized block size, because threading...
//
// These functions can mess things up badly in single player if not
// synchronized because the bounds fields are in an instance stored in the
// static block list... which is used by both server and client thread.
//
// Also, final getBlockBoundsMin/MaxX/Y/Z(), really?
// ----------------------------------------------------------------------- //
protected def setBlockBounds(bounds: AxisAlignedBB): Unit = {
this.bounds.set(bounds)
setBlockBounds(
bounds.minX.toFloat,
bounds.minY.toFloat,
bounds.minZ.toFloat,
bounds.maxX.toFloat,
bounds.maxY.toFloat,
bounds.maxZ.toFloat)
}
override def getCollisionBoundingBox(world: World, pos: BlockPos, state: IBlockState) = {
setBlockBoundsBasedOnState(world, pos)
new AxisAlignedBB(
pos.getX + bounds.get.minX, pos.getY + bounds.get.minY, pos.getZ + bounds.get.minZ,
pos.getX + bounds.get.maxX, pos.getY + bounds.get.maxY, pos.getZ + bounds.get.maxZ)
}
@SideOnly(Side.CLIENT)
override def getSelectedBoundingBox(world: World, pos: BlockPos): AxisAlignedBB = {
new AxisAlignedBB(
pos.getX + bounds.get.minX, pos.getY + bounds.get.minY, pos.getZ + bounds.get.minZ,
pos.getX + bounds.get.maxX, pos.getY + bounds.get.maxY, pos.getZ + bounds.get.maxZ)
}
@SideOnly(Side.CLIENT)
override def shouldSideBeRendered(world: IBlockAccess, pos: BlockPos, side: EnumFacing) =
(side == EnumFacing.DOWN && bounds.get.minY > 0) ||
(side == EnumFacing.UP && bounds.get.maxY < 1) ||
(side == EnumFacing.NORTH && bounds.get.minZ > 0) ||
(side == EnumFacing.SOUTH && bounds.get.maxZ < 1) ||
(side == EnumFacing.WEST && bounds.get.minX > 0) ||
(side == EnumFacing.EAST && bounds.get.maxX < 1) ||
!world.getBlockState(pos).getBlock.isOpaqueCube
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
// Rendering // Rendering
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
@ -144,40 +193,6 @@ abstract class SimpleBlock(material: Material = Material.iron) extends BlockCont
case _ => super.recolorBlock(world, pos, side, color) case _ => super.recolorBlock(world, pos, side, color)
} }
// This function can mess things up badly in single player if not
// synchronized because it sets fields in an instance stored in the
// static block list... which is used by both server and client thread.
// The other place where this is locked is in collisionRayTrace below,
// which seems to be the only built-in function that *logically* depends
// on the state bounds (rest is rendering which is unimportant).
final override def setBlockBoundsBasedOnState(world: IBlockAccess, pos: BlockPos) =
this.synchronized(doSetBlockBoundsBasedOnState(world, pos))
protected def doSetBlockBoundsBasedOnState(world: IBlockAccess, pos: BlockPos): Unit =
super.setBlockBoundsBasedOnState(world, pos)
protected def setBlockBounds(bounds: AxisAlignedBB) {
setBlockBounds(
bounds.minX.toFloat,
bounds.minY.toFloat,
bounds.minZ.toFloat,
bounds.maxX.toFloat,
bounds.maxY.toFloat,
bounds.maxZ.toFloat)
}
// NOTE: must not be final for immibis microblocks to work.
override def collisionRayTrace(world: World, pos: BlockPos, origin: Vec3, end: Vec3) =
this.synchronized(intersect(world, pos, origin, end))
override def getCollisionBoundingBox(world: World, pos: BlockPos, state: IBlockState) = this.synchronized {
doSetBlockBoundsBasedOnState(world, pos)
super.getCollisionBoundingBox(world, pos, state)
}
protected def intersect(world: World, pos: BlockPos, origin: Vec3, end: Vec3) =
super.collisionRayTrace(world, pos, origin, end)
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
override def canConnectRedstone(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = false override def canConnectRedstone(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = false

View File

@ -1,14 +0,0 @@
package li.cil.oc.common.block.traits
import li.cil.oc.common.block.SimpleBlock
import net.minecraft.util.BlockPos
import net.minecraft.world.IBlockAccess
trait SpecialBlock extends SimpleBlock {
override def isNormalCube(world: IBlockAccess, pos: BlockPos) = false
override def isOpaqueCube = false
// TODO new equivalent?
// override def renderAsNormalBlock = false
}

View File

@ -228,24 +228,24 @@ class Drone(val world: World) extends Entity(world) with MachineHost with intern
override def entityInit() { override def entityInit() {
// Running or not. // Running or not.
dataWatcher.addObject(2, byte2Byte(0: Byte)) dataWatcher.addObject(5, byte2Byte(0: Byte))
// Target position. // Target position.
dataWatcher.addObject(3, float2Float(0f))
dataWatcher.addObject(4, float2Float(0f))
dataWatcher.addObject(5, float2Float(0f))
// Max acceleration.
dataWatcher.addObject(6, float2Float(0f)) dataWatcher.addObject(6, float2Float(0f))
dataWatcher.addObject(7, float2Float(0f))
dataWatcher.addObject(8, float2Float(0f))
// Max acceleration.
dataWatcher.addObject(9, float2Float(0f))
// Selected inventory slot. // Selected inventory slot.
dataWatcher.addObject(7, byte2Byte(0: Byte)) dataWatcher.addObject(10, byte2Byte(0: Byte))
// Current and maximum energy. // Current and maximum energy.
dataWatcher.addObject(8, int2Integer(0)) dataWatcher.addObject(11, int2Integer(0))
dataWatcher.addObject(9, int2Integer(100)) dataWatcher.addObject(12, int2Integer(100))
// Status text. // Status text.
dataWatcher.addObject(10, "") dataWatcher.addObject(13, "")
// Inventory size for client. // Inventory size for client.
dataWatcher.addObject(11, byte2Byte(0: Byte)) dataWatcher.addObject(14, byte2Byte(0: Byte))
// Light color. // Light color.
dataWatcher.addObject(12, int2Integer(0x66DD55)) dataWatcher.addObject(15, int2Integer(0x66DD55))
} }
def initializeAfterPlacement(stack: ItemStack, player: EntityPlayer, position: Vec3) { def initializeAfterPlacement(stack: ItemStack, player: EntityPlayer, position: Vec3) {
@ -272,50 +272,50 @@ class Drone(val world: World) extends Entity(world) with MachineHost with intern
components.connectComponents() components.connectComponents()
} }
def isRunning = dataWatcher.getWatchableObjectByte(2) != 0 def isRunning = dataWatcher.getWatchableObjectByte(5) != 0
def targetX = dataWatcher.getWatchableObjectFloat(3) def targetX = dataWatcher.getWatchableObjectFloat(6)
def targetY = dataWatcher.getWatchableObjectFloat(4) def targetY = dataWatcher.getWatchableObjectFloat(7)
def targetZ = dataWatcher.getWatchableObjectFloat(5) def targetZ = dataWatcher.getWatchableObjectFloat(8)
def targetAcceleration = dataWatcher.getWatchableObjectFloat(6) def targetAcceleration = dataWatcher.getWatchableObjectFloat(9)
def selectedSlot = dataWatcher.getWatchableObjectByte(7) & 0xFF def selectedSlot = dataWatcher.getWatchableObjectByte(10) & 0xFF
def globalBuffer = dataWatcher.getWatchableObjectInt(8) def globalBuffer = dataWatcher.getWatchableObjectInt(11)
def globalBufferSize = dataWatcher.getWatchableObjectInt(9) def globalBufferSize = dataWatcher.getWatchableObjectInt(12)
def statusText = dataWatcher.getWatchableObjectString(10) def statusText = dataWatcher.getWatchableObjectString(13)
def inventorySize = dataWatcher.getWatchableObjectByte(11) & 0xFF def inventorySize = dataWatcher.getWatchableObjectByte(14) & 0xFF
def lightColor = dataWatcher.getWatchableObjectInt(12) def lightColor = dataWatcher.getWatchableObjectInt(15)
def setRunning(value: Boolean) = dataWatcher.updateObject(2, byte2Byte(if (value) 1: Byte else 0: Byte)) def setRunning(value: Boolean) = dataWatcher.updateObject(5, byte2Byte(if (value) 1: Byte else 0: Byte))
// Round target values to low accuracy to avoid floating point errors accumulating. // Round target values to low accuracy to avoid floating point errors accumulating.
def targetX_=(value: Float): Unit = dataWatcher.updateObject(3, float2Float(math.round(value * 4) / 4f)) def targetX_=(value: Float): Unit = dataWatcher.updateObject(6, float2Float(math.round(value * 4) / 4f))
def targetY_=(value: Float): Unit = dataWatcher.updateObject(4, float2Float(math.round(value * 4) / 4f)) def targetY_=(value: Float): Unit = dataWatcher.updateObject(7, float2Float(math.round(value * 4) / 4f))
def targetZ_=(value: Float): Unit = dataWatcher.updateObject(5, float2Float(math.round(value * 4) / 4f)) def targetZ_=(value: Float): Unit = dataWatcher.updateObject(8, float2Float(math.round(value * 4) / 4f))
def targetAcceleration_=(value: Float): Unit = dataWatcher.updateObject(6, float2Float(math.max(0, math.min(maxAcceleration, value)))) def targetAcceleration_=(value: Float): Unit = dataWatcher.updateObject(9, float2Float(math.max(0, math.min(maxAcceleration, value))))
def selectedSlot_=(value: Int) = dataWatcher.updateObject(7, byte2Byte(value.toByte)) def selectedSlot_=(value: Int) = dataWatcher.updateObject(10, byte2Byte(value.toByte))
def globalBuffer_=(value: Int) = dataWatcher.updateObject(8, int2Integer(value)) def globalBuffer_=(value: Int) = dataWatcher.updateObject(11, int2Integer(value))
def globalBufferSize_=(value: Int) = dataWatcher.updateObject(9, int2Integer(value)) def globalBufferSize_=(value: Int) = dataWatcher.updateObject(12, int2Integer(value))
def statusText_=(value: String) = dataWatcher.updateObject(10, Option(value).map(_.lines.map(_.take(10)).take(2).mkString("\n")).getOrElse("")) def statusText_=(value: String) = dataWatcher.updateObject(13, Option(value).map(_.lines.map(_.take(10)).take(2).mkString("\n")).getOrElse(""))
def inventorySize_=(value: Int) = dataWatcher.updateObject(11, byte2Byte(value.toByte)) def inventorySize_=(value: Int) = dataWatcher.updateObject(14, byte2Byte(value.toByte))
def lightColor_=(value: Int) = dataWatcher.updateObject(12, int2Integer(value)) def lightColor_=(value: Int) = dataWatcher.updateObject(15, int2Integer(value))
@SideOnly(Side.CLIENT) @SideOnly(Side.CLIENT)
override def func_180426_a(x: Double, y: Double, z: Double, yaw: Float, pitch: Float, data: Int, unused: Boolean) { override def func_180426_a(x: Double, y: Double, z: Double, yaw: Float, pitch: Float, data: Int, unused: Boolean) {