Category System - AntonIT99/Flans-Mod-Ultimate-2.0 GitHub Wiki
Category System
The category system lets you apply content-pack settings to groups of items without
editing every item .txt file. It is useful for server balancing, modpacks, and
large content packs where many guns, bullets, grenades, or other items should share
the same values.
For the full list of content-pack parameters that can be used in category properties, see Config Reference.
What Categories Do
A category is a named group with:
items: the short names of the items affected by the category.properties: content-pack parameters to apply to all of those items.inherits(optional): a same-type parent category to reuse. See Inheritance and Default Overrides.exceptions(optional): properties that specific items of the category must not receive. See Exceptions.
When the mod loads an item, it reads the item's normal content-pack .txt file and
then applies matching category properties. For simple one-value settings, category
properties usually override the value from the content-pack file. For repeatable
settings, category properties add extra lines.
This means categories are a good way to:
- rebalance many weapons at once;
- create shared behavior for ammunition groups;
- override built-in default tuning without editing content packs;
- keep local/server balance changes separate from downloaded content packs.
Where Category Files Are
User-editable category files are in:
config/flansmodultimate/
Built-in default examples are copied to:
config/flansmodultimate/default/
Do not put your custom edits in the default folder. Those files are owned by the
mod and may be refreshed when the built-in defaults change. Put your edits in the
matching file directly inside config/flansmodultimate/.
Category Files by Type
Each item type has its own category file.
| Item type | Category file | Content-pack folder |
|---|---|---|
| AA guns | aagun_categories.json |
aaguns |
| Armor | armor_categories.json |
armorFiles |
| Armor boxes | armor_box_categories.json |
armorBoxes |
| Attachments | attachment_categories.json |
attachments |
| Bullets and ammunition | bullet_categories.json |
bullets |
| Gloves | glove_categories.json |
gloves |
| Grenades and thrown shootables | grenade_categories.json |
grenades |
| Guns | gun_categories.json |
guns |
| Gun boxes | gun_box_categories.json |
boxes |
| Item holders | item_holder_categories.json |
itemHolders |
| Parts | part_categories.json |
parts |
| Tools | tool_categories.json |
tools |
If you want to edit guns, use gun_categories.json. If you want to edit bullets or
ammo, use bullet_categories.json. A gun category cannot affect a bullet, and a
bullet category cannot affect a gun.
Basic JSON Format
An empty category file should contain:
{}
A category file with one category looks like this:
{
"Category Name": {
"properties": {
"ConfigKey": "value",
"AnotherConfigKey": 123
},
"items": [
"item_short_name_1",
"item_short_name_2"
]
}
}
The category name identifies it for inheritance and default overrides. Names are
case-sensitive. Use clear names such as
"Assault Rifle Tuning" or "Heavy Explosive Ammo".
Item Names
Items are matched by their content-pack ShortName, not by display name, file name,
or Minecraft registry ID.
Example content-pack line:
ShortName AK47
Use this in a category:
"items": [
"ak47"
]
Short names are sanitized by the mod, so it is best to write them in lowercase and replace spaces with underscores.
When a content-pack item is renamed, shipped/default categories should add the new
sanitized short name without deleting the former one. Keeping both names preserves
compatibility with older content-pack releases and external packs that still use the
legacy ShortName. Remove a legacy category entry only as an explicit retirement,
not as an automatic part of a rename or coverage cleanup.
Property Names
Property names are the same settings used in content-pack .txt files. For example:
- gun properties such as
RoundsPerMin,MuzzleVelocity,Dispersion,Recoil; - AA-gun properties such as firing-event
RoundsPerMin,Dispersion,RealMassKg, andUseRealisticVehicleHealth; - bullet properties such as
Mass,FallSpeed,ExplosiveMassTNTg,PenetrationAt100m; - grenade properties such as
Fuse,ExplosiveMassTNTg,FragType; - armor properties such as
Defence,DamageReduction,Durability. - mecha properties such as
RealMassKg,RealMaxSpeedKmh,RotateSpeed,StepHeight,JumpHeight,Reach, andUseRealisticVehicleHealth.
Use Config Reference to find the exact property name, expected format, default value, and which type supports it.
Historical gun and AA-gun categories must define RoundsPerMin and Dispersion.
Research the exact configuration first and use a compatible specialist or game
source as a fallback. If neither establishes a value, use a gameplay-coherent value
based on comparable weapons and disclose that it is invented in the category batch
report.
MuzzleVelocity is resolved from ammunition when ammunition MuzzleVelocity or
BulletSpeed is present; that value takes precedence over the gun's. Ordinary small
arms normally define gun-category velocity as the barrel-specific source and
fallback. Autocannon belts, shells, and missiles define ammunition velocity for the
exact projectile/load; a matching gun or AA gun may retain a compatible fallback.
Do not put different configurations on the two sides.
Property Values
Category property values may be:
- a JSON string;
- a JSON number;
- an array of strings or numbers.
Examples:
"RoundsPerMin": 750
"ExplosiveMassTNTg": "85"
"AddRound": [
"AP 1 162 0 800 45",
"HE 2 135 16 835 0"
]
Do not use raw JSON booleans inside properties. Use strings instead:
"TranslucentRendering": "true"
or use 1 / 0 where the content-pack parameter accepts boolean-style values.
For properties that normally have several values on one line, put the whole value part in one string. Do not repeat the property name inside the value.
Content-pack line:
AddRound AP 1 162 0 800 45
Category value:
"AddRound": "AP 1 162 0 800 45"
If you need several AddRound lines, use an array.
Override and Add Behavior
The category system adds property lines after the item's normal content-pack lines. Most single-value parameters use the last value, so category values override the content-pack value.
Example:
Content-pack gun file: RoundsPerMin 600
Category property: "RoundsPerMin": 750
Final value: 750
Repeatable parameters keep multiple lines. Category values are added to the existing lines.
Example:
Content-pack bullet file: AddRound Ball 1 147 0 850 30
Category property: "AddRound": "Tracer 1 145 0 850 25"
Final result: both rounds are available
Categories can select a different merge strategy for individual properties with
propertyModes:
"properties": {
"AddRound": [
"AP 1 162 0 800 45",
"HE 2 135 16 835 0"
]
},
"propertyModes": {
"AddRound": "replace"
}
The supported modes are:
append: add the category values after existing values. This is the default and preserves the behavior of category files that do not declare a mode.replace: discard values supplied by the content definition or earlier categories, then use the values from this category.ifAbsent: apply the category values only when neither the content definition nor an earlier category supplied that property.
Property names and mode values are case-insensitive. A complete category-authored
AddRound belt should normally use replace. It then remains usable as a fallback
in the content definition when categories are disabled without doubling the belt
when categories are enabled.
If an item belongs to several categories that set the same single-value property, the later applied category wins. Avoid putting the same item in several categories that edit the same value unless you are deliberately overriding something.
Exceptions
Sometimes almost every item in a category should share the same value, but a few
variants must keep their own. Instead of splitting the category, add an optional
exceptions block.
exceptions maps a property name to the list of items that must not receive
that property. Those items still receive every other property of the category.
{
"Panzerkampfwagen VI Ausf. H1 Tiger": {
"properties": {
"RealMassKg": 57250,
"RealEnginePowerPS": 650,
"RealMaxSpeedKmh": "45.4",
"DriveType": "TRACKED",
"RealMaxReverseSpeedKmh": "9.2"
},
"items": [
"44_tiger1h",
"tiger",
"tiger131",
"tigersnow"
],
"exceptions": {
"RealMaxSpeedKmh": ["tiger131", "tigersnow"]
}
}
}
In this example:
44_tiger1handtigerreceive all six properties;tiger131andtigersnowreceive everything exceptRealMaxSpeedKmh, so they keep the speed written in their own content-pack file (or one set by another category).
Rules:
exceptionsis optional. Category files without it keep working unchanged.- Keys are property names taken from
properties. A key that does not exist inpropertiessimply does nothing. - Values are item short names. A single item may be written without brackets:
"RealMaxSpeedKmh": "tiger131". - Property names and item names are matched case-insensitively.
- An excepted item stays a member of the category. Only the listed property is skipped for it.
- Exceptions are per category. They do not block a property applied by a different category, so if a default category also sets the same property, add the exception there or override the value in your user category.
Use exceptions for variants that differ in only one or two values, such as a snow skin with a different top speed, a captured vehicle with a different engine, or a single gun in a family with a different rate of fire.
Default Categories and User Categories
By default, the mod loads built-in categories from:
config/flansmodultimate/default/
Then it loads your user categories from:
config/flansmodultimate/
User categories apply after untouched default categories. Your user category can override default category values for the same items.
To disable all built-in default categories, edit:
config/flansmodultimate-content-loading.toml
Set:
useDefaultCategories=false
Leave this enabled if you want the mod's built-in balancing categories. Disable it if you want only your own categories applied. Explicit inheritance can still reuse built-in definitions.
Inheritance and Default Overrides
Use the optional inherits string to name one parent category from the same
InfoType subtype (the same category file). Category names are case-sensitive;
property names and item short names are case-insensitive.
{
"My Ammo Base": {
"properties": { "Mass": 12, "FallSpeed": 1 },
"items": []
},
"My Heavy Ammo": {
"inherits": "My Ammo Base",
"properties": { "Mass": 20 },
"items": ["my_heavy_ammo"]
}
}
The child receives Mass = 20 and FallSpeed = 1. Parents may appear later in the
file, and inheritance chains are supported. A parent with an empty items list is
a useful settings template. Inheritance also carries the parent's items: if the
parent lists items, the child applies to those items as well as its own.
Editing a Built-in Category
With useDefaultCategories=true, declaring the exact same category name in the
user file automatically merges it with the built-in category. No inherits is
needed. For example, if a built-in category named Example Ammo supplies Mass,
FallSpeed, and items old_ammo_a and old_ammo_b, this user declaration:
{
"Example Ammo": {
"properties": { "Mass": 20 },
"items": ["my_extra_ammo"]
}
}
keeps the built-in FallSpeed, changes Mass to 20, and applies the resulting
settings to all three items. Omitting items keeps all built-in members. The
merged category is applied once, so redeclaration does not duplicate repeatable
properties from the built-in declaration.
Explicitly Inheriting Built-in Settings
Use "inherits": "default:Example Ammo" to select the original built-in definition,
even if a user category has the same name. Replace Example Ammo with an actual
name from the corresponding default file. This works with
useDefaultCategories=false, including when the child has the same name as its
built-in parent. Only your child is activated; other default categories stay
disabled. The child still inherits the selected parent's item membership.
An unqualified name such as "inherits": "Example Ammo" selects the active
category, including user edits. When defaults are disabled, unqualified names can
only select user categories; same-name declarations do not automatically keep
built-in values or items. The default: prefix is reserved for built-in lookup.
Merge and Application Rules
- Precedence is the same-name built-in base (when enabled), then the explicitly inherited parent, then the child's own fields.
propertiesmerge by parameter name. An overridden parameter replaces its entire value list, including repeatable parameters such asAddRound. Omitted parameters retain inherited values.itemsare combined in order, removing case-insensitive duplicates. An empty list does not remove inherited members.propertyModesandexceptionsmerge by parameter name too. A child entry replaces that parameter's inherited mode or exception list. Use an empty exception list ("Mass": []) to clear an inherited exclusion for that property.propertyModescontrol application to content-pack lines and earlier categories; they do not change the inheritance merge rules.- Untouched built-in categories apply first, followed by user categories in user
JSON order. Parent lookup order does not change application order. If both a
parent and child contain an item, both categories apply; repeatable properties
can therefore be added twice unless an appropriate
replacemode is used. - Cross-type parents, missing parents, self-inheritance, and inheritance cycles
are invalid. Affected categories and their dependents are skipped with an error
in the log; unrelated valid categories still load. Use
default:Namewhen a same-name user category should inherit its built-in definition instead of itself.
Restart the game or server after editing category files.
Examples
Tune a Gun Group
File: config/flansmodultimate/gun_categories.json
{
"Assault Rifle Balance": {
"properties": {
"RoundsPerMin": 650,
"Dispersion": 0.28,
"Recoil": 1.1
},
"items": [
"ak47",
"m16a4",
"g36c"
]
}
}
This applies the same rate of fire, dispersion, and recoil to all listed guns.
Override One Default Weapon Value
File: config/flansmodultimate/gun_categories.json
{
"My AK Override": {
"properties": {
"Dispersion": 0.18
},
"items": [
"ak47"
]
}
}
If a built-in default category also changes ak47 dispersion, this user category
wins because user categories load after default categories.
Create Heavy Explosive Ammo
File: config/flansmodultimate/bullet_categories.json
{
"Heavy Explosive Ammo": {
"properties": {
"Mass": 42,
"ExplosiveMassTNTg": "1.3",
"PenetrationAt100m": 20
},
"items": [
"barrettexplosiveammo"
]
}
}
This changes the physical and explosive behavior of the listed bullet item.
Add Several Rounds to Ammo
File: config/flansmodultimate/bullet_categories.json
{
"Mixed 20mm Rounds": {
"properties": {
"AddRound": [
"AP 1 162 0 800 45",
"HE 2 135 16 835 0"
]
},
"items": [
"20mmammo"
]
}
}
Each array entry behaves like one extra AddRound line in the bullet config.
Tune Grenades
File: config/flansmodultimate/grenade_categories.json
{
"Frag Grenades": {
"properties": {
"ExplosiveMassTNTg": "85",
"FragType": "STD_FRAG",
"Fuse": 80
},
"items": [
"mk2frag",
"44_mk2frag"
]
}
}
Fuse is measured in ticks. Minecraft runs 20 ticks per second, so 80 ticks is
about 4 seconds.
FragType describes casing construction, while FragPattern describes the
directions fragments leave the burst. The engine derives useful reach from
effective fragment count, charge-to-metal ratio and distance; individual
FragRadius values are no longer used. See Fragmentation Damage
for the model and the S-Mine, Claymore and AHEAD examples.
Recommended Workflow
- Start the game or server once so the category files are generated.
- Open the matching file in
config/flansmodultimate/. - Find the item's
ShortNamein its content-pack.txtfile. - Find the property you want in Config Reference.
- Add or edit your category JSON.
- Restart the game or server.
- Test the affected items in-game.
For multiplayer, apply gameplay categories on the server and keep clients in sync with the same content/category setup when the changes affect item behavior, models, or generated assets.
Troubleshooting
| Problem | What to check |
|---|---|
| The game fails to start after editing a category file | Validate the JSON. Check commas, quotes, brackets, and that the file is not empty. Use {} for an empty file. |
| A category does not affect an item | Check that the item is in the correct type file and that items uses the item's ShortName. |
| A property is ignored | Make sure the property is valid for that item type. Use Config Reference. |
| A boolean property causes problems | Use "true" or "false" as a string, not raw JSON true or false. |
| A multi-value property only partially works | Put the whole right-hand side in one string, such as "AP 1 162 0 800 45". |
| Default category behavior still applies | Override the same property in your user category, or set useDefaultCategories=false. |
| A property still applies to an excepted item | Check that the exceptions key matches a key in properties and that the item short name is spelled the same as in items. Another category may also set that property. |
| Your custom edits disappeared | Make sure you edited config/flansmodultimate/*.json, not config/flansmodultimate/default/*.json. |
Mecha category maintenance
Mecha chassis use mecha_categories.json and the mechas definition folder.
Tools and upgrades are separate mecha_item definitions. The repository coverage
scanner now includes chassis from source packs and ZIP packs; a missing shipped
mecha category file leaves all chassis in the research queue.
The maintainer skill's references/mechas.md defines Utility, Recon, Assault and
Heavy profiles with fixed movement and part-health targets. These are initial
balance assignments, not physical specifications or playtested guarantees.
Health categories preserve each model's collision geometry and disable realistic
mass-based health scaling. Engine and addon modifiers still affect performance;
mounted weapons keep their own categories. Chassis rules do not require tank or
aircraft propulsion parameters. Adding these maintenance rules does not itself
assign existing mechas to categories.