JMonkey Initializer - Creating a dynamic Gradle temple to start a project from

What is it
In Getting started in JMonkeyEngine - #11 by richtea we were discussing the possibility of a JMonkey Initialiser. Similar to the Spring Initialzr to produce a dynamically generated “starter template” as a zip to make Gradle based development less scary for newcomers.

I have created a prototype of this project hosted at jmeinitializer.onemillionworlds.com and the source for it is at GitHub - richardTingle/jmeinitializer (The template with merge fields is at jmeinitializer/src/main/resources/jmetemplate at master · richardTingle/jmeinitializer · GitHub).

What’s it based on

Its a spring boot application with a react front end

What does it do

It asks the user what their game will be called, their package name and what libraries they want to use. They then select to download that starter project and are given a zip. That zip contains a main class with their game name, a build.gradle file with all the libraries they asked for and all the other “stuff” that means it should just open in the IDE of their choice with no “rename this” and “change that” that a static template might have.

It also keeps track of the most recent stable versions of libraries from search.maven.org so it will always offer the most recent stable version of a library.

What’s still to do

Obviously I’ve not includes as many libraries as we might want, I’ve just included enough to prove the concept. Equally the ones I’ve chosen as the “ticked by default” are not necessarily the right ones (And I didn’t really know what some of the libraries were for so my descriptions might be a bit off).

In particular there is no Lemur library option. This is because Lemur is (I think) still on jcentre and so I can’t get its version with a search to search.maven.org. I wanted lemur to be the default gui library so this isn’t ideal. Possible option is to hard code the version for jcentre libraries and accept that it will have to be manually updated from time to time for these. (Although as I think jcentre is swiftly shutting up shop this issue may soon come to a head).

I’ve created a react front end that the prototype itself serves, but possibly it makes sense for this to just be the backend and the front end to be part of https://jmonkeyengine.org?

There’s also a question; if you include log4j2 should you get a starter log4j2.xlm in the project? Should other libraries be “set up” (Could get complicated).

What might still be to do

I’ve used in browser compilation for react, this isn’t “best practice”, mostly I think because its slow, but I only have a little sprinkling of react, so maybe its fine. I await harsh criticism

Disclaimer
For the avoidance of doubt I imagine both the JMonkey Initialiser itself and the repo for it being in JMonkey world, I’ve put it up at jmeinitializer.onemillionworlds.com solely to demo the prototype (and I’ll take it down again at some point)

What next
I guess I’m looking to get some feedback on if this is a useful idea in the first instance. And if it is what’s the next steps to get it in official JMonkey world

16 Likes

Hello @richtea that would be a great work, just a note on the UI, a jme game could be a multiple platform game, the radiobuttons have to be checkboxes, so as if a user wants to have the desktop & android/iOS dependences together.

And BTW I have intentions to build a cross platform testcase template using gradle (Android + PC), I will release it on the forum soon.

4 Likes

That’s very nice. Is it possible to show the gradle file before downloading the archive?

4 Likes

Jcenter said they will host libraries indefinitely. So it will so far only “come to a head” when I need to make another release. (Probably take me 3-4 solid days of effort to convert all of my projects to a newer gradle, wrestle with the poop that is maven central, etc…)

In the mean time, I wonder if there is a way to get the release information from git.

2 Likes

Ah excellent! Then theres no problem. I’ll hard code lemur’s version as a “fallback version” but have it search maven central as well; if a version turns up there it will start using it, until then it will use the hard coded version.

1 Like

A preview build.gradle should be very doable. I’ll have a play

1 Like

Nice job

As mentioned by others, a multiplatform project would be much appreciated. (Android + PC for the moment, AFAIK iOS build is not possible currently with Gradle and requires the JME SDK)

In case it helps you can take a look at these templates:

I think there should be 3 subprojects:
-android
-desktop
-game // holds game logic and is shared with android and desktop

But I have no idea how assets are handled in Android.

2 Likes

Is there a way to provide a template for a new library to you app?
Eg. let’s say i can add to the store an endpoint that outputs a template for any library published there, would it be possible to have the app pull from that?

1 Like

That sounds doable. What exactly would the template be template as in actual java code? I’m thinking having multiple libraries selected, if each has it’s own template how do they get merged? Or do you just mean; name, description text, maven coordinate

1 Like

i was just thinking about maven coordinates,maybe also a java file that gets included into an example folder, but this last thing is unnecessary, so forget that if it is annoying to implement or makes the code ugly.
Where do you store the libraries coordinates in the current app?

1 Like

That’s a good idea! And not difficult to implement at all. I’d probably want an endpoint that outputted something like this:

[
  {
     "displayName":"Particle Monkey",
     "groupId":"com.github.Jeddic",
     "artifacts":[
         {
            "artifactId":"particlemonkey",
            "fallbackVersion": "1.0.2"
     ],
     "category":"GENERAL",
     "description":"Particle Monkey is a more modern particle system with better artistic controls."
  },
  {
     ... next library....
  }
]

Json is something I can easily parse but I’m open to any sensible format. (The fallbackVersion would only be necessary for things I couldn’t get from mavencentral)

ArtifactId is an array as some things (e.g. lemur) have multiple artifacts.

If the we wanted a single example class either it could be embedded in the json as an extra key, say exampleTemplate. Although how many libraries are there? The size could get big quickly, might be better to make a rest call per library to get the template? Especially if templates are allowed to have multiple classes (which also wouldn’t be difficult)

Its worth noting that for my existing libraries I have a regex for each one to decide what a “release” version is (e.g. for jMonkey its anything that ends “-stable”). For these I’d need to just use “only numbers and dots”.

I’ve currently got these categories:

  • JME_PLATFORM (currently allows only 1, but discussion here suggest should allow multiple; may need to have different GameName.java for different platforms and multimodule for multiplatform)
  • JME_GENERAL (allows multiple select, uses the jmonkeyengineVersion)
  • PHYSICS (only 1 allowed)
  • GUI (Only 1 allowed)
  • NETWORKING (Only 1 allowed)
  • GENERAL (allows multiple select)

Ok that’s perfect. I am working to a new set of apis, there will be a list api that accept a search query and returns a list of unique ids for each entry, and then a get api that can be called to get the relevant infos for each entry, we can select the categories using tags in the search query. I’ll work to something that can resemble the output you proposed.

2 Likes

Based on the feedback here (and just stuff I wanted to do) I’ve made the following changes:

build.gradle preview

As requested, the initializer will now produce a preview of the build.gradle file

This may not be possible for multi platform (and therefor multi module) projects, as then there will be multiple build.gradles

Move towards pulling (some) libraries from jmonkey store

I’ve changed libraries from being an enum to being a record, which should make obtaining libraries from an API endpoint easy

Fallback versions

I can now set a fallback version on each library, so libraries not yet on maven central can be used. This also means I’ve added lemur to the list of libraries.

Log4j.xml

No one really asked for this, but I’ve included a log4j2.xml in the template if the log4j2 library is included. I did this because of my own painful experience that the log4j documentation suggests a very games unfriendly logging pattern; including the line number of the logging statement. Which produces lovely logs, but is brutally slow. My template doesn’t use expensive things

I’ve done this in a generic way that would make other “library specific” files possible in the template. (This is separate from the examples package suggested by RiccardoBlb, which would come from the jmonkey store itself)

Still to come

Multiplatform/Multimodule projects; this is not something I’ve played with myself so I’ll have to have an explore

4 Likes

Nice Work !

The multiplatform module consists of the project(root module) build.gradle and each platform module contains its own build.gradle, the one with the root module has the repositories (so may be we don’t need a preview for this), the other two modules (android/desktop) contains a build.gradle similar to the one in this image(so that may need a split screen to preview the desktop and android together.

I have spent along time working on a good CrossPlatform module that contains a self building scripts for both android and desktop, here is the repository, the gradle is preconfigured for android build & i have added desktop jar building task :

EDIT :
Sorry, i forgot there is a 3rd module called :game that would hold the game code & it would be included within the :desktop & :app modules.

2 Likes

Ooo, very useful. With your permission I’ll take heavy inspiration from that

3 Likes

Having been distracted by other things for a couple of months I’ve now returned to this. I’ve added multi-module and “real” android support to the initialiser.

With plain projects (not including any of the 3rd party libraries, just JME stuff) both the Android, Desktop and [Android and Desktop multi-module] projects all seem to work fine immediately from creation (desktop launchers launch in IntelliJ, Android apps get installed and launched from Android studio).

I don’t have much android experience (the android template is heavily based on what @Paul_G provided) so if anyone was able to check they are reasonable that would be very much appreciated.

One point where I did deviate from Paul_G’s template was that I used the AndroidHarness rather than doing the set up myself as that seemed simpler. But I’m happy to be told that was wrong.

Problems/questions/thoughts

Android errors with third party libraries

If the user selects any third party libraries they immediately get errors like:

Duplicate class com.google.common.util.concurrent.ListenableFuture found in modules jetified-guava-19.0 (com.google.guava:guava:19.0) and jetified-listenablefuture-1.0 (com.google.guava:listenablefuture:1.0)

Or

2 files found with path 'META-INF/DEPENDENCIES'.

Is that a normal android thing I just can’t do anything about or am I doing something wrong in the templating? It feels like I’m not going to be able to do the kind of "if X then Y stuff I’d need to do to make it happy dynamically.

app/src/res files

Paul_G’s android template had a lot of files in app/src/res that I’ve left in but I have no idea what they are for, should I be leaving them in?

JME_VR

With my own personal interest in VR I’m definitely going to include a VR template, but I’m going to wait till action based openVR is in to create one.

JME_IOS

I don’t exactly understand how to use this and have no way to test it. So I’m just not going to worry about it for now.

Assistance

If anyone has any comments on the templates (or anything) I’d very much appreciate it, either here, or if people are feeling particularly helpful as PRs against the repo at GitHub - richardTingle/jmeinitializer

2 Likes

May I suggest not adding log4j by default? Please consider using Logback as the default option.

1 Like

Ah, I should have made that clearer. I only include a log4j2.xml if log4j2 is selected as a required library

Including Logback as an option is a good suggestion though

3 Likes

Oh cool! Thanks for clarifying. :slight_smile:

Hi Richard, nice work !

The android template is good (I have not tested yet but quick look on it on the gradle preview).

About the third parties, you may the add the option of an exclusion dialog that would enable the user to exclude the selected third parties (if any has been selected) to be excluded on a specific platform (the user should learn by himself what should be excluded on other OSes based on the libraries provided by the OS SDK in this case the android SDK).

The files in the res are the android resources files (android assets including images, svgs, XML layout files), there should be some default generated resources for each fresh new android project like the one generated from android studio, the one on my repo are somehow trivial, they contain the layout XML, I am using in the screens posted on the repo, so if you are using a very basic android project (AndroidHarness activity) without using any layout or assets, you can add the default res folder generated by any new android project from android studio.

Also, your desktop template already supports Pi without touching any gradle thing, if we are going to use lwjgl3.2.3 from the jme side, otherwise we would need to add another section for Pi or armhf devices !

One more thing, I will be available to test jme-Initializer in 2 more weeks, I will let you know if there are more things I have discovered.

Thanks for your great tool !!