{"id":1137,"date":"2019-05-14T14:16:49","date_gmt":"2019-05-14T14:16:49","guid":{"rendered":"http:\/\/smartfoxserver.com\/blog\/?p=1137"},"modified":"2019-05-15T13:20:49","modified_gmt":"2019-05-15T13:20:49","slug":"object-serialization-between-static-and-dynamic-languages","status":"publish","type":"post","link":"https:\/\/smartfoxserver.com\/blog\/object-serialization-between-static-and-dynamic-languages\/","title":{"rendered":"Object serialization between static and dynamic languages"},"content":{"rendered":"<p>Among\u00a0the advanced features provided in the SmartFoxServer SDK is the ability to exchange any class instance between client and server with minimal coding intervention. This is particularly useful for statically typed languages such as Java, C# and Actionscript, while dynamic languages such as Javascript are not directly supported.<\/p>\n<p>In this article we&#8217;re going to\u00a0discuss\u00a0an alternative way to implement custom serialization for classes that are needed from both client and server side to implement our game logic.<\/p>\n<p>If you&#8217;re not entirely familiar with the topic of class serialization in SFS2X we recommend reading this <a href=\"http:\/\/docs2x.smartfoxserver.com\/AdvancedTopics\/class-serialization\" target=\"_blank\" rel=\"noopener noreferrer\">article from our documentation<\/a><!--more--><\/p>\n<h2>\u00bb The Basics<\/h2>\n<p>SmartFoxServer\u00a0provides\u00a0two fundamental classes, <strong>SFSObject<\/strong> and <strong>SFSArray<\/strong>, on both client and server side that are\u00a0used to exchange data between the two end points.<\/p>\n<p><strong>SFSObject<\/strong> and <strong>SFSArray<\/strong> represent platform-neutral, high level objects that abstract the data transport between client and server. They\u00a0can be used to represent data in form of a Map\/Dictionary or List\/Array respectively,\u00a0supporting multiple\u00a0data types\u00a0and nested objects to create complex data structures.<\/p>\n<p>Both classes also support two generic <strong>getClass()<\/strong>\/<strong>putClass()<\/strong> methods that allow to serialize custom class instances provided they implement a specific interface. This is particularly useful when we need to exchange specific game entities such as characters, NPCs, weapons etc. between client and server (if you need more info on this please refer to the <a href=\"http:\/\/docs2x.smartfoxserver.com\/DevelopmentBasics\/sfsobject-sfsarray\" target=\"_blank\">documentation here<\/a>).<\/p>\n<p>As alluded in this article intro, not all languages are supported: for example <strong>Javascript<\/strong>\u00a0with its dynamic structure and classless OOP foundations doesn&#8217;t work well\u00a0with class serialization.<br \/>\nSo what options do we have if we need to exchange custom objects between client and servers?<\/p>\n<h2>\u00bb\u00a0Custom serialization<\/h2>\n<p>One simple and elegant solution is to add a couple of specialized methods to our game entities, to serialize\/deserialize them before we send them over the network.<\/p>\n<p>To demonstrate this approach we can jump straight into an example: imagine we have a weapon entity that we need to send from server to client and viceversa.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\npublic class GammaRayGun\r\n{\r\n\tprivate int reloadTime;\r\n\tprivate int magazineSize;\r\n\tprivate double damagePerSecond;\r\n\tprivate double accuracy;\r\n\t\r\n\tpublic GammaRayGun()\r\n\t{\r\n\t\r\n\t}\r\n\t\r\n\t\/\/ ...\r\n\t\/\/ getters and setters\r\n\t\/\/ ...\r\n\t\r\n\tpublic ISFSObject toSFSObject()\r\n\t{\r\n\t\tISFSObject sfso = new SFSObject();\r\n\t\tsfso.putInt(&quot;rt&quot;, reloadTime);\r\n\t\tsfso.putInt(&quot;ms&quot;, magazineSize);\r\n\t\tsfso.putDouble(&quot;ds&quot;, damagePerSecond);\r\n\t\tsfso.putDouble(&quot;ac&quot;, accuracy);\r\n\t\t\r\n\t\treturn sfso;\r\n\t}\r\n\t\r\n\tpublic static GammaRayGun fromSFSObject(ISFSObject sfso)\r\n\t{\r\n\t\tGammaRayGun gun = new GammaRayGun();\r\n\t\t\r\n\t\tgun.setReloadTime( sfso.getInt(&quot;rt&quot;) );\r\n\t\tgun.setMagazineSize( sfso.getInt(&quot;ms&quot;) );\r\n\t\tgun.setDamagePerSecond( sfso.getDouble(&quot;ds&quot;) );\r\n\t\tgun.setAccuracy( sfso.getDouble(&quot;ac&quot;) );\t\t\r\n\t\t\r\n\t\treturn gun;\r\n\t}\r\n}\r\n<\/pre>\n<p>This is the server side implementation in Java. The <strong>toSFSObject()<\/strong> method\u00a0wraps the properties we need to exchange with the client in an SFSObject ready to be sent alongside other data, if needed. The <strong>fromSFSObject()<\/strong> works in the opposite direction, by taking an entity&#8217;s serialized data and rebuilding the original object. <\/p>\n<p>Now we can take a look at the relative implementation in Javascript:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nvar GammaRayGun = function() \r\n{\r\n\tthis.reloadTime = 0\r\n\tthis.magazineSize = 0\r\n\tthis.damagePerSecond = 0\r\n\tthis.accuracy = 0\r\n}\r\n\r\nGammaRayGun.prototype.toSFSObject = function()\r\n{\r\n\tvar sfso = new SFS2X.SFSObject()\r\n\tsfso.putInt(&quot;rt&quot;, this.reloadTime)\r\n\tsfso.putInt(&quot;ms&quot;, this.magazineSize)\r\n\tsfso.putDouble(&quot;ds&quot;, this.damagePerSecond)\r\n\tsfso.putDouble(&quot;ac&quot;, this.accuracy)\r\n\t\r\n\treturn sfso\r\n}\r\n\r\nGammaRayGun.fromSFSObject = function(sfso)\r\n{\r\n\tvar gun = new GammaRayGun()\r\n\r\n\tgun.reloadTime = sfso.getInt(&quot;rt&quot;)\r\n\tgun.magazineSize = sfso.getInt(&quot;ms&quot;)\r\n\tgun.damagePerSecond = sfso.getDouble(&quot;ds&quot;)\r\n\tgun.accuracy = sfso.getDouble(&quot;ac&quot;)\r\n\r\n\treturn gun\r\n}\r\n<\/pre>\n<p>The code mirrors the server side version in Javascript, using the relative <a href=\"https:\/\/www.smartfoxserver.com\/download\/#p=client\" target=\"_blank\">SmartFoxServer 2X JS API<\/a>.<\/p>\n<p>Even if it requires a bit of extra code, this solutions allows you to fine tune which field should be transmitted and which data types should be used by the network serializer. In our example we are using <strong>double<\/strong> for floating point values, but if you need less precision you could use <strong>float<\/strong> instead and save some bandwidth. Similarly with the <strong>int<\/strong> values you may opt for a smaller data type, such as short or byte, and trim the packet size to a minimum.<\/p>\n<p>Finally you may also consider this approach for other client-side languages that fully support class serialization. The reason for this is that class serialization requires extra data to be sent for each entity to identify its class, and it isn&#8217;t as flexible in fine tuning each data type. If small packet size is a priority in your game, this approach will yield better overall results.<\/p>\n<p>In conclusion you can experiment with both strategies if you&#8217;re using statically typed languages on the client side, or use the alternative approach we have outlined here, if using a language not supported by our class serialization.<\/p>\n<p>If you want to discuss this topic further or you have other questions <a href=\"https:\/\/www.smartfoxserver.com\/forums\/\" target=\"_blank\">you can reach us in our support forums<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Among\u00a0the advanced features provided in the SmartFoxServer SDK is the ability to exchange any class instance between client and server with minimal coding intervention. This is particularly useful for statically typed languages such as Java, C# and Actionscript, while dynamic languages such as Javascript are not directly supported. In this article we&#8217;re going to\u00a0discuss\u00a0an alternative [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[23],"tags":[106,31,8,80,72],"_links":{"self":[{"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/posts\/1137"}],"collection":[{"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/comments?post=1137"}],"version-history":[{"count":20,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/posts\/1137\/revisions"}],"predecessor-version":[{"id":1162,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/posts\/1137\/revisions\/1162"}],"wp:attachment":[{"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/media?parent=1137"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/categories?post=1137"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/tags?post=1137"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}