Author Topic: Saving Info in files  (Read 1674 times)

What is the best way to save information about multiple clients in one file?
For an example let's say a player earns 5 XP and I needed to save that so it wouldn't be lost
for the next time they join the server. And then the same thing happened with like 4 other players.
How would I be able to save that information using .txt files and then go back to it to retrieve
that information for the next time one of those players joins back?

UPDATE: okay I think I'm getting somewhere
Code: [Select]
funcion saveXP(%client)
{
%FW = new fileObject();
%FW.openForWrite("config/server/Ranks/XP.txt");
%FW.writeLine(%client.bl_id SPC %client.XP);
%FW.close();
%FW.delete();
}
I'm just completely lost on how I would retrieve that information to use it again in the server...
what if there's like 20 lines? how would I find that one specific line for the player?
« Last Edit: November 24, 2016, 03:09:29 PM by NAT3 »

Assuming %client has been set, something along the lines of:
Code: [Select]
%fo = new FileObject();
%fo.openForRead("config/server/Ranks/XP.txt");
while(!%fo.isEOF()) {
  %line = %fo.readLine();

  if(getWord(%line, 0) == %client.bl_id) {
    %client.XP = getWord(%line, 1);
    break;
  }
}
%fo.close();
%fo.delete();

However, you may find it more efficient to store values in individual files per BLID. It really depends on how often the file needs to be opened and closed. If it's something that loads only once, a single file should be fine. If you need to dynamically save and load each time a player joins or leaves, then separate files be user will be more efficient.

However, you may find it more efficient to store values in individual files per BLID. It really depends on how often the file needs to be opened and closed. If it's something that loads only once, a single file should be fine. If you need to dynamically save and load each time a player joins or leaves, then separate files be user will be more efficient.

This was my intention with Saver, but people didn't get it. However, saving a bunch of people at the same time did impact performance.

The game has a default add-on that is designed to save client's variables continuously, even when they leave the server (Script_Player_Persistence). When clients rejoin, this script will automatically set the clients's variables to what they were when they left. Below is an example of how to implement it in a server.cs file.

Code: [Select]
LoadRequiredAddOn("Script_Player_Persistence");
if(isFunction(RegisterPersistenceVar))
{
  RegisterPersistenceVar("storedMoney", false, "");    //storedMoney is the variable that it will keep track of
  RegisterPersistenceVar("winCount", false, "");        //You can make it keep track of multiple variables
}

You have to run that once when you start the server, and then any changes to %client.storedMoney or %client.winCount will be saved.
It works by creating a txt file in config>server>persistence and continuously updating it. It's smart to occasionally back up this persistence.txt file because I think it can overwrite stuff if something weird happens on the server.

This is the method I used for pizza delivery gamemode to keep track of like 12 different player stats.
« Last Edit: November 25, 2016, 02:42:00 AM by Farad »

you could also use global variables e.g. $XP::Data[%blid] = %xp;
then export the global variables e.g. export("$XP::Data*");
then just execute the exported .cs every time the server starts and save it every time the server closes or set it on a schedule perhaps.

Using global vars, export, and exec is probably the fastest and easiest method. Just make sure you're not using any spaces or certain chars within the []s.
For example...
$Example[%ip] = 1;
%ip being something like 127.0.0.1, this would work fine, up until you try to load it, because it's going to try executing:
$Example127.0.0.1 = 1;
Which of course, results in a syntax error.

Using global vars, export, and exec is probably the fastest and easiest method. Just make sure you're not using any spaces or certain chars within the []s.
For example...
$Example[%ip] = 1;
%ip being something like 127.0.0.1, this would work fine, up until you try to load it, because it's going to try executing:
$Example127.0.0.1 = 1;
Which of course, results in a syntax error.
You can use getSafeVariableName to make sure the contents doesn't screw up with the variables.

I'd do something like this:
Code: [Select]
if(isFile("config/server/XP/data.cs")) {
  exec("config/server/XP/data.cs");
}

function storeXP()
{
   export("$XPSave_*","config/server/XP/data.cs");
}

//Function to add XP to client, by carrying out an action or whatever, call it with giveXP(%client,%amt);
// %client is the client, obviously. %amt is the amount of XP.
function giveXP(%client,%amt)
{
   $XPSave_[%client.BL_ID] += %amt; // Add to variable (You could also deduct by using minus numbers.)
   storeXP();
}

package LoadXP
{
function gameConnection::autoAdminCheck(%client)
{
if($XPSave_[%client.BL_ID]) {
                    messageClient(%client, '', "\c6Welcome back,\c3" SPC %client.name SPC"\c6. Your XP (\c3" @ $XPSave_[%client.BL_ID] @ "\c6) has been restored.");
                    %client.XP = $XPSave_[%client.BL_ID];
                } else {
                    %client.XP = 0;
                }               
return Parent::autoAdminCheck(%client);
}
};
activatePackage(LoadXP);

The export function will export every variable that has a prefix of "$XPSave_"
The * works as a wildcard and in the data.cs file, it'll record it in variable form.
For example:
Code: [Select]
$XPSave_14911 = 31;
$XPSave_14553 = 33;
$XPSave_14552 = 43;

Also, returning a function that already exists is important.

You shouldn't call export every time a variable is changed. Just save it every few minutes or something like that.

Also, returning a function that already exists is important.
In this case, yes it is. And in almost all cases it's best to return it.

But you absolutely never need to when packaging serverCmd_/clientCmd_ functions.