Jump to content
code34

iniDBI - Save and Load data to the server or your local computer without databases!

Recommended Posts

In regards to the ""Inidb: read failed not enough parameter"" error I'm getting:

["Houses", _x, "Owner"] call iniDB_read

INI:

[House1]
Owner="None"
OwnerName="None"

Function: iniDB_read

Prototype: [databasename, section, variablename, ("STRING"|"ARRAY"|"SCALAR")] call iniDB_read;

Usage: ["myDatabaseFile", "sectionname", name player, "STRING"] call iniDB_read;

Usage: ["myDatabaseFile", "sectionname", "position", "ARRAY"] call iniDB_read;

Usage: ["myDatabaseFile", "sectionname", "health", "SCALAR"] call iniDB_read;

Missing a type parameter :)

Share this post


Link to post
Share on other sites
I thought the type param wasnt necessary if the data type was string?

lol it was written on the first page :)

Notes: fourth parameters musts exist (not like in iniDB where it is optionnal)

i check for the 4 parameters it s a best practice to use variable type

Share this post


Link to post
Share on other sites

Hi,

First of all, thank's a lot for your work.

I've got a little problem and my searches about it were not concluent so I hope you can help me ;)

So here is the problem.

I need to save players loadout on the server without making players install inidbi and it doesn't work.

What I've done : (On a dedicated server)

Installed @inidbi in the server root (all folders and the dll are okay)

Added -mod=@inidbi (RTP says the inidbi.pbo is loaded)

Got a simple test mission with just a soldier. Here are the files :

INIT.SQF :

if (isServer) then 
{
	call compile preProcessFile "\inidbi\init.sqf";
	fn_getLoadout = compile preprocessFileLineNumbers 'save\loadout\fn_getLoadout.sqf';
	fn_setLoadout = compile preprocessFileLineNumbers 'save\loadout\fn_setLoadout.sqf';
	diag_log "inidbOK";
	diag_log "inidbOK";
	diag_log "inidbOK";
	diag_log "inidbOK";
	diag_log "inidbOK";
	diag_log "inidbOK";
	diag_log "inidbOK";
	diag_log "inidbOK";
	diag_log "inidbOK";
	diag_log "inidbOK";
};
if (!isServer) then 
{
player setVariable["profileName", profileName, true]; 
[[[player],"save\fn_dataSaveClient.sqf"],"BIS_fnc_execvm",false,true] spawn BIS_fnc_MP;
};

save\fn_dataSaveClient.sqf

//
//	script by loki
//	Oct. 2013
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

_unit = _this select 0;
_puid = getPlayerUID _unit;

if(!isServer) exitWith {};
if(!alive _unit) exitWith {};
// Allow users with multiple profiles to make new profiles and have new lives
// We want to use CRC hashes for the name because some people have spaces, weird characters or some other stuff so it's just better this way.
_profileName = _unit getVariable["profileName", ""];

if(_profileName == "") exitWith {};

_unitFileName = format["%2_%1", _puid, (_profileName call iniDB_CRC32)];

// this will save to the same file, but use different sections for each side
// i.e. persistent data will carry over _per side player has played.
_sectionTitle = format["%1 - playerDatas", name _unit];
_sectionTitle2 = format["%1 - playerGear", name _unit];

//main header
[_unitFileName, "account", "Profile Name", _profileName] call iniDB_write;
[_unitFileName, "account", "Player GUID", getPlayerUID _unit] call iniDB_write;

//server
[_unitFileName, "server", "Server Start Time", serverTime] call iniDB_write;

//mission
[_unitFileName, "mission", "Saved at Location", position _unit] call iniDB_write;
[_unitFileName, "mission", "Saved at Direction",getDir _unit] call iniDB_write;

//playerStats
[_unitFileName, _sectionTitle, "Player Side", side _unit] call iniDB_write;
[_unitFileName, _sectionTitle, "Player Group", group _unit] call iniDB_write;
[_unitFileName, _sectionTitle, "Player Moral", morale _unit] call iniDB_write;
[_unitFileName, _sectionTitle, "Player Grid Position", mapGridPosition _unit] call iniDB_write;
[_unitFileName, "mission", "Alive", 1] call iniDB_write;

[_unitFileName, _sectionTitle, "Player Score", score _unit] call iniDB_write;
[_unitFileName, _sectionTitle, "Player Rank", rank _unit] call iniDB_write;
[_unitFileName, _sectionTitle, "Player Rating", rating _unit] call iniDB_write;
[_unitFileName, _sectionTitle, "UnitDescription", getDescription _unit] call iniDB_write;


//MASTER GEAR SAVE LOADOUT
//primary weapons
[_unitFileName, _sectionTitle2, "loadout", ([_unit] call fn_getLoadout)] call iniDB_write;

fn_getloadout does not need to be showed because I think the error does not come from it.

Technically, when I start the mission on the server and get in game, my actual soldier loadout must be saved but it's not and here is the error I get in the server RPT in loop :

 5:14:25 Error in expression <data];
_data = call compile _data;

if((_data select 0)) then {
_data select 1;
>
5:14:25   Error position: <_data select 0)) then {
_data select 1;
>
5:14:25   Error Undefined variable in expression: _data
5:14:25 Error in expression <["crc", _this] call iniDB_HashFunction;
_this;
};

iniDB_MD5 = {
_this = ["md5",>
5:14:25   Error position: <_this;
};

iniDB_MD5 = {
_this = ["md5",>
5:14:25   Error Undefined variable in expression: _this

Addon loading proof ?

==== Loaded addons ====

dta\bin.pbo - unknown
dta\core.pbo - 0
dta\languagecore_f.pbo - 67042
C:\Arma3Server\@inidbi\addons\inidbi.pbo - unknown

And I get the exactly same error when I uset he inidbi test mission available on armaholic page

Thank's by advance for you help I work on this from 5 hours ago and I'm sorry for my really bad english

Have a good day

Edited by Mash6

Share this post


Link to post
Share on other sites

hi,

i recommand you to don't use the checksum functions:

_unitFileName = format["%2_%1", _puid, (_profileName call iniDB_CRC32)];

I don't review thoses functions that are in the original state of inidb. So the code is unchecked, and i had in mind few months ago to delete them.

Share this post


Link to post
Share on other sites

Ok i'll change that but have you got any idea for my error because it doesnt work in all case

Share this post


Link to post
Share on other sites

the errors you copy are from the checksum functions. If you ve got other, can you copy them here ?

Share this post


Link to post
Share on other sites

I am new ArmA 3 server and I loaded this onto my server in order to be able to do player saving. I went in to test this and if I went prone and hit escape it displayed "Player Saved". I then exited back out all the way and then logged back into the game on my server and it let me choose my player type like normal and then it went to the screen that says welcome to a3wasteland. Please wait while your client initializes." And it goes no further. But if I hit escape and then choose respawn the game starts up but just like a new player or like I was killed. Which I guess when you respawn you are killing yourself. I am very new at this and I just have a basic knowledge of the script usage. If anybody can please help me with this it would be greatly appreciated.

Share this post


Link to post
Share on other sites

I am very new at this and I just have a basic knowledge of the script usage. If anybody can please help me with this it would be greatly appreciated.

Example:

server\init.sqf

call (compile (preprocessFileLineNumbers "\inidbi\init.sqf"));

_scriptHandler = [] execVM "server\eventHandlers\init.sqf";

waitUntil {
	sleep 0.1;

	scriptDone _scriptHandler
};
server\eventHandlers\init.sqf

onPlayerProfileReceipt = compileFinal (preprocessFileLineNumbers "server\eventHandlers\onPlayerProfileReceipt.sqf");
onPlayerProfileRequest = compileFinal (preprocessFileLineNumbers "server\eventHandlers\onPlayerProfileRequest.sqf");

"playerProfile" addPublicVariableEventHandler {call onPlayerProfileReceipt};
"playerUid" addPublicVariableEventHandler {call onPlayerProfileRequest};
server\eventHandlers\onPlayerProfileReceipt.sqf

_uid = playerProfile select 0;
_profile = playerProfile select 1;

playerProfile = nil;

if ((count _profile) > 0) then {
	[_uid, "profile", "damage", _profile select 0] call iniDB_write;
	[_uid, "profile", "position", _profile select 1] call iniDB_write;
	[_uid, "profile", "magazines", _profile select 2] call iniDB_write;
	[_uid, "profile", "weapons", _profile select 3] call iniDB_write;
};

true
server\eventHandlers\onPlayerProfileRequest.sqf

playerProfile = [];

if (playerUid call iniDB_exists) then {
	{
		_variableName = _x select 0;
		_variableType = _x select 1;

		_variableValue = [playerUid, "profile", _variableName, _variableType] call iniDB_read;

		playerProfile pushBack _variableValue;
	}
	forEach [
		["damage", "SCALAR"],
		["position", "ARRAY"],
		["magazines", "ARRAY"],
		["weapons", "ARRAY"]
	];
};

{if ((getPlayerUID _x) == playerUid) exitWith {(owner _x) publicVariableClient "playerProfile"}} forEach playableUnits;

playerProfile = nil;
playerUid = nil;

true
player\init.sqf

resetProfile = compileFinal (preprocessFileLineNumbers "player\functions\resetProfile.sqf");
setUpPlayer = compileFinal (preprocessFileLineNumbers "player\functions\setUpPlayer.sqf");

profileBroadcaster = compileFinal (preprocessFileLineNumbers "player\scripts\profileBroadcaster.sqf");

playerUid = getPlayerUID player;

publicVariableServer "playerUid";

playerUid = nil;

player globalChat "Profile is requested";

waitUntil {
	sleep 0.1;

	!(isNil "playerProfile")
};

if ((count playerProfile) > 0) then {
	player globalChat "Profile is found";

	playerDamage = playerProfile select 0;
	playerPosition = playerProfile select 1;
	playerMagazines = playerProfile select 2;
	playerWeapons = playerProfile select 3;
}
else {
	player globalChat "Profile is not found";

	call resetProfile;
};

playerProfile = nil;

call setUpPlayer;

[] spawn profileBroadcaster;
player\scripts\profileBroadcaster.sqf

while {true} do {
	sleep (2 * 60);

	_weapons = (weapons player) - ["ItemCompass", "ItemMap", "ItemRadio", "ItemWatch"];

	playerProfile = [
		getPlayerUID player,

		[
			damage player,
			[position player, direction player],
			magazines player,
			_weapons
		]
	];

	publicVariableServer "playerProfile";

	playerProfile = nil;

	player globalChat "Profile is saved";
};
Hope it will help. Edited by Schatten

Share this post


Link to post
Share on other sites

Hi, i got a problem when i tried to load the data from server.

I am using addAction which is attached in an object to Load the data.

this allowDamage false;
this addAction ["<t color='#55ff55'>Load Profiles</t>", "player\build.sqf"];

and here is the build.sqf

if(!isServer) exitWith {};
playa = _this select 1;

PosPlaya = ["IWK_db", getPlayerUID playa, "Position", "ARRAY"] call inidb_read;

IDclient = owner playa;
IDclient publicVariableClient "PosPlaya";
playa setPos PosPlaya;

but when I run it, nothing happen to player. anyone can help me to solve this problem?

Edited by azams

Share this post


Link to post
Share on other sites

2 azams,

iniDBI(IMPROVED) - A simple server-side database extension using INI files

So you need to send request to server, server needs to retrieve data from database and send them to player.

Share this post


Link to post
Share on other sites
2 azams,

So you need to send request to server, server needs to retrieve data from database and send them to player.

yes, the player wants to get the data from server. its already 2 days looking around this forum and google but still got no solution. can you explain more how to retrieve data from server and send it back to player?

thanks.

Share this post


Link to post
Share on other sites
its already 2 days looking around this forum and google but still got no solution. can you explain more how to retrieve data from server and send it back to player?

Do not you helped my previous post?

Share this post


Link to post
Share on other sites

im sorry, i've tried your script but i found some missing file on your post (ex: setUpPlayer.sqf and spawnPlayer.sqf).

and also i want to know the logic rather than just copying the script.

Share this post


Link to post
Share on other sites
im sorry, i've tried your script but i found some missing file on your post (ex: setUpPlayer.sqf and spawnPlayer.sqf).

These files are specific to each mission.

server\init.sqf same like in my previous post.

server\eventHandlers\init.sqf

onRequestPosPlaya = compile (preprocessFileLineNumbers "server\eventHandlers\onRequestPosPlaya.sqf");

"requestPosPlaya" addPublicVariableEventHandler {(_this select 1) call onRequestPosPlaya};

server\eventHandlers\onRequestPosPlaya.sqf

PosPlaya = [];

_id = 0;

_dbName = _this select 0;
_uid = _this select 1;

if (_dbName call iniDB_exists) then {PosPlaya = _this call iniDB_read};

{if (_uid == (getPlayerUID _x)) exitWith {_id = owner _x}} count playableUnits;

_id publicVariableClient "PosPlaya";

true

In player\init.sqf you need to add this code:

isPosPlayaReceived = false;

_scriptHandler = [] execVM "player\eventHandlers\init.sqf";

waitUntil {
sleep 0.1;

scriptDone _scriptHandler
};

player\eventHandlers\init.sqf

onReceivePosPlaya = compile (preprocessFileLineNumbers "player\eventHandlers\onReceivePosPlaya.sqf");

"PosPlaya" addPublicVariableEventHandler {[] call onReceivePosPlaya};

player\eventHandlers\onReceivePosPlaya.sqf

isPosPlayaReceived = true;

true

player\build.sqf

_playa = _this select 1;

requestPosPlaya = ["IWK_db", getPlayerUID _playa, "Position", "ARRAY"];

publicVariableServer "requestPosPlaya";

_startTime = time;

waitUntil {
sleep 0.1;

isPosPlayaReceived or {(time - _startTime) > 10}
};

if (isPosPlayaReceived) then {
if ((count PosPlaya) > 0) then {_playa setPos PosPlaya};

isPosPlayaReceived = false;
};

i want to know the logic rather than just copying the script

Logic is simple:

you need to send request to server, server needs to retrieve data from database and send them to player.

I think it can be clearly seen in player\build.sqf.

Edited by Schatten

Share this post


Link to post
Share on other sites

thank you Schatten. you really saved my time.

By your helps, now I got the logic.

here is the edited script from yours:

isProfileFound = false;
isProfileLoaded = false;
isProfileNotFound = false;

_scriptHandler = [] execVM "player\eventHandlers\init.sqf";

waitUntil {
sleep 0.1;

scriptDone _scriptHandler
};

requestPlayerProfile = getPlayerUID player;

_startTime = time;

publicVariableServer "requestPlayerProfile";

waitUntil {
sleep 0.1;

isProfileFound or {isProfileNotFound} or {(time - _startTime) > 10}
};

if (isProfileFound) then {
waitUntil {
	sleep 0.1;
	player setDamage (playerProfile select 0);
	player setDir (playerProfile select 1);
	player setPos (playerProfile select 2);
	_wep = playerProfile select 3;
	{
		player addWeapon _x;
	} foreach _wep;
	player addVest (playerProfile select 4);
	player addUniform (playerProfile select 5);
	player addbackpack (playerProfile select 6);
	_wep = playerProfile select 7;
	{
		player addMagazine _x;
	} foreach _wep;
	player addHeadgear (playerProfile select 8);
	_wep = playerProfile select 9;
	{
		player addPrimaryWeaponItem _x;
	} foreach _wep;
	_wep = playerProfile select 10;
	{
		player addSecondaryWeaponItem _x;
	} foreach _wep;
	_wep = playerProfile select 11;
	{
		player addHandgunItem _x;
	} foreach _wep;
	_wep = playerProfile select 12;
	{
		player addItem _x;
	} foreach _wep;
	_wep = playerProfile select 13;
	{
		player assignItem _x;
	} foreach _wep;

	isProfileLoaded
};
} else {
cutText ["Profile NOT Found","PLAIN",5];
};

switch (true) do {
case isProfileFound: {
	isProfileFound = false;
	isProfileLoaded = false;
};
case isProfileNotFound: {isProfileNotFound = false};
};

Share this post


Link to post
Share on other sites
How can I save bases with this this thing in my custom mission?

Look how it is implemented here.

Share this post


Link to post
Share on other sites

Hi guys,

I have a problem with retrieving playerdata from a dedi server. Saving to server works fine using this method, but the LoadPlayer function in oo_pdw.sqf doens't seem to get the proper values returned from "fn_LoadFromServer".

Here's a link to my code:

https://drive.google.com/file/d/0B-rvnkrtT-3ma2RDTVE2SEhXbEU/view?usp=sharing

Can anyone please help me out here.. thanks in advance!

Share this post


Link to post
Share on other sites
Hi guys,

I have a problem with retrieving playerdata from a dedi server. Saving to server works fine using this method, but the LoadPlayer function in oo_pdw.sqf doens't seem to get the proper values returned from "fn_LoadFromServer".

Here's a link to my code:

https://drive.google.com/file/d/0B-rvnkrtT-3ma2RDTVE2SEhXbEU/view?usp=sharing

Can anyone please help me out here.. thanks in advance!

hi,

can you copy the error, or the call code part with parameters

Share this post


Link to post
Share on other sites

It doesn't give any errors. It simply doens't work the way I think it does (maybe I just fail at programming). Player data won't get loaded they just spawn with default loadout/position etc..

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×