Compare commits

..

No commits in common. "c2d6800981d0b6e1a27e180f3fd26d685335e7cc" and "e25e598057bbe2ffdaba3bae610744f5ea2cdfe4" have entirely different histories.

11 changed files with 876 additions and 72 deletions

View file

@ -7,7 +7,7 @@ plugins {
} }
group = "dev.frogmc" group = "dev.frogmc"
version = "0.0.1-alpha.28" + ("+local".takeUnless { project.hasProperty("FrogMCSnapshotsMavenPassword") } ?: "") version = "0.0.1-alpha.27" + ("+local".takeUnless { project.hasProperty("FrogMCSnapshotsMavenPassword") } ?: "")
repositories { repositories {
maven { maven {
@ -24,7 +24,7 @@ repositories {
} }
dependencies { dependencies {
implementation("dev.frogmc:thyroxine:0.0.1-alpha.18") implementation("dev.frogmc:thyroxine:0.0.1-alpha.17")
implementation("org.ow2.asm:asm:9.7") implementation("org.ow2.asm:asm:9.7")
implementation("org.ow2.asm:asm-commons:9.7") implementation("org.ow2.asm:asm-commons:9.7")
implementation("org.ow2.asm:asm-tree:9.7") implementation("org.ow2.asm:asm-tree:9.7")

View file

@ -2,3 +2,4 @@ plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0" id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
} }
rootProject.name = "phytotelma" rootProject.name = "phytotelma"

View file

@ -8,28 +8,40 @@ import dev.frogmc.phytotelma.build.PhytotelmaBuildTask
import dev.frogmc.phytotelma.common.Env import dev.frogmc.phytotelma.common.Env
import dev.frogmc.phytotelma.ext.PhytotelmaGradleExtension import dev.frogmc.phytotelma.ext.PhytotelmaGradleExtension
import dev.frogmc.phytotelma.ext.PhytotelmaGradleExtensionImpl import dev.frogmc.phytotelma.ext.PhytotelmaGradleExtensionImpl
import dev.frogmc.phytotelma.mappings.renameDstNamespace
import dev.frogmc.phytotelma.mixin.remapper.MixinAnnotationRemapper
import dev.frogmc.phytotelma.nest.NestStripper
import dev.frogmc.phytotelma.run.AssetDownloader import dev.frogmc.phytotelma.run.AssetDownloader
import dev.frogmc.phytotelma.run.RunConfigGenerator import dev.frogmc.phytotelma.run.RunConfigGenerator
import dev.frogmc.phytotelma.run.task.RunGameTask import dev.frogmc.phytotelma.run.task.RunGameTask
import dev.frogmc.phytotelma.vineflower.FrogJavadocProvider import dev.frogmc.phytotelma.vineflower.FrogJavadocProvider
import dev.frogmc.thyroxine.RemappingStep
import dev.frogmc.thyroxine.Thyroxine
import dev.frogmc.thyroxine.api.Mapper
import dev.frogmc.thyroxine.api.data.MappingBundle
import dev.frogmc.thyroxine.api.data.MappingData
import dev.frogmc.thyroxine.provider.MojmapProvider
import dev.frogmc.thyroxine.writer.tiny.TinyV2Writer
import net.fabricmc.fernflower.api.IFabricJavadocProvider import net.fabricmc.fernflower.api.IFabricJavadocProvider
import org.gradle.api.Plugin import org.gradle.api.Plugin
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.plugins.JavaBasePlugin import org.gradle.api.plugins.JavaBasePlugin
import org.gradle.api.plugins.JavaPlugin import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.tasks.Delete import org.gradle.api.tasks.Delete
import org.gradle.internal.impldep.org.jsoup.helper.Consumer
import org.jetbrains.java.decompiler.main.Fernflower import org.jetbrains.java.decompiler.main.Fernflower
import org.jetbrains.java.decompiler.main.decompiler.PrintStreamLogger import org.jetbrains.java.decompiler.main.decompiler.PrintStreamLogger
import org.jetbrains.java.decompiler.main.decompiler.SingleFileSaver import org.jetbrains.java.decompiler.main.decompiler.SingleFileSaver
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences
import org.objectweb.asm.commons.ClassRemapper
import java.io.OutputStream
import java.io.PrintStream import java.io.PrintStream
import java.net.URI import java.net.URI
import java.nio.charset.StandardCharsets import java.nio.charset.StandardCharsets
import java.nio.file.FileSystems import java.nio.file.*
import java.nio.file.Files import java.nio.file.attribute.BasicFileAttributes
import java.nio.file.Path
import java.nio.file.StandardCopyOption
import java.time.LocalDateTime import java.time.LocalDateTime
import java.util.*
import kotlin.io.path.* import kotlin.io.path.*
@ -50,6 +62,10 @@ class PhytotelmaPlugin : Plugin<Project> {
} }
project.repositories.apply { project.repositories.apply {
maven {
it.name = "Remapped Mod Dependencies"
it.url = project.layout.buildDirectory.asFile.get().resolve("remappedMods").toURI()
}
maven { maven {
it.name = "Minecraft/Local" it.name = "Minecraft/Local"
it.url = localCacheDir.toUri() it.url = localCacheDir.toUri()
@ -75,6 +91,23 @@ class PhytotelmaPlugin : Plugin<Project> {
PhytotelmaGradleExtensionImpl::class.java PhytotelmaGradleExtensionImpl::class.java
) )
ModConfigurations.configurations.forEach { conf ->
project.configurations.create("mod" + conf.name.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.ROOT) else it.toString() }) { c ->
c.isCanBeResolved = true
c.isCanBeConsumed = false
when (conf.dependencyType) {
DependencyType.RUNTIME -> project.configurations.getByName(JavaPlugin.RUNTIME_ELEMENTS_CONFIGURATION_NAME)
.extendsFrom(c)
DependencyType.COMPILE -> project.configurations.getByName(JavaPlugin.API_ELEMENTS_CONFIGURATION_NAME)
.extendsFrom(c)
DependencyType.NONE -> {}
}
}
}
project.configurations.register(Constants.INCLUDE_CONFIGURATION) { project.configurations.register(Constants.INCLUDE_CONFIGURATION) {
it.isCanBeResolved = true it.isCanBeResolved = true
it.isCanBeConsumed = false it.isCanBeConsumed = false
@ -109,7 +142,7 @@ class PhytotelmaPlugin : Plugin<Project> {
projectData.remappedGameJarPath!!.resolveSibling( projectData.remappedGameJarPath!!.resolveSibling(
fileName.substring( fileName.substring(
0, 0,
fileName.lastIndexOf(".") fileName.lastIndexOf("-")
) + "-sources.jar" ) + "-sources.jar"
) )
if (output.exists()) { if (output.exists()) {
@ -117,10 +150,10 @@ class PhytotelmaPlugin : Plugin<Project> {
output.deleteExisting() output.deleteExisting()
} }
val options = mutableMapOf<String, Any>() val options = mutableMapOf<String, Any>()
println("Preparing javadocs...") println("Preparing Parchment...")
val javadocs = ProjectStorage.get(project).mappings!! val javadocs = ProjectStorage.get(project).mappings!!
options[IFabricJavadocProvider.PROPERTY_NAME] = options[IFabricJavadocProvider.PROPERTY_NAME] =
FrogJavadocProvider(javadocs.get("named")) FrogJavadocProvider(javadocs.get(ProjectStorage.get(project).targetNamespace))
println("Decompiling...") println("Decompiling...")
val logger = PrintStreamLogger(PrintStream(System.out)) val logger = PrintStreamLogger(PrintStream(System.out))
@ -167,6 +200,21 @@ class PhytotelmaPlugin : Plugin<Project> {
project.tasks.getByName(JavaPlugin.JAR_TASK_NAME).outputs.upToDateWhen { false } project.tasks.getByName(JavaPlugin.JAR_TASK_NAME).outputs.upToDateWhen { false }
project.tasks.getByName(JavaPlugin.JAR_TASK_NAME).actions.addLast { task -> project.tasks.getByName(JavaPlugin.JAR_TASK_NAME).actions.addLast { task ->
val storage = ProjectStorage.get(project)
if (storage.targetNamespace != Constants.MOJMAP_NAMESPACE) {
val moj = if (storage.intermediaryNs == Constants.MOJMAP_NAMESPACE) {
MojmapProvider.get(
storage.minecraftVersion!!,
globalCacheDir.resolve("net/minecraft/client/${storage.minecraftVersion}/client-${storage.minecraftVersion}.txt"),
globalCacheDir.resolve("net/minecraft/server/${storage.minecraftVersion}/server-${storage.minecraftVersion}.txt")
).reverse().renameDstNamespace(Constants.MOJMAP_NAMESPACE)
} else null
val mappings = (moj?.let {
MappingBundle.merge(
storage.mappings!!.reverse(), it
)
} ?: storage.mappings!!).forNamespaces(storage.targetNamespace, storage.intermediaryNs)
task.outputs.files.forEach { file -> task.outputs.files.forEach { file ->
val temp = Files.createTempFile("", file.name) val temp = Files.createTempFile("", file.name)
Files.copy(file.toPath(), temp, StandardCopyOption.REPLACE_EXISTING) Files.copy(file.toPath(), temp, StandardCopyOption.REPLACE_EXISTING)
@ -177,7 +225,7 @@ class PhytotelmaPlugin : Plugin<Project> {
.plus( .plus(
""" """
Built-By: Phytotelma ${this.javaClass.`package`.implementationVersion} Built-By: Phytotelma ${this.javaClass.`package`.implementationVersion}
Target-Namespace: Mojmap Target-Namespace: ${data.intermediaryNs}
Built-For: Minecraft ${data.minecraftVersion} Built-For: Minecraft ${data.minecraftVersion}
Build-Date: ${LocalDateTime.now()} Build-Date: ${LocalDateTime.now()}
""".trimIndent() """.trimIndent()
@ -188,8 +236,18 @@ class PhytotelmaPlugin : Plugin<Project> {
.get<String>("frog.extensions.frogloader.accesswidener")?.let { name -> .get<String>("frog.extensions.frogloader.accesswidener")?.let { name ->
val aw = metadata.resolveSibling(name) val aw = metadata.resolveSibling(name)
AccessWidener.checkAW(aw, ProjectStorage.get(project).remappedGameJarPath!!) AccessWidener.checkAW(aw, ProjectStorage.get(project).remappedGameJarPath!!)
remapAccesswidener(mappings, aw)
} }
} }
Thyroxine.remap(
mappings,
temp,
file.toPath(),
false,
defaultRemappingSteps(ProjectStorage.get(project).remappedGameJarPath!!)
)
Files.deleteIfExists(temp)
}
} }
} }
@ -209,6 +267,184 @@ class PhytotelmaPlugin : Plugin<Project> {
task.group = Constants.TASK_GROUP task.group = Constants.TASK_GROUP
task.delete = setOf(globalCacheDir) task.delete = setOf(globalCacheDir)
} }
project.afterEvaluate {
remapModDependencies(project)
}
}
private fun defaultRemappingSteps(vararg sourceNSJars: Path): MutableList<RemappingStep> {
return mutableListOf(
RemappingStep(::ClassRemapper),
RemappingStep { cv, mapper -> MixinAnnotationRemapper(cv, mapper, *sourceNSJars) },
)
}
private fun remapModDependencies(project: Project) {
val out = System.out
// Mute the output from thyroxine as there may be a lot of remapping operations here
System.setOut(PrintStream(OutputStream.nullOutputStream()))
val mojmapGameJar = ProjectStorage.get(project).remappedGameJarPath!!.resolveSibling("mojmap.jar")
val version = ProjectStorage.get(project).minecraftVersion!!
val officialClientJar = VersionChecker.downloadClient(project, version)
val officialServerJar = VersionChecker.downloadServer(project, version)
ModConfigurations.configurations.forEach { conf ->
val artifacts = project.configurations.getByName("mod" + conf.name.replaceFirstChar {
if (it.isLowerCase()) it.titlecase(
Locale.getDefault()
) else it.toString()
})
.resolvedConfiguration.resolvedArtifacts
if (artifacts.isEmpty()) {
return
}
val mojmap = MojmapProvider.get(version,
globalCacheDir.resolve("net/minecraft/client/${version}/client-${version}.txt"),
globalCacheDir.resolve("net/minecraft/server/${version}/server-${version}.txt"))
if (mojmapGameJar.notExists()) {
val remappedClient = officialClientJar.resolveSibling("client-$version-mojmap.jar")
val remappedServer = officialServerJar.resolveSibling("server-$version-mojmap.jar")
Thyroxine.remap(mojmap.data.first(), officialClientJar, remappedClient, true, false)
Thyroxine.remap(mojmap.data.first(), officialServerJar, remappedServer, true, false)
FileSystems.newFileSystem(mojmapGameJar, mutableMapOf<String, String>("create" to "true")).use { mergedFs ->
val consumer = object : Consumer<FileSystem> {
override fun accept(fs: FileSystem) {
Files.walkFileTree(fs.getPath("/"), object : SimpleFileVisitor<Path>() {
override fun visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult {
val target = mergedFs.getPath(file.toString())
target.createParentDirectories()
if (target.notExists()) {
file.copyTo(target)
}
return super.visitFile(file, attrs)
}
})
}
}
FileSystems.newFileSystem(remappedClient).use { consumer.accept(it) }
FileSystems.newFileSystem(remappedServer).use { consumer.accept(it) }
}
}
val target = project.configurations.create("mod" + conf.name.replaceFirstChar {
if (it.isLowerCase()) it.titlecase(
Locale.getDefault()
) else it.toString()
} + "Mapped") { c ->
c.isTransitive = false
conf.classpathNames.forEach {
project.configurations.getByName(it).extendsFrom(c)
}
}
val storage = ProjectStorage.get(project)
TinyV2Writer.write(
storage.mappings!!,
project.projectDir.resolve("storageMappings.tiny").writer()
)
val officialStore = storage.mappings!!.forNamespaces(storage.targetNamespace!!, "official").reverse()
TinyV2Writer.write(
MappingBundle(officialStore),
project.projectDir.resolve("officialStore.tiny").toPath().writer()
)
val mojOfficial = mojmap.reverse().renameDstNamespace(Constants.MOJMAP_NAMESPACE).data[0].reverse()
val targetPath = project.layout.buildDirectory.asFile.get().toPath().resolve("remappedMods")
.resolve("dev/frogmc/phytotelma/remapped_mods")
val remappedPaths = mutableListOf<Path>()
artifacts.forEach { artifact ->
val group = artifact.moduleVersion.id.group
val name = artifact.moduleVersion.id.name
val groupname = (group + "_" + name).replace(".", "_")
val artifactVersion = artifact.moduleVersion.id.version
val classifier = artifact.classifier
val remappedPath = targetPath.resolve(groupname).resolve(artifactVersion)
.resolve(groupname + "-" + artifactVersion + (classifier?.let { "-$it" } ?: "") + ".jar")
remappedPath.createParentDirectories()
remappedPaths.add(remappedPath)
val pom = remappedPath.resolveSibling(remappedPath.fileName.toString().removeSuffix(".jar") + ".pom")
pom.writeText(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\" xmlns=\"http://maven.apache.org/POM/4.0.0\"\n" +
"\t\t xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n" +
"\t<modelVersion>4.0.0</modelVersion>\n" +
"\t<groupId>dev.frogmc.phytotelma.remapped_mods</groupId>\n" +
"\t<artifactId>$groupname</artifactId>\n" +
"\t<version>$artifactVersion</version>\n" +
"</project>"
)
remappedPaths.add(pom)
val temp = remappedPath.resolveSibling(remappedPath.fileName.toString() + ".tmp")
Thyroxine.remap(
mojOfficial, artifact.file.toPath(), temp, false, defaultRemappingSteps(
mojmapGameJar
), mojmapGameJar
)
Thyroxine.remap(
officialStore, temp, remappedPath, false, defaultRemappingSteps(
officialClientJar, officialServerJar
), officialClientJar, officialServerJar
)
Files.deleteIfExists(temp)
NestStripper.stripJij(remappedPath)
FileSystems.newFileSystem(remappedPath).use { fs ->
val metadata = fs.getPath(Constants.MOD_METADATA_FILE)
tomlParser.parse(metadata, FileNotFoundAction.READ_NOTHING)
.get<String>("frog.extensions.frogloader.accesswidener")?.let { name ->
val aw = metadata.resolveSibling(name)
remapAccesswidener(mojOfficial, aw)
remapAccesswidener(officialStore, aw)
AccessWidener.checkAW(aw, ProjectStorage.get(project).remappedGameJarPath!!)
}
}
project.dependencies.add(
target.name,
"dev.frogmc.phytotelma.remapped_mods:$groupname:$artifactVersion" + (classifier?.let { ":$it" }
?: "")
)
}
Files.deleteIfExists(mojmapGameJar)
}
System.setOut(out)
}
private fun remapAccesswidener(mappings: MappingData, aw: Path) {
val mapper = Mapper(mappings) { listOf() }
val buffer = buildString {
aw.forEachLine {
if ((it.contains("\t") || it.contains(" ")) && !it.startsWith("#")) {
val parts = it.split("[\\t #]+".toRegex()).toMutableList()
if (parts.size > 2) {
val type = parts[1]
when (type) {
"class" -> {
parts[2] = mapper.map(parts[2])
}
"field" -> {
parts[3] = mapper.mapFieldName(parts[2], parts[3], parts[4])
parts[4] = mapper.mapDesc(parts[4])
parts[2] = mapper.map(parts[2])
}
"method" -> {
parts[3] = mapper.mapMethodName(parts[2], parts[3], parts[4])
parts[4] = mapper.mapMethodDesc(parts[4])
parts[2] = mapper.map(parts[2])
}
}
appendLine(parts.joinToString(" "))
return@forEachLine
}
}
appendLine(it)
}
}
aw.writeText(buffer)
} }
companion object { companion object {

View file

@ -71,13 +71,15 @@ object ProjectStorage {
class ProjectData( class ProjectData(
var localCacheDir: Path?, var localCacheDir: Path?,
var minecraftVersion: String?, var minecraftVersion: String?,
var parchmentVersion: String?,
var remappedGameJarPath: Path?, var remappedGameJarPath: Path?,
var mappings: MappingBundle?, var mappings: MappingBundle?,
var mappingsName: String?,
var intermediaryNs: String?,
var targetNamespace: String?,
var manifestUrl: String?, var manifestUrl: String?,
var jarManifestProperties: MutableMap<String, String> var jarManifestProperties: MutableMap<String, String>
) { ) {
internal constructor() : this(null,null, null, null, null, null, mutableMapOf()) internal constructor() : this(null, null, null, null, null, null, null, null, mutableMapOf())
} }
class ProjectDataTypeAdapter : TypeAdapter<ProjectData>() { class ProjectDataTypeAdapter : TypeAdapter<ProjectData>() {
@ -89,6 +91,8 @@ class ProjectDataTypeAdapter : TypeAdapter<ProjectData>() {
out.name("remapped_game_jar_path").value(value.remappedGameJarPath?.absolutePathString()) out.name("remapped_game_jar_path").value(value.remappedGameJarPath?.absolutePathString())
out.name("mappings") out.name("mappings")
value.mappings?.let { MappingBundleTypeAdapter.write(out, it) } ?: out.nullValue() value.mappings?.let { MappingBundleTypeAdapter.write(out, it) } ?: out.nullValue()
out.name("mappings_name").value(value.mappingsName)
out.name("target_namespace").value(value.targetNamespace)
out.name("jar_manifest_properties") out.name("jar_manifest_properties")
out.beginObject() out.beginObject()
value.jarManifestProperties.forEach { (s, s2) -> value.jarManifestProperties.forEach { (s, s2) ->
@ -114,13 +118,17 @@ class ProjectDataTypeAdapter : TypeAdapter<ProjectData>() {
data.minecraftVersion = value data.minecraftVersion = value
} }
"parchment_version" -> {
data.parchmentVersion = value
}
"remapped_game_jar_path" -> { "remapped_game_jar_path" -> {
data.remappedGameJarPath = Path.of(value) data.remappedGameJarPath = Path.of(value)
} }
"mappings_name" -> {
data.mappingsName = value
}
"target_namespace" -> {
data.targetNamespace = value
}
} }
} else if (name == "mappings") { } else if (name == "mappings") {
data.mappings = MappingBundleTypeAdapter.read(r) data.mappings = MappingBundleTypeAdapter.read(r)

View file

@ -1,10 +1,25 @@
package dev.frogmc.phytotelma.ext package dev.frogmc.phytotelma.ext
import dev.frogmc.phytotelma.Constants import dev.frogmc.phytotelma.Constants
import dev.frogmc.phytotelma.PhytotelmaPlugin
import dev.frogmc.phytotelma.ProjectStorage
import dev.frogmc.phytotelma.mappings.filterClasses
import dev.frogmc.phytotelma.mappings.renameDstNamespace
import dev.frogmc.phytotelma.mappings.renameNamespaces
import dev.frogmc.thyroxine.api.data.MappingBundle
import dev.frogmc.thyroxine.parser.tiny.TinyV2Parser
import dev.frogmc.thyroxine.provider.MojmapProvider
import dev.frogmc.thyroxine.provider.ParchmentProvider
import org.gradle.api.Action
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.model.ObjectFactory import org.gradle.api.model.ObjectFactory
import org.gradle.api.provider.Property import org.gradle.api.provider.Property
import org.gradle.api.provider.Provider
import java.nio.charset.StandardCharsets
import java.nio.file.FileSystems
import java.nio.file.Path
import javax.inject.Inject import javax.inject.Inject
import kotlin.io.path.readText
@Suppress("MemberVisibilityCanBePrivate", "unused") @Suppress("MemberVisibilityCanBePrivate", "unused")
abstract class MinecraftConfiguration @Inject constructor( abstract class MinecraftConfiguration @Inject constructor(
@ -13,9 +28,263 @@ abstract class MinecraftConfiguration @Inject constructor(
) { ) {
val version: Property<String> = objects.property(String::class.java).unset() val version: Property<String> = objects.property(String::class.java).unset()
val parchmentVersion: Property<String> = objects.property(String::class.java).unset() var mappings: Provider<MappingBundle> = mojmapParchment()
val intermediaryNamespace: Property<String> = objects.property(String::class.java).convention(Constants.MOJMAP_NAMESPACE)
val manifestUrl: Property<String> = objects.property(String::class.java).convention(Constants.MOJANG_MANIFEST_URL) val manifestUrl: Property<String> = objects.property(String::class.java).convention(Constants.MOJANG_MANIFEST_URL)
internal lateinit var mappingsName: String
internal lateinit var targetNamespace: String
fun mojmapParchment(): Provider<MappingBundle> {
return mojmapParchment {}
}
fun mojmapParchment(action: Action<ParchmentConfiguration>): Provider<MappingBundle> {
return project.provider {
val conf = objects.newInstance(ParchmentConfiguration::class.java)
conf.gameVersion.convention(version)
conf.version.convention(project.provider { ParchmentProvider.findForMinecraftVersion(conf.gameVersion.get()) })
action.execute(conf)
val cacheDir = PhytotelmaPlugin.globalCacheDir
mappingsName = "mojmap(${version.get()})+parchment(${conf.gameVersion.get()}, ${conf.version.get()})"
targetNamespace = Constants.MOJMAP_NAMESPACE
return@provider MappingBundle.merge(
MojmapProvider.get(
version.get(),
cacheDir.resolve("net/minecraft/client/${version.get()}/client-${version.get()}.txt"),
cacheDir.resolve("net/minecraft/server/${version.get()}/server-${version.get()}.txt")
).reverse(),
ParchmentProvider.getParchment(
conf.gameVersion.get(),
cacheDir.resolve("org/parchmentmc/parchment/${conf.gameVersion.get()}/${conf.version.get()}")
)
).renameDstNamespace(targetNamespace)
}
}
fun parchment(action: Action<ParchmentConfiguration>): Provider<MappingBundle> {
return project.provider {
val conf = objects.newInstance(ParchmentConfiguration::class.java)
conf.gameVersion.convention(version)
conf.version.convention(project.provider { ParchmentProvider.findForMinecraftVersion(conf.gameVersion.get()) })
action.execute(conf)
val cacheDir = PhytotelmaPlugin.globalCacheDir
mappingsName = "parchment(${conf.gameVersion.get()}, ${conf.version.get()})"
targetNamespace = "parchment"
return@provider ParchmentProvider.getParchment(
conf.gameVersion.get(),
cacheDir.resolve("org/parchmentmc/parchment/${conf.gameVersion.get()}/${conf.version.get()}")
).renameNamespaces(Constants.MOJMAP_NAMESPACE, "parchment")
}
}
fun mojmap(): Provider<MappingBundle> {
return project.provider {
val cacheDir = PhytotelmaPlugin.globalCacheDir
mappingsName = "mojmap(${version.get()})"
targetNamespace = Constants.MOJMAP_NAMESPACE
return@provider MojmapProvider.get(
version.get(),
cacheDir.resolve("net/minecraft/client/${version.get()}/client-${version.get()}.txt"),
cacheDir.resolve("net/minecraft/server/${version.get()}/server-${version.get()}.txt")
).reverse().renameDstNamespace(targetNamespace)
}
}
fun quiltMappings(action: Action<VersionConfiguration>): Provider<MappingBundle> {
return project.provider {
val conf = objects.newInstance(VersionConfiguration::class.java)
action.execute(conf)
if (!conf.version.isPresent()) {
error("No version provided for quilt mappings!")
}
mappingsName = "quilt-mappings(${conf.version.get()})"
targetNamespace = "quilt-mappings"
// Use qm via intermediary because hashed publications are broken
return@provider twoStepMappings(
"net.fabricmc:intermediary:${version.get()}:v2",
"org.quiltmc:quilt-mappings:${conf.version.get()}:intermediary-v2"
).flatten().renameDstNamespace(targetNamespace)
}
}
fun yarn(action: Action<VersionConfiguration>): Provider<MappingBundle> {
return project.provider {
val conf = objects.newInstance(VersionConfiguration::class.java)
action.execute(conf)
if (!conf.version.isPresent) {
error("No version provided for yarn!")
}
mappingsName = "yarn(${conf.version.get()})"
targetNamespace = "yarn"
// Use qm via intermediary because hashed publications are broken
return@provider twoStepMappings(
"net.fabricmc:intermediary:${version.get()}:v2",
"net.fabricmc:yarn:${conf.version.get()}:v2"
).flatten(true).renameDstNamespace(targetNamespace)
}
}
fun feather(action: Action<VersionConfiguration>): Provider<MappingBundle> {
return project.provider {
val conf = objects.newInstance(VersionConfiguration::class.java)
action.execute(conf)
if (!conf.version.isPresent) {
error("No version provided for feather!")
}
mappingsName = "feather(${conf.version.get()})"
targetNamespace = "feather"
intermediaryNamespace.set("intermediary")
ProjectStorage.get(project).jarManifestProperties["Calamus-Generation"] = "2"
return@provider twoStepMappings(
"net.ornithemc:calamus-intermediary-gen2:${version.get()}:v2",
"net.ornithemc:feather-gen2:${conf.version.get()}:v2"
).flatten(true).renameDstNamespace(targetNamespace)
}
}
fun twoStepMappings(action: Action<TwoStepMappingsConfiguration>): Provider<MappingBundle> {
return project.provider {
val conf = objects.newInstance(TwoStepMappingsConfiguration::class.java)
action.execute(conf)
if (!conf.first.isPresent) {
error("No version provided for first mapping step!")
}
if (!conf.second.isPresent) {
error("No version provided for second mapping step!")
}
mappingsName = "custom/two-step(${conf.first.get()}, ${conf.second.get()})"
val bundle = twoStepMappings(conf.first.get(), conf.second.get())
targetNamespace = bundle.flattenData().dstNamespace
return@provider bundle
}
}
fun tinyMappings(action: Action<NameConfiguration>): Provider<MappingBundle> {
return project.provider {
val conf = objects.newInstance(NameConfiguration::class.java)
action.execute(conf)
if (!conf.name.isPresent) {
error("No maven coordinate provided for tiny mappings!")
}
mappingsName = "custom/tiny(${conf.name.get()})"
val bundle = tinyMappings(conf.name.get())
targetNamespace = bundle.flattenData().dstNamespace
return@provider bundle
}
}
fun mappings(action: Action<MappingConfiguration>): Provider<MappingBundle> {
return project.provider {
val conf = objects.newInstance(MappingConfiguration::class.java)
action.execute(conf)
if (!conf.mappings.isPresent) {
error("No mappings provided!")
}
val bundle = conf.mappings.get()
mappingsName = "custom(${bundle.srcNamespaces()}, ${bundle.dstNamespaces()})"
targetNamespace = bundle.flattenData().dstNamespace
return@provider bundle
}
}
fun layer(action: Action<LayerConfiguration>): Provider<MappingBundle> {
return project.provider {
val conf = objects.newInstance(LayerConfiguration::class.java)
action.execute(conf)
var back = MappingBundle()
var name = "layer["
if (conf.layers.get().isEmpty()) {
mappingsName = "$name]"
targetNamespace = "official"
return@provider MappingBundle()
}
val layers = conf.layers.get().mapIndexed { index, provider ->
if (index == 0) {
val bundle = (provider.get() as MappingBundle).flatten()
name += mappingsName
back.insert(bundle)
return@mapIndexed bundle
}
val bundle = (provider.get() as MappingBundle)
.filterClasses { !it.startsWith("net/minecraft/unmapped") && !it.startsWith("net/minecraft/class_") }
.flatten(true)
name += ", $mappingsName"
back = back.flatten(false)
val prevDst = back.data[0].dstNamespace
val dst = bundle.data[0].dstNamespace
val remapped = MappingBundle.merge(bundle.reverse(), back)
.flatten(prevDst, dst)
.insert(back.docsForNamespace(dst))
back.insert(remapped)
return@mapIndexed remapped
}
mappingsName = "$name]"
val result = MappingBundle.merge(*layers.toTypedArray())
.flatten("official", layers.last().dstNamespaces()[0])
targetNamespace = result.data[0].dstNamespace
return@provider result
}
}
private fun twoStepMappings(intermediary: String, mappings: String): MappingBundle {
return MappingBundle.merge(tinyMappings(intermediary), tinyMappings(mappings))
}
private fun tinyMappings(name: String): MappingBundle {
mavenMappings(name).let { path ->
FileSystems.newFileSystem(path).use {
return TinyV2Parser.parse(it.getPath("mappings/mappings.tiny").readText(StandardCharsets.UTF_8))
}
}
}
@Suppress("UnstableApiUsage")
private fun mavenMappings(name: String): Path {
val configuration = project.configurations.create("mappings") {
it.isCanBeResolved = true
it.isCanBeDeclared = true
}
configuration.dependencies.add(project.dependencies.create(name))
val path = configuration.resolve().first().toPath()
project.configurations.remove(configuration)
return path
}
abstract class TwoStepMappingsConfiguration @Inject constructor(objects: ObjectFactory) {
val first: Property<String> = objects.property(String::class.java).unset()
val second: Property<String> = objects.property(String::class.java).unset()
}
abstract class ParchmentConfiguration @Inject constructor(objects: ObjectFactory) {
val gameVersion: Property<String> = objects.property(String::class.java).unset()
val version: Property<String> = objects.property(String::class.java).unset()
}
abstract class LayerConfiguration @Inject constructor(objects: ObjectFactory) {
internal val layers = objects.listProperty(Provider::class.java)
fun add(mappings: Provider<MappingBundle>): LayerConfiguration {
layers.add(mappings)
return this
}
}
abstract class MappingConfiguration @Inject constructor(objects: ObjectFactory) {
val mappings: Property<MappingBundle> = objects.property(MappingBundle::class.java).unset()
}
}
abstract class NameConfiguration @Inject constructor(objects: ObjectFactory) {
val name: Property<String> = objects.property(String::class.java).unset()
} }
abstract class VersionConfiguration @Inject constructor(objects: ObjectFactory) { abstract class VersionConfiguration @Inject constructor(objects: ObjectFactory) {

View file

@ -7,19 +7,19 @@ import dev.frogmc.phytotelma.accesswidener.AccessWidener
import dev.frogmc.phytotelma.ext.datagen.DatagenExtension import dev.frogmc.phytotelma.ext.datagen.DatagenExtension
import dev.frogmc.phytotelma.run.AssetDownloader import dev.frogmc.phytotelma.run.AssetDownloader
import dev.frogmc.phytotelma.run.RunConfigGenerator import dev.frogmc.phytotelma.run.RunConfigGenerator
import dev.frogmc.phytotelma.run.RuntimeAccessFixVisitor
import dev.frogmc.phytotelma.run.datagen.DatagenConfigGenerator import dev.frogmc.phytotelma.run.datagen.DatagenConfigGenerator
import dev.frogmc.phytotelma.run.datagen.DatagenTask import dev.frogmc.phytotelma.run.datagen.DatagenTask
import dev.frogmc.thyroxine.RemappingStep
import dev.frogmc.thyroxine.Thyroxine import dev.frogmc.thyroxine.Thyroxine
import dev.frogmc.thyroxine.api.data.MappingBundle import dev.frogmc.thyroxine.api.data.MappingData
import dev.frogmc.thyroxine.provider.MojmapProvider
import dev.frogmc.thyroxine.provider.ParchmentProvider
import org.gradle.api.Action import org.gradle.api.Action
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.model.ObjectFactory import org.gradle.api.model.ObjectFactory
import org.gradle.api.plugins.JavaPlugin import org.gradle.api.plugins.JavaPlugin
import org.gradle.internal.impldep.org.jsoup.helper.Consumer
import java.nio.file.* import java.nio.file.*
import java.nio.file.attribute.BasicFileAttributes import java.nio.file.attribute.BasicFileAttributes
import java.util.function.Consumer
import javax.inject.Inject import javax.inject.Inject
import kotlin.io.path.copyTo import kotlin.io.path.copyTo
import kotlin.io.path.createParentDirectories import kotlin.io.path.createParentDirectories
@ -38,26 +38,14 @@ abstract class PhytotelmaGradleExtensionImpl @Inject constructor(
error("No Minecraft version provided!") error("No Minecraft version provided!")
} }
val version = mcConf.version.get() val version = mcConf.version.get()
val parchmentVersion = mcConf.parchmentVersion.get()
val projectData = ProjectStorage.get(project) val projectData = ProjectStorage.get(project)
projectData.manifestUrl = mcConf.manifestUrl.get() projectData.manifestUrl = mcConf.manifestUrl.get()
if (VersionChecker.validateVersion(project, version, offlineMode = project.gradle.startParameter.isOffline)) { if (VersionChecker.validateVersion(project, version, offlineMode = project.gradle.startParameter.isOffline)) {
projectData.minecraftVersion = version projectData.minecraftVersion = version
val mappings = MappingBundle.merge( val mappings = mcConf.mappings.get()
MappingBundle.merge( println("Using mappings: " + mcConf.mappingsName)
MojmapProvider.get(
version,
projectData.localCacheDir!!.resolve("net/minecraft/client/${version}/client-${version}.txt"),
projectData.localCacheDir!!.resolve("net/minecraft/server/${version}/server-${version}.txt")
).reverse(),
ParchmentProvider.getParchment(
version,
projectData.localCacheDir!!.resolve("org/parchmentmc/parchment/${version}/${parchmentVersion}")
)
)
)
projectData.mappings = mappings projectData.mappings = mappings
val clientJar = VersionChecker.downloadClient(project, version) val clientJar = VersionChecker.downloadClient(project, version)
@ -68,19 +56,18 @@ abstract class PhytotelmaGradleExtensionImpl @Inject constructor(
projectData.localCacheDir!!.resolve("net/minecraft/server/$version/server-$version-remapped.jar") projectData.localCacheDir!!.resolve("net/minecraft/server/$version/server-$version-remapped.jar")
remappedClientJar.createParentDirectories() remappedClientJar.createParentDirectories()
remappedServerJar.createParentDirectories() remappedServerJar.createParentDirectories()
val flattened = mappings.flattenData() if (remappedClientJar.notExists() || mcConf.mappingsName != projectData.mappingsName) {
if (remappedClientJar.notExists() || parchmentVersion != projectData.parchmentVersion) {
println("Remapping client...") println("Remapping client...")
Thyroxine.remap( Thyroxine.remap(
flattened, mappings.forNamespaces("official", mcConf.targetNamespace),
clientJar, remappedClientJar, true, true clientJar, remappedClientJar, true, true
) )
VersionChecker.saveClientPomFile(version, remappedClientJar.parent) VersionChecker.saveClientPomFile(version, remappedClientJar.parent)
} }
if (remappedServerJar.notExists() || parchmentVersion != projectData.parchmentVersion) { if (remappedServerJar.notExists() || mcConf.mappingsName != projectData.mappingsName) {
println("Remapping server...") println("Remapping server...")
Thyroxine.remap( Thyroxine.remap(
flattened, mappings.forNamespaces("official", mcConf.targetNamespace),
serverJar, remappedServerJar, true, true serverJar, remappedServerJar, true, true
) )
VersionChecker.saveServerPomFile(version, remappedServerJar.parent) VersionChecker.saveServerPomFile(version, remappedServerJar.parent)
@ -89,11 +76,12 @@ abstract class PhytotelmaGradleExtensionImpl @Inject constructor(
projectData.localCacheDir!!.resolve("net/minecraft/minecraft-merged/$version/minecraft-merged-$version.jar") projectData.localCacheDir!!.resolve("net/minecraft/minecraft-merged/$version/minecraft-merged-$version.jar")
projectData.remappedGameJarPath = mergedJar projectData.remappedGameJarPath = mergedJar
var applyAW = AccessWidener.needsUpdate(project) var applyAW = AccessWidener.needsUpdate(project)
if (mergedJar.notExists() || applyAW || parchmentVersion != projectData.parchmentVersion) { projectData.intermediaryNs = mcConf.intermediaryNamespace.get()
projectData.parchmentVersion = parchmentVersion if (mergedJar.notExists() || applyAW || mcConf.mappingsName != projectData.mappingsName) {
projectData.mappingsName = mcConf.mappingsName
println("Merging game...") println("Merging game...")
mergedJar.createParentDirectories()
FileSystems.newFileSystem(mergedJar, mapOf("create" to "true")).use { mergedFs -> FileSystems.newFileSystem(mergedJar, mutableMapOf<String, String>("create" to "true")).use { mergedFs ->
val consumer = object : Consumer<FileSystem> { val consumer = object : Consumer<FileSystem> {
override fun accept(fs: FileSystem) { override fun accept(fs: FileSystem) {
Files.walkFileTree(fs.getPath("/"), object : SimpleFileVisitor<Path>() { Files.walkFileTree(fs.getPath("/"), object : SimpleFileVisitor<Path>() {
@ -111,7 +99,10 @@ abstract class PhytotelmaGradleExtensionImpl @Inject constructor(
FileSystems.newFileSystem(remappedClientJar).use { consumer.accept(it) } FileSystems.newFileSystem(remappedClientJar).use { consumer.accept(it) }
FileSystems.newFileSystem(remappedServerJar).use { consumer.accept(it) } FileSystems.newFileSystem(remappedServerJar).use { consumer.accept(it) }
} }
VersionChecker.saveMergedPomFile(version, mergedJar.parent)
projectData.targetNamespace = mcConf.targetNamespace
RunConfigGenerator.generate(project) RunConfigGenerator.generate(project)
applyAW = AccessWidener.hasAW(project) applyAW = AccessWidener.hasAW(project)
@ -139,6 +130,21 @@ abstract class PhytotelmaGradleExtensionImpl @Inject constructor(
AccessWidener.apply(project, mergedJar) AccessWidener.apply(project, mergedJar)
} }
} }
project.afterEvaluate {
if (mcConf.targetNamespace != Constants.MOJMAP_NAMESPACE) {
Thyroxine.remap(
MappingData("", ""),
mergedJar,
mergedJar.resolveSibling(Constants.ALTERNATIVE_RUNTIME_JAR_NAME),
false,
listOf(RemappingStep { classVisitor, _ ->
RuntimeAccessFixVisitor(classVisitor)
})
)
} else {
Files.deleteIfExists(mergedJar.resolveSibling(Constants.ALTERNATIVE_RUNTIME_JAR_NAME))
}
}
} }
} }

View file

@ -0,0 +1,275 @@
package dev.frogmc.phytotelma.mixin.remapper
import com.google.common.base.Strings
import dev.frogmc.phytotelma.Constants
import org.objectweb.asm.*
import org.objectweb.asm.commons.AnnotationRemapper
import org.objectweb.asm.commons.ClassRemapper
import org.objectweb.asm.commons.FieldRemapper
import org.objectweb.asm.commons.MethodRemapper
import org.objectweb.asm.commons.Remapper
import org.objectweb.asm.tree.ClassNode
import java.nio.file.FileSystems
import java.nio.file.Path
import kotlin.io.path.exists
import kotlin.io.path.readBytes
class MixinAnnotationRemapper(
cv: ClassVisitor,
private val mapper: Remapper,
private vararg val contextJars: Path
) : ClassRemapper(Constants.ASM_VERSION, cv, mapper) {
private var target: String? = null
private var targetNode: ClassNode? = null
override fun visit(
version: Int,
access: Int,
name: String?,
signature: String?,
superName: String?,
interfaces: Array<out String>?
) {
super.visit(version, access, name, signature, superName, interfaces)
}
override fun visitAnnotation(descriptor: String?, visible: Boolean): AnnotationVisitor? {
if (descriptor == null || descriptor != "Lorg/spongepowered/asm/mixin/Mixin;") {
return super.visitAnnotation(descriptor, visible)
}
return object : AnnotationVisitor(Constants.ASM_VERSION, super.visitAnnotation(descriptor, visible)) {
override fun visitArray(name: String?): AnnotationVisitor {
return object : AnnotationVisitor(Constants.ASM_VERSION, super.visitArray(name)) {
override fun visit(none: String?, value: Any?) {
var newVal = value
if (value is Type) {
target = value.internalName
} else if (
value is String
) {
if (target == null) {
target = value
}
newVal = mapper.map(value)
}
super.visit(none, newVal)
}
}
}
override fun visit(name: String?, value: Any?) {
val newVal = when (value) {
is String -> {
target = value
mapper.map(value)
}
is Type -> {
target = value.internalName
value
}
else -> value
}
super.visit(name, newVal)
}
override fun visitEnd() {
if (target != null) {
targetNode = ClassNode()
for (gameJar in contextJars) {
FileSystems.newFileSystem(gameJar).use { fs ->
fs.getPath("$target.class").takeIf { it.exists() }
?.readBytes()?.let(::ClassReader).let { it?.accept(targetNode, 0) }
}
if (targetNode != null) {
break
}
}
}
super.visitEnd()
}
}
}
override fun visitMethod(
access: Int,
name: String?,
descriptor: String?,
signature: String?,
exceptions: Array<out String>?
): MethodVisitor? {
val newMethodName = target?.let { mapper.mapMethodName(it, name, descriptor) }?: name
return super.visitMethod(access, newMethodName, descriptor, signature, exceptions)?.let {
if (targetNode != null) {
MixinMethodVisitor(it, mapper, targetNode!!)
} else it
}
}
override fun visitField(
access: Int,
name: String?,
descriptor: String?,
signature: String?,
value: Any?
): FieldVisitor? {
val newFieldName = target?.let { mapper.mapFieldName(it, name, descriptor) }?:name
return super.visitField(access, newFieldName, descriptor, signature, value)?.let {
if (targetNode != null) {
MixinFieldVisitor(it, mapper, targetNode!!)
} else it
}
}
class MixinFieldVisitor(fv: FieldVisitor, private val mapper: Remapper, private val targetNode: ClassNode) :
FieldRemapper(Constants.ASM_VERSION, fv, mapper) {
override fun visitAnnotation(descriptor: String?, visible: Boolean): AnnotationVisitor {
return MixinAnnotationVisitor(super.visitAnnotation(descriptor, visible), descriptor!!, mapper, targetNode)
}
}
class MixinMethodVisitor(mv: MethodVisitor, private val mapper: Remapper, private val targetNode: ClassNode) :
MethodRemapper(Constants.ASM_VERSION, mv, mapper) {
override fun visitAnnotation(descriptor: String?, visible: Boolean): AnnotationVisitor {
return MixinAnnotationVisitor(super.visitAnnotation(descriptor, visible), descriptor!!, mapper, targetNode)
}
}
class MixinAnnotationVisitor(
av: AnnotationVisitor,
private val desc: String,
private val mapper: Remapper,
private val owner: ClassNode,
private var annotationName: String = ""
) :
AnnotationRemapper(Constants.ASM_VERSION, desc, av, mapper) {
override fun visitAnnotation(name: String?, descriptor: String?): AnnotationVisitor {
return MixinAnnotationVisitor(super.visitAnnotation(name, descriptor), descriptor!!, mapper, owner)
}
override fun visitArray(name: String?): AnnotationVisitor {
return MixinAnnotationVisitor(super.visitArray(name), desc, mapper, owner, name!!)
}
override fun visit(n: String?, value: Any?) {
val name = n ?: annotationName
var newVal = value
if (value is String) {
if (desc == "Lorg/spongepowered/asm/mixin/gen/Invoker;") {
val methodName = value.substringBefore("(")
val desc = value.indexOf("(").takeIf { it > -1 }?.let(value::substring)
if (desc == null) {
val method = owner.methods.find { it.name == methodName }
if (method != null) {
newVal = mapper.mapMethodName(owner.name, methodName, method.desc)
}
} else {
newVal = mapper.mapMethodName(owner.name, methodName, desc)
}
} else if (desc == "Lorg/spongepowered/asm/mixin/gen/Accessor;") {
val field = owner.fields.find { it.name == value }
if (field != null) {
newVal = mapper.mapFieldName(owner.name, value, field.desc)
}
} else if (name == "aliases") {
val field = owner.fields.find { it.name == value }
if (field != null) {
newVal = mapper.mapFieldName(owner.name, value, field.desc)
}
} else if (name == "method") {
val methodName = value.substringBefore("(")
val desc = value.indexOf("(").takeIf { it > -1 }?.let(value::substring)
if (desc == null) {
val method = owner.methods.find { it.name == methodName }
if (method != null) {
val newName = mapper.mapMethodName(
owner.name,
methodName,
method.desc
)
newVal = newName + mapper.mapMethodDesc(method.desc)
}
} else {
val newName = mapper.mapMethodName(
owner.name,
methodName,
desc
)
newVal = newName + mapper.mapMethodDesc(desc)
}
} else if (name == "target") {
newVal = remapMemberInfo(value, mapper)
}
}
super.visit(name, newVal)
}
private fun remapMemberInfo(input: String, mapper: Remapper): String {
var desc: String? = null
var owner: String? = null
var name = Strings.nullToEmpty(input).replace("\\s".toRegex(), "")
var tail = ""
val arrowPos: Int = name.indexOf("->")
if (arrowPos > -1) {
tail = name.substring(arrowPos + 2)
name = name.substring(0, arrowPos)
}
val lastDotPos = name.lastIndexOf('.')
val semiColonPos = name.indexOf(';')
if (lastDotPos > -1) {
owner = name.substring(0, lastDotPos).replace('.', '/')
name = name.substring(lastDotPos + 1)
} else if (semiColonPos > -1 && name.startsWith("L")) {
owner = name.substring(1, semiColonPos).replace('.', '/')
name = name.substring(semiColonPos + 1)
}
val parenPos = name.indexOf('(')
val colonPos = name.indexOf(':')
if (parenPos > -1) {
desc = name.substring(parenPos)
name = name.substring(0, parenPos)
} else if (colonPos > -1) {
desc = name.substring(colonPos + 1)
name = name.substring(0, colonPos)
}
if ((name.indexOf('/') > -1 || name.indexOf('.') > -1) && owner == null) {
owner = name
name = ""
}
var quantifier = ""
if (name.endsWith("*")) {
quantifier = "*"
name = name.substring(0, name.length - 1)
} else if (name.endsWith("+")) {
quantifier = "+"
name = name.substring(0, name.length - 1)
} else if (name.endsWith("}")) {
quantifier = ""
val bracePos = name.indexOf("{")
if (bracePos >= 0) {
quantifier = name.substring(bracePos)
name = name.substring(0, bracePos)
}
} else if (name.indexOf("{") >= 0) {
quantifier = ""
}
val mappedOwner = mapper.map(owner!!)
val mappedDesc = mapper.mapMethodDesc(desc!!)
val mappedName = mapper.mapMethodName(owner, name, desc)
return "L$mappedOwner;$mappedName$mappedDesc$quantifier$tail"
}
}
}

View file

@ -1,5 +1,6 @@
package dev.frogmc.phytotelma.run package dev.frogmc.phytotelma.run
import dev.frogmc.phytotelma.Constants
import dev.frogmc.phytotelma.PhytotelmaPlugin import dev.frogmc.phytotelma.PhytotelmaPlugin
import dev.frogmc.phytotelma.ProjectStorage import dev.frogmc.phytotelma.ProjectStorage
import dev.frogmc.phytotelma.VersionChecker import dev.frogmc.phytotelma.VersionChecker
@ -34,7 +35,11 @@ object RunConfigGenerator {
} }
val projectData = ProjectStorage.get(project) val projectData = ProjectStorage.get(project)
val runtimeGameJar = projectData.remappedGameJarPath!! var runtimeGameJar = projectData.remappedGameJarPath!!
if (projectData.targetNamespace != Constants.MOJMAP_NAMESPACE) {
runtimeGameJar = runtimeGameJar.resolveSibling(Constants.ALTERNATIVE_RUNTIME_JAR_NAME)
}
val projectName = if (project.rootDir == project.projectDir) "" else " (${project.name})" val projectName = if (project.rootDir == project.projectDir) "" else " (${project.name})"
for (adapter in ADAPTERS) { for (adapter in ADAPTERS) {

View file

@ -1,5 +1,6 @@
package dev.frogmc.phytotelma.run.datagen package dev.frogmc.phytotelma.run.datagen
import dev.frogmc.phytotelma.Constants
import dev.frogmc.phytotelma.ProjectStorage import dev.frogmc.phytotelma.ProjectStorage
import dev.frogmc.phytotelma.ext.datagen.DatagenExtension import dev.frogmc.phytotelma.ext.datagen.DatagenExtension
import dev.frogmc.phytotelma.run.RunConfigGenerator import dev.frogmc.phytotelma.run.RunConfigGenerator
@ -26,7 +27,10 @@ object DatagenConfigGenerator {
} }
val projectData = ProjectStorage.get(project) val projectData = ProjectStorage.get(project)
val runtimeGameJar = projectData.remappedGameJarPath!! var runtimeGameJar = projectData.remappedGameJarPath!!
if (projectData.targetNamespace != Constants.MOJMAP_NAMESPACE) {
runtimeGameJar = runtimeGameJar.resolveSibling(Constants.ALTERNATIVE_RUNTIME_JAR_NAME)
}
for (adapter in RunConfigGenerator.ADAPTERS) { for (adapter in RunConfigGenerator.ADAPTERS) {
if (!adapter.shouldGenerate()) if (!adapter.shouldGenerate())

View file

@ -55,7 +55,11 @@ abstract class RunGameTask @Inject constructor(env: Env) : JavaExec() {
SourceSet.MAIN_SOURCE_SET_NAME SourceSet.MAIN_SOURCE_SET_NAME
).runtimeClasspath.filter { it.exists() }) ).runtimeClasspath.filter { it.exists() })
val runtimeGameJar = projectData.remappedGameJarPath!! var runtimeGameJar = projectData.remappedGameJarPath!!
if (projectData.targetNamespace != Constants.MOJMAP_NAMESPACE) {
println("Using alternative runtime jar to make use package access fixing")
runtimeGameJar = runtimeGameJar.resolveSibling(Constants.ALTERNATIVE_RUNTIME_JAR_NAME)
}
jvmArguments.addAll( jvmArguments.addAll(
"-Xmx${project.properties.getOrDefault("frogmc.gameHeap", "2048M")}", "-Xmx${project.properties.getOrDefault("frogmc.gameHeap", "2048M")}",

View file

@ -12,21 +12,17 @@ class FrogJavadocProvider(data: DocumentationData) : IFabricJavadocProvider {
private val classMap = data.classes.stream().collect(Collectors.toMap({ it.name() }, { it })) private val classMap = data.classes.stream().collect(Collectors.toMap({ it.name() }, { it }))
override fun getClassDoc(structClass: StructClass): String? { override fun getClassDoc(structClass: StructClass): String? {
if (structClass.qualifiedName.contains("package-info")) { return classMap[structClass.qualifiedName]?.javadoc?.joinToString("\n")
println(structClass)
}
println(structClass)
return classMap[structClass.qualifiedName]?.javadoc?.takeUnless { it.isEmpty() }?.joinToString("\n")
} }
override fun getFieldDoc(structClass: StructClass, structField: StructField): String? { override fun getFieldDoc(structClass: StructClass, structField: StructField): String? {
return classMap[structClass.qualifiedName] return classMap[structClass.qualifiedName]
?.getField(structField.name, structField.descriptor) ?.getField(structField.name, structField.descriptor)
?.orElse(null)?.javadoc?.takeUnless { it.isEmpty() }?.joinToString("\n") ?.orElse(null)?.javadoc?.joinToString("\n")
} }
override fun getMethodDoc(structClass: StructClass, structMethod: StructMethod): String? { override fun getMethodDoc(structClass: StructClass, structMethod: StructMethod): String? {
return classMap[structClass.qualifiedName]?.getMethod(structMethod.name, structMethod.descriptor) return classMap[structClass.qualifiedName]?.getMethod(structMethod.name, structMethod.descriptor)
?.orElse(null)?.javadoc?.takeUnless { it.isEmpty() }?.joinToString("\n") ?.orElse(null)?.javadoc?.joinToString("\n")
} }
} }