dreadedentity 278 Posted September 17, 2014 Hello all, I'm trying to create a mission kind of like a "Life" server. I want everything to be persistent, however, so database interactions are necessary. But the database will be stored on the server machine so I need a way to broadcast the variables across the network. Fortunately, a solution for this already exists in arma. Unfortunately, I don't understand how it works at all. Basically, when a player joins my game, the server should retrieve his stats, then the server will publicVariableClient to the client that just connected and sync his stats (if they exist). My problem is that I'm getting an undefined variable error in the little script I wrote. Here's what I've got so far: init.sqf "stats" addPublicVariableEventHandler { money = _this select 1; }; if (isDedicated) then { call compile preProcessFile "\inidbi\init.sqf"; //using @iniDB for read/write ["connect", "onPlayerConnected", { missionNamespace setVariable ["stats", ["PLAYERINFO", _uid, "MONEY", "STRING"] call iniDB_read]; _id publicVariableClient "stats"; }] call BIS_fnc_addStackedEventHandler; }; if (!isServer) then { sleep 2; hintSilent format["%1", money]; }; Like I said above, the error I'm getting is "Undefined variable in expression: money". So I guess I'm having trouble getting the variable saved on the client machine. Can anybody help me shed some light on this? Share this post Link to post Share on other sites
Heeeere's johnny! 51 Posted September 17, 2014 (edited) I'm not sure if I understand you logic correctly. Please correct me if I'm wrong. So the PVEH for "stats" should be clientside, just as the "if(!isServer)" statement, right? And the code in between is serverside? So, right away, I could tell you this: Firstly, telling from your stats array, it should be "money = _this select 2;". Secondly, you should place your hintSilent statement behind a while loop: while {isNil "money"} do { sleep 1; }; hintSilent format ["%1", money]; I'm not sure though about this "missionNamespace setVariable" thing as I don't know if that's necessary when using "publicVariable" commands, but I think it isn't. Anyway, try that and please let us know the result. Regards, waltenberg aka Johnny Edited October 11, 2014 by waltenberg Share this post Link to post Share on other sites
dreadedentity 278 Posted September 17, 2014 Well the database part is irrelevant, I'm just trying to understand how to pass a variable from server to client. That's not an array, it's just a variable. iniDB_read takes 4 parameters and returns one. I could replace that line with: stats = ["PLAYERINFO", _uid, "MONEY", "STRING"] call iniDB_read]; and it does the same thing. To explain a little more about how iniDB handles things, the first parameter is the filename. So if I opened up PLAYERINFO.ini, it would look like this: ["MYPLAYERID"] //second argument MONEY="3000" //third argument //fourth argument is variable type you want to return I have every reason to believe I've coded the database interaction correctly, I'm just not sure how to use publicVariable. Share this post Link to post Share on other sites
Viba 1 Posted September 18, 2014 publicVariableClient requires the owner id of the player object so it knows who to send the data to, you can get it by doing: (owner playerobject). On your own client that would simply be (owner player). On the server you either have to find the desired player object by scripts or have the client send somekind of loadrequest that contains the clients player object, or you could use the mission.sqm defined name for the player slot the player is occupying. publicvariable broadcasts a variable and it's value across the network, a defined publicvariableeventhandler for that variable is triggered across all clients (and server), but not on the client/server that broadcasted it. So essentially publicvariable sends variable to everyone, publicvariableclient sends variable from server to a specific client, publicvariableserver sends variable from client to server only. Share this post Link to post Share on other sites
Larrow 2827 Posted September 18, 2014 Is this just a typo in your post? "\inidbi\init.sqf" should be "\inidb\init.sqf" Where are you testing this? At the moment you have it set for dedicated usage only. I prefer to do this the other way round. As in the player once he is initialized asks for his stats, just saves any timing issues with initialization, if the player is asking for his stats then he is definitely going to be initialized. //isServer so will also work for hosted server if (isServer) then { //Init iniDB call compile preprocessFile "\inidb\init.sqf"; //server function for sending stats to client fnc_getStats = { _who = objectFromNetId (_this select 0); _uid = _this select 1 stats = ["PLAYERINFO", _uid, "MONEY", "STRING"] call iniDB_read; (owner _who) publicVariableClient "stats"; }; }; //client - including hosted client if (!isDedicated) then { //waituntil the player exists waitUntil {!isNull player}; //set up a PVEH for retrieving stats "stats" addPublicVariableEventHandler { money = _this select 1; hintSilent money; }; //Ask server for stats [ [netId player, getPlayerUID player], "fnc_getStats", false] call BIS_fnc_MP; }; untested code just for examples sake, although i have used iniDB set up this way. The netID stuff is not really needed but atleast i know i am sending a reference to a unique object and is not going to be interpreted wrong. I realize your end goal is a dedicated with iniDB but for testing purposes having Hosted available could save some hassle. Share this post Link to post Share on other sites
dreadedentity 278 Posted September 18, 2014 Larrow I think iniDB updated and changed the @modname, confirming @inidbi in my computer. It was a long road with many problems, but I was somehow able to use my second pc to run the dedi from, that's my test enviornment. I came to a similar conclusion as you, and made the client ask the server for his info, so the server will get the client's session ID (there really needs to be a better way to do this btw). Rewrote my init.sqf to look like this "stats" addPublicVariableEventHandler { money = _this select 1; }; if (isDedicated) then { call compile preProcessFile "\inidbi\init.sqf"; "PV_ClientID" addPublicVariableEventHandler { stats = ["PLAYERINFO", _uid, "MONEY", "STRING"] call iniDB_read; (_this select 1) publicVariableClient "stats"; }; // ["connect", "onPlayerConnected", { // missionNamespace setVariable ["stats", ["PLAYERINFO", _uid, "MONEY", "STRING"] call iniDB_read]; // _id publicVariableClient "stats"; // }] call BIS_fnc_addStackedEventHandler; }; if (!isServer) then { PV_ClientID = owner player; publicVariableServer "PV_ClientID"; sleep 5; hintSilent format ["%1", money]; }; It's pretty messy and I'm still getting the "Undefined variable in expression: money" script error. I'll look over your code, but the secret to publicVariable is just eluding me for some reason. Share this post Link to post Share on other sites
Larrow 2827 Posted September 19, 2014 Thats not going to work DE. Several problems:- You never send a UID, _uid in the server PVEH is undefined. owner player on a client will be a crap result 0, owner only works from the server. Share this post Link to post Share on other sites