Debugging Mixin¶
Tip
The Mixins section of Best Practices has a discussion on mixins, coremods, and other low-level definitions.
Spongepowered Mixin is the subsystem that allows SpongeAPI and other programs to interface with Minecraft. This article is not to provide a comprehensive explanation of Mixin. Please see Mixin’s wiki for its documentation and support options.
Note
Mixin has its own repository which you can clone and import into IntelliJ to find error messages and research problems. Alternatively, you can specify your local clone of the Mixin repository as a Module in the Project Settings of your Sponge implementation and debug Mixin.
Output¶
By default, a directory named .mixin.out
is created in the run
directory. The directory contains a sub-directory
named audit
with empty reports in text and comma-separated-values formatted files. These files are used if the
mixin.checks.interfaces
option is enabled.
However, Mixin supports Java System Properties to enable various debugging and auditing features. There are times when you may need or want to see the results of the process. You can see the mixin output by supplying one of the following VM options:
-Dmixin.debug=true |
Turns on all debugging features |
-Dmixin.debug.export=true |
Turns on only the feature that sends the output to disk |
In IntelliJ, open the Run/Debug Configurations
window by clicking on Run
-> Edit Configurations...
. Be sure
to add the options to the appropriate application (Minecraft Client
, Minecraft Server
, or both).
A new directory named classes
is created in the .mixin.out
directory when one of these options is used. This
directory contains the new class content from the mixin process in a standard package/class structure.
Note
These options are not contingent upon having cloned the Mixin repository, adding Mixin as a module, or using the Minecraft Development for IntelliJ plugin by DemonWav.
Tip
See Mixin Java System Properties for more mixin VM options with explanations for each option.
Decompiling¶
There are a several ways to view the class files from the mixin process.
IDE
Opening the file in your IDE will decompile it and display the source code
Fernflower
Having the fernflower jar on your runtime classpath will cause the class files to be decompiled as they are created.
JD-Gui is a standalone graphical utility that displays Java source codes of class files.
Phases And Environments¶
Important to understanding Mixin is knowing that game execution is split into two distinct phases: pre-init
and
default
. The pre-init
phase occurs between starting the game (running a command, script, double-clicking a
shortcut, clicking a “launch” button or whatever method you use to tell your computer to run Minecraft) and launching
the game (all modifications are complete and the game starts up and enters its main loop). The default
phase begins
when the game is in its “ready to be loaded” state and is the same as simply launching Minecraft.
Changes occur to infrastructure classes (loader, transformers, etc.) during the pre-init
phase. Mixin also gathers
information pertaining to all other mixins during the pre-init
phase and applies them during the default
phase.
Phases are handled by separating them into environments, where the pre-init
phase is the PREINIT
environment and the default
phase is the DEFAULT
environment.
Tip
Environments are among the properties specified in mixin configuration files. Examples of how they are specified
are "target": "@env(PREINIT)"
and "target": "@env(DEFAULT)"
Configurations¶
The primary resource Mixin requires is the configuration file(s). Each configuration file defines a mixin set - the mixins to be applied with that configuration. Any mixin not specified by a configuration is not applied even though the mixin may exist in the code. An application may have one to many sets; however, each set must contain mixins for only one environment. Another reason to separate configurations into multiple files is for organizational purposes.
Each mixin set (configuration file) is subdivided into three discrete areas: common, client, and server. The common mixins are mixed first followed by client or server, depending on the detected side.
Who Started It?¶
The Mixin subsystem interacts with all programs through a single instance of the subsystem, regardless of file, author, or organization. Yet, only one starts the subsystem, and it determines which version of Mixin is used. A problem occurs many times because an older version of Mixin is started. So, the order in which files are launched is important. Ideally, Sponge should launch first after Forge and before other tweakers and coremods.
A Broken Mixin¶
The game will crash when a class cannot be loaded, and this condition is known as a broken mixin. A broken mixin generally means a problem exists with the annotations and/or signature. For example, consider the following log snippet:
MixinSpongeSmeltingRecipe.java:41: error: No obfuscation mapping for @Overwrite method
default String getId() {
^
This error was corrected by changing the @Overwrite
annotation to @Overwrite(remap = false)
. The
remap element set to false causes the annotation processor to skip this annotation when attempting to build the
obfuscation table for the mixin.
Analysis of the source code might lead one to think the default
keyword in the method declaration is the problem.
Changing the keyword to static
results in the following log snippet:
MixinSpongeSmeltingRecipe.java:41: error: getId() in MixinSpongeSmeltingRecipe clashes with getId() in
static String getId() {
^
overriding method is static
MixinSpongeSmeltingRecipe.java:40: error: method does not override or implement a method from a supertype
@Override
^
MixinSpongeSmeltingRecipe.java:42: error: non-static variable this cannot be referenced from a static context
return CustomSmeltingRecipeIds.getDefaultId((SmeltingRecipe) this);
^
As you can see, three different errors occurred instead of the one error. The correct fix was adding the remap
element as described above. Keep in mind, though, the point of this example is not to show how to solve this problem,
but to demonstrate what a broken mixin looks like and to point out that most broken mixins are the result of incorrect
annotations or signatures.
Note
See the Mixin Wiki for a description on methods’ signatures
This section will be expanded in the future to list common causes of broken mixins and the solutions to fix them. If you feel like you can help, you can do so on our GitHub repository.
Minecraft Development for IntelliJ¶
A useful tool for working with Mixin is the Minecraft Development plugin for IntelliJ. You can debug and step through mixin code without having to deal with outputted class files from the mixin class loader.
Note
The plugin’s website provides information about installing and support options. A link to its GitHub repository is also provided where you can contribute and/or learn more about the project.
Installing¶
To use the plugin without cloning the source:
- Open
File -> Settings -> Plugins
and selectMarketplace
. - Search for minecraft in the search bar and select
Minecraft Development by DemonWav
. - Click the
Install
button (do not restart IntelliJ yet). - Go to https://github.com/minecraft-dev/MinecraftDev and download a ZIP file of the repository.
- Do one of the following:
- Open your program of choice for extracting zip files. Navigate to the
idea-configs
directory and copy/extract the contents of that directory to the.idea
directory of your Sponge workspace. - Extract the zip file to a location on your drive. Navigate to the
idea-configs
directory and copy the contents of that directory to the.idea
directory of your Sponge workspace.
- Open your program of choice for extracting zip files. Navigate to the
- Restart IntelliJ
The plugin will now be active and your project will have useful configurations and copyright settings.
Using¶
Coming soon!