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
110
111
112
113
114
115
116
117
118
119
120
121
|
package moe.nea.firmament.features.world
import io.github.moulberry.repo.constants.Islands
import net.minecraft.text.Text
import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.Position
import net.minecraft.util.math.Vec3i
import moe.nea.firmament.annotations.Subscribe
import moe.nea.firmament.events.SkyblockServerUpdateEvent
import moe.nea.firmament.events.TickEvent
import moe.nea.firmament.events.WorldRenderLastEvent
import moe.nea.firmament.repo.RepoManager
import moe.nea.firmament.util.MC
import moe.nea.firmament.util.SBData
import moe.nea.firmament.util.SkyBlockIsland
import moe.nea.firmament.util.WarpUtil
import moe.nea.firmament.util.render.RenderInWorldContext
object NavigationHelper {
var targetWaypoint: NavigableWaypoint? = null
set(value) {
field = value
recalculateRoute()
}
var nextTeleporter: Islands.Teleporter? = null
private set
val Islands.Teleporter.toIsland get() = SkyBlockIsland.forMode(this.getTo())
val Islands.Teleporter.fromIsland get() = SkyBlockIsland.forMode(this.getFrom())
val Islands.Teleporter.blockPos get() = BlockPos(x.toInt(), y.toInt(), z.toInt())
@Subscribe
fun onWorldSwitch(event: SkyblockServerUpdateEvent) {
recalculateRoute()
}
fun recalculateRoute() {
val tp = targetWaypoint
val currentIsland = SBData.skyblockLocation
if (tp == null || currentIsland == null) {
nextTeleporter = null
return
}
val route = findRoute(currentIsland, tp.island, mutableSetOf())
nextTeleporter = route?.get(0)
}
private fun findRoute(
fromIsland: SkyBlockIsland,
targetIsland: SkyBlockIsland,
visitedIslands: MutableSet<SkyBlockIsland>
): MutableList<Islands.Teleporter>? {
var shortestChain: MutableList<Islands.Teleporter>? = null
for (it in RepoManager.neuRepo.constants.islands.teleporters) {
if (it.toIsland in visitedIslands) continue
if (it.fromIsland != fromIsland) continue
if (it.toIsland == targetIsland) return mutableListOf(it)
visitedIslands.add(fromIsland)
val nextRoute = findRoute(it.toIsland, targetIsland, visitedIslands) ?: continue
nextRoute.add(0, it)
if (shortestChain == null || shortestChain.size > nextRoute.size) {
shortestChain = nextRoute
}
visitedIslands.remove(fromIsland)
}
return shortestChain
}
@Subscribe
fun onMovement(event: TickEvent) { // TODO: add a movement tick event maybe?
val tp = targetWaypoint ?: return
val p = MC.player ?: return
if (p.squaredDistanceTo(tp.position.toCenterPos()) < 5 * 5) {
targetWaypoint = null
}
}
@Subscribe
fun drawWaypoint(event: WorldRenderLastEvent) {
val tp = targetWaypoint ?: return
val nt = nextTeleporter
RenderInWorldContext.renderInWorld(event) {
if (nt != null) {
waypoint(nt.blockPos,
Text.literal("Teleporter to " + nt.toIsland.userFriendlyName),
Text.literal("(towards " + tp.name + "§f)"))
} else if (tp.island == SBData.skyblockLocation) {
waypoint(tp.position,
Text.literal(tp.name))
}
}
}
fun tryWarpNear() {
val tp = targetWaypoint
if (tp == null) {
MC.sendChat(Text.literal("Could not find a waypoint to warp you to. Select one first."))
return
}
WarpUtil.teleportToNearestWarp(tp.island, tp.position.asPositionView())
}
}
fun Vec3i.asPositionView(): Position {
return object : Position {
override fun getX(): Double {
return this@asPositionView.x.toDouble()
}
override fun getY(): Double {
return this@asPositionView.y.toDouble()
}
override fun getZ(): Double {
return this@asPositionView.z.toDouble()
}
}
}
|