Sending/receiving classes

Post here your questions about the Unity / .Net / Mono / Windows 8 / Windows Phone 8 API for SFS2X

Moderators: Lapo, Bax

User avatar
Zelek
Posts: 36
Joined: 24 Jun 2010, 22:36

Postby Zelek » 15 Sep 2011, 03:55

It took me a while to figure that out as well. My current setup (which works) consists of a "Scripts/serializable" folder in Unity. I enclose my classes in that folder with "namespace serializable {". In Java, for the server, I have a "serializable" package that is adjacent to my main Extension package. They are both children of the "src" folder.

You could maybe try mimicking that setup initially, just to get it to work, then massage things around to subfolders and ensure that it still works afterwards.

Looking at your code, perhaps the namespace in C# should just be "Serialization". Also, note that enums and private fields don't get serialized. GetJavaPackageName() is unnecessary if you're using the most recent client patch of the SmartFox plugin in Unity.
Jarnul
Posts: 3
Joined: 22 Jan 2012, 14:26

Serializable C#->Java -> C#

Postby Jarnul » 22 Jan 2012, 20:45

Whiskey wrote:I would love to see that as well. After some testing, I found with GetDump of the object to send that after PutClass both Unity (before sending), and the server (after receiving and before sending back) report the contents of the object as:

Code: Select all

(class) test: nl.inthere.sfs2x.serialization.TestObject


However, when the object is received in Unity (and evt.Params["params" is casted to an SFSObject) the contents are reported as:

Code: Select all

(sfs_object) test:
   (utf_string) $C: nl.inthere.sfs2x.serialization.TestObject
   (sfs_array) $F:
      (sfs_object)
         (utf_string) V: Server generated class
         (utf_string) N: name
      
      (sfs_object)
         (int) V: 24
         (utf_string) N: id

The values are correct, but it is not classified as a class, so GetClass can't find it.


Hi. How i'm get class to c# is now?
This is very important!
ThomasLund
Posts: 1297
Joined: 14 Mar 2008, 07:52
Location: Sweden

Postby ThomasLund » 24 Jan 2012, 13:15

Here is a test class that might help you.

Please not that this test does NOT send to the server. Its only testing the serialization and deserialization client side.

TestObject is a basic little test class I made. Can be most anything. Also added below for completeness

Code: Select all

      [Test]
      public void TestObjectNestedClass() {
         DefaultSFSDataSerializer serializer = DefaultSFSDataSerializer.Instance;
         DefaultSFSDataSerializer.RunningAssembly = Assembly.GetExecutingAssembly();
         
         ISFSObject sfsObj = new SFSObject();
         
         TestObject obj1 = new TestObject();
         obj1.intField = 60;
         TestObject obj2 = new TestObject();
         obj2.intField = 70;
         
         sfsObj.PutClass("obj1", obj1);
         sfsObj.PutClass("obj2", obj2);
                                                      
         ByteArray data = serializer.Object2Binary(sfsObj);
         Assert.Greater(data.Length, 0);
         
         ISFSObject res = serializer.Binary2Object(data);
         Assert.AreEqual(2, res.Size());
         
         TestObject res1 = res.GetClass("obj1") as TestObject;
         TestObject res2 = res.GetClass("obj2") as TestObject;
         
         Assert.AreEqual(60, res1.intField);
         Assert.AreEqual(70, res2.intField);
      }

   public class TestObject : SerializableSFSType {
      
      public int intField;
      public string strField;
      public bool boolField;
      public double doubleField;
      
      public NestedObject nestedField;
      
      public ArrayList arrayField;
      public Hashtable dictField;
            
      public bool IsEqual(TestObject anotherObject) {
         if (this.intField!=anotherObject.intField) return false;
         if (this.strField!=anotherObject.strField) return false;
         if (this.boolField!=anotherObject.boolField) return false;
         if (this.doubleField!=anotherObject.doubleField) return false;
                  
         return true;
      }
   }

Full Control - maker of Unity/C# and Java SFS API and indie games
Follow on twitter: http://twitter.com/thomas_h_lund
sonht10
Posts: 5
Joined: 26 Dec 2012, 09:00

Re: Sending/receiving classes

Postby sonht10 » 05 Jan 2013, 07:31

ThomasLund wrote:I just wanted to give a heads up on this little buried gem in the new API.

You can pretty easily send and receive class structures between C# and Java on the backend without having to create intermediate SFSObject structures.

I will soon make a small example project, but here are some of the details on how to get started on this.

First off - read more about this advanced feature here
http://docs2x.smartfoxserver.com/Advanc ... ialization

To get this working in C#, there is one additional nugget of information that you need. In your code you need to add this:

Code: Select all

         DefaultSFSDataSerializer.RunningAssembly = Assembly.GetExecutingAssembly();

otherwise the serialization wont work. Also remember (as stated in the linked documentation page) that your class/package names need to match on server and on client side.

Below are some cut'n'pastes from a test case I got. It should serve as example until I get a small project together that you can run.

First up - we make a test class which is what we want to transport

Code: Select all

   public class TestObject : SerializableSFSType {
      
      public int intField;
      public string strField;
      public bool boolField;
      public double doubleField;
      
      public NestedObject nestedField;
      
      public ArrayList arrayField;
      public Hashtable dictField;
            
      public bool IsEqual(TestObject anotherObject) {
         if (this.intField!=anotherObject.intField) return false;
         if (this.strField!=anotherObject.strField) return false;
         if (this.boolField!=anotherObject.boolField) return false;
         if (this.doubleField!=anotherObject.doubleField) return false;
                  
         return true;
      }
   
      #region SerializableSFSType implementation
      public string GetJavaPackageName ()
      {
         return "";
      }
      
      #endregion
      
   }


And here is a usage example where my test code serializes and deserializes the object. Note that here it doesnt actually send it to the server. But inserting a send/receive is trivial.

Code: Select all

   [Test]
      public void TestClass() {
         DefaultSFSDataSerializer serializer = DefaultSFSDataSerializer.Instance;
         DefaultSFSDataSerializer.RunningAssembly = Assembly.GetExecutingAssembly();
         
         TestObject testObj = new TestObject();
         testObj.intField = 10;
         testObj.strField = "test";
         testObj.boolField = true;
         testObj.doubleField = 1.421;
         testObj.nestedField = new NestedObject();
         testObj.nestedField.intField = 20;
         
         testObj.arrayField = new ArrayList();
         testObj.arrayField.Add((int)1);
         testObj.arrayField.Add("testArray");
         
         testObj.dictField = new Hashtable();
         testObj.dictField["test1"] = false;
         testObj.dictField["test2"] = "testDict";
         
         ISFSObject obj = serializer.Cs2Sfs(testObj);
         Assert.IsNotNull(obj);
         TestObject receivedTestObj = serializer.Sfs2Cs(obj) as TestObject;
         Assert.IsNotNull(receivedTestObj);
         
         Assert.IsTrue(receivedTestObj.IsEqual(testObj));
         Assert.IsNotNull(receivedTestObj.nestedField);
         Assert.AreEqual(testObj.nestedField.intField, receivedTestObj.nestedField.intField);
         
         Assert.IsNotNull(receivedTestObj.arrayField);
         Assert.AreEqual(2, receivedTestObj.arrayField.Count);
         Assert.AreEqual(1, (int)receivedTestObj.arrayField[0]);
         Assert.AreEqual("testArray", (string)receivedTestObj.arrayField[1]);
         
         Assert.IsNotNull(receivedTestObj.dictField);
         Assert.AreEqual(2, receivedTestObj.dictField.Count);
         Assert.AreEqual(false, (bool)receivedTestObj.dictField["test1"]);
         Assert.AreEqual("testDict", (string)receivedTestObj.dictField["test2"]);
               
      }


Some important notes to get this working:
1. Only non-generic ArrayList and Hashtable work in C#
2. Hashtable can have only use string type as the key
3. The java extension must be in __lib__ folder to allow sending classes from C# (AS3) -> Java
4. C# class needs this: DefaultSFSDataSerializer.RunningAssembly = Assembly.GetExecutingAssembly();
5. Package names need to match in the C# and Java class

Previous requirement of C# class having
   public string GetJavaPackageName ()
     {
        return "";
     }
is not needed anymore




"DefaultSFSDataSerializer.RunningAssembly = Assembly.GetExecutingAssembly();"

where to put this code in the example ?

my error: java.lang.NullPointerException

please help ! thanks !

Return to “SFS2X C# API”

Who is online

Users browsing this forum: No registered users and 1 guest