How to handle saving settings

Hello, I’m about to refactor my launcher to take cli args and save/load settings, but after reading the docs on this, I’m unsure how to handle it.

Where the AppSettings doc says:

 Set this parameter to false if you want the application to load user settings from previous launches.

and

The settings are saved based on the title of your game

makes me think that settings are saved and loaded in the background by jme3, but the docs don’t mention that (other than that line).

So my question is, should I be saving the AppSettings like a regular object or does jme3 handle saving and loading AppSettings for us?

To add, if the settings save/load is handled by jme3, how is that done when I need an instance of AppSettings to set the title on?

There is a weird relationship between setting load defaults to true and app settings auto-loading and being able to preset your own stuff when not already set by the user previously.

I’ve found the best general pattern is what I do in the main method in the example in this comment:

Reproduced here with less context:

    public static void main( String... args ) throws Exception {

        Main main = new Main();
        AppSettings settings = new AppSettings(true);

        // Set some defaults that will get overwritten if
        // there were previously saved settings from the last time the user
        // ran.
        settings.setWidth(1280);
        settings.setHeight(720);
        settings.setVSync(true);

        String title = "MyApp";
        settings.load(title);
        settings.setTitle(title);

        settings.setUseJoysticks(true);

        main.setSettings(settings);

        main.start();
    }

new AppSettings(true) will have app settings fill in values with default values.

Then you can set any that you want different defaults for (common one is screen resolution because default is 640x480 or something). And any other app settings setup.

Then specifically load the previous settings using the app title.

The settings dialog will automatically save any changes the user makes.

2 Likes

Much appreciated!

That is an interesting relationship!

This brings another question to mind though:

Say I want to implement a custom settings dialog, say in a Settings screen that can be navigated to via the main menu. Do I have to save the settings myself after the user applies them (say an apply button that calls app.restart())? Or is that handled automatically?

I’m thinking, as an example, of the apply button in the settings screen:

(Button source) -> {
    settings.save(title); // is this needed? 
    app.restart();
}

I think it’s the settings dialog that saves the settings… but I’d have to look at the code to see. Or you could look.

1 Like

I’ll take a look for you, you’ve already done so much :smile:
I’ll put what I find back here for completeness

So, from my digging around in showSettingsDialog, I found that the settings dialog doesn’t save settings, and rummaging around in setSettings shows the same. So it seems that settings aren’t saved by jme3 (from what I can tell).

But in my tests, I found that settings are not saved by default, so manual saving is necessary.

More interestingly though, I’ve found that settings managed by the dialog are not honored, even if the dialog is not displayed. I tested this theory using set/get BitsPerPixel.
With a default of 24, I set BitsPerPixel to 16 before the app is started, and retrieve the value back in simpleInitApp only to get 24 back. Setting it to 16 in simpleInitApp and calling app.restart applies the setting as expected.
This may have to do with the behavior of defaults and the defaults that the dialog sets, but even if the dialog is displayed and 16 is selected, the dialog remebers 16 but the default still seems to be 24.

Summary of my findings:

  • Jme3 does not save settings by default.
  • Settings must be saved manually, using a preferences key (usually the title) , or OutputStream
  • The settings dialog is confusing

I’ll try to make a minimal example of saving settings to complete this thread.

It definitely does. Note that your application title must match exactly (exactly) the string you used to save the settings or you won’t be able to load them back again and it will look like they weren’t saved.

Yes.

I’d need to see code. It shouldn’t be the case.

Note: some modes won’t let you set 16 bits per pixel anyway. So your test may already be flawed.

1 Like

Here is a test you can run to prove what I’m saying. Use the code I gave for app startup.

Change the size to something different in the settings dialog. Note that the window will be a different size.

Run the app again and note that it remembers the size you selected.

Comment out the settings.load() line from my example and run again. Note that it will flop back to the defaults set.

It might be that I have been running my app under the default title, and have recently changed it to my games name

The settings dialog sets (and remembers) 16 b/p, so I think it’s supported

Here’s the code I tested with:


import com.jme3.app.SimpleApplication;
import com.jme3.system.AppSettings;
import java.util.prefs.BackingStoreException;

public class Test extends SimpleApplication {
    public static void main( String... args ) throws BackingStoreException {
        AppSettings settings = new AppSettings(true);
        System.out.println("BPP [default] : "+settings.getBitsPerPixel());
        settings.setBitsPerPixel(16);
        System.out.println("BPP [set] : "+settings.getBitsPerPixel());
        settings.load("Test");
        settings.setTitle("Test");
        Test main = new Test();
//        main.setShowSettings(false);
        main.setSettings(settings);
        main.start();
    }        
    
    @Override
    public void simpleInitApp() {
        System.out.println("BPP [live] : "+settings.getBitsPerPixel());
        stop();
    } 
}

Run it once to allow the settings dialog to show, set it as b/p to 24, then it run. Output for me was:

... // unrelated output
BPP [default]: 24
BPP [set]: 16
... // unrelated output
BPP [live]: 24

as expected. Then uncomment main.setShowSettings(false); and run again. Even without the settings dialog running, the output is still:

... // unrelated output
BPP [default]: 24
BPP [set]: 16
... // unrelated output
BPP [live]: 24

I feel that I have a critical lack of understanding here

Why do you think those two things are related?

On modern Windows, I think it’s essentially impossible to really set anything other than 24 bits per pixel in windowed mode.

That worked as expected. I’m clearly lacking some vital information here, I’m gonna go play around with some tests so I can get a better understanding of this

I had just thought that since putting 16 in the dialog and the app reporting the setting as 16 during runtime, that it was the mode in use

I did not know that, thank you for the info! I really don’t know much about that setting, I honestly picked a random one from the dialog and setting a int to 16 or 24 seemed easy enough to check, sorry about that!