Retera / WarsmashModEngine

An emulation engine to improve Warcraft III modding
GNU Affero General Public License v3.0
255 stars 45 forks source link

Running main methods for simple debugging or desktop-1.0.jar does not work by default #15

Open tdauth opened 2 years ago

tdauth commented 2 years ago

I wanted to run several main methods which would also be helpful for debugging.

I wanted to run MdxEditor.main and got:

Caused by: java.io.FileNotFoundException: warsmash.ini (Das System kann die angegebene Datei nicht finden)

which means that the file cannot be found in German. Maybe just log a warning and create default settings. The same for TerrainView.main.

If you need to load Warcraft III data just use the service registry to extract the installation path of Frozen Throne. If you need help with this just look at https://stackoverflow.com/questions/62289/read-write-to-windows-registry-using-java Java should be platform independent but on Windows you could automatically get the data with the service registry

Can you add an example warsmash.ini file to the README? I have no idea what the content should be. I found one in core.assets. You could link it in the README. It looks like you have to specify the MPQ files which can be done a lot easier using the service registry. I guess reading Reforged CASC archives is not an option yet?

When I run the DesktopLauncher.main method I get this error:

Execution failed for task ':desktop:DesktopLauncher.main()'.
> Process 'command 'C:/Users/Tamino/.jdks/corretto-1.8.0_332/bin/java.exe'' finished with non-zero exit value 1

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

building the project with the gradle task desktop:dist and then running the JAR does lead to no output:

java -jar desktop-1.0.jar

It was before I modified the file with 7z but after removing the duplicated file there is still no output and the program exits immediately. Removing the duplicated file "META-INF/services/javax.imageio.spi.ImageReaderSpi"" is really annoying. Is there any way to fix this?

I think overall it should be much easier to run Warsmash which would allow more people to use/debug/improve it.

Retera commented 2 years ago

Hi tdauth,

Maybe just log a warning and create default settings.

I see it as not feasible to generate a default settings. From 2012 to 2019 I was maintaining a Warcraft 3 modeling tool with this same problem and originally I would autodetect the registry and Warcraft III game like you are saying. Unfortunately due to a series of patches and the high volume of users who download disparate versions of the game that do not write the registry keys, plus more importantly the fact that Blizzard Entertainment stopped the game itself from writing these keys around the year 2018, when I upgraded my modeling tool with a GUI for users to choose the configuration that this INI file is based on, at that point users stopped sending me endless requests of unsolvable issues about corner cases in the autodetect for MPQs or CASC. In addition, those few users who do still ask me how to configure it can quickly be told whether to push the MPQ or CASC buttons in the GUI. Surely it would be nice in the future if Warsmash had a GUI for configuring the INI automatically similar to my other tool, but for the time being the INI gets it done for me.

With that in mind, there is a bit of a guide covering the format of these INI files here on the Warsmash subforum of the Hive Workshop: https://www.hiveworkshop.com/threads/overview-and-setup.331776/

So, speaking from my ten years of experience, it was just not easier to autodetect the location of this data based on the Registry. Warcraft III has too many versions and was not generally that consistent. I am also not sure what the future of Warcraft III as a game -- and how people get it -- will be, so in case there is some future where the game and its assets actually become no longer officially available, this problem would become even worse.

I do not know specifically why you are getting the "non-zero exit value" but this is a known issue on the current experimental branch. My solution was to make some desktop:runGame command or something like that on gradle because the old run command is getting overwritten by the runtime plugin that I was using for deployment, and it is overwritten with something that does not work because of the configurations currently necessary for this project.

When you run the desktop JAR and get no output, this is because unless you pass the "-nolog" argument, STDOUT and STDERR are piped to files in the "Logs" folder that gets generated, so that I can ask users to sent me these logs in the future so I can help them. But as a developer I usually run "-nolog" so that my IDE will just show me the STDOUT and STDERR directly. If you want to read the sourcecode of how the Warsmash "-nolog" argument works, you can see that in the DesktopLauncher.java file.

I think the experimental build might have a solution to fixing the "spi" thing. If it's not in there already, somebody solved it in a fork of my modeling tool with a JDK17 gradle version and some magic gradle compile flag, so we can probably copy that when we get there.

tdauth commented 2 years ago

Okay is there a global location where I could place one .ini file then which will be read by all main methods? How do you test the separate main methods? The guide could be linked in the README since I started from this repo and not Hive.

Are you saying that the output is written to log files? "-nolog" is passed by default? I simply executed the jar with the command in my first post without passing any extra arguments.

v4dkou commented 2 years ago

@Retera I am willing to develop a GUI for configuring Warsmash.

I propose adding a new class that inherits libGDX's Screen called WarsmashGdxConfigScreen and in DesktopLauncher.java use warsmashGdxMultiScreenGame.setScreen to show this GUI before launching the game itself.

WarsmashGdxConfigScreen would then return the DataTable, no matter where it got it (whether it's an INI file as it is now, or it's launched from a debugger as proposed by @tdauth) Hence loadWarsmashIni static method would be moved to WarsmashGdxConfigScreen.

On top of that, this GUI would make it easier for newcomers to try out Warsmash.

Thoughts/suggestions?

Retera commented 2 years ago

A wise developer, Ghostwolf, once told me that on a high level I was going about some of these types of things in the wrong way. The DataTable class, as well as the DataSourceDescriptor and DataSource interfaces created based off of it during startup were originally a 1:1 copy from my other repo: https://github.com/Retera/ReterasModelStudio/blob/master/craft3data/src/com/hiveworkshop/wc3/units/DataTable.java https://github.com/Retera/ReterasModelStudio/blob/master/craft3data/src/com/hiveworkshop/wc3/gui/datachooser/DataSource.java

I respect Ghostwolf's opinion for sure; he wrote the mdx-m3-viewer repo that Warsmash started as a direct copy of. Before disappearing into the sunset, he was quite convinced that Warsmash and the Retera Model Studio editor gui should share code from a third repo as a gradle dependency that would contain MDX/MDL model parsing logic. He might not have been as familiar with my DataSource and DataTable classes but surely the same logic would apply to those as well. This problem you have highlighted is another great example of how this stuff is an issue; basically the GUI that you are offering to write already exists in a different form as a Swing project here: https://github.com/Retera/ReterasModelStudio/blob/master/craft3data/src/com/hiveworkshop/wc3/gui/datachooser/DataSourceChooserPanel.java

Although this does not produce an INI file, it basically is just a few small code changes away from being an INI file editor for Warsmash's exact format. I guess in an ideological future this would be a part of a third repo of data tools or something and Warsmash would itself probably be the gameplay logic and render pipeline.

I think there might be some allure to having users who launch the application of Warsmash be immediately presented with the 3D game menu after it is all configured, but I know I also like to switch between "warsmash.ini" files which there is not a convenient mechanism for yet. What do you see as the reason for the tradeoff of making the config editor built into the LibGDX game instead of (for example) if we copied the swing GUI linked above and made that a second application that a user of Warsmash could run prior to launching the LibGDX game itself?

v4dkou commented 2 years ago

@Retera That Swing UI should work fine too!

The main reason I'd like that configuration GUI to run from the main desktop is to solve the issue of not being able to run Warsmash from debugger. @tdauth 's first proposed solution of looking up in Windows' registry wouldn't work for me, as I run Linux. (although it might be a great addition to the GUI)

How about adding a way to supply "working directory" to Warsmash (i.e. from Gradle), so that debugging could be done against specific copy of Warsmash installation (which could contain W3 assets and warsmash.ini)?

P.S. You should probably start an issue here about merging ReterasModelStudio and Warsmash repos so that people willing to contribute (like me) could track it and link PRs to it.

Retera commented 2 years ago

To be honest rather than to use IntelliJ, often I am an old timer and I edit this project using Eclipse with the ANTLR plugin. The Eclipse gradle integration creates an Eclipse project that still lets me enter whatever working directory I want, and lets me run from the debugger, despite otherwise copying its run information from the gradle build. But the Eclipse ANTLR stuff always wanted to use the wrong folder and I never bothered to figure how to fix that so for now part of my Eclipse project setup is manual, which is why i tell newcomers to just use IntelliJ.

So, I definitely use the debugger. But the working directory asset folder paradigm of LibGDX and my "DataSource" system of finding Warcraft 3 assets from an independent game install are somewhat at odds with each other. That's one reason running Warsmash on Android and other platforms that LibGDX supposedly supports would currently not work. My PC's "warsmash.ini" file has been in the repo in the LibGDX assets folder since day one, though, so it should be there as some form of example. I think the example might be out of date though, because I started ignoring it on git when I started moving more frequently between workstations with different War3 install locations.

Regarding the idea of a registry key lookup, that Swing GUI already does a registry lookup in an optional branch that can guide the user but is just empty on GNU/Linux last time I tested. So, if we make a wizard for Warsmash, that might be a good way to go -- letting the wizard suggest by Windows registry if available, but not require it.

So, there is kind of already a working directory idea inherited used for where to find the INI. But I guess I have been a little inefficient with that -- on my gaming PC I have about 8 or 10 "warsmash_XYZ.ini" files with different suffixes and I rename them to "warsmash.ini" when I want to use the game assets specified by that config. For example, I have the INI file for older War3 patches like 1.22 and 1.27, then another one that can target Reforged assets with those new graphics if I want to switch and play with those for a bit. But yeah making a way to specify INI path could improve that use case probably.

tdauth commented 1 year ago

I use Intellij and my custom warsmash.ini in the root project folder. The main issue is that there is no description in the README on how to debug/run warsmash after changing some code. This info could be added in a simplified way to the README in a section like "How tun Run from IDE":

I think this would really help many new users who want to create pull requests. Then there is no need for a GUI or installation detection etc. There were no checks for example if even the entry [Emulator] exists in the ini file, so the application just stopped without any output. I had some wrong entries in the .ini file which caused it stopping.

Now I get:

Caused by: java.lang.NullPointerException: Cannot invoke "com.etheller.interpreter.ast.function.JassFunction.call(java.util.List, com.etheller.interpreter.ast.scope.GlobalScope, com.etheller.interpreter.ast.scope.TriggerExecutionScope)" because the return value of "com.etheller.interpreter.ast.scope.GlobalScope.getFunctionByName(String)" is null

I will start a branch and pull request to add some info to the README which helped me to even run this method with the correct ini file.

Depending on your working directory you should also specify the resources directory with files like "resources/Icon16.png". They could not be found automatically.

Retera commented 1 year ago

A lot of the defaults are based on LibGDX. Generally, LibGDX would always have an assets folder which is commonly in core/ so it ends up with core/assets. If you just use the generic LibGDX gradle project generator to make a new game, that's the way it is setup by default.

Rather than to use the LibGDX resource resolution system, to save time (and better support the emulation of Warcraft III style map imports) I dumped in the Retera Model Studio resource resolution pipeline, which runs separately and finds assets in its own way. So, the LibGDX resource system is expecting us to run from the IDE with core/assets as the working directory, but Warsmash is expecting the current working directory to have a file warsmash.ini that dictates where to find MPQs or Folders of Warcraft III style assets.

Typically default LibGDX gradle projects have a run target to run them, but because I was using the "badass runtime plugin" to automatically handle JPackage stuff and package the game into a release, it is possible to use runGame from gradle to run with all of these directories specified in the manner they should be.

So when I clone this repo to a new computer, I do not have the issues you listed above as long as I follow the simple rule of erasing whatever was in "core/assets/warsmash.ini" and setting up that file with computer-specific information about how to find Warcraft III assets. After doing that, I can run "./gradlew runGmae" from a command line or from IntelliJ's "Gradle Task" icon, and then the game works instantly. When doing it this way, I do not experience issues with the JASS loader failing and I do not need to specify the main class name DesktopLauncher to anything.

Retera commented 1 year ago

Apologies, the issue was unintentionally closed and has been reopened.