diff options
| author | Linnea Gräf <nea@nea.moe> | 2024-08-11 13:22:24 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-08-11 13:22:24 +0200 |
| commit | 8903d9fa783455558d20eb32a2038c87ab5913be (patch) | |
| tree | 2c925d0ecf625f8e8a5505960d0d51d2201e88e2 | |
| parent | a8d4861b051298cc8a1db3c5210a32abab866b1e (diff) | |
| download | skyhanni-8903d9fa783455558d20eb32a2038c87ab5913be.tar.gz skyhanni-8903d9fa783455558d20eb32a2038c87ab5913be.tar.bz2 skyhanni-8903d9fa783455558d20eb32a2038c87ab5913be.zip | |
Add multi version preprocessor (#2283)
Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com>
34 files changed, 1027 insertions, 188 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 379f842d8..8275ac8b0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,44 +1,63 @@ name: Build on: - push: - branches: - - "*" - paths-ignore: - - ".gitignore" - pull_request: - branches: - - "*" - paths-ignore: - - ".gitignore" - workflow_dispatch: + push: + branches: + - "*" + paths-ignore: + - ".gitignore" + pull_request: + branches: + - "*" + paths-ignore: + - ".gitignore" + workflow_dispatch: permissions: write-all jobs: - build: - runs-on: ubuntu-latest - name: "Build and test" - steps: - - uses: actions/checkout@v3 - - name: Set up JDK 17 - uses: actions/setup-java@v3 - with: - java-version: 17 - distribution: temurin - cache: gradle - - name: Setup gradle - uses: gradle/gradle-build-action@v2 - - name: Build with Gradle - run: ./gradlew build -x test --stacktrace - - uses: actions/upload-artifact@v3 - name: Upload development build - with: - name: "Development Build" - path: build/libs/*.jar - - name: Test with Gradle - run: ./gradlew test - - uses: actions/upload-artifact@v3 - name: "Upload test report" - if: ${{ !cancelled() }} - with: - name: "Test Results" - path: build/reports/tests/test/ + build: + runs-on: ubuntu-latest + name: "Build and test" + steps: + - uses: actions/checkout@v3 + - name: Set up JDK 21 + uses: actions/setup-java@v3 + with: + java-version: 21 + distribution: temurin + cache: gradle + - name: Setup gradle + uses: gradle/gradle-build-action@v2 + - name: Build with Gradle + run: ./gradlew assemble -x test --stacktrace + - uses: actions/upload-artifact@v3 + name: Upload development build + with: + name: "Development Build" + path: versions/1.8.9/build/libs/*.jar + - name: Test with Gradle + run: ./gradlew test + - uses: actions/upload-artifact@v3 + name: "Upload test report" + if: ${{ !cancelled() }} + with: + name: "Test Results" + path: versions/1.8.9/build/reports/tests/test/ + preprocess: + runs-on: ubuntu-latest + name: "Build multi version" + steps: + - uses: actions/checkout@v3 + - name: Set up JDK 21 + uses: actions/setup-java@v3 + with: + java-version: 21 + distribution: temurin + cache: gradle + - name: Setup gradle + uses: gradle/gradle-build-action@v2 + - name: Enable preprocessor + run: | + mkdir -p .gradle + echo skyhanni.multi-version=preprocess-only > .gradle/private.properties + - name: Build with Gradle + run: ./gradlew build --stacktrace diff --git a/.github/workflows/generate-constants.yaml b/.github/workflows/generate-constants.yaml index 505a035b2..c589676d0 100644 --- a/.github/workflows/generate-constants.yaml +++ b/.github/workflows/generate-constants.yaml @@ -18,10 +18,10 @@ jobs: name: "Generate regexes" steps: - uses: actions/checkout@v3 - - name: Set up JDK 17 + - name: Set up JDK 21 uses: actions/setup-java@v3 with: - java-version: 17 + java-version: 21 distribution: temurin cache: gradle - name: Setup gradle @@ -33,7 +33,7 @@ jobs: name: Upload generated repo regexes with: name: Repo Regexes - path: build/regexes/constants.json + path: versions/1.8.9/build/regexes/constants.json publish-regexes: runs-on: ubuntu-latest needs: regexes diff --git a/.gitignore b/.gitignore index c303fd98c..d77f4bd8b 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ gradle.properties .devauth/* !.devauth/config.toml +.kotlin diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 62ffd979e..57f22f2e2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -180,3 +180,194 @@ Plugin [HotSwap Agent](https://plugins.jetbrains.com/plugin/9552-hotswapagent) t Follow [this](https://forums.Minecraftforge.net/topic/82228-1152-3110-intellij-and-gradlew-forge-hotswap-and-dcevm-tutorial/) tutorial. + +## 1.21 / Modern version development + +You might have noticed that while the SkyHanni source code is found in `src/`, the actual tasks for compiling, building and running the mod +are located in a subproject called `1.8.9`. This is because SkyHanni is preparing for the eventual fall of 1.8.9 (via the foraging update or +otherwise). + +To do so (while not disrupting regular development) we use [preprocessor](https://github.com/Deftu/RM-Preprocessor). Preprocessor +automatically transforms code based on mappings as well as comment directives to create multiple variants of your source code for +different Minecraft versions. + +Note also that the only targets we consider are 1.8.9 and 1.21 (or whatever the latest version we may target). The other versions are only there +to make mappings translate more easily (more on that later). + +### Goals + +It is the explicit goal of this operation to passively generate a 1.21 version of SH using preprocessor. To this end, contributors are +encouraged to add mappings and preprocessing directives to their features to make them compile on 1.21. *However*, this is considered a very +low priority. Due to the confusing nature (and the slower initial setup time due to decompiling four versions of Minecraft), this feature +is disabled by default. Similarly, it is up to each contributor to decide if they want to learn how to use preprocessor mappings and +directives. An explicit non-goal is to maintain two SH versions continuously; instead, we only want to make the eventual transition to 1.21 a task +that can be slowly worked on over a long span of time. + +### Set Up + +The modern version variants can be set using `skyhanni.multi-version` in `.gradle/private.properties` to three levels. + +`off` completely disables any preprocessor action or alternative versions. There will be only one project (although still at the `:1.8.9` +subproject path), and alternative version sources will not be generated (although old generated sources **will not be deleted**). To make +setting up a dev environment as fast and discernible as possible, this is the default option. + +`preprocess-only` adds the `preprocessCode` task as well as all the version subprojects. Compiling or running newer versions is not +possible, but the `preprocessCode` task can be run manually to inspect the generated source code. This mode is what should most often be +used when making alterations to the mappings or modifying preprocessor directives. Note that while this setting generally ignores any failed +renaming attempts, if something is so badly mangled that it cannot even guess a name for a function, it will still break the build. Those +situations should be rare, however. (In the entire SH codebase prior to me introducing this system I only found <10 such cases). You can +specifically compile 1.8.9 using `./gradlew :1.8.9:build`. This does not affect the regular execution of the client which will only compile +1.8.9. + +`compile` enables compilation for the `:1.21` subproject. This means that a `build` or `assemble` task will try (and fail) to compile a +1.21 (as well as 1.8.9) JAR. This mode may be useful for someone seeking out issues to fix, but is generally not useful in day to day +operations since the compile will never succeed and will block things like hotswap compilations (via <kbd>CTRL+F9</kbd>) from completing. + +### Improving mappings + +The different project versions are set up in such a way that each version depends on a slightly older version from which it is then adapted. +There are two main versions (1.8.9 and 1.21), but there are also a few bridge versions. These exist to make remapping easier since automatic +name mappings between 1.8.9 and 1.21 do not really exist. This is the current layout for our remaps: First, we remap to 1.12. This still +largely uses the old rendering system and has a lot of similar names to 1.8.9. As such, only very little needs to be adapted in terms of +behaviour, and at best, a couple of names need to be updated manually. The big jump is from 1.12 to 1.16. We use 1.16 since we don't want to +make too large of a jump (which could lead to a lot more missing names), but we still want to jump to a version with Fabric (and specifically +with Fabric intermediary mappings). We also can't really jump to an earlier version since 1.14 and 1.15 have a really poor Fabric API and +still have some of the old rendering code, meaning we would need to adapt to two slightly different rendering engines instead of just one +big rendering change. Despite the preprocessor's best efforts, this version will likely have the most manual mapping changes. Note that we +actually have two projects on 1.16. There is the Forge project, which is the one we remap to first. Then we remap to the corresponding +Fabric/Yarn mappings. This is because remapping between Searge and Yarn is very inconsistent unless it is done on one and the same version. +Finally, we remap from 1.16 to 1.21. This is a fairly small change, especially since Fabric intermediary mappings make different names +between versions very rare. The only real changes that need to be done in this jump are behavioural ones. + +The preprocessor does some built-in remapping (changing names), based on obfuscated names, but sometimes the automatic matching fails. If it +cannot find a new name (or the name it automatically determines was wrong), you can change the corresponding mapping. In order to make +this as smooth as possible, it is generally recommended to find the earliest spot at which the mappings deviate. So fixing a mapping on the +hop from 1.16 to 1.21 is generally not recommended. This is because, while we do not care about 1.12 or 1.16 compiling for its own merit, +we do care about the automatically inferred name changes from 1.12 to 1.16 and so on, which only work if those versions already have the +correct names available. + +#### A missing/incorrect name + +This is the easiest part. If a name for a function simply could not be automatically remapped, all you need to do is to add an entry in the +corresponding mapping.txt file. These can be found at `versions/mapping-<newVersion>-<oldVersion>.txt`. + +``` +# You can use # to comment lines + +# You can rename a class simply by writing the two names +# The first name is the name on the newer version (the first one in the file name); the second one is the name in the old version. +net.minecraft.util.math.MathHelper net.minecraft.util.MathHelper +# If you want to rename an inner class, remember to use $s +net.minecraft.world.scores.Team$Visibility net.minecraft.scoreboard.Team$EnumVisible + +# You can rename a field by writing the name of the containing class in the new version, and then the new and old name of the field. +# Again, the first field name is the one in the newer version (first in the file name). +net.minecraft.world.entity.Entity xOld prevPosX + +# Finally, you can also rename methods. To do so, you need to first specify the name of the containing class in the new version, then +# the name of the new and old method name. The first method name is the newer version name (first in the file name). +net.minecraft.util.text.Style getHoverEvent() getChatHoverEvent() +``` + +Adding a mapping like this is the easiest way to fix a broken method call, field access, or class reference. It will also apply to all +files, so you might be fixing issues in files you didn't even look at. It will even work in mixin targets, as long as they are unambiguous +(consider using the method descriptor instead of just the method name for your mixin). However, if something aside from the name changed, +this will not suffice. + +#### Conditional compilation + +In addition to the built-in remapping, there is also the more complicated art of preprocessor directives. Directives allow you to comment or +uncomment sections of the code depending on the version you are on. Uncommented sections are renamed as usual, so even within those directives, +you only need to write code for the *lowest* version that your comment is active in. As such, I once again highly recommend to target your +directive to the lowest version in which it applies, so that other sections that call into that code as well as your code can make use of +as many automatic renames as possible. + +There is only really one directive, which is `if`. Take this function, for example: + +```kt +private fun WorldClient.getAllEntities(): Iterable<Entity> = +//#if MC < 1.16 + loadedEntityList +//#else +//$$ entitiesForRendering() +//#endif +``` + +The first `#if` instructs the preprocessor to only uncomment the following code if the Minecraft version is less than 1.16. Then, the `#else` +uncomments the other section on versions 1.16 and above. Finally, the `#endif` ends the else block and lets the following functions always remain +active. To distinguish regular comments from preprocessor comments, preprocessor only works with comments that start with `//$$`. So let's +walk through what is happening here. + +In 1.8.9, the code remains unchanged. **Note that this means the programmer is responsible for commenting out the unused parts. +The preprocessor will never change the `src/` directory**. + +Next, the preprocessor converts the code to 1.12. 1.12 still has the `loadedEntityList` as well as the same name for the `WorldClient` and +`Entity` classes, so nothing is changed. + +Next, the code gets converted to 1.16 Forge. Since 1.16 is not less than 1.16, it will comment out the first line and uncomment the second line. +1.16 Forge also uses a different name for `WorldClient` and a different package for `Entity`, so those are also changed (the package change +is only visible in the imports): + +```kt +private fun ClientLevel.getAllEntities(): Iterable<Entity> = +//#if MC < 1.14 +//$$ loadedEntityList +//#else + entitiesForRendering() +//#endif +``` + +Now the code gets converted to 1.16 Fabric. Since those two targets are on the same Minecraft version name changes almost never fail to be +done automatically. Notice the different names for `ClientWorld` as well as `entities`. The method is called `getEntities()` on Fabric, but +since this is Kotlin code, the preprocessor automatically cleans up `getEntities()` using +[Kotlin property access syntax](https://kotlinlang.org/docs/java-interop.html#getters-and-setters). + +```kt +private fun ClientWorld.getAllEntities(): Iterable<Entity> = +//#if MC < 1.14 +//$$ loadedEntityList +//#else + entities +//#endif +``` + +Finally, the code gets converted to 1.21 using intermediary mappings. This last step does not bring any new challenges, so we end up with: + +```kt +private fun ClientWorld.getAllEntities(): Iterable<Entity> = +//#if MC < 1.14 +//$$ loadedEntityList +//#else + entities +//#endif +``` + +#### If expressions + +Let's look at the syntax of those `#if` expressions. + +First of all, the `#else` block is optional. If you just want code on some versions (for example for adding a method call that is implicitly +done on newer versions, or simply because the corresponding code for newer versions has to be done in some other place), you can just omit +the `#else` section and you will simply not compile any code at that spot. + +There is also an `#elseif` in case you want to switch behaviour based on multiple version brackets. Again, while we don't actually target +1.12 or 1.16, making those versions compile will help other parts of the code to upgrade to 1.21 more cleanly and easily. So, making those +versions work (or at least providing a stub like `error("Not implemented on this version") as List<Entity>` to make types infer correctly) +should be something you look out for. + +`#if` and `#elseif` also do not support complicated expressions. The only operations supported are `!=`, `==`, `>=`, `<=`, `<` and `>`. You +cannot join two checks using `&&` or similar, instead needing to use nested `#if`s. + +The actual versions being worked with here are not actually semantically compared Minecraft versions, but instead integers in the form +`major * 10000 + minor * 100 + patch`. So, for example, `1.12` turns into `11200`. Both `11200` and `1.12` can be used in directives, but +`1.12` style values are generally easier to understand. + +You can also check if you are on Forge using the `FORGE` variable. It is set to either 1 or 0. Similarly, there is also a `JAVA` variable to +check the Java version this Minecraft version is on. For the `FORGE` variable there is an implicit `!= 0` to check added if you just check +for the variable using `#if FORGE`. + +#### Helpers + +Sadly, `#if` expressions cannot be applied globally (unlike name changes), so it is often very helpful to create a helper method and call +that method from various places in the codebase. This is generally already policy in SH for a lot of things. For more complex types that +change beyond just their name (for example different generics), a `typealias` can be used in combination with `#if` expressions. diff --git a/build.gradle.kts b/build.gradle.kts index 8aaa2d638..773c7ac28 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,52 +1,39 @@ -import org.apache.commons.lang3.SystemUtils +import at.skyhanni.sharedvariables.MinecraftVersion +import at.skyhanni.sharedvariables.MultiVersionStage +import at.skyhanni.sharedvariables.ProjectTarget +import at.skyhanni.sharedvariables.SHVersionInfo +import at.skyhanni.sharedvariables.versionString +import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile -import java.io.ByteArrayOutputStream plugins { idea java - id("gg.essential.loom") version "0.10.0.+" - id("dev.architectury.architectury-pack200") version "0.1.3" id("com.github.johnrengelman.shadow") version "7.1.2" - kotlin("jvm") version "1.9.0" - id("com.bnorm.power.kotlin-power-assert") version "0.13.0" + id("gg.essential.loom") + id("dev.deftu.gradle.preprocess") + kotlin("jvm") + id("com.google.devtools.ksp") + kotlin("plugin.power-assert") `maven-publish` - id("com.google.devtools.ksp") version "1.9.0-1.0.13" id("moe.nea.shot") version "1.0.0" } -group = "at.hannibal2.skyhanni" -version = "0.26.Beta.21" - -val gitHash by lazy { - val baos = ByteArrayOutputStream() - exec { - standardOutput = baos - commandLine("git", "rev-parse", "--short", "HEAD") - isIgnoreExitValue = true - } - baos.toByteArray().decodeToString().trim() -} - -// Toolchains: -java { - toolchain.languageVersion.set(JavaLanguageVersion.of(8)) -} - -sourceSets.main { - output.setResourcesDir(sourceSets.main.flatMap { it.java.classesDirectory }) - java.srcDir(layout.projectDirectory.dir("src/main/kotlin")) - kotlin.destinationDirectory.set(java.destinationDirectory) -} +val target = ProjectTarget.values().find { it.projectPath == project.path }!! repositories { mavenCentral() mavenLocal() + maven("https://maven.minecraftforge.net") { + metadataSources { + artifact() // We love missing POMs + } + } maven("https://repo.spongepowered.org/maven/") // mixin maven("https://pkgs.dev.azure.com/djtheredstoner/DevAuth/_packaging/public/maven/v1") // DevAuth maven("https://jitpack.io") { // NotEnoughUpdates (compiled against) content { - includeGroupByRegex("com\\.github\\..*") + includeGroupByRegex("(com|io)\\.github\\..*") } } maven("https://repo.nea.moe/releases") // libautoupdate @@ -55,6 +42,53 @@ repositories { maven("https://maven.teamresourceful.com/repository/thatgravyboat/") // DiscordIPC } +// Toolchains: +java { + toolchain.languageVersion.set(target.minecraftVersion.javaLanguageVersion) + // We specifically request ADOPTIUM because if we do not restrict the vendor DCEVM is a + // possible candidate. Some DCEVMs are however incompatible with some things gradle is doing, + // causing crashes during tests. You can still manually select DCEVM in the Minecraft Client + // IntelliJ run configuration. + toolchain.vendor.set(JvmVendorSpec.ADOPTIUM) +} +val runDirectory = rootProject.file("run") +runDirectory.mkdirs() +// Minecraft configuration: +loom { + if (this.isForgeLike) + forge { + pack200Provider.set(dev.architectury.pack200.java.Pack200Adapter()) + mixinConfig("mixins.skyhanni.json") + } + mixin { + useLegacyMixinAp.set(true) + defaultRefmapName.set("mixins.skyhanni.refmap.json") + } + runs { + named("client") { + if (target == ProjectTarget.MAIN) { + isIdeConfigGenerated = true + appendProjectPathToConfigName.set(false) + } + this.runDir(runDirectory.relativeTo(projectDir).toString()) + property("mixin.debug", "true") + if (System.getenv("repo_action") != "true") { + property("devauth.configDir", rootProject.file(".devauth").absolutePath) + } + vmArgs("-Xmx4G") + programArgs("--tweakClass", "at.hannibal2.skyhanni.tweaker.SkyHanniTweaker") + programArgs("--tweakClass", "io.github.notenoughupdates.moulconfig.tweaker.DevelopmentResourceTweaker") + } + removeIf { it.name == "server" } + } +} + +if (target == ProjectTarget.MAIN) + sourceSets.main { + resources.destinationDirectory.set(kotlin.destinationDirectory) + output.setResourcesDir(kotlin.destinationDirectory) + } + val shadowImpl: Configuration by configurations.creating { configurations.implementation.get().extendsFrom(this) } @@ -72,13 +106,22 @@ val headlessLwjgl by configurations.creating { isTransitive = false isVisible = false } - -val shot = shots.shot("minecraft", project.file("shots.txt")) +tasks.runClient { + this.javaLauncher.set(javaToolchains.launcherFor { + languageVersion.set(target.minecraftVersion.javaLanguageVersion) + }) +} +val shot = shots.shot("minecraft", rootProject.file("shots.txt")) dependencies { - minecraft("com.mojang:minecraft:1.8.9") - mappings("de.oceanlabs.mcp:mcp_stable:22-1.8.9") - forge("net.minecraftforge:forge:1.8.9-11.15.1.2318-1.8.9") + minecraft("com.mojang:minecraft:${target.minecraftVersion.versionName}") + if (target.mappingDependency == "official") { + mappings(loom.officialMojangMappings()) + } else { + mappings(target.mappingDependency) + } + if (target.forgeDep != null) + "forge"(target.forgeDep!!) // Discord RPC client shadowImpl("com.jagrosh:DiscordIPC:0.5.3") { @@ -93,10 +136,16 @@ dependencies { compileOnly(ksp(project(":annotation-processors"))!!) - shadowImpl("org.spongepowered:mixin:0.7.11-SNAPSHOT") { - isTransitive = false + val mixinVersion = if (target.minecraftVersion >= MinecraftVersion.MC11200) "0.8.2" else "0.7.11-SNAPSHOT" + + if (!target.isFabric) { + shadowImpl("org.spongepowered:mixin:$mixinVersion") { + isTransitive = false + } + annotationProcessor("org.spongepowered:mixin:0.8.5-SNAPSHOT") + annotationProcessor("com.google.code.gson:gson:2.10.1") + annotationProcessor("com.google.guava:guava:17.0") } - annotationProcessor("org.spongepowered:mixin:0.8.4-SNAPSHOT") implementation(kotlin("stdlib-jdk8")) shadowImpl("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") { @@ -133,14 +182,16 @@ dependencies { implementation("net.hypixel:mod-api:0.3.1") } -configurations.getByName("minecraftNamed").dependencies.forEach { - shot.applyTo(it as HasConfigurableAttributes<*>) +afterEvaluate { + loom.runs.named("client") { + programArgs("--mods", devenvMod.resolve().joinToString(",") { it.relativeTo(runDirectory).path }) + } } tasks.withType(Test::class) { useJUnitPlatform() javaLauncher.set(javaToolchains.launcherFor(java.toolchain)) - workingDir(file("run")) + workingDir(file(runDirectory)) systemProperty("junit.jupiter.extensions.autodetection.enabled", "true") } @@ -151,46 +202,6 @@ kotlin { enableLanguageFeature("BreakContinueInInlineLambdas") } } - sourceSets.main { - kotlin.srcDir("build/generated/ksp/main/kotlin") - } - sourceSets.test { - kotlin.srcDir("build/generated/ksp/test/kotlin") - } -} - -// Minecraft configuration: -loom { - launchConfigs { - "client" { - property("mixin.debug", "true") - if (System.getenv("repo_action") != "true") { - property("devauth.configDir", rootProject.file(".devauth").absolutePath) - } - arg("--tweakClass", "at.hannibal2.skyhanni.tweaker.SkyHanniTweaker") - arg("--tweakClass", "io.github.notenoughupdates.moulconfig.tweaker.DevelopmentResourceTweaker") - arg("--mods", devenvMod.resolve().joinToString(",") { it.relativeTo(file("run")).path }) - } - } - forge { - pack200Provider.set(dev.architectury.pack200.java.Pack200Adapter()) - mixinConfig("mixins.skyhanni.json") - } - @Suppress("UnstableApiUsage") - mixin { - defaultRefmapName.set("mixins.skyhanni.refmap.json") - } - runConfigs { - "client" { - if (SystemUtils.IS_OS_MAC_OSX) { - vmArgs.remove("-XstartOnFirstThread") - } - vmArgs.add("-Xmx4G") - } - "server" { - isIdeConfigGenerated = false - } - } } // Tasks: @@ -199,51 +210,70 @@ tasks.processResources { filesMatching(listOf("mcmod.info", "fabric.mod.json")) { expand("version" to version) } + if (target.isFabric) { + exclude("mcmod.info") + } // else do NOT exclude fabric.mod.json. We use fabric.mod.json in order to show a logo in prism launcher. } -val generateRepoPatterns by tasks.creating(JavaExec::class) { - javaLauncher.set(javaToolchains.launcherFor(java.toolchain)) - mainClass.set("net.fabricmc.devlaunchinjector.Main") - workingDir(project.file("run")) - classpath(sourceSets.main.map { it.runtimeClasspath }, sourceSets.main.map { it.output }) - jvmArgs( - "-Dfabric.dli.config=${project.file(".gradle/loom-cache/launch.cfg").absolutePath}", - "-Dfabric.dli.env=client", - "-Dfabric.dli.main=net.minecraft.launchwrapper.Launch", - "-Dorg.lwjgl.opengl.Display.allowSoftwareOpenGL=true", - "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5006", - "-javaagent:${headlessLwjgl.singleFile.absolutePath}" - ) - val outputFile = project.file("build/regexes/constants.json") - environment("SKYHANNI_DUMP_REGEXES", "${gitHash}:${outputFile.absolutePath}") - environment("SKYHANNI_DUMP_REGEXES_EXIT", "true") +if (target == ProjectTarget.MAIN) { |
