aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/moe/nea/firmament/features/world
diff options
context:
space:
mode:
authorLinnea Gräf <nea@nea.moe>2024-08-07 21:34:16 +0200
committerLinnea Gräf <nea@nea.moe>2024-08-07 21:34:16 +0200
commitb4f9ca21ef801bb3e39c53ae21bb6bf4398c94e9 (patch)
tree1f7928e5587b6d4d7ca071949f0a70bf81282c14 /src/main/kotlin/moe/nea/firmament/features/world
parent9b277bd897490d13ee4549a086e8d1b5f4cd0e10 (diff)
downloadfirmament-b4f9ca21ef801bb3e39c53ae21bb6bf4398c94e9.tar.gz
firmament-b4f9ca21ef801bb3e39c53ae21bb6bf4398c94e9.tar.bz2
firmament-b4f9ca21ef801bb3e39c53ae21bb6bf4398c94e9.zip
Add /firm npcs command
Diffstat (limited to 'src/main/kotlin/moe/nea/firmament/features/world')
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/world/NPCWaypoints.kt40
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/world/NavigableWaypoint.kt22
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/world/NavigationHelper.kt121
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/world/NpcWaypointGui.kt68
4 files changed, 251 insertions, 0 deletions
diff --git a/src/main/kotlin/moe/nea/firmament/features/world/NPCWaypoints.kt b/src/main/kotlin/moe/nea/firmament/features/world/NPCWaypoints.kt
new file mode 100644
index 0000000..592b8fa
--- /dev/null
+++ b/src/main/kotlin/moe/nea/firmament/features/world/NPCWaypoints.kt
@@ -0,0 +1,40 @@
+package moe.nea.firmament.features.world
+
+import moe.nea.firmament.annotations.Subscribe
+import moe.nea.firmament.commands.thenExecute
+import moe.nea.firmament.events.CommandEvent
+import moe.nea.firmament.events.ReloadRegistrationEvent
+import moe.nea.firmament.util.MoulConfigUtils
+import moe.nea.firmament.util.ScreenUtil
+
+object NPCWaypoints {
+
+ var allNpcWaypoints = listOf<NavigableWaypoint>()
+
+ @Subscribe
+ fun onRepoReloadRegistration(event: ReloadRegistrationEvent) {
+ event.repo.registerReloadListener {
+ allNpcWaypoints = it.items.items.values
+ .asSequence()
+ .filter { !it.island.isNullOrBlank() }
+ .map {
+ NavigableWaypoint.NPCWaypoint(it)
+ }
+ .toList()
+ }
+ }
+
+ @Subscribe
+ fun onOpenGui(event: CommandEvent.SubCommand) {
+ event.subcommand("npcs") {
+ thenExecute {
+ ScreenUtil.setScreenLater(MoulConfigUtils.loadScreen(
+ "npc_waypoints",
+ NpcWaypointGui(allNpcWaypoints),
+ null))
+ }
+ }
+ }
+
+
+}
diff --git a/src/main/kotlin/moe/nea/firmament/features/world/NavigableWaypoint.kt b/src/main/kotlin/moe/nea/firmament/features/world/NavigableWaypoint.kt
new file mode 100644
index 0000000..28a517f
--- /dev/null
+++ b/src/main/kotlin/moe/nea/firmament/features/world/NavigableWaypoint.kt
@@ -0,0 +1,22 @@
+package moe.nea.firmament.features.world
+
+import io.github.moulberry.repo.data.NEUItem
+import net.minecraft.util.math.BlockPos
+import moe.nea.firmament.util.SkyBlockIsland
+
+abstract class NavigableWaypoint {
+ abstract val name: String
+ abstract val position: BlockPos
+ abstract val island: SkyBlockIsland
+
+ data class NPCWaypoint(
+ val item: NEUItem,
+ ) : NavigableWaypoint() {
+ override val name: String
+ get() = item.displayName
+ override val position: BlockPos
+ get() = BlockPos(item.x, item.y, item.z)
+ override val island: SkyBlockIsland
+ get() = SkyBlockIsland.forMode(item.island)
+ }
+}
diff --git a/src/main/kotlin/moe/nea/firmament/features/world/NavigationHelper.kt b/src/main/kotlin/moe/nea/firmament/features/world/NavigationHelper.kt
new file mode 100644
index 0000000..acdfb86
--- /dev/null
+++ b/src/main/kotlin/moe/nea/firmament/features/world/NavigationHelper.kt
@@ -0,0 +1,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()
+ }
+ }
+}
diff --git a/src/main/kotlin/moe/nea/firmament/features/world/NpcWaypointGui.kt b/src/main/kotlin/moe/nea/firmament/features/world/NpcWaypointGui.kt
new file mode 100644
index 0000000..6146e50
--- /dev/null
+++ b/src/main/kotlin/moe/nea/firmament/features/world/NpcWaypointGui.kt
@@ -0,0 +1,68 @@
+package moe.nea.firmament.features.world
+
+import io.github.notenoughupdates.moulconfig.observer.ObservableList
+import io.github.notenoughupdates.moulconfig.xml.Bind
+import moe.nea.firmament.features.events.anniversity.AnniversaryFeatures.atOnce
+import moe.nea.firmament.keybindings.SavedKeyBinding
+
+class NpcWaypointGui(
+ val allWaypoints: List<NavigableWaypoint>,
+) {
+
+ data class NavigableWaypointW(val waypoint: NavigableWaypoint) {
+ @Bind
+ fun name() = waypoint.name
+
+ @Bind
+ fun isSelected() = NavigationHelper.targetWaypoint == waypoint
+
+ @Bind
+ fun click() {
+ if (SavedKeyBinding.isShiftDown()) {
+ NavigationHelper.targetWaypoint = waypoint
+ NavigationHelper.tryWarpNear()
+ } else if (isSelected()) {
+ NavigationHelper.targetWaypoint = null
+ } else {
+ NavigationHelper.targetWaypoint = waypoint
+ }
+ }
+ }
+
+ @JvmField
+ @field:Bind
+ var search: String = ""
+ var lastSearch: String? = null
+
+ @Bind("results")
+ fun results(): ObservableList<NavigableWaypointW> {
+ return results
+ }
+
+ @Bind
+ fun tick() {
+ if (search != lastSearch) {
+ updateSearch()
+ lastSearch = search
+ }
+ }
+
+ val results: ObservableList<NavigableWaypointW> = ObservableList(mutableListOf())
+
+ fun updateSearch() {
+ val split = search.split(" +".toRegex())
+ results.atOnce {
+ results.clear()
+ allWaypoints.filter { waypoint ->
+ if (search.isBlank()) {
+ true
+ } else {
+ split.all { waypoint.name.contains(it, ignoreCase = true) }
+ }
+ }.mapTo(results) {
+ NavigableWaypointW(it)
+ }
+ }
+ }
+
+}