Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions enigma-cli/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ plugins {
dependencies {
shadow(implementation project(':enigma'))
testImplementation(testFixtures(project(':enigma')))
//implementation("org.quiltmc:quilt-enigma-plugin:2.3.1+local")
}

application {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package org.quiltmc.enigma.command;

import org.quiltmc.enigma.api.Enigma;
import org.quiltmc.enigma.api.EnigmaProfile;
import org.quiltmc.enigma.api.EnigmaProject;
import org.quiltmc.enigma.api.ProgressListener;
import org.quiltmc.enigma.api.translation.mapping.serde.MappingSaveParameters;
import org.quiltmc.enigma.api.translation.mapping.serde.MappingsWriter;
import org.tinylog.Logger;

import java.io.IOException;
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;

public class DropProposedMappingsCommand extends Command {
public DropProposedMappingsCommand() {
super(Argument.INPUT_JAR.required(),
Argument.INPUT_MAPPINGS.required(),
Argument.ENIGMA_PROFILE.required(),
Argument.MAPPING_OUTPUT.optional());
}

@Override
public void run(String... args) throws Exception {
Path jarIn = getReadablePath(this.getArg(args, 0));
Path mappingsIn = getReadablePath(this.getArg(args, 1));
Path profile = getReadablePath(this.getArg(args, 2));
String mappingsOutArg = this.getArg(args, 3);
Path mappingsOut = mappingsOutArg != null && !mappingsOutArg.isEmpty() ? getReadablePath(mappingsOutArg) : mappingsIn;

run(jarIn, mappingsIn, profile, mappingsOut);
}

@Override
public String getName() {
return "drop-proposed-mappings";
}

@Override
public String getDescription() {
return "Removes all proposed mapping entries that are the same as manually written entries from the provided mappings.";
}

public static void run(Path jarIn, Path mappingsIn, Path profilePath, Path mappingsOut) throws Exception {
if (mappingsIn == null) {
Logger.warn("No mappings input specified, skipping.");
return;
}

Enigma enigma = createEnigma(EnigmaProfile.read(profilePath), null);

MappingsWriter writer = CommandsUtil.getWriter(enigma, mappingsIn);
EnigmaProject project = openProject(jarIn, mappingsIn, enigma);

Logger.info("Dropping proposed mappings...");

var droppedMappings = project.dropProposedMappings(ProgressListener.createEmpty());

if (!droppedMappings.isEmpty()) {
Logger.info("Found and dropped {} duplicate mappings.", droppedMappings.size());
Logger.info("Writing mappings...");

if (mappingsOut == mappingsIn) {
Logger.info("Overwriting input mappings");
Files.walkFileTree(mappingsIn, new SimpleFileVisitor<>() {
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
Files.delete(dir);
return FileVisitResult.CONTINUE;
}

@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Files.delete(file);
return FileVisitResult.CONTINUE;
}
});

Files.deleteIfExists(mappingsIn);
}

MappingSaveParameters saveParameters = project.getEnigma().getProfile().getMappingSaveParameters();
writer.write(project.getRemapper().getMappings(), mappingsOut, ProgressListener.createEmpty(), saveParameters);
} else {
Logger.info("No duplicate proposed mappings found.");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ private static void logEnigmaInfo() {
register(new MapSpecializedMethodsCommand());
register(new InsertProposedMappingsCommand());
register(new DropInvalidMappingsCommand());
register(new DropProposedMappingsCommand());
register(new FillClassMappingsCommand());
register(new HelpCommand());
register(new PrintStatsCommand());
Expand Down
64 changes: 64 additions & 0 deletions enigma/src/main/java/org/quiltmc/enigma/api/EnigmaProject.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.quiltmc.enigma.api.analysis.index.mapping.MappingsIndex;
import org.quiltmc.enigma.api.service.ObfuscationTestService;
import org.quiltmc.enigma.api.source.TokenType;
import org.quiltmc.enigma.api.translation.mapping.tree.EntryTreeNode;
import org.quiltmc.enigma.api.translation.mapping.tree.EntryTreeUtil;
import org.quiltmc.enigma.api.translation.mapping.tree.HashEntryTree;
import org.quiltmc.enigma.impl.bytecode.translator.TranslationClassVisitor;
Expand Down Expand Up @@ -40,6 +41,7 @@
import java.io.StringWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -167,6 +169,68 @@ private Collection<Entry<?>> dropMappings(EntryTree<EntryMapping> mappings, Prog
return dropper.getDroppedMappings().keySet();
}

public Collection<Entry<?>> dropProposedMappings(ProgressListener progress) {
DeltaTrackingTree<EntryMapping> mappings = this.remapper.getMappings();
EntryTree<EntryMapping> proposedMappings = this.remapper.getProposedMappings();
progress.init((int) proposedMappings.getAllEntries().count(), "Proposed Mappings to check");

List<Entry<?>> dropped = new ArrayList<>();

int steps = 0;
for (EntryTreeNode<EntryMapping> proposedMapping : proposedMappings) {
progress.step(steps++, proposedMapping.getEntry().getFullName());

if (proposedMapping.getValue() == null) {
continue;
}

if (!mappings.contains(proposedMapping.getEntry())) {
continue;
}

EntryMapping entryMapping = mappings.get(proposedMapping.getEntry());

if (entryMapping.tokenType().isProposed()) {
continue;
}

if (entryMapping.targetName() == null) {
continue;
}

// if (entryMapping.javadoc() != null) {
// continue;
// }

// ParentedEntry<?> parent = ((ParentedEntry<?>) proposedMapping.getEntry());
// while (parent != null && parent.getParent() != null) {
// parent = (ParentedEntry<?>) parent.getParent();
// }
//
// if (!parent.getFullName().equals("net/minecraft/unmapped/C_ygpuayyc")) {
// continue;
// }

if (proposedMapping.getValue().sourcePluginId().equals("quiltmc:name_proposal/delegate_params")) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should preserve fallback-proposed names as well
also why do delegate params need an exception?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this was a work around until we figure out why we are getting the massive spooky diffs,

Copy link
Member

@supersaiyansubtlety supersaiyansubtlety Sep 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, ok
it could be a useful to have an arg for proposer plugin ids to exclude

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

potentially, but i also feel like that defeats a bit of the purpose of this feature, which is to make sure that no more proposed names are left in the mappings. If the proposer is fragile enough to break with this, its probably not written very well.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

true
I wouldn't expect it to be used often
maybe it would be better not to have an arg; if a proposer is having issues it can just be set to fallback as a workaround

continue;
}

dropped.add(proposedMapping.getEntry());



if (entryMapping.targetName().equals(proposedMapping.getValue().targetName())) {
if (entryMapping.javadoc() != null) {
mappings.insert(proposedMapping.getEntry(), entryMapping.withName(null, TokenType.OBFUSCATED));
continue;
}
mappings.remove(proposedMapping.getEntry());
}
}

return dropped;
}

public boolean isNavigable(Entry<?> obfEntry) {
if (obfEntry instanceof ClassEntry classEntry && this.isAnonymousOrLocal(classEntry)) {
return false;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.quiltmc.enigma.api.translation.mapping.tree;

import org.quiltmc.enigma.api.source.TokenType;
import org.quiltmc.enigma.api.translation.Translator;
import org.quiltmc.enigma.api.translation.mapping.EntryMap;
import org.quiltmc.enigma.api.translation.mapping.EntryMapping;
Expand Down Expand Up @@ -42,10 +43,15 @@ public EntryMapping remove(Entry<?> entry) {
@Override
public EntryMapping get(Entry<?> entry) {
EntryMapping main = this.mainTree.get(entry);

if (main == null || (main.equals(EntryMapping.OBFUSCATED) && this.secondaryTree.contains(entry))) {
return this.secondaryTree.get(entry);
}

if (main.tokenType().equals(TokenType.OBFUSCATED) && this.secondaryTree.contains(entry)) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ix0rai what is your opinion on this? it allows for javadocs to be on empty mappings, but get a name from a proposer

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just making sure you know i'm not ignoring you, i'm pretty busy rn and i want to look into javadoc support on obf mappings a bit deeper

return EntryMapping.merge(main, this.secondaryTree.get(entry));
}

return main;
}

Expand Down
Loading