From 6984843e41f59f108857d3c3fb278f80cf835947 Mon Sep 17 00:00:00 2001 From: ix0rai Date: Wed, 11 Dec 2024 22:35:54 -0600 Subject: [PATCH] draft of dynamic proposal (no definitions file) --- .../enigma_plugin/QuiltEnigmaPlugin.java | 5 +- .../proposal/MojmapNameProposer.java | 16 ++--- .../proposal/MojmapPackageProposer.java | 64 +++++++++++++++++++ .../proposal/UncheckedProposalService.java | 24 +++++++ .../org/quiltmc/enigma_plugin/MojmapTest.java | 19 +++++- 5 files changed, 115 insertions(+), 13 deletions(-) create mode 100644 src/main/java/org/quiltmc/enigma_plugin/proposal/MojmapPackageProposer.java create mode 100644 src/main/java/org/quiltmc/enigma_plugin/proposal/UncheckedProposalService.java diff --git a/src/main/java/org/quiltmc/enigma_plugin/QuiltEnigmaPlugin.java b/src/main/java/org/quiltmc/enigma_plugin/QuiltEnigmaPlugin.java index 4cd1b48..5fcb3e6 100644 --- a/src/main/java/org/quiltmc/enigma_plugin/QuiltEnigmaPlugin.java +++ b/src/main/java/org/quiltmc/enigma_plugin/QuiltEnigmaPlugin.java @@ -25,12 +25,14 @@ import org.quiltmc.enigma_plugin.obfuscation.NameObfuscationTestService; import org.quiltmc.enigma_plugin.proposal.DefaultProposalService; import org.quiltmc.enigma_plugin.proposal.FallbackProposalService; +import org.quiltmc.enigma_plugin.proposal.UncheckedProposalService; public class QuiltEnigmaPlugin implements EnigmaPlugin { public static final String SERVICE_ID_PREFIX = "quiltmc:"; public static final String INDEX_SERVICE_ID = SERVICE_ID_PREFIX + "jar_index"; public static final String NAME_PROPOSAL_SERVICE_ID = SERVICE_ID_PREFIX + "name_proposal"; - public static final String FALLBACK_NAME_PROPOSAL_SERVICE_ID = SERVICE_ID_PREFIX + "name_proposal/fallback"; + public static final String FALLBACK_NAME_PROPOSAL_SERVICE_ID = NAME_PROPOSAL_SERVICE_ID + "/fallback"; + public static final String UNCHECKED_NAME_PROPOSAL_SERVICE_ID = NAME_PROPOSAL_SERVICE_ID + "/unchecked"; public static final String OBFUSCATION_SERVICE_ID = SERVICE_ID_PREFIX + "obfuscation_test"; @Override @@ -39,6 +41,7 @@ public void init(EnigmaPluginContext ctx) { ctx.registerService(JarIndexerService.TYPE, indexer::withContext); ctx.registerService(NameProposalService.TYPE, ctx1 -> new DefaultProposalService(indexer, ctx1)); ctx.registerService(NameProposalService.TYPE, ctx1 -> new FallbackProposalService(indexer, ctx1)); + ctx.registerService(NameProposalService.TYPE, ctx1 -> new UncheckedProposalService(indexer, ctx1)); ctx.registerService(ObfuscationTestService.TYPE, NameObfuscationTestService::new); } } diff --git a/src/main/java/org/quiltmc/enigma_plugin/proposal/MojmapNameProposer.java b/src/main/java/org/quiltmc/enigma_plugin/proposal/MojmapNameProposer.java index dff5aa6..668940e 100644 --- a/src/main/java/org/quiltmc/enigma_plugin/proposal/MojmapNameProposer.java +++ b/src/main/java/org/quiltmc/enigma_plugin/proposal/MojmapNameProposer.java @@ -1,6 +1,7 @@ package org.quiltmc.enigma_plugin.proposal; import org.quiltmc.enigma.api.Enigma; +import org.quiltmc.enigma.api.analysis.index.jar.EntryIndex; import org.quiltmc.enigma.api.analysis.index.jar.JarIndex; import org.quiltmc.enigma.api.translation.mapping.EntryMapping; import org.quiltmc.enigma.api.translation.mapping.EntryRemapper; @@ -12,13 +13,16 @@ import java.nio.file.Path; import java.util.Map; +import java.util.Objects; import java.util.Optional; public class MojmapNameProposer extends NameProposer { public static final String ID = "mojmap"; private final String mojmapPath; - private EntryTree mojmaps; + // must be static for now. nasty hack to make sure we don't read mojmaps twice + // we can guarantee that this is nonnull for the other proposer because jar proposal blocks dynamic proposal + public static EntryTree mojmaps; @SuppressWarnings("OptionalUsedAsFieldOrParameterType") public MojmapNameProposer(Optional path) { @@ -55,14 +59,4 @@ private void proposeNodeAndChildren(Map, EntryMapping> mappings, EntryT node.getChildNodes().forEach((child) -> proposeNodeAndChildren(mappings, child)); } - - @Override - public void proposeDynamicNames(EntryRemapper remapper, Entry obfEntry, EntryMapping oldMapping, EntryMapping newMapping, Map, EntryMapping> mappings) { - // todo dynamically fix class names to match their moj package - // todo definitions file - - if (obfEntry instanceof ClassEntry classEntry && !classEntry.isInnerClass() && mojmaps != null) { - - } - } } diff --git a/src/main/java/org/quiltmc/enigma_plugin/proposal/MojmapPackageProposer.java b/src/main/java/org/quiltmc/enigma_plugin/proposal/MojmapPackageProposer.java new file mode 100644 index 0000000..7554070 --- /dev/null +++ b/src/main/java/org/quiltmc/enigma_plugin/proposal/MojmapPackageProposer.java @@ -0,0 +1,64 @@ +package org.quiltmc.enigma_plugin.proposal; + +import org.quiltmc.enigma.api.Enigma; +import org.quiltmc.enigma.api.analysis.index.jar.EntryIndex; +import org.quiltmc.enigma.api.analysis.index.jar.JarIndex; +import org.quiltmc.enigma.api.translation.mapping.EntryMapping; +import org.quiltmc.enigma.api.translation.mapping.EntryRemapper; +import org.quiltmc.enigma.api.translation.representation.entry.ClassEntry; +import org.quiltmc.enigma.api.translation.representation.entry.Entry; +import org.tinylog.Logger; + +import java.util.Map; + +public class MojmapPackageProposer extends NameProposer { + public static final String ID = "mojmap_packages"; + + public MojmapPackageProposer() { + super(ID); + } + + @Override + public void insertProposedNames(Enigma enigma, JarIndex index, Map, EntryMapping> mappings) { + // no-op + } + + @Override + public void proposeDynamicNames(EntryRemapper remapper, Entry obfEntry, EntryMapping oldMapping, EntryMapping newMapping, Map, EntryMapping> mappings) { + // todo definitions file + + if (obfEntry == null) { + // initial proposal for all classes + for (ClassEntry classEntry : remapper.getJarIndex().getIndex(EntryIndex.class).getClasses()) { + this.tryProposeForEntry(remapper, mappings, classEntry); + } + } else { + this.tryProposeForEntry(remapper, mappings, obfEntry); + } + } + + private void tryProposeForEntry(EntryRemapper remapper, Map, EntryMapping> mappings, Entry entry) { + var mojmaps = MojmapNameProposer.mojmaps; + + if (entry instanceof ClassEntry classEntry && !classEntry.isInnerClass() && mojmaps != null) { + String newName = getMojmappedName(remapper, classEntry); + mappings.put(classEntry, new EntryMapping(newName)); + } + } + + private String getMojmappedName(EntryRemapper remapper, ClassEntry classEntry) { + var mojmaps = MojmapNameProposer.mojmaps; + + var mapping = mojmaps.get(classEntry); + if (mapping != null && mapping.targetName() != null) { + String mojmapName = mapping.targetName(); + String oldPackage = mojmapName.substring(0, mojmapName.lastIndexOf('/')); + String className = remapper.deobfuscate(classEntry).getSimpleName(); + + return oldPackage + "/" + className; + } else { + Logger.error("failed to propose name: could not find mojmap for " + classEntry.getFullName()); + return null; + } + } +} diff --git a/src/main/java/org/quiltmc/enigma_plugin/proposal/UncheckedProposalService.java b/src/main/java/org/quiltmc/enigma_plugin/proposal/UncheckedProposalService.java new file mode 100644 index 0000000..864d624 --- /dev/null +++ b/src/main/java/org/quiltmc/enigma_plugin/proposal/UncheckedProposalService.java @@ -0,0 +1,24 @@ +package org.quiltmc.enigma_plugin.proposal; + +import org.quiltmc.enigma.api.service.EnigmaServiceContext; +import org.quiltmc.enigma.api.service.NameProposalService; +import org.quiltmc.enigma_plugin.Arguments; +import org.quiltmc.enigma_plugin.QuiltEnigmaPlugin; +import org.quiltmc.enigma_plugin.index.JarIndexer; + +public class UncheckedProposalService extends NameProposerService { + public UncheckedProposalService(JarIndexer indexer, EnigmaServiceContext context) { + super(); + this.addIfEnabled(context, Arguments.DISABLE_MOJMAP, MojmapPackageProposer::new); + } + + @Override + public String getId() { + return QuiltEnigmaPlugin.UNCHECKED_NAME_PROPOSAL_SERVICE_ID; + } + + @Override + public boolean bypassValidation() { + return true; + } +} diff --git a/src/test/java/org/quiltmc/enigma_plugin/MojmapTest.java b/src/test/java/org/quiltmc/enigma_plugin/MojmapTest.java index 47808c6..cada78b 100644 --- a/src/test/java/org/quiltmc/enigma_plugin/MojmapTest.java +++ b/src/test/java/org/quiltmc/enigma_plugin/MojmapTest.java @@ -10,12 +10,15 @@ import org.quiltmc.enigma.api.ProgressListener; import org.quiltmc.enigma.api.class_provider.ClasspathClassProvider; import org.quiltmc.enigma.api.source.TokenType; +import org.quiltmc.enigma.api.translation.mapping.EntryMapping; import org.quiltmc.enigma.api.translation.representation.MethodDescriptor; import org.quiltmc.enigma.api.translation.representation.TypeDescriptor; import org.quiltmc.enigma.api.translation.representation.entry.ClassEntry; import org.quiltmc.enigma.api.translation.representation.entry.Entry; import org.quiltmc.enigma.api.translation.representation.entry.FieldEntry; import org.quiltmc.enigma.api.translation.representation.entry.MethodEntry; +import org.quiltmc.enigma.util.validation.PrintNotifier; +import org.quiltmc.enigma.util.validation.ValidationContext; import org.quiltmc.launchermeta.version.v1.DownloadableFile; import org.quiltmc.launchermeta.version.v1.Version; import org.quiltmc.launchermeta.version_manifest.VersionEntry; @@ -98,6 +101,9 @@ void setupEnigma() throws IOException { "args": { "mojmap_path": "./build/mojmap_cache/server-mappings.txt" } + }, + { + "id": "quiltmc:name_proposal/unchecked" } ] } @@ -110,7 +116,7 @@ void setupEnigma() throws IOException { } @Test - void test() { + void testStaticProposal() { // assert that all types propose properly // note that mojmaps do not contain params @@ -126,6 +132,17 @@ void test() { assertMapping(getExplosionResistance, "getExplosionResistance", TokenType.JAR_PROPOSED); } + @Test + void testDynamicProposal() { + ClassEntry a = new ClassEntry("a"); + assertMapping(a, "com/mojang/math/Axis", TokenType.JAR_PROPOSED); + + ValidationContext vc = new ValidationContext(PrintNotifier.INSTANCE); + project.getRemapper().putMapping(vc, a, new EntryMapping("gaming/Gaming")); + + assertMapping(a, "com/mojang/math/Gaming", TokenType.DEOBFUSCATED); + } + private void assertMapping(Entry entry, String name, TokenType type) { var mapping = project.getRemapper().getMapping(entry); assertEquals(entry, name, mapping.targetName());