Skip to content

Register commands

In this section, we'll walk you through creating a simple command. By the end of this section, you'll have a basic understanding of how to define and register commands with Endstone.

Create a command

Let's start with a simple command /hello that greets the command sender.

src/endstone_my_plugin/my_plugin.py
 fromendstone.pluginimport Plugin

 classMyPlugin(Plugin):
 api_version = "0.10"

  commands = {
  "hello": {
  "description": "Greet the command sender.",
  "usages": ["/hello"],
  }
  }

 # ...
src/my_plugin.cpp
 #include"my_plugin.h"

 ENDSTONE_PLUGIN("my_plugin","0.1.0",MyPlugin)
 {
 description="My first C++ plugin for Endstone servers";

 command("hello")
 .description("Greet the command sender.")
 .usages("/hello");
 }

And it's just as simple as that! You've just created a new command with description and usages.

Add permissions

By the default, all the commands in endstone requires the operator permission to execute for security reasons. Since we are creating a simple command here, we might want to change its permission for everyone to use.

Let's make the following changes to our code.

src/endstone_my_plugin/my_plugin.py
 fromendstone.commandimport Command, CommandSender
 fromendstone.pluginimport Plugin

 classMyPlugin(Plugin):
 api_version = "0.10"

 commands = {
 "hello": {
 "description": "Greet the command sender.",
 "usages": ["/hello"],
  "permissions": ["my_plugin.command.hello"],
 }
 }

  permissions = {
  "my_plugin.command.hello": {
  "description": "Allow users to use the /hello command.",
  "default": True, #(1)!
  }
  }

 # ...
  1. ⭐ See tips

Tip

The default field sets the permission level required for executing the command. Possible values are:

  • True or "true": everyone can execute this command
  • False or "false": on one can execute this command, unless explicitly granted the permission.
  • "op": only operators can execute this command
  • "not_op": only non-operators can execute this command
  • "console": only console can execute this command
src/my_plugin.cpp
 #include"my_plugin.h"

 ENDSTONE_PLUGIN("my_plugin","0.1.0",MyPlugin)
 {
 description="My first C++ plugin for Endstone servers";

 command("hello")
 .description("Greet the command sender.")
 .usages("/hello")
 .permissions("my_plugin.command.hello");

 permission("my_plugin.command.hello")
 .description("Allow users to use the /hello command.")
 .default_(endstone::PermissionDefault::True);/*(1)!*/
 }
  1. ⭐ See tips

Tip

The default_ method sets the permission level required for executing the command. Possible values are:

  • endstone::PermissionDefault::True: everyone can execute this command
  • endstone::PermissionDefault::False: on one can execute this command, unless explicitly granted the permission.
  • endstone::PermissionDefault::Operator: only operators can execute this command
  • endstone::PermissionDefault::NotOperator: only non-operators can execute this command
  • endstone::PermissionDefault::Console: only console can execute this command

Handle the commands

Now, the next step is to handle the commands we just created. Let's say we want to send a "Hello, World!" greeting message to whoever execute this command. It's just a few more lines away from that.

src/endstone_my_plugin/my_plugin.py
 fromendstone.commandimport Command, CommandSender
 fromendstone.pluginimport Plugin

 classMyPlugin(Plugin):
 api_version = "0.10"

 commands = {
 "hello": {
 "description": "Greet the command sender.",
 "usages": ["/hello"],
 "permissions": ["my_plugin.command.hello"],
 }
 }

 permissions = {
 "my_plugin.command.hello": {
 "description": "Allow users to use the /hello command.",
 "default": True,
 }
 }

  defon_command(self, sender: CommandSender, command: Command, args: list[str]) -> bool:
  if command.name == "hello":
  sender.send_message("Hello World!")
   return True

 # ...
include/my_plugin.h
 #include<endstone/endstone.hpp>

 classMyPlugin:publicendstone::Plugin{
 public:
 boolonCommand(endstone::CommandSender&sender,constendstone::Command&command,conststd::vector<std::string>&args)override
 {
 if(command.getName()=="hello")
 {
 sender.sendMessage("Hello World!");
 }
 returntrue;
 }

 // ...
 };

Now, install your plugin and restart your server. Join the game and type /help hello. You should see the usage information, which indicates that our command has been successfully added to the game!

Now, type /hello, and you should receive the message "Hello World!".

Example command

Add parameters to commands

Now, let's say we want to send a custom message to greet the sender instead of "Hello World!". We can add a parameter to the command that accepts a message.

In Endstone, there are two basic kinds of parameters:

Kind Description Syntax
Mandatory This parameter must be provided <name: type>
Optional This parameter is optional and can be omitted [name: type]

Let's change our code to add an optional parameter msg with message type. Based on the table above, the syntax should be [msg: message]. Let's add it to our code.

src/endstone_my_plugin/my_plugin.py
 fromendstone.commandimport Command, CommandSender
 fromendstone.pluginimport Plugin

 classMyPlugin(Plugin):
 api_version = "0.10"

 commands = {
 "hello": {
 "description": "Greet the command sender.",
  "usages": ["/hello [msg: message]"],
 "permissions": ["my_plugin.command.hello"],
 }
 }

 permissions = {
 "my_plugin.command.hello": {
 "description": "Allow users to use the /hello command.",
 "default": True,
 }
 }

 defon_command(self, sender: CommandSender, command: Command, args: list[str]) -> bool:
 if command.name == "hello":
  if len(args) == 0: #(1)!
  sender.send_message("Hello World!")
  else:
  sender.send_message(args[0])

 return True

 # ...
  1. βœ… Here, we checked if the optional parameter is provided.
src/my_plugin.cpp
 #include"my_plugin.h"

 ENDSTONE_PLUGIN("my_plugin","0.1.0",MyPlugin)
 {
 description="My first C++ plugin for Endstone servers";

 command("hello")
 .description("Greet the command sender.")
 .usages("/hello [msg: message]")
 .permissions("my_plugin.command.hello");

 permission("my_plugin.command.hello")
 .description("Allow users to use the /hello command.")
 .default_(endstone::PermissionDefault::True);
 }
include/my_plugin.h
 #include<endstone/endstone.hpp>

 classMyPlugin:publicendstone::Plugin{
 public:
 boolonCommand(endstone::CommandSender&sender,constendstone::Command&command,conststd::vector<std::string>&args)override
 {
 if(command.getName()=="hello")
 {
 if(args.empty()){
 sender.sendMessage("Hello World!");
 }
 else{
 sender.sendMessage(args[0]);
 }
 }
 returntrue;
 }

 // ...
 };

πŸ₯³ And it's done! Now when the users use /hello This is my message!, "This is my message!" will be shown to them instead of "Hello World!".

Tip

To make the parameter mandatory, change the parameter from [msg: message] to <msg: message>

Built-in types

In the section above, we added a parameter with type message which is a built-in type supported by Endstone. Here is a full list of all built-in types currently supported.

Type Alias Description Possible Value
int Represents an integer 10
float Represents a floating point number 3.14
bool Represents a boolean true
target actor, entity, player Represents a target selector @e, @r, PlayerName
str string Represents a string, terminated by space Hello
block_pos vec3i Represents a 3-Dimensionalinteger position 1 2 3
pos vec3, vec3f Represents a 3-Dimensional float position 1.0 2.0 3.0
message Represents a message with everything until end of line Hello World!
json Represents a JSON string {"key": "value"}
block Represents a block type wood
block_states Represents the block states ["wood_type"="birch","stripped_bit"=true]
entity_type Represents a entity type minecraft:creeper

User-defined enum types

Enum Types can be used to represent a set of predefined string constants. This behavior is similar to how literal types function in modern programming languages such as Node.js and Python. Enum types provide a way to define a "type" comprised of a set of named constants, referred to as the enumeration, or in short, "enum".

Endstone allows developer to add their own enums. The basic syntax follows the pattern:

  • Mandatory: (value1|value2|value3)<name: EnumType>
  • Optional: (value1|value2|value3)[name: EnumType]

Here, all possible values, separated by the pipeline operator |, are scoped inside the parentheses (), followed by the parameter kind, name and type.

Example

An example of using enum types in command usages is: /home (add|list|del)<action: HomeAction>

In this example, the parameter is named action and has a user-defined enum type HomeAction. When using the command, the user must select one of the specified action from the set: add, list, or del.

AltStyle γ«γ‚ˆγ£γ¦ε€‰ζ›γ•γ‚ŒγŸγƒšγƒΌγ‚Έ (->γ‚ͺγƒͺγ‚ΈγƒŠγƒ«) /