Zay-ES Net throws exception when enums are sent

Hello dear community,

For a multiplayer game the client has an app state which takes care about Models with a certain type. My Model component holds an enum, “ModelType”. I use this enum in a filter (on client side) to get a all entities with a player model. It looks like follows:

this.players = entityData.getEntities(new FieldFilter(Model.class, "modelType", ModelType.Player), Model.class);

When I ask for those entities I get the following exception on the client:

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:282)
	at com.jme3.network.base.DefaultClient.send(DefaultClient.java:262)
	at com.simsilica.es.client.RemoteEntityData.getEntities(RemoteEntityData.java:380)
	at de.gamedevbaden.crucified.appstates.view.VisualEquipmentAppState.initialize(VisualEquipmentAppState.java:34)
	at com.jme3.app.state.AppStateManager.initializePending(AppStateManager.java:251)
	at com.jme3.app.state.AppStateManager.update(AppStateManager.java:281)
	at com.jme3.app.SimpleApplication.update(SimpleApplication.java:236)
	at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:151)
	at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:193)
	at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:232)
	at java.lang.Thread.run(Thread.java:745)
Caused by: com.jme3.network.serializing.SerializerException: Error writing object for field:private com.simsilica.es.ComponentFilter com.simsilica.es.net.GetEntitySetMessage.filter
	at com.jme3.network.serializing.serializers.FieldSerializer.writeObject(FieldSerializer.java:209)
	at com.jme3.network.serializing.Serializer.writeClassAndObject(Serializer.java:458)
	at com.jme3.network.base.MessageProtocol.messageToBuffer(MessageProtocol.java:73)
	... 11 more
Caused by: com.jme3.network.serializing.SerializerException: Error writing object for field:private java.lang.Object com.simsilica.es.filter.FieldFilter.value
	at com.jme3.network.serializing.serializers.FieldSerializer.writeObject(FieldSerializer.java:209)
	at com.jme3.network.serializing.Serializer.writeClassAndObject(Serializer.java:458)
	at com.jme3.network.serializing.serializers.FieldSerializer.writeObject(FieldSerializer.java:204)
	... 13 more
Caused by: java.lang.IllegalArgumentException: Class has not been registered:class de.gamedevbaden.crucified.enums.ModelType but resolved to generic serializer for:class java.lang.Enum
	at com.jme3.network.serializing.Serializer.writeClassAndObject(Serializer.java:454)
	at com.jme3.network.serializing.serializers.FieldSerializer.writeObject(FieldSerializer.java:204)
	... 15 more 

However, when I register that class (enum), add the Serializable mark and add an empty constructor I get the following exception on the server:

java.lang.RuntimeException: Registration error: no-argument constructor not found on:class de.gamedevbaden.crucified.enums.ModelType
	at com.jme3.network.serializing.serializers.FieldSerializer.checkClass(FieldSerializer.java:80)
	at com.jme3.network.serializing.serializers.FieldSerializer.initialize(FieldSerializer.java:85)
	at com.jme3.network.serializing.Serializer.registerClassForId(Serializer.java:220)
	at com.jme3.network.serializing.Serializer.registerClass(Serializer.java:252)
	at com.jme3.network.serializing.Serializer.registerClass(Serializer.java:166)
	at de.gamedevbaden.crucified.net.NetworkUtils.initSerializers(NetworkUtils.java:29)
	at de.gamedevbaden.crucified.net.server.GameServer.initialize(GameServer.java:55)
	at com.jme3.app.state.AppStateManager.initializePending(AppStateManager.java:251)
	at com.jme3.app.state.AppStateManager.update(AppStateManager.java:281)
	at com.jme3.app.SimpleApplication.update(SimpleApplication.java:236)
	at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:151)
	at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:193)
	at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:232)
	at java.lang.Thread.run(Thread.java:745)

Is there a “restriction” that I can’t send enums? Should enums be replaced through Strings in this case?

Best regards
Domenic

Have you tried following the Suggestion?
Adding a no argument Constructor (Also called serialization constructor)

So, yes, I did. but this doesn’t have an effect because an enum constructor is private, public is (unfortunatly) not allowed here.

1 Like

You can see how sim-eth-es does it in ObjectType.class / ObjectTypes.class:

I’ve done the same for any new ‘enums’ I needed :slight_smile:

It’s not really a Zay-es net thing (Though if you ever want to use Zay-es SQL storage then you will also want to stay away from enums for reasons)… it’s a spider monkey thing.

If you want to send enums then you will have to register a proper serializer for them. FieldSerializer can’t be used for enums because you can’t instantiate an enum… it also makes no sense for enums.

http://javadoc.jmonkeyengine.org/com/jme3/network/serializing/serializers/EnumSerializer.html

That’s why I put this topic into the networking section :slight_smile:

[quote=“pspeed, post:5, topic:38637”]
If you want to send enums then you will have to register a proper serializer for them. [/quote]

Works perfectly, thank you @pspeed!