How to serialize an ArrayList<CustomObject>?

Hi! I’m here again!! This time i need help to serialize my player inventory, i would love to send it via Client to the server, then, the server would attach it to the ServerDataManager.

this is my code:

public class PlayerInventory {
private int id;

private Objeto casco;
private Objeto armadura;
private Objeto cinturon;
private Objeto piernas;
private Objeto botas;
private Objeto ArmaPrimaria;
private Objeto ArmaSecundaria;

//private ArrayList<Objeto> mochila = new ArrayList();

If I send that arrayList, my client just crashes, any ideas to solve this issue?
Thanks!

Crashes = your computer blew up? The OS blue screened? A core dump?

So many millions of possibilities… should we try to answer them one by one or can we have a hint?

We need more code! Furthermore we have to less information.

Is “Objeto” a serialized object at all?
What do you actually send? An object of the “PlayerInventory” class?

Crash was not the proper word to say: i get this error on client:
Grave: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]
java.lang.RuntimeException: Error serializing message
at com.jme3.network.base.MessageProtocol.messageToBuffer(MessageProtocol.java:81)
at com.jme3.network.base.DefaultClient.send(DefaultClient.java:237)
at com.jme3.network.base.DefaultClient.send(DefaultClient.java:207)
at mygame.ClientMain.simpleUpdate(ClientMain.java:81)
at com.jme3.app.SimpleApplication.update(SimpleApplication.java:242)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:151)
at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:185)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:228)
at java.lang.Thread.run(Thread.java:744)
Caused by: com.jme3.network.serializing.SerializerException: Error writing object for field:private mygame.PlayerInventory mygame.messages.PlayerInventoryMessage.playerInventory
at com.jme3.network.serializing.serializers.FieldSerializer.writeObject(FieldSerializer.java:180)
at com.jme3.network.serializing.Serializer.writeClassAndObject(Serializer.java:389)
at com.jme3.network.base.MessageProtocol.messageToBuffer(MessageProtocol.java:73)
… 8 more
Caused by: com.jme3.network.serializing.SerializerException: Error writing object for field:private mygame.Objeto mygame.PlayerInventory.armaPrimaria
at com.jme3.network.serializing.serializers.FieldSerializer.writeObject(FieldSerializer.java:180)
at com.jme3.network.serializing.Serializer.writeClassAndObject(Serializer.java:389)
at com.jme3.network.serializing.serializers.FieldSerializer.writeObject(FieldSerializer.java:175)
… 10 more
Caused by: java.lang.IllegalArgumentException: Class has not been registered:class mygame.Objeto
at com.jme3.network.serializing.Serializer.getSerializerRegistration(Serializer.java:324)
at com.jme3.network.serializing.Serializer.getSerializerRegistration(Serializer.java:293)
at com.jme3.network.serializing.Serializer.writeClass(Serializer.java:368)
at com.jme3.network.serializing.Serializer.writeClassAndObject(Serializer.java:388)
at com.jme3.network.serializing.serializers.FieldSerializer.writeObject(FieldSerializer.java:175)
… 12 more

on my PlayerInventory.java:
@Serializable
public class PlayerInventory {
private int id;

private Objeto casco = new Objeto();
private Objeto armadura;
private Objeto cinturon;
private Objeto piernas;
private Objeto botas;
private Objeto armaPrimaria;
private Objeto armaSecundaria;

private ArrayList<Objeto> mochila = new ArrayList();

public PlayerInventory(){}

public PlayerInventory(int id){
    this.id = id;
}
@Override
public String toString(){
    return "Casco: "+casco.getName()+"\n Armadura: "+armadura.getName()+"\n Cinturon: "+cinturon.getName()+
           "\n Piernas: "+piernas.getName()+ "\n Botas: "+botas.getName()+"\n Arma Primaria: "+armaPrimaria.getName()+
            "\n Arma Secundaria: "+armaSecundaria.getName();
}

my class Objeto:

@Serializable
public class Objeto {
private final String name;
private float masa;
private final int valor;
private Spatial spatial;

private RigidBodyControl RGB;

public Objeto(){
    name = " - ";
    masa = 0.1f;
    valor = 0;
    spatial = new Geometry(" - ",new Box (1,1,1));
}


public Objeto (String n,int v,float m){
    name = n;
    valor = v;
    masa = m;
    spatial = new Geometry(" - ",new Box (1,1,1));
}

my PlayerInventoryMessage.java:
@Serializable
public class PlayerInventoryMessage extends AbstractMessage{

private PlayerInventory playerInventory;

public PlayerInventoryMessage(){}

public PlayerInventoryMessage(PlayerInventory playerInventory){
    this.playerInventory = playerInventory;
}

and finally, the error comes from the client here:

@Override
public void simpleUpdate(float tpf){
if (client.isConnected()){
client.send(new PlayerDataMessage(playerData));
client.send(new PlayerInventoryMessage(playerInventory));
System.out.println(playerInventory.toString());
}
}

I mean… the error is right there. You didn’t register that class as being serializable.

And this post is at the top of the forum… sticky:

I already arranged that error, didn’t remember to put Objeto as @Serializable, anyway getting more errors :frowning:
Grave: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]
java.lang.RuntimeException: Error serializing message
at com.jme3.network.base.MessageProtocol.messageToBuffer(MessageProtocol.java:81)
at com.jme3.network.base.DefaultClient.send(DefaultClient.java:237)
at com.jme3.network.base.DefaultClient.send(DefaultClient.java:207)
at mygame.ClientMain.simpleUpdate(ClientMain.java:81)
at com.jme3.app.SimpleApplication.update(SimpleApplication.java:242)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:151)
at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:185)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:228)
at java.lang.Thread.run(Thread.java:744)
Caused by: com.jme3.network.serializing.SerializerException: Error writing object for field:private mygame.PlayerInventory mygame.messages.PlayerInventoryMessage.playerInventory
at com.jme3.network.serializing.serializers.FieldSerializer.writeObject(FieldSerializer.java:180)
at com.jme3.network.serializing.Serializer.writeClassAndObject(Serializer.java:389)
at com.jme3.network.base.MessageProtocol.messageToBuffer(MessageProtocol.java:73)
… 8 more
Caused by: com.jme3.network.serializing.SerializerException: Error writing object for field:private mygame.Objeto mygame.PlayerInventory.armaPrimaria
at com.jme3.network.serializing.serializers.FieldSerializer.writeObject(FieldSerializer.java:180)
at com.jme3.network.serializing.Serializer.writeClassAndObject(Serializer.java:389)
at com.jme3.network.serializing.serializers.FieldSerializer.writeObject(FieldSerializer.java:175)
… 10 more
Caused by: com.jme3.network.serializing.SerializerException: Error writing object for field:private com.jme3.scene.Spatial mygame.Objeto.spatial
at com.jme3.network.serializing.serializers.FieldSerializer.writeObject(FieldSerializer.java:180)
at com.jme3.network.serializing.Serializer.writeClassAndObject(Serializer.java:389)
at com.jme3.network.serializing.serializers.FieldSerializer.writeObject(FieldSerializer.java:175)
… 12 more
Caused by: java.lang.IllegalArgumentException: Class has not been registered:class com.jme3.scene.Geometry
at com.jme3.network.serializing.Serializer.getSerializerRegistration(Serializer.java:324)
at com.jme3.network.serializing.Serializer.getSerializerRegistration(Serializer.java:293)
at com.jme3.network.serializing.Serializer.writeClass(Serializer.java:368)
at com.jme3.network.serializing.Serializer.writeClassAndObject(Serializer.java:388)
at com.jme3.network.serializing.serializers.FieldSerializer.writeObject(FieldSerializer.java:175)
… 14 more

So i went on the forum and saw this old post:

I’ll try to refix this and post my results

The only problem you have is : you are trying to mix everything in a really poor design. Your Objeto is a data class + a visualisation class + a physic class …networked classes are just data ! You should NEVER NEVER send anything else over the network.

And if i can add one more thing, sending the player inventory each frame is not a really good idea too…you will have a bad time as soon as you will have more than one player connected :wink:

:slight_smile: Maybe he’s trying to make a game where it’s really easy to cheat. :slight_smile:

…sorry… couldn’t resist.

Client authoritative is a bad idea in general.

Okay! Thank you for your counsel! I’m going to subdivide my class in more java classes, then I’ll just send the data. So i won’t send the inventory all the time, I’ll be thinking when I’ll need to send it

I suppose, but this is my first networked game, just getting some ideas to improve it, I would love to put this server sided, but I can’t find some good tutorials, i saw a lot of them that were already deleted from svn like monkey zone and others.
No problemo, I like jokes :stuck_out_tongue:

That’s a good start. In fact you don’t need to send anything each frame except if you have a real time game where you sync position/rotation (and it should be server side controlled as pspeed said). Then you have to think of an event system based…you only need to send playerinventory when it has changed (item added/removed etc…), you will send player shoot, only when player press your mouse button right?

@pspeed lol, maybe :wink:

And for the tuts part, pspeed has done some good tutorials for networked based applications, based on entity systems (which is a really good architecture for decoupling data from visuals, you should give it a look). Search for monkey trap for entity system example and i don’t remember the other example with the networking think with spaceship but i’m pretty sure paul will link it :stuck_out_tongue:

@Tennya

This is a very good networking example for jme :

SimEthereal is high performance network library for jme integrated with jMonkeyEngine’s SpiderMonkey networking library.

You will find this example in two version: sim-eth-basic , sim-eth-es.
First one is the way you should start with. In the next level if you want to base your game design on Entity Component System design then you can take a look at second example which is the same example but with ES design using Zay-ES.

pspeed is the author of those libraries and examples.

And along those lines, a complete basic starter networked game using SimEthereal…

One without an ES:

And one WITH an ES:

And just a networked ES example with no SimEthereal:

Another question, if for example, one player picks an item how should I message this to avoid cheating?
I would do:
1 - Ask server to get player inventory
2 - Server returns my inventory
3 - update player inventory via server side
4 - send message to server with new values?
5 - update server values

would this be possible or this isn’t a good option?

Nope, at point 4 you let the client tell the server what your inveory should look like => CHEAT !

Just do that something like that :
1 client send message to server to tell : hey i want to pick this item
2 server side, the server allow player to grab it or not
2.1 if no don’t do anything or send a message to client to inform that player can’t get that object
2.2 if yes add new item on server side to player inventory
3 Send new inventory to client. Two options : send the complete inventory(which contains the new picked item) or do it in a clever way and just send an update inventory message with the item id and a flag add/remove for example and let the client refresh ui and inventory system when received

You are thinking in a wrong way. Client/Server apps always work like this (for auhoritative server)
1 client ask to do somehing
2 server valid or invalid client request
3 server send update if needed
4 client update visuals with received infos

1 Like

okay, I’ve understood the server authoritative I think, but this brings me another question, in which case the server would not allow to pick an item? For example when the inventory size its the max of items allowed?

This point is totally up to you ! You can define all the rules you want, it is your game ^^

But yes it could be a case where server not allows that action, or if the player is not is the right state to getit (need to do another action or valid a quest before being able to loot for example) … etc…