diff --git a/.github/workflows/commit.yml b/.github/workflows/commit.yml index 7e75edf..f8f9eb3 100644 --- a/.github/workflows/commit.yml +++ b/.github/workflows/commit.yml @@ -4,7 +4,7 @@ on: push jobs: build: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - name: Checkout repository uses: actions/checkout@v4 diff --git a/README.md b/README.md index f487602..7381597 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ pluginManagement { Then, add the following to your `build.gradle.kts` file: ```kotlin plugins { - id("dev.galacticraft.mojarn") version("0.4.1+11") + id("dev.galacticraft.mojarn") version("0.5.0+13") } ``` diff --git a/build.gradle.kts b/build.gradle.kts index 7e00e64..1e6243a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -87,8 +87,8 @@ license { } gradlePlugin { - website.set("https://github.com/TeamGalacticraft/Mojarn") - vcsUrl.set("https://github.com/TeamGalacticraft/Mojarn") + website.set("https://github.com/TeamGalacticraft/mojarn") + vcsUrl.set("https://github.com/TeamGalacticraft/mojarn") plugins { create(pluginId) { diff --git a/gradle.properties b/gradle.properties index c5bb2af..e9eda06 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ plugin.group=dev.galacticraft plugin.name=Mojarn plugin.id=mojarn plugin.description=Mixes official and yarn mappings for better argument names -plugin.version=0.4.1 +plugin.version=0.5.0 -loom.version=1.7.3 +loom.version=1.7.4 mapping-io.version=0.6.1 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2b18997..fb602ee 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=5b9c5eb3f9fc2c94abaea57d90bd78747ca117ddbbf96c859d3741181a12bf2a -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip +distributionSha256Sum=31c55713e40233a8303827ceb42ca48a47267a0ad4bab9177123121e71524c26 +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/src/main/java/dev/galacticraft/mojarn/impl/MojarnMappingsLayer.java b/src/main/java/dev/galacticraft/mojarn/impl/MojarnMappingsLayer.java index c197e48..9c49a7c 100644 --- a/src/main/java/dev/galacticraft/mojarn/impl/MojarnMappingsLayer.java +++ b/src/main/java/dev/galacticraft/mojarn/impl/MojarnMappingsLayer.java @@ -28,11 +28,12 @@ import net.fabricmc.mappingio.MappedElementKind; import net.fabricmc.mappingio.MappingVisitor; import net.fabricmc.mappingio.tree.MappingTree; +import net.fabricmc.mappingio.tree.MappingTreeView; import net.fabricmc.mappingio.tree.MemoryMappingTree; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.io.IOException; +import java.io.*; import java.util.*; import java.util.regex.Pattern; @@ -48,6 +49,7 @@ public class MojarnMappingsLayer implements MappingLayer { private final boolean skipDifferent; private final boolean mapVariables; private final boolean skipCI; + private int skipped = 0; public MojarnMappingsLayer(@NotNull MappingLayer intermediary, @NotNull MappingLayer mojang, @NotNull MappingLayer yarn, boolean remapArguments, boolean partialMatch, boolean skipDifferent, boolean mapVariables, boolean skipCI) { this.intermediary = intermediary; @@ -62,6 +64,8 @@ public MojarnMappingsLayer(@NotNull MappingLayer intermediary, @NotNull MappingL @Override public void visit(MappingVisitor mappingVisitor) throws IOException { + this.skipped = 0; + long start = System.currentTimeMillis(); this.mojang.visit(mappingVisitor); @@ -88,15 +92,15 @@ public void visit(MappingVisitor mappingVisitor) throws IOException { int named = yarnTree.getNamespaceId(MappingsNamespace.NAMED.toString()); // map yarn class names to official class names - Map yarn2official = new HashMap<>(yarnTree.getClasses().size()); + HashMap yarn2official = new HashMap<>(yarnTree.getClasses().size()); for (MappingTree.ClassMapping clazz : officialTree.getClasses()) { MappingTree.ClassMapping yarn = yarnTree.getClass(clazz.getDstName(intermediary)); if (yarn != null) { String yarnName = getClassName(yarn.getDstName(named)); String officialName = getClassName(clazz.getDstName(official)); // ignore classes that have the same name in both mappings - if (yarnName != null && !yarnName.equals(officialName)) { - yarn2official.put(yarnName, officialName); + if (yarnName != null && officialName != null && !yarnName.equals(officialName)) { + yarn2official.put(yarnName, lowerCamelCase(officialName)); } } } @@ -106,6 +110,7 @@ public void visit(MappingVisitor mappingVisitor) throws IOException { // cached arraylist for method descriptor parsing List descriptor = new ArrayList<>(16); + HashMap names = new HashMap<>(16); // visit all official classes for (MappingTree.ClassMapping clazz : officialTree.getClasses()) { @@ -125,10 +130,9 @@ public void visit(MappingVisitor mappingVisitor) throws IOException { if (dstDesc != null) { mappingVisitor.visitMethod(method.getSrcName(), method.getSrcDesc()); + names.clear(); // reset used names parseMethodDescriptor(dstDesc.toCharArray(), descriptor); - HashMap names = new HashMap<>(); - // visit all method arguments mapArguments(mappingVisitor, yarnMethod, named, descriptor, yarnTree, yarn2official, names); @@ -186,12 +190,25 @@ private static void parseMethodDescriptor(char[] desc, List descriptor) * @throws IOException if the mapping visitor fails to accept the name(s) */ private void mapArguments(MappingVisitor output, MappingTree.MethodMapping method, int named, List<@Nullable String> descriptor, MemoryMappingTree yarnTree, Map yarn2official, HashMap names) throws IOException { - int i = 0; - for (MappingTree.MethodArgMapping arg : method.getArgs()) { + int offset = 0; + MappingTree.MethodArgMapping[] args = method.getArgs().toArray(new MappingTree.MethodArgMapping[0]); + Arrays.sort(args, Comparator.comparingInt(MappingTreeView.MethodArgMappingView::getLvIndex)); + if (args.length == descriptor.size()) { + offset = -1; + } else if (args.length != 0 && args[args.length - 1].getLvIndex() >= descriptor.size()) { + offset = args[args.length - 1].getLvIndex() - descriptor.size() + 1; + } + + for (MappingTree.MethodArgMapping arg : args) { String argName = arg.getDstName(named); if (argName != null) { + if (offset >= 0 && (arg.getLvIndex() - offset < 0 || arg.getLvIndex() - offset >= descriptor.size())) { + MojarnPlugin.LOGGER.debug("Skipping method {} (LVT offset mismatch)}", method.getName(named)); + skipped++; + break; + } // check if the argument is a class - String desc = descriptor.get(i++); + String desc = descriptor.get(offset < 0 ? -(offset-- + 1) : arg.getLvIndex() - offset); if (this.remapArguments && desc != null) { // get the class mapping of the argument type MappingTree.ClassMapping typeClass = yarnTree.getClass(desc, named); @@ -200,8 +217,9 @@ private void mapArguments(MappingVisitor output, MappingTree.MethodMapping metho // skip if class remapping is disabled String typeName = getClassName(desc); - if (yarn2official.containsKey(typeName)) { - argName = remapToOfficial(yarn2official, typeName, argName); + String remapped = yarn2official.get(typeName); + if (remapped != null) { + argName = tryRemap(typeName, argName, remapped); } } } @@ -220,12 +238,13 @@ private void mapArguments(MappingVisitor output, MappingTree.MethodMapping metho /** * Remaps the argument name based on its type - * @param yarn2official map of yarn to official class mapping names + * * @param typeName the (yarn) type name of the argument * @param argName the argument name to remap + * @param remapped the remapped (target) argument name * @return the remapped name, or {@code null} if the name should be dropped. */ - private @Nullable String remapToOfficial(Map yarn2official, @NotNull String typeName, String argName) { + private @Nullable String tryRemap(@NotNull String typeName, String argName, String remapped) { // check if class ends in numeric suffix if (!Character.isDigit(typeName.charAt(typeName.length() - 1))) { // strip numeric suffix on argument (if it exists) @@ -236,15 +255,17 @@ private void mapArguments(MappingVisitor output, MappingTree.MethodMapping metho // check if the argument name is the same as the type name if (argName.equalsIgnoreCase(typeName)) { - String offDst = yarn2official.get(typeName); - return lowerCamelCase(offDst); + return remapped; } else if (this.partialMatch) { // check if the argument name contains part of the type name // split the name ("CamelCase" -> ["Camel", "Case"]) - for (String s : PATTERN.split(typeName)) { - if (s.equalsIgnoreCase(argName)) { - String offDst = yarn2official.get(typeName); - return lowerCamelCase(offDst); + String[] split = PATTERN.split(typeName); + String[] split1 = PATTERN.split(remapped); + if (split.length == split1.length) { + for (int i = 0; i < split.length; i++) { + if (split[i].equalsIgnoreCase(argName)) { + return lowerCamelCase(split1[i]); + } } } } diff --git a/src/main/java/dev/galacticraft/mojarn/impl/MojarnMappingsSpecBuilderImpl.java b/src/main/java/dev/galacticraft/mojarn/impl/MojarnMappingsSpecBuilderImpl.java index d95126a..ce717ab 100644 --- a/src/main/java/dev/galacticraft/mojarn/impl/MojarnMappingsSpecBuilderImpl.java +++ b/src/main/java/dev/galacticraft/mojarn/impl/MojarnMappingsSpecBuilderImpl.java @@ -30,7 +30,7 @@ public class MojarnMappingsSpecBuilderImpl implements MojarnMappingsSpecBuilder { boolean nameSyntheticMethods = false; boolean remapArguments = true; - boolean partialMatch = false; + boolean partialMatch = true; boolean skipDifferent = false; boolean mapVariables = true; boolean skipCI = true;