mirror of
https://github.com/architectury/architectury-loom.git
synced 2026-04-03 05:57:42 -05:00
Merge remote-tracking branch 'architectury/dev/0.7-forge' into dev/future
This commit is contained in:
@@ -61,6 +61,7 @@ import net.fabricmc.loom.configuration.launch.LaunchProviderSettings;
|
||||
import net.fabricmc.loom.configuration.processors.JarProcessor;
|
||||
import net.fabricmc.loom.configuration.processors.JarProcessorManager;
|
||||
import net.fabricmc.loom.configuration.providers.MinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.forge.FieldMigratedMappingsProvider;
|
||||
import net.fabricmc.loom.configuration.providers.forge.ForgeProvider;
|
||||
import net.fabricmc.loom.configuration.providers.forge.ForgeUniversalProvider;
|
||||
import net.fabricmc.loom.configuration.providers.forge.ForgeUserdevProvider;
|
||||
@@ -392,7 +393,7 @@ public class LoomGradleExtension {
|
||||
}
|
||||
|
||||
public MappingsProvider getMappingsProvider() {
|
||||
return getDependencyManager().getProvider(MappingsProvider.class);
|
||||
return getDependencyManager().getProvider(isForge() ? FieldMigratedMappingsProvider.class : MappingsProvider.class);
|
||||
}
|
||||
|
||||
public McpConfigProvider getMcpConfigProvider() {
|
||||
|
||||
@@ -57,7 +57,7 @@ public class LoomGradlePlugin implements Plugin<Project> {
|
||||
project.getLogger().lifecycle("Architectury Loom: " + loomVersion);
|
||||
}
|
||||
|
||||
refreshDeps = project.getGradle().getStartParameter().isRefreshDependencies();
|
||||
refreshDeps = project.getGradle().getStartParameter().isRefreshDependencies() || "true".equals(System.getProperty("loom.refresh"));
|
||||
|
||||
if (refreshDeps) {
|
||||
MappingsCache.INSTANCE.invalidate();
|
||||
|
||||
@@ -133,6 +133,11 @@ public class ModCompileRemapper {
|
||||
File input = artifact.getFile();
|
||||
|
||||
try (ZipFile zipFile = new ZipFile(input)) {
|
||||
if (zipFile.getEntry("architectury.common.marker") != null) {
|
||||
logger.info("Found architectury common mod in " + config + ": {}", artifact.getId());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (forge) {
|
||||
if (zipFile.getEntry("META-INF/mods.toml") != null) {
|
||||
logger.info("Found Forge mod in " + config + ": {}", artifact.getId());
|
||||
|
||||
@@ -1,3 +1,27 @@
|
||||
/*
|
||||
* 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.build.nesting;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@@ -40,6 +40,7 @@ import net.fabricmc.loom.build.mixin.ScalaApInvoker;
|
||||
import net.fabricmc.loom.configuration.ide.SetupIntelijRunConfigs;
|
||||
import net.fabricmc.loom.configuration.providers.LaunchProvider;
|
||||
import net.fabricmc.loom.configuration.providers.MinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.forge.FieldMigratedMappingsProvider;
|
||||
import net.fabricmc.loom.configuration.providers.forge.ForgeProvider;
|
||||
import net.fabricmc.loom.configuration.providers.forge.ForgeUniversalProvider;
|
||||
import net.fabricmc.loom.configuration.providers.forge.ForgeUserdevProvider;
|
||||
@@ -177,7 +178,7 @@ public final class CompileConfiguration {
|
||||
dependencyManager.addProvider(new ForgeUniversalProvider(project));
|
||||
}
|
||||
|
||||
dependencyManager.addProvider(new MappingsProvider(project));
|
||||
dependencyManager.addProvider(extension.isForge() ? new FieldMigratedMappingsProvider(project) : new MappingsProvider(project));
|
||||
dependencyManager.addProvider(new LaunchProvider(project));
|
||||
|
||||
dependencyManager.handleDependencies(project);
|
||||
|
||||
@@ -72,7 +72,7 @@ public class LoomDependencyManager {
|
||||
return provider;
|
||||
}
|
||||
|
||||
public <T> T getProvider(Class<T> clazz) {
|
||||
public <T> T getProvider(Class<? extends T> clazz) {
|
||||
for (DependencyProvider provider : dependencyProviderList) {
|
||||
if (provider.getClass() == clazz) {
|
||||
return (T) provider;
|
||||
@@ -140,7 +140,7 @@ public class LoomDependencyManager {
|
||||
String platformSuffix = extension.isForge() ? "_forge" : "";
|
||||
String mappingsKey = mappingsProvider.getMappingsKey() + platformSuffix;
|
||||
|
||||
if (extension.getInstallerJson() == null) {
|
||||
if (extension.getInstallerJson() == null && !extension.isForge()) {
|
||||
//If we've not found the installer JSON we've probably skipped remapping Fabric loader, let's go looking
|
||||
project.getLogger().info("Searching through modCompileClasspath for installer JSON");
|
||||
final Configuration configuration = project.getConfigurations().getByName(Constants.Configurations.MOD_COMPILE_CLASSPATH);
|
||||
@@ -159,10 +159,10 @@ public class LoomDependencyManager {
|
||||
handleInstallerJson(extension.getInstallerJson(), project);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (extension.getInstallerJson() == null && !extension.isForge()) {
|
||||
project.getLogger().warn("fabric-installer.json not found in classpath!");
|
||||
if (extension.getInstallerJson() == null) {
|
||||
project.getLogger().warn("fabric-installer.json not found in classpath!");
|
||||
}
|
||||
}
|
||||
|
||||
ModCompileRemapper.remapDependencies(project, mappingsKey, extension, sourceRemapper);
|
||||
|
||||
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
* 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.configuration.providers.forge;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.AbstractMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.google.common.collect.HashBasedTable;
|
||||
import com.google.common.collect.Table;
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.google.gson.Gson;
|
||||
import dev.architectury.mappingslayers.api.mutable.MappingsEntry;
|
||||
import dev.architectury.mappingslayers.api.mutable.MutableClassDef;
|
||||
import dev.architectury.mappingslayers.api.mutable.MutableFieldDef;
|
||||
import dev.architectury.mappingslayers.api.mutable.MutableTinyTree;
|
||||
import dev.architectury.mappingslayers.api.utils.MappingsUtils;
|
||||
import dev.architectury.refmapremapper.utils.DescriptorRemapper;
|
||||
import org.gradle.api.Project;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
import org.objectweb.asm.FieldVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.LoomGradlePlugin;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider;
|
||||
import net.fabricmc.loom.util.FileSystemUtil;
|
||||
import net.fabricmc.loom.util.ThreadingUtils;
|
||||
import net.fabricmc.loom.util.srg.SrgMerger;
|
||||
import net.fabricmc.mapping.tree.ClassDef;
|
||||
import net.fabricmc.mapping.tree.FieldDef;
|
||||
import net.fabricmc.mapping.tree.TinyMappingFactory;
|
||||
import net.fabricmc.mapping.tree.TinyTree;
|
||||
|
||||
public class FieldMigratedMappingsProvider extends MappingsProvider {
|
||||
private List<Map.Entry<FieldMember, String>> migratedFields = new ArrayList<>();
|
||||
public Path migratedFieldsCache;
|
||||
public Path rawTinyMappings;
|
||||
public Path rawTinyMappingsWithSrg;
|
||||
|
||||
public FieldMigratedMappingsProvider(Project project) {
|
||||
super(project);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void provide(DependencyInfo dependency, Consumer<Runnable> postPopulationScheduler) throws Exception {
|
||||
LoomGradleExtension extension = getExtension();
|
||||
PatchProvider patchProvider = getExtension().getPatchProvider();
|
||||
migratedFieldsCache = patchProvider.getProjectCacheFolder().resolve("migrated-fields.json");
|
||||
migratedFields.clear();
|
||||
|
||||
if (LoomGradlePlugin.refreshDeps) {
|
||||
Files.deleteIfExists(migratedFieldsCache);
|
||||
} else if (Files.exists(migratedFieldsCache)) {
|
||||
try (BufferedReader reader = Files.newBufferedReader(migratedFieldsCache)) {
|
||||
Map<String, String> map = new Gson().fromJson(reader, new TypeToken<Map<String, String>>() {
|
||||
}.getType());
|
||||
migratedFields = new ArrayList<>();
|
||||
map.forEach((key, newDescriptor) -> {
|
||||
String[] split = key.split("#");
|
||||
migratedFields.add(new AbstractMap.SimpleEntry<>(new FieldMember(split[0], split[1]), newDescriptor));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
super.provide(dependency, postPopulationScheduler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void manipulateMappings(Path mappingsJar) throws IOException {
|
||||
LoomGradleExtension extension = getExtension();
|
||||
Path mappingsFolder = mappingsDir.resolve(extension.getMinecraftProvider().getMinecraftVersion() + "/forge-" + extension.getPatchProvider().forgeVersion);
|
||||
this.rawTinyMappings = tinyMappings.toPath();
|
||||
this.rawTinyMappingsWithSrg = tinyMappingsWithSrg;
|
||||
String mappingsJarName = mappingsJar.getFileName().toString();
|
||||
|
||||
if (getExtension().shouldGenerateSrgTiny()) {
|
||||
if (Files.notExists(rawTinyMappingsWithSrg) || isRefreshDeps()) {
|
||||
// Merge tiny mappings with srg
|
||||
SrgMerger.mergeSrg(getExtension().getSrgProvider().getSrg().toPath(), rawTinyMappings, rawTinyMappingsWithSrg, true);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Files.createDirectories(mappingsFolder);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
|
||||
tinyMappings = mappingsFolder.resolve("mappings.tiny").toFile();
|
||||
tinyMappingsJar = mappingsFolder.resolve("mappings.jar").toFile();
|
||||
tinyMappingsWithSrg = mappingsFolder.resolve("mappings-srg.tiny");
|
||||
mixinTinyMappingsWithSrg = mappingsFolder.resolve("mixin-srg.tiny").toFile();
|
||||
srgToNamedSrg = mappingsFolder.resolve("srg-to-named.srg").toFile();
|
||||
|
||||
try {
|
||||
updateFieldMigration();
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateFieldMigration() throws IOException {
|
||||
if (!Files.exists(migratedFieldsCache)) {
|
||||
generateNewFieldMigration();
|
||||
Map<String, String> map = new HashMap<>();
|
||||
migratedFields.forEach(entry -> {
|
||||
map.put(entry.getKey().owner + "#" + entry.getKey().field, entry.getValue());
|
||||
});
|
||||
Files.write(migratedFieldsCache, new Gson().toJson(map).getBytes(StandardCharsets.UTF_8));
|
||||
Files.deleteIfExists(tinyMappings.toPath());
|
||||
}
|
||||
|
||||
if (!Files.exists(tinyMappings.toPath())) {
|
||||
Table<String, String, String> fieldDescriptorMap = HashBasedTable.create();
|
||||
|
||||
for (Map.Entry<FieldMember, String> entry : migratedFields) {
|
||||
fieldDescriptorMap.put(entry.getKey().owner, entry.getKey().field, entry.getValue());
|
||||
}
|
||||
|
||||
MutableTinyTree mappings;
|
||||
|
||||
try (BufferedReader reader = Files.newBufferedReader(rawTinyMappings)) {
|
||||
mappings = MappingsUtils.copyAsMutable(TinyMappingFactory.loadWithDetection(reader));
|
||||
|
||||
for (MutableClassDef classDef : mappings.getClassesMutable()) {
|
||||
Map<String, String> row = fieldDescriptorMap.row(classDef.getIntermediary());
|
||||
|
||||
if (!row.isEmpty()) {
|
||||
for (MutableFieldDef fieldDef : classDef.getFieldsMutable()) {
|
||||
String newDescriptor = row.get(fieldDef.getIntermediary());
|
||||
|
||||
if (newDescriptor != null) {
|
||||
fieldDef.setDescriptor(MappingsEntry.NS_INTERMEDIARY, newDescriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Files.write(tinyMappings.toPath(), MappingsUtils.serializeToString(mappings).getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE);
|
||||
}
|
||||
}
|
||||
|
||||
private void generateNewFieldMigration() throws IOException {
|
||||
Map<FieldMember, String> fieldDescriptorMap = new ConcurrentHashMap<>();
|
||||
LoomGradleExtension extension = getExtension();
|
||||
ThreadingUtils.TaskCompleter completer = ThreadingUtils.taskCompleter();
|
||||
|
||||
class Visitor extends ClassVisitor {
|
||||
private final ThreadLocal<String> lastClass = new ThreadLocal<>();
|
||||
|
||||
Visitor(int api) {
|
||||
super(api);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
|
||||
lastClass.set(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) {
|
||||
fieldDescriptorMap.put(new FieldMember(lastClass.get(), name), descriptor);
|
||||
return super.visitField(access, name, descriptor, signature, value);
|
||||
}
|
||||
}
|
||||
|
||||
Visitor visitor = new Visitor(Opcodes.ASM9);
|
||||
|
||||
for (MinecraftPatchedProvider.Environment environment : MinecraftPatchedProvider.Environment.values()) {
|
||||
File patchedSrgJar = environment.patchedSrgJar.apply(extension.getMappingsProvider().patchedProvider);
|
||||
FileSystemUtil.FileSystemDelegate system = FileSystemUtil.getJarFileSystem(patchedSrgJar, false);
|
||||
completer.onComplete(value -> system.close());
|
||||
|
||||
for (Path fsPath : (Iterable<? extends Path>) Files.walk(system.get().getPath("/"))::iterator) {
|
||||
if (Files.isRegularFile(fsPath) && fsPath.toString().endsWith(".class")) {
|
||||
completer.add(() -> {
|
||||
byte[] bytes = Files.readAllBytes(fsPath);
|
||||
new ClassReader(bytes).accept(visitor, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
completer.complete();
|
||||
Map<FieldMember, String> migratedFields = new HashMap<>();
|
||||
|
||||
try (BufferedReader reader = Files.newBufferedReader(rawTinyMappingsWithSrg)) {
|
||||
TinyTree mappings = TinyMappingFactory.loadWithDetection(reader);
|
||||
Map<String, String> srgToIntermediary = new HashMap<>();
|
||||
|
||||
for (ClassDef aClass : mappings.getClasses()) {
|
||||
srgToIntermediary.put(aClass.getName("srg"), aClass.getName("intermediary"));
|
||||
}
|
||||
|
||||
for (ClassDef classDef : mappings.getClasses()) {
|
||||
String ownerSrg = classDef.getName("srg");
|
||||
String ownerIntermediary = classDef.getName("intermediary");
|
||||
|
||||
for (FieldDef fieldDef : classDef.getFields()) {
|
||||
String fieldSrg = fieldDef.getName("srg");
|
||||
String descriptorSrg = fieldDef.getDescriptor("srg");
|
||||
|
||||
FieldMember member = new FieldMember(ownerSrg, fieldSrg);
|
||||
String newDescriptor = fieldDescriptorMap.get(member);
|
||||
|
||||
if (newDescriptor != null && !newDescriptor.equals(descriptorSrg)) {
|
||||
String fieldIntermediary = fieldDef.getName("intermediary");
|
||||
String descriptorIntermediary = fieldDef.getDescriptor("intermediary");
|
||||
String newDescriptorRemapped = DescriptorRemapper.remapDescriptor(newDescriptor,
|
||||
clazz -> srgToIntermediary.getOrDefault(clazz, clazz));
|
||||
migratedFields.put(new FieldMember(ownerIntermediary, fieldIntermediary), newDescriptorRemapped);
|
||||
getProject().getLogger().info(ownerIntermediary + "#" + fieldIntermediary + ": " + descriptorIntermediary + " -> " + newDescriptorRemapped);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.migratedFields.clear();
|
||||
this.migratedFields.addAll(migratedFields.entrySet());
|
||||
}
|
||||
|
||||
public static class FieldMember {
|
||||
public String owner;
|
||||
public String field;
|
||||
|
||||
public FieldMember(String owner, String field) {
|
||||
this.owner = owner;
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
FieldMember that = (FieldMember) o;
|
||||
return Objects.equals(owner, that.owner) && Objects.equals(field, that.field);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(owner, field);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -77,7 +77,6 @@ import org.zeroturnaround.zip.ZipUtil;
|
||||
|
||||
import net.fabricmc.loom.configuration.DependencyProvider;
|
||||
import net.fabricmc.loom.configuration.providers.MinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider;
|
||||
import net.fabricmc.loom.util.Checksum;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
@@ -92,7 +91,6 @@ import net.fabricmc.loom.util.srg.SpecialSourceExecutor;
|
||||
import net.fabricmc.mapping.tree.TinyTree;
|
||||
|
||||
public class MinecraftPatchedProvider extends DependencyProvider {
|
||||
private final MappingsProvider mappingsProvider;
|
||||
// Step 1: Remap Minecraft to SRG
|
||||
private File minecraftClientSrgJar;
|
||||
private File minecraftServerSrgJar;
|
||||
@@ -112,9 +110,8 @@ public class MinecraftPatchedProvider extends DependencyProvider {
|
||||
private File projectAt = null;
|
||||
private boolean atDirty = false;
|
||||
|
||||
public MinecraftPatchedProvider(MappingsProvider mappingsProvider, Project project) {
|
||||
public MinecraftPatchedProvider(Project project) {
|
||||
super(project);
|
||||
this.mappingsProvider = mappingsProvider;
|
||||
}
|
||||
|
||||
public void initFiles() throws IOException {
|
||||
@@ -149,26 +146,30 @@ public class MinecraftPatchedProvider extends DependencyProvider {
|
||||
MinecraftProvider minecraftProvider = getExtension().getMinecraftProvider();
|
||||
PatchProvider patchProvider = getExtension().getPatchProvider();
|
||||
String minecraftVersion = minecraftProvider.getMinecraftVersion();
|
||||
String jarSuffix = "-patched-forge-" + patchProvider.forgeVersion;
|
||||
String patchId = "forge-" + patchProvider.forgeVersion;
|
||||
|
||||
if (getExtension().useFabricMixin) {
|
||||
jarSuffix += "-fabric-mixin";
|
||||
patchId += "-fabric-mixin";
|
||||
}
|
||||
|
||||
minecraftProvider.setJarSuffix(jarSuffix);
|
||||
minecraftProvider.setJarSuffix(patchId);
|
||||
|
||||
File globalCache = getExtension().getUserCache();
|
||||
File cache = usesProjectCache() ? getExtension().getProjectPersistentCache() : globalCache;
|
||||
File globalDir = new File(globalCache, patchId);
|
||||
File projectDir = new File(cache, patchId);
|
||||
globalDir.mkdirs();
|
||||
projectDir.mkdirs();
|
||||
|
||||
minecraftClientSrgJar = new File(globalCache, "minecraft-" + minecraftVersion + "-client-srg.jar");
|
||||
minecraftServerSrgJar = new File(globalCache, "minecraft-" + minecraftVersion + "-server-srg.jar");
|
||||
minecraftClientPatchedSrgJar = new File(globalCache, "minecraft-" + minecraftVersion + "-client-srg" + jarSuffix + ".jar");
|
||||
minecraftServerPatchedSrgJar = new File(globalCache, "minecraft-" + minecraftVersion + "-server-srg" + jarSuffix + ".jar");
|
||||
minecraftClientPatchedSrgATJar = new File(cache, "minecraft-" + minecraftVersion + "-client-srg-at" + jarSuffix + ".jar");
|
||||
minecraftServerPatchedSrgATJar = new File(cache, "minecraft-" + minecraftVersion + "-server-srg-at" + jarSuffix + ".jar");
|
||||
minecraftClientPatchedOfficialJar = new File(cache, "minecraft-" + minecraftVersion + "-client" + jarSuffix + ".jar");
|
||||
minecraftServerPatchedOfficialJar = new File(cache, "minecraft-" + minecraftVersion + "-server" + jarSuffix + ".jar");
|
||||
minecraftMergedPatchedJar = new File(cache, "minecraft-" + minecraftVersion + "-merged" + jarSuffix + ".jar");
|
||||
minecraftClientPatchedSrgJar = new File(globalDir, "client-srg-patched.jar");
|
||||
minecraftServerPatchedSrgJar = new File(globalDir, "server-srg-patched.jar");
|
||||
minecraftClientPatchedSrgATJar = new File(projectDir, "client-srg-at-patched.jar");
|
||||
minecraftServerPatchedSrgATJar = new File(projectDir, "server-srg-at-patched.jar");
|
||||
minecraftClientPatchedOfficialJar = new File(projectDir, "client-patched.jar");
|
||||
minecraftServerPatchedOfficialJar = new File(projectDir, "server-patched.jar");
|
||||
minecraftMergedPatchedJar = new File(projectDir, "merged-patched.jar");
|
||||
|
||||
if (isRefreshDeps() || Stream.of(getGlobalCaches()).anyMatch(Predicates.not(File::exists))) {
|
||||
cleanAllCache();
|
||||
@@ -210,6 +211,8 @@ public class MinecraftPatchedProvider extends DependencyProvider {
|
||||
};
|
||||
}
|
||||
|
||||
private boolean dirty;
|
||||
|
||||
@Override
|
||||
public void provide(DependencyInfo dependency, Consumer<Runnable> postPopulationScheduler) throws Exception {
|
||||
initFiles();
|
||||
@@ -218,22 +221,24 @@ public class MinecraftPatchedProvider extends DependencyProvider {
|
||||
getProject().getLogger().lifecycle(":found dirty access transformers");
|
||||
}
|
||||
|
||||
boolean dirty = false;
|
||||
this.dirty = false;
|
||||
|
||||
if (!minecraftClientSrgJar.exists() || !minecraftServerSrgJar.exists()) {
|
||||
dirty = true;
|
||||
this.dirty = true;
|
||||
// Remap official jars to MCPConfig remapped srg jars
|
||||
createSrgJars(getProject().getLogger());
|
||||
}
|
||||
|
||||
if (!minecraftClientPatchedSrgJar.exists() || !minecraftServerPatchedSrgJar.exists()) {
|
||||
dirty = true;
|
||||
this.dirty = true;
|
||||
patchJars(getProject().getLogger());
|
||||
injectForgeClasses(getProject().getLogger());
|
||||
}
|
||||
}
|
||||
|
||||
public void finishProvide() throws Exception {
|
||||
if (atDirty || !minecraftClientPatchedSrgATJar.exists() || !minecraftServerPatchedSrgATJar.exists()) {
|
||||
dirty = true;
|
||||
this.dirty = true;
|
||||
accessTransformForge(getProject().getLogger());
|
||||
}
|
||||
|
||||
@@ -244,6 +249,8 @@ public class MinecraftPatchedProvider extends DependencyProvider {
|
||||
if (dirty || !minecraftMergedPatchedJar.exists()) {
|
||||
mergeJars(getProject().getLogger());
|
||||
}
|
||||
|
||||
this.dirty = false;
|
||||
}
|
||||
|
||||
private void writeAtHash() throws IOException {
|
||||
@@ -285,9 +292,9 @@ public class MinecraftPatchedProvider extends DependencyProvider {
|
||||
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);
|
||||
|
||||
ThreadingUtils.run(() -> {
|
||||
Files.copy(SpecialSourceExecutor.produceSrgJar(getProject(), mappingsProvider, "client", specialSourceJar, minecraftProvider.minecraftClientJar.toPath(), tmpSrg[0]), minecraftClientSrgJar.toPath());
|
||||
Files.copy(SpecialSourceExecutor.produceSrgJar(getProject(), "client", specialSourceJar, minecraftProvider.minecraftClientJar.toPath(), tmpSrg[0]), minecraftClientSrgJar.toPath());
|
||||
}, () -> {
|
||||
Files.copy(SpecialSourceExecutor.produceSrgJar(getProject(), mappingsProvider, "server", specialSourceJar, minecraftProvider.minecraftServerJar.toPath(), tmpSrg[0]), minecraftServerSrgJar.toPath());
|
||||
Files.copy(SpecialSourceExecutor.produceSrgJar(getProject(), "server", specialSourceJar, minecraftProvider.minecraftServerJar.toPath(), tmpSrg[0]), minecraftServerSrgJar.toPath());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -327,7 +334,7 @@ public class MinecraftPatchedProvider extends DependencyProvider {
|
||||
|
||||
private void injectForgeClasses(Logger logger) throws IOException {
|
||||
logger.lifecycle(":injecting forge classes into minecraft");
|
||||
ThreadingUtils.run(Arrays.asList(Environment.values()), environment -> {
|
||||
ThreadingUtils.run(Environment.values(), environment -> {
|
||||
copyAll(getExtension().getForgeUniversalProvider().getForge(), environment.patchedSrgJar.apply(this));
|
||||
copyUserdevFiles(getExtension().getForgeUserdevProvider().getUserdevJar(), environment.patchedSrgJar.apply(this));
|
||||
});
|
||||
@@ -392,7 +399,7 @@ public class MinecraftPatchedProvider extends DependencyProvider {
|
||||
((Map<?, ?>) field.get(list)).clear();
|
||||
}
|
||||
|
||||
private enum Environment {
|
||||
public enum Environment {
|
||||
CLIENT(provider -> provider.minecraftClientSrgJar,
|
||||
provider -> provider.minecraftClientPatchedSrgJar,
|
||||
provider -> provider.minecraftClientPatchedSrgATJar,
|
||||
@@ -427,7 +434,7 @@ public class MinecraftPatchedProvider extends DependencyProvider {
|
||||
private void remapPatchedJars(Logger logger) throws Exception {
|
||||
Path[] libraries = MinecraftMappedProvider.getRemapClasspath(getProject());
|
||||
|
||||
ThreadingUtils.run(Arrays.asList(Environment.values()), environment -> {
|
||||
ThreadingUtils.run(Environment.values(), environment -> {
|
||||
logger.lifecycle(":remapping minecraft (TinyRemapper, " + environment.side() + ", srg -> official)");
|
||||
TinyTree mappingsWithSrg = getExtension().getMappingsProvider().getMappingsWithSrg();
|
||||
|
||||
@@ -458,23 +465,26 @@ public class MinecraftPatchedProvider extends DependencyProvider {
|
||||
}
|
||||
|
||||
private void patchJars(Logger logger) throws IOException {
|
||||
Stopwatch stopwatch = Stopwatch.createStarted();
|
||||
logger.lifecycle(":patching jars");
|
||||
|
||||
PatchProvider patchProvider = getExtension().getPatchProvider();
|
||||
patchJars(minecraftClientSrgJar, minecraftClientPatchedSrgJar, patchProvider.clientPatches);
|
||||
patchJars(minecraftServerSrgJar, minecraftServerPatchedSrgJar, patchProvider.serverPatches);
|
||||
|
||||
ThreadingUtils.run(Arrays.asList(Environment.values()), environment -> {
|
||||
ThreadingUtils.run(Environment.values(), environment -> {
|
||||
copyMissingClasses(environment.srgJar.apply(this), environment.patchedSrgJar.apply(this));
|
||||
fixParameterAnnotation(environment.patchedSrgJar.apply(this));
|
||||
});
|
||||
|
||||
logger.lifecycle(":patched jars in " + stopwatch.stop());
|
||||
}
|
||||
|
||||
private void patchJars(File clean, File output, Path patches) throws IOException {
|
||||
PrintStream previous = System.out;
|
||||
|
||||
try {
|
||||
System.setOut(new PrintStream(new NullOutputStream()));
|
||||
System.setOut(new PrintStream(NullOutputStream.NULL_OUTPUT_STREAM));
|
||||
} catch (SecurityException ignored) {
|
||||
// Failed to replace logger filter, just ignore
|
||||
}
|
||||
@@ -507,7 +517,7 @@ 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 (FileSystemUtil.FileSystemDelegate sourceFs = FileSystemUtil.getJarFileSystem(source, false);
|
||||
FileSystemUtil.FileSystemDelegate targetFs = FileSystemUtil.getJarFileSystem(target, false)) {
|
||||
FileSystemUtil.FileSystemDelegate targetFs = FileSystemUtil.getJarFileSystem(target, false)) {
|
||||
for (Path sourceDir : toWalk.apply(sourceFs.get())) {
|
||||
Path dir = sourceDir.toAbsolutePath();
|
||||
Files.walk(dir)
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.forge;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.net.URI;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
@@ -42,6 +44,7 @@ public class PatchProvider extends DependencyProvider {
|
||||
public Path clientPatches;
|
||||
public Path serverPatches;
|
||||
public String forgeVersion;
|
||||
public Path projectCacheFolder;
|
||||
|
||||
public PatchProvider(Project project) {
|
||||
super(project);
|
||||
@@ -65,8 +68,19 @@ public class PatchProvider extends DependencyProvider {
|
||||
|
||||
private void init(String forgeVersion) {
|
||||
this.forgeVersion = forgeVersion;
|
||||
clientPatches = getExtension().getProjectPersistentCache().toPath().resolve("patches-" + forgeVersion + "-client.lzma");
|
||||
serverPatches = getExtension().getProjectPersistentCache().toPath().resolve("patches-" + forgeVersion + "-server.lzma");
|
||||
projectCacheFolder = getExtension().getProjectPersistentCache().toPath().resolve(forgeVersion);
|
||||
clientPatches = projectCacheFolder.resolve("patches-client.lzma");
|
||||
serverPatches = projectCacheFolder.resolve("patches-server.lzma");
|
||||
|
||||
try {
|
||||
Files.createDirectories(projectCacheFolder);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Path getProjectCacheFolder() {
|
||||
return projectCacheFolder;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -42,8 +42,11 @@ import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Stopwatch;
|
||||
import com.google.common.net.UrlEscapers;
|
||||
import com.google.gson.JsonObject;
|
||||
import dev.architectury.mappingslayers.api.utils.MappingsModificationUtils;
|
||||
import dev.architectury.mappingslayers.api.utils.MappingsUtils;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.tools.ant.util.StringUtils;
|
||||
import org.gradle.api.Project;
|
||||
@@ -86,7 +89,7 @@ public class MappingsProvider extends DependencyProvider {
|
||||
public String minecraftVersion;
|
||||
public String mappingsVersion;
|
||||
|
||||
private final Path mappingsDir;
|
||||
protected final Path mappingsDir;
|
||||
private final Path mappingsStepsDir;
|
||||
private Path intermediaryTiny;
|
||||
private boolean hasRefreshed = false;
|
||||
@@ -94,8 +97,8 @@ public class MappingsProvider extends DependencyProvider {
|
||||
private Path baseTinyMappings;
|
||||
// The mappings we use in practice
|
||||
public File tinyMappings;
|
||||
// tinyMappings wrapped in a jar
|
||||
public File tinyMappingsJar;
|
||||
public File mappingsMixinExport;
|
||||
public Path tinyMappingsWithSrg;
|
||||
public File mixinTinyMappingsWithSrg; // FORGE: The mixin mappings have srg names in intermediary.
|
||||
public File srgToNamedSrg; // FORGE: srg to named in srg file format
|
||||
@@ -181,12 +184,13 @@ public class MappingsProvider extends DependencyProvider {
|
||||
jarClassifier = jarClassifier + depStringSplit[3];
|
||||
}
|
||||
|
||||
tinyMappings = mappingsDir.resolve(StringUtils.removeSuffix(mappingsJar.getName(), ".jar") + ".tiny").toFile();
|
||||
unpickDefinitionsFile = mappingsDir.resolve(StringUtils.removeSuffix(mappingsJar.getName(), ".jar") + ".unpick").toFile();
|
||||
tinyMappingsJar = new File(getExtension().getUserCache(), mappingsJar.getName().replace(".jar", "-" + jarClassifier + ".jar"));
|
||||
tinyMappingsWithSrg = mappingsDir.resolve(StringUtils.removeSuffix(mappingsJar.getName(), ".jar") + "-srg.tiny");
|
||||
mixinTinyMappingsWithSrg = mappingsDir.resolve(StringUtils.removeSuffix(mappingsJar.getName(), ".jar") + "-mixin-srg.tiny").toFile();
|
||||
srgToNamedSrg = mappingsDir.resolve(StringUtils.removeSuffix(mappingsJar.getName(), ".jar") + "-srg-named.srg").toFile();
|
||||
String removeSuffix = StringUtils.removeSuffix(mappingsJar.getName(), ".jar");
|
||||
tinyMappings = mappingsDir.resolve(removeSuffix + ".tiny").toFile();
|
||||
unpickDefinitionsFile = mappingsDir.resolve(removeSuffix + ".unpick").toFile();
|
||||
tinyMappingsJar = new File(getExtension().getUserCache(), removeSuffix + "-" + jarClassifier + ".jar");
|
||||
tinyMappingsWithSrg = mappingsDir.resolve(removeSuffix + "-srg.tiny");
|
||||
mixinTinyMappingsWithSrg = mappingsDir.resolve(removeSuffix + "-mixin-srg.tiny").toFile();
|
||||
srgToNamedSrg = mappingsDir.resolve(removeSuffix + "-srg-named.srg").toFile();
|
||||
|
||||
if (!tinyMappings.exists() || isRefreshDeps()) {
|
||||
storeMappings(getProject(), minecraftProvider, mappingsJar.toPath(), postPopulationScheduler);
|
||||
@@ -196,6 +200,20 @@ public class MappingsProvider extends DependencyProvider {
|
||||
}
|
||||
}
|
||||
|
||||
if (getExtension().isForge()) {
|
||||
patchedProvider = new MinecraftPatchedProvider(getProject());
|
||||
patchedProvider.provide(dependency, postPopulationScheduler);
|
||||
}
|
||||
|
||||
manipulateMappings(mappingsJar.toPath());
|
||||
|
||||
if (getExtension().shouldGenerateSrgTiny()) {
|
||||
if (Files.notExists(tinyMappingsWithSrg) || isRefreshDeps()) {
|
||||
// Merge tiny mappings with srg
|
||||
SrgMerger.mergeSrg(getExtension().getSrgProvider().getSrg().toPath(), tinyMappings.toPath(), tinyMappingsWithSrg, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (!tinyMappingsJar.exists() || isRefreshDeps()) {
|
||||
ZipUtil.pack(new ZipEntrySource[] {new FileSource("mappings/mappings.tiny", tinyMappings)}, tinyMappingsJar);
|
||||
}
|
||||
@@ -211,12 +229,6 @@ public class MappingsProvider extends DependencyProvider {
|
||||
populateUnpickClasspath();
|
||||
}
|
||||
|
||||
if (getExtension().shouldGenerateSrgTiny()) {
|
||||
if (Files.notExists(tinyMappingsWithSrg) || isRefreshDeps()) {
|
||||
SrgMerger.mergeSrg(getExtension().getSrgProvider().getSrg().toPath(), tinyMappings.toPath(), tinyMappingsWithSrg, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (getExtension().isForge()) {
|
||||
if (!getExtension().shouldGenerateSrgTiny()) {
|
||||
throw new IllegalStateException("We have to generate srg tiny in a forge environment!");
|
||||
@@ -247,8 +259,7 @@ public class MappingsProvider extends DependencyProvider {
|
||||
processorManager.setupProcessors();
|
||||
|
||||
if (extension.isForge()) {
|
||||
patchedProvider = new MinecraftPatchedProvider(this, getProject());
|
||||
patchedProvider.provide(dependency, postPopulationScheduler);
|
||||
patchedProvider.finishProvide();
|
||||
}
|
||||
|
||||
if (processorManager.active() || (extension.isForge() && patchedProvider.usesProjectCache())) {
|
||||
@@ -262,6 +273,8 @@ public class MappingsProvider extends DependencyProvider {
|
||||
mappedProvider.provide(dependency, postPopulationScheduler);
|
||||
}
|
||||
|
||||
public void manipulateMappings(Path mappingsJar) throws IOException { }
|
||||
|
||||
private void storeMappings(Project project, MinecraftProvider minecraftProvider, Path yarnJar, Consumer<Runnable> postPopulationScheduler)
|
||||
throws Exception {
|
||||
project.getLogger().info(":extracting " + yarnJar.getFileName());
|
||||
@@ -407,21 +420,21 @@ public class MappingsProvider extends DependencyProvider {
|
||||
extractMappings(unmergedYarnJarFs, unmergedYarn);
|
||||
}
|
||||
|
||||
Stopwatch stopwatch = Stopwatch.createStarted();
|
||||
project.getLogger().info(":merging mappings");
|
||||
Path invertedIntermediary = Paths.get(mappingsStepsDir.toString(), "inverted-intermediary.tiny");
|
||||
reorderMappings(getIntermediaryTiny(), invertedIntermediary, "intermediary", "official");
|
||||
Path unorderedMergedMappings = Paths.get(mappingsStepsDir.toString(), "unordered-merged.tiny");
|
||||
project.getLogger().info(":merging");
|
||||
mergeMappings(invertedIntermediary, unmergedYarn, unorderedMergedMappings);
|
||||
reorderMappings(unorderedMergedMappings, tinyMappings.toPath(), "official", "intermediary", "named");
|
||||
Files.deleteIfExists(invertedIntermediary);
|
||||
Files.deleteIfExists(unorderedMergedMappings);
|
||||
project.getLogger().info(":merged mappings in " + stopwatch.stop());
|
||||
}
|
||||
|
||||
private void reorderMappings(Path oldMappings, Path newMappings, String... newOrder) {
|
||||
Command command = new CommandReorderTinyV2();
|
||||
String[] args = new String[2 + newOrder.length];
|
||||
args[0] = oldMappings.toAbsolutePath().toString();
|
||||
args[1] = newMappings.toAbsolutePath().toString();
|
||||
System.arraycopy(newOrder, 0, args, 2, newOrder.length);
|
||||
runCommand(command, args);
|
||||
private void reorderMappings(Path oldMappings, Path newMappings, String... newOrder) throws IOException {
|
||||
MappingsModificationUtils.modify(oldMappings, newMappings, tree ->
|
||||
MappingsUtils.reorderNamespaces(tree, Arrays.asList(newOrder)));
|
||||
}
|
||||
|
||||
private void mergeMappings(Path intermediaryMappings, Path yarnMappings, Path newMergedMappings) {
|
||||
|
||||
@@ -47,6 +47,8 @@ import java.util.jar.Manifest;
|
||||
import com.google.common.base.Stopwatch;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import dev.architectury.tinyremapper.IMappingProvider;
|
||||
import dev.architectury.tinyremapper.NonClassCopyMode;
|
||||
import dev.architectury.tinyremapper.OutputConsumerPath;
|
||||
import dev.architectury.tinyremapper.TinyRemapper;
|
||||
import org.gradle.api.Project;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -55,9 +57,11 @@ import net.fabricmc.loom.configuration.DependencyProvider;
|
||||
import net.fabricmc.loom.configuration.providers.MinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.tr.OutputRemappingHandler;
|
||||
import net.fabricmc.loom.configuration.sources.ForgeSourcesRemapper;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
import net.fabricmc.loom.util.DownloadUtil;
|
||||
import net.fabricmc.loom.util.FileSystemUtil;
|
||||
import net.fabricmc.loom.util.OperatingSystem;
|
||||
import net.fabricmc.loom.util.ThreadingUtils;
|
||||
import net.fabricmc.loom.util.TinyRemapperMappingsHelper;
|
||||
import net.fabricmc.loom.util.srg.AtRemapper;
|
||||
@@ -66,7 +70,7 @@ import net.fabricmc.loom.util.srg.InnerClassRemapper;
|
||||
import net.fabricmc.mapping.tree.TinyTree;
|
||||
|
||||
public class MinecraftMappedProvider extends DependencyProvider {
|
||||
private static final Map<String, String> JSR_TO_JETBRAINS = new ImmutableMap.Builder<String, String>()
|
||||
public static final Map<String, String> JSR_TO_JETBRAINS = new ImmutableMap.Builder<String, String>()
|
||||
.put("javax/annotation/Nullable", "org/jetbrains/annotations/Nullable")
|
||||
.put("javax/annotation/Nonnull", "org/jetbrains/annotations/NotNull")
|
||||
.put("javax/annotation/concurrent/Immutable", "org/jetbrains/annotations/Unmodifiable")
|
||||
@@ -132,6 +136,16 @@ public class MinecraftMappedProvider extends DependencyProvider {
|
||||
}
|
||||
|
||||
addDependencies(dependency, postPopulationScheduler);
|
||||
|
||||
getProject().afterEvaluate(project -> {
|
||||
if (getExtension().isForge() && !OperatingSystem.isCIBuild()) {
|
||||
try {
|
||||
ForgeSourcesRemapper.addBaseForgeSources(project);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void mapMinecraftJar() throws Exception {
|
||||
@@ -158,32 +172,28 @@ public class MinecraftMappedProvider extends DependencyProvider {
|
||||
try (FileSystemUtil.FileSystemDelegate inputFs = FileSystemUtil.getJarFileSystem(input, false)) {
|
||||
ThreadingUtils.TaskCompleter taskCompleter = ThreadingUtils.taskCompleter();
|
||||
|
||||
try (FileSystemUtil.FileSystemDelegate assetsFs = FileSystemUtil.getJarFileSystem(tmpAssets, true)) {
|
||||
for (Path path : (Iterable<? extends Path>) Files.walk(inputFs.get().getPath("/"))::iterator) {
|
||||
if (Files.isRegularFile(path)) {
|
||||
if (path.getFileName().toString().endsWith(".class")) {
|
||||
taskCompleter.add(() -> {
|
||||
byte[] bytes = Files.readAllBytes(path);
|
||||
for (Path path : (Iterable<? extends Path>) Files.walk(inputFs.get().getPath("/"))::iterator) {
|
||||
if (Files.isRegularFile(path)) {
|
||||
if (path.getFileName().toString().endsWith(".class")) {
|
||||
taskCompleter.add(() -> {
|
||||
byte[] bytes = Files.readAllBytes(path);
|
||||
|
||||
synchronized (inputByteList) {
|
||||
inputByteList.add(bytes);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Path p = assetsFs.get().getPath(path.toString());
|
||||
|
||||
if (p.getParent() != null) {
|
||||
Files.createDirectories(p.getParent());
|
||||
synchronized (inputByteList) {
|
||||
inputByteList.add(bytes);
|
||||
}
|
||||
|
||||
taskCompleter.add(() -> {
|
||||
Files.copy(path, p);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
taskCompleter.complete();
|
||||
taskCompleter.complete();
|
||||
}
|
||||
|
||||
try (OutputConsumerPath tmpAssetsPath = new OutputConsumerPath.Builder(tmpAssets).assumeArchive(true).build()) {
|
||||
if (getExtension().isForge()) {
|
||||
tmpAssetsPath.addNonClassFiles(input, NonClassCopyMode.FIX_META_INF, null);
|
||||
} else {
|
||||
tmpAssetsPath.addNonClassFiles(input);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,27 @@
|
||||
/*
|
||||
* 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.configuration.providers.minecraft.tr;
|
||||
|
||||
import org.cadixdev.mercury.Mercury;
|
||||
|
||||
@@ -1,3 +1,27 @@
|
||||
/*
|
||||
* 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.configuration.providers.minecraft.tr;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
* 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.configuration.sources;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.cadixdev.lorenz.MappingSet;
|
||||
import org.cadixdev.mercury.Mercury;
|
||||
import org.cadixdev.mercury.remapper.MercuryRemapper;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.Dependency;
|
||||
import org.gradle.api.artifacts.ResolvedArtifact;
|
||||
import org.gradle.api.plugins.JavaPlugin;
|
||||
import org.zeroturnaround.zip.ZipUtil;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.build.ModCompileRemapper;
|
||||
import net.fabricmc.loom.configuration.providers.LaunchProvider;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider;
|
||||
import net.fabricmc.loom.task.GenerateSourcesTask;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
import net.fabricmc.loom.util.DeletingFileVisitor;
|
||||
import net.fabricmc.loom.util.FileSystemUtil;
|
||||
import net.fabricmc.loom.util.SourceRemapper;
|
||||
import net.fabricmc.loom.util.ThreadingUtils;
|
||||
import net.fabricmc.lorenztiny.TinyMappingsReader;
|
||||
|
||||
public class ForgeSourcesRemapper {
|
||||
public static void addBaseForgeSources(Project project) throws IOException {
|
||||
Path sourcesJar = GenerateSourcesTask.getMappedJarFileWithSuffix(project, "-sources.jar").toPath();
|
||||
|
||||
if (!Files.exists(sourcesJar)) {
|
||||
addForgeSources(project, sourcesJar);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addForgeSources(Project project, Path sourcesJar) throws IOException {
|
||||
try (FileSystemUtil.FileSystemDelegate delegate = FileSystemUtil.getJarFileSystem(sourcesJar, true)) {
|
||||
ThreadingUtils.TaskCompleter taskCompleter = ThreadingUtils.taskCompleter();
|
||||
|
||||
provideForgeSources(project, (path, bytes) -> {
|
||||
Path fsPath = delegate.get().getPath(path);
|
||||
|
||||
if (fsPath.getParent() != null) {
|
||||
try {
|
||||
Files.createDirectories(fsPath.getParent());
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
taskCompleter.add(() -> {
|
||||
Files.write(fsPath, bytes, StandardOpenOption.CREATE);
|
||||
});
|
||||
});
|
||||
|
||||
taskCompleter.complete();
|
||||
}
|
||||
}
|
||||
|
||||
public static void provideForgeSources(Project project, BiConsumer<String, byte[]> consumer) throws IOException {
|
||||
List<Path> forgeInstallerSources = new ArrayList<>();
|
||||
|
||||
for (ResolvedArtifact artifact : project.getConfigurations().getByName(Constants.Configurations.FORGE_INSTALLER).getResolvedConfiguration().getResolvedArtifacts()) {
|
||||
File forgeInstallerSource = ModCompileRemapper.findSources(project.getDependencies(), artifact);
|
||||
|
||||
if (forgeInstallerSource != null) {
|
||||
forgeInstallerSources.add(forgeInstallerSource.toPath());
|
||||
}
|
||||
}
|
||||
|
||||
project.getLogger().lifecycle(":found {} forge source jars", forgeInstallerSources.size());
|
||||
Map<String, byte[]> forgeSources = extractSources(forgeInstallerSources);
|
||||
project.getLogger().lifecycle(":extracted {} forge source classes", forgeSources.size());
|
||||
remapSources(project, forgeSources);
|
||||
forgeSources.forEach(consumer);
|
||||
}
|
||||
|
||||
private static void remapSources(Project project, Map<String, byte[]> sources) throws IOException {
|
||||
File tmpInput = File.createTempFile("tmpInputForgeSources", null);
|
||||
tmpInput.delete();
|
||||
tmpInput.deleteOnExit();
|
||||
File tmpOutput = File.createTempFile("tmpOutputForgeSources", null);
|
||||
tmpOutput.delete();
|
||||
tmpOutput.deleteOnExit();
|
||||
|
||||
try (FileSystemUtil.FileSystemDelegate delegate = FileSystemUtil.getJarFileSystem(tmpInput, true)) {
|
||||
ThreadingUtils.TaskCompleter taskCompleter = ThreadingUtils.taskCompleter();
|
||||
|
||||
for (Map.Entry<String, byte[]> entry : sources.entrySet()) {
|
||||
Path path = delegate.get().getPath(entry.getKey());
|
||||
|
||||
if (path.getParent() != null) {
|
||||
Files.createDirectories(path.getParent());
|
||||
}
|
||||
|
||||
taskCompleter.add(() -> {
|
||||
Files.write(path, entry.getValue(), StandardOpenOption.CREATE);
|
||||
});
|
||||
}
|
||||
|
||||
taskCompleter.complete();
|
||||
}
|
||||
|
||||
remapForgeSourcesInner(project, tmpInput.toPath(), tmpOutput.toPath());
|
||||
tmpInput.delete();
|
||||
int[] failedToRemap = {0};
|
||||
|
||||
try (FileSystemUtil.FileSystemDelegate delegate = FileSystemUtil.getJarFileSystem(tmpOutput, false)) {
|
||||
ThreadingUtils.TaskCompleter taskCompleter = ThreadingUtils.taskCompleter();
|
||||
|
||||
for (Map.Entry<String, byte[]> entry : new HashSet<>(sources.entrySet())) {
|
||||
taskCompleter.add(() -> {
|
||||
Path path = delegate.get().getPath(entry.getKey());
|
||||
|
||||
if (Files.exists(path)) {
|
||||
sources.put(entry.getKey(), Files.readAllBytes(path));
|
||||
} else {
|
||||
sources.remove(entry.getKey());
|
||||
project.getLogger().error("forge source failed to remap " + entry.getKey());
|
||||
failedToRemap[0]++;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
taskCompleter.complete();
|
||||
}
|
||||
|
||||
tmpOutput.delete();
|
||||
|
||||
if (failedToRemap[0] > 0) {
|
||||
project.getLogger().error("{} forge sources failed to remap", failedToRemap[0]);
|
||||
}
|
||||
}
|
||||
|
||||
private static void remapForgeSourcesInner(Project project, Path tmpInput, Path tmpOutput) throws IOException {
|
||||
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
|
||||
Mercury mercury = SourceRemapper.createMercuryWithClassPath(project, false);
|
||||
|
||||
MappingSet mappings = new TinyMappingsReader(extension.getMappingsProvider().getMappingsWithSrg(), "srg", "named").read();
|
||||
|
||||
for (Map.Entry<String, String> entry : MinecraftMappedProvider.JSR_TO_JETBRAINS.entrySet()) {
|
||||
mappings.getOrCreateClassMapping(entry.getKey()).setDeobfuscatedName(entry.getValue());
|
||||
}
|
||||
|
||||
Dependency annotationDependency = extension.getDependencyManager().getProvider(LaunchProvider.class).annotationDependency;
|
||||
Set<File> files = project.getConfigurations().getByName(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME)
|
||||
.files(annotationDependency);
|
||||
|
||||
for (File file : files) {
|
||||
mercury.getClassPath().add(file.toPath());
|
||||
}
|
||||
|
||||
// Distinct and add the srg jar at the top, so it gets prioritized
|
||||
mercury.getClassPath().add(0, extension.getMinecraftMappedProvider().getSrgJar().toPath());
|
||||
List<Path> newClassPath = mercury.getClassPath().stream()
|
||||
.distinct()
|
||||
.filter(Files::isRegularFile)
|
||||
.collect(Collectors.toList());
|
||||
mercury.getClassPath().clear();
|
||||
mercury.getClassPath().addAll(newClassPath);
|
||||
|
||||
mercury.getProcessors().add(MercuryRemapper.create(mappings));
|
||||
boolean isSrcTmp = false;
|
||||
|
||||
if (!Files.isDirectory(tmpInput)) {
|
||||
Path tmpInput1 = tmpInput;
|
||||
// create tmp directory
|
||||
isSrcTmp = true;
|
||||
tmpInput = Files.createTempDirectory("fabric-loom-src");
|
||||
ZipUtil.unpack(tmpInput1.toFile(), tmpInput.toFile());
|
||||
}
|
||||
|
||||
try (FileSystemUtil.FileSystemDelegate outputFs = FileSystemUtil.getJarFileSystem(tmpOutput, true)) {
|
||||
Path outputFsRoot = outputFs.get().getPath("/");
|
||||
mercury.rewrite(tmpInput, outputFsRoot);
|
||||
} catch (Exception e) {
|
||||
project.getLogger().warn("Could not remap " + tmpInput + " fully!", e);
|
||||
}
|
||||
|
||||
if (isSrcTmp) {
|
||||
Files.walkFileTree(tmpInput, new DeletingFileVisitor());
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<String, byte[]> extractSources(List<Path> forgeInstallerSources) throws IOException {
|
||||
Map<String, byte[]> sources = new ConcurrentHashMap<>();
|
||||
ThreadingUtils.TaskCompleter taskCompleter = ThreadingUtils.taskCompleter();
|
||||
|
||||
for (Path path : forgeInstallerSources) {
|
||||
FileSystemUtil.FileSystemDelegate system = FileSystemUtil.getJarFileSystem(path, false);
|
||||
taskCompleter.onComplete(stopwatch -> system.close());
|
||||
|
||||
for (Path filePath : (Iterable<? extends Path>) Files.walk(system.get().getPath("/"))::iterator) {
|
||||
if (Files.isRegularFile(filePath) && filePath.getFileName().toString().endsWith(".java")) {
|
||||
taskCompleter.add(() -> sources.put(filePath.toString(), Files.readAllBytes(filePath)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
taskCompleter.complete();
|
||||
return sources;
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.tasks.InputFile;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
|
||||
@@ -42,6 +43,7 @@ import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.api.decompilers.DecompilationMetadata;
|
||||
import net.fabricmc.loom.api.decompilers.LoomDecompiler;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider;
|
||||
import net.fabricmc.loom.configuration.sources.ForgeSourcesRemapper;
|
||||
import net.fabricmc.loom.decompilers.LineNumberRemapper;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
import net.fabricmc.loom.util.gradle.ProgressLogger;
|
||||
@@ -81,6 +83,10 @@ public class GenerateSourcesTask extends AbstractLoomTask {
|
||||
Files.copy(linemappedJarDestination, runtimeJar, StandardCopyOption.REPLACE_EXISTING);
|
||||
Files.delete(linemappedJarDestination);
|
||||
}
|
||||
|
||||
if (getExtension().isForge()) {
|
||||
ForgeSourcesRemapper.addForgeSources(getProject(), sourcesDestination);
|
||||
}
|
||||
}
|
||||
|
||||
private void remapLineNumbers(Path oldCompiledJar, Path linemap, Path linemappedJarDestination) throws IOException {
|
||||
@@ -100,7 +106,11 @@ public class GenerateSourcesTask extends AbstractLoomTask {
|
||||
}
|
||||
|
||||
private File getMappedJarFileWithSuffix(String suffix) {
|
||||
LoomGradleExtension extension = getProject().getExtensions().getByType(LoomGradleExtension.class);
|
||||
return getMappedJarFileWithSuffix(getProject(), suffix);
|
||||
}
|
||||
|
||||
public static File getMappedJarFileWithSuffix(Project project, String suffix) {
|
||||
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
|
||||
MappingsProvider mappingsProvider = extension.getMappingsProvider();
|
||||
File mappedJar = mappingsProvider.mappedProvider.getMappedJar();
|
||||
String path = mappedJar.getAbsolutePath();
|
||||
|
||||
@@ -59,6 +59,7 @@ public final class LoomTasks {
|
||||
|
||||
registerIDETasks(tasks);
|
||||
registerRunTasks(tasks, project);
|
||||
registerLaunchSettings(project);
|
||||
registerDecompileTasks(tasks, project);
|
||||
}
|
||||
|
||||
@@ -109,6 +110,17 @@ public final class LoomTasks {
|
||||
extension.getRunConfigs().create("server", RunConfigSettings::server);
|
||||
}
|
||||
|
||||
private static void registerLaunchSettings(Project project) {
|
||||
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
|
||||
Preconditions.checkArgument(extension.getLaunchConfigs().size() == 0, "Launch configurations must not be registered before loom");
|
||||
extension.getLaunchConfigs().create("client");
|
||||
extension.getLaunchConfigs().create("server");
|
||||
|
||||
if (extension.isForge()) {
|
||||
extension.getLaunchConfigs().create("data");
|
||||
}
|
||||
}
|
||||
|
||||
private static void registerDecompileTasks(TaskContainer tasks, Project project) {
|
||||
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
|
||||
|
||||
|
||||
@@ -1,3 +1,27 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
public enum ModPlatform {
|
||||
|
||||
@@ -34,13 +34,18 @@ import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.google.common.base.Stopwatch;
|
||||
|
||||
public class ThreadingUtils {
|
||||
public static <T> void run(T[] values, UnsafeConsumer<T> action) {
|
||||
run(Arrays.stream(values)
|
||||
.<UnsafeRunnable>map(t -> () -> action.accept(t))
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
public static <T> void run(Collection<T> values, UnsafeConsumer<T> action) {
|
||||
run(values.stream()
|
||||
.<UnsafeRunnable>map(t -> () -> action.accept(t))
|
||||
@@ -134,7 +139,7 @@ public class ThreadingUtils {
|
||||
Stopwatch stopwatch = Stopwatch.createUnstarted();
|
||||
List<CompletableFuture<?>> tasks = new ArrayList<>();
|
||||
ExecutorService service = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
|
||||
List<Consumer<Stopwatch>> completionListener = new ArrayList<>();
|
||||
List<UnsafeConsumer<Stopwatch>> completionListener = new ArrayList<>();
|
||||
|
||||
public TaskCompleter add(UnsafeRunnable job) {
|
||||
if (!stopwatch.isRunning()) {
|
||||
@@ -152,7 +157,7 @@ public class ThreadingUtils {
|
||||
return this;
|
||||
}
|
||||
|
||||
public TaskCompleter onComplete(Consumer<Stopwatch> consumer) {
|
||||
public TaskCompleter onComplete(UnsafeConsumer<Stopwatch> consumer) {
|
||||
completionListener.add(consumer);
|
||||
return this;
|
||||
}
|
||||
@@ -161,13 +166,20 @@ public class ThreadingUtils {
|
||||
try {
|
||||
CompletableFuture.allOf(tasks.toArray(new CompletableFuture[0])).exceptionally(this).get();
|
||||
service.shutdownNow();
|
||||
stopwatch.stop();
|
||||
|
||||
for (Consumer<Stopwatch> consumer : completionListener) {
|
||||
consumer.accept(stopwatch);
|
||||
if (stopwatch.isRunning()) {
|
||||
stopwatch.stop();
|
||||
}
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
try {
|
||||
for (UnsafeConsumer<Stopwatch> consumer : completionListener) {
|
||||
consumer.accept(stopwatch);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,10 +40,9 @@ import org.gradle.api.Project;
|
||||
import org.zeroturnaround.zip.ZipUtil;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider;
|
||||
|
||||
public class SpecialSourceExecutor {
|
||||
public static Path produceSrgJar(Project project, MappingsProvider provider, String side, File specialSourceJar, Path officialJar, Path srgPath)
|
||||
public static Path produceSrgJar(Project project, String side, File specialSourceJar, Path officialJar, Path srgPath)
|
||||
throws Exception {
|
||||
Set<String> filter = Files.readAllLines(srgPath, StandardCharsets.UTF_8).stream()
|
||||
.filter(s -> !s.startsWith("\t"))
|
||||
|
||||
Reference in New Issue
Block a user