Ich freu mich bereits mega auf das Update und nun ist es endlich da. Die Fixes für die Sprachen sind da, viele neue Funktionen und nach einer so langen Zeit, haben sie auch bestimmt ihren Coding Style angepasst. Deswegen werde ich diesemal Terraria 1.2 Decompilen und den Source Code ein wenig analysieren und schauen was sich alles so verändert hat. Meine Erwartungen an den Source Code:
- übersichtlicher
- betriebenes Refactoring
Meine Hoffnung ist es, dass wenigstens ein paar Funktionen verbessert worden sind und man einen guten Überblick im Source Code behält ;) Wir werden sehen und ich freue mich schon auf das Decompiling. Sollte ja nicht Schwer werden :D
Zum decompilen benutze ich für C# Anwendungen ILSpy. Ein super Decompiler und er hat mir bisher immer sehr geholfen. Doch diesmal scheint es ein wenig verhext mit ILSpy zu sein. Irgendwie scheint das Programm immer abzustürzen und ich kann keinen triftigen Grund dafür erkennen. Also das Programm noch einmal heruntergeladen, jedoch mit dem selben Ergebnis.
Naja dann werde ich wohl jede Klasse einzeln exportieren. Es ist zwar ein wenig aufwendiger, aber ich komme ja an die Sourcen :P
Nach dem ich ein paar Klassen exportiert habe und bei der Klasse Item.cs angekommen bin, stürzt ILSpy wieder ab. Ich habe erstmal die Item.cs ignoriert und bei den anderen Klassen weitergemacht.
Fazit: Alle Klassen außer die Item.cs konnten decompiled werden. Da ILSpy mir nicht verrät warum es abschmiert, lade ich mir ersteinmal den Source Code runter und versuche mal ILSpy im Debugging Modus.
Scheiße?!? Stackoverflow Exception? Was hat das denn nun wieder zu bedeuten. Der Fehler weißt auf die Funktion FindConditions hin. FindConditions o.O Conditions ??? AAAAAHHHHH!!!! Könnt ihr euch noch an diese verdammte super mega verschachtelte If Abfrage in Terraria 1.1.2 erinnern. Da hab ich mich noch in dem Artikel für diesen schlimmen Code entschuldigt. Der Decompiler kommt nun wahrscheinlich mit dieser Abfrage nicht mehr klar, weil diese noch größer geworden ist.
Dann versuche ich mal ILSpy zu fixen, wenn das denn überhaupt geht. Nach einer grundlegenden Analyse der betroffenen Funktionen und ein wenig Internetrecherche, kam ich zu dem Schluss, dass ich ILSpy nicht fixen kann. Rekursive Methoden ist hier das Stichwort. Die Funktionsweise des Decompiler ist, dass er einen IF-Zweig betritt und schaut ob es neue Zweige gibt. Wenn ja wird die selbe Methode noch einmal aufgerufen. Bei Terraria ist die Verschachtelung so riesig und geht wahrscheinlich über 1000 (Anzahl der Items). Damit kann ich dies nicht fixen und ich denke mal die Entwickler von IlSpy gehen nicht davon aus, dass ein Affe über 1000 verschachtelte If-Abfragen macht. Entweder ich schreib diese Funktion in IlSpy komplett um, oder suche mir einen anderen Decompiler.
Gesagt getan. Ich habe dotPeek gefunden und dieser hat auch auf Anhieb Terraria decompiled. Bei der Fehlerbehebung des Source Codes ist mir jedoch aufgefallen, dass der Decompiler mehr Fehler einbaut und damit den Source Code in Teilen unbrauchbar macht. Also bleibt bei IlSpy!
Wieder zurück zu ILSpy
Ich kam auf die Idee, einige Dinge aus dem Source Code von IlSpy auszukommentieren. Wenn man folgende Passage auskommentiert, werden die Else-Zweige nicht aufgelöst und man erhält ein Source Code mit goto jumps.
// if (falseTarget != null && HasSingleEdgeEnteringBlock(falseTarget)) { // HashSet<ControlFlowNode> content = FindDominatedNodes(scope, falseTarget); // scope.ExceptWith(content); // ilCond.FalseBlock.Body.AddRange(FindConditions(content, falseTarget)); // }
Das gute daran ist, dass der Source Code trotzdem funktioniert, aber es ist eher unschön mit Goto Befehlen zu arbeiten. In diesem Fall bin ich aber der Meinung, dass es hilft den Source Code übersichtlicher macht. Wer will sich schon durch dieses Wirr-Warr von über 1000 Verzweigungen kämpfen.
Zunächst decompile ich das gesamte Projekt, damit ich eine Projekt-Datei am Ende bekomme. Danach stelle ich wieder IlSpy in den Originalzustand zurück und exportiere jede Klasse einzeln, sodass die If-Else Zweige wieder ordentlich sind (außer bei der Item.cs). Bei der Item.cs gehe ich ein wenig anders vor. Hierbei werde ich die Datei mit einem Texteditor bearbeiten und anschließen alle Methoden ersetzen, die ich auch mit dem Decompiler ordentlich decompilen konnte. Damit habe ich am Ende eine Item.cs die man einigermaßen gebrauchen kann.
Die Fehlerbehebungen
private static Action<char> CS$<>9__CachedAnonymousMethodDelegate1;</p>
Alle Variablen mit diesem Namen umbennen Beispiel: CS$<>9__CachedAnonymousMethodDelegate1 in CachedAnonymousMethodDelegate1
private static void <Initialize>b__0(char keyStroke)</p>
Methode umbennen und alle Aufrufe anpassen
Cannot implicity convert … in byte
Beispiel:
color.R = Main.mouseTextColor / 2;
Korrekt:
color.R = (byte) (Main.mouseTextColor / 2);
Wenn die Konvertierung in short erfolgen sollte, dann einfach byte mit short ersetzen :D
?? Fehler
Beispiel:
int num75 = num70 ?? -1;
Korrektur:
int num75 = (num70 != null) ? num70 : -1;
Man muss nur überprüfen ob der Wert vorhanden ist, wenn nicht dann muss er mit -1 ersetzt werden.
Am Ende wäre noch diese Zeile die ich auskommentiert habe:
//this.velocity != value2;
Fazit
Interessant finde ich es, dass schon einige Leute vor mir versucht haben Terraria 1.2 zu decompilen. Sie haben ILSpy sehr früh durch dotPeek ersetzt. Resultat war, dass verschiedene Dinge nicht laufen. Bei meiner Version sollten alle Dinge auf anhieb laufen, aber beim Decompiler besteht immer die Gefahr, dass er immer irgendetwas versaut :)
Ich habe jetzt auch eine GitHub Account und dort könnt ihr euch den Source Code anschauen. Jetzt kommt bestimmt wieder die Frage, warum veröffentlichst du das und du hilfst damit der Piraterie.
Erstens: es gibt keine Vereinbarung, wie es bei anderen Spielen ist, dass man das Spiel decompilen darf. Es ist eine ähnliche Situation, wie bei Minecraft.
Zweitens: Der Content Ordner wird immer noch benötigt, um das Spiel zu spielen und diesen bekommt ihr nur, wenn ihr das Original Spiel besitzt :P
Wenn ihr fehler entdeckt, einfach in die Kommentare schreiben oder auf GitHub melden.
https://github.com/TheVamp/Terraria-Source-Code
Also, viel Spaß beim lernen und analysieren ;)
Greetz TheVamp
Vielen Dank für diesen Artikel. Ich wollte eigentlich nur ein kleines Item ändern und bin dabei ebenfalls auf die ominöse Projectile und Item Datei gestoßen. Ich habe soetwas noch nie gesehen und hätte auch nie geglaubt, dass man so wirklich so einen Müll zusammenprogrammieren kann.
Danke für die Lösungsansätze, wobei ich die Idee mit dem modifizieren schon verworfen haben, das macht keinen Spaß mit so viel Müll.
.net Reflector hat mich bei Terraria und anderen Games enttäuscht. Es war nicht in der Lage halbwegs funktionsfähigen Code zu generieren. Ich könnte wetten, es scheitert genauso an Terraria, wie IlSpy ;)
Zudem kostet die Software was und arbeitet genauso zuverlässig wie IlSpy.
PS: Ich hab gerade .net Reflector ausprobiert. Es stürzt genauso wie IlSpy ab :) Tja das ist ein Problem, wie bei Terraria programmiert wurde und ein genereller falscher Ansatz, wie man die Abfragen decompiled
für das decompiling eignet sich .net reflector immer noch am besten, so als tipp ;)