Jump to content

PZ Source Code Spelunking, Debugging, and Decompiling


Eggplanticus

Recommended Posts

In this thread I want to discuss how to peruse, and possibly debug the (decompiled) sources of pz. Please note that I do not in any way advocate copying or otherwise infringing upon the intellectual properties of the developers. This thread is mainly meant to help advanced users or programmers isolate problems in the code. Please note, I do not know how to recompile pz. I'm not sure it's even possible, given that decompiling doesn't always work correctly.

Browsing the code:
all that is required to browse the code is a Java decompiler. There is a freely available one called JD GUI on the Internet.

 

Debugging the code:
This is much more complicated. To debug the code you need the following tools:
1) Eclipse (java ide)
2) the JD-Eclipse plugin (java decompiler) http://java.decompiler.free.fr/
3) the JDEclipse-realign plugin (allows debugging)  http://mchr3k.github.io/jdeclipse-realign/

 

Configuring the plugins:

You might need to go to window -> preferences -> general -> editors -> file associations -> *.class without source and set the default editor to the viewer with [decompiled] next to it in order for it to open .class files without problems.

 

Configuring Eclipse:

 

1) Create a new project called pz.

 

2) Create a new folder under the project

2.1) Parent folder: pz

2.2) Folder name: pz_classes

2.3) Click advanced -> link to alternate location -> browse -> select the folder which contains project zomboid on your computer

 

3)Go to project->properties->Java build path

3.1) Click add Jars: add the jinput, lwjgl, lwjgl_util jar files

3.2) Click add class folder: select pz_classes folder

 

You can now browse the pz sources through eclipse, just by clicking on the class directories and look clicking on the class files.

 

Configuring the environment to run pz:

note: pz is run from the class zombie.core.LaunchDialog

 

4) Right-click LaunchDialog.class -> debug as -> debug configurations

 

Set up the pz environment variables

4.1) Click on the arguments tab

4.2) In the VM arguments box add the following lines (this is taken from the projectzomboid.sh file)

 

-Djava.library.path=${PATH_TO_PZCLASSES}
-Dorg.lwjgl.util.NoChecks=true
-Dorg.lwjgl.librarypath=${PATH_TO_PZCLASSES}
-Xms768m
-Xmx768m
-XX:-UseSplitVerifier

 

4.3) Set the working directory (just below the vm arguments box) to "other", click Workspace, and select the pz directory as the working directory.

 

Congratulations, you can now run pz in the Eclipse debugger!

 

Just click the little bug-beetle thing to launch it. Remember, the file you want to run is LaunchDialog.class.

 

If pz crashes, if you're lucky, the debugger will stop on the exact (decompiled) source line where the crash occurs.

 

Debugging example:

This is not going to be a tutorial on debugging, since if you are doing this, you should probably know the basics already.  However since it's not possible to recompile the decompiled code, at least to my limited knowledge, sometimes debugging is not easy. So here is an example of how I did it:

 

 to test/debug/fix some issues I had with the 2.9.9.16 forum build crashing on linux, I had to do the following:

 

1) set a breakpoint at the first line of main() in LaunchDialog

2) In the expressions tab of the of the debugger (top-right window) I put in some java expressions I wanted to try: System.loadLibrary("xx");
 

3) run the debugger on LaunchDialog

4) the program will stop at the first line of main and the expression will be evaluated automatically

5) click the resume button to continue

 

So that's it. Easy, right?  (clyde)

Edited by Eggplanticus
Link to comment
Share on other sites

It's easier to pick a source file and clean out all errors introduced by the decompilation process (garbage bridge methods, unnamed constructors, references to  anonymous inner classes that have been revamped into outer classes, exploded switch statements, illegal legal accessors, and lost access types) and use the current zombie class files to assist in the recompile.

JavaDoc is invaluable for this work.

In NetBeans, this is as simple as adding the entire Project Zomboid directory to your project and building the worked-on class there.

It's a long process, though. I only made it through the first 200-odd classes before I went a bit insane.

Link to comment
Share on other sites

I installed the JD Eclipse plugin AND realign plugins altogether from here : http://mchr3k.github.io/jdeclipse-realign/

Then entered the update-site url (http://mchr3k-eclipse.appspot.com/) in eclipse menu -> help -> install new software... -> work with

Finally installed both JD plugins.

 

Apparently working as far as turning binaries into source code is concerned.

 

So are they the plugins you use ? Can you please put some links in the OP ?

 

Still have to try to run the game from the IDE though.

Link to comment
Share on other sites

I get this exception when debugging :
 

Aug 27, 2013 5:23:18 PM zombie.GameWindow initShared
SEVERE: null
java.lang.NullPointerException
at zombie.scripting.ScriptManager.LoadDirPP(ScriptManager.java:783)
at zombie.GameWindow.initShared(GameWindow.java:214)
at zombie.GameWindow.init(GameWindow.java:1362)
at zombie.GameWindow.maina(GameWindow.java:874)
at zombie.core.LaunchDialog.main(LaunchDialog.java:217)
 
Aug 27, 2013 5:23:19 PM zombie.GameWindow LoadTexturePack
SEVERE: null
java.io.FileNotFoundException: media/texturepacks/UI.pack (No such file or directory)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at java.io.FileInputStream.<init>(FileInputStream.java:97)
at zombie.GameWindow.LoadTexturePack(GameWindow.java:1195)
at zombie.GameWindow.initShared(GameWindow.java:233)
at zombie.GameWindow.init(GameWindow.java:1362)
at zombie.GameWindow.maina(GameWindow.java:874)
at zombie.core.LaunchDialog.main(LaunchDialog.java:217)
 
Aug 27, 2013 5:23:19 PM zombie.core.LaunchDialog main
SEVERE: null
java.io.FileNotFoundException: media/zombiefont2.fnt (No such file or directory)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at java.io.FileInputStream.<init>(FileInputStream.java:97)
at zombie.core.fonts.AngelCodeFont.<init>(AngelCodeFont.java:169)
at zombie.ui.TextManager.Init(TextManager.java:140)
at zombie.GameWindow.initShared(GameWindow.java:235)
at zombie.GameWindow.init(GameWindow.java:1362)
at zombie.GameWindow.maina(GameWindow.java:874)
at zombie.core.LaunchDialog.main(LaunchDialog.java:217)

 
Debug configuration :
 

-Djava.library.path="/media/ECC3-C3B0/Downloads/PZ/projectzomboid_LINUX/"
-Dorg.lwjgl.util.NoChecks=true
-Dorg.lwjgl.librarypath="/media/ECC3-C3B0/Downloads/PZ/projectzomboid_LINUX/"
-Xms768m
-Xmx768m
-XX:-UseSplitVerifier

where "/media/ECC3-C3B0/Downloads/PZ/projectzomboid_LINUX/" is the absolute path to the pz root folder (same as pzclasses folder right ?)

 

EDIT: and when i first robotically used {PATH_TO_PZCLASSES} it obviously said that the variable is undefined

 

The 'java.io.FileNotFoundException: media/zombiefont2.fnt (No such file or directory)' seems to indicate a problem with the paths (the file is actually in the media folder) but i don't have a clue how this is to be addressed.

 

EDIT 2 : java.decompiler.free.fr page access is forbidden (was working a few days ago though)

Link to comment
Share on other sites

It's easier to pick a source file and clean out all errors introduced by the decompilation process (garbage bridge methods, unnamed constructors, references to  anonymous inner classes that have been revamped into outer classes, exploded switch statements, illegal legal accessors, and lost access types) and use the current zombie class files to assist in the recompile.

JavaDoc is invaluable for this work.

In NetBeans, this is as simple as adding the entire Project Zomboid directory to your project and building the worked-on class there.

It's a long process, though. I only made it through the first 200-odd classes before I went a bit insane.

 

How is that easier?

Link to comment
Share on other sites

I get this exception when debugging :

 

Aug 27, 2013 5:23:18 PM zombie.GameWindow initShared

SEVERE: null

java.lang.NullPointerException

at zombie.scripting.ScriptManager.LoadDirPP(ScriptManager.java:783)

at zombie.GameWindow.initShared(GameWindow.java:214)

at zombie.GameWindow.init(GameWindow.java:1362)

at zombie.GameWindow.maina(GameWindow.java:874)

at zombie.core.LaunchDialog.main(LaunchDialog.java:217)

 

Aug 27, 2013 5:23:19 PM zombie.GameWindow LoadTexturePack

SEVERE: null

java.io.FileNotFoundException: media/texturepacks/UI.pack (No such file or directory)

at java.io.FileInputStream.open(Native Method)

at java.io.FileInputStream.<init>(FileInputStream.java:138)

at java.io.FileInputStream.<init>(FileInputStream.java:97)

at zombie.GameWindow.LoadTexturePack(GameWindow.java:1195)

at zombie.GameWindow.initShared(GameWindow.java:233)

at zombie.GameWindow.init(GameWindow.java:1362)

at zombie.GameWindow.maina(GameWindow.java:874)

at zombie.core.LaunchDialog.main(LaunchDialog.java:217)

 

Aug 27, 2013 5:23:19 PM zombie.core.LaunchDialog main

SEVERE: null

java.io.FileNotFoundException: media/zombiefont2.fnt (No such file or directory)

at java.io.FileInputStream.open(Native Method)

at java.io.FileInputStream.<init>(FileInputStream.java:138)

at java.io.FileInputStream.<init>(FileInputStream.java:97)

at zombie.core.fonts.AngelCodeFont.<init>(AngelCodeFont.java:169)

at zombie.ui.TextManager.Init(TextManager.java:140)

at zombie.GameWindow.initShared(GameWindow.java:235)

at zombie.GameWindow.init(GameWindow.java:1362)

at zombie.GameWindow.maina(GameWindow.java:874)

at zombie.core.LaunchDialog.main(LaunchDialog.java:217)

 

Debug configuration :

 

-Djava.library.path="/media/ECC3-C3B0/Downloads/PZ/projectzomboid_LINUX/"

-Dorg.lwjgl.util.NoChecks=true

-Dorg.lwjgl.librarypath="/media/ECC3-C3B0/Downloads/PZ/projectzomboid_LINUX/"

-Xms768m

-Xmx768m

-XX:-UseSplitVerifier

where "/media/ECC3-C3B0/Downloads/PZ/projectzomboid_LINUX/" is the absolute path to the pz root folder (same as pzclasses folder right ?)

 

EDIT: and when i first robotically used {PATH_TO_PZCLASSES} it obviously said that the variable is undefined

 

The 'java.io.FileNotFoundException: media/zombiefont2.fnt (No such file or directory)' seems to indicate a problem with the paths (the file is actually in the media folder) but i don't have a clue how this is to be addressed.

 

Your paths are somehow screwed up. Maybe try them without a trailing '/'.

Link to comment
Share on other sites

How is that easier?

 

Everything works? It's one file at a time?

But I might have misread your post this morning -- you're using jd-plugin, not jd-gui, so you don't have to deal with every single class being decompiled into an unusable mess at once, right?

Link to comment
Share on other sites

 

I get this exception when debugging :

 

Aug 27, 2013 5:23:18 PM zombie.GameWindow initShared

SEVERE: null

java.lang.NullPointerException

at zombie.scripting.ScriptManager.LoadDirPP(ScriptManager.java:783)

at zombie.GameWindow.initShared(GameWindow.java:214)

at zombie.GameWindow.init(GameWindow.java:1362)

at zombie.GameWindow.maina(GameWindow.java:874)

at zombie.core.LaunchDialog.main(LaunchDialog.java:217)

 

Aug 27, 2013 5:23:19 PM zombie.GameWindow LoadTexturePack

SEVERE: null

java.io.FileNotFoundException: media/texturepacks/UI.pack (No such file or directory)

at java.io.FileInputStream.open(Native Method)

at java.io.FileInputStream.<init>(FileInputStream.java:138)

at java.io.FileInputStream.<init>(FileInputStream.java:97)

at zombie.GameWindow.LoadTexturePack(GameWindow.java:1195)

at zombie.GameWindow.initShared(GameWindow.java:233)

at zombie.GameWindow.init(GameWindow.java:1362)

at zombie.GameWindow.maina(GameWindow.java:874)

at zombie.core.LaunchDialog.main(LaunchDialog.java:217)

 

Aug 27, 2013 5:23:19 PM zombie.core.LaunchDialog main

SEVERE: null

java.io.FileNotFoundException: media/zombiefont2.fnt (No such file or directory)

at java.io.FileInputStream.open(Native Method)

at java.io.FileInputStream.<init>(FileInputStream.java:138)

at java.io.FileInputStream.<init>(FileInputStream.java:97)

at zombie.core.fonts.AngelCodeFont.<init>(AngelCodeFont.java:169)

at zombie.ui.TextManager.Init(TextManager.java:140)

at zombie.GameWindow.initShared(GameWindow.java:235)

at zombie.GameWindow.init(GameWindow.java:1362)

at zombie.GameWindow.maina(GameWindow.java:874)

at zombie.core.LaunchDialog.main(LaunchDialog.java:217)

 

Debug configuration :

 

-Djava.library.path="/media/ECC3-C3B0/Downloads/PZ/projectzomboid_LINUX/"

-Dorg.lwjgl.util.NoChecks=true

-Dorg.lwjgl.librarypath="/media/ECC3-C3B0/Downloads/PZ/projectzomboid_LINUX/"

-Xms768m

-Xmx768m

-XX:-UseSplitVerifier

where "/media/ECC3-C3B0/Downloads/PZ/projectzomboid_LINUX/" is the absolute path to the pz root folder (same as pzclasses folder right ?)

 

EDIT: and when i first robotically used {PATH_TO_PZCLASSES} it obviously said that the variable is undefined

 

The 'java.io.FileNotFoundException: media/zombiefont2.fnt (No such file or directory)' seems to indicate a problem with the paths (the file is actually in the media folder) but i don't have a clue how this is to be addressed.

 

Your paths are somehow screwed up. Maybe try them without a trailing '/'.

 

Thanks but same fate when i remove the trailing '/' or the double quotes. Will try other things later on.

Link to comment
Share on other sites

Aha! I forgot to mention that you had to set the working directory too. See 4.3 in the OP now.

Yippie ! Now stuck at the good old XInitThreads error.

Thanks again.

 

EDIT : Now working... sayonara windows !

EDIT2 : Note on the 'expressions' tab. If it's not present as a tab next to variables/breakpoints, the view can be opened via menu -> window -> show view -> expressions.

Link to comment
Share on other sites

So the xinitthreads call worked for you too?

Sir Yes Sir.  :wub:

Had to struggle with the overwhelming eclipse interface though...

 

And btw it's on a 32bit machine and i added the corresponding library (your libxx.so) for download to the "linux drives lemmy crazy" thread. Should be working for all distribs right ?

 

EDIT : And also i hope the mult core ithreading restrictions for linux that lemmy is referring to for the next update are not gonna prevent us from using your trick.

Link to comment
Share on other sites

Great, thanks for testing out this fix on your system! The fact that it works on two different platforms makes me confident that it is an actual fix and not just luck.

Don't tell me you typed random words in the lib source, run a random command that compiled it, installed random plugins in random eclipse and them randomly setup your random project, and randomly debugged it ?? Reminds of the tale about the ridiculous probablity for a monkey with a typewriter to write Hamlet.  :-) .

 

Hats off & looking forward to seeing an eggplant on pz contributors' screen.

See ya around for next optimization round !

Link to comment
Share on other sites

  • 1 year later...
  • 1 month later...

Update to Eggplanticus thread (thanks Eggplanticus I would not have been able to set-it up without you).

 

The following instructions are updated to today's Eclipse and Project Zomboid Build 32.5. 

 

I will try to keep them up to date.  Eggplanticus if you are still active please update your original post so that this is at the top.

 

The text in bold is from Eggplanticus the text not in bold  is the text I added.

 

 

In this thread I want to discuss how to peruse, and possibly debug the (decompiled) sources of pz. Please note that I do not in any way advocate copying or otherwise infringing upon the intellectual properties of the developers. This thread is mainly meant to help advanced users or programmers isolate problems in the code. Please note, I do not know how to recompile pz. I'm not sure it's even possible, given that decompiling doesn't always work correctly.

Browsing the code:
all that is required to browse the code is a Java decompiler. There is a freely available one called JD GUI on the Internet.

 

Debugging the code:
This is much more complicated. To debug the code you need the following tools:
1) Eclipse (java ide) 
https://eclipse.org/downloads/

or Netbean https://netbeans.org/downloads/ + JDK http://www.oracle.com/technetwork/java/javase/downloads/index.html

 

 

 

2) the JD-Eclipse plugin (java decompiler) http://java.decompiler.free.fr/

 

2)For Eclipse java decompiler: http://sourceforge.net/projects/jadclipse/

2.1)You also need the JAD.EXE: http://varaneckas.com/jad/

You can point to the JAD.EXE when you configure the plugin

 

2) For Netbean  java decompiler

 

3) the JDEclipse-realign plugin (allows debugging)  http://mchr3k.github...clipse-realign/  (still exist haven't used it yet)

 

Configuring the plugins:

You might need to go to window -> preferences -> general -> editors -> file associations -> *.class without source and set the default editor to the viewer with [decompiled] next to it in order for it to open .class files without problems. (I didn't have to do this step to get project zomboid started in debug mode but you might have to).

 

 

Configuring Eclipse:

 

1) Create a new java project called pz.

 

2) Create a new folder under the project

2.1) Parent folder: pz

2.2) Folder name: pz_classes

2.3) Click advanced -> link to alternate location -> browse -> select the folder which contains project zomboid on your computer  (note the location of that project zomboid folder - NOTE: I recommend you work with a new copy of the folder and not the one you normally play on, also backing up your project zomboid content under your user would be a good move if you care about your save files).

 

3)Go to project->properties->Java build path

3.1) Click add Jars: add the jinput, lwjgl, lwjgl_util jar files (these jar files are no longer enough has additional executable jar files were added)

You also need to select (not all of them might be required but it will work - I didn't have time to test yet which one is absolutely required and which on is not):

com.springsource.org.objectweb.asm_2.2.3

jbullet

lzma

uncommons-maths-1.2.3

 

The SQL JAR FILE might also be required.  I was able to start a game without adding it (NOTE:  I have also started the game with sqlite-jdbc-3.8.7 and it also seem to work so far). 

 

3.2) Click add class folder: select pz_classes folder

 

You can now browse the pz sources through eclipse, just by clicking on the class directories and look clicking on the class files.

 

Configuring the environment to run pz:

note: pz is run from the class zombie.core.LaunchDialog

 

4) Right-click LaunchDialog.class -> debug as -> debug configurations

 

Set up the pz environment variables

4.1) Click on the arguments tab

4.2) In the VM arguments box add the following lines (this is taken from the projectzomboid.sh file)

 

-Djava.library.path=${PATH_TO_PZCLASSES}

-Dorg.lwjgl.util.NoChecks=true
-Dorg.lwjgl.librarypath=${PATH_TO_PZCLASSES}
-Xms768m
-Xmx768m

 

 

 

${PATH_TO_PZCLASSES}  is actually the location of your projectzomboid work folder.

So for example if it is in C:\JAVA\PROJECT ZOMBOID,  you need to have

-Djava.library.path="C:\JAVA\PROJECT ZOMBOID"

 

4.3) Set the working directory (just below the vm arguments box) to "other", click Workspace, and select the pz directory as the working directory.

 

Again in the example above this would be "C:\JAVA\PROJECT ZOMBOID"

 

Congratulations, you can now run pz in the Eclipse debugger!

 

Just click the little bug-beetle thing to launch it. Remember, the file you want to run is LaunchDialog.class.

 

If pz crashes, if you're lucky, the debugger will stop on the exact (decompiled) source line where the crash occurs.

 

Debugging example:

This is not going to be a tutorial on debugging, since if you are doing this, you should probably know the basics already.  However since it's not possible to recompile the decompiled code, at least to my limited knowledge, sometimes debugging is not easy. So here is an example of how I did it:

 

 to test/debug/fix some issues I had with the 2.9.9.16 forum build crashing on linux, I had to do the following:

 

1) set a breakpoint at the first line of main() in LaunchDialog

2) In the expressions tab of the of the debugger (top-right window) I put in some java expressions I wanted to try: System.loadLibrary("xx");
 

3) run the debugger on LaunchDialog

4) the program will stop at the first line of main and the expression will be evaluated automatically

5) click the resume button to continue

 

So that's it. Easy, right?   (clyde)

 

Hope this help everyone new to project zomboid modding that wants to get started with Build 32.5 and explore the Java components and the order that the lua component are called.

 

***Added notes on JAD.EXE

 

***Removed color and added portion on NetBean (more to follow as I configure it)

Link to comment
Share on other sites

 

RAINBOW TEXT 

 

 

I have a headache and this text did not help it. 

 

You seem to be going in the right direction, however de-compiled code is virtually not perfect.

 

Although Eclipse is my choice to do Java work personally, some alternatives should be mentioned like NetBeans.

 

In my experience with reversing compiled code or libraries (even dis-assembly or attempt pseudo de-compilers), I would assume something does not work. I only assume that compiled .class files to be in working order.

 

For the majority of modders, I would assume that de-compiling code would be mostly for reference, as most of the things people want to do with the game is already doable through the lua interface provided.

 

For the remaining few, this would really only serve a few purposes: 

  • Adding support (E.G: Model loading, or tweaks to the core code).
  • General understanding of the mechanics of the game.
  • (Unfortunately) malicious and or harmful activity, although much rarer to deal with, thanks to the spike in modders over the past half-dozen years.

I would make a tutorial on this myself, however, I don't see a real desire for this. 

 

Realizing the interest in doing Java instead of Lua (Partially due to my bias as a Java nut) has made me consider writing a class-loader environment alternative to Lua, implementing the very same API Lua provides. 

 

It's hard writing a intermediate / advanced tutorial for modding. Java is way easier in comparison to C# de-compilers, or the all-mighty assembly modification methods to mod games. 

Link to comment
Share on other sites

Thanks for your input Jab.

 

I modified the post to use bold and non bold only and will add NetBean instructions.

 

I'm more a COBOL and Visual Basic programmer (along with REXX, CLIST, Assembler on Z/OS (mainframe)).   I'm working on becoming more knowledgeable in JAVA and LUA (for personal interest) so I want to work on creating mods for Project Zomboid (having some fun while learning it).

 

My main goal for the decompiling of class is for additional understanding of the code that might not be obvious through the LUA files or the project zomboid java documents.

 

I have no preference fro Eclipse or NetBean since they are both new to me but I will try both out and posts the instructions here.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...