{"id":736,"date":"2017-06-23T09:53:56","date_gmt":"2017-06-23T09:53:56","guid":{"rendered":"http:\/\/smartfoxserver.com\/blog\/?p=736"},"modified":"2017-06-23T09:56:49","modified_gmt":"2017-06-23T09:56:49","slug":"kotlin-and-smartfoxserver-2x-part-3","status":"publish","type":"post","link":"https:\/\/smartfoxserver.com\/blog\/kotlin-and-smartfoxserver-2x-part-3\/","title":{"rendered":"Kotlin and SmartFoxServer 2X, part 3"},"content":{"rendered":"<p>This is the third and final chapter of our explorations with Kotlin and SmartFoxServer 2X. After building the first Kotlin extension in <a href=\"http:\/\/smartfoxserver.com\/blog\/kotlin-and-smartfoxserver-2x\/\" target=\"_blank\" rel=\"noopener noreferrer\">part one<\/a> and creating a basic client app in <a href=\"http:\/\/smartfoxserver.com\/blog\/kotlin-and-smartfoxserver-2x-part-2\/\" target=\"_blank\" rel=\"noopener noreferrer\">part two<\/a> we&#8217;re now completing the picture with a client\/server example.<\/p>\n<p><!--more--><\/p>\n<p>Word of advice: if you haven&#8217;t followed the two previous chapters make sure to go back and review them before starting with\u00a0this last chapter.<\/p>\n<h2>\u00bb\u00a0Putting it all together<\/h2>\n<p>In this final installment we&#8217;re going to translate in Kotlin our client and server <a href=\"http:\/\/docs2x.smartfoxserver.com\/ExtensionsJava\/quick-start\" target=\"_blank\" rel=\"noopener noreferrer\">quick start example<\/a>\u00a0from the documentation, applying what we have learned so far about Kotlin.<\/p>\n<h3>Server side<\/h3>\n<pre class=\"brush: scala; title: ; notranslate\" title=\"\">\r\npackage sfs2x.kt\r\n\r\nimport com.smartfoxserver.v2.core.ISFSEvent\r\nimport com.smartfoxserver.v2.core.SFSEventType\r\nimport com.smartfoxserver.v2.entities.User\r\nimport com.smartfoxserver.v2.entities.data.ISFSObject\r\nimport com.smartfoxserver.v2.entities.data.SFSObject\r\nimport com.smartfoxserver.v2.extensions.BaseClientRequestHandler\r\nimport com.smartfoxserver.v2.extensions.SFSExtension\r\n\r\nval CMD_SUM = &quot;sum&quot;\r\n\r\nclass SumHandler : BaseClientRequestHandler()\r\n{\r\n    override fun handleClientRequest(user: User, params: ISFSObject)\r\n    {\r\n        if (params.containsKey(&quot;n1&quot;) &amp;&amp; params.containsKey(&quot;n2&quot;))\r\n        {\r\n            val n1 = params.getInt(&quot;n1&quot;)\r\n            val n2 = params.getInt(&quot;n2&quot;)\r\n\r\n            val resObj = SFSObject()\r\n            resObj.putInt(&quot;res&quot;, n1 + n2)\r\n\r\n            send(CMD_SUM, resObj, user)\r\n        }\r\n    }\r\n}\r\n\r\nclass KotlinTestExtension : SFSExtension()\r\n{\r\n    override  fun init()\r\n    {\r\n        trace(&quot;Kotlin Extension ready!&quot;)\r\n\r\n        addRequestHandler(CMD_SUM, SumHandler());\r\n    }\r\n\r\n    override fun destroy() {\r\n        super.destroy()\r\n\r\n        trace(&quot;Kotlin Extension shutting down.&quot;);\r\n    }\r\n}\r\n<\/pre>\n<p>We have already learned how to create an Extension class by inheriting from the parent <strong>SFSExtension<\/strong> class and overriding the <strong>init()<\/strong> method. This time we&#8217;re also implementing a request handler by creating a class that extends\u00a0<strong>BaseClientRequestHandler<\/strong>.<\/p>\n<p>Our <strong>SumHandler\u00a0<\/strong>implementation takes two integer parameters, sums them together and sends them back to the client, wrapped in an SFSObject.<\/p>\n<p>As a side note, it&#8217;s worth noticing how Kotlin is more flexible with class definitions as we&#8217;re not constrained to the one-class-per-file rule\u00a0of Java development.<\/p>\n<h3>Client\u00a0side<\/h3>\n<pre class=\"brush: scala; title: ; notranslate\" title=\"\">\r\nimport com.smartfoxserver.v2.entities.data.SFSObject\r\nimport com.sun.xml.internal.rngom.parse.host.Base\r\nimport sfs2x.client.SmartFox\r\nimport sfs2x.client.core.BaseEvent\r\nimport sfs2x.client.core.IEventListener\r\nimport sfs2x.client.core.SFSEvent\r\nimport sfs2x.client.requests.ExtensionRequest\r\nimport sfs2x.client.requests.LoginRequest\r\nimport sfs2x.client.util.ConfigData\r\n\r\nclass SFSEventListener : IEventListener\r\n{\r\n    override fun dispatch(evt: BaseEvent?)\r\n    {\r\n\r\n        when (evt?.type)\r\n        {\r\n            SFSEvent.CONNECTION -&gt; onConnection(evt)\r\n            SFSEvent.CONNECTION_LOST -&gt; println(&quot;Connection lost&quot;)\r\n            SFSEvent.LOGIN -&gt; onLogin(evt)\r\n            SFSEvent.LOGIN_ERROR -&gt;onLoginError(evt)\r\n            SFSEvent.EXTENSION_RESPONSE -&gt;onExtensionResp(evt)\r\n        }\r\n    }\r\n\r\n    fun onConnection(evt:BaseEvent)\r\n    {\r\n        val success = evt.arguments.get(&quot;success&quot;) as Boolean\r\n\r\n        if (success)\r\n        {\r\n            println(&quot;Connected to server...&quot;)\r\n            sfs.send(LoginRequest(&quot;&quot;, &quot;&quot;, cfg.zone))\r\n        }\r\n\r\n        else println(&quot;Connection failed!&quot;)\r\n    }\r\n\r\n    fun onLogin(evt:BaseEvent)\r\n    {\r\n        println(&quot;Logged in as: &quot; + sfs.mySelf.name)\r\n        \r\n        val sfso = SFSObject()\r\n        sfso.putInt(&quot;n1&quot;, 15)\r\n        sfso.putInt(&quot;n2&quot;, 50)\r\n\r\n        sfs.send( ExtensionRequest(&quot;sum&quot;, sfso) )\r\n    }\r\n\r\n    fun onLoginError(evt:BaseEvent)\r\n    {\r\n        val errorMsg = evt.arguments.get(&quot;errorMessage&quot;);\r\n        println(&quot;Login failed: ${errorMsg}&quot;)\r\n    }\r\n\r\n    fun onExtensionResp(evt:BaseEvent)\r\n    {\r\n        val params = evt.arguments.get(&quot;params&quot;) as SFSObject\r\n        println(&quot;Result = &quot; + params.getInt(&quot;res&quot;))\r\n    }\r\n}\r\n\r\nval sfs = SmartFox()\r\nval cfg = ConfigData()\r\nval listener = SFSEventListener()\r\n\r\nfun main(args: Array&lt;String&gt;)\r\n{\r\n    println(&quot;SFS2X API Version: ${sfs.version}&quot;)\r\n\r\n    cfg.host = &quot;127.0.0.1&quot;\r\n    cfg.port = 9933\r\n    cfg.zone = &quot;BasicExamples&quot;\r\n    cfg.isDebug = false\r\n\r\n    sfs.setClientDetails(&quot;Kotlin&quot;, &quot;&quot;)\r\n    sfs.addEventListener(SFSEvent.CONNECTION, listener)\r\n    sfs.addEventListener(SFSEvent.CONNECTION_LOST, listener)\r\n    sfs.addEventListener(SFSEvent.LOGIN, listener)\r\n    sfs.addEventListener(SFSEvent.LOGIN_ERROR, listener)\r\n    sfs.addEventListener(SFSEvent.EXTENSION_RESPONSE, listener)\r\n\r\n    \/\/ Start connection\r\n    sfs.connect(cfg)\r\n}\r\n<\/pre>\n<p>As seen in our previous chapter in Kotlin we&#8217;re free to write functions outside of classes, so our <strong>main()<\/strong> method doesn&#8217;t require any class definitions around it. Here we define our connection parameters an register the events we&#8217;re going to listen to.<\/p>\n<p>Also notice the usage of the <strong>setClientDetails()<\/strong> method to identify the client&#8217;s technology. This is an optional step that can be useful to distinguish between different client technologies in our server logs and usage statistics, for example using the <a href=\"http:\/\/www.smartfoxserver.com\/products\/analytics#p=features\" target=\"_blank\" rel=\"noopener noreferrer\">Analytics module<\/a>.<\/p>\n<p>Sending and receiving extension messages is no different from the Java counterpart. All we need to do is wrapping the request (or response) parameters in an SFSObject and send them to the other side. In this case we&#8217;re sending two integers (called &#8220;n1&#8221; and &#8220;n2) and we&#8217;re expecting an integer (called &#8220;res&#8221;) in the server response.<\/p>\n<h2>\u00bb Conclusions<\/h2>\n<p>We have found Kotlin a solid alternative to Java development for both client and server sides. It&#8217;s relatively easy to get started with and it&#8217;s definitely less strict and verbose than Java. Paired with its functional style, modern approach to OOP and interoperability with Java, it is a great tool for developing with SmartFoxServer and building multiplayer apps and games.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is the third and final chapter of our explorations with Kotlin and SmartFoxServer 2X. After building the first Kotlin extension in part one and creating a basic client app in part two we&#8217;re now completing the picture with a client\/server example.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[],"_links":{"self":[{"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/posts\/736"}],"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=736"}],"version-history":[{"count":13,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/posts\/736\/revisions"}],"predecessor-version":[{"id":753,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/posts\/736\/revisions\/753"}],"wp:attachment":[{"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/media?parent=736"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/categories?post=736"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/tags?post=736"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}