Changes

Dealing with all of Curle's comments
Line 7: Line 7:     
== Overall process ==
 
== Overall process ==
When setting up the environment for the first time or ForgeGradle determines the environment is out of data (changed access transformers, mappings, or forge version), a gradle refresh triggers three things:
+
Whenever a gradle refresh is triggered, a few things occur:
 
# ForgeGradle downloads the jar and MCPConfig zip and triggers the extractSrg/createSrgToMcp task.
 
# ForgeGradle downloads the jar and MCPConfig zip and triggers the extractSrg/createSrgToMcp task.
 
# After that, it processes the jar - applies access transformers from forge/userdev, SAS from forge, and decompiles.
 
# After that, it processes the jar - applies access transformers from forge/userdev, SAS from forge, and decompiles.
 
# Finally, it patches and finalizes the code, ready for modder consumption.
 
# Finally, it patches and finalizes the code, ready for modder consumption.
 +
 +
This can either be triggered whenever an environment is first being set up, or when ForgeGradle determines the existing environment is out of date whether from changed access transformers, mapping sets, or the current forge version.
    
== Needed knowledge ==
 
== Needed knowledge ==
 
=== Obfuscation ===
 
=== Obfuscation ===
'''Obfuscation''' is the process of renaming all of the fields, methods, and classes of the compiled code into unreadable, machine-generated names (such as <code>aaa</code>, <code>bC</code>), and removing package structures (this makes everything package-local and makes the obfuscated code smaller somewhat. This is commonly used by companies to prevent external entities from easily decompiling their released binaries/executables and retrieving their source code/intellectual property, though it does have size advantages.
+
'''Obfuscation''' is the process of renaming all of the fields, methods, and classes of the compiled code into unreadable, machine-generated names (such as <code>aaa</code>, <code>bC</code>), and removing package structures (this makes everything package-local and makes the obfuscated code smaller somewhat. This is commonly used by companies to prevent external entities from easily decompiling their released binaries/executables and retrieving their source code/intellectual property.
    
Additionally, due to the way the Local Variable Table (LVT) of Java bytecode is stored, every function-local variable name is turned to <code>☃</code> (that's right, a snowman) in the compiled files. This makes immediate recompilation of the game literally and physically impossible, as every Java compiler currently available requires that local variables have unique names.
 
Additionally, due to the way the Local Variable Table (LVT) of Java bytecode is stored, every function-local variable name is turned to <code>☃</code> (that's right, a snowman) in the compiled files. This makes immediate recompilation of the game literally and physically impossible, as every Java compiler currently available requires that local variables have unique names.
Line 40: Line 42:  
The process can be broken up into 3 steps; MCPConfig, patch and provide.
 
The process can be broken up into 3 steps; MCPConfig, patch and provide.
 
The MCPConfig step is, understandably, the biggest and most prone to failure.
 
The MCPConfig step is, understandably, the biggest and most prone to failure.
An explanation of MCPConfig itself, how it works, what it's for (but NOT how to use it) can be found [[Toolchain:MCPConfig|here]]. For the purpose of this guide, you need only know that its' goal is to get the game decompiled, and into a state where it can immediately be recompiled. Due to certain flaws in the rest of the toolchain, this means it needs to fix and patch the source code before passing it onto Forge.
+
An explanation of MCPConfig itself, how it works, what it's for (but NOT how to use it) can be found [[Toolchain:MCPConfig|here]]. For the purpose of this guide, you need only know that its' goal is to get the game decompiled, and into a state where it can immediately be recompiled. This means it needs to fix and patch the source code before passing it onto Forge.
    
In this way, MCPConfig can be thought of the vanilla side of the setup. It does not modify the game.
 
In this way, MCPConfig can be thought of the vanilla side of the setup. It does not modify the game.
Line 59: Line 61:  
* Once the step is all parsed in, it is executed:
 
* Once the step is all parsed in, it is executed:
 
** java -jar &lt;version&gt; &lt;args&gt; &lt;jvmArgs&gt;
 
** java -jar &lt;version&gt; &lt;args&gt; &lt;jvmArgs&gt;
  −
An example config.json can be found [https://github.com/MinecraftForge/MCPConfig/blob/master/versions/release/1.17.1/config.json here].
      
It defines the steps:
 
It defines the steps:
Line 73: Line 73:  
** version: net.minecraftforge.lex:vignette:0.2.0.10
 
** version: net.minecraftforge.lex:vignette:0.2.0.10
 
** args: --jar-in {input} --jar-out {output} --mapping-format tsrg2 --mappings {mappings} --fernflower-meta --cfg {libraries} --create-inits --fix-param-annotations
 
** args: --jar-in {input} --jar-out {output} --mapping-format tsrg2 --mappings {mappings} --fernflower-meta --cfg {libraries} --create-inits --fix-param-annotations
 +
 +
{{Tip|An example config.json can be found [https://github.com/MinecraftForge/MCPConfig/blob/master/versions/release/1.17.1/config.json here].}}
    
More information about each of these tools can be found at the link provided, as well as what each of these arguments do. A brief description is provided.
 
More information about each of these tools can be found at the link provided, as well as what each of these arguments do. A brief description is provided.
    
=== ForgeFlower ===  
 
=== ForgeFlower ===  
The decompiler used by ForgeGradle is a custom fork of [https://github.com/JetBrains/intellij-community/tree/master/plugins/java-decompiler/engine Jetbrains' FernFlower], called [https://github.com/MinecraftForge/ForgeFlower ForgeFlower].
+
The decompiler used by ForgeGradle is a custom fork of [https://github.com/JetBrains/intellij-community/tree/master/plugins/java-decompiler/engine Jetbrains' FernFlower], called [https://github.com/MinecraftForge/ForgeFlower ForgeFlower] which searches the jar for files, cleans up the bytecode, and then converts it into a reasonable best-guess interpretation.
   −
It simply searches the jar for files, cleans up the bytecode, and then converts it into a reasonable best-guess interpretation.
+
It also produces the following side effects:
 
  −
It:
   
* Removes synthetic parameters from constructors
 
* Removes synthetic parameters from constructors
 
** In bytecode, inner classes have the outer class as their first constructor parameter, but Java source code does not.
 
** In bytecode, inner classes have the outer class as their first constructor parameter, but Java source code does not.
Line 101: Line 101:     
=== Mergetool ===
 
=== Mergetool ===
The game is split into two distributions; server and client.
+
The game is split into two distributions; server and client. Since the server is just a subset of the client, the client contains the server-only classes as well.
 
  −
Because the server contains no rendering code, and the client contains none of the server-specific code (like the UI), this means there are differences between what can run on one side or the other. Since the server is just a subset of the client, the client contains the server-only classes as well.
      
To get around this, we have a tool called Mergetool, which can search for the differences between two files (down to the function level) and merge them into one large (referred to as joined) jar file. It also can also annotate those files as necessary.
 
To get around this, we have a tool called Mergetool, which can search for the differences between two files (down to the function level) and merge them into one large (referred to as joined) jar file. It also can also annotate those files as necessary.
Line 112: Line 110:  
Vignette is where SRG starts to come into play. It serves the role of our deobfuscator, performing deobfuscation.
 
Vignette is where SRG starts to come into play. It serves the role of our deobfuscator, performing deobfuscation.
   −
This process is done with the help of a '''deobfusation map''', a file generated by the original obfuscator (in this case, ProGuard) that contains a map of the obfuscated names to original, non-obfuscated names. This is commonly used on debofuscating stack traces outputted by an obfuscated program, for debugging purposes.<ref name="retrace"/>
+
This process is done with the help of a '''deobfusation map''', a file generated by the original obfuscator (in this case, ProGuard) that contains a map of the obfuscated names to original, non-obfuscated names. This is commonly used on deobfuscating stack traces outputted by an obfuscated program, for debugging purposes.<ref name="retrace"/>
    
We have three sets of deobfuscation maps available to us; the obf->SRG mappings distributed with the MCPConfig system, the Yarn intermediary system, or the official mappings.<ref name="mojmappings"/>.
 
We have three sets of deobfuscation maps available to us; the obf->SRG mappings distributed with the MCPConfig system, the Yarn intermediary system, or the official mappings.<ref name="mojmappings"/>.
Line 142: Line 140:  
=== Patches ===
 
=== Patches ===
 
Once we have the source code ready to go, the final step in the setup is to apply patches.
 
Once we have the source code ready to go, the final step in the setup is to apply patches.
These are done trivially using [https://github.com/MinecraftForge/DiffPatch DiffPatch].
+
These are done trivially using [https://github.com/MinecraftForge/DiffPatch DiffPatch].
    
== The Forge Side ==
 
== The Forge Side ==
Line 148: Line 146:  
After the MCPConfig/SetupMCP tasks are finished, ForgeGradle will print '''MCP Environment Setup is complete''' and wait for the user input.
 
After the MCPConfig/SetupMCP tasks are finished, ForgeGradle will print '''MCP Environment Setup is complete''' and wait for the user input.
   −
The next step is to run the <code>gradlew setup</code> task, which does what it implies: Applying the Forge system to the processed vanilla code.
+
When running the <code>gradlew setup</code> task, it will rerun the SetupMCP tasks and then start applying the Forge system to the processed vanilla code.
   −
First, it applies ATs. After that, patches. Finally, the official mappings are applied.
+
First, it applies ATs. After that, patches. Finally, the official mappings, or some other mappings from a provider like Parchment, are applied.
    
All in all, compared to the MCPConfig setup, this is a string of extremely basic tasks - mostly just one-line commands.
 
All in all, compared to the MCPConfig setup, this is a string of extremely basic tasks - mostly just one-line commands.
Line 161: Line 159:  
* <code>AccessTransformers.jar --inJar {input} --outJar {output} --logFile accesstransform.log --atFile {at.cfg}</code>
 
* <code>AccessTransformers.jar --inJar {input} --outJar {output} --logFile accesstransform.log --atFile {at.cfg}</code>
   −
[https://github.com/MinecraftForge/MinecraftForge/blob/1.17.x/src/main/resources/META-INF/accesstransformer.cfg The current AT cfg can be found here.]
+
[https://github.com/MinecraftForge/MinecraftForge/blob/1.17.x/src/main/resources/META-INF/accesstransformer.cfg The AT cfg for Forge can be found here.]
    
=== Applying Patches ===
 
=== Applying Patches ===
   −
The patches used for Forge itself at install time are different from those used by MCPConfig, which means there are two separate patching stages performed.
+
The patches used for Forge itself are different from those used by MCPConfig, which means there are two separate patching stages performed.
    
As opposed to the minimal MCPConfig patching, with the goal to make the code recompilable, the Forge patching is done to apply the API and mod loader to the code.
 
As opposed to the minimal MCPConfig patching, with the goal to make the code recompilable, the Forge patching is done to apply the API and mod loader to the code.
   −
It does this in a very similar way, with the [https://github.com/MinecraftForge/BinaryPatcher BinaryPatcher] utility.
+
It does this in a very similar way, with the [https://github.com/MinecraftForge/BinaryPatcher BinaryPatcher] utility used at install time/during a CI build or [https://github.com/MinecraftForge/DiffPatch DiffPatch] in all other situations.