diff options
Diffstat (limited to 'src/main/java/at/hannibal2/skyhanni/test')
-rw-r--r-- | src/main/java/at/hannibal2/skyhanni/test/SkyHanniDebugsAndTests.kt | 33 | ||||
-rw-r--r-- | src/main/java/at/hannibal2/skyhanni/test/graph/GraphEditor.kt (renamed from src/main/java/at/hannibal2/skyhanni/test/GraphEditor.kt) | 39 | ||||
-rw-r--r-- | src/main/java/at/hannibal2/skyhanni/test/graph/GraphEditorBugFinder.kt | 95 | ||||
-rw-r--r-- | src/main/java/at/hannibal2/skyhanni/test/graph/GraphNodeEditor.kt (renamed from src/main/java/at/hannibal2/skyhanni/test/GraphNodeEditor.kt) | 68 |
4 files changed, 194 insertions, 41 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/test/SkyHanniDebugsAndTests.kt b/src/main/java/at/hannibal2/skyhanni/test/SkyHanniDebugsAndTests.kt index 5b7333189..045ce5bce 100644 --- a/src/main/java/at/hannibal2/skyhanni/test/SkyHanniDebugsAndTests.kt +++ b/src/main/java/at/hannibal2/skyhanni/test/SkyHanniDebugsAndTests.kt @@ -131,36 +131,13 @@ object SkyHanniDebugsAndTests { } fun testCommand(args: Array<String>) { + SkyHanniMod.coroutineScope.launch { + asyncTest() + } + } + private fun asyncTest() { -// val a = Thread { OSUtils.copyToClipboard("123") } -// val b = Thread { OSUtils.copyToClipboard("456") } -// a.start() -// b.start() - -// for ((i, s) in ScoreboardData.siedebarLinesFormatted().withIndex()) { -// println("$i: '$s'") -// } - -// val name = args[0] -// val pitch = args[1].toFloat() -// val sound = SoundUtils.createSound("note.harp", 1.35f) -// val sound = SoundUtils.createSound("random.orb", 11.2f) -// SoundUtils.createSound(name, pitch).playSound() - -// a = args[0].toDouble() -// b = args[1].toDouble() -// c = args[2].toDouble() - -// for (line in getPlayerTabOverlay().footer.unformattedText -// .split("\n")) { -// println("footer: '$line'") -// } -// -// -// for (line in TabListUtils.getTabList()) { -// println("tablist: '$line'") -// } } fun findNullConfig(args: Array<String>) { diff --git a/src/main/java/at/hannibal2/skyhanni/test/GraphEditor.kt b/src/main/java/at/hannibal2/skyhanni/test/graph/GraphEditor.kt index d4038162f..1aefeda52 100644 --- a/src/main/java/at/hannibal2/skyhanni/test/GraphEditor.kt +++ b/src/main/java/at/hannibal2/skyhanni/test/graph/GraphEditor.kt @@ -1,4 +1,4 @@ -package at.hannibal2.skyhanni.test +package at.hannibal2.skyhanni.test.graph import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.data.IslandGraphs @@ -26,6 +26,7 @@ import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.LorenzVec import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators import at.hannibal2.skyhanni.utils.OSUtils +import at.hannibal2.skyhanni.utils.RaycastUtils import at.hannibal2.skyhanni.utils.RenderUtils.draw3DLine_nea import at.hannibal2.skyhanni.utils.RenderUtils.drawDynamicText import at.hannibal2.skyhanni.utils.RenderUtils.drawWaypointFilled @@ -127,6 +128,7 @@ object GraphEditor { if (!inEditMode && !inTextMode) { add("§ePlace: §6${KeyboardManager.getKeyName(config.placeKey)}") add("§eSelect: §6${KeyboardManager.getKeyName(config.selectKey)}") + add("§eSelect (Look): §6${KeyboardManager.getKeyName(config.selectRaycastKey)}") add("§eConnect: §6${KeyboardManager.getKeyName(config.connectKey)}") add("§eTest: §6${KeyboardManager.getKeyName(config.dijkstraKey)}") add("§eVision: §6${KeyboardManager.getKeyName(config.throughBlocksKey)}") @@ -259,7 +261,9 @@ object GraphEditor { } } - private fun chatAtDisable() = ChatUtils.clickableChat("Graph Editor is now inactive. §lClick to activate.", ::commandIn) + private fun chatAtDisable() = ChatUtils.clickableChat("Graph Editor is now inactive. §lClick to activate.", + GraphEditor::commandIn + ) private fun input() { if (LorenzUtils.isAnyGuiActive()) return @@ -346,13 +350,35 @@ object GraphEditor { closedNode } } + if (config.selectRaycastKey.isKeyClicked()) { + val playerRay = RaycastUtils.createPlayerLookDirectionRay() + var minimumDistance = Double.MAX_VALUE + var minimumNode: GraphingNode? = null + for (node in nodes) { + val nodeCenterPosition = node.position.add(0.5, 0.5, 0.5) + val distance = RaycastUtils.findDistanceToRay(playerRay, nodeCenterPosition) + if (distance > minimumDistance) { + continue + } + if (minimumDistance > 1.0) { + minimumNode = node + minimumDistance = distance + continue + } + if (minimumNode == null || minimumNode.position.distanceSqToPlayer() > node.position.distanceSqToPlayer()) { + minimumNode = node + minimumDistance = distance + } + } + activeNode = minimumNode + } if (activeNode != closedNode && config.connectKey.isKeyClicked()) { val edge = getEdgeIndex(activeNode, closedNode) if (edge == null) { addEdge(activeNode, closedNode) feedBackInTutorial("Added new edge.") } else { - this.edges.removeAt(edge) + edges.removeAt(edge) checkDissolve() selectedEdge = findEdgeBetweenActiveAndClosed() feedBackInTutorial("Removed edge.") @@ -405,6 +431,7 @@ object GraphEditor { val compileGraph = compileGraph() if (config.useAsIslandArea) { IslandGraphs.setNewGraph(compileGraph) + GraphEditorBugFinder.runTests() } val json = compileGraph.toJson() OSUtils.copyToClipboard(json) @@ -457,7 +484,7 @@ object GraphEditor { nodes.remove(closedNode) edges.removeIf { it.isInEdge(closedNode) } if (closedNode == activeNode) activeNode = null - this.closedNode = null + GraphEditor.closedNode = null return } } @@ -505,7 +532,7 @@ object GraphEditor { prune() val indexedTable = nodes.mapIndexed { index, node -> node.id to index }.toMap() val nodes = nodes.mapIndexed { index, it -> GraphNode(index, it.position, it.name, it.tags.mapNotNull { it.internalName }) } - val neighbours = this.nodes.map { node -> + val neighbours = GraphEditor.nodes.map { node -> edges.filter { it.isInEdge(node) }.map { edge -> val otherNode = if (node == edge.node1) edge.node2 else edge.node1 nodes[indexedTable[otherNode.id]!!] to node.position.distance(otherNode.position) @@ -523,7 +550,7 @@ object GraphEditor { it.id, it.position, it.name, - it.tagNames?.mapNotNull { GraphNodeTag.byId(it) }?.toMutableList() ?: mutableListOf(), + it.tagNames.mapNotNull { tag -> GraphNodeTag.byId(tag) }.toMutableList(), ) }, ) diff --git a/src/main/java/at/hannibal2/skyhanni/test/graph/GraphEditorBugFinder.kt b/src/main/java/at/hannibal2/skyhanni/test/graph/GraphEditorBugFinder.kt new file mode 100644 index 000000000..aee75ec5f --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/test/graph/GraphEditorBugFinder.kt @@ -0,0 +1,95 @@ +package at.hannibal2.skyhanni.test.graph + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.data.IslandGraphs +import at.hannibal2.skyhanni.data.model.GraphNode +import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent +import at.hannibal2.skyhanni.features.misc.IslandAreas.getAreaTag +import at.hannibal2.skyhanni.test.graph.GraphEditor.distanceSqToPlayer +import at.hannibal2.skyhanni.utils.GraphUtils +import at.hannibal2.skyhanni.utils.LorenzVec +import at.hannibal2.skyhanni.utils.RenderUtils.drawDynamicText +import kotlinx.coroutines.launch +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import java.awt.Color + +// Trying to find errors in Area Graph for the current graph editor instance +object GraphEditorBugFinder { + private var errorsInWorld = emptyMap<LorenzVec, String>() + + fun runTests() { + SkyHanniMod.coroutineScope.launch { + asyncTest() + } + } + + private fun asyncTest() { + val graph = IslandGraphs.currentIslandGraph ?: return + val errorsInWorld: MutableMap<LorenzVec, String> = mutableMapOf() + val nodes = graph.nodes + + val nearestArea = mutableMapOf<GraphNode, GraphNode>() + for (node in nodes) { + val pathToNearestArea = GraphUtils.findFastestPath(graph, node) { it.getAreaTag(ignoreConfig = true) != null }?.first + if (pathToNearestArea == null) { + continue + } + val areaNode = pathToNearestArea.lastOrNull() ?: error("Empty path to nearest area") + nearestArea[node] = areaNode + } + var bugs = 0 + for (node in nodes) { + val areaNode = nearestArea[node]?.name ?: continue + for (neighbour in node.neighbours.keys) { + val neighbouringAreaNode = nearestArea[neighbour]?.name ?: continue + if (neighbouringAreaNode == areaNode) continue + if ((null == node.getAreaTag(ignoreConfig = true))) { + bugs++ + errorsInWorld[node.position] = "§cConflicting areas $areaNode and $neighbouringAreaNode" + } + } + } + for (node in nodes) { + val nameNull = node.name.isNullOrBlank() + val tagsEmpty = node.tags.isEmpty() + if (nameNull > tagsEmpty) { + errorsInWorld[node.position] = "§cMissing name despite having tags" + bugs++ + } + if (tagsEmpty > nameNull) { + errorsInWorld[node.position] = "§cMissing tags despite having name" + bugs++ + } + } + + val clusters = GraphUtils.findDisjointClusters(graph) + if (clusters.size > 1) { + val closestCluster = clusters.minBy { it.minOf { it.position.distanceSqToPlayer() } } + val foreignClusters = clusters.filter { it !== closestCluster } + val closestForeignNodes = foreignClusters.map { network -> network.minBy { it.position.distanceSqToPlayer() } } + closestForeignNodes.forEach { + errorsInWorld[it.position] = "§cDisjoint node network" + bugs++ + } + val closestForeignNode = closestForeignNodes.minBy { it.position.distanceSqToPlayer() } + val closestNodeToForeignNode = closestCluster.minBy { it.position.distanceSq(closestForeignNode.position) } + IslandGraphs.pathFind(closestNodeToForeignNode.position, Color.RED) + } + + println("found $bugs bugs!") + this.errorsInWorld = errorsInWorld + if (clusters.size <= 1) { + IslandGraphs.pathFind(errorsInWorld.keys.minByOrNull { it.distanceSqToPlayer() } ?: return, Color.RED) + } + } + + @SubscribeEvent + fun onRenderWorld(event: LorenzRenderWorldEvent) { + if (!isEnabled()) return + + for ((location, text) in errorsInWorld) { + event.drawDynamicText(location, text, 1.5) + } + } + fun isEnabled() = GraphEditor.isEnabled() +} diff --git a/src/main/java/at/hannibal2/skyhanni/test/GraphNodeEditor.kt b/src/main/java/at/hannibal2/skyhanni/test/graph/GraphNodeEditor.kt index f541b16e3..e6c4536d8 100644 --- a/src/main/java/at/hannibal2/skyhanni/test/GraphNodeEditor.kt +++ b/src/main/java/at/hannibal2/skyhanni/test/graph/GraphNodeEditor.kt @@ -1,10 +1,10 @@ -package at.hannibal2.skyhanni.test +package at.hannibal2.skyhanni.test.graph import at.hannibal2.skyhanni.data.model.GraphNodeTag import at.hannibal2.skyhanni.data.model.TextInput import at.hannibal2.skyhanni.events.GuiRenderEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule -import at.hannibal2.skyhanni.test.GraphEditor.distanceSqToPlayer +import at.hannibal2.skyhanni.test.graph.GraphEditor.distanceSqToPlayer import at.hannibal2.skyhanni.utils.CollectionUtils.addString import at.hannibal2.skyhanni.utils.KeyboardManager import at.hannibal2.skyhanni.utils.LorenzUtils @@ -29,12 +29,12 @@ object GraphNodeEditor { private val textInput = TextInput() private var nodesDisplay = emptyList<Renderable>() private var lastUpdate = SimpleTimeMark.farPast() + private val tagsToShow: MutableList<GraphNodeTag> = GraphNodeTag.entries.toMutableList() @SubscribeEvent fun onGuiRender(event: GuiRenderEvent) { if (!isEnabled()) return - config.namedNodesList.renderRenderables( getNodeNames(), posLabel = "Graph Nodes List", @@ -52,15 +52,66 @@ object GraphNodeEditor { lastUpdate = SimpleTimeMark.now() nodesDisplay = buildList { val list = drawNodeNames() - val size = list.size - addString("§eGraph Nodes: $size") - val height = (size * 10).coerceAtMost(250) + val total = GraphEditor.nodes.count { it.name?.isNotBlank() ?: false } + val shown = list.size + add( + Renderable.clickAndHover( + "§eGraph Nodes: $shown/$total", + listOf("§eClick to toggle node tags!"), + onClick = { + updateToggleTags() + }, + ), + ) + val height = (shown * 10).coerceAtMost(250) if (list.isNotEmpty()) { add(list.buildSearchableScrollable(height, textInput, scrollValueNodes, velocity = 10.0)) } } } + private fun updateToggleTags() { + lastUpdate = SimpleTimeMark.now() + 60.seconds + nodesDisplay = buildList { + addString("§eToggle Visible Tags") + for (tag in GraphNodeTag.entries) { + val isVisible = tag in tagsToShow + val nodes = GraphEditor.nodes.count { tag in it.tags } + val visibilityText = if (isVisible) " §aVisible" else " §7Invisible" + val name = " - ${tag.displayName} §8($nodes nodes) $visibilityText" + add( + Renderable.clickAndHover( + name, + listOf("§eClick to " + (if (isVisible) "hide" else "show") + " nodes with this tag!"), + onClick = { + toggleTag(tag) + updateToggleTags() + }, + ), + ) + } + addString("") + add( + Renderable.clickAndHover( + "§cGo Back!", + tips = listOf("§eClick to go back to the node list!"), + onClick = { + updateNodeNames() + }, + ), + ) + } + + } + + private fun toggleTag(tag: GraphNodeTag) { + if (tag in tagsToShow) { + tagsToShow.remove(tag) + } else { + tagsToShow.add(tag) + } + } + private fun updateTagView(node: GraphingNode) { lastUpdate = SimpleTimeMark.now() + 60.seconds nodesDisplay = buildList { @@ -123,7 +174,10 @@ object GraphNodeEditor { private fun drawNodeNames(): List<Searchable> = buildList { for ((node, distance: Double) in GraphEditor.nodes.map { it to it.position.distanceSqToPlayer() }.sortedBy { it.second }) { - val name = node.name?.takeIf { !it.isBlank() } ?: continue + if (node.tags.isNotEmpty()) { + if (!node.tags.any { it in tagsToShow }) continue + } + val name = node.name?.takeIf { it.isNotBlank() } ?: continue val color = if (node == GraphEditor.activeNode) "§a" else "§7" val distanceFormat = sqrt(distance).toInt().addSeparators() val tagText = node.tags.let { tags -> |