Task System
Task System
Section titled “Task System”The Task System is Journey’s core framework for creating quests, objectives, and player activities. Tasks can range from simple single-objective quests to complex multi-stage adventures with different progression modes and conditional requirements.
Overview
Section titled “Overview”Tasks in Journey consist of:
- Subtasks: Individual objectives that players complete
- Events: Triggers that advance subtask progress (28 event types)
- Progression Types: How subtasks are presented (LINEAR, SEQUENTIAL, RANDOMIZED)
- Filters: MoLang conditions to validate events
- Rewards: What players receive upon completion
- Repetition: Whether and how tasks can repeat
Basic Task Structure
Section titled “Basic Task Structure”Every task follows this structure:
{ "name": "<gold>Display Name", "description": [ "<gray>First line of description", "<yellow>Additional details" ], "sequential": "linear", "subtask_count": 1, "start_requirement": "", "icon": { "item_id": "minecraft:compass" }, "repeat_type": "NONE", "repeat_interval": 0, "party_shared": false, "rewards": [], "tasks": []}Key Fields:
name- Display name (supports MiniMessage formatting)description- Array of description linessequential- Progression type:"linear","sequential", or"randomized"(also acceptstrue/falsefor backward compatibility)subtask_count- For randomized: how many subtasks to selectstart_requirement- MoLang condition to start (empty = always available)icon- Item icon for UI displayrepeat_type-"NONE","DAILY","WEEKLY", or"CUSTOM"repeat_interval- Days between repeats (for CUSTOM type)party_shared- Default sharing for all subtasks (default:false)rewards- Task completion rewardstasks- Array of subtasks
Progression Types
Section titled “Progression Types”Journey supports three sequential types that control how subtasks are presented to players.
LINEAR ("sequential": "linear")
Section titled “LINEAR ("sequential": "linear")”All subtasks are active simultaneously. Players can complete them in any order.
Use Cases:
- Collection challenges
- Exploration objectives
- Parallel goals
Example:
{ "name": "<gold>Pokémon Variety Challenge", "sequential": "linear", "tasks": [ { "id": "catch_fire", "name": "Catch Fire Pokémon", "event": "POKEMON_CAUGHT", "filter": "q.pokemon.species.identifier == 'cobblemon:charmander'", "target": 3 }, { "id": "catch_water", "name": "Catch Water Pokémon", "event": "POKEMON_CAUGHT", "filter": "q.pokemon.species.identifier == 'cobblemon:squirtle'", "target": 3 }, { "id": "catch_grass", "name": "Catch Grass Pokémon", "event": "POKEMON_CAUGHT", "filter": "q.pokemon.species.identifier == 'cobblemon:bulbasaur'", "target": 3 } ]}SEQUENTIAL ("sequential": "sequential")
Section titled “SEQUENTIAL ("sequential": "sequential")”Subtasks must be completed in order. Only the current subtask is active.
Use Cases:
- Story progression
- Tutorial chains
- Ordered quest steps
Example:
{ "name": "<gold>Gym Challenge", "sequential": "sequential", "tasks": [ { "id": "defeat_trainers", "name": "Defeat Gym Trainers", "event": "BATTLE_VICTORY", "filter": "1.0", "target": 3 }, { "id": "talk_to_leader", "name": "Challenge Gym Leader", "event": "ENTITY_INTERACT", "filter": "q.entity.uuid == 'gym-leader-uuid'", "target": 1 }, { "id": "defeat_leader", "name": "Defeat Gym Leader", "event": "BATTLE_VICTORY", "filter": "1.0", "target": 1 } ]}RANDOMIZED ("sequential": "randomized")
Section titled “RANDOMIZED ("sequential": "randomized")”A random subset of subtasks are selected from the available pool. Requires subtask_count parameter.
Use Cases:
- Daily quests with variety
- Random challenges
- Replayable content
Example:
{ "name": "<gold>Daily Challenge", "sequential": "randomized", "subtask_count": 3, "tasks": [ { "id": "option1", "name": "Catch Water Pokémon", "event": "POKEMON_CAUGHT", "filter": "q.pokemon.species.identifier == 'cobblemon:magikarp'", "target": 5 }, { "id": "option2", "name": "Win Battles", "event": "BATTLE_VICTORY", "filter": "q.battle.is_wild", "target": 10 }, { "id": "option3", "name": "Explore Zones", "event": "ENTER_ZONE", "filter": "1.0", "target": 3 }, { "id": "option4", "name": "Evolve Pokémon", "event": "POKEMON_EVOLVE", "filter": "1.0", "target": 1 }, { "id": "option5", "name": "Harvest Berries", "event": "BERRY_HARVESTED", "filter": "1.0", "target": 20 } ]}Note: Exactly subtask_count (3) subtasks will be randomly selected from the 5 options.
Subtask Structure
Section titled “Subtask Structure”Subtasks are the individual objectives within a task:
{ "id": "unique_subtask_id", "name": "<yellow>Display Name", "description": "<gray>What the player needs to do", "event": "EVENT_TYPE", "event_data": {}, "filter": "q.condition == value", "target": 10, "location": { "x": 100, "y": 64, "z": 200 }, "time_limit": "30m", "optional": false, "party_shared": null, "rewards": []}Key Fields:
id- Unique identifier within the taskname- Display name for this objectivedescription- Objective detailsevent- One of 28 Journey event types (see events.md)event_data- Optional event-specific configurationfilter- MoLang expression to validate eventstarget- How many times the event must occurlocation- Optional waypoint marker for playerstime_limit- Optional time constraint (format:30s,5m,1h)optional- If true, not required for task completionparty_shared- Override task-level sharing (default: inherits from task)rewards- Rewards given when this subtask completes
Reward Types
Section titled “Reward Types”Journey supports four reward types:
Currency Reward
Section titled “Currency Reward”Requires Impactor economy integration.
{ "type": "currency", "data": { "currency": "impactor:pokedollars", "amount": 500 }}Command Reward
Section titled “Command Reward”Executes a server command. Use {player} placeholder for player name.
{ "type": "command", "data": { "command": "give {player} minecraft:diamond 5" }}Multiple Commands:
{ "type": "command", "data": { "command": "give {player} cobblemon:rare_candy 3" }},{ "type": "command", "data": { "command": "tellraw {player} {\"text\":\"Reward claimed!\",\"color\":\"green\"}" }}Script Reward
Section titled “Script Reward”Executes MoLang scripts. Access to all player MoLang functions.
{ "type": "script", "data": { "scripts": [ "q.player.add_flag('quest_complete');", "q.player.tell_minimessage('<gold>Quest completed!');" ] }}Common Script Patterns:
// Set flags"scripts": ["q.player.add_flag('gym_badge_boulder');"]
// Give levelable XP"scripts": ["q.player.progress_levelable('trainer_rank', 100);"]
// Launch timeline"scripts": ["q.player.launch_timeline('victory_cutscene');"]
// Multiple actions"scripts": [ "q.player.add_flag('champion_defeated');", "q.player.progress_levelable('story_progress', 1);", "q.player.tell_minimessage('<gold>You are the Champion!');"]Timeline Reward
Section titled “Timeline Reward”Launches a timeline sequence for the player.
{ "type": "timeline", "data": { "timeline": "namespace:timeline_id" }}Complete Task Examples
Section titled “Complete Task Examples”Example 1: Simple Catch Quest (LINEAR)
Section titled “Example 1: Simple Catch Quest (LINEAR)”File: config/journey/tasks/catch_starter.json
{ "name": "<gold>Catch Your First Pokémon", "description": [ "<gray>Catch any Pokémon to begin your journey!" ], "sequential": "linear", "icon": { "item_id": "cobblemon:poke_ball" }, "repeat_type": "NONE", "repeat_interval": 0, "rewards": [ { "type": "currency", "data": { "currency": "impactor:pokedollars", "amount": 100 } } ], "tasks": [ { "id": "catch_first", "name": "Catch a Pokémon", "description": "Catch any wild Pokémon", "event": "POKEMON_CAUGHT", "filter": "1.0", "target": 1, "rewards": [] } ]}Example 2: Multi-Stage Quest (SEQUENTIAL)
Section titled “Example 2: Multi-Stage Quest (SEQUENTIAL)”File: config/journey/tasks/gym_challenge.json
{ "name": "<blue>First Gym Challenge", "description": [ "<gray>Defeat the trainers and challenge", "<gray>the gym leader to earn your badge!" ], "sequential": "sequential", "start_requirement": "q.player.has_flag('tutorial_complete')", "icon": { "item_id": "cobblemon:gym_badge" }, "repeat_type": "NONE", "rewards": [ { "type": "script", "data": { "scripts": [ "q.player.add_flag('gym_badge_boulder');", "q.player.tell_minimessage('<gold>You earned the Boulder Badge!');" ] } } ], "tasks": [ { "id": "enter_gym", "name": "Enter the Gym", "event": "ENTER_ZONE", "filter": "q.zone.uuid == 'pewter-gym-uuid'", "target": 1, "location": { "x": 100, "y": 64, "z": 200 }, "rewards": [] }, { "id": "defeat_trainers", "name": "Defeat Trainers", "description": "Defeat 2 gym trainers", "event": "BATTLE_VICTORY", "filter": "!q.battle.is_wild", "target": 2, "rewards": [ { "type": "currency", "data": { "currency": "impactor:pokedollars", "amount": 200 } } ] }, { "id": "talk_to_leader", "name": "Challenge the Leader", "event": "ENTITY_INTERACT", "filter": "q.entity.uuid == 'brock-uuid'", "target": 1, "rewards": [] }, { "id": "defeat_leader", "name": "Defeat Brock", "description": "Win the gym battle", "event": "BATTLE_VICTORY", "filter": "!q.battle.is_wild", "target": 1, "rewards": [ { "type": "currency", "data": { "currency": "impactor:pokedollars", "amount": 500 } } ] } ]}Example 3: Daily Quest (RANDOMIZED)
Section titled “Example 3: Daily Quest (RANDOMIZED)”File: config/journey/tasks/daily_challenge.json
{ "name": "<gold>Daily Challenge", "description": [ "<gray>Complete 3 random objectives", "<gray>for bonus rewards!" ], "sequential": "randomized", "subtask_count": 3, "icon": { "item_id": "minecraft:clock" }, "repeat_type": "DAILY", "repeat_interval": 1, "rewards": [ { "type": "currency", "data": { "currency": "impactor:pokedollars", "amount": 1000 } } ], "tasks": [ { "id": "catch_pokemon", "name": "Catch Pokémon", "event": "POKEMON_CAUGHT", "filter": "1.0", "target": 5, "rewards": [] }, { "id": "win_battles", "name": "Win Battles", "event": "BATTLE_VICTORY", "filter": "1.0", "target": 10, "rewards": [] }, { "id": "harvest_apricorns", "name": "Harvest Apricorns", "event": "APRICORN_HARVESTED", "filter": "1.0", "target": 20, "rewards": [] }, { "id": "evolve_pokemon", "name": "Evolve Pokémon", "event": "POKEMON_EVOLVE", "filter": "1.0", "target": 1, "rewards": [] }, { "id": "explore_zones", "name": "Explore Zones", "event": "ENTER_ZONE", "filter": "1.0", "target": 3, "rewards": [] } ]}Note: 3 of these 5 objectives will be randomly selected each day.
Task Requirements
Section titled “Task Requirements”Control when tasks become available using start_requirement:
No Requirements
Section titled “No Requirements”{ "start_requirement": ""}Flag-Based
Section titled “Flag-Based”{ "start_requirement": "q.player.has_flag('tutorial_complete')"}Task Completion
Section titled “Task Completion”{ "start_requirement": "q.player.has_completed_task('journey:previous_quest')"}Multiple Conditions
Section titled “Multiple Conditions”{ "start_requirement": "q.player.has_flag('gym_badge_1') && q.player.has_flag('gym_badge_2') && q.player.has_flag('gym_badge_3')"}Levelable-Based
Section titled “Levelable-Based”{ "start_requirement": "q.player.levelable_level('trainer_rank') >= 25.0"}Repeat Configuration
Section titled “Repeat Configuration”No Repeat (One-Time Quest)
Section titled “No Repeat (One-Time Quest)”{ "repeat_type": "NONE", "repeat_interval": 0}Daily Reset
Section titled “Daily Reset”{ "repeat_type": "DAILY", "repeat_interval": 1}Weekly Reset
Section titled “Weekly Reset”{ "repeat_type": "WEEKLY", "repeat_interval": 1}Custom Interval
Section titled “Custom Interval”{ "repeat_type": "CUSTOM", "repeat_interval": 3}Resets every 3 days.
Event Filters
Section titled “Event Filters”Filters use MoLang to validate whether an event should count toward progress.
Simple Filters
Section titled “Simple Filters”// Always accepts"filter": "1.0"
// Always rejects"filter": "0.0"Event Data Filters
Section titled “Event Data Filters”// Pokémon species"filter": "q.pokemon.species.identifier == 'cobblemon:pikachu'"
// Zone UUID"filter": "q.zone.uuid == 'zone-uuid-here'"
// Entity UUID"filter": "q.entity.uuid == 'npc-uuid-here'"
// Item ID"filter": "q.item.id == 'cobblemon:rare_candy'"Method Filters
Section titled “Method Filters”// Starter check"filter": "q.pokemon.is_starter"
// Wild battle check"filter": "q.battle.is_wild"
// Inverted"filter": "!q.battle.is_wild"Player Function Filters
Section titled “Player Function Filters”// Zone restriction"filter": "q.player.is_in_zone('zone-uuid')"
// Task completion check"filter": "q.player.has_completed_task('other:quest')"
// Flag check"filter": "q.player.has_flag('permission_granted')"Compound Filters
Section titled “Compound Filters”// AND logic"filter": "q.pokemon.is_starter && q.pokemon.level >= 16.0"
// OR logic"filter": "q.pokemon.species.identifier == 'cobblemon:charmander' || q.pokemon.species.identifier == 'cobblemon:charmeleon'"
// Complex combination"filter": "q.entity.uuid == 'npc-uuid' && q.player.has_completed_task('previous:quest') && !q.player.has_flag('already_done')"Best Practices
Section titled “Best Practices”Task Design
Section titled “Task Design”✅ DO:
- Use clear, descriptive names
- Provide helpful descriptions
- Set reasonable target values
- Test filters before deployment
- Use waypoint locations for guidance
❌ DON’T:
- Create tasks with 20+ subtasks
- Use vague objective descriptions
- Set impossibly high targets
- Forget to test filter logic
- Chain too many sequential requirements
Filter Design
Section titled “Filter Design”✅ DO:
- Start with simple filters (
1.0) - Add complexity incrementally
- Test each condition separately
- Use player functions for context
- Document complex logic
❌ DON’T:
- Create overly complex filters
- Assume all query paths exist
- Forget the
q.prefix - Use untested Cobblemon data paths
Reward Balance
Section titled “Reward Balance”✅ DO:
- Scale rewards to difficulty
- Provide milestone rewards (subtasks)
- Use variety (currency + items + flags)
- Test reward economy
❌ DON’T:
- Over-reward simple tasks
- Forget subtask rewards
- Create inflation with repeatable quests
- Give rewards without testing
Task Registration
Section titled “Task Registration”Tasks are automatically registered from JSON files in config/journey/tasks/.
File Structure
Section titled “File Structure”config/journey/tasks/├── starter_quests/│ ├── choose_starter.json│ └── first_catch.json├── gym_challenges/│ ├── pewter_gym.json│ └── cerulean_gym.json└── daily_quests/ └── daily_challenge.jsonFile Naming
Section titled “File Naming”Tasks are identified by filename (without .json):
- File:
pewter_gym.json - Task ID:
journey:pewter_gym
Use namespaces for organization:
- File:
gyms/pewter.json - Task ID:
journey:gyms/pewter
Commands
Section titled “Commands”Start a Task
Section titled “Start a Task”Give a task to a player:
/journey starttask <player> <task_id>Example:
/journey starttask @p journey:tutorial_questTrack a Task
Section titled “Track a Task”Show task progress in the player’s UI:
/journey tracktask <player> <task_id>Complete Task
Section titled “Complete Task”Force complete a task:
/journey completetask <player> <task_id>Remove Task
Section titled “Remove Task”Remove a task from a player (doesn’t mark as completed):
/journey removetask <player> <task_id>Remove Completed Task
Section titled “Remove Completed Task”Remove a task from the completed tasks list:
/journey removecompletedtask <player>Progress Subtask
Section titled “Progress Subtask”Manually progress a subtask:
/journey progresssubtask <player> <task_id> <subtask_id> <amount>Example:
/journey progresssubtask @p journey:gather_items gather_wood 5Complete Subtask
Section titled “Complete Subtask”Force complete a specific subtask:
/journey completesubtask <player> <task_id> <subtask_id>Integration with Other Systems
Section titled “Integration with Other Systems”With Flags
Section titled “With Flags”{ "start_requirement": "q.player.has_flag('unlock_post_game')", "rewards": [ { "type": "script", "data": { "scripts": ["q.player.add_flag('champion_defeated');"] } } ]}With Levelables
Section titled “With Levelables”{ "start_requirement": "q.player.levelable_level('combat') >= 50.0", "rewards": [ { "type": "script", "data": { "scripts": ["q.player.progress_levelable('combat', 500);"] } } ]}With Zones
Section titled “With Zones”{ "tasks": [ { "id": "explore_zone", "event": "ENTER_ZONE", "filter": "q.zone.uuid == 'secret-area-uuid' && q.player.has_flag('map_unlocked')", "target": 1 } ]}With Task Items
Section titled “With Task Items”Tasks can be embedded in items (see task-items.md):
/journey taskitem give @p journey:quest_task minecraft:paperWith Party System
Section titled “With Party System”Enable party sharing for tasks so party members contribute to shared progress:
{ "name": "<gold>Party Dungeon Quest", "description": ["<gray>Work together to clear the dungeon!"], "sequential": "linear", "party_shared": true, "tasks": [ { "id": "defeat_bosses", "name": "Defeat Dungeon Bosses", "event": "BATTLE_VICTORY", "filter": "q.battle.is_boss", "target": 5 }, { "id": "find_treasure", "name": "Find Hidden Treasure", "event": "BLOCK_BREAK", "filter": "q.block.id == 'minecraft:chest'", "target": 3, "party_shared": false } ]}Party Sharing Behavior:
party_sharedat task level sets the default for all subtasksparty_sharedat subtask level overrides the task default- When
true, progress from any party member counts for all members - Requires Party System to be enabled
- Works cross-server with NATS configuration
Example Use Cases:
- ✅ Shared: Kill boss monsters together (all kills count)
- ✅ Shared: Collect resources as a group (all items count)
- ❌ Not Shared: Talk to NPC (each member talks separately)
- ❌ Not Shared: Enter specific zone (each member enters separately)
Journey’s task system provides a flexible, event-driven framework for creating engaging player objectives. All examples in this documentation are verified against working production configurations.