Skip to content

Commit 778ed4d

Browse files
committed
feat: requirements.md
1 parent cb97d77 commit 778ed4d

File tree

3 files changed

+293
-20
lines changed

3 files changed

+293
-20
lines changed

docs/en/create-commands/requirements.md

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ We want to put a requirement on this command that the player needs to have at le
4141

4242
:::tabs
4343
===Java
44-
44+
<<< @/../reference-code/src/main/java/createcommands/Requirements.java#baseOnPlayerLevelExample
4545
===Kotlin
46-
46+
<<< @/../reference-code/src/main/kotlin/createcommands/Requirements.kt#baseOnPlayerLevelExample
4747
:::
4848

4949
It's important to note that in this example, we case the `sender` to a `player` for the requirement method. We know that the sender is definitely a player because we use `executesPlayer()`, which ensures that this is the case. Now that we've got this, **we need to make sure we update the player's requirements _when their exp changes_**. This is covered in more detail in the section about updating requirements below.
@@ -69,18 +69,18 @@ To represent our party in code, we'll use a simple `Map` called `partyMembers` w
6969

7070
:::tabs
7171
===Java
72-
72+
<<< @/../reference-code/src/main/java/createcommands/Requirements.java#partySystemExampleStep1
7373
===Kotlin
74-
74+
<<< @/../reference-code/src/main/kotlin/createcommands/Requirements.kt#partySystemExampleStep1
7575
:::
7676

7777
To begin with, let's create the `/party create <partyName>` command. First, we must declare our arguments:
7878

7979
:::tabs
8080
===Java
81-
81+
<<< @/../reference-code/src/main/java/createcommands/Requirements.java#partySystemExampleStep2
8282
===Kotlin
83-
83+
<<< @/../reference-code/src/main/kotlin/createcommands/Requirements.kt#partySystemExampleStep2
8484
:::
8585

8686
In this argument declaration, we put a requirement on the literal `create`, where the player does not have a party. In other words, if the player does not have a party, they are allowed to run `/party create <partyName>`. If a player already has a party, then they won't be allowed to run this command.
@@ -89,18 +89,18 @@ Now that we've declared our arguments, we can now declare our main command `/par
8989

9090
:::tabs
9191
===Java
92-
92+
<<< @/../reference-code/src/main/java/createcommands/Requirements.java#partySystemExampleStep3
9393
===Kotlin
94-
94+
<<< @/../reference-code/src/main/kotlin/createcommands/Requirements.kt#partySystemExampleStep3
9595
:::
9696

9797
So now we've added the ability to create a party if we're not already in it. Now we need to implement our `party tp <player>` command. Again, we must start by declaring our arguments:
9898

9999
:::tabs
100100
===Java
101-
101+
<<< @/../reference-code/src/main/java/createcommands/Requirements.java#partySystemExampleStep4
102102
===Kotlin
103-
103+
<<< @/../reference-code/src/main/kotlin/createcommands/Requirements.kt#partySystemExampleStep4
104104
:::
105105

106106
Notice something here? There's some code repetition for the `withRequirement` method - this is the same predicate that we used earlier, except we remove the negation. If you are interested, you can view the section [Predicate tips](./predicatetips.md) for a method to improve code reuse.
@@ -109,9 +109,9 @@ Once the arguments have been declared, we can now implement our party teleportat
109109

110110
:::tabs
111111
===Java
112-
112+
<<< @/../reference-code/src/main/java/createcommands/Requirements.java#partySystemExampleStep5
113113
===Kotlin
114-
114+
<<< @/../reference-code/src/main/kotlin/createcommands/Requirements.kt#partySystemExampleStep5
115115
:::
116116

117117
What's important to note in this example is that if you spend the time to set up the arguments properly, it severely decreases the amount of code required to write your command. This makes the commands you declare easier to understand and follow and you don't end up having to put all of these checks in the body of your command executor.
@@ -132,13 +132,11 @@ The CommandAPI handles this in a very simple method call:
132132
CommandAPI.updateRequirements(player);
133133
```
134134

135-
<div class="warning">
136-
137-
**Developer's Note:**
135+
:::danger Developer's Note:
138136

139137
The `CommandAPI.updateRequirements(player);` method can be used anywhere, **except** for the `withRequirement` method. Using it inside this method will crash the server. This is by design – just make sure you don't use it within the `withRequirement` method and everything will be fine!
140138

141-
</div>
139+
:::
142140

143141
To illustrate how to use this, we'll go over the two examples above:
144142

@@ -183,9 +181,9 @@ When a player creates a new party, we need to ensure that their requirements are
183181

184182
:::tabs
185183
===Java
186-
184+
<<< @/../reference-code/src/main/java/createcommands/Requirements.java#updateRequirementsExample
187185
===Kotlin
188-
186+
<<< @/../reference-code/src/main/kotlin/createcommands/Requirements.kt#updateRequirementsExample
189187
:::
190188

191189
That's it!
@@ -202,9 +200,9 @@ For example, you can apply multiple requirements for a command by calling the `w
202200

203201
:::tabs
204202
===Java
205-
203+
<<< @/../reference-code/src/main/java/createcommands/Requirements.java#multipleRequirementsExample
206204
===Kotlin
207-
205+
<<< @/../reference-code/src/main/kotlin/createcommands/Requirements.kt#multipleRequirementsExample
208206
:::
209207

210208
::::
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
package createcommands;
2+
3+
import dev.jorel.commandapi.CommandAPI;
4+
import dev.jorel.commandapi.CommandAPICommand;
5+
import dev.jorel.commandapi.arguments.Argument;
6+
import dev.jorel.commandapi.arguments.LiteralArgument;
7+
import dev.jorel.commandapi.arguments.PlayerArgument;
8+
import dev.jorel.commandapi.arguments.SafeSuggestions;
9+
import dev.jorel.commandapi.arguments.StringArgument;
10+
import org.bukkit.Bukkit;
11+
import org.bukkit.Material;
12+
import org.bukkit.entity.Player;
13+
import org.bukkit.inventory.ItemStack;
14+
import org.bukkit.inventory.meta.Damageable;
15+
import org.bukkit.inventory.meta.ItemMeta;
16+
17+
import java.util.ArrayList;
18+
import java.util.HashMap;
19+
import java.util.List;
20+
import java.util.Map;
21+
import java.util.Map.Entry;
22+
import java.util.UUID;
23+
24+
class Requirements {
25+
{
26+
// #region baseOnPlayerLevelExample
27+
new CommandAPICommand("repair")
28+
.withRequirement(sender -> ((Player) sender).getLevel() >= 30)
29+
.executesPlayer((player, args) -> {
30+
31+
// Repair the item back to full durability
32+
ItemStack is = player.getInventory().getItemInMainHand();
33+
ItemMeta itemMeta = is.getItemMeta();
34+
if (itemMeta instanceof Damageable damageable) {
35+
damageable.setDamage(0);
36+
is.setItemMeta(itemMeta);
37+
}
38+
39+
// Subtract 30 levels
40+
player.setLevel(player.getLevel() - 30);
41+
})
42+
.register();
43+
// #endregion baseOnPlayerLevelExample
44+
45+
// #region partySystemExampleStep1
46+
Map<UUID, String> partyMembers = new HashMap<>();
47+
// #endregion partySystemExampleStep1
48+
49+
// #region partySystemExampleStep2
50+
List<Argument<?>> arguments = new ArrayList<>();
51+
52+
// The "create" literal, with a requirement that a player must have a party
53+
arguments.add(new LiteralArgument("create")
54+
.withRequirement(sender -> !partyMembers.containsKey(((Player) sender).getUniqueId()))
55+
);
56+
57+
arguments.add(new StringArgument("partyName"));
58+
// #endregion partySystemExampleStep2
59+
60+
// #region partySystemExampleStep3
61+
new CommandAPICommand("party")
62+
.withArguments(arguments)
63+
.executesPlayer((player, args) -> {
64+
65+
// Get the name of the party to create
66+
String partyName = (String) args.get("partyName");
67+
68+
partyMembers.put(player.getUniqueId(), partyName);
69+
})
70+
.register();
71+
// #endregion partySystemExampleStep3
72+
73+
// #region partySystemExampleStep4
74+
arguments = new ArrayList<>();
75+
arguments.add(new LiteralArgument("tp")
76+
.withRequirement(sender -> partyMembers.containsKey(((Player) sender).getUniqueId()))
77+
);
78+
79+
arguments.add(new PlayerArgument("player")
80+
.replaceSafeSuggestions(SafeSuggestions.suggest(info -> {
81+
82+
// Store the list of party members to teleport to
83+
List<Player> playersToTeleportTo = new ArrayList<>();
84+
85+
String partyName = partyMembers.get(((Player) info.sender()).getUniqueId());
86+
// Find the party members
87+
for (Entry<UUID, String> entry : partyMembers.entrySet()) {
88+
89+
// Ignore yourself
90+
if (entry.getKey().equals(((Player) info.sender()).getUniqueId())) {
91+
continue;
92+
} else {
93+
// If the party member is in the same party as you
94+
if (entry.getValue().equals(partyName)) {
95+
Player target = Bukkit.getPlayer(entry.getKey());
96+
if (target.isOnline()) {
97+
// Add them if they are online
98+
playersToTeleportTo.add(target);
99+
}
100+
}
101+
}
102+
}
103+
104+
return playersToTeleportTo.toArray(new Player[0]);
105+
})));
106+
// #endregion partySystemExampleStep4
107+
108+
// #region partySystemExampleStep5
109+
new CommandAPICommand("party")
110+
.withArguments(arguments)
111+
.executesPlayer((player, args) -> {
112+
Player target = (Player) args.get("player");
113+
player.teleport(target);
114+
})
115+
.register();
116+
// #endregion partySystemExampleStep5
117+
118+
// #region updateRequirementsExample
119+
new CommandAPICommand("party")
120+
.withArguments(arguments)
121+
.executesPlayer((player, args) -> {
122+
123+
// Get the name of the party to create
124+
String partyName = (String) args.get("partyName");
125+
126+
partyMembers.put(player.getUniqueId(), partyName);
127+
128+
CommandAPI.updateRequirements(player);
129+
})
130+
.register();
131+
// #endregion updateRequirementsExample
132+
133+
// #region multipleRequirementsExample
134+
new CommandAPICommand("someCommand")
135+
.withRequirement(sender -> ((Player) sender).getLevel() >= 30)
136+
.withRequirement(sender -> ((Player) sender).getInventory().contains(Material.DIAMOND_PICKAXE))
137+
.withRequirement(sender -> ((Player) sender).isInvulnerable())
138+
.executesPlayer((player, args) -> {
139+
// Code goes here
140+
})
141+
.register();
142+
// #endregion multipleRequirementsExample
143+
}
144+
}
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package createcommands
2+
3+
import dev.jorel.commandapi.CommandAPI
4+
import dev.jorel.commandapi.CommandAPICommand
5+
import dev.jorel.commandapi.arguments.*
6+
import dev.jorel.commandapi.executors.PlayerCommandExecutor
7+
import org.bukkit.Bukkit
8+
import org.bukkit.Material
9+
import org.bukkit.entity.Player
10+
import org.bukkit.inventory.meta.Damageable
11+
import java.util.*
12+
13+
fun requirements() {
14+
// #region baseOnPlayerLevelExample
15+
CommandAPICommand("repair")
16+
.withRequirement { (it as Player).level >= 30 }
17+
.executesPlayer(PlayerCommandExecutor { player, _ ->
18+
19+
// Repair the item back to full durability
20+
val item = player.inventory.itemInMainHand
21+
val itemMeta = item.itemMeta
22+
if (itemMeta is Damageable) {
23+
itemMeta.damage = 0
24+
item.setItemMeta(itemMeta)
25+
}
26+
27+
// Subtract 30 levels
28+
player.level = player.level - 30
29+
})
30+
.register()
31+
// #endregion baseOnPlayerLevelExample
32+
33+
// #region partySystemExampleStep1
34+
val partyMembers = mutableMapOf<UUID, String>()
35+
// #endregion partySystemExampleStep1
36+
37+
// #region partySystemExampleStep2
38+
var arguments = mutableListOf<Argument<*>>()
39+
40+
// The "create" literal, with a requirement that a player must have a party
41+
arguments.add(LiteralArgument("create")
42+
.withRequirement { !partyMembers.containsKey((it as Player).uniqueId) }
43+
)
44+
45+
arguments.add(StringArgument("partyName"))
46+
// #endregion partySystemExampleStep2
47+
48+
// #region partySystemExampleStep3
49+
CommandAPICommand("party")
50+
.withArguments(*arguments.toTypedArray())
51+
.executesPlayer(PlayerCommandExecutor { player, args ->
52+
53+
// Get the name of the party to create
54+
val partyName = args["partyName"] as String
55+
56+
partyMembers[player.uniqueId] = partyName
57+
})
58+
.register()
59+
// #endregion partySystemExampleStep3
60+
61+
// #region partySystemExampleStep4
62+
arguments = mutableListOf<Argument<*>>()
63+
arguments.add(LiteralArgument("tp")
64+
.withRequirement { partyMembers.containsKey((it as Player).uniqueId) })
65+
66+
arguments.add(PlayerArgument("player")
67+
.replaceSafeSuggestions(SafeSuggestions.suggest { info ->
68+
69+
// Store the list of party members to teleport to
70+
val playersToTeleportTo = mutableListOf<Player>()
71+
72+
val partyName = partyMembers[(info.sender() as Player).uniqueId]
73+
74+
// Find the party members
75+
for ((uuid, party) in partyMembers) {
76+
77+
// Ignore yourself
78+
if (uuid == (info.sender() as Player).uniqueId) {
79+
continue
80+
} else {
81+
// If the party member is in the same party as you
82+
if (party == partyName) {
83+
val target = Bukkit.getPlayer(uuid)!!
84+
if (target.isOnline) {
85+
// Add them if they are online
86+
playersToTeleportTo.add(target)
87+
}
88+
}
89+
}
90+
}
91+
92+
playersToTeleportTo.toTypedArray()
93+
}))
94+
// #endregion partySystemExampleStep4
95+
96+
// #region partySystemExampleStep5
97+
CommandAPICommand("party")
98+
.withArguments(arguments)
99+
.executesPlayer(PlayerCommandExecutor { player, args ->
100+
val target = args["player"] as Player
101+
player.teleport(target)
102+
})
103+
.register()
104+
// #endregion partySystemExampleStep5
105+
106+
// #region updateRequirementsExample
107+
CommandAPICommand("party")
108+
.withArguments(arguments)
109+
.executesPlayer(PlayerCommandExecutor { player, args ->
110+
111+
// Get the name of the party to create
112+
val partyName = args["partyName"] as String
113+
114+
partyMembers[player.uniqueId] = partyName
115+
116+
CommandAPI.updateRequirements(player)
117+
})
118+
.register()
119+
// #endregion updateRequirementsExample
120+
121+
// #region multipleRequirementsExample
122+
CommandAPICommand("someCommand")
123+
.withRequirement { (it as Player).level >= 30 }
124+
.withRequirement { (it as Player).inventory.contains(Material.DIAMOND_PICKAXE) }
125+
.withRequirement { (it as Player).isInvulnerable }
126+
.executesPlayer(PlayerCommandExecutor { player, args ->
127+
// Code goes here
128+
})
129+
.register()
130+
// #endregion multipleRequirementsExample
131+
}

0 commit comments

Comments
 (0)