nageyqma·git
HTTPS https://git.nageyqma.icu/nageyqma/odin_next.git SSH git@git.nageyqma.icu:nageyqma/odin_next.git

HTTPS 链接可直接 git clone;推送代码请使用 SSH。

4.1 KB · 117 行raw
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
package com.odtheking.odin.utils

import com.odtheking.odin.OdinMod.mc
import com.odtheking.odin.features.impl.dungeon.map.tile.RoomRotation
import net.minecraft.core.BlockPos
import net.minecraft.world.phys.AABB
import net.minecraft.world.phys.Vec3
import kotlin.math.cos
import kotlin.math.floor
import kotlin.math.sin

operator fun Vec3.component1(): Double = x
operator fun Vec3.component2(): Double = y
operator fun Vec3.component3(): Double = z

operator fun BlockPos.component1(): Int = x
operator fun BlockPos.component2(): Int = y
operator fun BlockPos.component3(): Int = z

operator fun Vec3.unaryMinus(): Vec3 = Vec3(-x, -y, -z)

fun Vec3.floorVec(): Vec3 =
    Vec3(floor(x), floor(y), floor(z))

fun Vec3.addVec(x: Number = 0.0, y: Number = 0.0, z: Number = 0.0): Vec3 =
    Vec3(this.x + x.toDouble(), this.y + y.toDouble(), this.z + z.toDouble())

/**
 * Rotates a BlockPos around the given rotation.
 * @param rotation The rotation to rotate around
 * @return The rotated BlockPos
 */
fun BlockPos.rotateAroundNorth(rotation: RoomRotation): BlockPos =
    when (rotation) {
        RoomRotation.NORTH -> BlockPos(-this.x, this.y, -this.z)
        RoomRotation.WEST ->  BlockPos(-this.z, this.y, this.x)
        RoomRotation.SOUTH -> BlockPos(this.x, this.y, this.z)
        RoomRotation.EAST ->  BlockPos(this.z, this.y, -this.x)
    }

fun Vec3.rotateAroundNorth(rotation: RoomRotation): Vec3 =
    when (rotation) {
        RoomRotation.NORTH -> Vec3(-this.x, this.y, -this.z)
        RoomRotation.WEST ->  Vec3(-this.z, this.y, this.x)
        RoomRotation.SOUTH -> Vec3(this.x, this.y, this.z)
        RoomRotation.EAST ->  Vec3(this.z, this.y, -this.x)
    }

/**
 * Rotates a BlockPos to the given rotation.
 * @param rotation The rotation to rotate to
 * @return The rotated BlockPos
 */
fun BlockPos.rotateToNorth(rotation: RoomRotation): BlockPos =
    when (rotation) {
        RoomRotation.NORTH -> BlockPos(-this.x, this.y, -this.z)
        RoomRotation.WEST ->  BlockPos(this.z, this.y, -this.x)
        RoomRotation.SOUTH -> BlockPos(this.x, this.y, this.z)
        RoomRotation.EAST ->  BlockPos(-this.z, this.y, this.x)
    }

fun Vec3.rotateToNorth(rotation: RoomRotation): Vec3 =
    when (rotation) {
        RoomRotation.NORTH -> Vec3(-this.x, this.y, -this.z)
        RoomRotation.WEST ->  Vec3(this.z, this.y, -this.x)
        RoomRotation.SOUTH -> Vec3(this.x, this.y, this.z)
        RoomRotation.EAST ->  Vec3(-this.z, this.y, this.x)
    }

fun isXZInterceptable(box: AABB, range: Double, pos: Vec3, yaw: Float, pitch: Float): Boolean {
    val start = pos.addVec(y = (mc.player?.eyeY ?: 0.0))
    val goal = start.add(getLook(yaw, pitch).multiply(range, range, range))

    return isVecInZ(start.intermediateWithXValue(goal, box.minX), box) ||
            isVecInZ(start.intermediateWithXValue(goal, box.maxX), box) ||
            isVecInX(start.intermediateWithZValue(goal, box.minZ), box) ||
            isVecInX(start.intermediateWithZValue(goal, box.maxZ), box)
}

private fun getLook(yaw: Float, pitch: Float): Vec3 {
    val f2 = -cos(-pitch * 0.017453292f).toDouble()
    return Vec3(
        sin(-yaw * 0.017453292f - 3.1415927f) * f2,
        sin(-pitch * 0.017453292f).toDouble(),
        cos(-yaw * 0.017453292f - 3.1415927f) * f2
    )
}

private fun isVecInX(vec: Vec3?, box: AABB): Boolean =
    vec != null && vec.x >= box.minX && vec.x <= box.maxX

private fun isVecInZ(vec: Vec3?, box: AABB): Boolean =
    vec != null && vec.z >= box.minZ && vec.z <= box.maxZ

private fun Vec3.intermediateWithXValue(goal: Vec3, x: Double): Vec3? {
    val dx = goal.x - this.x
    if (dx * dx < 1e-8) return null
    val t = (x - this.x) / dx
    return if (t in 0.0..1.0) Vec3(
        this.x + dx * t,
        this.y + (goal.y - this.y) * t,
        this.z + (goal.z - this.z) * t
    ) else null
}

private fun Vec3.intermediateWithZValue(goal: Vec3, z: Double): Vec3? {
    val dz = goal.z - this.z
    if (dz * dz < 1e-8) return null
    val t = (z - this.z) / dz
    return if (t in 0.0..1.0) Vec3(
        this.x + (goal.x - this.x) * t,
        this.y + (goal.y - this.y) * t,
        this.z + dz * t
    ) else null
}

val BlockPos.center: Vec3 get() = Vec3.atCenterOf(this)