aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorshedaniel <daniel@shedaniel.me>2021-08-30 14:10:32 +0800
committershedaniel <daniel@shedaniel.me>2021-08-30 14:10:32 +0800
commit9366d42baa22b53b16ad8b21b843576ec8c964c7 (patch)
treea83f8a0b0b4f1b78fc5d293aeccac27dfc9f4c19
parentd819b1cc47b26572ab6af85258e54d5737bead69 (diff)
downloadarchitectury-loom-9366d42baa22b53b16ad8b21b843576ec8c964c7.tar.gz
architectury-loom-9366d42baa22b53b16ad8b21b843576ec8c964c7.tar.bz2
architectury-loom-9366d42baa22b53b16ad8b21b843576ec8c964c7.zip
Start work on porting 0.7.4 over
Signed-off-by: shedaniel <daniel@shedaniel.me>
-rw-r--r--build.gradle3
-rw-r--r--forge-runtime/.gitignore6
-rw-r--r--forge-runtime/build.gradle93
-rw-r--r--forge-runtime/src/main/java/dev/architectury/loom/forgeruntime/YarnNamingService.java128
-rw-r--r--forge-runtime/src/main/java/dev/architectury/loom/forgeruntime/mixin/ForgeLoomMixinRemapperInjectorService.java93
-rw-r--r--forge-runtime/src/main/java/dev/architectury/loom/forgeruntime/mixin/MixinIntermediaryDevRemapper.java233
-rw-r--r--forge-runtime/src/main/java/mcp/MethodsReturnNonnullByDefault.java35
-rw-r--r--forge-runtime/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.INameMappingService1
-rw-r--r--forge-runtime/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService1
-rw-r--r--settings.gradle1
-rw-r--r--src/main/java/net/fabricmc/loom/LoomGradleExtension.java10
-rw-r--r--src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java4
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java7
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/ide/RunConfig.java27
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/ide/RunConfigSettings.java18
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/ide/SetupIntelijRunConfigs.java8
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/launch/LaunchProviderSettings.java16
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java2
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/providers/LaunchProvider.java49
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/providers/forge/FieldMigratedMappingsProvider.java4
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeProvider.java7
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeUserdevProvider.java228
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/providers/forge/McpConfigProvider.java66
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/providers/forge/MinecraftPatchedProvider.java277
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/providers/forge/PatchProvider.java4
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/providers/mappings/GradleMappingContext.java2
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingsDependency.java55
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProviderImpl.java42
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftMappedProvider.java37
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/sources/ForgeSourcesRemapper.java10
-rw-r--r--src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java10
-rw-r--r--src/main/java/net/fabricmc/loom/extension/MinecraftGradleExtension.java12
-rw-r--r--src/main/java/net/fabricmc/loom/task/LoomTasks.java16
-rw-r--r--src/main/java/net/fabricmc/loom/task/MigrateMappingsTask.java9
-rw-r--r--src/main/java/net/fabricmc/loom/util/Constants.java9
-rw-r--r--src/main/java/net/fabricmc/loom/util/DependencyDownloader.java45
-rw-r--r--src/main/java/net/fabricmc/loom/util/MappingsProviderVerbose.java71
-rw-r--r--src/main/java/net/fabricmc/loom/util/srg/InnerClassRemapper.java64
-rw-r--r--src/main/java/net/fabricmc/loom/util/srg/SpecialSourceExecutor.java5
-rw-r--r--src/main/java/net/fabricmc/loom/util/srg/SrgMerger.java103
-rw-r--r--src/main/java/net/fabricmc/loom/util/srg/Tsrg2Utils.java209
-rw-r--r--src/test/groovy/net/fabricmc/loom/test/unit/layeredmappings/LayeredMappingsSpecification.groovy5
42 files changed, 1214 insertions, 811 deletions
diff --git a/build.gradle b/build.gradle
index c377e0ef..73226e3a 100644
--- a/build.gradle
+++ b/build.gradle
@@ -91,7 +91,7 @@ dependencies {
// tinyfile management
implementation ('dev.architectury:tiny-remapper:1.1.0')
- implementation ('dev.architectury:mappings-layers-core:1.3.8')
+ implementation ('dev.architectury:mappings-layers-core:1.4.9')
implementation ('net.fabricmc:tiny-mappings-parser:0.3.0+build.17')
implementation 'net.fabricmc:access-widener:1.1.0'
@@ -135,6 +135,7 @@ dependencies {
compileOnly('org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.21')
// Forge patches
+ implementation ('net.minecraftforge:installertools:1.2.0')
implementation ('net.minecraftforge:binarypatcher:1.1.1')
implementation ('org.cadixdev:lorenz:0.5.3')
implementation ('org.cadixdev:lorenz-asm:0.5.3')
diff --git a/forge-runtime/.gitignore b/forge-runtime/.gitignore
deleted file mode 100644
index 31ecb657..00000000
--- a/forge-runtime/.gitignore
+++ /dev/null
@@ -1,6 +0,0 @@
-# Ignore everything
-/*
-
-!/src
-!/build.gradle
-!/.gitignore
diff --git a/forge-runtime/build.gradle b/forge-runtime/build.gradle
deleted file mode 100644
index 388db8e3..00000000
--- a/forge-runtime/build.gradle
+++ /dev/null
@@ -1,93 +0,0 @@
-plugins {
- id 'java'
- id 'maven-publish'
- id 'checkstyle'
- id 'com.github.johnrengelman.shadow' version '7.0.0'
- id "com.diffplug.spotless"
-}
-
-group = rootProject.group
-archivesBaseName = 'architectury-loom-forge-runtime'
-version = rootProject.version
-
-sourceCompatibility = JavaVersion.VERSION_1_8
-targetCompatibility = JavaVersion.VERSION_1_8
-
-configurations {
- include
- compileOnly.extendsFrom include
-}
-
-tasks.withType(JavaCompile).configureEach {
- it.options.encoding = "UTF-8"
- it.options.release = 8
-}
-
-repositories {
- mavenCentral()
- maven { url "https://maven.fabricmc.net/" }
- maven {
- url "https://maven.minecraftforge.net/"
- content {
- excludeGroupByRegex "org\\.eclipse\\.?.*"
- }
- }
-}
-
-dependencies {
- // shadowed
- include ('net.fabricmc:tiny-mappings-parser:0.3.0+build.17')
-
- // guaranteed to be there at runtime
- compileOnly ('cpw.mods:modlauncher:6.1.3')
- compileOnly ('org.spongepowered:mixin:0.8.2')
- compileOnly ('com.google.code.gson:gson:2.8.6')
- compileOnly ('com.google.guava:guava:21.0')
- compileOnly ('org.apache.logging.log4j:log4j-api:2.11.2')
-}
-
-jar {
- archiveClassifier = "slim"
-}
-
-shadowJar {
- archiveClassifier = ""
- configurations = [project.configurations.include]
- relocate "net.fabricmc.mapping", "dev.architectury.loom.forgeruntime.shadow.mapping"
- relocate "net.fabricmc.mappings", "dev.architectury.loom.forgeruntime.shadow.mappings"
-}
-
-assemble.dependsOn shadowJar
-
-spotless {
- java {
- licenseHeaderFile(rootProject.file("HEADER")).yearSeparator("-")
- targetExclude("**/loom/forgeruntime/mixin/MixinIntermediaryDevRemapper.java")
- }
-}
-
-checkstyle {
- configFile = rootProject.checkstyle.configFile
- toolVersion = rootProject.checkstyle.toolVersion
-}
-
-publishing {
- publications {
- maven(MavenPublication) {
- artifactId = 'architectury-loom-forge-runtime'
- shadow.component it
- }
- }
-
- repositories {
- if (System.getenv("MAVEN_PASS") != null) {
- maven {
- url = "https://deploy.shedaniel.me/"
- credentials {
- username = "shedaniel"
- password = System.getenv("MAVEN_PASS")
- }
- }
- }
- }
-}
diff --git a/forge-runtime/src/main/java/dev/architectury/loom/forgeruntime/YarnNamingService.java b/forge-runtime/src/main/java/dev/architectury/loom/forgeruntime/YarnNamingService.java
deleted file mode 100644
index 6a291de3..00000000
--- a/forge-runtime/src/main/java/dev/architectury/loom/forgeruntime/YarnNamingService.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * This file is part of fabric-loom, licensed under the MIT License (MIT).
- *
- * Copyright (c) 2020-2021 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 dev.architectury.loom.forgeruntime;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.AbstractMap;
-import java.util.Map;
-import java.util.Optional;
-import java.util.function.BiFunction;
-import java.util.function.Predicate;
-
-import cpw.mods.modlauncher.api.INameMappingService;
-
-import net.fabricmc.mapping.tree.TinyMappingFactory;
-import net.fabricmc.mapping.tree.TinyTree;
-
-public class YarnNamingService implements INameMappingService {
- private static final String PATH_TO_MAPPINGS = "fabric.yarnWithSrg.path";
- private TinyTree mappings = null;
-
- @Override
- public String mappingName() {
- return "srgtoyarn";
- }
-
- @Override
- public String mappingVersion() {
- return "1";
- }
-
- @Override
- public Map.Entry<String, String> understanding() {
- return new AbstractMap.SimpleImmutableEntry<>("srg", "mcp");
- }
-
- @Override
- public BiFunction<Domain, String, String> namingFunction() {
- return this::remap;
- }
-
- private TinyTree getMappings() {
- if (mappings != null) {
- return mappings;
- }
-
- String pathStr = System.getProperty(PATH_TO_MAPPINGS);
- if (pathStr == null) throw new RuntimeException("Missing system property '" + PATH_TO_MAPPINGS + "'!");
- Path path = Paths.get(pathStr);
-
- try (BufferedReader reader = Files.newBufferedReader(path)) {
- mappings = TinyMappingFactory.loadWithDetection(reader);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
-
- return mappings;
- }
-
- private String remap(Domain domain, String name) {
- TinyTree mappings = getMappings();
-
- switch (domain) {
- case CLASS:
- boolean dot = name.contains(".");
- return find(mappings.getClasses(), def -> maybeReplace(dot, def.getName("srg"), '/', '.').equals(name))
- .map(def -> maybeReplace(dot, def.getName("named"), '/', '.'))
- .orElse(name);
- case METHOD:
- return mappings.getClasses().stream()
- .flatMap(def -> def.getMethods().stream())
- .filter(def -> def.getName("srg").equals(name))
- .findAny()
- .map(def -> def.getName("named"))
- .orElse(name);
- case FIELD:
- return mappings.getClasses().stream()
- .flatMap(def -> def.getFields().stream())
- .filter(def -> def.getName("srg").equals(name))
- .findAny()
- .map(def -> def.getName("named"))
- .orElse(name);
- default:
- return name;
- }
- }
-
- // From CollectionUtil
- private static <E> Optional<E> find(Iterable<? extends E> collection, Predicate<? super E> filter) {
- for (E e : collection) {
- if (filter.test(e)) {
- return Optional.of(e);
- }
- }
-
- return Optional.empty();
- }
-
- private static String maybeReplace(boolean run, String s, char from, char to) {
- return run ? s.replace(from, to) : s;
- }
-}
diff --git a/forge-runtime/src/main/java/dev/architectury/loom/forgeruntime/mixin/ForgeLoomMixinRemapperInjectorService.java b/forge-runtime/src/main/java/dev/architectury/loom/forgeruntime/mixin/ForgeLoomMixinRemapperInjectorService.java
deleted file mode 100644
index 8b1839fb..00000000
--- a/forge-runtime/src/main/java/dev/architectury/loom/forgeruntime/mixin/ForgeLoomMixinRemapperInjectorService.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * This file is part of fabric-loom, licensed under the MIT License (MIT).
- *
- * Copyright (c) 2021 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 dev.architectury.loom.forgeruntime.mixin;
-
-import java.io.BufferedReader;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
-
-import cpw.mods.modlauncher.api.IEnvironment;
-import cpw.mods.modlauncher.api.ITransformationService;
-import cpw.mods.modlauncher.api.ITransformer;
-import cpw.mods.modlauncher.api.IncompatibleEnvironmentException;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.spongepowered.asm.mixin.MixinEnvironment;
-
-import net.fabricmc.mapping.tree.TinyMappingFactory;
-import net.fabricmc.mapping.tree.TinyTree;
-
-public class ForgeLoomMixinRemapperInjectorService implements ITransformationService {
- private static final Logger LOGGER = LogManager.getLogger("ForgeLoomRemapperInjector");
-
- @Override
- public String name() {
- return "ForgeLoomMixinRemapperInjector";
- }
-
- @Override
- public void initialize(IEnvironment environment) {
- }
-
- @Override
- public void beginScanning(IEnvironment environment) {
- LOGGER.debug("We will be injecting our remapper.");
-
- try {
- MixinEnvironment.getDefaultEnvironment().getRemappers().add(new MixinIntermediaryDevRemapper(Objects.requireNonNull(resolveMappings()), "intermediary", "named"));
- LOGGER.debug("We have successfully injected our remapper.");
- } catch (Exception e) {
- LOGGER.debug("We have failed to inject our remapper.", e);
- }
- }
-
- @Override
- public void onLoad(IEnvironment env, Set<String> otherServices) throws IncompatibleEnvironmentException {
- }
-
- @Override
- public List<ITransformer> transformers() {
- return Collections.emptyList();
- }
-
- private static TinyTree resolveMappings() {
- try {
- String srgNamedProperty = System.getProperty("mixin.forgeloom.inject.mappings.srg-named");
- Path path = Paths.get(srgNamedProperty);
-
- try (BufferedReader reader = Files.newBufferedReader(path)) {
- return TinyMappingFactory.loadWithDetection(reader);
- }
- } catch (Throwable throwable) {
- throwable.printStackTrace();
- return null;
- }
- }
-}
diff --git a/forge-runtime/src/main/java/dev/architectury/loom/forgeruntime/mixin/MixinIntermediaryDevRemapper.java b/forge-runtime/src/main/java/dev/architectury/loom/forgeruntime/mixin/MixinIntermediaryDevRemapper.java
deleted file mode 100644
index f331a9ca..00000000
--- a/forge-runtime/src/main/java/dev/architectury/loom/forgeruntime/mixin/MixinIntermediaryDevRemapper.java
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * 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 dev.architectury.loom.forgeruntime.mixin;
-
-import java.util.ArrayDeque;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Queue;
-import java.util.Set;
-
-import org.spongepowered.asm.mixin.transformer.ClassInfo;
-
-import net.fabricmc.mapping.tree.ClassDef;
-import net.fabricmc.mapping.tree.Descriptored;
-import net.fabricmc.mapping.tree.TinyTree;
-import net.fabricmc.mapping.util.MixinRemapper;
-
-public class MixinIntermediaryDevRemapper extends MixinRemapper {
- private static final String ambiguousName = "<ambiguous>"; // dummy value for ambiguous mappings - needs querying with additional owner and/or desc info
-
- private final Set<String> allPossibleClassNames = new HashSet<>();
- private final Map<String, String> nameFieldLookup = new HashMap<>();
- private final Map<String, String> nameMethodLookup = new HashMap<>();
- private final Map<String, String> nameDescFieldLookup = new HashMap<>();
- private final Map<String, String> nameDescMethodLookup = new HashMap<>();
-
- public MixinIntermediaryDevRemapper(TinyTree mappings, String from, String to) {
- super(mappings, from, to);
-
- for (ClassDef classDef : mappings.getClasses()) {
- allPossibleClassNames.add(classDef.getName(from));
- allPossibleClassNames.add(classDef.getName(to));
-
- putMemberInLookup(from, to, classDef.getFields(), nameFieldLookup, nameDescFieldLookup);
- putMemberInLookup(from, to, classDef.getMethods(), nameMethodLookup, nameDescMethodLookup);
- }
- }
-
- private <T extends Descriptored> void putMemberInLookup(String from, String to, Collection<T> descriptored, Map<String, String> nameMap, Map<String, String> nameDescMap) {
- for (T field : descriptored) {
- String nameFrom = field.getName(from);
- String descFrom = field.getDescriptor(from);
- String nameTo = field.getName(to);
-
- String prev = nameMap.putIfAbsent(nameFrom, nameTo);
-
- if (prev != null && prev != ambiguousName && !prev.equals(nameTo)) {
- nameDescMap.put(nameFrom, ambiguousName);
- }
-
- String key = getNameDescKey(nameFrom, descFrom);
- prev = nameDescMap.putIfAbsent(key, nameTo);
-
- if (prev != null && prev != ambiguousName && !prev.equals(nameTo)) {
- nameDescMap.put(key, ambiguousName);
- }
- }
- }
-
- private void throwAmbiguousLookup(String type, String name, String desc) {
- throw new RuntimeException("Ambiguous Mixin: " + type + " lookup " + name + " " + desc + " is not unique");
- }
-
- private String mapMethodNameInner(String owner, String name, String desc) {
- String result = super.mapMethodName(owner, name, desc);
-
- if (result.equals(name)) {
- String otherClass = unmap(owner);
- return super.mapMethodName(otherClass, name, unmapDesc(desc));
- } else {
- return result;
- }
- }
-
- private String mapFieldNameInner(String owner, String name, String desc) {
- String result = super.mapFieldName(owner, name, desc);
-
- if (result.equals(name)) {
- String otherClass = unmap(owner);
- return super.mapFieldName(otherClass, name, unmapDesc(desc));
- } else {
- return result;
- }
- }
-
- @Override
- public String mapMethodName(String owner, String name, String desc) {
- // handle unambiguous values early
- if (owner == null || allPossibleClassNames.contains(owner)) {
- String newName;
-
- if (desc == null) {
- newName = nameMethodLookup.get(name);
- } else {
- newName = nameDescMethodLookup.get(getNameDescKey(name, desc));
- }
-
- if (newName != null) {
- if (newName == ambiguousName) {
- if (owner == null) {
- throwAmbiguousLookup("method", name, desc);
- }
- } else {
- return newName;
- }
- } else if (owner == null) {
- return name;
- } else {
- // FIXME: this kind of namespace mixing shouldn't happen..
- // TODO: this should not repeat more than once
- String unmapOwner = unmap(owner);
- String unmapDesc = unmapDesc(desc);
-
- if (!unmapOwner.equals(owner) || !unmapDesc.equals(desc)) {
- return mapMethodName(unmapOwner, name, unmapDesc);
- } else {
- // take advantage of the fact allPossibleClassNames
- // and nameDescLookup cover all sets; if none are present,
- // we don't have a mapping for it.
- return name;
- }
- }
- }
-
- Queue<ClassInfo> classInfos = new ArrayDeque<>();
- classInfos.add(ClassInfo.forName(owner));
-
- while (!classInfos.isEmpty()) {
- ClassInfo c = classInfos.remove();
- String ownerO = unmap(c.getName());
- String s;
-
- if (!(s = mapMethodNameInner(ownerO, name, desc)).equals(name)) {
- return s;
- }
-
- if (!c.getSuperName().startsWith("java/")) {
- ClassInfo cSuper = c.getSuperClass();
-
- if (cSuper != null) {
- classInfos.add(cSuper);
- }
- }
-
- for (String itf : c.getInterfaces()) {
- if (itf.startsWith("java/")) {
- continue;
- }
-
- ClassInfo cItf = ClassInfo.forName(itf);
-
- if (cItf != null) {
- classInfos.add(cItf);
- }
- }
- }
-
- return name;
- }
-
- @Override
- public String mapFieldName(String owner, String name, String desc) {
- // handle unambiguous values early
- if (owner == null || allPossibleClassNames.contains(owner)) {
- String newName = nameDescFieldLookup.get(getNameDescKey(name, desc));
-
- if (newName != null) {
- if (newName == ambiguousName) {
- if (owner == null) {
- throwAmbiguousLookup("field", name, desc);
- }
- } else {
- return newName;
- }
- } else if (owner == null) {
- return name;
- } else {
- // FIXME: this kind of namespace mixing shouldn't happen..
- // TODO: this should not repeat more than once
- String unmapOwner = unmap(owner);
- String unmapDesc = unmapDesc(desc);
-
- if (!unmapOwner.equals(owner) || !unmapDesc.equals(desc)) {
- return mapFieldName(unmapOwner, name, unmapDesc);
- } else {
- // take advantage of the fact allPossibleClassNames
- // and nameDescLookup cover all sets; if none are present,
- // we don't have a mapping for it.
- return name;
- }
- }
- }
-
- ClassInfo c = ClassInfo.forName(map(owner));
-
- while (c != null) {
- String nextOwner = unmap(c.getName());
- String s;
-
- if (!(s = mapFieldNameInner(nextOwner, name, desc)).equals(name)) {
- return s;
- }
-
- if (c.getSuperName().startsWith("java/")) {
- break;
- }
-
- c = c.getSuperClass();
- }
-
- return name;
- }
-
- private static String getNameDescKey(String name, String descriptor) {
- return name + ";;" + descriptor;
- }
-}
diff --git a/forge-runtime/src/main/java/mcp/MethodsReturnNonnullByDefault.java b/forge-runtime/src/main/java/mcp/MethodsReturnNonnullByDefault.java
deleted file mode 100644
index bfa2d691..00000000
--- a/forge-runtime/src/main/java/mcp/MethodsReturnNonnullByDefault.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * This file is part of fabric-loom, licensed under the MIT License (MIT).
- *
- * Copyright (c) 2020-2021 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 mcp;
-
-/**
- * A dummy class, required for some Forge classes to load
- * because {@code MethodsReturnNonnullByDefault} in MCP has runtime retention.
- *
- * @deprecated Don't use this in your mods. JetBrains annotations are there for you.
- */
-@Deprecated
-public @interface MethodsReturnNonnullByDefault {
-}
diff --git a/forge-runtime/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.INameMappingService b/forge-runtime/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.INameMappingService
deleted file mode 100644
index ec41d220..00000000
--- a/forge-runtime/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.INameMappingService
+++ /dev/null
@@ -1 +0,0 @@
-dev.architectury.loom.forgeruntime.YarnNamingService
diff --git a/forge-runtime/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService b/forge-runtime/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService
deleted file mode 100644
index 679794d7..00000000
--- a/forge-runtime/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService
+++ /dev/null
@@ -1 +0,0 @@
-dev.architectury.loom.forgeruntime.mixin.ForgeLoomMixinRemapperInjectorService \ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
index 0b542936..0dfb5fc9 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,3 +1,2 @@
rootProject.name = "architectury-loom"
include "bootstrap"
-include "forge-runtime"
diff --git a/src/main/java/net/fabricmc/loom/LoomGradleExtension.java b/src/main/java/net/fabricmc/loom/LoomGradleExtension.java
index 6c3541e9..63ad8974 100644
--- a/src/main/java/net/fabricmc/loom/LoomGradleExtension.java
+++ b/src/main/java/net/fabricmc/loom/LoomGradleExtension.java
@@ -122,6 +122,16 @@ public interface LoomGradleExtension extends LoomGradleExtensionAPI {
return getDependencyManager().getProvider(McpConfigProvider.class);
}
+ @Override
+ default boolean isForgeAndOfficial() {
+ return isForge() && getMcpConfigProvider().isOfficial();
+ }
+
+ @Override
+ default boolean isForgeAndNotOfficial() {
+ return isForge() && !getMcpConfigProvider().isOfficial();
+ }
+
default SrgProvider getSrgProvider() {
return getDependencyManager().getProvider(SrgProvider.class);
}
diff --git a/src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java b/src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java
index 3d39cd51..ab5db4a8 100644
--- a/src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java
+++ b/src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java
@@ -195,6 +195,10 @@ public interface LoomGradleExtensionAPI {
return getPlatform().get() == ModPlatform.FORGE;
}
+ boolean isForgeAndOfficial();
+
+ boolean isForgeAndNotOfficial();
+
boolean supportsInclude();
void setGenerateSrgTiny(Boolean generateSrgTiny);
diff --git a/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java b/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java
index e6589da5..d23072f6 100644
--- a/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java
+++ b/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java
@@ -83,8 +83,9 @@ public final class CompileConfiguration {
extension.createLazyConfiguration(Constants.Configurations.FORGE_USERDEV).configure(configuration -> configuration.setTransitive(false));
extension.createLazyConfiguration(Constants.Configurations.FORGE_INSTALLER).configure(configuration -> configuration.setTransitive(false));
extension.createLazyConfiguration(Constants.Configurations.FORGE_UNIVERSAL).configure(configuration -> configuration.setTransitive(false));
- extension.createLazyConfiguration(Constants.Configurations.FORGE_DEPENDENCIES).configure(configuration -> configuration.setTransitive(false));
+ extension.createLazyConfiguration(Constants.Configurations.FORGE_DEPENDENCIES);
extension.createLazyConfiguration(Constants.Configurations.FORGE_NAMED).configure(configuration -> configuration.setTransitive(false));
+ extension.createLazyConfiguration(Constants.Configurations.FORGE_EXTRA).configure(configuration -> configuration.setTransitive(false));
extension.createLazyConfiguration(Constants.Configurations.MCP_CONFIG).configure(configuration -> configuration.setTransitive(false));
extendsFrom(Constants.Configurations.MINECRAFT_DEPENDENCIES, Constants.Configurations.FORGE_DEPENDENCIES, project);
@@ -93,6 +94,10 @@ public final class CompileConfiguration {
extendsFrom(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_NAMED, project);
extendsFrom(JavaPlugin.TEST_COMPILE_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_NAMED, project);
extendsFrom(JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_NAMED, project);
+ extendsFrom(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_EXTRA, project);
+ extendsFrom(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_EXTRA, project);
+ extendsFrom(JavaPlugin.TEST_COMPILE_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_EXTRA, project);
+ extendsFrom(JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_EXTRA, project);
}
if (extension.supportsInclude()) {
diff --git a/src/main/java/net/fabricmc/loom/configuration/ide/RunConfig.java b/src/main/java/net/fabricmc/loom/configuration/ide/RunConfig.java
index a8d77353..e630939c 100644
--- a/src/main/java/net/fabricmc/loom/configuration/ide/RunConfig.java
+++ b/src/main/java/net/fabricmc/loom/configuration/ide/RunConfig.java
@@ -24,21 +24,15 @@
package net.fabricmc.loom.configuration.ide;
-import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.HashMap;
import java.util.Objects;
-import java.util.UUID;
import java.util.function.Consumer;
-import java.util.function.Supplier;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import java.util.stream.StreamSupport;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
@@ -132,23 +126,6 @@ public class RunConfig {
runConfig.mainClass = "net.fabricmc.devlaunchinjector.Main";
runConfig.vmArgs = "-Dfabric.dli.config=" + encodeEscaped(extension.getFiles().getDevLauncherConfig().getAbsolutePath()) + " -Dfabric.dli.env=" + environment.toLowerCase();
-
- if (extension.isForge()) {
- List<String> modClasses = new ArrayList<>();
-
- for (Supplier<SourceSet> sourceSetSupplier : extension.getForgeLocalMods()) {
- SourceSet sourceSet = sourceSetSupplier.get();
- String sourceSetName = sourceSet.getName() + "_" + UUID.randomUUID().toString().replace("-", "").substring(0, 7);
-
- Stream.concat(
- Stream.of(sourceSet.getOutput().getResourcesDir().getAbsolutePath()),
- StreamSupport.stream(sourceSet.getOutput().getClassesDirs().spliterator(), false)
- .map(File::getAbsolutePath)
- ).map(s -> sourceSetName + "%%" + s).collect(Collectors.toCollection(() -> modClasses));
- }
-
- runConfig.envVariables.put("MOD_CLASSES", String.join(File.pathSeparator, modClasses));
- }
}
// Turns camelCase/PascalCase into Capital Case
@@ -162,6 +139,7 @@ public class RunConfig {
}
public static RunConfig runConfig(Project project, RunConfigSettings settings) {
+ settings.evaluateNow();
LoomGradleExtension extension = LoomGradleExtension.get(project);
String name = settings.getName();
@@ -195,6 +173,7 @@ public class RunConfig {
}
RunConfig runConfig = new RunConfig();
+ runConfig.envVariables.putAll(settings.envVariables);
runConfig.configName = configName;
populate(project, extension, runConfig, environment);
runConfig.ideaModuleName = getIdeaModuleName(project, sourceSet);
diff --git a/src/main/java/net/fabricmc/loom/configuration/ide/RunConfigSettings.java b/src/main/java/net/fabricmc/loom/configuration/ide/RunConfigSettings.java
index 28f2f2f6..c7c0792f 100644
--- a/src/main/java/net/fabricmc/loom/configuration/ide/RunConfigSettings.java
+++ b/src/main/java/net/fabricmc/loom/configuration/ide/RunConfigSettings.java
@@ -28,6 +28,7 @@ import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
@@ -36,6 +37,7 @@ import org.gradle.api.Named;
import org.gradle.api.Project;
import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.tasks.SourceSet;
+import org.jetbrains.annotations.ApiStatus;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.util.Constants;
@@ -96,6 +98,8 @@ public final class RunConfigSettings implements Named {
private final Project project;
private final LoomGradleExtension extension;
+ public final Map<String, String> envVariables = new HashMap<>();
+ private List<Runnable> evaluateLater = new ArrayList<>();
public RunConfigSettings(Project project, String baseName) {
this.baseName = baseName;
@@ -107,6 +111,20 @@ public final class RunConfigSettings implements Named {
runDir("run");
}
+ @ApiStatus.Internal
+ public void evaluateLater(Runnable runnable) {
+ this.evaluateLater.add(runnable);
+ }
+
+ @ApiStatus.Internal
+ public void evaluateNow() {
+ for (Runnable runnable : this.evaluateLater) {
+ runnable.run();
+ }
+
+ this.evaluateLater.clear();
+ }
+
public Project getProject() {
return project;
}
diff --git a/src/main/java/net/fabricmc/loom/configuration/ide/SetupIntelijRunConfigs.java b/src/main/java/net/fabricmc/loom/configuration/ide/SetupIntelijRunConfigs.java
index db815e94..52006eaa 100644
--- a/src/main/java/net/fabricmc/loom/configuration/ide/SetupIntelijRunConfigs.java
+++ b/src/main/java/net/fabricmc/loom/configuration/ide/SetupIntelijRunConfigs.java
@@ -46,13 +46,13 @@ public class SetupIntelijRunConfigs {
}
try {
- generate(project);
+ generate(project, false);
} catch (IOException e) {
throw new RuntimeException("Failed to generate run configs", e);
}
}
- private static void generate(Project project) throws IOException {
+ public static void generate(Project project, boolean override) throws IOException {
Project rootProject = project.getRootProject();
LoomGradleExtension extension = LoomGradleExtension.get(project);
@@ -82,6 +82,10 @@ public class SetupIntelijRunConfigs {
File runConfigs = new File(runConfigsDir, name + projectPath + ".xml");
String runConfigXml = config.fromDummy("idea_run_config_template.xml");
+ if (runConfigs.exists() && override) {
+ runConfigs.delete();
+ }
+
if (!runConfigs.exists()) {
FileUtils.writeStringToFile(runConfigs, runConfigXml, StandardCharsets.UTF_8);
}
diff --git a/src/main/java/net/fabricmc/loom/configuration/launch/LaunchProviderSettings.java b/src/main/java/net/fabricmc/loom/configuration/launch/LaunchProviderSettings.java
index 3a0c8eca..0ac814b5 100644
--- a/src/main/java/net/fabricmc/loom/configuration/launch/LaunchProviderSettings.java
+++ b/src/main/java/net/fabricmc/loom/configuration/launch/LaunchProviderSettings.java
@@ -33,11 +33,13 @@ import java.util.Map;
import org.gradle.api.Named;
import org.gradle.api.Project;
+import org.jetbrains.annotations.ApiStatus;
public class LaunchProviderSettings implements Named {
private final String name;
private List<Map.Entry<String, String>> properties = new ArrayList<>();
private List<String> arguments = new ArrayList<>();
+ private List<Runnable> evaluateLater = new ArrayList<>();
public LaunchProviderSettings(Project project, String name) {
this.name = name;
@@ -48,6 +50,20 @@ public class LaunchProviderSettings implements Named {
return name;
}
+ @ApiStatus.Internal
+ public void evaluateLater(Runnable runnable) {
+ this.evaluateLater.add(runnable);
+ }
+
+ @ApiStatus.Internal
+ public void evaluateNow() {
+ for (Runnable runnable : this.evaluateLater) {
+ runnable.run();
+ }
+
+ this.evaluateLater.clear();
+ }
+
public void arg(String argument) {
this.arguments.add(argument);
}
diff --git a/src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java b/src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java
index b7b37506..46d2e2ae 100644
--- a/src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java
+++ b/src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java
@@ -164,7 +164,7 @@ public class ModProcessor {
remapper.readClassPathAsync(mc);
- if (extension.isForge()) {
+ if (extension.isForgeAndNotOfficial()) {
remapper.readClassPathAsync(mappedProvider.getForgeSrgJar().toPath());
}
diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/LaunchProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/LaunchProvider.java
index 9fc55c0f..af90c480 100644
--- a/src/main/java/net/fabricmc/loom/configuration/providers/LaunchProvider.java
+++ b/src/main/java/net/fabricmc/loom/configuration/providers/LaunchProvider.java
@@ -60,31 +60,21 @@ public class LaunchProvider extends DependencyProvider {
.property("log4j.configurationFile", getAllLog4JConfigFiles())
.property("client", "java.library.path", getExtension().getMinecraftProvider().nativesDir().getAbsolutePath())
- .property("client", "org.lwjgl.librarypath", getExtension().getMinecraftProvider().nativesDir().getAbsolutePath())
+ .property("client", "org.lwjgl.librarypath", getExtension().getMinecraftProvider().nativesDir().getAbsolutePath());
- .argument("client", "--assetIndex")
- .argument("client", getExtension().getMinecraftProvider().getVersionInfo().assetIndex().fabricId(getExtension().getMinecraftProvider().minecraftVersion()))
- .argument("client", "--assetsDir")
- .argument("client", new File(getDirectories().getUserCache(), "assets").getAbsolutePath());
+ if (!getExtension().isForge()) {
+ launchConfig
+ .argument("client", "--assetIndex")
+ .argument("client", getExtension().getMinecraftProvider().getVersionInfo().assetIndex().fabricId(getExtension().getMinecraftProvider().minecraftVersion()))
+ .argument("client", "--assetsDir")
+ .argument("client", new File(getDirectories().getUserCache(), "assets").getAbsolutePath());
+ }
if (getExtension().isForge()) {
launchConfig
// Should match YarnNamingService.PATH_TO_MAPPINGS in forge-runtime
.property("fabric.yarnWithSrg.path", getExtension().getMappingsProvider().tinyMappingsWithSrg.toAbsolutePath().toString())
- .argument("--fml.mcVersion")
- .argument(getExtension().getMinecraftProvider().minecraftVersion())
- .argument("--fml.forgeVersion")
- .argument(getExtension().getForgeProvider().getVersion().getForgeVersion())
-
- .argument("client", "--launchTarget")
- .argument("client", "fmluserdevclient")
-
- .argument("server", "--launchTarget")
- .argument("server", "fmluserdevserver")
-
- .argument("data", "--launchTarget")
- .argument("data", "fmluserdevdata")
.argument("data", "--all")
.argument("data", "--mod")
.argument("data", String.join(",", getExtension().getDataGenMods()))
@@ -109,7 +99,18 @@ public class LaunchProvider extends DependencyProvider {
}
}
+ addDependency(Constants.Dependencies.DEV_LAUNCH_INJECTOR + Constants.Dependencies.Versions.DEV_LAUNCH_INJECTOR, Constants.Configurations.LOOM_DEVELOPMENT_DEPENDENCIES);
+ addDependency(Constants.Dependencies.TERMINAL_CONSOLE_APPENDER + Constants.Dependencies.Versions.TERMINAL_CONSOLE_APPENDER, Constants.Configurations.LOOM_DEVELOPMENT_DEPENDENCIES);
+ addDependency(Constants.Dependencies.JETBRAINS_ANNOTATIONS + Constants.Dependencies.Versions.JETBRAINS_ANNOTATIONS, JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME);
+
+ if (getExtension().isForge()) {
+ addDependency(Constants.Dependencies.FORGE_RUNTIME + Constants.Dependencies.Versions.FORGE_RUNTIME, Constants.Configurations.FORGE_EXTRA);
+ addDependency(Constants.Dependencies.JAVAX_ANNOTATIONS + Constants.Dependencies.Versions.JAVAX_ANNOTATIONS, JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME);
+ }
+
for (LaunchProviderSettings settings : getExtension().getLaunchConfigs()) {
+ settings.evaluateNow();
+
for (String argument : settings.getArguments()) {
launchConfig.argument(settings.getName(), argument);
}
@@ -129,16 +130,6 @@ public class LaunchProvider extends DependencyProvider {
writeLog4jConfig();
FileUtils.writeStringToFile(getDirectories().getDevLauncherConfig(), launchConfig.asString(), StandardCharsets.UTF_8);
- addDependency(Constants.Dependencies.DEV_LAUNCH_INJECTOR + Constants.Dependencies.Versions.DEV_LAUNCH_INJECTOR, Constants.Configurations.LOOM_DEVELOPMENT_DEPENDENCIES);
- addDependency(Constants.Dependencies.TERMINAL_CONSOLE_APPENDER + Constants.Dependencies.Versions.TERMINAL_CONSOLE_APPENDER, Constants.Configurations.LOOM_DEVELOPMENT_DEPENDENCIES);
- addDependency(Constants.Dependencies.JETBRAINS_ANNOTATIONS + Constants.Dependencies.Versions.JETBRAINS_ANNOTATIONS, JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME);
-
- if (getExtension().isForge()) {
- addDependency(Constants.Dependencies.FORGE_RUNTIME + Constants.Dependencies.Versions.FORGE_RUNTIME, JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME);
- addDependency(Constants.Dependencies.FORGE_RUNTIME + Constants.Dependencies.Versions.FORGE_RUNTIME, JavaPlugin.RUNTIME_ONLY_CONFIGURATION_NAME);
- addDependency(Constants.Dependencies.JAVAX_ANNOTATIONS + Constants.Dependencies.Versions.JAVAX_ANNOTATIONS, JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME);
- }
-
postPopulationScheduler.accept(this::writeRemapClassPath);
}
@@ -178,7 +169,7 @@ public class LaunchProvider extends DependencyProvider {
remapClasspath.add(getExtension().getMinecraftMappedProvider().getIntermediaryJar());
- if (getExtension().isForge()) {
+ if (getExtension().isForgeAndNotOfficial()) {
remapClasspath.add(getExtension().getMinecraftMappedProvider().getForgeIntermediaryJar());
}
diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/FieldMigratedMappingsProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/FieldMigratedMappingsProvider.java
index 518398df..2440f526 100644
--- a/src/main/java/net/fabricmc/loom/configuration/providers/forge/FieldMigratedMappingsProvider.java
+++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/FieldMigratedMappingsProvider.java
@@ -103,7 +103,7 @@ public class FieldMigratedMappingsProvider extends MappingsProviderImpl {
@Override
protected String createMappingsIdentifier(String mappingsName, String version, String classifier) {
- return super.createMappingsIdentifier(mappingsName, version, classifier) + "-forge-" + getExtension().getPatchProvider().forgeVersion;
+ return super.createMappingsIdentifier(mappingsName, version, classifier) + "-forge-" + getExtension().getForgeProvider().getVersion().getCombined();
}
@Override
@@ -116,7 +116,7 @@ public class FieldMigratedMappingsProvider extends MappingsProviderImpl {
if (getExtension().shouldGenerateSrgTiny()) {
if (Files.notExists(rawTinyMappingsWithSrg) || isRefreshDeps()) {
// Merge tiny mappings with srg
- SrgMerger.mergeSrg(getExtension().getSrgProvider().getSrg().toPath(), rawTinyMappings, rawTinyMappingsWithSrg, true);
+ SrgMerger.mergeSrg(this::getMojmapSrgFileIfPossible, getRawSrgFile(), rawTinyMappings, rawTinyMappingsWithSrg, true);
}
}
diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeProvider.java
index 50f6f82c..f9e1b9ef 100644
--- a/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeProvider.java
+++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeProvider.java
@@ -55,10 +55,13 @@ public class ForgeProvider extends DependencyProvider {
}
public static final class ForgeVersion {
+ private final String combined;
private final String minecraftVersion;
private final String forgeVersion;
public ForgeVersion(String combined) {
+ this.combined = combined;
+
if (combined == null) {
this.minecraftVersion = "NO_VERSION";
this.forgeVersion = "NO_VERSION";
@@ -76,6 +79,10 @@ public class ForgeProvider extends DependencyProvider {
}
}
+ public String getCombined() {
+ return combined;
+ }
+
public String getMinecraftVersion() {
return minecraftVersion;
}
diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeUserdevProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeUserdevProvider.java
index 26add71e..2dd91d9d 100644
--- a/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeUserdevProvider.java
+++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeUserdevProvider.java
@@ -25,6 +25,7 @@
package net.fabricmc.loom.configuration.providers.forge;
import java.io.File;
+import java.io.IOException;
import java.io.Reader;
import java.net.URI;
import java.nio.file.FileSystem;
@@ -32,19 +33,46 @@ import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
+import java.nio.file.StandardOpenOption;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
import java.util.function.Consumer;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
import com.google.common.collect.ImmutableMap;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import org.gradle.api.Project;
+import org.gradle.api.artifacts.Dependency;
+import org.gradle.api.artifacts.ModuleDependency;
+import org.gradle.api.artifacts.transform.InputArtifact;
+import org.gradle.api.artifacts.transform.TransformAction;
+import org.gradle.api.artifacts.transform.TransformOutputs;
+import org.gradle.api.artifacts.transform.TransformParameters;
+import org.gradle.api.artifacts.type.ArtifactTypeDefinition;
+import org.gradle.api.attributes.Attribute;
+import org.gradle.api.file.FileSystemLocation;
+import org.gradle.api.provider.Provider;
+import org.gradle.api.tasks.SourceSet;
import net.fabricmc.loom.configuration.DependencyProvider;
+import net.fabricmc.loom.configuration.ide.RunConfigSettings;
+import net.fabricmc.loom.configuration.launch.LaunchProviderSettings;
import net.fabricmc.loom.util.Constants;
+import net.fabricmc.loom.util.DependencyDownloader;
+import net.fabricmc.loom.util.FileSystemUtil;
public class ForgeUserdevProvider extends DependencyProvider {
private File userdevJar;
+ private JsonObject json;
+ private Consumer<Runnable> postPopulationScheduler;
public ForgeUserdevProvider(Project project) {
super(project);
@@ -52,6 +80,18 @@ public class ForgeUserdevProvider extends DependencyProvider {
@Override
public void provide(DependencyInfo dependency, Consumer<Runnable> postPopulationScheduler) throws Exception {
+ this.postPopulationScheduler = postPopulationScheduler;
+ Attribute<Boolean> transformed = Attribute.of("architectury-loom-forge-dependencies-transformed", Boolean.class);
+
+ getProject().getDependencies().registerTransform(RemoveNameProvider.class, spec -> {
+ spec.getFrom().attribute(transformed, false);
+ spec.getTo().attribute(transformed, true);
+ });
+
+ for (ArtifactTypeDefinition type : getProject().getDependencies().getArtifactTypes()) {
+ type.getAttributes().attribute(transformed, false);
+ }
+
userdevJar = new File(getDirectories().getProjectPersistentCache(), "forge-" + dependency.getDependency().getVersion() + "-userdev.jar");
Path configJson = getDirectories()
@@ -68,8 +108,6 @@ public class ForgeUserdevProvider extends DependencyProvider {
}
}
- JsonObject json;
-
try (Reader reader = Files.newBufferedReader(configJson)) {
json = new Gson().fromJson(reader, JsonObject.class);
}
@@ -79,19 +117,199 @@ public class ForgeUserdevProvider extends DependencyProvider {
addDependency(json.get("universal").getAsString(), Constants.Configurations.FORGE_UNIVERSAL);
for (JsonElement lib : json.get("libraries").getAsJsonArray()) {
+ Dependency dep = null;
+
if (lib.getAsString().startsWith("org.spongepowered:mixin:")) {
if (getExtension().isUseFabricMixin()) {
- addDependency("net.fabricmc:sponge-mixin:0.8.2+build.24", Constants.Configurations.FORGE_DEPENDENCIES);
- continue;
+ dep = addDependency("net.fabricmc:sponge-mixin:0.8.2+build.24", Constants.Configurations.FORGE_DEPENDENCIES);
}
}
- addDependency(lib.getAsString(), Constants.Configurations.FORGE_DEPENDENCIES);
+ if (dep == null) {
+ dep = addDependency(lib.getAsString(), Constants.Configurations.FORGE_DEPENDENCIES);
+ }
+
+ if (lib.getAsString().split(":").length < 4) {
+ ((ModuleDependency) dep).attributes(attributes -> {
+ attributes.attribute(transformed, true);
+ });
+ }
}
// TODO: Read launch configs from the JSON too
// TODO: Should I copy the patches from here as well?
// That'd require me to run the "MCP environment" fully up to merging.
+ for (Map.Entry<String, JsonElement> entry : json.getAsJsonObject("runs").entrySet()) {
+ LaunchProviderSettings launchSettings = getExtension().getLaunchConfigs().findByName(entry.getKey());
+ RunConfigSettings settings = getExtension().getRunConfigs().findByName(entry.getKey());
+ JsonObject value = entry.getValue().getAsJsonObject();
+
+ if (launchSettings != null) {
+ launchSettings.evaluateLater(() -> {
+ if (value.has("args")) {
+ launchSettings.arg(StreamSupport.stream(value.getAsJsonArray("args").spliterator(), false)
+ .map(JsonElement::getAsString)
+ .map(this::processTemplates)
+ .collect(Collectors.toList()));
+ }
+
+ if (value.has("props")) {
+ for (Map.Entry<String, JsonElement> props : value.getAsJsonObject("props").entrySet()) {
+ String string = processTemplates(props.getValue().getAsString());
+
+ launchSettings.property(props.getKey(), string);
+ }
+ }
+ });
+ }
+
+ if (settings != null) {
+ settings.evaluateLater(() -> {
+ settings.defaultMainClass(value.getAsJsonPrimitive("main").getAsString());
+ settings.vmArgs(StreamSupport.stream(value.getAsJsonArray("jvmArgs").spliterator(), false)
+ .map(JsonElement::getAsString)
+ .map(this::processTemplates)
+ .collect(Collectors.toList()));
+ for (Map.Entry<String, JsonElement> env : value.getAsJsonObject("env").entrySet()) {
+ String string = processTemplates(env.getValue().getAsString());
+
+ settings.envVariables.put(env.getKey(), string);
+ }
+ });
+ }
+ }
+ }
+
+ public abstract static class RemoveNameProvider implements TransformAction<TransformParameters.None> {
+ @InputArtifact
+ public abstract Provider<FileSystemLocation> getInput();
+
+ @Override
+ public void transform(TransformOutputs outputs) {
+ try {
+ File input = getInput().get().getAsFile();
+ //architectury-loom-forge-dependencies-transformed
+ File output = outputs.file(input.getName() + "-alfd-transformed.jar");
+ Files.copy(input.toPath(), output.toPath(), StandardCopyOption.REPLACE_EXISTING);
+
+ try (FileSystemUtil.FileSystemDelegate fs = FileSystemUtil.getJarFileSystem(output, false)) {
+ Path path = fs.get().getPath("META-INF/services/cpw.mods.modlauncher.api.INameMappingService");
+ Files.deleteIfExists(path);
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ public String processTemplates(String string) {
+ if (string.startsWith("{")) {
+ String key = string.substring(1, string.length() - 1);
+
+ // TODO: Look into ways to not hardcode
+ if (key.equals("runtime_classpath")) {
+ string = runtimeClasspath().stream()
+ .map(File::getAbsolutePath)
+ .collect(Collectors.joining(File.pathSeparator));
+ } else if (key.equals("minecraft_classpath")) {
+ string = minecraftClasspath().stream()
+ .map(File::getAbsolutePath)
+ .collect(Collectors.joining(File.pathSeparator));
+ } else if (key.equals("runtime_classpath_file")) {
+ Path path = getDirectories().getProjectPersistentCache().toPath().resolve("forge_runtime_classpath.txt");
+
+ postPopulationScheduler.accept(() -> {
+ try {
+ Files.writeString(path, runtimeClasspath().stream()
+ .map(File::getAbsolutePath)
+ .collect(Collectors.joining("\n")),
+ StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ });
+
+ string = path.toAbsolutePath().toString();
+ } else if (key.equals("minecraft_classpath_file")) {
+ Path path = getDirectories().getProjectPersistentCache().toPath().resolve("forge_minecraft_classpath.txt");
+
+ postPopulationScheduler.accept(() -> {
+ try {
+ Files.writeString(path, minecraftClasspath().stream()
+ .map(File::getAbsolutePath)
+ .collect(Collectors.joining("\n")),
+ StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ });
+
+ string = path.toAbsolutePath().toString();
+ } else if (key.equals("asset_index")) {
+ string = getExtension().getMinecraftProvider().getVersionInfo().assetIndex().fabricId(getExtension().getMinecraftProvider().minecraftVersion());
+ } else if (key.equals("assets_root")) {
+ string = new File(getDirectories().getUserCache(), "assets").getAbsolutePath();
+ } else if (key.equals("natives")) {
+ string = getMinecraftProvider().nativesDir().getAbsolutePath();
+ } else if (key.equals("source_roots")) {
+ List<String> modClasses = new ArrayList<>();
+
+ for (Supplier<SourceSet> sourceSetSupplier : getExtension().getForgeLocalMods()) {
+ SourceSet sourceSet = sourceSetSupplier.get();
+ String sourceSetName = sourceSet.getName() + "_" + UUID.randomUUID().toString().replace("-", "").substring(0, 7);
+
+ Stream.concat(
+ Stream.of(sourceSet.getOutput().getResourcesDir().getAbsolutePath()),
+ StreamSupport.stream(sourceSet.getOutput().getClassesDirs().spliterator(), false)
+ .map(File::getAbsolutePath)
+ ).map(s -> sourceSetName + "%%" + s).collect(Collectors.toCollection(() -> modClasses));
+ }
+
+ string = String.join(File.pathSeparator, modClasses);
+ } else if (json.has(key)) {
+ JsonElement element = json.get(key);
+
+ if (element.isJsonArray()) {
+ string = StreamSupport.stream(element.getAsJsonArray().spliterator(), false)
+ .map(JsonElement::getAsString)
+ .flatMap(str -> {
+ if (str.contains(":")) {
+ return DependencyDownloader.download(getProject(), str, false, false).getFiles().stream()
+ .map(File::getAbsolutePath)
+ .filter(dep -> !dep.contains("bootstraplauncher")); // TODO: Hack
+ }
+
+ return Stream.of(str);
+ })
+ .collect(Collectors.joining(File.pathSeparator));
+ } else {
+ string = element.toString();
+ }
+ } else {
+ getProject().getLogger().warn("Unrecognized template! " + string);
+ }
+ }
+
+ return string;
+ }
+
+ private Set<File> runtimeClasspath() {
+ // Should we actually include the runtime classpath here? Forge doesn't seem to be using this property anyways
+ Set<File> mcLibs = DependencyDownloader.resolveFiles(getProject().getConfigurations().getByName(Constants.Configurations.FORGE_DEPENDENCIES), true);
+ mcLibs.addAll(DependencyDownloader.resolveFiles(getProject().getConfigurations().getByName(Constants.Configurations.MINECRAFT_DEPENDENCIES), false));
+ mcLibs.addAll(DependencyDownloader.resolveFiles(getProject().getConfigurations().getByName(Constants.Configurations.FORGE_EXTRA), false));
+ mcLibs.addAll(DependencyDownloader.resolveFiles(getProject().getConfigurations().getByName(Constants.Configurations.MINECRAFT_NAMED), false));
+ mcLibs.addAll(DependencyDownloader.resolveFiles(getProject().getConfigurations().getByName(Constants.Configurations.FORGE_NAMED), false));
+ return mcLibs;
+ }
+
+ private Set<File> minecraftClasspath() {
+ Set<File> mcLibs = DependencyDownloader.resolveFiles(getProject().getConfigurations().getByName(Constants.Configurations.FORGE_DEPENDENCIES), true);
+ mcLibs.addAll(DependencyDownloader.resolveFiles(getProject().getConfigurations().getByName(Constants.Configurations.MINECRAFT_DEPENDENCIES), false));
+ mcLibs.addAll(DependencyDownloader.resolveFiles(getProject().getConfigurations().getByName(Constants.Configurations.FORGE_EXTRA), false));
+ mcLibs.addAll(DependencyDownloader.resolveFiles(getProject().getConfigurations().getByName(Constants.Configurations.MINECRAFT_NAMED), false));
+ mcLibs.addAll(DependencyDownloader.resolveFiles(getProject().getConfigurations().getByName(Constants.Configurations.FORGE_NAMED), false));
+ return mcLibs;
}
public File getUserdevJar() {
diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/McpConfigProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/McpConfigProvider.java
index 78375240..c8d7b0c0 100644
--- a/src/main/java/net/fabricmc/loom/configuration/providers/forge/McpConfigProvider.java
+++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/McpConfigProvider.java
@@ -24,19 +24,33 @@
package net.fabricmc.loom.configuration.providers.forge;
+import java.io.BufferedWriter;
import java.io.File;
+import java.io.IOException;
+import java.io.Reader;
+import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
+import java.nio.file.StandardOpenOption;
import java.util.function.Consumer;
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import org.apache.commons.io.IOUtils;
import org.gradle.api.Project;
+import org.zeroturnaround.zip.ZipUtil;
import net.fabricmc.loom.configuration.DependencyProvider;
import net.fabricmc.loom.util.Constants;
+import net.fabricmc.loom.util.FileSystemUtil;
public class McpConfigProvider extends DependencyProvider {
private File mcp;
+ private Path configJson;
+ private Path mappings;
+ private Boolean official;
+ private String mappingsPath;
public McpConfigProvider(Project project) {
super(project);
@@ -46,25 +60,63 @@ public class McpConfigProvider extends DependencyProvider {
public void provide(DependencyInfo dependency, Consumer<Runnable> postPopulationScheduler) throws Exception {
init(dependency.getDependency().getVersion());
- if (mcp.exists() && !isRefreshDeps()) {
- return; // No work for us to do here
- }
-
Path mcpZip = dependency.resolveFile().orElseThrow(() -> new RuntimeException("Could not resolve MCPConfig")).toPath();
- if (!mcp.exists() || isRefreshDeps()) {
+ if (!mcp.exists() || !Files.exists(configJson) || isRefreshDeps()) {
Files.copy(mcpZip, mcp.toPath(), StandardCopyOption.REPLACE_EXISTING);
+
+ try (FileSystemUtil.FileSystemDelegate fs = FileSystemUtil.getJarFileSystem(mcp, false)) {
+ Files.copy(fs.get().getPath("config.json"), configJson, StandardCopyOption.REPLACE_EXISTING);
+ }
}
+
+ JsonObject json;
+
+ try (Reader reader = Files.newBufferedReader(configJson)) {
+ json = new Gson().fromJson(reader, JsonObject.class);
+ }
+
+ official = json.has("official") && json.getAsJsonPrimitive("official").getAsBoolean();
+ mappingsPath = json.get("data").getAsJsonObject().get("mappings").getAsString();
}
- private void init(String version) {
- mcp = new File(getDirectories().getUserCache(), "mcp-" + version + ".zip");
+ private void init(String version) throws IOException {
+ File dir = getMinecraftProvider().dir("mcp/" + version);
+ mcp = new File(dir, "mcp.zip");
+ configJson = dir.toPath().resolve("mcp-config.json");
+ mappings = dir.toPath().resolve("mcp-config-mappings.txt");
+
+ if (isRefreshDeps()) {
+ Files.deleteIfExists(mappings);
+ }
+ }
+
+ public Path getMappings() {
+ if (Files.notExists(mappings)) {
+ if (!ZipUtil.handle(getMcp(), getMappingsPath(), (in, zipEntry) -> {
+ try (BufferedWriter writer = Files.newBufferedWriter(mappings, StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) {
+ IOUtils.copy(in, writer, StandardCharsets.UTF_8);
+ }
+ })) {
+ throw new IllegalStateException("Failed to find mappings '" + getMappingsPath() + "' in " + getMcp().getAbsolutePath() + "!");
+ }
+ }
+
+ return mappings;
}
public File getMcp() {
return mcp;
}
+ public boolean isOfficial() {
+ return official;
+ }
+
+ public String getMappingsPath() {
+ return mappingsPath;
+ }
+
@Override
public String getTargetConfig() {
return Constants.Configurations.MCP_CONFIG;
diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/MinecraftPatchedProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/MinecraftPatchedProvider.java
index e4d60816..ae988155 100644
--- a/src/main/java/net/fabricmc/loom/configuration/providers/forge/MinecraftPatchedProvider.java
+++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/MinecraftPatchedProvider.java
@@ -29,7 +29,6 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UncheckedIOException;
@@ -55,47 +54,63 @@ import java.util.function.Function;
import java.util.function.Predicate;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
+import java.util.regex.Pattern;
import java.util.stream.Stream;
import com.google.common.base.Preconditions;
-import com.google.common.base.Predicates;
import com.google.common.base.Stopwatch;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.hash.Hashing;
import com.google.common.io.ByteSource;
-import com.google.gson.JsonParser;
import de.oceanlabs.mcp.mcinjector.adaptors.ParameterAnnotationFixer;
+import dev.architectury.mappingslayers.api.mutable.MutableClassDef;
+import dev.architectury.mappingslayers.api.mutable.MutableMethodDef;
+import dev.architectury.mappingslayers.api.mutable.MutableTinyTree;
+import dev.architectury.mappingslayers.api.utils.MappingsUtils;
import dev.architectury.tinyremapper.InputTag;
import dev.architectury.tinyremapper.OutputConsumerPath;
import dev.architectury.tinyremapper.TinyRemapper;
import net.minecraftforge.binarypatcher.ConsoleTool;
-import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.FileUtils;
import org.apache.commons.io.output.NullOutputStream;
import org.gradle.api.Project;
import org.gradle.api.file.FileCollection;
import org.gradle.api.logging.LogLevel;
import org.gradle.api.logging.Logger;
+import org.gradle.api.logging.configuration.ShowStacktrace;
import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.tasks.SourceSet;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.ClassNode;
import org.zeroturnaround.zip.ZipUtil;
+import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.configuration.DependencyProvider;
+import net.fabricmc.loom.configuration.providers.MinecraftProvider;
import net.fabricmc.loom.configuration.providers.MinecraftProviderImpl;
+import net.fabricmc.loom.configuration.providers.mappings.GradleMappingContext;
+import net.fabricmc.loom.configuration.providers.mappings.MappingNamespace;
+import net.fabricmc.loom.configuration.providers.mappings.mojmap.MojangMappingLayer;
+import net.fabricmc.loom.configuration.providers.mappings.mojmap.MojangMappingsSpec;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.DependencyDownloader;
import net.fabricmc.loom.util.FileSystemUtil;
+import net.fabricmc.loom.util.MappingsProviderVerbose;
import net.fabricmc.loom.util.ThreadingUtils;
import net.fabricmc.loom.util.TinyRemapperMappingsHelper;
import net.fabricmc.loom.util.function.FsPathConsumer;
import net.fabricmc.loom.util.srg.InnerClassRemapper;
import net.fabricmc.loom.util.srg.SpecialSourceExecutor;
+import net.fabricmc.loom.util.srg.Tsrg2Utils;
import net.fabricmc.mapping.tree.TinyTree;
+import net.fabricmc.mappingio.MappingVisitor;
public class MinecraftPatchedProvider extends DependencyProvider {
private static final String LOOM_PATCH_VERSION_KEY = "Loom-Patch-Version";
@@ -115,11 +130,14 @@ public class MinecraftPatchedProvider extends DependencyProvider {
// Step 5: Remap Patched AT & Forge to Official (global or project)
private File minecraftMergedPatchedJar;
private File forgeMergedJar;
+ private File minecraftClientExtra;
private File projectAtHash;
private Set<File> projectAts = new HashSet<>();
private boolean atDirty = false;
private boolean filesDirty = false;
+ private Path mcpConfigMappings;
+ private Path[] mergedMojangTsrg2Files;
public MinecraftPatchedProvider(Project project) {
super(project);
@@ -161,34 +179,29 @@ public class MinecraftPatchedProvider extends DependencyProvider {
MinecraftProviderImpl minecraftProvider = getExtension().getMinecraftProvider();
PatchProvider patchProvider = getExtension().getPatchProvider();
String minecraftVersion = minecraftProvider.minecraftVersion();
- String patchId = "forge-" + patchProvider.forgeVersion;
-
- if (getExtension().isUseFabricMixin()) {
- patchId += "-fabric-mixin";
- }
+ String patchId = "forge-" + getExtension().getForgeProvider().getVersion().getCombined();
minecraftProvider.setJarSuffix(patchId);
- File globalCache = getDirectories().getUserCache();
+ File globalCache = getMinecraftProvider().dir("forge/" + getExtension().getForgeProvider().getVersion().getCombined());
File cache = usesProjectCache() ? getDirectories().getProjectPersistentCache() : globalCache;
- File globalDir = new File(globalCache, patchId);
- File projectDir = new File(cache, patchId);
- globalDir.mkdirs();
+ File projectDir = new File(cache, "forge/" + getExtension().getForgeProvider().getVersion().getCombined());
projectDir.mkdirs();
- minecraftClientSrgJar = new File(globalCache, "minecraft-" + minecraftVersion + "-client-srg.jar");
- minecraftServerSrgJar = new File(globalCache, "minecraft-" + minecraftVersion + "-server-srg.jar");
- minecraftClientPatchedSrgJar = new File(globalDir, "client-srg-patched.jar");
- minecraftServerPatchedSrgJar = new File(globalDir, "server-srg-patched.jar");
- minecraftMergedPatchedSrgJar = new File(globalDir, "merged-srg-patched.jar");
- forgeMergedJar = new File(globalDir, "forge-official.jar");
+ minecraftClientSrgJar = new File(globalCache, "minecraft-client-srg.jar");
+ minecraftServerSrgJar = new File(globalCache, "minecraft-server-srg.jar");
+ minecraftClientPatchedSrgJar = new File(globalCache, "client-srg-patched.jar");
+ minecraftServerPatchedSrgJar = new File(globalCache, "server-srg-patched.jar");
+ minecraftMergedPatchedSrgJar = new File(globalCache, "merged-srg-patched.jar");
+ forgeMergedJar = getExtension().isForgeAndOfficial() ? null : new File(globalCache, "forge-official.jar");
minecraftMergedPatchedSrgAtJar = new File(projectDir, "merged-srg-at-patched.jar");
minecraftMergedPatchedJar = new File(projectDir, "merged-patched.jar");
+ minecraftClientExtra = new File(globalCache, "forge-client-extra.jar");
- if (isRefreshDeps() || Stream.of(getGlobalCaches()).anyMatch(Predicates.not(File::exists))
+ if (isRefreshDeps() || Stream.of(getGlobalCaches()).anyMatch(((Predicate<File>) File::exists).negate())
|| !isPatchedJarUpToDate(minecraftMergedPatchedJar)) {
cleanAllCache();
- } else if (atDirty || Stream.of(getProjectCache()).anyMatch(Predicates.not(File::exists))) {
+ } else if (atDirty || Stream.of(getProjectCache()).anyMatch(((Predicate<File>) File::exists).negate())) {
cleanProjectCache();
}
}
@@ -213,14 +226,21 @@ public class MinecraftPatchedProvider extends DependencyProvider {
}
private File[] getGlobalCaches() {
- return new File[] {
+ File[] files = {
minecraftClientSrgJar,
minecraftServerSrgJar,
minecraftClientPatchedSrgJar,
minecraftServerPatchedSrgJar,
minecraftMergedPatchedSrgJar,
- forgeMergedJar,
+ minecraftClientExtra,
};
+
+ if (forgeMergedJar != null) {
+ Arrays.copyOf(files, files.length + 1);
+ files[files.length - 1] = forgeMergedJar;
+ }
+
+ return files;
}
public void cleanProjectCache() {
@@ -270,7 +290,7 @@ public class MinecraftPatchedProvider extends DependencyProvider {
accessTransformForge(getProject().getLogger());
}
- if (!forgeMergedJar.exists()) {
+ if (forgeMergedJar != null && !forgeMergedJar.exists()) {
this.dirty = true;
}
@@ -278,10 +298,25 @@ public class MinecraftPatchedProvider extends DependencyProvider {
if (dirty) {
remapPatchedJar(input, getProject().getLogger());
+
+ if (getExtension().isForgeAndOfficial()) {
+ fillClientExtraJar();
+ }
}
this.filesDirty = dirty;
this.dirty = false;
+
+ if (getExtension().isForgeAndOfficial()) {
+ addDependency(minecraftClientExtra, Constants.Configurations.FORGE_EXTRA);
+ }
+ }
+
+ private void fillClientExtraJar() throws IOException {
+ Files.deleteIfExists(minecraftClientExtra.toPath());
+ FileSystemUtil.getJarFileSystem(minecraftClientExtra, true).close();
+
+ copyNonClassFiles(getExtension().getMinecraftProvider().minecraftClientJar, minecraftClientExtra);
}
private TinyRemapper buildRemapper(Path input) throws IOException {
@@ -291,12 +326,16 @@ public class MinecraftPatchedProvider extends DependencyProvider {
.logger(getProject().getLogger()::lifecycle)
.logUnknownInvokeDynamic(false)
.withMappings(TinyRemapperMappingsHelper.create(mappingsWithSrg, "srg", "official", true))
- .withMappings(InnerClassRemapper.of(input, mappingsWithSrg, "srg", "official"))
+ .withMappings(InnerClassRemapper.of(InnerClassRemapper.readClassNames(input), mappingsWithSrg, "srg", "official"))
.renameInvalidLocals(true)
.rebuildSourceFilenames(true)
.fixPackageAccess(true)
.build();
+ if (getProject().getGradle().getStartParameter().getLogLevel().compareTo(LogLevel.LIFECYCLE) < 0) {
+ MappingsProviderVerbose.saveFile(remapper);
+ }
+
remapper.readClassPath(libraries);
remapper.prepareClasses();
return remapper;
@@ -309,39 +348,105 @@ public class MinecraftPatchedProvider extends DependencyProvider {
}
private void createSrgJars(Logger logger) throws Exception {
- McpConfigProvider mcpProvider = getExtension().getMcpConfigProvider();
-
MinecraftProviderImpl minecraftProvider = getExtension().getMinecraftProvider();
+ String dep = getExtension().isForgeAndOfficial() ? Constants.Dependencies.VIGNETTE + Constants.Dependencies.Versions.VIGNETTE
+ : Constants.Dependencies.SPECIAL_SOURCE + Constants.Dependencies.Versions.SPECIAL_SOURCE + ":shaded";
+ FileCollection classpath = DependencyDownloader.download(getProject(), dep, true, true);
+ produceSrgJar(getExtension().isForgeAndOfficial(), minecraftProvider.minecraftClientJar.toPath(), minecraftProvider.minecraftServerJar.toPath(), classpath);
+ }
- String[] mappingsPath = {null};
+ private void produceSrgJar(boolean official, Path clientJar, Path serverJar, FileCollection classpath) throws IOException {
+ Path tmpSrg = getToSrgMappings();
+ Set<File> mcLibs = getProject().getConfigurations().getByName(Constants.Configurations.MINECRAFT_DEPENDENCIES).resolve();
- if (!ZipUtil.handle(mcpProvider.getMcp(), "config.json", (in, zipEntry) -> {
- mappingsPath[0] = JsonParser.parseReader(new InputStreamReader(in)).getAsJsonObject().get("data").getAsJsonObject().get("mappings").getAsString();
- })) {
- throw new IllegalStateException("Failed to find 'config.json' in " + mcpProvider.getMcp().getAbsolutePath() + "!");
+ ThreadingUtils.run(() -> {
+ Files.copy(SpecialSourceExecutor.produceSrgJar(getProject(), "client", classpath, clientJar, tmpSrg), minecraftClientSrgJar.toPath());
+ }, () -> {
+ Files.copy(SpecialSourceExecutor.produceSrgJar(getProject(), "server", classpath, serverJar, tmpSrg), minecraftServerSrgJar.toPath());
+ });
+ }
+
+ private Path getToSrgMappings() throws IOException {
+ if (getExtension().isForgeAndOfficial()) {
+ return getMergedMojangTsrg2(true);
+ } else {
+ return getExtension().getMcpConfigProvider().getMappings();
}
+ }
- Path[] tmpSrg = {null};
+ private static void visitMojmap(MappingVisitor visitor, LoomGradleExtension extension) {
+ GradleMappingContext context = new GradleMappingContext(extension.getForgeProvider().getProject(), "tmp-mojmap");
+
+ try {
+ FileUtils.deleteDirectory(context.workingDirectory("/"));
+ MojangMappingLayer layer = new MojangMappingsSpec(() -> true).createLayer(context);
+ layer.visit(visitor);
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ } finally {
+ try {
+ FileUtils.deleteDirectory(context.workingDirectory("/"));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
- if (!ZipUtil.handle(mcpProvider.getMcp(), mappingsPath[0], (in, zipEntry) -> {
- tmpSrg[0] = Files.createTempFile(null, null);
+ public static Path getMojmapTsrg(LoomGradleExtension extension) throws IOException {
+ Path path = extension.getMinecraftProvider().dir("forge").toPath().resolve("mojmap.tsrg");
- try (BufferedWriter writer = Files.newBufferedWriter(tmpSrg[0])) {
- IOUtils.copy(in, writer, StandardCharsets.UTF_8);
+ if (Files.notExists(path)) {
+ try (BufferedWriter writer = Files.newBufferedWriter(path, StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) {
+ Tsrg2Utils.writeTsrg(visitor -> visitMojmap(visitor, extension),
+ MappingNamespace.NAMED.stringValue(), false, writer);
}
- })) {
- throw new IllegalStateException("Failed to find mappings '" + mappingsPath[0] + "' in " + mcpProvider.getMcp().getAbsolutePath() + "!");
}
- String atDependency = Constants.Dependencies.SPECIAL_SOURCE + Constants.Dependencies.Versions.SPECIAL_SOURCE + ":shaded";
- // Do getFiles() to resolve it before multithreading it
- FileCollection classpath = getProject().files(DependencyDownloader.download(getProject(), atDependency).getFiles());
+ return path;
+ }
- ThreadingUtils.run(() -> {
- Files.copy(SpecialSourceExecutor.produceSrgJar(getProject(), "client", classpath, minecraftProvider.minecraftClientJar.toPath(), tmpSrg[0]), minecraftClientSrgJar.toPath());
- }, () -> {
- Files.copy(SpecialSourceExecutor.produceSrgJar(getProject(), "server", classpath, minecraftProvider.minecraftServerJar.toPath(), tmpSrg[0]), minecraftServerSrgJar.toPath());
+ public static Path getMojmapTsrg2(LoomGradleExtension extension) throws IOException {
+ Path path = extension.getMinecraftProvider().dir("forge").toPath().resolve("mojmap.tsrg");
+
+ if (Files.notExists(path)) {
+ try (BufferedWriter writer = Files.newBufferedWriter(path, StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) {
+ Tsrg2Utils.writeTsrg2(visitor -> visitMojmap(visitor, extension), writer);
+ }
+ }
+
+ return path;
+ }
+
+ public Path getMergedMojangTsrg2(boolean hasParameters) throws IOException {
+ if (mergedMojangTsrg2Files == null) {
+ Path out = Files.createTempFile("merged-mojang-tsrg2", null);
+ Path outTrimmed = Files.createTempFile("merged-mojang-tsrg2-trimmed", null);
+ net.minecraftforge.installertools.ConsoleTool.main(new String[]{
+ "--task",
+ "MERGE_MAPPING",
+ "--left",
+ getExtension().getMcpConfigProvider().getMappings().toAbsolutePath().toString(),
+ "--right",
+ getMojmapTsrg(getExtension()).toAbsolutePath().toString(),
+ "--classes",
+ "--output",
+ out.toAbsolutePath().toString()
});
+
+ MutableTinyTree mappings = MappingsUtils.deserializeFromTsrg2(FileUtils.readFileToString(out.toFile(), StandardCharsets.UTF_8));
+
+ for (MutableClassDef classDef : mappings.getClassesMutable()) {
+ for (MutableMethodDef methodDef : classDef.getMethodsMutable()) {
+ methodDef.getParametersMutable().clear();
+ }
+ }
+
+ Files.writeString(outTrimmed, MappingsUtils.serializeToTsrg2(mappings), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
+
+ mergedMojangTsrg2Files = new Path[]{out, outTrimmed};
+ }
+
+ return mergedMojangTsrg2Files[hasParameters ? 0 : 1];
}
private void fixParameterAnnotation(File jarFile) throws Exception {
@@ -378,6 +483,60 @@ public class MinecraftPatchedProvider extends DependencyProvider {
getProject().getLogger().info(":fixing parameter annotations for " + jarFile.getAbsolutePath() + " in " + stopwatch);
}
+ private void deleteParameterNames(File jarFile) throws Exception {
+ getProject().getLogger().info(":deleting parameter names for " + jarFile.getAbsolutePath());
+ Stopwatch stopwatch = Stopwatch.createStarted();
+
+ try (FileSystem fs = FileSystems.newFileSystem(new URI("jar:" + jarFile.toURI()), ImmutableMap.of("create", false))) {
+ ThreadingUtils.TaskCompleter completer = ThreadingUtils.taskCompleter();
+ Pattern vignetteParameters = Pattern.compile("p_\\d+_");
+
+ for (Path file : (Iterable<? extends Path>) Files.walk(fs.getPath("/"))::iterator) {
+ if (!file.toString().endsWith(".class")) continue;
+
+ completer.add(() -> {
+ byte[] bytes = Files.readAllBytes(file);
+ ClassReader reader = new ClassReader(bytes);
+ ClassWriter writer = new ClassWriter(0);
+
+ reader.accept(new ClassVisitor(Opcodes.ASM9, writer) {
+ @Override
+ public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
+ return new MethodVisitor(Opcodes.ASM9, super.visitMethod(access, name, descriptor, signature, exceptions)) {
+ @Override
+ public void visitParameter(String name, int access) {
+ if (vignetteParameters.matcher(name).matches()) {
+ super.visitParameter(null, access);
+ } else {
+ super.visitParameter(name, access);
+ }
+ }
+
+ @Override
+ public void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end, int index) {
+ if (!vignetteParameters.matcher(name).matches()) {
+ super.visitLocalVariable(name, descriptor, signature, start, end, index);
+ }
+ }
+ };
+ }
+ }, 0);
+
+ byte[] out = writer.toByteArray();
+
+ if (!Arrays.equals(bytes, out)) {
+ Files.delete(file);
+ Files.write(file, out);
+ }
+ });
+ }
+
+ completer.complete();
+ }
+
+ getProject().getLogger().info(":deleting parameter names for " + jarFile.getAbsolutePath() + " in " + stopwatch);
+ }
+
private File getForgeJar() {
return getExtension().getForgeUniversalProvider().getForge();
}
@@ -453,8 +612,10 @@ public class MinecraftPatchedProvider extends DependencyProvider {
spec.setClasspath(classpath);
// if running with INFO or DEBUG logging
- if (getProject().getGradle().getStartParameter().getLogLevel().compareTo(LogLevel.LIFECYCLE) < 0) {
+ if (getProject().getGradle().getStartParameter().getShowStacktrace() != ShowStacktrace.INTERNAL_EXCEPTIONS
+ || getProject().getGradle().getStartParameter().getLogLevel().compareTo(LogLevel.LIFECYCLE) < 0) {
spec.setStandardOutput(System.out);
+ spec.setErrorOutput(System.err);
} else {
spec.setStandardOutput(NullOutputStream.NULL_OUTPUT_STREAM);
spec.setErrorOutput(NullOutputStream.NULL_OUTPUT_STREAM);
@@ -529,7 +690,12 @@ public class MinecraftPatchedProvider extends DependencyProvider {
ThreadingUtils.run(Environment.values(), environment -> {
copyMissingClasses(environment.srgJar.apply(this), environment.patchedSrgJar.apply(this));
- fixParameterAnnotation(environment.patchedSrgJar.apply(this));
+
+ if (getExtension().isForgeAndNotOfficial()) {
+ fixParameterAnnotation(environment.patchedSrgJar.apply(this));
+ } else {
+ deleteParameterNames(environment.patchedSrgJar.apply(this));
+ }
});
logger.lifecycle(":patched jars in " + stopwatch.stop());
@@ -565,9 +731,12 @@ public class MinecraftPatchedProvider extends DependencyProvider {
logger.lifecycle(":copying resources");
// Copy resources
- MinecraftProviderImpl minecraftProvider = getExtension().getMinecraftProvider();
- copyNonClassFiles(minecraftProvider.minecraftClientJar, minecraftMergedPatchedSrgJar);
- copyNonClassFiles(minecraftProvider.minecraftServerJar, minecraftMergedPatchedSrgJar);
+ if (getExtension().isForgeAndNotOfficial()) {
+ // Copy resources
+ MinecraftProviderImpl minecraftProvider = getExtension().getMinecraftProvider();
+ copyNonClassFiles(minecraftProvider.minecraftClientJar, minecraftMergedPatchedSrgJar);
+ copyNonClassFiles(minecraftProvider.minecraftServerJar, minecraftMergedPatchedSrgJar);
+ }
}
private void walkFileSystems(File source, File target, Predicate<Path> filter, Function<FileSystem, Iterable<Path>> toWalk, FsPathConsumer action)
@@ -576,6 +745,7 @@ public class MinecraftPatchedProvider extends DependencyProvider {
FileSystemUtil.FileSystemDelegate targetFs = FileSystemUtil.getJarFileSystem(target, false)) {
for (Path sourceDir : toWalk.apply(sourceFs.get())) {
Path dir = sourceDir.toAbsolutePath();
+ if (!Files.exists(dir)) continue;
Files.walk(dir)
.filter(Files::isRegularFile)
.filter(filter)
@@ -616,9 +786,12 @@ public class MinecraftPatchedProvider extends DependencyProvider {
}
private void copyNonClassFiles(File source, File target) throws IOException {
- Predicate<Path> filter = file -> {
+ Predicate<Path> filter = getExtension().isForgeAndOfficial() ? file -> {
String s = file.toString();
return !s.endsWith(".class");
+ } : file -> {
+ String s = file.toString();
+ return !s.endsWith(".class") || (s.startsWith("META-INF") && !s.startsWith("META-INF/services"));
};
walkFileSystems(source, target, filter, this::copyReplacing);
diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/PatchProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/PatchProvider.java
index 2d6d8f46..d49ae8b4 100644
--- a/src/main/java/net/fabricmc/loom/configuration/providers/forge/PatchProvider.java
+++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/PatchProvider.java
@@ -43,7 +43,6 @@ import net.fabricmc.loom.util.Constants;
public class PatchProvider extends DependencyProvider {
public Path clientPatches;
public Path serverPatches;
- public String forgeVersion;
public Path projectCacheFolder;
public PatchProvider(Project project) {
@@ -67,8 +66,7 @@ public class PatchProvider extends DependencyProvider {
}
private void init(String forgeVersion) {
- this.forgeVersion = forgeVersion;
- projectCacheFolder = getDirectories().getProjectPersistentCache().toPath().resolve(forgeVersion);
+ projectCacheFolder = getMinecraftProvider().dir("forge/" + forgeVersion).toPath();
clientPatches = projectCacheFolder.resolve("patches-client.lzma");
serverPatches = projectCacheFolder.resolve("patches-server.lzma");
diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/GradleMappingContext.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/GradleMappingContext.java
index 047d75af..e62e9e91 100644
--- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/GradleMappingContext.java
+++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/GradleMappingContext.java
@@ -25,9 +25,7 @@
package net.fabricmc.loom.configuration.providers.mappings;
import java.io.File;
-import java.io.IOException;
-import org.apache.commons.io.FileUtils;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.logging.Logger;
diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingsDependency.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingsDependency.java
index 878a37e4..ff48a5cf 100644
--- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingsDependency.java
+++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingsDependency.java
@@ -35,8 +35,19 @@ import java.util.Collections;
import java.util.Objects;
import java.util.Set;
+import org.gradle.api.Action;
import org.gradle.api.artifacts.Dependency;
+import org.gradle.api.artifacts.ExternalDependency;
+import org.gradle.api.artifacts.ExternalModuleDependency;
+import org.gradle.api.artifacts.ModuleIdentifier;
+import org.gradle.api.artifacts.ModuleVersionIdentifier;
+import org.gradle.api.artifacts.MutableVersionConstraint;
import org.gradle.api.artifacts.SelfResolvingDependency;
+import org.gradle.api.artifacts.VersionConstraint;
+import org.gradle.api.internal.artifacts.DefaultModuleIdentifier;
+import org.gradle.api.internal.artifacts.ModuleVersionSelectorStrictSpec;
+import org.gradle.api.internal.artifacts.dependencies.AbstractModuleDependency;
+import org.gradle.api.internal.artifacts.dependencies.DefaultMutableVersionConstraint;
import org.gradle.api.tasks.TaskDependency;
import org.zeroturnaround.zip.ByteSource;
import org.zeroturnaround.zip.ZipEntrySource;
@@ -48,7 +59,7 @@ import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch;
import net.fabricmc.mappingio.format.Tiny2Writer;
import net.fabricmc.mappingio.tree.MemoryMappingTree;
-public class LayeredMappingsDependency implements SelfResolvingDependency {
+public class LayeredMappingsDependency extends AbstractModuleDependency implements SelfResolvingDependency, ExternalModuleDependency {
private static final String GROUP = "loom";
private static final String MODULE = "mappings";
@@ -57,6 +68,7 @@ public class LayeredMappingsDependency implements SelfResolvingDependency {
private final String version;
public LayeredMappingsDependency(MappingContext mappingContext, LayeredMappingSpec layeredMappingSpec, String version) {
+ super(null);
this.mappingContext = mappingContext;
this.layeredMappingSpec = layeredMappingSpec;
this.version = version;
@@ -119,6 +131,21 @@ public class LayeredMappingsDependency implements SelfResolvingDependency {
}
@Override
+ public VersionConstraint getVersionConstraint() {
+ return new DefaultMutableVersionConstraint(getVersion());
+ }
+
+ @Override
+ public boolean matchesStrictly(ModuleVersionIdentifier identifier) {
+ return new ModuleVersionSelectorStrictSpec(this).isSatisfiedBy(identifier);
+ }
+
+ @Override
+ public ModuleIdentifier getModule() {
+ return DefaultModuleIdentifier.newId(GROUP, MODULE);
+ }
+
+ @Override
public boolean contentEquals(Dependency dependency) {
if (dependency instanceof LayeredMappingsDependency layeredMappingsDependency) {
return Objects.equals(layeredMappingsDependency.getVersion(), this.getVersion());
@@ -128,11 +155,35 @@ public class LayeredMappingsDependency implements SelfResolvingDependency {
}
@Override
- public Dependency copy() {
+ public boolean isChanging() {
+ return false;
+ }
+
+ @Override
+ public ExternalModuleDependency setChanging(boolean b) {
+ return this;
+ }
+
+ @Override
+ public boolean isForce() {
+ return false;
+ }
+
+ @Override
+ public ExternalDependency setForce(boolean b) {
+ return this;
+ }
+
+ @Override
+ public ExternalModuleDependency copy() {
return new LayeredMappingsDependency(mappingContext, layeredMappingSpec, version);
}
@Override
+ public void version(Action<? super MutableVersionConstraint> action) {
+ }
+
+ @Override
public String getReason() {
return null;
}
diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProviderImpl.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProviderImpl.java
index edddf340..eb6343cc 100644
--- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProviderImpl.java
+++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProviderImpl.java
@@ -27,6 +27,7 @@ package net.fabricmc.loom.configuration.providers.mappings;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
+import java.io.UncheckedIOException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystem;
@@ -151,7 +152,7 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings
if (getExtension().shouldGenerateSrgTiny()) {
if (Files.notExists(tinyMappingsWithSrg) || isRefreshDeps()) {
// Merge tiny mappings with srg
- SrgMerger.mergeSrg(getExtension().getSrgProvider().getSrg().toPath(), tinyMappings, tinyMappingsWithSrg, true);
+ SrgMerger.mergeSrg(this::getMojmapSrgFileIfPossible, getRawSrgFile(), tinyMappings, tinyMappingsWithSrg, true);
}
}
@@ -216,7 +217,27 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings
mappedProvider.provide(dependency, postPopulationScheduler);
}
- public void manipulateMappings(Path mappingsJar) throws IOException { }
+ protected Path getRawSrgFile() throws IOException {
+ LoomGradleExtension extension = getExtension();
+
+ if (extension.isForgeAndOfficial()) {
+ return patchedProvider.getMergedMojangTsrg2(false);
+ }
+
+ return extension.getSrgProvider().getSrg().toPath();
+ }
+
+ protected Path getMojmapSrgFileIfPossible() {
+ try {
+ LoomGradleExtension extension = getExtension();
+ return MinecraftPatchedProvider.getMojmapTsrg2(extension);
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+
+ public void manipulateMappings(Path mappingsJar) throws IOException {
+ }
private String getMappingsClassifier(DependencyInfo dependency, boolean isV2) {
String[] depStringSplit = dependency.getDepString().split(":");
@@ -248,7 +269,8 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings
}
}
- private void storeMappings(Project project, MinecraftProviderImpl minecraftProvider, Path yarnJar, Consumer<Runnable> postPopulationScheduler) throws IOException {
+ private void storeMappings(Project project, MinecraftProviderImpl minecraftProvider, Path yarnJar, Consumer<Runnable> postPopulationScheduler)
+ throws IOException {
project.getLogger().info(":extracting " + yarnJar.getFileName());
if (isMCP(yarnJar)) {
@@ -298,7 +320,7 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings
provider.provide(DependencyInfo.create(getProject(), configuration.getDependencies().iterator().next(), configuration), postPopulationScheduler);
}
- Path srgPath = provider.getSrg().toPath();
+ Path srgPath = getRawSrgFile();
TinyFile file = new MCPReader(intermediaryTinyPath, srgPath).read(mcpJar);
TinyV2Writer.write(file, tinyMappings);
}
@@ -426,20 +448,20 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings
try {
Command command = new CommandMergeTinyV2();
runCommand(command, intermediaryMappings.toAbsolutePath().toString(),
- yarnMappings.toAbsolutePath().toString(),
- newMergedMappings.toAbsolutePath().toString(),
- "intermediary", "official");
+ yarnMappings.toAbsolutePath().toString(),
+ newMergedMappings.toAbsolutePath().toString(),
+ "intermediary", "official");
} catch (Exception e) {
throw new RuntimeException("Could not merge mappings from " + intermediaryMappings.toString()
- + " with mappings from " + yarnMappings, e);
+ + " with mappings from " + yarnMappings, e);
}
}
private void suggestFieldNames(MinecraftProviderImpl minecraftProvider, Path oldMappings, Path newMappings) {
Command command = new CommandProposeFieldNames();
runCommand(command, minecraftProvider.getMergedJar().getAbsolutePath(),
- oldMappings.toAbsolutePath().toString(),
- newMappings.toAbsolutePath().toString());
+ oldMappings.toAbsolutePath().toString(),
+ newMappings.toAbsolutePath().toString());
}
private void runCommand(Command command, String... args) {
diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftMappedProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftMappedProvider.java
index a396e5b4..1407511e 100644
--- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftMappedProvider.java
+++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftMappedProvider.java
@@ -101,7 +101,7 @@ public class MinecraftMappedProvider extends DependencyProvider {
needToRemap = true;
}
- if (getExtension().isForge() && (!getForgeMappedJar().exists() || !getForgeIntermediaryJar().exists() || !getForgeSrgJar().exists() || isRefreshDeps() || isForgeAtDirty)) {
+ if (getExtension().isForgeAndNotOfficial() && (!getForgeMappedJar().exists() || !getForgeIntermediaryJar().exists() || !getForgeSrgJar().exists() || isRefreshDeps() || isForgeAtDirty)) {
needToRemap = true;
}
@@ -120,7 +120,7 @@ public class MinecraftMappedProvider extends DependencyProvider {
minecraftSrgJar.delete();
}
- if (getExtension().isForge()) {
+ if (getExtension().isForgeAndNotOfficial()) {
if (getForgeMappedJar().exists()) {
getForgeMappedJar().delete();
}
@@ -158,16 +158,18 @@ public class MinecraftMappedProvider extends DependencyProvider {
addDependencies(dependency, postPopulationScheduler);
- if (getExtension().isForge()) {
+ if (getExtension().isForgeAndNotOfficial()) {
getProject().getRepositories().flatDir(repository -> repository.dir(new File(getJarDirectory(getDirectories().getUserCache(), "mapped"), "forge")));
getProject().getDependencies().add(Constants.Configurations.FORGE_NAMED,
- getProject().getDependencies().module("net.minecraftforge-loom:forge:" + getJarVersionString("mapped")));
+ getProject().getDependencies().module("net.minecraftforge-loom:forge-mapped:" + getMinecraftProvider().minecraftVersion() + "/" + getExtension().getMappingsProvider().mappingsIdentifier() + "/forge"));
+ }
+ if (getExtension().isForge()) {
getProject().afterEvaluate(project -> {
if (!OperatingSystem.isCIBuild()) {
try {
- ForgeSourcesRemapper.addBaseForgeSources(project);
+ ForgeSourcesRemapper.addBaseForgeSources(project, getExtension().isForgeAndOfficial());
} catch (IOException e) {
e.printStackTrace();
}
@@ -241,13 +243,13 @@ public class MinecraftMappedProvider extends DependencyProvider {
forgeAssets.toFile().deleteOnExit();
Info vanilla = new Info(vanillaAssets, input, outputMapped, outputIntermediary, outputSrg);
- Info forge = getExtension().isForge() ? new Info(forgeAssets, inputForge, forgeOutputMapped, forgeOutputIntermediary, forgeOutputSrg) : null;
+ Info forge = getExtension().isForgeAndNotOfficial() ? new Info(forgeAssets, inputForge, forgeOutputMapped, forgeOutputIntermediary, forgeOutputSrg) : null;
TinyRemapper remapper = remapperArray[0] = buildRemapper();
assetsOut(input, vanillaAssets);
- if (getExtension().isForge()) {
+ if (getExtension().isForgeAndNotOfficial()) {
assetsOut(inputForge, forgeAssets);
}
@@ -271,6 +273,8 @@ public class MinecraftMappedProvider extends DependencyProvider {
}
public void remap(TinyRemapper remapper, Info vanilla, @Nullable Info forge, String fromM) throws IOException {
+ Set<String> classNames = getExtension().isForge() ? InnerClassRemapper.readClassNames(vanilla.input) : null;
+
for (String toM : getExtension().isForge() ? Arrays.asList("intermediary", "srg", "named") : Arrays.asList("intermediary", "named")) {
Path output = "named".equals(toM) ? vanilla.outputMapped : "srg".equals(toM) ? vanilla.outputSrg : vanilla.outputIntermediary;
Path outputForge = forge == null ? null : "named".equals(toM) ? forge.outputMapped : "srg".equals(toM) ? forge.outputSrg : forge.outputIntermediary;
@@ -285,7 +289,7 @@ public class MinecraftMappedProvider extends DependencyProvider {
remapper.readInputs(forgeTag, forge.input);
}
- remapper.replaceMappings(getMappings(vanilla.input, fromM, toM));
+ remapper.replaceMappings(getMappings(classNames, fromM, toM));
OutputRemappingHandler.remap(remapper, vanilla.assets, output, null, vanillaTag);
if (forge != null) {
@@ -325,13 +329,13 @@ public class MinecraftMappedProvider extends DependencyProvider {
return builder.build();
}
- public Set<IMappingProvider> getMappings(@Nullable Path fromJar, String fromM, String toM) throws IOException {
+ public Set<IMappingProvider> getMappings(@Nullable Set<String> fromClassNames, String fromM, String toM) throws IOException {
Set<IMappingProvider> providers = new HashSet<>();
providers.add(TinyRemapperMappingsHelper.create(getExtension().isForge() ? getExtension().getMappingsProvider().getMappingsWithSrg() : getExtension().getMappingsProvider().getMappings(), fromM, toM, true));
if (getExtension().isForge()) {
- if (fromJar != null) {
- providers.add(InnerClassRemapper.of(fromJar, getExtension().getMappingsProvider().getMappingsWithSrg(), fromM, toM));
+ if (fromClassNames != null) {
+ providers.add(InnerClassRemapper.of(fromClassNames, getExtension().getMappingsProvider().getMappingsWithSrg(), fromM, toM));
}
} else {
providers.add(out -> JSR_TO_JETBRAINS.forEach(out::acceptClass));
@@ -357,11 +361,16 @@ public class MinecraftMappedProvider extends DependencyProvider {
minecraftMappedJar = new File(getExtension().getMappingsProvider().mappingsWorkingDir().toFile(), "minecraft-mapped.jar");
inputJar = getExtension().isForge() ? mappingsProvider.patchedProvider.getMergedJar() : minecraftProvider.getMergedJar();
- if (getExtension().isForge()) {
+ if (getExtension().isForgeAndNotOfficial()) {
inputForgeJar = mappingsProvider.patchedProvider.getForgeMergedJar();
- forgeIntermediaryJar = new File(getExtension().getMappingsProvider().mappingsWorkingDir().toFile(), "forge-intermediary.jar");
- forgeSrgJar = new File(getExtension().getMappingsProvider().mappingsWorkingDir().toFile(), "forge-srg.jar");
+ forgeIntermediaryJar = new File(getExtension().getMappingsProvider().mappingsWorkingDir().toFile(), "forge/forge-intermediary.jar");
+ forgeSrgJar = new File(getExtension().getMappingsProvider().mappingsWorkingDir().toFile(), "forge/forge-srg.jar");
forgeMappedJar = new File(getExtension().getMappingsProvider().mappingsWorkingDir().toFile(), "forge/forge-mapped.jar");
+ } else {
+ inputForgeJar = null;
+ forgeIntermediaryJar = null;
+ forgeSrgJar = null;
+ forgeMappedJar = null;
}
}
diff --git a/src/main/java/net/fabricmc/loom/configuration/sources/ForgeSourcesRemapper.java b/src/main/java/net/fabricmc/loom/configuration/sources/ForgeSourcesRemapper.java
index db56ae5e..0e204eb4 100644
--- a/src/main/java/net/fabricmc/loom/configuration/sources/ForgeSourcesRemapper.java
+++ b/src/main/java/net/fabricmc/loom/configuration/sources/ForgeSourcesRemapper.java
@@ -58,8 +58,8 @@ 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", true).toPath();
+ public static void addBaseForgeSources(Project project, boolean isOfficial) throws IOException {
+ Path sourcesJar = GenerateSourcesTask.getMappedJarFileWithSuffix(project, "-sources.jar", !isOfficial).toPath();
if (!Files.exists(sourcesJar)) {
addForgeSources(project, sourcesJar);
@@ -185,7 +185,11 @@ public class ForgeSourcesRemapper {
// Distinct and add the srg jar at the top, so it gets prioritized
mercury.getClassPath().add(0, extension.getMinecraftMappedProvider().getSrgJar().toPath());
- mercury.getClassPath().add(0, extension.getMinecraftMappedProvider().getForgeSrgJar().toPath());
+
+ if (extension.isForgeAndNotOfficial()) {
+ mercury.getClassPath().add(0, extension.getMinecraftMappedProvider().getForgeSrgJar().toPath());
+ }
+
List<Path> newClassPath = mercury.getClassPath().stream()
.distinct()
.filter(Files::isRegularFile)
diff --git a/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java b/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java
index 5feeafbe..1f274f12 100644
--- a/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java
+++ b/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java
@@ -367,6 +367,16 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
}
@Override
+ public boolean isForgeAndOfficial() {
+ throw new RuntimeException("Yeah... something is really wrong");
+ }
+
+ @Override
+ public boolean isForgeAndNotOfficial() {
+ throw new RuntimeException("Yeah... something is really wrong");
+ }
+
+ @Override
protected String getMinecraftVersion() {
throw new RuntimeException("Yeah... something is really wrong");
}
diff --git a/src/main/java/net/fabricmc/loom/extension/MinecraftGradleExtension.java b/src/main/java/net/fabricmc/loom/extension/MinecraftGradleExtension.java
index 2921b451..5550cb8a 100644
--- a/src/main/java/net/fabricmc/loom/extension/MinecraftGradleExtension.java
+++ b/src/main/java/net/fabricmc/loom/extension/MinecraftGradleExtension.java
@@ -161,6 +161,18 @@ public class MinecraftGradleExtension implements LoomGradleExtensionAPI {
}
@Override
+ public boolean isForgeAndOfficial() {
+ reportDeprecation();
+ return parent.isForgeAndOfficial();
+ }
+
+ @Override
+ public boolean isForgeAndNotOfficial() {
+ reportDeprecation();
+ return parent.isForgeAndNotOfficial();
+ }
+
+ @Override
public boolean supportsInclude() {
reportDeprecation();
return parent.supportsInclude();
diff --git a/src/main/java/net/fabricmc/loom/task/LoomTasks.java b/src/main/java/net/fabricmc/loom/task/LoomTasks.java
index 883169f8..5f41b03e 100644
--- a/src/main/java/net/fabricmc/loom/task/LoomTasks.java
+++ b/src/main/java/net/fabricmc/loom/task/LoomTasks.java
@@ -25,6 +25,8 @@
package net.fabricmc.loom.task;
import java.io.File;
+import java.io.IOException;
+import java.io.UncheckedIOException;
import com.google.common.base.Preconditions;
import org.gradle.api.Project;
@@ -33,6 +35,7 @@ import org.gradle.api.tasks.TaskContainer;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.api.decompilers.LoomDecompiler;
import net.fabricmc.loom.configuration.ide.RunConfigSettings;
+import net.fabricmc.loom.configuration.ide.SetupIntelijRunConfigs;
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
import net.fabricmc.loom.decompilers.fernflower.FabricFernFlowerDecompiler;
import net.fabricmc.loom.util.Constants;
@@ -86,6 +89,19 @@ public final class LoomTasks {
t.dependsOn("downloadAssets");
t.setGroup(Constants.TaskGroup.IDE);
});
+
+ tasks.register("genIntelliJRuns", AbstractLoomTask.class, t -> {
+ t.setDescription("Generates IntelliJ IDEA launch configurations.");
+ t.dependsOn("downloadAssets");
+ t.setGroup("ide");
+ t.doLast(task -> {
+ try {
+ SetupIntelijRunConfigs.generate(task.getProject(), true);
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ });
+ });
}
private static void registerRunTasks(TaskContainer tasks, Project project) {
diff --git a/src/main/java/net/fabricmc/loom/task/MigrateMappingsTask.java b/src/main/java/net/fabricmc/loom/task/MigrateMappingsTask.java
index 6febed33..84cee1c9 100644
--- a/src/main/java/net/fabricmc/loom/task/MigrateMappingsTask.java
+++ b/src/main/java/net/fabricmc/loom/task/MigrateMappingsTask.java
@@ -187,9 +187,12 @@ public class MigrateMappingsTask extends AbstractLoomTask {
if (extension.isForge()) {
mercury.getClassPath().add(minecraftMappedProvider.getSrgJar().toPath());
- mercury.getClassPath().add(minecraftMappedProvider.getForgeMappedJar().toPath());
- mercury.getClassPath().add(minecraftMappedProvider.getForgeIntermediaryJar().toPath());
- mercury.getClassPath().add(minecraftMappedProvider.getForgeSrgJar().toPath());
+
+ if (extension.isForgeAndNotOfficial()) {
+ mercury.getClassPath().add(minecraftMappedProvider.getForgeMappedJar().toPath());
+ mercury.getClassPath().add(minecraftMappedProvider.getForgeIntermediaryJar().toPath());
+ mercury.getClassPath().add(minecraftMappedProvider.getForgeSrgJar().toPath());
+ }
}
mercury.getProcessors().add(MercuryRemapper.create(mappingSet));
diff --git a/src/main/java/net/fabricmc/loom/util/Constants.java b/src/main/java/net/fabricmc/loom/util/Constants.java
index f53dbf50..f3f0bf5a 100644
--- a/src/main/java/net/fabricmc/loom/util/Constants.java
+++ b/src/main/java/net/fabricmc/loom/util/Constants.java
@@ -79,6 +79,7 @@ public class Constants {
public static final String FORGE_UNIVERSAL = "forgeUniversal";
public static final String FORGE_DEPENDENCIES = "forgeDependencies";
public static final String FORGE_NAMED = "forgeNamed";
+ public static final String FORGE_EXTRA = "forgeExtra";
public static final String MAPPING_CONSTANTS = "mappingsConstants";
public static final String UNPICK_CLASSPATH = "unpick";
@@ -95,9 +96,10 @@ public class Constants {
public static final String TERMINAL_CONSOLE_APPENDER = "net.minecrell:terminalconsoleappender:";
public static final String JETBRAINS_ANNOTATIONS = "org.jetbrains:annotations:";
public static final String JAVAX_ANNOTATIONS = "com.google.code.findbugs:jsr305:"; // I hate that I have to add these.
- public static final String FORGE_RUNTIME = "dev.architectury:architectury-loom-forge-runtime:";
+ public static final String FORGE_RUNTIME = "dev.architectury:architectury-loom-runtime:";
public static final String ACCESS_TRANSFORMERS = "net.minecraftforge:accesstransformers:";
public static final String SPECIAL_SOURCE = "net.md-5:SpecialSource:";
+ public static final String VIGNETTE = "net.minecraftforge.lex:vignette:";
private Dependencies() {
}
@@ -111,9 +113,10 @@ public class Constants {
public static final String TERMINAL_CONSOLE_APPENDER = "1.2.0";
public static final String JETBRAINS_ANNOTATIONS = "19.0.0";
public static final String JAVAX_ANNOTATIONS = "3.0.2";
- public static final String FORGE_RUNTIME = "$LOOM_VERSION"; // replaced with current version at build time
- public static final String ACCESS_TRANSFORMERS = "2.2.0";
+ public static final String FORGE_RUNTIME = "1.0.1";
+ public static final String ACCESS_TRANSFORMERS = "3.0.1";
public static final String SPECIAL_SOURCE = "1.8.3";
+ public static final String VIGNETTE = "0.2.0.10";
private Versions() {
}
diff --git a/src/main/java/net/fabricmc/loom/util/DependencyDownloader.java b/src/main/java/net/fabricmc/loom/util/DependencyDownloader.java
index a7201cbb..85bcbe00 100644
--- a/src/main/java/net/fabricmc/loom/util/DependencyDownloader.java
+++ b/src/main/java/net/fabricmc/loom/util/DependencyDownloader.java
@@ -24,7 +24,14 @@
package net.fabricmc.loom.util;
+import java.io.File;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
import org.gradle.api.Project;
+import org.gradle.api.artifacts.Configuration;
+import org.gradle.api.artifacts.Dependency;
+import org.gradle.api.artifacts.ModuleDependency;
import org.gradle.api.file.FileCollection;
/**
@@ -41,8 +48,40 @@ public final class DependencyDownloader {
* @return the resolved files
*/
public static FileCollection download(Project project, String dependencyNotation) {
- var dependency = project.getDependencies().create(dependencyNotation);
- var config = project.getConfigurations().detachedConfiguration(dependency);
- return config.fileCollection(dep -> true);
+ return download(project, dependencyNotation, true, false);
+ }
+
+ public static FileCollection download(Project project, String dependencyNotation, boolean transitive, boolean resolve) {
+ Dependency dependency = project.getDependencies().create(dependencyNotation);
+
+ if (dependency instanceof ModuleDependency) {
+ ((ModuleDependency) dependency).setTransitive(transitive);
+ }
+
+ Configuration config = project.getConfigurations().detachedConfiguration(dependency);
+ config.setTransitive(transitive);
+ FileCollection files = config.fileCollection(dep -> true);
+
+ if (resolve) {
+ files = project.files(files.getFiles());
+ }
+
+ return files;
+ }
+
+ private static Set<File> resolve(Configuration configuration, boolean transitive) {
+ Configuration copy = configuration.copy();
+ copy.setTransitive(transitive);
+ Set<File> files = new LinkedHashSet<>(copy.resolve());
+
+ for (Configuration extendsForm : configuration.getExtendsFrom()) {
+ files.addAll(resolve(extendsForm, transitive));
+ }
+
+ return files;
+ }
+
+ public static Set<File> resolveFiles(Configuration configuration, boolean transitive) {
+ return resolve(configuration, transitive);
}
}
diff --git a/src/main/java/net/fabricmc/loom/util/MappingsProviderVerbose.java b/src/main/java/net/fabricmc/loom/util/MappingsProviderVerbose.java
new file mode 100644
index 00000000..6bdb7932
--- /dev/null
+++ b/src/main/java/net/fabricmc/loom/util/MappingsProviderVerbose.java
@@ -0,0 +1,71 @@
+package net.fabricmc.loom.util;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Set;
+
+import dev.architectury.mappingslayers.api.mutable.MutableTinyMetadata;
+import dev.architectury.mappingslayers.api.mutable.MutableTinyTree;
+import dev.architectury.mappingslayers.api.utils.MappingsUtils;
+import dev.architectury.tinyremapper.IMappingProvider;
+import dev.architectury.tinyremapper.TinyRemapper;
+
+public class MappingsProviderVerbose {
+ public static void saveFile(TinyRemapper providers) throws IOException {
+ try {
+ Field field = TinyRemapper.class.getDeclaredField("mappingProviders");
+ field.setAccessible(true);
+ Set<IMappingProvider> mappingProviders = (Set<IMappingProvider>) field.get(providers);
+ saveFile(mappingProviders);
+ } catch (IllegalAccessException | NoSuchFieldException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static void saveFile(Iterable<IMappingProvider> providers) throws IOException {
+ MutableTinyTree tree = MappingsUtils.create(MutableTinyMetadata.create(2, 0, Arrays.asList("from", "to"), new HashMap<>()));
+
+ for (IMappingProvider provider : providers) {
+ provider.load(new IMappingProvider.MappingAcceptor() {
+ @Override
+ public void acceptClass(String from, String to) {
+ tree.getOrCreateClass(from).setName(1, to);
+ }
+
+ @Override
+ public void acceptMethod(IMappingProvider.Member from, String to) {
+ tree.getOrCreateClass(from.owner).getOrCreateMethod(from.name, from.desc)
+ .setName(1, to);
+ }
+
+ @Override
+ public void acceptMethodArg(IMappingProvider.Member from, int lvIndex, String to) {
+ tree.getOrCreateClass(from.owner).getOrCreateMethod(from.name, from.desc)
+ .getOrCreateParameter(lvIndex, "")
+ .setName(1, to);
+ }
+
+ @Override
+ public void acceptMethodVar(IMappingProvider.Member from, int i, int i1, int i2, String s) {
+ // NO-OP
+ }
+
+ @Override
+ public void acceptField(IMappingProvider.Member from, String to) {
+ tree.getOrCreateClass(from.owner).getOrCreateField(from.name, from.desc)
+ .setName(1, to);
+ }
+ });
+ }
+
+ Path check = Files.createTempFile("CHECK", null);
+ Files.writeString(check, MappingsUtils.serializeToString(tree), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
+ System.out.println("Saved debug check mappings to " + check);
+ }
+}
diff --git a/src/main/java/net/fabricmc/loom/util/srg/InnerClassRemapper.java b/src/main/java/net/fabricmc/loom/util/srg/InnerClassRemapper.java
index 1949c55d..edc7e263 100644
--- a/src/main/java/net/fabricmc/loom/util/srg/InnerClassRemapper.java
+++ b/src/main/java/net/fabricmc/loom/util/srg/InnerClassRemapper.java
@@ -27,11 +27,14 @@ package net.fabricmc.loom.util.srg;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.util.HashSet;
import java.util.Iterator;
-import java.util.Map;
+import java.util.Set;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
+import com.google.common.collect.BiMap;
+import com.google.common.collect.HashBiMap;
import dev.architectury.tinyremapper.IMappingProvider;
import net.fabricmc.loom.util.FileSystemUtil;
@@ -40,22 +43,16 @@ import net.fabricmc.mapping.tree.ClassDef;
import net.fabricmc.mapping.tree.TinyTree;
public class InnerClassRemapper {
- public static IMappingProvider of(Path fromJar, TinyTree mappingsWithSrg, String from, String to) throws IOException {
+ public static IMappingProvider of(Set<String> fromClassNames, TinyTree mappingsWithSrg, String from, String to) throws IOException {
return sink -> {
- remapInnerClass(fromJar, mappingsWithSrg, from, to, sink::acceptClass);
+ remapInnerClass(fromClassNames, mappingsWithSrg, from, to, sink::acceptClass);
};
}
- private static void remapInnerClass(Path fromJar, TinyTree mappingsWithSrg, String from, String to, BiConsumer<String, String> action) {
- try (FileSystemDelegate system = FileSystemUtil.getJarFileSystem(fromJar, false)) {
- Map<String, String> availableClasses = mappingsWithSrg.getClasses().stream()
- .collect(Collectors.groupingBy(classDef -> classDef.getName(from),
- Collectors.<ClassDef, String>reducing(
- null,
- classDef -> classDef.getName(to),
- (first, last) -> last
- ))
- );
+ public static Set<String> readClassNames(Path jar) {
+ Set<String> set = new HashSet<>();
+
+ try (FileSystemDelegate system = FileSystemUtil.getJarFileSystem(jar, false)) {
Iterator<Path> iterator = Files.walk(system.get().getPath("/")).iterator();
while (iterator.hasNext()) {
@@ -65,21 +62,42 @@ public class InnerClassRemapper {
if (!Files.isDirectory(path) && name.contains("$") && name.endsWith(".class")) {
String className = name.substring(0, name.length() - 6);
+ set.add(className);
+ }
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
- if (!availableClasses.containsKey(className)) {
- String parentName = className.substring(0, className.indexOf('$'));
- String childName = className.substring(className.indexOf('$') + 1);
- String remappedParentName = availableClasses.getOrDefault(parentName, parentName);
- String remappedName = remappedParentName + "$" + childName;
+ return set;
+ }
+
+ private static void remapInnerClass(Set<String> classNames, TinyTree mappingsWithSrg, String from, String to, BiConsumer<String, String> action) {
+ BiMap<String, String> availableClasses = HashBiMap.create(mappingsWithSrg.getClasses().stream()
+ .collect(Collectors.groupingBy(classDef -> classDef.getName(from),
+ Collectors.<ClassDef, String>reducing(
+ null,
+ classDef -> classDef.getName(to),
+ (first, last) -> last
+ ))
+ ));
+
+ for (String className : classNames) {
+ if (!availableClasses.containsKey(className)) {
+ String parentName = className.substring(0, className.indexOf('$'));
+ String childName = className.substring(className.indexOf('$') + 1);
+ String remappedParentName = availableClasses.getOrDefault(parentName, parentName);
+ String remappedName = remappedParentName + "$" + childName;
- if (!className.equals(remappedName)) {
- action.accept(className, remappedName);
- }
+ if (!className.equals(remappedName)) {
+ if (availableClasses.containsValue(remappedName)) {
+ // https://github.com/MinecraftForge/MinecraftForge/blob/b027a92dd287d6810a9fdae4d4b1e1432d7dc9cc/patches/minecraft/net/minecraft/Util.java.patch#L8
+ action.accept(className, remappedName + "_UNBREAK");
+ } else {
+ action.accept(className, remappedName);
}
}
}
- } catch (IOException e) {
- throw new RuntimeException(e);
}
}
}
diff --git a/src/main/java/net/fabricmc/loom/util/srg/SpecialSourceExecutor.java b/src/main/java/net/fabricmc/loom/util/srg/SpecialSourceExecutor.java
index 8d5e7738..327825d3 100644
--- a/src/main/java/net/fabricmc/loom/util/srg/SpecialSourceExecutor.java
+++ b/src/main/java/net/fabricmc/loom/util/srg/SpecialSourceExecutor.java
@@ -39,6 +39,7 @@ import org.apache.commons.io.output.NullOutputStream;
import org.gradle.api.Project;
import org.gradle.api.file.FileCollection;
import org.gradle.api.logging.LogLevel;
+import org.gradle.api.logging.configuration.ShowStacktrace;
import org.zeroturnaround.zip.ZipUtil;
import net.fabricmc.loom.LoomGradleExtension;
@@ -87,8 +88,10 @@ public class SpecialSourceExecutor {
spec.setMain("net.md_5.specialsource.SpecialSource");
// if running with INFO or DEBUG logging
- if (project.getGradle().getStartParameter().getLogLevel().compareTo(LogLevel.LIFECYCLE) < 0) {
+ if (project.getGradle().getStartParameter().getShowStacktrace() != ShowStacktrace.INTERNAL_EXCEPTIONS
+ || project.getGradle().getStartParameter().getLogLevel().compareTo(LogLevel.LIFECYCLE) < 0) {
spec.setStandardOutput(System.out);
+ spec.setErrorOutput(System.err);
} else {
spec.setStandardOutput(NullOutputStream.NULL_OUTPUT_STREAM);
spec.setErrorOutput(NullOutputStream.NULL_OUTPUT_STREAM);
diff --git a/src/main/java/net/fabricmc/loom/util/srg/SrgMerger.java b/src/main/java/net/fabricmc/loom/util/srg/SrgMerger.java
index 39a2b57c..e2cf730f 100644
--- a/src/main/java/net/fabricmc/loom/util/srg/SrgMerger.java
+++ b/src/main/java/net/fabricmc/loom/util/srg/SrgMerger.java
@@ -27,15 +27,20 @@ package net.fabricmc.loom.util.srg;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
+import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Supplier;
+import com.google.common.base.MoreObjects;
import dev.architectury.mappingslayers.api.mutable.MutableClassDef;
+import dev.architectury.mappingslayers.api.mutable.MutableDescriptored;
import dev.architectury.mappingslayers.api.mutable.MutableFieldDef;
import dev.architectury.mappingslayers.api.mutable.MutableMethodDef;
import dev.architectury.mappingslayers.api.mutable.MutableTinyTree;
@@ -56,6 +61,7 @@ import net.fabricmc.mapping.tree.FieldDef;
import net.fabricmc.mapping.tree.MethodDef;
import net.fabricmc.mapping.tree.TinyMappingFactory;
import net.fabricmc.mapping.tree.TinyTree;
+import net.fabricmc.mappingio.format.TsrgReader;
import net.fabricmc.stitch.commands.tinyv2.TinyClass;
import net.fabricmc.stitch.commands.tinyv2.TinyField;
import net.fabricmc.stitch.commands.tinyv2.TinyFile;
@@ -80,8 +86,9 @@ public final class SrgMerger {
* @throws MappingException if the input tiny tree's default namespace is not 'official'
* or if an element mentioned in the SRG file does not have tiny mappings
*/
- public static void mergeSrg(Path srg, Path tiny, Path out, boolean lenient) throws IOException, MappingException {
- MappingSet arr = readSrg(srg);
+ public static void mergeSrg(Supplier<Path> mojmap, Path srg, Path tiny, Path out, boolean lenient) throws IOException, MappingException {
+ Map<String, List<MutableDescriptored>> addRegardlessSrgs = new HashMap<>();
+ MappingSet arr = readSrg(srg, mojmap, addRegardlessSrgs);
TinyTree foss;
try (BufferedReader reader = Files.newBufferedReader(tiny)) {
@@ -100,19 +107,19 @@ public final class SrgMerger {
List<TinyClass> classes = new ArrayList<>();
for (TopLevelClassMapping klass : arr.getTopLevelClassMappings()) {
- classToTiny(foss, namespaces, klass, classes::add, lenient);
+ classToTiny(addRegardlessSrgs, foss, namespaces, klass, classes::add, lenient);
}
TinyFile file = new TinyFile(header, classes);
TinyV2Writer.write(file, out);
}
- private static MappingSet readSrg(Path srg) throws IOException {
+ private static MappingSet readSrg(Path srg, Supplier<Path> mojmap, Map<String, List<MutableDescriptored>> addRegardlessSrgs) throws IOException {
try (BufferedReader reader = Files.newBufferedReader(srg)) {
String content = IOUtils.toString(reader);
if (content.startsWith("tsrg2")) {
- return readTsrg2(content);
+ return readTsrg2(content, mojmap, addRegardlessSrgs);
} else {
try (TSrgReader srgReader = new TSrgReader(new StringReader(content))) {
return srgReader.read();
@@ -121,31 +128,45 @@ public final class SrgMerger {
}
}
- private static MappingSet readTsrg2(String content) {
- MappingSet set = MappingSet.create();
- MutableTinyTree tree = MappingsUtils.deserializeFromTsrg2(content);
- int obfIndex = tree.getMetadata().index("obf");
- int srgIndex = tree.getMetadata().index("srg");
+ private static MappingSet readTsrg2(String content, Supplier<Path> mojmap, Map<String, List<MutableDescriptored>> addRegardlessSrgs) throws IOException {
+ MappingSet set;
- for (MutableClassDef classDef : tree.getClassesMutable()) {
- ClassMapping<?, ?> classMapping = set.getOrCreateClassMapping(classDef.getName(obfIndex));
- classMapping.setDeobfuscatedName(classDef.getName(srgIndex));
+ try (Tsrg2Utils.MappingsIO2LorenzWriter lorenzWriter = new Tsrg2Utils.MappingsIO2LorenzWriter(0, false)) {
+ TsrgReader.read(new StringReader(content), lorenzWriter);
+ set = lorenzWriter.read();
+ MutableTinyTree mojmapTree = readTsrg2ToTinyTree(mojmap.get());
- for (MutableFieldDef fieldDef : classDef.getFieldsMutable()) {
- FieldMapping fieldMapping = classMapping.getOrCreateFieldMapping(fieldDef.getName(obfIndex));
- fieldMapping.setDeobfuscatedName(fieldDef.getName(srgIndex));
- }
+ for (MutableClassDef classDef : mojmapTree.getClassesMutable()) {
+ for (MutableMethodDef methodDef : classDef.getMethodsMutable()) {
+ String name = methodDef.getName(0);
+
+ if (name.indexOf('<') != 0 && name.equals(methodDef.getName(1))) {
+ addRegardlessSrgs.computeIfAbsent(classDef.getName(0), $ -> new ArrayList<>()).add(methodDef);
+ }
+ }
- for (MutableMethodDef methodDef : classDef.getMethodsMutable()) {
- MethodMapping methodMapping = classMapping.getOrCreateMethodMapping(methodDef.getName(obfIndex), methodDef.getDescriptor(obfIndex));
- methodMapping.setDeobfuscatedName(methodDef.getName(srgIndex));
+ for (MutableFieldDef fieldDef : classDef.getFieldsMutable()) {
+ if (fieldDef.getName(0).equals(fieldDef.getName(1))) {
+ addRegardlessSrgs.computeIfAbsent(classDef.getName(0), $ -> new ArrayList<>()).add(fieldDef);
+ }
+ }
}
}
return set;
}
- private static void classToTiny(TinyTree foss, List<String> namespaces, ClassMapping<?, ?> klass, Consumer<TinyClass> classConsumer, boolean lenient) {
+ private static MutableTinyTree readTsrg2ToTinyTree(Path path) throws IOException {
+ MutableTinyTree tree;
+
+ try (BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
+ tree = MappingsUtils.deserializeFromTsrg2(IOUtils.toString(reader));
+ }
+
+ return tree;
+ }
+
+ private static void classToTiny(Map<String, List<MutableDescriptored>> addRegardlessSrgs, TinyTree foss, List<String> namespaces, ClassMapping<?, ?> klass, Consumer<TinyClass> classConsumer, boolean lenient) {
String obf = klass.getFullObfuscatedName();
String srg = klass.getFullDeobfuscatedName();
ClassDef classDef = foss.getDefaultNamespaceClassMap().get(obf);
@@ -170,9 +191,17 @@ public final class SrgMerger {
MethodDef def = CollectionUtil.find(
classDef.getMethods(),
m -> m.getName("official").equals(method.getObfuscatedName()) && m.getDescriptor("official").equals(method.getObfuscatedDescriptor())
- ).orElse(nullOrThrow(lenient, () -> new MappingException("Missing method: " + method.getFullObfuscatedName() + " (srg: " + method.getFullDeobfuscatedName() + ")")));
+ ).orElse(null);
- if (def == null) continue;
+ if (def == null) {
+ if (tryMatchRegardlessSrgs(addRegardlessSrgs, namespaces, obf, methods, method)) continue;
+
+ if (!lenient) {
+ throw new MappingException("Missing method: " + method.getFullObfuscatedName() + " (srg: " + method.getFullDeobfuscatedName() + ")");
+ }
+
+ continue;
+ }
List<String> methodNames = CollectionUtil.map(
namespaces,
@@ -207,8 +236,34 @@ public final class SrgMerger {
classConsumer.accept(tinyClass);
for (InnerClassMapping innerKlass : klass.getInnerClassMappings()) {
- classToTiny(foss, namespaces, innerKlass, classConsumer, lenient);
+ classToTiny(addRegardlessSrgs, foss, namespaces, innerKlass, classConsumer, lenient);
+ }
+ }
+
+ private static boolean tryMatchRegardlessSrgs(Map<String, List<MutableDescriptored>> addRegardlessSrgs, List<String> namespaces, String obf,
+ List<TinyMethod> methods, MethodMapping method) {
+ List<MutableDescriptored> mutableDescriptoredList = addRegardlessSrgs.get(obf);
+
+ if (!method.getDeobfuscatedName().equals(method.getObfuscatedName())) {
+ for (MutableDescriptored descriptored : MoreObjects.firstNonNull(mutableDescriptoredList, Collections.<MutableDescriptored>emptyList())) {
+ if (descriptored.isMethod() && descriptored.getName(0).equals(method.getObfuscatedName()) && descriptored.getDescriptor(0).equals(method.getObfuscatedDescriptor())) {
+ List<String> methodNames = CollectionUtil.map(
+ namespaces,
+ namespace -> "srg".equals(namespace) ? method.getDeobfuscatedName() : method.getObfuscatedName()
+ );
+
+ methods.add(new TinyMethod(
+ method.getObfuscatedDescriptor(), methodNames,
+ /* parameters */ Collections.emptyList(),
+ /* locals */ Collections.emptyList(),
+ /* comments */ Collections.emptyList()
+ ));
+ return true;
+ }
+ }
}
+
+ return false;
}
@Nullable
diff --git a/src/main/java/net/fabricmc/loom/util/srg/Tsrg2Utils.java b/src/main/java/net/fabricmc/loom/util/srg/Tsrg2Utils.java
new file mode 100644
index 00000000..e6ddf578
--- /dev/null
+++ b/src/main/java/net/fabricmc/loom/util/srg/Tsrg2Utils.java
@@ -0,0 +1,209 @@
+package net.fabricmc.loom.util.srg;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.UncheckedIOException;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Consumer;
+
+import dev.architectury.mappingslayers.api.mutable.MutableClassDef;
+import dev.architectury.mappingslayers.api.mutable.MutableFieldDef;
+import dev.architectury.mappingslayers.api.mutable.MutableMethodDef;
+import dev.architectury.mappingslayers.api.mutable.MutableParameterDef;
+import dev.architectury.mappingslayers.api.mutable.MutableTinyMetadata;
+import dev.architectury.mappingslayers.api.mutable.MutableTinyTree;
+import dev.architectury.mappingslayers.api.utils.MappingsUtils;
+import org.cadixdev.lorenz.MappingSet;
+import org.cadixdev.lorenz.io.srg.tsrg.TSrgWriter;
+import org.cadixdev.lorenz.model.ClassMapping;
+import org.cadixdev.lorenz.model.MethodMapping;
+
+import net.fabricmc.mappingio.MappingVisitor;
+import net.fabricmc.mappingio.MappingWriter;
+import net.fabricmc.mappingio.adapter.ForwardingMappingVisitor;
+import net.fabricmc.mappingio.format.TsrgReader;
+import net.fabricmc.mappingio.tree.MappingTree;
+import net.fabricmc.mappingio.tree.MemoryMappingTree;
+
+public class Tsrg2Utils {
+ public static void convert(Reader reader, Writer writer) throws IOException {
+ writeTsrg(visitor -> {
+ try {
+ TsrgReader.read(reader, visitor);
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }, "srg", false, writer);
+ }
+
+ public static void writeTsrg(Consumer<MappingVisitor> visitorConsumer, String dstNamespace, boolean applyParameterMappings, Writer writer)
+ throws IOException {
+ MappingSet set;
+
+ try (MappingsIO2LorenzWriter lorenzWriter = new MappingsIO2LorenzWriter(dstNamespace, applyParameterMappings)) {
+ visitorConsumer.accept(lorenzWriter);
+ set = lorenzWriter.read();
+ }
+
+ try (TSrgWriter w = new TSrgWriter(writer)) {
+ w.write(set);
+ }
+ }
+
+ public static void writeTsrg2(Consumer<MappingVisitor> visitorConsumer, Writer writer)
+ throws IOException {
+ MutableTinyTree tree;
+
+ try (MappingsIO2MappingsUtils w = new MappingsIO2MappingsUtils()) {
+ visitorConsumer.accept(w);
+ tree = w.read();
+ }
+
+ writer.write(MappingsUtils.serializeToTsrg2(tree));
+ }
+
+ // TODO Move this elsewhere
+ public abstract static class MappingsIO2Others extends ForwardingMappingVisitor implements MappingWriter {
+ public MappingsIO2Others() {
+ super(new MemoryMappingTree());
+ }
+
+ public MappingTree tree() {
+ return (MappingTree) next;
+ }
+
+ @Override
+ public void close() throws IOException {
+ MappingTree tree = tree();
+ List<String> names = new ArrayList<>();
+
+ for (MappingTree.ClassMapping aClass : tree.getClasses()) {
+ names.add(aClass.getSrcName());
+ }
+
+ for (String name : names) {
+ tree.removeClass(name);
+ }
+ }
+ }
+
+ public static class MappingsIO2LorenzWriter extends MappingsIO2Others {
+ private final Object dstNamespaceUnresolved;
+ private int dstNamespace;
+ private boolean applyParameterMappings;
+
+ public MappingsIO2LorenzWriter(int dstNamespace, boolean applyParameterMappings) {
+ this.dstNamespaceUnresolved = dstNamespace;
+ this.applyParameterMappings = applyParameterMappings;
+ }
+
+ public MappingsIO2LorenzWriter(String dstNamespace, boolean applyParameterMappings) {
+ this.dstNamespaceUnresolved = dstNamespace;
+ this.applyParameterMappings = applyParameterMappings;
+ }
+
+ @Override
+ public void visitNamespaces(String srcNamespace, List<String> dstNamespaces) throws IOException {
+ super.visitNamespaces(srcNamespace, dstNamespaces);
+ this.dstNamespace = dstNamespaceUnresolved instanceof Integer ? (Integer) dstNamespaceUnresolved : dstNamespaces.indexOf((String) dstNamespaceUnresolved);
+ }
+
+ public MappingSet read() throws IOException {
+ return this.read(MappingSet.create());
+ }
+
+ public MappingSet read(final MappingSet mappings) throws IOException {
+ MappingTree tree = tree();
+
+ for (MappingTree.ClassMapping aClass : tree.getClasses()) {
+ ClassMapping<?, ?> lClass = mappings.getOrCreateClassMapping(aClass.getSrcName())
+ .setDeobfuscatedName(aClass.getDstName(dstNamespace));
+
+ for (MappingTree.FieldMapping aField : aClass.getFields()) {
+ String srcDesc = aField.getSrcDesc();
+
+ if (srcDesc == null || srcDesc.isEmpty()) {
+ lClass.getOrCreateFieldMapping(aField.getSrcName())
+ .setDeobfuscatedName(aField.getDstName(dstNamespace));
+ } else {
+ lClass.getOrCreateFieldMapping(aField.getSrcName(), srcDesc)
+ .setDeobfuscatedName(aField.getDstName(dstNamespace));
+ }
+ }
+
+ for (MappingTree.MethodMapping aMethod : aClass.getMethods()) {
+ MethodMapping lMethod = lClass.getOrCreateMethodMapping(aMethod.getSrcName(), aMethod.getSrcDesc())
+ .setDeobfuscatedName(aMethod.getDstName(dstNamespace));
+
+ if (applyParameterMappings) {
+ for (MappingTree.MethodArgMapping aArg : aMethod.getArgs()) {
+ lMethod.getOrCreateParameterMapping(aArg.getLvIndex())
+ .setDeobfuscatedName(aArg.getDstName(dstNamespace));
+ }
+ }
+ }
+ }
+
+ return mappings;
+ }
+ }
+
+ public static class MappingsIO2MappingsUtils extends MappingsIO2Others {
+ public MutableTinyTree read() {
+ MappingTree tree = tree();
+ int dstNamesSize = tree.getDstNamespaces().size();
+ List<String> namespaces = new ArrayList<>();
+ namespaces.add(tree.getSrcNamespace());
+ namespaces.addAll(tree.getDstNamespaces());
+ Map<String, String> properties = new HashMap<>();
+
+ for (Map.Entry<String, String> entry : tree.getMetadata()) {
+ properties.put(entry.getKey(), entry.getValue());
+ }
+
+ MutableTinyTree out = MappingsUtils.create(MutableTinyMetadata.create(2, 0, namespaces, properties));
+
+ for (MappingTree.ClassMapping aClass : tree.getClasses()) {
+ MutableClassDef classDef = out.getOrCreateClass(aClass.getSrcName());
+ classDef.setComment(aClass.getComment());
+
+ for (int i = 0; i < dstNamesSize; i++) {
+ classDef.setName(i + 1, aClass.getDstName(i));
+ }
+
+ for (MappingTree.MethodMapping aMethod : aClass.getMethods()) {
+ MutableMethodDef methodDef = classDef.getOrCreateMethod(aMethod.getSrcName(), aMethod.getSrcDesc());
+ methodDef.setComment(aMethod.getComment());
+
+ for (int i = 0; i < dstNamesSize; i++) {
+ methodDef.setName(i + 1, aMethod.getDstName(i));
+ }
+
+ for (MappingTree.MethodArgMapping aMethodArg : aMethod.getArgs()) {
+ MutableParameterDef parameterDef = methodDef.getOrCreateParameter(aMethodArg.getLvIndex(), aMethodArg.getSrcName());
+ parameterDef.setComment(aMethodArg.getComment());
+
+ for (int i = 0; i < dstNamesSize; i++) {
+ parameterDef.setName(i + 1, aMethodArg.getDstName(i));
+ }
+ }
+ }
+
+ for (MappingTree.FieldMapping aField : aClass.getFields()) {
+ MutableFieldDef fieldDef = classDef.getOrCreateField(aField.getSrcName(), aField.getSrcDesc());
+ fieldDef.setComment(aField.getComment());
+
+ for (int i = 0; i < dstNamesSize; i++) {
+ fieldDef.setName(i + 1, aField.getDstName(i));
+ }
+ }
+ }
+
+ return out;
+ }
+ }
+}
diff --git a/src/test/groovy/net/fabricmc/loom/test/unit/layeredmappings/LayeredMappingsSpecification.groovy b/src/test/groovy/net/fabricmc/loom/test/unit/layeredmappings/LayeredMappingsSpecification.groovy
index 5c087a9d..64a37b5f 100644
--- a/src/test/groovy/net/fabricmc/loom/test/unit/layeredmappings/LayeredMappingsSpecification.groovy
+++ b/src/test/groovy/net/fabricmc/loom/test/unit/layeredmappings/LayeredMappingsSpecification.groovy
@@ -109,11 +109,6 @@ abstract class LayeredMappingsSpecification extends Specification implements Lay
}
@Override
- File workingDirectory() {
- return tempDir
- }
-
- @Override
File workingDirectory(String name) {
return new File(tempDir, name)
}