(Solved) Calling SimpleApplication.start( JmeContext.Type ) always makes the application headless?

The title pretty much says it all.



When I use start() everything goes fine, when I use start( JmeContext.Type.Display ) all hell brakes loose, spamming “SEVERE: Uncaught exception thrown in Thread[Headless Application Thread,5,main]” like no tomorrow.



It looks like calling start() with a JmeContext.Type value makes the server headless, no matter what JmeContext.Type you use.

just tried it, and it worked fine. Are you instantiating the right app in your main call?

Hmmm… by overriding start() and start(JmeContext.Type) I somehow bugged it.



This is what caused the bug:

[java]

@Override

public void start()

{

JmeContextType = JmeContext.Type.Display;



Logger.getLogger( “” ).setLevel( Level.SEVERE );

AppSettings newSettings = new AppSettings( false );

// change settings

setSettings( newSettings );



super.start();

}

@Override

public void start( JmeContext.Type type )

{

JmeContextType = type;



Logger.getLogger( “” ).setLevel( Level.SEVERE );

AppSettings newSettings = new AppSettings( false );

// change settings

setSettings( newSettings );



super.start( type );

}

[/java]



I guess the server is headless before super.start() has been called, which caused the exception.



Anyway, so I changed it to this:

[java]

@Override

public void start()

{

JmeContextType = JmeContext.Type.Display;



Logger.getLogger( “” ).setLevel( Level.SEVERE );



super.start();



AppSettings newSettings = new AppSettings( false );

// change settings

setSettings( newSettings );

}

@Override

public void start( JmeContext.Type type )

{

JmeContextType = type;



Logger.getLogger( “” ).setLevel( Level.SEVERE );



super.start( type );



AppSettings newSettings = new AppSettings( false );

// change settings

setSettings( newSettings );

}

[/java]



But now flyCam is null (which is normal when the application is headless),

can you figure out what I’m doing wrong here? Removing the AppSettings code fixes the bug, why?

@patrickvane1993 said:
But now flyCam is null (which is normal when the application is headless),
can you figure out what I'm doing wrong here? Removing the AppSettings code fixes the bug, why?


We need to see more code. How are you instantiating your SimpleApplication subclass? Does it have its own constructor?

I’ll strip some code, gimme a couple minutes.

Yeah, a simple test case that we could all try and you have verified still fails would be best of all.

Here you go:



Main.java

[java]package client;



import com.jme3.system.AppSettings;

import java.util.logging.Level;

import java.util.logging.Logger;





public class Main extends ImprovedApplication

{

private static Main instance;





public static Main sharedInstance()

{

if( instance == null )

instance = new Main();

return instance;

}





@Override

public void setup( AppSettings settings )

{

settings.setTitle( "My Title" );

settings.setFrameRate( 0 );

}





@Override

public void simpleInitApp()

{

flyCam.setEnabled( false );

}





public static void main( String[] args )

{

Logger.getLogger( "" ).setLevel( Level.SEVERE );

Main.sharedInstance().start();

}

}

[/java]



ImprovedApplication.java

[java]package client;



import com.jme3.app.SimpleApplication;

import com.jme3.system.AppSettings;

import com.jme3.system.JmeContext;





public abstract class ImprovedApplication extends SimpleApplication

{

@Override

public void start()

{

AppSettings newSettings = new AppSettings( false );

setup( newSettings );

setSettings( newSettings );



super.start();

}



@Override

public void start( JmeContext.Type type )

{

AppSettings newSettings = new AppSettings( false );

setup( newSettings );

setSettings( newSettings );



super.start( type );

}



public abstract void setup( AppSettings settings );

}

[/java]

flyCam isn’t setup until after simpleInit because it was moved to an app state. If you don’t want a fly cam then you can remove the app state… or just not include it (using the special SimpleApplication constructor).

Ah ok, thanks

Ehm, but then I got another question. How can I change the flycam’s movement speed to 20f? What’s the best way to do it?

Actually, looking at the code, I’m wrong.



As long as SimpleApplication still has the FlyCamAppState registered then there will be a flyCam by the time simpleInit() is called.



…unless input is disabled for some reason. If input is disabled then no flyCam will be created before simpleInit()… but if input is disabled then flyCam has no purpose.

I don’t have time to trace through the SimpleApplication code in a debugger right now… but if you are so inclined then you may figure out why things aren’t working.

Well, by commenting this line:

[java]setSettings( newSettings );[/java]

it will work fine, but whereever I put the 3 lines (in start() or in simpleInitApp()), it somehow causes the flyCam to become null.



The only way to fix it, is to put it in simpleInitApp(), then use the existing settings variable (instead of creating a new AppSettings object) and then call restart().

But why? Why does creating a new AppSettings object and setting it as the settings causes a bug?

For extra clearance, here is the working code (altho this restarts the app, causing the frame to disappear and reappear).



Main.java

[java]package client;



import com.jme3.system.AppSettings;

import java.util.logging.Level;

import java.util.logging.Logger;





public class Main extends ImprovedApplication

{

private static Main instance;





public static Main sharedInstance()

{

if( instance == null )

instance = new Main();

return instance;

}





@Override

public void setup( AppSettings settings )

{

settings.setTitle( "My Title" );

settings.setFrameRate( 0 );

}





@Override

public void simpleInitApp()

{

setup( settings ); // <-- hotfix

restart(); // <-- hotfix



flyCam.setMoveSpeed( 20f );

}





public static void main( String[] args )

{

Logger.getLogger( "" ).setLevel( Level.SEVERE );

Main.sharedInstance().start();

}

}

[/java]



ImprovedApplication.java

[java]package client;



import com.jme3.app.SimpleApplication;

import com.jme3.system.AppSettings;

import com.jme3.system.JmeContext;





public abstract class ImprovedApplication extends SimpleApplication

{

@Override

public void start()

{

//AppSettings newSettings = new AppSettings( false );

//setup( newSettings );

//setSettings( newSettings );



super.start();

}



@Override

public void start( JmeContext.Type type )

{

//AppSettings newSettings = new AppSettings( false );

//setup( newSettings );

//setSettings( newSettings );



super.start( type );

}



public abstract void setup( AppSettings settings );

}

[/java]

You are constructing AppSettings with no defaults (passing false):

[java]AppSettings newSettings = new AppSettings( false );[/java]

This will default to a null renderer (i.e. newSettings.getRenderer() returns null, and so a NullContext and NullRenderer implementation ends up being used). Try adding:

[java]newSettings.setRenderer(AppSettings.LWJGL_OPENGL2);[/java]

Or else pass true when you create AppSettings, and reset any defaults you don’t like.

2 Likes
@rectalogic said:
You are constructing AppSettings with no defaults (passing false):
[java]AppSettings newSettings = new AppSettings( false );[/java]
This will default to a null renderer (i.e. newSettings.getRenderer() returns null, and so a NullContext and NullRenderer implementation ends up being used). Try adding:
[java]newSettings.setRenderer(AppSettings.LWJGL_OPENGL2);[/java]
Or else pass true when you create AppSettings, and reset any defaults you don't like.


I think this is incorrect.

This is Mythruna's startup sequence:
[java]
MainStart app = new MainStart();

app.setPauseOnLostFocus(false);

BufferedImage[] icons = new BufferedImage[] {
ImageIO.read( MainStart.class.getResource( "globe-128.png" ) ),
ImageIO.read( MainStart.class.getResource( "globe-32.png" ) ),
ImageIO.read( MainStart.class.getResource( "globe-16.png" ) )
};

AppSettings settings = new AppSettings(false);
settings.setTitle( "Mythruna RCG v0.1" );
settings.setSettingsDialogImage( "/Interface/mythruna-title.png" );
settings.setIcons(icons);

if( ClientOptions.getInstance().isFirstTime() ) {
settings.setWidth( 1280 );
settings.setHeight( 720 );
ClientOptions.getInstance().setFirstTime(false);
ClientOptions.getInstance().save();
}

app.setSettings( settings );
app.start();
[/java]

I left it complete just in case there is some magic that I do that makes it work.

Passing true makes it use defaults over any preferences saved... false is a very common thing to pass.

setRendered() didn’t fix the problem, but giving true instead of false to the constructor did!



Thanks.