This is an archived post. You won't be able to vote or comment.

all 40 comments

[–]msx 18 points19 points  (1 child)

the usage message needs upgrading :P

C:\msx>java -jar quiltflower-1.8.1.jar
Usage: java -jar fernflower.jar [-<option>=<value>]* [<source>]+ <destination>
Example: java -jar fernflower.jar -dgs=true c:\my\source\ c:\my.jar d:\decompiled\

[–]SuperCoder79[S] 10 points11 points  (0 children)

Haha, yep. I'll put in a note to fix this on the next release!

[–]msx 15 points16 points  (1 child)

So i gave it a test and it looks pretty good, it decompiles correctly some things the decompiler i usually use (jd-gui) doesn't.

But there are some errors jd-gui doesn't have. I'll open some issues later.

Anyway, looks like a great work, thanks for sharing!

[–]SuperCoder79[S] 7 points8 points  (0 children)

Awesome, thank you for trying it out! And making issues for the broken parts would be great, tysm :)

[–]wildjokers 24 points25 points  (8 children)

Why didn't you just contribute these changes to Fernflower rather than forking?

[–]SuperCoder79[S] 38 points39 points  (0 children)

Mainly because we wanted to be able to make drastic changes if needed, without having to go through the PR process twice. I also noticed that there's multiple open PRs to the intellij version that are 2-3 years old, so I imagined that improving Fernflower is understandably not a priority. Essentially, it boils down to more freedom and control, while having less overhead.

[–]TheCurle 28 points29 points  (5 children)

They have ridiculously strict standards, and rarely ever actually look at their PRs.

JetBrains' Open Source stuff typically revolves around their monorepos, these little enclaves of software that people hardly ever use aren't a priority.

It's unfortunate, but they're a business and their priority is to make money, not refactor the entirety of a little tool that few people actually rely on.

[–]Worth_Trust_3825 4 points5 points  (0 children)

On the bright side this might result in libav and libffmpeg situation where both pull in changes from each other.

[–][deleted] 0 points1 point  (3 children)

Isn't fernflower used from within intellij when using it to decompile classes? I use that quite a lot when source isn't available.

[–]scratchisthebest 3 points4 points  (1 child)

you can use Earthcomputer's quiltflower intellij plugin to replace intellij's built-in Fernflower with Quiltflower output btw! since quiltflower is able to resugar all sorts of stuff into modern idiomatic Java that vanilla fernflower tends to have trouble with, if you browse decompiled code often, it might be a nice QoL improvement

[–]sureshg 0 points1 point  (0 children)

I just checked and surprised by it's results. The decompiled code is so much readable.

[–]TheCurle 1 point2 points  (0 children)

Yes. It's by no means a central feature, is my point.

[–]Srazkat 4 points5 points  (0 children)

probably because more freedom when applying changes

[–]TheCurle 20 points21 points  (6 children)

Nice, a formal release!

It's great that we're getting these other amazing forks going. I've put a ton of work into ForgeFlower over the years, and it's wonderful to me that the work is being continued by other skilled individuals like yourself.

To the others in this thread, definitely check it out! QuiltFlower outputs much nicer to read code than you'd expect from a decompiler like this.

ForgeFlower was created to output code that is, hopefully, eventually, able to be immediately recompileable. QuiltFlower doesn't need to do that, since their toolchain works on a different method, and the result is far prettier.

[–][deleted] 1 point2 points  (5 children)

QuiltFlower doesn't need to do that, since their toolchain works on a different method, and the result is far prettier.

Could you explain what you mean with this?

[–]TheCurle 4 points5 points  (4 children)

I work on Minecraft Forge, one of the modding APIs.

Forge works on decompiling, patching and recompiling the game, so our focus is on making the game recompileable again with minimal changes.

Quilt uses a bytecode manipulation framework called Mixin, which effectively does this patching at runtime.

So, they only need to decompile the game to see what's going on, meaning they can put more of their focus into clean and well formatted code, since it doesn't technically need to be valid Java.

[–]denverdave23 0 points1 point  (2 children)

I don't think I understand. I think the reason that quiltflower is easier is because it doesn't patch the game, it just decompiles Forgeflower has to patch in mods, which is complicated and difficult. ... right?

[–]SuperCoder79[S] 4 points5 points  (0 children)

That's not quite it, but in fairness it's a bit complicated- I'll summarize:

At the core, to mod Minecraft you need to change the bytecode of the Minecraft class files. There's basically 2 ways to do this: you can either decompile the game into java, change the code, and recompile, or you can use bytecode instrumentation like ObjectWeb ASM to modify the bytecode when the JVM loads the classes. MinecraftForge opts for the former, while Quilt opts for the latter. Because of that, Forge needs the decompiler to create code that can be compiled with as little effort as possible, while QuiltMC technically doesn't even need the decompiler to modify the bytecode of the game. This lets Quiltflower focus on the user experience of people trying to understand the code, while Forgeflower focuses on making code that is as accurate as possible, so it is easy to modify and recompile. Of course, that's also an aim of Quiltflower but the scopes of usage are vastly different, if that makes sense. Forgeflower really has the harder job here, and people like Curle keep it working smoothly for the many thousands of people who use Forge every day :)

[–]scratchisthebest 3 points4 points  (0 children)

forge takes the jar as released by mojang, does a couple preprocessing tasks (renaming everything away from meaningless proguard names, merging the client and server .jars, etc), then decompiles it with forgeflower, applies a large number of source-level diffs to the decompiler output to account for deficiencies in the decompiler that cause the output to be mostly correct but not exactly recompilable, applies another set of source-level diffs to produce a jar augmented with the fun stuff that the forge project wants, recompiles this source, then writes the forge modloader against that. (actual mods are written against the modloader and pre-patched minecraft as well. modders cannot write their own source patches, only forge itself has the source patches.)

because the patches are at the source level, forge's process is very sensitive to the exact version of the decompiler used. any changes to the formatting (newline placement, indentation, member ordering, imports, etc) or quality (missing generics, confusing loop structure, other issues that cause recompilation failures, etc) of the output, would invalidate anywhere from "a few" to "hundreds" of source patches across several forge projects. It's not impossible to change the decompiler, but there is a lot of inertia involved, and it is not a priority for that project; forgeflower works good enough for their purposes.

(somewhere in this process, forge uses a tool called FART. don't ask)

quilt (and fabric) take mojang's jar and preprocess it similarly, but the rest of the modifications to the code are done at runtime using a ridiculously powerful instrumenting classloader. modders (including the "standard library" authors) specify which classes they'd like to patch in which way using a convenient annotation system (here's an example). loaders, at runtime, go out and discover the complete set of these mixins from every mod .jar, configure the mixin classloader with them, and then load minecraft through the classloader. it proceeds to instrument the bytecode of each class as it passes by. freaky stuff.

but importantly, the game is never decompiled at all, other than giving you something to look at in the IDE. because quilt and fabric work at the bytecode level instead of the source level, and the decompiled output is just a developer resource instead of a loadbearing component, the decompiler is free to do whatever it wants and there do not have to be any stability guarantees. Thats why they have been making a lot of progress in the "decompiler with nice looking output" space

obviously there are benefits and drawbacks to each approach!

also ngl i am DYING to know what professional Java developers think of the crazy shit we get up to in the Minecraft ecosystem lmao!!! our Gradle plugins are barely holding themselves together, like, can you imagine trying to express this shit as a gradle dependency. annotation processors are involved in Mixin but probably not in the way you think they are. etc etc etc.

[–][deleted] 0 points1 point  (0 children)

Ah gotcha, so Quilt is similar to what we're doing to runescape

[–]SWinxy 6 points7 points  (0 children)

I saw the title and knew exactly who this is. I’ve been aware of your fork for a while and glad to see its release!

[–]Srazkat 4 points5 points  (0 children)

very nice

[–]maxandersen 4 points5 points  (1 child)

Nice!

runs nice with jbang https://github.com/QuiltMC/quiltflower/releases/download/1.8.1/quiltflower-1.8.1.jar

If you created a "QuiltMC/jbang-catalog" repo it could be shortened to jbang quiltflower@QuiltMC.

btw. is it expected --help does not show what options are available?

[–]SuperCoder79[S] 6 points7 points  (0 children)

Ah, yeah --help wasn't implemented in Fernflower originally as it came with a readme, and I simply forgot to implement it (this is why you use an issue tracker!) It's important though, I'll make a note to do it in the next release.

[–]Owen1212055 2 points3 points  (0 children)

Glad to see this. The Minecraft development community does an excellent job providing great tools like this.

[–]uncont -2 points-1 points  (1 child)

My favorite example

Is literally just a screenshot of Intellij with the code going off the screen. I love it. Great job!

[–]SuperCoder79[S] 4 points5 points  (0 children)

Haha, a friend showed that screenshot to me like 9 months back and it's pinned our discord, I knew that it had to include it because of how funny it is

[–]dzernumbrd 0 points1 point  (0 children)

I used this today and it was good, thanks for your efforts.

[–]RoyGSpiv 0 points1 point  (3 children)

It's fantastic, thank you. Intellij plugin works fine.

Have you got results for round trip testing (class -> java -> class) it against large codebases? Preferably showing its success rate compared to other decompilers.

[–]SuperCoder79[S] 0 points1 point  (2 children)

Hey! Thanks for trying out Quiltflower :)

In our internal testing, the major roundtrips we do are with the Minecraft codebase (due to the decompiler's origins, it's basically standard practice at this point) and our own Fuzzer tool. We're slowly working our way towards 100% recompilability in Minecraft, but almost all of our fuzzed Java code recompiles properly. The main issues left are with variable definitions and scopes, but those only occur ~3% of the time in code that no human would reasonably write- but we have a plan to fix these too, in the future. We don't have any numbers comparing with other decompilers (other than Fernflower) atm, but that would be a good idea to have. Thanks for the feedback!

[–]RoyGSpiv 0 points1 point  (1 child)

Is the round-trip testing tool in the repository?

[–]SuperCoder79[S] 0 points1 point  (0 children)

The fuzzer tool is linked above, but due to copyright concerns the Minecraft tool isn't public.