A somewhat overengineered and janky asset downloader for M*hjong S**l.
- It parses the game metadata from a fucky format to something usable.
- It uses the game metadata to categorize assets and change their names to english (where applicable).
- It determines on which server an asset should exist (not every server has them all).
- It resolves conflicts between regional versions of assets, by skipping exact duplicates and renaming everything else.
- It "decrypts" assets (where applicable).
- It filters assets older than a given version if desired, making updates less time consuming.
- Download all assets
./asset_janny
- ...but skip ones older than game version 0.10.149
./asset_janny --min-version=0.10.149
- ...but in the original catfood file structure
./asset_janny --remap=none
- ...but put files for each region in a separate directory
./asset_janny --on-conflict=prefix_dir
- Just show me the URLs it would download and where
./asset_janny --dry-run
- Just save this weird magic catfood file with asset metadata
./asset_janny --dry-run --dump-metadata
When using a binary release, run ./asset_janny --help to get a list of
options, much like this one:
./asset_janny
--output=[path]
directory to which files will be downloaded [default: ./assets]
--max-version=[version]
download assets for a specific version (inclusive), instead of the latest one [default: none]
has to conform to the [major].[minor].[patch] format
--min-version=[version]
download assets more recent than this version (exclusive) [default: none]
has to conform to the [major].[minor].[patch] format
--min-version-file=[path]
like --min-version but reads the value from a file [default: none]
fetched version will be saved to this file, making it useful for automating incremental downloads
note: --min-version takes precedence
--jobs=[n]
number of concurrent download jobs [default: 1]
--progress | --no-progress
display the progress bar [default: true]
--dry-run
do not execute download jobs [default: false]
implies --no-progress
--on-conflict=prefix_file|suffix_file|prefix_dir|skip
how conflicting names of files from different regions should be handled [default: suffix_file]
'suffix_file' adds [region] to the end of a file name
'prefix_file' adds [region] to the beginning of a file name
'prefix_dir' will move files to output/[region] directory
'skip' will skip the download of conflicting file
note: only files that have different size will have the policy applied
files with the same size are assumed to be equivalent and are always skipped
--remap=none|version|metadata
how file paths should be transformed before writing local files [default: metadata]
changing this can be useful as an escape hatch for when the metadata format
significantly changes, breaking the program
'none' uses remote paths as is (implies --on-conflict=skip)
'version' strips version prefix
'metadata' translates remote file paths according to game's metadata
--decrypt | --no-decrypt
whether encrypted files should be decrypted before write [default: true]
--dump-metadata | --no-dump-metadata
write the decoded game metadata file as json [default: false]
--dump-mappings | --no-dump-mappings
write URLs and paths they would be saved to [default: false]
--include-low-quality | --no-include-low-quality
downloads lower quality files when multiple quality variants exist [default: false]
--include-old-cn-resources | --no-include-old-cn-resources
downloads CN server resources from before the quality variants were introduced [default: false]
note: all these resources exist in the new 'lang' directories too
--help
show this information and exit
Running ./asset_janny with no extra arguments will start the download process
into the current directory, with default options.
In order to run this from source, you will need deno. Use
deno task run to run the program. deno task dist to build executables and a
JS bundle.
- Windows build is completely untested. I'd be surprised if it actually works fine.
- Some assets don't seem to exist on any of the servers, so they will throw errors at runtime. That's expected. Please let me know if you aware of some fix for this. It's possible that I just overlooked some edge case.
- The name remapping aspect of the program is strongly tied to the structure of
game's metadata format. There's a good chance that an update will break it and
the code will need to be updated. Just in case, there's an escape hatch for
this exact issue: the
--no-remapflag. It naively determines which assets should be decrypted, by checking that the path containsIt now excludes known mangled files, but it's a brittle solution.extendRes. Sometimes it mangles unencrypted files instead.