Gothic Online Forums
[New G2O][Client-Side] LocalStorage - Printable Version

+- Gothic Online Forums (https://archive.gothic-online.com)
+-- Forum: Scripting (English) (https://archive.gothic-online.com/forum-11.html)
+--- Forum: Resources (https://archive.gothic-online.com/forum-14.html)
+---- Forum: Modules (https://archive.gothic-online.com/forum-32.html)
+---- Thread: [New G2O][Client-Side] LocalStorage (/thread-2748.html)



[New G2O][Client-Side] LocalStorage - Patrix - 08.05.2020

*Introduction:



Hi, many of us propably wanted to have some kind of possibility to store some data on client-side.
It would be very useful for things like: user settings, and similar to write them directly on client-pc.
The read operation will much more efficient, because those config data wouldn't be transfered via packets from server.

However, there are some problems with the client-side, that can't be easily avoided.
First of all, what if someone (scripter) tries to override some file using some interface similar to file?
We can avoid this type of problem by taking the responsibility from scripter to serialize/deserialize data.
But there is also the second problem, what if scripter would try to write as much data as he can to intentionally take as much hardware memory as possible?
This problem is also really easily to bypass by simply applying max size limit for a file.

And that's what my module does.
It gives you a possibility to write/read some data for a client, in pretty much "safe" way.
In later part of this topic i will cover the usage of this module in squirrel, installation, as well as how the module itself works.

Download



*Module requirements



- Module is using Visual Studio 2015 toolset (v140), client needs to install Microsoft Visual C++ 2015 Redistributable Package.
- Module requires (maximum) 1 MB for LocalStorage.json on your hard drive (read more if you want to know why 1 MB)
- Module often use more than 1 MB of RAM
- Module can slow down game load time due to parsing file (if the file is really large)
- Module can slow down exiting from game due to saving file (if the file is really large)



*How this module works?



The module itself is based on the idea of localStorage introduced int HTML5.
You can read more in this tutorial how this mechanism works, it's pretty straightforward.
The special object called LocalStorage gives you possibility to store the data on client-pc without expiration time. The programmer of the website can only interact with the LocalStorage object.
This object doesn't give you the way to save/read the data directly from sort of a file, or local database, it handles this task for you. You can only add some data to the LocalStorage or get the data from it.

Now, when we know what the LocalStorage is, let's focus on the module implementation. How does it work?
It's pretty simple actually, when you connect to the server via launcher, the first thing which G2O does is saving some data into windows registry.
What data? Your nickname, the ip_port of the server which you are connecting to, and the server world (to avoid double loading of the world problem which occurs in GMP mod).
After that, the client gets launched and it makes special directory made only for specific server. This directory is made for saving some files specifc for server which we are connecting to.
Interesting enough the exact location of this folder looks like this: PathToYourGame/Multiplayer/store/ip_port/ where "ip" is the addres, for example 127.0.0.1
and "port" is for example 28970. Knowing that we can simply read ip_port entry from the registry, to access this special directory made for the server.
The interesting fact is that this directory won't be deleted by G2O, so those folders are perfect for storing the data specifc for one server (for example: LocalStorage file Smile).

My module simply creates in this directory file "LocalStorage.json". Every data that user puts in LocalStorage will eventually be placed in this folder.
This file is saved periodically when some changes were made in LocalStorage object. The json format isn't using any whitespace characters to preserve as much bytes as possible.
File is also saved automatically when player exits from game, to prevent data loss.
Also, as i mentioned in introduction section, to prevent scripter from generating big files, the module introduced the file size limit.
That means, that when scripter tries to add new data to the LocalStorage, first the current size of the JSON is checked.
If the size after putting new data into JSON is larger than the limit, the data is simply not putted into JSON format.
By JSON i mean the memory representation, not the file it self.

Conclusion:
- LocalStorage.json file is stored in GamePath/Multiplayer/store/ip_port/ directory
- LocalStorage.json file size limit is 1 MB
- LocalStorage is saved periodically only when content of the JSON object is changed (this won't lag the game)
- LocalStorage is also saved when player exits from game only when cont of the JSON object is changed



*List of functions:



string or null LocalStorage.key(int idx) // gets the LocalStorage key via numeric index (index should be a value from 0 to n). If the key isn't present at specified intex, it returns null
int LocalStorage.len() // returns the number of entries stored in LocalStorage
auto LocalStorage.getItem(string key) // returns the value stored in key. This function can return: null, bool, int, float, string, array, table. null is return only if the value doesn't exists at specified index (key)
void LocalStorage.setItem(string key, auto value) // tries to add entry to LocalStorage. This function may fail if maximum file size is exceeded. Warning! value cannot be null!
void LocalStorage.removeItem(string key) // removes specified entry from LocalStorage based on key
void LocalStorage.clear() // Removes all entries from LocalStorage.



*Installation:

Info: If you put your module inside subdirectory on the server, this subdirectory will be also included in Game/Multiplayer/Modules/ directory. You only need to create this subdirectory and put the module inside it
NOTE! As a server creator you are responsible for installing this module on client's PC's. Modules aren't downloaded by default from server due to security reasons.



Client:
Put the module inside this directory: PathToYourGame/Multiplayer/Modules/

Server:
Put your module inside your server directory, then add this line to your config.xml file:

PHP
  1. <module src="LocalStorage.dll" type="client" />





*Examples:



*Basic read & write:



Squirrel Script
  1. local playTimeSeconds // how long client was playing on server (in seconds)
  2.  
  3. addEventHandler("onInit", function()
  4. {
  5. playTimeSeconds = LocalStorage.getItem("playTimeSeconds") || 0 // or 0 simply prevents from assigning null value to playingTime variable, if item with this name doesn't exists
  6. })
  7.  
  8. setTimer(function()
  9. {
  10. // incrementing playTimeSeconds
  11. ++playTimeSeconds
  12.  
  13. // updating value in LocalStorage object
  14. LocalStorage.setItem("playTimeSeconds", playTimeSeconds)
  15. }, 1000, 0)





*Iterating through all keys



Squirrel Script
  1. addEventHandler("onInit", function()
  2. {
  3. for (local i = 0, end = LocalStorage.len(); i != end; ++i)
  4. print(LocalStorage.key(i)) // this will print all of the LocalStorage keys in client console
  5. })





*Iterating through all values



Squirrel Script
  1. addEventHandler("onInit", function()
  2. {
  3. for (local i = 0, end = LocalStorage.len(); i != end; ++i)
  4. {
  5. local key = LocalStorage.key(i)
  6. local value = LocalStorage.getItem(key)
  7.  
  8. print("[" + key +"] = "+ value) // this will print all of the LocalStorage key:value pairs in client console
  9. }
  10. })



I forgot to mention that module reports an error if the load won't be successfull with te detailed description what goes wrong.
Unfortunately specific error message will be shown from version 0.1.7+ (the only way from me, to report an error from module is to use "error" function in squirrel, and after this update this function allows to print custom errors in client console).