Skip to content

Commit

Permalink
move downloadMinecraftLibraries and openGlConstantUnpickGenerator con…
Browse files Browse the repository at this point in the history
…figuration to MappingsPlugin

rework both tasks' inputs and outputs significantly
downloadMinecraftLibraries is still screwy though: it accesses and modifies project in its task action
add Task suffix to OpenGlConstantUnpickGenerator class
rename PropertyUtil -> ProviderUtil and add projectDirProviderOf
  • Loading branch information
supersaiyansubtlety committed Sep 29, 2024
1 parent 32b7c0e commit 5616c3a
Show file tree
Hide file tree
Showing 8 changed files with 173 additions and 77 deletions.
46 changes: 34 additions & 12 deletions buildSrc/src/main/java/quilt/internal/MappingsPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,13 @@
import quilt.internal.tasks.setup.MergeJarsTask;
import quilt.internal.tasks.unpick.CombineUnpickDefinitionsTask;
import quilt.internal.tasks.unpick.RemapUnpickDefinitionsTask;
import quilt.internal.tasks.unpick.gen.OpenGlConstantUnpickGenerator;
import quilt.internal.tasks.unpick.gen.OpenGlConstantUnpickGeneratorTask;

import java.io.File;

public class MappingsPlugin implements Plugin<Project> {
import static quilt.internal.util.ProviderUtil.projectDirProviderOf;

public abstract class MappingsPlugin implements Plugin<Project> {
public static final String INSERT_AUTO_GENERATED_MAPPINGS_TASK_NAME = "insertAutoGeneratedMappings";

@Override
Expand Down Expand Up @@ -95,9 +97,10 @@ public void apply(@NotNull Project project) {
task -> {
task.getServerBootstrapJar().convention(downloadMinecraftJars.get().getServerBootstrapJar());

task.getServerJar().convention(() ->
new File(ext.getFileConstants().cacheFilesMinecraft, Constants.MINECRAFT_VERSION + "-server.jar")
);
task.getServerJar().convention(() -> new File(
ext.getFileConstants().cacheFilesMinecraft,
Constants.MINECRAFT_VERSION + "-server.jar"
));
}
);

Expand All @@ -108,7 +111,10 @@ public void apply(@NotNull Project project) {
// TODO see if output jars like this can all go in a directory (build/minecraftJars/?)
task.getMergedFile().convention(() -> project.file(Constants.MINECRAFT_VERSION + "-merged.jar"));
});
tasks.register(DownloadMinecraftLibrariesTask.TASK_NAME, DownloadMinecraftLibrariesTask.class);
final var downloadMinecraftLibraries = tasks.register(DownloadMinecraftLibrariesTask.TASK_NAME, DownloadMinecraftLibrariesTask.class, task -> {
task.getVersionFile().convention(downloadWantedVersionManifest.get().getVersionFile());
task.getLibrariesDir().convention(projectDirProviderOf(project, ext.getFileConstants().libraries));
});

final var downloadPerVersionMappings =
tasks.register(DownloadPerVersionMappingsTask.TASK_NAME, DownloadPerVersionMappingsTask.class);
Expand All @@ -117,8 +123,8 @@ public void apply(@NotNull Project project) {
tasks.register(INSERT_AUTO_GENERATED_MAPPINGS_TASK_NAME, AddProposedMappingsTask.class, task -> {
task.dependsOn(downloadPerVersionMappings);

task.getInputJar().set(ext.getFileConstants().perVersionMappingsJar);
task.getInputMappings().set(buildMappingsTiny.getOutputMappings());
task.getInputJar().convention(() -> ext.getFileConstants().perVersionMappingsJar);
task.getInputMappings().convention(buildMappingsTiny.getOutputMappings());
});

tasks.register(MergeTinyTask.TASK_NAME, MergeTinyTask.class);
Expand All @@ -132,14 +138,30 @@ public void apply(@NotNull Project project) {

tasks.register(CombineUnpickDefinitionsTask.TASK_NAME, CombineUnpickDefinitionsTask.class);
tasks.register(RemapUnpickDefinitionsTask.TASK_NAME, RemapUnpickDefinitionsTask.class);
tasks.register(OpenGlConstantUnpickGenerator.TASK_NAME, OpenGlConstantUnpickGenerator.class);
tasks.register(OpenGlConstantUnpickGeneratorTask.TASK_NAME, OpenGlConstantUnpickGeneratorTask.class, task -> {
// TODO eliminate this
task.dependsOn(MapPerVersionMappingsJarTask.TASK_NAME);

task.getVersionFile().convention(downloadMinecraftLibraries.get().getVersionFile());

task.getPerVersionMappingsJar().convention(() -> ext.getFileConstants().perVersionMappingsJar);

// TODO make sure this works even after MapPerVersionMappingsJarTask is updated
task.getArtifactsByUrl().convention(downloadMinecraftLibraries.get().artifactsByUrl);

task.getUnpickGlStateManagerDefinitions().convention(() ->
ext.getFileConstants().unpickGlStateManagerDefinitions
);

task.getUnpickGlDefinitions().convention(() -> ext.getFileConstants().unpickGlDefinitions);
});

tasks.register(GeneratePackageInfoMappingsTask.TASK_NAME, GeneratePackageInfoMappingsTask.class);
tasks.register(DownloadDictionaryFileTask.TASK_NAME, DownloadDictionaryFileTask.class);
final var mappingLint = tasks.create(MappingLintTask.TASK_NAME, MappingLintTask.class);
final var mappingLint = tasks.register(MappingLintTask.TASK_NAME, MappingLintTask.class);
tasks.register(FindDuplicateMappingFilesTask.TASK_NAME, FindDuplicateMappingFilesTask.class, task -> {
task.getMappingDirectory().set(mappingLint.getMappingDirectory());
mappingLint.dependsOn(task);
task.getMappingDirectory().set(mappingLint.get().getMappingDirectory());
mappingLint.get().dependsOn(task);
});

tasks.register(CheckIntermediaryMappingsTask.TASK_NAME, CheckIntermediaryMappingsTask.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
import org.jetbrains.annotations.VisibleForTesting;
import quilt.internal.Constants;
import quilt.internal.tasks.EnigmaProfileConsumingTask;
import quilt.internal.util.PropertyUtil;
import quilt.internal.util.ProviderUtil;

public abstract class AddProposedMappingsTask extends EnigmaProfileConsumingTask {
@OutputFile
Expand All @@ -59,9 +59,9 @@ public AddProposedMappingsTask() {
public void addProposedMappings() throws Exception {
this.getLogger().lifecycle(":seeking auto-mappable entries");

final Path input = PropertyUtil.getPath(this.getInputMappings());
final Path output = PropertyUtil.getPath(this.getOutputMappings());
final Path jar = PropertyUtil.getPath(this.getInputJar());
final Path input = ProviderUtil.getPath(this.getInputMappings());
final Path output = ProviderUtil.getPath(this.getOutputMappings());
final Path jar = ProviderUtil.getPath(this.getInputJar());

addProposedMappings(input, output, this.fileConstants.tempDir.toPath(), jar, this.getEnigmaProfile().get());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import quilt.internal.Constants;
import quilt.internal.tasks.DefaultMappingsTask;
import quilt.internal.tasks.jarmapping.MapPerVersionMappingsJarTask;
import quilt.internal.util.PropertyUtil;
import quilt.internal.util.ProviderUtil;

public abstract class BuildMappingsTinyTask extends DefaultMappingsTask {
public static final String TASK_NAME = "buildMappingsTiny";
Expand All @@ -40,7 +40,7 @@ public void execute() throws IOException, MappingParseException {
buildMappingsTiny(
this.fileConstants.perVersionMappingsJar.toPath(),
this.getMappings().get().getAsFile().toPath(),
PropertyUtil.getPath(this.getOutputMappings())
ProviderUtil.getPath(this.getOutputMappings())
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import quilt.internal.Constants;
import quilt.internal.tasks.DefaultMappingsTask;
import quilt.internal.tasks.setup.CheckIntermediaryMappingsTask;
import quilt.internal.util.PropertyUtil;
import quilt.internal.util.ProviderUtil;

import java.io.File;
import java.io.IOException;
Expand Down Expand Up @@ -49,8 +49,8 @@ public RemoveIntermediaryTask() {

@TaskAction
public void removeIntermediary() throws Exception {
final Path mappingsTinyInput = PropertyUtil.getPath(this.getInput());
final Path output = PropertyUtil.getPath(this.getOutputMappings());
final Path mappingsTinyInput = ProviderUtil.getPath(this.getInput());
final Path output = ProviderUtil.getPath(this.getOutputMappings());

this.getLogger().lifecycle(":removing intermediary");
removeIntermediary(mappingsTinyInput, output);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,27 @@
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.commons.io.FileUtils;
import org.gradle.api.GradleException;
import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.provider.MapProperty;
import org.gradle.api.provider.Property;
import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.Internal;
import org.gradle.api.tasks.OutputDirectory;
import org.gradle.api.tasks.TaskAction;
import org.quiltmc.launchermeta.version.v1.DownloadableFile;
import org.quiltmc.launchermeta.version.v1.Library;
import org.quiltmc.launchermeta.version.v1.Version;
import quilt.internal.Constants;
import quilt.internal.FileConstants;
Expand All @@ -20,70 +32,114 @@
public abstract class DownloadMinecraftLibrariesTask extends DefaultMappingsTask {
public static final String TASK_NAME = "downloadMinecraftLibraries";

/**
* This is only populated after the task has run.
* <p>
* It should only be accessed from other {@linkplain TaskAction tasks' actions} and via
* {@linkplain MapProperty lazy} {@linkplain org.gradle.api.tasks.Input input}.
*/
public final Provider<Map<String, File>> artifactsByUrl;

@InputFile
public abstract RegularFileProperty getVersionFile();

@Internal("Fingerprinting is handled by getVersionFile")
protected abstract Property<Version> getVersion();

@OutputDirectory
public abstract DirectoryProperty getLibrariesDir();

@Internal("Fingerprinting is handled by getLibrariesDir")
protected abstract MapProperty<String, File> getArtifactsByUrl();

public DownloadMinecraftLibrariesTask() {
super(Constants.Groups.SETUP_GROUP);
// TODO is this because library sources may change even on the same version?
this.outputsNeverUpToDate();

this.dependsOn(DownloadWantedVersionManifestTask.TASK_NAME);
this.getVersion().convention(this.getVersionFile().map(file -> {
try {
return Version.fromString(FileUtils.readFileToString(file.getAsFile(), StandardCharsets.UTF_8));
} catch (IOException e) {
throw new GradleException("Failed to read version file", e);
}
}));

this.getVersionFile().convention(
this.getTaskNamed(DownloadWantedVersionManifestTask.TASK_NAME, DownloadWantedVersionManifestTask.class)
.getVersionFile()
);
// provide an informative error message if this property is accessed incorrectly
this.getArtifactsByUrl().convention(this.getProject().provider(() -> {
throw new GradleException(
"artifactsByUrl has not been populated. " +
"It should only be accessed from other tasks' actions and via lazy input."
);
}));

this.getOutputs().dir(this.fileConstants.libraries);
this.outputsNeverUpToDate();
this.artifactsByUrl = this.getArtifactsByUrl();
}

@TaskAction
public void downloadMinecraftLibrariesTask() throws IOException {
final Version file = Version.fromString(FileUtils.readFileToString(
this.getVersionFile().get().getAsFile(), StandardCharsets.UTF_8
));

public void downloadMinecraftLibrariesTask() {
this.getLogger().lifecycle(":downloading minecraft libraries");

if (!this.fileConstants.libraries.exists()) {
this.fileConstants.libraries.mkdirs();
}
this.getLibrariesDir().get().getAsFile().mkdirs();

final AtomicBoolean failed = new AtomicBoolean(false);

final Object lock = new Object();

file.getLibraries().parallelStream().forEach(library -> {
final Optional<DownloadableFile.PathDownload> artifact = library.getDownloads().getArtifact();
if (artifact.isEmpty()) {
return;
final List<Library> librariesSrc = this.getVersion().get().getLibraries();

final Map<String, File> artifactsByUrl = librariesSrc.parallelStream().flatMap(library -> {
final Optional<DownloadableFile.PathDownload> artifactPath = library.getDownloads().getArtifact();
if (artifactPath.isEmpty()) {
return Stream.empty();
}

final String url = artifactPath.get().getUrl();
final File artifact = this.artifactOf(url);

boolean thisFailed = false;
try {
final String url = artifact.get().getUrl();
this.startDownload()
.src(url)
.dest(getArtifactFile(this.fileConstants, url))
.overwrite(false)
.download();
.src(url)
.dest(artifact)
.overwrite(false)
.download();
} catch (IOException e) {
failed.set(true);
thisFailed = true;
e.printStackTrace();
} catch (NoSuchElementException e) {
new RuntimeException("Unable to find artifact for " + library.getName(), e).printStackTrace();
}

synchronized (lock) {
// TODO this is screwy.
// Could we put these in a configuration in MappingsPlugin
// and pass the configuration to an input of this task?
this.getProject().getDependencies().add("decompileClasspath", library.getName());
}
});

if (thisFailed) {
failed.set(true);

return Stream.empty();
} else {
return Stream.of(Map.entry(url, artifact));
}
}).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

// TODO is it intended that downloading continues after the first failure,
// but we still throw an exception after we've tried downloading each library?
if (failed.get()) {
throw new RuntimeException("Unable to download libraries for specified minecraft version.");
}

this.getArtifactsByUrl().set(artifactsByUrl);
}

public static File getArtifactFile(FileConstants fileConstants, String url) {
return new File(fileConstants.libraries, url.substring(url.lastIndexOf("/") + 1));
private File artifactOf(String url) {
return new File(
this.getLibrariesDir().get().getAsFile(),
url.substring(url.lastIndexOf("/") + 1)
);
}
}
Loading

0 comments on commit 5616c3a

Please sign in to comment.