Nifty Change Screen Error?

Hey all, my client applet runs fine until it tries to switch screens.
The server-client works fine from the SDK itself.
I can’t figure out where this error is coming from at all, it only mentions nifty (but like I said this bug only appears on the applet).

I am using:
Product Version: jMonkeyEngine SDK 3.0RC2
3.0.0.10449 External Libraries Nightly
3.0.0.10462 Libraries Nightly
Java: 1.6.0_22; Java HotSpot™ Server VM 17.1-b03
System: Windows 7 version 6.1 running on x86; Cp1252; en_GB (jmonkeyplatform)
3.0.0.10216.2 Nifty GUI (nightly)

The following error is what is returned.
[java]
Exception in thread “LWJGL Renderer Thread” java.lang.NullPointerException
at java.util.logging.Logger.doSetParent(Unknown Source)
at java.util.logging.Logger.getAnonymousLogger(Unknown Source)
at java.util.logging.Logger.getAnonymousLogger(Unknown Source)
at de.lessvoid.nifty.screen.Screen$EndScreenEndNotify.perform(Screen.java:678)
at de.lessvoid.nifty.screen.Screen$LocalEndNotify.perform(Screen.java:638)
at de.lessvoid.nifty.elements.Element$LocalEndNotify.perform(Element.java:1957)
at de.lessvoid.nifty.elements.Element$LocalEndNotify.perform(Element.java:1957)
at de.lessvoid.nifty.effects.EffectProcessorImpl.checkFinish(EffectProcessorImpl.java:339)
at de.lessvoid.nifty.effects.EffectProcessorImpl.renderActive(EffectProcessorImpl.java:315)
at de.lessvoid.nifty.effects.EffectProcessorImpl.renderPre(EffectProcessorImpl.java:62)
at de.lessvoid.nifty.effects.EffectManager$RenderPhasePre.render(EffectManager.java:301)
at de.lessvoid.nifty.effects.EffectManager.renderInternal(EffectManager.java:163)
at de.lessvoid.nifty.effects.EffectManager.renderPre(EffectManager.java:150)
at de.lessvoid.nifty.elements.Element.render(Element.java:718)
at de.lessvoid.nifty.elements.Element.renderInternalChildElements(Element.java:751)
at de.lessvoid.nifty.elements.Element.renderChildren(Element.java:744)
at de.lessvoid.nifty.elements.Element.render(Element.java:713)
at de.lessvoid.nifty.screen.Screen.renderLayers(Screen.java:314)
at de.lessvoid.nifty.Nifty.render(Nifty.java:321)
at com.jme3.niftygui.NiftyJmeDisplay.postQueue(NiftyJmeDisplay.java:178)
at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:979)
at com.jme3.renderer.RenderManager.render(RenderManager.java:1035)
at com.jme3.app.SimpleApplication.update(SimpleApplication.java:252)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:151)
at com.jme3.system.lwjgl.LwjglCanvas.runLoop(LwjglCanvas.java:229)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:228)
at java.lang.Thread.run(Unknown Source)
[/java]

How the change screen is called (all binding and nifty xml stuff is done at project startup).
[java]app.enqueue(new Callable() {
public Void call() throws Exception {
nifty.gotoScreen(“lobby”);
Main.state=State.LOBBY;
return null;
}
});[/java]

The xml for the nifty can be seen here:
http://facelessgames.com/niftyscreens.txt
Is this something caused by the nifty nightly build or something else entirely.
Just to expand a little. This error started occurring after updating my Java version. Could this cause nifty issues?
All the best.

I would never use that method of calling gotoscreen. It’s outside of the mainthread.
When I create a new object or initiate something that nothing else is dealing with (not even the renderer) then I use call() method.
But if u want to gotoscreen you must time it with the mainthread imo.
Try like this:
[java]public class GameFinish extends AbstractAppState{
public GameFinish(){
MainGame.getState().attach(this);
}

public void update(float tpf){
	MainGame.getState().detach(this);

nifty.gotoScreen(“lobby”);
Main.state=State.LOBBY;
}
}[/java]
It will gotoscreen in the nearest frame possible. To call it, simply do:
[java]
app.enqueue(new Callable() {
public Void call() throws Exception {
new GameFinish();
return null;
}
});
[/java]

This is what I think would solve the problem, but maybe theres other, better, options that I don’t know of…

You are right about the app.enque @addez but I’ve no idea where you are doing with the GameFinish bit.

All he needs is
[java]
app.enqueue(new Callable() {
public Object call() throws Exception {
nifty.gotoScreen(“lobby”);
Main.state=State.LOBBY;
return null;
}
});
[/java]

1 Like

o_O

Why do you create an app state just to remove it? Baby kittens are crying.

I’m glad people vote me down every time I try to help.
Makes me even more eager to contribute to this forum and it’s people.

@Addez said: I'm glad people vote me down every time I try to help. Makes me even more eager to contribute to this forum and it's people.

I didn’t vote you down but on the other hand I’d be hard pressed to come up with a more misleading response than your code. I’m trying to be as nice as possible.

First, you use an app state to do what a Callable already does. Then you instantiate a callable to add the app state when adding app states is already thread safe.

Not only that, your very first sentence: “I would never use that method of calling gotoscreen. It’s outside of the mainthread.”

…is completely incorrect.

So I can understand why someone might down vote you. The desire to help is not always the same as being helpful… and in this case, it was the opposite of being helpful. People attempting to follow your advice would actually be worse off than when they started.

To the OP, it seems like something is messed up with the Java logging setup. Are you manually messing with the logging hierarchy or removing loggers or something weird?

I don’t really know what can cause this error inside of JUL.

1 Like

I see.
Well, not that I want to highjack this thread or anything, but I’v tried to add models into the rootnode using this call() method, and it doesn’t work.
It only works if I do it my way so I don’t understand how this “call” method can be threadsafe…

@Addez said: I see. Well, not that I want to highjack this thread or anything, but I'v tried to add models into the rootnode using this call() method, and it doesn't work. It only works if I do it my way so I don't understand how this "call" method can be threadsafe..

Using app.enqueue( Callable) runs the Callable on the render thread… the EXACT same thread that would be running your app state.

So if it didn’t work then something else was wrong.

Your way also delays the execution by one frame. So maybe something else in your code wasn’t setup properly but a frame later was. Usually that’s a sign of lots of bad things happening, ie: other constructs like this that are delaying things extra frames for no reason.

app.enqueue() will cause the Callable to be run at the beginning of the next frame. stateManager.attach() will cause the state to be initialized and updated on the next frame. So enqueuing a callable to attach the state will be delayed by two whole frames.

And if you are using a state to emulate a callable then it is completely unnecessary to use the callable in the first place. If that also failed then I’m quite sure it was because you were depending on something elsewhere in your application that was also delayed by a frame. At any rate, it was sign of potentially bad practices elsewhere and not a problem with JME’s preferred approaches.

I’m the one voted you down, and it was nothing personal but when a post contains completely wrong/misleading advice then the -1 on it warns people to read on before using it.

I can promise you that app.enqueue already solves your threading issues. Rather than continuing the hijack on this one though if you start a new thread with the issues you are having I’m sure I and others would be happy to take a look…

Hey all, thanks for the support.
I’ve replaced all calls of gotoScreen for all parts of my nifty gui with:

[java]app.enqueue(new Callable() {
public Object call() throws Exception {
nifty.gotoScreen(“lobby”);
Main.state=State.LOBBY;
return null;
}
});[/java]

However I am repeatedly getting the same error. I’ve tried this on multiple screen changeovers and it always comes up with the same error. Possibly something to do with my gui setup?

Here’s how I init my screens and attach them to the stateManager:
[java] nifty.registerScreenController(startscreen);
nifty.registerScreenController(lobbyscreen);
nifty.registerScreenController(newuserscreen);
nifty.registerScreenController(playscreen);
nifty.addXml(“Interface/Nifty/gameStart.xml”);
nifty.addXml(“Interface/Nifty/gameLobby.xml”);
nifty.addXml(“Interface/Nifty/newUser.xml”);
nifty.addXml(“Interface/Nifty/gamePlay.xml”);

    startscreen.bind(nifty, nifty.getScreen("start"));    
    lobbyscreen.bind(nifty, nifty.getScreen("lobby"));
    newuserscreen.bind(nifty, nifty.getScreen("newuser"));
    playscreen.bind(nifty, nifty.getScreen("play"));
    
    stateManager.attach(playscreen);
    stateManager.attach(lobbyscreen);[/java] 

and an example of one of the screen classes:
[java]
import Client.Main;
import Client.Messages.LoginMessage;
import com.jme3.app.Application;
import com.jme3.app.state.AbstractAppState;
import com.jme3.app.state.AppStateManager;
import com.jme3.input.InputManager;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import de.lessvoid.nifty.Nifty;
import de.lessvoid.nifty.controls.Label;
import de.lessvoid.nifty.controls.TextField;
import de.lessvoid.nifty.screen.Screen;
import de.lessvoid.nifty.screen.ScreenController;
import java.util.concurrent.Callable;

public class startScreen extends AbstractAppState implements ScreenController {

private Nifty nifty;
private Screen screen;
private Main app;
private String usr, pas;
InputManager inputManager;

public startScreen(Main _app) {
    this.app = _app;
    this.inputManager=app.getInputManager();
    inputManager.addMapping("Go", new KeyTrigger(KeyInput.KEY_RETURN));
    inputManager.addListener(actionListener, "Go");
}

 @Override
public void initialize(AppStateManager stateManager, Application app) {
    super.initialize(stateManager, app);
}

public void bind(Nifty nifty, Screen screen) {
    this.nifty = nifty;
    this.screen = screen;
}

public void onStartScreen() {
}

public void login() {
        usr = nifty.getCurrentScreen().findNiftyControl("Username", TextField.class).getText();
        pas = nifty.getCurrentScreen().findNiftyControl("Password", TextField.class).getText();
        app.client.send(new LoginMessage(usr, pas));
}

public void printmessage(String msg) {
    nifty.getCurrentScreen().findNiftyControl("Message", Label.class).setText(msg);
}

public void printservermessage(String msg) {
    nifty.getCurrentScreen().findNiftyControl("ServerMessage", Label.class).setText(msg);
}

public void createuser() {
    if(app.client!=null)
    {
                          app.enqueue(new Callable() {
                public Object call() throws Exception {
            nifty.gotoScreen("newuser");
            return null;}});
    }

}

public String getuser() {
    return usr;
}

public String getpass() {
    return pas;
}

public void onEndScreen() {
}

public Screen getScreen() {
    return screen;
}

public void quitGame() {
    app.stop();
}

private ActionListener actionListener = new ActionListener() {
    public void onAction(String name, boolean keyPressed, float tpf) {
        if (name.equals("Go") && keyPressed) {
            if (app.client != null) {
                login();
            }
        }
    }
};

@Override
public void update(float tpf) {
    /**
     * jME update loop!
     */
}

}
[/java]

Screens are also manipulated by the listener I have setup on client side, if this makes any difference.
Just to remind everyone that this is working absolutely fine within the SDK, its just the applet that is playing up.

Video shows explanation of the bug.

Best regards.
[video]http://www.youtube.com/watch?v=m-o6xz57nsk&feature=youtu.be[/video]

To the OP, it seems like something is messed up with the Java logging setup. Are you manually messing with the logging hierarchy or removing loggers or something weird?

I don’t really know what can cause this error inside of JUL.

Hey all, when you mentioned the logger I started looking at code not to do with the game but to do with the actual applet setup in the simpleInitApp function. I managed to fix the problem. Basically, so that it would work in an applet I was calling:
[java] System.setSecurityManager(null); [/java]

This is what was causing the Null value exception. After removing this and signing the applet as normal, the issue is now gone and the applet works fine.

Thanks so much for all the help. Thumbed up you guys.