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
|
package moe.nea.firmament.util
import io.github.moulberry.repo.constants.Islands
import io.github.moulberry.repo.constants.Islands.Warp
import kotlinx.serialization.Serializable
import kotlinx.serialization.serializer
import kotlin.math.sqrt
import kotlin.time.Duration.Companion.seconds
import net.minecraft.text.Text
import net.minecraft.util.math.Position
import moe.nea.firmament.annotations.Subscribe
import moe.nea.firmament.commands.thenExecute
import moe.nea.firmament.events.CommandEvent
import moe.nea.firmament.events.ProcessChatEvent
import moe.nea.firmament.repo.RepoManager
import moe.nea.firmament.util.data.Config
import moe.nea.firmament.util.data.ProfileSpecificDataHolder
object WarpUtil {
val warps: Sequence<Islands.Warp>
get() = RepoManager.neuRepo.constants.islands.warps
.asSequence()
.filter { it.warp !in ignoredWarps }
val ignoredWarps = setOf("carnival", "")
@Serializable
data class Data(
val excludedWarps: MutableSet<String> = mutableSetOf(),
)
@Config
object DConfig : ProfileSpecificDataHolder<Data>(serializer(), "warp-util", ::Data)
private var lastAttemptedWarp = ""
private var lastWarpAttempt = TimeMark.farPast()
fun findNearestWarp(island: SkyBlockIsland, pos: Position): Islands.Warp? {
return warps.asSequence().filter { it.mode == island.locrawMode }.minByOrNull {
if (DConfig.data?.excludedWarps?.contains(it.warp) == true) {
return@minByOrNull Double.MAX_VALUE
} else {
return@minByOrNull squaredDist(pos, it)
}
}
}
private fun squaredDist(pos: Position, warp: Warp): Double {
val dx = pos.x - warp.x
val dy = pos.y - warp.y
val dz = pos.z - warp.z
return dx * dx + dy * dy + dz * dz
}
fun teleportToNearestWarp(island: SkyBlockIsland, pos: Position) {
val nearestWarp = findNearestWarp(island, pos)
if (nearestWarp == null) {
MC.sendChat(Text.translatable("firmament.warp-util.no-warp-found", island.userFriendlyName))
return
}
if (island == SBData.skyblockLocation
&& sqrt(squaredDist(pos, nearestWarp)) > 1.1 * sqrt(squaredDist((MC.player ?: return).pos, nearestWarp))
) {
MC.sendChat(Text.translatable("firmament.warp-util.already-close", nearestWarp.warp))
return
}
MC.sendChat(Text.translatable("firmament.warp-util.attempting-to-warp", nearestWarp.warp))
lastWarpAttempt = TimeMark.now()
lastAttemptedWarp = nearestWarp.warp
MC.sendCommand("warp ${nearestWarp.warp}")
}
@Subscribe
fun clearUnlockedWarpsCommand(event: CommandEvent.SubCommand) {
event.subcommand("clearwarps") {
thenExecute {
DConfig.data?.excludedWarps?.clear()
DConfig.markDirty()
source.sendFeedback(Text.translatable("firmament.warp-util.clear-excluded"))
}
}
}
init {
ProcessChatEvent.subscribe("WarpUtil:processChat") {
if (it.unformattedString == "You haven't unlocked this fast travel destination!"
&& lastWarpAttempt.passedTime() < 2.seconds
) {
DConfig.data?.excludedWarps?.add(lastAttemptedWarp)
DConfig.markDirty()
MC.sendChat(Text.stringifiedTranslatable("firmament.warp-util.mark-excluded", lastAttemptedWarp))
lastWarpAttempt = TimeMark.farPast()
}
if (it.unformattedString.startsWith("You may now fast travel to")) {
DConfig.data?.excludedWarps?.clear()
DConfig.markDirty()
}
}
}
}
|