diff --git a/jme3-networking/src/main/java/com/jme3/network/message/SerializerRegistrationsMessage.java b/jme3-networking/src/main/java/com/jme3/network/message/SerializerRegistrationsMessage.java
new file mode 100644
index 000000000..da7f2a7cf
--- /dev/null
+++ b/jme3-networking/src/main/java/com/jme3/network/message/SerializerRegistrationsMessage.java
@@ -0,0 +1,188 @@
+/*
+ * $Id: SerializerRegistrationsMessage.java 3829 2014-11-24 07:25:43Z pspeed $
+ *
+ * Copyright (c) 2012, Paul Speed
+ * All rights reserved.
+ */
+
+package com.jme3.network.message;
+
+import com.jme3.network.AbstractMessage;
+import com.jme3.network.serializing.Serializable;
+import com.jme3.network.serializing.Serializer;
+import com.jme3.network.serializing.SerializerRegistration;
+import com.jme3.network.serializing.serializers.FieldSerializer;
+import java.util.*;
+import java.util.jar.Attributes;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+
+/**
+ * Holds a compiled set of message registration information that
+ * can be sent over the wire. The received message can then be
+ * used to register all of the classes using the same IDs and
+ * same ordering, etc.. The intent is that the server compiles
+ * this message once it is sure that all serializable classes have
+ * been registered. It can then send this to each new client and
+ * they can use it to register all of the classes without requiring
+ * exactly reproducing the same calls that the server did to register
+ * messages.
+ *
+ *
Normally, JME recommends that apps have a common utility method
+ * that they call on both client and server. However, this makes
+ * pluggable services nearly impossible as some central class has to
+ * know about all registered serializers. This message implementation
+ * gets around by only requiring registration on the server.
+ *
+ * @author Paul Speed
+ */
+@Serializable
+public class SerializerRegistrationsMessage extends AbstractMessage {
+
+ static final Logger log = Logger.getLogger(SerializerRegistrationsMessage.class.getName());
+
+ public static final Set ignore = new HashSet();
+ static {
+ // We could build this automatically but then we
+ // risk making a client and server out of date simply because
+ // their JME versions are out of date.
+ ignore.add(Boolean.class);
+ ignore.add(Float.class);
+ ignore.add(Boolean.class);
+ ignore.add(Byte.class);
+ ignore.add(Character.class);
+ ignore.add(Short.class);
+ ignore.add(Integer.class);
+ ignore.add(Long.class);
+ ignore.add(Float.class);
+ ignore.add(Double.class);
+ ignore.add(String.class);
+
+ ignore.add(DisconnectMessage.class);
+ ignore.add(ClientRegistrationMessage.class);
+
+ ignore.add(Date.class);
+ ignore.add(AbstractCollection.class);
+ ignore.add(AbstractList.class);
+ ignore.add(AbstractSet.class);
+ ignore.add(ArrayList.class);
+ ignore.add(HashSet.class);
+ ignore.add(LinkedHashSet.class);
+ ignore.add(LinkedList.class);
+ ignore.add(TreeSet.class);
+ ignore.add(Vector.class);
+ ignore.add(AbstractMap.class);
+ ignore.add(Attributes.class);
+ ignore.add(HashMap.class);
+ ignore.add(Hashtable.class);
+ ignore.add(IdentityHashMap.class);
+ ignore.add(TreeMap.class);
+ ignore.add(WeakHashMap.class);
+ ignore.add(Enum.class);
+
+ ignore.add(GZIPCompressedMessage.class);
+ ignore.add(ZIPCompressedMessage.class);
+
+ ignore.add(ChannelInfoMessage.class);
+
+ ignore.add(SerializerRegistrationsMessage.class);
+ ignore.add(SerializerRegistrationsMessage.Registration.class);
+ }
+
+ public static SerializerRegistrationsMessage INSTANCE;
+ public static Registration[] compiled;
+ private static final Serializer fieldSerializer = new FieldSerializer();
+
+ private Registration[] registrations;
+
+ public SerializerRegistrationsMessage() {
+ setReliable(true);
+ }
+
+ public SerializerRegistrationsMessage( Registration... registrations ) {
+ setReliable(true);
+ this.registrations = registrations;
+ }
+
+ public static void compile() {
+
+ // Let's just see what they are here
+ List list = new ArrayList();
+ for( SerializerRegistration reg : Serializer.getSerializerRegistrations() ) {
+ Class type = reg.getType();
+ if( ignore.contains(type) )
+ continue;
+ if( type.isPrimitive() )
+ continue;
+
+ list.add(new Registration(reg));
+ }
+
+ if( log.isLoggable(Level.FINE) ) {
+ log.log( Level.FINE, "Number of registered classes:{0}", list.size());
+ for( Registration reg : list ) {
+ log.log( Level.FINE, " {0}", reg);
+ }
+ }
+ compiled = list.toArray(new Registration[list.size()]);
+
+ INSTANCE = new SerializerRegistrationsMessage(compiled);
+ }
+
+ public void registerAll() {
+ for( Registration reg : registrations ) {
+ log.log( Level.INFO, "Registering:{0}", reg);
+ reg.register();
+ }
+ }
+
+ @Serializable
+ public static final class Registration {
+
+ private short id;
+ private String className;
+ private String serializerClassName;
+
+ public Registration() {
+ }
+
+ public Registration( SerializerRegistration reg ) {
+
+ this.id = reg.getId();
+ this.className = reg.getType().getName();
+ if( reg.getSerializer().getClass() != FieldSerializer.class ) {
+ this.serializerClassName = reg.getSerializer().getClass().getName();
+ }
+ }
+
+ public void register() {
+ try {
+ Class type = Class.forName(className);
+ Serializer serializer;
+ if( serializerClassName == null ) {
+ serializer = fieldSerializer;
+ } else {
+ Class serializerType = Class.forName(serializerClassName);
+ serializer = (Serializer)serializerType.newInstance();
+ }
+ SerializerRegistration result = Serializer.registerClassForId(id, type, serializer);
+ log.log( Level.FINE, " result:{0}", result);
+ } catch( ClassNotFoundException e ) {
+ throw new RuntimeException( "Class not found attempting to register:" + this, e );
+ } catch( InstantiationException e ) {
+ throw new RuntimeException( "Error instantiating serializer registering:" + this, e );
+ } catch( IllegalAccessException e ) {
+ throw new RuntimeException( "Error instantiating serializer registering:" + this, e );
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "Registration[" + id + " = " + className + ", serializer=" + serializerClassName + "]";
+ }
+ }
+}
+
+
+