Mod

Mebahel's RPG - Villager Quests and Companions

Quick rating

Mebahel's RPG - Villager Quests and Companions

No reviews yet

Mebahel's RPG: Villager Quests & Companions adds story-driven villager quests, branching choices, named enemies, rumors, quest tracking, companion recruitment, and RPG-style notifications to your world.

Adventure/Exploration
Mod Loaders
Forge
NeoForge
Fabric
Quilt
Minecraft

Community voices

Reviews

Versions
Loading versions…
Match includes

Click once to include, again to exclude, again to clear

Rating Any
Any 0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0
Min
Max
Play Status
Reviews
Time Played
hrs+
Verified developers only
Has developer response
List view
Grid view
Compact view
Sort by
Date
Rating
Helpful
Unhelpful
Edited
Sort ascending
Delete this review?

This removes your review from the project. You can write a new review after.

Review submitted for moderation

Your review has been sent to moderators, who will check that it meets our guidelines before it appears publicly.

No reviews yet. Be the first to review this project!

Get it on

Available Platforms

Compatibility

Supported Environments

Dev Environment
Client Required
Server Required

About

Project Details

Type
Mod
License
All Rights Reserved
Latest Version
mebahelrpgrquest-1.1.1-fabric-1.21.1
Authors
CurseForge
Modrinth

For authors

Embed Badge

If you're the author of this project, you can embed a live badge anywhere that supports HTML or Markdown. It updates automatically whenever ratings change.

Custom banner text
ModDex rating badge preview

Use HTML for any page that supports it, or Markdown for README files and Markdown-based descriptions.

Identifiers

Platform IDs

CurseForge ID
Modrinth ID

Resources

External Links

Source Issues Wiki Discord

About

Description

Mebahel's RPG: Villager Quests & Companions

Turn Minecraft villages into living RPG hubs.

Mebahel's RPG: Villager Quests & Companions adds story-driven villager quests, rumors, named enemies, branching choices, quest tracking, RPG-style notifications, and recruitable companions. Villagers are no longer just traders standing near a bell. They can ask for help, warn you about nearby threats, send you toward strange structures, reveal hidden stories through rumors, or pull you into choices that change what happens next.

Some quests are simple village jobs. Others become full story arcs with investigations, moral decisions, ambushes, raids, hidden follow-ups, named targets, and enemies who might not deserve the axe you were sent to bring.

If you like vanilla Minecraft but want villages to give you more reasons to explore, protect, question, and return, this mod is built for that.


Dependencies

Forge / NeoForge

Fabric


Compatible Mods

The following compatibility has been confirmed by the mod author or tested by players:

  • Guard Villagers — supported through a dedicated configuration file that lets guards offer selected quests when the mod is installed.
  • Villagers Reborn — confirmed compatible. Its villager model and interaction changes can be used alongside this mod's quests.
  • Epic Villages — tested by players and confirmed working with the quest system.
  • Luki's Grand Capitals — tested by players and confirmed working with the quest system.
  • Villager Retaliation — both mods can be used together. Their quest systems remain separate, but the core features can coexist.

Village overhaul mods are generally compatible because quests can be assigned to villagers inside both vanilla and modded villages or structures.


What This Mod Adds

  • Over 50 included quests built around villages, roads, mines, raids, ruined portals, witches, raiders, skeletons, undead soldiers, false heroes, strange survivors, and hidden contracts.
  • Branching storylines where killing, sparing, exposing, defending, escorting, delivering, or investigating can lead to different follow-up quests.
  • Named quest targets with custom dialogue, equipment, locations, health, mounts, drops, ambushes, and spare/attack choices.
  • Recruitable companions from selected mercy paths, including restored enemies who can later fight beside you.
  • Villager rumors that unlock hidden quests gradually instead of dumping every story on day one.
  • Quest journal and HUD tracking for active objectives, coordinates, structures, destinations, and threat targets.
  • RPG-style quest notifications with custom sounds when quests start, update, or complete.
  • Many objective types: kill, collect, deliver, read, escort, bring back, reach a structure, break blocks, place blocks, detonate TNT, enter or leave the Nether, defend raids, wait for time to pass, talk to entities, and return to the quest giver.
  • Datapack and mod support so creators can add quests and rumors with JSON files.

How It Feels In Game

You arrive at a village. A farmer heard something moving near an old portal. A smith remembers smoke below a mine. Someone claims a celebrated hero may be wearing stolen glory. A witch outside the village might be a threat, or she might be the only person telling the truth.

You talk, choose responses, accept the quest, track it in your journal, follow coordinates or structure clues, and return for rewards. Some targets fight immediately. Some talk first. Some can be spared. Sometimes mercy opens a longer path. Sometimes it brings danger back to the village.

The goal is to make villages feel like places with memory, consequences, and unfinished business.


Rumors and Discovery

Not every quest appears the same way.

Some villagers can offer jobs directly. Others may only give you a rumor. Hearing the right rumor can unlock hidden content, such as smoke below an old mine, a stranger among the dead, or trouble that appears only after a village has already survived a raid.

This lets the world reveal stories gradually as you play.


Companions

Certain spared characters can eventually become permanent companions.

Companions are designed to be useful without turning villages into chaos. They follow your lead, focus on hostile threats, and avoid randomly attacking peaceful villagers, iron golems, or passive animals.

Some companions also support equipment interaction through the companion inventory screen.


Quest Journal and HUD

Press J by default to open the quest journal.

The journal and tracker help you follow active objectives with contextual labels such as:

  • Threat location for named enemy targets.
  • Destination for escort quests.
  • Structure location for exploration objectives.
  • Target location when no more specific label applies.

Coordinates in the journal are clickable by default, and active objectives can be followed through the HUD tracker. Coordinate clicking can be disabled in the configuration.


Configuration

Server/world config file:

config/mebahelrpgrquest.json

Current configurable values:

{
  "villagerQuestChance": 0.20,
  "villagerRumorChance": 0.33,
  "disableQuestCoordinateClick": false,
  "shareQuestsBetweenPlayers": false,
  "inventoryJournalButtonPosition": "left",
  "hideInventoryJournalButton": false
}
  • villagerQuestChance is the quest assignment weight for a newly loaded villager.
  • villagerRumorChance is the rumor assignment weight for a newly loaded villager.
  • The two values compete in one roll. Any remaining weight up to 1.0 means no quest or rumor is assigned.
  • Values are clamped between 0.0 and 1.0. If their sum is above 1.0, quest and rumor are normalized against each other with no empty outcome.
  • disableQuestCoordinateClick controls coordinate interaction in the quest journal. Keep it set to false to let players click quest coordinates, or set it to true to disable coordinate clicking.
  • shareQuestsBetweenPlayers controls multiplayer quest sharing. Keep it set to false for separate quest progress per player, or set it to true to share quest progress, failures, completions, claimed rewards, and quest traits between all players on the server.
  • inventoryJournalButtonPosition controls where the inventory quest journal button appears. Use left for the default left side or right to move it to the right side. Invalid values fall back to left.
  • hideInventoryJournalButton hides the inventory quest journal button when set to true. It is false by default.

Additional Quest Configuration Files

  • Guard Villager quests: a dedicated configuration file lets you assign quests to guards from the Guard Villagers mod when it is installed.
  • Removed quests: a dedicated configuration file lets you list quest ids that should be removed from the available quest pool. Use it to disable included quests without editing the mod files.

Community

Join the Discord to follow development, report bugs, share quest ideas, or discuss custom quest lines:

https://discord.com/invite/y8uC2NepkB


Creating Custom Quests

Anyone can create new quests for the mod with JSON files in a datapack or addon. You can add dialogue, objectives, rumors, named enemies, rewards, choices, ambushes, raids, deliveries, escorts, and complete branching questlines.

File Locations

Place quest and rumor files in your own namespace:

data/<namespace>/quests/<quest_file>.json
data/<namespace>/rumors/<rumor_file>.json

For example:

data/my_quests/quests/old_well.json

This creates the quest id:

my_quests:old_well

Quest subfolders are allowed, but they do not become part of the quest id. Keep every quest filename unique inside your namespace.

Quick Start

  1. Choose the example below that is closest to the quest you want to make.
  2. Copy its JSON into a new file under data/<namespace>/quests/ or data/<namespace>/rumors/.
  3. Replace the example namespace with your own namespace.
  4. Change the dialogue, entities, structures, objectives, rewards, and linked quest ids.
  5. Reload the datapack and test the quest in a development or backup world.

JSON does not allow comments or trailing commas. Always use full identifiers such as minecraft:zombie, and use full quest ids such as my_quests:old_well when one file references another.

Player-facing text can use a translation object:

{
  "translate": "quest.my_quests.old_well.title",
  "fallback": "The Old Well"
}

The fallback value is displayed when no matching translation is available, so a separate language file is optional.


Quest Examples

Each example is kept in a separate expandable section. Copy the closest template and adapt only the parts your quest needs.

Named Threat with Attack or Spare Branches

Spawn a named enemy, let the player speak to it, then continue into a different quest depending on whether the target is attacked or spared.

Use this template for a quest that spawns a named threat, lets the player talk to it, then branches on attack or spare. #### First Quest
{
  "title": "QUEST TITLE",
  "summary": "Villager-facing summary shown before acceptance.",

  "flow": {
    "on_kill": "modid:kill_branch_2",
    "on_spare": "modid:spare_branch_2"
  },

  "goals": [
    {
      "id": "talk_to_threat",
      "talk": "minecraft:zombie",
      "amount": 1,
      "name": "NAMED THREAT"
    },
    {
      "id": "kill_threat",
      "kill": "minecraft:zombie",
      "amount": 1,
      "attack_only": true,
      "from_threats": true
    }
  ],

  "threat": {
    "entity": "minecraft:zombie",
    "name": "NAMED THREAT",
    "structure": "minecraft:ruined_portal",
    "search_radius": 4000,
    "spawn_on_accept": true,
    "spawn_min_radius": 3,
    "spawn_max_radius": 6,
    "spare": true,
    "glow": false,
    "max_health": 150,
    "equipment": {
      "mainhand": "minecraft:diamond_sword",
      "helmet": {
        "item": "minecraft:iron_helmet",
        "enchants": {
          "minecraft:unbreaking": 3
        }
      }
    },
    "line": "Quest giver line that describes the threat.",
    "target": "Initial line spoken by the threat.",
    "talk": [
      ["Player question one?", "Threat answer one."],
      ["Player question two?", "Threat answer two."]
    ]
  },

  "choice": {
    "attack": {
      "label": "Attack choice label.",
      "traits": ["trait_from_attack"],
      "return": "Quest giver line after the target is killed."
    },
    "spare": {
      "label": "Spare choice label.",
      "line": "Immediate line after sparing the target.",
      "post": "Follow-up line shown after the spare.",
      "villager": "Quest giver line after spare.",
      "traits": ["trait_from_spare"],
      "rewards_from_giver": true,
      "rewards": {
        "xp": 160,
        "items": {
          "minecraft:iron_ingot": 4
        }
      },
      "after": {
        "offer_chance": 70,
        "ambush_chance": 30,
        "nothing_chance": 0,
        "ambush": "minecraft:zombie",
        "ambush_name": "Fallback Ambush Name",
        "count": 5,
        "ambush_max_health": 50,
        "ambush_equipment": {
          "helmet": "minecraft:leather_helmet"
        },
        "line": "Line used when the spared target offers the next quest.",
        "ambush_line": "Line used if mercy triggers an ambush.",
        "nothing": "Line used if no follow-up happens."
      }
    }
  },

  "dialogue": {
    "return": "Quest giver line after kill.",
    "reward": "Quest giver reward line.",
    "done": "Quest giver already-completed line."
  },

  "rewards": {
    "xp": 260,
    "items": {
      "minecraft:emerald": 10
    }
  }
}
For spare-enabled threat confrontations, prefer the `talk` plus `attack_only` kill pattern shown above. The first interaction opens dialogue without completing the stage; the stage completes only after the player explicitly chooses attack or spare. #### Kill Branch
{
  "title": "KILL BRANCH TITLE",
  "summary": "Follow-up summary after the player chose attack.",

  "dialogue": {
    "intro": "Intro line.",
    "offer": [
      ["Player question?", "Quest giver answer."]
    ],
    "return": "Return line.",
    "reward": "Reward line.",
    "done": "Already completed line."
  },

  "goals": ["kill 3 minecraft:zombified_piglin"],

  "threats": [
    {
      "entity": "minecraft:zombified_piglin",
      "name": "Branch Threat",
      "structure": "minecraft:ruined_portal",
      "search_radius": 4000,
      "spawn_on_accept": true,
      "spare": false,
      "max_health": 70,
      "equipment": {
        "mainhand": "minecraft:golden_sword"
      }
    }
  ],

  "rewards": {
    "xp": 360,
    "items": {
      "minecraft:emerald": 14
    }
  }
}
#### Spare Branch
{
  "title": "SPARE BRANCH TITLE",
  "summary": "Follow-up summary after the player chose spare.",

  "flow": {
    "next": "modid:spare_branch_3"
  },

  "dialogue": {
    "intro": "Intro line from the spared target or quest giver.",
    "offer": [
      ["Player question?", "Answer."]
    ],
    "return": "Return line.",
    "reward": "Reward line.",
    "done": "Already completed line."
  },

  "goals": [
    {
      "collect": "minecraft:iron_ingot",
      "amount": 4
    }
  ],

  "rewards": {
    "xp": 240,
    "items": {
      "minecraft:emerald": 6
    }
  }
}

Staged Building and Defense

Ask the player to build or gather supplies first, then begin a second stage that spawns attackers around the quest giver.

Use this when the player must build or gather something first, then a new wave of threats appears in a later stage. Based on `questlines/village_build/village_pig_enclosure.json`. Key points: - `sequential_objectives: true` makes stage `0` finish before stage `1` starts. - Build objectives use `place`, `bring`, `collect`, or other normal objective shortcuts. - Threats can be assigned to `stage: 1` and spawned around the quest giver with `spawn_origin: "quest_giver"`. - Use `from_threats: true` on kill goals when the spawned named/custom threats should count. - Add one `threats` entry per mob to spawn. `amount` is not read on threat entries.
{
  "title": {
    "translate": "quest.example.first_pen_defense.title",
    "fallback": "A Pen Worth Defending"
  },
  "summary": {
    "translate": "quest.example.first_pen_defense.summary",
    "fallback": "Build a small animal pen, bring livestock inside, then defend it from raiders."
  },
  "sequential_objectives": true,
  "dialogue": {
    "intro": {
      "translate": "quest.example.first_pen_defense.dialogue.intro",
      "fallback": "The villager points to a bare patch of grass near the farm."
    },
    "offer": [
      [
        {
          "translate": "quest.example.first_pen_defense.dialogue.offer.0.0",
          "fallback": "What do you need built?"
        },
        {
          "translate": "quest.example.first_pen_defense.dialogue.offer.0.1",
          "fallback": "A fence, a gate, two torches, and enough room for the first herd."
        }
      ]
    ],
    "return": {
      "translate": "quest.example.first_pen_defense.dialogue.return",
      "fallback": "The pen held. So did you."
    },
    "reward": {
      "translate": "quest.example.first_pen_defense.dialogue.reward",
      "fallback": "Take this. A defended farm feeds more than one house."
    },
    "done": {
      "translate": "quest.example.first_pen_defense.dialogue.done",
      "fallback": "The animals are still inside, and the raiders are gone."
    }
  },
  "goals": [
    {
      "id": "place_fences",
      "place": "minecraft:oak_fence",
      "amount": 12,
      "stage": 0,
      "range": 60
    },
    {
      "id": "place_gate",
      "place": "minecraft:oak_fence_gate",
      "amount": 1,
      "stage": 0,
      "range": 60
    },
    {
      "id": "place_torches",
      "place": "minecraft:torch",
      "amount": 2,
      "stage": 0,
      "range": 60,
      "say": {
        "translate": "quest.example.first_pen_defense.goals.place_torches.say",
        "fallback": "The pen is lit. Stay close."
      }
    },
    {
      "id": "bring_animals",
      "bring": "minecraft:pig",
      "amount": 2,
      "stage": 0,
      "range": 60
    },
    {
      "id": "kill_raiders",
      "kill": "minecraft:pillager",
      "amount": 3,
      "stage": 1,
      "from_threats": true
    },
    {
      "id": "kill_raider_captain",
      "kill": "minecraft:vindicator",
      "amount": 1,
      "stage": 1,
      "from_threats": true
    }
  ],
  "threats": [
    {
      "entity": "minecraft:pillager",
      "name": {
        "translate": "quest.example.first_pen_defense.threats.0.name",
        "fallback": "Hungry Raider"
      },
      "stage": 1,
      "spawn_origin": "quest_giver",
      "spawn_min_radius": 18,
      "spawn_max_radius": 30,
      "spawn_on_accept": true,
      "spare_enabled": false,
      "glow": true
    },
    {
      "entity": "minecraft:pillager",
      "name": {
        "translate": "quest.example.first_pen_defense.threats.1.name",
        "fallback": "Fence-Cutting Raider"
      },
      "stage": 1,
      "spawn_origin": "quest_giver",
      "spawn_min_radius": 18,
      "spawn_max_radius": 30,
      "spawn_on_accept": true,
      "spare_enabled": false,
      "glow": true
    },
    {
      "entity": "minecraft:pillager",
      "name": {
        "translate": "quest.example.first_pen_defense.threats.2.name",
        "fallback": "Torch-Kicking Raider"
      },
      "stage": 1,
      "spawn_origin": "quest_giver",
      "spawn_min_radius": 18,
      "spawn_max_radius": 30,
      "spawn_on_accept": true,
      "spare_enabled": false,
      "glow": true
    },
    {
      "entity": "minecraft:vindicator",
      "name": {
        "translate": "quest.example.first_pen_defense.threats.3.name",
        "fallback": "Fence Breaker"
      },
      "stage": 1,
      "spawn_origin": "quest_giver",
      "spawn_min_radius": 22,
      "spawn_max_radius": 34,
      "spawn_on_accept": true,
      "spare_enabled": false,
      "glow": true,
      "max_health": 40.0
    }
  ],
  "rewards": {
    "xp": 180,
    "items": {
      "minecraft:emerald": 6,
      "minecraft:wheat": 12
    }
  },
  "traits": {
    "complete": [
      "farm_defender"
    ]
  }
}

Generated Container, Written Book, and TNT

Place quest items inside a structure container, make the player read a written clue, then complete a demolition objective and spawn enemies.

Use this when a structure should contain generated quest items, a written-book clue, and a demolition step near a target block. Based on `questlines/sculk/sculk_mineshaft_investigation.json`. Key points: - `read_book` objectives must include `item: "minecraft:written_book"`. - `quest_book.title`, `quest_book.author`, and `quest_book.pages` can be translation objects. - Use `in_chest: true` with `container` to spawn the objective item inside a generated container. - Generated chest/container items are placed into random empty slots by the quest item spawner. - `detonate_tnt` should use `block` for the target block near the explosion, not the TNT block itself. - `force_place_block: true` can prepare the target block when the structure does not reliably contain one.
{
  "title": {
    "translate": "quest.example.mine_demolition.title",
    "fallback": "Notes Under the Mine"
  },
  "summary": {
    "translate": "quest.example.mine_demolition.summary",
    "fallback": "Find a sealed mineshaft, recover the foreman's notes, and destroy the marked spawner."
  },
  "sequential_objectives": true,
  "goals": [
    {
      "id": "reach_old_mine",
      "reach": "minecraft:mineshaft",
      "structure": "minecraft:mineshaft",
      "radius": 3200,
      "range": 80,
      "stage": 0,
      "auto_advance": true
    },
    {
      "id": "read_foreman_notes",
      "type": "read_book",
      "item": "minecraft:written_book",
      "amount": 1,
      "structure": "minecraft:mineshaft",
      "container": "minecraft:barrel",
      "stage": 1,
      "radius": 3200,
      "in_chest": true,
      "auto_advance": true,
      "tag": "example_foreman_notes",
      "quest_book": {
        "title": {
          "translate": "quest.example.mine_demolition.book.title",
          "fallback": "Foreman's Notes"
        },
        "author": {
          "translate": "quest.example.mine_demolition.book.author",
          "fallback": "Mine Foreman"
        },
        "pages": [
          {
            "translate": "quest.example.mine_demolition.book.page.0",
            "fallback": "We sealed the lower drift after the spawner woke again. If anyone returns, place charges near the cage, not in the tunnel mouth."
          }
        ]
      },
      "block_patch": {
        "radius": 4,
        "palette": [
          "minecraft:sculk",
          "minecraft:deepslate"
        ]
      }
    },
    {
      "id": "take_tnt_from_barrel",
      "collect": "minecraft:tnt",
      "amount": 3,
      "mandatory": false,
      "sequential": true,
      "stage": 1,
      "in_chest": true,
      "structure": "minecraft:mineshaft",
      "container": "minecraft:barrel"
    },
    {
      "id": "place_demolition_charges",
      "place": "minecraft:tnt",
      "amount": 3,
      "structure": "minecraft:mineshaft",
      "stage": 2,
      "range": 12
    },
    {
      "id": "detonate_spawner",
      "type": "detonate_tnt",
      "block": "minecraft:spawner",
      "required_mob": "minecraft:skeleton",
      "structure": "minecraft:mineshaft",
      "force_place_block": true,
      "amount": 3,
      "stage": 2,
      "radius": 3200,
      "range": 14,
      "auto_advance": true,
      "block_patch": {
        "radius": 3,
        "palette": [
          "minecraft:sculk",
          "minecraft:deepslate"
        ]
      }
    },
    {
      "id": "kill_what_crawls_out",
      "kill": "minecraft:zombie",
      "amount": 4,
      "stage": 3,
      "from_threats": true
    }
  ],
  "threats": [
    {
      "entity": "minecraft:zombie",
      "name": {
        "translate": "quest.example.mine_demolition.threats.0.name",
        "fallback": "Sculk-Crowned Dead"
      },
      "stage": 3,
      "spawn_origin": "player",
      "spawn_min_radius": 8,
      "spawn_max_radius": 16,
      "spawn_on_accept": true,
      "spare_enabled": false,
      "glow": true,
      "equipment": {
        "head": "minecraft:sculk"
      }
    },
    {
      "entity": "minecraft:zombie",
      "name": {
        "translate": "quest.example.mine_demolition.threats.1.name",
        "fallback": "Sculk-Marked Dead"
      },
      "stage": 3,
      "spawn_origin": "player",
      "spawn_min_radius": 8,
      "spawn_max_radius": 16,
      "spawn_on_accept": true,
      "spare_enabled": false,
      "glow": true,
      "equipment": {
        "head": "minecraft:sculk"
      }
    },
    {
      "entity": "minecraft:zombie",
      "name": {
        "translate": "quest.example.mine_demolition.threats.2.name",
        "fallback": "Sculk-Marked Dead"
      },
      "stage": 3,
      "spawn_origin": "player",
      "spawn_min_radius": 8,
      "spawn_max_radius": 16,
      "spawn_on_accept": true,
      "spare_enabled": false,
      "glow": true,
      "equipment": {
        "head": "minecraft:sculk"
      }
    },
    {
      "entity": "minecraft:zombie",
      "name": {
        "translate": "quest.example.mine_demolition.threats.3.name",
        "fallback": "Sculk-Marked Dead"
      },
      "stage": 3,
      "spawn_origin": "player",
      "spawn_min_radius": 8,
      "spawn_max_radius": 16,
      "spawn_on_accept": true,
      "spare_enabled": false,
      "glow": true,
      "equipment": {
        "head": "minecraft:sculk"
      }
    }
  ],
  "rewards": {
    "xp": 320,
    "items": {
      "minecraft:emerald": 10,
      "minecraft:echo_shard": 1
    }
  }
}

Delivery to Another Structure or Village

Collect supplies, travel to another structure or village, hand the items to a generated target, and return to the original quest giver.

Use this when the player gathers items, travels to another structure, gives the items to a spawned target, then returns to the original quest giver. Based on `delivery_cobblestone_oak_log_other_village.json`. Key points: - The delivery target is configured in `threat`. - `delivery_objectives` must list the objective ids that should be handed over. - The target talk objective should usually use `auto_advance: true`. - Add a final `return: true` objective in the next stage if the player must report back. - `min_structure_distance` is useful when the target should not spawn in the same village.
{
  "title": {
    "translate": "quest.example.remote_delivery.title",
    "fallback": "Stone for the Next Village"
  },
  "summary": {
    "translate": "quest.example.remote_delivery.summary",
    "fallback": "Carry supplies to a messenger waiting in another village."
  },
  "sequential_objectives": true,
  "goals": [
    {
      "id": "delivery_cobblestone",
      "collect": "minecraft:cobblestone",
      "amount": 32,
      "mandatory": true,
      "stage": 0
    },
    {
      "id": "delivery_oak_logs",
      "collect": "minecraft:oak_log",
      "amount": 16,
      "mandatory": true,
      "stage": 0
    },
    {
      "id": "deliver_to_messenger",
      "talk": "minecraft:villager",
      "amount": 1,
      "mandatory": true,
      "stage": 0,
      "auto_advance": true,
      "name": {
        "translate": "quest.example.remote_delivery.goals.deliver_to_messenger.name",
        "fallback": "Village Messenger"
      },
      "say": {
        "translate": "quest.example.remote_delivery.goals.deliver_to_messenger.say",
        "fallback": "The messenger takes the supplies. Return to the villager who sent you."
      }
    },
    {
      "id": "return_to_sender",
      "return": true,
      "amount": 1,
      "mandatory": true,
      "stage": 1
    }
  ],
  "threat": {
    "entity": "minecraft:villager",
    "name": {
      "translate": "quest.example.remote_delivery.threat.name",
      "fallback": "Village Messenger"
    },
    "structure": "minecraft:villages",
    "search_radius": 4200,
    "spawn_radius": 10,
    "spawn_on_accept": true,
    "spare_enabled": false,
    "glow": false,
    "target_line": {
      "translate": "quest.example.remote_delivery.threat.target_line",
      "fallback": "If you have the stone and oak, hand them over before the wall gives way."
    },
    "delivery_objectives": [
      "delivery_cobblestone",
      "delivery_oak_logs"
    ],
    "delivery_choice_label": {
      "translate": "quest.example.remote_delivery.threat.delivery_choice_label",
      "fallback": "Hand over supplies"
    },
    "delivered_line": {
      "translate": "quest.example.remote_delivery.threat.delivered_line",
      "fallback": "That will hold. Tell them the road between our villages is still worth keeping open."
    },
    "depart_after_delivery": false,
    "min_structure_distance": 700
  },
  "rewards": {
    "xp": 180,
    "items": {
      "minecraft:emerald": 7,
      "minecraft:bread": 6
    }
  }
}

Village Raid Defense

Start a normal Minecraft raid when the quest is accepted and complete the objective when the village survives.

Use this when accepting the quest should start a village raid and completing the raid should complete the objective. Based on `questlines/village_defense/village_defense_chain_3_the_bell_and_the_raid.json`. Key points: - Use `type: "defend_raid"`. - `amount: 1` is the normal value for a single raid defense objective. - This objective depends on the normal Minecraft raid flow, so it should be offered from a villager in or near the village being defended. - Use rewards with enchanted items when the raid reward should feel unique.
{
  "title": {
    "translate": "quest.example.bell_raid.title",
    "fallback": "The Bell and the Raid"
  },
  "summary": {
    "translate": "quest.example.bell_raid.summary",
    "fallback": "Stand with the village and survive the raid."
  },
  "dialogue": {
    "intro": {
      "translate": "quest.example.bell_raid.dialogue.intro",
      "fallback": "The villager stands beside the bell, one hand on the rope."
    },
    "offer": [
      [
        {
          "translate": "quest.example.bell_raid.dialogue.offer.0.0",
          "fallback": "You think they are coming now?"
        },
        {
          "translate": "quest.example.bell_raid.dialogue.offer.0.1",
          "fallback": "If we ring the bell, they will know we are ready to fight."
        }
      ]
    ],
    "return": {
      "translate": "quest.example.bell_raid.dialogue.return",
      "fallback": "The horn is silent. The village still stands."
    },
    "reward": {
      "translate": "quest.example.bell_raid.dialogue.reward",
      "fallback": "This was taken from the raid leader. By right of battle, it is yours."
    },
    "done": {
      "translate": "quest.example.bell_raid.dialogue.done",
      "fallback": "The bell rings for warning again, not fear."
    }
  },
  "goals": [
    {
      "id": "defend_the_village",
      "type": "defend_raid",
      "amount": 1
    }
  ],
  "rewards": {
    "xp": 650,
    "items": {
      "minecraft:emerald": 20,
      "minecraft:crossbow": {
        "count": 1,
        "enchantments": [
          {
            "id": "minecraft:power",
            "level": 3
          },
          {
            "id": "minecraft:unbreaking",
            "level": 2
          },
          {
            "id": "minecraft:piercing",
            "level": 1
          }
        ]
      }
    }
  },
  "traits": {
    "complete": [
      "village_defender"
    ]
  }
}

Rumor That Unlocks a Hidden Quest

Keep a quest unavailable until the player hears the correct rumor from a villager.

Use this when a quest should not appear until a villager rumor unlocks it. Based on `rumors/mine_smoke_below.json` and `blaze_mineshaft_threat.json`. Key points: - The rumor file lives under `data/<namespace>/rumors/<rumor_id>.json`. - `unlock_quest` should be the full quest id. - When the rumor is discovered, the player receives the trait `quest_discovered:<full quest id>`. - The hidden quest should require that trait. - Use `conditions.not_completed_quests` so the rumor stops being useful after the quest is complete. - Rumor `line` and `discovered_line` are currently plain strings. Rumor file:
{
  "id": "example_smoke_below",
  "weight": 15,
  "line": "Miners swear smoke is rising from shafts sealed for years.",
  "unlock_quest": "example:hidden_mineshaft_fire",
  "conditions": {
    "not_completed_quests": [
      "example:hidden_mineshaft_fire"
    ]
  },
  "discovered_line": "Rumor discovered: something hot and hostile is moving in an old mineshaft."
}
Hidden quest file:
{
  "title": {
    "translate": "quest.example.hidden_mineshaft_fire.title",
    "fallback": "Flame in the Mineshaft"
  },
  "summary": {
    "translate": "quest.example.hidden_mineshaft_fire.summary",
    "fallback": "A villager reports a blaze burning through an abandoned mineshaft."
  },
  "requires": {
    "traits": [
      "quest_discovered:example:hidden_mineshaft_fire"
    ]
  },
  "goals": [
    {
      "id": "kill_mine_blaze",
      "kill": "minecraft:blaze",
      "amount": 1
    }
  ],
  "threat": {
    "entity": "minecraft:blaze",
    "name": {
      "translate": "quest.example.hidden_mineshaft_fire.threat.name",
      "fallback": "Ignivar the Mineflame"
    },
    "structure": "minecraft:mineshaft",
    "search_radius": 4000,
    "spawn_on_accept": true,
    "spare_enabled": false,
    "max_health": 150.0,
    "offer_line": {
      "translate": "quest.example.hidden_mineshaft_fire.threat.offer_line",
      "fallback": "Something from the Nether is burning through an old mineshaft."
    },
    "target_line": {
      "translate": "quest.example.hidden_mineshaft_fire.threat.target_line",
      "fallback": "The blaze crackles with hostile heat. There is no sign it understands mercy."
    }
  },
  "rewards": {
    "xp": 260,
    "items": {
      "minecraft:emerald": 12,
      "minecraft:blaze_rod": 2
    }
  }
}

Escort to a Structure

Escort a quest entity to a searched structure, with configurable search distance and completion range.

Use this when the quest giver or quest entity must be escorted to a target structure. Based on `questlines/armed_zombie/armed_zombie_chain_spare_2_forgotten_road.json`. Key points: - Use the `escort` shortcut with a structure id. The parser converts it to `escort_entity`. - `radius` controls how far the structure search can go. - `range` controls how close the escorted entity must be to the target structure. - This works well as a follow-up after a spare/recruit branch.
{
  "title": {
    "translate": "quest.example.forgotten_road.title",
    "fallback": "The Forgotten Road"
  },
  "summary": {
    "translate": "quest.example.forgotten_road.summary",
    "fallback": "Escort a spared enemy toward the village road it remembers."
  },
  "flow": {
    "next": "example:remembered_name"
  },
  "dialogue": {
    "intro": {
      "translate": "quest.example.forgotten_road.dialogue.intro",
      "fallback": "The spared creature keeps its weapon low and looks toward the road."
    },
    "offer": [
      [
        {
          "translate": "quest.example.forgotten_road.dialogue.offer.0.0",
          "fallback": "You remember a village?"
        },
        {
          "translate": "quest.example.forgotten_road.dialogue.offer.0.1",
          "fallback": "A bell. Smoke. A well with cracked stone. Take me there."
        }
      ]
    ],
    "return": {
      "translate": "quest.example.forgotten_road.dialogue.return",
      "fallback": "The bell. I know that sound."
    },
    "reward": {
      "translate": "quest.example.forgotten_road.dialogue.reward",
      "fallback": "I found this under the well stones. It was mine once."
    },
    "done": {
      "translate": "quest.example.forgotten_road.dialogue.done",
      "fallback": "The village road remembers me."
    }
  },
  "goals": [
    {
      "id": "escort_to_village",
      "escort": "minecraft:village_plains",
      "radius": 3500,
      "range": 40
    }
  ],
  "rewards": {
    "xp": 220,
    "items": {
      "minecraft:iron_ingot": 6,
      "minecraft:emerald": 4
    }
  },
  "traits": {
    "complete": [
      "escort_memory"
    ]
  }
}

Mebahel's RPG: Villager Quests & Companions

Turn Minecraft villages into living RPG hubs.

Mebahel's RPG: Villager Quests & Companions adds story-driven villager quests, rumors, named enemies, branching choices, quest tracking, RPG-style notifications, and recruitable companions. Villagers are no longer just traders standing near a bell. They can ask for help, warn you about nearby threats, send you toward strange structures, reveal hidden stories through rumors, or pull you into choices that change what happens next.

Some quests are simple village jobs. Others become full story arcs with investigations, moral decisions, ambushes, raids, hidden follow-ups, named targets, and enemies who might not deserve the axe you were sent to bring.

If you like vanilla Minecraft but want villages to give you more reasons to explore, protect, question, and return, this mod is built for that.


Dependencies

Forge / NeoForge

Fabric


Compatible Mods

The following compatibility has been confirmed by the mod author or tested by players:

  • Guard Villagers — supported through a dedicated configuration file that lets guards offer selected quests when the mod is installed.
  • Villagers Reborn — confirmed compatible. Its villager model and interaction changes can be used alongside this mod's quests.
  • Epic Villages — tested by players and confirmed working with the quest system.
  • Luki's Grand Capitals — tested by players and confirmed working with the quest system.
  • Villager Retaliation — both mods can be used together. Their quest systems remain separate, but the core features can coexist.

Village overhaul mods are generally compatible because quests can be assigned to villagers inside both vanilla and modded villages or structures.


What This Mod Adds

  • Over 50 included quests built around villages, roads, mines, raids, ruined portals, witches, raiders, skeletons, undead soldiers, false heroes, strange survivors, and hidden contracts.
  • Branching storylines where killing, sparing, exposing, defending, escorting, delivering, or investigating can lead to different follow-up quests.
  • Named quest targets with custom dialogue, equipment, locations, health, mounts, drops, ambushes, and spare/attack choices.
  • Recruitable companions from selected mercy paths, including restored enemies who can later fight beside you.
  • Villager rumors that unlock hidden quests gradually instead of dumping every story on day one.
  • Quest journal and HUD tracking for active objectives, coordinates, structures, destinations, and threat targets.
  • RPG-style quest notifications with custom sounds when quests start, update, or complete.
  • Many objective types: kill, collect, deliver, read, escort, bring back, reach a structure, break blocks, place blocks, detonate TNT, enter or leave the Nether, defend raids, wait for time to pass, talk to entities, and return to the quest giver.
  • Datapack and mod support so creators can add quests and rumors with JSON files.

How It Feels In Game

You arrive at a village. A farmer heard something moving near an old portal. A smith remembers smoke below a mine. Someone claims a celebrated hero may be wearing stolen glory. A witch outside the village might be a threat, or she might be the only person telling the truth.

You talk, choose responses, accept the quest, track it in your journal, follow coordinates or structure clues, and return for rewards. Some targets fight immediately. Some talk first. Some can be spared. Sometimes mercy opens a longer path. Sometimes it brings danger back to the village.

The goal is to make villages feel like places with memory, consequences, and unfinished business.


Rumors and Discovery

Not every quest appears the same way.

Some villagers can offer jobs directly. Others may only give you a rumor. Hearing the right rumor can unlock hidden content, such as smoke below an old mine, a stranger among the dead, or trouble that appears only after a village has already survived a raid.

This lets the world reveal stories gradually as you play.


Companions

Certain spared characters can eventually become permanent companions.

Companions are designed to be useful without turning villages into chaos. They follow your lead, focus on hostile threats, and avoid randomly attacking peaceful villagers, iron golems, or passive animals.

Some companions also support equipment interaction through the companion inventory screen.


Quest Journal and HUD

Press J by default to open the quest journal.

The journal and tracker help you follow active objectives with contextual labels such as:

  • Threat location for named enemy targets.
  • Destination for escort quests.
  • Structure location for exploration objectives.
  • Target location when no more specific label applies.

Coordinates in the journal are clickable by default, and active objectives can be followed through the HUD tracker. Coordinate clicking can be disabled in the configuration.


Configuration

Server/world config file:

config/mebahelrpgrquest.json

Current configurable values:

{
  "villagerQuestChance": 0.20,
  "villagerRumorChance": 0.33,
  "disableQuestCoordinateClick": false,
  "shareQuestsBetweenPlayers": false,
  "inventoryJournalButtonPosition": "left",
  "hideInventoryJournalButton": false
}
  • villagerQuestChance is the quest assignment weight for a newly loaded villager.
  • villagerRumorChance is the rumor assignment weight for a newly loaded villager.
  • The two values compete in one roll. Any remaining weight up to 1.0 means no quest or rumor is assigned.
  • Values are clamped between 0.0 and 1.0. If their sum is above 1.0, quest and rumor are normalized against each other with no empty outcome.
  • disableQuestCoordinateClick controls coordinate interaction in the quest journal. Keep it set to false to let players click quest coordinates, or set it to true to disable coordinate clicking.
  • shareQuestsBetweenPlayers controls multiplayer quest sharing. Keep it set to false for separate quest progress per player, or set it to true to share quest progress, failures, completions, claimed rewards, and quest traits between all players on the server.
  • inventoryJournalButtonPosition controls where the inventory quest journal button appears. Use left for the default left side or right to move it to the right side. Invalid values fall back to left.
  • hideInventoryJournalButton hides the inventory quest journal button when set to true. It is false by default.

Additional Quest Configuration Files

  • Guard Villager quests: a dedicated configuration file lets you assign quests to guards from the Guard Villagers mod when it is installed.
  • Removed quests: a dedicated configuration file lets you list quest ids that should be removed from the available quest pool. Use it to disable included quests without editing the mod files.

Community

Join the Discord to follow development, report bugs, share quest ideas, or discuss custom quest lines:

https://discord.com/invite/y8uC2NepkB


Creating Custom Quests

Anyone can create new quests for the mod with JSON files in a datapack or addon. You can add dialogue, objectives, rumors, named enemies, rewards, choices, ambushes, raids, deliveries, escorts, and complete branching questlines.

File Locations

Place quest and rumor files in your own namespace:

data/<namespace>/quests/<quest_file>.json
data/<namespace>/rumors/<rumor_file>.json

For example:

data/my_quests/quests/old_well.json

This creates the quest id:

my_quests:old_well

Quest subfolders are allowed, but they do not become part of the quest id. Keep every quest filename unique inside your namespace.

Quick Start

  1. Choose the example below that is closest to the quest you want to make.
  2. Copy its JSON into a new file under data/<namespace>/quests/ or data/<namespace>/rumors/.
  3. Replace the example namespace with your own namespace.
  4. Change the dialogue, entities, structures, objectives, rewards, and linked quest ids.
  5. Reload the datapack and test the quest in a development or backup world.

JSON does not allow comments or trailing commas. Always use full identifiers such as minecraft:zombie, and use full quest ids such as my_quests:old_well when one file references another.

Player-facing text can use a translation object:

{
  "translate": "quest.my_quests.old_well.title",
  "fallback": "The Old Well"
}

The fallback value is displayed when no matching translation is available, so a separate language file is optional.


Quest Examples

Each example is kept in a separate expandable section. Copy the closest template and adapt only the parts your quest needs.

Named Threat with Attack or Spare Branches

Spawn a named enemy, let the player speak to it, then continue into a different quest depending on whether the target is attacked or spared.

 

Use this template for a quest that spawns a named threat, lets the player talk to it, then branches on attack or spare.

First Quest

{
  "title": "QUEST TITLE",
  "summary": "Villager-facing summary shown before acceptance.",

  "flow": {
    "on_kill": "modid:kill_branch_2",
    "on_spare": "modid:spare_branch_2"
  },

  "goals": [
    {
      "id": "talk_to_threat",
      "talk": "minecraft:zombie",
      "amount": 1,
      "name": "NAMED THREAT"
    },
    {
      "id": "kill_threat",
      "kill": "minecraft:zombie",
      "amount": 1,
      "attack_only": true,
      "from_threats": true
    }
  ],

  "threat": {
    "entity": "minecraft:zombie",
    "name": "NAMED THREAT",
    "structure": "minecraft:ruined_portal",
    "search_radius": 4000,
    "spawn_on_accept": true,
    "spawn_min_radius": 3,
    "spawn_max_radius": 6,
    "spare": true,
    "glow": false,
    "max_health": 150,
    "equipment": {
      "mainhand": "minecraft:diamond_sword",
      "helmet": {
        "item": "minecraft:iron_helmet",
        "enchants": {
          "minecraft:unbreaking": 3
        }
      }
    },
    "line": "Quest giver line that describes the threat.",
    "target": "Initial line spoken by the threat.",
    "talk": [
      ["Player question one?", "Threat answer one."],
      ["Player question two?", "Threat answer two."]
    ]
  },

  "choice": {
    "attack": {
      "label": "Attack choice label.",
      "traits": ["trait_from_attack"],
      "return": "Quest giver line after the target is killed."
    },
    "spare": {
      "label": "Spare choice label.",
      "line": "Immediate line after sparing the target.",
      "post": "Follow-up line shown after the spare.",
      "villager": "Quest giver line after spare.",
      "traits": ["trait_from_spare"],
      "rewards_from_giver": true,
      "rewards": {
        "xp": 160,
        "items": {
          "minecraft:iron_ingot": 4
        }
      },
      "after": {
        "offer_chance": 70,
        "ambush_chance": 30,
        "nothing_chance": 0,
        "ambush": "minecraft:zombie",
        "ambush_name": "Fallback Ambush Name",
        "count": 5,
        "ambush_max_health": 50,
        "ambush_equipment": {
          "helmet": "minecraft:leather_helmet"
        },
        "line": "Line used when the spared target offers the next quest.",
        "ambush_line": "Line used if mercy triggers an ambush.",
        "nothing": "Line used if no follow-up happens."
      }
    }
  },

  "dialogue": {
    "return": "Quest giver line after kill.",
    "reward": "Quest giver reward line.",
    "done": "Quest giver already-completed line."
  },

  "rewards": {
    "xp": 260,
    "items": {
      "minecraft:emerald": 10
    }
  }
}

For spare-enabled threat confrontations, prefer the talk plus attack_only kill pattern shown above. The first interaction opens dialogue without completing the stage; the stage completes only after the player explicitly chooses attack or spare.

Kill Branch

{
  "title": "KILL BRANCH TITLE",
  "summary": "Follow-up summary after the player chose attack.",

  "dialogue": {
    "intro": "Intro line.",
    "offer": [
      ["Player question?", "Quest giver answer."]
    ],
    "return": "Return line.",
    "reward": "Reward line.",
    "done": "Already completed line."
  },

  "goals": ["kill 3 minecraft:zombified_piglin"],

  "threats": [
    {
      "entity": "minecraft:zombified_piglin",
      "name": "Branch Threat",
      "structure": "minecraft:ruined_portal",
      "search_radius": 4000,
      "spawn_on_accept": true,
      "spare": false,
      "max_health": 70,
      "equipment": {
        "mainhand": "minecraft:golden_sword"
      }
    }
  ],

  "rewards": {
    "xp": 360,
    "items": {
      "minecraft:emerald": 14
    }
  }
}

Spare Branch

{
  "title": "SPARE BRANCH TITLE",
  "summary": "Follow-up summary after the player chose spare.",

  "flow": {
    "next": "modid:spare_branch_3"
  },

  "dialogue": {
    "intro": "Intro line from the spared target or quest giver.",
    "offer": [
      ["Player question?", "Answer."]
    ],
    "return": "Return line.",
    "reward": "Reward line.",
    "done": "Already completed line."
  },

  "goals": [
    {
      "collect": "minecraft:iron_ingot",
      "amount": 4
    }
  ],

  "rewards": {
    "xp": 240,
    "items": {
      "minecraft:emerald": 6
    }
  }
}

Staged Building and Defense

Ask the player to build or gather supplies first, then begin a second stage that spawns attackers around the quest giver.

 

Use this when the player must build or gather something first, then a new wave of threats appears in a later stage.

Based on questlines/village_build/village_pig_enclosure.json.

Key points:

  • sequential_objectives: true makes stage 0 finish before stage 1 starts.
  • Build objectives use place, bring, collect, or other normal objective shortcuts.
  • Threats can be assigned to stage: 1 and spawned around the quest giver with spawn_origin: "quest_giver".
  • Use from_threats: true on kill goals when the spawned named/custom threats should count.
  • Add one threats entry per mob to spawn. amount is not read on threat entries.
{
  "title": {
    "translate": "quest.example.first_pen_defense.title",
    "fallback": "A Pen Worth Defending"
  },
  "summary": {
    "translate": "quest.example.first_pen_defense.summary",
    "fallback": "Build a small animal pen, bring livestock inside, then defend it from raiders."
  },
  "sequential_objectives": true,
  "dialogue": {
    "intro": {
      "translate": "quest.example.first_pen_defense.dialogue.intro",
      "fallback": "The villager points to a bare patch of grass near the farm."
    },
    "offer": [
      [
        {
          "translate": "quest.example.first_pen_defense.dialogue.offer.0.0",
          "fallback": "What do you need built?"
        },
        {
          "translate": "quest.example.first_pen_defense.dialogue.offer.0.1",
          "fallback": "A fence, a gate, two torches, and enough room for the first herd."
        }
      ]
    ],
    "return": {
      "translate": "quest.example.first_pen_defense.dialogue.return",
      "fallback": "The pen held. So did you."
    },
    "reward": {
      "translate": "quest.example.first_pen_defense.dialogue.reward",
      "fallback": "Take this. A defended farm feeds more than one house."
    },
    "done": {
      "translate": "quest.example.first_pen_defense.dialogue.done",
      "fallback": "The animals are still inside, and the raiders are gone."
    }
  },
  "goals": [
    {
      "id": "place_fences",
      "place": "minecraft:oak_fence",
      "amount": 12,
      "stage": 0,
      "range": 60
    },
    {
      "id": "place_gate",
      "place": "minecraft:oak_fence_gate",
      "amount": 1,
      "stage": 0,
      "range": 60
    },
    {
      "id": "place_torches",
      "place": "minecraft:torch",
      "amount": 2,
      "stage": 0,
      "range": 60,
      "say": {
        "translate": "quest.example.first_pen_defense.goals.place_torches.say",
        "fallback": "The pen is lit. Stay close."
      }
    },
    {
      "id": "bring_animals",
      "bring": "minecraft:pig",
      "amount": 2,
      "stage": 0,
      "range": 60
    },
    {
      "id": "kill_raiders",
      "kill": "minecraft:pillager",
      "amount": 3,
      "stage": 1,
      "from_threats": true
    },
    {
      "id": "kill_raider_captain",
      "kill": "minecraft:vindicator",
      "amount": 1,
      "stage": 1,
      "from_threats": true
    }
  ],
  "threats": [
    {
      "entity": "minecraft:pillager",
      "name": {
        "translate": "quest.example.first_pen_defense.threats.0.name",
        "fallback": "Hungry Raider"
      },
      "stage": 1,
      "spawn_origin": "quest_giver",
      "spawn_min_radius": 18,
      "spawn_max_radius": 30,
      "spawn_on_accept": true,
      "spare_enabled": false,
      "glow": true
    },
    {
      "entity": "minecraft:pillager",
      "name": {
        "translate": "quest.example.first_pen_defense.threats.1.name",
        "fallback": "Fence-Cutting Raider"
      },
      "stage": 1,
      "spawn_origin": "quest_giver",
      "spawn_min_radius": 18,
      "spawn_max_radius": 30,
      "spawn_on_accept": true,
      "spare_enabled": false,
      "glow": true
    },
    {
      "entity": "minecraft:pillager",
      "name": {
        "translate": "quest.example.first_pen_defense.threats.2.name",
        "fallback": "Torch-Kicking Raider"
      },
      "stage": 1,
      "spawn_origin": "quest_giver",
      "spawn_min_radius": 18,
      "spawn_max_radius": 30,
      "spawn_on_accept": true,
      "spare_enabled": false,
      "glow": true
    },
    {
      "entity": "minecraft:vindicator",
      "name": {
        "translate": "quest.example.first_pen_defense.threats.3.name",
        "fallback": "Fence Breaker"
      },
      "stage": 1,
      "spawn_origin": "quest_giver",
      "spawn_min_radius": 22,
      "spawn_max_radius": 34,
      "spawn_on_accept": true,
      "spare_enabled": false,
      "glow": true,
      "max_health": 40.0
    }
  ],
  "rewards": {
    "xp": 180,
    "items": {
      "minecraft:emerald": 6,
      "minecraft:wheat": 12
    }
  },
  "traits": {
    "complete": [
      "farm_defender"
    ]
  }
}

Generated Container, Written Book, and TNT

Place quest items inside a structure container, make the player read a written clue, then complete a demolition objective and spawn enemies.

 

Use this when a structure should contain generated quest items, a written-book clue, and a demolition step near a target block.

Based on questlines/sculk/sculk_mineshaft_investigation.json.

Key points:

  • read_book objectives must include item: "minecraft:written_book".
  • quest_book.title, quest_book.author, and quest_book.pages can be translation objects.
  • Use in_chest: true with container to spawn the objective item inside a generated container.
  • Generated chest/container items are placed into random empty slots by the quest item spawner.
  • detonate_tnt should use block for the target block near the explosion, not the TNT block itself.
  • force_place_block: true can prepare the target block when the structure does not reliably contain one.
{
  "title": {
    "translate": "quest.example.mine_demolition.title",
    "fallback": "Notes Under the Mine"
  },
  "summary": {
    "translate": "quest.example.mine_demolition.summary",
    "fallback": "Find a sealed mineshaft, recover the foreman's notes, and destroy the marked spawner."
  },
  "sequential_objectives": true,
  "goals": [
    {
      "id": "reach_old_mine",
      "reach": "minecraft:mineshaft",
      "structure": "minecraft:mineshaft",
      "radius": 3200,
      "range": 80,
      "stage": 0,
      "auto_advance": true
    },
    {
      "id": "read_foreman_notes",
      "type": "read_book",
      "item": "minecraft:written_book",
      "amount": 1,
      "structure": "minecraft:mineshaft",
      "container": "minecraft:barrel",
      "stage": 1,
      "radius": 3200,
      "in_chest": true,
      "auto_advance": true,
      "tag": "example_foreman_notes",
      "quest_book": {
        "title": {
          "translate": "quest.example.mine_demolition.book.title",
          "fallback": "Foreman's Notes"
        },
        "author": {
          "translate": "quest.example.mine_demolition.book.author",
          "fallback": "Mine Foreman"
        },
        "pages": [
          {
            "translate": "quest.example.mine_demolition.book.page.0",
            "fallback": "We sealed the lower drift after the spawner woke again. If anyone returns, place charges near the cage, not in the tunnel mouth."
          }
        ]
      },
      "block_patch": {
        "radius": 4,
        "palette": [
          "minecraft:sculk",
          "minecraft:deepslate"
        ]
      }
    },
    {
      "id": "take_tnt_from_barrel",
      "collect": "minecraft:tnt",
      "amount": 3,
      "mandatory": false,
      "sequential": true,
      "stage": 1,
      "in_chest": true,
      "structure": "minecraft:mineshaft",
      "container": "minecraft:barrel"
    },
    {
      "id": "place_demolition_charges",
      "place": "minecraft:tnt",
      "amount": 3,
      "structure": "minecraft:mineshaft",
      "stage": 2,
      "range": 12
    },
    {
      "id": "detonate_spawner",
      "type": "detonate_tnt",
      "block": "minecraft:spawner",
      "required_mob": "minecraft:skeleton",
      "structure": "minecraft:mineshaft",
      "force_place_block": true,
      "amount": 3,
      "stage": 2,
      "radius": 3200,
      "range": 14,
      "auto_advance": true,
      "block_patch": {
        "radius": 3,
        "palette": [
          "minecraft:sculk",
          "minecraft:deepslate"
        ]
      }
    },
    {
      "id": "kill_what_crawls_out",
      "kill": "minecraft:zombie",
      "amount": 4,
      "stage": 3,
      "from_threats": true
    }
  ],
  "threats": [
    {
      "entity": "minecraft:zombie",
      "name": {
        "translate": "quest.example.mine_demolition.threats.0.name",
        "fallback": "Sculk-Crowned Dead"
      },
      "stage": 3,
      "spawn_origin": "player",
      "spawn_min_radius": 8,
      "spawn_max_radius": 16,
      "spawn_on_accept": true,
      "spare_enabled": false,
      "glow": true,
      "equipment": {
        "head": "minecraft:sculk"
      }
    },
    {
      "entity": "minecraft:zombie",
      "name": {
        "translate": "quest.example.mine_demolition.threats.1.name",
        "fallback": "Sculk-Marked Dead"
      },
      "stage": 3,
      "spawn_origin": "player",
      "spawn_min_radius": 8,
      "spawn_max_radius": 16,
      "spawn_on_accept": true,
      "spare_enabled": false,
      "glow": true,
      "equipment": {
        "head": "minecraft:sculk"
      }
    },
    {
      "entity": "minecraft:zombie",
      "name": {
        "translate": "quest.example.mine_demolition.threats.2.name",
        "fallback": "Sculk-Marked Dead"
      },
      "stage": 3,
      "spawn_origin": "player",
      "spawn_min_radius": 8,
      "spawn_max_radius": 16,
      "spawn_on_accept": true,
      "spare_enabled": false,
      "glow": true,
      "equipment": {
        "head": "minecraft:sculk"
      }
    },
    {
      "entity": "minecraft:zombie",
      "name": {
        "translate": "quest.example.mine_demolition.threats.3.name",
        "fallback": "Sculk-Marked Dead"
      },
      "stage": 3,
      "spawn_origin": "player",
      "spawn_min_radius": 8,
      "spawn_max_radius": 16,
      "spawn_on_accept": true,
      "spare_enabled": false,
      "glow": true,
      "equipment": {
        "head": "minecraft:sculk"
      }
    }
  ],
  "rewards": {
    "xp": 320,
    "items": {
      "minecraft:emerald": 10,
      "minecraft:echo_shard": 1
    }
  }
}

Delivery to Another Structure or Village

Collect supplies, travel to another structure or village, hand the items to a generated target, and return to the original quest giver.

 

Use this when the player gathers items, travels to another structure, gives the items to a spawned target, then returns to the original quest giver.

Based on delivery_cobblestone_oak_log_other_village.json.

Key points:

  • The delivery target is configured in threat.
  • delivery_objectives must list the objective ids that should be handed over.
  • The target talk objective should usually use auto_advance: true.
  • Add a final return: true objective in the next stage if the player must report back.
  • min_structure_distance is useful when the target should not spawn in the same village.
{
  "title": {
    "translate": "quest.example.remote_delivery.title",
    "fallback": "Stone for the Next Village"
  },
  "summary": {
    "translate": "quest.example.remote_delivery.summary",
    "fallback": "Carry supplies to a messenger waiting in another village."
  },
  "sequential_objectives": true,
  "goals": [
    {
      "id": "delivery_cobblestone",
      "collect": "minecraft:cobblestone",
      "amount": 32,
      "mandatory": true,
      "stage": 0
    },
    {
      "id": "delivery_oak_logs",
      "collect": "minecraft:oak_log",
      "amount": 16,
      "mandatory": true,
      "stage": 0
    },
    {
      "id": "deliver_to_messenger",
      "talk": "minecraft:villager",
      "amount": 1,
      "mandatory": true,
      "stage": 0,
      "auto_advance": true,
      "name": {
        "translate": "quest.example.remote_delivery.goals.deliver_to_messenger.name",
        "fallback": "Village Messenger"
      },
      "say": {
        "translate": "quest.example.remote_delivery.goals.deliver_to_messenger.say",
        "fallback": "The messenger takes the supplies. Return to the villager who sent you."
      }
    },
    {
      "id": "return_to_sender",
      "return": true,
      "amount": 1,
      "mandatory": true,
      "stage": 1
    }
  ],
  "threat": {
    "entity": "minecraft:villager",
    "name": {
      "translate": "quest.example.remote_delivery.threat.name",
      "fallback": "Village Messenger"
    },
    "structure": "minecraft:villages",
    "search_radius": 4200,
    "spawn_radius": 10,
    "spawn_on_accept": true,
    "spare_enabled": false,
    "glow": false,
    "target_line": {
      "translate": "quest.example.remote_delivery.threat.target_line",
      "fallback": "If you have the stone and oak, hand them over before the wall gives way."
    },
    "delivery_objectives": [
      "delivery_cobblestone",
      "delivery_oak_logs"
    ],
    "delivery_choice_label": {
      "translate": "quest.example.remote_delivery.threat.delivery_choice_label",
      "fallback": "Hand over supplies"
    },
    "delivered_line": {
      "translate": "quest.example.remote_delivery.threat.delivered_line",
      "fallback": "That will hold. Tell them the road between our villages is still worth keeping open."
    },
    "depart_after_delivery": false,
    "min_structure_distance": 700
  },
  "rewards": {
    "xp": 180,
    "items": {
      "minecraft:emerald": 7,
      "minecraft:bread": 6
    }
  }
}

Village Raid Defense

Start a normal Minecraft raid when the quest is accepted and complete the objective when the village survives.

 

Use this when accepting the quest should start a village raid and completing the raid should complete the objective.

Based on questlines/village_defense/village_defense_chain_3_the_bell_and_the_raid.json.

Key points:

  • Use type: "defend_raid".
  • amount: 1 is the normal value for a single raid defense objective.
  • This objective depends on the normal Minecraft raid flow, so it should be offered from a villager in or near the village being defended.
  • Use rewards with enchanted items when the raid reward should feel unique.
{
  "title": {
    "translate": "quest.example.bell_raid.title",
    "fallback": "The Bell and the Raid"
  },
  "summary": {
    "translate": "quest.example.bell_raid.summary",
    "fallback": "Stand with the village and survive the raid."
  },
  "dialogue": {
    "intro": {
      "translate": "quest.example.bell_raid.dialogue.intro",
      "fallback": "The villager stands beside the bell, one hand on the rope."
    },
    "offer": [
      [
        {
          "translate": "quest.example.bell_raid.dialogue.offer.0.0",
          "fallback": "You think they are coming now?"
        },
        {
          "translate": "quest.example.bell_raid.dialogue.offer.0.1",
          "fallback": "If we ring the bell, they will know we are ready to fight."
        }
      ]
    ],
    "return": {
      "translate": "quest.example.bell_raid.dialogue.return",
      "fallback": "The horn is silent. The village still stands."
    },
    "reward": {
      "translate": "quest.example.bell_raid.dialogue.reward",
      "fallback": "This was taken from the raid leader. By right of battle, it is yours."
    },
    "done": {
      "translate": "quest.example.bell_raid.dialogue.done",
      "fallback": "The bell rings for warning again, not fear."
    }
  },
  "goals": [
    {
      "id": "defend_the_village",
      "type": "defend_raid",
      "amount": 1
    }
  ],
  "rewards": {
    "xp": 650,
    "items": {
      "minecraft:emerald": 20,
      "minecraft:crossbow": {
        "count": 1,
        "enchantments": [
          {
            "id": "minecraft:power",
            "level": 3
          },
          {
            "id": "minecraft:unbreaking",
            "level": 2
          },
          {
            "id": "minecraft:piercing",
            "level": 1
          }
        ]
      }
    }
  },
  "traits": {
    "complete": [
      "village_defender"
    ]
  }
}

Rumor That Unlocks a Hidden Quest

Keep a quest unavailable until the player hears the correct rumor from a villager.

 

Use this when a quest should not appear until a villager rumor unlocks it.

Based on rumors/mine_smoke_below.json and blaze_mineshaft_threat.json.

Key points:

  • The rumor file lives under data/<namespace>/rumors/<rumor_id>.json.
  • unlock_quest should be the full quest id.
  • When the rumor is discovered, the player receives the trait quest_discovered:<full quest id>.
  • The hidden quest should require that trait.
  • Use conditions.not_completed_quests so the rumor stops being useful after the quest is complete.
  • Rumor line and discovered_line are currently plain strings.

Rumor file:

{
  "id": "example_smoke_below",
  "weight": 15,
  "line": "Miners swear smoke is rising from shafts sealed for years.",
  "unlock_quest": "example:hidden_mineshaft_fire",
  "conditions": {
    "not_completed_quests": [
      "example:hidden_mineshaft_fire"
    ]
  },
  "discovered_line": "Rumor discovered: something hot and hostile is moving in an old mineshaft."
}

Hidden quest file:

{
  "title": {
    "translate": "quest.example.hidden_mineshaft_fire.title",
    "fallback": "Flame in the Mineshaft"
  },
  "summary": {
    "translate": "quest.example.hidden_mineshaft_fire.summary",
    "fallback": "A villager reports a blaze burning through an abandoned mineshaft."
  },
  "requires": {
    "traits": [
      "quest_discovered:example:hidden_mineshaft_fire"
    ]
  },
  "goals": [
    {
      "id": "kill_mine_blaze",
      "kill": "minecraft:blaze",
      "amount": 1
    }
  ],
  "threat": {
    "entity": "minecraft:blaze",
    "name": {
      "translate": "quest.example.hidden_mineshaft_fire.threat.name",
      "fallback": "Ignivar the Mineflame"
    },
    "structure": "minecraft:mineshaft",
    "search_radius": 4000,
    "spawn_on_accept": true,
    "spare_enabled": false,
    "max_health": 150.0,
    "offer_line": {
      "translate": "quest.example.hidden_mineshaft_fire.threat.offer_line",
      "fallback": "Something from the Nether is burning through an old mineshaft."
    },
    "target_line": {
      "translate": "quest.example.hidden_mineshaft_fire.threat.target_line",
      "fallback": "The blaze crackles with hostile heat. There is no sign it understands mercy."
    }
  },
  "rewards": {
    "xp": 260,
    "items": {
      "minecraft:emerald": 12,
      "minecraft:blaze_rod": 2
    }
  }
}

Escort to a Structure

Escort a quest entity to a searched structure, with configurable search distance and completion range.

 

Use this when the quest giver or quest entity must be escorted to a target structure.

Based on questlines/armed_zombie/armed_zombie_chain_spare_2_forgotten_road.json.

Key points:

  • Use the escort shortcut with a structure id. The parser converts it to escort_entity.
  • radius controls how far the structure search can go.
  • range controls how close the escorted entity must be to the target structure.
  • This works well as a follow-up after a spare/recruit branch.
{
  "title": {
    "translate": "quest.example.forgotten_road.title",
    "fallback": "The Forgotten Road"
  },
  "summary": {
    "translate": "quest.example.forgotten_road.summary",
    "fallback": "Escort a spared enemy toward the village road it remembers."
  },
  "flow": {
    "next": "example:remembered_name"
  },
  "dialogue": {
    "intro": {
      "translate": "quest.example.forgotten_road.dialogue.intro",
      "fallback": "The spared creature keeps its weapon low and looks toward the road."
    },
    "offer": [
      [
        {
          "translate": "quest.example.forgotten_road.dialogue.offer.0.0",
          "fallback": "You remember a village?"
        },
        {
          "translate": "quest.example.forgotten_road.dialogue.offer.0.1",
          "fallback": "A bell. Smoke. A well with cracked stone. Take me there."
        }
      ]
    ],
    "return": {
      "translate": "quest.example.forgotten_road.dialogue.return",
      "fallback": "The bell. I know that sound."
    },
    "reward": {
      "translate": "quest.example.forgotten_road.dialogue.reward",
      "fallback": "I found this under the well stones. It was mine once."
    },
    "done": {
      "translate": "quest.example.forgotten_road.dialogue.done",
      "fallback": "The village road remembers me."
    }
  },
  "goals": [
    {
      "id": "escort_to_village",
      "escort": "minecraft:village_plains",
      "radius": 3500,
      "range": 40
    }
  ],
  "rewards": {
    "xp": 220,
    "items": {
      "minecraft:iron_ingot": 6,
      "minecraft:emerald": 4
    }
  },
  "traits": {
    "complete": [
      "escort_memory"
    ]
  }
}

Screenshots

Gallery

  • Quest Journal
    Quest Journal Quest Journal
  • Guard Villager from the Guard Villagers mod giving a hunt quest
    Guard Villager from the Guard Villagers mod giving a hunt quest Guard Villager from the Guard Villagers mod giving a hunt quest
  • Talking to Sir Alaric Ashward from the quest "The Armed Dead"
    Talking to Sir Alaric Ashward from the quest "The Armed Dead" Talking to Sir Alaric Ashward from the quest "The Armed Dead"
  • Sir Alaric Ashward as a companion
    Sir Alaric Ashward as a companion Sir Alaric Ashward as a companion
  • Managing Sir Alaric Ashward  equipment
    Managing Sir Alaric Ashward equipment Managing Sir Alaric Ashward gears
  • Talking to a Villager to get a Quest
    Talking to a Villager to get a Quest Talking to a Villager to get a Quest
  • Building a new house for the village from the quest "Room for New Neighbors"
    Building a new house for the village from the quest "Room for New Neighbors" Building a new house for the village from the quest "Room for New Neighbors"
  • Fighting threats from the "Ashes at the Frame" quest
    Fighting threats from the "Ashes at the Frame" quest Fighting threats from the "Ashes at the Frame" quest
  • Talking to "Oswin the Dead Scholar" from the "Among the Dead" quest
    Talking to "Oswin the Dead Scholar" from the "Among the Dead" quest Talking to "Oswin the Dead Scholar" from the "Among the Dead" quest
  • Fighting choice from "Among the Dead" quest
    Fighting choice from "Among the Dead" quest Fighting choice from "Among the Dead" quest
  • Talking to Sir Alaric Ashward from the quest "The Armed Dead"
    Talking to Sir Alaric Ashward from the quest "The Armed Dead" Talking to Sir Alaric Ashward from the quest "The Armed Dead"
  • Guard Villager from the Guard Villagers mod giving a hunt quest
    Guard Villager from the Guard Villagers mod giving a hunt quest Guard Villager from the Guard Villagers mod giving a hunt quest
  • Sir Alaric Ashward as a companion
    Sir Alaric Ashward as a companion Sir Alaric Ashward as a companion
  • Managing Sir Alaric Ashward  equipment
    Managing Sir Alaric Ashward equipment Managing Sir Alaric Ashward equipment
  • Talking to a Villager to get a Quest
    Talking to a Villager to get a Quest Talking to a Villager to get a Quest
  • Building a new house for the village from the quest "Room for Ne
    Building a new house for the village from the quest "Room for Ne Building a new house for the village from the quest "Room for New Neighbors"
  • Fighting threats from the "Ashes at the Frame" quest
    Fighting threats from the "Ashes at the Frame" quest Fighting threats from the "Ashes at the Frame" quest
  • Talking to "Oswin the Dead Scholar" from the "Among the Dead" qu
    Talking to "Oswin the Dead Scholar" from the "Among the Dead" qu Talking to "Oswin the Dead Scholar" from the "Among the Dead" quest
  • Fighting choice from "Among the Dead" quest
    Fighting choice from "Among the Dead" quest Fighting choice from "Among the Dead" quest

Versions

Files

Relations

Project Relations

More like this

Similar Mods

Suggestions use data such as tags, dependencies, dependents, descriptions, titles, and more to rank how much they overlap with this mod.

On ModDex

Community snapshot

0
Ratings
0
Followers
0
In stacks

By the numbers

Statistics

~3,000
Total Downloads
CurseForge
~2,000
Modrinth
<1,000
Last Updated
CurseForge
Created
CurseForge
Modrinth
Last synced
When ModDex last fetched and imported data for this project from CurseForge or Modrinth. High-traffic and active projects are checked more often.
Next pipeline sync