Shai
Member-
Content Count
5 -
Joined
-
Last visited
-
Medals
Community Reputation
10 GoodAbout Shai
-
Rank
Rookie
-
iniDB - Save and Load data to the server or your local computer without databases!
Shai replied to SicSemperTyrannis's topic in ARMA 3 - ADDONS & MODS: COMPLETE
I got a kludge working to get around the string length limitations on inidb. On server restart: LoadItemDatabase.sqf // @file Version: 2.0 // @file Name: LoadItemDatabase.sqf // @file Author: Reaper // @file Created: 2013-08-08 // @file Description: When the server starts, load items from the ObjectIndex.ini, which contains a count of possible ini files. // @file Args: Private ["_ObjType","_ObjPos","_ObjDirect","_ArrayCount","_NewVeh","_ObjVectorUp","_ObjVectorDir","_DBExists","_IniFile","_i","_ActiveObjects","_ObjINIArray","_DBIndex"]; _ObjINIArray = []; _ActiveObjects = []; _DBExists = "ObjectIndex" Call IniDB_Exists; Diag_Log Format ["LoadItemDatabase: _DBExists: %1",_DBExists]; //Pull the current index from the INI _DBIndex = ["ObjectIndex","ObjectIndex","DBIndex","NUMBER"] call IniDB_Read; Diag_Log Format ["LoadItemDatabase: _DBIndex: %1",_DBIndex]; //Ensure that we have something to load If (_DBIndex > 0) Then { // Build an array of file names based upon the _DBIndex For [{_i = 1}, {_i < (_DBIndex + 1)}, {_i = _i + 1}] do { _IniFile = Format ["%1_ObjArray",_i]; Diag_Log Format ["%1_ObjArray",_i]; _ObjINIArray = _ObjINIArray + [_IniFile]; }; Diag_Log Format ["LoadItemDatabase: Fully Constructed _ObjINIArray is %1",_ObjINIArray]; }; {// Filter through the array to find missing ini objects _iniExists = _x Call iniDB_Exists; Diag_Log Format ["LoadItemDatabase: Filtering Possible Objects - %1 Exists Returns %2", _x, _iniExists]; If !(_iniExists) Then { _ObjINIArray - _ObjINIArray - [_x]; Diag_Log Format ["LoadItemDatabase: Removing %1 from _ObjINIArray", _x]; }; } ForEach _ObjINIArray; { // check to see if the INI actually exists, to avoid errors // _iniExists = _x Call iniDB_Exists; // Diag_Log Format ["LoadItemDatabase: %1 exists returns %2", _x, _iniExists]; // Sleep 0.1; // check to see if the type has been set to "delete" //Retrieve all of the saved variables for the object. _ObjType = [_x,"ObjectInfo","_ObjType","STRING"] Call IniDB_Read; _ObjPos = [_x,"ObjectInfo","_ObjPos","ARRAY"] Call IniDB_Read; _ObjDirect = [_x,"ObjectInfo","_ObjDirect","SCALAR"] Call IniDB_Read; _ObjVectorUp = [_x,"ObjectInfo","_ObjVectorUp","ARRAY"] Call IniDB_Read; _ObjVectorDir = [_x,"ObjectInfo","_ObjVectorDir","ARRAY"] Call IniDB_Read; Sleep 0.1; Diag_Log Format["LOADING FROM ITEM DATABASE: _ObjType: %1 _ObjPos: %2: _ObjDirect: %3 _ObjVectorUp: %4 _ObjVectorDir: %5",_ObjType,_ObjPos,_ObjDirect,_ObjVectorUp,_ObjVectorDir]; //Create the object (vehicle) _NewVeh = createVehicle [_ObjType,_ObjPos,[],0,"None"]; // Set the position exactly, because CreateVehicle will fuck around with objects. _NewVeh setPos _ObjPos; //I'm trying this command to try and better capture it's location and direction _NewVeh setVectorDirAndUp [_ObjVectorDir,_ObjVectorUp]; // the Obj_DBIndex is a variable that contains the name of the database where the object info is stored. _NewVeh SetVariable ["Obj_DBIndex", _x, True]; _NewVeh setVariable ["objectLocked", True, True]; // Build a list of the active objects that are being loaded. _ActiveObjects = _ActiveObjects + [_NewVeh]; Sleep 0.1; } ForEach _ObjINIArray; ActiveObjects = _ActiveObjects; ObjINIArray = _ObjINIArray; DBIndex = _DBIndex; PublicVariable "ActiveObjects"; PublicVariable "ObjINIArray"; PublicVariable "DBIndex"; When an object is locked through the mouse wheel, it updates the global variable ObjectSaveRelay, which, through the Publicvariableeventhandler triggers this code: ObjSaving.sqf // @file Version: 2.0 // @file Name: ObjSaving.sqf // @file Author: Reaper // @file Created: 2013-08-08 // @file Description: When an object is locked, save it to the server. Since we're using // iniDB, I guess the easiest thing to do will be to save files as array elements. I tried // saving them in one long array, but there must be a max return limit on characters rom iniDB_Read, because after saving maybe two dozen // items, it would no longer read values back. // @file Args: Private["_NewObject","_ObjType","_ObjPos","_ObjDirect","_DBCheck","_ObjINIArrayEntry","_NewDBIndex","_ObjVectorUp","_ObjVectorDir"]; // ObjectSaveRelay has been updated, so store it to a private variable. _NewObject = ObjectSaveRelay; Sleep 0.1; _ObjType = TypeOf _NewObject; _ObjPos = Position _NewObject; _ObjDirect = Direction _NewObject; _ObjVectorUp = vectorUp _NewObject; _ObjVectorDir = vectorDir _NewObject; // Check to see if the object already has an array entry (unlocked and then relocked). // If the Obj_DBIndex variable isn't nil, use it for saving (object was previously saved, then unlocked) If !(isNil{_NewObject GetVariable "Obj_DBIndex";}) Then { _ObjINIArrayEntry = _NewObject GetVariable "Obj_DBIndex"; Diag_Log Format ["ObjSaving: _ObjINIArrayEntry is %1_ObjArray", _ObjINIArrayEntry]; }; // Object has never been saved If (isNil {_NewObject GetVariable "Obj_DBIndex"}) then { DBIndex = DBIndex + 1; PublicVariable "DBIndex"; _NewDBINdex = DBIndex; // Use the incremented index for the new object ini _NewDBIndex = Format ["%1_ObjArray",_NewDBIndex]; Diag_Log Format ["ObjSaving: Object has no INI array entry, it is being created as %1",_NewDBIndex]; _NewObject SetVariable ["Obj_DBIndex", _NewDBIndex, True]; ObjINIArray = ObjINIArray + [_NewDBIndex]; PublicVariable "ObjINIArray"; _ObjINIArrayEntry = _NewDBIndex; } else { _ObjINIArrayEntry = _NewObject GetVariable "Obj_DBIndex"; //ObjINIArray = ObjINIArray + [_NewDBIndex]; PublicVariable "ObjINIArray"; }; // Push the updated count into the database, so we know how many object entries have been made, to sort through // on server start. ["ObjectIndex","ObjectIndex","DBIndex",DBIndex] Call IniDB_Write; // create/update a database ini file for the object [_ObjINIArrayEntry,"ObjectInfo","_ObjType",_ObjType] Call IniDB_Write; [_ObjINIArrayEntry,"ObjectInfo","_ObjPos",_ObjPos] Call IniDB_Write; [_ObjINIArrayEntry,"ObjectInfo","_ObjDirect",_ObjDirect] Call IniDB_Write; [_ObjINIArrayEntry,"ObjectInfo","_ObjVectorUp",_ObjVectorUp] Call IniDB_Write; [_ObjINIArrayEntry,"ObjectInfo","_ObjVectorDir",_ObjVectorDir] Call IniDB_Write; // Update the index database with the new file name ActiveObjects = ActiveObjects + [_NewObject]; PublicVariable "ActiveObjects"; Diag_Log Format ["ObjSaving: ObjSaving: Active Objects are %1", ActiveObjects]; Diag_Log Format ["ObjSaving: ObjSaving: ObjectDBIndex is %1", ObjINIArray]; Diag_Log Format ["ObjSaving: ObjSaving: New DBIndex is %1", DBIndex]; // Diag_Log Format ["ObjSaving: Object %1 has been flagged for storage", _NewObject]; // ObjectArray = ObjectArray + [_ObjType,_ObjPos,_ObjDirect]; // Push the object array to the database // ["ObjectDatabase","ObjectDatabase","ObjectArray",ObjectArray] Call IniDB_Write; The exact same thing happens when an object is unlocked, triggering this code: ObjRemoval.sqf // @file Version: 1.1 // @file Name: ObjRemoval.sqf // @file Author: Reaper // @file Created: 2013-08-08 // @file Description: Remove an item from the DB when it's unlocked // @file Args: Private ["_ObjType","_ObjPos","_ObjDirect","_RemObj","_ObjINIArrayEntry","_ActiveObjects","_ObjINIArray"]; _RemObj = ObjectRemoveRelay; _ActiveObjects = ActiveObjects; _ObjINIArray = ObjINIArray; Diag_Log Format ["Object %1 passed for removal",_RemObj]; //If the vehicle is in the active array If (_RemObj In _ActiveObjects) Then { Diag_Log Format ["Object Array currently is %1", _ActiveObjects]; // The index name is supposed to be saved with the object as a variable, so pull it // so that we know which ini file needs to be removed. _ObjINIArrayEntry = _RemObj GetVariable "Obj_DBIndex"; _ObjINIArray = _ObjINIArray - [_ObjINIArrayEntry]; // Remove the database file _ObjINIArrayEntry call IniDB_Delete; _ActiveObjects = _ActiveObjects - [_RemObj]; Diag_Log Format ["_ActiveObjects Array Trimmed to %1",_ActiveObjects]; //["ObjectIndex","ObjectIndex","ObjectIndex",_ObjINIArray] Call IniDB_Write; } Else { Diag_Log Format ["Object %1 is not in the array!", _RemObj]; }; It has a lot of cruft in it, because I took the previous method of saving and loading objects and kind of incrementally adapted it, but it works. I set up a base of ~ 20 walls and stands, and they survived a server reboot just fine. One gap is that the current lock code stores the side of the player who locked it, preventing other players from removing the object if the locking side is near by. That's just another variable I'll have to set at some point. Eventually I'll add a function during the load process that eliminates gaps in the array, but since they only effect performance immediately upon server load (iterating through arrays checking for valid files), it's kind of low on the priorities. Next up, purchased vehicle saving! -
iniDB - Save and Load data to the server or your local computer without databases!
Shai replied to SicSemperTyrannis's topic in ARMA 3 - ADDONS & MODS: COMPLETE
A good chunk of this seems to be broken with the latest arma 3 update - am I the only one experiencing this? -
iniDB - Save and Load data to the server or your local computer without databases!
Shai replied to SicSemperTyrannis's topic in ARMA 3 - ADDONS & MODS: COMPLETE
The latest A3 patch seemed to break this for me; anyone else having issues? I was using it to save players and locations of locked fortifications on my wasteland server; the player saving is still OK, but fortifications is broken. I'm saving an INI which contains the names of all saved fortifications, called ObjectIndex.ini. This is what happens when I check to see if it exists: _DBExists = ["ObjectIndex"] Call IniDB_Exists; Diag_Log Format ["_DBExists: %1",_DBExists]; [/Code] and in the RPT log I get "_DBExists: false" But the file is obviously there; in fact, if I trim it back to a couple of fortifications, it STILL returns false, but it actually loads the objects. Here's my ObjectIndex.ini file: (I'm saving the objects when they're locked by server time and object name). Is there some limit to the length of an array that iniDB_Read can pull now? Like I said, this was all working before the patch, and I haven't made any changes. -
Using ForEach with mission.sqm classes
Shai replied to Shai's topic in ARMA 3 - MISSION EDITING & SCRIPTING
*sigh*. The guy who made the map made no sensible pattern to what he called the markers; I was hoping to do an but he named them all sorts of things, from S1_87 to shouse. I just had the trigger capture pass the string of the name of the marker as an execVM arg, so I could periodically check it for color. -
Hey all - I have a bunch of markers that are being captured in my mission.sqm - 70 or so. I'd like to keep track of who owns each marker. I could do something like - _color = GetMarkerColor "S1_83_1_1"; If (_color == "ColorBlue") Then { _BlueCount = _BlueCount + 1;}; But I don't want to have to do that dozens of times. I'd rather do something like - { _Color = GetMarkerColor _x; If (_color == "ColorBlue") Then { _BlueCount = _BlueCount + 1;}; } ForEach Mission.sqm Class; But I don't know if such a thing is possible. If I could load all of the mission objects into an array, I could check to see if they fit the criteria of a capture marker (rectangular, one of three colors, etc). But how do I grab all of the mission objects/classes?