Skip to content

Commit

Permalink
draft of dynamic proposal (no definitions file)
Browse files Browse the repository at this point in the history
  • Loading branch information
ix0rai committed Dec 12, 2024
1 parent 1dac507 commit 6984843
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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<EntryMapping> 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<EntryMapping> mojmaps;

@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
public MojmapNameProposer(Optional<String> path) {
Expand Down Expand Up @@ -55,14 +59,4 @@ private void proposeNodeAndChildren(Map<Entry<?>, EntryMapping> mappings, EntryT

node.getChildNodes().forEach((child) -> proposeNodeAndChildren(mappings, child));
}

@Override
public void proposeDynamicNames(EntryRemapper remapper, Entry<?> obfEntry, EntryMapping oldMapping, EntryMapping newMapping, Map<Entry<?>, EntryMapping> mappings) {
// todo dynamically fix class names to match their moj package
// todo definitions file

if (obfEntry instanceof ClassEntry classEntry && !classEntry.isInnerClass() && mojmaps != null) {

}
}
}
Original file line number Diff line number Diff line change
@@ -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<Entry<?>, EntryMapping> mappings) {
// no-op
}

@Override
public void proposeDynamicNames(EntryRemapper remapper, Entry<?> obfEntry, EntryMapping oldMapping, EntryMapping newMapping, Map<Entry<?>, 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<Entry<?>, 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;
}
}
}
Original file line number Diff line number Diff line change
@@ -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<NameProposalService> 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;
}
}
19 changes: 18 additions & 1 deletion src/test/java/org/quiltmc/enigma_plugin/MojmapTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -98,6 +101,9 @@ void setupEnigma() throws IOException {
"args": {
"mojmap_path": "./build/mojmap_cache/server-mappings.txt"
}
},
{
"id": "quiltmc:name_proposal/unchecked"
}
]
}
Expand All @@ -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

Expand All @@ -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());
Expand Down

0 comments on commit 6984843

Please sign in to comment.