diff --git a/engine/src/networking/com/jme3/network/message/ClientRegistrationMessage.java b/engine/src/networking/com/jme3/network/message/ClientRegistrationMessage.java index fcbf36be6..472ae51f1 100644 --- a/engine/src/networking/com/jme3/network/message/ClientRegistrationMessage.java +++ b/engine/src/networking/com/jme3/network/message/ClientRegistrationMessage.java @@ -33,7 +33,10 @@ package com.jme3.network.message; import com.jme3.network.AbstractMessage; -import com.jme3.network.serializing.Serializable; +import com.jme3.network.serializing.*; +import com.jme3.network.serializing.serializers.StringSerializer; +import java.io.IOException; +import java.nio.ByteBuffer; /** * Client registration is a message that contains a unique ID. This ID @@ -42,10 +45,13 @@ import com.jme3.network.serializing.Serializable; * to couple the TCP and UDP connections together into one 'Client' on the * server. * - * @author Lars Wesselius + * @author Lars Wesselius, Paul Speed */ @Serializable() public class ClientRegistrationMessage extends AbstractMessage { + + public static final short SERIALIZER_ID = -44; + private long id; private String gameName; private int version; @@ -73,4 +79,49 @@ public class ClientRegistrationMessage extends AbstractMessage { public int getVersion() { return version; } + + public String toString() { + return getClass().getName() + "[id=" + id + ", gameName=" + gameName + ", version=" + version + "]"; + } + + /** + * A message-specific serializer to avoid compatibility issues + * between versions. This serializer is registered to the specific + * SERIALIZER_ID which is compatible with previous versions of the + * SM serializer registrations... and now will be forever. + */ + public static class ClientRegistrationSerializer extends Serializer { + + public ClientRegistrationMessage readObject( ByteBuffer data, Class c ) throws IOException { + + // Read the null/non-null marker + if (data.get() == 0x0) + return null; + + ClientRegistrationMessage msg = new ClientRegistrationMessage(); + + msg.gameName = StringSerializer.readString(data); + msg.id = data.getLong(); + msg.version = data.getInt(); + + return msg; + } + + public void writeObject(ByteBuffer buffer, Object object) throws IOException { + + // Add the null/non-null marker + buffer.put( (byte)(object != null ? 0x1 : 0x0) ); + if (object == null) { + // Nothing left to do + return; + } + + ClientRegistrationMessage msg = (ClientRegistrationMessage)object; + StringSerializer.writeString( msg.gameName, buffer ); + + buffer.putLong(msg.id); + buffer.putInt(msg.version); + } + } + } diff --git a/engine/src/networking/com/jme3/network/message/DisconnectMessage.java b/engine/src/networking/com/jme3/network/message/DisconnectMessage.java index ab667c3be..c821c6d6e 100644 --- a/engine/src/networking/com/jme3/network/message/DisconnectMessage.java +++ b/engine/src/networking/com/jme3/network/message/DisconnectMessage.java @@ -33,15 +33,21 @@ package com.jme3.network.message; import com.jme3.network.AbstractMessage; -import com.jme3.network.serializing.Serializable; +import com.jme3.network.serializing.*; +import com.jme3.network.serializing.serializers.StringSerializer; +import java.io.IOException; +import java.nio.ByteBuffer; /** * Represents a disconnect message. * - * @author Lars Wesselius + * @author Lars Wesselius, Paul Speed */ @Serializable() public class DisconnectMessage extends AbstractMessage { + + public static final short SERIALIZER_ID = -42; + public static final String KICK = "Kick"; public static final String USER_REQUESTED = "User requested"; public static final String ERROR = "Error"; @@ -65,4 +71,45 @@ public class DisconnectMessage extends AbstractMessage { public void setType(String type) { this.type = type; } + + public String toString() { + return getClass().getName() + "[reason=" + reason + ", type=" + type + "]"; + } + + /** + * A message-specific serializer to avoid compatibility issues + * between versions. This serializer is registered to the specific + * SERIALIZER_ID which is compatible with previous versions of the + * SM serializer registrations... and now will be forever. + */ + public static class DisconnectSerializer extends Serializer { + + public DisconnectMessage readObject( ByteBuffer data, Class c ) throws IOException { + + // Read the null/non-null marker + if (data.get() == 0x0) + return null; + + DisconnectMessage msg = new DisconnectMessage(); + + msg.reason = StringSerializer.readString(data); + msg.type = StringSerializer.readString(data); + + return msg; + } + + public void writeObject(ByteBuffer buffer, Object object) throws IOException { + + // Add the null/non-null marker + buffer.put( (byte)(object != null ? 0x1 : 0x0) ); + if (object == null) { + // Nothing left to do + return; + } + + DisconnectMessage msg = (DisconnectMessage)object; + StringSerializer.writeString( msg.reason, buffer ); + StringSerializer.writeString( msg.type, buffer ); + } + } } diff --git a/engine/src/networking/com/jme3/network/serializing/Serializer.java b/engine/src/networking/com/jme3/network/serializing/Serializer.java index ffdcdf7bf..ba2ace7a1 100644 --- a/engine/src/networking/com/jme3/network/serializing/Serializer.java +++ b/engine/src/networking/com/jme3/network/serializing/Serializer.java @@ -73,30 +73,20 @@ public abstract class Serializer { private static boolean strictRegistration = true; - /**************************************************************** - **************************************************************** - **************************************************************** - - READ THIS BEFORE CHANGING ANYTHING BELOW - - If a registration is moved or removed before the - ClientRegistrationMessage then it screws up the application's - ability to gracefully warn users about bad versions. - - There really needs to be a version rolled into the protocol - and I intend to do that very soon. In the mean time, don't - edit the static registrations without decrementing nextId - appropriately. - - Yes, that's how fragile this is. Live and learn. - - **************************************************************** - **************************************************************** - ****************************************************************/ - // Registers the classes we already have serializers for. static { + + // Preregister some fixed serializers so that they don't move + // if the list below is modified. Automatic ID generation will + // skip these IDs. + registerClassForId( DisconnectMessage.SERIALIZER_ID, DisconnectMessage.class, + new DisconnectMessage.DisconnectSerializer() ); + registerClassForId( ClientRegistrationMessage.SERIALIZER_ID, ClientRegistrationMessage.class, + new ClientRegistrationMessage.ClientRegistrationSerializer() ); + + + registerClass(boolean.class, new BooleanSerializer()); registerClass(byte.class, new ByteSerializer()); registerClass(char.class, new CharSerializer()); @@ -125,8 +115,6 @@ public abstract class Serializer { registerClass(AbstractList.class, new CollectionSerializer()); registerClass(AbstractSet.class, new CollectionSerializer()); registerClass(ArrayList.class, new CollectionSerializer()); - registerClass(BeanContextServicesSupport.class, new CollectionSerializer()); - registerClass(BeanContextSupport.class, new CollectionSerializer()); registerClass(HashSet.class, new CollectionSerializer()); registerClass(LinkedHashSet.class, new CollectionSerializer()); registerClass(LinkedList.class, new CollectionSerializer()); @@ -139,7 +127,6 @@ public abstract class Serializer { registerClass(HashMap.class, new MapSerializer()); registerClass(Hashtable.class, new MapSerializer()); registerClass(IdentityHashMap.class, new MapSerializer()); - //registerClass(java.awt.RenderingHints.class, new MapSerializer()); registerClass(TreeMap.class, new MapSerializer()); registerClass(WeakHashMap.class, new MapSerializer()); @@ -147,8 +134,6 @@ public abstract class Serializer { registerClass(GZIPCompressedMessage.class, new GZIPSerializer()); registerClass(ZIPCompressedMessage.class, new ZIPSerializer()); - registerClass(DisconnectMessage.class); - registerClass(ClientRegistrationMessage.class); registerClass(ChannelInfoMessage.class); } @@ -186,7 +171,7 @@ public abstract class Serializer { } protected static SerializerRegistration registerClassForId( short id, Class cls, Serializer serializer ) { - + SerializerRegistration reg = new SerializerRegistration(serializer, cls, id); idRegistrations.put(id, reg);