aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
authorCalMWolfs <94038482+CalMWolfs@users.noreply.github.com>2024-09-25 05:04:42 +1000
committerGitHub <noreply@github.com>2024-09-24 21:04:42 +0200
commit262583b1abec71bcbe16c4cabe1f7fbab9d6bd50 (patch)
tree7529286e8ff332981202ba113f652ac0c420389b /src/main
parentf77477f5d22e33b34d1723b0c89dd08244b40f85 (diff)
downloadskyhanni-262583b1abec71bcbe16c4cabe1f7fbab9d6bd50.tar.gz
skyhanni-262583b1abec71bcbe16c4cabe1f7fbab9d6bd50.tar.bz2
skyhanni-262583b1abec71bcbe16c4cabe1f7fbab9d6bd50.zip
Backend: Add pages to /shnavigate (#2583)
Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com>
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/commands/HelpCommand.kt61
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/pathfind/NavigationHelper.kt39
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/reminders/ReminderManager.kt80
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/chat/Text.kt77
4 files changed, 126 insertions, 131 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/features/commands/HelpCommand.kt b/src/main/java/at/hannibal2/skyhanni/features/commands/HelpCommand.kt
index 0f07c47f8..2eb5dc3fb 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/commands/HelpCommand.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/commands/HelpCommand.kt
@@ -3,14 +3,9 @@ package at.hannibal2.skyhanni.features.commands
import at.hannibal2.skyhanni.config.commands.Commands
import at.hannibal2.skyhanni.utils.StringUtils.splitLines
import at.hannibal2.skyhanni.utils.chat.Text
-import at.hannibal2.skyhanni.utils.chat.Text.asComponent
-import at.hannibal2.skyhanni.utils.chat.Text.center
import at.hannibal2.skyhanni.utils.chat.Text.hover
-import at.hannibal2.skyhanni.utils.chat.Text.onClick
-import at.hannibal2.skyhanni.utils.chat.Text.send
import at.hannibal2.skyhanni.utils.chat.Text.suggest
import net.minecraft.util.IChatComponent
-import kotlin.math.ceil
object HelpCommand {
@@ -35,57 +30,21 @@ object HelpCommand {
}
}
- private fun showPage(
- page: Int,
- search: String,
- commands: List<Commands.CommandInfo>,
- ) {
+ private fun showPage(page: Int, search: String, commands: List<Commands.CommandInfo>) {
val filtered = commands.filter {
it.name.contains(search, ignoreCase = true) || it.description.contains(search, ignoreCase = true)
}
- val maxPage = if (filtered.isNotEmpty()) {
- ceil(filtered.size.toDouble() / COMMANDS_PER_PAGE).toInt()
- } else 1
- val page = page.coerceIn(1, maxPage)
- val title = if (search.isEmpty()) "§6SkyHanni Commands" else "§6SkyHanni Commands matching '$search'"
+ val title = if (search.isBlank()) "SkyHanni Commands" else "SkyHanni Commands Matching: \"$search\""
- val text = mutableListOf<IChatComponent>()
-
- text.add(Text.createDivider())
- text.add(title.asComponent().center())
- text.add(
- Text.join(
- if (page > 1) "§6§l<<".asComponent {
- this.hover = "§eClick to view page ${page - 1}".asComponent()
- this.onClick { showPage(page - 1, search, commands) }
- } else null,
- " ",
- "§6(Page $page of $maxPage)",
- " ",
- if (page < maxPage) "§6§l>>".asComponent {
- this.hover = "§eClick to view page ${page + 1}".asComponent()
- this.onClick { showPage(page + 1, search, commands) }
- } else null,
- ).center(),
- )
- text.add(Text.createDivider())
-
- if (filtered.isEmpty()) {
- text.add(Text.EMPTY)
- text.add("§cNo commands found.".asComponent().center())
- text.add(Text.EMPTY)
- } else {
- val start = (page - 1) * COMMANDS_PER_PAGE
- val end = (page * COMMANDS_PER_PAGE).coerceAtMost(filtered.size)
- for (i in start until end) {
- text.add(createCommandEntry(filtered[i]))
- }
- }
-
- text.add(Text.createDivider())
-
- Text.multiline(text).send(HELP_ID)
+ Text.displayPaginatedList(
+ title,
+ filtered,
+ chatLineId = HELP_ID,
+ emptyMessage = "No commands found.",
+ currentPage = page,
+ maxPerPage = COMMANDS_PER_PAGE,
+ ) { createCommandEntry(it) }
}
fun onCommand(args: Array<String>, commands: List<Commands.CommandInfo>) {
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/pathfind/NavigationHelper.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/pathfind/NavigationHelper.kt
index 3e15e404c..7f67dd98c 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/misc/pathfind/NavigationHelper.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/pathfind/NavigationHelper.kt
@@ -6,18 +6,16 @@ import at.hannibal2.skyhanni.data.model.GraphNode
import at.hannibal2.skyhanni.data.model.GraphNodeTag
import at.hannibal2.skyhanni.data.model.findShortestDistance
import at.hannibal2.skyhanni.utils.CollectionUtils.sorted
-import at.hannibal2.skyhanni.utils.LorenzUtils.round
+import at.hannibal2.skyhanni.utils.NumberUtil.roundTo
import at.hannibal2.skyhanni.utils.chat.Text
import at.hannibal2.skyhanni.utils.chat.Text.asComponent
-import at.hannibal2.skyhanni.utils.chat.Text.center
import at.hannibal2.skyhanni.utils.chat.Text.hover
import at.hannibal2.skyhanni.utils.chat.Text.onClick
import at.hannibal2.skyhanni.utils.chat.Text.send
import kotlinx.coroutines.launch
-import net.minecraft.util.IChatComponent
object NavigationHelper {
- private val NAVIGATION_CHAT_ID = -6457562
+ private const val NAVIGATION_CHAT_ID = -6457562
val allowedTags = listOf(
GraphNodeTag.NPC,
@@ -41,40 +39,41 @@ object NavigationHelper {
private fun doCommandAsync(args: Array<String>) {
val searchTerm = args.joinToString(" ").lowercase()
val distances = calculateDistances(searchTerm)
- val names = calculateNames(distances)
+ val locations = calculateNames(distances)
- val text = mutableListOf<IChatComponent>()
- text.add(Text.createDivider())
- text.add("§7Found ${names.size} locations ($searchTerm)".asComponent().center())
val goBack = {
onCommand(searchTerm.split(" ").toTypedArray())
IslandGraphs.stop()
}
- // TODO dont show a too long list, add pages
- for ((name, node) in names) {
- val distance = distances[node]!!.round(1)
+ val title = if (searchTerm.isBlank()) "SkyHanni Navigation Locations" else "SkyHanni Navigation Locations Matching: \"$searchTerm\""
+
+ Text.displayPaginatedList(
+ title,
+ locations,
+ chatLineId = NAVIGATION_CHAT_ID,
+ emptyMessage = "No locations found.",
+ ) { (name, node) ->
+ val distance = distances[node]!!.roundTo(1)
val component = "$name §e$distance".asComponent()
component.onClick {
IslandGraphs.pathFind(node.position)
sendNavigateMessage(name, goBack)
}
val tag = node.tags.first { it in allowedTags }
- // TODO include most closest area, if this is no area (type in area = forger in forge)
component.hover =
("§eClick to start navigating to\n" + "§7Type: §r${tag.displayName}\n" + "§7Distance: §e$distance blocks").asComponent()
- text.add(component)
+ component
}
- text.add(Text.createDivider())
- Text.multiline(text).send(NAVIGATION_CHAT_ID)
}
private fun sendNavigateMessage(name: String, goBack: () -> Unit) {
val componentText = "§7Navigating to §r$name".asComponent()
componentText.onClick(onClick = goBack)
+ componentText.hover = "§eClick to stop navigating and return to previous search".asComponent()
componentText.send(NAVIGATION_CHAT_ID)
}
- private fun calculateNames(distances: Map<GraphNode, Double>): MutableMap<String, GraphNode> {
+ private fun calculateNames(distances: Map<GraphNode, Double>): List<Pair<String, GraphNode>> {
val names = mutableMapOf<String, GraphNode>()
for (node in distances.sorted().keys) {
// hiding areas that are none
@@ -84,23 +83,23 @@ object NavigationHelper {
if (name in names) continue
names[name] = node
}
- return names
+ return names.toList()
}
private fun calculateDistances(
searchTerm: String,
): Map<GraphNode, Double> {
- val grapth = IslandGraphs.currentIslandGraph ?: return emptyMap()
+ val graph = IslandGraphs.currentIslandGraph ?: return emptyMap()
val closedNote = IslandGraphs.closedNote ?: return emptyMap()
- val nodes = grapth.nodes
+ val nodes = graph.nodes
val distances = mutableMapOf<GraphNode, Double>()
for (node in nodes) {
val name = node.name ?: continue
val remainingTags = node.tags.filter { it in allowedTags }
if (remainingTags.isEmpty()) continue
if (name.lowercase().contains(searchTerm)) {
- distances[node] = grapth.findShortestDistance(closedNote, node)
+ distances[node] = graph.findShortestDistance(closedNote, node)
}
if (remainingTags.size != 1) {
println("found node with invalid amount of tags: ${node.name} (${remainingTags.map { it.cleanName }}")
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/reminders/ReminderManager.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/reminders/ReminderManager.kt
index 1df878ac9..a4ee7bc6a 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/misc/reminders/ReminderManager.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/reminders/ReminderManager.kt
@@ -11,7 +11,6 @@ import at.hannibal2.skyhanni.utils.TimeUtils.format
import at.hannibal2.skyhanni.utils.TimeUtils.minutes
import at.hannibal2.skyhanni.utils.chat.Text
import at.hannibal2.skyhanni.utils.chat.Text.asComponent
-import at.hannibal2.skyhanni.utils.chat.Text.center
import at.hannibal2.skyhanni.utils.chat.Text.command
import at.hannibal2.skyhanni.utils.chat.Text.hover
import at.hannibal2.skyhanni.utils.chat.Text.send
@@ -49,65 +48,34 @@ object ReminderManager {
}
private fun listReminders(page: Int) {
- val reminders = getSortedReminders()
- val maxPage = (reminders.size + REMINDERS_PER_PAGE - 1) / REMINDERS_PER_PAGE
-
- listPage = page.coerceIn(0, maxPage)
-
- val text: MutableList<IChatComponent> = mutableListOf()
-
- text.add(Text.createDivider())
-
- text.add(
+ Text.displayPaginatedList(
+ "SkyHanni Reminders",
+ getSortedReminders(),
+ chatLineId = REMINDERS_LIST_ID,
+ emptyMessage = "No reminders found.",
+ currentPage = page,
+ maxPerPage = REMINDERS_PER_PAGE,
+ ) { reminderEntry ->
+ val id = reminderEntry.key
+ val reminder = reminderEntry.value
Text.join(
- if (listPage > 1) "§6§l<<".asComponent {
- hover = "§eClick to view page ${listPage - 1}".asComponent()
- command = "/shremind list ${listPage - 1}"
- } else null,
+ "§c✕".asComponent {
+ hover = "§7Click to remove".asComponent()
+ command = "/shremind remove -l $id"
+ }.wrap("§8[", "§8]"),
" ",
- "§6Reminders (Page $listPage of $maxPage)",
+ "§e✎".asComponent {
+ hover = "§7Click to start editing".asComponent()
+ suggest = "/shremind edit -l $id ${reminder.reason} "
+ }.wrap("§8[", "§8]"),
" ",
- if (listPage < maxPage) "§6§l>>".asComponent {
- hover = "§eClick to view page ${listPage + 1}".asComponent()
- command = "/shremind list ${listPage + 1}"
- } else null,
- ).center(),
- )
-
- if (reminders.isNotEmpty()) {
- for (i in (listPage - 1) * REMINDERS_PER_PAGE until listPage * REMINDERS_PER_PAGE) {
- if (i >= reminders.size) break
- val (id, reminder) = reminders[i]
-
- text.add(
- Text.join(
- "§c✕".asComponent {
- hover = "§7Click to remove".asComponent()
- command = "/shremind remove -l $id"
- }.wrap("§8[", "§8]"),
- " ",
- "§e✎".asComponent {
- hover = "§7Click to start editing".asComponent()
- suggest = "/shremind edit -l $id ${reminder.reason} "
- }.wrap("§8[", "§8]"),
- " ",
- "§6${reminder.formatShort()}".asComponent {
- hover = "§7${reminder.formatFull()}".asComponent()
- }.wrap("§8[", "§8]"),
- " ",
- "§7${reminder.reason}",
- ),
- )
- }
- } else {
- text.add(Text.EMPTY)
- text.add("§cNo reminders found.".asComponent().center())
- text.add(Text.EMPTY)
+ "§6${reminder.formatShort()}".asComponent {
+ hover = "§7${reminder.formatFull()}".asComponent()
+ }.wrap("§8[", "§8]"),
+ " ",
+ "§7${reminder.reason}",
+ )
}
-
- text.add(Text.createDivider())
-
- Text.join(*text.toTypedArray(), separator = Text.NEWLINE).send(REMINDERS_LIST_ID)
}
private fun createReminder(args: Array<String>) {
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/chat/Text.kt b/src/main/java/at/hannibal2/skyhanni/utils/chat/Text.kt
index 024550ec5..fe7486d0d 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/chat/Text.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/chat/Text.kt
@@ -60,6 +60,7 @@ object Text {
}
return this
}
+
fun IChatComponent.center(width: Int = Minecraft.getMinecraft().ingameGUI.chatGUI.chatWidth): IChatComponent {
val textWidth = this.width()
val spaceWidth = SPACE.width()
@@ -99,10 +100,78 @@ object Text {
this.command = "/shaction $token"
}
-
- fun createDivider() = Text.HYPHEN.fitToChat().style {
+ fun createDivider(dividerColor: EnumChatFormatting = EnumChatFormatting.BLUE) = HYPHEN.fitToChat().style {
strikethrough = true
- color = EnumChatFormatting.BLUE
+ color = dividerColor
+ }
+
+ /**
+ * Displays a paginated list of entries in the chat.
+ *
+ * @param title The title of the paginated list.
+ * @param list The list of entries to paginate and display.
+ * @param chatLineId The ID of the chat line for message updates.
+ * @param emptyMessage The message to display if the list is empty.
+ * @param currentPage The current page to display.
+ * @param maxPerPage The number of entries to display per page.
+ * @param dividerColor The color of the divider lines.
+ * @param formatter A function to format each entry into an IChatComponent.
+ */
+ fun <T> displayPaginatedList(
+ title: String,
+ list: List<T>,
+ chatLineId: Int,
+ emptyMessage: String,
+ currentPage: Int = 1,
+ maxPerPage: Int = 15,
+ dividerColor: EnumChatFormatting = EnumChatFormatting.BLUE,
+ formatter: (T) -> IChatComponent,
+ ) {
+ val text = mutableListOf<IChatComponent>()
+
+ val totalPages = (list.size + maxPerPage - 1) / maxPerPage
+ val page = if (totalPages == 0) 0 else currentPage
+
+ text.add(createDivider(dividerColor))
+ text.add("§6$title".asComponent().center())
+
+ if (totalPages > 1) {
+ text.add(
+ join(
+ if (page > 1) "§6§l<<".asComponent {
+ hover = "§eClick to view page ${page - 1}".asComponent()
+ onClick {
+ displayPaginatedList(title, list, chatLineId, emptyMessage, page - 1, maxPerPage, dividerColor, formatter)
+ }
+ } else null,
+ " ",
+ "§6(Page $page of $totalPages)",
+ " ",
+ if (page < totalPages) "§6§l>>".asComponent {
+ hover = "§eClick to view page ${page + 1}".asComponent()
+ onClick {
+ displayPaginatedList(title, list, chatLineId, emptyMessage, page + 1, maxPerPage, dividerColor, formatter)
+ }
+ } else null,
+ ).center(),
+ )
+ }
+
+ text.add(createDivider(dividerColor))
+
+ if (list.isNotEmpty()) {
+ val start = (page - 1) * maxPerPage
+ val end = (page * maxPerPage).coerceAtMost(list.size)
+ for (i in start until end) {
+ text.add(formatter(list[i]))
+ }
+ } else {
+ text.add(EMPTY)
+ text.add("§c$emptyMessage".asComponent().center())
+ text.add(EMPTY)
+ }
+
+ text.add(createDivider(dividerColor))
+ multiline(text).send(chatLineId)
}
-
}