hello, for my game I’m trying to send a GameState via a GameStateMessage. Since the GameState is rather large I understand that I need to create my own Serializer, however I’m not sure how to to write my own writeObject() and readObject(). Can anyone help me out? A GameStateMessage only has one field that holds a GameState
Why do you need to create your own serializer? This will not actually work around any size limitations of a message.
What kind of information is in GameState?
This is a card game so a GameState has all the info such as decks, players hands, players themselves, all cards in play. If the serializer doesn’t remove the size limitations then what does?
If your message exceeds 64k in size then you need to break it up or find a way to optimize the size somehow. Some games send entire world state in less than a fraction of that, so I’d be very surprised if your message wouldn’t fit.
Sometimes optimizing the size means creating a custom serializer… sometimes it’s just how the message is defined.
import SVNPackage.Package.Daejeon;
import com.jme3.network.connection.Client;
import com.jme3.network.events.ConnectionListener;
import com.jme3.network.events.MessageAdapter;
import com.jme3.network.message.Message;
import com.jme3.network.serializing.Serializer;
import java.io.IOException;
public class ClientMain extends MessageAdapter implements ConnectionListener {
public Client client;
public ClientMain() throws IOException{
client = new Client(“5.232.191.179”, 3333, 4444);
client.start();
Serializer.registerClass(GameStateMessage.class);
client.addMessageListener(this, GameStateMessage.class);
client.addConnectionListener(this);
}
public void sendMessage(GameStateMessage gm) throws IOException
{
client.send(gm);
System.out.println(“message was sent.”);
}
@Override
public void messageReceived(Message message) {
GameStateMessage GSMessage = (GameStateMessage) message;
Daejeon.mainGame.setGameState(GSMessage.g);
System.out.println(“Message received.”);
}
@Override
public void clientConnected(Client client) {
}
@Override
public void clientDisconnected(Client client) {
this.client.clientDisconnected(client);
}
}
import com.jme3.network.connection.Client;
import com.jme3.network.connection.Server;
import com.jme3.network.events.MessageAdapter;
import com.jme3.network.message.Message;
import com.jme3.network.serializing.Serializer;
import java.io.IOException;
public class ServerMain extends MessageAdapter{
public static Server myServer;
public static void main(String[] args) throws IOException {
myServer = new Server(3333, 4444);
myServer.start();
Serializer.registerClass(GameStateMessage.class);
myServer.addMessageListener(myServer, GameStateMessage.class);
}
@Override
public void messageReceived(Message message) {
GameStateMessage gsm = (GameStateMessage) message;
System.out.println("Server received message.");
try {
if (gsm instanceof GameStateMessage)
for (Client c: myServer.getConnectors())
c.send(gsm);
} catch (IOException e) {System.out.println(e);}
}
}
@Serializable
public class GameStateMessage extends Message{
public GameState g;
public GameStateMessage()
{
}
public GameStateMessage(GameState g)
{
this.g = g;
}
}
could u take a look at my code and see if anything is wrong?
the problem im having is that either my client.send() isnt working or my server is not receiving any messages. This code DOES work for a simple helloMessage from the tutorial.
What version are you running? Straight alpha 4 or a nightly build? Recent?
Are there any log messages for the failure? If the server receives bad data then it should log that. If the client fails to serialize then SpiderMonkey should log that too.
Without seeing any different, my guess is that GameState is failing to serialize or deserialize. Either it is not final or @Serializable (and registered) or it contains something that is not final or @Serializable (and registered). In all cases, recent code should show an error somewhere. Or the classes that are registered are not also registered on the server or something.
Actually, thinking about it some more… in all cases, the GameState class and the classes of the fields it contains need to be registered with the Serializer if they are not already one of the pre-supported types.
I’m running alpha 4 and there are no logs of failure, just nothing shows up ( i put system.out messages to indicate if the method being called). I’ve made just about all my classes serializable and still doesnt work. Would it be a problem is there are some fields i.e. random, ArrayList, sound?
First, when you say “made just about all of my classes serializable”, I’m just confirming that you mean that you marked them @Serializable and registered the classes with the Serializer on both the client and the server.
Second, Random and Sound probably will cause you issues. I don’t remember whether ArrayList is covered or not.
Third, lots of changes were made to SpiderMonkey since Alpha 4 to improve the error reporting of Serializer. Serializer was the one thing I didn’t replace when I rewrote SpiderMonkey and I’ve lived to regret it time and again… but at least now it doesn’t swallow all of its errors.
And finally, the game state you keep to run your game is not usually what someone would actually send over the network connection. My guess is most games put just the relevant data in a specially designed message that doesn’t include non-essential stuff like Random and Sound.
If you really want to send all of that stuff, your best bet is probably to use Java’s serialization to just turn the game state into a byte[] array and stick that in your message. You could even zip it. Because at that point, neither speed nor network efficiency is anywhere in play.
And if you don’t want to send the extra stuff but also don’t want to shuffle data over into a specific message then we’re back to your original question about manually serializing. But you’d essentially have to do the same data decomposition you’d just be doing it at the byte level… and, yuck.
yea i marked all classes with @Serializable and registered them both in the same order. I attempted to create a relevant GameState without the weird random and sound. I keep testing with smaller and smaller messages but nothing seems to work I’ve been at this for quite some time now and I must say I’m completely out of ideas. Is there a way to check what is serializable and what isn’t?
Your best bet is to start using a nightly build that will have the latest error reporting. Then at least you’ll see what’s wrong. It’s pretty simple to do in the JMP plugins… just turn it on and update.