Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backend: /shgraphfindall #3100

Open
wants to merge 5 commits into
base: beta
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ import at.hannibal2.skyhanni.test.command.CopyScoreboardCommand
import at.hannibal2.skyhanni.test.command.TestChatCommand
import at.hannibal2.skyhanni.test.command.TrackParticlesCommand
import at.hannibal2.skyhanni.test.command.TrackSoundsCommand
import at.hannibal2.skyhanni.test.graph.GraphEditor
import at.hannibal2.skyhanni.utils.APIUtils
import at.hannibal2.skyhanni.utils.ExtendedChatColor
import at.hannibal2.skyhanni.utils.ItemPriceUtils
Expand Down Expand Up @@ -623,11 +622,6 @@ object Commands {
category = CommandCategory.DEVELOPER_TEST
callback { SkyHanniMod.repo.reloadLocalRepo() }
}
event.register("shgraph") {
description = "Enables the graph editor"
category = CommandCategory.DEVELOPER_TEST
callback { GraphEditor.commandIn() }
}
event.register("shrepopatterns") {
description = "See where regexes are loaded from"
category = CommandCategory.DEVELOPER_TEST
Expand Down
126 changes: 103 additions & 23 deletions src/main/java/at/hannibal2/skyhanni/test/graph/GraphEditor.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package at.hannibal2.skyhanni.test.graph

import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.api.event.HandleEvent
import at.hannibal2.skyhanni.config.commands.CommandCategory
import at.hannibal2.skyhanni.config.commands.CommandRegistrationEvent
import at.hannibal2.skyhanni.data.IslandGraphs
import at.hannibal2.skyhanni.data.IslandGraphs.pathFind
import at.hannibal2.skyhanni.data.model.Graph
import at.hannibal2.skyhanni.data.model.GraphNode
import at.hannibal2.skyhanni.data.model.GraphNodeTag
Expand All @@ -19,11 +23,11 @@ import at.hannibal2.skyhanni.utils.KeyboardManager.isKeyClicked
import at.hannibal2.skyhanni.utils.KeyboardManager.isKeyHeld
import at.hannibal2.skyhanni.utils.LocationUtils
import at.hannibal2.skyhanni.utils.LocationUtils.distanceToPlayer
import at.hannibal2.skyhanni.utils.LocationUtils.playerLocation
import at.hannibal2.skyhanni.utils.LorenzColor
import at.hannibal2.skyhanni.utils.LorenzUtils
import at.hannibal2.skyhanni.utils.LorenzVec
import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators
import at.hannibal2.skyhanni.utils.NumberUtil.roundTo
import at.hannibal2.skyhanni.utils.OSUtils
import at.hannibal2.skyhanni.utils.RaycastUtils
import at.hannibal2.skyhanni.utils.RenderUtils.draw3DLineNea
Expand All @@ -39,6 +43,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable
import java.awt.Color
import kotlin.math.min

@Suppress("LargeClass")
@SkyHanniModule
object GraphEditor {

Expand Down Expand Up @@ -97,6 +102,12 @@ object GraphEditor {
private val edgeDijkstraColor = LorenzColor.DARK_BLUE.addOpacity(150)
private val edgeSelectedColor = LorenzColor.DARK_RED.addOpacity(150)

private val nodesAlreadyFound = mutableListOf<LorenzVec>()
private val nodesToFind: List<LorenzVec>
get() = IslandGraphs.currentIslandGraph?.nodes?.map { it.position }?.filter { it !in nodesAlreadyFound }.orEmpty()
private var currentNodeToFind: LorenzVec? = null
private var active = false

@SubscribeEvent(priority = EventPriority.HIGHEST)
fun onRender(event: LorenzRenderWorldEvent) {
if (!isEnabled()) return
Expand Down Expand Up @@ -195,6 +206,54 @@ object GraphEditor {
input()
if (nodes.isEmpty()) return
closestNode = nodes.minBy { it.position.distanceSqToPlayer() }
handleAllNodeFind()

}

private fun handleAllNodeFind() {
if (!active) return

if (nodesToFind.isEmpty()) return
val closest = nodesToFind.minBy { it.distanceSqToPlayer() }
if (closest.distanceToPlayer() >= 3) return
nodesAlreadyFound.add(closest)

if (nodesToFind.isEmpty()) {
currentNodeToFind = null
ChatUtils.chat("Found all nodes on this island")
return
}

calculateNewAllNodeFind()
}

private fun calculateNewAllNodeFind(): LorenzVec {
val next = GraphUtils.findAllShortestDistancesOnCurrentIsland(
LocationUtils.playerLocation(),
).distances.keys.first { it.position in nodesToFind }.position

val max = IslandGraphs.currentIslandGraph?.nodes?.size ?: -1
val todo = nodesToFind.size
val done = max - todo
val percentage = (done.toDouble() / max.toDouble()) * 100
val node = GraphUtils.nearestNodeOnCurrentIsland(next)
node.pathFind(
"Progress: ${done.addSeparators()}/${max.addSeparators()} (${percentage.roundTo(2)}%)",
condition = { active },
)
currentNodeToFind = next
return next
}

private fun toggleFindAll() {
active = !active
if (active) {
nodesAlreadyFound.clear()
calculateNewAllNodeFind()
ChatUtils.chat("Graph navigation over all nodes started.")
} else {
ChatUtils.chat("Graph navigation over all nodes stopped.")
}
}

private fun LorenzRenderWorldEvent.drawNode(node: GraphingNode) {
Expand Down Expand Up @@ -260,8 +319,8 @@ object GraphEditor {
val quad1 = edge.node1.position + lineVec / 4.0
val quad2 = edge.node1.position + lineVec * (3.0 / 4.0)

val pyramidSize = lineVec.normalize()
.times(min(lineVec.length() / 10.0, 1.0)) * (if (edge.direction == EdgeDirection.ONE_TO_TWO) 1.0 else -1.0)
val pyramidSize =
lineVec.normalize().times(min(lineVec.length() / 10.0, 1.0)) * (if (edge.direction == EdgeDirection.ONE_TO_TWO) 1.0 else -1.0)

val lineOffsetVec = LorenzVec(0.5, 0.5, 0.5)

Expand All @@ -288,7 +347,21 @@ object GraphEditor {
else -> nodeColor
}

fun commandIn() {
@HandleEvent
fun onCommandRegistration(event: CommandRegistrationEvent) {
event.register("shgraph") {
description = "Enables the graph editor"
category = CommandCategory.DEVELOPER_TEST
callback { toggleFeature() }
}
event.register("shgraphfindall") {
description = "Navigate over the whole graph network"
category = CommandCategory.DEVELOPER_TEST
callback { toggleFindAll() }
}
}

fun toggleFeature() {
config.enabled = !config.enabled
if (config.enabled) {
ChatUtils.chat("Graph Editor is now active.")
Expand All @@ -299,7 +372,7 @@ object GraphEditor {

private fun chatAtDisable() = ChatUtils.clickableChat(
"Graph Editor is now inactive. §lClick to activate.",
GraphEditor::commandIn,
GraphEditor::toggleFeature,
)

private fun input() {
Expand Down Expand Up @@ -489,6 +562,9 @@ object GraphEditor {
if (config.useAsIslandArea) {
IslandGraphs.setNewGraph(compileGraph)
GraphEditorBugFinder.runTests()
if (active) {
calculateNewAllNodeFind()
}
}
val json = compileGraph.toJson()
OSUtils.copyToClipboard(json)
Expand Down Expand Up @@ -599,9 +675,8 @@ object GraphEditor {
}
val neighbours = GraphEditor.nodes.map { node ->
edges.filter { it.isInEdge(node) && it.isValidDirectionFrom(node) }.map { edge ->
val otherNode =
if (node == edge.node1) edge.node2
else edge.node1
val otherNode = if (node == edge.node1) edge.node2
else edge.node1
// TODO: Fix this to not use a bang bang
@Suppress("MapGetWithNotNullAssertionOperator")
nodes[indexedTable[otherNode.id]!!] to node.position.distance(otherNode.position)
Expand All @@ -628,20 +703,24 @@ object GraphEditor {
val neighbors = graph.map { node ->
// TODO: Fix this to not use bang bangs
@Suppress("MapGetWithNotNullAssertionOperator")
node.neighbours.map { GraphingEdge(translation[node]!!, translation[it.key]!!, EdgeDirection.ONE_TO_TWO) }
node.neighbours.map {
GraphingEdge(
translation[node]!!,
translation[it.key]!!,
EdgeDirection.ONE_TO_TWO,
)
}
}.flatten()

val reduced = neighbors.groupingBy { it }.reduce(
{ _, accumulator, element ->
if (
(element.node1 == accumulator.node1 && accumulator.direction != element.direction) ||
(element.node1 == accumulator.node2 && accumulator.direction == element.direction)
) {
accumulator.direction = EdgeDirection.BOTH
}
accumulator
},
)
val reduced = neighbors.groupingBy { it }.reduce { _, accumulator, element ->
if (
(element.node1 == accumulator.node1 && accumulator.direction != element.direction) ||
(element.node1 == accumulator.node2 && accumulator.direction == element.direction)
) {
accumulator.direction = EdgeDirection.BOTH
}
accumulator
}

edges.addAll(reduced.values)
id = nodes.lastOrNull()?.id?.plus(1) ?: 0
Expand Down Expand Up @@ -675,8 +754,7 @@ object GraphEditor {
highlightedNodes.addAll(inGraph)

highlightedEdges.addAll(
highlightedNodes.zipWithNext { a, b -> edges.firstOrNull { it.isValidConnectionFromTo(a, b) } }
.filterNotNull(),
highlightedNodes.zipWithNext { a, b -> edges.firstOrNull { it.isValidConnectionFromTo(a, b) } }.filterNotNull(),
)
}

Expand All @@ -690,7 +768,9 @@ object GraphEditor {
ghostPosition = null
}

fun LorenzVec.distanceSqToPlayer(): Double = ghostPosition?.let { distanceSq(it) } ?: distanceSq(playerLocation())
fun LorenzVec.distanceSqToPlayer(): Double {
return ghostPosition?.let { distanceSq(it) } ?: distanceSq(LocationUtils.playerLocation())
}
}

// The node object the graph editor is working with
Expand Down
18 changes: 16 additions & 2 deletions src/main/java/at/hannibal2/skyhanni/utils/GraphUtils.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package at.hannibal2.skyhanni.utils

import at.hannibal2.skyhanni.data.IslandGraphs
import at.hannibal2.skyhanni.data.model.DijkstraTree
import at.hannibal2.skyhanni.data.model.Graph
import at.hannibal2.skyhanni.data.model.GraphNode
Expand Down Expand Up @@ -114,8 +115,21 @@ object GraphUtils {
)
}

fun findAllShortestDistances(start: GraphNode): DijkstraTree {
return findDijkstraDistances(start) { false }
fun findAllShortestDistancesOnCurrentIsland(
start: LorenzVec,
bailout: (GraphNode) -> Boolean = { false },
): DijkstraTree = findDijkstraDistances(nearestNodeOnCurrentIsland(start), bailout)

fun nearestNodeOnCurrentIsland(location: LorenzVec): GraphNode {
val graph = IslandGraphs.currentIslandGraph ?: error("no island found")
return graph.nodes.minBy { it.position.distanceSq(location) }
}

fun findAllShortestDistances(
start: GraphNode,
bailout: (GraphNode) -> Boolean = { false },
): DijkstraTree {
return findDijkstraDistances(start, bailout)
}

fun findShortestPathAsGraphWithDistance(start: GraphNode, end: GraphNode): Pair<Graph, Double> {
Expand Down
Loading