Compare commits

...

2 commits

10 changed files with 489 additions and 170 deletions

View file

@ -7,7 +7,7 @@ plugins {
} }
group = "dev.frogmc" group = "dev.frogmc"
version = "0.0.1-alpha.12" version = "0.0.1-alpha.13"
repositories { repositories {
maven { maven {
@ -18,17 +18,18 @@ repositories {
name = "FrogMC Maven Snapshots" name = "FrogMC Maven Snapshots"
url = uri("https://maven.frogmc.dev/snapshots") url = uri("https://maven.frogmc.dev/snapshots")
} }
mavenLocal()
mavenCentral() mavenCentral()
} }
dependencies { dependencies {
implementation("dev.frogmc:thyroxine:0.0.1-alpha.5") implementation("dev.frogmc:thyroxine:0.0.1-alpha.6")
implementation("org.ow2.asm:asm:9.7") implementation("org.ow2.asm:asm:9.7")
implementation("com.google.code.gson:gson:2.10.1") implementation("com.google.code.gson:gson:2.10.1")
implementation("org.vineflower:vineflower:1.10.1") implementation("org.vineflower:vineflower:1.10.1")
testImplementation(kotlin("test")) testImplementation(kotlin("test"))
implementation("com.electronwill.night-config:toml:3.7.3") implementation("com.electronwill.night-config:toml:3.8.0")
implementation("com.google.jimfs:jimfs:1.3.0") implementation("com.google.jimfs:jimfs:1.3.0")
} }

View file

@ -12,4 +12,5 @@ object Constants {
const val GEN_RUN_CONFIGS_TASK = "genRunConfigs" const val GEN_RUN_CONFIGS_TASK = "genRunConfigs"
const val RUN_CLIENT_TASK = "runClient" const val RUN_CLIENT_TASK = "runClient"
const val RUNT_SERVER_TASK = "runServer" const val RUNT_SERVER_TASK = "runServer"
const val DEV_NAMESPACE = "named"
} }

View file

@ -1,29 +1,12 @@
package dev.frogmc.phytotelma package dev.frogmc.phytotelma
import dev.frogmc.phytotelma.accesswidener.AccessWidener
import dev.frogmc.phytotelma.build.PhytotelmaBuildTask
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.run.AssetDownloader
import dev.frogmc.phytotelma.run.RunConfigGenerator
import dev.frogmc.phytotelma.run.task.RunGameTask
import dev.frogmc.phytotelma.vineflower.ParchmentJavadocProvider
import dev.frogmc.thyroxine.provider.ParchmentProvider
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.JavaPlugin
import org.jetbrains.java.decompiler.main.Fernflower
import org.jetbrains.java.decompiler.main.decompiler.PrintStreamLogger
import org.jetbrains.java.decompiler.main.decompiler.SingleFileSaver
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences
import java.io.PrintStream
import java.net.URI import java.net.URI
import java.nio.file.Path import java.nio.file.Path
import kotlin.io.path.createDirectories import kotlin.io.path.createDirectories
import kotlin.io.path.deleteExisting
import kotlin.io.path.exists
class PhytotelmaPlugin : Plugin<Project> { class PhytotelmaPlugin : Plugin<Project> {
@ -67,98 +50,6 @@ class PhytotelmaPlugin : Plugin<Project> {
"phytotelma", "phytotelma",
PhytotelmaGradleExtensionImpl::class.java PhytotelmaGradleExtensionImpl::class.java
) )
project.extensions.findByType(PhytotelmaGradleExtension::class.java) ?: return
project.tasks.register("genSources") {task ->
task.group = Constants.TASK_GROUP
task.actions.add {
val projectData = ProjectStorage.get(it.project)
val fileName = projectData.remappedGameJarPath!!.fileName.toString()
val output =
projectData.remappedGameJarPath!!.resolveSibling(
fileName.substring(
0,
fileName.lastIndexOf("-")
) + "-sources.jar"
)
if (output.exists()) {
println("Output $output already exists, deleting!")
output.deleteExisting()
}
val options = mutableMapOf<String, Any>()
println("Preparing Parchment...")
val parchment = ParchmentProvider.getParchment(
projectData.minecraftVersion!!,
projectData.parchmentVersion!!,
globalCacheDir.resolve("org/parchmentmc/parchment/${projectData.minecraftVersion}/${projectData.parchmentVersion}/")
)
options[IFabricJavadocProvider.PROPERTY_NAME] = ParchmentJavadocProvider(parchment)
println("Decompiling...")
val logger = PrintStreamLogger(PrintStream(System.out))
options.putAll(
mapOf(
IFernflowerPreferences.DECOMPILE_GENERIC_SIGNATURES to "1",
IFernflowerPreferences.BYTECODE_SOURCE_MAPPING to "1",
IFernflowerPreferences.REMOVE_SYNTHETIC to "1",
IFernflowerPreferences.LOG_LEVEL to "error",
IFernflowerPreferences.THREADS to Runtime.getRuntime().availableProcessors().toString(),
IFernflowerPreferences.INDENT_STRING to "\t"
)
)
val decomp = Fernflower(
SingleFileSaver(output.toFile()),
options, logger
)
decomp.addSource(projectData.remappedGameJarPath!!.toFile())
decomp.decompileContext()
}
}
project.tasks.register(Constants.GEN_RUN_CONFIGS_TASK) {task ->
task.group = Constants.TASK_GROUP
task.doFirst {
RunConfigGenerator.generate(project)
}
}
project.tasks.register(Constants.RUN_CLIENT_TASK, RunGameTask::class.java, Env.CLIENT)
project.tasks.register(Constants.RUNT_SERVER_TASK, RunGameTask::class.java, Env.SERVER)
project.tasks.register(Constants.DOWNLOAD_ASSETS_TASK) { task ->
task.group = Constants.TASK_GROUP
task.doFirst {
AssetDownloader.download(it.project)
}
}
project.configurations.register(Constants.INCLUDE_CONFIGURATION) {
it.isCanBeResolved = true
it.isCanBeConsumed = false
}
project.configurations.register(Constants.MINECRAFT_CONFIGURATION) {
project.configurations.getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME).extendsFrom(it)
project.configurations.getByName(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME).extendsFrom(it)
project.configurations.getByName(JavaPlugin.TEST_COMPILE_CLASSPATH_CONFIGURATION_NAME).extendsFrom(it)
project.configurations.getByName(JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME).extendsFrom(it)
it.isCanBeResolved = false
it.isCanBeConsumed = false
it.isTransitive = false
}
val buildTask = project.tasks.register(Constants.BUILD_TASK, PhytotelmaBuildTask::class.java)
project.tasks.getByName("build").dependsOn(buildTask)
project.tasks.register(Constants.UPDATE_AW_TASK) { task ->
task.group = Constants.TASK_GROUP
task.actions.addFirst {
AccessWidener.apply(project, ProjectStorage.get(it.project).remappedGameJarPath!!)
}
}
} }
companion object { companion object {

View file

@ -1,5 +1,6 @@
package dev.frogmc.phytotelma package dev.frogmc.phytotelma
import dev.frogmc.thyroxine.api.data.MappingBundle
import org.gradle.api.Project import org.gradle.api.Project
import java.nio.file.Path import java.nio.file.Path
@ -8,15 +9,19 @@ object ProjectStorage {
private val data = mutableMapOf<Project, ProjectData>() private val data = mutableMapOf<Project, ProjectData>()
fun get(project: Project): ProjectData { fun get(project: Project): ProjectData {
if (!data.containsKey(project)){ if (!data.containsKey(project)) {
data[project] = ProjectData(null, null, null, null) data[project] = ProjectData(null, null, null, null, null, null)
} }
return data[project]!! return data[project]!!
} }
} }
class ProjectData(var localCacheDir: Path?, class ProjectData(
var localCacheDir: Path?,
var minecraftVersion: String?, var minecraftVersion: String?,
var remappedGameJarPath: Path?, var remappedGameJarPath: Path?,
var parchmentVersion: String?) var mappings: MappingBundle?,
var mappingsName: String?,
var targetNamespace: String?
)

View file

@ -0,0 +1,181 @@
package dev.frogmc.phytotelma.ext
import dev.frogmc.phytotelma.PhytotelmaPlugin
import dev.frogmc.phytotelma.mappings.renameDstNamespace
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.model.ObjectFactory
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 kotlin.io.path.readText
@Suppress("MemberVisibilityCanBePrivate", "unused")
abstract class MinecraftConfiguration @Inject constructor(
private val project: Project,
private val objects: ObjectFactory
) {
var version: String? = null
internal var mappings: Provider<MappingBundle> = mojmapParchment()
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 = version
action.execute(conf)
val cacheDir = PhytotelmaPlugin.globalCacheDir
if (conf.version == null) {
conf.version = ParchmentProvider.findForMinecraftVersion(conf.gameVersion)
}
mappingsName = "mojmap($version)+parchment(${conf.gameVersion}, ${conf.version})"
return@provider MappingBundle.merge(
MojmapProvider.get(
version,
cacheDir.resolve("net/minecraft/client/$version/client-$version.txt")
).orElseThrow().reverse(),
ParchmentProvider.getParchment(
version,
cacheDir.resolve("org/parchmentmc/parchment/${conf.gameVersion}/${conf.version}")
)
)
}
}
fun mojmap(): Provider<MappingBundle> {
return project.provider {
val cacheDir = PhytotelmaPlugin.globalCacheDir
mappingsName = "mojmap($version)"
return@provider MojmapProvider.get(
version,
cacheDir.resolve("net/minecraft/client/$version/client-$version.txt")
).orElseThrow().reverse()
}
}
fun quiltMappings(action: Action<VersionConfiguration>): Provider<MappingBundle> {
return project.provider {
val conf = objects.newInstance(VersionConfiguration::class.java)
action.execute(conf)
if (conf.version == null) {
error("No version provided for quilt mappings!")
}
mappingsName = "quilt(${conf.version})"
targetNamespace = "quilt"
// Use qm via intermediary because hashed publications are broken
return@provider twoStepMappings(
"net.fabricmc:intermediary:$version:v2",
"org.quiltmc:quilt-mappings:${conf.version}:intermediary-v2"
).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 == null) {
error("No version provided for first mapping step!")
}
if (conf.second == null) {
error("No version provided for second mapping step!")
}
mappingsName = "custom/two-step(${conf.first!!}, ${conf.second!!})"
val bundle = twoStepMappings(conf.first!!, conf.second!!)
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 == null) {
error("No maven coordinate provided for tiny mappings!")
}
mappingsName = "custom/tiny(${conf.name})"
val bundle = tinyMappings(conf.name!!)
targetNamespace = bundle.flattenData().dstNamespace
return@provider bundle
}
}
fun mappings(action: Action<MappingBundle>): Provider<MappingBundle> {
return project.provider {
val bundle = MappingBundle()
action.execute(bundle)
mappingsName = "custom(${bundle.srcNamespaces()}, ${bundle.dstNamespaces()})"
targetNamespace = bundle.flattenData().dstNamespace
return@provider bundle
}
}
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 {
var first: String? = null
var second: String? = null
}
abstract class ParchmentConfiguration {
var gameVersion: String? = null
var version: String? = null
}
abstract class LayerConfiguration {
internal val layers = mutableListOf<Provider<MappingBundle>>()
fun add(mappings: Provider<MappingBundle>): LayerConfiguration {
layers.add(mappings)
return this
}
}
}
abstract class NameConfiguration {
var name: String? = null
}
abstract class VersionConfiguration {
var version: String? = null
}

View file

@ -1,25 +1,13 @@
package dev.frogmc.phytotelma.ext package dev.frogmc.phytotelma.ext
import org.gradle.api.provider.Provider import org.gradle.api.Action
@Suppress("unused") @Suppress("unused")
interface PhytotelmaGradleExtension { interface PhytotelmaGradleExtension {
fun minecraft(version: String, parchmentGameVersion: String? = null, parchmentVersion: String? = null) fun minecraft(action: Action<MinecraftConfiguration>)
fun minecraft(version: Provider<String>, parchmentGameVersion: Provider<String>? = null, parchmentVersion: Provider<String>? = null) { fun loader(action: Action<VersionConfiguration>)
minecraft(version.get(), parchmentGameVersion?.get(), parchmentVersion?.get())
}
fun loader(version: String) fun froglib(action: Action<VersionConfiguration>)
fun loader(version: Provider<String>) {
loader(version.get())
}
fun froglib(version: String)
fun froglib(version: Provider<String>) {
froglib(version.get())
}
} }

View file

@ -5,22 +5,252 @@ 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
import dev.frogmc.phytotelma.accesswidener.AccessWidener import dev.frogmc.phytotelma.accesswidener.AccessWidener
import dev.frogmc.phytotelma.build.PhytotelmaBuildTask
import dev.frogmc.phytotelma.common.Env
import dev.frogmc.phytotelma.mappings.renameDstNamespace
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.vineflower.FrogJavadocProvider
import dev.frogmc.thyroxine.Thyroxine import dev.frogmc.thyroxine.Thyroxine
import dev.frogmc.thyroxine.parser.ProguardParser import dev.frogmc.thyroxine.api.data.MappingBundle
import dev.frogmc.thyroxine.provider.MojmapProvider import dev.frogmc.thyroxine.provider.MojmapProvider
import dev.frogmc.thyroxine.provider.ParchmentProvider import net.fabricmc.fernflower.api.IFabricJavadocProvider
import org.gradle.api.Action
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.model.ObjectFactory
import org.gradle.api.plugins.JavaBasePlugin
import org.gradle.api.plugins.JavaPlugin
import org.jetbrains.java.decompiler.main.Fernflower
import org.jetbrains.java.decompiler.main.decompiler.PrintStreamLogger
import org.jetbrains.java.decompiler.main.decompiler.SingleFileSaver
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences
import java.io.PrintStream
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.StandardCopyOption
import javax.inject.Inject import javax.inject.Inject
import kotlin.io.path.createParentDirectories import kotlin.io.path.createParentDirectories
import kotlin.io.path.deleteExisting
import kotlin.io.path.exists
import kotlin.io.path.notExists import kotlin.io.path.notExists
abstract class PhytotelmaGradleExtensionImpl : PhytotelmaGradleExtension { abstract class PhytotelmaGradleExtensionImpl @Inject constructor(
private val project: Project,
private val objects: ObjectFactory
) : PhytotelmaGradleExtension {
@Inject private fun setupTasks() {
abstract fun getProject(): Project project.tasks.register("genSources") { task ->
task.group = Constants.TASK_GROUP
task.actions.add {
val projectData = ProjectStorage.get(it.project)
val fileName = projectData.remappedGameJarPath!!.fileName.toString()
val output =
projectData.remappedGameJarPath!!.resolveSibling(
fileName.substring(
0,
fileName.lastIndexOf("-")
) + "-sources.jar"
)
if (output.exists()) {
println("Output $output already exists, deleting!")
output.deleteExisting()
}
val options = mutableMapOf<String, Any>()
println("Preparing Parchment...")
val javadocs = ProjectStorage.get(project).mappings!!
options[IFabricJavadocProvider.PROPERTY_NAME] =
FrogJavadocProvider(javadocs.docsForNamespace(Constants.DEV_NAMESPACE))
println("Decompiling...")
val logger = PrintStreamLogger(PrintStream(System.out))
options.putAll(
mapOf(
IFernflowerPreferences.DECOMPILE_GENERIC_SIGNATURES to "1",
IFernflowerPreferences.BYTECODE_SOURCE_MAPPING to "1",
IFernflowerPreferences.REMOVE_SYNTHETIC to "1",
IFernflowerPreferences.LOG_LEVEL to "error",
IFernflowerPreferences.THREADS to Runtime.getRuntime().availableProcessors().toString(),
IFernflowerPreferences.INDENT_STRING to "\t"
)
)
val decomp = Fernflower(
SingleFileSaver(output.toFile()),
options, logger
)
decomp.addSource(projectData.remappedGameJarPath!!.toFile())
decomp.decompileContext()
}
}
project.tasks.register(Constants.GEN_RUN_CONFIGS_TASK) { task ->
task.group = Constants.TASK_GROUP
task.doFirst {
RunConfigGenerator.generate(project)
}
}
project.tasks.register(Constants.RUN_CLIENT_TASK, RunGameTask::class.java, Env.CLIENT)
project.tasks.register(Constants.RUNT_SERVER_TASK, RunGameTask::class.java, Env.SERVER)
project.tasks.register(Constants.DOWNLOAD_ASSETS_TASK) { task ->
task.group = Constants.TASK_GROUP
task.doFirst {
AssetDownloader.download(it.project)
}
}
project.configurations.register(Constants.INCLUDE_CONFIGURATION) {
it.isCanBeResolved = true
it.isCanBeConsumed = false
}
project.configurations.register(Constants.MINECRAFT_CONFIGURATION) {
project.configurations.getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME).extendsFrom(it)
project.configurations.getByName(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME).extendsFrom(it)
project.configurations.getByName(JavaPlugin.TEST_COMPILE_CLASSPATH_CONFIGURATION_NAME).extendsFrom(it)
project.configurations.getByName(JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME).extendsFrom(it)
it.isCanBeResolved = false
it.isCanBeConsumed = false
it.isTransitive = false
}
val buildTask = project.tasks.register(Constants.BUILD_TASK, PhytotelmaBuildTask::class.java)
project.tasks.getByName(JavaBasePlugin.BUILD_TASK_NAME).dependsOn(buildTask)
project.tasks.getByName(JavaPlugin.JAR_TASK_NAME).actions.addLast {
val storage = ProjectStorage.get(project)
if (storage.targetNamespace != "mojmap") {
val mappings = MappingBundle.merge(
storage.mappings!!.reverse(), MojmapProvider.get(
storage.minecraftVersion!!,
PhytotelmaPlugin.globalCacheDir.resolve("net/minecraft/client/${storage.minecraftVersion}/client-${storage.minecraftVersion}.txt")
).orElseThrow().reverse().renameDstNamespace("mojmap")
).forNamespaces(storage.targetNamespace, "mojmap")
it.outputs.files.forEach { file ->
val temp = Files.createTempFile("", file.name)
Files.copy(file.toPath(), temp, StandardCopyOption.REPLACE_EXISTING)
Thyroxine.remap(mappings, temp, file.toPath(), false, false)
Files.deleteIfExists(temp)
}
}
}
project.tasks.register(Constants.UPDATE_AW_TASK) { task ->
task.group = Constants.TASK_GROUP
task.actions.addFirst {
AccessWidener.apply(project, ProjectStorage.get(it.project).remappedGameJarPath!!)
}
}
val configuration = project.configurations.create("modImplemenation") {
it.isCanBeResolved = true
it.isCanBeConsumed = false
}
project.afterEvaluate {
remapModDependencies(configuration)
}
}
private fun remapModDependencies(configuration: Configuration) {
// TODO
val mappings =
ProjectStorage.get(project).mappings!!.forNamespaces("mojmap", ProjectStorage.get(project).targetNamespace)
val targetPath = ProjectStorage.get(project).localCacheDir!!
val remappedPaths = mutableListOf<Path>()
configuration.resolvedConfiguration.resolvedArtifacts.forEach {
val remappedPath = targetPath.resolve(it.id.toString().replace(":", "/").replace(".", "/"))
remappedPaths.add(remappedPath)
configuration.dependencies.removeIf { d -> d.group + ":" + d.name + ":" + d.version == it.id.toString() }
}
}
override fun minecraft(action: Action<MinecraftConfiguration>) {
println("Setting up Tasks...")
setupTasks()
println("Setting up Minecraft...")
val mcConf = objects.newInstance(MinecraftConfiguration::class.java)
action.execute(mcConf)
if (mcConf.version == null) {
error("No Minecraft version provided!")
}
val version = mcConf.version!!
if (VersionChecker.validateVersion(version, offlineMode = project.gradle.startParameter.isOffline)) {
val projectData = ProjectStorage.get(project)
projectData.minecraftVersion = version
val mappings = mcConf.mappings.get()
println("Using mappings: " + mcConf.mappingsName)
projectData.mappings = mappings
val clientJar = VersionChecker.downloadClient(project, version)
val remappedJar =
projectData.localCacheDir!!.resolve("net/minecraft/client/$version/client-$version-remapped.jar")
remappedJar.createParentDirectories()
projectData.remappedGameJarPath = remappedJar
println("Time to setup Minecraft!")
val applyAW = AccessWidener.needsUpdate(project)
if (remappedJar.notExists() || applyAW || mcConf.mappingsName != projectData.mappingsName) {
projectData.mappingsName = mcConf.mappingsName
println("Remapping the game...")
projectData.targetNamespace = mcConf.targetNamespace
Thyroxine.remap(
mappings.forNamespaces("official", mcConf.targetNamespace),
clientJar, remappedJar, true, true
)
}
project.dependencies.add(
Constants.MINECRAFT_CONFIGURATION,
"net.minecrell:terminalconsoleappender:1.2.0"
)
VersionChecker.getDependencies(version) {
project.dependencies.add(Constants.MINECRAFT_CONFIGURATION, it)
}
VersionChecker.savePomFile(version, remappedJar.parent)
project.dependencies.add(Constants.MINECRAFT_CONFIGURATION, "net.minecraft:client:$version:remapped")
println("Generating run configurations...")
RunConfigGenerator.generate(project)
if (applyAW) {
project.afterEvaluate {
println("Applying AccessWideners...")
AccessWidener.apply(project, remappedJar)
}
}
}
}
override fun loader(action: Action<VersionConfiguration>) {
val conf = objects.newInstance(VersionConfiguration::class.java)
action.execute(conf)
if (conf.version == null) {
error("No loader version provided!")
}
project.dependencies.add("implementation", "dev.frogmc:frogloader:${conf.version!!}")
}
override fun froglib(action: Action<VersionConfiguration>) {
val conf = objects.newInstance(VersionConfiguration::class.java)
action.execute(conf)
if (conf.version == null) {
error("No froglib version provided!")
}
project.dependencies.add("implementation", "dev.frogmc:froglib:${conf.version!!}")
}
/*override fun minecraft(version: String, parchmentGameVersion: String?, parchmentVersion: String?) {
override fun minecraft(version: String, parchmentGameVersion: String?, parchmentVersion: String?) {
if (VersionChecker.validateVersion(version, offlineMode = getProject().gradle.startParameter.isOffline)) { if (VersionChecker.validateVersion(version, offlineMode = getProject().gradle.startParameter.isOffline)) {
println("Setting up Minecraft...") println("Setting up Minecraft...")
val parchmentGameVer = parchmentGameVersion?: version val parchmentGameVer = parchmentGameVersion?: version
@ -41,12 +271,10 @@ abstract class PhytotelmaGradleExtensionImpl : PhytotelmaGradleExtension {
if (remappedJar.notExists() || applyAW) { if (remappedJar.notExists() || applyAW) {
println("Remapping the game...") println("Remapping the game...")
val data = kotlin.runCatching { val data = kotlin.runCatching {
ProguardParser.read(
MojmapProvider.get( MojmapProvider.get(
version, version,
clientJar.resolveSibling("client-$version.txt") clientJar.resolveSibling("client-$version.txt")
).orElseThrow() ).orElseThrow().reverse()
).reverse()
}.getOrNull() }.getOrNull()
val paramMappings = if (parchment.isNotEmpty()) kotlin.runCatching { val paramMappings = if (parchment.isNotEmpty()) kotlin.runCatching {
ParchmentProvider.getParchment( ParchmentProvider.getParchment(
@ -62,7 +290,7 @@ abstract class PhytotelmaGradleExtensionImpl : PhytotelmaGradleExtension {
println("Parameter mappings will not be present as the version $parchmentVersion for minecraft version $parchmentGameVer could not be found") println("Parameter mappings will not be present as the version $parchmentVersion for minecraft version $parchmentGameVer could not be found")
} }
if (data != null) { if (data != null) {
Thyroxine.remap(data, clientJar, remappedJar, true, paramMappings) Thyroxine.remap(data.forNamespaces("official", "named"), clientJar, remappedJar, true, true)
} else { } else {
error("Failed to remap the game as no mojmap version was found for game version $version. Other mapping formats may be implemented in the future.") error("Failed to remap the game as no mojmap version was found for game version $version. Other mapping formats may be implemented in the future.")
} }
@ -101,5 +329,5 @@ abstract class PhytotelmaGradleExtensionImpl : PhytotelmaGradleExtension {
override fun froglib(version: String) { override fun froglib(version: String) {
getProject().dependencies.add("implementation", "dev.frogmc:froglib:$version") getProject().dependencies.add("implementation", "dev.frogmc:froglib:$version")
} }*/
} }

View file

@ -0,0 +1,21 @@
package dev.frogmc.phytotelma.mappings
import dev.frogmc.thyroxine.api.data.DocumentationData
import dev.frogmc.thyroxine.api.data.MappingBundle
import dev.frogmc.thyroxine.api.data.MappingData
fun MappingBundle.renameDstNamespace(newDst: String): MappingBundle {
val renamed = MappingBundle()
val oldData = flattenData()
val newData = MappingData(oldData.srcNamespace, newDst)
val newDocs = DocumentationData(newDst)
oldData.apply {
newData.classes.putAll(classes)
newData.fields.putAll(fields)
newData.methods.putAll(methods)
newData.parameters.putAll(parameters)
}
return renamed.insert(newData, newDocs.insert(get(oldData.dstNamespace)))
}

View file

@ -0,0 +1,28 @@
package dev.frogmc.phytotelma.vineflower
import dev.frogmc.thyroxine.api.data.DocumentationData
import net.fabricmc.fernflower.api.IFabricJavadocProvider
import org.jetbrains.java.decompiler.struct.StructClass
import org.jetbrains.java.decompiler.struct.StructField
import org.jetbrains.java.decompiler.struct.StructMethod
import java.util.stream.Collectors
class FrogJavadocProvider(data: DocumentationData) : IFabricJavadocProvider {
private val classMap = data.classes.stream().collect(Collectors.toMap({ it.name() }, { it }))
override fun getClassDoc(structClass: StructClass): String? {
return classMap[structClass.qualifiedName]?.javadoc?.joinToString("\n")
}
override fun getFieldDoc(structClass: StructClass, structField: StructField): String? {
return classMap[structClass.qualifiedName]
?.getField(structField.name, structField.descriptor)
?.orElse(null)?.javadoc?.joinToString("\n")
}
override fun getMethodDoc(structClass: StructClass, structMethod: StructMethod): String? {
return classMap[structClass.qualifiedName]?.getMethod(structMethod.name, structMethod.descriptor)
?.orElse(null)?.javadoc?.joinToString("\n")
}
}

View file

@ -1,25 +0,0 @@
package dev.frogmc.phytotelma.vineflower
import dev.frogmc.thyroxine.api.data.Parchment
import net.fabricmc.fernflower.api.IFabricJavadocProvider
import org.jetbrains.java.decompiler.struct.StructClass
import org.jetbrains.java.decompiler.struct.StructField
import org.jetbrains.java.decompiler.struct.StructMethod
class ParchmentJavadocProvider(private val parchment: Parchment) : IFabricJavadocProvider {
override fun getClassDoc(structClass: StructClass): String? {
return parchment.getClass(structClass.qualifiedName).orElse(null)?.javadoc?.joinToString("\n")
}
override fun getFieldDoc(structClass: StructClass, structField: StructField): String? {
return parchment.getClass(structClass.qualifiedName)
.flatMap { it.getField(structField.name, structField.descriptor) }
.orElse(null)?.javadoc?.joinToString("\n")
}
override fun getMethodDoc(structClass: StructClass, structMethod: StructMethod): String? {
return parchment.getClass(structClass.qualifiedName)
.flatMap { it.getMethod(structMethod.name, structMethod.descriptor) }
.orElse(null)?.javadoc?.joinToString("\n")
}
}