Skip to content

Options files

Alejandro González edited this page Jul 1, 2023 · 49 revisions

This document is for PackSquash version v0.4.0. Different versions may use incompatible sets of options. If you have to use an older version, something that we don't recommend or support, please refer to the documentation appropriate for that version:

Table of contents

Introduction

PackSquash requires options to be explicitly configured to function. These options are read from TOML v1.0.0 documents that contain specific keys and tables. TOML is expected to be easy for humans to read and easy for programs to parse and generate.

The only required option is pack_directory. The following sections describe in detail all the options you can customize. If they are too dense for you, or you aren't sure how an option works, you may find the examples at the end of this document useful to get started.

How to pass options

PackSquash can parse TOML documents containing the options documented here from two sources:

  • From a file. The TOML document with options thus becomes the so-called options file. The path of the options file to read is passed as a command-line parameter. Options files are the recommended way for end-users to store, exchange, and make PackSquash use a set of options.
  • From its standard input stream (usually, the user keyboard or pipe). This source is used if PackSquash is not passed a path in its command line parameters or if the path is a hyphen ("-"). Reading options from the standard input is suitable for making PackSquash consume the output of another program (piping) or advanced interactive usage.

You can also get a full list of supported command-line arguments via the --help switch.

Global options

The global options are key and value pairs that control what pack is processed and how. They belong outside of any table (i.e., before any table begins). PackSquash rejects options files that contain global options not described in this section to improve extensibility. This section describes such available options.

pack_directory

Type: String

Default value: none (required)

The absolute or relative path to the directory where the pack that will be optimized resides.

If you use a literal string (i.e., surround the path with single quotes, 'like this') you won't need to escape any characters, but you won't be able to write paths that contain a single quote. On the other hand, if you use basic strings (i.e., surround the path by double quotes, "like this"), you will need to escape double quotes, backslashes, and other special characters defined by the TOML specification, but you will be able to write paths that contain a single quote. For more details about how strings are parsed, please read the TOML specification.

Example:

pack_directory = 'C:\path\to\pack'

output_file_path

Type: String

Default value: pack.zip (file pack.zip in the current working directory)

The absolute or relative path to the ZIP file that contains the optimized pack that PackSquash will generate. This path must point to a file that may already exist or not, but never to a directory.

If the ZIP file indicated by this path already exists, PackSquash may try to open and use it to generate a new version, depending on the values of the zip_spec_conformance_level and never_store_squash_times options. Please read their description for more details.

Example:

output_file_path = 'C:\path\to\result\pack\zip\file\my_pack.zip'

recompress_compressed_files

Type: Boolean

Default value: false

If true, this option makes PackSquash try to compress files whose contents are already compressed before adding them to the generated ZIP file, after all the file type-specific optimizations have been applied. This can squeeze in some extra savings at the cost of noticeably increased pack processing times. Currently, Ogg and PNG assets are the only already compressed files affected by this option, but this may change in the future.

Example:

recompress_compressed_files = true

zip_compression_iterations

Type: Integer in the [0, 255] interval

Default value: 20

The number of Zopfli compression iterations that PackSquash will do when compressing a file of 1 MiB magnitude just before it is added to the generated ZIP file. This affects files whose contents are not already compressed or all files if recompress_compressed_files is enabled.

A higher number of iterations means that bigger files will be subject to more compression iterations, which may lead to higher space savings but is slower. Lower numbers imply that, in general, fewer compression iterations will be done, which is quicker but reduces space savings.

Note that PackSquash calculates the exact number of iterations for a file depending on its size, so this number of iterations only guides that computation. More precisely, PackSquash targets a reference compression time, so smaller files will be compressed more, and larger files will be compressed less. Also, the file size is converted into a non-linear magnitude that grows slower than the file size itself (in mathematical terms, the order of the function is that of a fractional power, which is less than linear), and this magnitude is what is really used to compute the number of iterations. A consequence of this design is that PackSquash will be "hesitant" to reduce the number of iterations for bigger files to meet the target time, exceeding it, but not by too much.

Unless set to zero, the number of iterations is clamped to the [1, 20] interval, so using values outside that interval for this option will only change the magnitude threshold where iterations start being reduced to meet a target time.

Zero is a special case: no file will be compressed, no matter its size. This is useful to speed up the process without sacrificing file-specific optimization techniques. It might also speed up the loading of your pack by Minecraft clients because they won't have to decompress any file, which is a bottleneck, especially with the advent of fast storage devices. The obvious downside is that the generated ZIP files will likely be larger, which increases bandwidth requirements. However, if the decompression speed is much greater than the storage device speed (i.e., a beefy CPU is paired with a slow HDD, for example), Minecraft clients may take longer to load the pack.

Example:

zip_compression_iterations = 5

automatic_minecraft_quirks_detection

Type: Boolean

Default value: true

When this option is set to true, PackSquash will try to automatically deduce an appropriate set of Minecraft quirks that affect how pack files can be optimized by looking at the pack files. This automatic detection works fine in most circumstances, but because quirks affect specific Minecraft versions, and maybe only under some conditions, it might be inexact.

If you exactly know what quirks affect your pack and do not want PackSquash to come up with its own set of quirks to work around, set this option to false, and configure work_around_minecraft_quirks accordingly. Otherwise, you can leave it set to true.

Please note that the automatic Minecraft quirks detection may validate and process the contents of the pack.mcmeta file, even if validate_pack_metadata_file and automatic_asset_types_mask_detection are set to false. To prevent PackSquash from validating that file, these options should be all set to false.

Example:

automatic_minecraft_quirks_detection = true

work_around_minecraft_quirks

Type: Array of String

Default value: [] (empty array; no quirks worked around, unless automatic_minecraft_quirks_detection is set to true and quirks were detected)

Some Minecraft versions have some quirks that limit how some files can be compressed before they stop being interpreted correctly by the game. PackSquash can work around these quirks, but doing so may come at the cost of reduced space savings, increased processing times, or other undesirable consequences, so such workarounds should only be done if a pack is affected by them. This option allows to manually specify a comma-separated list of quirks that will be worked around if automatic_minecraft_quirks_detection is set to false. The following quirks are supported:

  • grayscale_images_gamma_miscorrection: older versions of Minecraft (probably all versions since 1.6 until 1.13 are affected) assume that grayscale images are in a fairly uncommon color space instead of the more common sRGB space presumed for the rest of color types. Because PackSquash can compress full-color images that only have gray pixels to actual grayscale format to save space, affected Minecraft versions display those images with colors that look "washed out". The workaround implemented for this quirk stops PackSquash from trying to reduce color images to grayscale format under any circumstances, which may hurt compression.
  • restrictive_banner_layer_texture_format_check: older versions of Minecraft (probably all versions from 1.6 until 1.13 are affected) require banner and shield layer textures to be stored in RGBA format, or else the layers they represent won't be applied at all, even if the palette contains transparency data. PackSquash can convert images encoded in RGBA format to palette format to save space, triggering this quirky behavior in affected versions. This workaround stops PackSquash from changing the color format of the affected textures to a palette, which includes color quantization, as it is used to generate a palette. This incurs some space costs.
  • bad_entity_eye_layer_texture_transparency_blending: all currently known Minecraft versions overlay entity layer textures in a way that does not rightly account for transparency, taking into account their color and not only their transparency values as blending coefficients to use for overlying that texture (see MC-235953). PackSquash can change the color of transparent pixels, triggering this behavior. This workaround stops PackSquash from changing the color of transparent pixels and quantizing the pixels to a palette to reduce texture file size, as both optimizations do not guarantee that the color of transparent pixels will stay the same.
  • java8_zip_parsing: the latest Minecraft versions, from 1.17 onwards, are compiled for Java 16+, which means that they do not support older Java versions. On the other hand, Java 8 was used almost ubiquitously with older Minecraft clients, especially in modded environments. However, a lot of things have changed in newer Java versions, including low-level details of how ZIP files are parsed. When a ZIP specification conformance level that adds extraction protection is used, this workaround tells PackSquash to use obfuscation techniques that work fine with Java 8. This comes at the cost of protection that is a bit different, but the small differences will extremely likely not matter in protection strength. Compressibility can be impacted negatively, though. This quirk does not have any effect if an affected ZIP specification conformance level is not chosen or if the Minecraft client is run using newer Java versions.
  • ogg_obfuscation_incompatibility: the latest Minecraft versions, from 1.14 onwards, refactored their audio decoding in such a way that the obfuscation techniques PackSquash uses were made possible. Older Minecraft versions do not support these obfuscated files, showing errors in the console and freezing the game when they are played. This workaround ensures that no obfuscation is done to any Ogg Vorbis file generated by PackSquash, so the pack will work with older versions at the cost of no obfuscation. Note that, due to 1.13 and 1.14 sharing the same pack format version, the autodetection code for this quirk will err on the safe side and only consider Minecraft versions starting from 1.15 to not be affected by this quirk.

When automatic_minecraft_quirks_detection is set to true, PackSquash will use an automatically detected set of quirks no matter what, ignoring the value of this option.

Example:

work_around_minecraft_quirks = ['grayscale_images_gamma_miscorrection', 'restrictive_banner_layer_texture_format_check', 'bad_entity_eye_layer_texture_transparency_blending', 'java8_zip_parsing', 'ogg_obfuscation_incompatibility']

automatic_asset_types_mask_detection

Type: Boolean

Default value: true

By default, PackSquash will attempt to automatically deduce the appropriate set of pack files to include in the generated ZIP by checking what Minecraft versions it targets, according to the pack format version. This works fine in most circumstances and saves space if the pack contains legacy or too new files for the targeted Minecraft version, but it might be undesirable sometimes.

If you want PackSquash to include every pack file it recognizes and is enabled in allow_mods no matter what, set this option to false. Otherwise, leave it set to true to let it exclude files that are known to be not relevant.

When this option is set to true, the pack.mcmeta file may be read and validated, even if validate_pack_metadata_file and automatic_minecraft_quirks_detection are set to false. To guarantee that file is not read no matter what, these options should be all set to false.

Example:

automatic_asset_types_mask_detection = true

allow_mods

Type: Array of String

Default value: [] (empty array; skip all mod-specific files)

PackSquash supports pack files that are only consumed by certain Minecraft mods, but, in the interest of optimizing packs as much as possible, it assumes that mod-specific files will not be used by the game by default and discards (skips) them from the generated ZIP file. This will break your pack unless you tell PackSquash about the involved mods via this option, whose value is a comma-separated list of mod identifiers. The following mods are supported:

  • OptiFine: adds support for Java properties files used by several of its features (.properties) and Custom Entity Model files (.jem, .jemc, .jpm, and .jpmc). It also accepts and optimizes vanilla models in the custom item feature files directory.
  • Minecraft Transit Railway 3: adds support for Blockbench modded entity model projects for custom train models (.bbmodel and .bbmodelc) in the mtr asset namespace.

Example:

allow_mods = ['OptiFine', 'Minecraft Transit Railway 3']

This option is only supported if PackSquash was compiled with support for mods, which always is the case if you use a PackSquash build downloaded from this repository.

skip_pack_icon

Type: Boolean

Default value: false

Under some circumstances, the pack.png pack icon won't be shown in the Minecraft UI, even if it is present. Therefore, skipping it will save space without any side effects if the pack is to be used only under these circumstances. If this option is set to true, the pack.png file that contains the pack icon will not be added to the generated ZIP file.

In most older Minecraft versions, which include 1.16.3 and 1.17.1, pack icons are not shown for server resource packs.

Example:

skip_pack_icon = true

validate_pack_metadata_file

Type: Boolean

Default value: true

This option controls whether the pack metadata file, pack.mcmeta, will be validated (true) or not (false). Validating this file is a good thing in most circumstances, and you should only disable this option if you are extremely concerned about performance, need to add a pack.mcmeta file to the generated ZIP file later, want to use PackSquash with folders that are not a Minecraft pack, or similar reasons.

Even if this option is set to false, the pack.mcmeta may still be validated if automatic_minecraft_quirks_detection or automatic_asset_types_mask_detection are enabled. To guarantee that the pack metadata file is not validated no matter what, both options should be set to false.

Example:

validate_pack_metadata_file = true

ignore_system_and_hidden_files

Type: Boolean

Default value: true

This option controls whether PackSquash will ignore system (i.e., whose name signals they were generated by a ubiquitous and well-known program that is not related to a Minecraft pack) and hidden files (i.e., whose name starts with a dot), not printing status messages about them, nor even trying to process them. If true, these files will be ignored. If false, these files will not be treated specially and will be processed as normal. Ignoring these files is usually a good thing to do unless your pack really contains files that are filtered out by this option.

Example:

ignore_system_and_hidden_files = false

zip_spec_conformance_level

Type: String

Default value: pedantic

PackSquash uses a custom ZIP compressor that is able to balance ZIP file specification conformance and interoperability with increased performance, space savings, compressibility, and protection against external programs being able to extract files from it. This option lets you choose the ZIP specification conformance level that is most suitable to your pack and situation. The following levels are available:

  • pedantic: the generated ZIP files will follow the ZIP file specification to the letter, with the objective that they can be used with virtually any ZIP file manipulation program. This is a safe and user-friendly default, but it has a big downside: PackSquash can't do anything that may render the ZIP files it generates unconventional. This means that identical files after file type-specific optimizations will not be stored only once (i.e., deduplicated), the generated ZIP files will not contain the metadata needed to reuse them in future runs to speed up execution, files will be able to be extracted from them as normal, and compressibility of the ZIP file internal structures will not be improved. Anyway, you still get file type-specific optimizations, Zopfli compression, and metadata removal in both the generated ZIP and the pack file, which usually have a big impact on pack sizes.
  • high: similar to pedantic, but it allows storing the metadata needed to reuse the generated ZIP files in future PackSquash runs. This metadata is stored in a way that is compatible with the vast majority of ZIP file manipulation programs, although it technically does not conform to the ZIP file specification, so, while it is technically possible to find a program that rejects the file, in practice that is highly unlikely.
  • balanced: like high, but enables deduplication of identical files in the generated ZIP file. This yields significant space savings if somewhat big files are repeated in your pack, like textures or sounds, although it also helps with smaller files. Some ZIP file manipulation programs will still properly work when files are deduplicated, while others will not, so while this has a significant impact on interoperability, how that matters to you depends on what programs you expect to use with the ZIP file.
  • disregard: PackSquash will use every trick up its sleeve to give you every feature it offers, including extraction protection and improved internal ZIP file structures compressibility, without any consideration for interoperability whatsoever. The only constraint is that the pack works as usual within Minecraft.

The following table summarizes and compares what each available conformance level offers.

pedantic high balanced disregard
File type-specific optimizations
Zopfli compression
Metadata removal*1
Identical file deduplication
Extraction protection*2
Improved internal ZIP file structures compressibility*3
Programs that can manipulate the output ZIP file Any The vast majority of programs Select programs As few as possible
Levels whose output ZIP files can be reused with this level*4 high, balanced high, balanced disregard
Appropriate for Using PackSquash for the first time, doing backups, permissively licensed packs, trusting the users of your pack, and fostering collaboration and innovation Similar use cases as pedantic, but you want to take advantage of reusing previous ZIP files Similar use cases as high, but you want file deduplication too Proprietary packs whose usage you want to limit, especially for public server resource packs; just getting the best optimization possible

*1 Metadata removal includes non-critical PNG headers, Vorbis comments and ID3 tags, and filesystem metadata such as creation time, modification time, permissions, and proprietary user. This improves privacy and reduces file sizes.

*2 Due to Minecraft limitations, extraction protection is done using techniques that are not considered secure by modern information security standards (more specifically, they do not hold the Kerckhoffs's principle). In order words, it is not reasonable to expect strong security guarantees from this protection.

*3 Compressibility improvements do not reduce the actual size of the generated ZIP files. However, they allow for higher savings if the generated ZIP files are compressed again. This is useful when serving packs over an HTTP server with static compression enabled because it reduces bandwidth requirements, transparently compressing and decompressing the pack while it is being downloaded.

*4 In general, you should be careful when you try to reuse a generated ZIP file to speed up the optimization of a pack if you do any modification to the options file, update PackSquash, move that file between devices, modify it outside of PackSquash, or the set of Minecraft quirks to work around changes. Failure to follow this advice may lead to the generation of incorrect ZIP files in ways that may not be immediately obvious. Just changing the conformance level to another that is compatible with the level used in the previous run is fine, however. It is also okay to reuse a generated ZIP file as many times as desired if you don't change anything. These are the catches you should keep in mind:

  • First of all, you may set the never_store_squash_times option to a value that does not save the metadata needed to reuse ZIP files, independently of the conformance level. You should not reuse ZIP files that were generated with this option enabled (i.e., set to true) after you disable it (i.e., set it to false). Doing the opposite thing (i.e., from false to true) is fine, but that will end up not reusing the ZIP file.
  • Any change to an option that affects how files are compressed or optimized will not be applied for non-modified files because they will not be processed again.
  • If the set of Minecraft quirks to work around changes, either because PackSquash detects that the pack was upgraded or downgraded to work with another Minecraft version or you've explicitly set them to a different value, the change will not be applied for non-modified files.
  • PackSquash quickly detects whether a file was modified or not by looking at the modification timestamp provided by the filesystem and comparing it with an encrypted timestamp stored in the ZIP file. The encryption key used is device-specific (see the documentation on system identifiers for more information). If modification timestamps are not available or reliable, this detection may not work as expected (this usually is not the case unless you copy files between partitions or devices, though).
  • You should not modify otherwise reusable generated ZIP files outside of PackSquash. Doing so may change the file structure or timestamp metadata in ways that PackSquash doesn't expect. You can copy the generated file around and read or extract files from it.
  • Some effort is made to make ZIP files generated in the current version of PackSquash compatible with future versions, but this compatibility is by no means guaranteed. It is best to start from scratch after updating PackSquash unless you validate that the versions are compatible.
  • Reusing ZIP files that were generated with size_increasing_zip_obfuscation set to false after it is changed to true, and vice versa, is not safe. Trying to do so will, in the best-case scenario, end up not reusing the ZIP file at all, and in the worst-case scenario, corrupting data.

With these gotchas out of the way, to reuse a ZIP file that was previously generated by PackSquash, it suffices to set output_file_path to the path of that file. The previous version of the file will be overwritten after the pack is processed.

Example:

zip_spec_conformance_level = 'high'

size_increasing_zip_obfuscation

Type: Boolean

Default value: false

If zip_spec_conformance_level is set to disregard, enabling this option will add more protections against inspecting, extracting, or tampering with the generated ZIP file that will slightly increase its size. This option does not affect whether protections that do not increase the file size are added or not and does not have any effect if the conformance level does not feature protection.

Example:

size_increasing_zip_obfuscation = true

percentage_of_zip_structures_tuned_for_obfuscation_discretion

Type: Integer in the [0, 100] interval

Default value: 0

If zip_spec_conformance_level is set to disregard, this option sets the approximate probability for each internal generated ZIP file structure to be stored in a way that favors additional discretion of the fact that protection techniques were used, as opposed to a way that favors increased compressibility of the result ZIP file. This option is ignored for other conformance levels.

When this option is set to 0 (minimum value), every ZIP record will be stored favoring increased compressibility. Conversely, when it is set to 100 (maximum value), every ZIP record will be stored favoring increased discretion. Other values combine increased discretion and compressibility.

Example:

percentage_of_zip_structures_tuned_for_obfuscation_discretion = 100

never_store_squash_times

Type: Boolean

Default value: false

This option controls whether PackSquash will refuse to store the metadata needed to reuse previously generated ZIP files, and likewise not expect such data if the output ZIP file already exists, thus not reusing its contents to speed up the process in any way, no matter what the zip_spec_conformance_level is.

You might want to set this to true if you are concerned about the presence of encrypted metadata in the generated ZIP files, do not care about potential speedups in later runs, file modification timestamps are unreliable for some reason, or do not want PackSquash to get and use a system ID in any way. In fact, if PackSquash will not be run anymore on this pack, it is a good idea to set this to true, as this improves compressibility a bit and removes the now unnecessary metadata.

Example:

never_store_squash_times = true

threads

Type: Integer greater than zero

Default value: number of available physical CPU threads

The maximum number of concurrent threads that PackSquash will use to process the pack files. Higher numbers can spawn more threads, so if your computer has enough physical CPU threads, several files can be processed at once, improving the speed substantially. However, you might want to use a lower number of threads due to memory, power consumption, open file limitations or CPU time limitation concerns. This number is tentative, meaning that PackSquash may spawn extra threads for internal purposes.

Example:

threads = 4

spooling_buffers_size

Type: Integer greater than or equal to zero

Default value: half of the available main memory reported by the operating system / (number of available physical CPU threads + 1)

The maximum size of the in-memory buffers that temporarily hold data to be written to the generated ZIP file, in MiB. Ideally, if the buffers are big enough to hold the entire ZIP file and any additional scratch data, PackSquash will work almost entirely in memory and not do any disk operation, which is pretty fast. However, if some buffer grows bigger than this size threshold, it has to be rolled over to disk, which usually is much slower to operate with than main memory, because otherwise PackSquash could run out of available memory and be forced to abort its execution, which is a bad thing. The default value is meant to be an educated guess of the optimum value, taking into account the installed physical memory (RAM), the size of the pagination file or swap, the amount of memory currently used by other applications, that other applications may be launched or increase their memory demands while PackSquash executes, and the fact that PackSquash uses a buffer for each thread that processes packs + one for the generated ZIP file.

If you run into out-of-memory errors while executing PackSquash, try decrementing this value to be able to use it without such problems. Conversely, if you observe that PackSquash disk usage suddenly rises notably and there is enough available memory to spare, try incrementing this value for maximum performance.

Example:

spooling_buffers_size = 128

Per-file options

PackSquash supports customizing how several pack file types are compressed, on a per-file basis, via tables. Tables represent a group of options that are applied to the files whose relative path matches a extended glob pattern syntax contained in the table name.

For matching, the path component separator is normalized to a forward slash (/), so the configuration files are operating system agnostic. Also, the * and ? metacharacters can never match a path separator. The backslash character may be used to escape special characters.

For example, you can match any files inside a "music" or "ambience" folder that have a non-empty name and an audio file extension with the following pattern:

**/{music,ambience}/?*.{og[ga],mp3,wav,flac}

Another example that matches the same files as before, but only when they are in the "music" or "ambience" folders of a resource pack assets folder is:

assets/*/sounds/{music,ambience}/?*.{og[ga],mp3,wav,flac}

Keep in mind that if your pattern contains a dot or characters that are not ASCII letters, ASCII digits, underscores, and dashes (A-Za-z0-9_-), you will need to put them in a string (i.e., between single quotes, like 'this') when writing the table name in the options file.

Of course, different file types require different options. PackSquash will detect on the fly the file type the configuration you write is intended for. If several patterns match a single file, PackSquash will use the first one that customizes options appropriate for the file type, and if no pattern is appropriate or no pattern matches, use default options. There is a list of options you can change per file type below.

Audio files

You can customize how PackSquash transcodes the audio files of a pack via the following key and value pairs.

transcode_ogg

Type: Boolean

Default value: true

When true, Ogg files will be reencoded again to apply resampling, channel mixing, pitch shifting, and bitrate reduction, which may degrade their quality, but commonly saves quite a bit of space. If you change it to false, Ogg files will be added to the generated ZIP file without being reencoded or modified. Non-Ogg audio files will be reencoded no matter the value of this option.

Example:

transcode_ogg = false

two_pass_vorbis_optimization_and_validation

Type: Boolean

Default value: true

When true, an additional fast two-pass optimization and validation step will be performed on the generated Ogg Vorbis file before it is added to the pack, regardless of whether it has been transcoded. This enables PackSquash to ensure that the audio file will work fine in Minecraft, losslessly reduce its size by an average of 5%, and optionally obfuscate it to thwart its playback outside of Minecraft (see also ogg_obfuscation).

Due to how fast and unobtrusive this step is, it's usually best to leave it enabled. Good reasons to disable it include troubleshooting and wanting a slightly faster execution at the cost of missing out on the features described above.

Example:

two_pass_vorbis_optimization_and_validation = true

channels

Type: Integer greater than zero

Default value: number of channels of the input audio data

Specifies the number of audio channels that the processed audio file will have in the generated ZIP file. Values different to 1 (mono) or 2 (stereo) make little sense to use with current versions of Minecraft and are not allowed. As per MC-146721, Minecraft computes positional sound effects depending on whether sounds are mono or stereo, so even though mono sounds are more space-efficient (because they contain half the samples), downmixing stereo sounds to mono or upmixing mono sounds to stereo has side effects.

It should be noted that, although mono files contain half the audio data than stereo ones, this does not necessarily translate to half the space savings. The Vorbis codec used in Ogg files employs joint encoding, which encodes several audio signals as the data needed to reconstruct them from one main signal, and that is pretty efficient for common sounds.

Example:

channels = 2

sampling_frequency

Type: Integer greater than zero

Default value: 40050 (40.05 kHz) for stereo audio, 32000 (32 kHz) for mono audio

Specifies the sampling frequency (i.e., number of samples per second) to which the input audio file will be resampled (in Hertz, Hz). If this frequency is higher than the sampling frequency of the input audio file, the resampling will be skipped to avoid wasting space with redundant samples.

As per the Nyquist-Shannon theorem, for a given sampling frequency of 𝑥 Hz, only frequencies up to 𝑥 ÷ 2 Hz can be recreated without aliasing artifacts, in general. Human speech typically employs frequencies up to 6 kHz, so a sampling frequency of 12 kHz saves space while still providing acceptable audio quality. However, other sounds (e.g., music) have a broader frequency spectrum, up to 20 kHz (the generally accepted upper limit of the human hearing range). Therefore, in any case, a frequency greater than 40 kHz is wasteful for encoding audio that will be heard by humans and is not meant to be edited any further. The default value is meant to sound faithful to vanilla sounds that have a wide frequency spectrum while still providing significant savings.

Example:

sampling_frequency = 44100

empty_audio_optimization

Type: Boolean

Default value: true

If true, empty audio files (i.e., with no audio data, or full of complete silence) will be replaced with a special empty audio file that is optimized for size and contains no audio data. This kind of file works fine in Minecraft and most media players, but some may consider the lack of audio data an error.

This option is only honored if the audio file is being transcoded, which is always the case when the transcode_ogg option is set to true.

Example:

empty_audio_optimization = false

bitrate_control_mode

Type: String

Default value: CQF

The bitrate control mode used during transcoding. Different bitrate control modes have different tradeoffs between audio quality, file size, bandwidth predictability, and encoding speed. They also affect how the target_bitrate_control_metric is interpreted, if specified. The available bitrate control modes are:

  • CQF (Constant Quality Factor): the encoder will interpret the target metric as a quality factor and will try to keep the perceived subjective quality constant at all times. The encoder will have no hard pressures to limit the bitrate in any way, although the quality metric tends to be strongly correlated with an average bitrate for typical signals.
    • When in doubt, use this mode, as it provides an effective balance for most situations.
    • The quality factor (i.e., the target metric) is expected to be in the range [-2, 10], where -2 is the worst audio quality, and 10 is the best.
    • Some advantages of this bitrate control mode include:
      • It adapts well to different sampling frequencies and channel counts: the encoder knows that it needs fewer bits to encode mono signals than stereo signals of the same quality level, for example.
      • Unlike with bitrates, it's not possible to ask for unsupported quality levels.
      • Easy-to-encode audio segments are stored in minimal space, with consistent quality: there is no pressure to meet an average bitrate.
      • Performance is significantly higher than when using ABR or CABR modes, because the encoder bitrate management engine is not involved.
    • Some disadvantages of this bitrate control mode include:
      • The relationship between the quality factor and the actual average bitrate is difficult to predict accurately.
      • There are no guarantees against difficult to encode segments significantly bumping the average bitrate.
  • VBR (Variable BitRate): the encoder will interpret the target metric as an approximate bitrate in kbit/s, internally translating it to a quality factor. Therefore, this mode is equivalent to CQF, but with the quality factor selected in a different way.
    • Some advantages of this bitrate control mode over CQF include:
      • The relationship between quality factor and actual average bitrate is easier to predict.
    • Some disadvantages of this bitrate control mode over CQF include:
      • The same bitrate may yield different quality levels for different audio signals, or be too high or too low for the quality factors that apply to the signal.
  • ABR (Average BitRate): the encoder will interpret the target metric as an average bitrate in kbit/s, and will be coerced to maintain that bitrate for the entire audio signal by using a bitrate management engine. No specific subjective quality level will be targeted.
    • Some advantages of this bitrate control mode over CQF and VBR include:
      • The actual average stream bitrate is guaranteed to be very close to the specified average bitrate. Therefore, the resulting file sizes are more predictable.
      • The maximum instantaneous bitrate for an audio segment can be higher than the average for a small time window, as long as it doesn't affect the long-term average.
    • Some disadvantages of this bitrate control mode over CQF and VBR include:
      • Setting too low bitrates for the input signal may severely degrade audio quality, while setting too high bitrates may waste space on padding the data to maintain the average.
      • Easy-to-encode audio segments may be stored with more bits than necessary for a given quality level in order to maintain the average bitrate. Conversely, harder-to-encode segments may sound worse when the encoder is already outputting at a high bitrate, as it will be deprived of bits to devote to them. The resulting subjective quality will be more inconsistent.
      • Performance is significantly worse than when using CQF or VBR due to the bitrate management engine being engaged.
  • CABR (Constrained Average BitRate): the encoder will interpret the target metric as a hard maximum bitrate and internally selected a slightly lower average bitrate than the maximum to maintain. This mode is similar to ABR, but with the addition of a maximum bitrate.
    • Some advantages of this bitrate control mode over ABR include:
      • The actual average bitrate is guaranteed to never exceed the specified maximum bitrate, which limits the maximum file size with certainty.
    • Some disadvantages of this bitrate control mode over ABR include:
      • To ensure that the hard maximum bitrate is never exceeded, a lower average bitrate will be targeted, which provides headroom for hard-to-encode segments, but usually results in inferior quality.

Because the default value of target_bitrate_control_metric is a quality factor, specifying it when selecting a bitrate control mode other than CQF is required.

Example:

bitrate_control_mode = 'VBR'

target_bitrate_control_metric

Type: Float

Default value: 0.25 (quality factor, ≈68 kbit/s at 44.1 kHz) for stereo audio, 0.0 (quality factor) for mono audio

The metric to use as a target for the specified bitrate control mode when trancoding. Depending on the selected bitrate control mode, this will be interpreted as a quality factor, average bitrate, approximate bitrate, or maximum bitrate.

Example:

target_bitrate_control_metric = 48 # To be interpreted as a bitrate in kbit/s

ogg_obfuscation

Type: Boolean

Default value: false

If true, the generated Ogg Vorbis files will be mangled so that they will be harder to play outside of Minecraft. The obfuscation technique used by PackSquash is not robust against some scenarios or expert knowledge, but it does not increase file size.

This option is only taken into account if two_pass_vorbis_optimization_and_validation is set to true and the ogg_obfuscation_incompatibility quirk is not being worked around.

Example:

ogg_obfuscation = true

target_pitch

Type: Float

Default value: 1.0

Sets the in-game pitch shift coefficient that will result in the audio being played back at its original speed, affecting the perceived pitch and tempo. This coefficient is specified as an argument to the playsound command and other places where Minecraft accepts a sound pitch number. For values smaller than 1, the audio stored in the generated ZIP file will be sped up, so it has less duration, and the generated file is smaller. Conversely, for values larger than 1, the audio file will be slowed down, be longer, and thus bigger. A value that exactly is one does not modify the audio.

Changing the sampling frequency is a better way to save space than using this option. The effect on audio quality and file size that this option has is similar to lowering or increasing the sampling rate by the same factor. However, because this option enforces the sound playback to be pitch-shifted for it to sound right, this coefficient can be used as a shared secret, slowing down ripping attempts. Nevertheless, the offered protection is weak: there is a theoretical maximum of 230 keys (i.e., 32-bit IEEE 754 floating-point numbers in (0, 2], the interval accepted by Minecraft), which by itself is not difficult to brute force, and further practical considerations reduce the keyspace significantly.

Example:

target_pitch = 1.5

JSON files

You can customize how PackSquash optimizes the .json, .jsonc (JSON with comments), .mcmeta and .mcmetac files of a pack with the following key and value pairs. If allow_mods includes OptiFine, these options also apply to .jem, .jemc, .jpm, and .jpmc files. If allow_mods includes Minecraft Transit Railway 3, these options also apply to custom model files with .bbmodel and .bbmodelc extensions.

minify_json

Type: Boolean

Default value: true

When true, the JSON data will be minified, removing comments and unnecessary whitespace to improve space savings. If this is changed to false, the JSON will be prettified instead, reindenting it and adding spaces that make the content easier to read by humans, which takes more space but ensures consistent formatting. In any case, PackSquash will validate the JSON file.

Example:

minify_json = false

delete_bloat_keys

Type: Boolean

Default value: true

If this option is set to true, PackSquash will delete known-superfluous keys from JSON files, like credits or metadata added by pack authoring tools, that are completely ignored by Minecraft. This improves privacy and space savings. On the contrary, when set to false, those keys will be left as-is in the JSON file.

Example:

delete_bloat_keys = false

always_allow_json_comments

Type: Boolean

Default value: true

If true, PackSquash will allow comments in JSON files whose usual extension does not end with an extra c letter, which explicitly marks the file as having an extended JSON format that may contain comments. If false, comments will only be allowed in JSON files with those specific extensions: .jsonc, .mcmetac, etc.

Example:

always_allow_json_comments = false

PNG files

You can customize how PackSquash optimizes the PNG files of a pack with the following key and value pairs.

image_data_compression_iterations

Type: Integer in the [0, 255] interval

Default value: 5

Sets the number of Zopfli compression iterations that PackSquash will do to compress raw pixel data that amounts to a magnitude of 1 MiB. This option is similar to zip_compression_iterations and is used to feed the same linear model but with parameters better suited for image compression.

When the number of compression iterations drops to zero, which happens when this option is set to zero or the texture is pretty big, a much faster DEFLATE compression algorithm is used instead of Zopfli. This extra performance may come at the cost of file size. On the other side, the number of iterations is limited to a maximum of 15. Values greater than 15 are still useful for this setting because they change the threshold where iterations start being reduced in order to keep acceptable performance levels.

Example:

image_data_compression_iterations = 15

color_quantization_target

Type: String

Default value: auto

Sets the color quantization target for an image, which affects whether the lossy color quantization process is performed and how. Quantization is useful because it replaces the colors in the image with those in a palette that can fit in a certain bit depth, which helps save space considerably. Higher bit depths can represent more color variety but take more space. Lower bit depths are more space-efficient but may reduce color fidelity because fewer different colors can be represented. The supported color quantization targets are as follows:

  • none: no color quantization will be done at all. This means that PackSquash will only apply lossless optimizations to the image, not changing any visible colors in any way. Color quantization must be disabled on textures that are used as input data for custom shaders.
  • auto: like eight_bit_depth, but the image will not be color-quantized if PackSquash determines that not doing so is more space-efficient.
  • eight_bit_depth: the image will be reduced to at most 256 colors, which fit in 8 bits. This can only effectively be a lossy process if the input texture is more than 16x16 pixels because 16x16 pixels images contain at most 256 colors.
  • four_bit_depth: the image will be reduced to at most 16 colors, which fit in 4 bits. This halves the per-color storage requirements compared with 8 bits. However, there is only so much you can do with just 16 colors. Textures that are bigger than 4x4 pixels and have color variety will be susceptible to quality loss.
  • two_bit_depth: the image will be reduced to at most four colors, which fit in 2 bits. This halves the per-color storage requirements compared with 4 bits. This quantization target is only practical for extremely simple textures or if you find posterization effects artistically fitting.
  • one_bit_depth: the image will be reduced to at most two colors, which fit in 1 bit. This quantization target is only practical for extremely simple textures or if you find posterization effects artistically fitting.

With the exception of none, all of the targets above use an image-specific palette, and a configurable amount of dithering (see the color_quantization_dithering_level option). auto and eight_bit_depth provide a reasonably good quality while yielding high space savings, even for big textures with plenty of color variety.

Example:

color_quantization_target = 'none'

color_quantization_dithering_level

Type: Float in the [0, 1] interval

Default value: 0.85

The level of dithering that will be applied when quantizing colors. This option has no effect if color_quantization_target is set to not perform color quantization.

Dithering is a technique that improves the perceived color depth of color-quantized images by diffusing the reduced number of available colors in areas that lost color information. The dithered areas appear more as if they had their original colors preserved, reducing color banding artifacts. However, dithering can introduce noisy, hard-to-compress diffusion patterns.

In most images, especially natural-looking ones, color quantization saves enough space to compensate for the decreased dithered areas compressibility, so lots of dithering is a good idea because it gives better-looking results and still reduces file sizes. Extreme counterexamples are big images composed of big constant color blocks whose color is not in the quantized palette: here, dithering would reduce compressibility a lot while yielding a worse look than just completely replacing the color of the blocks, so reducing the dithering level is warranted.

color_quantization_dithering_level = 1

maximum_width_and_height

Type: Integer greater than or equal to zero

Default value: 8192

Sets the maximum width and height of the images that PackSquash will accept without throwing an error. The rationale behind this option is that limiting the size of the images that PackSquash can deal with sets a high bound of memory usage and image processing time, helping authoring efficient packs, and improving the compatibility of the pack with GPUs that only support smaller texture sizes.

In relation to the last point, Minecraft internally builds texture atlases with textures of resource packs, for efficiency reasons (a texture atlas is generated by stitching individual textures together so that they become part of a single larger texture). Assuming a maximum texture size of 65536x65536, 256 individual textures of 4096x4096 would fit in such an atlas, which is a fairly low number and not enough to hold all vanilla textures. Resource packs that replace only a few atlased textures may get away with textures that are even bigger than 4096x4096, but that might only happen on "beefy" GPUs, and, in general, it does not make much sense to mix small textures with such big textures.

It only makes sense to increase the default value if you know what you are doing, the affected images contain several animation frames or are texture atlases themselves, or use mods that somehow relax the need for GPUs to support big textures. If you do not plan on pushing Minecraft to its limits or making high-definition resource packs, setting this to an even lower value than the default is a good thing.

Example:

maximum_width_and_height = 4096

skip_alpha_optimizations

Type: Boolean

Default value: false

If set to true, this option prevents the color values of completely transparent pixels from being changed to achieve better compression. This optimization is visually lossless: completely transparent pixels are invisible no matter their color, and images that lack an alpha channel are not affected. However, if the image is meant to be used as data by custom shaders, edited further or contains steganographic data, this optimization may have undesirable side effects. Disabling alpha optimizations also reduces the time it takes to optimize an image, at the cost of a maybe increased file size.

Example:

skip_alpha_optimizations = true

downsize_if_single_color

Type: Boolean

Default value: true

If true, single-color textures that are estimated to be safe to resize will be downsized to the minimum resolution that maintains the maximum mipmap level. This usually provides significant space savings without side effects for this kind of textures, but in some cases, such as when using some modifications, custom shaders, animated textures, or custom fonts, issues may occur.

Example:

downsize_if_single_color = false

Shader files

You can customize how PackSquash optimizes the .vsh, .fsh, and .glsl files of a pack with the following key and value pairs.

shader_source_transformation_strategy

Type: String

Default value: minify

Defines how the GLSL source code of shaders will be transformed to a more optimized but semantically equivalent representation.

Please note that PackSquash may not be able to transform some shaders due to technical limitations. When this happens, the optimization strategy text for affected shaders will highlight that situation, and PackSquash will act as if the keep_as_is strategy was selected. Some of these limitations might be removed in the future, rendering PackSquash capable of transforming more shaders according to the selected strategy.

The available source transformation strategies are:

  • minify: minifies the shader source code (i.e., removes unnecessary whitespace, line breaks, comments and preprocessor directives) to save space and improve parsing performance.
  • prettify: prettifies the shader (i.e., formats its source in an indented, human-readable form), while expanding and removing preprocessor directives and comments.
  • keep_as_is: adds the source code as-is to the generated ZIP file, without removing comments or expanding preprocessor directives.

Example:

shader_source_transformation_strategy = 'keep_as_is'

is_top_level_shader

Type: Boolean

Default value: true for every vertex and fragment shader, false for include shaders

If true, PackSquash will consider this shader to be a top-level one (i.e., parsed by Minecraft as a translation unit and never included in other shaders). When false, this shader will not be considered top-level.

The value of this option is only honored for vertex and fragment shaders. By definition, include shaders never are top-level, so they can't be marked as top-level via this option.

In the vast majority of scenarios, vertex and fragment shaders are not meant to be included in other shaders (i.e., they are top-level). However, Minecraft technically allows such inclusion to happen, and it is exceedingly difficult for PackSquash to determine whether a vertex or fragment shader is being included by other shader. PackSquash needs to know whether a shader is top-level to decide whether it is appropriate to expand and remove preprocessor directives: if it is not top-level but PackSquash thinks it is, removing preprocessor directives may change the preprocessor behavior in the top-level shader, yielding potentially different GLSL source code.

It is strongly recommended to only explicitly set this option to false for the exceedingly rare cases where the default behavior generates semantically altered GLSL code, as doing so will make it harder for PackSquash to optimize the affected shaders. Otherwise, omitting it is the most appropriate course of action.

Example:

is_top_level_shader = false

Legacy language files

You can customize how PackSquash optimizes the .lang files used in older resource packs with the following key and value pairs. Please note that these files are only optimized on resource packs that target Minecraft 1.12.2 or older versions unless you set automatic_asset_types_mask_detection to false.

minify_legacy_language

Type: Boolean

Default value: true

If true, the legacy language file will be minified: empty lines and comments will be removed. This saves space and improves parsing performance. If false, the file will still be validated for errors but left as-is. Line endings are normalized to Unix style (using a single LF character) no matter what.

Example:

minify_legacy_language = false

strip_legacy_language_bom

Type: Boolean

Default value: true

If true, the BOM in the first line of the file will be stripped. This usually saves space and avoids user confusion, as the BOM is normally introduced inadvertently, and Minecraft interprets the BOM as a part of the line. Therefore, the BOM may undesirably become part of the key of the first language string, causing it not to work or prevent a comment from being parsed as such.

However, if a pack relies on the BOM being there because it refers to the first language string with a BOM, this behavior might have undesirable consequences. In such cases, set this option to false to leave the BOM alone.

Example:

strip_legacy_language_bom = false

Command function files

You can customize how PackSquash optimizes the .mcfunction files used in data packs with the following key and value pairs.

minify_command_function

Type: Boolean

Default value: true

If true, the command function file will be minified: empty lines and comments will be removed. This saves space and improves parsing performance. If false, the file will still be validated for errors but left as-is. Line endings are normalized to Unix style (using a single LF character) no matter what.

Example:

minify_command_function = false

Properties files

You can customize how PackSquash optimizes the .properties files of a pack with the following key and value pairs. Please note that these files only are processed if allow_mods includes OptiFine.

These options are only supported if PackSquash was compiled with support for the OptiFine mod, which always is the case if you use a PackSquash build downloaded from this repository.

minify_properties

Type: Boolean

Default value: true

When true, the properties will be minified, which removes comments and unnecessary whitespace to improve space savings. If you change this option to false, the properties will not be changed at all, but they will still be validated by PackSquash.

Example:

minify_properties = false

Custom files

Any unknown pack file can be marked as a custom file with the following key and value pairs, making it possible to customize how PackSquash deals with files that would otherwise be inevitably skipped. Please be mindful that this feature does not substitute proper support for files that are read by the game: if you are using it to work around such a missing feature, please let us know by opening an issue or getting in touch over Discord. Custom file options are ignored for files that belong to any known type.

force_include

Type: Boolean

Default value: false

If true, the custom file will be copied to the generated ZIP file as-is, without any specific optimizations. A false value explicitly asks for the default behavior of skipping the file.

Example:

force_include = true

Examples

You can run the examples proposed in this section by copying their contents to a text file, saving it wherever you like, and then launching PackSquash with the path to your options file as the first parameter. To do so, you can use a command prompt or terminal.

On Windows, you can open a command prompt by following these instructions, and then type a command like this (please remember to replace the example paths with the appropriate ones):

"C:\path\to\your\packsquash\executable\packsquash.exe" "C:\path\to\your\settings\file.toml"

Alternatively, if you don't like to type commands in the Windows command prompt, you can create a shortcut that does this for work for you or drag-and-drop the file to the executable. Keep in mind that doing so might complicate troubleshooting, as the PackSquash window will be immediately closed if something goes wrong, and you won't be able to see the error messages that PackSquash has shown.

Of course, you are free to modify these examples to suit your needs better or even create your options files from scratch.

Basic options file

This is a minimal valid options file. It only specifies the pack directory and leaves the rest of the options set to their defaults. The generated ZIP file will be saved at pack.zip in the current directory. We suggest starting with a minimal options file and adding options to it as needed to keep the file smaller, more readable, and easier to upgrade to future PackSquash versions.

pack_directory = 'C:\path\to\pack'

Basic options file but tuned for extreme compression

By default, PackSquash is designed to create quite small ZIP files using a reasonable amount of computing power. However, it is possible to squeeze out even more savings by changing some settings to be on the extreme side:

pack_directory = 'C:\path\to\pack'

recompress_compressed_files = true
zip_compression_iterations = 30
zip_spec_conformance_level = 'balanced'
skip_pack_icon = true

['**/*?.png']
image_data_compression_iterations = 15

Basic options file with extraction protection

This example is like Basic options file, but it enables PackSquash to do more aggressive ZIP file optimizations, including extraction protection, described in the zip_spec_conformance_level option documentation. However, it might be a bad idea to do these optimizations blindly: they make the ZIP file more cumbersome to work with, the extraction protection is not unbreakable, and they change how PackSquash reuses previously generated ZIP files. Check out the mentioned option documentation for more information.

pack_directory = 'C:\path\to\pack'
zip_spec_conformance_level = 'disregard'

Complex options file

This example options file changes every option that PackSquash offers, just for the sake of doing so. You will probably not need to do this in practice, and some values may be outright inappropriate for you, but this is useful to see how everything is grouped together.

Careless copying and pasting of this example is a bad idea and makes troubleshooting harder than you may realize. Please only click on this text to view it if you have a good reason to do so
# Lines that start with # are comments, and PackSquash ignores them.
# You can also start a comment in the middle of a line with #, that
# spans until the end of the line

# Global options
pack_directory = 'C:\path\to\pack'
output_file_path = 'C:\path\to\result\pack\zip\file\my_pack.zip'
recompress_compressed_files = true
zip_compression_iterations = 5
automatic_minecraft_quirks_detection = true
# The value of this option is ignored due to automatic quirk detection
# being enabled, but this usually does not matter
work_around_minecraft_quirks = ['grayscale_images_gamma_miscorrection', 'restrictive_banner_layer_texture_format_check', 'bad_entity_eye_layer_texture_transparency_blending', 'java8_zip_parsing', 'ogg_obfuscation_incompatibility']
automatic_asset_types_mask_detection = true
allow_mods = ['OptiFine', 'Minecraft Transit Railway 3']
skip_pack_icon = true
validate_pack_metadata_file = true
ignore_system_and_hidden_files = false
zip_spec_conformance_level = 'high'
# These two are actually ignored due to the ZIP spec conformance level
size_increasing_zip_obfuscation = true
percentage_of_zip_structures_tuned_for_obfuscation_discretion = 100
never_store_squash_times = true
# System dependent values. PackSquash automatically uses appropriate
# defaults for your system, so usually you should not need to set
# these
threads = 4
spooling_buffers_size = 128 # MiB

# Per-file options below

# A special silence file that for some reason must be kept exactly as-is
# (usually not the case)
['assets/craftmine/sounds/special_silence.ogg']
empty_audio_optimization = false

# Audio several hours long that would take a lot of time to transcode,
# optimize and validate
['assets/craftmine/sounds/forest_soundscape.ogg']
transcode_ogg = false
two_pass_vorbis_optimization_and_validation = false

# Other Ogg files do not get transcoded
['**/*?.ogg']
transcode_ogg = false

# Lossless music files get pitch shifted, compressed with good quality,
# and obfuscated if allowed by the target Minecraft version
['**/*?.{flac,wav}']
ogg_obfuscation = true
channels = 2
sampling_frequency = 44100
target_pitch = 1.5
bitrate_control_mode = 'VBR'
target_bitrate_control_metric = 128

# JSON files with comments get prettified and nothing is removed from them
['**/*?.jsonc']
minify_json = false
delete_bloat_keys = false

# Do not allow comments in any JSON file.
# Comments may be an useful JSON extension for documentation purposes, so
# please avoid blindly copying and pasting this unless you really want to
# limit their usage to .jsonc, .jemc, .jpmc, .mcmetac and .bbmodelc files!
['**/*?.{json,jem,jpm,mcmeta,bbmodel}']
always_allow_json_comments = false

# Quantize big natural-looking image, doing the highest quality dither
['assets/craftmine/textures/landscape.png']
color_quantization_target = 'eight_bit_depth'
color_quantization_dithering_level = 1

# Compress other textures losslessly no matter what. Keep them small,
# but don't downsize them
['**/*?.png']
image_data_compression_iterations = 15
color_quantization_target = 'none'
maximum_width_and_height = 2048
skip_alpha_optimizations = true
downsize_if_single_color = false

# Don't minify shaders
['**/*?.{fsh,vsh,glsl}']
shader_source_transformation_strategy = 'keep_as_is'
# It usually is a bad idea to explicitly configure this option. Read
# its documentation for more details
#is_top_level_shader = false

# Don't touch Minecraft 1.12.2 or older language files
['**/*?.lang']
minify_legacy_language = false
strip_legacy_language_bom = false

# Don't minify properties files
['**/*?.properties']
minify_properties = false

# Don't minify an example command function.
# Note that command functions are only accepted in data packs, and
# data packs do not contain other file types shown throughout this
# example file!
['data/craftmine/functions/main.mcfunction']
minify_command_function = false

# Include copyright and authorship information files in any directory.
# More information:
# https://www.gnu.org/prep/maintain/html_node/License-Notices.html
# https://www.gnu.org/prep/maintain/html_node/Recording-Contributors.html
['**/{COPYING,AUTHORS}']
force_include = true
Clone this wiki locally