-
Notifications
You must be signed in to change notification settings - Fork 2
Adding built-in support and rules for games #134
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
| {"generic", GameProfile::GENERIC}, | ||
| {"diablo1", GameProfile::DIABLO1}, | ||
| {"diablo", GameProfile::DIABLO1}, | ||
| {"lordsofmagic", GameProfile::LORDSOFMAGIC}, | ||
| {"lomse", GameProfile::LORDSOFMAGIC}, | ||
| {"starcraft", GameProfile::STARCRAFT1}, | ||
| {"starcraft1", GameProfile::STARCRAFT1}, | ||
| {"sc", GameProfile::STARCRAFT1}, | ||
| {"sc1", GameProfile::STARCRAFT1}, | ||
| {"warcraft2", GameProfile::WARCRAFT2}, | ||
| {"wc2", GameProfile::WARCRAFT2}, | ||
| {"war2", GameProfile::WARCRAFT2}, | ||
| {"diablo2", GameProfile::DIABLO2}, | ||
| {"d2", GameProfile::DIABLO2}, | ||
| {"warcraft3", GameProfile::WARCRAFT3}, | ||
| {"wc3", GameProfile::WARCRAFT3}, | ||
| {"war3", GameProfile::WARCRAFT3}, | ||
| {"warcraft3-map", GameProfile::WARCRAFT3_MAP}, | ||
| {"wc3-map", GameProfile::WARCRAFT3_MAP}, | ||
| {"war3-map", GameProfile::WARCRAFT3_MAP}, | ||
| {"wow1", GameProfile::WOW_1X}, | ||
| {"wow-vanilla", GameProfile::WOW_1X}, | ||
| {"wow2", GameProfile::WOW_2X}, | ||
| {"wow-tbc", GameProfile::WOW_2X}, | ||
| {"wow3", GameProfile::WOW_3X}, | ||
| {"wow-wotlk", GameProfile::WOW_3X}, | ||
| {"wow4", GameProfile::WOW_4X}, | ||
| {"wow-cataclysm", GameProfile::WOW_4X}, | ||
| {"wow5", GameProfile::WOW_5X}, | ||
| {"wow-mop", GameProfile::WOW_5X}, | ||
| {"starcraft2", GameProfile::STARCRAFT2}, | ||
| {"sc2", GameProfile::STARCRAFT2}, | ||
| {"diablo3", GameProfile::DIABLO3}, | ||
| {"d3", GameProfile::DIABLO3} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are all valid strings to use for the --game parameter
| case GameProfile::GENERIC: return "generic"; | ||
| case GameProfile::DIABLO1: return "diablo1"; | ||
| case GameProfile::LORDSOFMAGIC: return "lordsofmagic"; | ||
| case GameProfile::WARCRAFT2: return "warcraft2"; | ||
| case GameProfile::STARCRAFT1: return "starcraft1"; | ||
| case GameProfile::DIABLO2: return "diablo2"; | ||
| case GameProfile::WARCRAFT3: return "warcraft3"; | ||
| case GameProfile::WARCRAFT3_MAP: return "warcraft3-map"; | ||
| case GameProfile::WOW_1X: return "wow-vanilla"; | ||
| case GameProfile::WOW_2X: return "wow-tbc"; | ||
| case GameProfile::WOW_3X: return "wow-wotlk"; | ||
| case GameProfile::WOW_4X: return "wow-cataclysm"; | ||
| case GameProfile::WOW_5X: return "wow-mop"; | ||
| case GameProfile::STARCRAFT2: return "starcraft2"; | ||
| case GameProfile::DIABLO3: return "diablo3"; | ||
| default: return "generic"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These values will be displayed by CLI11. They are fewer than what the --game parameter accepts. I figured it would be a bit repetitive for the user to have to wade through too many aliases, e.g. "warcraft3, wc3, war3, warcraft3-map, wc3-map, war3-map". The reason I put these aliases there are, of course, to make it convenient for the user
| str(binary_path), "create", | ||
| "--version", str(version), | ||
| "--file-flags1", "4294967295", | ||
| "--file-flags2", "4294967295", | ||
| "--file-flags3", "0", | ||
| "--attr-flags", "15", | ||
| "--flags", "66048", | ||
| "--compression", "2", | ||
| "--compression-next", "4294967295", | ||
| "-o", str(output_file), | ||
| str(target_dir), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to have these MPQs be as similar as possible to how they were before, otherwise many old tests would need to be updated. But this test becomes a bit "messy" because of it.
| str(binary_path), "create", "-s", | ||
| "--file-flags1", "4294967295", | ||
| "--file-flags2", "4294967295", | ||
| "--file-flags3", "0", | ||
| "--attr-flags", "15", | ||
| "--flags", "512", | ||
| "--compression", "2", | ||
| "--compression-next", "4294967295", | ||
| "-o", str(output_file), | ||
| str(target_dir), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to have these MPQs be as similar as possible to how they were before, otherwise many old tests would need to be updated. But this test becomes a bit "messy" because of it.
| # Create output_file path without suffix (default extract behavior is MPQ without extension) | ||
| output_file = output_dir.with_suffix("") | ||
|
|
||
| # Create output_files set based on directory contents (not full path) | ||
| output_files = set(fi.name for fi in output_file.glob("*")) | ||
| output_files = set(fi.name for fi in output_dir.glob("*")) | ||
|
|
||
| assert result.returncode == 0, f"mpqcli failed with error: {result.stderr}" | ||
| assert output_lines == expected_lines, f"Unexpected output: {output_lines}" | ||
| assert output_file.exists(), "Output directory was not created" | ||
| assert output_dir.exists(), "Output directory was not created" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see now that this actually isn't related to the rest of the PR (sorry!). This change makes the test nicer and more consistent with other test cases though.
| "Header offset: 0", | ||
| "Header size: 32", | ||
| "Archive size: 1380", | ||
| "Archive size: 1381", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we're now creating archives with SFileCreateArchive2 instead of SFileCreateArchive, there are some minor size differences.
| expected_output = { | ||
| " 27 enUS (listfile)", | ||
| " 148 enUS (attributes)", | ||
| " 149 enUS (attributes)", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we're now creating archives with SFileCreateArchive2 instead of SFileCreateArchive, there are some minor size differences.
Listing and extracting works in older games, but not MPQ creation or adding files to archives.
The Readme says (emphasis mine):
... however, this is incorrect; mpqcli currently compresses using Zlib, which is a compression type that older games don't handle. Different games use different flags and compression methods, and they may differ on file types.
This PR implements support for all relevant Blizzard/Sierra games starting with Diablo I (1997) up until Diablo III (2012).
The CLI now exposes a
--gameflag forcreateandaddsubcommands, and by providing it, mpqcli automatically selects the correct settings based on the game and what sort of file the user is adding. The CLI also exposes ways to override all of these settings for advanced users, but just giving e.g.--game warcraft3should be enough for all normal usage.Three rules exist to determine what settings to chose: based on file size, based on a file name mask (e.g. *.wav), or default rules if nothing else applies.
This "compatibility matrix" of settings and games comes directly from Ladislav Zezula: ladislav-zezula/StormLib#406 (comment)
I realize it is quite a big PR, but it should hopefully be straight-forward enough. Please let me know if you have any thoughts or issues.