Skip to content

Commit e34ff7d

Browse files
authored
Merge pull request #121 from tqcuong2000/main
Add "cooldown checks" section
2 parents 1409c7c + f08e7ed commit e34ff7d

4 files changed

Lines changed: 230 additions & 0 deletions

File tree

src/lib/sidebar/tabs/Guides.svelte

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@
4242
import IconRuler2 from "~icons/tabler/ruler-2";
4343
import IconMathMaxMin from "~icons/tabler/math-max-min";
4444
import IconCat from "~icons/tabler/cat";
45+
import IconClock from "~icons/tabler/clock";
46+
import IconStar from "~icons/tabler/star";
47+
import IconHourglass from "~icons/tabler/hourglass-empty";
4548
import SidebarPlaceholder from "../navigation/SidebarPlaceholder.svelte";
4649
</script>
4750

@@ -71,6 +74,14 @@
7174
page="/guide/adding-new-features/custom-items/models" />
7275
</SidebarCategory>
7376

77+
<SidebarCategory name="Cooldowns" icon={IconHourglass}>
78+
<SidebarPage label="Summary" icon={IconPennant} page="/guide/cooldown" />
79+
80+
<SidebarHeading label="Techniques" />
81+
<SidebarPage label="Scoreboard" icon={IconScoreboard} page="/guide/cooldown/scoreboard" />
82+
<SidebarPage label="Worldclock" icon={IconClock} page="/guide/cooldown/worldclock" />
83+
</SidebarCategory>
84+
7485
<SidebarCategory name="Right Click Detection" icon={IconMouse}>
7586
<SidebarPage label="Summary" icon={IconPennant} page="/guide/right-click" />
7687

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
title: Cooldown checks
3+
description: Learn how to create and check cooldown timers using several common methods.
4+
version: 26.1
5+
---
6+
7+
# Cooldown checks
8+
9+
A cooldown restricts how frequently a player triggers a custom action. In most
10+
datapacks, these actions involve running functions or commands.
11+
12+
For example, consider a custom wand that shoots fireballs when a player
13+
right clicks. Without a cooldown, players could spam the wand, resulting
14+
in lag or unbalanced gameplay. Adding a cooldown ensures the player waits a few
15+
seconds before shooting another fireball.
16+
17+
## Core concepts
18+
- **Cooldown**: A timer that prevents an action from running again until a specified
19+
amount of time has elapsed since the last execution.
20+
- **Action**: The command or function the cooldown restricts.
21+
22+
23+
## Implementation methods
24+
25+
There are two main ways to implement a cooldown mechanic in your project:
26+
27+
- [Scoreboard-based cooldown](/guide/cooldown/scoreboard) - Uses a scoreboard objective to store how
28+
much time remaining until the cooldown expires. This is the simplest and the easiest to understand version,
29+
but if you're creating a larger datapack, or intend on using it with multiple players, you may prefer to use an alternative version to minimise system lag.
30+
- [Worldclock-based cooldown](/guide/cooldown/worldclock) - Uses the time on a worldclock to measure the elapsed time since an action was last used. This is a non-ticking approach that works well for large datapacks, or any project that uses many cooldown timers.
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
---
2+
title: Scoreboard-based cooldown
3+
description: Learn how to create and check cooldown timers using a scoreboard objective.
4+
version: 26.1
5+
---
6+
7+
# Scoreboard-based cooldown
8+
9+
A scoreboard-based cooldown stores a number on each player (or entity) and
10+
changes that number over time.
11+
12+
This guide uses a ticking approach, which means the datapack updates the
13+
cooldown every game tick (20 ticks per second). This works well
14+
for small projects with only a few cooldowns and short durations. If you track many cooldowns or
15+
many entities, this negatively affects performance, because the game has to run loads of commands.
16+
17+
In summary, this approach sets a player's score on a scoreboard, and then decreases that score every
18+
tick. This means that, when we need to do something which requires a cooldown, we can just check the
19+
score to see if the player has an active cooldown or not.
20+
21+
## What you will create
22+
23+
- A `my_cd` scoreboard objective (this tracks the actual cooldown for each plalyer)
24+
- A `tick` function (this reduces each player's cooldown score)
25+
- A `check_cooldown` function (this will be used to check and reset the player's cooldown)
26+
27+
:::tip
28+
29+
To learn how to trigger a function when a player uses an item, see the
30+
[Right-click menu](/guide/right-click) guide.
31+
32+
:::
33+
34+
### 1. Create the scoreboard objective
35+
36+
In your load function, create a dummy objective named `my_cd`. A dummy
37+
objective is just a scoreboard which can only be changed by commands.
38+
39+
```mcfunction:load.mcfunction
40+
scoreboard objectives add my_cd dummy
41+
```
42+
43+
### 2. Reduce the score in the `tick` function
44+
45+
In your `tick` function (which runs every tick), reduce the `my_cd`
46+
score by 1 for any player with `my_cd` ≥ 1.
47+
48+
```mcfunction:tick.mcfunction
49+
scoreboard players remove @a[scores={my_cd=1..}] my_cd 1
50+
```
51+
52+
:::note
53+
54+
Alternatively, if optimisation is an concern, you can decrease the commands used, and use a `minecraft:tick` advancement so that
55+
it only runs the command when the player has an active cooldown. To do this, you would need a tick advancement which runs a function -
56+
in that function, you would decrease the player's score and then revoke the advancement only if their score is 1 or more. This would replace
57+
the commands in the tick function, and slightly help to minimise lag.
58+
59+
:::
60+
61+
### 3. Create the `check_cooldown` function
62+
63+
You will run this function whenever you want to do something which is on a cooldown. For example,
64+
if you have a special item which you only want the player to be able to use once every 5 seconds,
65+
you would run this function to check if the player is on cooldown or not.
66+
67+
In this function, we check the executor's `my_cd` score to tell whether they have an active cooldown.
68+
- If the score is 1 or higher (i.e. they haven't reached the end of the cooldown), then the function will return a **failure**..
69+
- If the score is 0 or doesn't exist yet (i.e. they do not have an active cooldown), then the function will return a **success**.
70+
71+
```mcfunction:check_cooldown.mcfunction
72+
# If the player is still on cooldown, tell the player and stop here.
73+
execute if score @s my_cd matches 1.. run tellraw @s {color:"red",text:"This is on cooldown! Wait before you try again."}
74+
execute if score @s my_cd matches 1.. run return fail
75+
76+
# If the function hasn't yet been stopped, then the player is not on a cooldown
77+
# so we can set the cooldown and then return a success.
78+
79+
scoreboard players set @s my_cd 100
80+
return 1
81+
```
82+
83+
## 4. Using the `check_cooldown` function
84+
85+
Whenever the player does something that needs a cooldown, you can use `execute if function` with the `check_cooldown` function. If the
86+
player still is on a cooldown, then the function will fail and the command will not run. If the player isn't on a cooldown, then
87+
the function will set the cooldown and then return a success, so the command WILL run.
88+
89+
In this example, a creeper will only be summoned when the player has no active cooldown (in which case, the cooldown will be set).
90+
If the player has an active cooldown, then the creeper will not be summoned, and instead the error message in `check_cooldown.mcfunction`
91+
will be sent.
92+
93+
```mcfunction
94+
execute as <player> if function <namespace>:check_cooldown run summon creeper
95+
```
96+
97+
## Using multiple cooldowns
98+
99+
If you want to have multiple different cooldowns for different items, then you will need a different `cooldown` scoreboard and `check_cooldown`
100+
function for each cooldown. You will also need to decrease the score for each cooldown in the tick function.
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
---
2+
title: Worldclock-based cooldown
3+
description: Learn how to create and check cooldown timers using the world clock.
4+
version: 26.1
5+
---
6+
7+
# Worldclock-based cooldown
8+
9+
A worldclock cooldown works by storing a timestamp of when an action was last used in a scoreboard objective.
10+
Your datapack compares this stored time with the current time to determine if the cooldown has ended.
11+
12+
Although this is more complicated, this function doesn't rely on any ticking commands. This is especially
13+
good for much larger datapacks because it is the most performance-efficient method.
14+
15+
## What you will create
16+
- A `cooldown.json` clock in the world clock folder.
17+
- A `last_used` scoreboard objective (this stores when the action was last used).
18+
- A `<namespace>:check_cooldown` function (this is used to check the cooldown)
19+
20+
### 1. Setup the world clock
21+
In your datapack namespace, create a folder named `world_clock`. Then, create a file named `cooldown.json` inside the folder. This
22+
basically just registers a new world clock (think of this as a special type of stopwatch). This file needs no data, other than `{}`.
23+
24+
```json:/world_clock/cooldown.json
25+
{}
26+
```
27+
28+
Restart your world/server (`/reload` isn't enough here), then run `/time of <namespace>:cooldown query time` to verify that the clock exists.
29+
30+
### 2. Create the scoreboard objective
31+
32+
You will need a scoreboard objective stores the last time the action was used in the `cooldown` world clock. You can call this scoreboard
33+
anything - for simplicity, here we will call it `last_used`. You should create this scoreboard objective in your load function.
34+
35+
```mcfunction:load.mcfunction
36+
scoreboard objectives add last_used dummy
37+
```
38+
39+
### 3. Create the `check_cooldown` function
40+
41+
You will run this function whenever you want to do something which is on a cooldown. For example,
42+
if you have a special item which you only want the player to be able to use once every 5 seconds,
43+
you would run this function to check if the player is on cooldown or not.
44+
45+
In this function, we check the executor's `last_used` score against the current time on the `cooldown` clock. If the
46+
difference between the times is less than 100 ticks (5 seconds), then the function will return a **failure**. If not,
47+
then the function will return a **success** and the `last_used` will be set to the current time.
48+
49+
```mcfunction:check_cooldown.mcfunction
50+
# Temporarily store the current time on the cooldown clock
51+
execute store result score #current_time last_used run time of <namespace>:cooldown query time
52+
53+
# Calculate the difference in times (i.e. the time since the action was last used)
54+
# basically: "#current_time" = "#current_time" - time of last use
55+
scoreboard players operation #current_time last_used -= @s last_used
56+
57+
# If the difference is less than 100 ticks, then not enough time has passed, so we tell the player and then return a failure
58+
execute if score #current_time last_used matches ..100 run tellraw @s {color:"red",text:"This is on cooldown! Wait before you try again."}
59+
execute if score #current_time last_used matches ..100 run return fail
60+
61+
# If the function hasn't yet been stopped, then the player is not on a cooldown
62+
# so we can update the last_used time and then return a success.
63+
64+
execute store result score @s last_used run time of <namespace>:cooldown query time
65+
return 1
66+
```
67+
68+
:::warning
69+
Don't modify the `cooldown` world clock; it will break the cooldown calculations.
70+
:::
71+
72+
## 4. Using the `check_cooldown` function
73+
74+
Whenever the player does something that needs a cooldown, you can use `execute if function` with the `check_cooldown` function. If the
75+
player still is on a cooldown, then the function will fail and the command will not run. If the player isn't on a cooldown, then
76+
the function will set the cooldown and then return a success, so the command WILL run.
77+
78+
In this example, a creeper will only be summoned when the player has no active cooldown (in which case, the cooldown will be set).
79+
If the player has an active cooldown, then the creeper will not be summoned, and instead the error message in `check_cooldown.mcfunction`
80+
will be sent.
81+
82+
```mcfunction
83+
execute as <player> if function <namespace>:check_cooldown run summon creeper
84+
```
85+
86+
## Using multiple cooldowns
87+
88+
If you want to have multiple different cooldowns for different items, then you will need a different `last_used` scoreboard and `check_cooldown`
89+
function for each cooldown. However, you can re-use the `cooldown` world clock for as many cooldowns as you wish.

0 commit comments

Comments
 (0)