mirror of
https://github.com/architectury/architectury-loom.git
synced 2026-04-01 21:17:46 -05:00
NeoForge support (#166)
* Initial plumbing for NeoForge support
* Fix checkstyle
* Add ModPlatform.id
* Use NeoForge-specific cache
* Use NeoForge-specific dependency configuration
This is only for the "(neo)forge" configuration exposed
as API. The other configurations remain the same.
* Add test for basic NeoForge 1.20.2 projects
* Implement hacky fast track for NeoForge field migration
In other works, we skip field migrating for now.
* Disable patched decompilation task on Neo
* Disable mixin AP for building on NeoForge
* Many changes related to NeoForge mappings and remapping
* Code style and related fixes
* McpExecutor: Add support for downloading deps via Gradle
Also adds support for downloading a file without a repo
for NeoForm functions.
* Fix wrong configurations being used on NeoForge
* Fix mixin version detection on NeoForge
* Rename MinecraftPatchedProvider jar paths on NeoForge
* Test NeoForge against a client-only MC jar
* Add DFU for codecs, support NeoForge run config templates
* Centralise userdev config reading, support missing SAS
* Set up Shadow for bundling DFU
* Use correct name for NeoForm in cache files
* RemapJarTask: Fix check using isForgeLike for Forge
* MojangMappingsMerger: Complete and reorder mappings
* Fix SRG being used on NeoForge
* Fix SRG being used on NeoForge for ATs
* Use client pipeline for merged to avoid patch issues on Neo
* Update to architectury-loom-runtime 2.0
* Fix Minecraft jar name on Neo
* Fix MojangMappingsMerger having incomplete names
* Fix NeoForge mod dependency remapping using wrong mappings
* Quiet down MojangMappingsMerger
* Fix (Neo)Forge builtin coremods not being remapped
Fixes #146.
* Disable deprecated data generation API on NeoForge
* Use release version of the forge runtime
* Revert "Set up Shadow for bundling DFU"
This reverts commit 2bb8166744.
* Make NeoForge Field Migration work
* NeoForge shouldn't try to get datagen mods
* Fix checkstyle
* Remove mojang maven
* Split Forge and NeoForge extensions
* SimpleNeoForgeTest: Bump Neo version and fix Yarn version
* Remove resolved TODOs
* Re-enable joined NeoForm pipeline
* MPP: Rename srg -> intermediate jars
* Reintroduce namespace filtering for mapping trees
Should be a simple optimisation to avoid reading an
additional ns.
* ForgeRunTemplateTest: Fix code format
* Adapt SrgMerger into ForgeMappingsMerger (#169)
* Fix crash with NeoForge ext creation
* Adapt SrgMerger into ForgeMappingsMerger
* Update tiny-remapper
* Fix spotless
* Resolve reviews
* Fix checkstyle
* Remap ASMAPI.redirectFieldToMethod (#171)
* Remap ASMAPI.redirectFieldToMethod
* Move lastClassName outside the if
* Fix missing template variables in tests using forge/simple
* Add Java version to forge/simple test variables
* Disable naming service dependency on Neo
* Fix changing patch version not affecting mapped game jars
Fixes #167.
* Rename configuration: neoforge -> neoForge
---------
Co-authored-by: shedaniel <daniel@shedaniel.me>
This commit is contained in:
45
src/main/java/dev/architectury/loom/forge/UserdevConfig.java
Normal file
45
src/main/java/dev/architectury/loom/forge/UserdevConfig.java
Normal file
@@ -0,0 +1,45 @@
|
||||
package dev.architectury.loom.forge;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
|
||||
import net.fabricmc.loom.configuration.providers.forge.ForgeRunTemplate;
|
||||
|
||||
public record UserdevConfig(
|
||||
String mcp,
|
||||
String universal,
|
||||
String sources,
|
||||
String patches,
|
||||
Optional<String> patchesOriginalPrefix,
|
||||
Optional<String> patchesModifiedPrefix,
|
||||
String binpatches,
|
||||
BinaryPatcherConfig binpatcher,
|
||||
List<String> libraries,
|
||||
Map<String, ForgeRunTemplate> runs,
|
||||
List<String> sass
|
||||
) {
|
||||
public static final Codec<UserdevConfig> CODEC = RecordCodecBuilder.create(instance -> instance.group(
|
||||
Codec.STRING.fieldOf("mcp").forGetter(UserdevConfig::mcp),
|
||||
Codec.STRING.fieldOf("universal").forGetter(UserdevConfig::universal),
|
||||
Codec.STRING.fieldOf("sources").forGetter(UserdevConfig::sources),
|
||||
Codec.STRING.fieldOf("patches").forGetter(UserdevConfig::patches),
|
||||
Codec.STRING.optionalFieldOf("patchesOriginalPrefix").forGetter(UserdevConfig::patchesOriginalPrefix),
|
||||
Codec.STRING.optionalFieldOf("patchesModifiedPrefix").forGetter(UserdevConfig::patchesModifiedPrefix),
|
||||
Codec.STRING.fieldOf("binpatches").forGetter(UserdevConfig::binpatches),
|
||||
BinaryPatcherConfig.CODEC.fieldOf("binpatcher").forGetter(UserdevConfig::binpatcher),
|
||||
Codec.STRING.listOf().fieldOf("libraries").forGetter(UserdevConfig::libraries),
|
||||
ForgeRunTemplate.MAP_CODEC.fieldOf("runs").forGetter(UserdevConfig::runs),
|
||||
Codec.STRING.listOf().optionalFieldOf("sass", List.of()).forGetter(UserdevConfig::sass)
|
||||
).apply(instance, UserdevConfig::new));
|
||||
|
||||
public record BinaryPatcherConfig(String dependency, List<String> args) {
|
||||
public static final Codec<BinaryPatcherConfig> CODEC = RecordCodecBuilder.create(instance -> instance.group(
|
||||
Codec.STRING.fieldOf("version").forGetter(BinaryPatcherConfig::dependency),
|
||||
Codec.STRING.listOf().fieldOf("args").forGetter(BinaryPatcherConfig::args)
|
||||
).apply(instance, BinaryPatcherConfig::new));
|
||||
}
|
||||
}
|
||||
@@ -8,8 +8,6 @@ import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import org.gradle.api.Project;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -31,18 +29,16 @@ public final class ForgeLoggerConfig {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
|
||||
final JsonArray libraries = LoomGradleExtension.get(project)
|
||||
final List<String> libraries = LoomGradleExtension.get(project)
|
||||
.getForgeUserdevProvider()
|
||||
.getJson()
|
||||
.getAsJsonArray("libraries");
|
||||
.getConfig()
|
||||
.libraries();
|
||||
boolean found = false;
|
||||
|
||||
for (JsonElement library : libraries) {
|
||||
final String notation = library.getAsString();
|
||||
|
||||
if (LOGGER_CONFIG_ARTIFACTS.stream().anyMatch(artifact -> artifact.matches(notation))) {
|
||||
for (String library : libraries) {
|
||||
if (LOGGER_CONFIG_ARTIFACTS.stream().anyMatch(artifact -> artifact.matches(library))) {
|
||||
final File libraryFile = project.getConfigurations()
|
||||
.detachedConfiguration(project.getDependencies().create(notation))
|
||||
.detachedConfiguration(project.getDependencies().create(library))
|
||||
.setTransitive(false)
|
||||
.getSingleFile();
|
||||
|
||||
|
||||
38
src/main/java/dev/architectury/loom/util/MappingOption.java
Normal file
38
src/main/java/dev/architectury/loom/util/MappingOption.java
Normal file
@@ -0,0 +1,38 @@
|
||||
package dev.architectury.loom.util;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.fabricmc.loom.api.LoomGradleExtensionAPI;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
|
||||
public enum MappingOption {
|
||||
DEFAULT(null),
|
||||
WITH_SRG(MappingsNamespace.SRG.toString()),
|
||||
WITH_MOJANG(MappingsNamespace.MOJANG.toString());
|
||||
|
||||
private final String extraNamespace;
|
||||
|
||||
MappingOption(@Nullable String extraNamespace) {
|
||||
this.extraNamespace = extraNamespace;
|
||||
}
|
||||
|
||||
public MappingOption forNamespaces(String... namespaces) {
|
||||
if (extraNamespace == null) return this;
|
||||
|
||||
for (String namespace : namespaces) {
|
||||
if (extraNamespace.equals(namespace)) {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
return DEFAULT;
|
||||
}
|
||||
|
||||
public static MappingOption forPlatform(LoomGradleExtensionAPI extension) {
|
||||
return switch (extension.getPlatform().get()) {
|
||||
case FORGE -> WITH_SRG;
|
||||
case NEOFORGE -> WITH_MOJANG;
|
||||
default -> DEFAULT;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -50,6 +50,7 @@ import net.fabricmc.loom.configuration.providers.mappings.MappingConfiguration;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.library.LibraryProcessorManager;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.mapped.IntermediaryMinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.mapped.MojangMappedMinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.mapped.NamedMinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.mapped.SrgMinecraftProvider;
|
||||
import net.fabricmc.loom.extension.LoomFiles;
|
||||
@@ -95,6 +96,10 @@ public interface LoomGradleExtension extends LoomGradleExtensionAPI {
|
||||
|
||||
void setSrgMinecraftProvider(SrgMinecraftProvider<?> srgMinecraftProvider);
|
||||
|
||||
MojangMappedMinecraftProvider<?> getMojangMappedMinecraftProvider();
|
||||
|
||||
void setMojangMappedMinecraftProvider(MojangMappedMinecraftProvider<?> srgMinecraftProvider);
|
||||
|
||||
default List<Path> getMinecraftJars(MappingsNamespace mappingsNamespace) {
|
||||
return switch (mappingsNamespace) {
|
||||
case NAMED -> getNamedMinecraftProvider().getMinecraftJarPaths();
|
||||
@@ -104,6 +109,10 @@ public interface LoomGradleExtension extends LoomGradleExtensionAPI {
|
||||
ModPlatform.assertPlatform(this, ModPlatform.FORGE, () -> "SRG jars are only available on Forge.");
|
||||
yield getSrgMinecraftProvider().getMinecraftJarPaths();
|
||||
}
|
||||
case MOJANG -> {
|
||||
ModPlatform.assertPlatform(this, ModPlatform.NEOFORGE, () -> "Mojang-mapped jars are only available on NeoForge.");
|
||||
yield getMojangMappedMinecraftProvider().getMinecraftJarPaths();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -149,12 +158,12 @@ public interface LoomGradleExtension extends LoomGradleExtensionAPI {
|
||||
return isForge() && !getForge().getDataGenMods().isEmpty();
|
||||
}
|
||||
|
||||
default boolean isForgeAndOfficial() {
|
||||
return isForge() && getMcpConfigProvider().isOfficial();
|
||||
default boolean isForgeLikeAndOfficial() {
|
||||
return isForgeLike() && getMcpConfigProvider().isOfficial();
|
||||
}
|
||||
|
||||
default boolean isForgeAndNotOfficial() {
|
||||
return isForge() && !getMcpConfigProvider().isOfficial();
|
||||
default boolean isForgeLikeAndNotOfficial() {
|
||||
return isForgeLike() && !getMcpConfigProvider().isOfficial();
|
||||
}
|
||||
|
||||
DependencyProviders getDependencyProviders();
|
||||
@@ -179,4 +188,14 @@ public interface LoomGradleExtension extends LoomGradleExtensionAPI {
|
||||
|
||||
ForgeRunsProvider getForgeRunsProvider();
|
||||
void setForgeRunsProvider(ForgeRunsProvider forgeRunsProvider);
|
||||
|
||||
/**
|
||||
* The mapping file that is specific to the platform settings.
|
||||
* It contains SRG (Forge/common) or Mojang mappings (NeoForge) as needed.
|
||||
*
|
||||
* @return the platform mapping file path
|
||||
*/
|
||||
default Path getPlatformMappingFile() {
|
||||
return getMappingConfiguration().getPlatformMappingFile(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ import org.gradle.api.provider.SetProperty;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
/**
|
||||
* This is the forge extension api available exposed to build scripts.
|
||||
* This is the Forge extension API available to build scripts.
|
||||
*/
|
||||
@ApiStatus.NonExtendable
|
||||
public interface ForgeExtensionAPI {
|
||||
|
||||
@@ -235,10 +235,18 @@ public interface LoomGradleExtensionAPI {
|
||||
|
||||
Provider<ModPlatform> getPlatform();
|
||||
|
||||
default boolean isForgeLike() {
|
||||
return getPlatform().get().isForgeLike();
|
||||
}
|
||||
|
||||
default boolean isForge() {
|
||||
return getPlatform().get() == ModPlatform.FORGE;
|
||||
}
|
||||
|
||||
default boolean isNeoForge() {
|
||||
return getPlatform().get() == ModPlatform.NEOFORGE;
|
||||
}
|
||||
|
||||
default boolean isQuilt() {
|
||||
return getPlatform().get() == ModPlatform.QUILT;
|
||||
}
|
||||
@@ -265,4 +273,15 @@ public interface LoomGradleExtensionAPI {
|
||||
ForgeExtensionAPI getForge();
|
||||
|
||||
void forge(Action<ForgeExtensionAPI> action);
|
||||
|
||||
/**
|
||||
* Gets the NeoForge extension used to configure NeoForge details.
|
||||
*
|
||||
* @return the NeoForge extension
|
||||
* @throws UnsupportedOperationException if running on another platform
|
||||
* @see #isNeoForge()
|
||||
*/
|
||||
NeoForgeExtensionAPI getNeoForge();
|
||||
|
||||
void neoForge(Action<NeoForgeExtensionAPI> action);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2023 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.api;
|
||||
|
||||
import org.gradle.api.file.ConfigurableFileCollection;
|
||||
|
||||
/**
|
||||
* This is the NeoForge extension API available to build scripts.
|
||||
*/
|
||||
public interface NeoForgeExtensionAPI {
|
||||
/**
|
||||
* A collection of all project access transformers.
|
||||
* The collection should only contain AT files, and not directories or other files.
|
||||
*
|
||||
* <p>If this collection is empty, Loom tries to resolve the AT from the default path
|
||||
* ({@code META-INF/accesstransformer.cfg} in the {@code main} source set).
|
||||
*
|
||||
* @return the collection of AT files
|
||||
*/
|
||||
ConfigurableFileCollection getAccessTransformers();
|
||||
|
||||
/**
|
||||
* Adds a {@linkplain #getAccessTransformers() project access transformer}.
|
||||
*
|
||||
* @param file the file, evaluated as per {@link org.gradle.api.Project#file(Object)}
|
||||
*/
|
||||
void accessTransformer(Object file);
|
||||
}
|
||||
@@ -54,6 +54,14 @@ public enum MappingsNamespace {
|
||||
*/
|
||||
SRG,
|
||||
|
||||
/**
|
||||
* Mojang's official names from their deobfuscation maps.
|
||||
*
|
||||
* <p>They are used as the mapping set in a NeoForge production environment akin to Fabric's
|
||||
* {@linkplain #INTERMEDIARY intermediary mappings}.
|
||||
*/
|
||||
MOJANG,
|
||||
|
||||
/**
|
||||
* Named mappings are the developer friendly names used to develop mods against.
|
||||
*/
|
||||
@@ -70,6 +78,7 @@ public enum MappingsNamespace {
|
||||
case "official" -> OFFICIAL;
|
||||
case "intermediary" -> INTERMEDIARY;
|
||||
case "srg" -> SRG;
|
||||
case "mojang" -> MOJANG;
|
||||
case "named" -> NAMED;
|
||||
default -> null;
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2022 FabricMC
|
||||
* Copyright (c) 2022-2023 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
|
||||
@@ -34,8 +34,19 @@ public final class IntermediaryNamespaces {
|
||||
* Returns the intermediary namespace of the project.
|
||||
*/
|
||||
public static String intermediary(Project project) {
|
||||
return intermediaryNamespace(project).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the intermediary namespace of the project.
|
||||
*/
|
||||
public static MappingsNamespace intermediaryNamespace(Project project) {
|
||||
LoomGradleExtension extension = LoomGradleExtension.get(project);
|
||||
return extension.isForge() ? "srg" : "intermediary";
|
||||
return switch (extension.getPlatform().get()) {
|
||||
case FABRIC, QUILT -> MappingsNamespace.INTERMEDIARY;
|
||||
case FORGE -> MappingsNamespace.SRG;
|
||||
case NEOFORGE -> MappingsNamespace.MOJANG;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -64,7 +64,7 @@ public class JarNester {
|
||||
}
|
||||
}).collect(Collectors.toList()));
|
||||
|
||||
if (platform == ModPlatform.FORGE) {
|
||||
if (platform.isForgeLike()) {
|
||||
handleForgeJarJar(forgeJars, modJar, logger);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import java.util.function.Consumer;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.file.FileCollection;
|
||||
import org.gradle.api.plugins.JavaPlugin;
|
||||
import org.gradle.api.plugins.JavaPluginExtension;
|
||||
import org.gradle.api.tasks.AbstractCopyTask;
|
||||
@@ -72,6 +73,7 @@ import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftSourceSets;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.mapped.AbstractMappedMinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.mapped.IntermediaryMinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.mapped.MojangMappedMinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.mapped.NamedMinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.mapped.SrgMinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.sources.ForgeSourcesRemapper;
|
||||
@@ -132,7 +134,7 @@ public abstract class CompileConfiguration implements Runnable {
|
||||
|
||||
configureDecompileTasks(configContext);
|
||||
|
||||
if (extension.isForge()) {
|
||||
if (extension.isForgeLike()) {
|
||||
if (extension.isDataGenEnabled()) {
|
||||
getProject().getExtensions().getByType(JavaPluginExtension.class).getSourceSets().getByName("main").resources(files -> {
|
||||
files.srcDir(getProject().file("src/generated/resources"));
|
||||
@@ -165,7 +167,7 @@ public abstract class CompileConfiguration implements Runnable {
|
||||
getTasks().withType(AbstractCopyTask.class).configureEach(abstractCopyTask -> abstractCopyTask.setFilteringCharset(StandardCharsets.UTF_8.name()));
|
||||
getTasks().withType(JavaCompile.class).configureEach(javaCompile -> javaCompile.getOptions().setEncoding(StandardCharsets.UTF_8.name()));
|
||||
|
||||
if (extension.isForge()) {
|
||||
if (extension.isForgeLike()) {
|
||||
// Create default mod from main source set
|
||||
extension.mods(mods -> {
|
||||
final SourceSet main = getProject().getExtensions().getByType(JavaPluginExtension.class).getSourceSets().getByName(SourceSet.MAIN_SOURCE_SET_NAME);
|
||||
@@ -188,7 +190,7 @@ public abstract class CompileConfiguration implements Runnable {
|
||||
// Provide the vanilla mc jars -- TODO share across getProject()s.
|
||||
final MinecraftProvider minecraftProvider = jarConfiguration.getMinecraftProviderFunction().apply(configContext);
|
||||
|
||||
if (extension.isForge() && !(minecraftProvider instanceof ForgeMinecraftProvider)) {
|
||||
if (extension.isForgeLike() && !(minecraftProvider instanceof ForgeMinecraftProvider)) {
|
||||
throw new UnsupportedOperationException("Using Forge with split jars is not supported!");
|
||||
}
|
||||
|
||||
@@ -203,7 +205,7 @@ public abstract class CompileConfiguration implements Runnable {
|
||||
final MappingConfiguration mappingConfiguration = MappingConfiguration.create(getProject(), configContext.serviceManager(), mappingsDep, minecraftProvider);
|
||||
extension.setMappingConfiguration(mappingConfiguration);
|
||||
|
||||
if (extension.isForge()) {
|
||||
if (extension.isForgeLike()) {
|
||||
ForgeLibrariesProvider.provide(mappingConfiguration, project);
|
||||
((ForgeMinecraftProvider) minecraftProvider).getPatchedProvider().provide();
|
||||
}
|
||||
@@ -211,7 +213,7 @@ public abstract class CompileConfiguration implements Runnable {
|
||||
mappingConfiguration.setupPost(project);
|
||||
mappingConfiguration.applyToProject(getProject(), mappingsDep);
|
||||
|
||||
if (extension.isForge()) {
|
||||
if (extension.isForgeLike()) {
|
||||
extension.setForgeRunsProvider(ForgeRunsProvider.create(project));
|
||||
}
|
||||
|
||||
@@ -243,6 +245,10 @@ public abstract class CompileConfiguration implements Runnable {
|
||||
final SrgMinecraftProvider<?> srgMinecraftProvider = jarConfiguration.getSrgMinecraftProviderBiFunction().apply(project, minecraftProvider);
|
||||
extension.setSrgMinecraftProvider(srgMinecraftProvider);
|
||||
srgMinecraftProvider.provide(provideContext);
|
||||
} else if (extension.isNeoForge()) {
|
||||
final MojangMappedMinecraftProvider<?> mojangMappedMinecraftProvider = jarConfiguration.getMojangMappedMinecraftProviderBiFunction().apply(project, minecraftProvider);
|
||||
extension.setMojangMappedMinecraftProvider(mojangMappedMinecraftProvider);
|
||||
mojangMappedMinecraftProvider.provide(provideContext);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,8 +268,16 @@ public abstract class CompileConfiguration implements Runnable {
|
||||
extension.addMinecraftJarProcessor(InterfaceInjectionProcessor.class, "fabric-loom:interface-inject", interfaceInjection.getEnableDependencyInterfaceInjection().get());
|
||||
}
|
||||
|
||||
if (extension.isForge()) {
|
||||
extension.addMinecraftJarProcessor(AccessTransformerJarProcessor.class, "loom:access-transformer", configContext.project(), extension.getForge().getAccessTransformers());
|
||||
if (extension.isForgeLike()) {
|
||||
FileCollection accessTransformers;
|
||||
|
||||
if (extension.isNeoForge()) {
|
||||
accessTransformers = extension.getNeoForge().getAccessTransformers();
|
||||
} else {
|
||||
accessTransformers = extension.getForge().getAccessTransformers();
|
||||
}
|
||||
|
||||
extension.addMinecraftJarProcessor(AccessTransformerJarProcessor.class, "loom:access-transformer", configContext.project(), accessTransformers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -356,7 +370,7 @@ public abstract class CompileConfiguration implements Runnable {
|
||||
DependencyProviders dependencyProviders = new DependencyProviders();
|
||||
extension.setDependencyProviders(dependencyProviders);
|
||||
|
||||
if (extension.isForge()) {
|
||||
if (extension.isForgeLike()) {
|
||||
dependencyProviders.addProvider(new ForgeProvider(project));
|
||||
dependencyProviders.addProvider(new ForgeUserdevProvider(project));
|
||||
}
|
||||
@@ -365,7 +379,7 @@ public abstract class CompileConfiguration implements Runnable {
|
||||
dependencyProviders.addProvider(new SrgProvider(project));
|
||||
}
|
||||
|
||||
if (extension.isForge()) {
|
||||
if (extension.isForgeLike()) {
|
||||
dependencyProviders.addProvider(new McpConfigProvider(project));
|
||||
dependencyProviders.addProvider(new PatchProvider(project));
|
||||
dependencyProviders.addProvider(new ForgeUniversalProvider(project));
|
||||
|
||||
@@ -118,9 +118,16 @@ public abstract class LoomConfigurations implements Runnable {
|
||||
}
|
||||
});
|
||||
|
||||
if (extension.isForge()) {
|
||||
// Set up Forge configurations
|
||||
registerNonTransitive(Constants.Configurations.FORGE, Role.RESOLVABLE);
|
||||
if (extension.isForgeLike()) {
|
||||
// Set up Forge and NeoForge configurations
|
||||
if (extension.isForge()) {
|
||||
// Forge-specific configurations
|
||||
registerNonTransitive(Constants.Configurations.FORGE, Role.RESOLVABLE);
|
||||
} else if (extension.isNeoForge()) {
|
||||
// NeoForge-specific configurations
|
||||
registerNonTransitive(Constants.Configurations.NEOFORGE, Role.RESOLVABLE);
|
||||
}
|
||||
|
||||
registerNonTransitive(Constants.Configurations.FORGE_USERDEV, Role.RESOLVABLE);
|
||||
registerNonTransitive(Constants.Configurations.FORGE_INSTALLER, Role.RESOLVABLE);
|
||||
registerNonTransitive(Constants.Configurations.FORGE_UNIVERSAL, Role.RESOLVABLE);
|
||||
@@ -150,10 +157,16 @@ public abstract class LoomConfigurations implements Runnable {
|
||||
extendsFrom(JavaPlugin.TEST_COMPILE_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_EXTRA);
|
||||
extendsFrom(JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_EXTRA);
|
||||
|
||||
// Add Forge dev-time dependencies
|
||||
getDependencies().add(Constants.Configurations.FORGE_EXTRA, LoomVersions.FORGE_RUNTIME.mavenNotation());
|
||||
// Add Forge/NeoForge shared dev-time dependencies
|
||||
getDependencies().add(Constants.Configurations.FORGE_EXTRA, LoomVersions.UNPROTECT.mavenNotation());
|
||||
getDependencies().add(JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME, LoomVersions.JAVAX_ANNOTATIONS.mavenNotation());
|
||||
|
||||
// Add Forge-only dev-time dependencies
|
||||
if (extension.isForge()) {
|
||||
getDependencies().add(Constants.Configurations.FORGE_EXTRA, LoomVersions.NAMING_SERVICE.mavenNotation());
|
||||
getDependencies().add(Constants.Configurations.FORGE_EXTRA, LoomVersions.MIXIN_REMAPPER_SERVICE.mavenNotation());
|
||||
getDependencies().add(Constants.Configurations.FORGE_EXTRA, LoomVersions.MCP_ANNOTATIONS.mavenNotation());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,14 +37,14 @@ public class LoomDependencyManager {
|
||||
LoomGradleExtension extension = LoomGradleExtension.get(project);
|
||||
|
||||
SourceRemapper sourceRemapper = new SourceRemapper(project, serviceManager, true);
|
||||
String platformSuffix = extension.isForge() ? "_forge" : extension.isQuilt() ? "_arch_quilt" : "";
|
||||
String platformSuffix = extension.isForgeLike() ? "_forge" : extension.isQuilt() ? "_arch_quilt" : "";
|
||||
String mappingsIdentifier = extension.getMappingConfiguration().mappingsIdentifier() + platformSuffix;
|
||||
|
||||
ModConfigurationRemapper.supplyModConfigurations(project, serviceManager, mappingsIdentifier, extension, sourceRemapper);
|
||||
|
||||
sourceRemapper.remapAll();
|
||||
|
||||
if (extension.getInstallerData() == null && !extension.isForge()) {
|
||||
if (extension.getInstallerData() == null && !extension.isForgeLike()) {
|
||||
if (extension.isQuilt()) {
|
||||
project.getLogger().warn("quilt_installer.json not found in dependencies!");
|
||||
} else {
|
||||
|
||||
@@ -100,7 +100,7 @@ public abstract class MavenPublication implements Runnable {
|
||||
|
||||
if (hasSoftwareComponent(publication) || EXCLUDED_PUBLICATIONS.contains(publication)) {
|
||||
continue;
|
||||
} else if (!reportedDeprecation.get() && !LoomGradleExtension.get(getProject()).isForge()) {
|
||||
} else if (!reportedDeprecation.get() && !LoomGradleExtension.get(getProject()).isForgeLike()) {
|
||||
DeprecationHelper deprecationHelper = LoomGradleExtension.get(getProject()).getDeprecationHelper();
|
||||
deprecationHelper.warn("Loom is applying dependency data manually to publications instead of using a software component (from(components[\"java\"])). This is deprecated.");
|
||||
reportedDeprecation.set(true);
|
||||
|
||||
@@ -54,6 +54,7 @@ import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.api.processor.MinecraftJarProcessor;
|
||||
import net.fabricmc.loom.api.processor.ProcessorContext;
|
||||
import net.fabricmc.loom.api.processor.SpecContext;
|
||||
import net.fabricmc.loom.build.IntermediaryNamespaces;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
import net.fabricmc.loom.util.DependencyDownloader;
|
||||
import net.fabricmc.loom.util.ExceptionUtil;
|
||||
@@ -138,7 +139,7 @@ public class AccessTransformerJarProcessor implements MinecraftJarProcessor<Acce
|
||||
}
|
||||
}
|
||||
|
||||
accessTransformSet = accessTransformSet.remap(new TinyMappingsReader(context.getMappings(), MappingsNamespace.SRG.toString(), MappingsNamespace.NAMED.toString()).read());
|
||||
accessTransformSet = accessTransformSet.remap(new TinyMappingsReader(context.getMappings(), IntermediaryNamespaces.intermediary(project), MappingsNamespace.NAMED.toString()).read());
|
||||
|
||||
final Path accessTransformerPath = tempFiles.file("accesstransformer-merged", ".cfg");
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ public class SingleJarDecompileConfiguration extends DecompileConfiguration<Mapp
|
||||
task.setDescription("Decompile Minecraft using Forge's toolchain.");
|
||||
task.setGroup(Constants.TaskGroup.FABRIC);
|
||||
|
||||
task.getInputJar().set(MinecraftPatchedProvider.get(project).getMinecraftSrgJar().toFile());
|
||||
task.getInputJar().set(MinecraftPatchedProvider.get(project).getMinecraftIntermediateJar().toFile());
|
||||
task.getRuntimeJar().set(minecraftJar.toFile());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -345,7 +345,7 @@ public class RunConfigSettings implements Named {
|
||||
environment("client");
|
||||
defaultMainClass(Constants.Knot.KNOT_CLIENT);
|
||||
|
||||
if (getExtension().isForge()) {
|
||||
if (getExtension().isForgeLike()) {
|
||||
forgeTemplate("client");
|
||||
}
|
||||
}
|
||||
@@ -358,7 +358,7 @@ public class RunConfigSettings implements Named {
|
||||
environment("server");
|
||||
defaultMainClass(Constants.Knot.KNOT_SERVER);
|
||||
|
||||
if (getExtension().isForge()) {
|
||||
if (getExtension().isForgeLike()) {
|
||||
forgeTemplate("server");
|
||||
}
|
||||
}
|
||||
@@ -369,7 +369,7 @@ public class RunConfigSettings implements Named {
|
||||
* <p>This method can only be used on Forge.
|
||||
*/
|
||||
public void data() {
|
||||
ModPlatform.assertPlatform(getExtension(), ModPlatform.FORGE, () -> "RunConfigSettings.data() is only usable on Forge.");
|
||||
ModPlatform.assertForgeLike(getExtension(), () -> "RunConfigSettings.data() is only usable on Forge.");
|
||||
environment("data");
|
||||
forgeTemplate("data");
|
||||
}
|
||||
@@ -384,7 +384,7 @@ public class RunConfigSettings implements Named {
|
||||
* @since 1.0
|
||||
*/
|
||||
public void forgeTemplate(String templateName) {
|
||||
ModPlatform.assertPlatform(getExtension(), ModPlatform.FORGE);
|
||||
ModPlatform.assertForgeLike(getExtension());
|
||||
defaultMainClass(Constants.Forge.UNDETERMINED_MAIN_CLASS);
|
||||
// Evaluate later if Forge hasn't been resolved yet.
|
||||
evaluateNowOrLater(() -> {
|
||||
@@ -437,11 +437,11 @@ public class RunConfigSettings implements Named {
|
||||
* {@linkplain net.fabricmc.loom.api.LoomGradleExtensionAPI#getMods global container}
|
||||
* declared in the {@code loom} extension.
|
||||
*
|
||||
* <p>This method is currently only available on Forge.
|
||||
* <p>This method is currently only available on Forge and NeoForge.
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
public NamedDomainObjectContainer<ModSettings> getMods() {
|
||||
ModPlatform.assertPlatform(project, ModPlatform.FORGE);
|
||||
ModPlatform.assertForgeLike(extension);
|
||||
return mods;
|
||||
}
|
||||
|
||||
|
||||
@@ -60,8 +60,8 @@ public record ArtifactMetadata(boolean isFabricMod, RemapRequirements remapRequi
|
||||
RemapRequirements remapRequirements = RemapRequirements.DEFAULT;
|
||||
InstallerData installerData = null;
|
||||
|
||||
// Force-remap all mods on Forge.
|
||||
if (platform == ModPlatform.FORGE) {
|
||||
// Force-remap all mods on Forge and NeoForge.
|
||||
if (platform.isForgeLike()) {
|
||||
remapRequirements = RemapRequirements.OPT_IN;
|
||||
}
|
||||
|
||||
|
||||
@@ -41,10 +41,12 @@ import java.util.regex.Pattern;
|
||||
|
||||
import com.google.common.base.Stopwatch;
|
||||
import com.google.gson.JsonObject;
|
||||
import dev.architectury.loom.util.MappingOption;
|
||||
import dev.architectury.tinyremapper.InputTag;
|
||||
import dev.architectury.tinyremapper.NonClassCopyMode;
|
||||
import dev.architectury.tinyremapper.OutputConsumerPath;
|
||||
import dev.architectury.tinyremapper.TinyRemapper;
|
||||
import dev.architectury.tinyremapper.extension.mixin.MixinExtension;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.attributes.Usage;
|
||||
@@ -166,8 +168,15 @@ public class ModProcessor {
|
||||
|
||||
Stopwatch stopwatch = Stopwatch.createStarted();
|
||||
|
||||
boolean srg = (fromM.equals("srg") || toM.equals("srg")) && extension.isForge();
|
||||
MemoryMappingTree mappings = mappingConfiguration.getMappingsService(serviceManager, srg).getMappingTree();
|
||||
MappingOption mappingOption = MappingOption.DEFAULT;
|
||||
|
||||
if ((fromM.equals(MappingsNamespace.SRG.toString()) || toM.equals(MappingsNamespace.SRG.toString())) && extension.isForge()) {
|
||||
mappingOption = MappingOption.WITH_SRG;
|
||||
} else if ((fromM.equals(MappingsNamespace.MOJANG.toString()) || toM.equals(MappingsNamespace.MOJANG.toString())) && extension.isNeoForge()) {
|
||||
mappingOption = MappingOption.WITH_MOJANG;
|
||||
}
|
||||
|
||||
MemoryMappingTree mappings = mappingConfiguration.getMappingsService(serviceManager, mappingOption).getMappingTree();
|
||||
LoggerFilter.replaceSystemOut();
|
||||
TinyRemapper.Builder builder = TinyRemapper.newRemapper()
|
||||
.withKnownIndyBsm(extension.getKnownIndyBsms().get())
|
||||
@@ -185,9 +194,13 @@ public class ModProcessor {
|
||||
builder.extension(kotlinRemapperClassloader.getTinyRemapperExtension());
|
||||
}
|
||||
|
||||
if (extension.isNeoForge()) {
|
||||
builder.extension(new MixinExtension());
|
||||
}
|
||||
|
||||
final TinyRemapper remapper = builder.build();
|
||||
|
||||
for (Path minecraftJar : extension.getMinecraftJars(extension.isForge() ? MappingsNamespace.SRG : MappingsNamespace.INTERMEDIARY)) {
|
||||
for (Path minecraftJar : extension.getMinecraftJars(IntermediaryNamespaces.intermediaryNamespace(project))) {
|
||||
remapper.readClassPathAsync(minecraftJar);
|
||||
}
|
||||
|
||||
@@ -264,9 +277,9 @@ public class ModProcessor {
|
||||
stripNestedJars(output);
|
||||
remapJarManifestEntries(output);
|
||||
|
||||
if (extension.isForge()) {
|
||||
AtRemapper.remap(project.getLogger(), output, mappings);
|
||||
CoreModClassRemapper.remapJar(output, mappings, project.getLogger());
|
||||
if (extension.isForgeLike()) {
|
||||
AtRemapper.remap(project, output, mappings);
|
||||
CoreModClassRemapper.remapJar(project, extension.getPlatform().get(), output, mappings);
|
||||
}
|
||||
|
||||
dependency.copyToCache(project, output, null);
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
package net.fabricmc.loom.configuration.processors;
|
||||
|
||||
import dev.architectury.loom.util.MappingOption;
|
||||
import dev.architectury.tinyremapper.TinyRemapper;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
@@ -64,6 +65,7 @@ public record ProcessorContextImpl(ConfigContext configContext, MinecraftJar min
|
||||
@Override
|
||||
public MemoryMappingTree getMappings() {
|
||||
LoomGradleExtension extension = LoomGradleExtension.get(configContext().project());
|
||||
return extension.getMappingConfiguration().getMappingsService(configContext().serviceManager(), extension.isForge()).getMappingTree();
|
||||
final MappingOption mappingOption = MappingOption.forPlatform(extension);
|
||||
return extension.getMappingConfiguration().getMappingsService(configContext().serviceManager(), mappingOption).getMappingTree();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.forge;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
|
||||
/**
|
||||
* A string or a variable in a Forge configuration file, or an MCPConfig step or function.
|
||||
*/
|
||||
@@ -41,6 +43,16 @@ public sealed interface ConfigValue {
|
||||
*/
|
||||
String LOG = "log";
|
||||
|
||||
Codec<ConfigValue> CODEC = Codec.STRING.xmap(ConfigValue::of, configValue -> {
|
||||
if (configValue instanceof Constant constant) {
|
||||
return constant.value();
|
||||
} else if (configValue instanceof Variable variable) {
|
||||
return "{" + variable.name() + "}";
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Unmatched config value");
|
||||
});
|
||||
|
||||
String resolve(Resolver variableResolver);
|
||||
|
||||
static ConfigValue of(String str) {
|
||||
|
||||
@@ -66,8 +66,9 @@ import net.fabricmc.mappingio.tree.MemoryMappingTree;
|
||||
public final class FieldMigratedMappingConfiguration extends MappingConfiguration {
|
||||
private List<Map.Entry<FieldMember, String>> migratedFields = new ArrayList<>();
|
||||
public Path migratedFieldsCache;
|
||||
public Path rawTinyMappings;
|
||||
public Path rawTinyMappingsWithSrg;
|
||||
private Path rawTinyMappings;
|
||||
private Path rawTinyMappingsWithSrg;
|
||||
private Path rawTinyMappingsWithMojang;
|
||||
|
||||
public FieldMigratedMappingConfiguration(String mappingsIdentifier, Path mappingsWorkingDir) {
|
||||
super(mappingsIdentifier, mappingsWorkingDir);
|
||||
@@ -98,7 +99,10 @@ public final class FieldMigratedMappingConfiguration extends MappingConfiguratio
|
||||
}
|
||||
|
||||
public static String createForgeMappingsIdentifier(LoomGradleExtension extension, String mappingsName, String version, String classifier, String minecraftVersion) {
|
||||
return FieldMigratedMappingConfiguration.createMappingsIdentifier(mappingsName, version, classifier, minecraftVersion) + "-forge-" + extension.getForgeProvider().getVersion().getCombined();
|
||||
final String base = FieldMigratedMappingConfiguration.createMappingsIdentifier(mappingsName, version, classifier, minecraftVersion);
|
||||
final String platform = extension.getPlatform().get().id();
|
||||
final String forgeVersion = extension.getForgeProvider().getVersion().getCombined();
|
||||
return base + "-" + platform + "-" + forgeVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -107,23 +111,31 @@ public final class FieldMigratedMappingConfiguration extends MappingConfiguratio
|
||||
LoomGradleExtension extension = LoomGradleExtension.get(project);
|
||||
this.rawTinyMappings = tinyMappings;
|
||||
this.rawTinyMappingsWithSrg = tinyMappingsWithSrg;
|
||||
this.rawTinyMappingsWithMojang = tinyMappingsWithMojang;
|
||||
|
||||
tinyMappings = mappingsWorkingDir().resolve("mappings-field-migrated.tiny");
|
||||
tinyMappingsWithSrg = mappingsWorkingDir().resolve("mappings-srg-field-migrated.tiny");
|
||||
tinyMappingsWithMojang = mappingsWorkingDir().resolve("mappings-mojang-field-migrated.tiny");
|
||||
|
||||
try {
|
||||
updateFieldMigration(project);
|
||||
updateFieldMigration(project, extension.isNeoForge(), extension.shouldGenerateSrgTiny());
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
|
||||
project.getLogger().info(":migrated srg fields in " + stopwatch.stop());
|
||||
project.getLogger().info(":migrated {} fields in " + stopwatch.stop(), extension.getPlatform().get().id());
|
||||
}
|
||||
|
||||
public void updateFieldMigration(Project project) throws IOException {
|
||||
public void updateFieldMigration(Project project, boolean hasMojang, boolean hasSrg) throws IOException {
|
||||
if (!Files.exists(migratedFieldsCache)) {
|
||||
migratedFields.clear();
|
||||
migratedFields.addAll(generateNewFieldMigration(project, MinecraftPatchedProvider.get(project).getMinecraftPatchedSrgJar(), MappingsNamespace.SRG.toString(), rawTinyMappingsWithSrg).entrySet());
|
||||
|
||||
if (hasSrg) {
|
||||
migratedFields.addAll(generateNewFieldMigration(project, MinecraftPatchedProvider.get(project).getMinecraftPatchedIntermediateJar(), MappingsNamespace.SRG.toString(), rawTinyMappingsWithSrg).entrySet());
|
||||
} else if (hasMojang) {
|
||||
migratedFields.addAll(generateNewFieldMigration(project, MinecraftPatchedProvider.get(project).getMinecraftPatchedIntermediateJar(), MappingsNamespace.MOJANG.toString(), rawTinyMappingsWithMojang).entrySet());
|
||||
}
|
||||
|
||||
Map<String, String> map = new HashMap<>();
|
||||
migratedFields.forEach(entry -> {
|
||||
map.put(entry.getKey().owner + "#" + entry.getKey().field, entry.getValue());
|
||||
@@ -131,9 +143,10 @@ public final class FieldMigratedMappingConfiguration extends MappingConfiguratio
|
||||
Files.writeString(migratedFieldsCache, new Gson().toJson(map));
|
||||
Files.deleteIfExists(tinyMappings);
|
||||
Files.deleteIfExists(tinyMappingsWithSrg);
|
||||
Files.deleteIfExists(tinyMappingsWithMojang);
|
||||
}
|
||||
|
||||
if (Files.notExists(tinyMappings) || Files.notExists(tinyMappingsWithSrg)) {
|
||||
if (Files.notExists(tinyMappings) || (hasSrg && Files.notExists(tinyMappingsWithSrg)) || (hasMojang && Files.notExists(tinyMappingsWithMojang))) {
|
||||
Table<String, String, String> fieldDescriptorMap = HashBasedTable.create();
|
||||
|
||||
for (Map.Entry<FieldMember, String> entry : migratedFields) {
|
||||
@@ -141,7 +154,12 @@ public final class FieldMigratedMappingConfiguration extends MappingConfiguratio
|
||||
}
|
||||
|
||||
injectMigration(project, fieldDescriptorMap, rawTinyMappings, tinyMappings);
|
||||
injectMigration(project, fieldDescriptorMap, rawTinyMappingsWithSrg, tinyMappingsWithSrg);
|
||||
|
||||
if (hasSrg) {
|
||||
injectMigration(project, fieldDescriptorMap, rawTinyMappingsWithSrg, tinyMappingsWithSrg);
|
||||
} else if (hasMojang) {
|
||||
injectMigration(project, fieldDescriptorMap, rawTinyMappingsWithMojang, tinyMappingsWithMojang);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,6 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.hash.Hashing;
|
||||
import com.google.gson.JsonElement;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.Dependency;
|
||||
import org.gradle.api.artifacts.ModuleDependency;
|
||||
@@ -41,16 +40,18 @@ import org.gradle.api.artifacts.ResolvedArtifact;
|
||||
import org.gradle.api.artifacts.ResolvedConfiguration;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingContext;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.configuration.mods.ModConfigurationRemapper;
|
||||
import net.fabricmc.loom.configuration.mods.dependency.LocalMavenHelper;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.GradleMappingContext;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingConfiguration;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
import net.fabricmc.loom.util.ExceptionUtil;
|
||||
import net.fabricmc.loom.util.FileSystemUtil;
|
||||
import net.fabricmc.loom.util.PropertyUtil;
|
||||
import net.fabricmc.loom.util.srg.RemapObjectHolderVisitor;
|
||||
import net.fabricmc.loom.util.srg.SrgMerger;
|
||||
import net.fabricmc.loom.util.srg.ForgeMappingsMerger;
|
||||
import net.fabricmc.mappingio.tree.MemoryMappingTree;
|
||||
|
||||
public class ForgeLibrariesProvider {
|
||||
@@ -64,21 +65,31 @@ public class ForgeLibrariesProvider {
|
||||
final List<Dependency> dependencies = new ArrayList<>();
|
||||
|
||||
// Collect all dependencies with possible relocations, such as Mixin.
|
||||
for (JsonElement lib : extension.getForgeUserdevProvider().getJson().get("libraries").getAsJsonArray()) {
|
||||
for (String lib : extension.getForgeUserdevProvider().getConfig().libraries()) {
|
||||
String dep = null;
|
||||
|
||||
if (lib.getAsString().startsWith("org.spongepowered:mixin:")) {
|
||||
if (PropertyUtil.getAndFinalize(extension.getForge().getUseCustomMixin())) {
|
||||
if (lib.getAsString().contains("0.8.2")) {
|
||||
if (lib.startsWith("org.spongepowered:mixin:")) {
|
||||
// Don't apply custom mixin on NeoForge.
|
||||
if (extension.isForge() && PropertyUtil.getAndFinalize(extension.getForge().getUseCustomMixin())) {
|
||||
if (lib.contains("0.8.2")) {
|
||||
dep = "net.fabricmc:sponge-mixin:0.8.2+build.24";
|
||||
} else {
|
||||
dep = "dev.architectury:mixin-patched" + lib.getAsString().substring(lib.getAsString().lastIndexOf(":")) + ".+";
|
||||
String version = lib.substring(lib.lastIndexOf(":"));
|
||||
// Used for the file extension, for example @jar
|
||||
int atIndex = version.indexOf('@');
|
||||
|
||||
if (atIndex >= 0) {
|
||||
// Strip the file extension away
|
||||
version = version.substring(0, atIndex);
|
||||
}
|
||||
|
||||
dep = "dev.architectury:mixin-patched" + version + ".+";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dep == null) {
|
||||
dep = lib.getAsString();
|
||||
dep = lib;
|
||||
}
|
||||
|
||||
dependencies.add(project.getDependencies().create(dep));
|
||||
@@ -158,6 +169,10 @@ public class ForgeLibrariesProvider {
|
||||
if (Files.exists(fs.get().getPath("net/minecraftforge/fml/common/asm/ObjectHolderDefinalize.class"))) {
|
||||
remapObjectHolder(project, outputJar, mappingConfiguration);
|
||||
}
|
||||
|
||||
if (Files.exists(fs.getPath("net/neoforged/fml/common/asm/ObjectHolderDefinalize.class"))) {
|
||||
remapNeoForgeObjectHolder(project, outputJar, mappingConfiguration);
|
||||
}
|
||||
}
|
||||
|
||||
// Copy sources when not running under CI.
|
||||
@@ -178,8 +193,8 @@ public class ForgeLibrariesProvider {
|
||||
// Merge SRG mappings. The real SRG mapping file hasn't been created yet since the usual SRG merging
|
||||
// process occurs after all Forge libraries have been provided.
|
||||
// Forge libs are needed for MC, which is needed for the mappings.
|
||||
final SrgMerger.ExtraMappings extraMappings = SrgMerger.ExtraMappings.ofMojmapTsrg(MappingConfiguration.getMojmapSrgFileIfPossible(project));
|
||||
final MemoryMappingTree mappings = SrgMerger.mergeSrg(MappingConfiguration.getRawSrgFile(project), mappingConfiguration.tinyMappings, extraMappings, true);
|
||||
final ForgeMappingsMerger.ExtraMappings extraMappings = ForgeMappingsMerger.ExtraMappings.ofMojmapTsrg(MappingConfiguration.getMojmapSrgFileIfPossible(project));
|
||||
final MemoryMappingTree mappings = ForgeMappingsMerger.mergeSrg(MappingConfiguration.getRawSrgFile(project), mappingConfiguration.tinyMappings, extraMappings, true);
|
||||
|
||||
// Remap the object holders.
|
||||
RemapObjectHolderVisitor.remapObjectHolder(
|
||||
@@ -191,6 +206,24 @@ public class ForgeLibrariesProvider {
|
||||
}
|
||||
}
|
||||
|
||||
private static void remapNeoForgeObjectHolder(Project project, Path outputJar, MappingConfiguration mappingConfiguration) throws IOException {
|
||||
try {
|
||||
// Merge Mojang mappings. The real Mojang mapping file hasn't been created yet since the usual Mojang merging
|
||||
// process occurs after all Forge libraries have been provided.
|
||||
// Forge libs are needed for MC, which is needed for the mappings.
|
||||
final MappingContext context = new GradleMappingContext(project, "tmp-neoforge-libs");
|
||||
final MemoryMappingTree mappings = ForgeMappingsMerger.mergeMojang(context, mappingConfiguration.tinyMappings, null, true);
|
||||
|
||||
// Remap the object holders.
|
||||
RemapObjectHolderVisitor.remapObjectHolder(
|
||||
outputJar, "net.neoforged.fml.common.asm.ObjectHolderDefinalize", mappings,
|
||||
MappingsNamespace.MOJANG.toString(), MappingsNamespace.NAMED.toString()
|
||||
);
|
||||
} catch (IOException e) {
|
||||
throw new IOException("Could not remap object holders in " + outputJar, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconstructs the dependency notation of a resolved artifact.
|
||||
* @param artifact the artifact
|
||||
|
||||
@@ -32,14 +32,16 @@ import org.gradle.api.Project;
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.configuration.DependencyInfo;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
import net.fabricmc.loom.util.ModPlatform;
|
||||
|
||||
public class ForgeProvider extends DependencyProvider {
|
||||
private final ModPlatform platform;
|
||||
private ForgeVersion version = new ForgeVersion(null);
|
||||
private File globalCache;
|
||||
private File projectCache;
|
||||
|
||||
public ForgeProvider(Project project) {
|
||||
super(project);
|
||||
platform = getExtension().getPlatform().get();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -55,25 +57,16 @@ public class ForgeProvider extends DependencyProvider {
|
||||
|
||||
public File getGlobalCache() {
|
||||
if (globalCache == null) {
|
||||
globalCache = getMinecraftProvider().dir("forge/" + version.getCombined());
|
||||
globalCache = getMinecraftProvider().dir(platform.id() + "/" + version.getCombined());
|
||||
globalCache.mkdirs();
|
||||
}
|
||||
|
||||
return globalCache;
|
||||
}
|
||||
|
||||
public File getProjectCache() {
|
||||
if (projectCache == null) {
|
||||
projectCache = new File(getDirectories().getRootProjectPersistentCache(), getMinecraftProvider().minecraftVersion() + "/forge/" + getExtension().getForgeProvider().getVersion().getCombined() + "/project-" + getProject().getPath().replace(':', '@'));
|
||||
projectCache.mkdirs();
|
||||
}
|
||||
|
||||
return projectCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTargetConfig() {
|
||||
return Constants.Configurations.FORGE;
|
||||
return platform == ModPlatform.NEOFORGE ? Constants.Configurations.NEOFORGE : Constants.Configurations.FORGE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -83,9 +76,10 @@ public class ForgeProvider extends DependencyProvider {
|
||||
*/
|
||||
public static Path getForgeCache(Project project) {
|
||||
final LoomGradleExtension extension = LoomGradleExtension.get(project);
|
||||
final ModPlatform platform = extension.getPlatform().get();
|
||||
final String version = extension.getForgeProvider().getVersion().getCombined();
|
||||
return LoomGradleExtension.get(project).getMinecraftProvider()
|
||||
.dir("forge/" + version).toPath();
|
||||
.dir(platform.id() + "/" + version).toPath();
|
||||
}
|
||||
|
||||
public static final class ForgeVersion {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2022 FabricMC
|
||||
* Copyright (c) 2022-2023 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
|
||||
@@ -24,18 +24,17 @@
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.forge;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import org.gradle.api.Named;
|
||||
|
||||
import net.fabricmc.loom.configuration.ide.RunConfigSettings;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
import net.fabricmc.loom.util.Pair;
|
||||
import net.fabricmc.loom.util.function.CollectionUtil;
|
||||
|
||||
public record ForgeRunTemplate(
|
||||
@@ -46,6 +45,51 @@ public record ForgeRunTemplate(
|
||||
Map<String, ConfigValue> env,
|
||||
Map<String, ConfigValue> props
|
||||
) implements Named {
|
||||
public static final Codec<ForgeRunTemplate> CODEC = RecordCodecBuilder.create(instance -> instance.group(
|
||||
Codec.STRING.optionalFieldOf("name", "") // note: empty is used since DFU crashes with null
|
||||
.forGetter(ForgeRunTemplate::name),
|
||||
Codec.STRING.fieldOf("main")
|
||||
.forGetter(ForgeRunTemplate::main),
|
||||
ConfigValue.CODEC.listOf().optionalFieldOf("args", List.of())
|
||||
.forGetter(ForgeRunTemplate::args),
|
||||
ConfigValue.CODEC.listOf().optionalFieldOf("jvmArgs", List.of())
|
||||
.forGetter(ForgeRunTemplate::jvmArgs),
|
||||
Codec.unboundedMap(Codec.STRING, ConfigValue.CODEC).optionalFieldOf("env", Map.of())
|
||||
.forGetter(ForgeRunTemplate::env),
|
||||
Codec.unboundedMap(Codec.STRING, ConfigValue.CODEC).optionalFieldOf("props", Map.of())
|
||||
.forGetter(ForgeRunTemplate::props)
|
||||
).apply(instance, ForgeRunTemplate::new));
|
||||
|
||||
public static final Codec<Map<String, ForgeRunTemplate>> MAP_CODEC = Codec.unboundedMap(Codec.STRING, CODEC)
|
||||
.xmap(
|
||||
map -> {
|
||||
final Map<String, ForgeRunTemplate> newMap = new HashMap<>(map);
|
||||
|
||||
// Iterate through all templates and fill in empty names.
|
||||
// The NeoForge format doesn't include the name property, so we'll use the map keys
|
||||
// as a replacement.
|
||||
for (Map.Entry<String, ForgeRunTemplate> entry : newMap.entrySet()) {
|
||||
final ForgeRunTemplate template = entry.getValue();
|
||||
|
||||
if (template.name.isEmpty()) {
|
||||
final ForgeRunTemplate completed = new ForgeRunTemplate(
|
||||
entry.getKey(),
|
||||
template.main,
|
||||
template.args,
|
||||
template.jvmArgs,
|
||||
template.env,
|
||||
template.props
|
||||
);
|
||||
|
||||
entry.setValue(completed);
|
||||
}
|
||||
}
|
||||
|
||||
return newMap;
|
||||
},
|
||||
Function.identity()
|
||||
);
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
@@ -66,29 +110,4 @@ public record ForgeRunTemplate(
|
||||
// Add MOD_CLASSES, this is something that ForgeGradle does
|
||||
settings.getEnvironmentVariables().computeIfAbsent("MOD_CLASSES", $ -> ConfigValue.of("{source_roots}").resolve(configValueResolver));
|
||||
}
|
||||
|
||||
public static ForgeRunTemplate fromJson(JsonObject json) {
|
||||
if (json.has("parents") && !json.getAsJsonArray("parents").isEmpty()) {
|
||||
throw new IllegalArgumentException("Non-empty parents for run config template not supported!");
|
||||
}
|
||||
|
||||
String name = json.getAsJsonPrimitive("name").getAsString();
|
||||
String main = json.getAsJsonPrimitive("main").getAsString();
|
||||
List<ConfigValue> args = json.has("args") ? fromJson(json.getAsJsonArray("args")) : List.of();
|
||||
List<ConfigValue> jvmArgs = json.has("jvmArgs") ? fromJson(json.getAsJsonArray("jvmArgs")) : List.of();
|
||||
Map<String, ConfigValue> env = json.has("env") ? fromJson(json.getAsJsonObject("env"), ConfigValue::of) : Map.of();
|
||||
Map<String, ConfigValue> props = json.has("props") ? fromJson(json.getAsJsonObject("props"), ConfigValue::of) : Map.of();
|
||||
return new ForgeRunTemplate(name, main, args, jvmArgs, env, props);
|
||||
}
|
||||
|
||||
private static List<ConfigValue> fromJson(JsonArray json) {
|
||||
return CollectionUtil.map(json, child -> ConfigValue.of(child.getAsJsonPrimitive().getAsString()));
|
||||
}
|
||||
|
||||
private static <R> Map<String, R> fromJson(JsonObject json, Function<String, R> converter) {
|
||||
return json.entrySet().stream().map(entry -> {
|
||||
String value = entry.getValue().getAsJsonPrimitive().getAsString();
|
||||
return new Pair<>(entry.getKey(), converter.apply(value));
|
||||
}).collect(Collectors.toMap(Pair::left, Pair::right));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
@@ -39,6 +38,7 @@ import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.MultimapBuilder;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import dev.architectury.loom.forge.UserdevConfig;
|
||||
import org.gradle.api.NamedDomainObjectContainer;
|
||||
import org.gradle.api.NamedDomainObjectSet;
|
||||
import org.gradle.api.Project;
|
||||
@@ -58,19 +58,12 @@ public class ForgeRunsProvider {
|
||||
private final JsonObject json;
|
||||
private final NamedDomainObjectSet<ForgeRunTemplate> templates;
|
||||
|
||||
public ForgeRunsProvider(Project project, JsonObject json) {
|
||||
public ForgeRunsProvider(Project project, JsonObject json, UserdevConfig userdevConfig) {
|
||||
this.project = project;
|
||||
this.extension = LoomGradleExtension.get(project);
|
||||
this.json = json;
|
||||
this.templates = project.getObjects().namedDomainObjectSet(ForgeRunTemplate.class);
|
||||
readTemplates();
|
||||
}
|
||||
|
||||
private void readTemplates() {
|
||||
for (Map.Entry<String, JsonElement> entry : json.getAsJsonObject("runs").entrySet()) {
|
||||
ForgeRunTemplate template = ForgeRunTemplate.fromJson(entry.getValue().getAsJsonObject());
|
||||
templates.add(template);
|
||||
}
|
||||
this.templates.addAll(userdevConfig.runs().values());
|
||||
}
|
||||
|
||||
public NamedDomainObjectSet<ForgeRunTemplate> getTemplates() {
|
||||
@@ -78,8 +71,8 @@ public class ForgeRunsProvider {
|
||||
}
|
||||
|
||||
public static ForgeRunsProvider create(Project project) {
|
||||
JsonObject json = LoomGradleExtension.get(project).getForgeUserdevProvider().getJson();
|
||||
return new ForgeRunsProvider(project, json);
|
||||
final ForgeUserdevProvider userdevProvider = LoomGradleExtension.get(project).getForgeUserdevProvider();
|
||||
return new ForgeRunsProvider(project, userdevProvider.getJson(), userdevProvider.getConfig());
|
||||
}
|
||||
|
||||
public ConfigValue.Resolver getResolver(@Nullable RunConfigSettings runConfig) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2020-2022 FabricMC
|
||||
* Copyright (c) 2020-2023 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
|
||||
@@ -29,13 +29,13 @@ import java.io.Reader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.mojang.serialization.JsonOps;
|
||||
import dev.architectury.loom.forge.UserdevConfig;
|
||||
import org.gradle.api.Project;
|
||||
|
||||
import net.fabricmc.loom.LoomGradlePlugin;
|
||||
import net.fabricmc.loom.configuration.DependencyInfo;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
import net.fabricmc.loom.util.ZipUtils;
|
||||
@@ -43,8 +43,8 @@ import net.fabricmc.loom.util.ZipUtils;
|
||||
public class ForgeUserdevProvider extends DependencyProvider {
|
||||
private File userdevJar;
|
||||
private JsonObject json;
|
||||
private UserdevConfig config;
|
||||
Path joinedPatches;
|
||||
BinaryPatcherConfig binaryPatcherConfig;
|
||||
|
||||
public ForgeUserdevProvider(Project project) {
|
||||
super(project);
|
||||
@@ -64,17 +64,21 @@ public class ForgeUserdevProvider extends DependencyProvider {
|
||||
|
||||
try (Reader reader = Files.newBufferedReader(configJson)) {
|
||||
json = new Gson().fromJson(reader, JsonObject.class);
|
||||
config = UserdevConfig.CODEC.parse(JsonOps.INSTANCE, json)
|
||||
.getOrThrow(false, msg -> getProject().getLogger().error("Couldn't read userdev config, {}", msg));
|
||||
}
|
||||
|
||||
addDependency(json.get("mcp").getAsString(), Constants.Configurations.MCP_CONFIG);
|
||||
addDependency(json.get("mcp").getAsString(), Constants.Configurations.SRG);
|
||||
addDependency(json.get("universal").getAsString(), Constants.Configurations.FORGE_UNIVERSAL);
|
||||
addDependency(config.mcp(), Constants.Configurations.MCP_CONFIG);
|
||||
|
||||
if (!getExtension().isNeoForge()) {
|
||||
addDependency(config.mcp(), Constants.Configurations.SRG);
|
||||
}
|
||||
|
||||
addDependency(config.universal(), Constants.Configurations.FORGE_UNIVERSAL);
|
||||
|
||||
if (Files.notExists(joinedPatches)) {
|
||||
Files.write(joinedPatches, ZipUtils.unpack(userdevJar.toPath(), json.get("binpatches").getAsString()));
|
||||
Files.write(joinedPatches, ZipUtils.unpack(userdevJar.toPath(), config.binpatches()));
|
||||
}
|
||||
|
||||
binaryPatcherConfig = BinaryPatcherConfig.fromJson(json.getAsJsonObject("binpatcher"));
|
||||
}
|
||||
|
||||
public File getUserdevJar() {
|
||||
@@ -90,11 +94,7 @@ public class ForgeUserdevProvider extends DependencyProvider {
|
||||
return json;
|
||||
}
|
||||
|
||||
public record BinaryPatcherConfig(String dependency, List<String> args) {
|
||||
public static BinaryPatcherConfig fromJson(JsonObject json) {
|
||||
String dependency = json.get("version").getAsString();
|
||||
List<String> args = List.of(LoomGradlePlugin.GSON.fromJson(json.get("args"), String[].class));
|
||||
return new BinaryPatcherConfig(dependency, args);
|
||||
}
|
||||
public UserdevConfig getConfig() {
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,6 +52,8 @@ import java.util.stream.Stream;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Stopwatch;
|
||||
import de.oceanlabs.mcp.mcinjector.adaptors.ParameterAnnotationFixer;
|
||||
import dev.architectury.loom.forge.UserdevConfig;
|
||||
import dev.architectury.loom.util.MappingOption;
|
||||
import dev.architectury.loom.util.TempFiles;
|
||||
import dev.architectury.tinyremapper.InputTag;
|
||||
import dev.architectury.tinyremapper.NonClassCopyMode;
|
||||
@@ -69,6 +71,7 @@ import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.build.IntermediaryNamespaces;
|
||||
import net.fabricmc.loom.configuration.accesstransformer.AccessTransformerJarProcessor;
|
||||
import net.fabricmc.loom.configuration.providers.forge.mcpconfig.McpConfigProvider;
|
||||
import net.fabricmc.loom.configuration.providers.forge.mcpconfig.McpExecutor;
|
||||
@@ -86,12 +89,14 @@ import net.fabricmc.loom.util.ZipUtils;
|
||||
import net.fabricmc.loom.util.function.FsPathConsumer;
|
||||
import net.fabricmc.loom.util.service.ScopedSharedServiceManager;
|
||||
import net.fabricmc.loom.util.service.SharedServiceManager;
|
||||
import net.fabricmc.loom.util.srg.CoreModClassRemapper;
|
||||
import net.fabricmc.loom.util.srg.InnerClassRemapper;
|
||||
import net.fabricmc.mappingio.tree.MappingTree;
|
||||
import net.fabricmc.mappingio.tree.MemoryMappingTree;
|
||||
|
||||
public class MinecraftPatchedProvider {
|
||||
private static final String LOOM_PATCH_VERSION_KEY = "Loom-Patch-Version";
|
||||
private static final String CURRENT_LOOM_PATCH_VERSION = "8";
|
||||
private static final String CURRENT_LOOM_PATCH_VERSION = "9";
|
||||
private static final String NAME_MAPPING_SERVICE_PATH = "/inject/META-INF/services/cpw.mods.modlauncher.api.INameMappingService";
|
||||
|
||||
private final Project project;
|
||||
@@ -99,12 +104,12 @@ public class MinecraftPatchedProvider {
|
||||
private final MinecraftProvider minecraftProvider;
|
||||
private final Type type;
|
||||
|
||||
// Step 1: Remap Minecraft to SRG, merge if needed
|
||||
private Path minecraftSrgJar;
|
||||
// Step 1: Remap Minecraft to intermediate mappings, merge if needed
|
||||
private Path minecraftIntermediateJar;
|
||||
// Step 2: Binary Patch
|
||||
private Path minecraftPatchedSrgJar;
|
||||
private Path minecraftPatchedIntermediateJar;
|
||||
// Step 3: Access Transform
|
||||
private Path minecraftPatchedSrgAtJar;
|
||||
private Path minecraftPatchedIntermediateAtJar;
|
||||
// Step 4: Remap Patched AT & Forge to official
|
||||
private Path minecraftPatchedJar;
|
||||
private Path minecraftClientExtra;
|
||||
@@ -135,13 +140,16 @@ public class MinecraftPatchedProvider {
|
||||
private void initPatchedFiles() {
|
||||
String forgeVersion = getExtension().getForgeProvider().getVersion().getCombined();
|
||||
Path forgeWorkingDir = ForgeProvider.getForgeCache(project);
|
||||
String patchId = "forge-" + forgeVersion + "-";
|
||||
// Note: strings used instead of platform id since FML requires one of these exact strings
|
||||
// depending on the loader to recognise Minecraft.
|
||||
String patchId = (getExtension().isNeoForge() ? "neoforge" : "forge") + "-" + forgeVersion + "-";
|
||||
|
||||
minecraftProvider.setJarPrefix(patchId);
|
||||
|
||||
minecraftSrgJar = forgeWorkingDir.resolve("minecraft-" + type.id + "-srg.jar");
|
||||
minecraftPatchedSrgJar = forgeWorkingDir.resolve("minecraft-" + type.id + "-srg-patched.jar");
|
||||
minecraftPatchedSrgAtJar = forgeWorkingDir.resolve("minecraft-" + type.id + "-srg-at-patched.jar");
|
||||
final String intermediateId = getExtension().isNeoForge() ? "mojang" : "srg";
|
||||
minecraftIntermediateJar = forgeWorkingDir.resolve("minecraft-" + type.id + "-" + intermediateId + ".jar");
|
||||
minecraftPatchedIntermediateJar = forgeWorkingDir.resolve("minecraft-" + type.id + "-" + intermediateId + "-patched.jar");
|
||||
minecraftPatchedIntermediateAtJar = forgeWorkingDir.resolve("minecraft-" + type.id + "-" + intermediateId + "-at-patched.jar");
|
||||
minecraftPatchedJar = forgeWorkingDir.resolve("minecraft-" + type.id + "-patched.jar");
|
||||
minecraftClientExtra = forgeWorkingDir.resolve("client-extra.jar");
|
||||
}
|
||||
@@ -154,9 +162,9 @@ public class MinecraftPatchedProvider {
|
||||
|
||||
private Path[] getGlobalCaches() {
|
||||
Path[] files = {
|
||||
minecraftSrgJar,
|
||||
minecraftPatchedSrgJar,
|
||||
minecraftPatchedSrgAtJar,
|
||||
minecraftIntermediateJar,
|
||||
minecraftPatchedIntermediateJar,
|
||||
minecraftPatchedIntermediateAtJar,
|
||||
minecraftPatchedJar,
|
||||
minecraftClientExtra,
|
||||
};
|
||||
@@ -177,22 +185,22 @@ public class MinecraftPatchedProvider {
|
||||
|
||||
this.dirty = false;
|
||||
|
||||
if (Files.notExists(minecraftSrgJar)) {
|
||||
if (Files.notExists(minecraftIntermediateJar)) {
|
||||
this.dirty = true;
|
||||
|
||||
try (var tempFiles = new TempFiles()) {
|
||||
McpExecutor executor = createMcpExecutor(tempFiles.directory("loom-mcp"));
|
||||
Path output = executor.enqueue("rename").execute();
|
||||
Files.copy(output, minecraftSrgJar);
|
||||
Files.copy(output, minecraftIntermediateJar);
|
||||
}
|
||||
}
|
||||
|
||||
if (dirty || Files.notExists(minecraftPatchedSrgJar)) {
|
||||
if (dirty || Files.notExists(minecraftPatchedIntermediateJar)) {
|
||||
this.dirty = true;
|
||||
patchJars();
|
||||
}
|
||||
|
||||
if (dirty || Files.notExists(minecraftPatchedSrgAtJar)) {
|
||||
if (dirty || Files.notExists(minecraftPatchedIntermediateAtJar)) {
|
||||
this.dirty = true;
|
||||
accessTransformForge();
|
||||
}
|
||||
@@ -207,7 +215,6 @@ public class MinecraftPatchedProvider {
|
||||
fillClientExtraJar();
|
||||
}
|
||||
|
||||
this.dirty = false;
|
||||
DependencyProvider.addDependency(project, minecraftClientExtra, Constants.Configurations.FORGE_EXTRA);
|
||||
}
|
||||
|
||||
@@ -220,14 +227,16 @@ public class MinecraftPatchedProvider {
|
||||
|
||||
private TinyRemapper buildRemapper(SharedServiceManager serviceManager, Path input) throws IOException {
|
||||
Path[] libraries = TinyRemapperHelper.getMinecraftCompileLibraries(project);
|
||||
TinyMappingsService mappingsService = getExtension().getMappingConfiguration().getMappingsService(serviceManager, true);
|
||||
MemoryMappingTree mappingsWithSrg = mappingsService.getMappingTree();
|
||||
final MappingOption mappingOption = MappingOption.forPlatform(getExtension());
|
||||
TinyMappingsService mappingsService = getExtension().getMappingConfiguration().getMappingsService(serviceManager, mappingOption);
|
||||
final String sourceNamespace = IntermediaryNamespaces.intermediary(project);
|
||||
MemoryMappingTree mappings = mappingsService.getMappingTree();
|
||||
|
||||
TinyRemapper remapper = TinyRemapper.newRemapper()
|
||||
.logger(logger::lifecycle)
|
||||
.logUnknownInvokeDynamic(false)
|
||||
.withMappings(TinyRemapperHelper.create(mappingsWithSrg, "srg", "official", true))
|
||||
.withMappings(InnerClassRemapper.of(InnerClassRemapper.readClassNames(input), mappingsWithSrg, "srg", "official"))
|
||||
.withMappings(TinyRemapperHelper.create(mappings, sourceNamespace, "official", true))
|
||||
.withMappings(InnerClassRemapper.of(InnerClassRemapper.readClassNames(input), mappings, sourceNamespace, "official"))
|
||||
.renameInvalidLocals(true)
|
||||
.rebuildSourceFilenames(true)
|
||||
.build();
|
||||
@@ -359,8 +368,8 @@ public class MinecraftPatchedProvider {
|
||||
}
|
||||
|
||||
private void accessTransformForge() throws IOException {
|
||||
Path input = minecraftPatchedSrgJar;
|
||||
Path target = minecraftPatchedSrgAtJar;
|
||||
Path input = minecraftPatchedIntermediateJar;
|
||||
Path target = minecraftPatchedIntermediateAtJar;
|
||||
accessTransform(project, input, target);
|
||||
}
|
||||
|
||||
@@ -375,7 +384,7 @@ public class MinecraftPatchedProvider {
|
||||
extension.getForgeUserdevProvider().getUserdevJar().toPath(),
|
||||
((ForgeMinecraftProvider) extension.getMinecraftProvider())
|
||||
.getPatchedProvider()
|
||||
.getMinecraftPatchedSrgJar()
|
||||
.getMinecraftPatchedIntermediateJar()
|
||||
);
|
||||
|
||||
Files.deleteIfExists(target);
|
||||
@@ -400,7 +409,7 @@ public class MinecraftPatchedProvider {
|
||||
|
||||
private void remapPatchedJar(SharedServiceManager serviceManager) throws Exception {
|
||||
logger.lifecycle(":remapping minecraft (TinyRemapper, srg -> official)");
|
||||
Path mcInput = minecraftPatchedSrgAtJar;
|
||||
Path mcInput = minecraftPatchedIntermediateAtJar;
|
||||
Path mcOutput = minecraftPatchedJar;
|
||||
Path forgeJar = getForgeJar().toPath();
|
||||
Path forgeUserdevJar = getForgeUserdevJar().toPath();
|
||||
@@ -425,19 +434,27 @@ public class MinecraftPatchedProvider {
|
||||
}
|
||||
|
||||
copyUserdevFiles(forgeUserdevJar, mcOutput);
|
||||
remapCoreMods(mcOutput, serviceManager);
|
||||
applyLoomPatchVersion(mcOutput);
|
||||
}
|
||||
|
||||
private void remapCoreMods(Path patchedJar, SharedServiceManager serviceManager) throws Exception {
|
||||
final MappingOption mappingOption = MappingOption.forPlatform(getExtension());
|
||||
final TinyMappingsService mappingsService = getExtension().getMappingConfiguration().getMappingsService(serviceManager, mappingOption);
|
||||
final MappingTree mappings = mappingsService.getMappingTree();
|
||||
CoreModClassRemapper.remapJar(project, getExtension().getPlatform().get(), patchedJar, mappings);
|
||||
}
|
||||
|
||||
private void patchJars() throws Exception {
|
||||
Stopwatch stopwatch = Stopwatch.createStarted();
|
||||
logger.lifecycle(":patching jars");
|
||||
patchJars(minecraftSrgJar, minecraftPatchedSrgJar, type.patches.apply(getExtension().getPatchProvider(), getExtension().getForgeUserdevProvider()));
|
||||
patchJars(minecraftIntermediateJar, minecraftPatchedIntermediateJar, type.patches.apply(getExtension().getPatchProvider(), getExtension().getForgeUserdevProvider()));
|
||||
|
||||
copyMissingClasses(minecraftSrgJar, minecraftPatchedSrgJar);
|
||||
deleteParameterNames(minecraftPatchedSrgJar);
|
||||
copyMissingClasses(minecraftIntermediateJar, minecraftPatchedIntermediateJar);
|
||||
deleteParameterNames(minecraftPatchedIntermediateJar);
|
||||
|
||||
if (getExtension().isForgeAndNotOfficial()) {
|
||||
fixParameterAnnotation(minecraftPatchedSrgJar);
|
||||
if (getExtension().isForgeLikeAndNotOfficial()) {
|
||||
fixParameterAnnotation(minecraftPatchedIntermediateJar);
|
||||
}
|
||||
|
||||
logger.lifecycle(":patched jars in " + stopwatch.stop());
|
||||
@@ -445,7 +462,7 @@ public class MinecraftPatchedProvider {
|
||||
|
||||
private void patchJars(Path clean, Path output, Path patches) {
|
||||
ForgeToolExecutor.exec(project, spec -> {
|
||||
ForgeUserdevProvider.BinaryPatcherConfig config = getExtension().getForgeUserdevProvider().binaryPatcherConfig;
|
||||
UserdevConfig.BinaryPatcherConfig config = getExtension().getForgeUserdevProvider().getConfig().binpatcher();
|
||||
spec.classpath(DependencyDownloader.download(project, config.dependency()));
|
||||
spec.getMainClass().set("net.minecraftforge.binarypatcher.ConsoleTool");
|
||||
|
||||
@@ -565,18 +582,25 @@ public class MinecraftPatchedProvider {
|
||||
return new McpExecutor(project, minecraftProvider, cache, provider, type.mcpId);
|
||||
}
|
||||
|
||||
public Path getMinecraftSrgJar() {
|
||||
return minecraftSrgJar;
|
||||
public Path getMinecraftIntermediateJar() {
|
||||
return minecraftIntermediateJar;
|
||||
}
|
||||
|
||||
public Path getMinecraftPatchedSrgJar() {
|
||||
return minecraftPatchedSrgJar;
|
||||
public Path getMinecraftPatchedIntermediateJar() {
|
||||
return minecraftPatchedIntermediateJar;
|
||||
}
|
||||
|
||||
public Path getMinecraftPatchedJar() {
|
||||
return minecraftPatchedJar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the provider's state is dirty (regenerating jars).
|
||||
*/
|
||||
public boolean isDirty() {
|
||||
return dirty;
|
||||
}
|
||||
|
||||
public enum Type {
|
||||
CLIENT_ONLY("client", "client", (patch, userdev) -> patch.clientPatches),
|
||||
SERVER_ONLY("server", "server", (patch, userdev) -> patch.serverPatches),
|
||||
|
||||
@@ -45,6 +45,7 @@ import org.gradle.api.Project;
|
||||
import org.gradle.api.logging.LogLevel;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingContext;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.configuration.DependencyInfo;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.GradleMappingContext;
|
||||
@@ -216,7 +217,8 @@ public class SrgProvider extends DependencyProvider {
|
||||
|
||||
if (Files.notExists(mojmapTsrg) || extension.refreshDeps()) {
|
||||
try (BufferedWriter writer = Files.newBufferedWriter(mojmapTsrg, StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) {
|
||||
Tsrg2Utils.writeTsrg(visitor -> visitMojmap(visitor, project),
|
||||
GradleMappingContext context = new GradleMappingContext(project, "tmp-mojmap");
|
||||
Tsrg2Utils.writeTsrg(visitor -> visitMojangMappings(visitor, context),
|
||||
MappingsNamespace.NAMED.toString(), false, writer);
|
||||
}
|
||||
}
|
||||
@@ -233,8 +235,9 @@ public class SrgProvider extends DependencyProvider {
|
||||
|
||||
if (Files.notExists(mojmapTsrg2) || extension.refreshDeps()) {
|
||||
try (BufferedWriter writer = Files.newBufferedWriter(mojmapTsrg2, StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) {
|
||||
GradleMappingContext context = new GradleMappingContext(project, "tmp-mojmap");
|
||||
MemoryMappingTree tree = new MemoryMappingTree();
|
||||
visitMojmap(tree, project);
|
||||
visitMojangMappings(tree, context);
|
||||
writer.write(Tsrg2Writer.serialize(tree));
|
||||
}
|
||||
}
|
||||
@@ -243,21 +246,12 @@ public class SrgProvider extends DependencyProvider {
|
||||
return mojmapTsrg2;
|
||||
}
|
||||
|
||||
private static void visitMojmap(MappingVisitor visitor, Project project) {
|
||||
GradleMappingContext context = new GradleMappingContext(project, "tmp-mojmap");
|
||||
|
||||
public static void visitMojangMappings(MappingVisitor visitor, MappingContext context) {
|
||||
try {
|
||||
FileUtils.deleteDirectory(context.workingDirectory("/").toFile());
|
||||
MojangMappingLayer layer = new MojangMappingsSpec(() -> true, true).createLayer(context);
|
||||
layer.visit(visitor);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
} finally {
|
||||
try {
|
||||
FileUtils.deleteDirectory(context.workingDirectory("/").toFile());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2022 FabricMC
|
||||
* Copyright (c) 2022-2023 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
|
||||
@@ -24,12 +24,17 @@
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.forge.mcpconfig;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.fabricmc.loom.configuration.providers.forge.ConfigValue;
|
||||
import net.fabricmc.loom.configuration.providers.forge.mcpconfig.steplogic.StepLogic;
|
||||
import net.fabricmc.loom.util.function.CollectionUtil;
|
||||
|
||||
/**
|
||||
@@ -38,15 +43,23 @@ import net.fabricmc.loom.util.function.CollectionUtil;
|
||||
* @param version the Gradle-style dependency string of the program
|
||||
* @param args the command-line arguments
|
||||
* @param jvmArgs the JVM arguments
|
||||
* @param repo the Maven repository to download the dependency from
|
||||
* @param repo the Maven repository to download the dependency from, or {@code null} if not specified
|
||||
*/
|
||||
public record McpConfigFunction(String version, List<ConfigValue> args, List<ConfigValue> jvmArgs, String repo) {
|
||||
public record McpConfigFunction(String version, List<ConfigValue> args, List<ConfigValue> jvmArgs, @Nullable String repo) {
|
||||
private static final String VERSION_KEY = "version";
|
||||
private static final String ARGS_KEY = "args";
|
||||
private static final String JVM_ARGS_KEY = "jvmargs";
|
||||
private static final String REPO_KEY = "repo";
|
||||
|
||||
public String getDownloadUrl() {
|
||||
public Path download(StepLogic.ExecutionContext executionContext) throws IOException {
|
||||
if (repo != null) {
|
||||
return executionContext.downloadFile(getDownloadUrl());
|
||||
} else {
|
||||
return executionContext.downloadDependency(version);
|
||||
}
|
||||
}
|
||||
|
||||
private String getDownloadUrl() {
|
||||
String[] parts = version.split(":");
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(repo);
|
||||
@@ -72,7 +85,8 @@ public record McpConfigFunction(String version, List<ConfigValue> args, List<Con
|
||||
String version = json.get(VERSION_KEY).getAsString();
|
||||
List<ConfigValue> args = json.has(ARGS_KEY) ? configValuesFromJson(json.getAsJsonArray(ARGS_KEY)) : List.of();
|
||||
List<ConfigValue> jvmArgs = json.has(JVM_ARGS_KEY) ? configValuesFromJson(json.getAsJsonArray(JVM_ARGS_KEY)) : List.of();
|
||||
String repo = json.get(REPO_KEY).getAsString();
|
||||
JsonElement repoJson = json.get(REPO_KEY);
|
||||
@Nullable String repo = repoJson.isJsonPrimitive() ? repoJson.getAsString() : null;
|
||||
return new McpConfigFunction(version, args, jvmArgs, repo);
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,8 @@ public class McpConfigProvider extends DependencyProvider {
|
||||
}
|
||||
|
||||
private void init(String version) {
|
||||
Path dir = getMinecraftProvider().dir("mcp/" + version).toPath();
|
||||
String mcpName = getExtension().isNeoForge() ? "neoform" : "mcp";
|
||||
Path dir = getMinecraftProvider().dir(mcpName + "/" + version).toPath();
|
||||
mcp = dir.resolve("mcp.zip");
|
||||
unpacked = dir.resolve("unpacked");
|
||||
configJson = unpacked.resolve("config.json");
|
||||
|
||||
@@ -46,6 +46,8 @@ import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.artifacts.Dependency;
|
||||
import org.gradle.api.logging.LogLevel;
|
||||
import org.gradle.api.logging.Logger;
|
||||
import org.gradle.process.JavaExecSpec;
|
||||
@@ -298,12 +300,20 @@ public final class McpExecutor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path download(String url) throws IOException {
|
||||
public Path downloadFile(String url) throws IOException {
|
||||
Path path = getDownloadCache().resolve(Hashing.sha256().hashString(url, StandardCharsets.UTF_8).toString().substring(0, 24));
|
||||
redirectAwareDownload(url, path);
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path downloadDependency(String notation) {
|
||||
final Dependency dependency = project.getDependencies().create(notation);
|
||||
final Configuration configuration = project.getConfigurations().detachedConfiguration(dependency);
|
||||
configuration.setTransitive(false);
|
||||
return configuration.getSingleFile().toPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DownloadBuilder downloadBuilder(String url) {
|
||||
return LoomGradleExtension.get(project).download(url);
|
||||
|
||||
@@ -47,7 +47,7 @@ public final class FunctionLogic implements StepLogic {
|
||||
// The other tools seem to work with the name containing .jar anyway.
|
||||
// Technically, FG supports an "outputExtension" config value for steps, but it's not used in practice.
|
||||
context.setOutput("output.jar");
|
||||
Path jar = context.download(function.getDownloadUrl());
|
||||
Path jar = function.download(context);
|
||||
String mainClass;
|
||||
|
||||
try (JarFile jarFile = new JarFile(jar.toFile())) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2022 FabricMC
|
||||
* Copyright (c) 2022-2023 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
|
||||
@@ -61,7 +61,8 @@ public interface StepLogic {
|
||||
/** Mappings extracted from {@code data.mappings} in the MCPConfig JSON. */
|
||||
Path mappings();
|
||||
String resolve(ConfigValue value);
|
||||
Path download(String url) throws IOException;
|
||||
Path downloadFile(String url) throws IOException;
|
||||
Path downloadDependency(String notation);
|
||||
DownloadBuilder downloadBuilder(String url);
|
||||
void javaexec(Action<? super JavaExecSpec> configurator);
|
||||
Set<File> getMinecraftLibraries();
|
||||
|
||||
@@ -38,14 +38,14 @@ public interface ForgeMinecraftProvider {
|
||||
MinecraftPatchedProvider getPatchedProvider();
|
||||
|
||||
static MergedMinecraftProvider createMerged(ConfigContext context) {
|
||||
return LoomGradleExtension.get(context.project()).isForge() ? new MergedForgeMinecraftProvider(context) : new MergedMinecraftProvider(context);
|
||||
return LoomGradleExtension.get(context.project()).isForgeLike() ? new MergedForgeMinecraftProvider(context) : new MergedMinecraftProvider(context);
|
||||
}
|
||||
|
||||
static SingleJarMinecraftProvider createServerOnly(ConfigContext context) {
|
||||
return LoomGradleExtension.get(context.project()).isForge() ? SingleJarForgeMinecraftProvider.server(context) : SingleJarMinecraftProvider.server(context);
|
||||
return LoomGradleExtension.get(context.project()).isForgeLike() ? SingleJarForgeMinecraftProvider.server(context) : SingleJarMinecraftProvider.server(context);
|
||||
}
|
||||
|
||||
static SingleJarMinecraftProvider createClientOnly(ConfigContext context) {
|
||||
return LoomGradleExtension.get(context.project()).isForge() ? SingleJarForgeMinecraftProvider.client(context) : SingleJarMinecraftProvider.client(context);
|
||||
return LoomGradleExtension.get(context.project()).isForgeLike() ? SingleJarForgeMinecraftProvider.client(context) : SingleJarMinecraftProvider.client(context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ import java.util.Objects;
|
||||
|
||||
import com.google.common.base.Stopwatch;
|
||||
import com.google.gson.JsonObject;
|
||||
import dev.architectury.loom.util.MappingOption;
|
||||
import org.apache.tools.ant.util.StringUtils;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
@@ -54,6 +55,7 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.LoomGradlePlugin;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingContext;
|
||||
import net.fabricmc.loom.configuration.DependencyInfo;
|
||||
import net.fabricmc.loom.configuration.providers.forge.FieldMigratedMappingConfiguration;
|
||||
import net.fabricmc.loom.configuration.providers.forge.SrgProvider;
|
||||
@@ -67,10 +69,11 @@ import net.fabricmc.loom.util.ZipUtils;
|
||||
import net.fabricmc.loom.util.service.ScopedSharedServiceManager;
|
||||
import net.fabricmc.loom.util.service.SharedServiceManager;
|
||||
import net.fabricmc.loom.util.srg.MCPReader;
|
||||
import net.fabricmc.loom.util.srg.SrgMerger;
|
||||
import net.fabricmc.loom.util.srg.ForgeMappingsMerger;
|
||||
import net.fabricmc.loom.util.srg.SrgNamedWriter;
|
||||
import net.fabricmc.mappingio.MappingReader;
|
||||
import net.fabricmc.mappingio.format.MappingFormat;
|
||||
import net.fabricmc.mappingio.format.Tiny2Writer;
|
||||
import net.fabricmc.stitch.Command;
|
||||
import net.fabricmc.stitch.commands.CommandProposeFieldNames;
|
||||
import net.fabricmc.stitch.commands.tinyv2.TinyFile;
|
||||
@@ -87,6 +90,7 @@ public class MappingConfiguration {
|
||||
// The mappings we use in practice
|
||||
public Path tinyMappings;
|
||||
public final Path tinyMappingsJar;
|
||||
public Path tinyMappingsWithMojang;
|
||||
public Path tinyMappingsWithSrg;
|
||||
public final Map<String, Path> mixinTinyMappings; // The mixin mappings have other names in intermediary.
|
||||
public final Path srgToNamedSrg; // FORGE: srg to named in srg file format
|
||||
@@ -105,6 +109,7 @@ public class MappingConfiguration {
|
||||
this.tinyMappingsJar = mappingsWorkingDir.resolve("mappings.jar");
|
||||
this.unpickDefinitions = mappingsWorkingDir.resolve("mappings.unpick");
|
||||
this.tinyMappingsWithSrg = mappingsWorkingDir.resolve("mappings-srg.tiny");
|
||||
this.tinyMappingsWithMojang = mappingsWorkingDir.resolve("mappings-mojang.tiny");
|
||||
this.mixinTinyMappings = new HashMap<>();
|
||||
this.srgToNamedSrg = mappingsWorkingDir.resolve("mappings-srg-named.srg");
|
||||
}
|
||||
@@ -124,7 +129,7 @@ public class MappingConfiguration {
|
||||
final LoomGradleExtension extension = LoomGradleExtension.get(project);
|
||||
String mappingsIdentifier;
|
||||
|
||||
if (extension.isForge()) {
|
||||
if (extension.isForgeLike()) {
|
||||
mappingsIdentifier = FieldMigratedMappingConfiguration.createForgeMappingsIdentifier(extension, mappingsName, version, getMappingsClassifier(dependency, jarInfo.v2()), minecraftProvider.minecraftVersion());
|
||||
} else {
|
||||
mappingsIdentifier = createMappingsIdentifier(mappingsName, version, getMappingsClassifier(dependency, jarInfo.v2()), minecraftProvider.minecraftVersion());
|
||||
@@ -138,7 +143,7 @@ public class MappingConfiguration {
|
||||
|
||||
MappingConfiguration mappingConfiguration;
|
||||
|
||||
if (extension.isForge()) {
|
||||
if (extension.isForgeLike()) {
|
||||
mappingConfiguration = new FieldMigratedMappingConfiguration(mappingsIdentifier, workingDir);
|
||||
} else {
|
||||
mappingConfiguration = new MappingConfiguration(mappingsIdentifier, workingDir);
|
||||
@@ -155,21 +160,27 @@ public class MappingConfiguration {
|
||||
}
|
||||
|
||||
public TinyMappingsService getMappingsService(SharedServiceManager serviceManager) {
|
||||
return getMappingsService(serviceManager, false);
|
||||
return getMappingsService(serviceManager, MappingOption.DEFAULT);
|
||||
}
|
||||
|
||||
public TinyMappingsService getMappingsService(SharedServiceManager serviceManager, boolean withSrg) {
|
||||
final Path tinyMappings;
|
||||
|
||||
if (withSrg) {
|
||||
public TinyMappingsService getMappingsService(SharedServiceManager serviceManager, MappingOption mappingOption) {
|
||||
final Path tinyMappings = switch (mappingOption) {
|
||||
case WITH_SRG -> {
|
||||
if (Files.notExists(this.tinyMappingsWithSrg)) {
|
||||
throw new UnsupportedOperationException("Cannot get mappings service with SRG mappings without SRG enabled!");
|
||||
}
|
||||
|
||||
tinyMappings = this.tinyMappingsWithSrg;
|
||||
} else {
|
||||
tinyMappings = this.tinyMappings;
|
||||
yield this.tinyMappingsWithSrg;
|
||||
}
|
||||
case WITH_MOJANG -> {
|
||||
if (Files.notExists(this.tinyMappingsWithMojang)) {
|
||||
throw new UnsupportedOperationException("Cannot get mappings service with Mojang mappings without Mojang merging enabled!");
|
||||
}
|
||||
|
||||
yield this.tinyMappingsWithMojang;
|
||||
}
|
||||
default -> this.tinyMappings;
|
||||
};
|
||||
|
||||
return TinyMappingsService.create(serviceManager, Objects.requireNonNull(tinyMappings));
|
||||
}
|
||||
@@ -196,12 +207,31 @@ public class MappingConfiguration {
|
||||
public void setupPost(Project project) throws IOException {
|
||||
LoomGradleExtension extension = LoomGradleExtension.get(project);
|
||||
|
||||
if (extension.isNeoForge()) {
|
||||
// Generate the Mojmap-merged mappings if needed.
|
||||
// Note that this needs to happen before manipulateMappings for FieldMigratedMappingConfiguration.
|
||||
if (Files.notExists(tinyMappingsWithMojang) || extension.refreshDeps()) {
|
||||
final Stopwatch stopwatch = Stopwatch.createStarted();
|
||||
final MappingContext context = new GradleMappingContext(project, "tmp-neoforge");
|
||||
|
||||
try (Tiny2Writer writer = new Tiny2Writer(Files.newBufferedWriter(tinyMappingsWithMojang), false)) {
|
||||
ForgeMappingsMerger.mergeMojang(context, tinyMappings, null, true).accept(writer);
|
||||
}
|
||||
|
||||
project.getLogger().info(":merged mojang mappings in {}", stopwatch.stop());
|
||||
}
|
||||
}
|
||||
|
||||
if (extension.shouldGenerateSrgTiny()) {
|
||||
if (Files.notExists(tinyMappingsWithSrg) || extension.refreshDeps()) {
|
||||
// Merge tiny mappings with srg
|
||||
Stopwatch stopwatch = Stopwatch.createStarted();
|
||||
SrgMerger.ExtraMappings extraMappings = SrgMerger.ExtraMappings.ofMojmapTsrg(getMojmapSrgFileIfPossible(project));
|
||||
SrgMerger.mergeSrg(getRawSrgFile(project), tinyMappings, tinyMappingsWithSrg, extraMappings, true);
|
||||
ForgeMappingsMerger.ExtraMappings extraMappings = ForgeMappingsMerger.ExtraMappings.ofMojmapTsrg(getMojmapSrgFileIfPossible(project));
|
||||
|
||||
try (Tiny2Writer writer = new Tiny2Writer(Files.newBufferedWriter(tinyMappingsWithSrg), false)) {
|
||||
ForgeMappingsMerger.mergeSrg(getRawSrgFile(project), tinyMappings, extraMappings, true).accept(writer);
|
||||
}
|
||||
|
||||
project.getLogger().info(":merged srg mappings in " + stopwatch.stop());
|
||||
}
|
||||
}
|
||||
@@ -230,7 +260,7 @@ public class MappingConfiguration {
|
||||
|
||||
if (Files.notExists(srgToNamedSrg) || extension.refreshDeps()) {
|
||||
try (var serviceManager = new ScopedSharedServiceManager()) {
|
||||
TinyMappingsService mappingsService = getMappingsService(serviceManager, true);
|
||||
TinyMappingsService mappingsService = getMappingsService(serviceManager, MappingOption.WITH_SRG);
|
||||
SrgNamedWriter.writeTo(project.getLogger(), srgToNamedSrg, mappingsService.getMappingTree(), "srg", "named");
|
||||
}
|
||||
}
|
||||
@@ -300,7 +330,7 @@ public class MappingConfiguration {
|
||||
|
||||
MappingsMerger.mergeAndSaveMappings(baseTinyMappings, tinyMappings, intermediateMappingsService);
|
||||
} else {
|
||||
if (LoomGradleExtension.get(project).isForge()) {
|
||||
if (LoomGradleExtension.get(project).isForgeLike()) {
|
||||
// (2022-09-11) This is due to ordering issues.
|
||||
// To complete V1 mappings, we need the full MC jar.
|
||||
// On Forge, producing the full MC jar needs the list of all Forge dependencies
|
||||
@@ -507,14 +537,14 @@ public class MappingConfiguration {
|
||||
}
|
||||
|
||||
public Path getReplacedTarget(LoomGradleExtension loom, String namespace) {
|
||||
if (namespace.equals("intermediary")) return loom.shouldGenerateSrgTiny() ? tinyMappingsWithSrg : tinyMappings;
|
||||
if (namespace.equals("intermediary")) return getPlatformMappingFile(loom);
|
||||
|
||||
return mixinTinyMappings.computeIfAbsent(namespace, k -> {
|
||||
Path path = mappingsWorkingDir.resolve("mappings-mixin-" + namespace + ".tiny");
|
||||
|
||||
try {
|
||||
if (Files.notExists(path) || loom.refreshDeps()) {
|
||||
List<String> lines = new ArrayList<>(Files.readAllLines(loom.shouldGenerateSrgTiny() ? tinyMappingsWithSrg : tinyMappings));
|
||||
List<String> lines = new ArrayList<>(Files.readAllLines(getPlatformMappingFile(loom)));
|
||||
lines.set(0, lines.get(0).replace("intermediary", "yraidemretni").replace(namespace, "intermediary"));
|
||||
Files.deleteIfExists(path);
|
||||
Files.write(path, lines);
|
||||
@@ -527,6 +557,22 @@ public class MappingConfiguration {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* The mapping file that is specific to the platform settings.
|
||||
* It contains SRG (Forge/common) or Mojang mappings (NeoForge) as needed.
|
||||
*
|
||||
* @return the platform mapping file path
|
||||
*/
|
||||
public Path getPlatformMappingFile(LoomGradleExtension extension) {
|
||||
if (extension.shouldGenerateSrgTiny()) {
|
||||
return tinyMappingsWithSrg;
|
||||
} else if (extension.isNeoForge()) {
|
||||
return tinyMappingsWithMojang;
|
||||
} else {
|
||||
return tinyMappings;
|
||||
}
|
||||
}
|
||||
|
||||
public record UnpickMetadata(String unpickGroup, String unpickVersion) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ import net.fabricmc.loom.configuration.processors.MinecraftJarProcessorManager;
|
||||
import net.fabricmc.loom.configuration.providers.forge.minecraft.ForgeMinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.mapped.IntermediaryMinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.mapped.MappedMinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.mapped.MojangMappedMinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.mapped.NamedMinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.mapped.ProcessedNamedMinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.mapped.SrgMinecraftProvider;
|
||||
@@ -48,6 +49,7 @@ public enum MinecraftJarConfiguration {
|
||||
IntermediaryMinecraftProvider.MergedImpl::new,
|
||||
NamedMinecraftProvider.MergedImpl::new,
|
||||
SrgMinecraftProvider.MergedImpl::new,
|
||||
MojangMappedMinecraftProvider.MergedImpl::new,
|
||||
ProcessedNamedMinecraftProvider.MergedImpl::new,
|
||||
SingleJarDecompileConfiguration::new,
|
||||
List.of("client", "server")
|
||||
@@ -57,6 +59,7 @@ public enum MinecraftJarConfiguration {
|
||||
IntermediaryMinecraftProvider.SingleJarImpl::server,
|
||||
NamedMinecraftProvider.SingleJarImpl::server,
|
||||
SrgMinecraftProvider.SingleJarImpl::server,
|
||||
MojangMappedMinecraftProvider.SingleJarImpl::server,
|
||||
ProcessedNamedMinecraftProvider.SingleJarImpl::server,
|
||||
SingleJarDecompileConfiguration::new,
|
||||
List.of("server")
|
||||
@@ -66,6 +69,7 @@ public enum MinecraftJarConfiguration {
|
||||
IntermediaryMinecraftProvider.SingleJarImpl::client,
|
||||
NamedMinecraftProvider.SingleJarImpl::client,
|
||||
SrgMinecraftProvider.SingleJarImpl::client,
|
||||
MojangMappedMinecraftProvider.SingleJarImpl::client,
|
||||
ProcessedNamedMinecraftProvider.SingleJarImpl::client,
|
||||
SingleJarDecompileConfiguration::new,
|
||||
List.of("client")
|
||||
@@ -75,6 +79,7 @@ public enum MinecraftJarConfiguration {
|
||||
IntermediaryMinecraftProvider.SplitImpl::new,
|
||||
NamedMinecraftProvider.SplitImpl::new,
|
||||
SrgMinecraftProvider.SplitImpl::new,
|
||||
MojangMappedMinecraftProvider.SplitImpl::new,
|
||||
ProcessedNamedMinecraftProvider.SplitImpl::new,
|
||||
SplitDecompileConfiguration::new,
|
||||
List.of("client", "server")
|
||||
@@ -84,6 +89,7 @@ public enum MinecraftJarConfiguration {
|
||||
private final BiFunction<Project, MinecraftProvider, IntermediaryMinecraftProvider<?>> intermediaryMinecraftProviderBiFunction;
|
||||
private final BiFunction<Project, MinecraftProvider, NamedMinecraftProvider<?>> namedMinecraftProviderBiFunction;
|
||||
private final BiFunction<Project, MinecraftProvider, SrgMinecraftProvider<?>> srgMinecraftProviderBiFunction;
|
||||
private final BiFunction<Project, MinecraftProvider, MojangMappedMinecraftProvider<?>> mojangMappedMinecraftProviderBiFunction;
|
||||
private final BiFunction<NamedMinecraftProvider<?>, MinecraftJarProcessorManager, ProcessedNamedMinecraftProvider<?, ?>> processedNamedMinecraftProviderBiFunction;
|
||||
private final BiFunction<ConfigContext, MappedMinecraftProvider, DecompileConfiguration<?>> decompileConfigurationBiFunction;
|
||||
private final List<String> supportedEnvironments;
|
||||
@@ -94,6 +100,7 @@ public enum MinecraftJarConfiguration {
|
||||
BiFunction<Project, M, IntermediaryMinecraftProvider<M>> intermediaryMinecraftProviderBiFunction,
|
||||
BiFunction<Project, M, P> namedMinecraftProviderBiFunction,
|
||||
BiFunction<Project, M, SrgMinecraftProvider<M>> srgMinecraftProviderBiFunction,
|
||||
BiFunction<Project, M, MojangMappedMinecraftProvider<M>> mojangMappedMinecraftProviderBiFunction,
|
||||
BiFunction<P, MinecraftJarProcessorManager, ProcessedNamedMinecraftProvider<M, P>> processedNamedMinecraftProviderBiFunction,
|
||||
BiFunction<ConfigContext, Q, DecompileConfiguration<?>> decompileConfigurationBiFunction,
|
||||
List<String> supportedEnvironments
|
||||
@@ -102,6 +109,7 @@ public enum MinecraftJarConfiguration {
|
||||
this.intermediaryMinecraftProviderBiFunction = (BiFunction<Project, MinecraftProvider, IntermediaryMinecraftProvider<?>>) (Object) intermediaryMinecraftProviderBiFunction;
|
||||
this.namedMinecraftProviderBiFunction = (BiFunction<Project, MinecraftProvider, NamedMinecraftProvider<?>>) namedMinecraftProviderBiFunction;
|
||||
this.srgMinecraftProviderBiFunction = (BiFunction<Project, MinecraftProvider, SrgMinecraftProvider<?>>) (Object) srgMinecraftProviderBiFunction;
|
||||
this.mojangMappedMinecraftProviderBiFunction = (BiFunction<Project, MinecraftProvider, MojangMappedMinecraftProvider<?>>) (Object) mojangMappedMinecraftProviderBiFunction;
|
||||
this.processedNamedMinecraftProviderBiFunction = (BiFunction<NamedMinecraftProvider<?>, MinecraftJarProcessorManager, ProcessedNamedMinecraftProvider<?, ?>>) (Object) processedNamedMinecraftProviderBiFunction;
|
||||
this.decompileConfigurationBiFunction = (BiFunction<ConfigContext, MappedMinecraftProvider, DecompileConfiguration<?>>) decompileConfigurationBiFunction;
|
||||
this.supportedEnvironments = supportedEnvironments;
|
||||
@@ -131,6 +139,10 @@ public enum MinecraftJarConfiguration {
|
||||
return srgMinecraftProviderBiFunction;
|
||||
}
|
||||
|
||||
public BiFunction<Project, MinecraftProvider, MojangMappedMinecraftProvider<?>> getMojangMappedMinecraftProviderBiFunction() {
|
||||
return mojangMappedMinecraftProviderBiFunction;
|
||||
}
|
||||
|
||||
public List<String> getSupportedEnvironments() {
|
||||
return supportedEnvironments;
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ public abstract class MinecraftProvider {
|
||||
final DependencyInfo dependency = DependencyInfo.create(getProject(), Constants.Configurations.MINECRAFT);
|
||||
minecraftVersion = dependency.getDependency().getVersion();
|
||||
|
||||
if (getExtension().shouldGenerateSrgTiny() && !getExtension().isForge()) {
|
||||
if (getExtension().shouldGenerateSrgTiny() && !getExtension().isForgeLike()) {
|
||||
getProject().getDependencies().add(Constants.Configurations.SRG, "de.oceanlabs.mcp:mcp_config:" + minecraftVersion);
|
||||
}
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ public abstract sealed class MinecraftSourceSets permits MinecraftSourceSets.Sin
|
||||
configuration.extendsFrom(configurations.getByName(Constants.Configurations.LOADER_DEPENDENCIES));
|
||||
configuration.extendsFrom(configurations.getByName(Constants.Configurations.LOOM_DEVELOPMENT_DEPENDENCIES));
|
||||
|
||||
if (LoomGradleExtension.get(project).isForge()) {
|
||||
if (LoomGradleExtension.get(project).isForgeLike()) {
|
||||
configurations.getByName(Constants.Configurations.FORGE_RUNTIME_LIBRARY).extendsFrom(configuration);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -36,14 +36,17 @@ import java.util.Set;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.function.Function;
|
||||
|
||||
import dev.architectury.loom.util.MappingOption;
|
||||
import dev.architectury.tinyremapper.OutputConsumerPath;
|
||||
import dev.architectury.tinyremapper.TinyRemapper;
|
||||
import org.gradle.api.Project;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.build.IntermediaryNamespaces;
|
||||
import net.fabricmc.loom.configuration.ConfigContext;
|
||||
import net.fabricmc.loom.configuration.mods.dependency.LocalMavenHelper;
|
||||
import net.fabricmc.loom.configuration.providers.forge.minecraft.ForgeMinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.IntermediaryMappingsProvider;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingConfiguration;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.TinyMappingsService;
|
||||
@@ -176,6 +179,11 @@ public abstract class AbstractMappedMinecraftProvider<M extends MinecraftProvide
|
||||
}
|
||||
}
|
||||
|
||||
// Architectury: regenerate jars if patches have changed.
|
||||
if (minecraftProvider instanceof ForgeMinecraftProvider withForge && withForge.getPatchedProvider().isDirty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -194,7 +202,7 @@ public abstract class AbstractMappedMinecraftProvider<M extends MinecraftProvide
|
||||
|
||||
Files.deleteIfExists(remappedJars.outputJarPath());
|
||||
|
||||
final Set<String> classNames = extension.isForge() ? InnerClassRemapper.readClassNames(remappedJars.inputJar()) : Set.of();
|
||||
final Set<String> classNames = extension.isForgeLike() ? InnerClassRemapper.readClassNames(remappedJars.inputJar()) : Set.of();
|
||||
final Map<String, String> remappedSignatures = SignatureFixerApplyVisitor.getRemappedSignatures(getTargetNamespace() == MappingsNamespace.INTERMEDIARY, mappingConfiguration, getProject(), configContext.serviceManager(), toM);
|
||||
TinyRemapper remapper = TinyRemapperHelper.getTinyRemapper(getProject(), configContext.serviceManager(), fromM, toM, true, (builder) -> {
|
||||
builder.extraPostApplyVisitor(new SignatureFixerApplyVisitor(remappedSignatures));
|
||||
@@ -219,11 +227,21 @@ public abstract class AbstractMappedMinecraftProvider<M extends MinecraftProvide
|
||||
|
||||
getMavenHelper(remappedJars.name()).savePom();
|
||||
|
||||
if (extension.isForgeAndOfficial()) {
|
||||
if (extension.isForgeLikeAndOfficial()) {
|
||||
try (var serviceManager = new ScopedSharedServiceManager()) {
|
||||
TinyMappingsService mappingsService = extension.getMappingConfiguration().getMappingsService(serviceManager, true);
|
||||
MemoryMappingTree mappingsWithSrg = mappingsService.getMappingTree();
|
||||
RemapObjectHolderVisitor.remapObjectHolder(remappedJars.outputJar().getPath(), "net.minecraftforge.registries.ObjectHolderRegistry", mappingsWithSrg, "srg", "named");
|
||||
final MappingOption mappingOption = MappingOption.forPlatform(extension);
|
||||
final TinyMappingsService mappingsService = extension.getMappingConfiguration().getMappingsService(serviceManager, mappingOption);
|
||||
final String className;
|
||||
|
||||
if (extension.isNeoForge()) {
|
||||
className = "net.neoforged.neoforge.registries.ObjectHolderRegistry";
|
||||
} else {
|
||||
className = "net.minecraftforge.registries.ObjectHolderRegistry";
|
||||
}
|
||||
|
||||
final String sourceNamespace = IntermediaryNamespaces.intermediary(project);
|
||||
final MemoryMappingTree mappings = mappingsService.getMappingTree();
|
||||
RemapObjectHolderVisitor.remapObjectHolder(remappedJars.outputJar().getPath(), className, mappings, sourceNamespace, "named");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2023 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.minecraft.mapped;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import dev.architectury.tinyremapper.TinyRemapper;
|
||||
import org.gradle.api.Project;
|
||||
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MergedMinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.SingleJarEnvType;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.SingleJarMinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.SplitMinecraftProvider;
|
||||
import net.fabricmc.loom.util.SidedClassVisitor;
|
||||
|
||||
public abstract sealed class MojangMappedMinecraftProvider<M extends MinecraftProvider> extends AbstractMappedMinecraftProvider<M> permits MojangMappedMinecraftProvider.MergedImpl, MojangMappedMinecraftProvider.SingleJarImpl, MojangMappedMinecraftProvider.SplitImpl {
|
||||
public MojangMappedMinecraftProvider(Project project, M minecraftProvider) {
|
||||
super(project, minecraftProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MavenScope getMavenScope() {
|
||||
return MavenScope.GLOBAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final MappingsNamespace getTargetNamespace() {
|
||||
return MappingsNamespace.MOJANG;
|
||||
}
|
||||
|
||||
public static final class MergedImpl extends MojangMappedMinecraftProvider<MergedMinecraftProvider> implements Merged {
|
||||
public MergedImpl(Project project, MergedMinecraftProvider minecraftProvider) {
|
||||
super(project, minecraftProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RemappedJars> getRemappedJars() {
|
||||
return List.of(
|
||||
new RemappedJars(minecraftProvider.getMergedJar(), getMergedJar(), MappingsNamespace.OFFICIAL)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class SplitImpl extends MojangMappedMinecraftProvider<SplitMinecraftProvider> implements Split {
|
||||
public SplitImpl(Project project, SplitMinecraftProvider minecraftProvider) {
|
||||
super(project, minecraftProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RemappedJars> getRemappedJars() {
|
||||
return List.of(
|
||||
new RemappedJars(minecraftProvider.getMinecraftCommonJar(), getCommonJar(), MappingsNamespace.OFFICIAL),
|
||||
new RemappedJars(minecraftProvider.getMinecraftClientOnlyJar(), getClientOnlyJar(), MappingsNamespace.OFFICIAL, minecraftProvider.getMinecraftCommonJar())
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureRemapper(RemappedJars remappedJars, TinyRemapper.Builder tinyRemapperBuilder) {
|
||||
if (remappedJars.outputJar().equals(getClientOnlyJar())) {
|
||||
tinyRemapperBuilder.extraPostApplyVisitor(SidedClassVisitor.CLIENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final class SingleJarImpl extends MojangMappedMinecraftProvider<SingleJarMinecraftProvider> implements SingleJar {
|
||||
private final SingleJarEnvType env;
|
||||
|
||||
private SingleJarImpl(Project project, SingleJarMinecraftProvider minecraftProvider, SingleJarEnvType env) {
|
||||
super(project, minecraftProvider);
|
||||
this.env = env;
|
||||
}
|
||||
|
||||
public static SingleJarImpl server(Project project, SingleJarMinecraftProvider minecraftProvider) {
|
||||
return new SingleJarImpl(project, minecraftProvider, SingleJarEnvType.SERVER);
|
||||
}
|
||||
|
||||
public static SingleJarImpl client(Project project, SingleJarMinecraftProvider minecraftProvider) {
|
||||
return new SingleJarImpl(project, minecraftProvider, SingleJarEnvType.CLIENT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RemappedJars> getRemappedJars() {
|
||||
return List.of(
|
||||
new RemappedJars(minecraftProvider.getMinecraftEnvOnlyJar(), getEnvOnlyJar(), MappingsNamespace.OFFICIAL)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SingleJarEnvType env() {
|
||||
return env;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2021-2022 FabricMC
|
||||
* Copyright (c) 2021-2023 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
|
||||
@@ -40,6 +40,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import dev.architectury.loom.util.MappingOption;
|
||||
import org.apache.commons.io.output.NullOutputStream;
|
||||
import org.cadixdev.lorenz.MappingSet;
|
||||
import org.cadixdev.mercury.Mercury;
|
||||
@@ -48,6 +49,7 @@ import org.gradle.api.Project;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.build.IntermediaryNamespaces;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.TinyMappingsService;
|
||||
import net.fabricmc.loom.task.GenerateSourcesTask;
|
||||
import net.fabricmc.loom.util.DeletingFileVisitor;
|
||||
@@ -113,7 +115,7 @@ public class ForgeSourcesRemapper {
|
||||
|
||||
public static void provideForgeSources(Project project, SharedServiceManager serviceManager, BiConsumer<String, byte[]> consumer) throws IOException {
|
||||
LoomGradleExtension extension = LoomGradleExtension.get(project);
|
||||
String sourceDependency = extension.getForgeUserdevProvider().getJson().getAsJsonPrimitive("sources").getAsString();
|
||||
String sourceDependency = extension.getForgeUserdevProvider().getConfig().sources();
|
||||
List<Path> forgeInstallerSources = new ArrayList<>();
|
||||
|
||||
for (File file : DependencyDownloader.download(project, sourceDependency)) {
|
||||
@@ -202,8 +204,10 @@ public class ForgeSourcesRemapper {
|
||||
LoomGradleExtension extension = LoomGradleExtension.get(project);
|
||||
Mercury mercury = SourceRemapper.createMercuryWithClassPath(project, false);
|
||||
|
||||
TinyMappingsService mappingsService = extension.getMappingConfiguration().getMappingsService(serviceManager, true);
|
||||
MappingSet mappings = new TinyMappingsReader(mappingsService.getMappingTree(), "srg", "named").read();
|
||||
final MappingOption mappingOption = MappingOption.forPlatform(extension);
|
||||
final String sourceNamespace = IntermediaryNamespaces.intermediary(project);
|
||||
TinyMappingsService mappingsService = extension.getMappingConfiguration().getMappingsService(serviceManager, mappingOption);
|
||||
MappingSet mappings = new TinyMappingsReader(mappingsService.getMappingTree(), sourceNamespace, "named").read();
|
||||
|
||||
for (Map.Entry<String, String> entry : TinyRemapperHelper.JSR_TO_JETBRAINS.entrySet()) {
|
||||
mappings.getOrCreateClassMapping(entry.getKey()).setDeobfuscatedName(entry.getValue());
|
||||
@@ -217,8 +221,9 @@ public class ForgeSourcesRemapper {
|
||||
mercury.getClassPath().add(file.toPath());
|
||||
}
|
||||
|
||||
// Distinct and add the srg jar at the top, so it gets prioritized
|
||||
mercury.getClassPath().addAll(0, extension.getMinecraftJars(MappingsNamespace.SRG));
|
||||
// Distinct and add the srg/mojang jar at the top, so it gets prioritized
|
||||
MappingsNamespace sourceNs = extension.isNeoForge() ? MappingsNamespace.MOJANG : MappingsNamespace.SRG;
|
||||
mercury.getClassPath().addAll(0, extension.getMinecraftJars(sourceNs));
|
||||
|
||||
List<Path> newClassPath = mercury.getClassPath().stream()
|
||||
.distinct()
|
||||
|
||||
@@ -54,6 +54,7 @@ import net.fabricmc.loom.api.InterfaceInjectionExtensionAPI;
|
||||
import net.fabricmc.loom.api.LoomGradleExtensionAPI;
|
||||
import net.fabricmc.loom.api.MixinExtensionAPI;
|
||||
import net.fabricmc.loom.api.ModSettings;
|
||||
import net.fabricmc.loom.api.NeoForgeExtensionAPI;
|
||||
import net.fabricmc.loom.api.RemapConfigurationSettings;
|
||||
import net.fabricmc.loom.api.decompilers.DecompilerOptions;
|
||||
import net.fabricmc.loom.api.mappings.intermediate.IntermediateMappingsProvider;
|
||||
@@ -134,7 +135,7 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
|
||||
.convention(true);
|
||||
this.transitiveAccessWideners.finalizeValueOnRead();
|
||||
this.modProvidedJavadoc = project.getObjects().property(Boolean.class)
|
||||
.convention(project.provider(() -> !isForge()));
|
||||
.convention(project.provider(() -> !isForgeLike()));
|
||||
this.modProvidedJavadoc.finalizeValueOnRead();
|
||||
this.intermediary = project.getObjects().property(String.class)
|
||||
.convention("https://maven.fabricmc.net/net/fabricmc/intermediary/%1$s/intermediary-%1$s-v2.jar");
|
||||
@@ -446,6 +447,14 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
|
||||
|
||||
@Override
|
||||
public void setGenerateSrgTiny(Boolean generateSrgTiny) {
|
||||
if (isNeoForge()) {
|
||||
// This is unsupported because supporting the full 2x2 combination of
|
||||
// [no extra NS] [SRG]
|
||||
// [mojang] [SRG+mojang]
|
||||
// is a bit verbose to support.
|
||||
throw new UnsupportedOperationException("SRG is not supported on NeoForge.");
|
||||
}
|
||||
|
||||
this.generateSrgTiny = generateSrgTiny;
|
||||
}
|
||||
|
||||
@@ -473,6 +482,11 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
|
||||
action.execute(getForge());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void neoForge(Action<NeoForgeExtensionAPI> action) {
|
||||
action.execute(getNeoForge());
|
||||
}
|
||||
|
||||
// This is here to ensure that LoomGradleExtensionApiImpl compiles without any unimplemented methods
|
||||
private final class EnsureCompile extends LoomGradleExtensionApiImpl {
|
||||
private EnsureCompile() {
|
||||
@@ -514,5 +528,10 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
|
||||
public ForgeExtensionAPI getForge() {
|
||||
throw new RuntimeException("Yeah... something is really wrong");
|
||||
}
|
||||
|
||||
@Override
|
||||
public NeoForgeExtensionAPI getNeoForge() {
|
||||
throw new RuntimeException("Yeah... something is really wrong");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ import org.gradle.api.provider.Provider;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.api.ForgeExtensionAPI;
|
||||
import net.fabricmc.loom.api.NeoForgeExtensionAPI;
|
||||
import net.fabricmc.loom.api.mappings.intermediate.IntermediateMappingsProvider;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.configuration.InstallerData;
|
||||
@@ -52,6 +53,7 @@ import net.fabricmc.loom.configuration.providers.mappings.MappingConfiguration;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.library.LibraryProcessorManager;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.mapped.IntermediaryMinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.mapped.MojangMappedMinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.mapped.NamedMinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.mapped.SrgMinecraftProvider;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
@@ -65,7 +67,6 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen
|
||||
private final MixinExtension mixinApExtension;
|
||||
private final LoomFiles loomFiles;
|
||||
private final ConfigurableFileCollection unmappedMods;
|
||||
private final Supplier<ForgeExtensionAPI> forgeExtension;
|
||||
|
||||
private final List<AccessWidenerFile> transitiveAccessWideners = new ArrayList<>();
|
||||
|
||||
@@ -75,6 +76,7 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen
|
||||
private NamedMinecraftProvider<?> namedMinecraftProvider;
|
||||
private IntermediaryMinecraftProvider<?> intermediaryMinecraftProvider;
|
||||
private SrgMinecraftProvider<?> srgMinecraftProvider;
|
||||
private MojangMappedMinecraftProvider<?> mojangMappedMinecraftProvider;
|
||||
private InstallerData installerData;
|
||||
private boolean refreshDeps;
|
||||
private Provider<Boolean> multiProjectOptimisation;
|
||||
@@ -85,6 +87,8 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen
|
||||
// +-------------------+
|
||||
private DependencyProviders dependencyProviders;
|
||||
private ForgeRunsProvider forgeRunsProvider;
|
||||
private final Supplier<ForgeExtensionAPI> forgeExtension;
|
||||
private final Supplier<NeoForgeExtensionAPI> neoForgeExtension;
|
||||
|
||||
public LoomGradleExtensionImpl(Project project, LoomFiles files) {
|
||||
super(project, files);
|
||||
@@ -94,6 +98,7 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen
|
||||
this.loomFiles = files;
|
||||
this.unmappedMods = project.files();
|
||||
this.forgeExtension = Suppliers.memoize(() -> isForge() ? project.getObjects().newInstance(ForgeExtensionImpl.class, project, this) : null);
|
||||
this.neoForgeExtension = Suppliers.memoize(() -> isNeoForge() ? project.getObjects().newInstance(NeoForgeExtensionImpl.class, project) : null);
|
||||
|
||||
// Setup the default intermediate mappings provider.
|
||||
setIntermediateMappingsProvider(IntermediaryMappingsProvider.class, provider -> {
|
||||
@@ -185,6 +190,16 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen
|
||||
this.srgMinecraftProvider = srgMinecraftProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MojangMappedMinecraftProvider<?> getMojangMappedMinecraftProvider() {
|
||||
return Objects.requireNonNull(mojangMappedMinecraftProvider, "Cannot get MojangMappedMinecraftProvider before it has been setup");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMojangMappedMinecraftProvider(MojangMappedMinecraftProvider<?> mojangMappedMinecraftProvider) {
|
||||
this.mojangMappedMinecraftProvider = mojangMappedMinecraftProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileCollection getMinecraftJarsCollection(MappingsNamespace mappingsNamespace) {
|
||||
return getProject().files(
|
||||
@@ -293,6 +308,12 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen
|
||||
return forgeExtension.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NeoForgeExtensionAPI getNeoForge() {
|
||||
ModPlatform.assertPlatform(this, ModPlatform.NEOFORGE);
|
||||
return neoForgeExtension.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DependencyProviders getDependencyProviders() {
|
||||
return dependencyProviders;
|
||||
@@ -305,13 +326,13 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen
|
||||
|
||||
@Override
|
||||
public ForgeRunsProvider getForgeRunsProvider() {
|
||||
ModPlatform.assertPlatform(this, ModPlatform.FORGE);
|
||||
ModPlatform.assertForgeLike(this);
|
||||
return forgeRunsProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setForgeRunsProvider(ForgeRunsProvider forgeRunsProvider) {
|
||||
ModPlatform.assertPlatform(this, ModPlatform.FORGE);
|
||||
ModPlatform.assertForgeLike(this);
|
||||
this.forgeRunsProvider = forgeRunsProvider;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import org.gradle.api.provider.Provider;
|
||||
import org.gradle.api.tasks.SourceSet;
|
||||
import org.gradle.api.tasks.util.PatternSet;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.api.MixinExtensionAPI;
|
||||
import net.fabricmc.loom.build.IntermediaryNamespaces;
|
||||
|
||||
@@ -49,8 +50,7 @@ public abstract class MixinExtensionApiImpl implements MixinExtensionAPI {
|
||||
public MixinExtensionApiImpl(Project project) {
|
||||
this.project = Objects.requireNonNull(project);
|
||||
this.useMixinAp = project.getObjects().property(Boolean.class)
|
||||
// .convention(project.provider(() -> LoomGradleExtension.get(project).isForge()));
|
||||
.convention(true);
|
||||
.convention(project.provider(() -> !LoomGradleExtension.get(project).isNeoForge()));
|
||||
|
||||
this.refmapTargetNamespace = project.getObjects().property(String.class)
|
||||
.convention(project.provider(() -> IntermediaryNamespaces.intermediary(project)));
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2023 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.extension;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.file.ConfigurableFileCollection;
|
||||
|
||||
import net.fabricmc.loom.api.NeoForgeExtensionAPI;
|
||||
|
||||
public class NeoForgeExtensionImpl implements NeoForgeExtensionAPI {
|
||||
private final ConfigurableFileCollection accessTransformers;
|
||||
|
||||
@Inject
|
||||
public NeoForgeExtensionImpl(Project project) {
|
||||
accessTransformers = project.getObjects().fileCollection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigurableFileCollection getAccessTransformers() {
|
||||
return accessTransformers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accessTransformer(Object file) {
|
||||
accessTransformers.from(file);
|
||||
}
|
||||
}
|
||||
@@ -37,8 +37,6 @@ import codechicken.diffpatch.cli.PatchOperation;
|
||||
import codechicken.diffpatch.util.LoggingOutputStream;
|
||||
import codechicken.diffpatch.util.PatchMode;
|
||||
import com.google.common.base.Stopwatch;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import dev.architectury.loom.forge.ForgeTools;
|
||||
import dev.architectury.loom.util.TempFiles;
|
||||
import org.gradle.api.file.FileCollection;
|
||||
@@ -62,6 +60,7 @@ import net.fabricmc.loom.util.SourceRemapper;
|
||||
import net.fabricmc.loom.util.service.ScopedSharedServiceManager;
|
||||
import net.fabricmc.loom.util.service.SharedServiceManager;
|
||||
|
||||
// TODO: NeoForge support
|
||||
public abstract class GenerateForgePatchedSourcesTask extends AbstractLoomTask {
|
||||
/**
|
||||
* The SRG Minecraft file produced by the MCP executor.
|
||||
@@ -136,7 +135,7 @@ public abstract class GenerateForgePatchedSourcesTask extends AbstractLoomTask {
|
||||
|
||||
private Path sourcePatch(Path cache, Path rawDecompiled) throws IOException {
|
||||
ForgeUserdevProvider userdev = getExtension().getForgeUserdevProvider();
|
||||
String patchPathInZip = userdev.getJson().getAsJsonPrimitive("patches").getAsString();
|
||||
String patchPathInZip = userdev.getConfig().patches();
|
||||
Path output = cache.resolve("patched.jar");
|
||||
Path rejects = cache.resolve("rejects");
|
||||
|
||||
@@ -148,8 +147,8 @@ public abstract class GenerateForgePatchedSourcesTask extends AbstractLoomTask {
|
||||
.outputPath(output)
|
||||
.mode(PatchMode.ACCESS)
|
||||
.rejectsPath(rejects)
|
||||
.aPrefix(userdev.getJson().getAsJsonPrimitive("patchesOriginalPrefix").getAsString())
|
||||
.bPrefix(userdev.getJson().getAsJsonPrimitive("patchesModifiedPrefix").getAsString())
|
||||
.aPrefix(userdev.getConfig().patchesOriginalPrefix().orElseThrow())
|
||||
.bPrefix(userdev.getConfig().patchesModifiedPrefix().orElseThrow())
|
||||
.build()
|
||||
.operate();
|
||||
|
||||
@@ -173,18 +172,18 @@ public abstract class GenerateForgePatchedSourcesTask extends AbstractLoomTask {
|
||||
|
||||
try (var tempFiles = new TempFiles()) {
|
||||
final ForgeUserdevProvider userdevProvider = getExtension().getForgeUserdevProvider();
|
||||
final JsonArray sass = userdevProvider.getJson().getAsJsonArray("sass");
|
||||
final List<String> sass = userdevProvider.getConfig().sass();
|
||||
final List<Path> sasPaths = new ArrayList<>();
|
||||
|
||||
try (FileSystemUtil.Delegate fs = FileSystemUtil.getJarFileSystem(userdevProvider.getUserdevJar(), false)) {
|
||||
for (JsonElement sasPath : sass) {
|
||||
for (String sasPath : sass) {
|
||||
try {
|
||||
final Path from = fs.getPath(sasPath.getAsString());
|
||||
final Path from = fs.getPath(sasPath);
|
||||
final Path to = tempFiles.file(null, ".sas");
|
||||
Files.copy(from, to, StandardCopyOption.REPLACE_EXISTING);
|
||||
sasPaths.add(to);
|
||||
} catch (IOException e) {
|
||||
throw new IOException("Could not extract SAS " + sasPath.getAsString());
|
||||
throw new IOException("Could not extract SAS " + sasPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,7 +192,7 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask {
|
||||
}
|
||||
|
||||
// Inject Forge's own sources
|
||||
if (getExtension().isForge()) {
|
||||
if (getExtension().isForgeLike()) {
|
||||
try (var serviceManager = new ScopedSharedServiceManager()) {
|
||||
ForgeSourcesRemapper.addForgeSources(getProject(), serviceManager, getOutputJar().get().getAsFile().toPath());
|
||||
}
|
||||
@@ -296,7 +296,7 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask {
|
||||
params.getClassPath().setFrom(getProject().getConfigurations().getByName(Constants.Configurations.MINECRAFT_COMPILE_LIBRARIES));
|
||||
|
||||
// Architectury
|
||||
params.getForge().set(getExtension().isForge());
|
||||
params.getForge().set(getExtension().isForgeLike());
|
||||
});
|
||||
|
||||
try {
|
||||
@@ -416,9 +416,12 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask {
|
||||
if (Files.exists(linemap)) {
|
||||
if (getParameters().getForge().get()) {
|
||||
try {
|
||||
// Remove Forge classes from linemap
|
||||
// Remove Forge and NeoForge classes from linemap
|
||||
// TODO: We should instead not decompile Forge's classes at all
|
||||
LineMapVisitor.process(linemap, next -> new LineMapClassFilter(next, name -> !name.startsWith("net/minecraftforge/")));
|
||||
LineMapVisitor.process(linemap, next -> new LineMapClassFilter(next, name -> {
|
||||
// Skip both Forge and NeoForge classes.
|
||||
return !name.startsWith("net/minecraftforge/") && !name.startsWith("net/neoforged/");
|
||||
}));
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException("Failed to process linemap", e);
|
||||
}
|
||||
@@ -470,7 +473,7 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask {
|
||||
}
|
||||
|
||||
private Path getMappings() {
|
||||
Path inputMappings = getExtension().isForge() ? getExtension().getMappingConfiguration().tinyMappingsWithSrg : getExtension().getMappingConfiguration().tinyMappings;
|
||||
Path inputMappings = getExtension().getPlatformMappingFile();
|
||||
|
||||
MemoryMappingTree mappingTree = new MemoryMappingTree();
|
||||
|
||||
|
||||
@@ -196,6 +196,10 @@ public abstract class MigrateMappingsTask extends AbstractLoomTask {
|
||||
for (Path srgJar : extension.getMinecraftJars(MappingsNamespace.SRG)) {
|
||||
mercury.getClassPath().add(srgJar);
|
||||
}
|
||||
} else if (extension.isNeoForge()) {
|
||||
for (Path mojangJar : extension.getMinecraftJars(MappingsNamespace.MOJANG)) {
|
||||
mercury.getClassPath().add(mojangJar);
|
||||
}
|
||||
}
|
||||
|
||||
mercury.getProcessors().add(MercuryRemapper.create(mappingSet));
|
||||
|
||||
@@ -141,13 +141,13 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
|
||||
|
||||
getClasspath().from(getProject().getConfigurations().getByName(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME));
|
||||
getAddNestedDependencies().convention(true).finalizeValueOnRead();
|
||||
getReadMixinConfigsFromManifest().convention(LoomGradleExtension.get(getProject()).isForge()).finalizeValueOnRead();
|
||||
getReadMixinConfigsFromManifest().convention(LoomGradleExtension.get(getProject()).isForgeLike()).finalizeValueOnRead();
|
||||
getInjectAccessWidener().convention(false);
|
||||
|
||||
Configuration includeConfiguration = getProject().getConfigurations().getByName(Constants.Configurations.INCLUDE);
|
||||
IncludedJarFactory factory = new IncludedJarFactory(getProject());
|
||||
|
||||
if (!LoomGradleExtension.get(getProject()).isForge()) {
|
||||
if (!LoomGradleExtension.get(getProject()).isForgeLike()) {
|
||||
getNestedJars().from(factory.getNestedJars(includeConfiguration));
|
||||
} else {
|
||||
Provider<Pair<List<LazyNestedFile>, TaskDependency>> forgeNestedJars = factory.getForgeNestedJars(includeConfiguration);
|
||||
@@ -196,7 +196,7 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
|
||||
if (getAddNestedDependencies().get()) {
|
||||
params.getNestedJars().from(getNestedJars());
|
||||
|
||||
if (extension.isForge()) {
|
||||
if (extension.isForgeLike()) {
|
||||
params.getForgeNestedJars().set(getForgeNestedJars());
|
||||
}
|
||||
}
|
||||
@@ -326,7 +326,7 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
|
||||
addNestedJars();
|
||||
ModBuildExtensions.convertAwToAt(getParameters().getAtAccessWideners(), outputFile, getParameters().getMappingBuildServiceUuid());
|
||||
|
||||
if (getParameters().getPlatform().get() != ModPlatform.FORGE) {
|
||||
if (!getParameters().getPlatform().get().isForgeLike()) {
|
||||
modifyJarManifest();
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ import org.apache.commons.io.FileUtils;
|
||||
import org.gradle.api.logging.configuration.ConsoleOutput;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
|
||||
import net.fabricmc.loom.build.IntermediaryNamespaces;
|
||||
import net.fabricmc.loom.configuration.providers.forge.ConfigValue;
|
||||
import net.fabricmc.loom.configuration.providers.forge.ForgeRunTemplate;
|
||||
import net.fabricmc.loom.configuration.providers.forge.ForgeRunsProvider;
|
||||
@@ -75,7 +76,7 @@ public abstract class GenerateDLIConfigTask extends AbstractLoomTask {
|
||||
.property("client", "org.lwjgl.librarypath", nativesPath);
|
||||
}
|
||||
|
||||
if (!getExtension().isForge()) {
|
||||
if (!getExtension().isForgeLike()) {
|
||||
launchConfig
|
||||
.argument("client", "--assetIndex")
|
||||
.argument("client", getExtension().getMinecraftProvider().getVersionInfo().assetIndex().fabricId(getExtension().getMinecraftProvider().minecraftVersion()))
|
||||
@@ -98,7 +99,7 @@ public abstract class GenerateDLIConfigTask extends AbstractLoomTask {
|
||||
.argument("client", "Architectury Loom");
|
||||
}
|
||||
|
||||
if (getExtension().isForge()) {
|
||||
if (getExtension().isForgeLike()) {
|
||||
// Find the mapping files for Unprotect to use for figuring out
|
||||
// which classes are from Minecraft.
|
||||
String unprotectMappings = getProject().getConfigurations()
|
||||
@@ -108,37 +109,46 @@ public abstract class GenerateDLIConfigTask extends AbstractLoomTask {
|
||||
.map(File::getAbsolutePath)
|
||||
.collect(Collectors.joining(File.pathSeparator));
|
||||
|
||||
final String intermediateNs = IntermediaryNamespaces.intermediary(getProject());
|
||||
final String mappingsPath = getExtension().getPlatformMappingFile().toAbsolutePath().toString();
|
||||
|
||||
launchConfig
|
||||
// Should match YarnNamingService.PATH_TO_MAPPINGS in forge-runtime
|
||||
.property("fabric.yarnWithSrg.path", getExtension().getMappingConfiguration().tinyMappingsWithSrg.toAbsolutePath().toString())
|
||||
.property("unprotect.mappings", unprotectMappings)
|
||||
// See ArchitecturyNamingService in forge-runtime
|
||||
.property("architectury.naming.sourceNamespace", intermediateNs)
|
||||
.property("architectury.naming.mappingsPath", mappingsPath);
|
||||
|
||||
.property("mixin.env.remapRefMap", "true");
|
||||
if (getExtension().isForge()) {
|
||||
final List<String> dataGenMods = getExtension().getForge().getDataGenMods();
|
||||
|
||||
final List<String> dataGenMods = getExtension().getForge().getDataGenMods();
|
||||
// Only apply the hardcoded data arguments if the deprecated data generator API is being used.
|
||||
if (!dataGenMods.isEmpty()) {
|
||||
launchConfig
|
||||
.argument("data", "--all")
|
||||
.argument("data", "--mod")
|
||||
.argument("data", String.join(",", getExtension().getForge().getDataGenMods()))
|
||||
.argument("data", "--output")
|
||||
.argument("data", getProject().file("src/generated/resources").getAbsolutePath());
|
||||
}
|
||||
|
||||
// Only apply the hardcoded data arguments if the deprecated data generator API is being used.
|
||||
if (!dataGenMods.isEmpty()) {
|
||||
launchConfig
|
||||
.argument("data", "--all")
|
||||
.argument("data", "--mod")
|
||||
.argument("data", String.join(",", getExtension().getForge().getDataGenMods()))
|
||||
.argument("data", "--output")
|
||||
.argument("data", getProject().file("src/generated/resources").getAbsolutePath());
|
||||
}
|
||||
launchConfig.property("mixin.env.remapRefMap", "true");
|
||||
|
||||
if (PropertyUtil.getAndFinalize(getExtension().getForge().getUseCustomMixin())) {
|
||||
launchConfig.property("mixin.forgeloom.inject.mappings.srg-named", getExtension().getMappingConfiguration().getReplacedTarget(getExtension(), "srg").toAbsolutePath().toString());
|
||||
} else {
|
||||
launchConfig.property("net.minecraftforge.gradle.GradleStart.srg.srg-mcp", getExtension().getMappingConfiguration().srgToNamedSrg.toAbsolutePath().toString());
|
||||
}
|
||||
if (PropertyUtil.getAndFinalize(getExtension().getForge().getUseCustomMixin())) {
|
||||
// See mixin remapper service in forge-runtime
|
||||
launchConfig
|
||||
.property("architectury.mixinRemapper.sourceNamespace", intermediateNs)
|
||||
.property("architectury.mixinRemapper.mappingsPath", mappingsPath);
|
||||
} else {
|
||||
launchConfig.property("net.minecraftforge.gradle.GradleStart.srg.srg-mcp", getExtension().getMappingConfiguration().srgToNamedSrg.toAbsolutePath().toString());
|
||||
}
|
||||
|
||||
Set<String> mixinConfigs = PropertyUtil.getAndFinalize(getExtension().getForge().getMixinConfigs());
|
||||
Set<String> mixinConfigs = PropertyUtil.getAndFinalize(getExtension().getForge().getMixinConfigs());
|
||||
|
||||
if (!mixinConfigs.isEmpty()) {
|
||||
for (String config : mixinConfigs) {
|
||||
launchConfig.argument("-mixin.config");
|
||||
launchConfig.argument(config);
|
||||
if (!mixinConfigs.isEmpty()) {
|
||||
for (String config : mixinConfigs) {
|
||||
launchConfig.argument("-mixin.config");
|
||||
launchConfig.argument(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ public abstract class JarManifestService implements BuildService<JarManifestServ
|
||||
|
||||
private static Provider<MixinVersion> getMixinVersion(Project project) {
|
||||
return project.getConfigurations().named(Constants.Configurations.LOADER_DEPENDENCIES).map(configuration -> {
|
||||
if (LoomGradleExtension.get(project).isForge()) return new MixinVersion("unknown", "unknown");
|
||||
if (LoomGradleExtension.get(project).isForgeLike()) return new MixinVersion("unknown", "unknown");
|
||||
|
||||
// Not super ideal that this uses the mod compile classpath, should prob look into making this not a thing at somepoint
|
||||
Optional<Dependency> dependency = configuration
|
||||
|
||||
@@ -28,6 +28,7 @@ import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.util.Objects;
|
||||
|
||||
import dev.architectury.loom.util.MappingOption;
|
||||
import org.cadixdev.lorenz.MappingSet;
|
||||
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
@@ -46,8 +47,15 @@ public final class LorenzMappingService implements SharedService {
|
||||
|
||||
public static synchronized LorenzMappingService create(SharedServiceManager sharedServiceManager, MappingConfiguration mappingConfiguration, MappingsNamespace from, MappingsNamespace to) {
|
||||
return sharedServiceManager.getOrCreateService(mappingConfiguration.getBuildServiceName("LorenzMappingService", from.toString(), to.toString()), () -> {
|
||||
boolean srg = (from == MappingsNamespace.SRG || to == MappingsNamespace.SRG);
|
||||
MemoryMappingTree m = mappingConfiguration.getMappingsService(sharedServiceManager, srg).getMappingTree();
|
||||
MappingOption mappingOption = MappingOption.DEFAULT;
|
||||
|
||||
if (from == MappingsNamespace.SRG || to == MappingsNamespace.SRG) {
|
||||
mappingOption = MappingOption.WITH_SRG;
|
||||
} else if (from == MappingsNamespace.MOJANG || to == MappingsNamespace.MOJANG) {
|
||||
mappingOption = MappingOption.WITH_MOJANG;
|
||||
}
|
||||
|
||||
MemoryMappingTree m = mappingConfiguration.getMappingsService(sharedServiceManager, mappingOption).getMappingTree();
|
||||
|
||||
try {
|
||||
try (var reader = new TinyMappingsReader(m, from.toString(), to.toString())) {
|
||||
|
||||
@@ -52,7 +52,7 @@ public final class MappingsService implements SharedService {
|
||||
final MappingConfiguration mappingConfiguration = LoomGradleExtension.get(project).getMappingConfiguration();
|
||||
|
||||
final String name = mappingConfiguration.getBuildServiceName("mappingsProvider", from, to);
|
||||
return MappingsService.create(serviceManager, name, (from.equals("srg") || to.equals("srg")) && LoomGradleExtension.get(project).shouldGenerateSrgTiny() ? mappingConfiguration.tinyMappingsWithSrg : mappingConfiguration.tinyMappings, from, to, false);
|
||||
return MappingsService.create(serviceManager, name, LoomGradleExtension.get(project).getPlatformMappingFile(), from, to, false);
|
||||
}
|
||||
|
||||
private final Options options;
|
||||
|
||||
@@ -81,8 +81,8 @@ public class TinyRemapperService implements SharedService {
|
||||
|
||||
extension.getKnownIndyBsms().get().stream().sorted().forEach(joiner::add);
|
||||
|
||||
if (extension.isForge()) {
|
||||
joiner.add("forge");
|
||||
if (extension.isForgeLike()) {
|
||||
joiner.add(extension.getPlatform().get().id());
|
||||
}
|
||||
|
||||
final String id = joiner.toString();
|
||||
|
||||
@@ -74,6 +74,7 @@ public class Constants {
|
||||
public static final String SRG = "srg";
|
||||
public static final String MCP_CONFIG = "mcp";
|
||||
public static final String FORGE = "forge";
|
||||
public static final String NEOFORGE = "neoForge";
|
||||
public static final String FORGE_USERDEV = "forgeUserdev";
|
||||
public static final String FORGE_INSTALLER = "forgeInstaller";
|
||||
public static final String FORGE_UNIVERSAL = "forgeUniversal";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2021-2022 FabricMC
|
||||
* Copyright (c) 2021-2023 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
|
||||
@@ -36,7 +36,8 @@ import net.fabricmc.loom.api.LoomGradleExtensionAPI;
|
||||
public enum ModPlatform {
|
||||
FABRIC(false),
|
||||
FORGE(false),
|
||||
QUILT(true);
|
||||
QUILT(true),
|
||||
NEOFORGE(true);
|
||||
|
||||
boolean experimental;
|
||||
|
||||
@@ -44,10 +45,21 @@ public enum ModPlatform {
|
||||
this.experimental = experimental;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the lowercase ID of this mod platform.
|
||||
*/
|
||||
public String id() {
|
||||
return name().toLowerCase(Locale.ROOT);
|
||||
}
|
||||
|
||||
public boolean isExperimental() {
|
||||
return experimental;
|
||||
}
|
||||
|
||||
public boolean isForgeLike() {
|
||||
return this == FORGE || this == NEOFORGE;
|
||||
}
|
||||
|
||||
public static void assertPlatform(Project project, ModPlatform platform) {
|
||||
assertPlatform(LoomGradleExtension.get(project), platform);
|
||||
}
|
||||
@@ -55,8 +67,8 @@ public enum ModPlatform {
|
||||
public static void assertPlatform(LoomGradleExtensionAPI extension, ModPlatform platform) {
|
||||
assertPlatform(extension, platform, () -> {
|
||||
String msg = "Loom is not running on %s.%nYou can switch to it by adding 'loom.platform = %s' to your gradle.properties";
|
||||
String name = platform.name().toLowerCase(Locale.ROOT);
|
||||
return msg.formatted(name, name);
|
||||
String id = platform.id();
|
||||
return msg.formatted(id, id);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -65,4 +77,14 @@ public enum ModPlatform {
|
||||
throw new GradleException(message.get());
|
||||
}
|
||||
}
|
||||
|
||||
public static void assertForgeLike(LoomGradleExtensionAPI extension) {
|
||||
assertForgeLike(extension, () -> "Loom is not running on a Forge-like platform (Forge or NeoForge).");
|
||||
}
|
||||
|
||||
public static void assertForgeLike(LoomGradleExtensionAPI extension, Supplier<String> message) {
|
||||
if (!extension.getPlatform().get().isForgeLike()) {
|
||||
throw new GradleException(message.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,6 +203,10 @@ public class SourceRemapper {
|
||||
for (Path srgJar : extension.getMinecraftJars(MappingsNamespace.SRG)) {
|
||||
mercury.getClassPath().add(srgJar);
|
||||
}
|
||||
} else if (extension.isNeoForge()) {
|
||||
for (Path mojangJar : extension.getMinecraftJars(MappingsNamespace.MOJANG)) {
|
||||
mercury.getClassPath().add(mojangJar);
|
||||
}
|
||||
}
|
||||
|
||||
Set<File> files = project.getConfigurations()
|
||||
|
||||
@@ -33,6 +33,7 @@ import java.util.function.Consumer;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import dev.architectury.loom.util.MappingOption;
|
||||
import dev.architectury.tinyremapper.IMappingProvider;
|
||||
import dev.architectury.tinyremapper.TinyRemapper;
|
||||
import org.gradle.api.Project;
|
||||
@@ -70,8 +71,8 @@ public final class TinyRemapperHelper {
|
||||
|
||||
public static TinyRemapper getTinyRemapper(Project project, SharedServiceManager serviceManager, String fromM, String toM, boolean fixRecords, Consumer<TinyRemapper.Builder> builderConsumer, Set<String> fromClassNames) throws IOException {
|
||||
LoomGradleExtension extension = LoomGradleExtension.get(project);
|
||||
boolean srg = (fromM.equals(MappingsNamespace.SRG.toString()) || toM.equals(MappingsNamespace.SRG.toString())) && extension.isForge();
|
||||
MemoryMappingTree mappingTree = extension.getMappingConfiguration().getMappingsService(serviceManager, srg).getMappingTree();
|
||||
final MappingOption mappingOption = MappingOption.forPlatform(extension).forNamespaces(fromM, toM);
|
||||
MemoryMappingTree mappingTree = extension.getMappingConfiguration().getMappingsService(serviceManager, mappingOption).getMappingTree();
|
||||
|
||||
if (fixRecords && !mappingTree.getSrcNamespace().equals(fromM)) {
|
||||
throw new IllegalStateException("Mappings src namespace must match remap src namespace");
|
||||
@@ -81,7 +82,7 @@ public final class TinyRemapperHelper {
|
||||
|
||||
TinyRemapper.Builder builder = TinyRemapper.newRemapper()
|
||||
.logUnknownInvokeDynamic(false)
|
||||
.ignoreConflicts(extension.isForge())
|
||||
.ignoreConflicts(extension.isForgeLike())
|
||||
.cacheMappings(true)
|
||||
.threads(Runtime.getRuntime().availableProcessors())
|
||||
.logger(project.getLogger()::lifecycle)
|
||||
@@ -99,7 +100,7 @@ public final class TinyRemapperHelper {
|
||||
return next;
|
||||
});
|
||||
|
||||
if (extension.isForge()) {
|
||||
if (extension.isForgeLike()) {
|
||||
if (!fromClassNames.isEmpty()) {
|
||||
builder.withMappings(InnerClassRemapper.of(fromClassNames, mappingTree, fromM, toM));
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ public final class FabricModJsonFactory {
|
||||
}
|
||||
|
||||
public static boolean isModJar(Path input, ModPlatform platform) {
|
||||
if (platform == ModPlatform.FORGE) {
|
||||
if (platform.isForgeLike()) {
|
||||
return ZipUtils.contains(input, "META-INF/mods.toml");
|
||||
} else if (platform == ModPlatform.QUILT) {
|
||||
return ZipUtils.contains(input, "quilt.mod.json") || isModJar(input, ModPlatform.FABRIC);
|
||||
@@ -180,8 +180,8 @@ public final class FabricModJsonFactory {
|
||||
}
|
||||
|
||||
public static boolean isNestableModJar(Path input, ModPlatform platform) {
|
||||
// Forge don't care if the main jar is mod jar.
|
||||
if (platform == ModPlatform.FORGE) return true;
|
||||
// Forge and NeoForge don't care if the main jar is mod jar.
|
||||
if (platform.isForgeLike()) return true;
|
||||
return isModJar(input, platform);
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ public final class FabricModJsonFactory {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (platform == ModPlatform.FORGE) {
|
||||
if (platform.isForgeLike()) {
|
||||
return Files.exists(fs.getPath("META-INF/mods.toml"));
|
||||
} else if (platform == ModPlatform.QUILT) {
|
||||
return Files.exists(fs.getPath("quilt.mod.json")) || containsMod(fs, ModPlatform.FABRIC);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2020-2021 FabricMC
|
||||
* Copyright (c) 2020-2023 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
|
||||
@@ -34,8 +34,10 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.logging.Logger;
|
||||
|
||||
import net.fabricmc.loom.build.IntermediaryNamespaces;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
import net.fabricmc.loom.util.FileSystemUtil;
|
||||
import net.fabricmc.loom.util.function.CollectionUtil;
|
||||
@@ -47,7 +49,10 @@ import net.fabricmc.mappingio.tree.MappingTree;
|
||||
* @author Juuz
|
||||
*/
|
||||
public final class AtRemapper {
|
||||
public static void remap(Logger logger, Path jar, MappingTree mappings) throws IOException {
|
||||
public static void remap(Project project, Path jar, MappingTree mappings) throws IOException {
|
||||
final Logger logger = project.getLogger();
|
||||
final String sourceNamespace = IntermediaryNamespaces.intermediary(project);
|
||||
|
||||
try (FileSystemUtil.Delegate fs = FileSystemUtil.getJarFileSystem(jar, false)) {
|
||||
Path atPath = fs.getPath(Constants.Forge.ACCESS_TRANSFORMER_PATH);
|
||||
|
||||
@@ -76,7 +81,7 @@ public final class AtRemapper {
|
||||
String name = parts[1].replace('.', '/');
|
||||
parts[1] = CollectionUtil.find(
|
||||
mappings.getClasses(),
|
||||
def -> def.getName("srg").equals(name)
|
||||
def -> def.getName(sourceNamespace).equals(name)
|
||||
).map(def -> def.getName("named")).orElse(name).replace('/', '.');
|
||||
|
||||
if (parts.length >= 3) {
|
||||
@@ -84,7 +89,7 @@ public final class AtRemapper {
|
||||
parts[2] = parts[2].substring(0, parts[2].indexOf('(')) + remapDescriptor(parts[2].substring(parts[2].indexOf('(')), s -> {
|
||||
return CollectionUtil.find(
|
||||
mappings.getClasses(),
|
||||
def -> def.getName("srg").equals(s)
|
||||
def -> def.getName(sourceNamespace).equals(s)
|
||||
).map(def -> def.getName("named")).orElse(s);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2020-2021 FabricMC
|
||||
* Copyright (c) 2020-2023 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
|
||||
@@ -34,15 +34,19 @@ import java.nio.file.StandardOpenOption;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.logging.Logger;
|
||||
|
||||
import net.fabricmc.loom.build.IntermediaryNamespaces;
|
||||
import net.fabricmc.loom.util.FileSystemUtil;
|
||||
import net.fabricmc.loom.util.ModPlatform;
|
||||
import net.fabricmc.loom.util.function.CollectionUtil;
|
||||
import net.fabricmc.mappingio.tree.MappingTree;
|
||||
|
||||
@@ -53,8 +57,12 @@ import net.fabricmc.mappingio.tree.MappingTree;
|
||||
*/
|
||||
public final class CoreModClassRemapper {
|
||||
private static final Pattern CLASS_NAME_PATTERN = Pattern.compile("^(.*')((?:com\\.mojang\\.|net\\.minecraft\\.)[A-Za-z0-9.-_$]+)('.*)$");
|
||||
private static final Pattern REDIRECT_FIELD_TO_METHOD_PATTERN = Pattern.compile("^(.*\\w+\\s*\\.\\s*redirectFieldToMethod\\s*\\(\\s*\\w+\\s*,\\s*')(\\w*)('\\s*,(?:\\s*'(\\w+)'\\s*|.*)\\).*)$");
|
||||
|
||||
public static void remapJar(Project project, ModPlatform platform, Path jar, MappingTree mappings) throws IOException {
|
||||
final Logger logger = project.getLogger();
|
||||
final String sourceNamespace = IntermediaryNamespaces.intermediary(project);
|
||||
|
||||
public static void remapJar(Path jar, MappingTree mappings, Logger logger) throws IOException {
|
||||
try (FileSystemUtil.Delegate fs = FileSystemUtil.getJarFileSystem(jar, false)) {
|
||||
Path coremodsJsonPath = fs.getPath("META-INF", "coremods.json");
|
||||
|
||||
@@ -75,7 +83,7 @@ public final class CoreModClassRemapper {
|
||||
|
||||
if (Files.exists(js)) {
|
||||
logger.info(":remapping coremod '" + file + "'");
|
||||
remap(js, mappings);
|
||||
remap(js, platform, mappings, sourceNamespace);
|
||||
} else {
|
||||
logger.warn("Coremod '" + file + "' listed in coremods.json but not found");
|
||||
}
|
||||
@@ -83,9 +91,10 @@ public final class CoreModClassRemapper {
|
||||
}
|
||||
}
|
||||
|
||||
public static void remap(Path js, MappingTree mappings) throws IOException {
|
||||
public static void remap(Path js, ModPlatform platform, MappingTree mappings, String sourceNamespace) throws IOException {
|
||||
List<String> lines = Files.readAllLines(js);
|
||||
List<String> output = new ArrayList<>(lines);
|
||||
String lastClassName = null;
|
||||
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
String line = lines.get(i);
|
||||
@@ -93,13 +102,39 @@ public final class CoreModClassRemapper {
|
||||
|
||||
if (matcher.matches()) {
|
||||
String className = matcher.group(2).replace('.', '/');
|
||||
String remapped = CollectionUtil.find(mappings.getClasses(), def -> def.getName("srg").equals(className))
|
||||
String remapped = CollectionUtil.find(mappings.getClasses(), def -> def.getName(sourceNamespace).equals(className))
|
||||
.map(def -> def.getName("named"))
|
||||
.orElse(className);
|
||||
lastClassName = remapped;
|
||||
|
||||
if (!className.equals(remapped)) {
|
||||
output.set(i, matcher.group(1) + remapped.replace('/', '.') + matcher.group(3));
|
||||
}
|
||||
} else if (platform == ModPlatform.NEOFORGE && lastClassName != null) {
|
||||
matcher = REDIRECT_FIELD_TO_METHOD_PATTERN.matcher(line);
|
||||
|
||||
if (matcher.matches()) {
|
||||
String fieldName = matcher.group(2);
|
||||
String remapped = Optional.ofNullable(mappings.getClass(lastClassName, mappings.getNamespaceId("named")))
|
||||
.flatMap(clazz -> Optional.ofNullable(clazz.getField(fieldName, null, mappings.getNamespaceId(sourceNamespace))))
|
||||
.map(field -> field.getName("named"))
|
||||
.orElse(fieldName);
|
||||
|
||||
if (!fieldName.equals(remapped)) {
|
||||
String optionalMethod = matcher.group(4);
|
||||
String remappedMethod = optionalMethod == null ? null
|
||||
: Optional.ofNullable(mappings.getClass(lastClassName, mappings.getNamespaceId("named")))
|
||||
.flatMap(clazz -> Optional.ofNullable(clazz.getMethod(optionalMethod, null, mappings.getNamespaceId(sourceNamespace))))
|
||||
.map(method -> method.getName("named"))
|
||||
.orElse(null);
|
||||
|
||||
if (remappedMethod != null) {
|
||||
output.set(i, matcher.group(1) + remapped + matcher.group(3).replace("'" + optionalMethod + "'", "'" + remappedMethod + "'"));
|
||||
} else {
|
||||
output.set(i, matcher.group(1) + remapped + matcher.group(3));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,56 +34,57 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.ListMultimap;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingContext;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.configuration.providers.forge.SrgProvider;
|
||||
import net.fabricmc.loom.util.MappingException;
|
||||
import net.fabricmc.loom.util.function.CollectionUtil;
|
||||
import net.fabricmc.mappingio.FlatMappingVisitor;
|
||||
import net.fabricmc.mappingio.MappingReader;
|
||||
import net.fabricmc.mappingio.MappingVisitor;
|
||||
import net.fabricmc.mappingio.adapter.ForwardingMappingVisitor;
|
||||
import net.fabricmc.mappingio.adapter.MappingNsRenamer;
|
||||
import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch;
|
||||
import net.fabricmc.mappingio.adapter.RegularAsFlatMappingVisitor;
|
||||
import net.fabricmc.mappingio.format.MappingFormat;
|
||||
import net.fabricmc.mappingio.format.Tiny2Writer;
|
||||
import net.fabricmc.mappingio.format.TsrgReader;
|
||||
import net.fabricmc.mappingio.tree.MappingTree;
|
||||
import net.fabricmc.mappingio.tree.MappingTreeView;
|
||||
import net.fabricmc.mappingio.tree.MemoryMappingTree;
|
||||
|
||||
/**
|
||||
* Merges a Tiny file with an SRG file.
|
||||
* Merges a Tiny file with a new namespace.
|
||||
*
|
||||
* @author Juuz
|
||||
*/
|
||||
public final class SrgMerger {
|
||||
public final class ForgeMappingsMerger {
|
||||
private static final List<String> INPUT_NAMESPACES = List.of("official", "intermediary", "named");
|
||||
private final MemoryMappingTree srg;
|
||||
private final MemoryMappingTree newNs;
|
||||
private final MemoryMappingTree src;
|
||||
private final MemoryMappingTree output;
|
||||
private final FlatMappingVisitor flatOutput;
|
||||
private final boolean lenient;
|
||||
private final @Nullable MemoryMappingTree extra;
|
||||
private final ListMultimap<SrgMethodKey, MethodData> methodsBySrgName;
|
||||
private final ListMultimap<MethodKey, MethodData> methodsByNewNs;
|
||||
|
||||
private SrgMerger(Path srg, Path tiny, @Nullable ExtraMappings extraMappings, boolean lenient) throws IOException {
|
||||
this.srg = readSrg(srg);
|
||||
this.src = new MemoryMappingTree();
|
||||
private ForgeMappingsMerger(MemoryMappingTree newNs, MemoryMappingTree src, @Nullable ExtraMappings extraMappings, boolean lenient) throws IOException {
|
||||
this.newNs = newNs;
|
||||
Preconditions.checkArgument(this.newNs.getDstNamespaces().size() == 1, "New namespace must have exactly one destination namespace");
|
||||
this.src = src;
|
||||
this.output = new MemoryMappingTree();
|
||||
this.flatOutput = new RegularAsFlatMappingVisitor(output);
|
||||
this.lenient = lenient;
|
||||
this.methodsBySrgName = ArrayListMultimap.create();
|
||||
this.methodsByNewNs = ArrayListMultimap.create();
|
||||
|
||||
if (extraMappings != null) {
|
||||
this.extra = new MemoryMappingTree();
|
||||
MappingSourceNsSwitch nsSwitch = new MappingSourceNsSwitch(extra, "official");
|
||||
MappingVisitor visitor = nsSwitch;
|
||||
MappingVisitor visitor = new MappingSourceNsSwitch(this.extra, MappingsNamespace.OFFICIAL.toString());
|
||||
|
||||
if (!extraMappings.hasCorrectNamespaces()) {
|
||||
Map<String, String> namespaces = Map.of(
|
||||
@@ -98,33 +99,37 @@ public final class SrgMerger {
|
||||
this.extra = null;
|
||||
}
|
||||
|
||||
MappingReader.read(tiny, this.src);
|
||||
checkInputNamespaces(tiny);
|
||||
|
||||
this.output.visitNamespaces(this.src.getSrcNamespace(), Stream.concat(Stream.of("srg"), this.src.getDstNamespaces().stream()).collect(Collectors.toList()));
|
||||
var newDstNamespaces = new ArrayList<String>();
|
||||
newDstNamespaces.add(this.newNs.getDstNamespaces().get(0));
|
||||
newDstNamespaces.addAll(this.src.getDstNamespaces());
|
||||
this.output.visitNamespaces(this.src.getSrcNamespace(), newDstNamespaces);
|
||||
}
|
||||
|
||||
private void checkInputNamespaces(Path tiny) {
|
||||
List<String> inputNamespaces = new ArrayList<>(this.src.getDstNamespaces());
|
||||
inputNamespaces.add(0, this.src.getSrcNamespace());
|
||||
private static MemoryMappingTree readInput(Path tiny) throws IOException {
|
||||
MemoryMappingTree src = new MemoryMappingTree();
|
||||
MappingReader.read(tiny, src);
|
||||
List<String> inputNamespaces = new ArrayList<>(src.getDstNamespaces());
|
||||
inputNamespaces.add(0, src.getSrcNamespace());
|
||||
|
||||
if (!inputNamespaces.equals(INPUT_NAMESPACES)) {
|
||||
throw new MappingException("Mapping file " + tiny + " does not have 'official, intermediary, named' as its namespaces! Found: " + inputNamespaces);
|
||||
}
|
||||
|
||||
return src;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a destination name array where the first element
|
||||
* will be the srg name of the mapping element.
|
||||
* will be the new namespace name of the mapping element.
|
||||
*/
|
||||
private String[] createDstNameArray(MappingTree.ElementMappingView srg) {
|
||||
private String[] createDstNameArray(MappingTree.ElementMappingView newNs) {
|
||||
String[] dstNames = new String[output.getDstNamespaces().size()];
|
||||
dstNames[0] = srg.getDstName(0);
|
||||
dstNames[0] = newNs.getDstName(0);
|
||||
return dstNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies all the non-srg destination names from an element.
|
||||
* Copies all the original destination names from an element.
|
||||
*/
|
||||
private void copyDstNames(String[] dstNames, MappingTreeView.ElementMappingView from) {
|
||||
for (int i = 1; i < dstNames.length; i++) {
|
||||
@@ -135,37 +140,37 @@ public final class SrgMerger {
|
||||
/**
|
||||
* Fills in an array of destination names with the element's source name.
|
||||
*/
|
||||
private void fillMappings(String[] names, MappingTree.ElementMappingView srg) {
|
||||
private void fillMappings(String[] names, MappingTree.ElementMappingView newNs) {
|
||||
for (int i = 1; i < names.length; i++) {
|
||||
names[i] = srg.getSrcName();
|
||||
names[i] = newNs.getSrcName();
|
||||
}
|
||||
}
|
||||
|
||||
public MemoryMappingTree merge() throws IOException {
|
||||
for (MappingTree.ClassMapping srgClass : srg.getClasses()) {
|
||||
String[] dstNames = createDstNameArray(srgClass);
|
||||
MappingTree.ClassMapping tinyClass = src.getClass(srgClass.getSrcName());
|
||||
for (MappingTree.ClassMapping newNsClass : newNs.getClasses()) {
|
||||
String[] dstNames = createDstNameArray(newNsClass);
|
||||
MappingTree.ClassMapping tinyClass = src.getClass(newNsClass.getSrcName());
|
||||
String comment = null;
|
||||
|
||||
if (tinyClass != null) {
|
||||
copyDstNames(dstNames, tinyClass);
|
||||
comment = tinyClass.getComment();
|
||||
} else if (lenient) {
|
||||
// Tiny class not found, we'll just use srg names
|
||||
fillMappings(dstNames, srgClass);
|
||||
// Tiny class not found, we'll just use new namespace names
|
||||
fillMappings(dstNames, newNsClass);
|
||||
} else {
|
||||
throw new MappingException("Could not find class " + srgClass.getSrcName() + "|" + srgClass.getDstName(0));
|
||||
throw new MappingException("Could not find class " + newNsClass.getSrcName() + "|" + newNsClass.getDstName(0));
|
||||
}
|
||||
|
||||
flatOutput.visitClass(srgClass.getSrcName(), dstNames);
|
||||
if (comment != null) flatOutput.visitClassComment(srgClass.getSrcName(), comment);
|
||||
flatOutput.visitClass(newNsClass.getSrcName(), dstNames);
|
||||
if (comment != null) flatOutput.visitClassComment(newNsClass.getSrcName(), comment);
|
||||
|
||||
for (MappingTree.FieldMapping field : srgClass.getFields()) {
|
||||
mergeField(srgClass, field, tinyClass);
|
||||
for (MappingTree.FieldMapping field : newNsClass.getFields()) {
|
||||
mergeField(newNsClass, field, tinyClass);
|
||||
}
|
||||
|
||||
for (MappingTree.MethodMapping method : srgClass.getMethods()) {
|
||||
mergeMethod(srgClass, method, tinyClass);
|
||||
for (MappingTree.MethodMapping method : newNsClass.getMethods()) {
|
||||
mergeMethod(newNsClass, method, tinyClass);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,20 +179,20 @@ public final class SrgMerger {
|
||||
return output;
|
||||
}
|
||||
|
||||
private void mergeField(MappingTree.ClassMapping srgClass, MappingTree.FieldMapping srgField, @Nullable MappingTree.ClassMapping tinyClass) throws IOException {
|
||||
String[] dstNames = createDstNameArray(srgField);
|
||||
private void mergeField(MappingTree.ClassMapping newNsClass, MappingTree.FieldMapping newNsField, @Nullable MappingTree.ClassMapping tinyClass) throws IOException {
|
||||
String[] dstNames = createDstNameArray(newNsField);
|
||||
MappingTree.FieldMapping tinyField = null;
|
||||
String srcDesc = srgField.getSrcDesc();
|
||||
String srcDesc = newNsField.getSrcDesc();
|
||||
String comment = null;
|
||||
|
||||
if (tinyClass != null) {
|
||||
if (srcDesc != null) {
|
||||
tinyField = tinyClass.getField(srgField.getSrcName(), srgField.getSrcDesc());
|
||||
tinyField = tinyClass.getField(newNsField.getSrcName(), newNsField.getSrcDesc());
|
||||
} else {
|
||||
tinyField = CollectionUtil.find(tinyClass.getFields(), field -> field.getSrcName().equals(srgField.getSrcName())).orElse(null);
|
||||
tinyField = CollectionUtil.find(tinyClass.getFields(), field -> field.getSrcName().equals(newNsField.getSrcName())).orElse(null);
|
||||
}
|
||||
} else if (!lenient) {
|
||||
throw new MappingException("Could not find field " + srgClass.getDstName(0) + '.' + srgField.getDstName(0) + ' ' + srgField.getDstDesc(0));
|
||||
throw new MappingException("Could not find field " + newNsClass.getDstName(0) + '.' + newNsField.getDstName(0) + ' ' + newNsField.getDstDesc(0));
|
||||
}
|
||||
|
||||
if (tinyField != null) {
|
||||
@@ -195,27 +200,27 @@ public final class SrgMerger {
|
||||
srcDesc = tinyField.getSrcDesc();
|
||||
comment = tinyField.getComment();
|
||||
} else {
|
||||
fillMappings(dstNames, srgField);
|
||||
fillMappings(dstNames, newNsField);
|
||||
}
|
||||
|
||||
if (srcDesc != null) {
|
||||
flatOutput.visitField(srgClass.getSrcName(), srgField.getSrcName(), srcDesc, dstNames);
|
||||
if (comment != null) flatOutput.visitFieldComment(srgClass.getSrcName(), srgField.getSrcName(), srcDesc, comment);
|
||||
flatOutput.visitField(newNsClass.getSrcName(), newNsField.getSrcName(), srcDesc, dstNames);
|
||||
if (comment != null) flatOutput.visitFieldComment(newNsClass.getSrcName(), newNsField.getSrcName(), srcDesc, comment);
|
||||
} else if (!lenient) {
|
||||
throw new MappingException("Could not find descriptor for field " + srgClass.getDstName(0) + '.' + srgField.getDstName(0));
|
||||
throw new MappingException("Could not find descriptor for field " + newNsClass.getDstName(0) + '.' + newNsField.getDstName(0));
|
||||
}
|
||||
}
|
||||
|
||||
private void mergeMethod(MappingTree.ClassMapping srgClass, MappingTree.MethodMapping srgMethod, @Nullable MappingTree.ClassMapping tinyClass) throws IOException {
|
||||
String[] dstNames = createDstNameArray(srgMethod);
|
||||
private void mergeMethod(MappingTree.ClassMapping newNsClass, MappingTree.MethodMapping newNsMethod, @Nullable MappingTree.ClassMapping tinyClass) throws IOException {
|
||||
String[] dstNames = createDstNameArray(newNsMethod);
|
||||
MappingTree.MethodMapping tinyMethod = null;
|
||||
String intermediaryName, namedName;
|
||||
String comment = null;
|
||||
|
||||
if (tinyClass != null) {
|
||||
tinyMethod = tinyClass.getMethod(srgMethod.getSrcName(), srgMethod.getSrcDesc());
|
||||
tinyMethod = tinyClass.getMethod(newNsMethod.getSrcName(), newNsMethod.getSrcDesc());
|
||||
} else if (!lenient) {
|
||||
throw new MappingException("Could not find method " + srgClass.getDstName(0) + '.' + srgMethod.getDstName(0) + ' ' + srgMethod.getDstDesc(0));
|
||||
throw new MappingException("Could not find method " + newNsClass.getDstName(0) + '.' + newNsMethod.getDstName(0) + ' ' + newNsMethod.getDstDesc(0));
|
||||
}
|
||||
|
||||
if (tinyMethod != null) {
|
||||
@@ -224,7 +229,7 @@ public final class SrgMerger {
|
||||
namedName = tinyMethod.getName("named");
|
||||
comment = tinyMethod.getComment();
|
||||
} else {
|
||||
if (srgMethod.getSrcName().equals(srgMethod.getDstName(0))) {
|
||||
if (newNsMethod.getSrcName().equals(newNsMethod.getDstName(0))) {
|
||||
// These are only methods like <init> or toString which have the same name in every NS.
|
||||
// We can safely ignore those.
|
||||
return;
|
||||
@@ -233,7 +238,7 @@ public final class SrgMerger {
|
||||
@Nullable MappingTree.MethodMapping fillMethod = null;
|
||||
|
||||
if (extra != null) {
|
||||
MappingTree.MethodMapping extraMethod = extra.getMethod(srgClass.getSrcName(), srgMethod.getSrcName(), srgMethod.getSrcDesc());
|
||||
MappingTree.MethodMapping extraMethod = extra.getMethod(newNsClass.getSrcName(), newNsMethod.getSrcName(), newNsMethod.getSrcDesc());
|
||||
|
||||
if (extraMethod != null && extraMethod.getSrcName().equals(extraMethod.getDstName(0))) {
|
||||
fillMethod = extraMethod;
|
||||
@@ -246,33 +251,33 @@ public final class SrgMerger {
|
||||
} else {
|
||||
// Do not allow missing methods as these are typically subclass methods and cause issues where
|
||||
// class B extends A, and overrides a method from the superclass. Then the subclass method
|
||||
// DOES get a srg name but not a yarn/intermediary name.
|
||||
// DOES get a new namespace name but not a yarn/intermediary name.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!srgMethod.getSrcName().equals(dstNames[0])) { // ignore <init> and the likes
|
||||
methodsBySrgName.put(
|
||||
new SrgMethodKey(dstNames[0], srgMethod.getSrcDesc()),
|
||||
new MethodData(srgClass.getSrcName(), srgMethod.getSrcName(), srgMethod.getSrcDesc(), tinyMethod != null, intermediaryName, namedName)
|
||||
if (!newNsMethod.getSrcName().equals(dstNames[0])) { // ignore <init> and the likes
|
||||
methodsByNewNs.put(
|
||||
new MethodKey(dstNames[0], newNsMethod.getSrcDesc()),
|
||||
new MethodData(newNsClass.getSrcName(), newNsMethod.getSrcName(), newNsMethod.getSrcDesc(), tinyMethod != null, intermediaryName, namedName)
|
||||
);
|
||||
}
|
||||
|
||||
flatOutput.visitMethod(srgClass.getSrcName(), srgMethod.getSrcName(), srgMethod.getSrcDesc(), dstNames);
|
||||
if (comment != null) flatOutput.visitMethodComment(srgClass.getSrcName(), srgMethod.getSrcName(), srgMethod.getSrcDesc(), comment);
|
||||
flatOutput.visitMethod(newNsClass.getSrcName(), newNsMethod.getSrcName(), newNsMethod.getSrcDesc(), dstNames);
|
||||
if (comment != null) flatOutput.visitMethodComment(newNsClass.getSrcName(), newNsMethod.getSrcName(), newNsMethod.getSrcDesc(), comment);
|
||||
|
||||
if (tinyMethod != null) {
|
||||
for (MappingTree.MethodArgMapping arg : tinyMethod.getArgs()) {
|
||||
String[] argDstNames = new String[output.getDstNamespaces().size()];
|
||||
copyDstNames(argDstNames, arg);
|
||||
flatOutput.visitMethodArg(
|
||||
srgClass.getSrcName(), srgMethod.getSrcName(), srgMethod.getSrcDesc(),
|
||||
newNsClass.getSrcName(), newNsMethod.getSrcName(), newNsMethod.getSrcDesc(),
|
||||
arg.getArgPosition(), arg.getLvIndex(), arg.getSrcName(), argDstNames
|
||||
);
|
||||
|
||||
if (arg.getComment() != null) {
|
||||
flatOutput.visitMethodArgComment(
|
||||
srgClass.getSrcName(), srgMethod.getSrcName(), srgMethod.getSrcDesc(),
|
||||
newNsClass.getSrcName(), newNsMethod.getSrcName(), newNsMethod.getSrcDesc(),
|
||||
arg.getArgPosition(), arg.getLvIndex(), arg.getSrcName(),
|
||||
arg.getComment()
|
||||
);
|
||||
@@ -282,14 +287,14 @@ public final class SrgMerger {
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves conflicts where multiple methods map to an SRG method.
|
||||
* Resolves conflicts where multiple methods map to a method in the new namespace.
|
||||
* We will prefer the ones with the Tiny mappings.
|
||||
*/
|
||||
private void resolveConflicts() {
|
||||
List<String> conflicts = new ArrayList<>();
|
||||
|
||||
for (SrgMethodKey srg : methodsBySrgName.keySet()) {
|
||||
List<MethodData> methods = methodsBySrgName.get(srg);
|
||||
for (MethodKey methodKey : methodsByNewNs.keySet()) {
|
||||
List<MethodData> methods = methodsByNewNs.get(methodKey);
|
||||
if (methods.size() == 1) continue;
|
||||
|
||||
// Determine whether the names conflict
|
||||
@@ -326,8 +331,8 @@ public final class SrgMerger {
|
||||
List<MethodData> hasTiny = CollectionUtil.filter(methods, MethodData::hasTiny);
|
||||
|
||||
// Record conflicts if needed
|
||||
if (hasTiny.size() > 1) { // Multiple methods map to this SRG name
|
||||
// Sometimes unrelated methods share an SRG name. Probably overrides from a past version?
|
||||
if (hasTiny.size() > 1) { // Multiple methods map to this new name
|
||||
// Sometimes unrelated methods share a SRG name. Probably overrides from a past version?
|
||||
Set<String> intermediaryNames = new HashSet<>();
|
||||
|
||||
for (MethodData method : methods) {
|
||||
@@ -337,7 +342,7 @@ public final class SrgMerger {
|
||||
// Only record a conflict if we map one intermediary name with multiple named names
|
||||
if (intermediaryNames.size() == 1) {
|
||||
StringBuilder message = new StringBuilder();
|
||||
message.append("- multiple preferred methods for ").append(srg).append(':');
|
||||
message.append("- multiple preferred methods for ").append(newNs).append(':');
|
||||
|
||||
for (MethodData preferred : hasTiny) {
|
||||
message.append("\n\t> ").append(preferred);
|
||||
@@ -347,50 +352,14 @@ public final class SrgMerger {
|
||||
}
|
||||
|
||||
return null;
|
||||
} else if (hasTiny.isEmpty()) { // No methods map to this SRG name
|
||||
conflictReporter.accept("- no preferred methods found for " + srg + ", available: " + methods);
|
||||
} else if (hasTiny.isEmpty()) { // No methods map to this new name
|
||||
conflictReporter.accept("- no preferred methods found for " + newNs + ", available: " + methods);
|
||||
return null;
|
||||
}
|
||||
|
||||
return hasTiny.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges SRG mappings with a tiny mappings tree through the obf names.
|
||||
* This overload writes the mappings into a file.
|
||||
*
|
||||
* <p>The namespaces in the tiny file should be {@code official, intermediary, named}.
|
||||
* The SRG names will add a new namespace called {@code srg} so that the final namespaces
|
||||
* are {@code official, srg, intermediary, named}.
|
||||
*
|
||||
* <p>This method does not include local variables in the output.
|
||||
* It can, however, be used for remapping the game jar since it has all
|
||||
* classes, methods, fields, parameters and javadoc comments.
|
||||
*
|
||||
* <p>If {@code lenient} is true, the merger will not error when encountering names not present
|
||||
* in the tiny mappings. Instead, the names will be filled from the {@code official} namespace.
|
||||
*
|
||||
* @param srg the SRG file in .tsrg format
|
||||
* @param tiny the tiny file
|
||||
* @param out the output file, will be in tiny v2
|
||||
* @param extraMappings an extra mappings file that will be used to determine
|
||||
* whether an unobfuscated name is needed in the result file
|
||||
* @param lenient whether lenient mode is enabled
|
||||
* @throws IOException if an IO error occurs while reading or writing the mappings
|
||||
* @throws MappingException if the input tiny mappings' namespaces are incorrect
|
||||
* or if an element mentioned in the SRG file does not have tiny mappings in non-lenient mode
|
||||
*/
|
||||
public static void mergeSrg(Path srg, Path tiny, Path out, @Nullable ExtraMappings extraMappings, boolean lenient)
|
||||
throws IOException, MappingException {
|
||||
MemoryMappingTree tree = mergeSrg(srg, tiny, extraMappings, lenient);
|
||||
|
||||
try (Tiny2Writer writer = new Tiny2Writer(Files.newBufferedWriter(out), false)) {
|
||||
tree.accept(writer);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges SRG mappings with a tiny mappings tree through the obf names.
|
||||
* This overload returns a {@link MemoryMappingTree} of the merged mappings.
|
||||
@@ -418,20 +387,29 @@ public final class SrgMerger {
|
||||
*/
|
||||
public static MemoryMappingTree mergeSrg(Path srg, Path tiny, @Nullable ExtraMappings extraMappings, boolean lenient)
|
||||
throws IOException, MappingException {
|
||||
return new SrgMerger(srg, tiny, extraMappings, lenient).merge();
|
||||
return new ForgeMappingsMerger(readSrg(srg), readInput(tiny), extraMappings, lenient).merge();
|
||||
}
|
||||
|
||||
private MemoryMappingTree readSrg(Path srg) throws IOException {
|
||||
public static MemoryMappingTree mergeMojang(MappingContext context, Path tiny, @Nullable ExtraMappings extraMappings, boolean lenient)
|
||||
throws IOException, MappingException {
|
||||
MemoryMappingTree mojang = new MemoryMappingTree();
|
||||
SrgProvider.visitMojangMappings(new MappingNsRenamer(mojang, Map.of(MappingsNamespace.NAMED.toString(), MappingsNamespace.MOJANG.toString())), context);
|
||||
return new ForgeMappingsMerger(mojang, readInput(tiny), extraMappings, lenient).merge();
|
||||
}
|
||||
|
||||
private static MemoryMappingTree readSrg(Path srg) throws IOException {
|
||||
try (BufferedReader reader = Files.newBufferedReader(srg)) {
|
||||
MemoryMappingTree tsrg = new MemoryMappingTree();
|
||||
MemoryMappingTree temp = new MemoryMappingTree();
|
||||
TsrgReader.read(reader, temp);
|
||||
Map<String, String> namespaces = Map.of(
|
||||
temp.getSrcNamespace(), MappingsNamespace.OFFICIAL.toString(),
|
||||
temp.getDstNamespaces().get(0), MappingsNamespace.SRG.toString()
|
||||
);
|
||||
temp.accept(new MappingNsRenamer(tsrg, namespaces));
|
||||
return tsrg;
|
||||
MemoryMappingTree output = new MemoryMappingTree();
|
||||
TsrgReader.read(reader, new ForwardingMappingVisitor(output) {
|
||||
// Override the namespaces to be official -> srg
|
||||
@Override
|
||||
public void visitNamespaces(String srcNamespace, List<String> dstNamespaces) throws IOException {
|
||||
List<String> newDstNamespaces = new ArrayList<>(dstNamespaces);
|
||||
newDstNamespaces.set(0, MappingsNamespace.SRG.toString());
|
||||
super.visitNamespaces(MappingsNamespace.OFFICIAL.toString(), newDstNamespaces);
|
||||
}
|
||||
});
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -445,7 +423,7 @@ public final class SrgMerger {
|
||||
}
|
||||
}
|
||||
|
||||
private record SrgMethodKey(String name, String desc) {
|
||||
private record MethodKey(String name, String desc) {
|
||||
@Override
|
||||
public String toString() {
|
||||
return name + desc;
|
||||
Reference in New Issue
Block a user