diff --git a/src/main/kotlin/gg/skytils/skytilsmod/Skytils.kt b/src/main/kotlin/gg/skytils/skytilsmod/Skytils.kt
index 3c01a4d13..4e04f98c2 100644
--- a/src/main/kotlin/gg/skytils/skytilsmod/Skytils.kt
+++ b/src/main/kotlin/gg/skytils/skytilsmod/Skytils.kt
@@ -368,6 +368,7 @@ class Skytils {
cch.registerCommand(FragBotCommand)
cch.registerCommand(HollowWaypointCommand)
cch.registerCommand(LimboCommand)
+ cch.registerCommand(OrderedWaypointCommand)
cch.registerCommand(ScamCheckCommand)
cch.registerCommand(SlayerCommand)
diff --git a/src/main/kotlin/gg/skytils/skytilsmod/commands/impl/OrderedWaypointCommand.kt b/src/main/kotlin/gg/skytils/skytilsmod/commands/impl/OrderedWaypointCommand.kt
new file mode 100644
index 000000000..3cb2e3e95
--- /dev/null
+++ b/src/main/kotlin/gg/skytils/skytilsmod/commands/impl/OrderedWaypointCommand.kt
@@ -0,0 +1,103 @@
+/*
+ * Skytils - Hypixel Skyblock Quality of Life Mod
+ * Copyright (C) 2020-2023 Skytils
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package gg.skytils.skytilsmod.commands.impl
+
+import gg.essential.universal.UChat
+import gg.essential.universal.utils.MCClickEventAction
+import gg.essential.universal.wrappers.message.UMessage
+import gg.essential.universal.wrappers.message.UTextComponent
+import gg.skytils.skytilsmod.Skytils
+import gg.skytils.skytilsmod.commands.BaseCommand
+import gg.skytils.skytilsmod.features.impl.handlers.Waypoint
+import gg.skytils.skytilsmod.features.impl.handlers.WaypointCategory
+import gg.skytils.skytilsmod.features.impl.handlers.Waypoints
+import gg.skytils.skytilsmod.utils.SBInfo
+import gg.skytils.skytilsmod.utils.SkyblockIsland
+import gg.skytils.skytilsmod.utils.Utils
+import net.minecraft.client.entity.EntityPlayerSP
+import net.minecraft.command.WrongUsageException
+import kotlin.random.Random
+
+object OrderedWaypointCommand : BaseCommand("skytilsorderedwaypoint") {
+ private val lineId = Random.nextInt()
+ private var categoryCache = emptyList()
+ var trackedIsland: SkyblockIsland? = null
+ var trackedSet: MutableList? = null
+
+ private val categoryComparator: Comparator = Comparator.comparing {
+ it.name ?: ""
+ }.thenBy {
+ it.isExpanded
+ }.thenBy {
+ it.waypoints.size
+ }
+
+ override fun getCommandUsage(player: EntityPlayerSP): String =
+ "/${commandName}"
+
+ override fun processCommand(player: EntityPlayerSP, args: Array) {
+ if (!Utils.inSkyblock) throw WrongUsageException("You must be in Skyblock to use this command!")
+ if (args.isEmpty()) {
+ val isUnknownIsland = SkyblockIsland.entries.none { it.mode == SBInfo.mode }
+ categoryCache = Waypoints.categories.filter {
+ it.island.mode == SBInfo.mode || (isUnknownIsland && it.island == SkyblockIsland.Unknown)
+ }.sortedWith(categoryComparator)
+ }
+ val subcommand = args.getOrNull(0)
+ if (subcommand == null || subcommand == "selectmenu") {
+ val startIndex = args.getOrNull(1)?.toIntOrNull() ?: 0
+ val toIndex = startIndex + 10.coerceAtMost(categoryCache.size)
+ val list = categoryCache.subList(startIndex, toIndex)
+ UMessage("${Skytils.prefix} §bSelect a Waypoint Category!").apply {
+ chatLineId = lineId
+ list.withIndex().forEach { (i, c) ->
+ addTextComponent(UTextComponent("\n§a${c.name}§7 (${c.waypoints.size})").setClick(MCClickEventAction.RUN_COMMAND, "/${commandName} select ${i + startIndex}"))
+ }
+ if (startIndex >= 10) {
+ addTextComponent(UTextComponent("\n§7[§aPrevious§7]").setClick(MCClickEventAction.RUN_COMMAND, "/${commandName} selectmenu ${startIndex - 10}"))
+ }
+ if (toIndex < categoryCache.size) {
+ addTextComponent(UTextComponent("\n§7[§aNext§7]").setClick(MCClickEventAction.RUN_COMMAND, "/${commandName} selectmenu $toIndex"))
+ }
+ }.chat()
+ } else if (subcommand == "select") {
+ val category = categoryCache.getOrNull(args.getOrNull(1)?.toIntOrNull() ?: 0)
+ ?: throw WrongUsageException("Invalid category!")
+ UMessage("${Skytils.successPrefix} §aSelected category §b${category.name}§a!\n" +
+ "§b§lNote: this is a BETA feature!\n" +
+ "§bReport bugs on Discord!\n" +
+ "§bUpdates to waypoints will not be reflected."
+ ).apply {
+ chatLineId = lineId
+ }.chat()
+ trackedSet = category.waypoints.sortedBy { it.name }.toMutableList()
+ trackedIsland = category.island
+ } else if (subcommand == "stop") {
+ trackedSet = null
+ trackedIsland = null
+ UChat.chat("${Skytils.successPrefix} §aStopped tracking waypoints!")
+ }
+ }
+
+ fun doneTracking() {
+ trackedSet = null
+ trackedIsland = null
+ UChat.chat("${Skytils.successPrefix} §aDone tracking waypoints!")
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/gg/skytils/skytilsmod/features/impl/handlers/Waypoints.kt b/src/main/kotlin/gg/skytils/skytilsmod/features/impl/handlers/Waypoints.kt
index 30d6d9261..3776ad5db 100644
--- a/src/main/kotlin/gg/skytils/skytilsmod/features/impl/handlers/Waypoints.kt
+++ b/src/main/kotlin/gg/skytils/skytilsmod/features/impl/handlers/Waypoints.kt
@@ -21,6 +21,7 @@ import gg.essential.elementa.utils.withAlpha
import gg.essential.universal.UGraphics
import gg.essential.universal.UMatrixStack
import gg.skytils.skytilsmod.Skytils
+import gg.skytils.skytilsmod.commands.impl.OrderedWaypointCommand
import gg.skytils.skytilsmod.core.PersistentSave
import gg.skytils.skytilsmod.core.tickTimer
import gg.skytils.skytilsmod.events.impl.skyblock.LocrawReceivedEvent
@@ -31,6 +32,8 @@ import net.minecraft.util.BlockPos
import net.minecraftforge.client.event.RenderWorldLastEvent
import net.minecraftforge.event.world.WorldEvent
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import net.minecraftforge.fml.common.gameevent.TickEvent
+import net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent
import org.apache.commons.codec.binary.Base64
import org.apache.commons.codec.binary.Base64InputStream
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream
@@ -38,6 +41,7 @@ import java.awt.Color
import java.io.File
import java.io.Reader
import java.io.Writer
+import java.util.TreeSet
object Waypoints : PersistentSave(File(Skytils.modDir, "waypoints.json")) {
val categories = HashSet()
@@ -142,9 +146,25 @@ object Waypoints : PersistentSave(File(Skytils.modDir, "waypoints.json")) {
tickTimer(20, task = ::computeVisibleWaypoints)
}
+ @SubscribeEvent
+ fun onPlayerMove(event: ClientTickEvent) {
+ if (event.phase == TickEvent.Phase.END || mc.thePlayer?.hasMoved != true) return
+ if (SBInfo.mode != null && OrderedWaypointCommand.trackedIsland?.mode == SBInfo.mode) {
+ val tracked = OrderedWaypointCommand.trackedSet?.firstOrNull()
+ if (tracked == null) {
+ OrderedWaypointCommand.doneTracking()
+ } else if (tracked.pos.distanceSq(mc.thePlayer.position) < 2 * 2) {
+ OrderedWaypointCommand.trackedSet?.removeFirstOrNull()
+ }
+ }
+ }
+
@SubscribeEvent
fun onWorldRender(event: RenderWorldLastEvent) {
val matrixStack = UMatrixStack()
+ if (OrderedWaypointCommand.trackedIsland?.mode == SBInfo.mode) {
+ OrderedWaypointCommand.trackedSet?.firstOrNull()?.draw(event.partialTicks, matrixStack)
+ }
visibleWaypoints.forEach {
it.draw(event.partialTicks, matrixStack)
}
@@ -205,7 +225,6 @@ data class WaypointCategory(
@Serializable(with = SkyblockIsland.ModeSerializer::class)
var island: SkyblockIsland
)
-
@Serializable
data class Waypoint @OptIn(ExperimentalSerializationApi::class) constructor(
var name: String,