Skip to content

Commit

Permalink
Add support for parameters (including Parchment)
Browse files Browse the repository at this point in the history
  • Loading branch information
shedaniel committed Feb 3, 2024
1 parent 9cab540 commit 3df8f93
Show file tree
Hide file tree
Showing 10 changed files with 253 additions and 19 deletions.
2 changes: 1 addition & 1 deletion backend/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ configurations {
}

dependencies {
implementation("me.shedaniel:linkie-core:1.0.119")
implementation("me.shedaniel:linkie-core:1.0.120")
implementation("io.ktor:ktor-server-cors:2.2.3")
implementation("io.ktor:ktor-server-content-negotiation:2.2.3")
implementation("io.ktor:ktor-server-status-pages:2.2.3")
Expand Down
59 changes: 52 additions & 7 deletions backend/src/main/kotlin/me/shedaniel/linkie/web/LinkieHandles.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
package me.shedaniel.linkie.web

import com.soywiz.korio.async.launch
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.withContext
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.*
import me.shedaniel.linkie.*
import me.shedaniel.linkie.namespaces.YarnNamespace
import me.shedaniel.linkie.utils.MemberEntry
import me.shedaniel.linkie.utils.ResultHolder
import me.shedaniel.linkie.utils.toVersion
Expand All @@ -17,6 +22,7 @@ import nl.adaptivity.xmlutil.serialization.XmlSerialName
import java.io.File
import kotlin.math.max
import kotlin.math.min
import kotlin.properties.Delegates

val xml = XML {
autoPolymorphic = true
Expand Down Expand Up @@ -50,25 +56,48 @@ suspend fun search(
?: (translateNamespace?.defaultVersion?.takeIf { it in allVersions } ?: allVersions.first())

val provider = version?.let { namespace.getProvider(it) } ?: namespace.getProvider(defaultVersion)
val mappings = provider.get()
var mappings by Delegates.notNull<MappingsContainer>()
var yarnMappings: MappingsContainer? = null
coroutineScope {
launch { withContext(Dispatchers.Default) { mappings = provider.get() } }
if (!namespace.hasMethodArgs(provider.version!!) && provider.version!!.tryToVersion()?.takeIf { it > "1.14.4".toVersion() } != null) {
val yarnProvider = YarnNamespace.getProvider(provider.version!!)
if (!yarnProvider.isEmpty()) {
launch { withContext(Dispatchers.Default) { yarnMappings = yarnProvider.get() } }
}
}
}
val result = MappingsQueryUtils.query(mappings, query, *buildList {
if (allowClasses) add(MappingsEntryType.CLASS)
if (allowMethods) add(MappingsEntryType.METHOD)
if (allowFields) add(MappingsEntryType.FIELD)
}.toTypedArray(), limit = limit)
val argMappings: (Class, Method) -> List<MethodArg>? = if (yarnMappings != null) {
inner@{ clazz, method ->
val obfName = method.obfMergedName ?: return@inner null
val obfDesc = method.getObfMergedDesc(mappings)
val parentObfName = clazz.obfMergedName ?: return@inner null
val targetParent = yarnMappings!!.getClassByObfName(parentObfName) ?: return@inner null
val targetMethod =
targetParent.methods.firstOrNull { it.obfMergedName == obfName && it.getObfMergedDesc(yarnMappings!!) == obfDesc }
?: return@inner null

targetMethod.args
}
} else { _, _ -> null }
if (translateNamespace == null) {
return SearchResultEntries(
entries = result.results.asSequence().take(limit).mapNotNull {
toJsonFromEntry(mappings, it.value, it.score)
toJsonFromEntry(namespace, mappings, it.value, it.score, argMappings)
}.toList(),
fuzzy = result.fuzzy,
)
} else {
val target = translateNamespace.getProvider(provider.version!!).get()
val elements = mutableListOf<JsonElement>()
translate(mappings, target, result.results.asSequence().take(limit)) { from, to, score ->
toJsonFromEntry(mappings, from, score)?.also { obj ->
val translated = toJsonFromEntry(target, to, score)
toJsonFromEntry(namespace, mappings, from, score, argMappings)?.also { obj ->
val translated = toJsonFromEntry(translateNamespace, target, to, score) { _, _ -> null }
if (translated == null) elements.add(obj)
else {
elements.add(buildJsonObject {
Expand Down Expand Up @@ -190,7 +219,7 @@ fun getLoaderVersions(loader: String): MutableMap<String, MutableMap<String, Dep
return result
}

fun toJsonFromEntry(mappings: MappingsContainer, entry: Any?, score: Double): JsonObject? {
fun toJsonFromEntry(namespace: Namespace, mappings: MappingsContainer, entry: Any?, score: Double, argMappings: (Class, Method) -> List<MethodArg>?): JsonObject? {
return when (entry) {
is Class -> json.encodeToJsonElement(
SearchResultClassEntry.serializer(), SearchResultClassEntry(
Expand All @@ -204,7 +233,7 @@ fun toJsonFromEntry(mappings: MappingsContainer, entry: Any?, score: Double): Js
)
) as JsonObject

is MemberEntry<*> -> json.encodeToJsonElement(
is MemberEntry<*> -> (json.encodeToJsonElement(
SearchResultMemberEntry.serializer(), SearchResultMemberEntry(
obf = entry.member.obfMergedName,
intermediary = entry.member.intermediaryName,
Expand All @@ -224,7 +253,23 @@ fun toJsonFromEntry(mappings: MappingsContainer, entry: Any?, score: Double): Js
score = score,
memberType = if (entry.member is Field) "f" else "m"
)
) as JsonObject
) as JsonObject).let {
if (entry.member is Method) {
var guessed = false
val args = (entry.member as Method).args ?: (argMappings(entry.owner, entry.member as Method)?.also {
guessed = true
} ?: return@let it)
val map = it.toMutableMap()
map["p"] = buildJsonObject {
args.forEach { arg ->
put(arg.index.toString(), arg.name)
}
}
map["q"] = JsonPrimitive(guessed)
map["r"] = JsonPrimitive(!guessed && namespace.id.contains("mojang"))
JsonObject(map)
} else it
}

else -> null
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ fun startLinkie() {
BarnNamespace,
FeatherNamespace,
),
maximumLoadedVersions = 4,
remapSourceDaemonDuration = 10.minutes,
)
)
Expand Down
1 change: 1 addition & 0 deletions frontend/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ export default defineComponent({

<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap');
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,100..800;1,100..800&display=swap');
body {
@apply bg-base-100 dark:bg-base-dark-100;
Expand Down
6 changes: 6 additions & 0 deletions frontend/src/app/mappings-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ export interface MappingEntry {
ownerObfServer?: string,
obfServer?: string,
descObfServer?: string,
args?: { [index: number]: string },
argsGuessed?: boolean,
argsParchment?: boolean,
type: MappingType,
translatedTo?: MappingEntry,
}
Expand Down Expand Up @@ -241,6 +244,9 @@ export function mapEntryToMappingEntry(obj: any): MappingEntry {
ownerObfServer: obj.k,
obfServer: obj.l,
descObfServer: obj.m,
args: obj.p,
argsGuessed: obj.q,
argsParchment: obj.r,
type,
translatedTo,
} as MappingEntry
Expand Down
22 changes: 22 additions & 0 deletions frontend/src/components/Tooltip.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<template>
<div class="bg-base-content dark:bg-black/80 dark:backdrop-blur-md rounded-lg drop-shadow-lg p-3
text-base-200 dark:text-base-dark-content text-xs sm:text-sm
max-sm:hidden
invisible peer-hover:visible
absolute peer-hover:opacity-100 opacity-0 transition-all duration-200
scale-75 peer-hover:scale-100 whitespace-nowrap origin-top-left
top-[1.75rem] z-10">
<slot/>
</div>
</template>

<script lang="ts">
import {defineComponent} from "vue"
export default defineComponent({
name: "Tooltip",
})
</script>

<style scoped>
</style>
55 changes: 55 additions & 0 deletions frontend/src/components/mappings/AutoBold.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<script lang="ts">
import {defineComponent, h} from "vue"
import {VNodeArrayChildren} from "@vue/runtime-core"
export default defineComponent({
name: "AutoBold",
render() {
let text: string = this.$slots.default!!().map(value => {
if (value.type === "br") return "\n"
return (value.children ?? "undefined").toString()
}).join(" ")
.replace("<br>", "\n")
.replace("<br\>", "\n")
let children = [] as VNodeArrayChildren
// the text as * is bold, \n is newline
let bold = false
let current = ""
for (let i = 0; i < text.length; i++) {
let char = text.charAt(i)
if (char === "\n") {
if (bold) {
children.push(h("span", {class: "bold"}, current))
} else {
children.push(current)
}
bold = false
current = ""
children.push(h("br"))
} else if (char === "*") {
if (bold) {
children.push(h("span", {class: "bold"}, current))
} else {
children.push(current)
}
current = ""
bold = !bold
} else {
current += char
}
}
if (current.length > 0) {
if (bold) {
children.push(h("span", {class: "bold"}, current))
} else {
children.push(current)
}
}
return h("span", children)
},
})
</script>

<style scoped>
</style>
Loading

0 comments on commit 3df8f93

Please sign in to comment.