Error with messages in JMonkey Networking

So i was trying to do a Networking project using JMonkey. I followed the networking tutorial to pass messages (String) from the client to the server and vice versa and there was no problem. Then however when I tried to make my own version of it and send a Geometry the program stops. I believe everything is exactly the same as when I sent the String.

I read a few other questions where they had a very similar problem and they solved it apparently by registering the class with serializer and so I checked and i cannot see any problem with what I am doing, could anyone please help??

The code where it crashes is this:

[Client myClient;
@Override
public void simpleInitApp() {
try {
myClient = Network.connectToServer(“localhost”, 6143);
myClient.start();
ClientListener listener = new ClientListener(rootNode);
Serializer.registerClass(HelloMessage.class);
myClient.addMessageListener(listener, HelloMessage.class);
Serializer.registerClass(GeomPos.class);
myClient.addMessageListener(listener, GeomPos.class);

    Message message = new HelloMessage("Hello World!");
    myClient.send(message);
} catch (IOException ex) {
    Logger.getLogger(ClientMain.class.getName()).log(Level.SEVERE, null, ex);
}
flyCam.setEnabled(false);

// You must add a light to make the model visible
DirectionalLight sun = new DirectionalLight();
sun.setDirection(new Vector3f(-0.1f, -0.7f, -1.0f));
rootNode.addLight(sun);

assetManager.registerLocator("town.zip", ZipLocator.class);
Spatial gameLevel = assetManager.loadModel("main.scene");
gameLevel.setLocalTranslation(0, -5.2f, 0);
gameLevel.setLocalScale(2);
rootNode.attachChild(gameLevel);


Box b = new Box(1, 1, 1);
geom = new Geometry("Box", b);

Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.setColor("Color", ColorRGBA.Blue);
geom.setMaterial(mat);
geom.setLocalTranslation(0.0f, -3.80f, 0.0f);
rootNode.attachChild(geom);
Message msg = new GeomPos(geom);
myClient.send(msg); //This is the line where it crashes<--------------------------

initKeys();      

}]

Finally this is the GeomPos Message class:

[package mygame;

import com.jme3.network.AbstractMessage;
import com.jme3.network.serializing.Serializable;
import com.jme3.scene.Geometry;

@Serializable
public class GeomPos extends AbstractMessage{

private Geometry geom;

public GeomPos() {
}

public GeomPos(Geometry g) {
geom = g;
}

public Geometry getGeometry() {
return geom;
}

}]

[/java]

I get the following error:

INFO: Audio max auxilary sends: 4 May 17, 2014 11:50:29 PM com.jme3.app.Application handleError SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main] java.lang.RuntimeException: Error serializing message

Random things:

  1. send() will never throw an exception because the actual sending is done on another thread. If you want to listen for errors then you should register an error listener.

  2. Exceptions are one step away from useless without the full stack trace… but ESPECIALLY without the root cause.

  3. Geometry is not serializable so I’m surprised it even let you register your GeomPos class at all.

  4. Sending raw Geometry objects to the clients is a bad idea. You should be sending game objects and not view objects.

1 Like
@pspeed said: Random things: 1) send() will never throw an exception because the actual sending is done on another thread. If you want to listen for errors then you should register an error listener.
  1. Exceptions are one step away from useless without the full stack trace… but ESPECIALLY without the root cause.

  2. Geometry is not serializable so I’m surprised it even let you register your GeomPos class at all.

  3. Sending raw Geometry objects to the clients is a bad idea. You should be sending game objects and not view objects.

Thank you for your quick response. I’m sorry I am a noob here but could you tell me what makes an object serializable. I mean what’s the difference between a String and a Geometry? Also what would be the correct way to keep track of different player positions of different clients?
I thought i could just send the geometries and keep all the data I needed in the server including position angle, etc.

Once again, Thank you.

1 Like

If you need to send position, angle, etc… then send position, angle, etc… The Geometry will contain a TON more data than you need.

Serializable means that it’s been marked with the @Serializable annotation (like your message class) or has been specifically registered with the serializer. Many things like String and Vector3f are already pre-registered.

1 Like
@pspeed said: If you need to send position, angle, etc... then send position, angle, etc.. The Geometry will contain a _TON_ more data than you need.

Serializable means that it’s been marked with the @Serializable annotation (like your message class) or has been specifically registered with the serializer. Many things like String and Vector3f are already pre-registered.

So to register a new class I made I would just need to do the following:

[java]
@Serializable
public class MyClass
{
// member vars…
// member funcs…
}
[/java]

Again thank you for your response it was very enlightening

@AnIrony said: So to register a new class I made I would just need to do the following:

[java]
@Serializable
public class MyClass
{
// member vars…
// member funcs…
}
[/java]

Again thank you for your response it was very enlightening

You need that and to register it as you have in your previous code sample. You were registering your own message type just fine but nothing was registering Geometry… and that’s good because you shouldn’t be sending Geometry.

A word of advice: if you’ve never finished a single player game before then I highly recommend putting off networking if possible. It complicates things 100-fold (easily) and if you don’t yet have an idea of how to clearly separate game objects from view objects then it becomes even trickier to get right. These kinds of things are easier to work out in a single player game.

1 Like
@pspeed said: You need that and to register it as you have in your previous code sample. You were registering your own message type just fine but nothing was registering Geometry... and that's good because you shouldn't be sending Geometry.

A word of advice: if you’ve never finished a single player game before then I highly recommend putting off networking if possible. It complicates things 100-fold (easily) and if you don’t yet have an idea of how to clearly separate game objects from view objects then it becomes even trickier to get right. These kinds of things are easier to work out in a single player game.

What i mean is if i want my message to send a class I made, say class Player which has the members Vector3f position and String name. How can i make the message class accept the Player class so that it can send it. I can send the Vector3f and String variables if I have them declared directly in the message but not if they are inside another class.

[java]

public class Player
{
public Vector3f position;
public String name;
}

@Serializable
public class PlayerMessage extends AbstractMessage{
private Player aPlayer; //This way it won’t let me send the message
// Constructors, methods, etc
}

[/java]

So the question is what do I do to make PlayerMessage send Player objects?

I know I am bothering you a lot with these perhaps silly questions and I agree with you networking is very complicated and complicates the whole thing but I need to do this for a class I’m taking.
I don’t know if what I am trying to do is possible or not but if you help me with this that will be enough for me to keep going.

Once again,

Thank you very much

The same way you did for the message. The serializer doesn’t know what a message is… it only knows classes.

1 Like
@pspeed said: The same way you did for the message. The serializer doesn't know what a message is... it only knows classes.

Oh! Thanks! It works now. I didn’t understand from your previous comment that not only messages but also my own non-message classes should be registered by the serializer to be able to send them. My bad =/.

Adding this line made it work properly.

Serializer.registerClass(Player.class);

I know you might get mad because of my sloppiness but I really appreciate all the patience and help you gave me.

Thank you so much

If it was marked @Serializable then it should have been automatically registered when the message class was registered.

Note: serializer registration must be EXACTLY THE SAME on client and server. Same order, same classes, everything. So it’s usually a good idea to register them in some static utility method that both client and server share.

1 Like
@pspeed said: If it was marked @Serializable then it should have been automatically registered when the message class was registered.

Note: serializer registration must be EXACTLY THE SAME on client and server. Same order, same classes, everything. So it’s usually a good idea to register them in some static utility method that both client and server share.

I’ll keep that in mind seems like a good rule of thumb, however it was not automatically registered. I don’t know what happened there exactly but everything was solved by registering it manually. Is there anywhere I can find all serializable classes? Like how do I know if Maps are serializable for instance besides trial and error

@AnIrony said: I'll keep that in mind seems like a good rule of thumb, however it was not automatically registered. I don't know what happened there exactly but everything was solved by registering it manually. Is there anywhere I can find all serializable classes? Like how do I know if Maps are serializable for instance besides trial and error

The source code is available online or in the IDE. You can see it all.

1 Like