Serializer Problem

I am pretty sure this is a noob question, but i have followed the video tutorial on the tutorial page on how to connect a client and a server.

When i start my own project, i get this :

[java]SEVERE: Uncaught exception thrown in Thread[Headless Application Thread,5,main]

java.lang.RuntimeException: Error serializing message

at com.jme3.network.base.MessageProtocol.messageToBuffer(MessageProtocol.java:82)

at com.jme3.network.base.DefaultServer.broadcast(DefaultServer.java:201)

at Client.Client.update(Client.java:57)

at Client.Objects.update(Objects.java:24)

at Room.MainLand.update(MainLand.java:36)

at Engine.Main.simpleUpdate(Main.java:38)

at com.jme3.app.SimpleApplication.update(SimpleApplication.java:241)

at com.jme3.system.NullContext.run(NullContext.java:131)

at java.lang.Thread.run(Thread.java:722)

Caused by: com.jme3.network.serializing.SerializerException: Error writing object for field:private com.jme3.math.Vector3f Utility.UtNetworking$Player_PosDirMsg.direction

at com.jme3.network.serializing.serializers.FieldSerializer.writeObject(FieldSerializer.java:181)

at com.jme3.network.serializing.Serializer.writeClassAndObject(Serializer.java:392)

at com.jme3.network.base.MessageProtocol.messageToBuffer(MessageProtocol.java:74)

… 8 more

Caused by: java.lang.NullPointerException

at com.jme3.network.serializing.serializers.Vector3Serializer.writeObject(Vector3Serializer.java:24)

at com.jme3.network.serializing.serializers.FieldSerializer.writeObject(FieldSerializer.java:174)

… 10 more[/java]

Whenever i want to send any package, and i know i called the Serializer method :

[java]public class UtNetworking {

public static final int PORT = 6020;



public static void initializeSerializer() {

Serializer.registerClass(UtNetworking.Others_PosDirMsg.class);

Serializer.registerClass(UtNetworking.Player_PosDirMsg.class);

Serializer.registerClass(UtNetworking.Player_RequestToMove.class);

}



@Serializable

public static class Others_PosDirMsg extends AbstractMessage {



private Vector3f position, direction;

private int ID;

private String message;



public Others_PosDirMsg() {}



public Others_PosDirMsg(String msg, Vector3f pos, int id) {

position = pos; ID = id; message = msg;

} public Others_PosDirMsg(String msg, Vector3f pos, Vector3f dir, int id) {

position = pos; direction = dir; ID = id; message = msg;

}



public Vector3f getPosition() { return position; }

public Vector3f getDirection() { return direction; }

public int getID() { return ID; }

public String getMessage() { return message; }

}



@Serializable

public static class Player_PosDirMsg extends AbstractMessage {



private Vector3f position, direction;

private String message;



public Player_PosDirMsg() {}



public Player_PosDirMsg(String msg, Vector3f pos) {

position = pos; message = msg;

} public Player_PosDirMsg(String msg, Vector3f pos, Vector3f dir) {

position = pos; direction = dir; message = msg;

}



public Vector3f getPosition() { return position; }

public Vector3f getDirection() { return direction; }

public String getMessage() { return message; }

}



@Serializable

public static class Player_RequestToMove extends AbstractMessage {

private boolean right, left, jump;

private int ID;



public Player_RequestToMove() {}



public Player_RequestToMove(boolean r, boolean l, boolean j, int id) {

right = r; left = l; jump = j; ID = id;

}



public boolean isRight() { return right; }

public boolean isLeft() { return left; }

public boolean isJump() { return jump; }

public int getId() { return ID; }





}

}

[/java]



Any help, tip, info will be greatly appreciated.

The person who wrote the Vector3f serializer didn’t take nulls into account and the Serializer system does not handle nulls on its own.



Unfortunately, fixing it now will break applications that don’t upgrade their clients and servers at the same time. So for now you cannot have Vector3f fields that are null. So always make sure to set them to some value.

I have another problem :

[java]public void getKeyBoardInput(String name, boolean pressed, float tpf) {

if(name.equals("Left") && l != pressed) {

room.main.network.client.send(new Player_RequestToMove(false,pressed,false,ID));

} else if(name.equals("Right") && r != pressed) {

room.main.network.client.send(new Player_RequestToMove(pressed,false,false,ID));

} else if(name.equals("Jump")) {

room.main.network.client.send(new Player_RequestToMove(false,false,pressed,ID));

}

}[/java]

This sends a message if i click or unclick,

But when i close my client, the server is still receiving messages

@mathieu-roux222 said:
I have another problem :
[java]public void getKeyBoardInput(String name, boolean pressed, float tpf) {
if(name.equals("Left") && l != pressed) {
room.main.network.client.send(new Player_RequestToMove(false,pressed,false,ID));
} else if(name.equals("Right") && r != pressed) {
room.main.network.client.send(new Player_RequestToMove(pressed,false,false,ID));
} else if(name.equals("Jump")) {
room.main.network.client.send(new Player_RequestToMove(false,false,pressed,ID));
}
}[/java]
This sends a message if i click or unclick,
But when i close my client, the server is still receiving messages


Then your client is still running because the SpiderMonkey network connection wasn't properly closed.

thanks

I got a big porblem : Whenever i send this to the server :

[java]System.out.println("LEFT " + movement[0] + " RIGHT " + movement[1] + " JUMP " + movement[2]);

main.Network.client.send(new Player_ChangeDirection(ID, player.getPhysicsLocation(), dir, movement));[/java]

[java]@Serializable

public static class Player_ChangeDirection extends AbstractMessage {

private Vector3f position;

private int ID, direction;

private final boolean[] movement;



public Player_ChangeDirection() { movement = new boolean[3]; }



public Player_ChangeDirection(int id, Vector3f p, int dir, boolean movement[] ) {

position = p;

direction = dir;

ID = id;

this.movement = movement;

}



public int getId() { return ID; }

public Vector3f getPosition() { return position; }

public int getDirection() { return direction; }

public boolean[] getMovement() { return movement; }

}[/java]

It output : LEFT true RIGHT false JUMP false.

But on the server :

[java]if(m instanceof Player_ChangeDirection) {

final Player_ChangeDirection msg = (Player_ChangeDirection) m;



room.main.enqueue(new Callable() {



public Object call() throws Exception {

room.object.getPlayer(msg.getId()).setMovement(msg.getDirection()

, msg.getPosition(), msg.getMovement());

server.broadcast(Filters.notEqualTo(Connection_Listener.getHC(msg.getId())),

msg);

System.out.println("LEFT " + msg.getMovement()[0] + " RIGHT " + msg.getMovement()[1] + " JUMP " + msg.getMovement()[2]);

return null;

}



});[/java]

It output : LEFT false RIGHT false JUMP true

I know that the UtNetwork class is the same for the server and client, but when i send a value from the client to the server it isnt the same.

Any suggestions? Thanks

Maybe don’t make the field final.



Edit: Actually, it’s getting true from somewhere so I’m not sure what’s going on but it’s still odd to have the field final.

I need the field final so i can use it in the [java]public Object call() throws Exception {}[/java]

It looks like Left turns into Jump

Also, move the receive-side System.out.println() to right after you cast the message (before the Callable even) to eliminate that it’s setMovement() or something else that’s changing the value after it gets read.

Server : LEFT false RIGHT false JUMP false

Client : LEFT true RIGHT false JUMP false

It is really weird.

Fixed it :P, i just needed to remove the [java]final[/java] of the [java]boolean[] movement[/java]

But why does it change the data? Final makes it so it dont change the value, i put it there for security purpose

… well the object has to be created on the receiver side …

it is, the server creates the class [java]Player_ChangeDirection[/java] wich the server receive, and the both class on both client and server is the same, and i know it is being created.

Network layer creates the empty object. Network layer then sets the fields. I think it ignores final fields so that an exception isn’t thrown when it tries to set them maybe… anyway, usually final fields are meant not to be set after creation.



If you are worried about setting them later then you must be mixing game objects and network messages… which is pretty bad design, actually.



The thing that really confuses me is how you ended up with a “true” in there in the first example. Something must have been setting it to true. Actually, I think when arrays are final then you just can’t reset the reference to the array but you can still reset the values in the array… so it doesn’t really help keep you safe anyway.

@mathieu-roux222 said:
it is, the server creates the class [java]Player_ChangeDirection[/java] wich the server receive, and the both class on both client and server is the same, and i know it is being created.


Heh.. this is not like quantum physics and some entangled atoms ;) Theres no magic happening, the object still has to be created on the receiver side.

Sorry, i ment "it is created on the clien side, then the server receive it with [java]if( m instance Player_ChangeDirection)[/java].

Thanks for the answer pspeed :slight_smile:

Bu aniway problem solved so thanks to all!

@mathieu-roux222 said:
Sorry, i ment "it is created on the clien side, then the server receive it with [java]if( m instance Player_ChangeDirection)[/java].


And our point was that it didn't just magically appear on the server. The networking code had to create the object and set its fields.

Hopefully it all makes sense now.

Yes it does now thanks anyway :slight_smile: