diff --git a/build.gradle b/build.gradle index 261ca55..a491a6e 100644 --- a/build.gradle +++ b/build.gradle @@ -58,7 +58,7 @@ dependencies { implementation(include("io.github.llamalad7:mixinextras-fabric:${project.mixin_extras_version}")) implementation(include("com.github.thecatcore.CursedMixinExtensions:fabric:1.0.0")) - implementation(include("com.github.thecatcore:WFVAIO:1.1.0")) + implementation(include("com.github.thecatcore:WFVAIO:1.2.0")) testImplementation "net.fabricmc:fabric-loader-junit:${project.loader_version}" } @@ -163,3 +163,11 @@ Now allow ModRemappers to disable mixin remapping which is enabled by default fo embedded.version "spasm", project.spasm_version } } + +task testmodJar(type: Jar) { + from sourceSets.test.output + destinationDirectory = project.layout.buildDirectory.dir("libs") + archiveClassifier.set("testmod") +} + +build.dependsOn testmodJar \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index a6d695d..d2005f4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties minecraft_version = 1.6.4 yarn_build = 458 - loader_version = 0.15.10 + loader_version = 0.16.11 fabric_version = 1.9.1+1.12.2 mixin_extras_version=0.2.1 spasm_version=0.2 diff --git a/src/main/java/fr/catcore/modremapperapi/utils/Constants.java b/src/main/java/fr/catcore/modremapperapi/utils/Constants.java index e92f42e..26f2225 100644 --- a/src/main/java/fr/catcore/modremapperapi/utils/Constants.java +++ b/src/main/java/fr/catcore/modremapperapi/utils/Constants.java @@ -6,13 +6,20 @@ import java.io.File; public class Constants { + @Deprecated public static final File MAIN_FOLDER = CacheUtils.BASE_FOLDER.toFile(); + @Deprecated public static final File VERSIONED_FOLDER = CacheUtils.MAIN_FOLDER.toFile(); + @Deprecated public static final File LIB_FOLDER = CacheUtils.LIBRARY_FOLDER.toFile(); + @Deprecated public static final File EXTRA_MAPPINGS_FILE = CacheUtils.getCachePath("extra_mappings.tiny").toFile(); + @Deprecated public static final File REMAPPED_MAPPINGS_FILE = CacheUtils.getCachePath("remapped_mappings.tiny").toFile(); + @Deprecated public static final File MC_MAPPINGS_FILE = CacheUtils.getCachePath("mc_mappings.tiny").toFile(); + @Deprecated public static final File FULL_MAPPINGS_FILE = CacheUtils.getCachePath("full_mappings.tiny").toFile(); public static final Logger MAIN_LOGGER = Logger.get("ModRemappingAPI"); diff --git a/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/api/v2/CacheHandler.java b/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/api/v2/CacheHandler.java new file mode 100644 index 0000000..52c2b6c --- /dev/null +++ b/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/api/v2/CacheHandler.java @@ -0,0 +1,15 @@ +package io.github.fabriccompatibilitylayers.modremappingapi.api.v2; + +import io.github.fabriccompatibiltylayers.modremappingapi.impl.context.BaseModRemapperContext; + +import java.nio.file.Path; + +public interface CacheHandler { + Path resolveTemp(String name); + Path resolveCache(String name); + Path resolveLibrary(String name); + + static CacheHandler getCacheHandler(String contextId) { + return BaseModRemapperContext.get(contextId).getCacheHandler(); + } +} diff --git a/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/api/v2/MappingBuilder.java b/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/api/v2/MappingBuilder.java new file mode 100644 index 0000000..3410f96 --- /dev/null +++ b/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/api/v2/MappingBuilder.java @@ -0,0 +1,14 @@ +package io.github.fabriccompatibilitylayers.modremappingapi.api.v2; + +public interface MappingBuilder { + + ClassMapping addMapping(String sourceName, String targetName); + ClassMapping addMapping(String name); + + public interface ClassMapping { + ClassMapping field(String sourceName, String targetName, String sourceDescriptor); + ClassMapping field(String name, String descriptor); + ClassMapping method(String sourceName, String targetName, String sourceDescriptor); + ClassMapping method(String name, String descriptor); + } +} diff --git a/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/api/v2/MappingUtils.java b/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/api/v2/MappingUtils.java new file mode 100644 index 0000000..1cb791c --- /dev/null +++ b/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/api/v2/MappingUtils.java @@ -0,0 +1,90 @@ +package io.github.fabriccompatibilitylayers.modremappingapi.api.v2; + +import io.github.fabriccompatibiltylayers.modremappingapi.impl.MappingsUtilsImpl; +import org.jetbrains.annotations.Nullable; + +public interface MappingUtils { + /** + * + * @param className original class name + * @return remapped class name + */ + static String mapClass(String contextId, String className) { + return MappingsUtilsImpl.mapClass(MappingsUtilsImpl.getMappingsRegistry(contextId), className); + } + + /** + * + * @param className remapped class name + * @return original class name + */ + static String unmapClass(String contextId, String className) { + return MappingsUtilsImpl.unmapClass(MappingsUtilsImpl.getMappingsRegistry(contextId), className); + } + + /** + * + * @param className original class name + * @param fieldName + * @param fieldDesc + * @return + */ + static ClassMember mapField(String contextId, String className, String fieldName, @Nullable String fieldDesc) { + return MappingsUtilsImpl.mapField(MappingsUtilsImpl.getMappingsRegistry(contextId), className, fieldName, fieldDesc); + } + + /** + * + * @param className remapped class name + * @param fieldName + * @param fieldDesc + * @return + */ + static ClassMember mapFieldFromRemappedClass(String contextId, String className, String fieldName, @Nullable String fieldDesc) { + return MappingsUtilsImpl.mapFieldFromRemappedClass(MappingsUtilsImpl.getMappingsRegistry(contextId), className, fieldName, fieldDesc); + } + + /** + * + * @param className original class name + * @param methodName + * @param methodDesc + * @return + */ + static ClassMember mapMethod(String contextId, String className, String methodName, String methodDesc) { + return MappingsUtilsImpl.mapMethod(MappingsUtilsImpl.getMappingsRegistry(contextId), className, methodName, methodDesc); + } + + /** + * + * @param className remapped class name + * @param methodName + * @param methodDesc + * @return + */ + static ClassMember mapMethodFromRemappedClass(String contextId, String className, String methodName, String methodDesc) { + return MappingsUtilsImpl.mapMethodFromRemappedClass(MappingsUtilsImpl.getMappingsRegistry(contextId), className, methodName, methodDesc); + } + + static ClassMember mapField(String contextId, Class owner, String fieldName) { + return MappingsUtilsImpl.mapField(MappingsUtilsImpl.getMappingsRegistry(contextId), owner, fieldName); + } + + static ClassMember mapMethod(String contextId, Class owner, String methodName, Class[] parameterTypes) { + return MappingsUtilsImpl.mapMethod(MappingsUtilsImpl.getMappingsRegistry(contextId), owner, methodName, parameterTypes); + } + + /** + * + * @param desc original descriptor + * @return remapped descriptor + */ + static String mapDescriptor(String contextId, String desc) { + return MappingsUtilsImpl.mapDescriptor(MappingsUtilsImpl.getMappingsRegistry(contextId), desc); + } + + interface ClassMember { + String getName(); + @Nullable String getDesc(); + } +} diff --git a/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/api/v2/MappingsConfig.java b/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/api/v2/MappingsConfig.java new file mode 100644 index 0000000..08c3f5e --- /dev/null +++ b/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/api/v2/MappingsConfig.java @@ -0,0 +1,18 @@ +package io.github.fabriccompatibilitylayers.modremappingapi.api.v2; + +import io.github.fabriccompatibilitylayers.modremappingapi.impl.DefaultMappingsConfig; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; +import java.util.function.Supplier; + +public interface MappingsConfig { + @Nullable String getSourceNamespace(); + @Nullable Supplier getExtraMappings(); + Map getRenamingMap(); + @Nullable String getDefaultPackage(); + + static MappingsConfig defaultConfig() { + return new DefaultMappingsConfig(); + } +} diff --git a/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/api/v2/ModCandidate.java b/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/api/v2/ModCandidate.java new file mode 100644 index 0000000..e35596a --- /dev/null +++ b/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/api/v2/ModCandidate.java @@ -0,0 +1,22 @@ +package io.github.fabriccompatibilitylayers.modremappingapi.api.v2; + +import org.jetbrains.annotations.Nullable; + +import java.nio.file.Path; + +public interface ModCandidate { + String getId(); + Path getPath(); + String getType(); + @Nullable String getAccessWidenerPath(); + @Nullable ModCandidate getParent(); + @Nullable String getVersion(); + @Nullable String getParentSubPath(); + String getDestinationName(); + ModDiscovererConfig getDiscovererConfig(); + void setAccessWidener(byte[] data); + byte @Nullable [] getAccessWidener(); + void setDestination(Path destination); + @Nullable Path getDestination(); + void setPath(Path path); +} diff --git a/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/api/v2/ModDiscovererConfig.java b/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/api/v2/ModDiscovererConfig.java new file mode 100644 index 0000000..57da7b9 --- /dev/null +++ b/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/api/v2/ModDiscovererConfig.java @@ -0,0 +1,39 @@ +package io.github.fabriccompatibilitylayers.modremappingapi.api.v2; + +import io.github.fabriccompatibilitylayers.modremappingapi.impl.ModDiscovererConfigImpl; + +import java.nio.file.Path; +import java.util.List; +import java.util.function.BiFunction; +import java.util.function.Predicate; +import java.util.regex.Pattern; + +public interface ModDiscovererConfig { + static Builder builder(String folderName) { + return new ModDiscovererConfigImpl.BuilderImpl(folderName); + } + + String getFolderName(); + Pattern getFileNameMatcher(); + boolean searchRecursively(); + Predicate getDirectoryFilter(); + Collector getCandidateCollector(); + boolean getExportToOriginalFolder(); + boolean allowDirectoryMods(); + + interface Builder { + Builder fileNameMatcher(String pattern); + Builder searchRecursively(boolean searchRecursively); + Builder directoryFilter(Predicate filter); + Builder candidateCollector(Collector collector); + Builder exportToOriginalFolder(boolean exportToOriginalFolder); + Builder allowDirectoryMods(boolean allowDirectoryMods); + + ModDiscovererConfig build(); + } + + @FunctionalInterface + interface Collector { + List collect(ModDiscovererConfig config, Path modPath, List entries); + } +} diff --git a/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/api/v2/ModRemapper.java b/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/api/v2/ModRemapper.java new file mode 100644 index 0000000..468bac7 --- /dev/null +++ b/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/api/v2/ModRemapper.java @@ -0,0 +1,23 @@ +package io.github.fabriccompatibilitylayers.modremappingapi.api.v2; + +import net.fabricmc.api.EnvType; + +import java.util.List; + +public interface ModRemapper { + String getContextId(); + + void init(CacheHandler cacheHandler); + + List getModDiscoverers(); + List collectSubRemappers(List discoveredMods); + MappingsConfig getMappingsConfig(); + List getRemappingFlags(); + void afterRemapping(); + void afterAllRemappings(); + + void addRemappingLibraries(List libraries, EnvType environment); + void registerAdditionalMappings(MappingBuilder mappingBuilder); + void registerPreVisitors(VisitorInfos visitorInfos); + void registerPostVisitors(VisitorInfos visitorInfos); +} diff --git a/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/api/v2/RemapLibrary.java b/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/api/v2/RemapLibrary.java new file mode 100644 index 0000000..48187d6 --- /dev/null +++ b/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/api/v2/RemapLibrary.java @@ -0,0 +1,26 @@ +package io.github.fabriccompatibilitylayers.modremappingapi.api.v2; + +import io.github.fabriccompatibilitylayers.modremappingapi.impl.DefaultRemapLibrary; +import org.jetbrains.annotations.Nullable; + +import java.nio.file.Path; +import java.util.List; + +public interface RemapLibrary { + @Nullable String getURL(); + @Nullable Path getPath(); + String getFileName(); + List getToExclude(); + + static RemapLibrary of(Path path, String fileName) { + return new DefaultRemapLibrary(path, fileName); + } + + static RemapLibrary of(Path path, String fileName, List toExclude) { + return new DefaultRemapLibrary(path, fileName, toExclude); + } + + static RemapLibrary of(String url, String fileName, List toExclude) { + return new DefaultRemapLibrary(url, fileName, toExclude); + } +} diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/RemappingFlags.java b/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/api/v2/RemappingFlags.java similarity index 63% rename from src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/RemappingFlags.java rename to src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/api/v2/RemappingFlags.java index 06446b6..16d1e4b 100644 --- a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/RemappingFlags.java +++ b/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/api/v2/RemappingFlags.java @@ -1,4 +1,4 @@ -package io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper; +package io.github.fabriccompatibilitylayers.modremappingapi.api.v2; import org.jetbrains.annotations.ApiStatus; diff --git a/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/api/v2/VisitorInfos.java b/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/api/v2/VisitorInfos.java new file mode 100644 index 0000000..d416b33 --- /dev/null +++ b/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/api/v2/VisitorInfos.java @@ -0,0 +1,33 @@ +package io.github.fabriccompatibilitylayers.modremappingapi.api.v2; + +import org.jetbrains.annotations.Nullable; + +public interface VisitorInfos { + void registerSuperType(String target, String replacement); + + void registerTypeAnnotation(String target, String replacement); + + void registerMethodTypeIns(String target, String replacement); + + void registerFieldRef(String targetClass, String targetField, String targetDesc, FullClassMember classMember); + + void registerMethodInvocation(String targetClass, String targetMethod, String targetDesc, FullClassMember classMember); + + void registerLdc(String targetClass, Object targetLdc, Object replacement); + + void registerInstantiation(String target, String replacement); + + + static FullClassMember classMember(String owner, String name, @Nullable String desc, @Nullable Boolean isStatic) { + return new io.github.fabriccompatibiltylayers.modremappingapi.api.v1.VisitorInfos.FullClassMember(owner, name, desc, isStatic); + } + + static FullClassMember classMember(String owner, String name, @Nullable Boolean isStatic) { + return new io.github.fabriccompatibiltylayers.modremappingapi.api.v1.VisitorInfos.FullClassMember(owner, name, isStatic); + } + + interface FullClassMember extends MappingUtils.ClassMember { + String getOwner(); + @Nullable Boolean isStatic(); + } +} diff --git a/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/impl/DefaultMappingsConfig.java b/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/impl/DefaultMappingsConfig.java new file mode 100644 index 0000000..97f59ce --- /dev/null +++ b/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/impl/DefaultMappingsConfig.java @@ -0,0 +1,30 @@ +package io.github.fabriccompatibilitylayers.modremappingapi.impl; + +import io.github.fabriccompatibilitylayers.modremappingapi.api.v2.MappingsConfig; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.Supplier; + +public class DefaultMappingsConfig implements MappingsConfig { + @Override + public String getSourceNamespace() { + return "official"; + } + + @Override + public Supplier getExtraMappings() { + return null; + } + + @Override + public Map getRenamingMap() { + return new HashMap<>(); + } + + @Override + public @Nullable String getDefaultPackage() { + return null; + } +} diff --git a/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/impl/DefaultModCandidate.java b/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/impl/DefaultModCandidate.java new file mode 100644 index 0000000..3256828 --- /dev/null +++ b/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/impl/DefaultModCandidate.java @@ -0,0 +1,97 @@ +package io.github.fabriccompatibilitylayers.modremappingapi.impl; + +import io.github.fabriccompatibilitylayers.modremappingapi.api.v2.ModCandidate; +import io.github.fabriccompatibilitylayers.modremappingapi.api.v2.ModDiscovererConfig; +import org.jetbrains.annotations.Nullable; + +import java.nio.file.Path; + +public class DefaultModCandidate implements ModCandidate { + private String sanitizedFileName, id; + private Path path; + private final ModDiscovererConfig discovererConfig; + private Path destination; + + public DefaultModCandidate(Path path, ModDiscovererConfig discovererConfig) { + this.sanitizedFileName = path.getFileName().toString().replace(" ", "_"); + this.id = this.sanitizedFileName.replace(".jar", "").replace(".zip", ""); + this.path = path; + this.discovererConfig = discovererConfig; + + if (!this.sanitizedFileName.endsWith(".jar") && !this.sanitizedFileName.endsWith(".zip")) { + this.sanitizedFileName += ".zip"; + } + } + + @Override + public String getId() { + return id; + } + + @Override + public Path getPath() { + return path; + } + + @Override + public String getType() { + return "default"; + } + + @Override + public @Nullable String getAccessWidenerPath() { + return null; + } + + @Override + public @Nullable ModCandidate getParent() { + return null; + } + + @Override + public @Nullable String getVersion() { + return null; + } + + @Override + public @Nullable String getParentSubPath() { + return null; + } + + @Override + public String getDestinationName() { + return this.sanitizedFileName; + } + + @Override + public ModDiscovererConfig getDiscovererConfig() { + return discovererConfig; + } + + @Override + public void setAccessWidener(byte[] data) { + + } + + @Override + public byte @Nullable [] getAccessWidener() { + return null; + } + + @Override + public void setDestination(Path destination) { + this.destination = destination; + } + + @Override + public Path getDestination() { + return this.destination; + } + + @Override + public void setPath(Path path) { + this.path = path; + } + + +} diff --git a/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/impl/DefaultRemapLibrary.java b/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/impl/DefaultRemapLibrary.java new file mode 100644 index 0000000..55a2e4c --- /dev/null +++ b/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/impl/DefaultRemapLibrary.java @@ -0,0 +1,54 @@ +package io.github.fabriccompatibilitylayers.modremappingapi.impl; + +import io.github.fabriccompatibilitylayers.modremappingapi.api.v2.RemapLibrary; +import org.jetbrains.annotations.Nullable; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class DefaultRemapLibrary implements RemapLibrary { + private final @Nullable String url; + private final @Nullable Path path; + private final String fileName; + private final List toExclude; + + public DefaultRemapLibrary(@Nullable String url, String fileName, List toExclude) { + this.url = url; + this.path = null; + this.fileName = fileName; + this.toExclude = toExclude; + } + + public DefaultRemapLibrary(@Nullable Path path, String fileName, List toExclude) { + this.url = null; + this.path = path; + this.fileName = fileName; + this.toExclude = toExclude; + } + + public DefaultRemapLibrary(@Nullable Path path, String fileName) { + this(path, fileName, Collections.emptyList()); + } + + @Override + public @Nullable String getURL() { + return this.url; + } + + @Override + public @Nullable Path getPath() { + return this.path; + } + + @Override + public String getFileName() { + return this.fileName; + } + + @Override + public List getToExclude() { + return this.toExclude; + } +} diff --git a/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/impl/InternalCacheHandler.java b/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/impl/InternalCacheHandler.java new file mode 100644 index 0000000..7fe0e5a --- /dev/null +++ b/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/impl/InternalCacheHandler.java @@ -0,0 +1,11 @@ +package io.github.fabriccompatibilitylayers.modremappingapi.impl; + +import io.github.fabriccompatibilitylayers.modremappingapi.api.v2.CacheHandler; + +import java.nio.file.Path; + +public interface InternalCacheHandler extends CacheHandler { + Path resolveMappings(String name); + Path resolveRoot(String name); + Path getTempDirectory(); +} diff --git a/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/impl/ModDiscovererConfigImpl.java b/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/impl/ModDiscovererConfigImpl.java new file mode 100644 index 0000000..c111fe1 --- /dev/null +++ b/src/main/java/io/github/fabriccompatibilitylayers/modremappingapi/impl/ModDiscovererConfigImpl.java @@ -0,0 +1,145 @@ +package io.github.fabriccompatibilitylayers.modremappingapi.impl; + +import io.github.fabriccompatibilitylayers.modremappingapi.api.v2.ModCandidate; +import io.github.fabriccompatibilitylayers.modremappingapi.api.v2.ModDiscovererConfig; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.function.BiFunction; +import java.util.function.Predicate; +import java.util.regex.Pattern; + +@ApiStatus.Internal +public class ModDiscovererConfigImpl implements ModDiscovererConfig { + private final String folderName; + private final Pattern fileNameMatcher; + private final boolean searchRecursively; + private final Predicate directoryFilter; + private final @Nullable Collector candidateCollector; + private final boolean exportToOriginalFolder; + private final boolean allowDirectoryMods; + + private ModDiscovererConfigImpl(String folderName, Pattern fileNameMatcher, boolean searchRecursively, Predicate directoryFilter, @Nullable Collector candidateCollector, boolean exportToOriginalFolder, boolean allowDirectoryMods) { + this.folderName = folderName; + this.fileNameMatcher = fileNameMatcher; + this.searchRecursively = searchRecursively; + this.directoryFilter = directoryFilter; + this.candidateCollector = candidateCollector; + this.exportToOriginalFolder = exportToOriginalFolder; + this.allowDirectoryMods = allowDirectoryMods; + } + + @Override + public String getFolderName() { + return folderName; + } + + @Override + public Pattern getFileNameMatcher() { + return fileNameMatcher; + } + + @Override + public boolean searchRecursively() { + return searchRecursively; + } + + @Override + public Predicate getDirectoryFilter() { + return directoryFilter; + } + + @Override + public Collector getCandidateCollector() { + return this.candidateCollector == null ? this::defaultCandidateCollector : this.candidateCollector; + } + + @Override + public boolean getExportToOriginalFolder() { + return this.exportToOriginalFolder; + } + + private List defaultCandidateCollector(ModDiscovererConfig config, Path modPath, List fileList) { + List candidates = new ArrayList<>(); + + for (String file : fileList) { + if (file.endsWith(".class")) { + candidates.add(new DefaultModCandidate(modPath, config)); + break; + } + } + + return candidates; + } + + @Override + public boolean allowDirectoryMods() { + return allowDirectoryMods; + } + + public static class BuilderImpl implements ModDiscovererConfig.Builder { + private final String folderName; + private String fileNameMatcher = "(.+).jar$"; + private boolean searchRecursively = false; + private Predicate directoryFilter = s -> true; + private Collector candidateCollector; + private boolean exportToOriginalFolder = false; + private boolean allowDirectoryMods = false; + + public BuilderImpl(String folderName) { + this.folderName = folderName; + } + + @Override + public Builder fileNameMatcher(String pattern) { + this.fileNameMatcher = pattern; + return this; + } + + @Override + public Builder searchRecursively(boolean searchRecursively) { + this.searchRecursively = searchRecursively; + return this; + } + + @Override + public Builder directoryFilter(Predicate filter) { + this.directoryFilter = filter; + return this; + } + + @Override + public Builder candidateCollector(Collector collector) { + this.candidateCollector = collector; + return this; + } + + @Override + public Builder exportToOriginalFolder(boolean exportToOriginalFolder) { + this.exportToOriginalFolder = exportToOriginalFolder; + return this; + } + + @Override + public Builder allowDirectoryMods(boolean allowDirectoryMods) { + this.allowDirectoryMods = allowDirectoryMods; + return this; + } + + @Override + public ModDiscovererConfig build() { + return new ModDiscovererConfigImpl( + folderName, + Pattern.compile(fileNameMatcher), + searchRecursively, + directoryFilter, + candidateCollector, + exportToOriginalFolder, + allowDirectoryMods + ); + } + } +} diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/api/v1/MappingBuilder.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/api/v1/MappingBuilder.java index fb9e64a..8742693 100644 --- a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/api/v1/MappingBuilder.java +++ b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/api/v1/MappingBuilder.java @@ -1,10 +1,12 @@ package io.github.fabriccompatibiltylayers.modremappingapi.api.v1; +@Deprecated public interface MappingBuilder { ClassMapping addMapping(String sourceName, String targetName); ClassMapping addMapping(String name); + @Deprecated public interface ClassMapping { ClassMapping field(String sourceName, String targetName, String sourceDescriptor); ClassMapping field(String name, String descriptor); diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/api/v1/MappingUtils.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/api/v1/MappingUtils.java index 179df43..c7a3774 100644 --- a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/api/v1/MappingUtils.java +++ b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/api/v1/MappingUtils.java @@ -4,6 +4,10 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +/** + * @deprecated Use {@link io.github.fabriccompatibilitylayers.modremappingapi.api.v2.MappingUtils} instead. + */ +@Deprecated public interface MappingUtils { /** * @@ -84,15 +88,23 @@ static String mapDescriptor(String desc) { return MappingsUtilsImpl.mapDescriptor(MappingsUtilsImpl.getV1Registry(), desc); } - class ClassMember { + class ClassMember implements io.github.fabriccompatibilitylayers.modremappingapi.api.v2.MappingUtils.ClassMember { public final @NotNull String name; public final @Nullable String desc; public ClassMember(@NotNull String name, @Nullable String desc) { - assert name != null; - this.name = name; this.desc = desc; } + + @Override + public @NotNull String getName() { + return this.name; + } + + @Override + public @Nullable String getDesc() { + return this.desc; + } } } diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/api/v1/ModRemapper.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/api/v1/ModRemapper.java index f114218..d84b454 100644 --- a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/api/v1/ModRemapper.java +++ b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/api/v1/ModRemapper.java @@ -7,6 +7,11 @@ import java.util.Optional; import java.util.function.Supplier; +/** + * @deprecated Use {@link io.github.fabriccompatibilitylayers.modremappingapi.api.v2.ModRemapper} with entrypoint key "mod-remapper-api:modremapper_v2" + * instead. + */ +@Deprecated public interface ModRemapper { String[] getJarFolders(); diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/api/v1/RemapLibrary.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/api/v1/RemapLibrary.java index c0472fa..2539ef1 100644 --- a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/api/v1/RemapLibrary.java +++ b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/api/v1/RemapLibrary.java @@ -1,12 +1,14 @@ package io.github.fabriccompatibiltylayers.modremappingapi.api.v1; import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; -public class RemapLibrary { +@Deprecated +public class RemapLibrary implements io.github.fabriccompatibilitylayers.modremappingapi.api.v2.RemapLibrary { public final String url; public final Path path; public final List toExclude; @@ -40,4 +42,24 @@ public RemapLibrary(String url, Path path, List toExclude, String fileNa this.toExclude = toExclude; this.fileName = fileName; } + + @Override + public @Nullable String getURL() { + return this.url; + } + + @Override + public @Nullable Path getPath() { + return this.path; + } + + @Override + public String getFileName() { + return this.fileName; + } + + @Override + public List getToExclude() { + return this.toExclude; + } } diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/api/v1/VisitorInfos.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/api/v1/VisitorInfos.java index 4225d95..f96a303 100644 --- a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/api/v1/VisitorInfos.java +++ b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/api/v1/VisitorInfos.java @@ -3,6 +3,7 @@ import io.github.fabriccompatibiltylayers.modremappingapi.api.MappingUtils; import org.jetbrains.annotations.Nullable; +@Deprecated public interface VisitorInfos { void registerSuperType(String target, String replacement); @@ -18,7 +19,8 @@ public interface VisitorInfos { void registerInstantiation(String target, String replacement); - class FullClassMember extends MappingUtils.ClassMember { + @Deprecated + class FullClassMember extends MappingUtils.ClassMember implements io.github.fabriccompatibilitylayers.modremappingapi.api.v2.VisitorInfos.FullClassMember { public final String owner; public final @Nullable Boolean isStatic; @@ -31,5 +33,15 @@ public FullClassMember(String owner, String name, @Nullable String desc, @Nullab public FullClassMember(String owner, String name, @Nullable Boolean isStatic) { this(owner, name, null, isStatic); } + + @Override + public String getOwner() { + return this.owner; + } + + @Override + public @Nullable Boolean isStatic() { + return this.isStatic; + } } } diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/LibraryHandler.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/LibraryHandler.java index feb3b6a..0644188 100644 --- a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/LibraryHandler.java +++ b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/LibraryHandler.java @@ -1,33 +1,31 @@ package io.github.fabriccompatibiltylayers.modremappingapi.impl; import fr.catcore.modremapperapi.utils.Constants; -import io.github.fabriccompatibiltylayers.modremappingapi.api.v1.ModRemapper; -import io.github.fabriccompatibiltylayers.modremappingapi.api.v1.RemapLibrary; -import io.github.fabriccompatibiltylayers.modremappingapi.impl.utils.CacheUtils; +import io.github.fabriccompatibilitylayers.modremappingapi.api.v2.CacheHandler; +import io.github.fabriccompatibilitylayers.modremappingapi.api.v2.RemapLibrary; import io.github.fabriccompatibiltylayers.modremappingapi.impl.utils.FileUtils; -import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.tinyremapper.TinyRemapper; import java.io.IOException; import java.net.URISyntaxException; import java.nio.file.Files; import java.nio.file.Path; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.stream.Collectors; public class LibraryHandler { - private final Map remapLibraries = new HashMap<>(); + private Map remapLibraries = new HashMap<>(); private String sourceNamespace; + private CacheHandler cacheHandler; public LibraryHandler() {} - public void init(String sourceNamespace) { + public void init(String sourceNamespace, CacheHandler cacheHandler) { this.sourceNamespace = sourceNamespace; + this.cacheHandler = cacheHandler; - Path sourceLibraryPath = CacheUtils.getLibraryPath(this.sourceNamespace); + Path sourceLibraryPath = this.cacheHandler.resolveLibrary(this.sourceNamespace); if (!Files.exists(sourceLibraryPath)) { try { @@ -38,34 +36,32 @@ public void init(String sourceNamespace) { } } - public void gatherRemapLibraries(List remappers) { - try { - for (ModRemapper remapper : remappers) { - List libraries = new ArrayList<>(); - - remapper.addRemapLibraries(libraries, FabricLoader.getInstance().getEnvironmentType()); - - Map temp = CacheUtils.computeExtraLibraryPaths(libraries, sourceNamespace); - - for (Map.Entry entry : temp.entrySet()) { - RemapLibrary library = entry.getKey(); - Path path = entry.getValue(); + private Map computeExtraLibraryPaths(Collection sourcePaths, String target) { + return sourcePaths.stream() + .collect(Collectors.toMap(p -> p, + p -> this.cacheHandler.resolveLibrary(target).resolve(p.getFileName()))); + } - if (Files.exists(path)) continue; + public void cacheLibraries(List libraries) { + remapLibraries = computeExtraLibraryPaths(libraries, sourceNamespace); - if (!library.url.isEmpty()) { - Constants.MAIN_LOGGER.info("Downloading remapping library '" + library.fileName + "' from url '" + library.url + "'"); - FileUtils.downloadFile(library.url, path); - FileUtils.removeEntriesFromZip(path, library.toExclude); - Constants.MAIN_LOGGER.info("Remapping library ready for use."); - } else if (library.path != null) { - Constants.MAIN_LOGGER.info("Extracting remapping library '" + library.fileName + "' from mod jar."); - FileUtils.copyZipFile(library.path, path); - Constants.MAIN_LOGGER.info("Remapping library ready for use."); - } + try { + for (Map.Entry entry : remapLibraries.entrySet()) { + RemapLibrary library = entry.getKey(); + Path path = entry.getValue(); + + if (Files.exists(path)) continue; + + if (library.getURL() != null && !library.getURL().isEmpty()) { + Constants.MAIN_LOGGER.info("Downloading remapping library '" + library.getFileName() + "' from url '" + library.getURL() + "'"); + FileUtils.downloadFile(library.getURL(), path); + FileUtils.removeEntriesFromZip(path, library.getToExclude()); + Constants.MAIN_LOGGER.info("Remapping library ready for use."); + } else if (library.getPath() != null) { + Constants.MAIN_LOGGER.info("Extracting remapping library '" + library.getFileName() + "' from mod jar."); + FileUtils.copyZipFile(library.getPath(), path); + Constants.MAIN_LOGGER.info("Remapping library ready for use."); } - - remapLibraries.putAll(temp); } } catch (IOException | URISyntaxException e) { throw new RuntimeException(e); diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/MappingsUtilsImpl.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/MappingsUtilsImpl.java index 8f89c4e..0b51bc8 100644 --- a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/MappingsUtilsImpl.java +++ b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/MappingsUtilsImpl.java @@ -1,6 +1,7 @@ package io.github.fabriccompatibiltylayers.modremappingapi.impl; import io.github.fabriccompatibiltylayers.modremappingapi.api.MappingUtils; +import io.github.fabriccompatibiltylayers.modremappingapi.impl.context.BaseModRemapperContext; import io.github.fabriccompatibiltylayers.modremappingapi.impl.context.v1.ModRemapperV1Context; import io.github.fabriccompatibiltylayers.modremappingapi.impl.mappings.MappingsRegistry; import net.fabricmc.api.EnvType; @@ -31,6 +32,10 @@ public static MappingsRegistry getV1Registry() { return ModRemapperV1Context.INSTANCE.getMappingsRegistry(); } + public static MappingsRegistry getMappingsRegistry(String contextId) { + return BaseModRemapperContext.get(contextId).getMappingsRegistry(); + } + public static String mapClass(MappingsRegistry registry, String className) { int srcNamespace = registry.getFullMappings().getNamespaceId(registry.getSourceNamespace()); int targetNamespace = registry.getFullMappings().getNamespaceId(registry.getTargetNamespace()); @@ -151,11 +156,11 @@ public static MappingUtils.ClassMember mapMethod(MappingsRegistry registry, Clas String methodSubName = methodDef.getName(srcNamespace); if (Objects.equals(methodSubName, methodName)) { - String methodDescriptor = methodDef.getDesc(registry.getTargetNamespace()); + String methodDescriptor = methodDef.getDesc(targetNamespace); if (methodDescriptor != null && methodDescriptor.startsWith(argDesc)) { return new MappingUtils.ClassMember( - methodDef.getName(registry.getTargetNamespace()), + methodDef.getName(targetNamespace), methodDescriptor ); } diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/ModCandidate.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/ModCandidate.java deleted file mode 100644 index 3ba9b3f..0000000 --- a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/ModCandidate.java +++ /dev/null @@ -1,26 +0,0 @@ -package io.github.fabriccompatibiltylayers.modremappingapi.impl; - -import org.jetbrains.annotations.Nullable; - -import java.nio.file.Path; - -public class ModCandidate { - public final String modName; - public final @Nullable String accessWidenerName; - - public final Path file; - public final Path original; - - public byte[] accessWidener; - - public ModCandidate(String modName, @Nullable String accessWidenerName, Path file, Path original) { - this.modName = modName; - this.accessWidenerName = accessWidenerName; - this.file = file; - this.original = original; - } - - public ModCandidate(String modName, Path file, Path original) { - this(modName, null, file, original); - } -} diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/ModRemappingAPIImpl.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/ModRemappingAPIImpl.java index d04c1ae..7fda287 100644 --- a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/ModRemappingAPIImpl.java +++ b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/ModRemappingAPIImpl.java @@ -2,11 +2,17 @@ import fr.catcore.wfvaio.FabricVariants; import fr.catcore.wfvaio.WhichFabricVariantAmIOn; +import io.github.fabriccompatibilitylayers.modremappingapi.api.v2.ModRemapper; import io.github.fabriccompatibiltylayers.modremappingapi.impl.context.ModRemapperContext; import io.github.fabriccompatibiltylayers.modremappingapi.impl.context.v1.ModRemapperV1Context; +import io.github.fabriccompatibiltylayers.modremappingapi.impl.context.v2.ModRemmaperV2Context; import net.fabricmc.loader.api.FabricLoader; import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; public class ModRemappingAPIImpl { private static ModRemapperContext CURRENT_CONTEXT = null; @@ -16,6 +22,7 @@ public class ModRemappingAPIImpl { private static boolean init = false; private static boolean initializing = false; + private static final String v2EntrypointName = "mod-remapper-api:modremapper_v2"; public static void init() { if (!init && !initializing) { @@ -32,12 +39,37 @@ public static void init() { CURRENT_CONTEXT.afterRemap(); + Map> v2Remappers = FabricLoader.getInstance() + .getEntrypoints(v2EntrypointName, ModRemapper.class) + .stream().collect(Collectors.groupingBy(ModRemapper::getContextId)); + + List v2Keys = new ArrayList<>(v2Remappers.keySet()); + + while (!v2Keys.isEmpty()) { + String contextKey = v2Keys.remove(0); + ModRemmaperV2Context context = new ModRemmaperV2Context(contextKey, v2Remappers.get(contextKey)); + CURRENT_CONTEXT = context; + + CURRENT_CONTEXT.init(); + + Map> newRemappers = context.discoverMods(remapClassEdits) + .stream().collect(Collectors.groupingBy(ModRemapper::getContextId)); + + v2Keys.addAll(newRemappers.keySet()); + + newRemappers.forEach((k, v) -> v2Remappers.computeIfAbsent(k, k2 -> new ArrayList<>()).addAll(v)); + + context.afterRemap(); + } + + v2Remappers.values().forEach(l -> l.forEach(ModRemapper::afterAllRemappings)); + initializing = false; init = true; } } - public static ModRemapperContext getCurrentContext() { + public static ModRemapperContext getCurrentContext() { return CURRENT_CONTEXT; } } diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/VisitorInfosImpl.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/VisitorInfosImpl.java index db2c14d..48253bd 100644 --- a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/VisitorInfosImpl.java +++ b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/VisitorInfosImpl.java @@ -1,20 +1,20 @@ package io.github.fabriccompatibiltylayers.modremappingapi.impl; -import io.github.fabriccompatibiltylayers.modremappingapi.api.v1.VisitorInfos; +import io.github.fabriccompatibilitylayers.modremappingapi.api.v2.VisitorInfos; import org.jetbrains.annotations.ApiStatus; import java.util.HashMap; import java.util.Map; @ApiStatus.Internal -public class VisitorInfosImpl extends fr.catcore.modremapperapi.remapping.VisitorInfos implements VisitorInfos { +public class VisitorInfosImpl extends fr.catcore.modremapperapi.remapping.VisitorInfos implements VisitorInfos, io.github.fabriccompatibiltylayers.modremappingapi.api.v1.VisitorInfos { public final Map SUPERS = new HashMap<>(); public final Map ANNOTATION = new HashMap<>(); public final Map METHOD_TYPE = new HashMap<>(); public final Map INSTANTIATION = new HashMap<>(); - public final Map>> METHOD_INVOCATION = new HashMap<>(); - public final Map>> FIELD_REF = new HashMap<>(); + public final Map>> METHOD_INVOCATION = new HashMap<>(); + public final Map>> FIELD_REF = new HashMap<>(); public final Map> LDC = new HashMap<>(); @Override @@ -33,14 +33,24 @@ public void registerMethodTypeIns(String target, String replacement) { } @Override - public void registerFieldRef(String targetClass, String targetField, String targetDesc, FullClassMember classMember) { + public void registerFieldRef(String targetClass, String targetField, String targetDesc, io.github.fabriccompatibiltylayers.modremappingapi.api.v1.VisitorInfos.FullClassMember classMember) { + this.registerFieldRef(targetClass, targetField, targetDesc, (VisitorInfos.FullClassMember) classMember); + } + + @Override + public void registerMethodInvocation(String targetClass, String targetMethod, String targetDesc, io.github.fabriccompatibiltylayers.modremappingapi.api.v1.VisitorInfos.FullClassMember classMember) { + this.registerMethodInvocation(targetClass, targetMethod, targetDesc, (VisitorInfos.FullClassMember) classMember); + } + + @Override + public void registerFieldRef(String targetClass, String targetField, String targetDesc, VisitorInfos.FullClassMember classMember) { FIELD_REF.computeIfAbsent(targetClass, k -> new HashMap<>()) .computeIfAbsent(targetField, k -> new HashMap<>()) .put(targetDesc, classMember); } @Override - public void registerMethodInvocation(String targetClass, String targetMethod, String targetDesc, FullClassMember classMember) { + public void registerMethodInvocation(String targetClass, String targetMethod, String targetDesc, VisitorInfos.FullClassMember classMember) { METHOD_INVOCATION.computeIfAbsent(targetClass, k -> new HashMap<>()) .computeIfAbsent(targetMethod, k -> new HashMap<>()) .put(targetDesc, classMember); @@ -89,14 +99,14 @@ public void registerMethodLdcIns(MethodValue target, MethodValue replacement) { .put(target.value, replacement.value); } - private void registerMethodNamed(MethodNamed target, MethodNamed replacementObject, Map>> map) { + private void registerMethodNamed(MethodNamed target, MethodNamed replacementObject, Map>> map) { String targetClass = target.owner; String targetMember = target.name; String replacement = replacementObject.name; if (replacement == null) replacement = ""; - FullClassMember classMember = new FullClassMember(replacementObject.owner, replacement, null, null); + VisitorInfos.FullClassMember classMember = new io.github.fabriccompatibiltylayers.modremappingapi.api.v1.VisitorInfos.FullClassMember(replacementObject.owner, replacement, null, null); if (targetMember == null) targetMember = ""; diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/DefaultModRemapper.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/compatibility/V1DefaultModRemapper.java similarity index 83% rename from src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/DefaultModRemapper.java rename to src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/compatibility/V1DefaultModRemapper.java index 067aa8f..a6e239a 100644 --- a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/DefaultModRemapper.java +++ b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/compatibility/V1DefaultModRemapper.java @@ -1,4 +1,4 @@ -package io.github.fabriccompatibiltylayers.modremappingapi.impl; +package io.github.fabriccompatibiltylayers.modremappingapi.impl.compatibility; import io.github.fabriccompatibiltylayers.modremappingapi.api.v1.MappingBuilder; import io.github.fabriccompatibiltylayers.modremappingapi.api.v1.ModRemapper; @@ -8,10 +8,10 @@ import java.util.List; -public class DefaultModRemapper implements ModRemapper { +public class V1DefaultModRemapper implements ModRemapper { @Override public String[] getJarFolders() { - return new String[] {"mods"}; + return new String[]{"mods"}; } @Override diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/BaseModRemapperContext.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/BaseModRemapperContext.java index 2dc94b4..dbb5854 100644 --- a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/BaseModRemapperContext.java +++ b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/BaseModRemapperContext.java @@ -3,14 +3,22 @@ import java.util.HashMap; import java.util.Map; -public abstract class BaseModRemapperContext implements ModRemapperContext { +public abstract class BaseModRemapperContext implements ModRemapperContext { private static final Map REGISTRY = new HashMap<>(); + public final String contextId; + public BaseModRemapperContext(String id) { REGISTRY.put(id, this); + this.contextId = id; } public static ModRemapperContext get(String id) { return REGISTRY.get(id); } + + @Override + public String getId() { + return this.contextId; + } } diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/MappingsRegistryInstance.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/MappingsRegistryInstance.java index 30c2784..b56dcb7 100644 --- a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/MappingsRegistryInstance.java +++ b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/MappingsRegistryInstance.java @@ -1,16 +1,17 @@ package io.github.fabriccompatibiltylayers.modremappingapi.impl.context; -import fr.catcore.modremapperapi.utils.Constants; import fr.catcore.wfvaio.WhichFabricVariantAmIOn; +import io.github.fabriccompatibilitylayers.modremappingapi.impl.InternalCacheHandler; import io.github.fabriccompatibiltylayers.modremappingapi.api.v1.MappingBuilder; -import io.github.fabriccompatibiltylayers.modremappingapi.impl.MappingBuilderImpl; -import io.github.fabriccompatibiltylayers.modremappingapi.impl.MappingsUtilsImpl; +import io.github.fabriccompatibiltylayers.modremappingapi.impl.context.v1.V1MappingBuilderImpl; import io.github.fabriccompatibiltylayers.modremappingapi.impl.mappings.MappingTreeHelper; import io.github.fabriccompatibiltylayers.modremappingapi.impl.mappings.MappingsRegistry; import io.github.fabriccompatibiltylayers.modremappingapi.impl.utils.FileUtils; import io.github.fabriccompatibiltylayers.modremappingapi.impl.utils.VersionHelper; import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.mappingio.MappingVisitor; +import net.fabricmc.mappingio.adapter.MappingNsRenamer; +import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch; import net.fabricmc.mappingio.tree.MappingTree; import net.fabricmc.mappingio.tree.MemoryMappingTree; @@ -28,8 +29,11 @@ public class MappingsRegistryInstance extends MappingsRegistry { private String defaultPackage = ""; private String sourceNamespace = "official"; - public MappingsRegistryInstance() { + private final InternalCacheHandler cacheHandler; + + public MappingsRegistryInstance(InternalCacheHandler cacheHandler) { super(); + this.cacheHandler = cacheHandler; try { this.formatVanillaMappings(); @@ -80,9 +84,29 @@ public MemoryMappingTree getFormattedMappings() { } @Override - public void addToFormattedMappings(InputStream stream) throws IOException { + public void addToFormattedMappings(InputStream stream, Map renames) throws IOException { MappingTree extra = MappingTreeHelper.readMappings(stream); + if (!renames.isEmpty()) { + MemoryMappingTree renamed = new MemoryMappingTree(); + + MappingNsRenamer renamer = new MappingNsRenamer(renamed, renames); + + extra.accept(renamer); + + extra = renamed; + } + + if (!Objects.equals(extra.getSrcNamespace(), formatted.getSrcNamespace()) && extra.getDstNamespaces().contains(formatted.getSrcNamespace())) { + MemoryMappingTree switched = new MemoryMappingTree(); + + MappingSourceNsSwitch switcher = new MappingSourceNsSwitch(switched, formatted.getSrcNamespace()); + + extra.accept(switcher); + + extra = switched; + } + formatted = MappingTreeHelper.mergeIntoNew(formatted, extra); } @@ -99,7 +123,7 @@ public void completeFormattedMappings() throws IOException { } try { - MappingTreeHelper.exportMappings(formatted, Constants.MC_MAPPINGS_FILE.toPath()); + MappingTreeHelper.exportMappings(formatted, this.cacheHandler.resolveMappings("mc_mappings.tiny")); } catch (IOException e) { throw new RuntimeException("Error while writing formatted mappings", e); } @@ -111,7 +135,7 @@ public void setDefaultPackage(String defaultPackage) { @Override public void addModMappings(Path path) { - MappingBuilder mappingBuilder = new MappingBuilderImpl(mods); + MappingBuilder mappingBuilder = new V1MappingBuilderImpl(mods); try { FileUtils.listPathContent(path) @@ -129,7 +153,7 @@ public void generateModMappings() { try { mods.visitEnd(); - MappingTreeHelper.exportMappings(mods, Constants.REMAPPED_MAPPINGS_FILE.toPath()); + MappingTreeHelper.exportMappings(mods, this.cacheHandler.resolveMappings("remapped_mappings.tiny")); } catch (IOException e) { throw new RuntimeException("Error while generating mods mappings", e); } @@ -152,7 +176,7 @@ public void generateAdditionalMappings() { additional.visitEnd(); try { - MappingTreeHelper.exportMappings(additional, Constants.EXTRA_MAPPINGS_FILE.toPath()); + MappingTreeHelper.exportMappings(additional, this.cacheHandler.resolveMappings("extra_mappings.tiny")); } catch (IOException e) { throw new RuntimeException("Error while generating remappers mappings", e); } @@ -189,7 +213,7 @@ public String getTargetNamespace() { @Override public void writeFullMappings() { try { - MappingTreeHelper.exportMappings(full, Constants.FULL_MAPPINGS_FILE.toPath()); + MappingTreeHelper.exportMappings(full, this.cacheHandler.resolveMappings("full_mappings.tiny")); } catch (IOException e) { throw new RuntimeException(e); } diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/MixinData.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/MixinData.java new file mode 100644 index 0000000..a95e460 --- /dev/null +++ b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/MixinData.java @@ -0,0 +1,26 @@ +package io.github.fabriccompatibiltylayers.modremappingapi.impl.context; + +import net.fabricmc.tinyremapper.InputTag; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class MixinData { + private final Map> mixin2TargetMap = new HashMap<>(); + private final Map> mixinRefmapData = new HashMap<>(); + private final List hardMixins = new ArrayList<>(); + + public Map> getMixin2TargetMap() { + return mixin2TargetMap; + } + + public Map> getMixinRefmapData() { + return mixinRefmapData; + } + + public List getHardMixins() { + return hardMixins; + } +} diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/ModRemapperContext.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/ModRemapperContext.java index 3b3532e..6608a9b 100644 --- a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/ModRemapperContext.java +++ b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/ModRemapperContext.java @@ -1,9 +1,10 @@ package io.github.fabriccompatibiltylayers.modremappingapi.impl.context; +import io.github.fabriccompatibilitylayers.modremappingapi.api.v2.CacheHandler; +import io.github.fabriccompatibilitylayers.modremappingapi.api.v2.ModCandidate; import io.github.fabriccompatibiltylayers.modremappingapi.impl.LibraryHandler; -import io.github.fabriccompatibiltylayers.modremappingapi.impl.ModCandidate; import io.github.fabriccompatibiltylayers.modremappingapi.impl.mappings.MappingsRegistry; -import io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper.RemappingFlags; +import io.github.fabriccompatibilitylayers.modremappingapi.api.v2.RemappingFlags; import net.fabricmc.tinyremapper.TinyRemapper; import java.nio.file.Path; @@ -11,15 +12,18 @@ import java.util.Map; import java.util.Set; -public interface ModRemapperContext { +public interface ModRemapperContext { void init(); void remapMods(Map pathMap); void afterRemap(); - void discoverMods(boolean remapClassEdits); + List discoverMods(boolean remapClassEdits); void gatherRemappers(); - Map> getMixin2TargetMap(); MappingsRegistry getMappingsRegistry(); void addToRemapperBuilder(TinyRemapper.Builder builder); Set getRemappingFlags(); LibraryHandler getLibraryHandler(); + String getId(); + MixinData getMixinData(); + void gatherLibraries(); + CacheHandler getCacheHandler(); } diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/v1/ModRemapperV1Context.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/v1/ModRemapperV1Context.java index b965a39..f9c9f77 100644 --- a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/v1/ModRemapperV1Context.java +++ b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/v1/ModRemapperV1Context.java @@ -1,34 +1,46 @@ package io.github.fabriccompatibiltylayers.modremappingapi.impl.context.v1; import fr.catcore.modremapperapi.utils.Constants; +import io.github.fabriccompatibilitylayers.modremappingapi.api.v2.CacheHandler; +import io.github.fabriccompatibilitylayers.modremappingapi.api.v2.ModCandidate; +import io.github.fabriccompatibilitylayers.modremappingapi.api.v2.ModDiscovererConfig; +import io.github.fabriccompatibilitylayers.modremappingapi.impl.DefaultModCandidate; +import io.github.fabriccompatibilitylayers.modremappingapi.impl.InternalCacheHandler; import io.github.fabriccompatibiltylayers.modremappingapi.api.v1.MappingBuilder; import io.github.fabriccompatibiltylayers.modremappingapi.api.v1.ModRemapper; +import io.github.fabriccompatibiltylayers.modremappingapi.api.v1.RemapLibrary; import io.github.fabriccompatibiltylayers.modremappingapi.impl.*; import io.github.fabriccompatibiltylayers.modremappingapi.impl.compatibility.V0ModRemapper; import io.github.fabriccompatibiltylayers.modremappingapi.impl.context.BaseModRemapperContext; import io.github.fabriccompatibiltylayers.modremappingapi.impl.context.MappingsRegistryInstance; +import io.github.fabriccompatibiltylayers.modremappingapi.impl.context.MixinData; +import io.github.fabriccompatibiltylayers.modremappingapi.impl.context.v2.V2ModDiscoverer; import io.github.fabriccompatibiltylayers.modremappingapi.impl.mappings.MappingsRegistry; import io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper.ModTrRemapper; -import io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper.RemappingFlags; +import io.github.fabriccompatibilitylayers.modremappingapi.api.v2.RemappingFlags; import io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper.SoftLockFixer; import io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper.visitor.MRAApplyVisitor; +import io.github.fabriccompatibiltylayers.modremappingapi.impl.utils.FileUtils; import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.impl.launch.FabricLauncherBase; import net.fabricmc.tinyremapper.TinyRemapper; import java.io.IOException; import java.io.InputStream; +import java.net.URISyntaxException; +import java.nio.file.Files; import java.nio.file.Path; import java.util.*; import java.util.function.Supplier; +import java.util.stream.Collectors; -public class ModRemapperV1Context extends BaseModRemapperContext { +public class ModRemapperV1Context extends BaseModRemapperContext { private final Set remapFlags = new HashSet<>(); private final List remappers = new ArrayList<>(); - private final Map> mixin2TargetMap = new HashMap<>(); - private final MappingsRegistryInstance mappingsRegistry = new MappingsRegistryInstance(); + private final MixinData mixinData = new MixinData(); + private final InternalCacheHandler cacheHandler = new V1CacheHandler(); + private final MappingsRegistryInstance mappingsRegistry = new MappingsRegistryInstance(cacheHandler); private final LibraryHandler libraryHandler = new LibraryHandler(); - private final V1ModDiscoverer modDiscoverer = new V1ModDiscoverer(); public static ModRemapperV1Context INSTANCE; @@ -51,7 +63,7 @@ public void init() { mappings.ifPresent(inputStreamSupplier -> { try { - this.mappingsRegistry.addToFormattedMappings(inputStreamSupplier.get()); + this.mappingsRegistry.addToFormattedMappings(inputStreamSupplier.get(), new HashMap<>()); } catch (IOException e) { throw new RuntimeException(e); } @@ -68,9 +80,7 @@ public void init() { throw new RuntimeException(e); } - libraryHandler.init(this.mappingsRegistry.getSourceNamespace()); - - libraryHandler.gatherRemapLibraries(remappers); + this.gatherLibraries(); this.registerAdditionalMappings(); this.mappingsRegistry.generateAdditionalMappings(); @@ -92,19 +102,113 @@ public void afterRemap() { remappers.forEach(ModRemapper::afterRemap); } + private List collectCandidates(ModDiscovererConfig config, Path modPath, List entries) { + boolean fabric = false; + boolean hasClass = false; + + for (String entry : entries) { + if (entry.endsWith("fabric.mod.json") || entry.endsWith("quilt.mod.json") || entry.endsWith("quilt.mod.json5")) { + fabric = true; + break; + } + + if (entry.endsWith(".class")) { + hasClass = true; + } + } + + List list = new ArrayList<>(); + + if (hasClass && !fabric) { + list.add(new DefaultModCandidate(modPath, config)); + } + + return list; + } + @Override - public void discoverMods(boolean remapClassEdits) { - Map modPaths = this.modDiscoverer.init(remappers, remapClassEdits, this); + public List discoverMods(boolean remapClassEdits) { + Map> excluded = new HashMap<>(); + + Set modFolders = new HashSet<>(); + + for (ModRemapper remapper : remappers) { + Collections.addAll(modFolders, remapper.getJarFolders()); + + if (remapper instanceof V0ModRemapper) { + excluded.putAll(((V0ModRemapper) remapper).getExclusions()); + } + } + + List candidates = new ArrayList<>(); + Map config2Discoverer = new HashMap<>(); + + for (String modFolder : modFolders) { + ModDiscovererConfig config = ModDiscovererConfig.builder(modFolder) + .fileNameMatcher("(.+).(jar|zip)$") + .candidateCollector(this::collectCandidates) + .build(); + V2ModDiscoverer discoverer = new V2ModDiscoverer(config); + config2Discoverer.put(config, discoverer); + candidates.addAll(discoverer.collect()); + } + + try { + this.handleV0Excluded(candidates, excluded); + } catch (IOException | URISyntaxException e) { + throw new RuntimeException(e); + } + + Map> config2Candidates = + candidates.stream().collect(Collectors.groupingBy(ModCandidate::getDiscovererConfig)); + + for (Map.Entry> entry : config2Candidates.entrySet()) { + ModDiscovererConfig config = entry.getKey(); + + try { + config2Discoverer.get(config).excludeClassEdits(entry.getValue(), this.cacheHandler, this.mappingsRegistry); + } catch (IOException | URISyntaxException e) { + throw new RuntimeException(e); + } + } - for (ModCandidate candidate : modPaths.keySet()) { - mappingsRegistry.addModMappings(candidate.original); + for (ModCandidate candidate : candidates) { + mappingsRegistry.addModMappings(candidate.getPath()); } mappingsRegistry.generateModMappings(); - this.remapMods(modPaths); + Map candidateToOutput = new HashMap<>(); + + for (Map.Entry> entry : config2Candidates.entrySet()) { + ModDiscovererConfig config = entry.getKey(); + + candidateToOutput.putAll( + config2Discoverer.get(config).computeDestinations(entry.getValue(), this.cacheHandler) + ); + } + + if (!candidateToOutput.isEmpty()) this.remapMods(candidateToOutput); + + candidateToOutput.values().forEach(FabricLauncherBase.getLauncher()::addToClassPath); + + return new ArrayList<>(); + } - modPaths.values().forEach(FabricLauncherBase.getLauncher()::addToClassPath); + private void handleV0Excluded(List mods, Map> excludedMap) throws IOException, URISyntaxException { + for (ModCandidate modCandidate : mods) { + if (excludedMap.containsKey(modCandidate.getId())) { + if (Files.isDirectory(modCandidate.getPath())) { + for (String excluded : excludedMap.get(modCandidate.getId())) { + if (Files.deleteIfExists(modCandidate.getPath().resolve(excluded))) { + Constants.MAIN_LOGGER.debug("File deleted: " + modCandidate.getPath().resolve(excluded)); + } + } + } else { + FileUtils.removeEntriesFromZip(modCandidate.getPath(), excludedMap.get(modCandidate.getId())); + } + } + } } private static final String v0EntrypointName = "mod-remapper-api:modremapper"; @@ -121,18 +225,13 @@ public void gatherRemappers() { remappers.addAll(FabricLoader.getInstance().getEntrypoints(v1EntrypointName, ModRemapper.class)); } - @Override - public Map> getMixin2TargetMap() { - return mixin2TargetMap; - } - @Override public MappingsRegistry getMappingsRegistry() { return this.mappingsRegistry; } private void registerAdditionalMappings() { - MappingBuilder builder = new MappingBuilderImpl(mappingsRegistry.getAdditionalMappings()); + MappingBuilder builder = new V1MappingBuilderImpl(mappingsRegistry.getAdditionalMappings()); for (ModRemapper remapper : remappers) { remapper.registerMappings(builder); @@ -162,4 +261,27 @@ public Set getRemappingFlags() { public LibraryHandler getLibraryHandler() { return libraryHandler; } + + @Override + public MixinData getMixinData() { + return mixinData; + } + + @Override + public void gatherLibraries() { + libraryHandler.init(this.mappingsRegistry.getSourceNamespace(), this.cacheHandler); + + List libraries = new ArrayList<>(); + + for (ModRemapper remapper : remappers) { + remapper.addRemapLibraries(libraries, FabricLoader.getInstance().getEnvironmentType()); + } + + libraryHandler.cacheLibraries(new ArrayList<>(libraries)); + } + + @Override + public CacheHandler getCacheHandler() { + return this.cacheHandler; + } } diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/v1/V1CacheHandler.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/v1/V1CacheHandler.java new file mode 100644 index 0000000..87dcc44 --- /dev/null +++ b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/v1/V1CacheHandler.java @@ -0,0 +1,56 @@ +package io.github.fabriccompatibiltylayers.modremappingapi.impl.context.v1; + +import io.github.fabriccompatibilitylayers.modremappingapi.impl.InternalCacheHandler; +import io.github.fabriccompatibiltylayers.modremappingapi.impl.utils.CacheUtils; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +public class V1CacheHandler implements InternalCacheHandler { + private final Path contextDirectory = CacheUtils.MAIN_FOLDER; + private final Path tempDirectory = contextDirectory.resolve("temp"); + private final Path libsDirectory = CacheUtils.LIBRARY_FOLDER; + + public V1CacheHandler() { + for (Path p : new Path[] {tempDirectory, libsDirectory}) { + if (!Files.exists(p)) { + try { + Files.createDirectories(p); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + } + + @Override + public Path resolveMappings(String name) { + return this.resolveRoot(name); + } + + @Override + public Path resolveRoot(String name) { + return contextDirectory.resolve(name); + } + + @Override + public Path getTempDirectory() { + return tempDirectory; + } + + @Override + public Path resolveTemp(String name) { + return tempDirectory.resolve(name); + } + + @Override + public Path resolveCache(String name) { + return this.resolveRoot(name); + } + + @Override + public Path resolveLibrary(String name) { + return libsDirectory.resolve(name); + } +} diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/MappingBuilderImpl.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/v1/V1MappingBuilderImpl.java similarity index 92% rename from src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/MappingBuilderImpl.java rename to src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/v1/V1MappingBuilderImpl.java index 1222533..d22c996 100644 --- a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/MappingBuilderImpl.java +++ b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/v1/V1MappingBuilderImpl.java @@ -1,4 +1,4 @@ -package io.github.fabriccompatibiltylayers.modremappingapi.impl; +package io.github.fabriccompatibiltylayers.modremappingapi.impl.context.v1; import io.github.fabriccompatibiltylayers.modremappingapi.api.v1.MappingBuilder; import net.fabricmc.mappingio.MappedElementKind; @@ -7,10 +7,10 @@ import org.jetbrains.annotations.Nullable; @ApiStatus.Internal -public class MappingBuilderImpl implements MappingBuilder { +public class V1MappingBuilderImpl implements MappingBuilder { private final MemoryMappingTree next; - public MappingBuilderImpl(MemoryMappingTree next) { + public V1MappingBuilderImpl(MemoryMappingTree next) { this.next = next; } diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/v1/V1ModDiscoverer.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/v1/V1ModDiscoverer.java deleted file mode 100644 index 03b0a01..0000000 --- a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/v1/V1ModDiscoverer.java +++ /dev/null @@ -1,176 +0,0 @@ -package io.github.fabriccompatibiltylayers.modremappingapi.impl.context.v1; - -import fr.catcore.modremapperapi.utils.Constants; -import io.github.fabriccompatibiltylayers.modremappingapi.api.v1.ModRemapper; -import io.github.fabriccompatibiltylayers.modremappingapi.impl.ModCandidate; -import io.github.fabriccompatibiltylayers.modremappingapi.impl.compatibility.V0ModRemapper; -import io.github.fabriccompatibiltylayers.modremappingapi.impl.discover.BaseModDiscoverer; -import io.github.fabriccompatibiltylayers.modremappingapi.impl.utils.CacheUtils; -import io.github.fabriccompatibiltylayers.modremappingapi.impl.utils.FileUtils; -import net.fabricmc.loader.api.FabricLoader; -import org.jetbrains.annotations.NotNull; - -import java.io.IOException; -import java.net.URISyntaxException; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.*; -import java.util.stream.Collectors; - -public class V1ModDiscoverer extends BaseModDiscoverer { - private final Map> excluded = new HashMap<>(); - - public Map init(List modRemappers, boolean remapClassEdits, ModRemapperV1Context context) { - Set modFolders = new HashSet<>(); - - for (ModRemapper remapper : modRemappers) { - Collections.addAll(modFolders, remapper.getJarFolders()); - - if (remapper instanceof V0ModRemapper) { - excluded.putAll(((V0ModRemapper) remapper).getExclusions()); - } - } - - List mods = new ArrayList<>(); - - for (String jarFolder : modFolders) { - Path mcSubFolder = FabricLoader.getInstance().getGameDir().resolve(jarFolder); - Path cacheFolder = CacheUtils.getCachePath(jarFolder); - - try { - if (!Files.exists(mcSubFolder)) Files.createDirectories(mcSubFolder); - if (!Files.exists(cacheFolder)) Files.createDirectories(cacheFolder); - else FileUtils.emptyDir(cacheFolder); - - mods.addAll(this.discoverMods(mcSubFolder, cacheFolder)); - - this.handleV0Excluded(mods); - } catch (IOException | URISyntaxException e) { - e.printStackTrace(); - } - } - - Path mainTempDir = CacheUtils.getCachePath("temp"); - - if (Files.exists(mainTempDir)) { - FileUtils.emptyDir(mainTempDir); - } - - try { - Files.createDirectory(mainTempDir); - } catch (IOException e) { - throw new RuntimeException(e); - } - - Map modPaths = mods.stream() - .filter(entry -> Files.exists(entry.original)) - .collect(Collectors.toMap(entry -> entry, entry -> entry.file)); - - if (!remapClassEdits) { - modPaths = excludeClassEdits(modPaths, mainTempDir, context.getMappingsRegistry()); - } - - return modPaths; - } - - private void handleV0Excluded(List mods) throws IOException, URISyntaxException { - for (ModCandidate modCandidate : mods) { - if (excluded.containsKey(modCandidate.modName)) { - if (Files.isDirectory(modCandidate.file)) { - for (String excluded : excluded.get(modCandidate.modName)) { - if (Files.deleteIfExists(modCandidate.file.resolve(excluded))) { - Constants.MAIN_LOGGER.debug("File deleted: " + modCandidate.file.resolve(excluded)); - } - } - } else { - FileUtils.removeEntriesFromZip(modCandidate.file, excluded.get(modCandidate.modName)); - } - } - } - } - - @Override - public boolean isValidFileName(String fileName) { - return fileName.endsWith(".jar") || fileName.endsWith(".zip"); - } - - @Override - public boolean allowDirectoryMods() { - return true; - } - - @Override - public boolean searchRecursively() { - return false; - } - - @Override - public boolean isValidDirectoryName(String directoryName) { - return false; - } - - @Override - public Optional discoverFolderMod(Path folder, Path destinationFolder) throws IOException { - String name = folder.getFileName().toString().replace(" ", "_"); - Path destination = destinationFolder.resolve(name + ".zip"); - - final boolean[] hasClasses = {false}; - - Files.walkFileTree(folder, new SimpleFileVisitor() { - @Override - public @NotNull FileVisitResult visitFile(Path file, @NotNull BasicFileAttributes attrs) throws IOException { - if (file.toString().endsWith(".class")) { - hasClasses[0] = true; - return FileVisitResult.TERMINATE; - } - - return super.visitFile(file, attrs); - } - }); - - if (hasClasses[0]) { - return Optional.of( - new ModCandidate( - name, - destination, - folder - ) - ); - } - - return Optional.empty(); - } - - @Override - public Optional discoverFileMod(Path file, Path destinationFolder) throws IOException { - String fileName = file.getFileName().toString().replace(" ", "_"); - String modName = fileName.replace(".jar", "").replace(".zip", ""); - - List entries = FileUtils.listZipContent(file); - - boolean found = false; - - for (String entry : entries) { - if (entry.contains("fabric.mod.json")) return Optional.empty(); - - if (entry.endsWith(".class")) { - found = true; - } - } - - if (found) { - return Optional.of( - new ModCandidate( - modName, - destinationFolder.resolve(fileName), - file - ) - ); - } - - return Optional.empty(); - } -} diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/v2/ModRemmaperV2Context.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/v2/ModRemmaperV2Context.java new file mode 100644 index 0000000..08e38d1 --- /dev/null +++ b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/v2/ModRemmaperV2Context.java @@ -0,0 +1,208 @@ +package io.github.fabriccompatibiltylayers.modremappingapi.impl.context.v2; + +import fr.catcore.modremapperapi.utils.Constants; +import io.github.fabriccompatibilitylayers.modremappingapi.api.v2.*; +import io.github.fabriccompatibilitylayers.modremappingapi.impl.InternalCacheHandler; +import io.github.fabriccompatibiltylayers.modremappingapi.impl.LibraryHandler; +import io.github.fabriccompatibiltylayers.modremappingapi.impl.VisitorInfosImpl; +import io.github.fabriccompatibiltylayers.modremappingapi.impl.context.BaseModRemapperContext; +import io.github.fabriccompatibiltylayers.modremappingapi.impl.context.MappingsRegistryInstance; +import io.github.fabriccompatibiltylayers.modremappingapi.impl.context.MixinData; +import io.github.fabriccompatibiltylayers.modremappingapi.impl.mappings.MappingsRegistry; +import io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper.ModTrRemapper; +import io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper.SoftLockFixer; +import io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper.visitor.MRAApplyVisitor; +import io.github.fabriccompatibiltylayers.modremappingapi.impl.utils.CacheUtils; +import net.fabricmc.loader.api.FabricLoader; +import net.fabricmc.tinyremapper.TinyRemapper; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.util.*; +import java.util.stream.Collectors; + +public class ModRemmaperV2Context extends BaseModRemapperContext { + private final List remappers; + private final Set remapFlags = new HashSet<>(); + private final MixinData mixinData = new MixinData(); + private final MappingsRegistryInstance mappingsRegistry; + private final LibraryHandler libraryHandler = new LibraryHandler(); + private final InternalCacheHandler cacheHandler; + + public ModRemmaperV2Context(String id, List remappers) { + super(id); + this.remappers = remappers; + this.cacheHandler = new V2CacheHandler(CacheUtils.getCachePath(id)); + this.mappingsRegistry = new MappingsRegistryInstance(this.cacheHandler); + } + + @Override + public void init() { + for (ModRemapper remapper : remappers) { + remapper.init(this.cacheHandler); + + MappingsConfig mappings = remapper.getMappingsConfig(); + + if (mappings.getSourceNamespace() != null) { + this.mappingsRegistry.setSourceNamespace(mappings.getSourceNamespace()); + } + + if (mappings.getExtraMappings() != null) { + try { + this.mappingsRegistry.addToFormattedMappings(new ByteArrayInputStream(mappings.getExtraMappings().get().getBytes(StandardCharsets.UTF_8)), mappings.getRenamingMap()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + if (mappings.getDefaultPackage() != null) { + this.mappingsRegistry.setDefaultPackage(mappings.getDefaultPackage()); + } + + remapFlags.addAll(remapper.getRemappingFlags()); + } + + try { + this.mappingsRegistry.completeFormattedMappings(); + } catch (IOException e) { + throw new RuntimeException(e); + } + + this.gatherLibraries(); + + this.registerAdditionalMappings(); + this.mappingsRegistry.generateAdditionalMappings(); + } + + @Override + public void remapMods(Map pathMap) { + Constants.MAIN_LOGGER.debug("Starting jar remapping!"); + SoftLockFixer.preloadClasses(); + TinyRemapper remapper = ModTrRemapper.makeRemapper(this); + Constants.MAIN_LOGGER.debug("Remapper created!"); + ModTrRemapper.remapMods(remapper, pathMap, this); + Constants.MAIN_LOGGER.debug("Jar remapping done!"); + + this.mappingsRegistry.writeFullMappings(); + } + + @Override + public void afterRemap() { + for (ModRemapper remapper : remappers) { + remapper.afterRemapping(); + } + } + + @Override + public List discoverMods(boolean remapClassEdits) { + List collected = new ArrayList<>(); + List candidates = new ArrayList<>(); + Map config2Discoverer = new HashMap<>(); + + for (ModRemapper remapper : remappers) { + for (ModDiscovererConfig config : remapper.getModDiscoverers()) { + V2ModDiscoverer discoverer = new V2ModDiscoverer(config); + config2Discoverer.put(config, discoverer); + candidates.addAll(discoverer.collect()); + } + } + + for (ModRemapper remapper : remappers) { + collected.addAll(remapper.collectSubRemappers(candidates)); + } + + Map> config2Candidates = + candidates.stream().collect(Collectors.groupingBy(ModCandidate::getDiscovererConfig)); + + for (ModCandidate candidate : candidates) { + mappingsRegistry.addModMappings(candidate.getPath()); + } + + mappingsRegistry.generateModMappings(); + + Map candidateToOutput = new HashMap<>(); + + for (Map.Entry> entry : config2Candidates.entrySet()) { + ModDiscovererConfig config = entry.getKey(); + + candidateToOutput.putAll( + config2Discoverer.get(config).computeDestinations(entry.getValue(), this.cacheHandler) + ); + } + + if (!candidateToOutput.isEmpty()) this.remapMods(candidateToOutput); + + return collected; + } + + @Override + public void gatherRemappers() { + + } + + @Override + public MappingsRegistry getMappingsRegistry() { + return mappingsRegistry; + } + + private void registerAdditionalMappings() { + MappingBuilder builder = new V2MappingBuilderImpl(mappingsRegistry.getAdditionalMappings()); + + for (ModRemapper remapper : remappers) { + remapper.registerAdditionalMappings(builder); + } + } + + @Override + public void addToRemapperBuilder(TinyRemapper.Builder builder) { + VisitorInfosImpl preInfos = new VisitorInfosImpl(); + VisitorInfosImpl postInfos = new VisitorInfosImpl(); + + for (ModRemapper remapper : remappers) { + remapper.registerPreVisitors(preInfos); + remapper.registerPostVisitors(postInfos); + } + + builder.extraPreApplyVisitor(new MRAApplyVisitor(preInfos)); + builder.extraPostApplyVisitor(new MRAApplyVisitor(postInfos)); + } + + @Override + public Set getRemappingFlags() { + return remapFlags; + } + + @Override + public LibraryHandler getLibraryHandler() { + return libraryHandler; + } + + public List getRemappers() { + return remappers; + } + + @Override + public MixinData getMixinData() { + return mixinData; + } + + @Override + public void gatherLibraries() { + libraryHandler.init(this.mappingsRegistry.getSourceNamespace(), this.cacheHandler); + + List libraries = new ArrayList<>(); + + for (ModRemapper remapper : remappers) { + remapper.addRemappingLibraries(libraries, FabricLoader.getInstance().getEnvironmentType()); + } + + libraryHandler.cacheLibraries(libraries); + } + + @Override + public CacheHandler getCacheHandler() { + return this.cacheHandler; + } +} diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/v2/V2CacheHandler.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/v2/V2CacheHandler.java new file mode 100644 index 0000000..d3278f9 --- /dev/null +++ b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/v2/V2CacheHandler.java @@ -0,0 +1,60 @@ +package io.github.fabriccompatibiltylayers.modremappingapi.impl.context.v2; + +import io.github.fabriccompatibilitylayers.modremappingapi.impl.InternalCacheHandler; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +public class V2CacheHandler implements InternalCacheHandler { + private final Path contextDirectory; + private final Path tempDirectory, cacheDirectory, mappingsDirectory, librariesDirectory; + + public V2CacheHandler(Path contextDirectory) { + this.contextDirectory = contextDirectory; + tempDirectory = this.contextDirectory.resolve("temp"); + cacheDirectory = this.contextDirectory.resolve("cache"); + mappingsDirectory = this.contextDirectory.resolve("mappings"); + librariesDirectory = this.contextDirectory.resolve("libraries"); + + for (Path p : new Path[]{tempDirectory, cacheDirectory, mappingsDirectory, librariesDirectory}) { + if (!Files.exists(p)) { + try { + Files.createDirectories(p); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + } + + @Override + public Path resolveTemp(String name) { + return tempDirectory.resolve(name); + } + + @Override + public Path resolveCache(String name) { + return cacheDirectory.resolve(name); + } + + @Override + public Path resolveLibrary(String name) { + return librariesDirectory.resolve(name); + } + + @Override + public Path resolveMappings(String name) { + return mappingsDirectory.resolve(name); + } + + @Override + public Path resolveRoot(String name) { + return this.contextDirectory.resolve(name); + } + + @Override + public Path getTempDirectory() { + return tempDirectory; + } +} diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/v2/V2MappingBuilderImpl.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/v2/V2MappingBuilderImpl.java new file mode 100644 index 0000000..171a886 --- /dev/null +++ b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/v2/V2MappingBuilderImpl.java @@ -0,0 +1,76 @@ +package io.github.fabriccompatibiltylayers.modremappingapi.impl.context.v2; + +import io.github.fabriccompatibilitylayers.modremappingapi.api.v2.MappingBuilder; +import net.fabricmc.mappingio.MappedElementKind; +import net.fabricmc.mappingio.tree.MemoryMappingTree; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; + +@ApiStatus.Internal +public class V2MappingBuilderImpl implements MappingBuilder { + private final MemoryMappingTree next; + + public V2MappingBuilderImpl(MemoryMappingTree next) { + this.next = next; + } + + @Override + public ClassMapping addMapping(String sourceName, String targetName) { + this.next.visitClass(sourceName); + this.next.visitDstName(MappedElementKind.CLASS, 0, targetName); + return new ClassMappingImpl(sourceName, targetName, next); + } + + @Override + public ClassMapping addMapping(String name) { + this.next.visitClass(name); + return new ClassMappingImpl(name, null, next); + } + + private static class ClassMappingImpl implements ClassMapping { + private final String sourceName; + private final @Nullable String targetName; + private final MemoryMappingTree next; + + public ClassMappingImpl(String sourceName, @Nullable String targetName, MemoryMappingTree next) { + this.sourceName = sourceName; + this.targetName = targetName; + this.next = next; + } + + private void visit() { + this.next.visitClass(sourceName); + if (targetName != null) this.next.visitDstName(MappedElementKind.CLASS, 0, targetName); + } + + @Override + public ClassMapping field(String sourceName, String targetName, String sourceDescriptor) { + visit(); + + this.next.visitField(sourceName, sourceDescriptor); + if (targetName != null) this.next.visitDstName(MappedElementKind.FIELD, 0, targetName); + + return this; + } + + @Override + public ClassMapping field(String name, String descriptor) { + return this.field(name, null, descriptor); + } + + @Override + public ClassMapping method(String sourceName, String targetName, String sourceDescriptor) { + visit(); + + this.next.visitMethod(sourceName, sourceDescriptor); + if (targetName != null) this.next.visitDstName(MappedElementKind.METHOD, 0, targetName); + + return this; + } + + @Override + public ClassMapping method(String name, String descriptor) { + return this.method(name, null, descriptor); + } + } +} diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/v2/V2ModDiscoverer.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/v2/V2ModDiscoverer.java new file mode 100644 index 0000000..4850de5 --- /dev/null +++ b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/v2/V2ModDiscoverer.java @@ -0,0 +1,143 @@ +package io.github.fabriccompatibiltylayers.modremappingapi.impl.context.v2; + +import io.github.fabriccompatibilitylayers.modremappingapi.api.v2.ModCandidate; +import io.github.fabriccompatibilitylayers.modremappingapi.api.v2.ModDiscovererConfig; +import io.github.fabriccompatibilitylayers.modremappingapi.impl.InternalCacheHandler; +import io.github.fabriccompatibiltylayers.modremappingapi.impl.mappings.MappingsRegistry; +import io.github.fabriccompatibiltylayers.modremappingapi.impl.utils.FileUtils; +import net.fabricmc.loader.api.FabricLoader; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.stream.Collectors; + +public class V2ModDiscoverer { + private final ModDiscovererConfig config; + private Path originalDirectory; + + public V2ModDiscoverer(ModDiscovererConfig config) { + this.config = config; + } + + public List collect() { + originalDirectory = FabricLoader.getInstance().getGameDir().resolve(config.getFolderName()); + + if (!Files.isDirectory(originalDirectory)) return new ArrayList<>(); + + List candidates = new ArrayList<>(); + + try { + searchDir(candidates, originalDirectory); + } catch (IOException e) { + throw new RuntimeException(e); + } + + return candidates; + } + + private void searchDir(List candidates, Path dir) throws IOException { + try (DirectoryStream stream = Files.newDirectoryStream(dir)) { + for (Path path : stream) { + String name = path.getFileName().toString(); + + if (Files.isDirectory(path)) { + if (config.searchRecursively()) { + if (config.getDirectoryFilter().test(name)) searchDir(candidates, path); + } else if (config.allowDirectoryMods()) { + discoverMods(candidates, path); + } + } else if (Files.exists(path)) { + Matcher matcher = config.getFileNameMatcher().matcher(name); + + if (matcher.matches()) { + discoverMods(candidates, path); + } + } + } + } + } + + private void discoverMods(List candidates, Path modPath) throws IOException { + List entries = FileUtils.listPathContent(modPath); + + candidates.addAll(config.getCandidateCollector().collect(config, modPath, entries)); + } + + public void excludeClassEdits(List candidates, InternalCacheHandler cacheHandler, MappingsRegistry registry) throws IOException, URISyntaxException { + Path tempDirectory = cacheHandler.resolveTemp(this.config.getFolderName()); + + if (!Files.exists(tempDirectory)) { + try { + Files.createDirectories(tempDirectory); + } catch (IOException e) { + throw new RuntimeException(e); + } + } else { + FileUtils.emptyDir(tempDirectory); + } + + for (ModCandidate candidate : candidates) { + Path modPath = candidate.getPath(); + + String outputName = candidate.getDestinationName(); + Path outputPath = tempDirectory.resolve(outputName); + + if (Files.isDirectory(modPath)) { + FileUtils.zipFolder(modPath, outputPath); + } else { + Files.copy(modPath, outputPath); + } + + FileUtils.removeEntriesFromZip(outputPath, registry.getVanillaClassNames()); + + candidate.setPath(outputPath); + } + } + + public Map computeDestinations(List candidates, InternalCacheHandler cacheHandler) { + Path destination; + + if (config.getExportToOriginalFolder()) { + destination = originalDirectory; + } else { + destination = cacheHandler.resolveCache(config.getFolderName()); + } + + if (!Files.exists(destination)) { + try { + Files.createDirectories(destination); + } catch (IOException e) { + throw new RuntimeException(e); + } + } else if (!config.getExportToOriginalFolder()) { + FileUtils.emptyDir(destination); + } + + Path finalDestination = destination; + + return candidates.stream().collect(Collectors.toMap( + candidate -> candidate, + candidate -> { + Path modDestination = finalDestination.resolve(candidate.getDestinationName()); + candidate.setDestination(modDestination); + + if (Files.exists(modDestination)) { + try { + Files.delete(modDestination); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + return modDestination; + } + )); + } +} diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/discover/BaseModDiscoverer.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/discover/BaseModDiscoverer.java deleted file mode 100644 index f77c0e6..0000000 --- a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/discover/BaseModDiscoverer.java +++ /dev/null @@ -1,99 +0,0 @@ -package io.github.fabriccompatibiltylayers.modremappingapi.impl.discover; - -import io.github.fabriccompatibiltylayers.modremappingapi.impl.ModCandidate; -import io.github.fabriccompatibiltylayers.modremappingapi.impl.mappings.MappingsRegistry; -import io.github.fabriccompatibiltylayers.modremappingapi.impl.utils.FileUtils; -import org.spongepowered.include.com.google.common.collect.ImmutableList; - -import java.io.IOException; -import java.net.URISyntaxException; -import java.nio.file.DirectoryStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardCopyOption; -import java.util.*; - -public abstract class BaseModDiscoverer { - public abstract boolean isValidFileName(String fileName); - public abstract boolean allowDirectoryMods(); - public abstract boolean searchRecursively(); - public abstract boolean isValidDirectoryName(String directoryName); - public abstract Optional discoverFolderMod(Path folder, Path destinationFolder) throws IOException; - public abstract Optional discoverFileMod(Path file, Path destinationFolder) throws IOException; - - public List discoverMods(Path folder, Path destination) throws IOException { - List mods = new ArrayList<>(); - - if (!Files.isDirectory(folder)) return ImmutableList.of(); - - try (DirectoryStream stream = Files.newDirectoryStream(folder)) { - for (Path path : stream) { - String name = path.getFileName().toString(); - - if (Files.isDirectory(path)) { - if (searchRecursively() && isValidDirectoryName(name)) { - mods.addAll(discoverMods(folder.resolve(name), destination.resolve(name))); - } else if (allowDirectoryMods()) { - discoverFolderMod(path, destination) - .ifPresent(mods::add); - } - } else if (Files.exists(path) && isValidFileName(name)) { - discoverFileMod(path, destination) - .ifPresent(mods::add); - } - } - } - - return mods; - } - - public Map excludeClassEdits(Map modPaths, Path tempFolder, MappingsRegistry mappingsRegistry) { - Map map = new HashMap<>(); - Map convertMap = new HashMap<>(); - - for (Map.Entry entry : modPaths.entrySet()) { - ModCandidate modCandidate = entry.getKey(); - Path tempDir = tempFolder.resolve(entry.getValue().getParent().getFileName().toString()); - - if (!Files.exists(tempDir)) { - try { - Files.createDirectory(tempDir); - } catch (IOException e) { - e.printStackTrace(); - continue; - } - } - - Path tempFile = tempDir.resolve(entry.getValue().getFileName().toString()); - map.put(new ModCandidate( - modCandidate.modName, - modCandidate.accessWidenerName, - modCandidate.file, - tempFile - ), entry.getValue()); - convertMap.put(entry.getKey(), tempFile); - } - - List errored = new ArrayList<>(); - - for (Map.Entry entry : convertMap.entrySet()) { - ModCandidate modCandidate = entry.getKey(); - try { - if (Files.isDirectory(modCandidate.original)) { - FileUtils.zipFolder(modCandidate.original, entry.getValue()); - } else { - Files.copy(modCandidate.original, entry.getValue(), StandardCopyOption.REPLACE_EXISTING); - } - - FileUtils.removeEntriesFromZip(entry.getValue(), mappingsRegistry.getVanillaClassNames()); - } catch (IOException | URISyntaxException e) { - e.printStackTrace(); - errored.add(modCandidate); - } - } - - errored.forEach(map::remove); - - return map; - } -} diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/mappings/MappingsRegistry.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/mappings/MappingsRegistry.java index 0d42728..3c83517 100644 --- a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/mappings/MappingsRegistry.java +++ b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/mappings/MappingsRegistry.java @@ -43,7 +43,7 @@ public abstract class MappingsRegistry { public abstract List getVanillaClassNames(); public abstract MemoryMappingTree getFormattedMappings(); - public abstract void addToFormattedMappings(InputStream stream) throws IOException; + public abstract void addToFormattedMappings(InputStream stream, Map renames) throws IOException; public abstract void completeFormattedMappings() throws IOException; public abstract void addModMappings(Path path); public abstract void generateModMappings(); diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/ModTrRemapper.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/ModTrRemapper.java index 4e76089..c5d2687 100644 --- a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/ModTrRemapper.java +++ b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/ModTrRemapper.java @@ -1,12 +1,16 @@ package io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper; -import io.github.fabriccompatibiltylayers.modremappingapi.impl.ModCandidate; +import com.google.gson.Gson; +import io.github.fabriccompatibilitylayers.modremappingapi.api.v2.ModCandidate; +import io.github.fabriccompatibilitylayers.modremappingapi.api.v2.RemappingFlags; import io.github.fabriccompatibiltylayers.modremappingapi.impl.context.ModRemapperContext; import io.github.fabriccompatibiltylayers.modremappingapi.impl.mappings.MappingTreeHelper; import io.github.fabriccompatibiltylayers.modremappingapi.impl.mappings.MappingsRegistry; +import io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper.asm.mixin.RefmapBaseMixinExtension; import io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper.minecraft.MinecraftRemapper; +import io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper.resource.RefmapJson; import io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper.resource.RefmapRemapper; -import io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper.visitor.MixinPostApplyVisitor; +import io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper.visitor.MixinPostApplyVisitorProvider; import io.github.fabriccompatibiltylayers.modremappingapi.impl.utils.FileUtils; import net.fabricmc.accesswidener.AccessWidenerReader; import net.fabricmc.accesswidener.AccessWidenerRemapper; @@ -22,6 +26,7 @@ import org.objectweb.asm.commons.Remapper; import java.io.IOException; +import java.net.URISyntaxException; import java.nio.file.FileSystem; import java.nio.file.Files; import java.nio.file.Path; @@ -54,15 +59,17 @@ public static TinyRemapper makeRemapper(ModRemapperContext context) { context.addToRemapperBuilder(builder); if (context.getRemappingFlags().contains(RemappingFlags.MIXIN)) { - MixinPostApplyVisitor mixinPostApplyVisitor = new MixinPostApplyVisitor(); - builder.extraPostApplyVisitor(mixinPostApplyVisitor); - builder.extension(new MixinExtension(EnumSet.of(MixinExtension.AnnotationTarget.HARD))); + builder.extension(new RefmapBaseMixinExtension(inputTag -> !context.getMixinData().getHardMixins().contains(inputTag))); + + MixinPostApplyVisitorProvider mixinPostApplyVisitorProvider = new MixinPostApplyVisitorProvider(); + builder.extraPostApplyVisitor(mixinPostApplyVisitorProvider); + builder.extension(new MixinExtension(context.getMixinData().getHardMixins()::contains)); } TinyRemapper remapper = builder.build(); try { - MinecraftRemapper.addMinecraftJar(remapper, mappingsRegistry); + MinecraftRemapper.addMinecraftJar(remapper, mappingsRegistry, context.getCacheHandler()); } catch (IOException e) { throw new RuntimeException(e); } @@ -75,16 +82,24 @@ public static TinyRemapper makeRemapper(ModRemapperContext context) { public static void remapMods(TinyRemapper remapper, Map paths, ModRemapperContext context) { List outputConsumerPaths = new ArrayList<>(); - List resourceRemappers = new ArrayList<>(NonClassCopyMode.FIX_META_INF.remappers); - resourceRemappers.add(new RefmapRemapper()); + if (context.getRemappingFlags().contains(RemappingFlags.MIXIN)) { + try { + analyzeRefMaps(paths.keySet(), context); + } catch (IOException | URISyntaxException e) { + throw new RuntimeException(e); + } + } + + List resourcePostRemappers = new ArrayList<>(NonClassCopyMode.FIX_META_INF.remappers); + if (context.getRemappingFlags().contains(RemappingFlags.MIXIN)) resourcePostRemappers.add(new RefmapRemapper()); Consumer consumer = getRemapperConsumer(paths, context); TrRemapperHelper.applyRemapper( remapper, - paths.entrySet().stream().collect(Collectors.toMap(entry -> entry.getKey().original, Map.Entry::getValue)), + paths.entrySet().stream().collect(Collectors.toMap(entry -> entry.getKey().getPath(), Map.Entry::getValue)), outputConsumerPaths, - resourceRemappers, + resourcePostRemappers, true, context.getMappingsRegistry().getSourceNamespace(), context.getMappingsRegistry().getTargetNamespace(), @@ -96,12 +111,12 @@ public static void remapMods(TinyRemapper remapper, Map path ModCandidate candidate = entry.getKey(); Path jarPath = entry.getValue(); - if (candidate.accessWidenerName != null && candidate.accessWidener != null) { + if (candidate.getAccessWidenerPath() != null && candidate.getAccessWidener() != null) { try (FileSystem fs = FileUtils.getJarFileSystem(jarPath)) { - Files.delete(fs.getPath(candidate.accessWidenerName)); - Files.write(fs.getPath(candidate.accessWidenerName), candidate.accessWidener); + Files.delete(fs.getPath(candidate.getAccessWidenerPath())); + Files.write(fs.getPath(candidate.getAccessWidenerPath()), candidate.getAccessWidener()); } catch (Throwable t) { - throw new RuntimeException("Error while writing remapped access widener for '" + candidate.modName + "'", t); + throw new RuntimeException("Error while writing remapped access widener for '" + candidate.getId() + "'", t); } } } @@ -116,11 +131,11 @@ public static void remapMods(TinyRemapper remapper, Map path for (Map.Entry entry : paths.entrySet()) { ModCandidate candidate = entry.getKey(); - if (candidate.accessWidenerName != null) { - try (FileSystem jarFs = FileUtils.getJarFileSystem(candidate.original)) { - candidate.accessWidener = remapAccessWidener(Files.readAllBytes(jarFs.getPath(candidate.accessWidenerName)), currentRemapper.getRemapper(), context.getMappingsRegistry().getTargetNamespace()); + if (candidate.getAccessWidenerPath() != null) { + try (FileSystem jarFs = FileUtils.getJarFileSystem(candidate.getPath())) { + candidate.setAccessWidener(remapAccessWidener(Files.readAllBytes(jarFs.getPath(candidate.getAccessWidenerPath())), currentRemapper.getRemapper(), context.getMappingsRegistry().getTargetNamespace())); } catch (Throwable t) { - throw new RuntimeException("Error while remapping access widener for '" + candidate.modName + "'", t); + throw new RuntimeException("Error while remapping access widener for '" + candidate.getId() + "'", t); } } } @@ -137,4 +152,36 @@ private static byte[] remapAccessWidener(byte[] data, Remapper remapper, String accessWidenerReader.read(data, "intermediary"); return writer.write(); } + + private static Gson GSON = new Gson(); + + private static void analyzeRefMaps(Set candidates, ModRemapperContext context) throws IOException, URISyntaxException { + for (ModCandidate candidate : candidates) { + Path path = candidate.getPath(); + + List files = FileUtils.listPathContent(path); + + List refmaps = new ArrayList<>(); + + for (String file : files) { + if (file.contains("refmap") && file.endsWith(".json")) { + refmaps.add(file); + } + } + + if (!refmaps.isEmpty()) { + try (FileSystem fs = FileUtils.getJarFileSystem(path)) { + for (String refmap : refmaps) { + Path refmapPath = fs.getPath(refmap); + + RefmapJson refmapJson = GSON.fromJson(new String(Files.readAllBytes(refmapPath)), RefmapJson.class); + + refmapJson.remap(context.getMappingsRegistry().getFullMappings(), context.getMappingsRegistry().getSourceNamespace(), context.getMappingsRegistry().getTargetNamespace()); + + context.getMixinData().getMixinRefmapData().putAll(refmapJson.mappings); + } + } + } + } + } } diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/SoftLockFixer.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/SoftLockFixer.java index c247ae0..30d7093 100644 --- a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/SoftLockFixer.java +++ b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/SoftLockFixer.java @@ -68,11 +68,11 @@ public static void preloadClasses() { "fr.catcore.modremapperapi.remapping.VisitorInfos$MethodNamed", "fr.catcore.modremapperapi.remapping.VisitorInfos$MethodValue", "fr.catcore.modremapperapi.remapping.VisitorInfos$Type", - "io.github.fabriccompatibiltylayers.modremappingapi.impl.DefaultModRemapper", "io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper.resource.RefmapJson", - "io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper.visitor.MixinPostApplyVisitor", + "io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper.visitor.MixinPostApplyVisitorProvider", "io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper.asm.MRAClassVisitor", "io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper.asm.MRAMethodVisitor", + "io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper.asm.mixin.RefmapBaseMixinExtension", "io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper.visitor.MRAApplyVisitor", "io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper.resource.RefmapRemapper", "io.github.fabriccompatibiltylayers.modremappingapi.impl.mappings.MappingsRegistry", @@ -218,7 +218,10 @@ public static void preloadClasses() { getLibClassName("mappingio", "MappingUtil"), getLibClassName("mappingio", "MappingVisitor"), getLibClassName("mappingio", "MappingWriter"), - getLibClassName("mappingio", "MappingWriter$1") + getLibClassName("mappingio", "MappingWriter$1"), + + getLibClassName("tinyremapper", "extension.mixin.hard.ImprovedHardTargetMixinClassVisitor"), + getLibClassName("tinyremapper", "extension.mixin.hard.ImprovedMixinAnnotationVisitor"), }) { try { Constants.MAIN_LOGGER.debug("Preloading class: " + clazz); diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/TrRemapperHelper.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/TrRemapperHelper.java index 93c666a..a60acf8 100644 --- a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/TrRemapperHelper.java +++ b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/TrRemapperHelper.java @@ -1,7 +1,9 @@ package io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper; import fr.catcore.modremapperapi.utils.Constants; +import io.github.fabriccompatibilitylayers.modremappingapi.api.v2.RemappingFlags; import io.github.fabriccompatibiltylayers.modremappingapi.impl.ModRemappingAPIImpl; +import io.github.fabriccompatibiltylayers.modremappingapi.impl.utils.FileUtils; import net.fabricmc.tinyremapper.InputTag; import net.fabricmc.tinyremapper.OutputConsumerPath; import net.fabricmc.tinyremapper.TinyRemapper; @@ -9,19 +11,24 @@ import org.jetbrains.annotations.Nullable; import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.FileSystem; +import java.nio.file.Files; import java.nio.file.Path; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.Consumer; +import java.util.jar.Attributes; +import java.util.jar.Manifest; @ApiStatus.Internal public class TrRemapperHelper { - public static void applyRemapper(TinyRemapper remapper, Map paths, List outputConsumerPaths, List resourceRemappers, boolean analyzeMapping, String srcNamespace, String targetNamespace) { - applyRemapper(remapper, paths, outputConsumerPaths, resourceRemappers, analyzeMapping, srcNamespace, targetNamespace, null); + public static void applyRemapper(TinyRemapper remapper, Map paths, List outputConsumerPaths, List resourcePostRemappers, boolean analyzeMapping, String srcNamespace, String targetNamespace) { + applyRemapper(remapper, paths, outputConsumerPaths, resourcePostRemappers, analyzeMapping, srcNamespace, targetNamespace, null); } - public static void applyRemapper(TinyRemapper remapper, Map paths, List outputConsumerPaths, List resourceRemappers, boolean analyzeMapping, String srcNamespace, String targetNamespace, @Nullable Consumer action) { + public static void applyRemapper(TinyRemapper remapper, Map paths, List outputConsumerPaths, List resourcePostRemappers, boolean analyzeMapping, String srcNamespace, String targetNamespace, @Nullable Consumer action) { try { Map tagMap = new HashMap<>(); @@ -29,6 +36,11 @@ public static void applyRemapper(TinyRemapper remapper, Map paths, L for (Path input : paths.keySet()) { InputTag tag = remapper.createInputTag(); tagMap.put(input, tag); + + if (ModRemappingAPIImpl.getCurrentContext().getRemappingFlags().contains(RemappingFlags.MIXIN)) { + if (useHardMixinRemap(input)) ModRemappingAPIImpl.getCurrentContext().getMixinData().getHardMixins().add(tag); + } + remapper.readInputsAsync(tag, input); } @@ -43,7 +55,7 @@ public static void applyRemapper(TinyRemapper remapper, Map paths, L remapper.apply(outputConsumer, tagMap.get(entry.getKey())); Constants.MAIN_LOGGER.debug("Add input as non class file!"); - outputConsumer.addNonClassFiles(entry.getKey(), remapper, resourceRemappers); + outputConsumer.addNonClassFiles(entry.getKey(), remapper, resourcePostRemappers); Constants.MAIN_LOGGER.debug("Done 1!"); } @@ -72,4 +84,17 @@ public static void applyRemapper(TinyRemapper remapper, Map paths, L }); } } + + private static boolean useHardMixinRemap(Path inputPath) throws IOException, URISyntaxException { + try (FileSystem fs = FileUtils.getJarFileSystem(inputPath)) { + Path manifestPath = fs.getPath("/META-INF/MANIFEST.MF"); + + if (!Files.exists(manifestPath)) return false; + + Manifest manifest = new Manifest(Files.newInputStream(manifestPath)); + Attributes mainAttributes = manifest.getMainAttributes(); + + return "static".equalsIgnoreCase(mainAttributes.getValue("Fabric-Loom-Mixin-Remap-Type")); + } + } } diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/asm/MRAMethodVisitor.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/asm/MRAMethodVisitor.java index 1a9600a..f2fcde9 100644 --- a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/asm/MRAMethodVisitor.java +++ b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/asm/MRAMethodVisitor.java @@ -1,6 +1,6 @@ package io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper.asm; -import io.github.fabriccompatibiltylayers.modremappingapi.api.v1.VisitorInfos; +import io.github.fabriccompatibilitylayers.modremappingapi.api.v2.VisitorInfos; import io.github.fabriccompatibiltylayers.modremappingapi.impl.VisitorInfosImpl; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; @@ -57,9 +57,9 @@ public void visitFieldInsn(int opcode, String owner, String name, String descrip } if (classMember != null) { - currentOwner = classMember.owner; - currentName = classMember.name; - currentDescriptor = classMember.desc; + currentOwner = classMember.getOwner(); + currentName = classMember.getName(); + currentDescriptor = classMember.getDesc(); } } } @@ -107,11 +107,11 @@ public void visitMethodInsn(int opcode, String owner, String name, String descri } if (fullClassMember != null) { - currentOwner = fullClassMember.owner; - currentName = fullClassMember.name; - currentDescriptor = fullClassMember.desc; + currentOwner = fullClassMember.getOwner(); + currentName = fullClassMember.getName(); + currentDescriptor = fullClassMember.getDesc(); - if (fullClassMember.isStatic != null) currentOpcode = fullClassMember.isStatic ? INVOKESTATIC : INVOKEVIRTUAL; + if (fullClassMember.isStatic() != null) currentOpcode = fullClassMember.isStatic() ? INVOKESTATIC : INVOKEVIRTUAL; } } } diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/asm/mixin/RefmapBaseMixinExtension.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/asm/mixin/RefmapBaseMixinExtension.java new file mode 100644 index 0000000..ddcffe4 --- /dev/null +++ b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/asm/mixin/RefmapBaseMixinExtension.java @@ -0,0 +1,74 @@ +package io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper.asm.mixin; + +import net.fabricmc.tinyremapper.InputTag; +import net.fabricmc.tinyremapper.TinyRemapper; +import net.fabricmc.tinyremapper.api.TrEnvironment; +import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; +import net.fabricmc.tinyremapper.extension.mixin.hard.ImprovedHardTargetMixinClassVisitor; +import org.objectweb.asm.ClassVisitor; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.function.Consumer; +import java.util.function.Predicate; + +public class RefmapBaseMixinExtension implements TinyRemapper.Extension { + private final Map>> tasks; + private final Predicate inputTagFilter; + + public RefmapBaseMixinExtension(Predicate inputTagFilter) { + this.tasks = new ConcurrentHashMap<>(); + this.inputTagFilter = inputTagFilter; + } + + @Override + public void attach(TinyRemapper.Builder builder) { + builder.extraAnalyzeVisitor(new AnalyzeVisitorProvider()).extraStateProcessor(this::stateProcessor); + } + + private void stateProcessor(TrEnvironment environment) { + CommonData data = new CommonData(environment); + + for (Consumer task : tasks.getOrDefault(environment.getMrjVersion(), Collections.emptyList())) { + try { + task.accept(data); + } catch (RuntimeException e) { + environment.getLogger().error(e.getMessage()); + } + } + } + + private final class AnalyzeVisitorProvider implements TinyRemapper.AnalyzeVisitorProvider { + @Override + public ClassVisitor insertAnalyzeVisitor(int mrjVersion, String className, ClassVisitor next) { + return new ImprovedHardTargetMixinClassVisitor(tasks.computeIfAbsent(mrjVersion, k -> new ConcurrentLinkedQueue<>()), next); + } + + @Override + public ClassVisitor insertAnalyzeVisitor(int mrjVersion, String className, ClassVisitor next, InputTag[] inputTags) { + if (inputTagFilter == null || inputTags == null) { + return insertAnalyzeVisitor(mrjVersion, className, next); + } else { + for (InputTag tag : inputTags) { + if (inputTagFilter.test(tag)) { + return insertAnalyzeVisitor(mrjVersion, className, next); + } + } + + return next; + } + } + + @Override + public ClassVisitor insertAnalyzeVisitor(boolean isInput, int mrjVersion, String className, ClassVisitor next, InputTag[] inputTags) { + if (!isInput) { + return next; + } + + return insertAnalyzeVisitor(mrjVersion, className, next, inputTags); + } + } +} diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/minecraft/MinecraftRemapper.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/minecraft/MinecraftRemapper.java index 2601d85..f51dbab 100644 --- a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/minecraft/MinecraftRemapper.java +++ b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/minecraft/MinecraftRemapper.java @@ -1,11 +1,11 @@ package io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper.minecraft; import fr.catcore.modremapperapi.utils.Constants; +import io.github.fabriccompatibilitylayers.modremappingapi.api.v2.CacheHandler; import io.github.fabriccompatibiltylayers.modremappingapi.impl.RemapUtils; import io.github.fabriccompatibiltylayers.modremappingapi.impl.mappings.MappingTreeHelper; import io.github.fabriccompatibiltylayers.modremappingapi.impl.mappings.MappingsRegistry; import io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper.TrRemapperHelper; -import io.github.fabriccompatibiltylayers.modremappingapi.impl.utils.CacheUtils; import io.github.fabriccompatibiltylayers.modremappingapi.impl.utils.FileUtils; import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.tinyremapper.NonClassCopyMode; @@ -17,17 +17,23 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.*; +import java.util.stream.Collectors; @ApiStatus.Internal public class MinecraftRemapper { - private static Collection getMinecraftJar(Collection sourcePaths, String src, String target, MappingsRegistry mappingsRegistry) throws IOException { - Path targetFolder = CacheUtils.getLibraryPath(target); + private static Map computeLibraryPaths(Collection sourcePaths, Path basePath) { + return sourcePaths.stream().collect(Collectors.toMap(p -> p, + p -> basePath.resolve(p.getFileName()))); + } + + private static Collection getMinecraftJar(Collection sourcePaths, String src, String target, MappingsRegistry mappingsRegistry, CacheHandler cacheHandler) throws IOException { + Path targetFolder = cacheHandler.resolveLibrary(target); if (!Files.exists(targetFolder)) { Files.createDirectories(targetFolder); } - Map paths = CacheUtils.computeLibraryPaths(new HashSet<>(sourcePaths), target); + Map paths = computeLibraryPaths(new HashSet<>(sourcePaths), targetFolder); if (FileUtils.exist(paths.values())) return paths.values(); @@ -62,20 +68,21 @@ private static Collection getMinecraftJar(Collection sourcePaths, St } @ApiStatus.Internal - public static void addMinecraftJar(TinyRemapper remapper, MappingsRegistry mappingsRegistry) throws IOException { + public static void addMinecraftJar(TinyRemapper remapper, MappingsRegistry mappingsRegistry, CacheHandler cacheHandler) throws IOException { Collection classPath; if (FabricLoader.getInstance().isDevelopmentEnvironment()) { try { classPath = getMinecraftJar( - getMinecraftJar(RemapUtils.getRemapClasspath(), mappingsRegistry.getTargetNamespace(), "intermediary", mappingsRegistry), + getMinecraftJar(RemapUtils.getRemapClasspath(), mappingsRegistry.getTargetNamespace(), "intermediary", mappingsRegistry, cacheHandler), "intermediary", "official", - mappingsRegistry + mappingsRegistry, + cacheHandler ); if (!mappingsRegistry.isSourceNamespaceObf()) { - classPath = getMinecraftJar(classPath, "official", mappingsRegistry.getSourceNamespace(), mappingsRegistry); + classPath = getMinecraftJar(classPath, "official", mappingsRegistry.getSourceNamespace(), mappingsRegistry, cacheHandler); } } catch (IOException e) { throw new RuntimeException("Failed to populate default remap classpath", e); @@ -84,7 +91,7 @@ public static void addMinecraftJar(TinyRemapper remapper, MappingsRegistry mappi classPath = RemapUtils.getClassPathFromObjectShare(); if (!mappingsRegistry.isSourceNamespaceObf()) { - classPath = getMinecraftJar(classPath, "official", mappingsRegistry.getSourceNamespace(), mappingsRegistry); + classPath = getMinecraftJar(classPath, "official", mappingsRegistry.getSourceNamespace(), mappingsRegistry, cacheHandler); } } diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/resource/RefmapJson.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/resource/RefmapJson.java index b09f442..c004b4b 100644 --- a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/resource/RefmapJson.java +++ b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/resource/RefmapJson.java @@ -1,25 +1,210 @@ package io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper.resource; +import io.github.fabriccompatibiltylayers.modremappingapi.impl.ModRemappingAPIImpl; +import net.fabricmc.mappingio.tree.MappingTree; import net.fabricmc.tinyremapper.TinyRemapper; +import net.fabricmc.tinyremapper.api.TrRemapper; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; public class RefmapJson { public final Map> mappings = new HashMap<>(); public final Map>> data = new HashMap<>(); - public void remap(RefmapRemapper remapper, TinyRemapper tiny) { + public void remap(TinyRemapper tiny) { this.data.clear(); // for every class entry we need to remap the mappings of references this.mappings.forEach((mixinClass, refmapEntryMap) -> refmapEntryMap.replaceAll((originalName, oldMappedName) -> - remapper.mapRefMapEntry(mixinClass, oldMappedName, tiny) + mapRefMapEntry(mixinClass, oldMappedName, tiny) ) ); this.data.put("named:intermediary", this.mappings); } + + public void remap(MappingTree tree, String from, String to) { + this.data.clear(); + + this.mappings.forEach((mixinClass, refmapEntryMap) -> refmapEntryMap.entrySet() + .stream().filter(this::filterClass) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)) + .replaceAll((originalName, oldMappedName) -> + mapRefMapEntry(mixinClass, oldMappedName, tree, from, to))); + } + + private boolean filterClass(Map.Entry stringStringEntry) { + String value = stringStringEntry.getValue(); + + return value != null && + value.contains("/") && + !value.contains(";") && + !value.contains(":") && + !value.contains("("); + } + + private String mapRefMapEntry(String mixinClass, String old, MappingTree tree, String from, String to) { + int fromId = tree.getNamespaceId(from); + int toId = tree.getNamespaceId(to); + + return tree.mapClassName(old, fromId, toId); + } + + private String mapRefMapEntry(String mixinClass, String old, TinyRemapper remapper) { + TrRemapper trRemapper = remapper.getEnvironment().getRemapper(); + List supers = ModRemappingAPIImpl.getCurrentContext().getMixinData().getMixin2TargetMap().get(mixinClass); + // format is: + // owner + name + quantifier + (desc == null || desc.startsWith("(") ? "" : ":") + desc + (tail != null ? " -> " : "") + tail + String owner; // can be "" + String name; // can be "" + String quantifier; // can be "" + String desc; // can be "" + String tail; // can be "" + + // read the entry + { + String rest; + // get tail + { + String arrow = " -> "; + int arrowPosition = old.indexOf(arrow); + if (arrowPosition == -1) { // tail == null + tail = ""; + rest = old; + } else { + rest = old.substring(0, arrowPosition); + tail = old.substring(arrowPosition + arrow.length()); + } + } + + // get desc + { + int separatorPosition = rest.indexOf(":"); + if (separatorPosition == -1) { // separator == null + int parenthesisPosition = rest.indexOf("("); + if (parenthesisPosition == -1) { + desc = ""; + } else { + // if there's no ':', then there must be an opening bracket or **the desc is null** + desc = rest.substring(parenthesisPosition); + rest = rest.substring(0, parenthesisPosition); + } + } else { + desc = rest.substring(separatorPosition + 1); + rest = rest.substring(0, separatorPosition); + } + } + + // get owner + { + if (rest.startsWith("L")) { // owner != null + int endPosition = rest.indexOf(";"); + if (endPosition == -1) { + throw new RuntimeException( + "Cannot parse refmap entry of class " + mixinClass + ": it starts with 'L', and doesn't contain a ';': " + old); + } else { + owner = rest.substring(1, endPosition); + rest = rest.substring(endPosition + 1); // we don't want the ';' here + } + } else { + owner = ""; + } + } + + // get quantifier + { + // try to find either '{', '+' or '*' + int bracesPosition = rest.indexOf("{"); + if (bracesPosition == -1) + bracesPosition = rest.indexOf("*"); + if (bracesPosition == -1) + bracesPosition = rest.indexOf("+"); + + if (bracesPosition == -1) { + // try the * and + + quantifier = ""; + } else { + quantifier = rest.substring(bracesPosition); + rest = rest.substring(0, bracesPosition); + } + } + + // get name + { + name = rest; // only name is left +// if (name.isEmpty()) { +// throw new RuntimeException("Cannot parse refmap entry of class " + mixinClass + +// ": the name is \"\", so something went wrong: owner = \"" + owner + "\", name = \"" + name + +// "\", quantifier = \"" + quantifier + "\", desc = \"" + desc + "\", tail = \"" + tail + +// "\", old = \"" + old + "\""); +// } + } + } + + // for now just stop here, most stuff doesn't use quantifiers or tails + if (!quantifier.isEmpty()) + throw new RuntimeException("Quantifiers are not yet supported: " + old); + if (!tail.isEmpty()) + throw new RuntimeException("Tails are not yet supported: " + tail); + + // do the actual mapping + + // it's a class + if (owner.isEmpty() && desc.isEmpty()) { + return trRemapper.map(name); + } + + // it's a method + if (desc.startsWith("(") && desc.contains(")")) { + if (owner.isEmpty()) { // it's an @Invoker + if (supers == null || supers.isEmpty()) { + throw new RuntimeException("Can't find target class for mixin " + mixinClass); + } + + final String originalName = name; + String newDesc = trRemapper.mapMethodDesc(desc); + + if (!originalName.isEmpty()) { + for (String own : supers) { + name = trRemapper.mapMethodName(own, name, desc); + + if (!originalName.equals(name)) { + return name + newDesc; + } + } + } + + return originalName + newDesc; + } else { // just a normal method + return "L" + trRemapper.map(owner) + ";" + trRemapper.mapMethodName(owner, name, desc) + trRemapper.mapMethodDesc(desc); + } + } + + // it's an @Accessor + if (owner.isEmpty()) { + if (supers == null || supers.isEmpty()) { + throw new RuntimeException("Can't find target class for mixin " + mixinClass); + } + + final String originalName = name; + + for (String own : supers) { + name = trRemapper.mapFieldName(own, name, desc); + + if (!originalName.equals(name)) { + return name; + } + } + + return originalName; + } + + // just a normal field + return "L" + trRemapper.map(owner) + ";" + trRemapper.mapFieldName(owner, name, desc) + ":" + trRemapper.mapDesc(desc); + } } diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/resource/RefmapRemapper.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/resource/RefmapRemapper.java index 998c92f..e227f02 100644 --- a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/resource/RefmapRemapper.java +++ b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/resource/RefmapRemapper.java @@ -1,16 +1,13 @@ package io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper.resource; import com.google.gson.Gson; -import io.github.fabriccompatibiltylayers.modremappingapi.impl.ModRemappingAPIImpl; import net.fabricmc.tinyremapper.OutputConsumerPath; import net.fabricmc.tinyremapper.TinyRemapper; -import net.fabricmc.tinyremapper.api.TrRemapper; import java.io.*; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; -import java.util.List; public class RefmapRemapper implements OutputConsumerPath.ResourceRemapper { private Gson GSON; @@ -29,7 +26,7 @@ public void transform(Path destinationDirectory, Path relativePath, InputStream RefmapJson json = GSON.fromJson(new InputStreamReader(input), RefmapJson.class); - json.remap(this, remapper); + json.remap(remapper); try (OutputStream os = new BufferedOutputStream(Files.newOutputStream(outputFile))) { DataOutputStream outputStream = new DataOutputStream(os); @@ -37,155 +34,4 @@ public void transform(Path destinationDirectory, Path relativePath, InputStream outputStream.flush(); } } - - public String mapRefMapEntry(String mixinClass, String old, TinyRemapper remapper) { - TrRemapper trRemapper = remapper.getEnvironment().getRemapper(); - List supers = ModRemappingAPIImpl.getCurrentContext().getMixin2TargetMap().get(mixinClass); - // format is: - // owner + name + quantifier + (desc == null || desc.startsWith("(") ? "" : ":") + desc + (tail != null ? " -> " : "") + tail - String owner; // can be "" - String name; - String quantifier; // can be "" - String desc; // can be "" - String tail; // can be "" - - // read the entry - { - String rest; - // get tail - { - String arrow = " -> "; - int arrowPosition = old.indexOf(arrow); - if (arrowPosition == -1) { // tail == null - tail = ""; - rest = old; - } else { - rest = old.substring(0, arrowPosition); - tail = old.substring(arrowPosition + arrow.length()); - } - } - - // get desc - { - int separatorPosition = rest.indexOf(":"); - if (separatorPosition == -1) { // separator == null - int parenthesisPosition = rest.indexOf("("); - if (parenthesisPosition == -1) { - desc = ""; - } else { - // if there's no ':', then there must be an opening bracket or **the desc is null** - desc = rest.substring(parenthesisPosition); - rest = rest.substring(0, parenthesisPosition); - } - } else { - desc = rest.substring(separatorPosition + 1); - rest = rest.substring(0, separatorPosition); - } - } - - // get owner - { - if (rest.startsWith("L")) { // owner != null - int endPosition = rest.indexOf(";"); - if (endPosition == -1) { - throw new RuntimeException( - "Cannot parse refmap entry of class " + mixinClass + ": it starts with 'L', and doesn't contain a ';': " + old); - } else { - owner = rest.substring(1, endPosition); - rest = rest.substring(endPosition + 1); // we don't want the ';' here - } - } else { - owner = ""; - } - } - - // get quantifier - { - // try to find either '{', '+' or '*' - int bracesPosition = rest.indexOf("{"); - if (bracesPosition == -1) - bracesPosition = rest.indexOf("*"); - if (bracesPosition == -1) - bracesPosition = rest.indexOf("+"); - - if (bracesPosition == -1) { - // try the * and + - quantifier = ""; - } else { - quantifier = rest.substring(bracesPosition); - rest = rest.substring(0, bracesPosition); - } - } - - // get name - { - name = rest; // only name is left - if (name.isEmpty()) { - throw new RuntimeException("Cannot parse refmap entry of class " + mixinClass + - ": the name is \"\", so something went wrong: owner = \"" + owner + "\", name = \"" + name + - "\", quantifier = \"" + quantifier + "\", desc = \"" + desc + "\", tail = \"" + tail + - "\", old = \"" + old + "\""); - } - } - } - - // for now just stop here, most stuff doesn't use quantifiers or tails - if (!quantifier.isEmpty()) - throw new RuntimeException("Quantifiers are not yet supported: " + old); - if (!tail.isEmpty()) - throw new RuntimeException("Tails are not yet supported: " + tail); - - // do the actual mapping - - // it's a class - if (owner.isEmpty() && desc.isEmpty()) { - return trRemapper.map(name); - } - - // it's a method - if (desc.startsWith("(") && desc.contains(")")) { - if (owner.isEmpty()) { // it's an @Invoker - if (supers == null || supers.isEmpty()) { - throw new RuntimeException("Can't find target class for mixin " + mixinClass); - } - - final String originalName = name; - String newDesc = trRemapper.mapMethodDesc(desc); - - for (String own : supers) { - name = trRemapper.mapMethodName(own, name, desc); - - if (!originalName.equals(name)) { - return name + newDesc; - } - } - - return originalName + newDesc; - } else { // just a normal method - return "L" + trRemapper.map(owner) + ";" + trRemapper.mapMethodName(owner, name, desc) + trRemapper.mapMethodDesc(desc); - } - } - - // it's an @Accessor - if (owner.isEmpty()) { - if (supers == null || supers.isEmpty()) { - throw new RuntimeException("Can't find target class for mixin " + mixinClass); - } - - final String originalName = name; - - for (String own : supers) { - name = trRemapper.mapFieldName(own, name, desc); - - if (!originalName.equals(name)) { - return name; - } - } - - return originalName; - } - - // just a normal field - return "L" + trRemapper.map(owner) + ";" + trRemapper.mapFieldName(owner, name, desc) + ":" + trRemapper.mapDesc(desc); - } } diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/visitor/MixinPostApplyVisitor.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/visitor/MixinPostApplyVisitorProvider.java similarity index 77% rename from src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/visitor/MixinPostApplyVisitor.java rename to src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/visitor/MixinPostApplyVisitorProvider.java index e4b0a7b..47461bc 100644 --- a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/visitor/MixinPostApplyVisitor.java +++ b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/visitor/MixinPostApplyVisitorProvider.java @@ -11,16 +11,19 @@ import org.objectweb.asm.tree.ClassNode; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; -public class MixinPostApplyVisitor implements TinyRemapper.ApplyVisitorProvider { - public MixinPostApplyVisitor() {} +public class MixinPostApplyVisitorProvider implements TinyRemapper.ApplyVisitorProvider { + public MixinPostApplyVisitorProvider() {} @Override public ClassVisitor insertApplyVisitor(TrClass cls, ClassVisitor next) { ClassNode node = new ClassNode(); cls.accept(node, ClassReader.SKIP_FRAMES); + String className = cls.getName().replace(".", "/"); + List supers = new ArrayList<>(); for (List nodeList : new List[]{ @@ -41,7 +44,8 @@ public ClassVisitor insertApplyVisitor(TrClass cls, ClassVisitor next) { if (val instanceof Type) { theVal = ((Type) val).getInternalName(); } else { - theVal = (String) val; + theVal = ModRemappingAPIImpl.getCurrentContext().getMixinData().getMixinRefmapData() + .getOrDefault(className, new HashMap<>()).getOrDefault((String) val, (String) val); } supers.add(theVal); @@ -54,7 +58,7 @@ public ClassVisitor insertApplyVisitor(TrClass cls, ClassVisitor next) { }); } - ModRemappingAPIImpl.getCurrentContext().getMixin2TargetMap().put(cls.getName().replace(".", "/"), supers); + ModRemappingAPIImpl.getCurrentContext().getMixinData().getMixin2TargetMap().put(className, supers); return next; } diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/utils/CacheUtils.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/utils/CacheUtils.java index 04b4350..082a9eb 100644 --- a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/utils/CacheUtils.java +++ b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/utils/CacheUtils.java @@ -1,14 +1,9 @@ package io.github.fabriccompatibiltylayers.modremappingapi.impl.utils; -import io.github.fabriccompatibiltylayers.modremappingapi.api.v1.RemapLibrary; import net.fabricmc.loader.api.FabricLoader; import org.jetbrains.annotations.ApiStatus; -import java.nio.file.Files; import java.nio.file.Path; -import java.util.Collection; -import java.util.Map; -import java.util.stream.Collectors; @ApiStatus.Internal public class CacheUtils { @@ -16,29 +11,12 @@ public class CacheUtils { public static final Path MAIN_FOLDER = BASE_FOLDER .resolve(VersionHelper.MINECRAFT_VERSION) .resolve(VersionHelper.MOD_VERSION); - public static final Path LIBRARY_FOLDER = MAIN_FOLDER.resolve("libs"); + public static final Path LIBRARY_FOLDER = getCachePath("libs"); public static Path getCachePath(String pathName) { return MAIN_FOLDER.resolve(pathName); } - public static Path getLibraryPath(String pathName) { - return LIBRARY_FOLDER.resolve(pathName); - } - - @ApiStatus.Internal - public static Map computeLibraryPaths(Collection sourcePaths, String target) { - return sourcePaths.stream().collect(Collectors.toMap(p -> p, - p -> CacheUtils.getLibraryPath(target).resolve(p.toFile().getName()))); - } - - @ApiStatus.Internal - public static Map computeExtraLibraryPaths(Collection sourcePaths, String target) { - return sourcePaths.stream() - .collect(Collectors.toMap(p -> p, - p -> CacheUtils.getLibraryPath(target).resolve(p.fileName))); - } - static { BASE_FOLDER.toFile().mkdirs(); MAIN_FOLDER.toFile().mkdirs(); diff --git a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/utils/FileUtils.java b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/utils/FileUtils.java index 7713a63..57aea2c 100644 --- a/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/utils/FileUtils.java +++ b/src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/utils/FileUtils.java @@ -164,8 +164,8 @@ public FileVisitResult visitFileFailed(Path file, IOException exc) { } @Override - public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { - Files.delete(dir); + public FileVisitResult postVisitDirectory(Path subDir, IOException exc) throws IOException { + if (dir != subDir) Files.delete(subDir); return FileVisitResult.CONTINUE; } }); @@ -235,7 +235,7 @@ private static void zipFile(File fileToZip, String fileName, ZipOutputStream zip @ApiStatus.Internal public static FileSystem getJarFileSystem(Path path) throws URISyntaxException, IOException { - return FileSystems.newFileSystem(new URI("jar:" + path.toUri()), ZIP_PROPERTIES); + return FileSystems.newFileSystem(URI.create("jar:" + path.toUri()), ZIP_PROPERTIES); } @ApiStatus.Internal diff --git a/src/main/java/net/fabricmc/tinyremapper/extension/mixin/hard/ImprovedHardTargetMixinClassVisitor.java b/src/main/java/net/fabricmc/tinyremapper/extension/mixin/hard/ImprovedHardTargetMixinClassVisitor.java new file mode 100644 index 0000000..c6bcad5 --- /dev/null +++ b/src/main/java/net/fabricmc/tinyremapper/extension/mixin/hard/ImprovedHardTargetMixinClassVisitor.java @@ -0,0 +1,82 @@ +package net.fabricmc.tinyremapper.extension.mixin.hard; + +import net.fabricmc.tinyremapper.extension.mixin.common.MapUtility; +import net.fabricmc.tinyremapper.extension.mixin.common.data.*; +import net.fabricmc.tinyremapper.extension.mixin.hard.annotation.ImplementsAnnotationVisitor; +import net.fabricmc.tinyremapper.extension.mixin.hard.data.SoftInterface; +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.MethodVisitor; + +import java.util.*; +import java.util.function.Consumer; + +public class ImprovedHardTargetMixinClassVisitor extends ClassVisitor { + private final Collection> tasks; + private MxClass _class; + + // @Mixin + private final List targets = new ArrayList<>(); + + // @Implements + private final List interfaces = new ArrayList<>(); + + public ImprovedHardTargetMixinClassVisitor(Collection> tasks, ClassVisitor delegate) { + super(Constant.ASM_VERSION, delegate); + this.tasks = Objects.requireNonNull(tasks); + } + + /** + * This is called before visitAnnotation. + */ + @Override + public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { + this._class = new MxClass(name); + super.visit(version, access, name, signature, superName, interfaces); + } + + /** + * This is called before visitMethod & visitField. + */ + @Override + public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) { + AnnotationVisitor av = super.visitAnnotation(descriptor, visible); + + if (Annotation.MIXIN.equals(descriptor)) { + av = new ImprovedMixinAnnotationVisitor(av, targets, this._class); + } else if (Annotation.IMPLEMENTS.equals(descriptor)) { + av = new ImplementsAnnotationVisitor(av, interfaces); + } + + return av; + } + + @Override + public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) { + FieldVisitor fv = super.visitField(access, name, descriptor, signature, value); + MxMember field = _class.getField(name, descriptor); + + if (targets.isEmpty()) { + return fv; + } else { + return new HardTargetMixinFieldVisitor(tasks, fv, field, Collections.unmodifiableList(targets)); + } + } + + @Override + public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { + MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions); + MxMember method = _class.getMethod(name, descriptor); + + if (!interfaces.isEmpty() && !MapUtility.IGNORED_NAME.contains(name)) { + ImplementsAnnotationVisitor.visitMethod(tasks, method, interfaces); + } + + if (targets.isEmpty()) { + return mv; + } else { + return new HardTargetMixinMethodVisitor(tasks, mv, method, Collections.unmodifiableList(targets)); + } + } +} diff --git a/src/main/java/net/fabricmc/tinyremapper/extension/mixin/hard/ImprovedMixinAnnotationVisitor.java b/src/main/java/net/fabricmc/tinyremapper/extension/mixin/hard/ImprovedMixinAnnotationVisitor.java new file mode 100644 index 0000000..2ea4306 --- /dev/null +++ b/src/main/java/net/fabricmc/tinyremapper/extension/mixin/hard/ImprovedMixinAnnotationVisitor.java @@ -0,0 +1,62 @@ +package net.fabricmc.tinyremapper.extension.mixin.hard; + +import io.github.fabriccompatibiltylayers.modremappingapi.impl.ModRemappingAPIImpl; +import net.fabricmc.tinyremapper.extension.mixin.common.data.AnnotationElement; +import net.fabricmc.tinyremapper.extension.mixin.common.data.Constant; +import net.fabricmc.tinyremapper.extension.mixin.common.data.MxClass; +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.Type; + +import java.util.HashMap; +import java.util.List; +import java.util.Objects; + +public class ImprovedMixinAnnotationVisitor extends AnnotationVisitor { + private final List targets; + private final MxClass _class; + + public ImprovedMixinAnnotationVisitor(AnnotationVisitor delegate, List targetsOut, MxClass _class) { + super(Constant.ASM_VERSION, delegate); + + this.targets = Objects.requireNonNull(targetsOut); + this._class = Objects.requireNonNull(_class); + } + + @Override + public AnnotationVisitor visitArray(String name) { + AnnotationVisitor visitor = super.visitArray(name); + + if (name.equals(AnnotationElement.TARGETS)) { + return new AnnotationVisitor(Constant.ASM_VERSION, visitor) { + @Override + public void visit(String name, Object value) { + String srcName = ((String) value).replaceAll("\\s", "").replace('.', '/'); + String dstName = srcName; + + srcName = ModRemappingAPIImpl.getCurrentContext().getMixinData() + .getMixinRefmapData() + .getOrDefault(ImprovedMixinAnnotationVisitor.this._class.getName(), new HashMap<>()) + .getOrDefault(value, srcName); + + ImprovedMixinAnnotationVisitor.this.targets.add(srcName); + + value = dstName; + super.visit(name, value); + } + }; + } else if (name.equals(AnnotationElement.VALUE)) { + return new AnnotationVisitor(Constant.ASM_VERSION, visitor) { + @Override + public void visit(String name, Object value) { + Type srcType = Objects.requireNonNull((Type) value); + + ImprovedMixinAnnotationVisitor.this.targets.add(srcType.getInternalName()); + + super.visit(name, value); + } + }; + } else { + return visitor; + } + } +} \ No newline at end of file diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index f44c180..cbc799b 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -23,7 +23,7 @@ "environment": "*", "entrypoints": { "mod-remapper-api:modremapper_v1": [ - "io.github.fabriccompatibiltylayers.modremappingapi.impl.DefaultModRemapper" + "io.github.fabriccompatibiltylayers.modremappingapi.impl.compatibility.V1DefaultModRemapper" ], "spasm:raw_transformer": [ "io.github.fabriccompatibiltylayers.modremappingapi.impl.TransformerRegistry"