Hey monkeys,
I’m currently working on a multiplayer-Game and everything seemed to work fine… until yesterday evening:
when I start my server and connect clients to him random client windows close. example:
start client
connect player1
connect player2
connect player3 → player1 closes down
there is no System behind the client shutting down like ‘every 3rd client kicks the first connected’. Whenever i connect another client 0-3 other windows close down.
the closing window throws the following error:
Aug 13, 2012 4:56:24 PM com.jme3.app.Application handleError
Schwerwiegend: Uncaught exception thrown in Thread[LWJGL Renderer Thread,6,main]
java.lang.IllegalStateException: Scene graph is not properly updated for rendering.
State was changed after rootNode.updateGeometricState() call.
Make sure you do not modify the scene from another thread!
Problem spatial name: bubblehead-ogremesh
at com.jme3.scene.Spatial.checkCulling(Spatial.java:260)
at com.jme3.renderer.RenderManager.renderScene(RenderManager.java:636)
at com.jme3.renderer.RenderManager.renderScene(RenderManager.java:654)
at com.jme3.renderer.RenderManager.renderScene(RenderManager.java:654)
at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:965)
at com.jme3.renderer.RenderManager.render(RenderManager.java:1016)
at com.jme3.app.SimpleApplication.update(SimpleApplication.java:251)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:151)
at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:184)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:228)
at java.lang.Thread.run(Thread.java:722)
Aug 13, 2012 4:56:24 PM com.jme3.renderer.lwjgl.LwjglRenderer cleanup
Information: Deleting objects and invalidating state
AL lib: ReleaseALC: 1 device not closed
BUILD SUCCESSFUL (total time: 31 seconds)
I’m pretty much sure that theres a problem with how i add the new connected players to the game. currently it works as followed:
client recieves locationDatas(playerId/location/direction/…) from the server. and passes them on to my updatePlayerList method:
[java] public void updatePlayerList(LocationData datas){
if(multiplayerData[datas.getPlayerId()]==null&&datas.getPlayerId()!=client.getId()){
System.out.println(“new player”);
players[datas.getPlayerId()]=player2.clone();
playerNode.attachChild(players[datas.getPlayerId()]);
}
multiplayerData[datas.getPlayerId()]=datas;
}[/java](if the client ‘knows’ the player the multiplayerData[] is updated(this is the array where i store all players locations etc), otherwise a new player is attached to the playerNode, which is attached to the rootNode. I used an Spatial[] named players to make moving arround players more easy.)
another problem i faced was: How to add a new Player to the game the right way?
as you see i just made an array for all players. When a player logs in, he gets his own position in the array depending on his login id. But when a player logs out and in again he gets a new id. Since i want my server to run all day long the array would grow…and grow…and grow. since IDs are not reused and a lot of useless data will be stored on the server. (ehm…seems like I’m loosing track, sorry)
how did/would you, dear monkeys, manage adding/removing players/espacially spatials to the scene?
I would take a look at the wiki section about callables and multi-threading. I don’t think you can modify the scene graph from another thread directly.
See this thread, the same solution will solve your issue.
http://hub.jmonkeyengine.org/groups/physics/forum/topic/concurrentmodificationexception-1/
ty a lot. I’ll have a look at it
again thanks a lot. thou i have no idea, what exactly I’ve done here its working now:
i turned
[java]public void updatePlayerList(LocationData datas){
if(multiplayerData[datas.getPlayerId()]==null&&datas.getPlayerId()!=client.getId()){
System.out.println(“new player”);
players[datas.getPlayerId()]=player2.clone();
playerNode.attachChild(players[datas.getPlayerId()]);
}
multiplayerData[datas.getPlayerId()]=datas;
}[/java]
into
[java] public void updatePlayerList(final LocationData datas){
if(multiplayerData[datas.getPlayerId()]==null&&datas.getPlayerId()!=client.getId()){
System.out.println(“new player”);
players[datas.getPlayerId()]=player2.clone();
app.enqueue(new Callable<Void>() {
public Void call() throws Exception {
playerNode.attachChild(players[datas.getPlayerId()]);
throw new UnsupportedOperationException(“Not supported yet.”);
}
});
}
multiplayerData[datas.getPlayerId()]=datas;
}[/java]
again. i have no idea if this is the way u wanted me/acx234(the guy on the other topic) to solve the problem BUT it’s working
let me tell you what i think it’s doing and them please tell me wether I’m right or wrong:
before:
i tried tu just add a Spatial to the rootNode/playerNode and this made the program stuck since he was rendering and suddenly had to render 1 mode object but since he already started rendering he gets an error
now:
i enqueue the action of adding the spatial so it’s added when the new frame(?!?) is about to be rendered//new loop starts
however. why do I have to throw an exception and what kind of exception should i throw?
(ty again)
feels like I’m getting beaten up from you guys with those multithreading-stuff i should probably put my project to rest for a day or two and care about the almighty multithreading
thanks so far