1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
package at.hannibal2.skyhanni.utils
import net.minecraft.client.Minecraft
import net.minecraft.entity.Entity
import net.minecraft.util.AxisAlignedBB
import kotlin.math.max
import kotlin.math.min
object LocationUtils {
fun canSee(a: LorenzVec, b: LorenzVec) =
Minecraft.getMinecraft().theWorld.rayTraceBlocks(a.toVec3(), b.toVec3(), false, true, false) == null
fun playerLocation() = Minecraft.getMinecraft().thePlayer.getLorenzVec()
fun LorenzVec.distanceToPlayer() = distance(playerLocation())
fun LorenzVec.distanceToPlayerIgnoreY() = distanceIgnoreY(playerLocation())
fun LorenzVec.distanceSqToPlayer() = distanceSq(playerLocation())
fun LorenzVec.distanceToPlayerSqIgnoreY() = distanceSqIgnoreY(playerLocation())
fun Entity.distanceToPlayer() = getLorenzVec().distanceToPlayer()
fun Entity.distanceTo(location: LorenzVec) = getLorenzVec().distance(location)
fun Entity.distanceTo(other: Entity) = getLorenzVec().distance(other.getLorenzVec())
fun Entity.distanceToIgnoreY(location: LorenzVec) = getLorenzVec().distanceIgnoreY(location)
fun playerEyeLocation(): LorenzVec {
val player = Minecraft.getMinecraft().thePlayer
val vec = player.getLorenzVec()
return vec.add(y = player.getEyeHeight().toDouble())
}
fun AxisAlignedBB.isInside(vec: LorenzVec) = isVecInside(vec.toVec3())
fun AxisAlignedBB.isPlayerInside() = isInside(playerLocation())
fun LorenzVec.canBeSeen(radius: Double = 150.0): Boolean {
val a = playerEyeLocation()
val b = this
val noBlocks = canSee(a, b)
val notTooFar = a.distance(b) < radius
val inFov = true // TODO add Frustum "Frustum().isBoundingBoxInFrustum(entity.entityBoundingBox)"
return noBlocks && notTooFar && inFov
}
fun LorenzVec.canBeSeen(yOffsetRange: IntRange, radius: Double = 150.0): Boolean =
yOffsetRange.any { offset ->
this.add(y = offset).canBeSeen(radius)
}
fun AxisAlignedBB.minBox() = LorenzVec(minX, minY, minZ)
fun AxisAlignedBB.maxBox() = LorenzVec(maxX, maxY, maxZ)
fun AxisAlignedBB.rayIntersects(origin: LorenzVec, direction: LorenzVec): Boolean {
// Reference for Algorithm https://tavianator.com/2011/ray_box.html
val rayDirectionInverse = direction.inverse()
val t1 = (this.minBox() - origin) * rayDirectionInverse
val t2 = (this.maxBox() - origin) * rayDirectionInverse
val tmin = max(t1.minOfEachElement(t2).max(), Double.NEGATIVE_INFINITY)
val tmax = min(t1.maxOfEachElement(t2).min(), Double.POSITIVE_INFINITY)
return tmax >= tmin && tmax >= 0.0
}
fun AxisAlignedBB.union(aabbs: List<AxisAlignedBB>?): AxisAlignedBB? {
if (aabbs.isNullOrEmpty()) {
return null
}
var minX = this.minX
var minY = this.minY
var minZ = this.minZ
var maxX = this.maxX
var maxY = this.maxY
var maxZ = this.maxZ
aabbs.forEach { aabb ->
if (aabb.minX < minX) minX = aabb.minX
if (aabb.minY < minY) minY = aabb.minY
if (aabb.minZ < minZ) minZ = aabb.minZ
if (aabb.maxX > maxX) maxX = aabb.maxX
if (aabb.maxY > maxY) maxY = aabb.maxY
if (aabb.maxZ > maxZ) maxZ = aabb.maxZ
}
return AxisAlignedBB(minX, minY, minZ, maxX, maxY, maxZ)
}
fun AxisAlignedBB.getEdgeLengths() = maxBox() - minBox()
fun AxisAlignedBB.getCenter() = getEdgeLengths() * 0.5 + minBox()
fun AxisAlignedBB.getTopCenter() = getCenter().add(y = (maxY - minY) / 2)
fun AxisAlignedBB.clampTo(other: AxisAlignedBB): AxisAlignedBB {
val minX = max(this.minX, other.minX)
val minY = max(this.minY, other.minY)
val minZ = max(this.minZ, other.minZ)
val maxX = min(this.maxX, other.maxX)
val maxY = min(this.maxY, other.maxY)
val maxZ = min(this.maxZ, other.maxZ)
return AxisAlignedBB(minX, minY, minZ, maxX, maxY, maxZ)
}
}
|