aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorhannibal2 <24389977+hannibal002@users.noreply.github.com>2024-09-05 00:51:21 +0200
committerGitHub <noreply@github.com>2024-09-05 00:51:21 +0200
commit59eef491fef0d7dd7f4018febe4d91de01369cbe (patch)
treedb9a99de84cc96198db95047eda524737f6a5db1 /src/main/java
parentbf152b4376c453f9eee76a6521377cc4062e9838 (diff)
downloadskyhanni-59eef491fef0d7dd7f4018febe4d91de01369cbe.tar.gz
skyhanni-59eef491fef0d7dd7f4018febe4d91de01369cbe.tar.bz2
skyhanni-59eef491fef0d7dd7f4018febe4d91de01369cbe.zip
Backend: Added Tags to Graph Editor (#2464)
Co-authored-by: Thunderblade73 <85900443+thunderblade73@users.noreply.github.com> Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com>
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/model/Graph.kt35
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/model/GraphNodeTag.kt41
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/model/TextInput.kt7
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCollectionStats.kt3
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/mining/TunnelsMaps.kt7
-rw-r--r--src/main/java/at/hannibal2/skyhanni/test/GraphEditor.kt164
6 files changed, 221 insertions, 36 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/data/model/Graph.kt b/src/main/java/at/hannibal2/skyhanni/data/model/Graph.kt
index ab5d1ca2d..89fd413f5 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/model/Graph.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/model/Graph.kt
@@ -42,17 +42,30 @@ value class Graph(
out.beginObject()
value.forEach {
out.name(it.id.toString()).beginObject()
+
out.name("Position").value(with(it.position) { "$x:$y:$z" })
- if (it.name != null) {
- out.name("Name").value(it.name)
+
+ it.name?.let {
+ out.name("Name").value(it)
+ }
+
+ it.tagNames?.takeIf { it.isNotEmpty() }?.let {
+ out.name("Tags")
+ out.beginArray()
+ for (tagName in it) {
+ out.value(tagName)
+ }
+ out.endArray()
}
+
out.name("Neighbours")
out.beginObject()
- it.neighbours.forEach { (node, weight) ->
+ for ((node, weight) in it.neighbours) {
val id = node.id.toString()
out.name(id).value(weight.round(2))
}
out.endObject()
+
out.endObject()
}
out.endObject()
@@ -66,6 +79,7 @@ value class Graph(
reader.beginObject()
var position: LorenzVec? = null
var name: String? = null
+ var tags: List<String>? = null
var neighbors = mutableListOf<Pair<Int, Double>>()
while (reader.hasNext()) {
when (reader.nextName()) {
@@ -89,9 +103,19 @@ value class Graph(
name = reader.nextString()
}
+ "Tags" -> {
+ tags = mutableListOf()
+ reader.beginArray()
+ while (reader.hasNext()) {
+ val tagName = reader.nextString()
+ tags.add(tagName)
+ }
+ reader.endArray()
+ }
+
}
}
- val node = GraphNode(id, position!!, name)
+ val node = GraphNode(id, position!!, name, tags)
list.add(node)
neighbourMap[node] = neighbors
reader.endObject()
@@ -111,7 +135,8 @@ value class Graph(
}
}
-class GraphNode(val id: Int, val position: LorenzVec, val name: String? = null) {
+// The node object that gets parsed from/to json
+class GraphNode(val id: Int, val position: LorenzVec, val name: String? = null, val tagNames: List<String>? = null) {
/** Keys are the neighbours and value the edge weight (e.g. Distance) */
lateinit var neighbours: Map<GraphNode, Double>
diff --git a/src/main/java/at/hannibal2/skyhanni/data/model/GraphNodeTag.kt b/src/main/java/at/hannibal2/skyhanni/data/model/GraphNodeTag.kt
new file mode 100644
index 000000000..6cfac664b
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/data/model/GraphNodeTag.kt
@@ -0,0 +1,41 @@
+package at.hannibal2.skyhanni.data.model
+
+enum class GraphNodeTag(val internalName: String?, val displayName: String, val description: String) {
+ DEV("dev", "Dev", "Intentionally marked as dev."), // E.g. Spawn points, todos, etc
+
+ // Everywhere
+ NPC("npc", "§eNPC", "A NPC entity."), // also take from neu repo
+ AREA("area", "§aArea", "A SkyBlock Area."),
+ POI("poi", "PoI", "Point of interest."),
+ LAUNCH_PAD("launch", "Launch Pad", "Slime blocks sending you to another server."),
+
+ // on multiple islands
+ ROMEO("romeo", "Romeo & Juliette Quest", "Blocks related to the Romeo and Juliette/Ring of Love quest line."),
+ RACE("race", "Race Start/Stop", "A race start or stop point."),
+ SLAYER("slayer", "Slayer", "A Slayer area"),
+ // hoppity
+
+ // Hub
+ HUB_12_STARTER("starter_npc", "Starter NPC", "One of the 12 starter NPC's you need to talk to."),
+ // diana
+
+ // Farming Islands: Pelts
+ FARMING_CROP("farming_crop", "Farming Crop", "A spot where you can break crops on farming islands."),
+
+ // Rift
+ RIFT_ENIGMA("rift_enigma", "§5Enigma Soul", "Enigma Souls in the rift."),
+ RIFT_EYE("rift_eye", "§4Eye", "An Eye in the rift to teleport to."),
+
+ // Spider's Den
+ SPIDER_RELIC("SPIDER_RELIC", "§5Relic", "An relic in the Spider's Den."),
+
+ // Dwarven Mines
+ MINES_EMISSARY("mines_emissary", "§6Emissary", "A Emissary from the king."),
+ // commission areas
+
+ ;
+
+ companion object {
+ fun byId(internalName: String?): GraphNodeTag? = values().firstOrNull { it.internalName == internalName }
+ }
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/data/model/TextInput.kt b/src/main/java/at/hannibal2/skyhanni/data/model/TextInput.kt
index f1a5001ad..d7e6ff8e1 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/model/TextInput.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/model/TextInput.kt
@@ -2,6 +2,7 @@ package at.hannibal2.skyhanni.data.model
import at.hannibal2.skyhanni.utils.KeyboardManager
import at.hannibal2.skyhanni.utils.KeyboardManager.isKeyClicked
+import at.hannibal2.skyhanni.utils.LorenzColor
import at.hannibal2.skyhanni.utils.OSUtils
import at.hannibal2.skyhanni.utils.StringUtils.insert
import kotlinx.coroutines.runBlocking
@@ -14,12 +15,12 @@ class TextInput {
var textBox: String = ""
private var carriage: Int? = null
- fun editText() = textBox.let {
+ fun editText(textColor: LorenzColor = LorenzColor.WHITE, carriageColor: LorenzColor = LorenzColor.GREEN) = textBox.let {
with(carriage) {
if (this == null) it
- else it.insert(this, '|')
+ else it.insert(this, "${carriageColor.getChatColor()}|${textColor.getChatColor()}")
}
- }.replace("§", "&&")
+ }.replace("(?<!§.\\|)§(?!.\\|§.)".toRegex(), "&&")
fun finalText() = textBox.replace("&&", "§")
diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCollectionStats.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCollectionStats.kt
index f4d98e782..a06b3dcbc 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCollectionStats.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCollectionStats.kt
@@ -9,6 +9,7 @@ import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent
import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryAPI
import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
import at.hannibal2.skyhanni.utils.ChatUtils
+import at.hannibal2.skyhanni.utils.CollectionUtils.addString
import at.hannibal2.skyhanni.utils.CollectionUtils.collectWhile
import at.hannibal2.skyhanni.utils.CollectionUtils.consumeWhile
import at.hannibal2.skyhanni.utils.DisplayTableEntry
@@ -220,7 +221,7 @@ object HoppityCollectionStats {
val foundRabbitCount = getFoundRabbitsFromHypixel(event)
if (loggedRabbitCount < foundRabbitCount) {
- newList.add(Renderable.string(""))
+ newList.addString("")
newList.add(
Renderable.wrappedString(
"§cPlease Scroll through \n" + "§call pages!",
diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/TunnelsMaps.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/TunnelsMaps.kt
index d2d351878..b6c1c81d0 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/mining/TunnelsMaps.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/mining/TunnelsMaps.kt
@@ -21,6 +21,7 @@ import at.hannibal2.skyhanni.events.LorenzWarpEvent
import at.hannibal2.skyhanni.events.RepositoryReloadEvent
import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
import at.hannibal2.skyhanni.test.command.ErrorManager
+import at.hannibal2.skyhanni.utils.CollectionUtils.addString
import at.hannibal2.skyhanni.utils.CollectionUtils.filterNotNullKeys
import at.hannibal2.skyhanni.utils.ColorUtils.getFirstColorCode
import at.hannibal2.skyhanni.utils.ColorUtils.toChromaColor
@@ -284,12 +285,12 @@ object TunnelsMaps {
),
)
} else {
- add(Renderable.string(""))
+ addString("")
}
}
} else {
- add(Renderable.string(""))
- add(Renderable.string(""))
+ addString("")
+ addString("")
}
addAll(locationDisplay)
}
diff --git a/src/main/java/at/hannibal2/skyhanni/test/GraphEditor.kt b/src/main/java/at/hannibal2/skyhanni/test/GraphEditor.kt
index ababb9b65..ece6d16cb 100644
--- a/src/main/java/at/hannibal2/skyhanni/test/GraphEditor.kt
+++ b/src/main/java/at/hannibal2/skyhanni/test/GraphEditor.kt
@@ -3,6 +3,7 @@ package at.hannibal2.skyhanni.test
import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.data.model.Graph
import at.hannibal2.skyhanni.data.model.GraphNode
+import at.hannibal2.skyhanni.data.model.GraphNodeTag
import at.hannibal2.skyhanni.data.model.TextInput
import at.hannibal2.skyhanni.data.model.findShortestPathAsGraph
import at.hannibal2.skyhanni.data.model.toJson
@@ -38,6 +39,7 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable
import kotlin.math.sqrt
import kotlin.time.Duration.Companion.milliseconds
+import kotlin.time.Duration.Companion.seconds
@SkyHanniModule
object GraphEditor {
@@ -84,7 +86,7 @@ object GraphEditor {
private val edgeDijkstraColor = LorenzColor.DARK_BLUE.addOpacity(150)
val scrollValue = ScrollValue()
- var namedNodeList: List<Renderable> = emptyList()
+ var nodesDisplay = emptyList<Renderable>()
var lastUpdate = SimpleTimeMark.farPast()
@SubscribeEvent
@@ -128,7 +130,7 @@ object GraphEditor {
}
if (inTextMode) {
add("§eFormat: ${textBox.finalText()}")
- add("§eRaw: ${textBox.editText()}")
+ add("§eRaw: ${textBox.editText(textColor = LorenzColor.YELLOW)}")
}
}
@@ -137,7 +139,7 @@ object GraphEditor {
if (!isEnabled()) return
config.namedNodesList.renderRenderables(
buildList {
- val list = getNamedNodes()
+ val list = getNodeNames()
val size = list.size
addString("§eGraph Nodes: $size")
val height = (size * 10).coerceAtMost(150)
@@ -149,34 +151,117 @@ object GraphEditor {
)
}
- private fun getNamedNodes(): List<Renderable> {
+ private fun getNodeNames(): List<Renderable> {
if (lastUpdate.passedSince() > 250.milliseconds) {
- lastUpdate = SimpleTimeMark.now()
- namedNodeList = calculateNamedNodes()
+ updateNodeNames()
}
- return namedNodeList
+ return nodesDisplay
}
+ private fun updateNodeNames() {
+ lastUpdate = SimpleTimeMark.now()
+ nodesDisplay = drawNodeNames()
+ }
+
+ private fun updateTagView(node: GraphingNode) {
+ lastUpdate = SimpleTimeMark.now() + 60.seconds
+ nodesDisplay = drawTagNames(node)
+ }
+
+ private fun drawTagNames(node: GraphingNode): List<Renderable> = buildList {
+ addString("§eChange tag for node '${node.name}§e'")
+ addString("")
+
+ for (tag in GraphNodeTag.entries) {
+ val state = if (tag in node.tags) "§aYES" else "§cNO"
+ val name = state + " §r" + tag.displayName
+ add(createTagName(name, tag, node))
+ }
+ addString("")
+ add(
+ Renderable.clickAndHover(
+ "§cGo Back!",
+ tips = listOf("§eClick to go back to the node list!"),
+ onClick = {
+ updateNodeNames()
+ },
+ ),
+ )
+ }
+
+ private fun createTagName(
+ name: String,
+ tag: GraphNodeTag,
+ node: GraphingNode,
+ ) = Renderable.clickAndHover(
+ name,
+ tips = listOf(
+ "Tag ${tag.name}",
+ "§7${tag.description}",
+ "",
+ "§eClick to set tag for ${node.name} to ${tag.name}!",
+ ),
+ onClick = {
+ if (tag in node.tags) {
+ node.tags.remove(tag)
+ } else {
+ node.tags.add(tag)
+ }
+ updateTagView(node)
+ },
+ )
- private fun calculateNamedNodes(): List<Renderable> = buildList {
+ private fun drawNodeNames(): List<Renderable> = buildList {
for ((node, distance: Double) in nodes.map { it to it.position.distanceSqToPlayer() }.sortedBy { it.second }) {
val name = node.name?.takeIf { !it.isBlank() } ?: continue
val color = if (node == activeNode) "§a" else "§7"
val distanceFormat = sqrt(distance).toInt().addSeparators()
- val text = "${color}Node §r$name §f($distanceFormat)"
- add(
- Renderable.clickAndHover(
- text,
- emptyList(),
- onClick = {
- activeNode = node
- lastUpdate = SimpleTimeMark.farPast()
- },
- ),
- )
+ val tagText = node.tags.let {
+ if (it.isEmpty()) {
+ " §cNo tag§r"
+ } else {
+ val text = node.tags.map { it.internalName }.joinToString(", ")
+ " §f($text)"
+ }
+ }
+
+ val text = "${color}Node §r$name$tagText §7[$distanceFormat]"
+ add(createNodeTextLine(text, name, node))
}
}
+ private fun MutableList<Renderable>.createNodeTextLine(
+ text: String,
+ name: String,
+ node: GraphingNode,
+ ): Renderable = Renderable.clickAndHover(
+ text,
+ tips = buildList {
+ add("Node '$name'")
+ add("")
+
+ if (node.tags.isNotEmpty()) {
+ add("Tags: ")
+ for (tag in node.tags) {
+ add(" §8- §r${tag.displayName}")
+ }
+ add("")
+ }
+
+ add("§eClick to select/deselect this node!")
+ add("§eControl-Click to edit the tags for this node!")
+
+ },
+ onClick = {
+ if (KeyboardManager.isModifierKeyDown()) {
+ updateTagView(node)
+ } else {
+ activeNode = node
+ updateNodeNames()
+ }
+ },
+ )
+
private fun feedBackInTutorial(text: String) {
if (inTutorialMode) {
ChatUtils.chat(text)
@@ -199,10 +284,11 @@ object GraphEditor {
minimumAlpha = 0.2f,
inverseAlphaScale = true,
)
- if (node.name == null) return
+
+ val nodeName = node.name ?: return
this.drawDynamicText(
node.position,
- node.name!!,
+ nodeName,
0.8,
ignoreBlocks = seeThroughBlocks || node.position.distanceSqToPlayer() < 100,
smallestDistanceVew = 12.0,
@@ -210,6 +296,20 @@ object GraphEditor {
yOff = -15f,
maxDistance = 80,
)
+
+ val tags = node.tags
+ if (tags.isEmpty()) return
+ val tagText = tags.map { it.displayName }.joinToString(" §f+ ")
+ this.drawDynamicText(
+ node.position,
+ tagText,
+ 0.8,
+ ignoreBlocks = seeThroughBlocks || node.position.distanceSqToPlayer() < 100,
+ smallestDistanceVew = 12.0,
+ ignoreY = true,
+ yOff = 0f,
+ maxDistance = 80,
+ )
}
private fun LorenzRenderWorldEvent.drawEdge(edge: GraphingEdge) = this.draw3DLine_nea(
@@ -359,6 +459,7 @@ object GraphEditor {
val length = edges.sumOf { it.node1.position.distance(it.node2.position) }.toInt().addSeparators()
ChatUtils.chat(
"§lStats\n" +
+ "§eNamed Nodes: ${nodes.count { it.name != null }.addSeparators()}\n" +
"§eNodes: ${nodes.size.addSeparators()}\n" +
"§eEdges: ${edges.size.addSeparators()}\n" +
"§eLength: $length",
@@ -428,7 +529,7 @@ object GraphEditor {
private fun compileGraph(): Graph {
prune()
val indexedTable = nodes.mapIndexed { index, node -> node.id to index }.toMap()
- val nodes = nodes.mapIndexed { index, it -> GraphNode(index, it.position, it.name) }
+ val nodes = nodes.mapIndexed { index, it -> GraphNode(index, it.position, it.name, it.tags.mapNotNull { it.internalName }) }
val neighbours = this.nodes.map { node ->
edges.filter { it.isInEdge(node) }.map { edge ->
val otherNode = if (node == edge.node1) edge.node2 else edge.node1
@@ -441,7 +542,16 @@ object GraphEditor {
fun import(graph: Graph) {
clear()
- nodes.addAll(graph.map { GraphingNode(it.id, it.position, it.name) })
+ nodes.addAll(
+ graph.map {
+ GraphingNode(
+ it.id,
+ it.position,
+ it.name,
+ it.tagNames?.mapNotNull { GraphNodeTag.byId(it) }?.toMutableList() ?: mutableListOf(),
+ )
+ },
+ )
val translation = graph.mapIndexed { index, it -> it to nodes[index] }.toMap()
edges.addAll(
graph.map { node ->
@@ -494,7 +604,13 @@ object GraphEditor {
}
}
-private class GraphingNode(val id: Int, var position: LorenzVec, var name: String? = null) {
+// The node object the graph editor is working with
+private class GraphingNode(
+ val id: Int,
+ var position: LorenzVec,
+ var name: String? = null,
+ var tags: MutableList<GraphNodeTag> = mutableListOf(),
+) {
override fun hashCode(): Int {
return id