{"id":2194,"date":"2022-01-20T09:55:54","date_gmt":"2022-01-20T09:55:54","guid":{"rendered":"https:\/\/smartfoxserver.com\/blog\/?p=2194"},"modified":"2022-01-20T10:04:08","modified_gmt":"2022-01-20T10:04:08","slug":"custom-room-storage-with-sfs2x-2-18","status":"publish","type":"post","link":"https:\/\/smartfoxserver.com\/blog\/custom-room-storage-with-sfs2x-2-18\/","title":{"rendered":"Custom Room Storage with SFS2X 2.18"},"content":{"rendered":"\n<p>Since the release of SmartFoxServer 2.18 we have introduced a way to override the default implementations for the <a href=\"http:\/\/docs2x.smartfoxserver.com\/AdvancedTopics\/room-persistence-api\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"Room Persistence API (opens in a new tab)\">Room Persistence API<\/a> so that they can be customized to your needs.<\/p>\n\n\n\n<p>Prior to this release we provided a <strong>file-based<\/strong> and a relational <strong>database-based<\/strong> storage mechanisms that could be used in conjunction with the API to save the state of multiple active Rooms.<\/p>\n\n\n\n<p>With the new release you can now create your own <strong>storage implementations<\/strong> and plug them into the <strong>Persistence API<\/strong>. In this short article we&#8217;ll walk you through what has changed and how you can create a custom storage class.<\/p>\n\n\n\n<!--more-->\n\n\n\n<h2>\u00bb The basics<\/h2>\n\n\n\n<p>If you are not familiar with the <strong>Room Persistence API<\/strong> we highly recommend to start with the <a rel=\"noreferrer noopener\" aria-label=\"fundamentals on our docs website (opens in a new tab)\" href=\"http:\/\/docs2x.smartfoxserver.com\/AdvancedTopics\/room-persistence-api\" target=\"_blank\">fundamentals on our docs website<\/a>.<\/p>\n\n\n\n<p>In our quick-start example from the docs we show how to initialize the API in your Extension&#8217;s <strong>init()<\/strong> method:<\/p>\n\n\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\npublic void init()\n{\n    \/\/Initialize Persistence API\n    getParentZone().initRoomPersistence(RoomStorageMode.FILE_STORAGE, new FileRoomStorageConfig());\n \n    \/\/...\n}\n<\/pre>\n\n\n\n<p>It&#8217;s a simple one-line call to the Zone&#8217;s <strong>initRoomPersistence()<\/strong> method, where we provide the <strong>RoomStorageMode<\/strong> and the relative configuration object.<\/p>\n\n\n\n<p>In <strong>SmartFoxServer 2X 2.18<\/strong> we have added a new mode called <strong>CUSTOM<\/strong> which, unsurprisingly, allows us to specify a custom implementation of the <strong>IRoomStorage<\/strong> interface.<\/p>\n\n\n\n<h2>\u00bb Three easy steps<\/h2>\n\n\n\n<p>To get started with the development of a custom storage class we need three ingredients:<\/p>\n\n\n\n<ul><li>an implementation of the <strong>IRoomStorage<\/strong> interface<\/li><li>a configuration object extending <strong>BaseStorageConfig<\/strong><\/li><li>one line in the Extension&#8217;s main <strong>init()<\/strong> method to set it all up<\/li><\/ul>\n\n\n\n<h3>Implementing IRoomStorage<\/h3>\n\n\n\n<p>The interface is relatively simple in its structure, even if it exposes a number of different methods:<\/p>\n\n\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\nvoid init(Zone zone, BaseStorageConfig cfg);\nvoid destroy();\t\n\nvoid saveAllRooms() throws SFSStorageException;\nvoid saveRoom(Room theRoom) throws SFSStorageException;\nvoid saveAllRooms(String groupId) throws SFSStorageException;\n\nCreateRoomSettings loadRoom(String name) throws SFSStorageException;\nList&amp;amp;lt;CreateRoomSettings&amp;amp;gt; loadAllRooms() throws SFSStorageException;\nList&amp;amp;lt;CreateRoomSettings&amp;amp;gt; loadAllRooms(String groupId) throws SFSStorageException;\n\nvoid removeRoom(String name) throws SFSStorageException;\nvoid removeAllRooms(String groupId) throws SFSStorageException;\nvoid removeAllRooms() throws SFSStorageException;\n<\/pre>\n\n\n\n<p>(You can read more details in the <a rel=\"noreferrer noopener\" aria-label=\"server side javadoc (opens in a new tab)\" href=\"http:\/\/docs2x.smartfoxserver.com\/api-docs\/javadoc\/server\/\" target=\"_blank\">server side javadoc<\/a>)<\/p>\n\n\n\n<p>Essentially there are an <strong>init()<\/strong> and <strong>destroy()<\/strong> method that manage the life cycle of the object and allow to create and dispose useful resources (e.g. a database driver, a connection pool etc.)<\/p>\n\n\n\n<p>Then we have the <strong>load<\/strong>, <strong>save<\/strong> and <strong>remove<\/strong> methods each coming in sets of three, depending if we&#8217;re dealing with a single Room, a selection of Rooms or all the Rooms.<\/p>\n\n\n\n<h3>Create a configuration object<\/h3>\n\n\n\n<p>Next we need a <strong>configuration object<\/strong> that can be populated with settings for our Storage logic. For instance if we were to read and write from a database we&#8217;d need a connection string to reach the DB server and probably a database name and table name.<\/p>\n\n\n\n<p>The base class for our configuration object is called <strong>BaseStorageConfig<\/strong> and comes pre-populated with a few global settings:<\/p>\n\n\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\npublic class BaseStorageConfig\n{\n\tpublic boolean storeInactiveRooms = false;\n\t\n\tpublic boolean storeRoomVariables = true;\n\t\n\tpublic boolean skipStaticRooms = true;\n\t\n\tpublic String customStorageClassName;\n}\n<\/pre>\n\n\n\n<p>Continuing with the example of a DB-based storage here&#8217;s how one could extend the class:<\/p>\n\n\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\npublic class MyDBStorageConfig extends BaseStorageConfig\n{\n\tpublic String connectionString;\n\n\tpublic String driverName;\n\t\n\tpublic String databaseName;\n\t\n\tpublic String tableName;\n}\n<\/pre>\n\n\n\n<p><strong>PLEASE NOTE<\/strong>: keep in mind that your custom Storage logic should honor the settings contained in the base class. In other words it should check the values of the base class&#8217; flags and filter out the relative data accordingly.<\/p>\n\n\n\n<h3>Putting it all together<\/h3>\n\n\n\n<p>When it&#8217;s time to deploy the storage classes we can include them in our <strong>Extension jar file<\/strong>. Next we can initialize the <strong>Room Persistence API<\/strong> as follows:<\/p>\n\n\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\npublic class CustomRoomStorageExtension extends SFSExtension\n{\n\t@Override\n\tpublic void init()\n\t{\n\t\tMyDBStorageConfig config = new MyDBStorageConfig();\n\t\tconfig.param1 = ...\n\t\tconfig.paramX = ...\n\t\tconfig.customStorageClassName = &quot;my.sfs2x.game.MyRoomStorage&quot;;\n\t\t\n\t\tgetParentZone().initRoomPersistence(RoomStorageMode.CUSTOM, config);\n\t}\n}\n\n<\/pre>\n\n\n\n<p>Notice the <strong>customStorageClassName<\/strong> property: it must provide the <a rel=\"noreferrer noopener\" aria-label=\"fully qualified name (opens in a new tab)\" href=\"https:\/\/docs.oracle.com\/javase\/specs\/jls\/se10\/html\/jls-6.html#jls-6.7\" target=\"_blank\">fully qualified name<\/a> of our <strong>IRoomStorage<\/strong> implementation. This will instantiate the storage class and allow us to invoke the <strong>Room Persistence API<\/strong> as needed.<\/p>\n\n\n\n<h2>\u00bb A complete example<\/h2>\n\n\n\n<p>To help you build a custom Room Storage class we have included the source code for our <strong>file-based Room Storage implementation<\/strong> so you can look at a simple practical example. Hopefully this will clarify some of the more abstract concepts we have outlined here.<\/p>\n\n\n\n<div class=\"wp-block-file\"><a href=\"https:\/\/smartfoxserver.com\/blog\/wp-content\/uploads\/2022\/01\/FileRoomStorage.zip\">FileRoomStorage<\/a><a href=\"https:\/\/smartfoxserver.com\/blog\/wp-content\/uploads\/2022\/01\/FileRoomStorage.zip\" class=\"wp-block-file__button\" download>Download<\/a><\/div>\n\n\n\n<p>If you have any doubts or questions on this subject feel free to get in touch with us through our <a href=\"https:\/\/smartfoxserver.com\/forums\/\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\" (opens in a new tab)\">support forums<\/a> and let us know.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Since the release of SmartFoxServer 2.18 we have introduced a way to override the default implementations for the Room Persistence API so that they can be customized to your needs. Prior to this release we provided a file-based and a relational database-based storage mechanisms that could be used in conjunction with the API to save [&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":[21,151,148,150,32,149,7,111],"_links":{"self":[{"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/posts\/2194"}],"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=2194"}],"version-history":[{"count":20,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/posts\/2194\/revisions"}],"predecessor-version":[{"id":2230,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/posts\/2194\/revisions\/2230"}],"wp:attachment":[{"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/media?parent=2194"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/categories?post=2194"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/tags?post=2194"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}