mirror of
https://github.com/architectury/architectury-loom.git
synced 2026-04-02 13:37:45 -05:00
Fix setup errors + Multi-thread forge patching more.
This commit is contained in:
@@ -57,10 +57,9 @@ import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Locale;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
@@ -220,8 +219,11 @@ public class MinecraftPatchedProvider extends DependencyProvider {
|
||||
File specialSourceJar = new File(getExtension().getUserCache(), "SpecialSource-1.8.3-shaded.jar");
|
||||
DownloadUtil.downloadIfChanged(new URL("https://repo1.maven.org/maven2/net/md-5/SpecialSource/1.8.3/SpecialSource-1.8.3-shaded.jar"), specialSourceJar, getProject().getLogger(), true);
|
||||
|
||||
Files.copy(SpecialSourceExecutor.produceSrgJar(getProject(), specialSourceJar,minecraftProvider.minecraftClientJar.toPath(), tmpSrg[0]), minecraftClientSrgJar.toPath());
|
||||
Files.copy(SpecialSourceExecutor.produceSrgJar(getProject(), specialSourceJar, minecraftProvider.minecraftServerJar.toPath(), tmpSrg[0]), minecraftServerSrgJar.toPath());
|
||||
ThreadingUtils.run(() -> {
|
||||
Files.copy(SpecialSourceExecutor.produceSrgJar(getProject(), specialSourceJar, minecraftProvider.minecraftClientJar.toPath(), tmpSrg[0]), minecraftClientSrgJar.toPath());
|
||||
}, () -> {
|
||||
Files.copy(SpecialSourceExecutor.produceSrgJar(getProject(), specialSourceJar, minecraftProvider.minecraftServerJar.toPath(), tmpSrg[0]), minecraftServerSrgJar.toPath());
|
||||
});
|
||||
}
|
||||
|
||||
private void fixParameterAnnotation(File jarFile) throws Exception {
|
||||
@@ -250,11 +252,13 @@ public class MinecraftPatchedProvider extends DependencyProvider {
|
||||
|
||||
private void injectForgeClasses(Logger logger) throws IOException {
|
||||
logger.lifecycle(":injecting forge classes into minecraft");
|
||||
copyAll(getExtension().getForgeUniversalProvider().getForge(), minecraftClientPatchedSrgJar);
|
||||
copyAll(getExtension().getForgeUniversalProvider().getForge(), minecraftServerPatchedSrgJar);
|
||||
|
||||
copyUserdevFiles(getExtension().getForgeUserdevProvider().getUserdevJar(), minecraftClientPatchedSrgJar);
|
||||
copyUserdevFiles(getExtension().getForgeUserdevProvider().getUserdevJar(), minecraftServerPatchedSrgJar);
|
||||
ThreadingUtils.run(() -> {
|
||||
copyAll(getExtension().getForgeUniversalProvider().getForge(), minecraftClientPatchedSrgJar);
|
||||
copyUserdevFiles(getExtension().getForgeUserdevProvider().getUserdevJar(), minecraftClientPatchedSrgJar);
|
||||
}, () -> {
|
||||
copyAll(getExtension().getForgeUniversalProvider().getForge(), minecraftServerPatchedSrgJar);
|
||||
copyUserdevFiles(getExtension().getForgeUserdevProvider().getUserdevJar(), minecraftServerPatchedSrgJar);
|
||||
});
|
||||
|
||||
logger.lifecycle(":injecting loom classes into minecraft");
|
||||
File injection = File.createTempFile("loom-injection", ".jar");
|
||||
@@ -263,13 +267,12 @@ public class MinecraftPatchedProvider extends DependencyProvider {
|
||||
FileUtils.copyInputStreamToFile(in, injection);
|
||||
}
|
||||
|
||||
walkFileSystems(injection, minecraftClientPatchedSrgJar, it -> !it.getFileName().toString().equals("MANIFEST.MF"), this::copyReplacing);
|
||||
walkFileSystems(injection, minecraftServerPatchedSrgJar, it -> !it.getFileName().toString().equals("MANIFEST.MF"), this::copyReplacing);
|
||||
|
||||
logger.lifecycle(":access transforming minecraft");
|
||||
for (Environment environment : Environment.values()) {
|
||||
ThreadingUtils.run(Arrays.asList(Environment.values()), environment -> {
|
||||
String side = environment.side();
|
||||
File target = environment.patchedSrgJar.apply(this);
|
||||
walkFileSystems(injection, target, it -> !it.getFileName().toString().equals("MANIFEST.MF"), this::copyReplacing);
|
||||
|
||||
logger.lifecycle(":access transforming minecraft (" + side + ")");
|
||||
|
||||
File atJar = File.createTempFile("at" + side, ".jar");
|
||||
File at = File.createTempFile("at" + side, ".cfg");
|
||||
@@ -288,7 +291,7 @@ public class MinecraftPatchedProvider extends DependencyProvider {
|
||||
}
|
||||
|
||||
TransformerProcessor.main(args);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private enum Environment {
|
||||
@@ -317,63 +320,49 @@ public class MinecraftPatchedProvider extends DependencyProvider {
|
||||
.map(File::toPath)
|
||||
.toArray(Path[]::new);
|
||||
|
||||
ExecutorService service = Executors.newFixedThreadPool(2);
|
||||
List<Future<?>> futures = new LinkedList<>();
|
||||
ThreadingUtils.run(Arrays.asList(Environment.values()), environment -> {
|
||||
logger.lifecycle(":remapping minecraft (TinyRemapper, " + environment.side() + ", srg -> official)");
|
||||
TinyTree mappingsWithSrg = getExtension().getMappingsProvider().getMappingsWithSrg();
|
||||
|
||||
for (Environment environment : Environment.values()) {
|
||||
futures.add(service.submit(() -> {
|
||||
try {
|
||||
logger.lifecycle(":remapping minecraft (TinyRemapper, " + environment.side() + ", srg -> official)");
|
||||
TinyTree mappingsWithSrg = getExtension().getMappingsProvider().getMappingsWithSrg();
|
||||
Path input = environment.patchedSrgJar.apply(this).toPath();
|
||||
Path output = environment.patchedOfficialJar.apply(this).toPath();
|
||||
|
||||
Path input = environment.patchedSrgJar.apply(this).toPath();
|
||||
Path output = environment.patchedOfficialJar.apply(this).toPath();
|
||||
Files.deleteIfExists(output);
|
||||
|
||||
Files.deleteIfExists(output);
|
||||
TinyRemapper remapper = TinyRemapper.newRemapper()
|
||||
.withMappings(TinyRemapperMappingsHelper.create(mappingsWithSrg, "srg", "official", true))
|
||||
.withMappings(InnerClassRemapper.of(input, mappingsWithSrg, "srg", "official"))
|
||||
.renameInvalidLocals(true)
|
||||
.rebuildSourceFilenames(true)
|
||||
.fixPackageAccess(true)
|
||||
.build();
|
||||
|
||||
TinyRemapper remapper = TinyRemapper.newRemapper()
|
||||
.withMappings(TinyRemapperMappingsHelper.create(mappingsWithSrg, "srg", "official", true))
|
||||
.withMappings(InnerClassRemapper.of(input, mappingsWithSrg, "srg", "official"))
|
||||
.renameInvalidLocals(true)
|
||||
.rebuildSourceFilenames(true)
|
||||
.fixPackageAccess(true)
|
||||
.build();
|
||||
try (OutputConsumerPath outputConsumer = new OutputConsumerPath.Builder(output).build()) {
|
||||
outputConsumer.addNonClassFiles(input);
|
||||
|
||||
try (OutputConsumerPath outputConsumer = new OutputConsumerPath.Builder(output).build()) {
|
||||
outputConsumer.addNonClassFiles(input);
|
||||
|
||||
remapper.readClassPath(libraries);
|
||||
remapper.readInputs(input);
|
||||
remapper.apply(outputConsumer);
|
||||
} finally {
|
||||
remapper.finish();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
for (Future<?> future : futures) {
|
||||
future.get();
|
||||
}
|
||||
remapper.readClassPath(libraries);
|
||||
remapper.readInputs(input);
|
||||
remapper.apply(outputConsumer);
|
||||
} finally {
|
||||
remapper.finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private void patchJars(Logger logger) throws Exception {
|
||||
private void patchJars(Logger logger) throws IOException {
|
||||
logger.lifecycle(":patching jars");
|
||||
|
||||
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);
|
||||
|
||||
logger.lifecycle(":fixing parameter annotations for patched jars");
|
||||
fixParameterAnnotation(minecraftClientPatchedSrgJar);
|
||||
fixParameterAnnotation(minecraftServerPatchedSrgJar);
|
||||
ThreadingUtils.run(() -> {
|
||||
copyMissingClasses(minecraftClientSrgJar, minecraftClientPatchedSrgJar);
|
||||
fixParameterAnnotation(minecraftClientPatchedSrgJar);
|
||||
}, () -> {
|
||||
copyMissingClasses(minecraftServerSrgJar, minecraftServerPatchedSrgJar);
|
||||
fixParameterAnnotation(minecraftServerPatchedSrgJar);
|
||||
});
|
||||
}
|
||||
|
||||
private void patchJars(File clean, File output, Path patches) throws IOException {
|
||||
@@ -407,9 +396,9 @@ public class MinecraftPatchedProvider extends DependencyProvider {
|
||||
|
||||
private void walkFileSystems(File source, File target, Predicate<Path> filter, Function<FileSystem, Iterable<Path>> toWalk, 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 sourceDir : toWalk.apply(sourceFs)) {
|
||||
try (FileSystemUtil.FileSystemDelegate sourceFs = FileSystemUtil.getJarFileSystem(source, false);
|
||||
FileSystemUtil.FileSystemDelegate targetFs = FileSystemUtil.getJarFileSystem(target, false)) {
|
||||
for (Path sourceDir : toWalk.apply(sourceFs.get())) {
|
||||
Path dir = sourceDir.toAbsolutePath();
|
||||
Files.walk(dir)
|
||||
.filter(Files::isRegularFile)
|
||||
@@ -419,15 +408,13 @@ public class MinecraftPatchedProvider extends DependencyProvider {
|
||||
|
||||
try {
|
||||
Path relativeSource = root ? it : dir.relativize(it);
|
||||
Path targetPath = targetFs.getPath(relativeSource.toString());
|
||||
action.accept(sourceFs, targetFs, it, targetPath);
|
||||
Path targetPath = targetFs.get().getPath(relativeSource.toString());
|
||||
action.accept(sourceFs.get(), targetFs.get(), it, targetPath);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (URISyntaxException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
84
src/main/java/net/fabricmc/loom/util/FileSystemUtil.java
Normal file
84
src/main/java/net/fabricmc/loom/util/FileSystemUtil.java
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2016 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystemAlreadyExistsException;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
|
||||
public final class FileSystemUtil {
|
||||
public static class FileSystemDelegate implements AutoCloseable {
|
||||
private final FileSystem fileSystem;
|
||||
private final boolean owner;
|
||||
|
||||
public FileSystemDelegate(FileSystem fileSystem, boolean owner) {
|
||||
this.fileSystem = fileSystem;
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public FileSystem get() {
|
||||
return fileSystem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (owner) {
|
||||
fileSystem.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private FileSystemUtil() {
|
||||
|
||||
}
|
||||
|
||||
private static final Map<String, String> jfsArgsCreate = new HashMap<>();
|
||||
private static final Map<String, String> jfsArgsEmpty = new HashMap<>();
|
||||
|
||||
static {
|
||||
jfsArgsCreate.put("create", "true");
|
||||
}
|
||||
|
||||
public static FileSystemDelegate getJarFileSystem(File file, boolean create) throws IOException {
|
||||
return getJarFileSystem(file.toURI(), create);
|
||||
}
|
||||
|
||||
public static FileSystemDelegate getJarFileSystem(Path path, boolean create) throws IOException {
|
||||
return getJarFileSystem(path.toUri(), create);
|
||||
}
|
||||
|
||||
public static FileSystemDelegate getJarFileSystem(URI uri, boolean create) throws IOException {
|
||||
URI jarUri;
|
||||
try {
|
||||
jarUri = new URI("jar:" + uri.getScheme(), uri.getHost(), uri.getPath(), uri.getFragment());
|
||||
} catch (URISyntaxException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
|
||||
try {
|
||||
return new FileSystemDelegate(FileSystems.newFileSystem(jarUri, create ? jfsArgsCreate : jfsArgsEmpty), true);
|
||||
} catch (FileSystemAlreadyExistsException e) {
|
||||
return new FileSystemDelegate(FileSystems.getFileSystem(jarUri), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
91
src/main/java/net/fabricmc/loom/util/ThreadingUtils.java
Normal file
91
src/main/java/net/fabricmc/loom/util/ThreadingUtils.java
Normal file
@@ -0,0 +1,91 @@
|
||||
package net.fabricmc.loom.util;
|
||||
|
||||
import org.gradle.internal.impldep.com.google.api.client.repackaged.com.google.common.base.Function;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ThreadingUtils {
|
||||
public static <T> void run(Collection<T> values, UnsafeConsumer<T> action) {
|
||||
run(values.stream()
|
||||
.<UnsafeRunnable>map(t -> () -> action.accept(t))
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
public static void run(UnsafeRunnable... jobs) {
|
||||
run(Arrays.asList(jobs));
|
||||
}
|
||||
|
||||
public static void run(Collection<UnsafeRunnable> jobs) {
|
||||
try {
|
||||
ExecutorService service = Executors.newFixedThreadPool(Math.min(jobs.size(), Runtime.getRuntime().availableProcessors() / 2));
|
||||
List<Future<?>> futures = new LinkedList<>();
|
||||
for (UnsafeRunnable runnable : jobs) {
|
||||
futures.add(service.submit(() -> {
|
||||
try {
|
||||
runnable.run();
|
||||
} catch (Throwable throwable) {
|
||||
throw new RuntimeException(throwable);
|
||||
}
|
||||
}));
|
||||
}
|
||||
for (Future<?> future : futures) {
|
||||
future.get();
|
||||
}
|
||||
service.shutdownNow();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T, R> List<R> get(Collection<T> values, Function<T, R> action) {
|
||||
return get(values.stream()
|
||||
.<UnsafeCallable<R>>map(t -> () -> action.apply(t))
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public static <T> List<T> get(UnsafeCallable<T>... jobs) {
|
||||
return get(Arrays.asList(jobs));
|
||||
}
|
||||
|
||||
public static <T> List<T> get(Collection<UnsafeCallable<T>> jobs) {
|
||||
try {
|
||||
ExecutorService service = Executors.newFixedThreadPool(Math.min(jobs.size(), Runtime.getRuntime().availableProcessors() / 2));
|
||||
List<Future<T>> futures = new LinkedList<>();
|
||||
for (UnsafeCallable<T> runnable : jobs) {
|
||||
futures.add(service.submit(() -> {
|
||||
try {
|
||||
return runnable.call();
|
||||
} catch (Throwable throwable) {
|
||||
throw new RuntimeException(throwable);
|
||||
}
|
||||
}));
|
||||
}
|
||||
List<T> result = new ArrayList<>();
|
||||
for (Future<T> future : futures) {
|
||||
result.add(future.get());
|
||||
}
|
||||
service.shutdownNow();
|
||||
return result;
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public interface UnsafeRunnable {
|
||||
void run() throws Throwable;
|
||||
}
|
||||
|
||||
public interface UnsafeCallable<T> {
|
||||
T call() throws Throwable;
|
||||
}
|
||||
|
||||
public interface UnsafeConsumer<T> {
|
||||
void accept(T value) throws Throwable;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package net.fabricmc.loom.util.srg;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.gradle.api.Project;
|
||||
@@ -10,13 +9,15 @@ import org.zeroturnaround.zip.ZipUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.jar.JarOutputStream;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
public class SpecialSourceExecutor {
|
||||
public static Path produceSrgJar(Project project, File specialSourceJar, Path officialJar, Path srgPath) throws Exception {
|
||||
@@ -24,16 +25,14 @@ public class SpecialSourceExecutor {
|
||||
.filter(s -> !s.startsWith("\t"))
|
||||
.map(s -> s.split(" ")[0] + ".class")
|
||||
.collect(Collectors.toSet());
|
||||
Path stripped = project.getExtensions().getByType(LoomGradleExtension.class).getProjectBuildCache().toPath().resolve(officialJar.getFileName().toString().substring(0, officialJar.getFileName().toString().length() - 3) + "-filtered.jar");
|
||||
Path stripped = project.getExtensions().getByType(LoomGradleExtension.class).getProjectBuildCache().toPath().resolve(officialJar.getFileName().toString().substring(0, officialJar.getFileName().toString().length() - 4) + "-filtered.jar");
|
||||
Files.deleteIfExists(stripped);
|
||||
try (FileSystem strippedFs = FileSystems.newFileSystem(URI.create("jar:" + stripped.toUri()), ImmutableMap.of("create", true))) {
|
||||
try (JarOutputStream output = new JarOutputStream(Files.newOutputStream(stripped))) {
|
||||
ZipUtil.iterate(officialJar.toFile(), (in, zipEntry) -> {
|
||||
if (filter.contains(zipEntry.getName())) {
|
||||
Path path = strippedFs.getPath(zipEntry.getName());
|
||||
if (path.getParent() != null) {
|
||||
Files.createDirectories(path.getParent());
|
||||
}
|
||||
Files.write(path, IOUtils.toByteArray(in), StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW);
|
||||
output.putNextEntry((ZipEntry) zipEntry.clone());
|
||||
IOUtils.write(IOUtils.toByteArray(in), output);
|
||||
output.closeEntry();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user