Jump to content
MysteriousDude

Hash maps don't save correctly in SP?

Recommended Posts

I have a script that is loading in levels exported to SQF from the editor. The last line of that script returns all items created in an array like this:

 

[[_objects,_groups,_triggers,_waypoints,_logics,_markers],[_objectIDs,_groupIDs,_triggerIDs,_waypointIDs,_logicIDs,_markerIDs]]

 

If I store this array to a variable in the mission namespace, everything works okay after saving and loading the game. But if I store the array in a hash map, then everything is lost after saving and loading. The array still exists, but everything inside _objects, _groups etc. is empty/null.

 

I've recreated a basic example. Spawn a squad of units in the editor > export level to SQF > save as level.sqf in the mission folder. Then run the following code in init.sqf:

 

private _levelData = [] call compile preprocessFile "level.sqf";

TEST_A = _levelData;
TEST_B = [_levelData];
TEST_C = createHashMapFromArray [["_levelData", _levelData]];

addMissionEventHandler ["Loaded", {[] spawn TEST_results}];

TEST_results = {
	_items = TEST_A select 0;
	_groups = _items select 1;
	_group = _groups select 0;
	_units = units _group;

	hint format["TEST A: count %1 units", count _units]; // TEST A: count 4 units
	sleep 2;

	_data = TEST_B select 0;
	_items = _data select 0;
	_groups = _items select 1;
	_group = _groups select 0;
	_units = units _group;

	hint format["TEST B: count %1 units", count _units]; // TEST B: count 4 units
	sleep 2;

	_data = TEST_C get "_levelData";
	_items = _data select 0;
	_groups = _items select 1;
	_group = _groups select 0;
	_units = units _group;

	hint format["TEST C: count %1 units", count _units]; // TEST C: count 0 units ???
	sleep 2;
};

 

After saving and reloading, test A and B count 4 units, but test C counts nothing (although the array still exists)

 

What am I not understanding?

Share this post


Link to post
Share on other sites

Thx @MysteriousDude This was a fun one to figure out 🙂


What I think is happening is that when you load a save init.sqf is not executed. This is per design.

Instead variables and their current values are stored in the save file. When you load the mission these values are read back into memory.
There seems to be a bug (maybe) that, while arrays retain their reference to groups and objects when they are loaded from their serialized form, HashMaps do not.

I've posted a ticket about this on the feedback tracker to see if it's actually a bug and hopefully get it fixed: https://feedback.bistudio.com/T162726
Either way this workaround should work:

TEST_A = _levelData;
TEST_B = [_levelData];
TEST_C = createHashMapFromArray [["_levelData", _levelData]];

addMissionEventHandler ["Loaded", {
	TEST_C = createHashMapFromArray [["_levelData", TEST_A]];	
	[] spawn TEST_results;
}];

 

  • Like 2

Share this post


Link to post
Share on other sites

Thanks for checking it out. I will go with your workaround for now. Is there any solid documentation on what is saved, and how? I wasn't able to find much on it, but I can confirm what you have said from testing.

 

Any script that was running when saving (like an infinite while loop for example) will also resume when reloading. The "loaded" handler seems to execute before scripts resume from their saved state, but I can't tell if that's guaranteed if you use spawn in the handler.

Share this post


Link to post
Share on other sites
On 1/11/2022 at 9:55 AM, MysteriousDude said:

The "loaded" handler seems to execute before scripts resume from their saved state, but I can't tell if that's guaranteed if you use spawn in the handler.

 

All spawn does is launch a new scheduled scope. It has no effect on other code in the scope in which it's called. Any code in the handler that isn't spawned should be fine but all bets are off inside the TEST_results function.

 

Also to guarantee that the Loaded event handler has a chance to trigger even in a multiplayer setting define a preInit function with the event handler inside it. The current setup with it being added inside the init.sqf should be fine for singleplayer though.

  • Like 1

Share this post


Link to post
Share on other sites

objects can't be keys for hashmaps, but I'm not sure of what your hashmap is actually made of. What are keys, what are data? how many entry?

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

×