ContractRPG
Daily, weekly, special and server-wide contracts. Players hunt, mine, fish, craft and deliver to earn money, XP, points and loot — with a shop, ranks, rarities and a live boss-bar goal.
Everything a mission system needs
Installation
Get ContractRPG running in a minute — it needs no other plugin to start.
Steps
- Download ContractRPG.jar and drop it into your server's plugins/ folder.
- Restart the server (Java 21 required for 1.21+).
- (Optional) Install any integrations you want: Vault + economy, Citizens or FancyNpcs, MythicMobs, MythicLib, MMOItems, MMOCore, PlaceholderAPI.
- Edit the config files and run
/contract reload.
Integrations (all optional)
| Plugin | What it unlocks |
|---|---|
| Vault + economy | Money rewards (EssentialsX, CMI, any economy) |
| Citizens | Item-delivery contracts (NPC) |
| FancyNpcs | Item-delivery contracts (NPC), as an alternative to Citizens — needs Paper |
| MythicMobs | Hunt-MythicMob contracts |
| MythicLib + MMOItems | Deliver-MMOItem contracts |
| MMOCore | Use MMOCore levels/XP instead of the built-in one |
| PlaceholderAPI | Placeholders for scoreboards & holograms |
Supported server software
- Spigot, Paper and any fork — 1.21 and above.
- Folia — supported since 2.3.0. Every task the plugin schedules uses the regionised schedulers, so it loads and runs instead of failing at startup.
- Java 21 or newer.
Mission types
Every contract is one of these objectives. All progress is event-based — you must do it yourself.
| Type | Objective | What goes in mission-objective |
|---|---|---|
⚔️ HUNTING | Kill mobs (cows, zombies, creepers…) | The mob · ZOMBIE |
⛏️ MINING | Break blocks / mine ores | The block · IRON_ORE |
🎣 FISHING | Reel in fish with a rod (giving fish doesn't count) | The fish · SALMON |
🔨 CRAFTING | Craft items | The item · TORCH |
📦 DELIVER | Deliver items to a Citizens or FancyNpcs NPC | The item · WHEAT |
💎 DELIVER_MMOITEM | Deliver MMOItems to an NPC | TYPE:ID · MATERIAL:SILVER_INGOT |
🐉 HUNT_MYTHICMOB | Kill MythicMobs | The MythicMobs id · SkeletalKnight |
✨ ENCHANTING | Enchant items | The item enchanted · DIAMOND_SWORD |
🔥 SMELTING | Smelt items in a furnace | What comes out of the furnace · IRON_INGOT |
🐄 BREEDING | Breed animals | The animal · COW |
🐺 TAMING | Tame animals | The animal · WOLF |
💰 TRADING | Trade with villagers | Who you trade with · VILLAGER |
🧱 BLOCK_PLACE | Place blocks | The block · OAK_PLANKS |
⭐ XP_GAIN | Gain experience (XP) | Nothing — ignored |
🗡️ KILL_PLAYER | Kill players (PvP) | PLAYER |
🧭 EXPLORE | Travel a distance (blocks) | Nothing — ignored |
🌱 VISIT_BIOME | Visit a biome | The biome · PLAINS |
⚡ DAMAGE_DEALT | Deal damage | Who you hit · ZOMBIE or ANY |
🛡️ DAMAGE_TAKEN | Take damage | Who hits you · SKELETON or ANY |
🐎 RIDE | Ride / mount a distance | The mount · HORSE or ANY |
⏱️ PLAYTIME | Play for X minutes | Nothing — ignored |
🏰 STRUCTURE | Visit a structure (village, fortress…) | The structure · VILLAGE |
anti-farm.How to fill the mission-objective field
Names come straight from Minecraft's own enums (materials & entities): always UPPERCASE with underscores. One value per contract.
| Type | mission-objective | Example |
|---|---|---|
⚔️ HUNTING | Entity name | ZOMBIE · COW · CREEPER |
⛏️ MINING | Block / ore material | DIAMOND_ORE · COAL_ORE · OAK_LOG |
🎣 FISHING | Material you reel in | COD · SALMON · PUFFERFISH |
🔨 CRAFTING | Crafted material | TORCH · CHEST · BREAD |
📦 DELIVER | Material handed to the NPC | COBBLESTONE · SAND |
💎 DELIVER_MMOITEM | MMOItem as TYPE:ID | MATERIAL:SILVER_INGOT |
🐉 HUNT_MYTHICMOB | MythicMob internal name | Goblin · Yeti |
/contract create): it gives you a clickable picker for mobs, fish and MythicMobs, or just reads the item in your hand for mining / crafting / deliver.One full example per type (copy-paste into daily.yml / weekly.yml)
# HUNTING — kill entities
# Every entry goes under "contracts:" in daily.yml / weekly.yml / special.yml.
# Only mission-type + mission-objective change per type — the rest is the same.
contracts:
# HUNTING — kill entities
hunt_zombies:
display-name: "<#2E8B57>Kill Zombies"
contract-type: DAILY
mission-type: HUNTING
mission-objective: "ZOMBIE"
mission-requirement: 25
rewards: [ "eco give %player% 100" ]
display-rewards: [ "100 money" ]
experience-reward: 20
contract-points-reward: 7
level-requirement: 1
rarity: common
# MINING — break blocks / ores
mine_iron:
display-name: "<#A52A2A>Mine Iron"
contract-type: DAILY
mission-type: MINING
mission-objective: "IRON_ORE"
mission-requirement: 32
rewards: [ "eco give %player% 150" ]
display-rewards: [ "150 money" ]
experience-reward: 35
contract-points-reward: 11
level-requirement: 6
rarity: common
# FISHING — reel in fish with a rod
fish_salmon:
display-name: "<#FA8072>Fish Salmon"
contract-type: DAILY
mission-type: FISHING
mission-objective: "SALMON"
mission-requirement: 10
rewards: [ "eco give %player% 180" ]
display-rewards: [ "180 money" ]
experience-reward: 40
contract-points-reward: 13
level-requirement: 8
rarity: rare
# CRAFTING — craft items
craft_torch:
display-name: "<#FFD700>Craft Torches"
contract-type: DAILY
mission-type: CRAFTING
mission-objective: "TORCH"
mission-requirement: 64
rewards: [ "eco give %player% 70" ]
display-rewards: [ "70 money" ]
experience-reward: 15
contract-points-reward: 4
level-requirement: 1
rarity: common
# DELIVER — hand items to the delivery NPC (config.yml: delivery-npc-id for Citizens, delivery-fancynpc for FancyNpcs)
deliver_stone:
display-name: "<#808080>Deliver Cobblestone"
contract-type: DAILY
mission-type: DELIVER
mission-objective: "COBBLESTONE"
mission-requirement: 128
rewards: [ "eco give %player% 110" ]
display-rewards: [ "110 money" ]
experience-reward: 25
contract-points-reward: 7
level-requirement: 4
rarity: common
# DELIVER_MMOITEM — hand an MMOItem to the NPC (format TYPE:ID)
deliver_silver:
display-name: "<#C0C0C0>Deliver Silver Ingots"
contract-type: DAILY
mission-type: DELIVER_MMOITEM
mission-objective: "MATERIAL:SILVER_INGOT"
mission-requirement: 16
rewards: [ "eco give %player% 350" ]
display-rewards: [ "350 money" ]
experience-reward: 80
contract-points-reward: 30
level-requirement: 12
rarity: rare
# HUNT_MYTHICMOB — kill a MythicMob by its internal name
hunt_goblin:
display-name: "<#228B22>Kill Goblins"
contract-type: DAILY
mission-type: HUNT_MYTHICMOB
mission-objective: "Goblin"
mission-requirement: 15
rewards: [ "eco give %player% 300" ]
display-rewards: [ "300 money" ]
experience-reward: 70
contract-points-reward: 25
level-requirement: 10
rarity: rare
# ENCHANTING — enchant an item on the table
enchant_sword:
display-name: "<#9370DB>Enchant Swords"
contract-type: DAILY
mission-type: ENCHANTING
mission-objective: "DIAMOND_SWORD"
mission-requirement: 3
rewards: [ "eco give %player% 200" ]
display-rewards: [ "200 money" ]
experience-reward: 45
contract-points-reward: 14
level-requirement: 10
rarity: rare
# SMELTING — take the result OUT of the furnace
smelt_iron:
display-name: "<#CD853F>Smelt Iron"
contract-type: DAILY
mission-type: SMELTING
mission-objective: "IRON_INGOT"
mission-requirement: 32
rewards: [ "eco give %player% 160" ]
display-rewards: [ "160 money" ]
experience-reward: 30
contract-points-reward: 10
level-requirement: 5
rarity: common
# BREEDING — breed two animals
breed_cows:
display-name: "<#F5DEB3>Breed Cows"
contract-type: DAILY
mission-type: BREEDING
mission-objective: "COW"
mission-requirement: 8
rewards: [ "eco give %player% 140" ]
display-rewards: [ "140 money" ]
experience-reward: 28
contract-points-reward: 9
level-requirement: 3
rarity: common
# TAMING — tame an animal
tame_wolves:
display-name: "<#D2B48C>Tame Wolves"
contract-type: DAILY
mission-type: TAMING
mission-objective: "WOLF"
mission-requirement: 2
rewards: [ "eco give %player% 220" ]
display-rewards: [ "220 money" ]
experience-reward: 50
contract-points-reward: 15
level-requirement: 12
rarity: rare
# TRADING — the objective is WHO you trade with, not what you get
trade_villagers:
display-name: "<#32CD32>Trade with Villagers"
contract-type: DAILY
mission-type: TRADING
mission-objective: "VILLAGER"
mission-requirement: 10
rewards: [ "eco give %player% 190" ]
display-rewards: [ "190 money" ]
experience-reward: 38
contract-points-reward: 12
level-requirement: 6
rarity: common
# BLOCK_PLACE — place blocks
place_planks:
display-name: "<#DEB887>Place Oak Planks"
contract-type: DAILY
mission-type: BLOCK_PLACE
mission-objective: "OAK_PLANKS"
mission-requirement: 128
rewards: [ "eco give %player% 120" ]
display-rewards: [ "120 money" ]
experience-reward: 22
contract-points-reward: 6
level-requirement: 1
rarity: common
# KILL_PLAYER — PvP kills. The objective is always PLAYER
pvp_kills:
display-name: "<#DC143C>PvP Kills"
contract-type: DAILY
mission-type: KILL_PLAYER
mission-objective: "PLAYER"
mission-requirement: 3
rewards: [ "eco give %player% 500" ]
display-rewards: [ "500 money" ]
experience-reward: 90
contract-points-reward: 30
level-requirement: 15
rarity: legendary
# VISIT_BIOME — reach a biome
visit_desert:
display-name: "<#EDC9AF>Visit the Desert"
contract-type: DAILY
mission-type: VISIT_BIOME
mission-objective: "DESERT"
mission-requirement: 1
rewards: [ "eco give %player% 150" ]
display-rewards: [ "150 money" ]
experience-reward: 30
contract-points-reward: 10
level-requirement: 2
rarity: common
# DAMAGE_DEALT — damage you deal. Use ANY for "anything"
damage_zombies:
display-name: "<#B22222>Hurt Zombies"
contract-type: DAILY
mission-type: DAMAGE_DEALT
mission-objective: "ZOMBIE"
mission-requirement: 500
rewards: [ "eco give %player% 210" ]
display-rewards: [ "210 money" ]
experience-reward: 42
contract-points-reward: 13
level-requirement: 7
rarity: rare
# DAMAGE_TAKEN — damage you take. ANY also covers falls and fire
tank_skeletons:
display-name: "<#708090>Tank Skeletons"
contract-type: DAILY
mission-type: DAMAGE_TAKEN
mission-objective: "SKELETON"
mission-requirement: 200
rewards: [ "eco give %player% 230" ]
display-rewards: [ "230 money" ]
experience-reward: 46
contract-points-reward: 14
level-requirement: 9
rarity: rare
# RIDE — blocks ridden. Name the mount, or ANY for any of them
ride_horse:
display-name: "<#CD853F>Ride a Horse"
contract-type: DAILY
mission-type: RIDE
mission-objective: "HORSE"
mission-requirement: 1000
rewards: [ "eco give %player% 240" ]
display-rewards: [ "240 money" ]
experience-reward: 48
contract-points-reward: 15
level-requirement: 8
rarity: rare
# STRUCTURE — get close to a structure
visit_village:
display-name: "<#DAA520>Find a Village"
contract-type: DAILY
mission-type: STRUCTURE
mission-objective: "VILLAGE"
mission-requirement: 1
rewards: [ "eco give %player% 260" ]
display-rewards: [ "260 money" ]
experience-reward: 52
contract-points-reward: 16
level-requirement: 10
rarity: rare
# ---------------------------------------------------------------
# These three have NO objective: playing, walking and gaining XP do not
# happen "on" anything. Leave mission-objective out — and if you do write
# something, it is ignored.
# ---------------------------------------------------------------
# XP_GAIN — experience points gained
gain_xp:
display-name: "<#7FFF00>Gain Experience"
contract-type: DAILY
mission-type: XP_GAIN
mission-requirement: 500
rewards: [ "eco give %player% 200" ]
display-rewards: [ "200 money" ]
experience-reward: 40
contract-points-reward: 12
level-requirement: 5
rarity: rare
# EXPLORE — blocks travelled on foot
explore_1000:
display-name: "<#87CEEB>Go Exploring"
contract-type: DAILY
mission-type: EXPLORE
mission-requirement: 1000
rewards: [ "eco give %player% 170" ]
display-rewards: [ "170 money" ]
experience-reward: 34
contract-points-reward: 11
level-requirement: 3
rarity: common
# PLAYTIME — minutes connected
playtime_60:
display-name: "<#FFD700>Play for an Hour"
contract-type: DAILY
mission-type: PLAYTIME
mission-requirement: 60
rewards: [ "eco give %player% 280" ]
display-rewards: [ "280 money" ]
experience-reward: 56
contract-points-reward: 18
level-requirement: 1
rarity: rare
Options every contract accepts
They go inside the contract, at the same level as mission-type. Since 2.3.0 they work on every mission type: mining, hunting, fishing, crafting, MythicMobs and NPC deliveries used to skip them.
| Option | What it does |
|---|---|
worlds | Worlds where the contract counts. Empty or absent = all of them. worlds: [world, world_nether] |
anti-farm-ms | Minimum time between two progress ticks, in milliseconds. Cuts automated farms. anti-farm-ms: 1000 |
party-shared | One member's progress counts for everyone in the party who has that same contract accepted. party-shared: true |
party-split-reward | Splits the numeric rewards (money, XP, points) between members. Items are handed to each of them in full. party-split-reward: true |
Rewards & rarity
Contracts pay money, XP, contract points and optional item loot (with drop chances). Each contract has a rarity (Common / Rare / Legendary) that changes its color, glow and how often it appears — and higher-level players see more rare/legendary contracts.
The default files ship 24 daily, 12 weekly and 20+ special contracts, weighted by tier: many Common, fewer Rare, only a handful of Legendary — so higher tiers are rarer to roll.
Commands
Base command /contract — aliases /contracts, /crpg. Since 2.1 you can add your own in command-aliases. Press Tab to see only the commands you can use.
Players
| Command | What it does |
|---|---|
/contract | Open the contracts menu |
/contract shop | Open the point shop |
/contract top [level|points|contracts] | Leaderboard |
/contract global | View the active global contract & rewards |
/contract profile | Your profile & stats |
/contract party <invite|accept|leave|...> | Group contracts (invite / accept / leave) |
/contract market | Player marketplace (orders) |
/contract market create hand <amount> <price> | Order the item you are holding — custom items supported |
/contract redeem <code> | Redeem a code |
/contract suggest <text> | Suggest a contract |
/contract help | Command list |
/contract version | Plugin version & author |
Admin
| Command | What it does |
|---|---|
/contract create | Create a contract (GUI) |
/contract edit | Edit / delete contracts (GUI, by category) |
/contract reload | Reload config, languages, shop, contracts & global contracts — also from the console |
/contract reset | Force a mission reset for online players |
/contract resetplayer [player] | Reset a player's data |
/contract points [give|take|set] [player] [n] | Manage contract points |
/contract level [set|add] [player] [n] | Change a player's level |
/contract shopedit | In-game shop editor |
/contract global [next|reset|start <id>|stop] | Manage the global contract: skip to the next one, reset progress, start a specific one or stop them |
/contract booster <mult> <seconds> | Reward booster (×mult for N seconds) |
/contract analytics | Completion analytics (GUI) |
/contract suggestions | View player suggestions |
/contract placeholder | List placeholders |
Permissions
Grant these with LuckPerms or any permissions plugin.
| Permission | What it does | Default |
|---|---|---|
| contractrpg.use | Base command & menu | true |
| contractrpg.shop.open | Open the shop | true |
| contractrpg.reload | Reload | op |
| contractrpg.admin.reset | Mission reset | op |
| contractrpg.admin.shopedit | Shop editor | op |
| contractrpg.command.placeholder | Placeholder list | op |
| contractrpg.admin | Admin: create/edit, points, level, resetplayer | op |
Placeholders
Requires PlaceholderAPI. Great for scoreboards and DecentHolograms leaderboards.
%contractrpg_level%
%contractrpg_exp% %contractrpg_exp_required% %contractrpg_exp_bar%
%contractrpg_active_contracts_count%
%contractrpg_active_<1-N>_name%
%contractrpg_active_<1-N>_objective%
%contractrpg_active_<1-N>_progress%
%contractrpg_active_<1-N>_required%
%contractrpg_active_<1-N>_target%
%contractrpg_top_<level|points|completed>_<1-N>_name%
%contractrpg_top_<level|points|completed>_<1-N>_value%Configuration
Clean, commented files — most of it can be done in-game with the mission editor.
| File | What it unlocks |
|---|---|
config.yml | Leveling, storage, reroll, rarities, leaderboard, global contracts, completion FX, party, marketplace |
contracts/daily.yml · weekly.yml · special.yml | Your contracts |
global.yml | Server-wide global contracts |
shop.yml | Managed in-game with /contract shopedit |
lang/en·es·fr·zh.yml | Every message, fully editable |
<yellow> / <#ff8800> tags and classic &e / &#ff8800 codes — you can even mix them in one line.config.yml in detail
Every setting in plugins/ContractRPG/config.yml. Keys stay in English (that's how the plugin reads them); the comments follow your language.
Language, NPC & storage
language: "es" # language (file in /lang)
delivery-npc-id: -1 # Citizens NPC id for deliveries (-1 = none)
delivery-fancynpc: "" # FancyNpcs NPC name for deliveries (empty = none)
storage:
type: "yaml" # "yaml" or "sqlite"
auto-save-minutes: 5 # how often data is written to disk (0 = off)Command aliases
command-aliases: extra names for /contract
- missions
- contratos/reload is not enough. If another plugin already uses that name, it is skipped and a warning is logged.Leveling
leveling:
experience-base: 250 # XP for level 1→2; 2→3 = x2, etc.
level-up:
message: true # message on level up
title: true # on-screen title
sound: ENTITY_PLAYER_LEVELUP # sound (empty = off)
milestones: # commands when REACHING a level; %player% available
'5':
- "eco give %player% 1000"
'10':
- "eco give %player% 5000"MMOCore (optional)
mmocore:
enabled: false # true ONLY if you have MMOCore (use its levels/xp)Daily / weekly / special missions
show-locked-missions: true # show missions above your level, greyed out
daily-missions:
offered-amount: 4 # how many are offered to choose from
selectable-amount: 2 # how many can be accepted per day
reset-unfinished-on-new-offer: true # clears unfinished ones when new are offered
weekly-missions:
offered-amount: 3 # offered per week
selectable-amount: 1 # acceptable per week
reset-unfinished-on-new-offer: true
special-missions:
offered-amount: 2 # special missions offered
selectable-amount: 1offered-amount is how many contracts of that type are drawn at random for the player, and selectable-amount is how many they can accept. If you want players to see and pick from all of yours, set offered-amount above your total (for example 100). When they do not fit on one screen, the menu is split into pages with arrows at the bottom. The offer stays the same until the reset or a reroll, but it refreshes on its own when levelling up unlocks new contracts.Global contracts
global-contracts:
enabled: true # community goals (whole server contributes)
show-bossbar: true # progress boss bar on top
automatic: true # true = start and rotate on their own · false = only by hand with /contract global start
cooldown-min-minutes: 180 # min rest between globals (none active)
cooldown-max-minutes: 360 # max rest — the wait is random between the two. 0 and 0 = back-to-backautomatic: false no global contract runs until you start one with /contract global start <id> (it tab-completes the ids from global.yml), and when it is completed the server waits for your next command. /contract global stop ends the current one without rewards and keeps them stopped — even after a restart — until you start one again.Anti-farming
Closes the ways of finishing a contract without playing. All of it can be turned off.
anti-farm:
ignore-player-placed-blocks: true # a block a player placed does not count when broken
ignore-spawner-mobs: true # spawner mobs do not count as kills
ignore-spawn-egg-mobs: false # same for mobs spawned from an egg
placed-blocks-exempt: [] # materials that count even when you place them
max-tracked-blocks-per-chunk: 8192 # cap on blocks remembered per chunk (0 = no cap)
max-ride-blocks-per-second: 32 # above this it is treated as a teleport and ignoredignore-player-placed-blocks: false.Rarities
rarity-use-weight: true true = read weight · false = read chance
rarities: each contract can have rarity: <key>
common:
display-name: "<gray>» Common"
weight: 100 raffle tickets (higher = more frequent)
weight-per-level: 0 extra tickets per player level
chance: 74 the same as a percentage (they add to 100)
chance-per-level: 0
glow: false glow in the GUI
legendary:
display-name: "<#FFAA00>✦ Legendary ✦"
weight: 5
weight-per-level: 0.5
chance: 4
chance-per-level: 0.5
glow: true100 / 30 / 5 there are 135 tickets in total, so the real split is 74% / 22% / 3.7%. That is why raising one rarity lowers all the others — the pot grew. If you prefer plain percentages, set rarity-use-weight: false and use the chance lines. Either way, the console prints the real percentages on startup.Shop (discount per level)
shop:
discount-per-level: 0 # % discount per level (0.5 = -0.5%/level)
max-discount: 25 # max total discount (%)Reroll
reroll:
enabled: true # reroll offered contracts (daily/weekly)
cost: 10 # contract points per rerollLeaderboard
leaderboard:
enabled: true # player leaderboard
size: 10 # how many show in the top
update-interval-seconds: 300 # recompute (min 30 s)Completion sound & particles
completion:
sound: "ENTITY_PLAYER_LEVELUP" # sound on completion ("" = none)
sound-volume: 1.0 # volume
sound-pitch: 1.0 # pitch
particles: "TOTEM_OF_UNDYING" # particles ("" = none)
particles-count: 30 # particle countParty (group contracts)
party:
max-size: 4 # max members per party (leader included)Marketplace (player orders)
market:
max-open-orders: 5 # open orders per player (requires Vault)Example contract (with rarity + loot)
daily_hunt_cows:
display-name: "<#CD7F32>Daily: Fresh Meat"
contract-type: DAILY
mission-type: HUNTING
mission-objective: "COW"
mission-requirement: 15
rewards: [ "eco give %player% 70" ]
experience-reward: 15
contract-points-reward: 5
level-requirement: 1
rarity: rare
item-rewards:
'1': { material: DIAMOND, amount: 2, chance: 100 }
'2': { material: EMERALD, amount: 1, chance: 50 }Custom reward commands
rewards: is a list of console commands run when the contract is completed — use %player% for the player. display-rewards: is the human-readable text players see. Money is just the eco give command; you can add any command (ranks, kits, crates…).
rewards:
- "eco give %player% 500"
- "lp user %player% addgroup vip"
- "crates give %player% legendary 1"
display-rewards:
- "500 money"
- "VIP Rank"
- "1x Legendary Crate"command | display text), right-click to clear them all.Version history
Every release and what changed in it.
- ✨Create market orders from the menu: /contract market > Create an order > pick the item, set the amount and payment, publish. No commands needed.
- ✨The item list has every item in the game with a search, and hides items that cannot be obtained in survival (market.picker-hidden).
- ✨Custom items (Nexo, ItemsAdder, MMOItems...): while creating an order, click the item in your own inventory to ask for that exact item.
- ✨Right-click an order in /contract market to preview the item exactly as it is, with its name, lore, enchantments and everything its plugin adds.
- ✨The preview lists what the tooltip may hide (enchantments, durability, custom model data, source plugin) and lets you deliver from there.
- ✨In the order creator, click the chosen item to preview it the same way before publishing the order.
- 🔧Items show their real name in the market, deliveries, shop and rewards: the custom name first, then the item name used by Nexo and ItemsAdder.
- 🔧Items without a custom name show a readable name, like "Iron Ingot" instead of IRON_INGOT.
- 🐛Items from Nexo and newer ItemsAdder showed as their base material (for example PAPER) in the market: only the anvil-style name was checked.
- 🐛%contractrpg_active_N_objective% showed "Missing message: translation-keys..." for objectives not in the translation list. It now shows a readable name.
- 🐛On 1.21.1 and 1.21.2, biome visit contracts never progressed: the biome was always read as empty because of an API change in 1.21.3.
- 🔧Drop the jar in and restart. The new config and language keys are added to your files automatically.
- ✨Pages in the contract menus. A category only had room for 28 contracts, and everything past that — accepted, offered or locked — was silently cut off. The list is now split into pages with arrows at t
- 🐛The contract offer did not follow the player's level. Dailies and weeklies are frozen the first time the menu is opened, but the offer was never checked again after a level change: a player who went f
- 🐛SQLite: the shop purchase history was not being loaded since 2.3.0. It was saved but never read back, so on every login it came back empty — one-time shop items could be bought again and cooldowns wer
- 🐛On Minecraft 1.21.1 and 1.21.2, completing a contract failed with an IncompatibleClassChangeError and stopped right there: the player got the XP and the points but no money and no items, and the contr
- 🐛Contracts that got stuck at 100% because of the above are paid out automatically. They stayed active with full progress, and in that state they could never be completed again — the progress had alread
- 🔧A wrong sound or particle name in config.yml now just skips the effect and says so once in the console, instead of silently doing nothing.
- 🐛Hex colours and gradients in the language files were turned into the nearest of Minecraft's 16 basic colours before being sent. A <#8A2BE2> or a <gradient:...> in a message, the prefix, a menu or the
- ✨/contract global start <id>: start any global contract from global.yml right away (the ids tab-complete). The one currently running ends without rewards.
- ✨/contract global stop: end the current global contract without rewards and keep them stopped — even after a restart — until you start one again.
- ✨global-contracts.automatic in config.yml. true (the default) keeps today's behaviour: global contracts start and rotate on their own. false makes them manual: none runs until you start one, and after
- 🔧/contract global next now announces the new global contract to the whole server. Before, the boss bar simply switched to another contract with no message.
- 🐛One message of the contract editor used by add-ons ("that is not a number") was hardcoded in Spanish. It now comes from the language file.
- ✨FancyNpcs support for NPC deliveries. Put the NPC's name — the one you gave it with /npc create — in delivery-fancynpc, and right-clicking it does exactly what the Citizens delivery NPC does: it takes
- 🔧Citizens and FancyNpcs share one delivery logic, so they cannot behave differently: both apply worlds, anti-farm-ms and party-shared, both only take the item when something accepts it, and both confir
- 🐛A cancelled click on the delivery NPC still handed the item over. If another plugin cancelled the click on the Citizens NPC (a cooldown, a protected area), the delivery went through anyway. It no long
- 🐛MMOCore servers: every contract with a level-requirement above 1 was impossible to take. Contract EXP goes to MMOCore, so the plugin's internal level stayed at 1 forever — and the offer list, the lock
- 🐛/contract reload did not reload your contracts. It reloaded config, languages and shop, and silently ignored daily.yml, weekly.yml, special.yml and global.yml — a hand-edited contract needed a full se
- 🐛Mining contracts could be finished with a stack of stone: place a block, break it, repeat. Blocks a player placed are now marked and do not count when broken, and the mark is stored in the chunk so a
- 🐛Spawner farms completed hunting contracts on their own. Mobs that came out of a spawner no longer count as kills (spawn eggs optional).
- 🐛worlds, anti-farm-ms and party-shared did nothing on mining, hunting, fishing, crafting, MythicMobs and NPC deliveries. Those types walked their own code path and never reached the checks, even though
- 🐛Actions cancelled by another plugin still counted. Mining, placing, fishing or enchanting inside a protected WorldGuard region moved the counter even though nothing happened in the world, which turned
- 🐛Weekly contracts only reset if you happened to log in on a Monday. Anyone who missed that day carried their finished weeklies for the entire following week, unable to redo them and with no warning. Th
- 🐛A crash threw away the whole session. Data was written only when a player logged out and on a clean shutdown, so level, points and contract progress went back to whatever they were at login. There is
- 🐛SQLite: one connection was shared between async threads with no synchronisation, there was no reconnect if it ever dropped, and it was never closed on shutdown — which on Windows left the file locked
- 🐛Riding contracts counted teleports: a /home or a portal while mounted added the whole distance at once. Anything above anti-farm.max-ride-blocks-per-second is now treated as a teleport and ignored.
- 🐛The marketplace could take the armour off your back. Fulfilling an order counted and removed items from the armour and off-hand slots, so an order for diamond chestplates took the one you were wearing
- 🐛NPC deliveries fed sub-objectives and the global contract for free. Right-clicking the delivery NPC advanced multi-objective sub-objectives and the server-wide global contract before checking whether
- 🐛Two GUI lines were hardcoded in Spanish ("Progreso", "Recompensas") and showed up untranslated on every server. They are now in all four language files, along with four console messages that were also
- ✨Folia support. Every task now goes through the regionised schedulers, so the plugin loads and runs on Folia instead of failing at startup.
- ✨Anti-farming section in config.yml: player-placed blocks, spawner mobs, spawn-egg mobs, an exemption list and the riding cap. All of it can be turned off.
- 🔧Structure contracts no longer lag the server. The structure search — one of the most expensive calls in the API, able to generate chunks — ran every 5 seconds for every player with one of those contra
- 🔧The leaderboard no longer reads the whole table. It used to load every player row into memory and sort in Java on each refresh; it now asks the database only for the rows it needs, with indexes to mat
- 🔧Four per-player maps were never cleared on disconnect. The anti-farm one grew by one entry per player and per contract, indefinitely.
- 🔧The PlaceholderAPI expansion is now unregistered on shutdown, so reloading the plugin no longer leaves a stale one serving data from a dead instance.
- 🔧The wiki now documents worlds, anti-farm-ms, party-shared and party-split-reward — the per-contract options that were in the editor but written down nowhere — plus the new anti-farm section and the Fo
- 🐛Contracts asking for damage from a specific mob never advanced. The damage source was not passed through, and a projectile reported itself rather than its shooter — when a skeleton shoots you, the dam
- 🐛Damaging a mob with a bow did not count towards DAMAGE_DEALT contracts. The same bug in reverse: the plugin saw the arrow as the attacker instead of the player.
- 🐛An accepted contract vanished from the list after a reroll. It was never deleted — it stayed active and kept counting — but rerolling regenerates the offers, and offers leave out what you already hold
- 🐛Seven mission types could never be completed if the contract had an objective written in: PLAYTIME, EXPLORE, XP_GAIN, KILL_PLAYER, RIDE, DAMAGE_TAKEN and TRADING. They were compared against a fixed va
- ✨RIDE now accepts the mount: "ride 1000 blocks on a horse" is finally something you can ask for, and a pig no longer counts toward it.
- ✨DAMAGE_TAKEN accepts the attacker, so "survive 200 damage from skeletons" works. Falls and fire count as ANY.
- ✨TRADING accepts who you trade with, so "trade 10 times with villagers" works.
- 🔧The wiki now documents what goes in mission-objective for all 22 mission types, and ships a copy-paste example of every single one instead of only seven.
- 🐛Riding contracts never progressed on animals. Horses, pigs and striders don't fire the event the plugin was listening to — only boats and minecarts do. Distance on a mount is now measured directly.
- 🐛Multi-objective contracts could not be finished if one of their goals was moving, riding or visiting a structure. Those three checks only looked at the contract's main type, so a sub-objective of that
- 🐛NPC deliveries counted only toward their own contract: they were invisible to global contracts and to multi-objective sub-objectives.
- 🐛MythicMob kills didn't advance multi-objective sub-objectives either.
- 🐛Crafting missions could be completed without spending materials: clicking the result slot counted progress even when the craft never happened (full inventory, or a different item on the cursor).
- 🐛Crafting and trading counted 1 on a shift-click, no matter how many items were actually made or traded.
- 🐛Villager trades that never went through still added mission progress.
- 🔧command-aliases now explains itself: it names the plugin already holding an alias, and reports when the server won't refresh its command tree.
- ✨Tab completion for /contract, showing only the commands each player can actually use
- ✨Custom command aliases in command-aliases: set /missions, or whatever name you like
- ✨The marketplace accepts custom items: /contract market create hand
- ✨Rarity odds can be written as percentages with rarity-use-weight: false
- 🐛The marketplace silently discarded any item with a custom name, an enchantment or damage
- 🔧Improved — On startup, the console prints the real percentage of each rarity
- 🐛Changing offered-amount or selectable-amount had no effect on players who had already opened the mission menu
- 🔧Missions above your level are now shown greyed out with the level they need, instead of just not being there
- ✨show-locked-missions in config.yml — you decide whether locked missions are shown or hidden
- 🐛Buying from the shop crashed when the item had a coloured name
- 🐛The shop editor ignored your language setting: its menus were hardcoded. All 36 texts now come from the language files, translated to EN/ES/FR/ZH.
- 🐛Duplicate key in lang/es.yml: it threw a "duplicate keys found" warning on startup and made the shop editor's invalid-number message show without the plugin prefix.
- 🔧The 58 ready-made contracts now ship in English. They are examples - rename them to your own language from /contract editor.
- 🔧config.yml, shop.yml, global.yml, codes.yml and the contract files are now documented in English, along with the console messages.
- 🔧Language files repair themselves: a file with duplicated keys is rewritten clean on startup, keeping your texts, edits and comments.
- ✨Party contracts: form a group with /contract party and share progress and/or rewards (the admin decides per contract).
- ✨Player marketplace: post an order with /contract market ("pay X for Y items"); others fulfill it and get paid (needs Vault).
- ✨Multi-objective contracts: a single contract can require several goals at once — all must be completed.
- ✨Profile / stats GUI: /contract profile shows level, points, total completed, daily streak, favorite type and a breakdown by mission type.
- ✨Reward boosters: /contract booster <mult> <seconds> temporarily multiplies money, points and EXP from contracts.
- ✨Redeemable codes: /contract redeem <code> for events or Discord rewards (codes.yml).
- ✨Community suggestions: players use /contract suggest; admins review them with /contract suggestions.
- ✨Admin analytics: /contract analytics — a GUI with completion counts per contract to balance your economy.
- ✨Contracts by world/region: limit a contract to specific worlds (e.g. "kill 10 blazes in the Nether").
- ✨Anti-farm: a per-contract minimum time between progress to stop macro/afk abuse.
- ✨Smart reminders: on join, players are told about contracts that are almost complete.
- ✨Completion feedback: configurable sound + particles + title when a contract is completed.
- ✨New objective types: damage dealt, damage taken, riding/mounting distance, playtime, and visiting structures (village, fortress...).
- 🔧Every contract-configurable feature above is also in the in-game mission editor, with its own explanation.
- 🔧Language files now auto-update on new versions, just like the config — new messages appear without losing your edits.
- ✨Classic & color codes (&e, &6, &l, &#ff8800…) are now supported, alongside <minimessage> tags.
- 🔧You can mix & codes and <minimessage> in the same line — both work everywhere (rewards, titles, menus, boss bar).
- ✨Global contracts now rest between one another, so they stay rare and special.
- 🔧The gap is configurable (a random wait between two values in minutes).
- 🔧A server-wide announcement when a fresh global contract appears.
No notes for this version.
Discussion
Comment and share your experience on each plugin version.
No comments on this version yet — be the first!
No comments on this version yet — be the first!
No comments on this version yet — be the first!
No comments on this version yet — be the first!
No comments on this version yet — be the first!
No comments on this version yet — be the first!
No comments on this version yet — be the first!
No comments on this version yet — be the first!
No comments on this version yet — be the first!
No comments on this version yet — be the first!
No comments on this version yet — be the first!
No comments on this version yet — be the first!
No comments on this version yet — be the first!
No comments on this version yet — be the first!
No comments on this version yet — be the first!
No comments on this version yet — be the first!
No comments on this version yet — be the first!
No comments on this version yet — be the first!
Player reviews
What server owners think of this plugin.
Thank you for creating this amazing plugin. It works perfectly on my server. The support team is incredibly enthusiastic and quick to address and fix any issues.
buen plugin!