Skip to content

Commit

Permalink
Merge pull request #6 from exejar/master
Browse files Browse the repository at this point in the history
Mappings and version update to Weave-Gradle
  • Loading branch information
exejar authored Apr 3, 2024
2 parents fac948d + d198d9b commit 3591ad3
Show file tree
Hide file tree
Showing 13 changed files with 223 additions and 81,636 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
### Fork renamed 'minecraft' extension to 'weavecraft' to prevent conflict with other modding libraries

---

<img
align="right" width="200px"
src="https://raw.githubusercontent.com/Weave-MC/.github/master/assets/icon.png"
Expand Down
65 changes: 29 additions & 36 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
plugins {
kotlin("plugin.serialization") version "1.8.10"
`java-gradle-plugin`
`kotlin-dsl`
`maven-publish`
}
Expand All @@ -12,59 +11,53 @@ val projectGroup: String by project
group = projectGroup
version = projectVersion

java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(8))
}
}
kotlin.jvmToolchain(8)

repositories {
mavenLocal()
mavenCentral()
maven("https://repo.weavemc.dev/releases")
}

dependencies {
// Jupiter's JUNIT
// TODO: write unit tests
testImplementation(libs.junitApi)
testRuntimeOnly(libs.junitEngine)

// OW2 ASM
implementation(libs.asm)
implementation(libs.asmCommons)

// Kotlinx.serialization JSON library
implementation(libs.kxSerJSON)
implementation(libs.mappingsUtil)
implementation(libs.weaveInternals)
}

tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask<*>>()
.configureEach {
compilerOptions
.languageVersion
.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9)
}

publishing {
repositories {
maven {
name = "WeaveMC"
url = uri("https://repo.weavemc.dev/releases")
credentials(PasswordCredentials::class)
authentication {
create<BasicAuthentication>("basic")
}
}
}
}

gradlePlugin {
plugins {
create("weave") {
// Using jitpack.io for the time being
id = "com.github.weave-mc.weave-gradle"
displayName = "Weave Plugin"
id = projectGroup
displayName = projectName
description =
"Implements Remapped Minecraft libraries intended for developing Weave Mods"
implementationClass = "net.weavemc.gradle.WeavePlugin"
"Implements Remapped Minecraft libraries intended for developing Minecraft mods with Weave"
implementationClass = "$projectGroup.WeaveGradle"
}
}
}

// Use Gradle Plugin Portal later on when the plugin is finished
// val publishProps = Properties()
// file("gradle-publish.properties").inputStream().use { publishProps.load(it) }
//
// publishing {
// repositories {
// maven {
// url = uri("https://plugins.gradle.org/m2/")
// credentials {
// username = publishProps.getProperty("publishKey")
// password = publishProps.getProperty("publishSecret")
// }
// }
// }
// }
//
// tasks.getByName<Test>("test") {
// useJUnitPlatform()
// }
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
org.gradle.jvmargs = -Xmx2G
# Project properties
projectName = Weave-Gradle
projectGroup = net.weavemc
projectVersion = 1.0.0
projectGroup = net.weavemc.gradle
projectVersion = 1.0.0
5 changes: 4 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
[versions]
asm = "9.4" # https://asm.ow2.io/versions.html
junit = "5.8.1" # https://github.com/junit-team/junit5/releases
kxSer = "1.5.0" # https://github.com/Kotlin/kotlinx.serialization/releases
kxSer = "1.5.1" # https://github.com/Kotlin/kotlinx.serialization/releases
mappingsUtil = "0.1.3"

[libraries]
asm = { module = "org.ow2.asm:asm", version.ref = "asm" }
Expand All @@ -10,3 +11,5 @@ asmCommons = { module = "org.ow2.asm:asm-commons", version.ref = "asm" }
junitApi = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "junit" }
junitEngine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit" }
kxSerJSON = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kxSer" }
mappingsUtil = { module = "io.github.770grappenmaker:mappings-util", version.ref = "mappingsUtil" }
weaveInternals = { module = "net.weavemc:internals", version = "1.0.0" }
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
105 changes: 105 additions & 0 deletions src/main/kotlin/net/weavemc/gradle/WeaveGradle.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package net.weavemc.gradle

import com.grappenmaker.mappings.remapJar
import kotlinx.serialization.encodeToString
import net.weavemc.gradle.configuration.WeaveMinecraftExtension
import net.weavemc.gradle.configuration.pullDeps
import net.weavemc.gradle.util.Constants
import net.weavemc.gradle.util.mappedJarCache
import net.weavemc.gradle.util.minecraftJarCache
import net.weavemc.internals.MappingsRetrieval
import net.weavemc.internals.MinecraftVersion
import net.weavemc.internals.ModConfig
import org.gradle.api.DefaultTask
import org.gradle.api.GradleException
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.tasks.InputFile
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.create
import org.gradle.kotlin.dsl.get
import org.gradle.kotlin.dsl.withType
import org.gradle.language.jvm.tasks.ProcessResources
import java.io.File

/**
* Gradle build system plugin used to automate the setup of a modding environment.
*/
class WeaveGradle : Plugin<Project> {
/**
* [Plugin.apply]
*
* @param project The target project.
*/
override fun apply(project: Project) {
// Applying our default plugins
project.pluginManager.apply(JavaPlugin::class)

val ext = project.extensions.create("minecraft", WeaveMinecraftExtension::class)

project.afterEvaluate {
if (!ext.configuration.isPresent) throw GradleException(
"Configuration is missing, make sure to add a configuration through the minecraft {} block!"
)

if (!ext.version.isPresent) throw GradleException(
"Set a Minecraft version through the minecraft {} block!"
)

val version = ext.version.getOrElse(MinecraftVersion.V1_8_9)
pullDeps(version, ext.configuration.get().namespace)
}

project.tasks.withType<ProcessResources>().configureEach {
doLast {
val config = ext.configuration.get().copy(compiledFor = ext.version.get().versionName)
destinationDir.resolve("weave.mod.json").writeText(Constants.JSON.encodeToString(config))
}
}

val remapJarTask = project.tasks.register("remapJar", RemapJarTask::class.java) {
val version = ext.version.getOrElse(MinecraftVersion.V1_8_9)
minecraftJar = version.mappedJarCache(ext.configuration.get().namespace)
inputJar = project.tasks["jar"].outputs.files.singleFile
outputJar = inputJar.parentFile.resolve("${inputJar.nameWithoutExtension}-mapped.${inputJar.extension}")
}

project.tasks.named("assemble") { finalizedBy(remapJarTask) }
}

/**
* Remaps the jar back to vanilla mappings (obfuscated)
* The jar will then be mapped when loaded by Weave-Loader
*/
open class RemapJarTask: DefaultTask() {
@Internal
lateinit var minecraftJar: File

@InputFile
lateinit var inputJar: File

@OutputFile
lateinit var outputJar: File

@TaskAction
fun remap() {
val ext = project.extensions["minecraft"] as WeaveMinecraftExtension
val version = ext.version.get()
val fullMappings = version.loadMergedMappings()

val mid = ext.configuration.get().namespace
require(mid in fullMappings.namespaces) {
"Namespace $mid is not available in mappings! Available namespaces are: ${fullMappings.namespaces}"
}

remapJar(fullMappings, inputJar, outputJar, mid, "official", files = listOf(minecraftJar))
}
}
}

fun MinecraftVersion.loadMergedMappings() =
MappingsRetrieval.loadMergedWeaveMappings(versionName, minecraftJarCache).mappings
Original file line number Diff line number Diff line change
@@ -1,129 +1,71 @@
package net.weavemc.gradle.configuration

import com.grappenmaker.mappings.remapJar
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import net.weavemc.gradle.util.AccessWidener
import net.weavemc.gradle.loadMergedMappings
import net.weavemc.gradle.util.Constants
import net.weavemc.gradle.util.DownloadUtil
import net.weavemc.gradle.util.mappedJarCache
import net.weavemc.gradle.util.minecraftJarCache
import net.weavemc.internals.MinecraftVersion
import org.gradle.api.Project
import org.gradle.kotlin.dsl.maven
import org.objectweb.asm.ClassReader
import org.objectweb.asm.ClassWriter
import org.objectweb.asm.commons.ClassRemapper
import java.io.File
import java.net.URL
import java.util.jar.JarEntry
import java.util.jar.JarFile
import java.util.jar.JarOutputStream

private inline fun <reified T> String?.decodeJSON() =
if (this != null) Constants.JSON.decodeFromString<T>(this) else null

/**
* Pulls dependencies from [addMinecraftAssets] and [addMappedMinecraft]
*/
fun Project.pullDeps(version: MinecraftVersion) {
fun Project.pullDeps(version: MinecraftVersion, namespace: String) {
addMinecraftAssets(version)
addMappedMinecraft(version)
addMappedMinecraft(version, namespace)
}

/**
* Adds Minecraft as a dependency by providing the jar to the projects file tree.
*/
private fun Project.addMinecraftAssets(version: MinecraftVersion) {
val manifest = DownloadUtil.fetch(Constants.VERSION_MANIFEST).decodeJSON<VersionManifest>() ?: return
val versionEntry = manifest.versions.find { it.id == version.id } ?: return
val versionEntry = manifest.versions.find { it.id == version.versionName } ?: return
val versionInfo = DownloadUtil.fetch(versionEntry.url).decodeJSON<VersionInfo>() ?: return

val client = versionInfo.downloads.client
DownloadUtil.downloadAndChecksum(URL(client.url), client.sha1, version.minecraftJarCache.toPath())
DownloadUtil.checksumAndDownload(URL(client.url), client.sha1, version.minecraftJarCache.toPath())

repositories.maven("https://libraries.minecraft.net/")
repositories.maven {
name = "mojang"
setUrl("https://libraries.minecraft.net/")
}

versionInfo.libraries.filter { "twitch-platform" !in it.name && "twitch-external" !in it.name }
.forEach { dependencies.add("compileOnly", it.name) }
}

/**
* Adds the mapped Minecraft JAR to the project's dependencies.
*
* @param version The Minecraft version for which to add the mapped JAR.
*/
private fun Project.addMappedMinecraft(version: MinecraftVersion) = runCatching {
val mapped = File(version.cacheDirectory, "minecraft-mapped.jar")
if (mapped.exists()) {
dependencies.add("compileOnly", files(mapped))
return@runCatching
}

val remapper = createMinecraftRemapper(version)

JarFile(version.minecraftJarCache).use { mcJar ->
JarOutputStream(mapped.outputStream()).use { outputStream ->
for (entry in mcJar.entries()) {
if (!entry.name.endsWith(".class")) continue

val reader = ClassReader(mcJar.getInputStream(entry))
val cw = ClassWriter(0)
reader.accept(AccessWidener(ClassRemapper(cw, remapper)), 0)

val mappedName = remapper.map(reader.className) ?: reader.className
outputStream.putNextEntry(JarEntry("$mappedName.class"))
outputStream.write(cw.toByteArray())
}
}
private fun Project.addMappedMinecraft(version: MinecraftVersion, namespace: String) = runCatching {
val mapped = version.mappedJarCache(namespace)
if (!mapped.exists()) {
val fullMappings = version.loadMergedMappings()
remapJar(fullMappings, version.minecraftJarCache, mapped, to = namespace)
}

dependencies.add("compileOnly", files(mapped))
dependencies.add("compileOnly", project.files(mapped))
}.onFailure { it.printStackTrace() }

/**
* Represents a version manifest containing a list of manifest versions
*
* @property versions The list of manifest versions
*/
@Serializable
private data class VersionManifest(val versions: List<ManifestVersion>)

/**
* Represents a manifest version with an ID and URL.
*
* @property id The ID of the manifest version.
* @property url The URL of the manifest version.
*/
@Serializable
private data class ManifestVersion(val id: String, val url: String)

/**
* Represents version information containing downloads and a list of libraries.
*
* @property downloads The version downloads.
* @property libraries The list of libraries.
*/
@Serializable
private data class VersionInfo(val downloads: VersionDownloads, val libraries: List<Library>)

/**
* Represents version downloads containing the client download.
*
* @property client The client download.
*/
@Serializable
private data class VersionDownloads(val client: VersionDownload)

/**
* Represents a version download with a URL and SHA1 hash.
*
* @property url The URL of the version download.
* @property sha1 The SHA1 hash of the version download.
*/
@Serializable
private data class VersionDownload(val url: String, val sha1: String)

/**
* Represents a library with a name.
*
* @property name The name of the library.
*/
@Serializable
private data class Library(val name: String)
private data class Library(val name: String)
Loading

0 comments on commit 3591ad3

Please sign in to comment.