aboutsummaryrefslogtreecommitdiff
path: root/plugin/src/main/java/moe
diff options
context:
space:
mode:
authorLinnea Gräf <nea@nea.moe>2024-03-06 16:58:28 +0100
committerLinnea Gräf <nea@nea.moe>2024-03-06 16:58:28 +0100
commit488641115e6edd77adc34cbe6f1eac88444dedb8 (patch)
tree3202da6008bb56e631080efbda3b3ebe14909b34 /plugin/src/main/java/moe
parentda5f39ea4fe99a32bb3f4eec64ab92e3035e4762 (diff)
downloadzwirn-488641115e6edd77adc34cbe6f1eac88444dedb8.tar.gz
zwirn-488641115e6edd77adc34cbe6f1eac88444dedb8.tar.bz2
zwirn-488641115e6edd77adc34cbe6f1eac88444dedb8.zip
Add gradle plugin
Diffstat (limited to 'plugin/src/main/java/moe')
-rw-r--r--plugin/src/main/java/moe/nea/zwirn/plugin/ConvertSeargeToTinyTask.java37
-rw-r--r--plugin/src/main/java/moe/nea/zwirn/plugin/DiffTinyFilesTask.java39
-rw-r--r--plugin/src/main/java/moe/nea/zwirn/plugin/DownloadMinecraftTask.java49
-rw-r--r--plugin/src/main/java/moe/nea/zwirn/plugin/EnrichSeargeWithMCPTask.java46
-rw-r--r--plugin/src/main/java/moe/nea/zwirn/plugin/FixFieldDescriptorsTask.java34
-rw-r--r--plugin/src/main/java/moe/nea/zwirn/plugin/MapJarTask.java61
-rw-r--r--plugin/src/main/java/moe/nea/zwirn/plugin/MergeTinyFilesTask.java34
-rw-r--r--plugin/src/main/java/moe/nea/zwirn/plugin/PackMappingsTask.java39
-rw-r--r--plugin/src/main/java/moe/nea/zwirn/plugin/ReorderNamespacesTask.java41
-rw-r--r--plugin/src/main/java/moe/nea/zwirn/plugin/UnpackMappingsTask.java31
-rw-r--r--plugin/src/main/java/moe/nea/zwirn/plugin/ZwirnPlugin.java11
-rw-r--r--plugin/src/main/java/moe/nea/zwirn/plugin/ZwirnPluginUtils.java71
12 files changed, 493 insertions, 0 deletions
diff --git a/plugin/src/main/java/moe/nea/zwirn/plugin/ConvertSeargeToTinyTask.java b/plugin/src/main/java/moe/nea/zwirn/plugin/ConvertSeargeToTinyTask.java
new file mode 100644
index 0000000..a8f741f
--- /dev/null
+++ b/plugin/src/main/java/moe/nea/zwirn/plugin/ConvertSeargeToTinyTask.java
@@ -0,0 +1,37 @@
+package moe.nea.zwirn.plugin;
+
+import net.minecraftforge.srgutils.IMappingFile;
+import net.minecraftforge.srgutils.INamedMappingFile;
+import org.gradle.api.DefaultTask;
+import org.gradle.api.file.FileCollection;
+import org.gradle.api.file.RegularFileProperty;
+import org.gradle.api.tasks.InputFiles;
+import org.gradle.api.tasks.OutputFile;
+import org.gradle.api.tasks.TaskAction;
+
+import java.io.IOException;
+import java.util.zip.ZipFile;
+
+public abstract class ConvertSeargeToTinyTask extends DefaultTask {
+ @InputFiles
+ FileCollection srgArchive;
+
+ public void setSrgArchive(FileCollection srgArchive) {
+ this.srgArchive = srgArchive;
+ }
+
+ public FileCollection getSrgArchive() {
+ return srgArchive;
+ }
+
+ @OutputFile
+ public abstract RegularFileProperty getSrgTinyFile();
+
+ @TaskAction
+ public void convert() throws IOException {
+ var zipFile = new ZipFile(getSrgArchive().getSingleFile());
+ var srgFile = INamedMappingFile.load(zipFile.getInputStream(zipFile.getEntry("joined.srg")));
+ zipFile.close();
+ srgFile.write(ZwirnPluginUtils.getPath(getSrgTinyFile()), IMappingFile.Format.TINY);
+ }
+}
diff --git a/plugin/src/main/java/moe/nea/zwirn/plugin/DiffTinyFilesTask.java b/plugin/src/main/java/moe/nea/zwirn/plugin/DiffTinyFilesTask.java
new file mode 100644
index 0000000..4b4fa64
--- /dev/null
+++ b/plugin/src/main/java/moe/nea/zwirn/plugin/DiffTinyFilesTask.java
@@ -0,0 +1,39 @@
+package moe.nea.zwirn.plugin;
+
+import moe.nea.zwirn.Zwirn;
+import org.gradle.api.DefaultTask;
+import org.gradle.api.file.RegularFileProperty;
+import org.gradle.api.provider.ListProperty;
+import org.gradle.api.provider.Property;
+import org.gradle.api.tasks.Input;
+import org.gradle.api.tasks.InputFile;
+import org.gradle.api.tasks.OutputFile;
+import org.gradle.api.tasks.TaskAction;
+
+public abstract class DiffTinyFilesTask extends DefaultTask {
+ @InputFile
+ public abstract RegularFileProperty getMergedTinyFile();
+
+ @InputFile
+ public abstract RegularFileProperty getBaseTinyFile();
+
+ @OutputFile
+ public abstract RegularFileProperty getOutputTinyFile();
+
+ @Input
+ public abstract Property<String> getSharedNamespace();
+
+ @Input
+ public abstract ListProperty<String> getRetainedNamespaces();
+
+ @TaskAction
+ public void diffTiny() {
+ var merged = ZwirnPluginUtils.readTiny(getMergedTinyFile());
+ var base = ZwirnPluginUtils.readTiny(getBaseTinyFile());
+ var remerged = Zwirn.mergeTinyFile(base, merged, getSharedNamespace().get());
+ var overlay = Zwirn.createOverlayTinyFile(base, remerged, getRetainedNamespaces().get(), getSharedNamespace().get());
+ ZwirnPluginUtils.writeTiny(overlay, getOutputTinyFile());
+ }
+
+
+}
diff --git a/plugin/src/main/java/moe/nea/zwirn/plugin/DownloadMinecraftTask.java b/plugin/src/main/java/moe/nea/zwirn/plugin/DownloadMinecraftTask.java
new file mode 100644
index 0000000..f67d780
--- /dev/null
+++ b/plugin/src/main/java/moe/nea/zwirn/plugin/DownloadMinecraftTask.java
@@ -0,0 +1,49 @@
+package moe.nea.zwirn.plugin;
+
+import com.google.gson.JsonObject;
+import org.gradle.api.DefaultTask;
+import org.gradle.api.file.RegularFileProperty;
+import org.gradle.api.provider.Property;
+import org.gradle.api.tasks.Input;
+import org.gradle.api.tasks.OutputFile;
+import org.gradle.api.tasks.TaskAction;
+
+import java.io.IOException;
+import java.nio.file.Files;
+
+public abstract class DownloadMinecraftTask extends DefaultTask {
+ @Input
+ public abstract Property<String> getVersion();
+
+ @OutputFile
+ public abstract RegularFileProperty getMinecraftJar();
+
+
+ private JsonObject selectVersion(JsonObject meta) {
+ for (var version : meta.getAsJsonArray("versions")) {
+ if (version.getAsJsonObject().get("id").getAsString().equals(getVersion().get())) {
+ return version.getAsJsonObject();
+ }
+ }
+ throw new RuntimeException("Could not find version " + getVersion().get());
+ }
+
+ @TaskAction
+ public void downloadMinecraft() {
+ var meta = ZwirnPluginUtils.readUrl("https://launchermeta.mojang.com/mc/game/version_manifest.json");
+ var versionObject = selectVersion(meta);
+ var versionManifestUrl = versionObject.get("url").getAsString();
+ var versionManifest = ZwirnPluginUtils.readUrl(versionManifestUrl);
+ var downloadUrl = versionManifest.getAsJsonObject("downloads")
+ .getAsJsonObject("client").get("url").getAsString();
+ try (
+ var output = Files.newOutputStream(ZwirnPluginUtils.getPath(getMinecraftJar()));
+ var remote = ZwirnPluginUtils.readUrlAsStream(downloadUrl)
+ ) {
+ ZwirnPluginUtils.copy(remote, output);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+}
diff --git a/plugin/src/main/java/moe/nea/zwirn/plugin/EnrichSeargeWithMCPTask.java b/plugin/src/main/java/moe/nea/zwirn/plugin/EnrichSeargeWithMCPTask.java
new file mode 100644
index 0000000..7464dc4
--- /dev/null
+++ b/plugin/src/main/java/moe/nea/zwirn/plugin/EnrichSeargeWithMCPTask.java
@@ -0,0 +1,46 @@
+package moe.nea.zwirn.plugin;
+
+import moe.nea.zwirn.Zwirn;
+import net.fabricmc.stitch.commands.tinyv2.TinyV2Reader;
+import net.fabricmc.stitch.commands.tinyv2.TinyV2Writer;
+import org.gradle.api.DefaultTask;
+import org.gradle.api.file.FileCollection;
+import org.gradle.api.file.RegularFileProperty;
+import org.gradle.api.tasks.InputFile;
+import org.gradle.api.tasks.InputFiles;
+import org.gradle.api.tasks.OutputFile;
+import org.gradle.api.tasks.TaskAction;
+
+import java.io.IOException;
+import java.nio.file.FileSystems;
+
+public abstract class EnrichSeargeWithMCPTask extends DefaultTask {
+
+ @InputFiles
+ FileCollection mcpArchive;
+
+ public FileCollection getMcpArchive() {
+ return mcpArchive;
+ }
+
+ public void setMcpArchive(FileCollection mcpArchive) {
+ this.mcpArchive = mcpArchive;
+ }
+
+ @InputFile
+ public abstract RegularFileProperty getSrgTinyFile();
+
+ @OutputFile
+ public abstract RegularFileProperty getEnrichedTinyFile();
+
+ @TaskAction
+ public void enrich() throws IOException {
+ var mcpFs = FileSystems.newFileSystem(getMcpArchive().getSingleFile().toPath());
+ var enriched = Zwirn.enrichSeargeWithMCP(
+ TinyV2Reader.read(ZwirnPluginUtils.getPath(getSrgTinyFile())),
+ mcpFs.getPath("/")
+ );
+ mcpFs.close();
+ TinyV2Writer.write(enriched, ZwirnPluginUtils.getPath(getEnrichedTinyFile()));
+ }
+}
diff --git a/plugin/src/main/java/moe/nea/zwirn/plugin/FixFieldDescriptorsTask.java b/plugin/src/main/java/moe/nea/zwirn/plugin/FixFieldDescriptorsTask.java
new file mode 100644
index 0000000..fa8576d
--- /dev/null
+++ b/plugin/src/main/java/moe/nea/zwirn/plugin/FixFieldDescriptorsTask.java
@@ -0,0 +1,34 @@
+package moe.nea.zwirn.plugin;
+
+import moe.nea.zwirn.Zwirn;
+import net.fabricmc.stitch.commands.tinyv2.TinyV2Reader;
+import net.fabricmc.stitch.commands.tinyv2.TinyV2Writer;
+import org.gradle.api.DefaultTask;
+import org.gradle.api.file.RegularFileProperty;
+import org.gradle.api.tasks.InputFile;
+import org.gradle.api.tasks.TaskAction;
+
+import java.io.IOException;
+import java.nio.file.FileSystems;
+
+public abstract class FixFieldDescriptorsTask extends DefaultTask {
+
+ @InputFile
+ public abstract RegularFileProperty getJarInFirstNamespace();
+
+ @InputFile
+ public abstract RegularFileProperty getInputTinyFile();
+
+ @InputFile
+ public abstract RegularFileProperty getOutputTinyFile();
+
+ @TaskAction
+ public void fixFields() throws IOException {
+ var tinyIn = TinyV2Reader.read(ZwirnPluginUtils.getPath(getInputTinyFile()));
+ var fs = FileSystems.newFileSystem(ZwirnPluginUtils.getPath(getJarInFirstNamespace()));
+ var fixed = Zwirn.fixFieldDescriptorsFromJar(tinyIn, fs.getPath("/"));
+ fs.close();
+ TinyV2Writer.write(fixed, ZwirnPluginUtils.getPath(getOutputTinyFile()));
+ }
+
+}
diff --git a/plugin/src/main/java/moe/nea/zwirn/plugin/MapJarTask.java b/plugin/src/main/java/moe/nea/zwirn/plugin/MapJarTask.java
new file mode 100644
index 0000000..afeba08
--- /dev/null
+++ b/plugin/src/main/java/moe/nea/zwirn/plugin/MapJarTask.java
@@ -0,0 +1,61 @@
+package moe.nea.zwirn.plugin;
+
+import net.fabricmc.tinyremapper.OutputConsumerPath;
+import net.fabricmc.tinyremapper.TinyRemapper;
+import net.fabricmc.tinyremapper.TinyUtils;
+import org.gradle.api.DefaultTask;
+import org.gradle.api.file.FileCollection;
+import org.gradle.api.file.RegularFileProperty;
+import org.gradle.api.provider.Property;
+import org.gradle.api.tasks.*;
+
+import java.io.IOException;
+import java.util.regex.Pattern;
+
+public abstract class MapJarTask extends DefaultTask {
+ @InputFiles
+ FileCollection inputJar;
+
+ public FileCollection getInputJar() {
+ return inputJar;
+ }
+
+ public void setInputJar(FileCollection inputJar) {
+ this.inputJar = inputJar;
+ }
+
+ @InputFile
+ public abstract RegularFileProperty getMappingTinyFile();
+
+ @Input
+ public abstract Property<String> getInputNamespace();
+
+ @Input
+ public abstract Property<String> getOutputNamespace();
+
+ @OutputFile
+ public abstract RegularFileProperty getOutputJar();
+
+ @TaskAction
+ public void mapJar() throws IOException {
+ var mappingProvider =
+ TinyUtils.createTinyMappingProvider(
+ ZwirnPluginUtils.getPath(getMappingTinyFile()),
+ getInputNamespace().get(),
+ getOutputNamespace().get()
+ );
+ var remapper = TinyRemapper.newRemapper()
+ .withMappings(mappingProvider)
+ .renameInvalidLocals(true)
+ .rebuildSourceFilenames(true)
+ .invalidLvNamePattern(Pattern.compile("\\$\\$\\d+"))
+ .inferNameFromSameLvIndex(true)
+ .build();
+ try (var outputConsumer = new OutputConsumerPath.Builder(ZwirnPluginUtils.getPath(getOutputJar())).build()) {
+ remapper.readInputsAsync(ZwirnPluginUtils.getPath(getInputJar()));
+ remapper.apply(outputConsumer);
+ } finally {
+ remapper.finish();
+ }
+ }
+}
diff --git a/plugin/src/main/java/moe/nea/zwirn/plugin/MergeTinyFilesTask.java b/plugin/src/main/java/moe/nea/zwirn/plugin/MergeTinyFilesTask.java
new file mode 100644
index 0000000..8d6df84
--- /dev/null
+++ b/plugin/src/main/java/moe/nea/zwirn/plugin/MergeTinyFilesTask.java
@@ -0,0 +1,34 @@
+package moe.nea.zwirn.plugin;
+
+import moe.nea.zwirn.Zwirn;
+import org.gradle.api.DefaultTask;
+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.OutputFile;
+import org.gradle.api.tasks.TaskAction;
+
+public abstract class MergeTinyFilesTask extends DefaultTask {
+ @InputFile
+ public abstract RegularFileProperty getBaseTinyFile();
+
+ @InputFile
+ public abstract RegularFileProperty getOverlayTinyFile();
+
+ @Input
+ public abstract Property<String> getSharedNamespace();
+
+ @OutputFile
+ public abstract RegularFileProperty getOutputTinyFile();
+
+ @TaskAction
+ public void mergeTinyFiles() {
+ var merged = Zwirn.mergeTinyFile(
+ ZwirnPluginUtils.readTiny(getBaseTinyFile()),
+ ZwirnPluginUtils.readTiny(getOverlayTinyFile()),
+ getSharedNamespace().get()
+ );
+ ZwirnPluginUtils.writeTiny(merged, getOutputTinyFile());
+ }
+}
diff --git a/plugin/src/main/java/moe/nea/zwirn/plugin/PackMappingsTask.java b/plugin/src/main/java/moe/nea/zwirn/plugin/PackMappingsTask.java
new file mode 100644
index 0000000..0ab439a
--- /dev/null
+++ b/plugin/src/main/java/moe/nea/zwirn/plugin/PackMappingsTask.java
@@ -0,0 +1,39 @@
+package moe.nea.zwirn.plugin;
+
+import cuchaz.enigma.command.ConvertMappingsCommand;
+import cuchaz.enigma.translation.mapping.serde.MappingParseException;
+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.InputDirectory;
+import org.gradle.api.tasks.OutputFile;
+import org.gradle.api.tasks.TaskAction;
+
+import java.io.IOException;
+
+public abstract class PackMappingsTask extends DefaultTask {
+ @InputDirectory
+ public abstract DirectoryProperty getInputEnigmaDirectory();
+
+ @OutputFile
+ public abstract RegularFileProperty getOutputTinyFile();
+
+ @Input
+ public abstract Property<String> getObfuscatedNamespace();
+
+ @Input
+ public abstract Property<String> getReadableNamespace();
+
+ @TaskAction
+ public void packMappings() throws MappingParseException, IOException {
+ new ConvertMappingsCommand().run(
+ "enigma",
+ ZwirnPluginUtils.getPath(getInputEnigmaDirectory()).toAbsolutePath().toString(),
+ "tinyv2:" + getObfuscatedNamespace().get() + ":" + getReadableNamespace().get(),
+ ZwirnPluginUtils.getPath(getOutputTinyFile()).toAbsolutePath().toString()
+ );
+ }
+
+}
diff --git a/plugin/src/main/java/moe/nea/zwirn/plugin/ReorderNamespacesTask.java b/plugin/src/main/java/moe/nea/zwirn/plugin/ReorderNamespacesTask.java
new file mode 100644
index 0000000..b6f4498
--- /dev/null
+++ b/plugin/src/main/java/moe/nea/zwirn/plugin/ReorderNamespacesTask.java
@@ -0,0 +1,41 @@
+package moe.nea.zwirn.plugin;
+
+import moe.nea.zwirn.Zwirn;
+import net.fabricmc.stitch.commands.tinyv2.TinyV2Reader;
+import net.fabricmc.stitch.commands.tinyv2.TinyV2Writer;
+import org.gradle.api.DefaultTask;
+import org.gradle.api.file.RegularFileProperty;
+import org.gradle.api.provider.ListProperty;
+import org.gradle.api.tasks.Input;
+import org.gradle.api.tasks.InputFile;
+import org.gradle.api.tasks.OutputFile;
+import org.gradle.api.tasks.TaskAction;
+
+import java.io.IOException;
+
+public abstract class ReorderNamespacesTask extends DefaultTask {
+ @InputFile
+ public abstract RegularFileProperty getInputTinyFile();
+
+ @OutputFile
+ public abstract RegularFileProperty getOutputTinyFile();
+
+ @Input
+ public abstract ListProperty<Zwirn.RenameCommand> getNamespaceOrder();
+
+ public void appendNamespaceKeepName(String namespace) {
+ appendNamespaceRenamed(namespace, namespace);
+ }
+
+ public void appendNamespaceRenamed(String oldName, String newName) {
+ getNamespaceOrder().add(new Zwirn.RenameCommand(oldName, newName));
+ }
+
+ @TaskAction
+ public void reorderNamespaces() throws IOException {
+ var oldFile = TinyV2Reader.read(ZwirnPluginUtils.getPath(getInputTinyFile()));
+ var newFile = Zwirn.renameNamespaces(oldFile, getNamespaceOrder().get());
+ TinyV2Writer.write(newFile, ZwirnPluginUtils.getPath(getOutputTinyFile()));
+ }
+
+}
diff --git a/plugin/src/main/java/moe/nea/zwirn/plugin/UnpackMappingsTask.java b/plugin/src/main/java/moe/nea/zwirn/plugin/UnpackMappingsTask.java
new file mode 100644
index 0000000..3da938b
--- /dev/null
+++ b/plugin/src/main/java/moe/nea/zwirn/plugin/UnpackMappingsTask.java
@@ -0,0 +1,31 @@
+package moe.nea.zwirn.plugin;
+
+import cuchaz.enigma.command.ConvertMappingsCommand;
+import cuchaz.enigma.translation.mapping.serde.MappingParseException;
+import org.gradle.api.DefaultTask;
+import org.gradle.api.file.DirectoryProperty;
+import org.gradle.api.file.RegularFileProperty;
+import org.gradle.api.tasks.InputFile;
+import org.gradle.api.tasks.OutputDirectory;
+import org.gradle.api.tasks.TaskAction;
+
+import java.io.IOException;
+
+public abstract class UnpackMappingsTask extends DefaultTask {
+ @InputFile
+ public abstract RegularFileProperty getInputTinyFile();
+
+ @OutputDirectory
+ public abstract DirectoryProperty getOutputEnigmaDirectory();
+
+ @TaskAction
+ public void unpackMappings() throws MappingParseException, IOException {
+ new ConvertMappingsCommand()
+ .run(
+ "tinyv2",
+ ZwirnPluginUtils.getPath(getInputTinyFile()).toAbsolutePath().toString(),
+ "enigma",
+ ZwirnPluginUtils.getPath(getOutputEnigmaDirectory()).toAbsolutePath().toString()
+ );
+ }
+}
diff --git a/plugin/src/main/java/moe/nea/zwirn/plugin/ZwirnPlugin.java b/plugin/src/main/java/moe/nea/zwirn/plugin/ZwirnPlugin.java
new file mode 100644
index 0000000..888f378
--- /dev/null
+++ b/plugin/src/main/java/moe/nea/zwirn/plugin/ZwirnPlugin.java
@@ -0,0 +1,11 @@
+package moe.nea.zwirn.plugin;
+
+import org.gradle.api.Plugin;
+import org.gradle.api.Project;
+import org.jetbrains.annotations.NotNull;
+
+public class ZwirnPlugin implements Plugin<Project> {
+ @Override
+ public void apply(@NotNull Project target) {
+ }
+}
diff --git a/plugin/src/main/java/moe/nea/zwirn/plugin/ZwirnPluginUtils.java b/plugin/src/main/java/moe/nea/zwirn/plugin/ZwirnPluginUtils.java
new file mode 100644
index 0000000..fd1a5ee
--- /dev/null
+++ b/plugin/src/main/java/moe/nea/zwirn/plugin/ZwirnPluginUtils.java
@@ -0,0 +1,71 @@
+package moe.nea.zwirn.plugin;
+
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import net.fabricmc.stitch.commands.tinyv2.TinyFile;
+import net.fabricmc.stitch.commands.tinyv2.TinyV2Reader;
+import net.fabricmc.stitch.commands.tinyv2.TinyV2Writer;
+import org.gradle.api.file.FileCollection;
+import org.gradle.api.file.FileSystemLocationProperty;
+import org.gradle.api.file.RegularFileProperty;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.URL;
+import java.nio.file.Path;
+
+class ZwirnPluginUtils {
+ public static Gson gson = new Gson();
+
+ public static JsonObject readUrl(String url) {
+ try (var reader = new InputStreamReader(new URL(url).openStream())) {
+ return gson.fromJson(reader, JsonObject.class);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static Path getPath(FileSystemLocationProperty<?> property) {
+ return property.get().getAsFile().toPath();
+ }
+
+ public static InputStream readUrlAsStream(String downloadUrl) {
+ try {
+ return new URL(downloadUrl).openStream();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static void copy(InputStream input, OutputStream output) throws IOException {
+ byte[] buffer = new byte[4096];
+ while (true) {
+ int read = input.read(buffer);
+ if (read < 0) break;
+ output.write(buffer, 0, read);
+ }
+ }
+
+ public static Path getPath(FileCollection collection) {
+ return collection.getSingleFile().toPath();
+ }
+
+ public static TinyFile readTiny(RegularFileProperty tinyFile) {
+ try {
+ return TinyV2Reader.read(getPath(tinyFile));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static void writeTiny(TinyFile tiny, RegularFileProperty tinyFile) {
+ try{
+ TinyV2Writer.write(tiny, getPath(tinyFile));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}