From 240ee2bfb9c6a6938a5dbed4efe45a9de48a36d5 Mon Sep 17 00:00:00 2001 From: Marc Hermans Date: Mon, 12 Aug 2024 18:03:15 +0200 Subject: [PATCH] Start work on production runs. Should be doable. --- .../dsl/platform/model/LauncherProfile.groovy | 84 +++++++++++++++---- .../dsl/platform/model/OsCondition.groovy | 29 ++++++- .../gradle/dsl/platform/model/Rule.groovy | 11 +++ .../dsl/platform/model/WithRules.groovy | 14 ++++ .../extensions/DynamicProjectExtension.java | 18 +++- .../gradle/util/TransformerUtils.java | 5 ++ 6 files changed, 141 insertions(+), 20 deletions(-) diff --git a/dsl/platform/src/main/groovy/net/neoforged/gradle/dsl/platform/model/LauncherProfile.groovy b/dsl/platform/src/main/groovy/net/neoforged/gradle/dsl/platform/model/LauncherProfile.groovy index c1892d404..adb8d84fa 100644 --- a/dsl/platform/src/main/groovy/net/neoforged/gradle/dsl/platform/model/LauncherProfile.groovy +++ b/dsl/platform/src/main/groovy/net/neoforged/gradle/dsl/platform/model/LauncherProfile.groovy @@ -16,6 +16,7 @@ import org.gradle.api.tasks.Optional import javax.inject.Inject import java.lang.reflect.Type +import java.nio.file.Path import java.util.function.BiFunction import static net.neoforged.gradle.dsl.common.util.PropertyUtils.* @@ -41,11 +42,37 @@ abstract class LauncherProfile implements ConfigurableDSLElement> mergeDownloads( + final Provider> left, + final Provider> right + ) { + return left.orElse(Map.of()).zip(right.orElse(Map.of()), new BiFunction, Map, Map>() { + @Override + Map apply(Map l, Map r) { + final Map result = new HashMap<>(l) + result.putAll(r) + return result + } + }) + } - - return result + static Provider> mergeLibraries(ListProperty left, ListProperty right) { + return left.orElse(List.of()).zip(right.orElse(List.of()), new BiFunction, List, List>() { + @Override + List apply(List libraries, List u) { + final List result = new ArrayList<>(libraries) + result.addAll(u) + return result + } + }) } @Inject @@ -56,6 +83,14 @@ abstract class LauncherProfile implements ConfigurableDSLElement merge(List left, List right) { - final List result = new ArrayList<>(left) - result.addAll(right) - return result + private static Provider> mergeList(final ListProperty left, final ListProperty right) { + return left.orElse(List.of()).zip(right.orElse(List.of()), new BiFunction, List, List>() { + @Override + List apply(List l, List r) { + final List result = new ArrayList<>(l) + result.addAll(r) + return result + } + }) } @Inject @@ -237,14 +277,14 @@ abstract class LauncherProfile implements ConfigurableDSLElement value) { final Argument argument = getObjectFactory().newInstance(Argument.class); - argument.getValue().set(value); + argument.getValue().add(value); getGame().add(argument); return argument; } @@ -256,14 +296,14 @@ abstract class LauncherProfile implements ConfigurableDSLElement value) { final Argument argument = getObjectFactory().newInstance(Argument.class); - argument.getValue().set(value); + argument.getValue().add(value); getJVM().add(argument); return argument; } @@ -309,7 +349,7 @@ abstract class LauncherProfile implements ConfigurableDSLElement getValue(); + abstract ListProperty getValue(); @CompileStatic static class Serializer extends WithRules.Serializer { @@ -322,13 +362,21 @@ abstract class LauncherProfile implements ConfigurableDSLElement { @@ -36,6 +38,30 @@ abstract class OsCondition implements ConfigurableDSLElement { @Optional abstract Property getVersion(); + Provider isActive() { + def nameMatches = name.map { n -> + if (n == "windows") { + return System.getProperty("os.name").toLowerCase().contains("win") + } else if (n == "linux") { + return System.getProperty("os.name").toLowerCase().contains("unix") || System.getProperty("os.name").toLowerCase().contains("linux") + } else if (n == "osx") { + return System.getProperty("os.name").toLowerCase().contains("mac") + } else { + return false + } + }.orElse(true) + + def versionMatches = version.map { v -> return Pattern.compile(v).matcher(System.getProperty("os.version")).find() + }.orElse(true) + + def archMatches = arch.map { a -> return Pattern.compile(a).matcher(System.getProperty("os.arch")).find() + }.orElse(true) + + return nameMatches.zip(versionMatches.zip(archMatches, + { v, a -> v && a }), + { n, va -> n && va }) + } + @CompileStatic static class Serializer implements JsonSerializer, JsonDeserializer { @@ -47,8 +73,7 @@ abstract class OsCondition implements ConfigurableDSLElement { @Override OsCondition deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { - if (!jsonElement.isJsonObject()) - throw new JsonParseException("OS condition must be a json object") + if (!jsonElement.isJsonObject()) throw new JsonParseException("OS condition must be a json object") final JsonObject payload = jsonElement.getAsJsonObject(); final OsCondition instance = factory.newInstance(OsCondition.class); diff --git a/dsl/platform/src/main/groovy/net/neoforged/gradle/dsl/platform/model/Rule.groovy b/dsl/platform/src/main/groovy/net/neoforged/gradle/dsl/platform/model/Rule.groovy index 0c16f78cf..062646589 100644 --- a/dsl/platform/src/main/groovy/net/neoforged/gradle/dsl/platform/model/Rule.groovy +++ b/dsl/platform/src/main/groovy/net/neoforged/gradle/dsl/platform/model/Rule.groovy @@ -8,6 +8,7 @@ import net.neoforged.gradle.dsl.common.util.PropertyUtils import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.MapProperty import org.gradle.api.provider.Property +import org.gradle.api.provider.Provider import org.gradle.api.tasks.Input import org.gradle.api.tasks.Nested import org.gradle.api.tasks.Optional @@ -23,6 +24,16 @@ abstract class Rule implements ConfigurableDSLElement { @Optional abstract Property getAction(); + Provider isActive(Provider> enabledFeatures) { + def osMatches = getOs().flatMap {os -> os.isActive()}.orElse(true) + def featureMatches = features.zip(enabledFeatures, { Map f, List ef -> ef.every {feature -> f.getOrDefault(feature, true)} }).orElse(true) + + def combinedMatch = osMatches.zip(featureMatches, { Boolean os, Boolean features -> os && features }).orElse(true) + def matchingRuleAction = action.orElse(RuleAction.ALLOWED) + + return combinedMatch.zip(matchingRuleAction, { Boolean match, RuleAction action -> action.isAllowed() == match }).orElse(true) + } + @Nested @DSLProperty @Optional diff --git a/dsl/platform/src/main/groovy/net/neoforged/gradle/dsl/platform/model/WithRules.groovy b/dsl/platform/src/main/groovy/net/neoforged/gradle/dsl/platform/model/WithRules.groovy index bc6d6267b..d3ee2c2ae 100644 --- a/dsl/platform/src/main/groovy/net/neoforged/gradle/dsl/platform/model/WithRules.groovy +++ b/dsl/platform/src/main/groovy/net/neoforged/gradle/dsl/platform/model/WithRules.groovy @@ -11,21 +11,35 @@ import groovy.transform.CompileStatic import net.minecraftforge.gdi.ConfigurableDSLElement import net.minecraftforge.gdi.annotations.DSLProperty import net.neoforged.gradle.dsl.common.util.PropertyUtils +import net.neoforged.gradle.util.TransformerUtils import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.ListProperty +import org.gradle.api.provider.Provider import org.gradle.api.tasks.Input import org.gradle.api.tasks.Optional +import javax.inject.Inject import java.lang.reflect.Type @CompileStatic abstract class WithRules> implements ConfigurableDSLElement { + @Inject + abstract ObjectFactory getObjectFactory(); + @Input @Optional @DSLProperty abstract ListProperty getRules(); + Provider isActive() { + return isActive(getObjectFactory().listProperty(String.class)) + } + + Provider isActive(Provider> enabledFeatures) { + return getRules().map(TransformerUtils.allTrue({Rule rule -> rule.isActive(enabledFeatures)})) + } + @Override int hashCode() { return Objects.hash(getRules()); diff --git a/platform/src/main/java/net/neoforged/gradle/platform/extensions/DynamicProjectExtension.java b/platform/src/main/java/net/neoforged/gradle/platform/extensions/DynamicProjectExtension.java index 8a71e6532..fbabdb1c1 100644 --- a/platform/src/main/java/net/neoforged/gradle/platform/extensions/DynamicProjectExtension.java +++ b/platform/src/main/java/net/neoforged/gradle/platform/extensions/DynamicProjectExtension.java @@ -23,6 +23,7 @@ import net.neoforged.gradle.common.util.ToolUtilities; import net.neoforged.gradle.dsl.common.extensions.AccessTransformers; import net.neoforged.gradle.dsl.common.extensions.Mappings; +import net.neoforged.gradle.dsl.common.extensions.MinecraftArtifactCache; import net.neoforged.gradle.dsl.common.runs.run.Run; import net.neoforged.gradle.dsl.common.runs.run.RunManager; import net.neoforged.gradle.dsl.common.runs.type.RunType; @@ -260,7 +261,9 @@ public void runtime(final String neoFormVersion, Directory patches, Directory re final TaskProvider setupTask = configureSetupTasks(runtimeDefinition.getSourceJarTask().flatMap(WithOutput::getOutput), mainSource, runtimeDefinition.getMinecraftDependenciesConfiguration()); setupTask.configure(task -> task.getShouldLockDirectories().set(false)); - + + final MinecraftArtifactCache artifactCache = project.getExtensions().getByType(MinecraftArtifactCache.class); + project.afterEvaluate(evaledProject -> { final EnumMap> cleanProviders = new EnumMap<>(DistributionType.class); cleanProviders.put(DistributionType.CLIENT, createCleanProvider(runtimeDefinition.getGameArtifactProvidingTasks().get(GameArtifact.CLIENT_JAR), runtimeDefinition, workingDirectory)); @@ -397,6 +400,19 @@ public void runtime(final String neoFormVersion, Directory patches, Directory re CommonRuntimeExtension.configureCommonRuntimeTaskParameters(task, runtimeDefinition, workingDirectory); }); + + final TaskProvider createBinaryCombinedLauncher = project.getTasks().register("createCombinedLauncher", CreateLauncherJson.class, task -> { + task.getProfile().set(artifactCache.cacheVersionManifest(runtimeDefinition.getSpecification().getMinecraftVersion()).map( + file -> LauncherProfile.from(project.getObjects(), file.toPath()) + ).map(vanillaLauncherProfile -> LauncherProfile.merge(project.getObjects(), vanillaLauncherProfile, launcherProfile))); + task.getLibraries().from(installerConfiguration); + task.getLibraries().from(pluginLayerLibraryConfiguration); + task.getLibraries().from(gameLayerLibraryConfiguration); + task.getLibraries().from(moduleOnlyConfiguration); + task.getRepositoryURLs().set(repoCollection); + + CommonRuntimeExtension.configureCommonRuntimeTaskParameters(task, runtimeDefinition, workingDirectory); + }); final TaskProvider joinedCleanProvider = cleanProviders.get(DistributionType.JOINED); final TaskProvider strippedJar = project.getTasks().register("stripBinaryPatchedClasses", StripBinPatchedClasses.class, task -> { diff --git a/utils/src/main/java/net/neoforged/gradle/util/TransformerUtils.java b/utils/src/main/java/net/neoforged/gradle/util/TransformerUtils.java index f19e780a3..55a89b4a7 100644 --- a/utils/src/main/java/net/neoforged/gradle/util/TransformerUtils.java +++ b/utils/src/main/java/net/neoforged/gradle/util/TransformerUtils.java @@ -2,6 +2,7 @@ import com.google.common.collect.Multimap; import com.google.common.collect.Multimaps; +import groovy.lang.Closure; import groovyjarjarantlr4.v4.runtime.misc.NotNull; import org.gradle.api.Project; import org.gradle.api.Transformer; @@ -453,6 +454,10 @@ public static Provider lazyDefaulted(Provider provider, Provider va return provider.orElse(value); } + public static Transformer> allTrue(Function closure) { + return (Transformer>) es -> es.stream().map(closure).reduce(Boolean::logicalAnd).map(b -> b ? Boolean.TRUE : Boolean.FALSE).orElse(true); + } + /** * A definition for a transformer which can throw an exception. *