OFPEC Forum

Editors Depot - Mission Editing and Scripting => ArmA - Editing/Scripting Multiplayer => Topic started by: D007 on 25 Jul 2008, 06:28:59

Title: How do servers save players info for games like Sahrani life and evolution?
Post by: D007 on 25 Jul 2008, 06:28:59
I would really like to add this capability to games I make and host.
Could someone please point me in the right direction?

I spent like 5 hours looking for things regarding this issue, but either im blind.
Or there just isn't much about it XD.

I just want to save players money and nothing else.
I hope thats not to to hard.

so yea.. anyone got a link,script, editable mission? lol.. anything..
a direction you can point me in to get what I'm looking for maybe?
I'd appreciate it.. thank you.
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: ModestNovice on 27 Jul 2008, 01:50:10
I HAVE BEEN LOOKING for this FOR EVER as well, yet no luck either  :dunno:


I have had a look in Evo, but this relies on an Array.

The only big thing I know is :
OnPlayerConnected...

has something to do with it.

Code: [Select]
_name = _this select 0;//Get the name of the player to find stats
pscore = 0;//Set Score to 0
_max = count scores;//Count the score from the array
_i = 0;//Set sumthin here xD

//_i less then the count from array, add to your score
while {_i < _max} do {_unit = scores select _i;if (_unit == _name) then {pscore = (scores select (_i+1))};_i = _i + 2;}

allvar = [end,opar,osom,ocay,oort,ocor,obag,oobr,oepo,omas,opit,odol,lives];
allvar_packed = str (allvar);


Spooner? Mandoble? Wolfrug?

Any ideas?
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: D007 on 27 Jul 2008, 04:00:22
yep..lol...

All I have been able to find out is that you need another folder that is saved independently of the game.
A folder that is not part of arma but arma uses it for saves.
So when the server restarts, they use that folder again and it initiates the get player Id script and so forth.

I herad that there may be problems with duplicated Id's however making two people with the same id's information overwrite each others when they log on.
I wish people could be more willing to help people like us out..lol..
I mean why make such an awesome script then hang onto it just for yourself and your maps?
Pretty selfish if you ask me.
everything I make goes to a pbo then armaholic or anyone who even asks me.. hell I'll even email people who ask me for things personally..
I know someone has a script all written out and directions on where to put what folders and how to reference them etc etc etc..
but their just holding onto it..
all that animosity between great maps and great mission makers is just hurting the arma community..
wish more people would be less selfish.
but I'll keep digging and If i ever do see anything I will let ya know asap.



Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: ModestNovice on 27 Jul 2008, 06:02:07
appreciate it.

Will do the same  ;)
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: D007 on 24 Aug 2008, 17:26:02
Can anyone maybe point us in the right direction on how to do this? lol.
Would very much appreciate it. :)
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: Spooner on 24 Aug 2008, 18:06:02
You are both asking entirely different questions:
* DaChevs: How to save a player's data between player logins in a single mission, as used by Sahrani Life and Evolution. For a start, it is usual to set the mission as persistent ("persistent=1;" in description.ext) so that the mission won't end if all the players logged off. Otherwise, when you returned later, the data would have been lost anyway when the server started the mission the second time. This is best done with publicVariable as you suspected. There is no absolute connection with onPlayerConnected, though you could use that to help determine when a new player has connected. There isn't a simple "plug-and-play" script for doing this, or I would give it to you. I never got around to doing it for SPON Money, or I would point you in that direction ;P

* D007: How to save data between different missions, including when a mission is restarted on a server. For this, look towards ArmALib (http://www.flashpoint1985.com/cgi-bin/ikonboard311/ikonboard.cgi?act=ST&f=70&t=73859) but be aware that this requires an exe running on the server, so is not generally useful for most mission developers, unless they have a dedicated server to use for it (that is why I've not even bothered looking at it...).

Quote from: D007
I mean why make such an awesome script then hang onto it just for yourself and your maps?
Pretty selfish if you ask me.

Well, for one, you are asking about between-mission recording, not between-logins-in-the-same-mission recording. Nevertheless, people making missions like SL and Evo write their scripts specifically for those missions and it can be a non-trivial to unhook these scripts and port them across to other missions. As someone who writes generic scripts, I can tell you that there is at least twice as much work involved in making, documenting and releasing a script which will work in any mission compared to making one that will only work for you in your own mission. However, there is nothing stopping you backwards engineering how they did it, and replicating that, or even asking the authors.
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: Mr.Peanut on 24 Aug 2008, 21:15:14
These mods both use DSTS (http://www.armaholic.com/page.php?id=847) to save data server side. This external app is great for many applications. I have used it to dump position data from artillery to calculate trajectories.

Added event handler to artillery that calls this script:
Code: [Select]
_missile = nearestObject [vehicle player, _this select 4];
if (isNull  _missile)  exitWith {};
g_type = typeOf _missile;

g_wdir =  (_this select 0) weaponDirection (_this select 1);
g_theta = (g_wdir select 0) atan2 (g_wdir select 1);
g_phi = 90 - acos (g_wdir select 2)/sqrt((g_wdir select 0)^2+(g_wdir select 1)^2+(g_wdir select 2)^2);
g_initialpos = [(getPosASL vehicle player) select 0, (getPosASL vehicle player) select 1, 0];

hint format ["%1\n%2\n%3 %4", velocity _missile, g_type, g_theta, g_phi];

g_time = [];
g_wind = [];
g_vel = [];
g_vectorUp = [];
g_vectorDir = [];
g_pos = [];
g_time = [];
while {not isNull  _missile} do
{
   g_time = g_time + [time];
   g_vel = g_vel + [velocity _missile];   
//   g_wind = g_wind + [wind];   
//   g_vectorUp = g_vectorUp + [vectorUp _missile];   
//   g_vectorDir = g_vectorDir + [vectorDir _missile];
   g_pos = g_pos + [getPosASL _missile];   
   sleep 0.01;
};
hint format ["%1", count g_pos];
[] exec "writedata.sqs"

writedata.sqs
Code: [Select]
_data = format ["#%1 %2 %3 %4",g_type,g_theta,g_phi,g_initialpos]
_result = loadfile format ["::FILE WRITE ""C:\TEMP\TEST04.TXT"" ""FALSE"" ""%1""", _data]
_n = count g_pos
_i = 0
#loop
   _data = format [" %1  ", g_time select _i]
   _str = format [" %1 %2 %3 ", g_pos select _i select 0, g_pos select _i select 1, g_pos select _i select 2]
   _data = _data + _str
   _str = format [" %1 %2 %3 ", g_vel select _i select 0, g_vel select _i select 1, g_vel select _i select 2]
   _data = _data + _str
;   _str = format [" %1 %2 %3 ", g_wind select _i select 0, g_wind select _i select 1, g_wind select _i select 2]
;   _data = _data + _str
;   _str = format [" %1 %2 %3 ", g_vectorUp select _i select 0, g_vectorUp select _i select 1, g_vectorUp select _i select 2]
;   _data = _data + _str
;   _str = format [" %1 %2 %3\n", g_vectorDir select _i select 0, g_vectorDir select _i select 1, g_vectorDir select _i select 2]
;   _data = _data + _str
   _i=_i+1
   _result = loadfile format ["::FILE WRITE ""C:\TEMP\TEST04.TXT"" ""TRUE"" ""%1""", _data]
~0.00001
if (_i < _n) then {goto "loop"}
hint "done"
Because ArmA caches sqf scripts, you must use sqs scripts, or a sqf hack described on the DSTS forum. The applications are limitless. For example Spooner could hook it into his logger and dump an actual log file. The only hitch IIRC is whether you can detect via script that DSTS is available. A try-catch block could be used to do this.
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: Spooner on 24 Aug 2008, 22:34:38
Yes, DSTS is a system that predated ArmALib, but is pretty limited in comparison. I didn't realise that SL and Evo had implemented DSTS hooks in the standard mission though (Certainly, most people playing those missions won't be doing it on DSTS-equipped servers and will just be using the simple publicVariabled data recording). Sorry for misleading there...

try-catch doesn't work as you'd expect. Catch only catches variables that you have thrown manually via throw. It has nothing to do with ArmA's internal error system.
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: ModestNovice on 25 Aug 2008, 00:30:36
ah right, I suspected, and actually found this DSTS but really had no idea how to use it. But, only one question is, since it writes a file into a folder, isnt possible for someone to go in there and change the value, and when they connect they have billions of dollars??? :scratch:


Whoops! ...Stupid DaChevs, the files would be on the server  :-[
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: D007 on 25 Aug 2008, 10:00:58
You are both asking entirely different questions:
* DaChevs: How to save a player's data between player logins in a single mission, as used by Sahrani Life and Evolution. For a start, it is usual to set the mission as persistent ("persistent=1;" in description.ext) so that the mission won't end if all the players logged off. Otherwise, when you returned later, the data would have been lost anyway when the server started the mission the second time. This is best done with publicVariable as you suspected. There is no absolute connection with onPlayerConnected, though you could use that to help determine when a new player has connected. There isn't a simple "plug-and-play" script for doing this, or I would give it to you. I never got around to doing it for SPON Money, or I would point you in that direction ;P

* D007: How to save data between different missions, including when a mission is restarted on a server. For this, look towards ArmALib (http://www.flashpoint1985.com/cgi-bin/ikonboard311/ikonboard.cgi?act=ST&f=70&t=73859) but be aware that this requires an exe running on the server, so is not generally useful for most mission developers, unless they have a dedicated server to use for it (that is why I've not even bothered looking at it...).

Well, for one, you are asking about between-mission recording, not between-logins-in-the-same-mission recording. Nevertheless, people making missions like SL and Evo write their scripts specifically for those missions and it can be a non-trivial to unhook these scripts and port them across to other missions. As someone who writes generic scripts, I can tell you that there is at least twice as much work involved in making, documenting and releasing a script which will work in any mission compared to making one that will only work for you in your own mission. However, there is nothing stopping you backwards engineering how they did it, and replicating that, or even asking the authors.


Lol I'm sure you looked at sahrani lifes files then.
I have, extensively.. they made that mission and the files there in intentionally hard to decipher.
Their file system and referencing system are so in depth.
that if you didn't start as a mission maker for that mission, it will take you a week just to find out what the layout is like and how to access things in any sort of timely manner..lol

City life was however very kind in their methods :).
thank you city life..lol..

I spent weeks looking at those SL files. XD..
Believe me it's not that I haven't tried to reverse engineer it..
I wouldn't be here asking the "how do i" question If I hadn't first tried to do it myself.
I know a lot of people come here and just ask people to write scripts for them but that's not the way I work.

If I ask any question here, you can bet for at least 24 hours of actual work time.
I have tried to get that particular script working lol..
Usually more like 2 days pass before I ask anyone anything.
way I see it is if you don't rack your brain learning it, you will never retain the info you learned anyway.
getting info easy, just lets you forget it easy. :P..

saving info just for one mission, until the server restarts, would be just fine for starters though..
I'm just trying to make it easy servers who get the missions my brother and I make.
So they and I, can easily incorporate the save script.
It's just a great piece of rpg

But I have checked forms and biki and wiki and Bi and comref and and..lol..
I'm just stumped..


Thanks for all the hard work you must of put into the spon script by the way.
Huge benefit things like that give the community.
Works like a charm for Quarantine Unleashed.
and you didn't horde it all for yourself..lol..

thank you guys very much for your insight.
I Will look into all of these methods..
If anyone has a script that might show an example I'd sure appreciate it but np if not.
We'll just wee what we can see.
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: Mr.Peanut on 25 Aug 2008, 15:09:22
Might be I was wrong about Sahrani Life, but I am fairly certain Evo was made in part  as a demonstration of DSTS. Without an external app you cannot safeguard persistent data if the server goes down.

@Spoon:
Quote
try-catch doesn't work as you'd expect. Catch only catches variables that you have thrown manually via throw. It has nothing to do with ArmA's internal error system.
How is it used if it is not used for error trapping?

@D007:If you want data saved between logins for a continuous mission, you first need to decide what data you want saved. You then create an array for each player holding the name of the player and the data you want. You then make another larger array containing all the arrays for each player. You will have two such arrays. One for the players connected, and one for players who have disconnected. According to the ComRef the onPlayerDisconnected passes a variable _name to the script called, which I presume is the players name (but I have not tested this). So whenever a player disconnects you remove the subarray with their data from the players connected array, and add it to the players disconnected array. When that player reconnects you do the opposite. When a new player connects you add a new entry for them in the player connected array.

In your init.sqf you call a script only on the server. That means this script will only be run once, on the server, when the mission is first started. This script creates the player connected array, and fills it with your initial values for each player and publicVariables it.

The final step is to make sure the the player connected array is synchronised between all clients and the server. Since the publicVariable command now works with strings and arrays, I think all you need to do is publicVariable the player connected array each time it is change either on the server or on a client. Overuse of the publicVariable command can cause network lag, so make sure you use it only when required.

This is how I would approach the situation. External apps like ArmALib and DSTS need only be run on the server. They allow data storage in an SQL type database. Even if using them you would need to build a system to manage, synchronise and save your data.

Final word. If your data is not shared between clients (e.g. Bob does not need to know how much money Karl has) you don't need to publicVariable the whole player connected array, but you have to create a way for each client to update their data on the server within the player connected array. This adds another level of complication.

This probably does not help much, and writing it I see the need for such a system to be submitted to ofpec. But it won't be by me...  :whistle:

Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: Spooner on 25 Aug 2008, 15:59:44
It isn't useful for managing ArmA's internal errors, but it could be used to make your own error management system:
Code: [Select]
try
{
    // Do stuff
    if (not (_fish in _allowedValuesOfFish)) then { throw "Bleh! Fish is not right!" };
    // Do more stuff, which will not happen if something is thrown before this.
}
catch
{
   hint _exception;
};

This is actually exactly the way try/catch/throw works in vanilla C/C++. It is only in higher level languages, such as C#, Java or Python, or when C/C++ is extended (e.g. to Visual C++ or Borland C++) that exception management works as you are probably used to.

I'm sure the original Evo pre-dated DSTS (or at least had nothing to do with it), though I'd not be surprised if the the latest official, or third-party, versions used DSTS, since true persistence in Evo would be a good example of what you can achieve with DSTS.
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: D007 on 25 Aug 2008, 20:17:27
wow thats more to sink my teeth into than I realized.  ???

I'll have to give it a shot.. Just trying to save spon's cash really is all.
Will be an adventure for sure..lol..
At least I have an understanding of the depth
and necessities I need to look into.

If there are any scripters who might want to help with this for Quarantine Unleashed,
I'd sure appreciate it.
It's something I could learn to do.
I'm sure in time and by looking at existing files.
But learning from scratch is going to take a bit of time.
All of my time is currently consumed by updating the new releases :(.

Worse comes to worse I'll get into it when I can
and situate it for Quarantine Unleashed.
V1.1 coming out very soon, with lots of good new stuff.

But that's a bunch of great info.
Thank you :).

Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: Mr.Peanut on 26 Aug 2008, 02:10:02
Well, I started to poke around at this and realised half the crap I was trying to do was already in SPON_CORE(i.e. updated arrays of players, players' names, unique ids). At that point I stopped. Spooner could easily throw something like this together (i.e. mission persistent player data array with keyword index) in no time.
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: ModestNovice on 26 Aug 2008, 05:46:07
rofl  :D

Spooner, you got some splainin to do!

jkjk, yeh, the DSTS is not that bad, but how do install the exe on my server????

And he says something about like Net 1.1, or DSTS will not work, BUT he doesnt even say what Net is  :weeping:
Im so confused... :(
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: D007 on 26 Aug 2008, 07:49:20
U da man Spon.. the arma world needs you...    :clap:
Me.. I read your money script and That's all it takes for me to go back to updating releases..
the project is just to broad.

There's just to much info for me to absorb in any kind of timely manner.
I just don't have the time to figure this out and
to update the mission releases and bug fixes.
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: Mr.Peanut on 26 Aug 2008, 14:06:28
And he says something about like Net 1.1, or DSTS will not work, BUT he doesnt even say what Net is  :weeping: Im so confused... :(
As spooner said armalib is a more recent implementation than dsts so you should try using it. I had not heard of armalib until this thread. In addition dsts is not being developed anymore.
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: i0n0s on 26 Aug 2008, 18:31:57
.Net (http://en.wikipedia.org/wiki/.NET_Framework)
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: Spooner on 26 Aug 2008, 19:08:50
@Mr Peanut
Actually, all the SPON_player_* arrays are generated locally, so aren't actually updated across the network (this has advantages and disadvanges, of course; the main reason I have left it the way it is because this way allows stuff like the SPON Map addon to be client-side only).

Yes, I could do this, though perhaps not as "easily" as you imply, but I'm already busy with 100 other things (and I'd put it into SPON Money if I ever got around to doing it, but I've been promising to update SPON Money for a loooong time, so... ;P). I'll see what help I can put in on this thread, but I don't think I'm going to develop this whole system right now.
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: Mr.Peanut on 26 Aug 2008, 21:18:02
@spoon
How do you determine the new players when they connect? You get _id and _name, but how do you determine what object they are? And is onPlayer(Dis)Connected run on all clients or just the server?

Your SPON_player_* arrays are generated locally, but they should be the same on all nodes, correct? I never realised the isPlayer command could be used to test whether any unit was a player, I thought it was equivalent to == player.
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: Spooner on 27 Aug 2008, 12:51:04
The arrays are not consistent across machines, since they are updated only every 15 seconds and I'm sure this will become out of sync. Even if they are consistent in what objects they contain, the order of items might not be consistent.

Interestingly, if you team-switch (selectPlayer) out of your player object, then both the AI you leave behind and your new body are considered to be isPlayer. I suspect that playable AI on missions where "AIDisabled = 0" are isPlayers too, but I haven't checked that, since I hate having friendly AI in missions *sighs*
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: Mr.Peanut on 27 Aug 2008, 14:54:19
I hate AI in game too, and the fact that JIP means you spawn into one. It is a sharp hot pain in the arse.

Does this mean it is impossible to have a list of players without using the onPlayer(Dis)Connected commands? I did not want to touch those since they do not stack (What was BI thinking?). Someone really needs to add a system to SPON CORE that manages a stack like this, similar to how the key event handles are managed. :P

I suppose one other solution is for each player, in the init.sqf, launch a script that checks an array of all playable units, and broadcasts which playable unit they are to the server using dynamic variables. The server would be initialised with a publicEventHandler for each possible client. But then, as you suggest, if would be impossible to detect players disconnecting. What a mess...
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: Mr.Peanut on 02 Sep 2008, 15:58:10
(Yes a double post but its content should be independent of my last post)

Posting WIP code here for comments/criticism. Yes I know it is not commented. :P

What I really need to know is if I am on the right track.  The plan is to let any editor placed named in-game object have a data array.  If desired, I will add functions to add or remove objects from the array. There is an array called SMB_PDS_master that contains the names of all the players and npc objects. This array is scanned to match a name to an master index. Each player/npc has a data array that is referenced by that master index. At present, dead objects still hold data. I decided against using one huge array for all data for all objects, because it complicated matters, even if it might be the more proper way to implement. :P

You specify the "key" by which you want to call your data e.g. "money". Then use the get/set functions:
[_unit, "money", 10] call SMB_PDS_fSetValue
_value = [_unit, "money"] call SMB_PDS_fGetValue

[ASIDE]Will the following line:
Code: [Select]
SMB_PDS_playersConnected = SMB_PDS_playersConnected + [SMB_PDS_PLAYERS select _playerIndex];work as intended? Or will it store only the present player object and lose it between death and respawn? I don't rely on that line of code, but it sure would be handy. I suspect that it is crap though.  :shhh:[/ASIDE]

Adding in ArmALib to make data permanent on the server is pretty easy, though my (dis)connected functions would be different. Since ArmALib can detect itself, this would not be a problem. ArmALib is for windows servers only.


smb_pds\smb_pds_init.sqf
Call this near the top of your init.sqf with [] call compile preProcessFileLineNumbers "smb_pds\smb_pds_init.sqf"
Code: [Select]
#define SMB_PDS_PREFIX = "SMB_PDS_ARRAY_"
// User Defined
#define SMB_PDS_PLAYERS = [p1, p2, p3, p4, ...]
#define SMB_PDS_NPCS = [npc1, npc2, ...]
#define SMB_PDS_KEYS = ["Money","Pride",...]
#define SMB_PDS_DEFAULTS = [0, 10,...]
// End User Defined

//Global variables
//{SMB_PDS_names = SMB_PDS_names + [_x];} forEach SMB_PDS_PLAYERS;// crap
SMB_PDS_playersConnected = [];
SMB_PDS_namesConnected = [];
SMB_PDS_storeKeys = [];
SMB_PDS_storeData = [];
SMB_PDS_master = SMB_PDS_PLAYERS + [SMB_PDS_NPCS];

//Define functions
SMB_PDS_fGetData = compile preProcessFileLineNumbers "smb_pds\smb_pds_fGetData.sqf";
SMB_PDS_fSetData = compile preProcessFileLineNumbers "smb_pds\smb_pds_fSetData.sqf";

// Load store, if available, on server
if (isServer) then
{
    SMB_PDS_fOnPlayerConnected = compile preProcessFileLineNumbers "smb_pds\smb_pds_fOnPlayerConnected.sqf";
    SMB_PDS_fOnPlayerDisconnected = compile preProcessFileLineNumbers "smb_pds\smb_pds_fOnPlayerDisconnected.sqf";
    onPlayerConnected "[_name, _id] call SMB_PDS_fOnPlayerConnected;";
    onPlayerDisconnected "[_name, _id] call SMB_PDS_fOnPlayerDisconnected;";
};
nil;

smb_pds\smb_pds_fGetData.sqf
Code: [Select]
private ["_unit", "_key", "_value", "_nameList", "_masterIndex", "_keyIndex"];
_unit = _this select 0;
_key = _this select 1;
_nameList = [];
{_nameList = _nameList + [_x];} forEach SMB_PDS_master;
_masterIndex = _name find _nameList;
if (_masterIndex > -1) then
{
    _keyIndex = _key find SMB_PDS_KEYS;
    if (_keyIndex > -1) then
    {
        call compile format ["_value = " + SMB_PDS_PREFIX + "%1 select %2];", _masterIndex, _keyIndex];
    };
};
_value;

smb_pds\smb_pds_fSetData.sqf
Code: [Select]
private ["_unit", "_key", "_value", "_nameList", "_masterIndex", "_keyIndex"];
_unit = _this select 0;
_key = _this select 1;
_value = _this select 2;
_nameList = [];
{_nameList = _nameList + [_x];} forEach SMB_PDS_master;
_masterIndex = _name find _nameList;
if (_masterIndex > -1) then
{
    _keyIndex = _key find SMB_PDS_KEYS;
    if (_keyIndex > -1) then
    {
        call compile format [SMB_PDS_PREFIX + "%1 set [%2, %3];", _masterIndex, _keyIndex, _value];
        call compile format ["publicVariable """ + SMB_PDS_PREFIX + "%1"";", _masterIndex];
    };
};
nil;

smb_pds\smb_pds_fOnPlayerConnected.sqf
Code: [Select]
private ["_name", "_id", "_nameList", "_masterIndex", "_playerIndex", "_storeIndex"];
_name = _this select 0;
_id = _this select 1;
_nameList = [];
{_nameList = _nameList + [_x];} forEach SMB_PDS_PLAYERS;
_playerIndex = _name find _nameList;
if (_playerIndex > -1) then
{
    _nameList = [];
    {_nameList = _nameList + [_x];} forEach SMB_PDS_master;
    _masterIndex = _name find _nameList;
    SMB_PDS_playersConnected = SMB_PDS_playersConnected + [SMB_PDS_PLAYERS select _playerIndex];
    SMB_PDS_namesConnected = SMB_PDS_namesConnected + [_name];
    _storeIndex = _name find SMB_PDS_storeKeys;
    if (_storeIndex > -1) then
    {
        SMB_PDS_storeKeys = SMB_PDS_storeKeys - [_name]; 
        call compile format [SMB_PDS_PREFIX + "%1 = SMB_PDS_storeData select %2;", _masterIndex, _storeIndex];
        call compile format ["SMB_PDS_storeData = SMB_PDS_storeData - [[" + SMB_PDS_PREFIX + "%1]];", _storeIndex];
    }
    else
    {
        call compile format [SMB_PDS_PREFIX + "%1 = SMB_PDS_DEFAULTS;", _masterIndex];
    }
    call compile format ["{publicVariable _x} forEach [""" + \
        SMB_PDS_PREFIX + "%1"", ""SMB_PDS_playersConnected"", ""SMB_PDS_namesConnected""], masterIndex];"
};
nil;

smb_pds\smb_pds_fOnPlayerDisconnected.sqf
Code: [Select]
private ["_name", "_id", "_nameList", "_masterIndex", "_playerIndex"];
_name = _this select 0;
_id = _this select 1;
_nameList = [];
{_nameList = _nameList + [_x];} forEach SMB_PDS_PLAYERS;
_playerIndex = _name find _nameList;
if (_playerIndex > -1) then
{
    _nameList = [];
    {_nameList = _nameList + [_x];} forEach SMB_PDS_master;
    _masterIndex = _name find _nameList;
    SMB_PDS_playersConnected = SMB_PDS_playersConnected - [SMB_PDS_PLAYERS select _playerIndex];
    SMB_PDS_namesConnected = SMB_PDS_namesConnected - [_name];
    SMB_PDS_storeKeys = SMB_PDS_storeKeys + [_name]; 
    call compile format ["SMB_PDS_storeData = SMB_PDS_storeData + [[" + SMB_PDS_PREFIX + "%1]];", _masterIndex];
    {publicVariable _x} forEach ["SMB_PDS_playersConnected", "SMB_PDS_namesConnected"];
};
nil;
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: Spooner on 02 Sep 2008, 17:14:15
You seem to be on the right sort of track with this.

Using separate 1-D arrays rather than a large data-structure is good, because it allows you to use find (otherwise you spend a lot of time in iterating through a big structure).

The immediate issue with this is that you can only ever set values on one machine, ideally the server. For example, should the player sell something and get then set, he might overwrite the get/set from someone else transferring money to him. If you are just using numbers, then an add and subtract could more safely replace set. You still have to make sure that subtractions are only run on one machine, or values could go below 0. Alternatively, having subtract with a callback function when it has been confirmed that the value can be reduced.

While I was scanning the scripts, I noticed a few things you might appreciate:

Since publicVariable just takes a string,
Code: (smb_pds\smb_pds_fSetData.sqf) [Select]
call compile format ["publicVariable """ + SMB_PDS_PREFIX + "%1"";", _masterIndex];
can be simplified to:
Code: (smb_pds\smb_pds_fSetData.sqf) [Select]
publicVariable (SMB_PDS_PREFIX + (str _masterIndex));

You can also simplify:
Code: (smb_pds\smb_pds_fGetData.sqf) [Select]
call compile format ["_value = " + SMB_PDS_PREFIX + "%1 select %2;", _masterIndex, _keyIndex];
to (and although I like using + for strings too, it is confusing, for me at least, when you use format and + at the same time).
Code: (smb_pds\smb_pds_fGetData.sqf) [Select]
_value = call compile format ["%1%2 select %3;", SMB_PDS_PREFIX, _masterIndex, _keyIndex];

Code: (smb_pds\smb_pds_fOnPlayerDisconnected.sqf) [Select]
_nameList = [];
{_nameList = _nameList + [_x];} forEach SMB_PDS_master;
is equivalent to
Code: (smb_pds\smb_pds_fOnPlayerDisconnected.sqf) [Select]
_nameList = [] + SMB_PDS_master;
Though when you do this, you just use the new array once for a find, so no reason to copy the array in the first place.
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: h- on 02 Sep 2008, 17:56:17
Ok, this is getting too MP:ey to be at the advanced section..  :P

Moved.
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: hoz on 02 Sep 2008, 18:31:19
Sorry to butt in here but I saw this...

Quote
For a start, it is usual to set the mission as persistent ("persistent=1;" in description.ext)

Are you sure this isn't a server side setting?

Biki (http://community.bistudio.com/wiki/server.cfg)

I don't see it mentioned in the description.ext.

Sorry to hijack the discussion.
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: Spooner on 02 Sep 2008, 19:14:53
Sorry, yes, I wasn't thinking :whistle:
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: Mr.Peanut on 02 Sep 2008, 20:12:17
Thanks for the feedback. I've noticed a few other bugs as well. Christ what a quagmire! I was trying to avoid having to broadcast all data arrays every 15 seconds, but perhaps that is unavoidable. If it is unavoidable, it makes more sense to pack everything into one array.

The real question becomes how to stack requests to the server that fall in between the server broadcasting its status as locked or unlocked. Should data operations be serialized, or for maximum flexibility should compiled code strings be PV'd?

Other ponderables. When a player disconnects the AI retains the name until someone else spawns in?
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: B2KDragon on 02 Sep 2008, 23:23:23
or u could look out for armalibery which does all that cant remeber were i got it though lol :scratch:
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: D007 on 03 Sep 2008, 00:41:00
as for weather arma considers ai you spawn into even with disableai =true isplayers.
I'd say yes..
Unintentionally ended up finding that one out..
Or I'm missing something.. which is entirely possible.

seems when someone joins this mission they may go into the cut scene,
which is reserved for dead players..

trigger executes at "not alive player" to setpos the body to a graveyard and a cut scene.
then hidebody the corpse in the CS.

players that join may sometimes go straight into this cut scene.
Even though they had not died at all.

am I crazy or does that mean that body is always present?
So the body is never seen until someone joins?
then it is killed and taken over by the player?

and that transition from alive, to not live and back to alive, causes them to go into the CS?

and hot dayum Peanut..lol..
you went right into it didn't ya. :)..
cheers man..

Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: ModestNovice on 03 Sep 2008, 01:14:02
wow....Great Job Mr.Peanut :)

I can't wait, as for two of the servers I host my mission are linux = can't use armalib :(
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: Mr.Peanut on 03 Sep 2008, 14:13:36
It has bugs! So it does not work yet....

Quote
The immediate issue with this is that you can only ever set values on one machine, ideally the server. For example, should the player sell something and get then set, he might overwrite the get/set from someone else transferring money to him. If you are just using numbers, then an add and subtract could more safely replace set.
This is an issue for player-player interactions, but I might ignore those completely. Even SPON_Money is entirely client side isn't it?
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: Spooner on 03 Sep 2008, 14:38:27
Indeed it is, but people keep kicking me to fix it (I've actually already made a rack of improvements to it, but they haven't been finished, tested, etc. Please don't hold your breath though, since my enthusiasm for individual projects is fickle at best!)
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: Mr.Peanut on 03 Sep 2008, 14:55:19
So what are people asking for? Are they asking for player-player interactions? With player-player I have trouble imagining any system that is fool-proof.  The only (simple) way I can think of is locking the server to perform only one interaction at a time. Would people be satisfied with that? Somehow I doubt it. The only other way is to lock the server so that no other interactions can take place with the two clients presently interacting. One step further would be locking based on interaction type and client pair.  :blink: 
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: Spooner on 03 Sep 2008, 16:37:04
The big requests are for player-to-player money transfers and persistent bank balance (mainly just mission-persistent, but also using ArmALib). Not got anywhere with any of those, because I was working on different things (such as an abstract object system, but Wolfrug made one of those).
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: Mr.Peanut on 03 Sep 2008, 17:18:03
(such as an abstract object system, but Wolfrug made one of those)
Where is that? In his inventory system?
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: Spooner on 03 Sep 2008, 17:21:22
Yes, by abstract objects, I mean stuff that doesn't have an object to represent it, but you can manipulate, like money or "driving license". Also things like the "un-attached" attachments I use in SPON Attachments.
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: Mr.Peanut on 03 Sep 2008, 19:28:09
So for a server-client persistent data model, do you think the following would be sufficient?

1) Transactions are classified by channels. Each channel is named by [player name/index, data field name/index].
2) Only one channel of each name can be open at a time on the server.
3) When the server receives a transaction request it PV's which channels are now blocked.
4) If the server receives a request for a blocked channel, it declines the request and PV's this failure back to the sender.
5) Both get and set attempts on clients wait until the needed channel is free i.e. channel name variable is either nil or True
6) If a client's request is declined, it retries x times.
7) When each channel is blocked a server side script will timeout the block if it takes too long.


edit: Two different methods:
1) Each client sends multiple transactions to server at once. Server broadcasts which channels to lock.
2) Each client sends one transaction at a time. Client broadcasts which channels it is locking.

I am becoming a blathering idiot....  :blink: ...I should just read an RFC or two on asynchronous data transfers...
and then shoot myself... :goodnight:


Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: David.B. on 05 Sep 2008, 01:41:43
gl Mr. Peanut. myself and bishop are just finishing up quarantine. i keep checking up on this post to see if any luck yet so we can use it.. mission will probably be out without it ; ;,but its understandable.. tough work and not much credit doesnt motivate does it XD.. anyway keep up the good work.. thanks for the help on everything..hope you figure it out.
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: Mr.Peanut on 05 Sep 2008, 15:07:10
This is the state of affairs. If all your data is client-side(i.e. no item/money exchange between players), I have something ready to test, and least for mission persistent data(i.e.as long as server does not crash and mission is not restarted). It extremely light weight, without any error handling. Your problem will be integrating it with SPON_Money, but that is no biggy. PM me an email address and I'll send you what I have, with a few notes on usage and poking it into SPON_Money.

For true client data sharing(i.e. full item/money exchange between players) the issue is more complicated, as you would really like to store all data on the server and verify each transfer. It gets a bit messy for my ability.   
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: Spooner on 05 Sep 2008, 16:27:04
DaChevs doesn't use SPON Money ;P
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: Mr.Peanut on 05 Sep 2008, 16:27:39
I know, but D007 does.
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: Spooner on 05 Sep 2008, 16:42:00
Oops, lost track.
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: D007 on 06 Sep 2008, 23:42:59
I know, but D007 does.

Yes I do.. Yes I do..

Oh Peanut version 1.1 is out now.. If your trying to incorperate that into this..
"which we would greatly appreciate lol"
you may want to get the new version at armaholic key word quarantine.
Thanks a bunch.. cheers. :)
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: Mr.Peanut on 07 Sep 2008, 00:14:32
Okay.
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: ModestNovice on 07 Sep 2008, 05:04:59
Yes, but you motivated me to make my own Spooner, and all though I am not the best, I fell in love with creating my own mission/scripts. I thank all of you, especially Spooner and Myke, for helping me so much, and giving me the confidence to actually start this stuff myself. I appreciate you guys not tossing me in the dirt, and telling me to keep at it! Cuz it truly does pay-off :)

Thank you guys.


And Mr.Peanut, can ya send me a version of it? Thats all I am looking to do, I just want to keep what happened in the mission as it is playing, a restart is a chance for the admin to clear out the chaos.
But really, I don't think every transfer is required. Its more of, with my transfers it adds to ur inventory array, so basically, maybe as you disconnect, or maybe a trigger to save ur stats, so ya hit it just before you leave and it stores you vehicles (an array), your money (two variables) and items are not to important as they are cheap and available everywhere, but I think the most important thing to everyone is keeping your money because it takes so long to build it up ;)


Thanks a bunch for your work on this Mr.Peanut :)
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: Mr.Peanut on 07 Sep 2008, 23:53:58
Took an hour to install the ArmA server on my laptop today. So many damn patches...  :blink:
Anyhow, tried testing what I had(I forgot how much it sucks to MP test.. yuk....) and it did not work very well. I had read on the 6th sense MP wiki that onPlayerDisconnected fires(on the server) for each player in turn at the very start of the mission. This does not seem to be the case in my tests today. Back to the drawing board!
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: ModestNovice on 08 Sep 2008, 00:17:23
ugh, thts wierd.


Well, how bout scrap the onPlayerDisconnected and just have it saves stats every 5 mins or user generated (ie the trigger)?
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: Mr.Peanut on 09 Sep 2008, 01:59:39
Well, I am really losing my mind. I have attached a demo. Everything seems like it should be so straight forward...  :blink:

What is happening is that the players are not being assigned the default values when they connect SMB_PDSL_fOnPlayerConnected.  Shortly after each player joins or leaves, a hint pops up and shows the player data being saved is "[string]", so whatever I am doing wrong is assigning a null string to the player data array. In the demo there are 3 player slots,and each player's data should be stored in arrays SMB_PDSL_DATA_x where x is 0,1, or 2, depending on the slot.  There are three radio triggers each of which should display the master name list(which they do) and the data array for a slot. This does not work either.

Any help would be appreciated. I am missing something fundamental ...

Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: Spooner on 10 Sep 2008, 11:55:12
In the init file, you do:
Code: [Select]
if (not isNull player) then
But although this is true in SP and hosted MP at the start of the mission, it is false in dedicated clients until they have properly synced (it is actually also initially false on hosted MP if you are running from an addon, so bear that in mind). You probably want to do something like this:
Code: [Select]
[] spawn
{
    if (not server) then { waitUntil { alive player } }; // If not the server, you must be dedicated client, so wait for sync.
    if (not isNull player) then
    { ... }
};

Doing things like this:
Code: [Select]
call compile SMB_PDSL_PREFIX + str(SMB_PDSL_playerIndex) + " = SMB_PDSL_DEFAULTS;";
Will actually be parsed as if it were:
Code: [Select]
(call (compile SMB_PDSL_PREFIX)) + (str SMB_PDSL_playerIndex) + " = SMB_PDSL_DEFAULTS;";
So make use of brackets to make it clear to the interpreter what you actually mean ("str(SMB_PDSL_playerIndex)", "str SMB_PDSL_playerIndex" and "(str SMB_PDSL_playerIndex)" are all exactly equivalent, since commands bind very high, so use the one you like best):
Code: [Select]
call compile (SMB_PDSL_PREFIX + str SMB_PDSL_playerIndex + " = SMB_PDSL_DEFAULTS;");

Anyway, some food for thought for you to be getting on with...As far as I looked (just in the init file).
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: Mr.Peanut on 10 Sep 2008, 15:42:16
Thanks. I will test those suggestions. One of the things that drives me crazy about the BI interpreter is that its parsing rules for left to right or right to left are not clear. Not clear or consistent to me anyways. When I first started with OFP I used excessive parenthesis so I would not have to worry about it, but that can also lead to ugly illegible code, so I have been trying to pare down.
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: Spooner on 10 Sep 2008, 15:50:31
It is not the right-to-left-ness that is at issue. It is that all commands have a very high precedence, higher than operators like +, etc. Maybe I should compile a proper precedence list to make things clearer, though unless you understand the concept of operator precedence, which most people don't, I can't see it being too helpful.

I think this precedence issue this is one reason most people prefer format over + for concatenating strings ;P
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: Mr.Peanut on 10 Sep 2008, 16:06:12
Quote
It is not the right-to-left-ness that is at issue. It is that all commands have a very high precedence
Ah you computer science types and your fancy talk! Just wait, some day you will be trying to do work in physical oceanography and I will have the last laugh!

Code: [Select]
0.5 + _myArrayofScalars select 0
Code: [Select]
_myArrayofScalars select 0 + 0.5
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: Spooner on 10 Sep 2008, 17:06:42
OK, select has a lower precedence than +, so not all commands have higher precedence than mathematical operators (this whole argument is off-topic ;P).
Title: Re: How do servers save players info for games like Sahrani life and evolution?
Post by: Mr.Peanut on 11 Sep 2008, 16:11:08
Not an argument(is there a pun in there somewhere), a discussion.

Thanks for sorting me with the call compile and concatenation. I would otherwise have lost interest in continuing. Also thanks for the isNull player warning. I miss the days when JIP was but a misspelling of a slang verb arisen from bigotry and racism.