Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Entry Changes #364

Merged
merged 14 commits into from
Jul 8, 2021
Merged

Entry Changes #364

merged 14 commits into from
Jul 8, 2021

Conversation

2xsaiko
Copy link
Collaborator

@2xsaiko 2xsaiko commented Mar 25, 2021

Makes the concept of changes on a single mapping a single unit (an EntryChange<E>), instead of handling javadoc, deobf, etc. changes separately on both the internal and network layer. Also, EntryMapping no longer has to have a deobfuscated name attached, allowing an unobfuscated entry to have Javadocs.


This changes the file format of Enigma: "-" is now a valid deobfuscated name in the file format for all entries that is read as the entry being read having no name. This allows access modifiers to be saved without a deobfuscated name on the entry.
Example:

(currently valid in mainline Enigma)

CLASS net/minecraft/class_377 net/minecraft/client/font/FontStorage ACC:PROTECTED

(added by this PR)

CLASS net/minecraft/class_377 - ACC:PROTECTED

The following would also be read correctly but isn't saved due to being redundant (an entry defined by just its obfuscated name is still valid as before):

CLASS net/minecraft/class_377 -

Files saved that have this changed syntax in them (this should only happen if someone changes the access modifiers) can obviously not be read by older Enigma versions, but older mapping files can be read as is.


Changes:

  • Changes on an Entry mapping are described as a single patch unit (EntryChange<E>)
  • Entry mappings can exist without a mapped name, allowing an entry to be unmapped but have Javadoc attached
  • As a result, entry mappings can be empty
  • Empty entry mappings (EntryMapping.DEFAULT) replace null entry mappings (and everything dealing with entry mappings should no longer accept null values)
  • Network protocol changes to accommodate the above changes
  • File format changes to accommodate the above changes

@2xsaiko 2xsaiko force-pushed the the-mega-restructure branch from cd7968c to 188a944 Compare July 5, 2021 16:56
@2xsaiko 2xsaiko marked this pull request as ready for review July 5, 2021 17:04
@2xsaiko 2xsaiko requested review from Gegy, modmuss50 and liach July 5, 2021 17:05
@2xsaiko 2xsaiko changed the title The Mega Restructure™ Entry Changes Jul 5, 2021
throw new IOException("Field requires class parent");
}
TypeDescriptor desc = new TypeDescriptor(readString(input));
return new FieldEntry((ClassEntry) parent, name, desc, javadocs);
Copy link
Contributor

Choose a reason for hiding this comment

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

can use pattern matching instanceof now

@@ -0,0 +1,96 @@
package cuchaz.enigma.newabstraction;
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, mind choose a better package name, like cuchaz.enigma.change?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That package was temporary initially, I wanted to move everything out of it. Let me move these to cuchaz.enigma.translation.mapping

import cuchaz.enigma.translation.mapping.AccessModifier;
import cuchaz.enigma.translation.representation.entry.Entry;

public class EntryChange<E extends Entry<?>> {
Copy link
Contributor

Choose a reason for hiding this comment

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

This definitely should be a record.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Hmm, can you have a private constructor on a record? Cause I'd really hate to have the constructor public on this

Copy link
Contributor

Choose a reason for hiding this comment

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

rip no. In the canonical constructor you cannot even throw checked exceptions, but you can still have public static factory methods to help

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

now I'd have to decide between cleaner API or cleaner implementation
aaAAAAAAAA java why
tbh since I think it's unlikely that fields will be added to this class I'm inclined to leave it as is and not turn it into a record

EntryChange<?> that = (EntryChange<?>) o;
return Objects.equals(this.target, that.target) &&
Objects.equals(this.deobfName, that.deobfName) &&
Objects.equals(this.javadoc, that.javadoc);
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is access ignored, just curious?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I probably forgot to regenerate equals/hashcode when I added it.

Copy link
Contributor

Choose a reason for hiding this comment

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

Record time 😆 I don't forget about handling extra fields again

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

public class EntryMapping {
private final String targetName;
public final class EntryMapping {
Copy link
Contributor

Choose a reason for hiding this comment

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

probably can be a record as well


public RawEntryMapping(String targetName) {
this(targetName, null);
}

public RawEntryMapping(String targetName, AccessModifier access) {
this.access = access;
this.targetName = targetName;
this.targetName = targetName != null && !targetName.equals("-") ? targetName : null;
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, what is the - check for?

Choose a reason for hiding this comment

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

According to the PR description, it's used as a stand-in for a deobfuscated name in the Enigma format, to allow writing the access modifier component without a deobfuscated name.

Copy link
Contributor

Choose a reason for hiding this comment

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

https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.2.2
I suggest using one of . ; [ / to indicate an unchanged target name to avoid potential conflicts, preferably just .

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Is that necessary? These are deobf names, "-" is not a valid Java identifier character so you can't set it from the enigma UI and if you were to edit the file manually and have it remap correctly, you can't use methods with "-" in them from Java (nor probably any other JVM language). For all intents and purposes I think this is not really an issue (and I'd say "-" is more fitting as a placeholder to denote "no value" than any of these). I could make it "[none]" or something like that but as I said I don't think it'd be a problem.

Copy link
Member

Choose a reason for hiding this comment

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

Nitpick: dashes are usable in Kotlin if you escape the name with backticks (though that's extremely cursed)

if (entry instanceof ClassEntry) {
String line = writeClass((ClassEntry) entry, mapping);
writer.println(indent(line, depth));
line = writeClass((ClassEntry) entry, mapping);
Copy link
Contributor

Choose a reason for hiding this comment

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

same pattern matching comment

@liach liach requested a review from a team July 5, 2021 18:45

import java.util.Objects;

public class TristateChange<T> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
public class TristateChange<T> {
public final class TristateChange<T> {

this(targetName, AccessModifier.UNCHANGED, javadoc);
}

public EntryMapping(@Nonnull String targetName, AccessModifier accessModifier) {
public EntryMapping(@Nullable String targetName, AccessModifier accessModifier) {
this(targetName, accessModifier, null);
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Consider adding the canonical constructor to ensure accessModifier is not null

public EntryMapping {
	if (accessModifier == null) {
		accessModifier = AccessModifier.UNCHANGED;
	}
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Oh, that's some neat syntax! And good point, let me add an error message too though. I did test and fixed any occurrences of this getting passed null (there was only one from what I've tested and it broke loading mappings so I noticed immediately haha), but just in case.

@2xsaiko 2xsaiko merged commit 8efb624 into FabricMC:master Jul 8, 2021
@YanisBft YanisBft mentioned this pull request Jul 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants