aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
authorJuuxel <6596629+Juuxel@users.noreply.github.com>2020-07-27 20:29:56 +0300
committerJuuxel <6596629+Juuxel@users.noreply.github.com>2020-07-27 20:29:56 +0300
commit38721a3f8cd8fb63bd121caed9e42a8ed854760d (patch)
tree7e91af9d0bb7c5783b4dc29b9b68060e99d52f52 /src/main
parent3ff0f73791a761c0b3de2ebaa2717000ee375787 (diff)
downloadarchitectury-loom-38721a3f8cd8fb63bd121caed9e42a8ed854760d.tar.gz
architectury-loom-38721a3f8cd8fb63bd121caed9e42a8ed854760d.tar.bz2
architectury-loom-38721a3f8cd8fb63bd121caed9e42a8ed854760d.zip
Add non-patched and Forge classes to the game jar
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/net/fabricmc/loom/AbstractPlugin.java24
-rw-r--r--src/main/java/net/fabricmc/loom/LoomGradleExtension.java5
-rw-r--r--src/main/java/net/fabricmc/loom/providers/ForgeProvider.java49
-rw-r--r--src/main/java/net/fabricmc/loom/providers/ForgeUniversalProvider.java61
-rw-r--r--src/main/java/net/fabricmc/loom/providers/McpConfigProvider.java11
-rw-r--r--src/main/java/net/fabricmc/loom/providers/MinecraftProvider.java56
-rw-r--r--src/main/java/net/fabricmc/loom/providers/PatchProvider.java9
-rw-r--r--src/main/java/net/fabricmc/loom/util/Constants.java2
-rw-r--r--src/main/java/net/fabricmc/loom/util/FsPathConsumer.java39
9 files changed, 232 insertions, 24 deletions
diff --git a/src/main/java/net/fabricmc/loom/AbstractPlugin.java b/src/main/java/net/fabricmc/loom/AbstractPlugin.java
index fb216a6e..cc1626af 100644
--- a/src/main/java/net/fabricmc/loom/AbstractPlugin.java
+++ b/src/main/java/net/fabricmc/loom/AbstractPlugin.java
@@ -32,7 +32,6 @@ import java.util.Set;
import com.google.common.collect.ImmutableMap;
import groovy.util.Node;
-import net.fabricmc.loom.providers.*;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.Task;
@@ -50,23 +49,31 @@ import org.gradle.api.tasks.bundling.AbstractArchiveTask;
import org.gradle.api.tasks.javadoc.Javadoc;
import org.gradle.plugins.ide.idea.model.IdeaModel;
+import net.fabricmc.loom.providers.ForgeProvider;
+import net.fabricmc.loom.providers.ForgeUniversalProvider;
+import net.fabricmc.loom.providers.LaunchProvider;
+import net.fabricmc.loom.providers.MappingsCache;
+import net.fabricmc.loom.providers.MappingsProvider;
+import net.fabricmc.loom.providers.McpConfigProvider;
+import net.fabricmc.loom.providers.MinecraftProvider;
+import net.fabricmc.loom.providers.PatchProvider;
import net.fabricmc.loom.task.AbstractLoomTask;
+import net.fabricmc.loom.task.RemapAllSourcesTask;
import net.fabricmc.loom.task.RemapJarTask;
import net.fabricmc.loom.task.RemapSourcesJarTask;
-import net.fabricmc.loom.task.RemapAllSourcesTask;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.DownloadUtil;
import net.fabricmc.loom.util.FabricApiExtension;
import net.fabricmc.loom.util.GroovyXmlUtil;
+import net.fabricmc.loom.util.JarRemapper;
import net.fabricmc.loom.util.LoomDependencyManager;
import net.fabricmc.loom.util.NestedJars;
import net.fabricmc.loom.util.RemappedConfigurationEntry;
import net.fabricmc.loom.util.SetupIntelijRunConfigs;
+import net.fabricmc.loom.util.SourceRemapper;
import net.fabricmc.loom.util.mixin.JavaApInvoker;
import net.fabricmc.loom.util.mixin.KaptApInvoker;
import net.fabricmc.loom.util.mixin.ScalaApInvoker;
-import net.fabricmc.loom.util.SourceRemapper;
-import net.fabricmc.loom.util.JarRemapper;
public class AbstractPlugin implements Plugin<Project> {
protected Project project;
@@ -102,8 +109,9 @@ public class AbstractPlugin implements Plugin<Project> {
project.getExtensions().add("loom", project.getExtensions().getByName("minecraft"));
project.getExtensions().create("fabricApi", FabricApiExtension.class, project);
- // Force add Mojang repository
+ // Force add Mojang and Forge repositories
addMavenRepo(target, "Mojang", "https://libraries.minecraft.net/");
+ addMavenRepo(target, "Forge", "https://files.minecraftforge.net/maven/");
Configuration modCompileClasspathConfig = project.getConfigurations().maybeCreate(Constants.MOD_COMPILE_CLASSPATH);
modCompileClasspathConfig.setTransitive(true);
@@ -118,6 +126,10 @@ public class AbstractPlugin implements Plugin<Project> {
minecraftConfig.setTransitive(false);
Configuration forgeConfig = project.getConfigurations().maybeCreate(Constants.FORGE);
forgeConfig.setTransitive(false);
+ Configuration forgeInstallerConfig = project.getConfigurations().maybeCreate(Constants.FORGE_INSTALLER);
+ forgeInstallerConfig.setTransitive(false);
+ Configuration forgeUniversalConfig = project.getConfigurations().maybeCreate(Constants.FORGE_UNIVERSAL);
+ forgeUniversalConfig.setTransitive(false);
Configuration mcpConfig = project.getConfigurations().maybeCreate(Constants.MCP_CONFIG);
mcpConfig.setTransitive(false);
@@ -228,7 +240,9 @@ public class AbstractPlugin implements Plugin<Project> {
extension.setDependencyManager(dependencyManager);
dependencyManager.addProvider(new McpConfigProvider(getProject()));
+ dependencyManager.addProvider(new ForgeProvider(getProject()));
dependencyManager.addProvider(new PatchProvider(getProject()));
+ dependencyManager.addProvider(new ForgeUniversalProvider(getProject()));
dependencyManager.addProvider(new MinecraftProvider(getProject()));
dependencyManager.addProvider(new MappingsProvider(getProject()));
dependencyManager.addProvider(new LaunchProvider(getProject()));
diff --git a/src/main/java/net/fabricmc/loom/LoomGradleExtension.java b/src/main/java/net/fabricmc/loom/LoomGradleExtension.java
index bf058c1b..32ae2143 100644
--- a/src/main/java/net/fabricmc/loom/LoomGradleExtension.java
+++ b/src/main/java/net/fabricmc/loom/LoomGradleExtension.java
@@ -48,6 +48,7 @@ import org.gradle.api.plugins.BasePluginConvention;
import net.fabricmc.loom.api.decompilers.LoomDecompiler;
import net.fabricmc.loom.processors.JarProcessorManager;
+import net.fabricmc.loom.providers.ForgeUniversalProvider;
import net.fabricmc.loom.providers.MappingsProvider;
import net.fabricmc.loom.providers.MinecraftMappedProvider;
import net.fabricmc.loom.providers.MinecraftProvider;
@@ -336,6 +337,10 @@ public class LoomGradleExtension {
return getDependencyManager().getProvider(McpConfigProvider.class);
}
+ public ForgeUniversalProvider getForgeUniversalProvider() {
+ return getDependencyManager().getProvider(ForgeUniversalProvider.class);
+ }
+
public void setDependencyManager(LoomDependencyManager dependencyManager) {
this.dependencyManager = dependencyManager;
}
diff --git a/src/main/java/net/fabricmc/loom/providers/ForgeProvider.java b/src/main/java/net/fabricmc/loom/providers/ForgeProvider.java
new file mode 100644
index 00000000..f7baa613
--- /dev/null
+++ b/src/main/java/net/fabricmc/loom/providers/ForgeProvider.java
@@ -0,0 +1,49 @@
+/*
+ * This file is part of fabric-loom, licensed under the MIT License (MIT).
+ *
+ * Copyright (c) 2016, 2017, 2018 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.
+ */
+
+package net.fabricmc.loom.providers;
+
+import java.util.function.Consumer;
+
+import org.gradle.api.Project;
+
+import net.fabricmc.loom.util.Constants;
+import net.fabricmc.loom.util.DependencyProvider;
+
+public class ForgeProvider extends DependencyProvider {
+ public ForgeProvider(Project project) {
+ super(project);
+ }
+
+ @Override
+ public void provide(DependencyInfo dependency, Consumer<Runnable> postPopulationScheduler) throws Exception {
+ addDependency(dependency.getDepString() + ":universal", Constants.FORGE_UNIVERSAL);
+ addDependency(dependency.getDepString() + ":installer", Constants.FORGE_INSTALLER);
+ }
+
+ @Override
+ public String getTargetConfig() {
+ return Constants.FORGE;
+ }
+}
diff --git a/src/main/java/net/fabricmc/loom/providers/ForgeUniversalProvider.java b/src/main/java/net/fabricmc/loom/providers/ForgeUniversalProvider.java
new file mode 100644
index 00000000..37bc3c72
--- /dev/null
+++ b/src/main/java/net/fabricmc/loom/providers/ForgeUniversalProvider.java
@@ -0,0 +1,61 @@
+/*
+ * This file is part of fabric-loom, licensed under the MIT License (MIT).
+ *
+ * Copyright (c) 2016, 2017, 2018 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.
+ */
+
+package net.fabricmc.loom.providers;
+
+import java.io.File;
+import java.util.function.Consumer;
+
+import com.google.common.io.Files;
+import org.gradle.api.Project;
+
+import net.fabricmc.loom.util.Constants;
+import net.fabricmc.loom.util.DependencyProvider;
+
+public class ForgeUniversalProvider extends DependencyProvider {
+ private File forge;
+
+ public ForgeUniversalProvider(Project project) {
+ super(project);
+ }
+
+ @Override
+ public void provide(DependencyInfo dependency, Consumer<Runnable> postPopulationScheduler) throws Exception {
+ forge = new File(getExtension().getProjectPersistentCache(), "forge-" + dependency.getDependency().getVersion() + ".jar");
+
+ if (!forge.exists() || isRefreshDeps()) {
+ File dep = dependency.resolveFile().orElseThrow(() -> new IllegalStateException("Could not resolve Forge"));
+ Files.copy(dep, forge);
+ }
+ }
+
+ public File getForge() {
+ return forge;
+ }
+
+ @Override
+ public String getTargetConfig() {
+ return Constants.FORGE_UNIVERSAL;
+ }
+}
diff --git a/src/main/java/net/fabricmc/loom/providers/McpConfigProvider.java b/src/main/java/net/fabricmc/loom/providers/McpConfigProvider.java
index 4f4ef091..446bf29d 100644
--- a/src/main/java/net/fabricmc/loom/providers/McpConfigProvider.java
+++ b/src/main/java/net/fabricmc/loom/providers/McpConfigProvider.java
@@ -30,6 +30,7 @@ import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
import java.util.function.Consumer;
import com.google.common.collect.ImmutableMap;
@@ -50,19 +51,19 @@ public class McpConfigProvider extends DependencyProvider {
public void provide(DependencyInfo dependency, Consumer<Runnable> postPopulationScheduler) throws Exception {
init(dependency.getDependency().getVersion());
- if (mcp.exists() && srg.exists()) {
+ if (mcp.exists() && srg.exists() && !isRefreshDeps()) {
return; // No work for us to do here
}
Path mcpZip = dependency.resolveFile().orElseThrow(() -> new IllegalStateException("Could not resolve MCPConfig")).toPath();
- if (!mcp.exists()) {
- Files.copy(mcpZip, mcp.toPath());
+ if (!mcp.exists() || isRefreshDeps()) {
+ Files.copy(mcpZip, mcp.toPath(), StandardCopyOption.REPLACE_EXISTING);
}
- if (!srg.exists()) {
+ if (!srg.exists() || isRefreshDeps()) {
try (FileSystem fs = FileSystems.newFileSystem(new URI("jar:" + mcpZip.toUri()), ImmutableMap.of("create", false))) {
- Files.copy(fs.getPath("config", "joined.tsrg"), srg.toPath());
+ Files.copy(fs.getPath("config", "joined.tsrg"), srg.toPath(), StandardCopyOption.REPLACE_EXISTING);
}
}
}
diff --git a/src/main/java/net/fabricmc/loom/providers/MinecraftProvider.java b/src/main/java/net/fabricmc/loom/providers/MinecraftProvider.java
index bcc32a55..eef3f6f1 100644
--- a/src/main/java/net/fabricmc/loom/providers/MinecraftProvider.java
+++ b/src/main/java/net/fabricmc/loom/providers/MinecraftProvider.java
@@ -39,6 +39,7 @@ import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.Optional;
import java.util.function.Consumer;
+import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import java.util.zip.ZipError;
@@ -61,6 +62,7 @@ import org.gradle.api.logging.Logger;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.DependencyProvider;
import net.fabricmc.loom.util.DownloadUtil;
+import net.fabricmc.loom.util.FsPathConsumer;
import net.fabricmc.loom.util.IoConsumer;
import net.fabricmc.loom.util.ManifestVersion;
import net.fabricmc.loom.util.MinecraftVersionInfo;
@@ -289,6 +291,10 @@ public class MinecraftProvider extends DependencyProvider {
PatchProvider patchProvider = getExtension().getPatchProvider();
patchJars(minecraftClientSrgJar, minecraftClientPatchedSrgJar, patchProvider.clientPatches);
patchJars(minecraftServerSrgJar, minecraftServerPatchedSrgJar, patchProvider.serverPatches);
+
+ logger.lifecycle(":copying missing classes into patched jars");
+ copyMissingClasses(minecraftClientSrgJar, minecraftClientPatchedSrgJar);
+ copyMissingClasses(minecraftServerSrgJar, minecraftServerPatchedSrgJar);
}
private void patchJars(File clean, File output, Path patches) throws IOException {
@@ -311,29 +317,25 @@ public class MinecraftProvider extends DependencyProvider {
copyNonClassFiles(minecraftClientJar, minecraftMergedJar);
copyNonClassFiles(minecraftServerJar, minecraftMergedJar);
+ logger.lifecycle(":adding forge classes");
+ copyAll(getExtension().getForgeUniversalProvider().getForge(), minecraftMergedJar);
+
/*try (JarMerger jarMerger = new JarMerger(minecraftClientPatchedJar, minecraftServerPatchedJar, minecraftMergedJar)) {
jarMerger.enableSyntheticParamsOffset();
jarMerger.merge();
}*/
}
- private void copyNonClassFiles(File source, File target) throws IOException {
+ private void walkFileSystems(File source, File target, Predicate<Path> filter, FsPathConsumer action) throws IOException {
try (FileSystem sourceFs = FileSystems.newFileSystem(new URI("jar:" + source.toURI()), ImmutableMap.of("create", false));
FileSystem targetFs = FileSystems.newFileSystem(new URI("jar:" + target.toURI()), ImmutableMap.of("create", false))) {
for (Path rootDirectory : sourceFs.getRootDirectories()) {
java.nio.file.Files.walk(rootDirectory)
.filter(java.nio.file.Files::isRegularFile)
- .filter(it -> !it.toString().endsWith(".class"))
+ .filter(filter)
.forEach(it -> {
try {
- Path targetFile = targetFs.getPath(it.toString());
- Path parent = targetFile.getParent();
-
- if (parent != null) {
- java.nio.file.Files.createDirectories(parent);
- }
-
- java.nio.file.Files.copy(it, targetFile, StandardCopyOption.REPLACE_EXISTING);
+ action.accept(sourceFs, targetFs, it);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
@@ -344,6 +346,40 @@ public class MinecraftProvider extends DependencyProvider {
}
}
+ private void copyAll(File source, File target) throws IOException {
+ walkFileSystems(source, target, it -> true, this::copyReplacing);
+ }
+
+ private void copyMissingClasses(File source, File target) throws IOException {
+ walkFileSystems(source, target, it -> it.toString().endsWith(".class"), (sourceFs, targetFs, it) -> {
+ Path targetFile = targetFs.getPath(it.toString());
+
+ if (java.nio.file.Files.exists(targetFile)) return;
+ Path parent = targetFile.getParent();
+
+ if (parent != null) {
+ java.nio.file.Files.createDirectories(parent);
+ }
+
+ java.nio.file.Files.copy(it, targetFile);
+ });
+ }
+
+ private void copyNonClassFiles(File source, File target) throws IOException {
+ walkFileSystems(source, target, it -> !it.toString().endsWith(".class"), this::copyReplacing);
+ }
+
+ private void copyReplacing(FileSystem sourceFs, FileSystem targetFs, Path it) throws IOException {
+ Path targetFile = targetFs.getPath(it.toString());
+ Path parent = targetFile.getParent();
+
+ if (parent != null) {
+ java.nio.file.Files.createDirectories(parent);
+ }
+
+ java.nio.file.Files.copy(it, targetFile, StandardCopyOption.REPLACE_EXISTING);
+ }
+
public File getMergedJar() {
return minecraftMergedJar;
}
diff --git a/src/main/java/net/fabricmc/loom/providers/PatchProvider.java b/src/main/java/net/fabricmc/loom/providers/PatchProvider.java
index b8ba9d72..14a6a6c3 100644
--- a/src/main/java/net/fabricmc/loom/providers/PatchProvider.java
+++ b/src/main/java/net/fabricmc/loom/providers/PatchProvider.java
@@ -29,6 +29,7 @@ import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
import java.util.function.Consumer;
import com.google.common.collect.ImmutableMap;
@@ -50,14 +51,14 @@ public class PatchProvider extends DependencyProvider {
public void provide(DependencyInfo dependency, Consumer<Runnable> postPopulationScheduler) throws Exception {
init(dependency.getDependency().getVersion());
- if (Files.notExists(clientPatches) || Files.notExists(serverPatches)) {
+ if (Files.notExists(clientPatches) || Files.notExists(serverPatches) || isRefreshDeps()) {
getProject().getLogger().info(":extracting forge patches");
Path installerJar = dependency.resolveFile().orElseThrow(() -> new IllegalStateException("Could not resolve Forge installer")).toPath();
try (FileSystem fs = FileSystems.newFileSystem(new URI("jar:" + installerJar.toUri()), ImmutableMap.of("create", false))) {
- Files.copy(fs.getPath("data", "client.lzma"), clientPatches);
- Files.copy(fs.getPath("data", "server.lzma"), serverPatches);
+ Files.copy(fs.getPath("data", "client.lzma"), clientPatches, StandardCopyOption.REPLACE_EXISTING);
+ Files.copy(fs.getPath("data", "server.lzma"), serverPatches, StandardCopyOption.REPLACE_EXISTING);
}
}
}
@@ -70,6 +71,6 @@ public class PatchProvider extends DependencyProvider {
@Override
public String getTargetConfig() {
- return Constants.FORGE;
+ return Constants.FORGE_INSTALLER;
}
}
diff --git a/src/main/java/net/fabricmc/loom/util/Constants.java b/src/main/java/net/fabricmc/loom/util/Constants.java
index 755a670d..eca63879 100644
--- a/src/main/java/net/fabricmc/loom/util/Constants.java
+++ b/src/main/java/net/fabricmc/loom/util/Constants.java
@@ -55,6 +55,8 @@ public class Constants {
public static final String MAPPINGS_FINAL = "mappingsFinal";
public static final String MCP_CONFIG = "mcp";
public static final String FORGE = "forge";
+ public static final String FORGE_INSTALLER = "forgeInstaller";
+ public static final String FORGE_UNIVERSAL = "forgeUniversal";
public static final String MIXIN_COMPILE_EXTENSIONS_VERSION = "0.3.1.5";
public static final String DEV_LAUNCH_INJECTOR_VERSION = "0.2.1+build.8";
diff --git a/src/main/java/net/fabricmc/loom/util/FsPathConsumer.java b/src/main/java/net/fabricmc/loom/util/FsPathConsumer.java
new file mode 100644
index 00000000..6e1eeb2b
--- /dev/null
+++ b/src/main/java/net/fabricmc/loom/util/FsPathConsumer.java
@@ -0,0 +1,39 @@
+/*
+ * This file is part of fabric-loom, licensed under the MIT License (MIT).
+ *
+ * Copyright (c) 2016, 2017, 2018 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.
+ */
+
+package net.fabricmc.loom.util;
+
+import java.io.IOException;
+import java.nio.file.FileSystem;
+import java.nio.file.Path;
+
+/**
+ * Like Consumer, but can throw IOException and gets access to two file systems.
+ *
+ * @author Juuz
+ */
+@FunctionalInterface
+public interface FsPathConsumer {
+ void accept(FileSystem sourceFs, FileSystem targetFs, Path path) throws IOException;
+}