Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions src/main/scala/li/cil/oc/common/block/Item.scala
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,12 @@ class Item(value: Block, props: Properties) extends BlockItem(value, props) {
ctx.getLevel.getBlockEntity(ctxToUse.getClickedPos) match {
case keyboard: blockentity.Keyboard => // Ignore.
case rotatable: blockentity.traits.Rotatable =>
val physicalYaw = RotationHelper.fromYaw(ctxToUse.getPlayer.getYRot)
val localYaw = SableCompat.localFacing(ctxToUse.getLevel,
Vec3.atCenterOf(ctxToUse.getClickedPos), physicalYaw)
rotatable.setFromEntityPitchAndYaw(ctxToUse.getPlayer, localYaw)
if (!rotatable.validFacings.contains(rotatable.pitch)) {
rotatable.pitch = rotatable.validFacings.headOption.getOrElse(Direction.NORTH)
}
val localClickPos = Vec3.atCenterOf(ctxToUse.getClickedPos)
val forward = Vec3.directionFromRotation(ctxToUse.getPlayer.getXRot, ctxToUse.getPlayer.getYRot).reverse()
val side = Vec3.directionFromRotation(0, ctxToUse.getPlayer.getYRot + 90).reverse()
val localYaw = SableCompat.localHeading(ctxToUse.getLevel, localClickPos, forward, side)
val localPitch = SableCompat.localPitch(ctxToUse.getLevel, localClickPos, forward)
rotatable.setFromPitchAndYaw(localPitch.toFloat, localYaw.toFloat)
if (!rotatable.isInstanceOf[blockentity.RobotProxy]) {
rotatable.invertRotation()
}
Expand Down
15 changes: 13 additions & 2 deletions src/main/scala/li/cil/oc/common/blockentity/traits/Rotatable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ trait Rotatable extends RotationAware with internal.Rotatable {
pitch2Direction((entity.getXRot / 90).round + 1),
localYaw)

def setFromPitchAndYaw(localPitch: Float, localYaw: Float) =
trySetPitchYaw(
pitch2Direction((localPitch / 90).round + 1),
yaw2Direction((localYaw / 360 * 4).round & 3))

def setFromFacing(value: Direction) =
value match {
case Direction.DOWN | Direction.UP =>
Expand Down Expand Up @@ -135,6 +140,12 @@ trait Rotatable extends RotationAware with internal.Rotatable {

/** Validates new values against the allowed rotations as set in our block. */
protected def trySetPitchYaw(pitch: Direction, yaw: Direction) = {
var safePitch = pitch
var safeYaw = yaw
if (!pitch2Direction.contains(pitch))
safePitch = Direction.NORTH
if (!validFacings.contains(yaw))
safeYaw = validFacings.headOption.getOrElse(Direction.NORTH)
val oldState = getLevel.getBlockState(getBlockPos)
def setState(newState: BlockState): Boolean = {
if (oldState.hashCode() != newState.hashCode()) {
Expand All @@ -146,9 +157,9 @@ trait Rotatable extends RotationAware with internal.Rotatable {
}
getBlockState.getBlock match {
case rotatable if oldState.hasProperty(PropertyRotatable.Pitch) && oldState.hasProperty(PropertyRotatable.Yaw) =>
setState(oldState.setValue(PropertyRotatable.Pitch, pitch).setValue(PropertyRotatable.Yaw, yaw))
setState(oldState.setValue(PropertyRotatable.Pitch, safePitch).setValue(PropertyRotatable.Yaw, safeYaw))
case rotatable if oldState.hasProperty(PropertyRotatable.Facing) =>
setState(oldState.setValue(PropertyRotatable.Facing, yaw))
setState(oldState.setValue(PropertyRotatable.Facing, safeYaw))
case _ => false
}
}
Expand Down
47 changes: 45 additions & 2 deletions src/main/scala/li/cil/oc/util/SableCompat.scala
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,20 @@ object SableCompat {
}
}

/** Transform a world-space direction vector into a local-space vector.
*
* 'position' should be a location on the target sublevel
*/
def localDirection(level: Level, position: Vec3, facing: Vec3): Vec3 = {
if (facing == null) Vec3.ZERO
else if (level == null || position == null) facing
else {
val sublevel = SableCompanion.INSTANCE.getContaining(level, position)
if (sublevel == null) facing
else sublevel.logicalPose().transformNormalInverse(facing)
}
}

def distanceSquared(level: Level, a: Vec3, b: Vec3): Double = {
if (level == null) a.distanceToSqr(b)
else SableCompanion.INSTANCE.distanceSquaredWithSubLevels(level, a, b)
Expand All @@ -60,7 +74,7 @@ object SableCompat {
}
}

/** Get the transformed direction's horizontal heading in degrees.
/** Get the transformed direction's horizontal heading in degrees, converted from local-space to world-space.
*
* Zero points north (-Z), and values increase clockwise when viewed from
* above: east is 90, south is 180, and west is 270.
Expand All @@ -75,12 +89,41 @@ object SableCompat {
}
}

/** Get the transformed direction's elevation above the horizontal plane. */
/** Get the transformed direction's horizontal heading in degrees, converted from world-space to local-space.
*
* Zero points north (-Z), and values increase clockwise when viewed from
* above: east is 90, south is 180, and west is 270.
*/
def localHeading(level: Level, position: Vec3, facing: Vec3, side: Vec3): Double = {
var direction = localDirection(level, position, facing)
var horizontalLength = math.sqrt(direction.x * direction.x + direction.z * direction.z)
if (horizontalLength < 1.0e-3) { // Try to use the side/right vector to deduce yaw
direction = localDirection(level, position, side)
horizontalLength = math.sqrt(direction.x * direction.x + direction.z * direction.z)
if (horizontalLength < 1.0e-3) 0.0
else {
val heading = math.toDegrees(math.atan2(direction.z, direction.x)) % 360.0
if (heading < 0.0) heading + 360.0 else heading
}
}
else {
val heading = math.toDegrees(math.atan2(direction.x, -direction.z)) % 360.0
if (heading < 0.0) heading + 360.0 else heading
}
}

/** Get the transformed direction's elevation above the horizontal plane, converted from local-space to world-space. */
def physicalPitch(level: Level, position: Vec3, facing: Direction): Double = {
val direction = physicalDirection(level, position, facing)
math.toDegrees(math.atan2(direction.y, math.sqrt(direction.x * direction.x + direction.z * direction.z)))
}

/** Get the transformed direction's elevation above the horizontal plane, converted from world-space to local-space. */
def localPitch(level: Level, position: Vec3, facing: Vec3): Double = {
val direction = localDirection(level, position, facing)
math.toDegrees(math.atan2(direction.y, math.sqrt(direction.x * direction.x + direction.z * direction.z)))
}

/** Convert a physical cardinal direction into the local direction at a block. */
def localFacing(level: Level, position: Vec3, facing: Direction): Direction = {
if (level == null || position == null || facing == null) facing
Expand Down
Loading