Pixel Dream StudiosWiki

Bandits

Bandit profiles for hostile mercenaries, and where bandits spawn.

Custom bandit profiles

A bandit profile is a preset stamped onto a hostile mercenary (bandit) at spawn time, customizing its class, titles, gear, scale, and so on. Profiles let you build varied bandit encounters - a giant brute leading a raid, a fire-mage miniboss in a tower, a hooded archer ambush - and everything data driven.

Bandit profiles are applied to hostile mercenaries only (HostileRandomHumanEntity), the bandit / evil-mercenary variant. Regular contracted mercenaries are unaffected. Each field of a profile is optional: anything you leave out falls back to the random-roll behavior an unprofiled bandit would have, so a profile only constrains what it explicitly sets.

File location

data/magic_realms/mercenaries/bandit_profiles/<id>.json

The file's path is the profile's stable identifier (e.g. data/magic_realms/mercenaries/bandit_profiles/giant_warrior.json becomes magic_realms:giant_warrior).

Schema

FieldTypeDefaultNotes
weightint1Weighted-random selection weight, used when calling pickRandomFiltered.
entity_class"mage" / "warrior" / "rogue"randomPins the class. Without this, the class is rolled normally.
gender"male" / "female"randomPins the gender.
has_shieldboolrandomIf you pined warrior, this sets if it should have shield.
is_archerboolrandomIf you pined rogue, this sets if it should be an archer or an assassin.
star_levelint 1–3randomStat tier, affects the starting attributes.
titleslist of resource locations[]Titles granted outright at spawn, bypassing their normal requirements. All of their rewards apply exactly as if earned. Unknown ids are skipped with a warning.
displayed_titleresource location-Which of the granted titles shows above the bandit's name. Must be one of them. If omitted, the highest-priority non-hidden granted title is used.
entity_scalefloat1.0Resizes the bandit, useful for tiny or giant bandits. 1.5 = 50% bigger.
override_namestring-Replaces the rolled name (e.g. "Hulking Brute").
skin_presetresource location-Id of an entry in your skin_presets/ catalog (the resource location of its JSON file, e.g. "magic_realms:vex" for data/magic_realms/mercenaries/skin_presets/vex.json). The full preset is applied - texture, optional display name, and optional fixed_personality_id binding all carry over. Unknown ids log a warning and fall back to layered random skin.
magic_schoolslist of resource locations[]Mage-only. Explicit list of schools.
magic_schools_tagresource location-Mage-only. Pulls schools from a tag (used if magic_schools is empty).
explicit_spellslist of resource locations[]Exact spells the bandit casts. Highest priority.
spells_tagresource location-Pull spells from a tag (used if explicit_spells is empty).
spells_tag_pick_countintfull tag sizeWhen spells_tag is set, randomly pick this many spells from the tag instead of taking all.
equipmentobject: slot→item id{}Slot keys: "mainhand", "offhand", "head", "chest", "legs", "feet".
attribute_boostslist[]Flat attribute modifiers applied at the end of init, on top of class and level scaling. See below.
loot_tableresource location-Overrides the bandit's loot table on death (e.g. "magic_realms:entities/chuchu").
is_mini_bossboolfalseMarker flag readable as profile.isMiniBoss() for possible features (boss bar, drops, etc.).
immortalboolfalseSets the immortal flag - bandit will be stunned instead of dying.
fixed_personality_idstring-References an entry from your fixed_personalities catalog. Replaces the random archetype roll.
in_random_poolbooltrueIf false, the profile can only be invoked by id (commands, structures, code) and never selected by random pickers.

Difficulty is expressed through star_level, attribute_boosts, equipment and titles rather than a level range. Granting titles is usually the better lever of the two: the buff shows up on the bandit's nameplate, so a player who sees Unbroken floating over a raid leader understands why it isn't dying, instead of running into an invisible stat multiplier.

The spell rules in priority order: explicit_spells first, then spells_tag (with optional spells_tag_pick_count), then fall through to the regular class-driven generator.

Attribute boost format

Each boost uses Mojang's standard AttributeModifier codec. The id must be unique per boost - convention is to namespace it under your pack and the profile id:

{
  "attribute": "minecraft:generic.max_health",
  "id": "magic_realms:bandit/giant_warrior/health",
  "amount": 0.5,
  "operation": "add_multiplied_base"
}

Operations: add_value (flat), add_multiplied_base (% of base), add_multiplied_total (% of post-modifier total). Boosts apply after class/level attribute scaling, so add_multiplied_base of 0.5 on generic.max_health cleanly adds 50% on top of whatever the entity would normally have at its level.

Example: a giant warrior raid leader

A warrior bandit scaled up 1.5×, with full iron armor, 50% more HP, 50% knockback resistance, +3 attack damage, and two granted titles doing further work:

{
  "weight": 5,
  "entity_class": "warrior",
  "has_shield": false,
  "titles": [
    "magic_realms:veteran",
    "magic_realms:unbroken"
  ],
  "displayed_title": "magic_realms:unbroken",
  "entity_scale": 1.5,
  "override_name": "Hulking Brute",
  "equipment": {
    "mainhand": "minecraft:netherite_axe",
    "head":     "minecraft:iron_helmet",
    "chest":    "minecraft:iron_chestplate",
    "legs":     "minecraft:iron_leggings",
    "feet":     "minecraft:iron_boots"
  },
  "attribute_boosts": [
    {
      "attribute": "minecraft:generic.max_health",
      "id": "magic_realms:bandit/giant_warrior/health",
      "amount": 0.5,
      "operation": "add_multiplied_base"
    },
    {
      "attribute": "minecraft:generic.knockback_resistance",
      "id": "magic_realms:bandit/giant_warrior/kb_resist",
      "amount": 0.5,
      "operation": "add_value"
    },
    {
      "attribute": "minecraft:generic.attack_damage",
      "id": "magic_realms:bandit/giant_warrior/damage",
      "amount": 3.0,
      "operation": "add_value"
    }
  ],
  "loot_table": "magic_realms:entities/giant_warrior",
  "is_mini_boss": true
}

Example: a fire-mage miniboss

A three-star mage bandit casting a hand-picked fire and lightning kit, in netherite mage armor with a blaze manual spellbook in the offhand, plus double base health:

{
  "weight": 2,
  "entity_class": "mage",
  "star_level": 3,
  "titles": [
    "magic_realms:archmage"
  ],
  "override_name": "Pyromancer Initiate",
  "magic_schools": [
    "irons_spellbooks:fire",
    "irons_spellbooks:lightning"
  ],
  "explicit_spells": [
    "irons_spellbooks:fireball",
    "irons_spellbooks:firebolt",
    "irons_spellbooks:lightning_bolt",
    "irons_spellbooks:teleport",
    "irons_spellbooks:ball_lightning"
  ],
  "equipment": {
    "head": "irons_spellbooks:netherite_mage_helmet",
    "chest": "irons_spellbooks:netherite_mage_chestplate",
    "legs": "irons_spellbooks:netherite_mage_leggings",
    "feet": "irons_spellbooks:netherite_mage_boots",
    "offhand": "irons_spellbooks:blaze_spell_book"
  },
  "attribute_boosts": [
    {
      "attribute": "minecraft:generic.max_health",
      "id": "magic_realms:bandit/mage_miniboss/health",
      "amount": 1.0,
      "operation": "add_multiplied_base"
    }
  ],
  "is_mini_boss": true
}

Spawning bandits with a profile

Command - right now it's only available via commands for testing around:

/bandit summon "magic_realms:giant_warrior"
/bandit summon "magic_realms:mage_miniboss" 100 64 -200
/bandit list

Custom bandit spawns

Bandit profiles describe what a bandit is. This describes where they come from: magic_realms:add_bandit_spawns is a custom NeoForge biome modifier that adds natural bandit spawns to a set of biomes, and optionally pins those spawns to a weighted pool of profiles.

The entity type is implicit - this modifier only ever spawns bandits, so there's no entity field to get wrong.

File location

Biome modifiers are a NeoForge datapack registry, so they don't live under mercenaries/ with the rest:

data/<your_namespace>/neoforge/biome_modifier/<id>.json

Schema

FieldTypeDefaultNotes
typestringrequiredAlways "magic_realms:add_bandit_spawns".
biomesbiome id, list, or tagrequiredWhich biomes gain the spawn entry. A tag reference needs the leading #.
weightint ≥ 0requiredSpawn weight, relative to every other entry in the monster category for that biome. Vanilla overworld zombies sit around 95, skeletons 100, so a value in the tens makes bandits uncommon but not rare. 0 disables the entry.
minCountint ≥ 11Minimum group size per spawn attempt.
maxCountint ≥ 11Maximum group size. Must be ≥ minCount - the codec rejects the file otherwise, with an error naming both values.
profileslist[]Weighted pool of bandit profiles to pin spawns to. Omit it and bandits spawned here roll from the normal random pool instead.

Each entry in profiles is:

FieldTypeDefaultNotes
idresource locationrequiredA profile id from your bandit_profiles/ catalog. Unknown ids log a warning and the bandit falls back to a random roll.
weightint ≥ 11Relative weight within this modifier's pool only.

How a profile gets chosen

Worth understanding, because it explains why weight does double duty.

Vanilla's spawner doesn't record which biome modifier produced a given spawn - it merges every entry into one weighted list and rolls once. So when a bandit spawns, Magic Realms reconstructs the choice in two steps:

  1. Which modifier? Every add_bandit_spawns modifier that has a non-empty profile pool and covers the bandit's biome becomes a candidate, weighted by its own weight. This means two modifiers overlapping the same biome divide spawns in proportion to their spawn weights, which is what you'd intuitively expect.
  2. Which profile? A second weighted roll inside that modifier's profiles list.

Example: plain spawns, no profiles

Bandits appear in the biomes in your tag, in groups of one to three, using the normal random profile pool.

{
  "type": "magic_realms:add_bandit_spawns",
  "biomes": "#magic_realms:bandit_spawns_in",
  "weight": 15,
  "minCount": 1,
  "maxCount": 3
}

Example: a weighted profile pool

Highwaymen are common, the captain is a rare escort. With these weights the captain is one spawn in six.

{
  "type": "magic_realms:add_bandit_spawns",
  "biomes": "#magic_realms:bandit_spawns_in",
  "weight": 20,
  "minCount": 2,
  "maxCount": 4,
  "profiles": [
    { "id": "magic_realms:highwayman", "weight": 5 },
    { "id": "magic_realms:bandit_captain", "weight": 1 }
  ]
}

Example: biome-specific flavour

Targeting a small set of biomes directly rather than through a tag, to give the desert its own bandit type:

{
  "type": "magic_realms:add_bandit_spawns",
  "biomes": [
    "minecraft:desert",
    "minecraft:badlands"
  ],
  "weight": 10,
  "minCount": 1,
  "maxCount": 2,
  "profiles": [
    { "id": "magic_realms:sand_raider", "weight": 1 }
  ]
}

Targeting biomes that might not exist

Referencing an unregistered biome id directly crashes on world load. If you want to target a biome from a mod that may not be installed, put it in a biome tag as an optional entry and point biomes at the tag:

{
  "replace": false,
  "values": [
    "minecraft:plains",
    { "id": "biomesoplenty:lavender_field", "required": false }
  ]
}

Turning spawns off

Because biome modifiers are a datapack registry, a pack can override any of Magic Realms' spawn modifiers by placing a file at the same path and name with NeoForge's no-op type:

{
  "type": "neoforge:none"
}

Setting "weight": 0 on your own modifier achieves the same thing for files you control.

On this page