Jump to content
Sign in to follow this  
kazesim

Config Extractor

Recommended Posts

Extracts a whole config class to the Windows clipboard.

It includes every entry in that class plus every subclass (and sub-sub-etc-class) all the way back to the root.

The entries are left in the same order that they are in the config, with ones from parent classes added later, so that the most derived entries are at the top.

The output is formatted as standard ArmA cpp (instead of bin or sqf), so you should hopefully be able to just paste it in a config file without problems.

This is for people like me who hate using unPBO/unBin/Eliteness just to get a few config values. Instead you can just run this from in-game, paste the whole thing into Notepad++ or whatever and take out what you don't need. Due to it's complexity, it typically takes a few seconds to run, just wait until it says it's done. Don't use it on the huge Cfg- base classes as it will never finish.

I recommend making a "Scripts" folder in your ArmA root (same folder as the game's main exe) and putting it there. Then it can be called from anywhere in the game with "Scripts\NAME.sqf".

/*--------------------------------------------------------------------------------------------
Extracts a whole config class to the Windows clipboard
It includes every entry in that class plus every subclass (and sub-sub-etc-class) all the way back to the root
The entries are left in the same order that they are in the config, with ones from parent classes added later, so
 that the most derived entries are at the top
The output is formatted as standard ArmA cpp (instead of bin or sqf), so you should hopefully be able to just paste
 it in a config file without problems

Don't use this script on huge root classes like CfgVehicles / CfgWeapons, it will never finish

The parameter can be either the config class to extract, or an array:
0: Config (Class to extract)
1: Bool (Add comments indicating which parent class the entries came from, default false)
2: Bool (Include parent class names in the class definitions, default true)

Examples:
(configFile/'CfgWeapons'/'M16A2')               execVM "Scripts\cfgGet.sqf";
[configFile/'CfgVehicles'/'HMMWV', true]        execVM "Scripts\cfgGet.sqf";
[configFile/'CfgVehicles'/'HMMWV', true, false] execVM "Scripts\cfgGet.sqf";

This should work on any ArmA, tested on 2 and 3
v1.0
By Kazesim
--------------------------------------------------------------------------------------------*/

#define DQUOTE 34
#define INC(X) X = X + 1
#define ADD(X,Y) _list set [count _list, [X, Y]]

_addClassLabels = false;
_addParentClassDefs = true;

if ((typeName _this) == "ARRAY") then {
_count = count _this;
if (_count > 1) then {_addClassLabels = _this select 1};
if (_count > 2) then {_addParentClassDefs = _this select 2};
_this = _this select 0;
};
if not (isClass _this) exitWith {hint "Invalid class"; copyToClipboard "Invalid class"};

_offset = 0;
_tab = "";

_CRLF = toString [0x0D, 0x0A];
__TAB = toString [0x09];

_getTab = {
//Update the string containing the current number of tabs
private ["_c", "_t"];
_offset = _offset + _this;
_t = "";
for "_c" from 1 to _offset do {
	_t = _t + __TAB;
};
_tab = _t;
};

_insert = {
//Format: [array, item to insert, index]
private ["_array", "_index", "_count", "_save", "_last", "_c"];
_array = _this select 0;
_index = _this select 2;
_count = count _array;
_save = "";
_last = _this select 1;
for "_c" from _index to (_count - 1) do {
	_save = _array select _c;
	_array set [_c, _last];
	_last = _save;
};
_array set [_count, _last];
};

_formatString = {
//Re-double-quotes any quotes inside a string
private ["_c", "_x", "_count"];
_this = toArray _this;
_count = count _this;
for [{_c = 0}, {_c < _count}, {INC(_c)}] do {
	_x = _this select _c;
	if (_x == DQUOTE) then {
		[_this, DQUOTE, _c+1] call _insert;
		INC(_c);
		INC(_count);
	};
};
str toString _this;
};

_formatArray = {
//Switch all the brackets to braces, and add spaces after commas
private ["_str", "_last"];
_last = (count _this) - 1;
_str = "{";
{
	_str = _str + (switch (typeName _x) do {
		case "ARRAY": {_x call _formatArray};
		case "TEXT":  {_x call _formatString};
		case default  {str _x};
	});
	if (_forEachIndex != _last) then {_str = _str + ", "};
} forEach _this;
_str + "}";
};

_scanEntries = {
private ["_cfg", "_c", "_entry", "_name", "_added", "_str", "_list"];
_cfg = _this select 0;
_list = _this select 1;
_addLabel = _this select 2;
for "_c" from 0 to ((count _cfg) - 1) do {
	_entry = _cfg select _c;
	_name = configName _entry;
	_added = false;
	{if ((_x select 0) == _name) exitWith {_added = true}} forEach _list;
	if (!_added) then {
		//Add the class label comment, if enabled
		if (_addClassLabels and _addLabel) then {
			_str = format ["%1// %2%3", _tab, configName _cfg, _CRLF];
			ADD("", _str);
			_addLabel = false;
		};
		//Add the entry
		_str = "";
		if (isClass _entry) then {
			_str = _entry call _scanCfg;
		} else {
			_str = format ["%1%2%3 = %4;%5",
				_tab,
				_name,
				if (isArray _entry) then {"[]"} else {""},
				switch (true) do {
					case (isNumber _entry): {getNumber _entry};
					case (isText _entry):   {(getText _entry)  call _formatString};
					case (isArray _entry):  {(getArray _entry) call _formatArray};
				},
				_CRLF
			];
		};
		ADD(_name, _str);
	};
};
};

_scanCfg = {
private ["_list", "_tab", "_cfg", "_name", "_count", "_inherit", "_str", "_empty"];
_list = [];
0 call _getTab;

//Add the class name, parent class name, and starting brace
_cfg = _this;
_name = configName _cfg;
_count = count _cfg;
_inherit = configName inheritsFrom _cfg;
_empty = _count == 0 and _inherit == "";
_str = format ["%1class %2%3 {%4",
	_tab,
	_name,
	if (_inherit == "" or !_addParentClassDefs) then {
		"";
	} else {
		": " + _inherit;
	},
	if (_empty) then {""} else {_CRLF}
];
ADD(_name, _str);
1 call _getTab;

//Get all the entries from this class and every parent class
if (_count > 0) then {[_cfg, _list, false] call _scanEntries};
while {true} do {
	_inherit = inheritsFrom _cfg;
	_inheritName = configName _inherit;
	if (_inheritName == "") exitWith {}; //Last class
	_cfg = _inherit;
	[_cfg, _list, _name != _inheritName] call _scanEntries;
};

//Add the ending brace
-1 call _getTab;
_str = format ["%1};%2", if (_empty) then {""} else {_tab}, _CRLF];
ADD("", _str);

//Concat the string and return it
_str = "";
{_str = _str + (_x select 1)} forEach _list;
_str;
};

hint "Running...";
copyToClipboard (_this call _scanCfg);
hint "Done";

  • Like 2

Share this post


Link to post
Share on other sites

Thanks Kazesim,

Some very useful functionality there. I wondered if you would consider an addition?

I wrote a similar script to extract the entire Arma1 config as one file for general browsing, searching and tracing the inheritance. As you did a better job of formatting and exporting the config, I wondered if you would be willing to add that feature to your script? For what I want it for my script works fine, but I'm sure it would be helpful for others.

I've attached the output from my version below. I format mine in a slightly different way from you, but this isn't an issue as it's easy to modify your script to suit each persons preference.

allConfig.txt

If you can't no worries, it's still worth posting the file here, for anyone else who might find it useful.

Edit:

I'm not sure how that stupid emoticon ended up in the title, please ignore it.

Edited by UNN

Share this post


Link to post
Share on other sites

Sorry I always forget to check for replies.

I wasn't able to download that file, I'm pretty sure that site is worse than FilePlanet, which I didn't think was possible. If you can put it on Dropbox or something, or just paste it here I'll look at it.

And do you mean extracting the whole entire game config? You could theoretically do that with this script by just extracting the Cfg- classes. I'm afraid to actually try that though because it would take forever and probably either run out of memory or reach some kind of recursion limit. I haven't actually tested it on ArmA 1 since my copy of that game is broken thanks to FADE thinking that I have a pirate copy, but I'd assume it would work.

For just perusing the config I think it's easiest to just use the in-game browser. But yeah if you have managed to find a way to extract the whole thing then I'd like to see.

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
Sign in to follow this  

×