Skip to content

Timeline System

Timelines let you schedule actions to happen at precise moments — like a script for a play. You define “at tick 0, show a message; at tick 40, play a sound; at tick 60, give the player a reward” and Journey runs it all automatically.

They’re perfect for reward ceremonies, NPC dialogue sequences, and anything that needs precise timing.

A timeline is a map of tick numbers to actions. When launched, Journey counts through the ticks and fires each action at the right moment.

Key concept: 20 ticks = 1 second.

{
"timeline": {
"0": {
"type": "molang",
"script": "q.player.tell_minimessage('<gold>The adventure begins!')"
},
"40": {
"type": "command",
"command": "playsound minecraft:entity.experience_orb.pickup player {player}"
},
"60": {
"type": "molang",
"script": "q.player.add_flag('intro_seen')"
}
}
}

This timeline:

  • Tick 0 (immediately): Sends a gold message
  • Tick 40 (2 seconds later): Plays a sound
  • Tick 60 (3 seconds later): Sets a flag

TicksTime
150ms
50.25 seconds
100.5 seconds
201 second
402 seconds
603 seconds
1005 seconds
20010 seconds
12001 minute

Execute Molang scripts with full access to all player functions:

{
"type": "molang",
"script": "q.player.tell_minimessage('<gold>Hello world!')"
}

You can use any q.player.* function here — send messages, set flags, give items, launch other timelines, apply buffs, and more.

More examples:

{"type": "molang", "script": "q.player.add_flag('cutscene_complete')"}
{"type": "molang", "script": "q.player.apply_buff('speed_boost', 1200, 1)"}
{"type": "molang", "script": "q.player.tell_minimessage('<red>BOOM!')"}
{"type": "molang", "script": "q.player.remove_item('minecraft:tnt', 1)"}
{"type": "molang", "script": "q.player.progress_levelable('story_progress', 50)"}

Execute server commands. Use {player} as a placeholder for the player’s name:

{
"type": "command",
"command": "give {player} minecraft:diamond 5"
}

Commands run as the server console with full permissions. You can use selectors (@a, @p, etc.).

More examples:

{"type": "command", "command": "playsound minecraft:entity.player.levelup player {player}"}
{"type": "command", "command": "particle minecraft:explosion_emitter ~ ~1 ~ 0 0 0 0 1"}
{"type": "command", "command": "title {player} title {\"text\":\"Victory!\",\"color\":\"gold\"}"}

When you need several things to happen simultaneously, use an array:

{
"timeline": {
"55": [
{
"type": "command",
"command": "playsound minecraft:entity.generic.explode block {player} ~ ~ ~ 0.5 1"
},
{
"type": "molang",
"script": "q.player.tell_minimessage('<red>BOOM!')"
},
{
"type": "command",
"command": "particle minecraft:explosion_emitter ~ ~1 ~ 0 0 0 0 1"
},
{
"type": "molang",
"script": "q.player.remove_item('minecraft:tnt', 1)"
}
]
}
}

All four actions fire at tick 55 (2.75 seconds).


A professor talks to the player over several seconds:

File: config/journey/timelines/professor_intro.json

{
"timeline": {
"0": {
"type": "molang",
"script": "q.player.tell_minimessage('<gray>[<green>Professor Willow<gray>] <white>Welcome, young trainer!')"
},
"40": {
"type": "molang",
"script": "q.player.tell_minimessage('<gray>[<green>Professor Willow<gray>] <white>I see you have chosen your first Pokemon.')"
},
"80": {
"type": "molang",
"script": "q.player.tell_minimessage('<gray>[<green>Professor Willow<gray>] <white>Your journey starts now. Good luck!')"
},
"100": {
"type": "molang",
"script": "q.player.add_flag('professor_intro_complete')"
}
}
}

Pacing: 2 seconds between each dialogue line gives players time to read.

A dramatic reward presentation with sound and effects:

File: config/journey/timelines/gym_victory.json

{
"timeline": {
"0": {
"type": "molang",
"script": "q.player.tell_minimessage('<gold><bold>CONGRATULATIONS!')"
},
"20": {
"type": "command",
"command": "playsound minecraft:entity.player.levelup player {player}"
},
"40": [
{
"type": "command",
"command": "give {player} minecraft:diamond 5"
},
{
"type": "molang",
"script": "q.player.tell_minimessage('<green>You received <bold>5 Diamonds<reset><green>!')"
},
{
"type": "command",
"command": "particle minecraft:totem_of_undying ~ ~1 ~ 0.5 0.5 0.5 0.1 20"
}
],
"60": {
"type": "molang",
"script": "q.player.add_flag('gym_badge_boulder')"
}
}
}

Use Molang ternary expressions for branching within a timeline:

File: config/journey/timelines/secret_door.json

{
"timeline": {
"0": {
"type": "molang",
"script": "q.player.tell_minimessage('<gray>Checking access...')"
},
"40": {
"type": "molang",
"script": "q.player.has_flag('secret_key') ? q.player.tell_minimessage('<green>The door opens!') : q.player.tell_minimessage('<red>The door is locked.')"
},
"60": {
"type": "molang",
"script": "q.player.has_flag('secret_key') ? q.player.execute_command('tp {player} 100 70 200') : 0.0"
}
}
}

A real timeline from a production server — Professor Willow lights TNT:

File: config/journey/timelines/tnt_scene.json

{
"timeline": {
"5": {
"type": "molang",
"script": "q.player.tell_minimessage('<gray>[<green>Professor Willow<gray>] <white>Agh... The TNT wont ignite!')"
},
"35": {
"type": "molang",
"script": "q.player.tell_minimessage('<gray>[<green>Professor Willow<gray>] <white>Ah! Got it')"
},
"40": {
"type": "command",
"command": "playsound minecraft:entity.tnt.primed block {player} -584.00 80.11 -20.67 0.5 1"
},
"55": [
{
"type": "command",
"command": "playsound minecraft:entity.generic.explode block {player} -584.00 80.11 -20.67 0.5 1"
},
{
"type": "molang",
"script": "q.player.tell_minimessage('<red>BOOM!')"
},
{
"type": "molang",
"script": "q.player.remove_item('minecraft:tnt', 1)"
},
{
"type": "command",
"command": "particle minecraft:explosion_emitter -584.00 80.14 -20.62 0 0 0 0 1 normal"
},
{
"type": "molang",
"script": "q.player.add_flag('tnt_exploded')"
}
]
}
}

{
"rewards": [
{
"type": "timeline",
"data": {
"timeline": "journey:gym_victory"
}
}
]
}
{
"level": 10,
"required_experience": 1000,
"rewards": [
{
"type": "timeline",
"data": {
"timeline": "journey:level_milestone"
}
}
]
}
q.player.launch_timeline('journey:celebration')

This works in task script rewards, zone entry scripts, timeline actions, and anywhere else Molang runs.


Timeline files go in config/journey/timelines/:

config/journey/timelines/
├── professor_intro.json → journey:professor_intro
├── gym_victory.json → journey:gym_victory
├── tnt_scene.json → journey:tnt_scene
└── level_milestone.json → journey:level_milestone

The resource ID is journey:<filename_without_extension>.


  • 2-3 seconds (40-60 ticks) between dialogue lines gives players time to read
  • Sync sound and visuals — put them at the same tick in an array
  • Test in-game — server lag can affect timing slightly
  • Use Molang for player-specific things (messages, flags, items)
  • Use commands for world effects (particles, sounds, title text)
  • Batch simultaneous actions in arrays for synchronized effects
  • Use descriptive filenames: quest_complete_celebration.json not test2.json
  • Keep a planning doc with tick breakdowns for complex timelines

Timelines are fire-and-forget:

  • They cannot be paused or resumed once started
  • They cannot loop
  • They cannot wait for player input mid-sequence
  • They cannot be cancelled after launch

For interactive sequences, combine timelines with tasks (the task controls the flow, timelines handle the presentation).