Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 26 additions & 85 deletions docs/en/create-commands/arguments/types/entities-arguments.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,31 +38,15 @@ Say we want a command to remove certain types of entities. Typically, this would

Instead, we can combine all of these into one by using the `EntitySelectorArgument`. We want to be able to target multiple entities at a time, so we want to use the `EntitySelectorArgument.ManyEntities` constructor. We can simply retrieve the `Collection<Entity>` from this argument and iteratively remove each entity:

<div class="paper">

:::tabs
===Java
<<< @/../reference-code/paper/src/main/java/createcommands/arguments/types/EntitiesArguments.java#entitySelectorArgumentExample
<<< @/../reference-code/bukkit/src/main/java/createcommands/arguments/types/EntitiesArguments.java#entitySelectorArgumentExample
===Kotlin
<<< @/../reference-code/paper/src/main/kotlin/createcommands/arguments/types/EntitiesArguments.kt#entitySelectorArgumentExample
<<< @/../reference-code/bukkit/src/main/kotlin/createcommands/arguments/types/EntitiesArguments.kt#entitySelectorArgumentExample
===Kotlin DSL
<<< @/../reference-code/paper/src/main/kotlin/createcommands/arguments/types/EntitiesArguments.kt#entitySelectorArgumentExampleDSL
<<< @/../reference-code/bukkit/src/main/kotlin/createcommands/arguments/types/EntitiesArguments.kt#entitySelectorArgumentExampleDSL
:::

</div>
<div class="spigot">

:::tabs
===Java
<<< @/../reference-code/spigot/src/main/java/createcommands/arguments/types/EntitiesArguments.java#entitySelectorArgumentExample
===Kotlin
<<< @/../reference-code/spigot/src/main/kotlin/createcommands/arguments/types/EntitiesArguments.kt#entitySelectorArgumentExample
===Kotlin DSL
<<< @/../reference-code/spigot/src/main/kotlin/createcommands/arguments/types/EntitiesArguments.kt#entitySelectorArgumentExampleDSL
:::

</div>

We could then use this to target specific entities, for example:

- To remove all cows:
Expand All @@ -79,82 +63,55 @@ We could then use this to target specific entities, for example:

::::

## PlayerProfile argument
::::tip Example – Player argument without entity selectors

The `PlayerProfileArgument` can serve a similar purpose as the `EntitySelectorArgument.OnePlayer` or `EntitySelectorArgument.ManyPlayers` if you only reference online players, but it can also be used to reference players that are offline or have never logged into your server.

Because of this, it has a performance overhead even when the input is an online player or an entity selector.

<div class="paper">

The `PlayerProfileArgument` returns a `List<com.destroystokyo.paper.profile.PlayerProfile>`.

</div>
<div class="spigot">

The `PlayerProfileArgument` returns a `List<org.bukkit.profile.PlayerProfile>`.

</div>

::::tip Example – PlayerProfileArgument without entity selectors

When registering a `PlayerProfileArgument` you might notice that it includes `Entity Selectors` (`@a`, `@e`, `@r`, etc.). If you want to avoid those, you can use argument suggestions to only suggest the player names. For this example, let us create a /warp command:
When registering a `EntitySelectorArgument.OnePlayer` you might notice that it accepts `Entity Selectors` (`@a`, `@e`, `@r`, etc.). You might want to only suggest Player names to make it clearer than only one Player will be accepted. The [`ArgumentSuggestions`](../suggestions/suggestions.md) API makes this simple. For this example, let us create a /warp command:

```mccmd
/warp <player>
```

To get a `PlayerProfileArgument` which only suggests the actual names, we can define it like this:

<div class="paper">
To get a `EntitySelectorArgument.OnePlayer` which only suggests the actual names, we can define it like this:

:::tabs
===Java
<<< @/../reference-code/paper/src/main/java/createcommands/arguments/types/EntitiesArguments.java#buildNoSelectorSuggestions
<<< @/../reference-code/bukkit/src/main/java/createcommands/arguments/types/EntitiesArguments.java#buildNoSelectorSuggestions
===Kotlin
<<< @/../reference-code/paper/src/main/kotlin/createcommands/arguments/types/EntitiesArguments.kt#buildNoSelectorSuggestions
<<< @/../reference-code/bukkit/src/main/kotlin/createcommands/arguments/types/EntitiesArguments.kt#buildNoSelectorSuggestions
:::

</div>
<div class="spigot">
Now we can define the rest of the command and include our suggestion inside it like this:

:::tabs
===Java
<<< @/../reference-code/spigot/src/main/java/createcommands/arguments/types/EntitiesArguments.java#buildNoSelectorSuggestions
<<< @/../reference-code/bukkit/src/main/java/createcommands/arguments/types/EntitiesArguments.java#noSelectorSuggestionsExample
===Kotlin
<<< @/../reference-code/spigot/src/main/kotlin/createcommands/arguments/types/EntitiesArguments.kt#buildNoSelectorSuggestions
<<< @/../reference-code/bukkit/src/main/kotlin/createcommands/arguments/types/EntitiesArguments.kt#noSelectorSuggestionsExample
:::

</div>
And there we have it! One thing to note is that entity selectors are still a valid input; they’re just not included in the suggestions.

Now we can define the rest of the command and include our suggestion inside it like this:
![WarpCommand](/images/entityselectorplayerexample.gif)

::::

## PlayerProfile argument

The `PlayerProfileArgument` can serve a similar purpose as the `EntitySelectorArgument.OnePlayer` or `EntitySelectorArgument.ManyPlayers` if you only reference online players, but it can also be used to reference players that are offline or have never logged into your server.

Because of this, it has a performance overhead even when the input is an online player.

<div class="paper">

:::tabs
===Java
<<< @/../reference-code/paper/src/main/java/createcommands/arguments/types/EntitiesArguments.java#noSelectorSuggestionsExample
===Kotlin
<<< @/../reference-code/paper/src/main/kotlin/createcommands/arguments/types/EntitiesArguments.kt#noSelectorSuggestionsExample
:::
The `PlayerProfileArgument` returns a `List<com.destroystokyo.paper.profile.PlayerProfile>`.

</div>
<div class="spigot">

:::tabs
===Java
<<< @/../reference-code/spigot/src/main/java/createcommands/arguments/types/EntitiesArguments.java#noSelectorSuggestionsExample
===Kotlin
<<< @/../reference-code/spigot/src/main/kotlin/createcommands/arguments/types/EntitiesArguments.kt#noSelectorSuggestionsExample
:::
The `PlayerProfileArgument` returns a `List<org.bukkit.profile.PlayerProfile>`.

</div>

And there we have it! One thing to note is that entity selectors are still a valid input; they’re just not included in the suggestions.
![WarpCommand](/images/entityselectorplayerexample.gif)

::::

## AsyncPlayerProfile argument

The `AsyncPlayerProfileArgument` class is identical to the `PlayerProfileArgument` class, but instead of making the API call synchronously, it makes the API call asynchronously. This means that the command will not block the main thread while waiting for the API call to complete.
Expand Down Expand Up @@ -229,31 +186,15 @@ Say we want a command to spawn a specific type of entity, similar to the `/summo

Since we're trying to specify an entity type, we will use the `EntityTypeArgument` as our argument type for `<entity>`. We combine this with the `IntegerArgument` class with a specified range of $1 \le \textit{amount} \le 100$:

<div class="paper">

:::tabs
===Java
<<< @/../reference-code/paper/src/main/java/createcommands/arguments/types/EntitiesArguments.java#entityTypeArgumentExample
===Kotlin
<<< @/../reference-code/paper/src/main/kotlin/createcommands/arguments/types/EntitiesArguments.kt#entityTypeArgumentExample
===Kotlin DSL
<<< @/../reference-code/paper/src/main/kotlin/createcommands/arguments/types/EntitiesArguments.kt#entityTypeArgumentExampleDSL
:::

</div>
<div class="spigot">

:::tabs
===Java
<<< @/../reference-code/spigot/src/main/java/createcommands/arguments/types/EntitiesArguments.java#entityTypeArgumentExample
<<< @/../reference-code/bukkit/src/main/java/createcommands/arguments/types/EntitiesArguments.java#entityTypeArgumentExample
===Kotlin
<<< @/../reference-code/spigot/src/main/kotlin/createcommands/arguments/types/EntitiesArguments.kt#entityTypeArgumentExample
<<< @/../reference-code/bukkit/src/main/kotlin/createcommands/arguments/types/EntitiesArguments.kt#entityTypeArgumentExample
===Kotlin DSL
<<< @/../reference-code/spigot/src/main/kotlin/createcommands/arguments/types/EntitiesArguments.kt#entityTypeArgumentExampleDSL
<<< @/../reference-code/bukkit/src/main/kotlin/createcommands/arguments/types/EntitiesArguments.kt#entityTypeArgumentExampleDSL
:::

</div>

Note how in this example above, we have to explicitly state `Player player, CommandArguments args`. This is due to a limitation of Java's type inference system which is discussed [here](../../registration#setting-the-commands-executor).

::::
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package createcommands.arguments.types;

import dev.jorel.commandapi.CommandAPICommand;
import dev.jorel.commandapi.arguments.Argument;
import dev.jorel.commandapi.arguments.ArgumentSuggestions;
import dev.jorel.commandapi.arguments.EntitySelectorArgument;
import dev.jorel.commandapi.arguments.EntityTypeArgument;
import dev.jorel.commandapi.arguments.IntegerArgument;
import dev.jorel.commandapi.executors.CommandArguments;
import org.bukkit.Bukkit;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;

import java.util.Collection;

class EntitiesArguments {
static {
// #region entitySelectorArgumentExample
new CommandAPICommand("remove")
// Using a collective entity selector to select multiple entities
.withArguments(new EntitySelectorArgument.ManyEntities("entities"))
.executes((sender, args) -> {
// Parse the argument as a collection of entities (as stated above in the documentation)
@SuppressWarnings("unchecked")
Collection<Entity> entities = (Collection<Entity>) args.get("entities");

sender.sendMessage("Removed " + entities.size() + " entities");
for (Entity e : entities) {
e.remove();
}
})
.register();
// #endregion entitySelectorArgumentExample

// #region buildNoSelectorSuggestions
Argument<?> noSelectorSuggestions = new EntitySelectorArgument.OnePlayer("target")
.replaceSuggestions(ArgumentSuggestions.strings(info ->
Bukkit.getOnlinePlayers().stream().map(Player::getName).toArray(String[]::new)
));
// #endregion buildNoSelectorSuggestions

// #region noSelectorSuggestionsExample
new CommandAPICommand("warp")
.withArguments(noSelectorSuggestions)
.executesPlayer((player, args) -> {
Player target = (Player) args.get("target");
player.teleport(target);
})
.register();
// #endregion noSelectorSuggestionsExample

// #region entityTypeArgumentExample
new CommandAPICommand("spawnmob")
.withArguments(new EntityTypeArgument("entity"))
.withArguments(new IntegerArgument("amount", 1, 100)) // Prevent spawning too many entities
.executesPlayer((player, args) -> {
for (int i = 0; i < (int) args.get("amount"); i++) {
player.getWorld().spawnEntity(player.getLocation(), (EntityType) args.get("entity"));
}
})
.register();
// #endregion entityTypeArgumentExample
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package createcommands.arguments.types

import dev.jorel.commandapi.CommandAPICommand
import dev.jorel.commandapi.arguments.ArgumentSuggestions
import dev.jorel.commandapi.arguments.EntitySelectorArgument
import dev.jorel.commandapi.arguments.EntityTypeArgument
import dev.jorel.commandapi.arguments.IntegerArgument
import dev.jorel.commandapi.executors.CommandExecutor
import dev.jorel.commandapi.executors.PlayerCommandExecutor
import dev.jorel.commandapi.kotlindsl.*
import org.bukkit.Bukkit
import org.bukkit.entity.Entity
import org.bukkit.entity.EntityType
import org.bukkit.entity.Player

fun entitiesArguments() {
// #region entitySelectorArgumentExample
CommandAPICommand("remove")
// Using a collective entity selector to select multiple entities
.withArguments(EntitySelectorArgument.ManyEntities("entities"))
.executes(CommandExecutor { sender, args ->
// Parse the argument as a collection of entities (as stated above in the documentation)
val entities = args["entities"] as Collection<Entity>

sender.sendMessage("Removed ${entities.size} entities")
for (e in entities) {
e.remove()
}
})
.register()
// #endregion entitySelectorArgumentExample

// #region buildNoSelectorSuggestions
val noSelectorSuggestions = EntitySelectorArgument.OneEntity("target")
.replaceSuggestions(ArgumentSuggestions.strings { info ->
Bukkit.getOnlinePlayers().map { player -> player.name }.toTypedArray()
})
// #endregion buildNoSelectorSuggestions

// #region noSelectorSuggestionsExample
CommandAPICommand("warp")
.withArguments(noSelectorSuggestions)
.executesPlayer(PlayerCommandExecutor { player, args ->
val target = args["target"] as Player
player.teleport(target)
})
.register()
// #endregion noSelectorSuggestionsExample

// #region entityTypeArgumentExample
CommandAPICommand("spawnmob")
.withArguments(EntityTypeArgument("entity"))
.withArguments(IntegerArgument("amount", 1, 100)) // Prevent spawning too many entities
.executesPlayer(PlayerCommandExecutor { player, args ->
for (i in 0 until args["amount"] as Int) {
player.world.spawnEntity(player.location, args["entity"] as EntityType)
}
})
.register()
// #endregion entityTypeArgumentExample
}

fun entitiesArgumentsDSL() {
// #region entitySelectorArgumentExampleDSL
commandAPICommand("remove") {
// Using a collective entity selector to select multiple entities
entitySelectorArgumentManyEntities("entities")
anyExecutor { sender, args ->
// Parse the argument as a collection of entities (as stated above in the documentation)
val entities = args["entities"] as Collection<Entity>

sender.sendMessage("Removed ${entities.size} entities")
for (e in entities) {
e.remove()
}
}
}
// #endregion entitySelectorArgumentExampleDSL

// #region entityTypeArgumentExampleDSL
commandAPICommand("spawnmob") {
entityTypeArgument("entity")
integerArgument("amount", 1, 100) // Prevent spawning too many entities
playerExecutor { player, args ->
for (i in 0 until args["amount"] as Int) {
player.world.spawnEntity(player.location, args["entity"] as EntityType)
}
}
}
// #endregion entityTypeArgumentExampleDSL
}
Loading