From 76d2c364813b2cbd976551835ad1ab5534304abe Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Mon, 30 Sep 2024 18:34:12 -0700 Subject: [PATCH 1/9] WIP: Use ModDevGradle instead of archloom for common and NeoForge --- build.gradle | 82 ++++---------- buildSrc/build.gradle.kts | 11 ++ buildSrc/src/main/java/Aw2AtTask.java | 129 ++++++++++++++++++++++ buildSrc/src/main/java/CopyTask.java | 44 ++++++++ fabric/build.gradle | 55 ++++++++- neoforge/build.gradle | 58 ++++++++-- neoforge/gradle.properties | 1 - settings.gradle | 3 +- src/main/resources/moonrise.accesswidener | 7 ++ 9 files changed, 315 insertions(+), 75 deletions(-) create mode 100644 buildSrc/build.gradle.kts create mode 100644 buildSrc/src/main/java/Aw2AtTask.java create mode 100644 buildSrc/src/main/java/CopyTask.java delete mode 100644 neoforge/gradle.properties diff --git a/build.gradle b/build.gradle index 723b492d..4f75c67e 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,8 @@ import me.modmuss50.mpp.ReleaseType plugins { - id("xyz.jpenilla.quiet-architectury-loom") + id("java-library") + id("net.neoforged.moddev") id("me.modmuss50.mod-publish-plugin") version "0.7.2" apply false } @@ -18,24 +19,39 @@ def getGitCommit = { -> return stdout.toString().trim() } +Aw2AtTask.configureDefault( + getProject(), + layout.projectDirectory.file("src/main/resources/moonrise.accesswidener").getAsFile(), + sourceSets.main +) + +neoForge { + neoFormVersion = "1.21.3-20241023.131943" + validateAccessTransformers = true +} + +tasks.named("createMinecraftArtifacts") { + dependsOn("copyAt") +} dependencies { - modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" + // todo: check versions + compileOnly "net.fabricmc:sponge-mixin:0.13.4+mixin.0.8.5" + compileOnly "io.github.llamalad7:mixinextras-common:0.4.1" api("ca.spottedleaf:concurrentutil:${rootProject.concurrentutil_version}") api("ca.spottedleaf:yamlconfig:${rootProject.yamlconfig_version}") api("org.yaml:snakeyaml:${rootProject.snakeyaml_version}") - modImplementation "me.shedaniel.cloth:cloth-config:${rootProject.cloth_version}" + // todo: does cloth publish a platform-agnostic jar in mojang mappings? + compileOnly "me.shedaniel.cloth:cloth-config-neoforge:${rootProject.cloth_version}" } -File awFile = file("src/main/resources/moonrise.accesswidener") - allprojects { group = rootProject.maven_group version = rootProject.mod_version + "+" + getGitCommit() - plugins.apply("xyz.jpenilla.quiet-architectury-loom") + plugins.apply("java-library") java { withSourcesJar() @@ -62,11 +78,6 @@ allprojects { maven { url "https://maven.terraformersmc.com/releases/" } } - dependencies { - minecraft "com.mojang:minecraft:${project.minecraft_version}" - mappings loom.officialMojangMappings() - } - // make build reproducible tasks.withType(AbstractArchiveTask).configureEach { preserveFileTimestamps = false @@ -82,32 +93,12 @@ allprojects { rename { "${it}_${rootProject.base.archivesName.get()}"} } } - - loom { - accessWidenerPath = awFile - mixin { - useLegacyMixinAp = false - } - } } subprojects { - loom.mods { - main { - sourceSet("main") - sourceSet("main", project.rootProject) - } - } - loom.runs.all { - ideConfigGenerated true - property "mixin.debug", "true" - property "Moonrise.MaxViewDistance", "128" - } - plugins.apply("me.modmuss50.mod-publish-plugin") publishMods { - file = remapJar.archiveFile if (project.version.contains("-beta.")) { type = ReleaseType.BETA } else { @@ -129,33 +120,4 @@ subprojects { minecraftVersions = supportedMcVersions } } - - // Setup a run with lithium for compatibility testing - sourceSets.create("lithium") - configurations.create("lithium") - loom { - createRemapConfigurations(sourceSets.lithium) - runs { - register("lithiumClient") { - client() - property "mixin.debug", "true" - } - } - } - tasks.named("runLithiumClient", net.fabricmc.loom.task.RunGameTask.class) { - getClasspath().from(configurations.modRuntimeClasspathLithiumMapped) - } - dependencies { - String coordinates = "maven.modrinth:lithium:" - if (getProject().name == "Moonrise-NeoForge") { - coordinates += rootProject.neo_lithium_version - } else { - coordinates += rootProject.fabric_lithium_version - } - modLithiumRuntimeOnly coordinates - } -} - -loom.runs.all { - ideConfigGenerated false } diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts new file mode 100644 index 00000000..81dbb2bb --- /dev/null +++ b/buildSrc/build.gradle.kts @@ -0,0 +1,11 @@ +repositories { + gradlePluginPortal() + mavenCentral() + maven("https://maven.fabricmc.net/") + maven("https://maven.architectury.dev/") +} + +dependencies { + implementation("net.fabricmc:access-widener:2.1.0") + implementation("dev.architectury:at:1.0.1") +} diff --git a/buildSrc/src/main/java/Aw2AtTask.java b/buildSrc/src/main/java/Aw2AtTask.java new file mode 100644 index 00000000..c881ff85 --- /dev/null +++ b/buildSrc/src/main/java/Aw2AtTask.java @@ -0,0 +1,129 @@ +import dev.architectury.at.AccessChange; +import dev.architectury.at.AccessTransform; +import dev.architectury.at.AccessTransformSet; +import dev.architectury.at.ModifierChange; +import dev.architectury.at.io.AccessTransformFormats; +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import javax.inject.Inject; +import net.fabricmc.accesswidener.AccessWidenerReader; +import net.fabricmc.accesswidener.AccessWidenerVisitor; +import org.cadixdev.bombe.type.signature.MethodSignature; +import org.gradle.api.DefaultTask; +import org.gradle.api.Project; +import org.gradle.api.file.ProjectLayout; +import org.gradle.api.file.RegularFileProperty; +import org.gradle.api.tasks.CacheableTask; +import org.gradle.api.tasks.InputFile; +import org.gradle.api.tasks.OutputFile; +import org.gradle.api.tasks.PathSensitive; +import org.gradle.api.tasks.PathSensitivity; +import org.gradle.api.tasks.SourceSet; +import org.gradle.api.tasks.TaskAction; +import org.gradle.api.tasks.TaskProvider; + +@CacheableTask +public abstract class Aw2AtTask extends DefaultTask { + + @InputFile + @PathSensitive(PathSensitivity.NONE) + public abstract RegularFileProperty getInputFile(); + + @OutputFile + public abstract RegularFileProperty getOutputFile(); + + @Inject + public abstract ProjectLayout getLayout(); + + public static TaskProvider configureDefault( + final Project project, + final File awFile, + final SourceSet sourceSet + ) { + final TaskProvider aw2at = project.getTasks().register("aw2at", Aw2AtTask.class, task -> { + task.getOutputFile().set(project.getLayout().getBuildDirectory().file("aw2at/files/accesstransformer.cfg")); + task.getInputFile().set(awFile); + }); + + final TaskProvider copyTask = project.getTasks().register("copyAt", CopyTask.class, copy -> { + copy.getInputFile().set(aw2at.flatMap(Aw2AtTask::getOutputFile)); + copy.getOutputDirectory().set(project.getLayout().getBuildDirectory().dir("aw2at/dir")); + copy.getDestination().set("META-INF/accesstransformer.cfg"); + }); + + sourceSet.resources(resources -> { + resources.srcDir(copyTask.flatMap(CopyTask::getOutputDirectory)); + }); + + return aw2at; + } + + @TaskAction + public void run() { + try (final BufferedReader reader = Files.newBufferedReader(this.getInputFile().get().getAsFile().toPath())) { + final AccessTransformSet accessTransformSet = toAccessTransformSet(reader); + Files.deleteIfExists(this.getOutputFile().get().getAsFile().toPath()); + Files.createDirectories(this.getOutputFile().get().getAsFile().toPath().getParent()); + AccessTransformFormats.FML.write(this.getOutputFile().get().getAsFile().toPath(), accessTransformSet); + } catch (final IOException e) { + throw new RuntimeException(e); + } + } + + // Below methods are heavily based on architectury-loom Aw2At class (MIT licensed) + /* + MIT License + + Copyright (c) 2016 FabricMC + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + */ + + public static AccessTransformSet toAccessTransformSet(final BufferedReader reader) throws IOException { + AccessTransformSet atSet = AccessTransformSet.create(); + + new AccessWidenerReader(new AccessWidenerVisitor() { + @Override + public void visitClass(final String name, final AccessWidenerReader.AccessType access, final boolean transitive) { + atSet.getOrCreateClass(name).merge(toAt(access)); + } + + @Override + public void visitMethod(final String owner, final String name, final String descriptor, final AccessWidenerReader.AccessType access, final boolean transitive) { + atSet.getOrCreateClass(owner).mergeMethod(MethodSignature.of(name, descriptor), toAt(access)); + } + + @Override + public void visitField(final String owner, final String name, final String descriptor, final AccessWidenerReader.AccessType access, final boolean transitive) { + atSet.getOrCreateClass(owner).mergeField(name, toAt(access)); + } + }).read(reader); + + return atSet; + } + + public static AccessTransform toAt(final AccessWidenerReader.AccessType access) { + return switch (access) { + case ACCESSIBLE -> AccessTransform.of(AccessChange.PUBLIC); + case EXTENDABLE, MUTABLE -> AccessTransform.of(AccessChange.PUBLIC, ModifierChange.REMOVE); + }; + } +} diff --git a/buildSrc/src/main/java/CopyTask.java b/buildSrc/src/main/java/CopyTask.java new file mode 100644 index 00000000..b727a66d --- /dev/null +++ b/buildSrc/src/main/java/CopyTask.java @@ -0,0 +1,44 @@ +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Comparator; +import java.util.stream.Stream; +import org.gradle.api.DefaultTask; +import org.gradle.api.file.DirectoryProperty; +import org.gradle.api.file.RegularFileProperty; +import org.gradle.api.provider.Property; +import org.gradle.api.tasks.Input; +import org.gradle.api.tasks.InputFile; +import org.gradle.api.tasks.OutputDirectory; +import org.gradle.api.tasks.TaskAction; + +public abstract class CopyTask extends DefaultTask { + + @InputFile + public abstract RegularFileProperty getInputFile(); + + @Input + public abstract Property getDestination(); + + @OutputDirectory + public abstract DirectoryProperty getOutputDirectory(); + + @TaskAction + public void run() { + final Path outputDirPath = this.getOutputDirectory().get().getAsFile().toPath(); + try { + try (final Stream walk = Files.walk(outputDirPath)) { + for (final Path path : walk.sorted(Comparator.reverseOrder()).toList()) { + Files.delete(path); + } + } + + final Path destFile = outputDirPath.resolve(this.getDestination().get()); + Files.createDirectories(destFile.getParent()); + + Files.copy(this.getInputFile().get().getAsFile().toPath(), destFile); + } catch (final IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/fabric/build.gradle b/fabric/build.gradle index 0d2f6b94..b37116d9 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -1,5 +1,5 @@ plugins { - id("xyz.jpenilla.quiet-architectury-loom") + id("quiet-fabric-loom") id 'maven-publish' id 'com.gradleup.shadow' } @@ -13,10 +13,15 @@ configurations.implementation { } dependencies { - add('shadow', project([path: ":", configuration: "namedElements"])) - runtimeOnly(project(":").sourceSets.main.output) + minecraft "com.mojang:minecraft:${project.minecraft_version}" + mappings loom.officialMojangMappings() modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" + // todo: runs are broken (cannot find aw file) + //add('shadow', project([path: ":", configuration: "namedElements"])) + //runtimeOnly(project(":").sourceSets.main.output) + libs(project(":")) + libs("ca.spottedleaf:concurrentutil:${rootProject.concurrentutil_version}") libs("ca.spottedleaf:yamlconfig:${rootProject.yamlconfig_version}") libs("org.yaml:snakeyaml:${rootProject.snakeyaml_version}") @@ -49,6 +54,7 @@ shadowJar { } publishMods { + file = remapJar.archiveFile modLoaders = ["fabric"] modrinth { @@ -66,3 +72,46 @@ publishMods { ) } } + +loom { + accessWidenerPath.set(getRootProject().file("src/main/resources/moonrise.accesswidener")) + mixin { + useLegacyMixinAp = false + } + runs.all { + ideConfigGenerated true + property "mixin.debug", "true" + property "Moonrise.MaxViewDistance", "128" + } + mods { + main { + sourceSet("main") + sourceSet("main", project.rootProject) + } + } +} + +// Setup a run with lithium for compatibility testing +sourceSets.create("lithium") +configurations.create("lithium") +loom { + createRemapConfigurations(sourceSets.lithium) + runs { + register("lithiumClient") { + client() + property "mixin.debug", "true" + } + } +} +tasks.named("runLithiumClient", net.fabricmc.loom.task.RunGameTask.class) { + getClasspath().from(configurations.modRuntimeClasspathLithiumMapped) +} +dependencies { + String coordinates = "maven.modrinth:lithium:" + if (getProject().name == "Moonrise-NeoForge") { + coordinates += rootProject.neo_lithium_version + } else { + coordinates += rootProject.fabric_lithium_version + } + modLithiumRuntimeOnly coordinates +} diff --git a/neoforge/build.gradle b/neoforge/build.gradle index 14027e1a..417a43c3 100644 --- a/neoforge/build.gradle +++ b/neoforge/build.gradle @@ -1,7 +1,8 @@ -import net.fabricmc.loom.util.aw2at.Aw2At +import net.neoforged.moddevgradle.internal.RunGameTask +import java.nio.file.Files plugins { - id("xyz.jpenilla.quiet-architectury-loom") + id("net.neoforged.moddev") id 'maven-publish' id 'com.gradleup.shadow' } @@ -13,21 +14,55 @@ repositories { } } +Aw2AtTask.configureDefault( + getProject(), + rootProject.layout.projectDirectory.file("src/main/resources/moonrise.accesswidener").getAsFile(), + sourceSets.main +) + +neoForge { + version = rootProject.neoforge_version + validateAccessTransformers = true + runs { + client { + client() + mods.set([]) // Work around classpath issues by using the production jar for dev runs + } + server { + server() + mods.set([]) // Work around classpath issues by using the production jar for dev runs + } + } +} + +tasks.named("createMinecraftArtifacts") { + dependsOn("copyAt") +} + configurations.implementation { extendsFrom(configurations.shadow) } dependencies { - add('shadow', project([path: ":", configuration: "namedElements"])) - neoForge "net.neoforged:neoforge:${rootProject.neoforge_version}" + add('shadow', project(":")) shadow("ca.spottedleaf:concurrentutil:${rootProject.concurrentutil_version}") shadow("ca.spottedleaf:yamlconfig:${rootProject.yamlconfig_version}") shadow("org.yaml:snakeyaml:${rootProject.snakeyaml_version}") - forgeExtra("org.yaml:snakeyaml:${rootProject.snakeyaml_version}") - modImplementation "me.shedaniel.cloth:cloth-config-neoforge:${rootProject.cloth_version}" - include "me.shedaniel.cloth:cloth-config-neoforge:${rootProject.cloth_version}" + implementation "me.shedaniel.cloth:cloth-config-neoforge:${rootProject.cloth_version}" + jarJar "me.shedaniel.cloth:cloth-config-neoforge:${rootProject.cloth_version}" +} + +// Work around classpath issues by using the production jar for dev runs +tasks.withType(RunGameTask).configureEach { + dependsOn(tasks.shadowJar) + doFirst { + def jar = file("run/mods/main.jar") + jar.parentFile.mkdirs() + jar.delete() + Files.copy(tasks.shadowJar.archiveFile.get().asFile.toPath(), jar.toPath()) + } } processResources { @@ -38,8 +73,12 @@ processResources { } } +jar { + archiveClassifier = "" +} + shadowJar { - archiveClassifier = "dev-all" + archiveClassifier = "" destinationDirectory = layout.buildDirectory.dir("libs") configurations = [project.configurations.shadow] relocate 'ca.spottedleaf.concurrentutil', 'ca.spottedleaf.moonrise.libs.ca.spottedleaf.concurrentutil' @@ -47,9 +86,8 @@ shadowJar { relocate 'org.yaml.snakeyaml', 'ca.spottedleaf.moonrise.libs.org.yaml.snakeyaml' } -Aw2At.setup(getProject(), tasks.remapJar) - publishMods { + file = shadowJar.archiveFile modLoaders = ["neoforge"] modrinth { diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties deleted file mode 100644 index 7da18ea6..00000000 --- a/neoforge/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -loom.platform=neoforge diff --git a/settings.gradle b/settings.gradle index a5d55ae2..16e74c05 100644 --- a/settings.gradle +++ b/settings.gradle @@ -24,7 +24,8 @@ pluginManagement { plugins { id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0" - id("xyz.jpenilla.quiet-architectury-loom") version "1.7.310" apply false + id("quiet-fabric-loom") version "1.8.306" apply false + id("net.neoforged.moddev") version "2.0.49-beta" apply false id 'com.gradleup.shadow' version '8.3.0' apply false } diff --git a/src/main/resources/moonrise.accesswidener b/src/main/resources/moonrise.accesswidener index e217190b..b4415afe 100644 --- a/src/main/resources/moonrise.accesswidener +++ b/src/main/resources/moonrise.accesswidener @@ -22,6 +22,8 @@ accessible field net/minecraft/world/level/chunk/PalettedContainer data Lnet/min # PalettedContainer.Data accessible class net/minecraft/world/level/chunk/PalettedContainer$Data +# MDG requires we AT the constructor if we AT the class +accessible method net/minecraft/world/level/chunk/PalettedContainer$Data (Lnet/minecraft/world/level/chunk/PalettedContainer$Configuration;Lnet/minecraft/util/BitStorage;Lnet/minecraft/world/level/chunk/Palette;)V # PaletteResize @@ -150,6 +152,11 @@ accessible method net/minecraft/world/level/material/Fluid isEmpty ()Z accessible method net/minecraft/world/level/material/Fluid createLegacyBlock (Lnet/minecraft/world/level/material/FluidState;)Lnet/minecraft/world/level/block/state/BlockState; accessible method net/minecraft/world/level/material/Fluid isRandomlyTicking ()Z +# We need to manually copy these down for MDG +accessible method net/minecraft/world/level/material/EmptyFluid isEmpty ()Z +accessible method net/minecraft/world/level/material/EmptyFluid createLegacyBlock (Lnet/minecraft/world/level/material/FluidState;)Lnet/minecraft/world/level/block/state/BlockState; +accessible method net/minecraft/world/level/material/LavaFluid createLegacyBlock (Lnet/minecraft/world/level/material/FluidState;)Lnet/minecraft/world/level/block/state/BlockState; +accessible method net/minecraft/world/level/material/LavaFluid isRandomlyTicking ()Z # VisibilitySet accessible field net/minecraft/client/renderer/chunk/VisibilitySet FACINGS I From 5635373cff59b15ddc7fa342fbf1347c447d7ea7 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Tue, 1 Oct 2024 09:17:11 -0700 Subject: [PATCH 2/9] Replace AT task dependency workaround --- build.gradle | 7 ++----- neoforge/build.gradle | 7 ++----- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/build.gradle b/build.gradle index 4f75c67e..da7b1db6 100644 --- a/build.gradle +++ b/build.gradle @@ -19,7 +19,7 @@ def getGitCommit = { -> return stdout.toString().trim() } -Aw2AtTask.configureDefault( +def aw2at = Aw2AtTask.configureDefault( getProject(), layout.projectDirectory.file("src/main/resources/moonrise.accesswidener").getAsFile(), sourceSets.main @@ -28,10 +28,7 @@ Aw2AtTask.configureDefault( neoForge { neoFormVersion = "1.21.3-20241023.131943" validateAccessTransformers = true -} - -tasks.named("createMinecraftArtifacts") { - dependsOn("copyAt") + accessTransformers.files.setFrom(aw2at.flatMap { t -> t.getOutputFile() }) } dependencies { diff --git a/neoforge/build.gradle b/neoforge/build.gradle index 417a43c3..f04449fb 100644 --- a/neoforge/build.gradle +++ b/neoforge/build.gradle @@ -14,7 +14,7 @@ repositories { } } -Aw2AtTask.configureDefault( +def aw2at = Aw2AtTask.configureDefault( getProject(), rootProject.layout.projectDirectory.file("src/main/resources/moonrise.accesswidener").getAsFile(), sourceSets.main @@ -23,6 +23,7 @@ Aw2AtTask.configureDefault( neoForge { version = rootProject.neoforge_version validateAccessTransformers = true + accessTransformers.files.setFrom(aw2at.flatMap { t -> t.getOutputFile() }) runs { client { client() @@ -35,10 +36,6 @@ neoForge { } } -tasks.named("createMinecraftArtifacts") { - dependsOn("copyAt") -} - configurations.implementation { extendsFrom(configurations.shadow) } From 9b6982bf65f63fd572a42dafd0bffbf499b093dc Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Thu, 28 Nov 2024 11:35:00 -0700 Subject: [PATCH 3/9] Work on fixing runs --- build.gradle | 41 ++++++++++++++++------ fabric/build.gradle | 16 ++------- gradle/wrapper/gradle-wrapper.jar | Bin 43504 -> 43583 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- neoforge/build.gradle | 33 ++++++++++------- settings.gradle | 3 +- src/main/resources/moonrise.accesswidener | 2 ++ 7 files changed, 58 insertions(+), 39 deletions(-) diff --git a/build.gradle b/build.gradle index da7b1db6..17c4683b 100644 --- a/build.gradle +++ b/build.gradle @@ -3,21 +3,16 @@ import me.modmuss50.mpp.ReleaseType plugins { id("java-library") id("net.neoforged.moddev") - id("me.modmuss50.mod-publish-plugin") version "0.7.2" apply false + id("me.modmuss50.mod-publish-plugin") version "0.8.1" apply false } /* * Gets the version name from the latest Git tag */ // https://stackoverflow.com/questions/28498688/gradle-script-to-autoversion-and-include-the-commit-hash-in-android -def getGitCommit = { -> - def stdout = new ByteArrayOutputStream() - exec { - commandLine 'git', 'rev-parse', '--short', 'HEAD' - standardOutput = stdout - } - return stdout.toString().trim() -} +def getGitCommit = providers.exec { + commandLine 'git', 'rev-parse', '--short', 'HEAD' +}.standardOutput.getAsText().map { it.trim() } def aw2at = Aw2AtTask.configureDefault( getProject(), @@ -31,10 +26,24 @@ neoForge { accessTransformers.files.setFrom(aw2at.flatMap { t -> t.getOutputFile() }) } +class FixAsmRule implements ComponentMetadataRule { + @Override + void execute(ComponentMetadataContext ctx) { + ctx.details.allVariants { + it.withDependencies { + it.removeIf { + it.group == "org.ow2.asm" + } + } + } + } +} + dependencies { // todo: check versions - compileOnly "net.fabricmc:sponge-mixin:0.13.4+mixin.0.8.5" + compileOnly "net.fabricmc:sponge-mixin:0.15.4+mixin.0.8.7" compileOnly "io.github.llamalad7:mixinextras-common:0.4.1" + components.withModule("net.neoforged:minecraft-dependencies", FixAsmRule.class) api("ca.spottedleaf:concurrentutil:${rootProject.concurrentutil_version}") api("ca.spottedleaf:yamlconfig:${rootProject.yamlconfig_version}") @@ -46,7 +55,7 @@ dependencies { allprojects { group = rootProject.maven_group - version = rootProject.mod_version + "+" + getGitCommit() + version = rootProject.mod_version + "+" + getGitCommit.get() plugins.apply("java-library") @@ -94,6 +103,16 @@ allprojects { subprojects { plugins.apply("me.modmuss50.mod-publish-plugin") + plugins.apply 'java-library' + plugins.apply 'com.gradleup.shadow' + + configurations.create("libs") + configurations.shadow { + extendsFrom(configurations.libs) + } + configurations.implementation { + extendsFrom(configurations.libs) + } publishMods { if (project.version.contains("-beta.")) { diff --git a/fabric/build.gradle b/fabric/build.gradle index b37116d9..7c796da0 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -1,15 +1,6 @@ plugins { id("quiet-fabric-loom") id 'maven-publish' - id 'com.gradleup.shadow' -} - -configurations.create("libs") -configurations.shadow { - extendsFrom(configurations.libs) -} -configurations.implementation { - extendsFrom(configurations.libs) } dependencies { @@ -17,10 +8,9 @@ dependencies { mappings loom.officialMojangMappings() modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" - // todo: runs are broken (cannot find aw file) - //add('shadow', project([path: ":", configuration: "namedElements"])) - //runtimeOnly(project(":").sourceSets.main.output) - libs(project(":")) + runtimeOnly(project(":").sourceSets.main.output) + shadow(project(":")) + compileOnly(project(":")) libs("ca.spottedleaf:concurrentutil:${rootProject.concurrentutil_version}") libs("ca.spottedleaf:yamlconfig:${rootProject.yamlconfig_version}") diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 2c3521197d7c4586c843d1d3e9090525f1898cde..a4b76b9530d66f5e68d973ea569d8e19de379189 100644 GIT binary patch delta 3990 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index dedd5d1e..c1d5e018 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/neoforge/build.gradle b/neoforge/build.gradle index f04449fb..1a6db22e 100644 --- a/neoforge/build.gradle +++ b/neoforge/build.gradle @@ -4,7 +4,6 @@ import java.nio.file.Files plugins { id("net.neoforged.moddev") id 'maven-publish' - id 'com.gradleup.shadow' } repositories { @@ -24,34 +23,43 @@ neoForge { version = rootProject.neoforge_version validateAccessTransformers = true accessTransformers.files.setFrom(aw2at.flatMap { t -> t.getOutputFile() }) + mods { + moonrise { + sourceSet sourceSets.main + sourceSet rootProject.sourceSets.main + } + } runs { + configureEach { + additionalRuntimeClasspathConfiguration.extendsFrom configurations.libs + systemProperties.put('mixin.debug', 'true') + } client { client() - mods.set([]) // Work around classpath issues by using the production jar for dev runs + // loadedMods.set([]) // Work around module issues by using the production jar for dev runs } server { server() - mods.set([]) // Work around classpath issues by using the production jar for dev runs + // loadedMods.set([]) // Work around module issues by using the production jar for dev runs } } } -configurations.implementation { - extendsFrom(configurations.shadow) -} - dependencies { - add('shadow', project(":")) + runtimeOnly(project(":").sourceSets.main.output) + shadow(project(":")) + compileOnly(project(":")) - shadow("ca.spottedleaf:concurrentutil:${rootProject.concurrentutil_version}") - shadow("ca.spottedleaf:yamlconfig:${rootProject.yamlconfig_version}") - shadow("org.yaml:snakeyaml:${rootProject.snakeyaml_version}") + libs("ca.spottedleaf:concurrentutil:${rootProject.concurrentutil_version}") + libs("ca.spottedleaf:yamlconfig:${rootProject.yamlconfig_version}") + libs("org.yaml:snakeyaml:${rootProject.snakeyaml_version}") implementation "me.shedaniel.cloth:cloth-config-neoforge:${rootProject.cloth_version}" jarJar "me.shedaniel.cloth:cloth-config-neoforge:${rootProject.cloth_version}" } -// Work around classpath issues by using the production jar for dev runs +// Work around module issues by using the production jar for dev runs +/* tasks.withType(RunGameTask).configureEach { dependsOn(tasks.shadowJar) doFirst { @@ -61,6 +69,7 @@ tasks.withType(RunGameTask).configureEach { Files.copy(tasks.shadowJar.archiveFile.get().asFile.toPath(), jar.toPath()) } } + */ processResources { inputs.property "version", project.version diff --git a/settings.gradle b/settings.gradle index 16e74c05..634c0b9c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -13,7 +13,6 @@ pluginManagement { maven { name = 'jmp' url = 'https://repo.jpenilla.xyz/snapshots' - mavenContent { snapshotsOnly() } } maven { name = 'architectury' @@ -26,7 +25,7 @@ plugins { id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0" id("quiet-fabric-loom") version "1.8.306" apply false id("net.neoforged.moddev") version "2.0.49-beta" apply false - id 'com.gradleup.shadow' version '8.3.0' apply false + id 'com.gradleup.shadow' version '8.3.5' apply false } dependencyResolutionManagement { diff --git a/src/main/resources/moonrise.accesswidener b/src/main/resources/moonrise.accesswidener index b4415afe..103c46cf 100644 --- a/src/main/resources/moonrise.accesswidener +++ b/src/main/resources/moonrise.accesswidener @@ -312,3 +312,5 @@ accessible class net/minecraft/world/level/LocalMobCapCalculator$MobCounts # SectionStorage$PackedChunk accessible class net/minecraft/world/level/chunk/storage/SectionStorage$PackedChunk +# MDG requires we AT the constructor if we AT the class +accessible method net/minecraft/world/level/chunk/storage/SectionStorage$PackedChunk (Lit/unimi/dsi/fastutil/ints/Int2ObjectMap;Z)V From 882d73320375654e7d564a96e9e03de06c45be69 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Thu, 28 Nov 2024 14:53:45 -0700 Subject: [PATCH 4/9] More work on runs --- build.gradle | 37 ++++---- .../src/main/java/RemoveAsmDependency.java | 14 +++ buildSrc/src/main/java/RunConfigCommon.java | 5 ++ fabric/build.gradle | 41 ++++----- gradle.properties | 4 +- neoforge/build.gradle | 85 +++++++++++++------ settings.gradle | 2 +- 7 files changed, 122 insertions(+), 66 deletions(-) create mode 100644 buildSrc/src/main/java/RemoveAsmDependency.java create mode 100644 buildSrc/src/main/java/RunConfigCommon.java diff --git a/build.gradle b/build.gradle index 17c4683b..e8878d32 100644 --- a/build.gradle +++ b/build.gradle @@ -6,10 +6,8 @@ plugins { id("me.modmuss50.mod-publish-plugin") version "0.8.1" apply false } -/* - * Gets the version name from the latest Git tag - */ -// https://stackoverflow.com/questions/28498688/gradle-script-to-autoversion-and-include-the-commit-hash-in-android +extensions.create("runConfigCommon", RunConfigCommon.class) + def getGitCommit = providers.exec { commandLine 'git', 'rev-parse', '--short', 'HEAD' }.standardOutput.getAsText().map { it.trim() } @@ -21,29 +19,22 @@ def aw2at = Aw2AtTask.configureDefault( ) neoForge { - neoFormVersion = "1.21.3-20241023.131943" + neoFormVersion = neoform_version validateAccessTransformers = true accessTransformers.files.setFrom(aw2at.flatMap { t -> t.getOutputFile() }) } -class FixAsmRule implements ComponentMetadataRule { - @Override - void execute(ComponentMetadataContext ctx) { - ctx.details.allVariants { - it.withDependencies { - it.removeIf { - it.group == "org.ow2.asm" - } - } - } - } +runConfigCommon { + systemProperties.put "mixin.debug", "true" + systemProperties.put "Moonrise.MaxViewDistance", "128" } dependencies { // todo: check versions compileOnly "net.fabricmc:sponge-mixin:0.15.4+mixin.0.8.7" compileOnly "io.github.llamalad7:mixinextras-common:0.4.1" - components.withModule("net.neoforged:minecraft-dependencies", FixAsmRule.class) + // work around minecraft (MDG) forcing ASM 9.3 which is incompatible with the above deps... + components.withModule("net.neoforged:minecraft-dependencies", RemoveAsmDependency.class) api("ca.spottedleaf:concurrentutil:${rootProject.concurrentutil_version}") api("ca.spottedleaf:yamlconfig:${rootProject.yamlconfig_version}") @@ -136,4 +127,16 @@ subprojects { minecraftVersions = supportedMcVersions } } + + // Setup a run with lithium for compatibility testing + configurations.create("lithium") + dependencies { + String coordinates = "maven.modrinth:lithium:" + if (getProject().name == "Moonrise-NeoForge") { + coordinates += rootProject.neo_lithium_version + } else { + coordinates += rootProject.fabric_lithium_version + } + lithium coordinates + } } diff --git a/buildSrc/src/main/java/RemoveAsmDependency.java b/buildSrc/src/main/java/RemoveAsmDependency.java new file mode 100644 index 00000000..34a2346a --- /dev/null +++ b/buildSrc/src/main/java/RemoveAsmDependency.java @@ -0,0 +1,14 @@ +import java.util.Objects; +import org.gradle.api.artifacts.ComponentMetadataContext; +import org.gradle.api.artifacts.ComponentMetadataRule; + +public abstract class RemoveAsmDependency implements ComponentMetadataRule { + @Override + public void execute(final ComponentMetadataContext ctx) { + ctx.getDetails().allVariants(variant -> { + variant.withDependencies(deps -> { + deps.removeIf(dep -> Objects.equals(dep.getGroup(), "org.ow2.asm")); + }); + }); + } +} diff --git a/buildSrc/src/main/java/RunConfigCommon.java b/buildSrc/src/main/java/RunConfigCommon.java new file mode 100644 index 00000000..5fab6d17 --- /dev/null +++ b/buildSrc/src/main/java/RunConfigCommon.java @@ -0,0 +1,5 @@ +import org.gradle.api.provider.MapProperty; + +public abstract class RunConfigCommon { + public abstract MapProperty getSystemProperties(); +} diff --git a/fabric/build.gradle b/fabric/build.gradle index 7c796da0..b3762486 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -26,15 +26,20 @@ dependencies { include fabricApiLibs.base } -processResources { - inputs.property "version", project.version - +tasks.processResources { + def properties = [ + "version": project.version, + "minecraft_version": minecraft_version, + "loader_version": loader_version, + "mod_version": mod_version + ] + inputs.properties(properties) filesMatching("fabric.mod.json") { - expand "version": project.version, "minecraft_version": minecraft_version, "loader_version": loader_version, "mod_version": mod_version + expand properties } } -shadowJar { +tasks.shadowJar { archiveClassifier = "dev-all" destinationDirectory = layout.buildDirectory.dir("libs") configurations = [project.configurations.shadow] @@ -68,10 +73,8 @@ loom { mixin { useLegacyMixinAp = false } - runs.all { + runs.configureEach { ideConfigGenerated true - property "mixin.debug", "true" - property "Moonrise.MaxViewDistance", "128" } mods { main { @@ -81,27 +84,27 @@ loom { } } +afterEvaluate { + loom.runs.configureEach { cfg -> + runConfigCommon.systemProperties.get().each { + cfg.property it.key, it.value + } + } +} + // Setup a run with lithium for compatibility testing sourceSets.create("lithium") -configurations.create("lithium") loom { createRemapConfigurations(sourceSets.lithium) runs { register("lithiumClient") { client() - property "mixin.debug", "true" } } } +configurations.modLithiumRuntimeOnly { + extendsFrom configurations.lithium +} tasks.named("runLithiumClient", net.fabricmc.loom.task.RunGameTask.class) { getClasspath().from(configurations.modRuntimeClasspathLithiumMapped) } -dependencies { - String coordinates = "maven.modrinth:lithium:" - if (getProject().name == "Moonrise-NeoForge") { - coordinates += rootProject.neo_lithium_version - } else { - coordinates += rootProject.fabric_lithium_version - } - modLithiumRuntimeOnly coordinates -} diff --git a/gradle.properties b/gradle.properties index 1e30a971..d71d7771 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,12 +1,14 @@ # Done to increase the memory available to gradle. org.gradle.jvmargs=-Xmx2G -org.gradle.daemon=false +org.gradle.parallel=true +org.gradle.caching=true # Fabric Properties # check these on https://modmuss50.me/fabric.html minecraft_version=1.21.4 loader_version=0.16.9 supported_minecraft_versions=1.21.4 neoforge_version=21.4.0-beta +neoform_version=1.21.4-20241203.161809 fabric_api_version=0.110.5+1.21.4 snakeyaml_version=2.3 concurrentutil_version=0.0.2-SNAPSHOT diff --git a/neoforge/build.gradle b/neoforge/build.gradle index 1a6db22e..bc602139 100644 --- a/neoforge/build.gradle +++ b/neoforge/build.gradle @@ -1,5 +1,6 @@ -import net.neoforged.moddevgradle.internal.RunGameTask import java.nio.file.Files +import java.nio.file.StandardCopyOption +import net.neoforged.moddevgradle.internal.RunGameTask plugins { id("net.neoforged.moddev") @@ -30,17 +31,11 @@ neoForge { } } runs { - configureEach { - additionalRuntimeClasspathConfiguration.extendsFrom configurations.libs - systemProperties.put('mixin.debug', 'true') - } client { client() - // loadedMods.set([]) // Work around module issues by using the production jar for dev runs } server { server() - // loadedMods.set([]) // Work around module issues by using the production jar for dev runs } } } @@ -52,38 +47,29 @@ dependencies { libs("ca.spottedleaf:concurrentutil:${rootProject.concurrentutil_version}") libs("ca.spottedleaf:yamlconfig:${rootProject.yamlconfig_version}") - libs("org.yaml:snakeyaml:${rootProject.snakeyaml_version}") + additionalRuntimeClasspath libs("org.yaml:snakeyaml:${rootProject.snakeyaml_version}") implementation "me.shedaniel.cloth:cloth-config-neoforge:${rootProject.cloth_version}" jarJar "me.shedaniel.cloth:cloth-config-neoforge:${rootProject.cloth_version}" } -// Work around module issues by using the production jar for dev runs -/* -tasks.withType(RunGameTask).configureEach { - dependsOn(tasks.shadowJar) - doFirst { - def jar = file("run/mods/main.jar") - jar.parentFile.mkdirs() - jar.delete() - Files.copy(tasks.shadowJar.archiveFile.get().asFile.toPath(), jar.toPath()) - } -} - */ - -processResources { - inputs.property "version", project.version - +tasks.processResources { + def properties = [ + "version": project.version, + "minecraft_version": minecraft_version, + "mod_version": mod_version + ] + inputs.properties(properties) filesMatching("META-INF/neoforge.mods.toml") { - expand "version": project.version, "minecraft_version": minecraft_version, "loader_version": loader_version, "mod_version": mod_version + expand properties } } -jar { - archiveClassifier = "" +tasks.jar { + archiveClassifier = "slim" } -shadowJar { +tasks.shadowJar { archiveClassifier = "" destinationDirectory = layout.buildDirectory.dir("libs") configurations = [project.configurations.shadow] @@ -92,6 +78,10 @@ shadowJar { relocate 'org.yaml.snakeyaml', 'ca.spottedleaf.moonrise.libs.org.yaml.snakeyaml' } +tasks.assemble { + dependsOn tasks.shadowJar +} + publishMods { file = shadowJar.archiveFile modLoaders = ["neoforge"] @@ -111,3 +101,42 @@ publishMods { ) } } + +afterEvaluate { + neoForge.runs.configureEach { cfg -> + runConfigCommon.systemProperties.get().each { + cfg.systemProperties.put it.key, it.value + } + } +} + +// Setup a run with lithium for compatibility testing +neoForge { + runs { + lithiumClient { + client() + disableIdeRun() + } + } +} +tasks.withType(RunGameTask).configureEach { + if (name == "runLithiumClient") { + return + } + def out = gameDirectory.get().getAsFile().toPath().resolve("mods/lithium-tmp.jar") + doFirst { + Files.deleteIfExists(out) + } +} +def lithium = configurations.lithium +tasks.runLithiumClient { + def out = gameDirectory.get().getAsFile().toPath().resolve("mods/lithium-tmp.jar") + doFirst { + for (File file in lithium) { + Files.copy(file.toPath(), out, StandardCopyOption.REPLACE_EXISTING) + } + } + doLast { + Files.deleteIfExists(out) + } +} diff --git a/settings.gradle b/settings.gradle index 634c0b9c..0b50d854 100644 --- a/settings.gradle +++ b/settings.gradle @@ -23,7 +23,7 @@ pluginManagement { plugins { id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0" - id("quiet-fabric-loom") version "1.8.306" apply false + id("quiet-fabric-loom") version "1.8.309" apply false id("net.neoforged.moddev") version "2.0.49-beta" apply false id 'com.gradleup.shadow' version '8.3.5' apply false } From b2144a55aa51753f04c475374949c6259b7cb7fd Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Sat, 30 Nov 2024 12:29:03 -0700 Subject: [PATCH 5/9] use asm fix from adventure-platform-mod --- build.gradle | 2 +- .../src/main/java/RemoveAsmConstraint.java | 24 +++++++++++++++++++ .../src/main/java/RemoveAsmDependency.java | 14 ----------- 3 files changed, 25 insertions(+), 15 deletions(-) create mode 100644 buildSrc/src/main/java/RemoveAsmConstraint.java delete mode 100644 buildSrc/src/main/java/RemoveAsmDependency.java diff --git a/build.gradle b/build.gradle index e8878d32..57e07cf7 100644 --- a/build.gradle +++ b/build.gradle @@ -34,7 +34,7 @@ dependencies { compileOnly "net.fabricmc:sponge-mixin:0.15.4+mixin.0.8.7" compileOnly "io.github.llamalad7:mixinextras-common:0.4.1" // work around minecraft (MDG) forcing ASM 9.3 which is incompatible with the above deps... - components.withModule("net.neoforged:minecraft-dependencies", RemoveAsmDependency.class) + components.withModule("net.neoforged:minecraft-dependencies", RemoveAsmConstraint.class) api("ca.spottedleaf:concurrentutil:${rootProject.concurrentutil_version}") api("ca.spottedleaf:yamlconfig:${rootProject.yamlconfig_version}") diff --git a/buildSrc/src/main/java/RemoveAsmConstraint.java b/buildSrc/src/main/java/RemoveAsmConstraint.java new file mode 100644 index 00000000..67437858 --- /dev/null +++ b/buildSrc/src/main/java/RemoveAsmConstraint.java @@ -0,0 +1,24 @@ +import java.util.Objects; +import org.gradle.api.artifacts.CacheableRule; +import org.gradle.api.artifacts.ComponentMetadataContext; +import org.gradle.api.artifacts.ComponentMetadataRule; + +@CacheableRule +public abstract class RemoveAsmConstraint implements ComponentMetadataRule { + @Override + public void execute(final ComponentMetadataContext ctx) { + ctx.getDetails().allVariants(variants -> { + variants.withDependencies(deps -> { + deps.forEach(dep -> { + if (Objects.equals(dep.getGroup(), "org.ow2.asm")) { + if (dep.getVersionConstraint().getStrictVersion() != null) { + dep.version(v -> { + v.require(v.getStrictVersion()); + }); + } + } + }); + }); + }); + } +} diff --git a/buildSrc/src/main/java/RemoveAsmDependency.java b/buildSrc/src/main/java/RemoveAsmDependency.java deleted file mode 100644 index 34a2346a..00000000 --- a/buildSrc/src/main/java/RemoveAsmDependency.java +++ /dev/null @@ -1,14 +0,0 @@ -import java.util.Objects; -import org.gradle.api.artifacts.ComponentMetadataContext; -import org.gradle.api.artifacts.ComponentMetadataRule; - -public abstract class RemoveAsmDependency implements ComponentMetadataRule { - @Override - public void execute(final ComponentMetadataContext ctx) { - ctx.getDetails().allVariants(variant -> { - variant.withDependencies(deps -> { - deps.removeIf(dep -> Objects.equals(dep.getGroup(), "org.ow2.asm")); - }); - }); - } -} From 9004f12be6b0025a61c48c09fd054dd64176f872 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Sun, 1 Dec 2024 19:14:12 -0700 Subject: [PATCH 6/9] remove todo --- build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/build.gradle b/build.gradle index 57e07cf7..6b0bbf6d 100644 --- a/build.gradle +++ b/build.gradle @@ -30,7 +30,6 @@ runConfigCommon { } dependencies { - // todo: check versions compileOnly "net.fabricmc:sponge-mixin:0.15.4+mixin.0.8.7" compileOnly "io.github.llamalad7:mixinextras-common:0.4.1" // work around minecraft (MDG) forcing ASM 9.3 which is incompatible with the above deps... From c0b02ea7091b5f8ff278634dc7d701bf91b8ae82 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Sun, 1 Dec 2024 20:01:34 -0700 Subject: [PATCH 7/9] fix jarjar being missing from final neoforge jar --- neoforge/build.gradle | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/neoforge/build.gradle b/neoforge/build.gradle index bc602139..4d0efb9a 100644 --- a/neoforge/build.gradle +++ b/neoforge/build.gradle @@ -66,11 +66,11 @@ tasks.processResources { } tasks.jar { - archiveClassifier = "slim" + archiveClassifier = "dev" } tasks.shadowJar { - archiveClassifier = "" + archiveClassifier = "dev-all" destinationDirectory = layout.buildDirectory.dir("libs") configurations = [project.configurations.shadow] relocate 'ca.spottedleaf.concurrentutil', 'ca.spottedleaf.moonrise.libs.ca.spottedleaf.concurrentutil' @@ -78,12 +78,19 @@ tasks.shadowJar { relocate 'org.yaml.snakeyaml', 'ca.spottedleaf.moonrise.libs.org.yaml.snakeyaml' } +tasks.register("productionJar", Zip.class) { + archiveClassifier = "" + destinationDirectory = layout.buildDirectory.dir("libs") + from(tasks.jarJar) + from(zipTree(tasks.shadowJar.archiveFile)) +} + tasks.assemble { - dependsOn tasks.shadowJar + dependsOn tasks.productionJar } publishMods { - file = shadowJar.archiveFile + file = productionJar.archiveFile modLoaders = ["neoforge"] modrinth { From 7863c556f9519bb4731260e68ce90b92aa6b4b20 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Sun, 1 Dec 2024 20:05:29 -0700 Subject: [PATCH 8/9] fix archive extension --- neoforge/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/neoforge/build.gradle b/neoforge/build.gradle index 4d0efb9a..3caf2e6b 100644 --- a/neoforge/build.gradle +++ b/neoforge/build.gradle @@ -80,6 +80,7 @@ tasks.shadowJar { tasks.register("productionJar", Zip.class) { archiveClassifier = "" + archiveExtension = "jar" destinationDirectory = layout.buildDirectory.dir("libs") from(tasks.jarJar) from(zipTree(tasks.shadowJar.archiveFile)) From 73d73c935acccb8d170b7c9b1ad24cad5fd6b1bc Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Tue, 3 Dec 2024 11:32:04 -0700 Subject: [PATCH 9/9] temporary fix for reproducible at files --- buildSrc/src/main/java/Aw2AtTask.java | 3 +- .../main/java/at/AccessTransformSetImpl.java | 97 +++++++ .../java/at/ClassAccessTransformSetImpl.java | 256 ++++++++++++++++++ 3 files changed, 355 insertions(+), 1 deletion(-) create mode 100644 buildSrc/src/main/java/at/AccessTransformSetImpl.java create mode 100644 buildSrc/src/main/java/at/ClassAccessTransformSetImpl.java diff --git a/buildSrc/src/main/java/Aw2AtTask.java b/buildSrc/src/main/java/Aw2AtTask.java index c881ff85..b9805b0c 100644 --- a/buildSrc/src/main/java/Aw2AtTask.java +++ b/buildSrc/src/main/java/Aw2AtTask.java @@ -98,7 +98,8 @@ of this software and associated documentation files (the "Software"), to deal */ public static AccessTransformSet toAccessTransformSet(final BufferedReader reader) throws IOException { - AccessTransformSet atSet = AccessTransformSet.create(); + // TODO: Remove copied classes once https://github.com/architectury/at/pull/1 is released + AccessTransformSet atSet = new at.AccessTransformSetImpl(); new AccessWidenerReader(new AccessWidenerVisitor() { @Override diff --git a/buildSrc/src/main/java/at/AccessTransformSetImpl.java b/buildSrc/src/main/java/at/AccessTransformSetImpl.java new file mode 100644 index 00000000..029ed4e0 --- /dev/null +++ b/buildSrc/src/main/java/at/AccessTransformSetImpl.java @@ -0,0 +1,97 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2023 Architectury + * Copyright (c) 2018 Minecrell (https://github.com/Minecrell) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package at; + +import dev.architectury.at.AccessTransformSet; +import net.fabricmc.mappingio.tree.MappingTreeView; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +public class AccessTransformSetImpl implements AccessTransformSet { + + private final Map classes = new LinkedHashMap<>(); + + @Override + public Map getClasses() { + return Collections.unmodifiableMap(this.classes); + } + + @Override + public Optional getClass(String name) { + Objects.requireNonNull(name, "name"); + return Optional.ofNullable(this.classes.get(name.replace('.', '/'))); + } + + @Override + public Class getOrCreateClass(String name) { + Objects.requireNonNull(name, "name"); + return this.classes.computeIfAbsent(name.replace('.', '/'), n -> new ClassAccessTransformSetImpl(this, n)); + } + + @Override + public Optional removeClass(String name) { + Objects.requireNonNull(name, "name"); + return Optional.ofNullable(this.classes.remove(name.replace('.', '/'))); + } + + @Override + public AccessTransformSet remap(MappingTreeView mappings, String from, String to) { + throw new UnsupportedOperationException(); + } + + @Override + public void merge(AccessTransformSet other) { + other.getClasses().forEach((name, classSet) -> getOrCreateClass(name).merge(classSet)); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof AccessTransformSetImpl)) { + return false; + } + + AccessTransformSetImpl that = (AccessTransformSetImpl) o; + return this.classes.equals(that.classes); + } + + @Override + public int hashCode() { + return this.classes.hashCode(); + } + + @Override + public String toString() { + return "AccessTransformSet{" + classes + '}'; + } + +} diff --git a/buildSrc/src/main/java/at/ClassAccessTransformSetImpl.java b/buildSrc/src/main/java/at/ClassAccessTransformSetImpl.java new file mode 100644 index 00000000..79e6219c --- /dev/null +++ b/buildSrc/src/main/java/at/ClassAccessTransformSetImpl.java @@ -0,0 +1,256 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2023 Architectury + * Copyright (c) 2018 Minecrell (https://github.com/Minecrell) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package at; + +import dev.architectury.at.AccessTransform; +import dev.architectury.at.AccessTransformSet; +import org.cadixdev.bombe.analysis.InheritanceProvider; +import org.cadixdev.bombe.type.signature.MethodSignature; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Objects; +import java.util.StringJoiner; + +class ClassAccessTransformSetImpl implements AccessTransformSet.Class { + + private final AccessTransformSet parent; + private final String name; + + private AccessTransform classTransform = AccessTransform.EMPTY; + private AccessTransform allFields = AccessTransform.EMPTY; + private AccessTransform allMethods = AccessTransform.EMPTY; + + private final Map fields = new LinkedHashMap<>(); + private final Map methods = new LinkedHashMap<>(); + + private boolean complete; + + ClassAccessTransformSetImpl(AccessTransformSet parent, String name) { + this.parent = parent; + this.name = name; + } + + @Override + public AccessTransformSet getParent() { + return parent; + } + + @Override + public String getName() { + return name; + } + + @Override + public AccessTransform get() { + return this.classTransform; + } + + @Override + public AccessTransform merge(AccessTransform transform) { + return this.classTransform = this.classTransform.merge(transform); + } + + @Override + public AccessTransform replace(AccessTransform transform) { + return this.classTransform = Objects.requireNonNull(transform, "transform"); + } + + @Override + public AccessTransform allFields() { + return this.allFields; + } + + @Override + public AccessTransform mergeAllFields(AccessTransform transform) { + return this.allFields = this.allFields.merge(transform); + } + + @Override + public AccessTransform replaceAllFields(AccessTransform transform) { + return this.allFields = Objects.requireNonNull(transform, "transform"); + } + + @Override + public AccessTransform allMethods() { + return this.allMethods; + } + + @Override + public AccessTransform mergeAllMethods(AccessTransform transform) { + return this.allMethods = this.allMethods.merge(transform); + } + + @Override + public AccessTransform replaceAllMethods(AccessTransform transform) { + return this.allMethods = Objects.requireNonNull(transform, "transform"); + } + + @Override + public Map getFields() { + return Collections.unmodifiableMap(this.fields); + } + + @Override + public AccessTransform getField(String name) { + return this.fields.getOrDefault(Objects.requireNonNull(name, "name"), this.allFields); + } + + @Override + public AccessTransform mergeField(String name, AccessTransform transform) { + Objects.requireNonNull(name, "name"); + Objects.requireNonNull(transform, "transform"); + + if (transform.isEmpty()) { + return this.fields.getOrDefault(name, AccessTransform.EMPTY); + } + return this.fields.merge(name, transform, AccessTransform::merge); + } + + @Override + public AccessTransform replaceField(String name, AccessTransform transform) { + Objects.requireNonNull(name, "name"); + Objects.requireNonNull(transform, "transform"); + + if (transform.isEmpty()) { + return this.fields.remove(name); + } + return this.fields.put(name, transform); + } + + @Override + public Map getMethods() { + return Collections.unmodifiableMap(this.methods); + } + + @Override + public AccessTransform getMethod(MethodSignature signature) { + return this.methods.getOrDefault(Objects.requireNonNull(signature, "signature"), this.allMethods); + } + + @Override + public AccessTransform mergeMethod(MethodSignature signature, AccessTransform transform) { + Objects.requireNonNull(signature, "signature"); + Objects.requireNonNull(transform, "transform"); + + if (transform.isEmpty()) { + return this.methods.getOrDefault(signature, AccessTransform.EMPTY); + } + return this.methods.merge(signature, transform, AccessTransform::merge); + } + + @Override + public AccessTransform replaceMethod(MethodSignature signature, AccessTransform transform) { + Objects.requireNonNull(signature, "signature"); + Objects.requireNonNull(transform, "transform"); + + if (transform.isEmpty()) { + return this.methods.remove(signature); + } + return this.methods.put(signature, transform); + } + + @Override + public void merge(AccessTransformSet.Class other) { + Objects.requireNonNull(other, "other"); + + merge(other.get()); + mergeAllFields(other.allFields()); + mergeAllMethods(other.allMethods()); + + other.getFields().forEach(this::mergeField); + other.getMethods().forEach(this::mergeMethod); + } + + @Override + public boolean isComplete() { + return this.complete; + } + + @Override + public void complete(InheritanceProvider provider, InheritanceProvider.ClassInfo info) { + if (this.complete) { + return; + } + + for (InheritanceProvider.ClassInfo parent : info.provideParents(provider)) { + AccessTransformSet.Class parentAts = getParent().getOrCreateClass(parent.getName()); + parentAts.complete(provider, parent); + + parentAts.getMethods().forEach((signature, transform) -> { + if (info.overrides(signature, parent)) { + mergeMethod(signature, transform); + } + }); + } + + this.complete = true; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof ClassAccessTransformSetImpl)) { + return false; + } + + ClassAccessTransformSetImpl that = (ClassAccessTransformSetImpl) o; + return this.classTransform.equals(that.classTransform) && + this.allFields.equals(that.allFields) && + this.allMethods.equals(that.allMethods) && + this.fields.equals(that.fields) && + this.methods.equals(that.methods); + } + + @Override + public int hashCode() { + return Objects.hash(this.classTransform, this.allFields, this.allMethods, this.fields, this.methods); + } + + @Override + public String toString() { + StringJoiner joiner = new StringJoiner(", ", "AccessTransformSet.Class{", "}"); + if (!this.classTransform.isEmpty()) { + joiner.add(this.classTransform.toString()); + } + if (!this.allFields.isEmpty()) { + joiner.add("allFields=" + this.allFields); + } + if (!this.allMethods.isEmpty()) { + joiner.add("allMethods=" + this.allMethods); + } + if (!this.fields.isEmpty()) { + joiner.add("fields=" + this.fields); + } + if (!this.methods.isEmpty()) { + joiner.add("method=" + this.methods); + } + return joiner.toString(); + } +}