diff --git a/common/src/main/java/net/neoforged/gradle/common/runtime/definition/CommonRuntimeDefinition.java b/common/src/main/java/net/neoforged/gradle/common/runtime/definition/CommonRuntimeDefinition.java index 0e9960136..52b079f6d 100644 --- a/common/src/main/java/net/neoforged/gradle/common/runtime/definition/CommonRuntimeDefinition.java +++ b/common/src/main/java/net/neoforged/gradle/common/runtime/definition/CommonRuntimeDefinition.java @@ -17,6 +17,7 @@ import net.neoforged.gradle.dsl.common.util.GameArtifact; import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.Dependency; +import org.gradle.api.file.ConfigurableFileCollection; import org.gradle.api.provider.ListProperty; import org.gradle.api.provider.MapProperty; import org.gradle.api.tasks.TaskProvider; @@ -55,6 +56,9 @@ public abstract class CommonRuntimeDefinition> associatedTaskConsumer; + + @NotNull + private final ConfigurableFileCollection allDependencies; @NotNull private final VersionJson versionJson; @@ -76,6 +80,9 @@ protected CommonRuntimeDefinition( this.minecraftDependenciesConfiguration = minecraftDependenciesConfiguration; this.associatedTaskConsumer = associatedTaskConsumer; this.versionJson = versionJson; + + this.allDependencies = specification.getProject().files(); + this.allDependencies.from(getMinecraftDependenciesConfiguration()); } @Override @@ -152,6 +159,12 @@ public VersionJson getVersionJson() { return versionJson; } + @NotNull + @Override + public final ConfigurableFileCollection getAllDependencies() { + return allDependencies; + } + public void configureRun(RunImpl run) { final Map runtimeInterpolationData = buildRunInterpolationData(run); diff --git a/common/src/main/java/net/neoforged/gradle/common/runtime/tasks/DefaultExecute.java b/common/src/main/java/net/neoforged/gradle/common/runtime/tasks/DefaultExecute.java index 6ca36c08e..3d3e64c47 100644 --- a/common/src/main/java/net/neoforged/gradle/common/runtime/tasks/DefaultExecute.java +++ b/common/src/main/java/net/neoforged/gradle/common/runtime/tasks/DefaultExecute.java @@ -35,6 +35,8 @@ public DefaultExecute() { getRuntimeProgramArguments().convention(getProgramArguments()); getMultiRuntimeArguments().convention(getMultiArguments().AsMap()); + + getLogLevel().convention(LogLevel.ERROR); } @ServiceReference(CommonProjectPlugin.EXECUTE_SERVICE) diff --git a/common/src/main/java/net/neoforged/gradle/common/runtime/tasks/SourceAccessTransformer.java b/common/src/main/java/net/neoforged/gradle/common/runtime/tasks/SourceAccessTransformer.java index e4123d493..f9eb6d6f4 100644 --- a/common/src/main/java/net/neoforged/gradle/common/runtime/tasks/SourceAccessTransformer.java +++ b/common/src/main/java/net/neoforged/gradle/common/runtime/tasks/SourceAccessTransformer.java @@ -6,12 +6,7 @@ import org.gradle.api.file.ConfigurableFileCollection; import org.gradle.api.file.RegularFileProperty; import org.gradle.api.plugins.JavaPluginExtension; -import org.gradle.api.tasks.CacheableTask; -import org.gradle.api.tasks.InputFile; -import org.gradle.api.tasks.InputFiles; -import org.gradle.api.tasks.PathSensitive; -import org.gradle.api.tasks.PathSensitivity; -import org.gradle.api.tasks.SkipWhenEmpty; +import org.gradle.api.tasks.*; import java.io.File; import java.util.List; @@ -38,6 +33,15 @@ public SourceAccessTransformer() { args.add("--libraries-list=" + getLibraries().get().getAsFile().getAbsolutePath()); + final StringBuilder builder = new StringBuilder(); + getClasspath().forEach(f -> { + if (!builder.isEmpty()) { + builder.append(File.pathSeparator); + } + builder.append(f.getAbsolutePath()); + }); + args.add("--classpath=" + builder.toString()); + args.add(inputFile.getAsFile().getAbsolutePath()); args.add(outputFile.getAbsolutePath()); @@ -48,6 +52,7 @@ public SourceAccessTransformer() { getJavaVersion().convention(getProject().getExtensions().getByType(JavaPluginExtension.class).getToolchain().getLanguageVersion()); getTransformers().finalizeValueOnRead(); + getLogLevel().set(LogLevel.DISABLED); } @InputFile @@ -58,6 +63,11 @@ public SourceAccessTransformer() { @PathSensitive(PathSensitivity.NONE) public abstract RegularFileProperty getLibraries(); + @InputFiles + @Optional + @PathSensitive(PathSensitivity.NONE) + public abstract ConfigurableFileCollection getClasspath(); + @InputFiles @SkipWhenEmpty @PathSensitive(PathSensitivity.NONE) diff --git a/common/src/main/java/net/neoforged/gradle/common/util/CommonRuntimeTaskUtils.java b/common/src/main/java/net/neoforged/gradle/common/util/CommonRuntimeTaskUtils.java index cbc03ae22..078d43639 100644 --- a/common/src/main/java/net/neoforged/gradle/common/util/CommonRuntimeTaskUtils.java +++ b/common/src/main/java/net/neoforged/gradle/common/util/CommonRuntimeTaskUtils.java @@ -8,6 +8,7 @@ import net.neoforged.gradle.dsl.common.tasks.WithOutput; import net.neoforged.gradle.dsl.common.util.CommonRuntimeUtils; import net.neoforged.gradle.util.StringCapitalizationUtils; +import org.gradle.api.file.FileCollection; import org.gradle.api.file.FileTree; import org.gradle.api.tasks.TaskProvider; @@ -21,7 +22,7 @@ private CommonRuntimeTaskUtils() { throw new IllegalStateException("Can not instantiate an instance of: CommonRuntimeTaskUtils. This is a utility class"); } - public static TaskProvider createSourceAccessTransformer(Definition definition, String namePreFix, File workspaceDirectory, Consumer> dependentTaskConfigurationHandler, FileTree files, Collection data, TaskProvider listLibs) { + public static TaskProvider createSourceAccessTransformer(Definition definition, String namePreFix, File workspaceDirectory, Consumer> dependentTaskConfigurationHandler, FileTree files, Collection data, TaskProvider listLibs, FileCollection additionalClasspathElements) { final TaskProvider generator; if (!data.isEmpty()) { generator = definition.getSpecification().getProject().getTasks().register(CommonRuntimeUtils.buildTaskName(definition.getSpecification(), namePreFix + "AccessTransformerGenerator"), AccessTransformerFileGenerator.class, task -> { @@ -41,6 +42,7 @@ public static TaskProvider createSourceAccess } task.dependsOn(listLibs); task.getLibraries().set(listLibs.flatMap(WithOutput::getOutput)); + task.getClasspath().from(additionalClasspathElements); }); } diff --git a/dsl/common/src/main/groovy/net/neoforged/gradle/dsl/common/runtime/definition/Definition.groovy b/dsl/common/src/main/groovy/net/neoforged/gradle/dsl/common/runtime/definition/Definition.groovy index c14a2c53b..aba4c5f88 100644 --- a/dsl/common/src/main/groovy/net/neoforged/gradle/dsl/common/runtime/definition/Definition.groovy +++ b/dsl/common/src/main/groovy/net/neoforged/gradle/dsl/common/runtime/definition/Definition.groovy @@ -8,6 +8,8 @@ import net.neoforged.gradle.dsl.common.tasks.WithOutput import net.neoforged.gradle.dsl.common.util.GameArtifact import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.Dependency +import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.file.FileCollection import org.gradle.api.tasks.TaskProvider import org.jetbrains.annotations.NotNull @@ -87,4 +89,13 @@ interface Definition { */ @NotNull abstract TaskProvider getListLibrariesTaskProvider(); + + /** + * Returns all the files which should be considered dependencies of the runtime. + * This includes the runtime's own dependencies, as well as the dependencies of the minecraft dependency. + * + * @return The dependencies of the runtime. + */ + @NotNull + ConfigurableFileCollection getAllDependencies() } diff --git a/dsl/common/src/main/groovy/net/neoforged/gradle/dsl/common/tasks/Execute.groovy b/dsl/common/src/main/groovy/net/neoforged/gradle/dsl/common/tasks/Execute.groovy index 4e624acf9..ccc50beb9 100644 --- a/dsl/common/src/main/groovy/net/neoforged/gradle/dsl/common/tasks/Execute.groovy +++ b/dsl/common/src/main/groovy/net/neoforged/gradle/dsl/common/tasks/Execute.groovy @@ -6,6 +6,7 @@ import net.minecraftforge.gdi.annotations.DefaultMethods import net.neoforged.gradle.dsl.common.tasks.specifications.ExecuteSpecification import net.neoforged.gradle.dsl.common.util.RegexUtils import org.gradle.api.file.FileTree +import org.gradle.api.logging.Logger import org.gradle.api.provider.Provider import org.gradle.api.tasks.TaskAction import org.gradle.process.JavaExecSpec @@ -22,7 +23,6 @@ import java.util.stream.Collectors @DefaultMethods interface Execute extends WithWorkspace, WithOutput, WithJavaVersion, ExecuteSpecification { - default List interpolateVariableSubstitution(String value, String previous) { final Map> runtimeArguments = getRuntimeArguments().get() final Map>> multiRuntimeArguments = getMultiRuntimeArguments().get() @@ -87,7 +87,7 @@ interface Execute extends WithWorkspace, WithOutput, WithJavaVersion, ExecuteSpe final List substituted = ((Execute) this).interpolateVariableSubstitution(value, previous) if (substituted.size() != 1) { - interpolated.removeAt(interpolated.size() - 1); + interpolated.removeAt(interpolated.size() - 1) } interpolated.addAll(substituted) @@ -110,10 +110,12 @@ interface Execute extends WithWorkspace, WithOutput, WithJavaVersion, ExecuteSpe final Execute me = this - try (BufferedOutputStream log_out = new BufferedOutputStream(new FileOutputStream(consoleLogFile))) { + try (LoggerOutputStream error_out = new LoggerOutputStream(me.getLogger(), me.getLogLevel().get()) + BufferedOutputStream log_out = new BufferedOutputStream(new FileOutputStream(consoleLogFile)) + LogLevelAwareOutputStream standard_out = new LogLevelAwareOutputStream(log_out, ExecuteSpecification.LogLevel.WARN, getLogLevel().get()) ){ getExecuteOperation().javaexec({ JavaExecSpec java -> PrintWriter writer = new PrintWriter(log_out) - Function quote = s -> (CharSequence)('"' + s + '"') + Function quote = s -> (CharSequence) ('"' + s + '"') writer.println("JVM Args: " + jvmArgs.get().stream().map(quote).collect(Collectors.joining(", "))) writer.println("Run Args: " + programArgs.get().stream().map(quote).collect(Collectors.joining(", "))) writer.println("JVM: " + executable.get()) @@ -130,11 +132,71 @@ interface Execute extends WithWorkspace, WithOutput, WithJavaVersion, ExecuteSpe java.setClasspath(me.getObjectFactory().fileCollection().from(me.getExecutingJar().get())) java.setWorkingDir(me.getOutputDirectory().get()) java.getMainClass().set(mainClass) - java.setStandardOutput(log_out) + java.setStandardOutput(standard_out) + java.setErrorOutput(error_out) }).rethrowFailure().assertNormalExitValue() - return outputFile; + return outputFile + } + } + + private static final class LogLevelAwareOutputStream extends OutputStream { + + private final OutputStream target; + private final boolean shouldLog; + + public LogLevelAwareOutputStream(OutputStream target, ExecuteSpecification.LogLevel minLevel, ExecuteSpecification.LogLevel currentLevel) { + this.target = target; + this.shouldLog = minLevel.ordinal() > currentLevel.ordinal(); //Inverse selection logic, if current is error and min is warn then it should not log. + } + + @Override + void write(int b) throws IOException { + if (shouldLog) { + target.write(b); + } } } + private static final class LoggerOutputStream + extends OutputStream { + private final ByteArrayOutputStream baos = new ByteArrayOutputStream(1000) + private final Logger logger + private final ExecuteSpecification.LogLevel level + + LoggerOutputStream(Logger logger, ExecuteSpecification.LogLevel level) { + this.logger = logger + this.level = level + } + + @Override + void write(int b) { + if (level == ExecuteSpecification.LogLevel.DISABLED) return + + if (((char) b) == '\n') { + String line = baos.toString() + baos.reset() + + switch (level) { + case ExecuteSpecification.LogLevel.TRACE: + logger.trace(line) + break + case ExecuteSpecification.LogLevel.DEBUG: + logger.debug(line) + break + case ExecuteSpecification.LogLevel.ERROR: + logger.error(line) + break + case ExecuteSpecification.LogLevel.INFO: + logger.info(line) + break + case ExecuteSpecification.LogLevel.WARN: + logger.warn(line) + break + } + } else { + baos.write(b) + } + } + } } diff --git a/dsl/common/src/main/groovy/net/neoforged/gradle/dsl/common/tasks/specifications/ExecuteSpecification.groovy b/dsl/common/src/main/groovy/net/neoforged/gradle/dsl/common/tasks/specifications/ExecuteSpecification.groovy index e44324c0e..49176205f 100644 --- a/dsl/common/src/main/groovy/net/neoforged/gradle/dsl/common/tasks/specifications/ExecuteSpecification.groovy +++ b/dsl/common/src/main/groovy/net/neoforged/gradle/dsl/common/tasks/specifications/ExecuteSpecification.groovy @@ -18,6 +18,11 @@ import org.gradle.api.tasks.PathSensitivity interface ExecuteSpecification extends ProjectSpecification, OutputSpecification, JavaVersionSpecification { + enum LogLevel { + TRACE, DEBUG, INFO, WARN, ERROR, DISABLED + } + + /** * Defines the jvm arguments in a list which are passed to the java executable. * @@ -114,4 +119,8 @@ interface ExecuteSpecification extends ProjectSpecification, OutputSpecification */ @Internal MapProperty>> getMultiRuntimeArguments(); + + @DSLProperty + @Input + Property getLogLevel(); } diff --git a/dsl/common/src/main/groovy/net/neoforged/gradle/dsl/common/util/Constants.groovy b/dsl/common/src/main/groovy/net/neoforged/gradle/dsl/common/util/Constants.groovy index 6acc5aa07..3ae94de18 100644 --- a/dsl/common/src/main/groovy/net/neoforged/gradle/dsl/common/util/Constants.groovy +++ b/dsl/common/src/main/groovy/net/neoforged/gradle/dsl/common/util/Constants.groovy @@ -27,7 +27,7 @@ class Constants { public static final String DEFAULT_PARCHMENT_GROUP = "org.parchmentmc.data" public static final String DEFAULT_PARCHMENT_ARTIFACT_PREFIX = "parchment-" public static final String DEFAULT_PARCHMENT_MAVEN_URL = "https://maven.parchmentmc.org/" - public static final String JST_TOOL_ARTIFACT = "net.neoforged.jst:jst-cli-bundle:1.0.38" + public static final String JST_TOOL_ARTIFACT = "net.neoforged.jst:jst-cli-bundle:1.0.39" public static final String DEVLOGIN_TOOL_ARTIFACT = "net.covers1624:DevLogin:0.1.0.4" public static final String DEVLOGIN_MAIN_CLASS = "net.covers1624.devlogin.DevLogin" diff --git a/dsl/userdev/src/main/groovy/net/neoforged/gradle/dsl/userdev/runtime/specification/UserDevSpecification.groovy b/dsl/userdev/src/main/groovy/net/neoforged/gradle/dsl/userdev/runtime/specification/UserDevSpecification.groovy index cbee156f6..10560ca3a 100644 --- a/dsl/userdev/src/main/groovy/net/neoforged/gradle/dsl/userdev/runtime/specification/UserDevSpecification.groovy +++ b/dsl/userdev/src/main/groovy/net/neoforged/gradle/dsl/userdev/runtime/specification/UserDevSpecification.groovy @@ -1,8 +1,10 @@ package net.neoforged.gradle.dsl.userdev.runtime.specification; import groovy.transform.CompileStatic -import net.neoforged.gradle.dsl.common.runtime.spec.Specification; -import org.gradle.api.provider.Provider; +import net.neoforged.gradle.dsl.common.runtime.spec.Specification +import net.neoforged.gradle.dsl.neoform.runtime.specification.NeoFormSpecification; +import org.gradle.api.provider.Provider +import org.gradle.api.specs.Spec; import org.jetbrains.annotations.NotNull; /** diff --git a/neoform/src/main/java/net/neoforged/gradle/neoform/runtime/definition/NeoFormRuntimeDefinition.java b/neoform/src/main/java/net/neoforged/gradle/neoform/runtime/definition/NeoFormRuntimeDefinition.java index 0ff64f436..15bc5e666 100644 --- a/neoform/src/main/java/net/neoforged/gradle/neoform/runtime/definition/NeoFormRuntimeDefinition.java +++ b/neoform/src/main/java/net/neoforged/gradle/neoform/runtime/definition/NeoFormRuntimeDefinition.java @@ -30,7 +30,6 @@ public class NeoFormRuntimeDefinition extends CommonRuntimeDefinition assetsTaskProvider; private final TaskProvider nativesTaskProvider; - private TaskProvider debuggingMappingsTaskProvider; public NeoFormRuntimeDefinition(@NotNull NeoFormRuntimeSpecification specification, @NotNull LinkedHashMap> taskOutputs, @@ -47,6 +46,8 @@ public NeoFormRuntimeDefinition(@NotNull NeoFormRuntimeSpecification specificati this.neoform = neoform; this.assetsTaskProvider = assetsTaskProvider; this.nativesTaskProvider = nativesTaskProvider; + + this.getAllDependencies().from(getSpecification().getAdditionalRecompileDependencies()); } @Override @@ -58,11 +59,9 @@ public NeoFormConfigConfigurationSpecV2 getNeoFormConfig() { @Override public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof NeoFormRuntimeDefinition)) return false; + if (!(o instanceof NeoFormRuntimeDefinition that)) return false; if (!super.equals(o)) return false; - NeoFormRuntimeDefinition that = (NeoFormRuntimeDefinition) o; - return neoform.equals(that.neoform); } diff --git a/neoform/src/main/java/net/neoforged/gradle/neoform/runtime/specification/NeoFormRuntimeSpecification.java b/neoform/src/main/java/net/neoforged/gradle/neoform/runtime/specification/NeoFormRuntimeSpecification.java index 7822c608b..198d55158 100644 --- a/neoform/src/main/java/net/neoforged/gradle/neoform/runtime/specification/NeoFormRuntimeSpecification.java +++ b/neoform/src/main/java/net/neoforged/gradle/neoform/runtime/specification/NeoFormRuntimeSpecification.java @@ -77,7 +77,7 @@ public Provider getNeoFormArchive() { } @Override - public FileCollection getAdditionalRecompileDependencies() { + public @NotNull FileCollection getAdditionalRecompileDependencies() { return additionalRecompileDependencies; } diff --git a/neoform/src/main/java/net/neoforged/gradle/neoform/util/NeoFormAccessTransformerUtils.java b/neoform/src/main/java/net/neoforged/gradle/neoform/util/NeoFormAccessTransformerUtils.java index 610d7fa49..2d3a17c28 100644 --- a/neoform/src/main/java/net/neoforged/gradle/neoform/util/NeoFormAccessTransformerUtils.java +++ b/neoform/src/main/java/net/neoforged/gradle/neoform/util/NeoFormAccessTransformerUtils.java @@ -7,6 +7,7 @@ import net.neoforged.gradle.dsl.common.runtime.tasks.tree.TaskTreeAdapter; import net.neoforged.gradle.dsl.common.tasks.WithOutput; import org.gradle.api.Project; +import org.gradle.api.file.FileCollection; import org.gradle.api.tasks.TaskProvider; public class NeoFormAccessTransformerUtils { @@ -24,7 +25,7 @@ public static TaskTreeAdapter createAccessTransformerAdapter(final Project proje return null; } - final TaskProvider accessTransformerTask = CommonRuntimeTaskUtils.createSourceAccessTransformer(definition, "User", runtimeWorkspace, dependentTaskConfigurationHandler, accessTransformerFiles.getFiles().getAsFileTree(), accessTransformerFiles.getEntries().get(), definition.getListLibrariesTaskProvider()); + final TaskProvider accessTransformerTask = CommonRuntimeTaskUtils.createSourceAccessTransformer(definition, "User", runtimeWorkspace, dependentTaskConfigurationHandler, accessTransformerFiles.getFiles().getAsFileTree(), accessTransformerFiles.getEntries().get(), definition.getListLibrariesTaskProvider(), definition.getAllDependencies()); accessTransformerTask.configure(task -> task.getInputFile().set(previousTasksOutput.flatMap(WithOutput::getOutput))); accessTransformerTask.configure(task -> task.dependsOn(previousTasksOutput)); return accessTransformerTask; diff --git a/userdev/src/main/java/net/neoforged/gradle/userdev/runtime/definition/UserDevRuntimeDefinition.java b/userdev/src/main/java/net/neoforged/gradle/userdev/runtime/definition/UserDevRuntimeDefinition.java index 988a6cf12..45ede358f 100644 --- a/userdev/src/main/java/net/neoforged/gradle/userdev/runtime/definition/UserDevRuntimeDefinition.java +++ b/userdev/src/main/java/net/neoforged/gradle/userdev/runtime/definition/UserDevRuntimeDefinition.java @@ -54,6 +54,10 @@ public UserDevRuntimeDefinition(@NotNull UserDevRuntimeSpecification specificati this.additionalUserDevDependencies.getDependencies().add( clientExtraJar ); + + this.getAllDependencies().from(neoformRuntimeDefinition.getAllDependencies()); + this.getAllDependencies().from(getAdditionalUserDevDependencies()); + this.getAllDependencies().from(getUserdevConfiguration()); } @Override diff --git a/userdev/src/main/java/net/neoforged/gradle/userdev/runtime/extension/UserDevRuntimeExtension.java b/userdev/src/main/java/net/neoforged/gradle/userdev/runtime/extension/UserDevRuntimeExtension.java index a03bac0c0..1f26b0e0f 100644 --- a/userdev/src/main/java/net/neoforged/gradle/userdev/runtime/extension/UserDevRuntimeExtension.java +++ b/userdev/src/main/java/net/neoforged/gradle/userdev/runtime/extension/UserDevRuntimeExtension.java @@ -129,7 +129,7 @@ private TaskTreeAdapter createAccessTransformerAdapter(final String accessTransf userDev.matching(filter -> filter.include(accessTransformerDirectory + "/**")); return (definition, previousTasksOutput, runtimeWorkspace, gameArtifacts, mappingVersionData, dependentTaskConfigurationHandler) -> { - final TaskProvider accessTransformerTask = CommonRuntimeTaskUtils.createSourceAccessTransformer(definition, "Forges", runtimeWorkspace, dependentTaskConfigurationHandler, accessTransformerFiles, Collections.emptyList(), definition.getListLibrariesTaskProvider()); + final TaskProvider accessTransformerTask = CommonRuntimeTaskUtils.createSourceAccessTransformer(definition, "Forges", runtimeWorkspace, dependentTaskConfigurationHandler, accessTransformerFiles, Collections.emptyList(), definition.getListLibrariesTaskProvider(), definition.getAllDependencies()); accessTransformerTask.configure(task -> task.getInputFile().set(previousTasksOutput.flatMap(WithOutput::getOutput))); accessTransformerTask.configure(task -> task.dependsOn(previousTasksOutput)); return accessTransformerTask;