mirror of
https://github.com/architectury/architectury-loom.git
synced 2026-04-02 05:27:43 -05:00
Merge remote-tracking branch 'upstream/dev/0.9' into arch-prs/at-refactor
# Conflicts: # build.gradle # src/main/java/net/fabricmc/loom/configuration/providers/forge/MinecraftPatchedProvider.java # src/main/java/net/fabricmc/loom/util/Constants.java
This commit is contained in:
@@ -60,7 +60,7 @@ import net.fabricmc.loom.configuration.ide.RunConfigSettings;
|
||||
import net.fabricmc.loom.configuration.launch.LaunchProviderSettings;
|
||||
import net.fabricmc.loom.configuration.processors.JarProcessor;
|
||||
import net.fabricmc.loom.configuration.processors.JarProcessorManager;
|
||||
import net.fabricmc.loom.configuration.providers.MinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.MinecraftProviderImpl;
|
||||
import net.fabricmc.loom.configuration.providers.forge.FieldMigratedMappingsProvider;
|
||||
import net.fabricmc.loom.configuration.providers.forge.ForgeProvider;
|
||||
import net.fabricmc.loom.configuration.providers.forge.ForgeUniversalProvider;
|
||||
@@ -68,9 +68,12 @@ import net.fabricmc.loom.configuration.providers.forge.ForgeUserdevProvider;
|
||||
import net.fabricmc.loom.configuration.providers.forge.McpConfigProvider;
|
||||
import net.fabricmc.loom.configuration.providers.forge.PatchProvider;
|
||||
import net.fabricmc.loom.configuration.providers.forge.SrgProvider;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MojangMappingsDependency;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.GradleMappingContext;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpec;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpecBuilder;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingsDependency;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
|
||||
import net.fabricmc.loom.util.ModPlatform;
|
||||
import net.fabricmc.loom.util.function.LazyBool;
|
||||
|
||||
@@ -220,7 +223,14 @@ public class LoomGradleExtension {
|
||||
}
|
||||
|
||||
public Dependency officialMojangMappings() {
|
||||
return new MojangMappingsDependency(project, this);
|
||||
return layered(LayeredMappingSpecBuilder::officialMojangMappings);
|
||||
}
|
||||
|
||||
public Dependency layered(Action<LayeredMappingSpecBuilder> action) {
|
||||
LayeredMappingSpecBuilder builder = new LayeredMappingSpecBuilder(this);
|
||||
action.execute(builder);
|
||||
LayeredMappingSpec builtSpec = builder.build();
|
||||
return new LayeredMappingsDependency(new GradleMappingContext(project, "layers_" + builtSpec.getVersion().replace("+", "_").replace(".", "_")), builtSpec, builtSpec.getVersion());
|
||||
}
|
||||
|
||||
public LoomGradleExtension(Project project) {
|
||||
@@ -355,7 +365,7 @@ public class LoomGradleExtension {
|
||||
return new File((String) project.property("fabric.loom.natives.dir"));
|
||||
}
|
||||
|
||||
File natives = new File(getUserCache(), "natives/" + getMinecraftProvider().getMinecraftVersion());
|
||||
File natives = new File(getUserCache(), "natives/" + getMinecraftProvider().minecraftVersion());
|
||||
|
||||
if (!natives.exists()) {
|
||||
natives.mkdirs();
|
||||
@@ -384,16 +394,16 @@ public class LoomGradleExtension {
|
||||
return getDependencyManager().getProvider(PatchProvider.class);
|
||||
}
|
||||
|
||||
public MinecraftProvider getMinecraftProvider() {
|
||||
return getDependencyManager().getProvider(MinecraftProvider.class);
|
||||
public MinecraftProviderImpl getMinecraftProvider() {
|
||||
return getDependencyManager().getProvider(MinecraftProviderImpl.class);
|
||||
}
|
||||
|
||||
public MinecraftMappedProvider getMinecraftMappedProvider() {
|
||||
return getMappingsProvider().mappedProvider;
|
||||
}
|
||||
|
||||
public MappingsProvider getMappingsProvider() {
|
||||
return getDependencyManager().getProvider(isForge() ? FieldMigratedMappingsProvider.class : MappingsProvider.class);
|
||||
public MappingsProviderImpl getMappingsProvider() {
|
||||
return getDependencyManager().getProvider(isForge() ? FieldMigratedMappingsProvider.class : MappingsProviderImpl.class);
|
||||
}
|
||||
|
||||
public McpConfigProvider getMcpConfigProvider() {
|
||||
@@ -520,7 +530,7 @@ public class LoomGradleExtension {
|
||||
// Creates a new file each time its called, this is then held onto later when remapping the output jar
|
||||
// Required as now when using parallel builds the old single file could be written by another sourceset compile task
|
||||
public synchronized File getNextMixinMappings() {
|
||||
File mixinMapping = new File(getProjectBuildCache(), "mixin-map-" + getMinecraftProvider().getMinecraftVersion() + "-" + getMappingsProvider().mappingsVersion + "." + mixinMappings.size() + ".tiny");
|
||||
File mixinMapping = new File(getProjectBuildCache(), "mixin-map-" + getMinecraftProvider().minecraftVersion() + "-" + getMappingsProvider().mappingsVersion + "." + mixinMappings.size() + ".tiny");
|
||||
mixinMappings.add(mixinMapping);
|
||||
return mixinMapping;
|
||||
}
|
||||
|
||||
@@ -33,9 +33,10 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.plugins.PluginAware;
|
||||
|
||||
import net.fabricmc.loom.bootstrap.BootstrappedPlugin;
|
||||
import net.fabricmc.loom.configuration.CompileConfiguration;
|
||||
import net.fabricmc.loom.configuration.FabricApiExtension;
|
||||
import net.fabricmc.loom.configuration.MavenPublication;
|
||||
@@ -44,12 +45,20 @@ import net.fabricmc.loom.configuration.providers.mappings.MappingsCache;
|
||||
import net.fabricmc.loom.decompilers.DecompilerConfiguration;
|
||||
import net.fabricmc.loom.task.LoomTasks;
|
||||
|
||||
public class LoomGradlePlugin implements Plugin<Project> {
|
||||
public class LoomGradlePlugin implements BootstrappedPlugin {
|
||||
public static boolean refreshDeps;
|
||||
public static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
|
||||
public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
|
||||
@Override
|
||||
public void apply(PluginAware target) {
|
||||
target.getPlugins().apply(LoomRepositoryPlugin.class);
|
||||
|
||||
if (target instanceof Project project) {
|
||||
apply(project);
|
||||
}
|
||||
}
|
||||
|
||||
public void apply(Project project) {
|
||||
String loomVersion = LoomGradlePlugin.class.getPackage().getImplementationVersion();
|
||||
Set<String> loggedVersions = new HashSet<>(Arrays.asList(System.getProperty("loom.printed.logged", "").split(",")));
|
||||
@@ -58,6 +67,7 @@ public class LoomGradlePlugin implements Plugin<Project> {
|
||||
loggedVersions.add(loomVersion);
|
||||
System.setProperty("loom.printed.logged", String.join(",", loggedVersions));
|
||||
project.getLogger().lifecycle("Architectury Loom: " + loomVersion);
|
||||
project.getLogger().lifecycle("You are using an unstable version of Architectury Loom! Please report any issues found!");
|
||||
}
|
||||
|
||||
refreshDeps = project.getGradle().getStartParameter().isRefreshDependencies() || "true".equals(System.getProperty("loom.refresh"));
|
||||
|
||||
212
src/main/java/net/fabricmc/loom/LoomRepositoryPlugin.java
Normal file
212
src/main/java/net/fabricmc/loom/LoomRepositoryPlugin.java
Normal file
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2016, 2017, 2018 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.dsl.RepositoryHandler;
|
||||
import org.gradle.api.artifacts.repositories.IvyArtifactRepository;
|
||||
import org.gradle.api.initialization.Settings;
|
||||
import org.gradle.api.invocation.Gradle;
|
||||
import org.gradle.api.plugins.PluginAware;
|
||||
|
||||
public class LoomRepositoryPlugin implements Plugin<PluginAware> {
|
||||
@Override
|
||||
public void apply(PluginAware target) {
|
||||
RepositoryHandler repositories = null;
|
||||
|
||||
if (target instanceof Settings settings) {
|
||||
repositories = settings.getDependencyResolutionManagement().getRepositories();
|
||||
|
||||
// leave a marker so projects don't try to override these
|
||||
settings.getGradle().getPluginManager().apply(LoomRepositoryPlugin.class);
|
||||
} else if (target instanceof Project project) {
|
||||
if (project.getGradle().getPlugins().hasPlugin(LoomRepositoryPlugin.class)) {
|
||||
return;
|
||||
}
|
||||
|
||||
repositories = project.getRepositories();
|
||||
} else if (target instanceof Gradle) {
|
||||
return;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Expected target to be a Project or Settings, but was a " + target.getClass());
|
||||
}
|
||||
|
||||
Cache cache = new Cache(target);
|
||||
|
||||
// MavenConfiguration.java
|
||||
repositories.flatDir(repo -> {
|
||||
repo.setName("UserLocalCacheFiles");
|
||||
repo.dir(cache.getRootBuildCache());
|
||||
});
|
||||
repositories.maven(repo -> {
|
||||
repo.setName("UserLocalRemappedMods");
|
||||
repo.setUrl(cache.getRemappedModCache());
|
||||
});
|
||||
repositories.maven(repo -> {
|
||||
repo.setName("Fabric");
|
||||
repo.setUrl("https://maven.fabricmc.net/");
|
||||
});
|
||||
repositories.maven(repo -> {
|
||||
repo.setName("Mojang");
|
||||
repo.setUrl("https://libraries.minecraft.net/");
|
||||
});
|
||||
repositories.maven(repo -> {
|
||||
repo.setName("Forge");
|
||||
repo.setUrl("https://maven.minecraftforge.net/");
|
||||
|
||||
repo.content(descriptor -> {
|
||||
descriptor.excludeGroupByRegex("org\\.eclipse\\.?.*");
|
||||
});
|
||||
repo.metadataSources(sources -> {
|
||||
sources.mavenPom();
|
||||
sources.ignoreGradleMetadataRedirection();
|
||||
});
|
||||
});
|
||||
repositories.mavenCentral();
|
||||
|
||||
// MinecraftMappedProvider.java
|
||||
repositories.ivy(repo -> {
|
||||
repo.setUrl(cache.getUserCache());
|
||||
repo.patternLayout(layout -> {
|
||||
layout.artifact("[revision]/[artifact]-[revision](-[classifier])(.[ext])");
|
||||
});
|
||||
repo.metadataSources(IvyArtifactRepository.MetadataSources::artifact);
|
||||
});
|
||||
|
||||
// MinecraftProcessedProvider.java
|
||||
repositories.ivy(repo -> {
|
||||
repo.setUrl(cache.getRootPersistentCache());
|
||||
repo.patternLayout(layout -> {
|
||||
layout.artifact("[revision]/[artifact]-[revision](-[classifier])(.[ext])");
|
||||
});
|
||||
repo.metadataSources(IvyArtifactRepository.MetadataSources::artifact);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
final class Cache {
|
||||
private PluginAware target;
|
||||
|
||||
Cache(PluginAware target) {
|
||||
if (target instanceof Project || target instanceof Settings) {
|
||||
this.target = target;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Expected target to be a Project or Settings, but was a " + target.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
File getUserCache() {
|
||||
File gradleUserHomeDir = null;
|
||||
|
||||
if (target instanceof Settings settings) {
|
||||
gradleUserHomeDir = settings.getGradle().getGradleUserHomeDir();
|
||||
} else if (target instanceof Project project) {
|
||||
gradleUserHomeDir = project.getGradle().getGradleUserHomeDir();
|
||||
} else {
|
||||
throw new IllegalArgumentException("Expected target to be a Project or Settings, but was a " + target.getClass());
|
||||
}
|
||||
|
||||
File userCache = new File(gradleUserHomeDir, "caches" + File.separator + "fabric-loom");
|
||||
|
||||
if (!userCache.exists()) {
|
||||
userCache.mkdirs();
|
||||
}
|
||||
|
||||
return userCache;
|
||||
}
|
||||
|
||||
public File getRootPersistentCache() {
|
||||
File rootDir = null;
|
||||
|
||||
if (target instanceof Settings settings) {
|
||||
rootDir = settings.getRootDir();
|
||||
} else if (target instanceof Project project) {
|
||||
rootDir = project.getRootDir();
|
||||
} else {
|
||||
throw new IllegalArgumentException("Expected target to be a Project or Settings, but was a " + target.getClass());
|
||||
}
|
||||
|
||||
File persistentCache = new File(rootDir, ".gradle" + File.separator + "loom-cache");
|
||||
|
||||
if (!persistentCache.exists()) {
|
||||
persistentCache.mkdirs();
|
||||
}
|
||||
|
||||
return persistentCache;
|
||||
}
|
||||
|
||||
public File getRootBuildCache() {
|
||||
File rootDir = null;
|
||||
|
||||
if (target instanceof Settings settings) {
|
||||
rootDir = settings.getRootDir();
|
||||
} else if (target instanceof Project project) {
|
||||
rootDir = project.getRootDir();
|
||||
} else {
|
||||
throw new IllegalArgumentException("Expected target to be a Project or Settings, but was a " + target.getClass());
|
||||
}
|
||||
|
||||
File buildCache = new File(rootDir, "build" + File.separator + "loom-cache");
|
||||
|
||||
if (!buildCache.exists()) {
|
||||
buildCache.mkdirs();
|
||||
}
|
||||
|
||||
return buildCache;
|
||||
}
|
||||
|
||||
public File getRemappedModCache() {
|
||||
File remappedModCache = new File(getRootPersistentCache(), "remapped_mods");
|
||||
|
||||
if (!remappedModCache.exists()) {
|
||||
remappedModCache.mkdir();
|
||||
}
|
||||
|
||||
return remappedModCache;
|
||||
}
|
||||
|
||||
public File getNestedModCache() {
|
||||
File nestedModCache = new File(getRootPersistentCache(), "nested_mods");
|
||||
|
||||
if (!nestedModCache.exists()) {
|
||||
nestedModCache.mkdir();
|
||||
}
|
||||
|
||||
return nestedModCache;
|
||||
}
|
||||
|
||||
public File getNativesJarStore() {
|
||||
File natives = new File(getUserCache(), "natives/jars");
|
||||
|
||||
if (!natives.exists()) {
|
||||
natives.mkdirs();
|
||||
}
|
||||
|
||||
return natives;
|
||||
}
|
||||
}
|
||||
@@ -70,6 +70,7 @@ public class JarRemapper {
|
||||
LoggerFilter.replaceSystemOut();
|
||||
TinyRemapper.Builder remapperBuilder = TinyRemapper.newRemapper();
|
||||
remapperBuilder.logger(project.getLogger()::lifecycle);
|
||||
remapperBuilder.logUnknownInvokeDynamic(false);
|
||||
mappingProviders.forEach(remapperBuilder::withMappings);
|
||||
|
||||
if (remapOptions != null) {
|
||||
|
||||
@@ -29,12 +29,19 @@ import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public record MergedNestedJarProvider(NestedJarProvider... parents) implements NestedJarProvider {
|
||||
import org.gradle.api.Project;
|
||||
|
||||
public record MergedNestedJarProvider(NestedJarProvider... children) implements NestedJarProvider {
|
||||
@Override
|
||||
public Collection<File> provide() {
|
||||
return Arrays.stream(parents)
|
||||
return Arrays.stream(children)
|
||||
.map(NestedJarProvider::provide)
|
||||
.flatMap(Collection::stream)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepare(Project project) {
|
||||
Arrays.stream(children).forEach(nestedJarProvider -> nestedJarProvider.prepare(project));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,8 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
@@ -42,7 +43,6 @@ import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.artifacts.Dependency;
|
||||
import org.gradle.api.artifacts.DependencySet;
|
||||
import org.gradle.api.artifacts.ProjectDependency;
|
||||
import org.gradle.api.artifacts.ResolvedArtifact;
|
||||
import org.gradle.api.artifacts.ResolvedConfiguration;
|
||||
import org.gradle.api.artifacts.ResolvedDependency;
|
||||
import org.gradle.api.tasks.bundling.AbstractArchiveTask;
|
||||
@@ -103,17 +103,17 @@ public final class NestedDependencyProvider implements NestedJarProvider {
|
||||
|
||||
visited.add(dependency.getGroup() + ":" + dependency.getName() + ":" + dependency.getVersion());
|
||||
|
||||
// TODO change this to allow just normal jar tasks, so a project can have a none loom sub project
|
||||
Collection<Task> remapJarTasks = dependencyProject.getTasksByName("remapJar", false);
|
||||
Collection<Task> jarTasks = dependencyProject.getTasksByName("jar", false);
|
||||
|
||||
for (Task task : remapJarTasks.isEmpty() ? jarTasks : remapJarTasks) {
|
||||
if (task instanceof RemapJarTask remapJarTask) {
|
||||
File file = remapJarTask.getArchiveFile().get().getAsFile();
|
||||
fileList.add(new DependencyInfo<>(projectDependency, new ProjectDependencyMetaExtractor(), file));
|
||||
} else if (task instanceof AbstractArchiveTask abstractArchiveTask) {
|
||||
File file = abstractArchiveTask.getArchiveFile().get().getAsFile();
|
||||
fileList.add(new DependencyInfo<>(projectDependency, new ProjectDependencyMetaExtractor(), file));
|
||||
if (task instanceof AbstractArchiveTask abstractArchiveTask) {
|
||||
fileList.add(new DependencyInfo<>(
|
||||
projectDependency,
|
||||
new ProjectDependencyMetaExtractor(),
|
||||
abstractArchiveTask.getArchiveFile().get().getAsFile(),
|
||||
abstractArchiveTask.getArchiveClassifier().getOrNull()
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -133,14 +133,13 @@ public final class NestedDependencyProvider implements NestedJarProvider {
|
||||
continue;
|
||||
}
|
||||
|
||||
List<File> files = dependency
|
||||
.getModuleArtifacts()
|
||||
.stream()
|
||||
.map(ResolvedArtifact::getFile)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
for (File file : files) {
|
||||
fileList.add(new DependencyInfo<>(dependency, new ResolvedDependencyMetaExtractor(), file));
|
||||
for (var artifact : dependency.getModuleArtifacts()) {
|
||||
fileList.add(new DependencyInfo<>(
|
||||
dependency,
|
||||
new ResolvedDependencyMetaExtractor(),
|
||||
artifact.getFile(),
|
||||
artifact.getClassifier()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,7 +194,12 @@ public final class NestedDependencyProvider implements NestedJarProvider {
|
||||
|
||||
JsonObject jsonObject = new JsonObject();
|
||||
jsonObject.addProperty("schemaVersion", 1);
|
||||
jsonObject.addProperty("id", (metaExtractor.group(dependency) + "_" + metaExtractor.name(dependency)).replaceAll("\\.", "_").toLowerCase(Locale.ENGLISH));
|
||||
|
||||
jsonObject.addProperty("id",
|
||||
(metaExtractor.group(dependency) + "_" + metaExtractor.name(dependency) + info.getClassifierSuffix())
|
||||
.replaceAll("\\.", "_")
|
||||
.toLowerCase(Locale.ENGLISH)
|
||||
);
|
||||
jsonObject.addProperty("version", metaExtractor.version(dependency));
|
||||
jsonObject.addProperty("name", metaExtractor.name(dependency));
|
||||
|
||||
@@ -206,8 +210,8 @@ public final class NestedDependencyProvider implements NestedJarProvider {
|
||||
return LoomGradlePlugin.GSON.toJson(jsonObject);
|
||||
}
|
||||
|
||||
private record DependencyInfo<D>(D dependency, DependencyMetaExtractor<D> metaExtractor, File file) {
|
||||
public void validateInputs() {
|
||||
private record DependencyInfo<D>(D dependency, DependencyMetaExtractor<D> metaExtractor, File file, @Nullable String classifier) {
|
||||
void validateInputs() {
|
||||
if (!file.exists()) {
|
||||
throw new RuntimeException("Failed to include nested jars, as it could not be found @ " + file.getAbsolutePath());
|
||||
}
|
||||
@@ -216,6 +220,14 @@ public final class NestedDependencyProvider implements NestedJarProvider {
|
||||
throw new RuntimeException("Failed to include nested jars, as file was not a jar: " + file.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
String getClassifierSuffix() {
|
||||
if (classifier == null) {
|
||||
return "";
|
||||
} else {
|
||||
return "_" + classifier;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private interface DependencyMetaExtractor<D> {
|
||||
|
||||
@@ -58,6 +58,8 @@ public final class NestedJarPathProvider implements NestedJarProvider {
|
||||
}
|
||||
|
||||
private void validateFiles() {
|
||||
Preconditions.checkNotNull(files, "null files to nest, was prepare called?");
|
||||
|
||||
for (File file : files) {
|
||||
Preconditions.checkArgument(file.getName().endsWith(".jar"), String.format("Tried to nest %s but it is not a jar", file.getAbsolutePath()));
|
||||
Preconditions.checkArgument(file.exists(), String.format("Tried to nest jar %s but it does not exist", file.getAbsolutePath()));
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.gradle.api.plugins.JavaPlugin;
|
||||
import org.gradle.api.plugins.JavaPluginConvention;
|
||||
import org.gradle.api.tasks.SourceSet;
|
||||
import org.gradle.api.tasks.bundling.AbstractArchiveTask;
|
||||
import org.gradle.api.tasks.compile.JavaCompile;
|
||||
import org.gradle.api.tasks.javadoc.Javadoc;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
@@ -38,7 +39,7 @@ import net.fabricmc.loom.build.mixin.KaptApInvoker;
|
||||
import net.fabricmc.loom.build.mixin.ScalaApInvoker;
|
||||
import net.fabricmc.loom.configuration.ide.SetupIntelijRunConfigs;
|
||||
import net.fabricmc.loom.configuration.providers.LaunchProvider;
|
||||
import net.fabricmc.loom.configuration.providers.MinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.MinecraftProviderImpl;
|
||||
import net.fabricmc.loom.configuration.providers.forge.FieldMigratedMappingsProvider;
|
||||
import net.fabricmc.loom.configuration.providers.forge.ForgeProvider;
|
||||
import net.fabricmc.loom.configuration.providers.forge.ForgeUniversalProvider;
|
||||
@@ -46,7 +47,7 @@ import net.fabricmc.loom.configuration.providers.forge.ForgeUserdevProvider;
|
||||
import net.fabricmc.loom.configuration.providers.forge.McpConfigProvider;
|
||||
import net.fabricmc.loom.configuration.providers.forge.PatchProvider;
|
||||
import net.fabricmc.loom.configuration.providers.forge.SrgProvider;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
|
||||
import net.fabricmc.loom.task.GenVsCodeProjectTask;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
|
||||
@@ -139,15 +140,18 @@ public final class CompileConfiguration {
|
||||
Javadoc javadoc = (Javadoc) p.getTasks().getByName(JavaPlugin.JAVADOC_TASK_NAME);
|
||||
javadoc.setClasspath(main.getOutput().plus(main.getCompileClasspath()));
|
||||
|
||||
p.getTasks().withType(JavaCompile.class).configureEach(compile -> {
|
||||
// Fork the java compiler to ensure that it does not keep any files open.
|
||||
compile.getOptions().setFork(true);
|
||||
});
|
||||
|
||||
p.afterEvaluate(project -> {
|
||||
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
|
||||
|
||||
MavenConfiguration.setup(project);
|
||||
|
||||
LoomDependencyManager dependencyManager = new LoomDependencyManager();
|
||||
extension.setDependencyManager(dependencyManager);
|
||||
|
||||
dependencyManager.addProvider(new MinecraftProvider(project));
|
||||
dependencyManager.addProvider(new MinecraftProviderImpl(project));
|
||||
|
||||
if (extension.isForge()) {
|
||||
dependencyManager.addProvider(new ForgeProvider(project));
|
||||
@@ -164,7 +168,7 @@ public final class CompileConfiguration {
|
||||
dependencyManager.addProvider(new ForgeUniversalProvider(project));
|
||||
}
|
||||
|
||||
dependencyManager.addProvider(extension.isForge() ? new FieldMigratedMappingsProvider(project) : new MappingsProvider(project));
|
||||
dependencyManager.addProvider(extension.isForge() ? new FieldMigratedMappingsProvider(project) : new MappingsProviderImpl(project));
|
||||
dependencyManager.addProvider(new LaunchProvider(project));
|
||||
|
||||
dependencyManager.handleDependencies(project);
|
||||
|
||||
@@ -42,9 +42,10 @@ import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.build.ModCompileRemapper;
|
||||
import net.fabricmc.loom.configuration.DependencyProvider.DependencyInfo;
|
||||
import net.fabricmc.loom.configuration.mods.ModProcessor;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
import net.fabricmc.loom.util.SourceRemapper;
|
||||
import net.fabricmc.loom.LoomRepositoryPlugin;
|
||||
|
||||
public class LoomDependencyManager {
|
||||
private static class ProviderList {
|
||||
@@ -85,7 +86,7 @@ public class LoomDependencyManager {
|
||||
public void handleDependencies(Project project) {
|
||||
List<Runnable> afterTasks = new ArrayList<>();
|
||||
|
||||
MappingsProvider mappingsProvider = null;
|
||||
MappingsProviderImpl mappingsProvider = null;
|
||||
|
||||
project.getLogger().info(":setting up loom dependencies");
|
||||
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
|
||||
@@ -99,8 +100,8 @@ public class LoomDependencyManager {
|
||||
return list;
|
||||
}).providers.add(provider);
|
||||
|
||||
if (provider instanceof MappingsProvider) {
|
||||
mappingsProvider = (MappingsProvider) provider;
|
||||
if (provider instanceof MappingsProviderImpl) {
|
||||
mappingsProvider = (MappingsProviderImpl) provider;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,7 +195,9 @@ public class LoomDependencyManager {
|
||||
|
||||
project.getLogger().debug("Loom adding " + name + " from installer JSON");
|
||||
|
||||
if (jsonElement.getAsJsonObject().has("url")) {
|
||||
// If user choose to use dependencyResolutionManagement, then they should declare
|
||||
// these repositories manually in the settings file.
|
||||
if (jsonElement.getAsJsonObject().has("url") && !project.getGradle().getPlugins().hasPlugin(LoomRepositoryPlugin.class)) {
|
||||
String url = jsonElement.getAsJsonObject().get("url").getAsString();
|
||||
long count = project.getRepositories().stream().filter(artifactRepository -> artifactRepository instanceof MavenArtifactRepository)
|
||||
.map(artifactRepository -> (MavenArtifactRepository) artifactRepository)
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2016, 2017, 2018 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.repositories.MavenArtifactRepository;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
|
||||
public class MavenConfiguration {
|
||||
public static void setup(Project project) {
|
||||
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
|
||||
|
||||
project.getRepositories().flatDir(repo -> {
|
||||
repo.setName("UserLocalCacheFiles");
|
||||
repo.dir(extension.getRootProjectBuildCache());
|
||||
});
|
||||
|
||||
project.getRepositories().maven(repo -> {
|
||||
repo.setName("UserLocalRemappedMods");
|
||||
repo.setUrl(extension.getRemappedModCache());
|
||||
});
|
||||
|
||||
project.getRepositories().maven(repo -> {
|
||||
repo.setName("Fabric");
|
||||
repo.setUrl("https://maven.fabricmc.net/");
|
||||
});
|
||||
|
||||
project.getRepositories().maven(repo -> {
|
||||
repo.setName("Mojang");
|
||||
repo.setUrl("https://libraries.minecraft.net/");
|
||||
});
|
||||
|
||||
project.getRepositories().maven(repo -> {
|
||||
repo.setName("Forge");
|
||||
repo.setUrl("https://maven.minecraftforge.net/");
|
||||
|
||||
repo.metadataSources(sources -> {
|
||||
sources.mavenPom();
|
||||
|
||||
try {
|
||||
MavenArtifactRepository.MetadataSources.class.getDeclaredMethod("ignoreGradleMetadataRedirection")
|
||||
.invoke(sources);
|
||||
} catch (Throwable ignored) {
|
||||
// Method not available
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
project.getRepositories().mavenCentral();
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ import java.io.IOException;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.Task;
|
||||
import org.gradle.api.UnknownTaskException;
|
||||
@@ -153,7 +154,14 @@ public class RemapConfiguration {
|
||||
remapSourcesJarTask.dependsOn(sourcesTask);
|
||||
|
||||
if (isDefaultRemap) {
|
||||
remapSourcesJarTask.doLast(task -> project.getArtifacts().add("archives", remapSourcesJarTask.getOutput()));
|
||||
// Do not use lambda here, see: https://github.com/gradle/gradle/pull/17087
|
||||
//noinspection Convert2Lambda
|
||||
remapSourcesJarTask.doLast(new Action<>() {
|
||||
@Override
|
||||
public void execute(Task task) {
|
||||
project.getArtifacts().add("archives", remapSourcesJarTask.getOutput());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (extension.isShareCaches()) {
|
||||
|
||||
@@ -64,7 +64,7 @@ import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.LoomGradlePlugin;
|
||||
import net.fabricmc.loom.configuration.RemappedConfigurationEntry;
|
||||
import net.fabricmc.loom.configuration.processors.dependency.ModDependencyInfo;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
import net.fabricmc.loom.util.LoggerFilter;
|
||||
@@ -142,7 +142,7 @@ public class ModProcessor {
|
||||
String toM = "named";
|
||||
|
||||
MinecraftMappedProvider mappedProvider = extension.getMinecraftMappedProvider();
|
||||
MappingsProvider mappingsProvider = extension.getMappingsProvider();
|
||||
MappingsProviderImpl mappingsProvider = extension.getMappingsProvider();
|
||||
|
||||
Path mc = extension.isForge() ? mappedProvider.getSrgJar().toPath() : mappedProvider.getIntermediaryJar().toPath();
|
||||
Path[] mcDeps = project.getConfigurations().getByName(Constants.Configurations.LOADER_DEPENDENCIES).getFiles()
|
||||
@@ -157,6 +157,7 @@ public class ModProcessor {
|
||||
LoggerFilter.replaceSystemOut();
|
||||
TinyRemapper remapper = TinyRemapper.newRemapper()
|
||||
.logger(project.getLogger()::lifecycle)
|
||||
.logUnknownInvokeDynamic(false)
|
||||
.withMappings(TinyRemapperMappingsHelper.create(mappings, fromM, toM, false))
|
||||
.renameInvalidLocals(false)
|
||||
.build();
|
||||
|
||||
@@ -31,13 +31,13 @@ import java.util.function.Consumer;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.gradle.api.Project;
|
||||
|
||||
import net.fabricmc.loom.configuration.providers.MinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider;
|
||||
import net.fabricmc.loom.configuration.providers.MinecraftProviderImpl;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
|
||||
public class MinecraftProcessedProvider extends MinecraftMappedProvider {
|
||||
public static final String PROJECT_MAPPED_CLASSIFIER = "projectmapped";
|
||||
public final String projectMappedClassifier;
|
||||
|
||||
private File projectMappedJar;
|
||||
|
||||
@@ -46,6 +46,8 @@ public class MinecraftProcessedProvider extends MinecraftMappedProvider {
|
||||
public MinecraftProcessedProvider(Project project, JarProcessorManager jarProcessorManager) {
|
||||
super(project);
|
||||
this.jarProcessorManager = jarProcessorManager;
|
||||
this.projectMappedClassifier = "project-" + project.getPath().replace(':', '@')
|
||||
+ "-mapped";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -65,14 +67,12 @@ public class MinecraftProcessedProvider extends MinecraftMappedProvider {
|
||||
jarProcessorManager.process(projectMappedJar);
|
||||
}
|
||||
|
||||
getProject().getRepositories().flatDir(repository -> repository.dir(getJarDirectory(getExtension().getProjectPersistentCache(), PROJECT_MAPPED_CLASSIFIER)));
|
||||
|
||||
getProject().getDependencies().add(Constants.Configurations.MINECRAFT_NAMED,
|
||||
getProject().getDependencies().module("net.minecraft:minecraft:" + getJarVersionString(PROJECT_MAPPED_CLASSIFIER)));
|
||||
getProject().getDependencies().module("net.minecraft:minecraft:" + getJarVersionString(projectMappedClassifier)));
|
||||
}
|
||||
|
||||
private void invalidateJars() {
|
||||
File dir = getJarDirectory(getExtension().getUserCache(), PROJECT_MAPPED_CLASSIFIER);
|
||||
File dir = getJarDirectory(getExtension().getUserCache(), projectMappedClassifier);
|
||||
|
||||
if (dir.exists()) {
|
||||
getProject().getLogger().warn("Invalidating project jars");
|
||||
@@ -86,10 +86,10 @@ public class MinecraftProcessedProvider extends MinecraftMappedProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initFiles(MinecraftProvider minecraftProvider, MappingsProvider mappingsProvider) {
|
||||
public void initFiles(MinecraftProviderImpl minecraftProvider, MappingsProviderImpl mappingsProvider) {
|
||||
super.initFiles(minecraftProvider, mappingsProvider);
|
||||
|
||||
projectMappedJar = new File(getJarDirectory(getExtension().getProjectPersistentCache(), PROJECT_MAPPED_CLASSIFIER), "minecraft-" + getJarVersionString(PROJECT_MAPPED_CLASSIFIER) + ".jar");
|
||||
projectMappedJar = new File(getJarDirectory(getExtension().getRootProjectPersistentCache(), projectMappedClassifier), "minecraft-" + getJarVersionString(projectMappedClassifier) + ".jar");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -66,16 +66,17 @@ public class LaunchProvider extends DependencyProvider {
|
||||
.property("client", "org.lwjgl.librarypath", getExtension().getNativesDirectory().getAbsolutePath())
|
||||
|
||||
.argument("client", "--assetIndex")
|
||||
.argument("client", getExtension().getMinecraftProvider().getVersionInfo().assetIndex().fabricId(getExtension().getMinecraftProvider().getMinecraftVersion()))
|
||||
.argument("client", getExtension().getMinecraftProvider().getVersionInfo().assetIndex().fabricId(getExtension().getMinecraftProvider().minecraftVersion()))
|
||||
.argument("client", "--assetsDir")
|
||||
.argument("client", new File(getExtension().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().getMinecraftVersion())
|
||||
.argument(getExtension().getMinecraftProvider().minecraftVersion())
|
||||
.argument("--fml.forgeVersion")
|
||||
.argument(getExtension().getForgeProvider().getVersion().getForgeVersion())
|
||||
|
||||
@@ -136,7 +137,8 @@ public class LaunchProvider extends DependencyProvider {
|
||||
annotationDependency = addDependency(Constants.Dependencies.JETBRAINS_ANNOTATIONS + Constants.Dependencies.Versions.JETBRAINS_ANNOTATIONS, JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME);
|
||||
|
||||
if (getExtension().isForge()) {
|
||||
addDependency(Constants.Dependencies.JAVAX_ANNOTATIONS + Constants.Dependencies.Versions.JAVAX_ANNOTATIONS, "compileOnly");
|
||||
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);
|
||||
|
||||
@@ -24,247 +24,10 @@
|
||||
|
||||
package net.fabricmc.loom.configuration.providers;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.google.common.base.Stopwatch;
|
||||
import com.google.common.io.Files;
|
||||
import org.gradle.api.GradleException;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.logging.Logger;
|
||||
|
||||
import net.fabricmc.loom.LoomGradlePlugin;
|
||||
import net.fabricmc.loom.configuration.DependencyProvider;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.ManifestVersion;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftLibraryProvider;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
import net.fabricmc.loom.util.DownloadUtil;
|
||||
import net.fabricmc.loom.util.HashedDownloadUtil;
|
||||
import net.fabricmc.stitch.merge.JarMerger;
|
||||
|
||||
public class MinecraftProvider extends DependencyProvider {
|
||||
private String minecraftVersion;
|
||||
public interface MinecraftProvider {
|
||||
String minecraftVersion();
|
||||
|
||||
private MinecraftVersionMeta versionInfo;
|
||||
private MinecraftLibraryProvider libraryProvider;
|
||||
|
||||
private File minecraftJson;
|
||||
public File minecraftClientJar;
|
||||
public File minecraftServerJar;
|
||||
private File minecraftMergedJar;
|
||||
private File versionManifestJson;
|
||||
private String jarSuffix = "";
|
||||
|
||||
public MinecraftProvider(Project project) {
|
||||
super(project);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void provide(DependencyInfo dependency, Consumer<Runnable> postPopulationScheduler) throws Exception {
|
||||
minecraftVersion = dependency.getDependency().getVersion();
|
||||
|
||||
if (getExtension().shouldGenerateSrgTiny() && !getExtension().isForge()) {
|
||||
addDependency("de.oceanlabs.mcp:mcp_config:" + minecraftVersion, Constants.Configurations.SRG);
|
||||
}
|
||||
|
||||
boolean offline = getProject().getGradle().getStartParameter().isOffline();
|
||||
|
||||
initFiles();
|
||||
|
||||
downloadMcJson(offline);
|
||||
|
||||
try (FileReader reader = new FileReader(minecraftJson)) {
|
||||
versionInfo = LoomGradlePlugin.OBJECT_MAPPER.readValue(reader, MinecraftVersionMeta.class);
|
||||
}
|
||||
|
||||
// Add Loom as an annotation processor
|
||||
addDependency(getProject().files(this.getClass().getProtectionDomain().getCodeSource().getLocation()), "compileOnly");
|
||||
|
||||
if (offline) {
|
||||
if (minecraftClientJar.exists() && minecraftServerJar.exists()) {
|
||||
getProject().getLogger().debug("Found client and server jars, presuming up-to-date");
|
||||
} else if (minecraftMergedJar.exists()) {
|
||||
//Strictly we don't need the split jars if the merged one exists, let's try go on
|
||||
getProject().getLogger().warn("Missing game jar but merged jar present, things might end badly");
|
||||
} else {
|
||||
throw new GradleException("Missing jar(s); Client: " + minecraftClientJar.exists() + ", Server: " + minecraftServerJar.exists());
|
||||
}
|
||||
} else {
|
||||
downloadJars(getProject().getLogger());
|
||||
}
|
||||
|
||||
libraryProvider = new MinecraftLibraryProvider();
|
||||
libraryProvider.provide(this, getProject());
|
||||
|
||||
if (!minecraftMergedJar.exists() || isRefreshDeps()) {
|
||||
try {
|
||||
mergeJars(getProject().getLogger());
|
||||
} catch (Throwable e) {
|
||||
HashedDownloadUtil.delete(minecraftClientJar);
|
||||
HashedDownloadUtil.delete(minecraftServerJar);
|
||||
minecraftMergedJar.delete();
|
||||
|
||||
getProject().getLogger().error("Could not merge JARs! Deleting source JARs - please re-run the command and move on.", e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void initFiles() {
|
||||
minecraftJson = new File(getExtension().getUserCache(), "minecraft-" + minecraftVersion + "-info.json");
|
||||
minecraftClientJar = new File(getExtension().getUserCache(), "minecraft-" + minecraftVersion + "-client.jar");
|
||||
minecraftServerJar = new File(getExtension().getUserCache(), "minecraft-" + minecraftVersion + "-server.jar");
|
||||
minecraftMergedJar = new File(getExtension().getUserCache(), "minecraft-" + minecraftVersion + "-merged.jar");
|
||||
versionManifestJson = new File(getExtension().getUserCache(), "version_manifest.json");
|
||||
}
|
||||
|
||||
public void deleteFiles() {
|
||||
DownloadUtil.delete(minecraftClientJar);
|
||||
DownloadUtil.delete(minecraftServerJar);
|
||||
DownloadUtil.delete(minecraftMergedJar);
|
||||
}
|
||||
|
||||
private void downloadMcJson(boolean offline) throws IOException {
|
||||
if (getExtension().isShareCaches() && !getExtension().isRootProject() && versionManifestJson.exists() && !isRefreshDeps()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!offline && !isRefreshDeps() && hasRecentValidManifest()) {
|
||||
// We have a recent valid manifest file, so do nothing
|
||||
} else if (offline) {
|
||||
if (versionManifestJson.exists()) {
|
||||
// If there is the manifests already we'll presume that's good enough
|
||||
getProject().getLogger().debug("Found version manifests, presuming up-to-date");
|
||||
} else {
|
||||
// If we don't have the manifests then there's nothing more we can do
|
||||
throw new GradleException("Version manifests not found at " + versionManifestJson.getAbsolutePath());
|
||||
}
|
||||
} else {
|
||||
getProject().getLogger().debug("Downloading version manifests");
|
||||
DownloadUtil.downloadIfChanged(new URL(Constants.VERSION_MANIFESTS), versionManifestJson, getProject().getLogger());
|
||||
}
|
||||
|
||||
String versionManifest = Files.asCharSource(versionManifestJson, StandardCharsets.UTF_8).read();
|
||||
ManifestVersion mcManifest = LoomGradlePlugin.OBJECT_MAPPER.readValue(versionManifest, ManifestVersion.class);
|
||||
|
||||
Optional<ManifestVersion.Versions> optionalVersion = Optional.empty();
|
||||
|
||||
if (getExtension().customManifest != null) {
|
||||
ManifestVersion.Versions customVersion = new ManifestVersion.Versions();
|
||||
customVersion.id = minecraftVersion;
|
||||
customVersion.url = getExtension().customManifest;
|
||||
optionalVersion = Optional.of(customVersion);
|
||||
getProject().getLogger().lifecycle("Using custom minecraft manifest");
|
||||
}
|
||||
|
||||
if (!optionalVersion.isPresent()) {
|
||||
optionalVersion = mcManifest.versions().stream().filter(versions -> versions.id.equalsIgnoreCase(minecraftVersion)).findFirst();
|
||||
}
|
||||
|
||||
if (optionalVersion.isPresent()) {
|
||||
if (offline) {
|
||||
if (minecraftJson.exists()) {
|
||||
//If there is the manifest already we'll presume that's good enough
|
||||
getProject().getLogger().debug("Found Minecraft {} manifest, presuming up-to-date", minecraftVersion);
|
||||
} else {
|
||||
//If we don't have the manifests then there's nothing more we can do
|
||||
throw new GradleException("Minecraft " + minecraftVersion + " manifest not found at " + minecraftJson.getAbsolutePath());
|
||||
}
|
||||
} else {
|
||||
getProject().getLogger().debug("Downloading Minecraft {} manifest", minecraftVersion);
|
||||
|
||||
ManifestVersion.Versions version = optionalVersion.get();
|
||||
String url = version.url;
|
||||
|
||||
if (version.sha1 != null) {
|
||||
HashedDownloadUtil.downloadIfInvalid(new URL(url), minecraftJson, version.sha1, getProject().getLogger(), true);
|
||||
} else {
|
||||
// Use the etag if no hash found from url
|
||||
DownloadUtil.downloadIfChanged(new URL(url), minecraftJson, getProject().getLogger());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("Failed to find minecraft version: " + minecraftVersion);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasRecentValidManifest() throws IOException {
|
||||
if (getExtension().customManifest != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!versionManifestJson.exists() || !minecraftJson.exists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (versionManifestJson.lastModified() > System.currentTimeMillis() - 24 * 3_600_000) {
|
||||
// Version manifest hasn't been modified in 24 hours, time to get a new one.
|
||||
return false;
|
||||
}
|
||||
|
||||
ManifestVersion manifest = LoomGradlePlugin.OBJECT_MAPPER.readValue(Files.asCharSource(versionManifestJson, StandardCharsets.UTF_8).read(), ManifestVersion.class);
|
||||
Optional<ManifestVersion.Versions> version = manifest.versions().stream().filter(versions -> versions.id.equalsIgnoreCase(minecraftVersion)).findFirst();
|
||||
|
||||
// fail if the expected mc version was not found, will download the file again.
|
||||
return version.isPresent();
|
||||
}
|
||||
|
||||
private void downloadJars(Logger logger) throws IOException {
|
||||
if (getExtension().isShareCaches() && !getExtension().isRootProject() && minecraftClientJar.exists() && minecraftServerJar.exists() && !isRefreshDeps()) {
|
||||
return;
|
||||
}
|
||||
|
||||
MinecraftVersionMeta.Download client = versionInfo.download("client");
|
||||
MinecraftVersionMeta.Download server = versionInfo.download("server");
|
||||
|
||||
HashedDownloadUtil.downloadIfInvalid(new URL(client.url()), minecraftClientJar, client.sha1(), logger, false);
|
||||
HashedDownloadUtil.downloadIfInvalid(new URL(server.url()), minecraftServerJar, server.sha1(), logger, false);
|
||||
}
|
||||
|
||||
private void mergeJars(Logger logger) throws IOException {
|
||||
logger.info(":merging jars");
|
||||
Stopwatch stopwatch = Stopwatch.createStarted();
|
||||
|
||||
try (JarMerger jarMerger = new JarMerger(minecraftClientJar, minecraftServerJar, minecraftMergedJar)) {
|
||||
jarMerger.enableSyntheticParamsOffset();
|
||||
jarMerger.merge();
|
||||
}
|
||||
|
||||
logger.info(":merged jars in " + stopwatch);
|
||||
}
|
||||
|
||||
public File getMergedJar() {
|
||||
return minecraftMergedJar;
|
||||
}
|
||||
|
||||
public String getMinecraftVersion() {
|
||||
return minecraftVersion;
|
||||
}
|
||||
|
||||
public MinecraftVersionMeta getVersionInfo() {
|
||||
return versionInfo;
|
||||
}
|
||||
|
||||
public MinecraftLibraryProvider getLibraryProvider() {
|
||||
return libraryProvider;
|
||||
}
|
||||
|
||||
public String getJarSuffix() {
|
||||
return jarSuffix;
|
||||
}
|
||||
|
||||
public void setJarSuffix(String jarSuffix) {
|
||||
this.jarSuffix = jarSuffix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTargetConfig() {
|
||||
return Constants.Configurations.MINECRAFT;
|
||||
}
|
||||
MinecraftVersionMeta getVersionInfo();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,272 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2016, 2017, 2018 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.providers;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.google.common.base.Stopwatch;
|
||||
import com.google.common.io.Files;
|
||||
import org.gradle.api.GradleException;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.logging.Logger;
|
||||
|
||||
import net.fabricmc.loom.LoomGradlePlugin;
|
||||
import net.fabricmc.loom.configuration.DependencyProvider;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.ManifestVersion;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftLibraryProvider;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
import net.fabricmc.loom.util.DownloadUtil;
|
||||
import net.fabricmc.loom.util.HashedDownloadUtil;
|
||||
import net.fabricmc.stitch.merge.JarMerger;
|
||||
|
||||
public class MinecraftProviderImpl extends DependencyProvider implements MinecraftProvider {
|
||||
private String minecraftVersion;
|
||||
|
||||
private MinecraftVersionMeta versionInfo;
|
||||
private MinecraftLibraryProvider libraryProvider;
|
||||
|
||||
private File minecraftJson;
|
||||
public File minecraftClientJar;
|
||||
public File minecraftServerJar;
|
||||
private File minecraftMergedJar;
|
||||
private File versionManifestJson;
|
||||
private String jarSuffix = "";
|
||||
|
||||
public MinecraftProviderImpl(Project project) {
|
||||
super(project);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void provide(DependencyInfo dependency, Consumer<Runnable> postPopulationScheduler) throws Exception {
|
||||
minecraftVersion = dependency.getDependency().getVersion();
|
||||
|
||||
if (getExtension().shouldGenerateSrgTiny() && !getExtension().isForge()) {
|
||||
addDependency("de.oceanlabs.mcp:mcp_config:" + minecraftVersion, Constants.Configurations.SRG);
|
||||
}
|
||||
|
||||
boolean offline = getProject().getGradle().getStartParameter().isOffline();
|
||||
|
||||
initFiles();
|
||||
|
||||
downloadMcJson(offline);
|
||||
|
||||
try (FileReader reader = new FileReader(minecraftJson)) {
|
||||
versionInfo = LoomGradlePlugin.OBJECT_MAPPER.readValue(reader, MinecraftVersionMeta.class);
|
||||
}
|
||||
|
||||
// Add Loom as an annotation processor
|
||||
addDependency(getProject().files(this.getClass().getProtectionDomain().getCodeSource().getLocation()), "compileOnly");
|
||||
|
||||
if (offline) {
|
||||
if (minecraftClientJar.exists() && minecraftServerJar.exists()) {
|
||||
getProject().getLogger().debug("Found client and server jars, presuming up-to-date");
|
||||
} else if (minecraftMergedJar.exists()) {
|
||||
//Strictly we don't need the split jars if the merged one exists, let's try go on
|
||||
getProject().getLogger().warn("Missing game jar but merged jar present, things might end badly");
|
||||
} else {
|
||||
throw new GradleException("Missing jar(s); Client: " + minecraftClientJar.exists() + ", Server: " + minecraftServerJar.exists());
|
||||
}
|
||||
} else {
|
||||
downloadJars(getProject().getLogger());
|
||||
}
|
||||
|
||||
libraryProvider = new MinecraftLibraryProvider();
|
||||
libraryProvider.provide(this, getProject());
|
||||
|
||||
if (!minecraftMergedJar.exists() || isRefreshDeps()) {
|
||||
try {
|
||||
mergeJars(getProject().getLogger());
|
||||
} catch (Throwable e) {
|
||||
HashedDownloadUtil.delete(minecraftClientJar);
|
||||
HashedDownloadUtil.delete(minecraftServerJar);
|
||||
minecraftMergedJar.delete();
|
||||
|
||||
getProject().getLogger().error("Could not merge JARs! Deleting source JARs - please re-run the command and move on.", e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void initFiles() {
|
||||
minecraftJson = new File(getExtension().getUserCache(), "minecraft-" + minecraftVersion + "-info.json");
|
||||
minecraftClientJar = new File(getExtension().getUserCache(), "minecraft-" + minecraftVersion + "-client.jar");
|
||||
minecraftServerJar = new File(getExtension().getUserCache(), "minecraft-" + minecraftVersion + "-server.jar");
|
||||
minecraftMergedJar = new File(getExtension().getUserCache(), "minecraft-" + minecraftVersion + "-merged.jar");
|
||||
versionManifestJson = new File(getExtension().getUserCache(), "version_manifest.json");
|
||||
}
|
||||
|
||||
public void deleteFiles() {
|
||||
DownloadUtil.delete(minecraftClientJar);
|
||||
DownloadUtil.delete(minecraftServerJar);
|
||||
DownloadUtil.delete(minecraftMergedJar);
|
||||
}
|
||||
|
||||
private void downloadMcJson(boolean offline) throws IOException {
|
||||
if (getExtension().isShareCaches() && !getExtension().isRootProject() && versionManifestJson.exists() && !isRefreshDeps()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!offline && !isRefreshDeps() && hasRecentValidManifest()) {
|
||||
// We have a recent valid manifest file, so do nothing
|
||||
} else if (offline) {
|
||||
if (versionManifestJson.exists()) {
|
||||
// If there is the manifests already we'll presume that's good enough
|
||||
getProject().getLogger().debug("Found version manifests, presuming up-to-date");
|
||||
} else {
|
||||
// If we don't have the manifests then there's nothing more we can do
|
||||
throw new GradleException("Version manifests not found at " + versionManifestJson.getAbsolutePath());
|
||||
}
|
||||
} else {
|
||||
getProject().getLogger().debug("Downloading version manifests");
|
||||
DownloadUtil.downloadIfChanged(new URL(Constants.VERSION_MANIFESTS), versionManifestJson, getProject().getLogger());
|
||||
}
|
||||
|
||||
String versionManifest = Files.asCharSource(versionManifestJson, StandardCharsets.UTF_8).read();
|
||||
ManifestVersion mcManifest = LoomGradlePlugin.OBJECT_MAPPER.readValue(versionManifest, ManifestVersion.class);
|
||||
|
||||
Optional<ManifestVersion.Versions> optionalVersion = Optional.empty();
|
||||
|
||||
if (getExtension().customManifest != null) {
|
||||
ManifestVersion.Versions customVersion = new ManifestVersion.Versions();
|
||||
customVersion.id = minecraftVersion;
|
||||
customVersion.url = getExtension().customManifest;
|
||||
optionalVersion = Optional.of(customVersion);
|
||||
getProject().getLogger().lifecycle("Using custom minecraft manifest");
|
||||
}
|
||||
|
||||
if (!optionalVersion.isPresent()) {
|
||||
optionalVersion = mcManifest.versions().stream().filter(versions -> versions.id.equalsIgnoreCase(minecraftVersion)).findFirst();
|
||||
}
|
||||
|
||||
if (optionalVersion.isPresent()) {
|
||||
if (offline) {
|
||||
if (minecraftJson.exists()) {
|
||||
//If there is the manifest already we'll presume that's good enough
|
||||
getProject().getLogger().debug("Found Minecraft {} manifest, presuming up-to-date", minecraftVersion);
|
||||
} else {
|
||||
//If we don't have the manifests then there's nothing more we can do
|
||||
throw new GradleException("Minecraft " + minecraftVersion + " manifest not found at " + minecraftJson.getAbsolutePath());
|
||||
}
|
||||
} else {
|
||||
getProject().getLogger().debug("Downloading Minecraft {} manifest", minecraftVersion);
|
||||
|
||||
ManifestVersion.Versions version = optionalVersion.get();
|
||||
String url = version.url;
|
||||
|
||||
if (version.sha1 != null) {
|
||||
HashedDownloadUtil.downloadIfInvalid(new URL(url), minecraftJson, version.sha1, getProject().getLogger(), true);
|
||||
} else {
|
||||
// Use the etag if no hash found from url
|
||||
DownloadUtil.downloadIfChanged(new URL(url), minecraftJson, getProject().getLogger());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("Failed to find minecraft version: " + minecraftVersion);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasRecentValidManifest() throws IOException {
|
||||
if (getExtension().customManifest != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!versionManifestJson.exists() || !minecraftJson.exists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (versionManifestJson.lastModified() > System.currentTimeMillis() - 24 * 3_600_000) {
|
||||
// Version manifest hasn't been modified in 24 hours, time to get a new one.
|
||||
return false;
|
||||
}
|
||||
|
||||
ManifestVersion manifest = LoomGradlePlugin.OBJECT_MAPPER.readValue(Files.asCharSource(versionManifestJson, StandardCharsets.UTF_8).read(), ManifestVersion.class);
|
||||
Optional<ManifestVersion.Versions> version = manifest.versions().stream().filter(versions -> versions.id.equalsIgnoreCase(minecraftVersion)).findFirst();
|
||||
|
||||
// fail if the expected mc version was not found, will download the file again.
|
||||
return version.isPresent();
|
||||
}
|
||||
|
||||
private void downloadJars(Logger logger) throws IOException {
|
||||
if (getExtension().isShareCaches() && !getExtension().isRootProject() && minecraftClientJar.exists() && minecraftServerJar.exists() && !isRefreshDeps()) {
|
||||
return;
|
||||
}
|
||||
|
||||
MinecraftVersionMeta.Download client = versionInfo.download("client");
|
||||
MinecraftVersionMeta.Download server = versionInfo.download("server");
|
||||
|
||||
HashedDownloadUtil.downloadIfInvalid(new URL(client.url()), minecraftClientJar, client.sha1(), logger, false);
|
||||
HashedDownloadUtil.downloadIfInvalid(new URL(server.url()), minecraftServerJar, server.sha1(), logger, false);
|
||||
}
|
||||
|
||||
private void mergeJars(Logger logger) throws IOException {
|
||||
logger.info(":merging jars");
|
||||
Stopwatch stopwatch = Stopwatch.createStarted();
|
||||
|
||||
try (JarMerger jarMerger = new JarMerger(minecraftClientJar, minecraftServerJar, minecraftMergedJar)) {
|
||||
jarMerger.enableSyntheticParamsOffset();
|
||||
jarMerger.merge();
|
||||
}
|
||||
|
||||
logger.info(":merged jars in " + stopwatch);
|
||||
}
|
||||
|
||||
public File getMergedJar() {
|
||||
return minecraftMergedJar;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String minecraftVersion() {
|
||||
return minecraftVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MinecraftVersionMeta getVersionInfo() {
|
||||
return versionInfo;
|
||||
}
|
||||
|
||||
public MinecraftLibraryProvider getLibraryProvider() {
|
||||
return libraryProvider;
|
||||
}
|
||||
|
||||
public String getJarSuffix() {
|
||||
return jarSuffix;
|
||||
}
|
||||
|
||||
public void setJarSuffix(String jarSuffix) {
|
||||
this.jarSuffix = jarSuffix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTargetConfig() {
|
||||
return Constants.Configurations.MINECRAFT;
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,6 @@ import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
@@ -59,7 +58,7 @@ import org.objectweb.asm.Opcodes;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.LoomGradlePlugin;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
|
||||
import net.fabricmc.loom.util.FileSystemUtil;
|
||||
import net.fabricmc.loom.util.ThreadingUtils;
|
||||
import net.fabricmc.loom.util.srg.SrgMerger;
|
||||
@@ -68,7 +67,7 @@ import net.fabricmc.mapping.tree.FieldDef;
|
||||
import net.fabricmc.mapping.tree.TinyMappingFactory;
|
||||
import net.fabricmc.mapping.tree.TinyTree;
|
||||
|
||||
public class FieldMigratedMappingsProvider extends MappingsProvider {
|
||||
public class FieldMigratedMappingsProvider extends MappingsProviderImpl {
|
||||
private List<Map.Entry<FieldMember, String>> migratedFields = new ArrayList<>();
|
||||
public Path migratedFieldsCache;
|
||||
public Path rawTinyMappings;
|
||||
@@ -105,7 +104,7 @@ public class FieldMigratedMappingsProvider extends MappingsProvider {
|
||||
@Override
|
||||
public void manipulateMappings(Path mappingsJar) throws IOException {
|
||||
LoomGradleExtension extension = getExtension();
|
||||
Path mappingsFolder = mappingsDir.resolve(extension.getMinecraftProvider().getMinecraftVersion() + "/forge-" + extension.getPatchProvider().forgeVersion);
|
||||
Path mappingsFolder = getMappedVersionedDir(removeSuffix).resolve("forge/" + extension.getPatchProvider().forgeVersion);
|
||||
this.rawTinyMappings = tinyMappings.toPath();
|
||||
this.rawTinyMappingsWithSrg = tinyMappingsWithSrg;
|
||||
String mappingsJarName = mappingsJar.getFileName().toString();
|
||||
@@ -143,7 +142,7 @@ public class FieldMigratedMappingsProvider extends MappingsProvider {
|
||||
migratedFields.forEach(entry -> {
|
||||
map.put(entry.getKey().owner + "#" + entry.getKey().field, entry.getValue());
|
||||
});
|
||||
Files.write(migratedFieldsCache, new Gson().toJson(map).getBytes(StandardCharsets.UTF_8));
|
||||
Files.writeString(migratedFieldsCache, new Gson().toJson(map));
|
||||
Files.deleteIfExists(tinyMappings.toPath());
|
||||
}
|
||||
|
||||
@@ -174,7 +173,7 @@ public class FieldMigratedMappingsProvider extends MappingsProvider {
|
||||
}
|
||||
}
|
||||
|
||||
Files.write(tinyMappings.toPath(), MappingsUtils.serializeToString(mappings).getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE);
|
||||
Files.writeString(tinyMappings.toPath(), MappingsUtils.serializeToString(mappings), StandardOpenOption.CREATE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ 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;
|
||||
import java.net.URI;
|
||||
@@ -45,11 +46,16 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.Manifest;
|
||||
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.ImmutableMap;
|
||||
@@ -73,7 +79,7 @@ import org.objectweb.asm.tree.ClassNode;
|
||||
import org.zeroturnaround.zip.ZipUtil;
|
||||
|
||||
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.minecraft.MinecraftMappedProvider;
|
||||
import net.fabricmc.loom.util.Checksum;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
@@ -89,6 +95,10 @@ import net.fabricmc.loom.util.srg.SpecialSourceExecutor;
|
||||
import net.fabricmc.mapping.tree.TinyTree;
|
||||
|
||||
public class MinecraftPatchedProvider extends DependencyProvider {
|
||||
private static final String LOOM_PATCH_VERSION_KEY = "Loom-Patch-Version";
|
||||
private static final String CURRENT_LOOM_PATCH_VERSION = "2";
|
||||
private static final String NAME_MAPPING_SERVICE_PATH = "/inject/META-INF/services/cpw.mods.modlauncher.api.INameMappingService";
|
||||
|
||||
// Step 1: Remap Minecraft to SRG (global)
|
||||
private File minecraftClientSrgJar;
|
||||
private File minecraftServerSrgJar;
|
||||
@@ -106,12 +116,14 @@ public class MinecraftPatchedProvider extends DependencyProvider {
|
||||
@Nullable
|
||||
private File projectAt = null;
|
||||
private boolean atDirty = false;
|
||||
private boolean filesDirty = false;
|
||||
|
||||
public MinecraftPatchedProvider(Project project) {
|
||||
super(project);
|
||||
}
|
||||
|
||||
public void initFiles() throws IOException {
|
||||
filesDirty = false;
|
||||
projectAtHash = new File(getExtension().getProjectPersistentCache(), "at.sha256");
|
||||
|
||||
SourceSet main = getProject().getConvention().findPlugin(JavaPluginConvention.class).getSourceSets().getByName("main");
|
||||
@@ -140,9 +152,9 @@ public class MinecraftPatchedProvider extends DependencyProvider {
|
||||
atDirty = mismatched;
|
||||
}
|
||||
|
||||
MinecraftProvider minecraftProvider = getExtension().getMinecraftProvider();
|
||||
MinecraftProviderImpl minecraftProvider = getExtension().getMinecraftProvider();
|
||||
PatchProvider patchProvider = getExtension().getPatchProvider();
|
||||
String minecraftVersion = minecraftProvider.getMinecraftVersion();
|
||||
String minecraftVersion = minecraftProvider.minecraftVersion();
|
||||
String patchId = "forge-" + patchProvider.forgeVersion;
|
||||
|
||||
if (getExtension().useFabricMixin) {
|
||||
@@ -166,7 +178,8 @@ public class MinecraftPatchedProvider extends DependencyProvider {
|
||||
minecraftMergedPatchedSrgAtJar = new File(projectDir, "merged-srg-at-patched.jar");
|
||||
minecraftMergedPatchedJar = new File(projectDir, "merged-patched.jar");
|
||||
|
||||
if (isRefreshDeps() || Stream.of(getGlobalCaches()).anyMatch(Predicates.not(File::exists))) {
|
||||
if (isRefreshDeps() || Stream.of(getGlobalCaches()).anyMatch(Predicates.not(File::exists))
|
||||
|| !isPatchedSrgJarUpdateToDate(minecraftClientPatchedSrgJar) || !isPatchedSrgJarUpdateToDate(minecraftServerPatchedSrgJar)) {
|
||||
cleanAllCache();
|
||||
} else if (atDirty || Stream.of(getProjectCache()).anyMatch(Predicates.not(File::exists))) {
|
||||
cleanProjectCache();
|
||||
@@ -242,6 +255,11 @@ public class MinecraftPatchedProvider extends DependencyProvider {
|
||||
remapPatchedJars(getProject().getLogger());
|
||||
}
|
||||
|
||||
if (dirty || !minecraftMergedPatchedJar.exists()) {
|
||||
mergeJars(getProject().getLogger());
|
||||
}
|
||||
|
||||
this.filesDirty = dirty;
|
||||
this.dirty = false;
|
||||
}
|
||||
|
||||
@@ -258,12 +276,12 @@ public class MinecraftPatchedProvider extends DependencyProvider {
|
||||
private void createSrgJars(Logger logger) throws Exception {
|
||||
McpConfigProvider mcpProvider = getExtension().getMcpConfigProvider();
|
||||
|
||||
MinecraftProvider minecraftProvider = getExtension().getMinecraftProvider();
|
||||
MinecraftProviderImpl minecraftProvider = getExtension().getMinecraftProvider();
|
||||
|
||||
String[] mappingsPath = {null};
|
||||
|
||||
if (!ZipUtil.handle(mcpProvider.getMcp(), "config.json", (in, zipEntry) -> {
|
||||
mappingsPath[0] = new JsonParser().parse(new InputStreamReader(in)).getAsJsonObject().get("data").getAsJsonObject().get("mappings").getAsString();
|
||||
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() + "!");
|
||||
}
|
||||
@@ -330,25 +348,28 @@ public class MinecraftPatchedProvider extends DependencyProvider {
|
||||
copyAll(getExtension().getForgeUniversalProvider().getForge(), environment.patchedSrgJar.apply(this));
|
||||
copyUserdevFiles(getExtension().getForgeUserdevProvider().getUserdevJar(), environment.patchedSrgJar.apply(this));
|
||||
});
|
||||
}
|
||||
|
||||
logger.lifecycle(":injecting loom classes into minecraft");
|
||||
File injection = File.createTempFile("loom-injection", ".jar");
|
||||
private boolean isPatchedSrgJarUpdateToDate(File jar) {
|
||||
if (!jar.exists()) return false;
|
||||
|
||||
try (InputStream in = MinecraftProvider.class.getResourceAsStream("/inject/injection.jar")) {
|
||||
Files.copy(in, injection.toPath());
|
||||
boolean[] upToDate = {false};
|
||||
|
||||
if (!ZipUtil.handle(jar, "META-INF/MANIFEST.MF", (in, zipEntry) -> {
|
||||
Manifest manifest = new Manifest(in);
|
||||
Attributes attributes = manifest.getMainAttributes();
|
||||
String value = attributes.getValue(LOOM_PATCH_VERSION_KEY);
|
||||
|
||||
if (Objects.equals(value, CURRENT_LOOM_PATCH_VERSION)) {
|
||||
upToDate[0] = true;
|
||||
} else {
|
||||
getProject().getLogger().lifecycle(":forge patched jars not up to date. current version: " + value);
|
||||
}
|
||||
})) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (Environment environment : Environment.values()) {
|
||||
String side = environment.side();
|
||||
File target = environment.patchedSrgJar.apply(this);
|
||||
walkFileSystems(injection, target, it -> {
|
||||
if (it.getFileName().toString().equals("MANIFEST.MF")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return getExtension().useFabricMixin || !it.getFileName().toString().endsWith("cpw.mods.modlauncher.api.ITransformationService");
|
||||
}, this::copyReplacing);
|
||||
}
|
||||
return upToDate[0];
|
||||
}
|
||||
|
||||
private void accessTransformForge(Logger logger) throws Exception {
|
||||
@@ -423,7 +444,8 @@ public class MinecraftPatchedProvider extends DependencyProvider {
|
||||
|
||||
TinyRemapper remapper = TinyRemapper.newRemapper()
|
||||
.logger(getProject().getLogger()::lifecycle)
|
||||
.withMappings(TinyRemapperMappingsHelper.create(mappingsWithSrg, "srg", "official", true))
|
||||
.logUnknownInvokeDynamic(false)
|
||||
.withMappings(TinyRemapperMappingsHelper.create(mappingsWithSrg, "srg", "official", true))
|
||||
.withMappings(InnerClassRemapper.of(input, mappingsWithSrg, "srg", "official"))
|
||||
.renameInvalidLocals(true)
|
||||
.rebuildSourceFilenames(true)
|
||||
@@ -487,7 +509,7 @@ public class MinecraftPatchedProvider extends DependencyProvider {
|
||||
logger.lifecycle(":copying resources");
|
||||
|
||||
// Copy resources
|
||||
MinecraftProvider minecraftProvider = getExtension().getMinecraftProvider();
|
||||
MinecraftProviderImpl minecraftProvider = getExtension().getMinecraftProvider();
|
||||
copyNonClassFiles(minecraftProvider.minecraftClientJar, minecraftMergedPatchedSrgJar);
|
||||
copyNonClassFiles(minecraftProvider.minecraftServerJar, minecraftMergedPatchedSrgJar);
|
||||
}
|
||||
@@ -552,7 +574,13 @@ public class MinecraftPatchedProvider extends DependencyProvider {
|
||||
}
|
||||
|
||||
private void copyUserdevFiles(File source, File target) throws IOException {
|
||||
walkFileSystems(source, target, file -> true, fs -> Collections.singleton(fs.getPath("inject")), (sourceFs, targetFs, sourcePath, targetPath) -> {
|
||||
// Removes the Forge name mapping service definition so that our own is used.
|
||||
// If there are multiple name mapping services with the same "understanding" pair
|
||||
// (source -> target namespace pair), modlauncher throws a fit and will crash.
|
||||
// To use our YarnNamingService instead of MCPNamingService, we have to remove this file.
|
||||
Predicate<Path> filter = file -> !file.toString().equals(NAME_MAPPING_SERVICE_PATH);
|
||||
|
||||
walkFileSystems(source, target, filter, fs -> Collections.singleton(fs.getPath("inject")), (sourceFs, targetFs, sourcePath, targetPath) -> {
|
||||
Path parent = targetPath.getParent();
|
||||
|
||||
if (parent != null) {
|
||||
@@ -561,6 +589,22 @@ public class MinecraftPatchedProvider extends DependencyProvider {
|
||||
|
||||
Files.copy(sourcePath, targetPath);
|
||||
});
|
||||
|
||||
try (FileSystemUtil.FileSystemDelegate delegate = FileSystemUtil.getJarFileSystem(target, false)) {
|
||||
Path manifestPath = delegate.get().getPath("META-INF/MANIFEST.MF");
|
||||
|
||||
Preconditions.checkArgument(Files.exists(manifestPath), "META-INF/MANIFEST.MF does not exist in patched srg jar!");
|
||||
Manifest manifest = new Manifest();
|
||||
|
||||
try (InputStream stream = Files.newInputStream(manifestPath)) {
|
||||
manifest.read(stream);
|
||||
manifest.getMainAttributes().putValue(LOOM_PATCH_VERSION_KEY, CURRENT_LOOM_PATCH_VERSION);
|
||||
}
|
||||
|
||||
try (OutputStream stream = Files.newOutputStream(manifestPath)) {
|
||||
manifest.write(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public File getMergedJar() {
|
||||
@@ -572,7 +616,7 @@ public class MinecraftPatchedProvider extends DependencyProvider {
|
||||
}
|
||||
|
||||
public boolean isAtDirty() {
|
||||
return atDirty;
|
||||
return atDirty || filesDirty;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2016, 2017, 2018 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.logging.Logger;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.configuration.providers.MinecraftProvider;
|
||||
|
||||
public class GradleMappingContext implements MappingContext {
|
||||
private final Project project;
|
||||
private final LoomGradleExtension extension;
|
||||
private final String workingDirName;
|
||||
|
||||
public GradleMappingContext(Project project, String workingDirName) {
|
||||
this.project = project;
|
||||
this.extension = project.getExtensions().getByType(LoomGradleExtension.class);
|
||||
this.workingDirName = workingDirName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File mavenFile(String mavenNotation) {
|
||||
Configuration configuration = project.getConfigurations().detachedConfiguration(project.getDependencies().create(mavenNotation));
|
||||
return configuration.getSingleFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingsProvider mappingsProvider() {
|
||||
return extension.getMappingsProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MinecraftProvider minecraftProvider() {
|
||||
return extension.getMinecraftProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File workingDirectory(String name) {
|
||||
File tempDir = new File(mappingsProvider().getMappingsDir().toFile(), workingDirName);
|
||||
tempDir.mkdirs();
|
||||
return new File(tempDir, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Logger getLogger() {
|
||||
return project.getLogger();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2016, 2017, 2018 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record LayeredMappingSpec(List<MappingsSpec<?>> layers) {
|
||||
public String getVersion() {
|
||||
// TODO something better?
|
||||
return "layered+hash.%d".formatted(Math.abs(hashCode()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2016, 2017, 2018 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.gradle.api.Action;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.crane.CraneMappingsSpec;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.intermediary.IntermediaryMappingsSpec;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.mojmap.MojangMappingsSpec;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.parchment.ParchmentMappingsSpecBuilder;
|
||||
|
||||
public class LayeredMappingSpecBuilder {
|
||||
private final List<MappingsSpec<?>> layers = new LinkedList<>();
|
||||
@Nullable
|
||||
private final LoomGradleExtension extension;
|
||||
|
||||
public LayeredMappingSpecBuilder(LoomGradleExtension extension) {
|
||||
this.extension = extension;
|
||||
}
|
||||
|
||||
public LayeredMappingSpecBuilder officialMojangMappings() {
|
||||
layers.add(new MojangMappingsSpec(() -> extension != null && extension.isSilentMojangMappingsLicenseEnabled()));
|
||||
return this;
|
||||
}
|
||||
|
||||
public LayeredMappingSpecBuilder parchment(String mavenNotation) {
|
||||
parchment(mavenNotation, parchmentMappingsSpecBuilder -> parchmentMappingsSpecBuilder.setRemovePrefix(true));
|
||||
return this;
|
||||
}
|
||||
|
||||
public LayeredMappingSpecBuilder parchment(String mavenNotation, Action<ParchmentMappingsSpecBuilder> action) {
|
||||
var builder = ParchmentMappingsSpecBuilder.builder(mavenNotation);
|
||||
action.execute(builder);
|
||||
layers.add(builder.build());
|
||||
return this;
|
||||
}
|
||||
|
||||
public LayeredMappingSpecBuilder crane(String mavenNotation) {
|
||||
layers.add(new CraneMappingsSpec(mavenNotation));
|
||||
return this;
|
||||
}
|
||||
|
||||
public LayeredMappingSpec build() {
|
||||
List<MappingsSpec<?>> builtLayers = new LinkedList<>();
|
||||
// Intermediary is always the base layer
|
||||
builtLayers.add(new IntermediaryMappingsSpec());
|
||||
builtLayers.addAll(layers);
|
||||
|
||||
return new LayeredMappingSpec(Collections.unmodifiableList(builtLayers));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2016, 2017, 2018 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import org.gradle.api.artifacts.Dependency;
|
||||
import org.gradle.api.artifacts.SelfResolvingDependency;
|
||||
import org.gradle.api.tasks.TaskDependency;
|
||||
import org.zeroturnaround.zip.ByteSource;
|
||||
import org.zeroturnaround.zip.ZipEntrySource;
|
||||
import org.zeroturnaround.zip.ZipUtil;
|
||||
|
||||
import net.fabricmc.loom.LoomGradlePlugin;
|
||||
import net.fabricmc.mappingio.adapter.MappingDstNsReorder;
|
||||
import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch;
|
||||
import net.fabricmc.mappingio.format.Tiny2Writer;
|
||||
import net.fabricmc.mappingio.tree.MemoryMappingTree;
|
||||
|
||||
public class LayeredMappingsDependency implements SelfResolvingDependency {
|
||||
private static final String GROUP = "loom";
|
||||
private static final String MODULE = "mappings";
|
||||
|
||||
private final MappingContext mappingContext;
|
||||
private final LayeredMappingSpec layeredMappingSpec;
|
||||
private final String version;
|
||||
|
||||
public LayeredMappingsDependency(MappingContext mappingContext, LayeredMappingSpec layeredMappingSpec, String version) {
|
||||
this.mappingContext = mappingContext;
|
||||
this.layeredMappingSpec = layeredMappingSpec;
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<File> resolve() {
|
||||
Path mappingsDir = mappingContext.mappingsProvider().getMappingsDir();
|
||||
Path mappingsFile = mappingsDir.resolve(String.format("%s.%s-%s.tiny", GROUP, MODULE, getVersion()));
|
||||
|
||||
if (!Files.exists(mappingsFile) || LoomGradlePlugin.refreshDeps) {
|
||||
try {
|
||||
var processor = new LayeredMappingsProcessor(layeredMappingSpec);
|
||||
MemoryMappingTree mappings = processor.getMappings(mappingContext);
|
||||
|
||||
try (Writer writer = new StringWriter()) {
|
||||
Tiny2Writer tiny2Writer = new Tiny2Writer(writer, false);
|
||||
|
||||
MappingDstNsReorder nsReorder = new MappingDstNsReorder(tiny2Writer, Collections.singletonList(MappingNamespace.NAMED.stringValue()));
|
||||
MappingSourceNsSwitch nsSwitch = new MappingSourceNsSwitch(nsReorder, MappingNamespace.INTERMEDIARY.stringValue());
|
||||
mappings.accept(nsSwitch);
|
||||
|
||||
Files.deleteIfExists(mappingsFile);
|
||||
|
||||
ZipUtil.pack(new ZipEntrySource[] {
|
||||
new ByteSource("mappings/mappings.tiny", writer.toString().getBytes(StandardCharsets.UTF_8))
|
||||
}, mappingsFile.toFile());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to resolve Mojang mappings", e);
|
||||
}
|
||||
}
|
||||
|
||||
return Collections.singleton(mappingsFile.toFile());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<File> resolve(boolean transitive) {
|
||||
return resolve();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskDependency getBuildDependencies() {
|
||||
return task -> Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroup() {
|
||||
return GROUP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return MODULE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contentEquals(Dependency dependency) {
|
||||
if (dependency instanceof LayeredMappingsDependency layeredMappingsDependency) {
|
||||
return Objects.equals(layeredMappingsDependency.getVersion(), this.getVersion());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dependency copy() {
|
||||
return new LayeredMappingsDependency(mappingContext, layeredMappingSpec, version);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getReason() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void because(String s) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2016, 2017, 2018 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch;
|
||||
import net.fabricmc.mappingio.tree.MemoryMappingTree;
|
||||
|
||||
public class LayeredMappingsProcessor {
|
||||
private final LayeredMappingSpec layeredMappingSpec;
|
||||
|
||||
public LayeredMappingsProcessor(LayeredMappingSpec spec) {
|
||||
this.layeredMappingSpec = spec;
|
||||
}
|
||||
|
||||
public MemoryMappingTree getMappings(MappingContext context) throws IOException {
|
||||
MemoryMappingTree mappingTree = new MemoryMappingTree();
|
||||
|
||||
List<Class<? extends MappingLayer>> visitedLayers = new ArrayList<>();
|
||||
|
||||
for (MappingsSpec<?> spec : layeredMappingSpec.layers()) {
|
||||
MappingLayer layer = spec.createLayer(context);
|
||||
|
||||
for (Class<? extends MappingLayer> dependentLayer : layer.dependsOn()) {
|
||||
if (!visitedLayers.contains(dependentLayer)) {
|
||||
throw new RuntimeException("Layer %s depends on %s".formatted(layer.getClass().getName(), dependentLayer.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
visitedLayers.add(layer.getClass());
|
||||
|
||||
// We have to rebuild a new tree to work on when a layer doesnt merge into layered
|
||||
boolean rebuild = layer.getSourceNamespace() != MappingNamespace.NAMED;
|
||||
MemoryMappingTree workingTree;
|
||||
|
||||
if (rebuild) {
|
||||
var tempTree = new MemoryMappingTree();
|
||||
|
||||
// This can be null on the first layer
|
||||
if (mappingTree.getSrcNamespace() != null) {
|
||||
var sourceNsSwitch = new MappingSourceNsSwitch(tempTree, layer.getSourceNamespace().stringValue());
|
||||
mappingTree.accept(sourceNsSwitch);
|
||||
}
|
||||
|
||||
workingTree = tempTree;
|
||||
} else {
|
||||
workingTree = mappingTree;
|
||||
}
|
||||
|
||||
try {
|
||||
layer.visit(workingTree);
|
||||
} catch (IOException e) {
|
||||
throw new IOException("Failed to visit: " + layer.getClass(), e);
|
||||
}
|
||||
|
||||
if (rebuild) {
|
||||
mappingTree = new MemoryMappingTree();
|
||||
workingTree.accept(new MappingSourceNsSwitch(mappingTree, MappingNamespace.NAMED.stringValue()));
|
||||
}
|
||||
}
|
||||
|
||||
return mappingTree;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2016, 2017, 2018 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.gradle.api.logging.Logger;
|
||||
|
||||
import net.fabricmc.loom.configuration.providers.MinecraftProvider;
|
||||
|
||||
public interface MappingContext {
|
||||
File mavenFile(String mavenNotation);
|
||||
|
||||
MappingsProvider mappingsProvider();
|
||||
|
||||
MinecraftProvider minecraftProvider();
|
||||
|
||||
default String minecraftVersion() {
|
||||
return minecraftProvider().minecraftVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a temporary working dir to be used to store working files.
|
||||
*/
|
||||
File workingDirectory(String name);
|
||||
|
||||
Logger getLogger();
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2016, 2017, 2018 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import net.fabricmc.mappingio.MappingVisitor;
|
||||
|
||||
public interface MappingLayer {
|
||||
void visit(MappingVisitor mappingVisitor) throws IOException;
|
||||
|
||||
default MappingNamespace getSourceNamespace() {
|
||||
return MappingNamespace.NAMED;
|
||||
}
|
||||
|
||||
default List<Class<? extends MappingLayer>> dependsOn() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2016, 2017, 2018 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public enum MappingNamespace {
|
||||
OFFICIAL,
|
||||
INTERMEDIARY,
|
||||
NAMED;
|
||||
|
||||
public String stringValue() {
|
||||
return name().toLowerCase(Locale.ROOT);
|
||||
}
|
||||
}
|
||||
@@ -24,515 +24,11 @@
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Stopwatch;
|
||||
import com.google.common.net.UrlEscapers;
|
||||
import com.google.gson.JsonObject;
|
||||
import dev.architectury.mappingslayers.api.utils.MappingsModificationUtils;
|
||||
import dev.architectury.mappingslayers.api.utils.MappingsUtils;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.tools.ant.util.StringUtils;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.zeroturnaround.zip.FileSource;
|
||||
import org.zeroturnaround.zip.ZipEntrySource;
|
||||
import org.zeroturnaround.zip.ZipUtil;
|
||||
public interface MappingsProvider {
|
||||
Path getMappingsDir();
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.LoomGradlePlugin;
|
||||
import net.fabricmc.loom.configuration.DependencyProvider;
|
||||
import net.fabricmc.loom.configuration.accesswidener.AccessWidenerJarProcessor;
|
||||
import net.fabricmc.loom.configuration.processors.JarProcessorManager;
|
||||
import net.fabricmc.loom.configuration.processors.MinecraftProcessedProvider;
|
||||
import net.fabricmc.loom.configuration.providers.MinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.forge.MinecraftPatchedProvider;
|
||||
import net.fabricmc.loom.configuration.providers.forge.SrgProvider;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
import net.fabricmc.loom.util.DeletingFileVisitor;
|
||||
import net.fabricmc.loom.util.DownloadUtil;
|
||||
import net.fabricmc.loom.util.srg.MCPReader;
|
||||
import net.fabricmc.loom.util.srg.SrgMerger;
|
||||
import net.fabricmc.loom.util.srg.SrgNamedWriter;
|
||||
import net.fabricmc.mapping.reader.v2.TinyMetadata;
|
||||
import net.fabricmc.mapping.reader.v2.TinyV2Factory;
|
||||
import net.fabricmc.mapping.tree.TinyTree;
|
||||
import net.fabricmc.stitch.Command;
|
||||
import net.fabricmc.stitch.commands.CommandProposeFieldNames;
|
||||
import net.fabricmc.stitch.commands.tinyv2.CommandMergeTinyV2;
|
||||
import net.fabricmc.stitch.commands.tinyv2.TinyFile;
|
||||
import net.fabricmc.stitch.commands.tinyv2.TinyV2Writer;
|
||||
|
||||
public class MappingsProvider extends DependencyProvider {
|
||||
public MinecraftMappedProvider mappedProvider;
|
||||
public MinecraftPatchedProvider patchedProvider;
|
||||
|
||||
public String mappingsName;
|
||||
public String minecraftVersion;
|
||||
public String mappingsVersion;
|
||||
|
||||
protected final Path mappingsDir;
|
||||
private final Path mappingsStepsDir;
|
||||
private Path intermediaryTiny;
|
||||
private boolean hasRefreshed = false;
|
||||
// The mappings that gradle gives us
|
||||
private Path baseTinyMappings;
|
||||
// The mappings we use in practice
|
||||
public File tinyMappings;
|
||||
// tinyMappings wrapped in a jar
|
||||
public File tinyMappingsJar;
|
||||
public Path tinyMappingsWithSrg;
|
||||
public File mixinTinyMappingsWithSrg; // FORGE: The mixin mappings have srg names in intermediary.
|
||||
public File srgToNamedSrg; // FORGE: srg to named in srg file format
|
||||
|
||||
private File unpickDefinitionsFile;
|
||||
private boolean hasUnpickDefinitions;
|
||||
private UnpickMetadata unpickMetadata;
|
||||
|
||||
public MappingsProvider(Project project) {
|
||||
super(project);
|
||||
mappingsDir = getExtension().getUserCache().toPath().resolve("mappings");
|
||||
mappingsStepsDir = mappingsDir.resolve("steps");
|
||||
}
|
||||
|
||||
public void clean() throws IOException {
|
||||
FileUtils.deleteDirectory(mappingsDir.toFile());
|
||||
}
|
||||
|
||||
public TinyTree getMappings() throws IOException {
|
||||
return MappingsCache.INSTANCE.get(tinyMappings.toPath());
|
||||
}
|
||||
|
||||
public TinyTree getMappingsWithSrg() throws IOException {
|
||||
if (getExtension().shouldGenerateSrgTiny()) {
|
||||
return MappingsCache.INSTANCE.get(tinyMappingsWithSrg);
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException("Not running with Forge support / Tiny srg support.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void provide(DependencyInfo dependency, Consumer<Runnable> postPopulationScheduler) throws Exception {
|
||||
MinecraftProvider minecraftProvider = getDependencyManager().getProvider(MinecraftProvider.class);
|
||||
|
||||
getProject().getLogger().info(":setting up mappings (" + dependency.getDependency().getName() + " " + dependency.getResolvedVersion() + ")");
|
||||
|
||||
String version = dependency.getResolvedVersion();
|
||||
File mappingsJar = dependency.resolveFile().orElseThrow(() -> new RuntimeException("Could not find yarn mappings: " + dependency));
|
||||
|
||||
this.mappingsName = StringUtils.removeSuffix(dependency.getDependency().getGroup() + "." + dependency.getDependency().getName(), "-unmerged");
|
||||
this.minecraftVersion = minecraftProvider.getMinecraftVersion();
|
||||
|
||||
boolean isV2;
|
||||
|
||||
if (isMCP(mappingsJar.toPath())) {
|
||||
File old = mappingsJar;
|
||||
mappingsJar = mappingsDir.resolve(StringUtils.removeSuffix(mappingsJar.getName(), ".zip") + "-" + minecraftVersion + ".jar").toFile();
|
||||
FileUtils.copyFile(old, mappingsJar);
|
||||
mappingsName += "-" + minecraftVersion;
|
||||
}
|
||||
|
||||
// Only do this for official yarn, there isn't really a way we can get the mc version for all mappings
|
||||
if (dependency.getDependency().getGroup() != null && dependency.getDependency().getGroup().equals("net.fabricmc") && dependency.getDependency().getName().equals("yarn") && dependency.getDependency().getVersion() != null) {
|
||||
String yarnVersion = dependency.getDependency().getVersion();
|
||||
char separator = yarnVersion.contains("+build.") ? '+' : yarnVersion.contains("-") ? '-' : '.';
|
||||
String yarnMinecraftVersion = yarnVersion.substring(0, yarnVersion.lastIndexOf(separator));
|
||||
|
||||
if (!yarnMinecraftVersion.equalsIgnoreCase(minecraftVersion)) {
|
||||
throw new RuntimeException(String.format("Minecraft Version (%s) does not match yarn's minecraft version (%s)", minecraftVersion, yarnMinecraftVersion));
|
||||
}
|
||||
|
||||
// We can save reading the zip file + header by checking the file name
|
||||
isV2 = mappingsJar.getName().endsWith("-v2.jar");
|
||||
} else {
|
||||
isV2 = doesJarContainV2Mappings(mappingsJar.toPath());
|
||||
}
|
||||
|
||||
this.mappingsVersion = version + (isV2 ? "-v2" : "");
|
||||
|
||||
initFiles();
|
||||
|
||||
if (isRefreshDeps()) {
|
||||
cleanFiles();
|
||||
}
|
||||
|
||||
Files.createDirectories(mappingsDir);
|
||||
Files.createDirectories(mappingsStepsDir);
|
||||
|
||||
String[] depStringSplit = dependency.getDepString().split(":");
|
||||
String jarClassifier = "final";
|
||||
|
||||
if (depStringSplit.length >= 4) {
|
||||
jarClassifier = jarClassifier + depStringSplit[3];
|
||||
}
|
||||
|
||||
String removeSuffix = StringUtils.removeSuffix(mappingsJar.getName(), ".jar");
|
||||
tinyMappings = mappingsDir.resolve(removeSuffix + ".tiny").toFile();
|
||||
unpickDefinitionsFile = mappingsDir.resolve(removeSuffix + ".unpick").toFile();
|
||||
tinyMappingsJar = new File(getExtension().getUserCache(), removeSuffix + "-" + jarClassifier + ".jar");
|
||||
tinyMappingsWithSrg = mappingsDir.resolve(removeSuffix + "-srg.tiny");
|
||||
mixinTinyMappingsWithSrg = mappingsDir.resolve(removeSuffix + "-mixin-srg.tiny").toFile();
|
||||
srgToNamedSrg = mappingsDir.resolve(removeSuffix + "-srg-named.srg").toFile();
|
||||
|
||||
if (!tinyMappings.exists() || isRefreshDeps()) {
|
||||
storeMappings(getProject(), minecraftProvider, mappingsJar.toPath(), postPopulationScheduler);
|
||||
} else {
|
||||
try (FileSystem fileSystem = FileSystems.newFileSystem(mappingsJar.toPath(), (ClassLoader) null)) {
|
||||
extractUnpickDefinitions(fileSystem, unpickDefinitionsFile.toPath());
|
||||
}
|
||||
}
|
||||
|
||||
if (getExtension().isForge()) {
|
||||
patchedProvider = new MinecraftPatchedProvider(getProject());
|
||||
patchedProvider.provide(dependency, postPopulationScheduler);
|
||||
}
|
||||
|
||||
manipulateMappings(mappingsJar.toPath());
|
||||
|
||||
if (getExtension().shouldGenerateSrgTiny()) {
|
||||
if (Files.notExists(tinyMappingsWithSrg) || isRefreshDeps()) {
|
||||
// Merge tiny mappings with srg
|
||||
SrgMerger.mergeSrg(getExtension().getSrgProvider().getSrg().toPath(), tinyMappings.toPath(), tinyMappingsWithSrg, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (!tinyMappingsJar.exists() || isRefreshDeps()) {
|
||||
ZipUtil.pack(new ZipEntrySource[] {new FileSource("mappings/mappings.tiny", tinyMappings)}, tinyMappingsJar);
|
||||
}
|
||||
|
||||
if (hasUnpickDefinitions()) {
|
||||
String notation = String.format("%s:%s:%s:constants",
|
||||
dependency.getDependency().getGroup(),
|
||||
dependency.getDependency().getName(),
|
||||
dependency.getDependency().getVersion()
|
||||
);
|
||||
|
||||
getProject().getDependencies().add(Constants.Configurations.MAPPING_CONSTANTS, notation);
|
||||
populateUnpickClasspath();
|
||||
}
|
||||
|
||||
if (getExtension().isForge()) {
|
||||
if (!getExtension().shouldGenerateSrgTiny()) {
|
||||
throw new IllegalStateException("We have to generate srg tiny in a forge environment!");
|
||||
}
|
||||
|
||||
if (!mixinTinyMappingsWithSrg.exists() || isRefreshDeps()) {
|
||||
List<String> lines = new ArrayList<>(Files.readAllLines(tinyMappingsWithSrg));
|
||||
lines.set(0, lines.get(0).replace("intermediary", "yraidemretni").replace("srg", "intermediary"));
|
||||
Files.deleteIfExists(mixinTinyMappingsWithSrg.toPath());
|
||||
Files.write(mixinTinyMappingsWithSrg.toPath(), lines);
|
||||
}
|
||||
|
||||
if (!srgToNamedSrg.exists() || isRefreshDeps()) {
|
||||
SrgNamedWriter.writeTo(getProject().getLogger(), srgToNamedSrg.toPath(), getMappingsWithSrg(), "srg", "named");
|
||||
}
|
||||
}
|
||||
|
||||
addDependency(tinyMappingsJar, Constants.Configurations.MAPPINGS_FINAL);
|
||||
|
||||
LoomGradleExtension extension = getExtension();
|
||||
|
||||
if (extension.accessWidener != null) {
|
||||
extension.addJarProcessor(new AccessWidenerJarProcessor(getProject()));
|
||||
}
|
||||
|
||||
JarProcessorManager processorManager = new JarProcessorManager(extension.getJarProcessors());
|
||||
extension.setJarProcessorManager(processorManager);
|
||||
processorManager.setupProcessors();
|
||||
|
||||
if (extension.isForge()) {
|
||||
patchedProvider.finishProvide();
|
||||
}
|
||||
|
||||
if (processorManager.active() || (extension.isForge() && patchedProvider.usesProjectCache())) {
|
||||
mappedProvider = new MinecraftProcessedProvider(getProject(), processorManager);
|
||||
getProject().getLogger().lifecycle("Using project based jar storage");
|
||||
} else {
|
||||
mappedProvider = new MinecraftMappedProvider(getProject());
|
||||
}
|
||||
|
||||
mappedProvider.initFiles(minecraftProvider, this);
|
||||
mappedProvider.provide(dependency, postPopulationScheduler);
|
||||
}
|
||||
|
||||
public void manipulateMappings(Path mappingsJar) throws IOException { }
|
||||
|
||||
private void storeMappings(Project project, MinecraftProvider minecraftProvider, Path yarnJar, Consumer<Runnable> postPopulationScheduler)
|
||||
throws Exception {
|
||||
project.getLogger().info(":extracting " + yarnJar.getFileName());
|
||||
|
||||
if (isMCP(yarnJar)) {
|
||||
readAndMergeMCP(yarnJar, postPopulationScheduler);
|
||||
return;
|
||||
}
|
||||
|
||||
try (FileSystem fileSystem = FileSystems.newFileSystem(yarnJar, (ClassLoader) null)) {
|
||||
extractMappings(fileSystem, baseTinyMappings);
|
||||
extractUnpickDefinitions(fileSystem, unpickDefinitionsFile.toPath());
|
||||
}
|
||||
|
||||
if (baseMappingsAreMergedV2()) {
|
||||
// Architectury Loom Patch
|
||||
// If a merged tiny v2 mappings file is provided
|
||||
// Skip merging, should save a lot of time
|
||||
Files.copy(baseTinyMappings, tinyMappings.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||
} else if (baseMappingsAreV2()) {
|
||||
// These are unmerged v2 mappings
|
||||
mergeAndSaveMappings(project, yarnJar);
|
||||
} else {
|
||||
// These are merged v1 mappings
|
||||
if (tinyMappings.exists()) {
|
||||
tinyMappings.delete();
|
||||
}
|
||||
|
||||
project.getLogger().lifecycle(":populating field names");
|
||||
suggestFieldNames(minecraftProvider, baseTinyMappings, tinyMappings.toPath());
|
||||
}
|
||||
}
|
||||
|
||||
private void readAndMergeMCP(Path mcpJar, Consumer<Runnable> postPopulationScheduler) throws Exception {
|
||||
Path intermediaryTinyPath = getIntermediaryTiny();
|
||||
SrgProvider provider = getExtension().getSrgProvider();
|
||||
|
||||
if (provider == null) {
|
||||
if (!getExtension().shouldGenerateSrgTiny()) {
|
||||
Configuration srg = getProject().getConfigurations().maybeCreate(Constants.Configurations.SRG);
|
||||
srg.setTransitive(false);
|
||||
}
|
||||
|
||||
provider = new SrgProvider(getProject());
|
||||
getProject().getDependencies().add(provider.getTargetConfig(), "de.oceanlabs.mcp:mcp_config:" + minecraftVersion);
|
||||
Configuration configuration = getProject().getConfigurations().getByName(provider.getTargetConfig());
|
||||
provider.provide(DependencyInfo.create(getProject(), configuration.getDependencies().iterator().next(), configuration), postPopulationScheduler);
|
||||
}
|
||||
|
||||
Path srgPath = provider.getSrg().toPath();
|
||||
|
||||
TinyFile file = new MCPReader(intermediaryTinyPath, srgPath).read(mcpJar);
|
||||
TinyV2Writer.write(file, tinyMappings.toPath());
|
||||
}
|
||||
|
||||
private boolean isMCP(Path path) throws IOException {
|
||||
try (FileSystem fs = FileSystems.newFileSystem(path, (ClassLoader) null)) {
|
||||
return Files.exists(fs.getPath("fields.csv")) && Files.exists(fs.getPath("methods.csv"));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean baseMappingsAreV2() throws IOException {
|
||||
try (BufferedReader reader = Files.newBufferedReader(baseTinyMappings)) {
|
||||
TinyV2Factory.readMetadata(reader);
|
||||
return true;
|
||||
} catch (IllegalArgumentException e) {
|
||||
// TODO: just check the mappings version when Parser supports V1 in readMetadata()
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean doesJarContainV2Mappings(Path path) throws IOException {
|
||||
try (FileSystem fs = FileSystems.newFileSystem(path, (ClassLoader) null)) {
|
||||
try (BufferedReader reader = Files.newBufferedReader(fs.getPath("mappings", "mappings.tiny"))) {
|
||||
TinyV2Factory.readMetadata(reader);
|
||||
return true;
|
||||
} catch (IllegalArgumentException | NoSuchFileException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean baseMappingsAreMergedV2() throws IOException {
|
||||
try (BufferedReader reader = Files.newBufferedReader(baseTinyMappings)) {
|
||||
TinyMetadata metadata = TinyV2Factory.readMetadata(reader);
|
||||
return metadata.getNamespaces().containsAll(Arrays.asList("named", "intermediary", "official"));
|
||||
} catch (IllegalArgumentException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void extractMappings(FileSystem jar, Path extractTo) throws IOException {
|
||||
Files.copy(jar.getPath("mappings/mappings.tiny"), extractTo, StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
|
||||
private void extractUnpickDefinitions(FileSystem jar, Path extractTo) throws IOException {
|
||||
Path unpickPath = jar.getPath("extras/definitions.unpick");
|
||||
Path unpickMetadataPath = jar.getPath("extras/unpick.json");
|
||||
|
||||
if (!Files.exists(unpickPath) || !Files.exists(unpickMetadataPath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Files.copy(unpickPath, extractTo, StandardCopyOption.REPLACE_EXISTING);
|
||||
|
||||
unpickMetadata = parseUnpickMetadata(unpickMetadataPath);
|
||||
hasUnpickDefinitions = true;
|
||||
}
|
||||
|
||||
private UnpickMetadata parseUnpickMetadata(Path input) throws IOException {
|
||||
JsonObject jsonObject = LoomGradlePlugin.GSON.fromJson(Files.readString(input), JsonObject.class);
|
||||
|
||||
if (!jsonObject.has("version") || jsonObject.get("version").getAsInt() != 1) {
|
||||
throw new UnsupportedOperationException("Unsupported unpick version");
|
||||
}
|
||||
|
||||
return new UnpickMetadata(
|
||||
jsonObject.get("unpickGroup").getAsString(),
|
||||
jsonObject.get("unpickVersion").getAsString()
|
||||
);
|
||||
}
|
||||
|
||||
private void populateUnpickClasspath() {
|
||||
String unpickCliName = "unpick-cli";
|
||||
getProject().getDependencies().add(Constants.Configurations.UNPICK_CLASSPATH,
|
||||
String.format("%s:%s:%s", unpickMetadata.unpickGroup, unpickCliName, unpickMetadata.unpickVersion)
|
||||
);
|
||||
}
|
||||
|
||||
private void extractIntermediary(Path intermediaryJar, Path intermediaryTiny) throws IOException {
|
||||
getProject().getLogger().info(":extracting " + intermediaryJar.getFileName());
|
||||
|
||||
try (FileSystem unmergedIntermediaryFs = FileSystems.newFileSystem(intermediaryJar, (ClassLoader) null)) {
|
||||
extractMappings(unmergedIntermediaryFs, intermediaryTiny);
|
||||
}
|
||||
}
|
||||
|
||||
private void mergeAndSaveMappings(Project project, Path unmergedYarnJar) throws IOException {
|
||||
Path unmergedYarn = Paths.get(mappingsStepsDir.toString(), "unmerged-yarn.tiny");
|
||||
project.getLogger().info(":extracting " + unmergedYarnJar.getFileName());
|
||||
|
||||
try (FileSystem unmergedYarnJarFs = FileSystems.newFileSystem(unmergedYarnJar, (ClassLoader) null)) {
|
||||
extractMappings(unmergedYarnJarFs, unmergedYarn);
|
||||
}
|
||||
|
||||
Stopwatch stopwatch = Stopwatch.createStarted();
|
||||
project.getLogger().info(":merging mappings");
|
||||
Path invertedIntermediary = Paths.get(mappingsStepsDir.toString(), "inverted-intermediary.tiny");
|
||||
reorderMappings(getIntermediaryTiny(), invertedIntermediary, "intermediary", "official");
|
||||
Path unorderedMergedMappings = Paths.get(mappingsStepsDir.toString(), "unordered-merged.tiny");
|
||||
mergeMappings(invertedIntermediary, unmergedYarn, unorderedMergedMappings);
|
||||
reorderMappings(unorderedMergedMappings, tinyMappings.toPath(), "official", "intermediary", "named");
|
||||
Files.deleteIfExists(invertedIntermediary);
|
||||
Files.deleteIfExists(unorderedMergedMappings);
|
||||
project.getLogger().info(":merged mappings in " + stopwatch.stop());
|
||||
}
|
||||
|
||||
private void reorderMappings(Path oldMappings, Path newMappings, String... newOrder) throws IOException {
|
||||
MappingsModificationUtils.modify(oldMappings, newMappings, tree ->
|
||||
MappingsUtils.reorderNamespaces(tree, Arrays.asList(newOrder)));
|
||||
}
|
||||
|
||||
private void mergeMappings(Path intermediaryMappings, Path yarnMappings, Path newMergedMappings) {
|
||||
try {
|
||||
Command command = new CommandMergeTinyV2();
|
||||
runCommand(command, intermediaryMappings.toAbsolutePath().toString(),
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
private void suggestFieldNames(MinecraftProvider minecraftProvider, Path oldMappings, Path newMappings) {
|
||||
Command command = new CommandProposeFieldNames();
|
||||
runCommand(command, minecraftProvider.getMergedJar().getAbsolutePath(),
|
||||
oldMappings.toAbsolutePath().toString(),
|
||||
newMappings.toAbsolutePath().toString());
|
||||
}
|
||||
|
||||
private void runCommand(Command command, String... args) {
|
||||
try {
|
||||
command.run(args);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void initFiles() {
|
||||
baseTinyMappings = mappingsDir.resolve(mappingsName + "-tiny-" + minecraftVersion + "-" + mappingsVersion + "-base");
|
||||
}
|
||||
|
||||
public void cleanFiles() {
|
||||
try {
|
||||
if (Files.exists(mappingsStepsDir)) {
|
||||
Files.walkFileTree(mappingsStepsDir, new DeletingFileVisitor());
|
||||
}
|
||||
|
||||
if (Files.exists(baseTinyMappings)) {
|
||||
Files.deleteIfExists(baseTinyMappings);
|
||||
}
|
||||
|
||||
if (tinyMappings != null) {
|
||||
tinyMappings.delete();
|
||||
}
|
||||
|
||||
if (tinyMappingsJar != null) {
|
||||
tinyMappingsJar.delete();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTargetConfig() {
|
||||
return Constants.Configurations.MAPPINGS;
|
||||
}
|
||||
|
||||
public Path getMappingsDir() {
|
||||
return mappingsDir;
|
||||
}
|
||||
|
||||
public Path getIntermediaryTiny() throws IOException {
|
||||
if (intermediaryTiny == null) {
|
||||
minecraftVersion = getExtension().getMinecraftProvider().getMinecraftVersion();
|
||||
Preconditions.checkNotNull(minecraftVersion, "Minecraft version cannot be null");
|
||||
|
||||
intermediaryTiny = mappingsDir.resolve(String.format("intermediary-%s-v2.tiny", minecraftVersion));
|
||||
|
||||
if (!Files.exists(intermediaryTiny) || (isRefreshDeps() && !hasRefreshed)) {
|
||||
hasRefreshed = true;
|
||||
|
||||
// Download and extract intermediary
|
||||
String encodedMinecraftVersion = UrlEscapers.urlFragmentEscaper().escape(minecraftVersion);
|
||||
String intermediaryArtifactUrl = getExtension().getIntermediaryUrl().apply(encodedMinecraftVersion);
|
||||
Path intermediaryJar = mappingsDir.resolve("v2-intermediary-" + minecraftVersion + ".jar");
|
||||
DownloadUtil.downloadIfChanged(new URL(intermediaryArtifactUrl), intermediaryJar.toFile(), getProject().getLogger());
|
||||
|
||||
extractIntermediary(intermediaryJar, intermediaryTiny);
|
||||
}
|
||||
}
|
||||
|
||||
return intermediaryTiny;
|
||||
}
|
||||
|
||||
public String getMappingsKey() {
|
||||
return mappingsName + "." + minecraftVersion.replace(' ', '_').replace('.', '_').replace('-', '_') + "." + mappingsVersion;
|
||||
}
|
||||
|
||||
public File getUnpickDefinitionsFile() {
|
||||
return unpickDefinitionsFile;
|
||||
}
|
||||
|
||||
public boolean hasUnpickDefinitions() {
|
||||
return hasUnpickDefinitions;
|
||||
}
|
||||
|
||||
public record UnpickMetadata(String unpickGroup, String unpickVersion) {
|
||||
}
|
||||
File intermediaryTinyFile();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,582 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2016, 2017, 2018 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Stopwatch;
|
||||
import com.google.common.net.UrlEscapers;
|
||||
import com.google.gson.JsonObject;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.tools.ant.util.StringUtils;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.zeroturnaround.zip.FileSource;
|
||||
import org.zeroturnaround.zip.ZipEntrySource;
|
||||
import org.zeroturnaround.zip.ZipUtil;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.LoomGradlePlugin;
|
||||
import net.fabricmc.loom.configuration.DependencyProvider;
|
||||
import net.fabricmc.loom.configuration.accesswidener.AccessWidenerJarProcessor;
|
||||
import net.fabricmc.loom.configuration.processors.JarProcessorManager;
|
||||
import net.fabricmc.loom.configuration.processors.MinecraftProcessedProvider;
|
||||
import net.fabricmc.loom.configuration.providers.MinecraftProviderImpl;
|
||||
import net.fabricmc.loom.configuration.providers.forge.MinecraftPatchedProvider;
|
||||
import net.fabricmc.loom.configuration.providers.forge.SrgProvider;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
import net.fabricmc.loom.util.DeletingFileVisitor;
|
||||
import net.fabricmc.loom.util.DownloadUtil;
|
||||
import net.fabricmc.loom.util.srg.MCPReader;
|
||||
import net.fabricmc.loom.util.srg.SrgMerger;
|
||||
import net.fabricmc.loom.util.srg.SrgNamedWriter;
|
||||
import net.fabricmc.mapping.reader.v2.TinyMetadata;
|
||||
import net.fabricmc.mapping.reader.v2.TinyV2Factory;
|
||||
import net.fabricmc.mapping.tree.TinyTree;
|
||||
import net.fabricmc.mappingio.adapter.MappingNsCompleter;
|
||||
import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch;
|
||||
import net.fabricmc.mappingio.format.Tiny2Reader;
|
||||
import net.fabricmc.mappingio.format.Tiny2Writer;
|
||||
import net.fabricmc.mappingio.tree.MemoryMappingTree;
|
||||
import net.fabricmc.stitch.Command;
|
||||
import net.fabricmc.stitch.commands.CommandProposeFieldNames;
|
||||
import net.fabricmc.stitch.commands.tinyv2.TinyFile;
|
||||
import net.fabricmc.stitch.commands.tinyv2.TinyV2Writer;
|
||||
|
||||
public class MappingsProviderImpl extends DependencyProvider implements MappingsProvider {
|
||||
public MinecraftMappedProvider mappedProvider;
|
||||
public MinecraftPatchedProvider patchedProvider;
|
||||
|
||||
public String mappingsName;
|
||||
public String minecraftVersion;
|
||||
public String mappingsVersion;
|
||||
public String removeSuffix;
|
||||
|
||||
protected final Path mappingsDir;
|
||||
protected Path mappingsVersionedDir;
|
||||
private final Path mappingsStepsDir;
|
||||
private Path intermediaryTiny;
|
||||
private boolean hasRefreshed = false;
|
||||
// The mappings that gradle gives us
|
||||
private Path baseTinyMappings;
|
||||
// The mappings we use in practice
|
||||
public File tinyMappings;
|
||||
// tinyMappings wrapped in a jar
|
||||
public File tinyMappingsJar;
|
||||
public Path tinyMappingsWithSrg;
|
||||
public File mixinTinyMappingsWithSrg; // FORGE: The mixin mappings have srg names in intermediary.
|
||||
public File srgToNamedSrg; // FORGE: srg to named in srg file format
|
||||
|
||||
private File unpickDefinitionsFile;
|
||||
private boolean hasUnpickDefinitions;
|
||||
private UnpickMetadata unpickMetadata;
|
||||
|
||||
public MappingsProviderImpl(Project project) {
|
||||
super(project);
|
||||
mappingsDir = getExtension().getUserCache().toPath().resolve("mappings");
|
||||
mappingsStepsDir = mappingsDir.resolve("steps");
|
||||
}
|
||||
|
||||
public Path getMappingsVersionedDir() throws IOException {
|
||||
if (mappingsVersionedDir == null) {
|
||||
mappingsVersionedDir = mappingsDir.resolve(getExtension().getMinecraftProvider().minecraftVersion());
|
||||
|
||||
if (!Files.exists(mappingsVersionedDir)) {
|
||||
Files.createDirectories(mappingsVersionedDir);
|
||||
}
|
||||
}
|
||||
|
||||
return mappingsVersionedDir;
|
||||
}
|
||||
|
||||
public Path getMappedVersionedDir(String name) throws IOException {
|
||||
Path dir = getMappingsVersionedDir().resolve(name);
|
||||
|
||||
if (!Files.exists(dir)) {
|
||||
Files.createDirectories(dir);
|
||||
}
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
public void clean() throws IOException {
|
||||
FileUtils.deleteDirectory(mappingsDir.toFile());
|
||||
}
|
||||
|
||||
public TinyTree getMappings() throws IOException {
|
||||
return MappingsCache.INSTANCE.get(tinyMappings.toPath());
|
||||
}
|
||||
|
||||
public TinyTree getMappingsWithSrg() throws IOException {
|
||||
if (getExtension().shouldGenerateSrgTiny()) {
|
||||
return MappingsCache.INSTANCE.get(tinyMappingsWithSrg);
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException("Not running with Forge support / Tiny srg support.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void provide(DependencyInfo dependency, Consumer<Runnable> postPopulationScheduler) throws Exception {
|
||||
MinecraftProviderImpl minecraftProvider = getDependencyManager().getProvider(MinecraftProviderImpl.class);
|
||||
|
||||
getProject().getLogger().info(":setting up mappings (" + dependency.getDependency().getName() + " " + dependency.getResolvedVersion() + ")");
|
||||
|
||||
String version = dependency.getResolvedVersion();
|
||||
File mappingsJar = dependency.resolveFile().orElseThrow(() -> new RuntimeException("Could not find yarn mappings: " + dependency));
|
||||
|
||||
this.mappingsName = StringUtils.removeSuffix(dependency.getDependency().getGroup() + "." + dependency.getDependency().getName(), "-unmerged");
|
||||
this.minecraftVersion = minecraftProvider.minecraftVersion();
|
||||
|
||||
boolean isV2;
|
||||
|
||||
if (isMCP(mappingsJar.toPath())) {
|
||||
File old = mappingsJar;
|
||||
mappingsJar = mappingsDir.resolve(StringUtils.removeSuffix(mappingsJar.getName(), ".zip") + "-" + minecraftVersion + ".jar").toFile();
|
||||
FileUtils.copyFile(old, mappingsJar);
|
||||
mappingsName += "-" + minecraftVersion;
|
||||
}
|
||||
|
||||
// Only do this for official yarn, there isn't really a way we can get the mc version for all mappings
|
||||
if (dependency.getDependency().getGroup() != null && dependency.getDependency().getGroup().equals("net.fabricmc") && dependency.getDependency().getName().equals("yarn") && dependency.getDependency().getVersion() != null) {
|
||||
String yarnVersion = dependency.getDependency().getVersion();
|
||||
char separator = yarnVersion.contains("+build.") ? '+' : yarnVersion.contains("-") ? '-' : '.';
|
||||
String yarnMinecraftVersion = yarnVersion.substring(0, yarnVersion.lastIndexOf(separator));
|
||||
|
||||
if (!yarnMinecraftVersion.equalsIgnoreCase(minecraftVersion)) {
|
||||
throw new RuntimeException(String.format("Minecraft Version (%s) does not match yarn's minecraft version (%s)", minecraftVersion, yarnMinecraftVersion));
|
||||
}
|
||||
|
||||
// We can save reading the zip file + header by checking the file name
|
||||
isV2 = mappingsJar.getName().endsWith("-v2.jar") || mappingsJar.getName().endsWith("-mergedv2.jar");
|
||||
} else {
|
||||
isV2 = doesJarContainV2Mappings(mappingsJar.toPath());
|
||||
}
|
||||
|
||||
this.removeSuffix = StringUtils.removeSuffix(mappingsJar.getName(), ".jar");
|
||||
this.mappingsVersion = version + (isV2 ? "-v2" : "");
|
||||
|
||||
initFiles();
|
||||
|
||||
if (isRefreshDeps()) {
|
||||
cleanFiles();
|
||||
}
|
||||
|
||||
Files.createDirectories(mappingsDir);
|
||||
Files.createDirectories(mappingsStepsDir);
|
||||
|
||||
String[] depStringSplit = dependency.getDepString().split(":");
|
||||
String jarClassifier = "final";
|
||||
|
||||
if (depStringSplit.length >= 4) {
|
||||
jarClassifier = jarClassifier + depStringSplit[3];
|
||||
}
|
||||
|
||||
Path mappedVersionedDir = getMappedVersionedDir(removeSuffix);
|
||||
tinyMappings = mappedVersionedDir.resolve("mappings.tiny").toFile();
|
||||
unpickDefinitionsFile = mappedVersionedDir.resolve("definitions.unpick").toFile();
|
||||
tinyMappingsJar = new File(getExtension().getUserCache(), removeSuffix + "-" + jarClassifier + ".jar");
|
||||
tinyMappingsWithSrg = mappedVersionedDir.resolve("mappings-srg.tiny");
|
||||
mixinTinyMappingsWithSrg = mappedVersionedDir.resolve("mappings-mixin-srg.tiny").toFile();
|
||||
srgToNamedSrg = mappedVersionedDir.resolve("mappings-srg-named.srg").toFile();
|
||||
|
||||
if (!tinyMappings.exists() || isRefreshDeps()) {
|
||||
storeMappings(getProject(), minecraftProvider, mappingsJar.toPath(), postPopulationScheduler);
|
||||
} else {
|
||||
try (FileSystem fileSystem = FileSystems.newFileSystem(mappingsJar.toPath(), (ClassLoader) null)) {
|
||||
extractUnpickDefinitions(fileSystem, unpickDefinitionsFile.toPath());
|
||||
}
|
||||
}
|
||||
|
||||
if (getExtension().isForge()) {
|
||||
patchedProvider = new MinecraftPatchedProvider(getProject());
|
||||
patchedProvider.provide(dependency, postPopulationScheduler);
|
||||
}
|
||||
|
||||
manipulateMappings(mappingsJar.toPath());
|
||||
|
||||
if (getExtension().shouldGenerateSrgTiny()) {
|
||||
if (Files.notExists(tinyMappingsWithSrg) || isRefreshDeps()) {
|
||||
// Merge tiny mappings with srg
|
||||
SrgMerger.mergeSrg(getExtension().getSrgProvider().getSrg().toPath(), tinyMappings.toPath(), tinyMappingsWithSrg, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (!tinyMappingsJar.exists() || isRefreshDeps()) {
|
||||
ZipUtil.pack(new ZipEntrySource[] {new FileSource("mappings/mappings.tiny", tinyMappings)}, tinyMappingsJar);
|
||||
}
|
||||
|
||||
if (hasUnpickDefinitions()) {
|
||||
String notation = String.format("%s:%s:%s:constants",
|
||||
dependency.getDependency().getGroup(),
|
||||
dependency.getDependency().getName(),
|
||||
dependency.getDependency().getVersion()
|
||||
);
|
||||
|
||||
getProject().getDependencies().add(Constants.Configurations.MAPPING_CONSTANTS, notation);
|
||||
populateUnpickClasspath();
|
||||
}
|
||||
|
||||
if (getExtension().isForge()) {
|
||||
if (!getExtension().shouldGenerateSrgTiny()) {
|
||||
throw new IllegalStateException("We have to generate srg tiny in a forge environment!");
|
||||
}
|
||||
|
||||
if (!mixinTinyMappingsWithSrg.exists() || isRefreshDeps()) {
|
||||
List<String> lines = new ArrayList<>(Files.readAllLines(tinyMappingsWithSrg));
|
||||
lines.set(0, lines.get(0).replace("intermediary", "yraidemretni").replace("srg", "intermediary"));
|
||||
Files.deleteIfExists(mixinTinyMappingsWithSrg.toPath());
|
||||
Files.write(mixinTinyMappingsWithSrg.toPath(), lines);
|
||||
}
|
||||
|
||||
if (!srgToNamedSrg.exists() || isRefreshDeps()) {
|
||||
SrgNamedWriter.writeTo(getProject().getLogger(), srgToNamedSrg.toPath(), getMappingsWithSrg(), "srg", "named");
|
||||
}
|
||||
}
|
||||
|
||||
addDependency(tinyMappingsJar, Constants.Configurations.MAPPINGS_FINAL);
|
||||
|
||||
LoomGradleExtension extension = getExtension();
|
||||
|
||||
if (extension.accessWidener != null) {
|
||||
extension.addJarProcessor(new AccessWidenerJarProcessor(getProject()));
|
||||
}
|
||||
|
||||
JarProcessorManager processorManager = new JarProcessorManager(extension.getJarProcessors());
|
||||
extension.setJarProcessorManager(processorManager);
|
||||
processorManager.setupProcessors();
|
||||
|
||||
if (extension.isForge()) {
|
||||
patchedProvider.finishProvide();
|
||||
}
|
||||
|
||||
if (processorManager.active() || (extension.isForge() && patchedProvider.usesProjectCache())) {
|
||||
mappedProvider = new MinecraftProcessedProvider(getProject(), processorManager);
|
||||
getProject().getLogger().lifecycle("Using project based jar storage");
|
||||
} else {
|
||||
mappedProvider = new MinecraftMappedProvider(getProject());
|
||||
}
|
||||
|
||||
mappedProvider.initFiles(minecraftProvider, this);
|
||||
mappedProvider.provide(dependency, postPopulationScheduler);
|
||||
}
|
||||
|
||||
public void manipulateMappings(Path mappingsJar) throws IOException { }
|
||||
|
||||
private void storeMappings(Project project, MinecraftProviderImpl minecraftProvider, Path yarnJar, Consumer<Runnable> postPopulationScheduler)
|
||||
throws Exception {
|
||||
project.getLogger().info(":extracting " + yarnJar.getFileName());
|
||||
|
||||
if (isMCP(yarnJar)) {
|
||||
readAndMergeMCP(yarnJar, postPopulationScheduler);
|
||||
return;
|
||||
}
|
||||
|
||||
try (FileSystem fileSystem = FileSystems.newFileSystem(yarnJar, (ClassLoader) null)) {
|
||||
extractMappings(fileSystem, baseTinyMappings);
|
||||
extractUnpickDefinitions(fileSystem, unpickDefinitionsFile.toPath());
|
||||
}
|
||||
|
||||
if (baseMappingsAreMergedV2()) {
|
||||
// Architectury Loom Patch
|
||||
// If a merged tiny v2 mappings file is provided
|
||||
// Skip merging, should save a lot of time
|
||||
Files.copy(baseTinyMappings, tinyMappings.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||
} else if (baseMappingsAreV2()) {
|
||||
// These are unmerged v2 mappings
|
||||
mergeAndSaveMappings(project, yarnJar);
|
||||
} else {
|
||||
// These are merged v1 mappings
|
||||
if (tinyMappings.exists()) {
|
||||
tinyMappings.delete();
|
||||
}
|
||||
|
||||
project.getLogger().lifecycle(":populating field names");
|
||||
suggestFieldNames(minecraftProvider, baseTinyMappings, tinyMappings.toPath());
|
||||
}
|
||||
}
|
||||
|
||||
private void readAndMergeMCP(Path mcpJar, Consumer<Runnable> postPopulationScheduler) throws Exception {
|
||||
Path intermediaryTinyPath = getIntermediaryTiny();
|
||||
SrgProvider provider = getExtension().getSrgProvider();
|
||||
|
||||
if (provider == null) {
|
||||
if (!getExtension().shouldGenerateSrgTiny()) {
|
||||
Configuration srg = getProject().getConfigurations().maybeCreate(Constants.Configurations.SRG);
|
||||
srg.setTransitive(false);
|
||||
}
|
||||
|
||||
provider = new SrgProvider(getProject());
|
||||
getProject().getDependencies().add(provider.getTargetConfig(), "de.oceanlabs.mcp:mcp_config:" + minecraftVersion);
|
||||
Configuration configuration = getProject().getConfigurations().getByName(provider.getTargetConfig());
|
||||
provider.provide(DependencyInfo.create(getProject(), configuration.getDependencies().iterator().next(), configuration), postPopulationScheduler);
|
||||
}
|
||||
|
||||
Path srgPath = provider.getSrg().toPath();
|
||||
|
||||
TinyFile file = new MCPReader(intermediaryTinyPath, srgPath).read(mcpJar);
|
||||
TinyV2Writer.write(file, tinyMappings.toPath());
|
||||
}
|
||||
|
||||
private boolean isMCP(Path path) throws IOException {
|
||||
try (FileSystem fs = FileSystems.newFileSystem(path, (ClassLoader) null)) {
|
||||
return Files.exists(fs.getPath("fields.csv")) && Files.exists(fs.getPath("methods.csv"));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean baseMappingsAreV2() throws IOException {
|
||||
try (BufferedReader reader = Files.newBufferedReader(baseTinyMappings)) {
|
||||
TinyV2Factory.readMetadata(reader);
|
||||
return true;
|
||||
} catch (IllegalArgumentException | NoSuchFileException e) {
|
||||
// TODO: just check the mappings version when Parser supports V1 in readMetadata()
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean baseMappingsAreMergedV2() throws IOException {
|
||||
try (BufferedReader reader = Files.newBufferedReader(baseTinyMappings)) {
|
||||
TinyMetadata metadata = TinyV2Factory.readMetadata(reader);
|
||||
return metadata.getNamespaces().containsAll(Arrays.asList("named", "intermediary", "official"));
|
||||
} catch (IllegalArgumentException | NoSuchFileException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean doesJarContainV2Mappings(Path path) throws IOException {
|
||||
try (FileSystem fs = FileSystems.newFileSystem(path, (ClassLoader) null)) {
|
||||
try (BufferedReader reader = Files.newBufferedReader(fs.getPath("mappings", "mappings.tiny"))) {
|
||||
TinyV2Factory.readMetadata(reader);
|
||||
return true;
|
||||
} catch (IllegalArgumentException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void extractMappings(FileSystem jar, Path extractTo) throws IOException {
|
||||
Files.copy(jar.getPath("mappings/mappings.tiny"), extractTo, StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
|
||||
private void extractUnpickDefinitions(FileSystem jar, Path extractTo) throws IOException {
|
||||
Path unpickPath = jar.getPath("extras/definitions.unpick");
|
||||
Path unpickMetadataPath = jar.getPath("extras/unpick.json");
|
||||
|
||||
if (!Files.exists(unpickPath) || !Files.exists(unpickMetadataPath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Files.copy(unpickPath, extractTo, StandardCopyOption.REPLACE_EXISTING);
|
||||
|
||||
unpickMetadata = parseUnpickMetadata(unpickMetadataPath);
|
||||
hasUnpickDefinitions = true;
|
||||
}
|
||||
|
||||
private UnpickMetadata parseUnpickMetadata(Path input) throws IOException {
|
||||
JsonObject jsonObject = LoomGradlePlugin.GSON.fromJson(Files.readString(input), JsonObject.class);
|
||||
|
||||
if (!jsonObject.has("version") || jsonObject.get("version").getAsInt() != 1) {
|
||||
throw new UnsupportedOperationException("Unsupported unpick version");
|
||||
}
|
||||
|
||||
return new UnpickMetadata(
|
||||
jsonObject.get("unpickGroup").getAsString(),
|
||||
jsonObject.get("unpickVersion").getAsString()
|
||||
);
|
||||
}
|
||||
|
||||
private void populateUnpickClasspath() {
|
||||
String unpickCliName = "unpick-cli";
|
||||
getProject().getDependencies().add(Constants.Configurations.UNPICK_CLASSPATH,
|
||||
String.format("%s:%s:%s", unpickMetadata.unpickGroup, unpickCliName, unpickMetadata.unpickVersion)
|
||||
);
|
||||
}
|
||||
|
||||
private void extractIntermediary(Path intermediaryJar, Path intermediaryTiny) throws IOException {
|
||||
getProject().getLogger().info(":extracting " + intermediaryJar.getFileName());
|
||||
|
||||
try (FileSystem unmergedIntermediaryFs = FileSystems.newFileSystem(intermediaryJar, (ClassLoader) null)) {
|
||||
extractMappings(unmergedIntermediaryFs, intermediaryTiny);
|
||||
}
|
||||
}
|
||||
|
||||
private void mergeAndSaveMappings(Project project, Path unmergedYarnJar) throws IOException {
|
||||
Path unmergedYarn = Paths.get(mappingsStepsDir.toString(), "unmerged-yarn.tiny");
|
||||
project.getLogger().info(":extracting " + unmergedYarnJar.getFileName());
|
||||
|
||||
try (FileSystem unmergedYarnJarFs = FileSystems.newFileSystem(unmergedYarnJar, (ClassLoader) null)) {
|
||||
extractMappings(unmergedYarnJarFs, unmergedYarn);
|
||||
}
|
||||
|
||||
Stopwatch stopwatch = Stopwatch.createStarted();
|
||||
project.getLogger().info(":merging mappings");
|
||||
MemoryMappingTree tree = new MemoryMappingTree();
|
||||
MappingNsCompleter nsCompleter = new MappingNsCompleter(tree, Collections.singletonMap(MappingNamespace.NAMED.stringValue(), MappingNamespace.INTERMEDIARY.stringValue()), true);
|
||||
|
||||
try (BufferedReader reader = Files.newBufferedReader(getIntermediaryTiny(), StandardCharsets.UTF_8)) {
|
||||
Tiny2Reader.read(reader, nsCompleter);
|
||||
}
|
||||
|
||||
MemoryMappingTree tempTree = new MemoryMappingTree();
|
||||
|
||||
MappingSourceNsSwitch sourceNsSwitch = new MappingSourceNsSwitch(tempTree, MappingNamespace.OFFICIAL.stringValue());
|
||||
tree.accept(sourceNsSwitch);
|
||||
tree = tempTree;
|
||||
|
||||
try (BufferedReader reader = Files.newBufferedReader(unmergedYarn, StandardCharsets.UTF_8)) {
|
||||
Tiny2Reader.read(reader, tree);
|
||||
}
|
||||
|
||||
try (Tiny2Writer writer = new Tiny2Writer(Files.newBufferedWriter(tinyMappings.toPath(), StandardCharsets.UTF_8), false)) {
|
||||
tree.accept(writer);
|
||||
}
|
||||
|
||||
project.getLogger().info(":merged mappings in " + stopwatch.stop());
|
||||
}
|
||||
|
||||
private void suggestFieldNames(MinecraftProviderImpl minecraftProvider, Path oldMappings, Path newMappings) {
|
||||
Command command = new CommandProposeFieldNames();
|
||||
runCommand(command, minecraftProvider.getMergedJar().getAbsolutePath(),
|
||||
oldMappings.toAbsolutePath().toString(),
|
||||
newMappings.toAbsolutePath().toString());
|
||||
}
|
||||
|
||||
private void runCommand(Command command, String... args) {
|
||||
try {
|
||||
command.run(args);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void initFiles() throws IOException {
|
||||
baseTinyMappings = getMappedVersionedDir(removeSuffix).resolve("mappings-base.tiny");
|
||||
|
||||
if (Files.exists(mappingsStepsDir)) {
|
||||
Files.walkFileTree(mappingsStepsDir, new DeletingFileVisitor());
|
||||
}
|
||||
}
|
||||
|
||||
public void cleanFiles() {
|
||||
try {
|
||||
if (Files.exists(mappingsStepsDir)) {
|
||||
Files.walkFileTree(mappingsStepsDir, new DeletingFileVisitor());
|
||||
}
|
||||
|
||||
if (Files.exists(baseTinyMappings)) {
|
||||
Files.deleteIfExists(baseTinyMappings);
|
||||
}
|
||||
|
||||
if (tinyMappings != null) {
|
||||
tinyMappings.delete();
|
||||
}
|
||||
|
||||
if (tinyMappingsJar != null) {
|
||||
tinyMappingsJar.delete();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTargetConfig() {
|
||||
return Constants.Configurations.MAPPINGS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getMappingsDir() {
|
||||
return mappingsDir;
|
||||
}
|
||||
|
||||
public Path getIntermediaryTiny() throws IOException {
|
||||
if (intermediaryTiny == null) {
|
||||
minecraftVersion = getExtension().getMinecraftProvider().minecraftVersion();
|
||||
Preconditions.checkNotNull(minecraftVersion, "Minecraft version cannot be null");
|
||||
|
||||
intermediaryTiny = mappingsDir.resolve(String.format("intermediary-%s-v2.tiny", minecraftVersion));
|
||||
|
||||
if (isRefreshDeps() && !hasRefreshed) {
|
||||
Files.deleteIfExists(intermediaryTiny);
|
||||
}
|
||||
|
||||
if (!Files.exists(intermediaryTiny)) {
|
||||
hasRefreshed = true;
|
||||
intermediaryTiny = getMappingsVersionedDir().resolve("intermediary-v2.tiny");
|
||||
|
||||
// Download and extract intermediary
|
||||
String encodedMinecraftVersion = UrlEscapers.urlFragmentEscaper().escape(minecraftVersion);
|
||||
String intermediaryArtifactUrl = getExtension().getIntermediaryUrl().apply(encodedMinecraftVersion);
|
||||
Path intermediaryJar = getMappingsVersionedDir().resolve("intermediary-v2.jar");
|
||||
DownloadUtil.downloadIfChanged(new URL(intermediaryArtifactUrl), intermediaryJar.toFile(), getProject().getLogger());
|
||||
|
||||
extractIntermediary(intermediaryJar, intermediaryTiny);
|
||||
}
|
||||
}
|
||||
|
||||
return intermediaryTiny;
|
||||
}
|
||||
|
||||
public String getMappingsKey() {
|
||||
return mappingsName + "." + minecraftVersion.replace(' ', '_').replace('.', '_').replace('-', '_') + "." + mappingsVersion;
|
||||
}
|
||||
|
||||
public File getUnpickDefinitionsFile() {
|
||||
return unpickDefinitionsFile;
|
||||
}
|
||||
|
||||
public boolean hasUnpickDefinitions() {
|
||||
return hasUnpickDefinitions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File intermediaryTinyFile() {
|
||||
try {
|
||||
return getIntermediaryTiny().toFile();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to get intermediary", e);
|
||||
}
|
||||
}
|
||||
|
||||
public record UnpickMetadata(String unpickGroup, String unpickVersion) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2016, 2017, 2018 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings;
|
||||
|
||||
public interface MappingsSpec<L extends MappingLayer> {
|
||||
L createLayer(MappingContext context);
|
||||
}
|
||||
@@ -1,337 +0,0 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2016, 2017, 2018 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.cadixdev.lorenz.MappingSet;
|
||||
import org.cadixdev.lorenz.io.TextMappingsWriter;
|
||||
import org.cadixdev.lorenz.io.proguard.ProGuardReader;
|
||||
import org.cadixdev.lorenz.model.ClassMapping;
|
||||
import org.cadixdev.lorenz.model.FieldMapping;
|
||||
import org.cadixdev.lorenz.model.InnerClassMapping;
|
||||
import org.cadixdev.lorenz.model.MethodMapping;
|
||||
import org.cadixdev.lorenz.model.TopLevelClassMapping;
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.Dependency;
|
||||
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;
|
||||
import org.zeroturnaround.zip.ZipUtil;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.LoomGradlePlugin;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta;
|
||||
import net.fabricmc.loom.util.HashedDownloadUtil;
|
||||
import net.fabricmc.lorenztiny.TinyMappingsReader;
|
||||
import net.fabricmc.mapping.tree.TinyMappingFactory;
|
||||
|
||||
public class MojangMappingsDependency extends AbstractModuleDependency implements SelfResolvingDependency, ExternalModuleDependency {
|
||||
public static final String GROUP = "net.minecraft";
|
||||
public static final String MODULE = "mappings";
|
||||
// Keys in dependency manifest
|
||||
private static final String MANIFEST_CLIENT_MAPPINGS = "client_mappings";
|
||||
private static final String MANIFEST_SERVER_MAPPINGS = "server_mappings";
|
||||
|
||||
private final Project project;
|
||||
private final LoomGradleExtension extension;
|
||||
|
||||
private boolean changing;
|
||||
private boolean force;
|
||||
|
||||
public MojangMappingsDependency(Project project, LoomGradleExtension extension) {
|
||||
super(null);
|
||||
this.project = project;
|
||||
this.extension = extension;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExternalModuleDependency copy() {
|
||||
MojangMappingsDependency copiedProjectDependency = new MojangMappingsDependency(project, extension);
|
||||
this.copyTo(copiedProjectDependency);
|
||||
return copiedProjectDependency;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void version(Action<? super MutableVersionConstraint> action) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isForce() {
|
||||
return this.force;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExternalModuleDependency setForce(boolean force) {
|
||||
this.validateMutation(this.force, force);
|
||||
this.force = force;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChanging() {
|
||||
return this.changing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExternalModuleDependency setChanging(boolean changing) {
|
||||
this.validateMutation(this.changing, changing);
|
||||
this.changing = changing;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<File> resolve() {
|
||||
Path mappingsDir = extension.getMappingsProvider().getMappingsDir();
|
||||
Path mappingsFile = mappingsDir.resolve(String.format("%s.%s-%s.tiny", GROUP, MODULE, getVersion()));
|
||||
Path clientMappings = mappingsDir.resolve(String.format("%s.%s-%s-client.map", GROUP, MODULE, getVersion()));
|
||||
Path serverMappings = mappingsDir.resolve(String.format("%s.%s-%s-server.map", GROUP, MODULE, getVersion()));
|
||||
|
||||
if (!Files.exists(mappingsFile) || LoomGradlePlugin.refreshDeps) {
|
||||
MappingSet mappingSet;
|
||||
|
||||
try {
|
||||
mappingSet = getMappingsSet(clientMappings, serverMappings);
|
||||
|
||||
try (Writer writer = new StringWriter()) {
|
||||
new TinyWriter(writer, "intermediary", "named").write(mappingSet);
|
||||
Files.deleteIfExists(mappingsFile);
|
||||
|
||||
ZipUtil.pack(new ZipEntrySource[] {
|
||||
new ByteSource("mappings/mappings.tiny", writer.toString().getBytes(StandardCharsets.UTF_8))
|
||||
}, mappingsFile.toFile());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to resolve Mojang mappings", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (!extension.isSilentMojangMappingsLicenseEnabled()) {
|
||||
try (BufferedReader clientBufferedReader = Files.newBufferedReader(clientMappings, StandardCharsets.UTF_8)) {
|
||||
project.getLogger().warn("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
||||
project.getLogger().warn("Using of the official minecraft mappings is at your own risk!");
|
||||
project.getLogger().warn("Please make sure to read and understand the following license:");
|
||||
project.getLogger().warn("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
||||
String line;
|
||||
|
||||
while ((line = clientBufferedReader.readLine()).startsWith("#")) {
|
||||
project.getLogger().warn(line);
|
||||
}
|
||||
|
||||
project.getLogger().warn("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to read client mappings", e);
|
||||
}
|
||||
}
|
||||
|
||||
return Collections.singleton(mappingsFile.toFile());
|
||||
}
|
||||
|
||||
private MappingSet getMappingsSet(Path clientMappings, Path serverMappings) throws IOException {
|
||||
MinecraftVersionMeta versionInfo = extension.getMinecraftProvider().getVersionInfo();
|
||||
|
||||
if (versionInfo.download(MANIFEST_CLIENT_MAPPINGS) == null) {
|
||||
throw new RuntimeException("Failed to find official mojang mappings for " + getVersion());
|
||||
}
|
||||
|
||||
MinecraftVersionMeta.Download clientMappingsDownload = versionInfo.download(MANIFEST_CLIENT_MAPPINGS);
|
||||
MinecraftVersionMeta.Download serverMappingsDownload = versionInfo.download(MANIFEST_CLIENT_MAPPINGS);
|
||||
|
||||
HashedDownloadUtil.downloadIfInvalid(new URL(clientMappingsDownload.url()), clientMappings.toFile(), clientMappingsDownload.sha1(), project.getLogger(), false);
|
||||
HashedDownloadUtil.downloadIfInvalid(new URL(serverMappingsDownload.url()), serverMappings.toFile(), clientMappingsDownload.sha1(), project.getLogger(), false);
|
||||
|
||||
MappingSet mappings = MappingSet.create();
|
||||
|
||||
try (BufferedReader clientBufferedReader = Files.newBufferedReader(clientMappings, StandardCharsets.UTF_8);
|
||||
BufferedReader serverBufferedReader = Files.newBufferedReader(serverMappings, StandardCharsets.UTF_8)) {
|
||||
try (ProGuardReader proGuardReaderClient = new ProGuardReader(clientBufferedReader);
|
||||
ProGuardReader proGuardReaderServer = new ProGuardReader(serverBufferedReader)) {
|
||||
proGuardReaderClient.read(mappings);
|
||||
proGuardReaderServer.read(mappings);
|
||||
}
|
||||
}
|
||||
|
||||
MappingSet officialToNamed = mappings.reverse();
|
||||
MappingSet intermediaryToOfficial;
|
||||
|
||||
try (BufferedReader reader = Files.newBufferedReader(extension.getMappingsProvider().getIntermediaryTiny(), StandardCharsets.UTF_8)) {
|
||||
intermediaryToOfficial = new TinyMappingsReader(TinyMappingFactory.loadWithDetection(reader), "intermediary", "official").read();
|
||||
}
|
||||
|
||||
MappingSet intermediaryToMojang = MappingSet.create();
|
||||
|
||||
// Merging. Don't use MappingSet#merge
|
||||
iterateClasses(intermediaryToOfficial, inputMappings -> {
|
||||
officialToNamed.getClassMapping(inputMappings.getFullDeobfuscatedName())
|
||||
.ifPresent(namedClass -> {
|
||||
ClassMapping<?, ?> mojangClassMapping = intermediaryToMojang.getOrCreateClassMapping(inputMappings.getFullObfuscatedName())
|
||||
.setDeobfuscatedName(namedClass.getFullDeobfuscatedName());
|
||||
|
||||
for (FieldMapping fieldMapping : inputMappings.getFieldMappings()) {
|
||||
namedClass.getFieldMapping(fieldMapping.getDeobfuscatedName())
|
||||
.ifPresent(namedField -> {
|
||||
mojangClassMapping.getOrCreateFieldMapping(fieldMapping.getSignature())
|
||||
.setDeobfuscatedName(namedField.getDeobfuscatedName());
|
||||
});
|
||||
}
|
||||
|
||||
for (MethodMapping methodMapping : inputMappings.getMethodMappings()) {
|
||||
namedClass.getMethodMapping(methodMapping.getDeobfuscatedSignature())
|
||||
.ifPresent(namedMethod -> {
|
||||
mojangClassMapping.getOrCreateMethodMapping(methodMapping.getSignature())
|
||||
.setDeobfuscatedName(namedMethod.getDeobfuscatedName());
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return intermediaryToMojang;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<File> resolve(boolean transitive) {
|
||||
return resolve();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskDependency getBuildDependencies() {
|
||||
return task -> Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroup() {
|
||||
return GROUP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return MODULE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
if (extension.getDependencyManager() == null) return "1.0.0";
|
||||
return extension.getMinecraftProvider().getMinecraftVersion();
|
||||
}
|
||||
|
||||
@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 MojangMappingsDependency mojangMappingsDependency) {
|
||||
return mojangMappingsDependency.extension.getMinecraftProvider().getMinecraftVersion().equals(getVersion());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getReason() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void because(String s) {
|
||||
}
|
||||
|
||||
private static void iterateClasses(MappingSet mappings, Consumer<ClassMapping<?, ?>> consumer) {
|
||||
for (TopLevelClassMapping classMapping : mappings.getTopLevelClassMappings()) {
|
||||
iterateClass(classMapping, consumer);
|
||||
}
|
||||
}
|
||||
|
||||
private static void iterateClass(ClassMapping<?, ?> classMapping, Consumer<ClassMapping<?, ?>> consumer) {
|
||||
consumer.accept(classMapping);
|
||||
|
||||
for (InnerClassMapping innerClassMapping : classMapping.getInnerClassMappings()) {
|
||||
iterateClass(innerClassMapping, consumer);
|
||||
}
|
||||
}
|
||||
|
||||
private static class TinyWriter extends TextMappingsWriter {
|
||||
private final String namespaceFrom;
|
||||
private final String namespaceTo;
|
||||
|
||||
protected TinyWriter(Writer writer, String namespaceFrom, String namespaceTo) {
|
||||
super(writer);
|
||||
this.namespaceFrom = namespaceFrom;
|
||||
this.namespaceTo = namespaceTo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(MappingSet mappings) {
|
||||
writer.println("tiny\t2\t0\t" + namespaceFrom + "\t" + namespaceTo);
|
||||
|
||||
iterateClasses(mappings, classMapping -> {
|
||||
writer.println("c\t" + classMapping.getFullObfuscatedName() + "\t" + classMapping.getFullDeobfuscatedName());
|
||||
|
||||
for (FieldMapping fieldMapping : classMapping.getFieldMappings()) {
|
||||
fieldMapping.getType().ifPresent(fieldType -> {
|
||||
writer.println("\tf\t" + fieldType + "\t" + fieldMapping.getObfuscatedName() + "\t" + fieldMapping.getDeobfuscatedName());
|
||||
});
|
||||
}
|
||||
|
||||
for (MethodMapping methodMapping : classMapping.getMethodMappings()) {
|
||||
writer.println("\tm\t" + methodMapping.getSignature().getDescriptor() + "\t" + methodMapping.getObfuscatedName() + "\t" + methodMapping.getDeobfuscatedName());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package net.fabricmc.loom.configuration.providers.mappings.crane;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Collections;
|
||||
|
||||
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.MutableTinyTree;
|
||||
import dev.architectury.mappingslayers.api.utils.MappingsUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingLayer;
|
||||
import net.fabricmc.loom.util.FileSystemUtil;
|
||||
import net.fabricmc.mappingio.MappedElementKind;
|
||||
import net.fabricmc.mappingio.MappingVisitor;
|
||||
|
||||
public record CraneMappingLayer(File craneJar) implements MappingLayer {
|
||||
private static final String TINY_FILE_NAME = "crane.tiny";
|
||||
|
||||
@Override
|
||||
public void visit(MappingVisitor visitor) throws IOException {
|
||||
try (FileSystemUtil.FileSystemDelegate fs = FileSystemUtil.getJarFileSystem(craneJar().toPath(), false)) {
|
||||
try (BufferedReader reader = Files.newBufferedReader(fs.get().getPath(TINY_FILE_NAME), StandardCharsets.UTF_8)) {
|
||||
// can't use this, it requires 2 namespaces
|
||||
// Tiny2Reader.read(reader, mappingVisitor);
|
||||
MutableTinyTree tree = MappingsUtils.deserializeFromString(IOUtils.toString(reader));
|
||||
|
||||
do {
|
||||
if (visitor.visitHeader()) {
|
||||
visitor.visitNamespaces(tree.getMetadata().getNamespaces().get(0), Collections.emptyList());
|
||||
}
|
||||
|
||||
if (visitor.visitContent()) {
|
||||
for (MutableClassDef classDef : tree.getClassesMutable()) {
|
||||
if (visitor.visitClass(classDef.getName(0))) {
|
||||
if (!visitor.visitElementContent(MappedElementKind.CLASS)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (MutableFieldDef fieldDef : classDef.getFieldsMutable()) {
|
||||
if (visitor.visitField(fieldDef.getName(0), fieldDef.getDescriptor(0))) {
|
||||
if (!visitor.visitElementContent(MappedElementKind.FIELD)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (fieldDef.getComment() != null) {
|
||||
visitor.visitComment(MappedElementKind.FIELD, fieldDef.getComment());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (MutableMethodDef methodDef : classDef.getMethodsMutable()) {
|
||||
if (visitor.visitMethod(methodDef.getName(0), methodDef.getDescriptor(0))) {
|
||||
if (!visitor.visitElementContent(MappedElementKind.METHOD)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (MutableParameterDef parameterDef : methodDef.getParametersMutable()) {
|
||||
if (visitor.visitMethodArg(parameterDef.getLocalVariableIndex(), parameterDef.getLocalVariableIndex(), parameterDef.getName(0))) {
|
||||
if (!visitor.visitElementContent(MappedElementKind.METHOD_ARG)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (parameterDef.getComment() != null) {
|
||||
visitor.visitComment(MappedElementKind.METHOD_ARG, parameterDef.getComment());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (methodDef.getComment() != null) {
|
||||
visitor.visitComment(MappedElementKind.METHOD, methodDef.getComment());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (classDef.getComment() != null) {
|
||||
visitor.visitComment(MappedElementKind.FIELD, classDef.getComment());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (!visitor.visitEnd());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2016, 2017, 2018 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings.crane;
|
||||
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingContext;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsSpec;
|
||||
|
||||
public record CraneMappingsSpec(String mavenNotation) implements MappingsSpec<CraneMappingLayer> {
|
||||
@Override
|
||||
public CraneMappingLayer createLayer(MappingContext context) {
|
||||
return new CraneMappingLayer(context.mavenFile(mavenNotation()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2016, 2017, 2018 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings.intermediary;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Collections;
|
||||
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingLayer;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingNamespace;
|
||||
import net.fabricmc.mappingio.MappingVisitor;
|
||||
import net.fabricmc.mappingio.adapter.MappingNsCompleter;
|
||||
import net.fabricmc.mappingio.format.Tiny2Reader;
|
||||
|
||||
public record IntermediaryMappingLayer(File tinyFile) implements MappingLayer {
|
||||
@Override
|
||||
public MappingNamespace getSourceNamespace() {
|
||||
return MappingNamespace.OFFICIAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(MappingVisitor mappingVisitor) throws IOException {
|
||||
// Populate named with intermediary and add Add a "named" namespace
|
||||
MappingNsCompleter nsCompleter = new MappingNsCompleter(mappingVisitor, Collections.singletonMap(MappingNamespace.NAMED.stringValue(), MappingNamespace.INTERMEDIARY.stringValue()), true);
|
||||
|
||||
try (BufferedReader reader = Files.newBufferedReader(tinyFile().toPath(), StandardCharsets.UTF_8)) {
|
||||
Tiny2Reader.read(reader, nsCompleter);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2016, 2017, 2018 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings.intermediary;
|
||||
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingContext;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsSpec;
|
||||
|
||||
public record IntermediaryMappingsSpec() implements MappingsSpec<IntermediaryMappingLayer> {
|
||||
@Override
|
||||
public IntermediaryMappingLayer createLayer(MappingContext context) {
|
||||
return new IntermediaryMappingLayer(context.mappingsProvider().intermediaryTinyFile());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2016, 2017, 2018 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings.mojmap;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
import org.gradle.api.logging.Logger;
|
||||
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingLayer;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingNamespace;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.intermediary.IntermediaryMappingLayer;
|
||||
import net.fabricmc.loom.util.HashedDownloadUtil;
|
||||
import net.fabricmc.mappingio.MappingVisitor;
|
||||
import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch;
|
||||
import net.fabricmc.mappingio.format.ProGuardReader;
|
||||
|
||||
public record MojangMappingLayer(MinecraftVersionMeta.Download clientDownload,
|
||||
MinecraftVersionMeta.Download serverDownload,
|
||||
File workingDir,
|
||||
Logger logger,
|
||||
MojangMappingsSpec.SilenceLicenseOption silenceLicense) implements MappingLayer {
|
||||
@Override
|
||||
public void visit(MappingVisitor mappingVisitor) throws IOException {
|
||||
var clientMappings = new File(workingDir(), "client.txt");
|
||||
var serverMappings = new File(workingDir(), "server.txt");
|
||||
|
||||
download(clientMappings, serverMappings);
|
||||
|
||||
if (!silenceLicense.isSilent()) {
|
||||
printMappingsLicense(clientMappings.toPath());
|
||||
}
|
||||
|
||||
// Make official the source namespace
|
||||
MappingSourceNsSwitch nsSwitch = new MappingSourceNsSwitch(mappingVisitor, MappingNamespace.OFFICIAL.stringValue());
|
||||
|
||||
try (BufferedReader clientBufferedReader = Files.newBufferedReader(clientMappings.toPath(), StandardCharsets.UTF_8);
|
||||
BufferedReader serverBufferedReader = Files.newBufferedReader(serverMappings.toPath(), StandardCharsets.UTF_8)) {
|
||||
ProGuardReader.read(clientBufferedReader, MappingNamespace.NAMED.stringValue(), MappingNamespace.OFFICIAL.stringValue(), nsSwitch);
|
||||
ProGuardReader.read(serverBufferedReader, MappingNamespace.NAMED.stringValue(), MappingNamespace.OFFICIAL.stringValue(), nsSwitch);
|
||||
}
|
||||
}
|
||||
|
||||
private void download(File clientMappings, File serverMappings) throws IOException {
|
||||
HashedDownloadUtil.downloadIfInvalid(new URL(clientDownload().url()), clientMappings, clientDownload().sha1(), logger(), false);
|
||||
HashedDownloadUtil.downloadIfInvalid(new URL(serverDownload().url()), serverMappings, serverDownload().sha1(), logger(), false);
|
||||
}
|
||||
|
||||
private void printMappingsLicense(Path clientMappings) {
|
||||
try (BufferedReader clientBufferedReader = Files.newBufferedReader(clientMappings, StandardCharsets.UTF_8)) {
|
||||
logger().warn("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
||||
logger().warn("Using of the official minecraft mappings is at your own risk!");
|
||||
logger().warn("Please make sure to read and understand the following license:");
|
||||
logger().warn("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
||||
String line;
|
||||
|
||||
while ((line = clientBufferedReader.readLine()).startsWith("#")) {
|
||||
logger().warn(line);
|
||||
}
|
||||
|
||||
logger().warn("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to read client mappings", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingNamespace getSourceNamespace() {
|
||||
return MappingNamespace.OFFICIAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Class<? extends MappingLayer>> dependsOn() {
|
||||
return List.of(IntermediaryMappingLayer.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2016, 2017, 2018 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings.mojmap;
|
||||
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingContext;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsSpec;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta;
|
||||
|
||||
public record MojangMappingsSpec(SilenceLicenseOption silenceLicense) implements MappingsSpec<MojangMappingLayer> {
|
||||
// Keys in dependency manifest
|
||||
private static final String MANIFEST_CLIENT_MAPPINGS = "client_mappings";
|
||||
private static final String MANIFEST_SERVER_MAPPINGS = "server_mappings";
|
||||
|
||||
public MojangMappingsSpec(SilenceLicenseSupplier supplier) {
|
||||
this(new SilenceLicenseOption(supplier));
|
||||
}
|
||||
|
||||
public MojangMappingsSpec() {
|
||||
this(() -> false);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface SilenceLicenseSupplier {
|
||||
boolean isSilent();
|
||||
}
|
||||
|
||||
public record SilenceLicenseOption(SilenceLicenseSupplier supplier) {
|
||||
public boolean isSilent() {
|
||||
return supplier.isSilent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof SilenceLicenseOption that)) return false;
|
||||
return isSilent() == that.isSilent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Boolean.hashCode(isSilent());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return isSilent() + "";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MojangMappingLayer createLayer(MappingContext context) {
|
||||
MinecraftVersionMeta versionInfo = context.minecraftProvider().getVersionInfo();
|
||||
|
||||
if (versionInfo.download(MANIFEST_CLIENT_MAPPINGS) == null) {
|
||||
throw new RuntimeException("Failed to find official mojang mappings for " + context.minecraftVersion());
|
||||
}
|
||||
|
||||
return new MojangMappingLayer(
|
||||
versionInfo.download(MANIFEST_CLIENT_MAPPINGS),
|
||||
versionInfo.download(MANIFEST_SERVER_MAPPINGS),
|
||||
context.workingDirectory("mojang"),
|
||||
context.getLogger(),
|
||||
silenceLicense()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2016, 2017, 2018 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings.parchment;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Objects;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import net.fabricmc.loom.LoomGradlePlugin;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingLayer;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingNamespace;
|
||||
import net.fabricmc.mappingio.MappingVisitor;
|
||||
|
||||
public record ParchmentMappingLayer(File parchmentFile, boolean removePrefix) implements MappingLayer {
|
||||
private static final String PARCHMENT_DATA_FILE_NAME = "parchment.json";
|
||||
|
||||
@Override
|
||||
public void visit(MappingVisitor mappingVisitor) throws IOException {
|
||||
ParchmentTreeV1 parchmentData = getParchmentData();
|
||||
|
||||
if (removePrefix()) {
|
||||
mappingVisitor = new ParchmentPrefixStripingMappingVisitor(mappingVisitor);
|
||||
}
|
||||
|
||||
parchmentData.visit(mappingVisitor, MappingNamespace.NAMED.stringValue());
|
||||
}
|
||||
|
||||
private ParchmentTreeV1 getParchmentData() throws IOException {
|
||||
try (var zipFile = new ZipFile(parchmentFile())) {
|
||||
ZipEntry zipFileEntry = zipFile.getEntry(PARCHMENT_DATA_FILE_NAME);
|
||||
Objects.requireNonNull(zipFileEntry, "Could not find %s in parchment data file".formatted(PARCHMENT_DATA_FILE_NAME));
|
||||
|
||||
try (var reader = new InputStreamReader(zipFile.getInputStream(zipFileEntry))) {
|
||||
return LoomGradlePlugin.OBJECT_MAPPER.readValue(reader, ParchmentTreeV1.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2016, 2017, 2018 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings.parchment;
|
||||
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingContext;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsSpec;
|
||||
|
||||
public record ParchmentMappingsSpec(String mavenNotation, boolean removePrefix) implements MappingsSpec<ParchmentMappingLayer> {
|
||||
@Override
|
||||
public ParchmentMappingLayer createLayer(MappingContext context) {
|
||||
return new ParchmentMappingLayer(context.mavenFile(mavenNotation()), removePrefix());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2016, 2017, 2018 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings.parchment;
|
||||
|
||||
public class ParchmentMappingsSpecBuilder {
|
||||
private final String mavenNotation;
|
||||
|
||||
private boolean removePrefix;
|
||||
|
||||
private ParchmentMappingsSpecBuilder(String mavenNotation) {
|
||||
this.mavenNotation = mavenNotation;
|
||||
}
|
||||
|
||||
public static ParchmentMappingsSpecBuilder builder(String depNotation) {
|
||||
return new ParchmentMappingsSpecBuilder(depNotation);
|
||||
}
|
||||
|
||||
public ParchmentMappingsSpecBuilder setRemovePrefix(boolean removePrefix) {
|
||||
this.removePrefix = removePrefix;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ParchmentMappingsSpec build() {
|
||||
return new ParchmentMappingsSpec(mavenNotation, removePrefix);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2016, 2017, 2018 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings.parchment;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import net.fabricmc.mappingio.MappingVisitor;
|
||||
import net.fabricmc.mappingio.adapter.ForwardingMappingVisitor;
|
||||
|
||||
public final class ParchmentPrefixStripingMappingVisitor extends ForwardingMappingVisitor {
|
||||
protected ParchmentPrefixStripingMappingVisitor(MappingVisitor next) {
|
||||
super(next);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visitMethodArg(int argPosition, int lvIndex, String srcName) {
|
||||
return super.visitMethodArg(argPosition, lvIndex, stripMethodArg(srcName));
|
||||
}
|
||||
|
||||
public static String stripMethodArg(String arg) {
|
||||
if (arg.length() > 1 && arg.startsWith("p") && Character.isUpperCase(arg.charAt(1))) {
|
||||
String a2 = arg.substring(1); // Remove p
|
||||
return a2.substring(0, 1).toLowerCase(Locale.ROOT) + a2.substring(1); // Make first char lowercase
|
||||
}
|
||||
|
||||
return arg;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2016, 2017, 2018 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings.parchment;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.fabricmc.mappingio.MappedElementKind;
|
||||
import net.fabricmc.mappingio.MappingVisitor;
|
||||
|
||||
public record ParchmentTreeV1(
|
||||
String version,
|
||||
@Nullable
|
||||
List<Class> classes,
|
||||
@Nullable
|
||||
List<Package> packages
|
||||
) {
|
||||
public void visit(MappingVisitor visitor, String srcNamespace) {
|
||||
while (true) {
|
||||
if (visitor.visitHeader()) {
|
||||
visitor.visitNamespaces(srcNamespace, Collections.emptyList());
|
||||
}
|
||||
|
||||
if (visitor.visitContent()) {
|
||||
if (classes() != null) {
|
||||
for (Class c : classes()) {
|
||||
c.visit(visitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (visitor.visitEnd()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public record Class(
|
||||
String name,
|
||||
@Nullable
|
||||
List<Field> fields,
|
||||
@Nullable
|
||||
List<Method> methods,
|
||||
@Nullable
|
||||
List<String> javadoc
|
||||
) {
|
||||
public void visit(MappingVisitor visitor) {
|
||||
if (visitor.visitClass(name())) {
|
||||
if (!visitor.visitElementContent(MappedElementKind.CLASS)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (fields() != null) {
|
||||
for (Field field : fields()) {
|
||||
field.visit(visitor);
|
||||
}
|
||||
}
|
||||
|
||||
if (methods() != null) {
|
||||
for (Method method : methods()) {
|
||||
method.visit(visitor);
|
||||
}
|
||||
}
|
||||
|
||||
if (javadoc() != null) {
|
||||
visitor.visitComment(MappedElementKind.CLASS, String.join("\n", javadoc()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public record Field(
|
||||
String name,
|
||||
String descriptor,
|
||||
@Nullable
|
||||
List<String> javadoc
|
||||
) {
|
||||
public void visit(MappingVisitor visitor) {
|
||||
if (visitor.visitField(name, descriptor)) {
|
||||
if (!visitor.visitElementContent(MappedElementKind.FIELD)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (javadoc() != null) {
|
||||
visitor.visitComment(MappedElementKind.FIELD, String.join("\n", javadoc()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public record Method(
|
||||
String name,
|
||||
String descriptor,
|
||||
@Nullable
|
||||
List<Parameter> parameters,
|
||||
@Nullable
|
||||
List<String> javadoc
|
||||
) {
|
||||
public void visit(MappingVisitor visitor) {
|
||||
if (visitor.visitMethod(name, descriptor)) {
|
||||
if (!visitor.visitElementContent(MappedElementKind.METHOD)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (parameters() != null) {
|
||||
for (Parameter parameter : parameters()) {
|
||||
parameter.visit(visitor);
|
||||
}
|
||||
}
|
||||
|
||||
if (javadoc() != null) {
|
||||
visitor.visitComment(MappedElementKind.METHOD, String.join("\n", javadoc()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public record Parameter(
|
||||
int index,
|
||||
String name,
|
||||
@Nullable
|
||||
String javadoc
|
||||
) {
|
||||
public void visit(MappingVisitor visitor) {
|
||||
if (visitor.visitMethodArg(index, index, name)) {
|
||||
if (!visitor.visitElementContent(MappedElementKind.METHOD_ARG)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (javadoc() != null) {
|
||||
visitor.visitComment(MappedElementKind.METHOD_ARG, javadoc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public record Package(
|
||||
String name,
|
||||
List<String> javadoc
|
||||
) { }
|
||||
}
|
||||
@@ -29,13 +29,13 @@ import java.io.File;
|
||||
import org.gradle.api.Project;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.configuration.providers.MinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.MinecraftProviderImpl;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
|
||||
public class MinecraftLibraryProvider {
|
||||
public File MINECRAFT_LIBS;
|
||||
|
||||
public void provide(MinecraftProvider minecraftProvider, Project project) {
|
||||
public void provide(MinecraftProviderImpl minecraftProvider, Project project) {
|
||||
MinecraftVersionMeta versionInfo = minecraftProvider.getVersionInfo();
|
||||
|
||||
initFiles(project, minecraftProvider);
|
||||
@@ -47,7 +47,7 @@ public class MinecraftLibraryProvider {
|
||||
}
|
||||
}
|
||||
|
||||
private void initFiles(Project project, MinecraftProvider minecraftProvider) {
|
||||
private void initFiles(Project project, MinecraftProviderImpl minecraftProvider) {
|
||||
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
|
||||
MINECRAFT_LIBS = new File(extension.getUserCache(), "libraries");
|
||||
}
|
||||
|
||||
@@ -54,8 +54,8 @@ import org.gradle.api.Project;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.fabricmc.loom.configuration.DependencyProvider;
|
||||
import net.fabricmc.loom.configuration.providers.MinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider;
|
||||
import net.fabricmc.loom.configuration.providers.MinecraftProviderImpl;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.tr.OutputRemappingHandler;
|
||||
import net.fabricmc.loom.configuration.sources.ForgeSourcesRemapper;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
@@ -81,7 +81,7 @@ public class MinecraftMappedProvider extends DependencyProvider {
|
||||
private File minecraftIntermediaryJar;
|
||||
private File minecraftSrgJar;
|
||||
|
||||
private MinecraftProvider minecraftProvider;
|
||||
private MinecraftProviderImpl minecraftProvider;
|
||||
|
||||
public MinecraftMappedProvider(Project project) {
|
||||
super(project);
|
||||
@@ -151,7 +151,7 @@ public class MinecraftMappedProvider extends DependencyProvider {
|
||||
private void mapMinecraftJar() throws Exception {
|
||||
String fromM = "official";
|
||||
|
||||
MappingsProvider mappingsProvider = getExtension().getMappingsProvider();
|
||||
MappingsProviderImpl mappingsProvider = getExtension().getMappingsProvider();
|
||||
|
||||
Path input = inputJar.toPath();
|
||||
Path outputMapped = minecraftMappedJar.toPath();
|
||||
@@ -253,6 +253,7 @@ public class MinecraftMappedProvider extends DependencyProvider {
|
||||
public TinyRemapper getTinyRemapper() throws IOException {
|
||||
TinyRemapper.Builder builder = TinyRemapper.newRemapper()
|
||||
.renameInvalidLocals(true)
|
||||
.logUnknownInvokeDynamic(false)
|
||||
.ignoreConflicts(getExtension().isForge())
|
||||
.cacheMappings(true)
|
||||
.threads(Runtime.getRuntime().availableProcessors())
|
||||
@@ -290,13 +291,11 @@ public class MinecraftMappedProvider extends DependencyProvider {
|
||||
}
|
||||
|
||||
protected void addDependencies(DependencyInfo dependency, Consumer<Runnable> postPopulationScheduler) {
|
||||
getProject().getRepositories().flatDir(repository -> repository.dir(getJarDirectory(getExtension().getUserCache(), "mapped")));
|
||||
|
||||
getProject().getDependencies().add(Constants.Configurations.MINECRAFT_NAMED,
|
||||
getProject().getDependencies().module("net.minecraft:minecraft:" + getJarVersionString("mapped")));
|
||||
}
|
||||
|
||||
public void initFiles(MinecraftProvider minecraftProvider, MappingsProvider mappingsProvider) {
|
||||
public void initFiles(MinecraftProviderImpl minecraftProvider, MappingsProviderImpl mappingsProvider) {
|
||||
this.minecraftProvider = minecraftProvider;
|
||||
minecraftIntermediaryJar = new File(getExtension().getUserCache(), "minecraft-" + getJarVersionString("intermediary") + ".jar");
|
||||
minecraftSrgJar = !getExtension().isForge() ? null : new File(getExtension().getUserCache(), "minecraft-" + getJarVersionString("srg") + ".jar");
|
||||
@@ -309,7 +308,7 @@ public class MinecraftMappedProvider extends DependencyProvider {
|
||||
}
|
||||
|
||||
protected String getJarVersionString(String type) {
|
||||
return String.format("%s-%s-%s-%s%s", minecraftProvider.getMinecraftVersion(), type, getExtension().getMappingsProvider().mappingsName, getExtension().getMappingsProvider().mappingsVersion, minecraftProvider.getJarSuffix());
|
||||
return String.format("%s-%s-%s-%s%s", minecraftProvider.minecraftVersion(), type, getExtension().getMappingsProvider().mappingsName, getExtension().getMappingsProvider().mappingsVersion, minecraftProvider.getJarSuffix());
|
||||
}
|
||||
|
||||
public File getIntermediaryJar() {
|
||||
|
||||
@@ -43,13 +43,13 @@ import org.gradle.api.Project;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.LoomGradlePlugin;
|
||||
import net.fabricmc.loom.configuration.providers.MinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.MinecraftProviderImpl;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
import net.fabricmc.loom.util.HashedDownloadUtil;
|
||||
|
||||
public class MinecraftAssetsProvider {
|
||||
public static void provide(MinecraftProvider minecraftProvider, Project project) throws IOException {
|
||||
public static void provide(MinecraftProviderImpl minecraftProvider, Project project) throws IOException {
|
||||
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
|
||||
boolean offline = project.getGradle().getStartParameter().isOffline();
|
||||
|
||||
@@ -63,7 +63,7 @@ public class MinecraftAssetsProvider {
|
||||
assets.mkdirs();
|
||||
}
|
||||
|
||||
File assetsInfo = new File(assets, "indexes" + File.separator + assetIndex.fabricId(minecraftProvider.getMinecraftVersion()) + ".json");
|
||||
File assetsInfo = new File(assets, "indexes" + File.separator + assetIndex.fabricId(minecraftProvider.minecraftVersion()) + ".json");
|
||||
|
||||
project.getLogger().info(":downloading asset index");
|
||||
|
||||
|
||||
@@ -72,6 +72,7 @@ public abstract class AbstractFernFlowerDecompiler implements LoomDecompiler {
|
||||
put(IFernflowerPreferences.REMOVE_SYNTHETIC, "1");
|
||||
put(IFernflowerPreferences.LOG_LEVEL, "trace");
|
||||
put(IFernflowerPreferences.THREADS, metaData.numberOfThreads());
|
||||
put(IFernflowerPreferences.INDENT_STRING, "\t");
|
||||
}};
|
||||
|
||||
List<String> args = new ArrayList<>();
|
||||
@@ -106,7 +107,14 @@ public abstract class AbstractFernFlowerDecompiler implements LoomDecompiler {
|
||||
spec.getMainClass().set(fernFlowerExecutor().getName());
|
||||
spec.jvmArgs("-Xms200m", "-Xmx3G");
|
||||
spec.setArgs(args);
|
||||
spec.setErrorOutput(System.err);
|
||||
spec.setErrorOutput(new ConsumingOutputStream(line -> {
|
||||
if (line.startsWith("Inconsistent inner class entries")) {
|
||||
// Suppress this
|
||||
return;
|
||||
}
|
||||
|
||||
System.err.println(line);
|
||||
}));
|
||||
spec.setStandardOutput(new ConsumingOutputStream(line -> {
|
||||
if (line.startsWith("Listening for transport") || !line.contains("::")) {
|
||||
System.out.println(line);
|
||||
|
||||
@@ -42,7 +42,7 @@ import org.gradle.api.tasks.TaskAction;
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.api.decompilers.DecompilationMetadata;
|
||||
import net.fabricmc.loom.api.decompilers.LoomDecompiler;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
|
||||
import net.fabricmc.loom.configuration.sources.ForgeSourcesRemapper;
|
||||
import net.fabricmc.loom.decompilers.LineNumberRemapper;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
@@ -111,7 +111,7 @@ public class GenerateSourcesTask extends AbstractLoomTask {
|
||||
|
||||
public static File getMappedJarFileWithSuffix(Project project, String suffix) {
|
||||
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
|
||||
MappingsProvider mappingsProvider = extension.getMappingsProvider();
|
||||
MappingsProviderImpl mappingsProvider = extension.getMappingsProvider();
|
||||
File mappedJar = mappingsProvider.mappedProvider.getMappedJar();
|
||||
String path = mappedJar.getAbsolutePath();
|
||||
|
||||
|
||||
@@ -33,7 +33,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.providers.mappings.MappingsProvider;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
|
||||
import net.fabricmc.loom.decompilers.fernflower.FabricFernFlowerDecompiler;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
|
||||
@@ -125,7 +125,7 @@ public final class LoomTasks {
|
||||
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
|
||||
|
||||
project.afterEvaluate(p -> {
|
||||
MappingsProvider mappingsProvider = extension.getMappingsProvider();
|
||||
MappingsProviderImpl mappingsProvider = extension.getMappingsProvider();
|
||||
File inputJar = mappingsProvider.mappedProvider.getMappedJar();
|
||||
|
||||
if (mappingsProvider.hasUnpickDefinitions()) {
|
||||
|
||||
@@ -49,9 +49,10 @@ import org.gradle.api.tasks.TaskAction;
|
||||
import org.gradle.api.tasks.options.Option;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MojangMappingsDependency;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpecBuilder;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingsDependency;
|
||||
import net.fabricmc.loom.util.SourceRemapper;
|
||||
import net.fabricmc.lorenztiny.TinyMappingsJoiner;
|
||||
import net.fabricmc.mapping.tree.TinyMappingFactory;
|
||||
@@ -96,7 +97,7 @@ public class MigrateMappingsTask extends AbstractLoomTask {
|
||||
Files.createDirectories(outputDir);
|
||||
|
||||
File mappings = loadMappings();
|
||||
MappingsProvider mappingsProvider = extension.getMappingsProvider();
|
||||
MappingsProviderImpl mappingsProvider = extension.getMappingsProvider();
|
||||
|
||||
try {
|
||||
TinyTree currentMappings = mappingsProvider.getMappings();
|
||||
@@ -118,12 +119,13 @@ public class MigrateMappingsTask extends AbstractLoomTask {
|
||||
Set<File> files;
|
||||
|
||||
try {
|
||||
if (mappings.startsWith(MojangMappingsDependency.GROUP + ':' + MojangMappingsDependency.MODULE + ':') || mappings.startsWith("net.mojang.minecraft:mappings:")) {
|
||||
if (!mappings.endsWith(":" + project.getExtensions().getByType(LoomGradleExtension.class).getMinecraftProvider().getMinecraftVersion())) {
|
||||
if (mappings.startsWith("net.minecraft:mappings:") || mappings.startsWith("net.mojang.minecraft:mappings:")) {
|
||||
if (!mappings.endsWith(":" + project.getExtensions().getByType(LoomGradleExtension.class).getMinecraftProvider().minecraftVersion())) {
|
||||
throw new UnsupportedOperationException("Migrating Mojang mappings is currently only supported for the specified minecraft version");
|
||||
}
|
||||
|
||||
files = new MojangMappingsDependency(project, getExtension()).resolve();
|
||||
LayeredMappingsDependency dep = (LayeredMappingsDependency) getExtension().layered(LayeredMappingSpecBuilder::officialMojangMappings);
|
||||
files = dep.resolve();
|
||||
} else {
|
||||
Dependency dependency = project.getDependencies().create(mappings);
|
||||
files = project.getConfigurations().detachedConfiguration(dependency).resolve();
|
||||
|
||||
@@ -81,7 +81,7 @@ import net.fabricmc.loom.build.nesting.NestedDependencyProvider;
|
||||
import net.fabricmc.loom.build.nesting.NestedJarPathProvider;
|
||||
import net.fabricmc.loom.build.nesting.NestedJarProvider;
|
||||
import net.fabricmc.loom.configuration.accesswidener.AccessWidenerJarProcessor;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
import net.fabricmc.loom.util.SourceRemapper;
|
||||
import net.fabricmc.loom.util.TinyRemapperMappingsHelper;
|
||||
@@ -211,7 +211,7 @@ public class RemapJarTask extends Jar {
|
||||
throw new FileNotFoundException(input.toString());
|
||||
}
|
||||
|
||||
MappingsProvider mappingsProvider = extension.getMappingsProvider();
|
||||
MappingsProviderImpl mappingsProvider = extension.getMappingsProvider();
|
||||
|
||||
String fromM = this.fromM.get();
|
||||
String toM = this.toM.get();
|
||||
|
||||
@@ -91,6 +91,7 @@ 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 ACCESS_TRANSFORMERS = "net.minecraftforge:accesstransformers:";
|
||||
|
||||
private Dependencies() {
|
||||
@@ -105,6 +106,7 @@ 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";
|
||||
|
||||
private Versions() {
|
||||
|
||||
@@ -45,7 +45,7 @@ import org.zeroturnaround.zip.ZipUtil;
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.configuration.RemappedConfigurationEntry;
|
||||
import net.fabricmc.loom.configuration.providers.LaunchProvider;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.tr.MercuryUtils;
|
||||
import net.fabricmc.lorenztiny.TinyMappingsReader;
|
||||
import net.fabricmc.mapping.tree.TinyTree;
|
||||
@@ -175,7 +175,7 @@ public class SourceRemapper {
|
||||
}
|
||||
|
||||
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
|
||||
MappingsProvider mappingsProvider = extension.getMappingsProvider();
|
||||
MappingsProviderImpl mappingsProvider = extension.getMappingsProvider();
|
||||
|
||||
String intermediary = extension.isForge() ? "srg" : "intermediary";
|
||||
int id = -1;
|
||||
|
||||
@@ -24,7 +24,9 @@
|
||||
|
||||
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.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
@@ -35,12 +37,17 @@ import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.opencsv.CSVReader;
|
||||
import com.opencsv.exceptions.CsvValidationException;
|
||||
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.MutableTinyTree;
|
||||
import dev.architectury.mappingslayers.api.utils.MappingsUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.cadixdev.lorenz.MappingSet;
|
||||
import org.cadixdev.lorenz.io.srg.tsrg.TSrgReader;
|
||||
import org.cadixdev.lorenz.model.ClassMapping;
|
||||
@@ -180,17 +187,43 @@ public class MCPReader {
|
||||
private Map<MemberToken, String> readSrg() throws IOException {
|
||||
Map<MemberToken, String> tokens = new HashMap<>();
|
||||
|
||||
try (TSrgReader reader = new TSrgReader(Files.newBufferedReader(srgTsrgPath, StandardCharsets.UTF_8))) {
|
||||
MappingSet mappingSet = reader.read();
|
||||
try (BufferedReader reader = Files.newBufferedReader(srgTsrgPath, StandardCharsets.UTF_8)) {
|
||||
String content = IOUtils.toString(reader);
|
||||
|
||||
for (TopLevelClassMapping classMapping : mappingSet.getTopLevelClassMappings()) {
|
||||
appendClass(tokens, classMapping);
|
||||
if (content.startsWith("tsrg2")) {
|
||||
readTsrg2(tokens, content);
|
||||
} else {
|
||||
MappingSet mappingSet = new TSrgReader(new StringReader(content)).read();
|
||||
|
||||
for (TopLevelClassMapping classMapping : mappingSet.getTopLevelClassMappings()) {
|
||||
appendClass(tokens, classMapping);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
private void readTsrg2(Map<MemberToken, String> tokens, String content) {
|
||||
MutableTinyTree tree = MappingsUtils.deserializeFromTsrg2(content);
|
||||
int obfIndex = tree.getMetadata().index("obf");
|
||||
int srgIndex = tree.getMetadata().index("srg");
|
||||
|
||||
for (MutableClassDef classDef : tree.getClassesMutable()) {
|
||||
MemberToken ofClass = MemberToken.ofClass(classDef.getName(obfIndex));
|
||||
tokens.put(ofClass, classDef.getName(srgIndex));
|
||||
|
||||
for (MutableFieldDef fieldDef : classDef.getFieldsMutable()) {
|
||||
tokens.put(MemberToken.ofField(ofClass, fieldDef.getName(obfIndex)), fieldDef.getName(srgIndex));
|
||||
}
|
||||
|
||||
for (MutableMethodDef methodDef : classDef.getMethodsMutable()) {
|
||||
tokens.put(MemberToken.ofMethod(ofClass, methodDef.getName(obfIndex), methodDef.getDescriptor(obfIndex)),
|
||||
methodDef.getName(srgIndex));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void injectMcp(Path mcpJar, Map<String, String> intermediaryToSrgMap, Map<String, String[]> intermediaryToDocsMap, Map<String, Map<Integer, String>> intermediaryToParamsMap)
|
||||
throws IOException, CsvValidationException {
|
||||
Map<String, List<String>> srgToIntermediary = inverseMap(intermediaryToSrgMap);
|
||||
@@ -304,21 +337,12 @@ public class MCPReader {
|
||||
}
|
||||
}
|
||||
|
||||
private static class MemberToken {
|
||||
private final TokenType type;
|
||||
@Nullable
|
||||
private final MemberToken owner;
|
||||
private final String name;
|
||||
@Nullable
|
||||
private final String descriptor;
|
||||
|
||||
MemberToken(TokenType type, @Nullable MemberToken owner, String name, @Nullable String descriptor) {
|
||||
this.type = type;
|
||||
this.owner = owner;
|
||||
this.name = name;
|
||||
this.descriptor = descriptor;
|
||||
}
|
||||
|
||||
private record MemberToken(
|
||||
TokenType type,
|
||||
@Nullable MCPReader.MemberToken owner,
|
||||
String name,
|
||||
@Nullable String descriptor
|
||||
) {
|
||||
static MemberToken ofClass(String name) {
|
||||
return new MemberToken(TokenType.CLASS, null, name, null);
|
||||
}
|
||||
@@ -330,19 +354,6 @@ public class MCPReader {
|
||||
static MemberToken ofMethod(MemberToken owner, String name, String descriptor) {
|
||||
return new MemberToken(TokenType.METHOD, owner, name, descriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
MemberToken that = (MemberToken) o;
|
||||
return type == that.type && name.equals(that.name) && Objects.equals(descriptor, that.descriptor) && Objects.equals(owner, that.owner);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(type, name, descriptor, owner);
|
||||
}
|
||||
}
|
||||
|
||||
private enum TokenType {
|
||||
|
||||
@@ -26,6 +26,7 @@ package net.fabricmc.loom.util.srg;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
@@ -34,6 +35,12 @@ import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
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.MutableTinyTree;
|
||||
import dev.architectury.mappingslayers.api.utils.MappingsUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.cadixdev.lorenz.MappingSet;
|
||||
import org.cadixdev.lorenz.io.srg.tsrg.TSrgReader;
|
||||
import org.cadixdev.lorenz.model.ClassMapping;
|
||||
@@ -74,13 +81,9 @@ public final class SrgMerger {
|
||||
* 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;
|
||||
MappingSet arr = readSrg(srg);
|
||||
TinyTree foss;
|
||||
|
||||
try (TSrgReader reader = new TSrgReader(Files.newBufferedReader(srg))) {
|
||||
arr = reader.read();
|
||||
}
|
||||
|
||||
try (BufferedReader reader = Files.newBufferedReader(tiny)) {
|
||||
foss = TinyMappingFactory.loadWithDetection(reader);
|
||||
}
|
||||
@@ -104,6 +107,44 @@ public final class SrgMerger {
|
||||
TinyV2Writer.write(file, out);
|
||||
}
|
||||
|
||||
private static MappingSet readSrg(Path srg) throws IOException {
|
||||
try (BufferedReader reader = Files.newBufferedReader(srg)) {
|
||||
String content = IOUtils.toString(reader);
|
||||
|
||||
if (content.startsWith("tsrg2")) {
|
||||
return readTsrg2(content);
|
||||
} else {
|
||||
try (TSrgReader srgReader = new TSrgReader(new StringReader(content))) {
|
||||
return srgReader.read();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
for (MutableClassDef classDef : tree.getClassesMutable()) {
|
||||
ClassMapping<?, ?> classMapping = set.getOrCreateClassMapping(classDef.getName(obfIndex));
|
||||
classMapping.setDeobfuscatedName(classDef.getName(srgIndex));
|
||||
|
||||
for (MutableFieldDef fieldDef : classDef.getFieldsMutable()) {
|
||||
FieldMapping fieldMapping = classMapping.getOrCreateFieldMapping(fieldDef.getName(obfIndex));
|
||||
fieldMapping.setDeobfuscatedName(fieldDef.getName(srgIndex));
|
||||
}
|
||||
|
||||
for (MutableMethodDef methodDef : classDef.getMethodsMutable()) {
|
||||
MethodMapping methodMapping = classMapping.getOrCreateMethodMapping(methodDef.getName(obfIndex), methodDef.getDescriptor(obfIndex));
|
||||
methodMapping.setDeobfuscatedName(methodDef.getName(srgIndex));
|
||||
}
|
||||
}
|
||||
|
||||
return set;
|
||||
}
|
||||
|
||||
private static void classToTiny(TinyTree foss, List<String> namespaces, ClassMapping<?, ?> klass, Consumer<TinyClass> classConsumer, boolean lenient) {
|
||||
String obf = klass.getFullObfuscatedName();
|
||||
String srg = klass.getFullDeobfuscatedName();
|
||||
|
||||
Reference in New Issue
Block a user