OpenXcom Forum

OpenXcom Forks => OXCE Bugs => OpenXcom Extended (OXCE) => OXCE Bugs FIXED => Topic started by: Delian on December 14, 2024, 11:34:40 pm

Title: [FIXED] Crashes related to ruleset file load order
Post by: Delian on December 14, 2024, 11:34:40 pm
Currently we're loading files in the order of... newest to oldest (last write time descending order).
Usually this means z to a, because when users extract mod zip files (or clone a repository), these files are created on the hard drive in alphabetical order (the order in which they're downloaded, or order in which they appear in the zip file, which is usually alphabetically), so the z file is created last, and thus it's loaded first because it is the newest file.

This is both confusing (a normal user would expect the order to be a-z), and problematic, because if someone manually edits one of the rul files, even if they simply resave it without any changes, it changes the order in which the files (and folders) are loaded.


Currently we're loading files in the order of... z-a (descending case-sensitive alphabetical order).

This is both confusing (a normal user would expect the order to be case-insensitive a-z), and problematic, because if someone renames one of the files/folders, it changes the order in which the files are loaded.
And currently the majority of mods crash (or have other issues) if files are loaded in the wrong order.

Why is loading files in the wrong order problematic?
1. Wrong rule values. If a Rule object is defined in two .rul files, then the Rule object properties in the last file processed get to overwrite the properties of the first one.
2. Crashes due to erroneous error checks (https://github.com/MeridianOXC/OpenXcom/blob/d7d960493cb8db1b10eb811180d4004b3e927345/src/Mod/RuleItem.cpp#L558). If a Rule object is defined in two .rul files, then loading the wrong one first could throw due to object temporarily being in an invalid state.
3. Failed script parsing. Tag names need to be defined before Rule objects are allowed to set values for those tags. So the ruleset with tag names needs to be loaded first.

The 2nd problem could be solved by moving the error check to the afterLoad() function.
The 3nd problem could be solved by loading all the rul files and processing their "extended:" nodes before processing any other yaml nodes.
The 1st problem however cannot be solved. Even if we forcefully sort the files in a specific order, there's no guarantee that the modder won't rename them and thus cause a crash. It would also be inconvenient to modders if we forced a certain sort order.

Basically, what we need is to allow modders to specify which rul files to load first. That would solve all 3 of the problems. Perhaps something in metadata.yml or vars.rul.
Title: Re: Crashes related to ruleset file load order
Post by: Meridian on December 14, 2024, 11:47:19 pm
We don't guarantee any load order.

Mods need to be written in a way that is not dependent on load order.
Title: Re: Crashes related to ruleset file load order
Post by: Delian on December 15, 2024, 12:22:15 am
You say that, but... I've checked, and currently most the major mods (XPZ, XCF, 40k, ROS, TWoTS) have errors if files are loaded in the wrong order. The mod authors don't even know about it. Or maybe they know and they don't know how to fix it. The fact that they don't know that this is an issue is an issue in itself lol
Title: Re: Crashes related to ruleset file load order
Post by: Solarius Scorch on December 15, 2024, 01:12:21 am
I certainly don't know about it.

Please report such issues on the XCF subforum.
Title: Re: Crashes related to ruleset file load order
Post by: Yankes on December 15, 2024, 01:18:24 am
This could even depend on operating system and if we try load zip itself.
Title: Re: Crashes related to ruleset file load order
Post by: Meridian on December 15, 2024, 10:44:03 am
Currently we're loading files in the order of... newest to oldest (last write time descending order).

I am not aware of this.
I created a new file (create and last write time = now) "mmm.rul" and it was loaded in the middle, before L-files and after N-files.

As far as I know, OpenXcom doesn't sort the files in any particular way and doesn't guarantee any particular load order.
The order depends on the operating system, regional settings, load mode and probably some other factors.

1. Wrong rule values. If a Rule object is defined in two .rul files, then the Rule object properties in the last file processed get to overwrite the properties of the first one.

Within one mod, the rule value should not be defined twice.
Best practice is to define each object only once.
If you must split the definition into multiple places, for whatever reason, then at least keep them distinct (i.e. don't repeat the same attributes for the same object).
Otherwise... garbage in, garbage out.

2. Crashes due to erroneous error checks (https://github.com/MeridianOXC/OpenXcom/blob/d7d960493cb8db1b10eb811180d4004b3e927345/src/Mod/RuleItem.cpp#L558). If a Rule object is defined in two .rul files, then loading the wrong one first could throw due to object temporarily being in an invalid state.

Since 2014, I haven't seen or heard even a single false positive from this check. All reports were correctly found issues.

But you are technically correct, we can move it to afterLoad.

3. Failed script parsing. Tag names need to be defined before Rule objects are allowed to set values for those tags. So the ruleset with tag names needs to be loaded first.

Either define them in each file you need them,
or use the shared definition: https://openxcom.org/forum/index.php?topic=11102.0

You say that, but... I've checked, and currently most the major mods (XPZ, XCF, 40k, ROS, TWoTS) have errors if files are loaded in the wrong order. The mod authors don't even know about it. Or maybe they know and they don't know how to fix it. The fact that they don't know that this is an issue is an issue in itself lol

I will update the ruleset wiki to explicitly mention this.
Title: Re: Crashes related to ruleset file load order
Post by: Delian on December 15, 2024, 02:19:43 pm
I am not aware of this.

CrossPlatform.cpp#L642 (https://github.com/MeridianOXC/OpenXcom/blob/d7d960493cb8db1b10eb811180d4004b3e927345/src/Engine/CrossPlatform.cpp#L642)
Oops, I was wrong. I assumed the files were sorted based on last write time, because there's an elaborate lastWriteTime reading, conversion and storing (https://github.com/MeridianOXC/OpenXcom/blob/d7d960493cb8db1b10eb811180d4004b3e927345/src/Engine/CrossPlatform.cpp#L607). This last write time is then used... nowhere. Huh. Why is it being read then? Stoddaaaaard! :D
But yeah, sorry, the sorting is actually z to a. Unless, as Yankes mentioned, we're using a ziploader. Ziploader doesn't perform any sorting (but files in zips are usually a-z). So if a mod is inside a zip file, .ruls are (usually) loaded a-z, and if files are in a plain folder, then they're loaded z-a.
Hmm, if sorting is actually z-a, then the whole issue is a lot less problematic. And I didn't need to make this thread at all...

Within one mod, the rule value should not be defined twice.
Best practice is to define each object only once.
If you must split the definition into multiple places, for whatever reason, then at least keep them distinct (i.e. don't repeat the same attributes for the same object).

I agree. That would solve such issues.
Hmm. Modders are currently allowed to merge objects, but the order is only guaranteed in the order of mod hierarchy, from top (master) to bottom. In theory, if the modders were guaranteed or allowed to specify the load order, then the "Rule object merging" feature would also be safe between the .rul files within the mod. One could argue that the specific load order is a wanted feature based on the fact that modders already depend on it hehe. A good example is how the rulesets are defined in ROSIGMA. He's got normal object definitions, and then he's got a BALANCE folder, which overwrites his normal definitons. He's able to change and experiment with stuff in the BALANCE folder without having to worry about duplicate keys and specifics of his base definitions.
In other words, while we currently don't guarantee any load order, if we did allow modders to specify it, it would be a useful feature to the modders because it would allow them to safely layer their rule definitions in more possible ways.

Since 2014, I haven't seen or heard even a single false positive from this check. All reports were correctly found issues.

I know about it because yesterday, after I optimized VFS loading to be 3x faster...
Code: [Select]
[15-12-2024_11-50-19] [ERROR] failed to load '40k ROSIGMA Submod'; mod disabled
C:/OXCE/user/mods/rosigma/Ruleset/BALANCE/plasma.rul: Weapon STR_INQ_PLASMA has clip size 0 and no ammo defined. Please use 'clipSize: -1' for unlimited ammo, or allocate a compatibleAmmo item.
...this check failed for me when I tried loading ROSIGMA files in the wrong (a-z) order hehe.

Either define them in each file you need them,
or use the shared definition: https://openxcom.org/forum/index.php?topic=11102.0

Uhh. So that solution is basically an awkward way of trying to solve this same problem.
Why do I say it's awkward? Because with that solution the modders have to put extended: { tagsFile: "Ruleset/tagsFile.rul" } (boilerplate) into every .rul file. A better solution would've been for modders to set to load "Ruleset/tagsFile.rul" first, which would happen one time in one place, and then never worry about it again.
Title: Re: Crashes related to ruleset file load order
Post by: Yankes on December 15, 2024, 02:45:21 pm
Uhh. So that solution is basically an awkward way of trying to solve this same problem.
Why do I say it's awkward? Because with that solution the modders have to put extended: { tagsFile: "Ruleset/tagsFile.rul" } (boilerplate) into every .rul file. A better solution would've been for modders to set to load "Ruleset/tagsFile.rul" first, which would happen one time in one place, and then never worry about it again.
I disagree, I would even ban sharing tags between files (but this would break too many mods),
explicit loading is better as every one will know what is loaded and when.
For small "codebases" implicit loads like this are fine but more bigger code base things like this become "black magic" and nobody will
know when and how its work. Image that C++ allow skipping `#include` for some headers, image fun when one include conflict with other you
explicitly load. Right now I had couple of day "fun" figure out why sometimes OXCE compile or not under Cygwin with you commit:
https://github.com/biojppm/rapidyaml/issues/482
Image solving this problem when headers are loaded implicitly.
Title: Re: Crashes related to ruleset file load order
Post by: Delian on December 15, 2024, 03:05:59 pm
You're comparing apples to oranges. C++ only builds the files/functions that are encountered through the include chain, but we are unconditionally parsing everything. Different problem, different solution. Think of it like specifying an entry point: main.cpp. You do that in C++, without needing #include main.cpp in every file.

That repidyaml issue indeed looks fun (it seems like it's only cygwin problem?) hehe, but it's off topic.
Title: Re: Crashes related to ruleset file load order
Post by: Yankes on December 15, 2024, 03:22:33 pm
You're comparing apples to oranges. C++ only builds the files/functions that are encountered through the include chain, but we are unconditionally parsing everything. Different problem, different solution. Think of it like specifying an entry point: main.cpp. You do that in C++, without needing #include main.cpp in every file.
Do you know that old C do not need includes? You could write `foo(a, b)` and compiler will figure out that you want call some function and call it directly.
This was because C all functions need to have globally unique name and as long you link `foo.o` that had this function you code will create exe.
Less boilerplate and finding what include had this function, pure profit :>

But sometime after C community start creating jokes like "if it compile its means its work", thus C11 explicitly ban this fature.
Title: Re: Crashes related to ruleset file load order
Post by: Meridian on December 16, 2024, 02:18:22 pm
This last write time is then used... nowhere. Huh. Why is it being read then? Stoddaaaaard! :D

Maybe for the list of saves?
They can be sorted from newest to oldest...

Hmm, if sorting is actually z-a, then the whole issue is a lot less problematic. And I didn't need to make this thread at all...

If it only were that easy.

Sorting depends on a lot of things and is completely unreliable.

1/ some systems sort case-independent (...A a B...), some case-dependent (...Z a b...)
2/ some regions have special characters at the end of the alphabet (...y z ä...), some in the middle (a ä b...)
3/ some regions have character groups even for the basic 26... e.g. in English: ...Belgium < China < Denmark..., but in Slovak: ...Honduras < China < Island... ('ch' is sorted after 'h', not after 'c')
4/ some systems sort even files beginning with numbers differently, sometimes alphabetically: 1 < 2 < 222 < 3, sometimes numerically: 1 < 2 < 3 < 222

As I said... absolutely not guaranteed.

And no, I am definitely not going to code an OpenXcom-specific file sorting.

Uhh. So that solution is basically an awkward way of trying to solve this same problem.
Why do I say it's awkward? Because with that solution the modders have to put extended: { tagsFile: "Ruleset/tagsFile.rul" } (boilerplate) into every .rul file. A better solution would've been for modders to set to load "Ruleset/tagsFile.rul" first, which would happen one time in one place, and then never worry about it again.

It's not the same problem, don't mix apples and oranges :)

Loading that file first would not solve it.
Tag definitions are not visible cross-file.
They are needed in each file, directly or indirectly via "shared" file.
Title: Re: Crashes related to ruleset file load order
Post by: Delian on December 16, 2024, 04:54:45 pm
Maybe for the list of saves?
They can be sorted from newest to oldest...

Nope (https://github.com/MeridianOXC/OpenXcom/blob/d7d960493cb8db1b10eb811180d4004b3e927345/src/Savegame/SavedGame.cpp#L350). While it is possible to sort save files base on the last write time, that's implemented independently. I mean, even though we're calling the getFolderContents() (https://github.com/MeridianOXC/OpenXcom/blob/d7d960493cb8db1b10eb811180d4004b3e927345/src/Savegame/SavedGame.cpp#L255) function when retrieving the list of sav files, and the returned tuples include the last write time, the last write time is discarded. Yes, it would make sense to pass the tuple to the getSaveInfo() function because then we wouldn't need to call getDateModified() for every sav file again. But for now, I can say that the last write time, as retrieved by the getFolderContents() function (which is the function based on which we build the VFS and determines the sort order we load .rul files in), is not used anywhere.

Sorting depends on a lot of things and is completely unreliable.

I linked the part of code where we're sorting the list of retrieved filenames. In that link, I show that we're using std::sort() to sort this list. This std::sort() call uses a lambda which compares the filenames using the string > operator. The C++ 17 standard states (https://en.cppreference.com/w/cpp/string/basic_string/operator_cmp) that the comparison is done using the compare() member function. And the compare (https://en.cppreference.com/w/cpp/string/basic_string/compare) function states, quote:
"By default (with the default std::char_traits), this function is not locale-sensitive."
Tldr; You are talking about locale-aware sorting the OS does, but we ignore that because we perform std::sort() after retrieving the list of files, which is locale-independent.

Sure, I can code the OXCE-specific file sorting for you. But, do I need to do anything besides simply calling std::sort() to achieve that?

Loading that file first would not solve it.

That's literally what's happening right now. XPZ loads Yankes_Scripts.rul first, because Y is at the end of the alphabet, it's the last file in the folder, so it's loaded first. That's why it doesn't error during the loading. Because Yankes_Scripts.rul contains all the tag name definitions. These tags names are not defined anywhere else and the shared file isn't linked anywhere, yet it works.

Tag definitions are not visible cross-file.

As far as I can tell, script loading internally uses a shared list of tag names, and this list persists until the loading is finished. Meaning, once a tag is defined, the tag's value can subsequently be set by any rule object, no matter which file it's in.
Title: Re: Crashes related to ruleset file load order
Post by: Meridian on December 16, 2024, 05:06:10 pm
I linked the part of code where we're sorting the list of retrieved filenames. In that link, I show that we're using std::sort() to sort this list. This std::sort() call uses a lambda which compares the filenames using the string > operator. The C++ 17 standard states (https://en.cppreference.com/w/cpp/string/basic_string/operator_cmp) that the comparison is done using the compare() member function. And the compare (https://en.cppreference.com/w/cpp/string/basic_string/compare) function states, quote:
"By default (with the default std::char_traits), this function is not locale-sensitive."
Tldr; You are talking about locale-aware sorting the OS does, but we ignore that because we perform std::sort() after retrieving the list of files, which is locale-independent.

Sure, I can code the OXCE-specific file sorting for you. But, do I need to do anything besides simply calling std::sort() to achieve that?

OK, maybe it changed in the meantime and I have obsolete information.
I can check later.

The example I mentioned with 'CH' being between 'H' and 'I' instead of between 'B' and 'D' definitely was happening several years ago.
Solarius (Polish locale) had a crash, which I (Slovak locale) could not reproduce... at the end it turned out to be different file load order due to different locale. 100% sure.

That's literally what's happening right now. XPZ loads Yankes_Scripts.rul first, because Y is at the end of the alphabet, it's the last file in the folder, so it's loaded first. That's why it doesn't error during the loading. Because Yankes_Scripts.rul contains all the tag name definitions. These tags names are not defined anywhere else and the shared file isn't linked anywhere, yet it works.

As far as I can tell, script loading internally uses a shared list of tag names, and this list persists until the loading is finished. Meaning, once a tag is defined, the tag's value can subsequently be set by any rule object, no matter which file it's in.

OK, maybe I have again obsolete information.
(Again 100% sure it was like that before.)
Title: Re: Crashes related to ruleset file load order
Post by: Meridian on December 16, 2024, 05:43:45 pm
That's literally what's happening right now. XPZ loads Yankes_Scripts.rul first, because Y is at the end of the alphabet, it's the last file in the folder, so it's loaded first. That's why it doesn't error during the loading. Because Yankes_Scripts.rul contains all the tag name definitions. These tags names are not defined anywhere else and the shared file isn't linked anywhere, yet it works.

Btw. all tag usage in XPZ is also in `Yankes_Scripts.rul`

I have found only two usages outside of this file, and they are probably mistakes.

So XPZ does it correctly and defines tags in each file, where they are used.
File load order doesn't matter for XPZ.
Title: Re: Crashes related to ruleset file load order
Post by: Meridian on December 16, 2024, 06:01:14 pm
And here's an example of some problems resulting from different locales: https://openxcom.org/forum/index.php?topic=5146.msg83361#msg83361

Swedish flag with Spanish name;
or Italian name with a Japanese flag

(offset errors due to soldier name files sorted differently)

Not saying it's still happening, maybe it was already fixed/changed... just providing evidence that I am not making this up :)
Title: Re: Crashes related to ruleset file load order
Post by: Delian on December 16, 2024, 10:01:20 pm
I have found only two usages outside of this file, and they are probably mistakes.

So cruel to call them mistakes! They work fine! (as long as file loading is z-a)

And here's an example of some problems resulting from different locales: https://openxcom.org/forum/index.php?topic=5146.msg83361#msg83361

...

...

No, that problem wasn't due to different locales. It was due to duplicate folder names between common/SoldierName and Celebrate_Diversity/SoldierName.
The problem was that common/SoldierName has "argentina.nam", but Celebrate_Diversity does not (it has "argentinian.nam"). So after merging the two virtual dirs, this extra file causes the offset.
Note that, even though we were already using std::sort() for rul files back then, that doesn't apply to soldier names. For soldier names we explicitly (https://github.com/MeridianOXC/OpenXcom/blob/d7d960493cb8db1b10eb811180d4004b3e927345/src/Mod/RuleSoldier.cpp#L156) call a locale-aware sort.
Title: Re: Crashes related to ruleset file load order
Post by: Meridian on December 17, 2024, 09:47:56 am
No, that problem wasn't due to different locales.

Yes, it WAS also due to different locales!
Don't make me an idiot.

Both duplicate folder and locale issue needed to be fixed.
Fixing just one still lead to offset issues.
Different problems, same result for the player... dysfunctional mod.
Title: Re: Crashes related to ruleset file load order
Post by: Delian on December 17, 2024, 02:53:19 pm
Ok, but back then soldier name files were not yet being sorted locale-aware. Stoddard only made namepool sorting locale-aware 5 years ago.

Yes, I agree that there are some problems resulting from sorting in different locales. I am with you on that.

For demonstration:
Let's say that a modder defines "Flag25" to be Resources/Flags/Kenya.png.
How did the modder determine that Flag25 is Kenya? He looked at the SoldierNames (or whatever) folder and saw that the 26th file was Kenyan.nam
So nationality with index 25 is Kenya. Soldier with _nationality = 25 will get this flag.
Soldier also gets a name from names[_nationality]. So the name pool with index 25 will be used for the name. names vector was generated after locale-aware sorting files.
As you can guess, this will fail in other locales, because there's no guarantee that Kenyan.nam will be the 26th file after applying a locale-aware sort.
I don't know why Stoddard made name pool sorting locale-aware. It seems like a really bad idea to do that :D
To being with, anything (_nationality included) referring to the index position of a file in a folder is too fragile and is simply bound to fail one way or another. Add or remove a file and it fails.

So, uhh, what were we talking about again? Ruleset load order... yeah... so there's an issue that a lot of mods rely on the order the rul files are loaded in, while modders don't have any ability to specify what the order is. If you wish, I can try implementing something that would give modders some control over this order.
Title: Re: Crashes related to ruleset file load order
Post by: Meridian on December 28, 2024, 05:19:48 pm
Since 2014, I haven't seen or heard even a single false positive from this check. All reports were correctly found issues.

But you are technically correct, we can move it to afterLoad.

Check was moved: https://github.com/MeridianOXC/OpenXcom/commit/f3bec17944951f542c607a7b18564f60e0106d30

--

As for your proposed bugfix for sorting: https://github.com/Delian0/OpenXcom/commit/fb548b79a59b2731077d8286475396e9123560b0

It changed sorting not only for zipped mods, but also for folder mods, see attached example.
For example "xyz.rul" and "xyz/ppp.rul" are sorted differently before and after the change.
Is that intentional?
If yes, I don't mind, as I said we don't guarantee any particular file load order (and won't guarantee it in the future either).
(Just mentioning it will be a breaking change.)

All I am interested in is that on the same environment, under the same conditions, both folder and zipped mods would have the same file load order... which seems to be the case after the change.
Title: Re: Crashes related to ruleset file load order
Post by: Yankes on December 28, 2024, 05:43:30 pm
I think files should be first, before all folders. I think I could create some function that make better sorting like that.
Title: Re: Crashes related to ruleset file load order
Post by: Delian on December 28, 2024, 06:59:09 pm
Logically, '/' has a higher ascii code than '.', so in z-a sorting it will appear first. The intention behind this simple bugfix was to make sorting consistent. But as you show, applying the same sorting after the VFS loading is done will produce different results, which I wasn't aware of - that wasn't my intention.

I'm not sure what type of sorting would be the best. If it was up to me, I'd make it...
(https://i.postimg.cc/dt0K5NmV/Jugemu.png)
Breadth-first means all files in the current folder before moving into any subfolders.
Title: Re: Crashes related to ruleset file load order
Post by: Yankes on December 28, 2024, 09:14:33 pm
Right now I working on helper class that split `std::string_view` based on `/` and compare number of parts and then string parts on the fly.
Title: Re: Crashes related to ruleset file load order
Post by: Delian on December 29, 2024, 08:03:09 pm
Before, with code
Code: [Select]
std::vector<FileMap::FileRecord> sortedRulesetFiles = rulesetFiles;
std::sort(sortedRulesetFiles.begin(), sortedRulesetFiles.end(),
[](const FileMap::FileRecord& a, const FileMap::FileRecord& b)
{
return a.fullpath > b.fullpath;
});
result:
Code: [Select]
/rosigma/Ruleset/vars_ROSIGMA.rul
/rosigma/Ruleset/ufos.rul
/rosigma/Ruleset/ufopedia40k.rul
/rosigma/Ruleset/ufoTrajectories.rul
/rosigma/Ruleset/terrain_40k.rul
/rosigma/Ruleset/tags_ROSIGMA.rul
/rosigma/Ruleset/startingConditions_40k.rul
/rosigma/Ruleset/startingBase40k.rul
/rosigma/Ruleset/soldierBonuses.rul
/rosigma/Ruleset/scripts_40k.rul
/rosigma/Ruleset/scripts/scripts_turret_reload.rul
/rosigma/Ruleset/scripts/scripts_tenacious_enemies.rul
...
/rosigma/Ruleset/scripts/scripts_abilities_miracles.rul
/rosigma/Ruleset/scripts/scripts_abilities_commands.rul
/rosigma/Ruleset/scripts/scripts_UFO_visual_confirmed.rul
/rosigma/Ruleset/scripts/scripts_TU_accuracy_penalty.rul
/rosigma/Ruleset/scripts/script_dig_in.rul
/rosigma/Ruleset/scripts/Scripts_remove_flight.rul
/rosigma/Ruleset/scripts/IGMA_scripts_change_color_ammo.rul
/rosigma/Ruleset/scripts/IGMA_scripts_buff.rul
/rosigma/Ruleset/research_ROSIGMA.rul
/rosigma/Ruleset/regions.rul
/rosigma/Ruleset/palette.rul
/rosigma/Ruleset/musics.rul
/rosigma/Ruleset/missionsScripts.rul
/rosigma/Ruleset/mapScripts.rul
/rosigma/Ruleset/itemCategories.rul
/rosigma/Ruleset/invs.rul
/rosigma/Ruleset/interfaces.rul
/rosigma/Ruleset/globe40k.rul
/rosigma/Ruleset/facilities_ROSIGMA.rul
/rosigma/Ruleset/extraSprites_gibs_of_gory.rul
/rosigma/Ruleset/extraSprites_HANDOB.rul
/rosigma/Ruleset/extraSprites.rul
/rosigma/Ruleset/extraSounds.rul
/rosigma/Ruleset/events.rul
/rosigma/Ruleset/eventScripts.rul
/rosigma/Ruleset/eldar.rul
/rosigma/Ruleset/commendations.rul
/rosigma/Ruleset/arcScripts_ROSIGMA.rul
/rosigma/Ruleset/alienRaces_40k.rul
/rosigma/Ruleset/alienMissions_40k.rul
/rosigma/Ruleset/alienItemLevels.rul
/rosigma/Ruleset/alienDeployments_40k.rul
/rosigma/Ruleset/advancedTurrets.rul
/rosigma/Ruleset/Voices_40k.rul
/rosigma/Ruleset/SM/ufopaedia_SM.rul
/rosigma/Ruleset/SM/startingBase_SM.rul
/rosigma/Ruleset/SM/soldiers_SM.rul
/rosigma/Ruleset/SM/soldierTransformations.rul
/rosigma/Ruleset/SM/scripts_SM.rul
/rosigma/Ruleset/SM/manufacture_SM.rul
/rosigma/Ruleset/SM/manufacture_CSM.rul
/rosigma/Ruleset/SM/items_scripts_SM.rul
/rosigma/Ruleset/SM/items_SM.rul
/rosigma/Ruleset/SM/events_SM.rul
/rosigma/Ruleset/SM/crafts_SM.rul
/rosigma/Ruleset/SM/armors_SM.rul
/rosigma/Ruleset/SM/PRIMARIS/ufopaedia_PRIMARIS.rul
/rosigma/Ruleset/SM/PRIMARIS/manufacture_PRIMARIS.rul
/rosigma/Ruleset/SM/PRIMARIS/armors_PRIMARIS.rul
/rosigma/Ruleset/SM/Deathwatch/armors_voices_DW.rul
/rosigma/Ruleset/SM/Deathwatch/armors_layers_DW.rul
/rosigma/Ruleset/SM/Deathwatch/Deathwatch.rul
/rosigma/Ruleset/OTHER/manufacture_killpoints.rul
/rosigma/Ruleset/OTHER/corpses_killpoints.rul
/rosigma/Ruleset/OTHER/corpses_civ.rul
/rosigma/Ruleset/OTHER/captures_civ.rul
/rosigma/Ruleset/OTHER/alienDeployments_killpoints.rul
/rosigma/Ruleset/OTHER/alertSounds_disable.rul
/rosigma/Ruleset/IG/weapons_IG.rul
/rosigma/Ruleset/IG/units_IG.rul
/rosigma/Ruleset/IG/ufos_IG.rul
/rosigma/Ruleset/IG/ufopaedia_IG.rul
/rosigma/Ruleset/IG/training_mission_IG.rul
/rosigma/Ruleset/IG/terrains_IG.rul
/rosigma/Ruleset/IG/strategies/missionScripts_strategies_IG.rul
/rosigma/Ruleset/IG/strategies/manufacture_strategies_IG.rul
/rosigma/Ruleset/IG/strategies/items_strategies_IG.rul
/rosigma/Ruleset/IG/strategies/events_strategies_IG.rul
/rosigma/Ruleset/IG/strategies/eventScripts_strategies_IG.rul
/rosigma/Ruleset/IG/strategies/crafts_strategies_IG.rul
/rosigma/Ruleset/IG/startingBase_IG.rul
/rosigma/Ruleset/IG/soldiers_command_IG.rul
/rosigma/Ruleset/IG/soldiers_IG.rul
/rosigma/Ruleset/IG/soldierTransformation_IG.rul
/rosigma/Ruleset/IG/skills_IG.rul
/rosigma/Ruleset/IG/missions_IG.rul
/rosigma/Ruleset/IG/manufacture_IG.rul
/rosigma/Ruleset/IG/gibs_of_gory_IG.rul
/rosigma/Ruleset/IG/events_IG.rul
/rosigma/Ruleset/IG/eventScripts_IG.rul
/rosigma/Ruleset/IG/crafts_IG.rul
/rosigma/Ruleset/IG/corpses_IG.rul
/rosigma/Ruleset/IG/armors_voices_IG.rul
/rosigma/Ruleset/IG/armors_scripts_IG.rul
/rosigma/Ruleset/IG/armors_layers_IG.rul
/rosigma/Ruleset/IG/armors_IG.rul
/rosigma/Ruleset/IG/alienDeployments_IG.rul
/rosigma/Ruleset/ENEMY/zombification_weapons.rul
/rosigma/Ruleset/ENEMY/weapons_daemons.rul
/rosigma/Ruleset/ENEMY/weapons_chaos.rul
/rosigma/Ruleset/ENEMY/ufopaedia_chaos.rul
/rosigma/Ruleset/ENEMY/items_spawner.rul
/rosigma/Ruleset/ENEMY/corpses_chaos.rul
/rosigma/Ruleset/ENEMY/captures_chaos.rul
/rosigma/Ruleset/ENEMY/armors_daemon.rul
/rosigma/Ruleset/ENEMY/armors_cultist.rul
/rosigma/Ruleset/ENEMY/armors_chaos.rul
/rosigma/Ruleset/ENEMY/TZEENTCH/weapons_tzeentch.rul
/rosigma/Ruleset/ENEMY/TZEENTCH/corpses_tzeentch.rul
/rosigma/Ruleset/ENEMY/TZEENTCH/captures_tzeentch.rul
/rosigma/Ruleset/ENEMY/TZEENTCH/armors_tzeentch.rul
/rosigma/Ruleset/ENEMY/TRAITOR_GUARD/corpses_traitor_guard.rul
/rosigma/Ruleset/ENEMY/TRAITOR_GUARD/captures_traitor_guard.rul
/rosigma/Ruleset/ENEMY/TRAITOR_GUARD/armors_traitor_guard.rul
/rosigma/Ruleset/ENEMY/SLAANESH/weapons_slaanesh.rul
/rosigma/Ruleset/ENEMY/SLAANESH/corpses_slaanesh.rul
/rosigma/Ruleset/ENEMY/SLAANESH/captures_slaanesh.rul
/rosigma/Ruleset/ENEMY/SLAANESH/armors_slaanesh.rul
/rosigma/Ruleset/ENEMY/ORK/weapons_ORK.rul
/rosigma/Ruleset/ENEMY/ORK/units_ORK.rul
/rosigma/Ruleset/ENEMY/ORK/ufopaedia_ORK.rul
/rosigma/Ruleset/ENEMY/ORK/corpses_ORK.rul
/rosigma/Ruleset/ENEMY/ORK/captures_ORK.rul
/rosigma/Ruleset/ENEMY/ORK/armors_ORK.rul
/rosigma/Ruleset/ENEMY/ORK/armor_scripts_ORK.rul
/rosigma/Ruleset/ENEMY/NURGLE/units_nurgle.rul
/rosigma/Ruleset/ENEMY/NURGLE/corpses_nurgle.rul
/rosigma/Ruleset/ENEMY/NURGLE/captures_nurgle.rul
/rosigma/Ruleset/ENEMY/NURGLE/armors_nurgle.rul
/rosigma/Ruleset/ENEMY/NECRON/units_necron.rul
/rosigma/Ruleset/ENEMY/NECRON/score_necrons.rul
/rosigma/Ruleset/ENEMY/NECRON/gibs_of_gory_necrons.rul
/rosigma/Ruleset/ENEMY/KHORNE/corpses_khorne.rul
/rosigma/Ruleset/ENEMY/KHORNE/captures_khorne.rul
/rosigma/Ruleset/ENEMY/KHORNE/armors_khorne.rul
/rosigma/Ruleset/ENEMY/HERETICSISTER/corpses_hereticsisters.rul
/rosigma/Ruleset/ENEMY/HERETICSISTER/captures_hereticsisters.rul
/rosigma/Ruleset/ENEMY/HERETICSISTER/armors_hereticsisters.rul
/rosigma/Ruleset/ENEMY/GENE/weapons_gene.rul
/rosigma/Ruleset/ENEMY/GENE/units_gene.rul
/rosigma/Ruleset/ENEMY/GENE/corpses_gsc.rul
/rosigma/Ruleset/ENEMY/GENE/captures_gsc.rul
/rosigma/Ruleset/ENEMY/GENE/armors_gene.rul
/rosigma/Ruleset/ENEMY/DESERTERS/corpses_deserters.rul
/rosigma/Ruleset/ENEMY/DESERTERS/captures_deserters.rul
/rosigma/Ruleset/Difficulty/extraSprites_DifficultyMod_Bakgrounds.rul
/rosigma/Ruleset/CHAMBER/weapons_INQ.rul
/rosigma/Ruleset/CHAMBER/ufopaedia_INQ.rul
/rosigma/Ruleset/CHAMBER/startingBase_INQ.rul
/rosigma/Ruleset/CHAMBER/soldiers_INQ.rul
/rosigma/Ruleset/CHAMBER/manufacture_INQ.rul
/rosigma/Ruleset/CHAMBER/events_INQ.rul
/rosigma/Ruleset/CHAMBER/crafts_INQ.rul
/rosigma/Ruleset/CHAMBER/armors_INQ.rul
/rosigma/Ruleset/CHAMBER/INQUISITION_CORPSES.rul
/rosigma/Ruleset/CHAMBER/GREY KNIGHTS/soldierTransformations_GK.rul
/rosigma/Ruleset/CHAMBER/GREY KNIGHTS/crafts_GK.rul
/rosigma/Ruleset/CHAMBER/GREY KNIGHTS/armors_scripts_GK.rul
/rosigma/Ruleset/CHAMBER/GREY KNIGHTS/armors_layers_GK.rul
/rosigma/Ruleset/CHAMBER/GREY KNIGHTS/armors_GK.rul
/rosigma/Ruleset/CHAMBER/GREY KNIGHTS/armor_sprites.rul
/rosigma/Ruleset/CHAMBER/DEATHWATCH/ufopaedia_DW.rul
/rosigma/Ruleset/BALANCE/special_ammo.rul
/rosigma/Ruleset/BALANCE/special.rul
/rosigma/Ruleset/BALANCE/plasma_ammo.rul
/rosigma/Ruleset/BALANCE/plasma.rul
/rosigma/Ruleset/BALANCE/melta_ammo.rul
/rosigma/Ruleset/BALANCE/melta.rul
/rosigma/Ruleset/BALANCE/melee.rul
/rosigma/Ruleset/BALANCE/las_ammo.rul
/rosigma/Ruleset/BALANCE/las.rul
/rosigma/Ruleset/BALANCE/incendiaries_ammo.rul
/rosigma/Ruleset/BALANCE/incendiaries.rul
/rosigma/Ruleset/BALANCE/grav_ammo.rul
/rosigma/Ruleset/BALANCE/grav.rul
/rosigma/Ruleset/BALANCE/explosives.rul
/rosigma/Ruleset/BALANCE/ballistics_arbites.rul
/rosigma/Ruleset/BALANCE/ballistics_ammo.rul
/rosigma/Ruleset/BALANCE/ballistics_allfactions.rul
/rosigma/Ruleset/BALANCE/ballistics_adeptas.rul
/rosigma/Ruleset/BALANCE/ballistics_SM.rul
/rosigma/Ruleset/BALANCE/ballistics_IG.rul
/rosigma/Ruleset/ARBITES/ufopaedia_arbites.rul
/rosigma/Ruleset/ARBITES/startingBase_arbites.rul
/rosigma/Ruleset/ARBITES/soldiers_arbites.rul
/rosigma/Ruleset/ARBITES/soldierTransformation_arbites.rul
/rosigma/Ruleset/ARBITES/manufacture_arbites.rul
/rosigma/Ruleset/ARBITES/items_arbites.rul
/rosigma/Ruleset/ARBITES/crafts_arbites.rul
/rosigma/Ruleset/ARBITES/armors_voices_arbites.rul
/rosigma/Ruleset/ARBITES/armors_scripts_arbites.rul
/rosigma/Ruleset/ARBITES/armors_arbites.rul
/rosigma/Ruleset/ALLFACTIONS/weapons_turrets.rul
...
/rosigma/Ruleset/ALLFACTIONS/armors.rul
/rosigma/Ruleset/ADEPTAS/weapons_adeptas.rul
...
/rosigma/Ruleset/ADEPTAS/adeptas.rul
/rosigma/Ruleset/ADEPTAS/STRATEGIES/manufacture_strategies_adeptas.rul
/rosigma/Ruleset/ADEPTAS/STRATEGIES/items_strategies_adeptas.rul
/rosigma/Ruleset/ADEPTAS/STRATEGIES/events_strategies_adeptas.rul
/rosigma/Ruleset/ADEPTAS/STRATEGIES/eventScripts_strategies_adeptas.rul
/rosigma/Ruleset/40k.rul


after, with code
Code: [Select]
std::string bufA, bufB;
std::vector<FileMap::FileRecord> sortedRulesetFiles = rulesetFiles;
std::sort(sortedRulesetFiles.begin(), sortedRulesetFiles.end(),
[&](const FileMap::FileRecord& a, const FileMap::FileRecord& b)
{
size_t fileNamePosA = a.fullpath.find_last_of("/");
size_t fileNamePosB = b.fullpath.find_last_of("/");
std::string_view dirpathA(a.fullpath.data(), fileNamePosA);
std::string_view dirpathB(b.fullpath.data(), fileNamePosB);
if (dirpathA == dirpathB)
{
// files are in the same folder -> compare filenames
std::string_view filenameA = a.fullpath;
std::string_view filenameB = b.fullpath;
filenameA.remove_prefix(fileNamePosA + 1);
filenameB.remove_prefix(fileNamePosB + 1);
bufA.assign(filenameA);
bufB.assign(filenameB);
}
else
{
// files are in different folders -> compare folders
bufA.assign(dirpathA);
bufB.assign(dirpathB);
}
Unicode::lowerCase(bufA);
Unicode::lowerCase(bufB);
return bufA < bufB;
});
result:
Code: [Select]
/rosigma/Ruleset/40k.rul
/rosigma/Ruleset/advancedTurrets.rul
/rosigma/Ruleset/alienDeployments_40k.rul
/rosigma/Ruleset/alienItemLevels.rul
/rosigma/Ruleset/alienMissions_40k.rul
/rosigma/Ruleset/alienRaces_40k.rul
/rosigma/Ruleset/arcScripts_ROSIGMA.rul
/rosigma/Ruleset/commendations.rul
/rosigma/Ruleset/eldar.rul
/rosigma/Ruleset/events.rul
/rosigma/Ruleset/eventScripts.rul
/rosigma/Ruleset/extraSounds.rul
/rosigma/Ruleset/extraSprites.rul
/rosigma/Ruleset/extraSprites_gibs_of_gory.rul
/rosigma/Ruleset/extraSprites_HANDOB.rul
/rosigma/Ruleset/facilities_ROSIGMA.rul
/rosigma/Ruleset/globe40k.rul
/rosigma/Ruleset/interfaces.rul
/rosigma/Ruleset/invs.rul
/rosigma/Ruleset/itemCategories.rul
/rosigma/Ruleset/mapScripts.rul
/rosigma/Ruleset/missionsScripts.rul
/rosigma/Ruleset/musics.rul
/rosigma/Ruleset/palette.rul
/rosigma/Ruleset/regions.rul
/rosigma/Ruleset/research_ROSIGMA.rul
/rosigma/Ruleset/scripts_40k.rul
/rosigma/Ruleset/soldierBonuses.rul
/rosigma/Ruleset/startingBase40k.rul
/rosigma/Ruleset/startingConditions_40k.rul
/rosigma/Ruleset/tags_ROSIGMA.rul
/rosigma/Ruleset/terrain_40k.rul
/rosigma/Ruleset/ufopedia40k.rul
/rosigma/Ruleset/ufos.rul
/rosigma/Ruleset/ufoTrajectories.rul
/rosigma/Ruleset/vars_ROSIGMA.rul
/rosigma/Ruleset/Voices_40k.rul
/rosigma/Ruleset/ADEPTAS/adeptas.rul
...
/rosigma/Ruleset/ADEPTAS/weapons_adeptas.rul
/rosigma/Ruleset/ADEPTAS/STRATEGIES/events_strategies_adeptas.rul
/rosigma/Ruleset/ADEPTAS/STRATEGIES/eventScripts_strategies_adeptas.rul
/rosigma/Ruleset/ADEPTAS/STRATEGIES/items_strategies_adeptas.rul
/rosigma/Ruleset/ADEPTAS/STRATEGIES/manufacture_strategies_adeptas.rul
/rosigma/Ruleset/ALLFACTIONS/armors.rul
...
/rosigma/Ruleset/ALLFACTIONS/weapons_turrets.rul
/rosigma/Ruleset/ARBITES/armors_arbites.rul
/rosigma/Ruleset/ARBITES/armors_scripts_arbites.rul
/rosigma/Ruleset/ARBITES/armors_voices_arbites.rul
/rosigma/Ruleset/ARBITES/crafts_arbites.rul
/rosigma/Ruleset/ARBITES/items_arbites.rul
/rosigma/Ruleset/ARBITES/manufacture_arbites.rul
/rosigma/Ruleset/ARBITES/soldiers_arbites.rul
/rosigma/Ruleset/ARBITES/soldierTransformation_arbites.rul
/rosigma/Ruleset/ARBITES/startingBase_arbites.rul
/rosigma/Ruleset/ARBITES/ufopaedia_arbites.rul
/rosigma/Ruleset/BALANCE/ballistics_adeptas.rul
/rosigma/Ruleset/BALANCE/ballistics_allfactions.rul
/rosigma/Ruleset/BALANCE/ballistics_ammo.rul
/rosigma/Ruleset/BALANCE/ballistics_arbites.rul
/rosigma/Ruleset/BALANCE/ballistics_IG.rul
/rosigma/Ruleset/BALANCE/ballistics_SM.rul
/rosigma/Ruleset/BALANCE/explosives.rul
/rosigma/Ruleset/BALANCE/grav.rul
/rosigma/Ruleset/BALANCE/grav_ammo.rul
/rosigma/Ruleset/BALANCE/incendiaries.rul
/rosigma/Ruleset/BALANCE/incendiaries_ammo.rul
/rosigma/Ruleset/BALANCE/las.rul
/rosigma/Ruleset/BALANCE/las_ammo.rul
/rosigma/Ruleset/BALANCE/melee.rul
/rosigma/Ruleset/BALANCE/melta.rul
/rosigma/Ruleset/BALANCE/melta_ammo.rul
/rosigma/Ruleset/BALANCE/plasma.rul
/rosigma/Ruleset/BALANCE/plasma_ammo.rul
/rosigma/Ruleset/BALANCE/special.rul
/rosigma/Ruleset/BALANCE/special_ammo.rul
/rosigma/Ruleset/CHAMBER/armors_INQ.rul
/rosigma/Ruleset/CHAMBER/crafts_INQ.rul
/rosigma/Ruleset/CHAMBER/events_INQ.rul
/rosigma/Ruleset/CHAMBER/INQUISITION_CORPSES.rul
/rosigma/Ruleset/CHAMBER/manufacture_INQ.rul
/rosigma/Ruleset/CHAMBER/soldiers_INQ.rul
/rosigma/Ruleset/CHAMBER/startingBase_INQ.rul
/rosigma/Ruleset/CHAMBER/ufopaedia_INQ.rul
/rosigma/Ruleset/CHAMBER/weapons_INQ.rul
/rosigma/Ruleset/CHAMBER/DEATHWATCH/ufopaedia_DW.rul
/rosigma/Ruleset/CHAMBER/GREY KNIGHTS/armor_sprites.rul
/rosigma/Ruleset/CHAMBER/GREY KNIGHTS/armors_GK.rul
/rosigma/Ruleset/CHAMBER/GREY KNIGHTS/armors_layers_GK.rul
/rosigma/Ruleset/CHAMBER/GREY KNIGHTS/armors_scripts_GK.rul
/rosigma/Ruleset/CHAMBER/GREY KNIGHTS/crafts_GK.rul
/rosigma/Ruleset/CHAMBER/GREY KNIGHTS/soldierTransformations_GK.rul
/rosigma/Ruleset/Difficulty/extraSprites_DifficultyMod_Bakgrounds.rul
/rosigma/Ruleset/ENEMY/armors_chaos.rul
/rosigma/Ruleset/ENEMY/armors_cultist.rul
/rosigma/Ruleset/ENEMY/armors_daemon.rul
/rosigma/Ruleset/ENEMY/captures_chaos.rul
/rosigma/Ruleset/ENEMY/corpses_chaos.rul
/rosigma/Ruleset/ENEMY/items_spawner.rul
/rosigma/Ruleset/ENEMY/ufopaedia_chaos.rul
/rosigma/Ruleset/ENEMY/weapons_chaos.rul
/rosigma/Ruleset/ENEMY/weapons_daemons.rul
/rosigma/Ruleset/ENEMY/zombification_weapons.rul
/rosigma/Ruleset/ENEMY/DESERTERS/captures_deserters.rul
/rosigma/Ruleset/ENEMY/DESERTERS/corpses_deserters.rul
/rosigma/Ruleset/ENEMY/GENE/armors_gene.rul
/rosigma/Ruleset/ENEMY/GENE/captures_gsc.rul
/rosigma/Ruleset/ENEMY/GENE/corpses_gsc.rul
/rosigma/Ruleset/ENEMY/GENE/units_gene.rul
/rosigma/Ruleset/ENEMY/GENE/weapons_gene.rul
/rosigma/Ruleset/ENEMY/HERETICSISTER/armors_hereticsisters.rul
/rosigma/Ruleset/ENEMY/HERETICSISTER/captures_hereticsisters.rul
/rosigma/Ruleset/ENEMY/HERETICSISTER/corpses_hereticsisters.rul
/rosigma/Ruleset/ENEMY/KHORNE/armors_khorne.rul
/rosigma/Ruleset/ENEMY/KHORNE/captures_khorne.rul
/rosigma/Ruleset/ENEMY/KHORNE/corpses_khorne.rul
/rosigma/Ruleset/ENEMY/NECRON/gibs_of_gory_necrons.rul
/rosigma/Ruleset/ENEMY/NECRON/score_necrons.rul
/rosigma/Ruleset/ENEMY/NECRON/units_necron.rul
/rosigma/Ruleset/ENEMY/NURGLE/armors_nurgle.rul
/rosigma/Ruleset/ENEMY/NURGLE/captures_nurgle.rul
/rosigma/Ruleset/ENEMY/NURGLE/corpses_nurgle.rul
/rosigma/Ruleset/ENEMY/NURGLE/units_nurgle.rul
/rosigma/Ruleset/ENEMY/ORK/armor_scripts_ORK.rul
/rosigma/Ruleset/ENEMY/ORK/armors_ORK.rul
/rosigma/Ruleset/ENEMY/ORK/captures_ORK.rul
/rosigma/Ruleset/ENEMY/ORK/corpses_ORK.rul
/rosigma/Ruleset/ENEMY/ORK/ufopaedia_ORK.rul
/rosigma/Ruleset/ENEMY/ORK/units_ORK.rul
/rosigma/Ruleset/ENEMY/ORK/weapons_ORK.rul
/rosigma/Ruleset/ENEMY/SLAANESH/armors_slaanesh.rul
/rosigma/Ruleset/ENEMY/SLAANESH/captures_slaanesh.rul
/rosigma/Ruleset/ENEMY/SLAANESH/corpses_slaanesh.rul
/rosigma/Ruleset/ENEMY/SLAANESH/weapons_slaanesh.rul
/rosigma/Ruleset/ENEMY/TRAITOR_GUARD/armors_traitor_guard.rul
/rosigma/Ruleset/ENEMY/TRAITOR_GUARD/captures_traitor_guard.rul
/rosigma/Ruleset/ENEMY/TRAITOR_GUARD/corpses_traitor_guard.rul
/rosigma/Ruleset/ENEMY/TZEENTCH/armors_tzeentch.rul
/rosigma/Ruleset/ENEMY/TZEENTCH/captures_tzeentch.rul
/rosigma/Ruleset/ENEMY/TZEENTCH/corpses_tzeentch.rul
/rosigma/Ruleset/ENEMY/TZEENTCH/weapons_tzeentch.rul
/rosigma/Ruleset/IG/alienDeployments_IG.rul
/rosigma/Ruleset/IG/armors_IG.rul
/rosigma/Ruleset/IG/armors_layers_IG.rul
/rosigma/Ruleset/IG/armors_scripts_IG.rul
/rosigma/Ruleset/IG/armors_voices_IG.rul
/rosigma/Ruleset/IG/corpses_IG.rul
/rosigma/Ruleset/IG/crafts_IG.rul
/rosigma/Ruleset/IG/events_IG.rul
/rosigma/Ruleset/IG/eventScripts_IG.rul
/rosigma/Ruleset/IG/gibs_of_gory_IG.rul
/rosigma/Ruleset/IG/manufacture_IG.rul
/rosigma/Ruleset/IG/missions_IG.rul
/rosigma/Ruleset/IG/skills_IG.rul
/rosigma/Ruleset/IG/soldiers_command_IG.rul
/rosigma/Ruleset/IG/soldiers_IG.rul
/rosigma/Ruleset/IG/soldierTransformation_IG.rul
/rosigma/Ruleset/IG/startingBase_IG.rul
/rosigma/Ruleset/IG/terrains_IG.rul
/rosigma/Ruleset/IG/training_mission_IG.rul
/rosigma/Ruleset/IG/ufopaedia_IG.rul
/rosigma/Ruleset/IG/ufos_IG.rul
/rosigma/Ruleset/IG/units_IG.rul
/rosigma/Ruleset/IG/weapons_IG.rul
/rosigma/Ruleset/IG/strategies/crafts_strategies_IG.rul
/rosigma/Ruleset/IG/strategies/events_strategies_IG.rul
/rosigma/Ruleset/IG/strategies/eventScripts_strategies_IG.rul
/rosigma/Ruleset/IG/strategies/items_strategies_IG.rul
/rosigma/Ruleset/IG/strategies/manufacture_strategies_IG.rul
/rosigma/Ruleset/IG/strategies/missionScripts_strategies_IG.rul
/rosigma/Ruleset/OTHER/alertSounds_disable.rul
/rosigma/Ruleset/OTHER/alienDeployments_killpoints.rul
/rosigma/Ruleset/OTHER/captures_civ.rul
/rosigma/Ruleset/OTHER/corpses_civ.rul
/rosigma/Ruleset/OTHER/corpses_killpoints.rul
/rosigma/Ruleset/OTHER/manufacture_killpoints.rul
/rosigma/Ruleset/scripts/IGMA_scripts_buff.rul
/rosigma/Ruleset/scripts/IGMA_scripts_change_color_ammo.rul
/rosigma/Ruleset/scripts/script_dig_in.rul
/rosigma/Ruleset/scripts/scripts_abilities_commands.rul
/rosigma/Ruleset/scripts/scripts_abilities_miracles.rul
...
/rosigma/Ruleset/scripts/scripts_tenacious_enemies.rul
/rosigma/Ruleset/scripts/scripts_TU_accuracy_penalty.rul
/rosigma/Ruleset/scripts/scripts_turret_reload.rul
/rosigma/Ruleset/scripts/scripts_UFO_visual_confirmed.rul
/rosigma/Ruleset/SM/armors_SM.rul
/rosigma/Ruleset/SM/crafts_SM.rul
/rosigma/Ruleset/SM/events_SM.rul
/rosigma/Ruleset/SM/items_scripts_SM.rul
/rosigma/Ruleset/SM/items_SM.rul
/rosigma/Ruleset/SM/manufacture_CSM.rul
/rosigma/Ruleset/SM/manufacture_SM.rul
/rosigma/Ruleset/SM/scripts_SM.rul
/rosigma/Ruleset/SM/soldiers_SM.rul
/rosigma/Ruleset/SM/soldierTransformations.rul
/rosigma/Ruleset/SM/startingBase_SM.rul
/rosigma/Ruleset/SM/ufopaedia_SM.rul
/rosigma/Ruleset/SM/Deathwatch/armors_layers_DW.rul
/rosigma/Ruleset/SM/Deathwatch/armors_voices_DW.rul
/rosigma/Ruleset/SM/Deathwatch/Deathwatch.rul
/rosigma/Ruleset/SM/PRIMARIS/armors_PRIMARIS.rul
/rosigma/Ruleset/SM/PRIMARIS/manufacture_PRIMARIS.rul
/rosigma/Ruleset/SM/PRIMARIS/ufopaedia_PRIMARIS.rul
Title: Re: Crashes related to ruleset file load order
Post by: Yankes on December 29, 2024, 08:48:53 pm
Do we need use two `Unicode::lowerCase` for every comparison?
Title: Re: Crashes related to ruleset file load order
Post by: Delian on December 29, 2024, 09:04:24 pm
I could technically convert the whole vector into lowercase first, and then do comparisons. But I'm too lazy. This sorting took 3ms for 40k+rosigma+submods in debug mode. If you wanna make a faster version that saves these 3ms, be my guest :P
Title: Re: Crashes related to ruleset file load order
Post by: Yankes on December 30, 2024, 01:13:33 am
My question was too if its needed at all. Most cases modders work with files not zips, if we need choose one I would choose one closer to how files where handed:
z-A, case sensitive, and this make code simpler and faster for this 3ms too (`lowerCase` was most of this time or rest of sorting was?)
Title: Re: Crashes related to ruleset file load order
Post by: Delian on December 30, 2024, 02:10:09 am
As Meridian said, so far we didn't guarantee anything, so there's no "backwards compatibility" that needs to be upheld. As far as "needing" sorting, it only has to be consistent, meaning, it has to happen to prevent bugs that would arise due to different sorting between OS and files inside zips.

I'm ok with leaving sorting the way it's been, as you say (and how I put it in my commit), case sensitive z-a. The arguments about sort code being simpler and faster are irrelevant (lowerCase took 1ms, I optimized it well hehe).

My opinion is also that, if modders were given control over the order in which their .rul files are loaded, it would turn, what's currently a bug nest, into a useful feature.
Title: Re: Crashes related to ruleset file load order
Post by: Yankes on December 30, 2024, 03:04:07 am
> The arguments about sort code being simpler and faster are irrelevant

If we can choose arbitrary from two different sort orders then its relevant.
Same with "backwards compatibility" we will break some mods with any option we choose,
but prudent is at least consider version that will have smaller fallout.

> (lowerCase took 1ms, I optimized it well hehe)

ok, but this is only for ASCII case? with Unicode it was more ugly? Many users can have cyrillic characters in full path (like users folder name).
Title: Re: Crashes related to ruleset file load order
Post by: Meridian on December 30, 2024, 09:43:32 am
Difficult question indeed.

I would start with a "less fallout" case-sensitive version.

Then I would (manually) search for mods, which depend on file load order.
So far I know only of ROSIGMA, but there may be more.

Depending on the result, I'd talk to the affected mod authors and ask them to update their mods before we update OXCE... or decide to stay with the case-sensitive version, if too much trouble for either/both of us.
Title: Re: Crashes related to ruleset file load order
Post by: Meridian on December 30, 2024, 11:19:44 am
Well, ROSIGMA is not compatible with either of these two file load orders.

I guess we go one step back to the original proposal... and see if they can be convinced to clean up in the future.

EDIT: pushed to main branch: https://github.com/MeridianOXC/OpenXcom/commit/ae6ce0fb0b0fac97a4b49840156b31e796604afe