Commands (and how to use them!)
What makes both commands (and CVars) special in PikeConsole is that you actually do not initialize them yourself.
Instead we make use of a special Node called the CommandSet
By inheriting from this Node, we can create a command in just a few seconds.
Let's try it out by creating a simple echo command...
1️⃣ Create a Node to host the command set
Right click your scene tree and press Add a child Node or press Ctrl + A.
Create a Node using the root type Node.
Name this Node anything you want. It is recommended to keep the names clear and suffix it with "CommandSet" for hierarchical clarity.
2️⃣ Inherit the CommandSet class on the Node.
Add a script to the Node and have it inherit from the CommandSet class.
Note
The CommandSet should auto-complete in your IDE and automatically import the namespace.
If it doesn't, you need to manually import the the namespace at the top of the file:
1 | |
Once that is done, you will get prompted to implement the abstract classes.
For VSCode, press Ctrl + . and choose Import abstract class.
You should now have something like this:
1 2 3 4 5 6 7 8 9 10 | |
3️⃣ Add the command to the Node
The InstantiateCommands is a declarative method that is automatically run by the CommandSet Node to initialize commands.
Any commands returned by this method will be automatically added to the command registry.
To instantiate the command, we will use the Command() shorthand method that is provided by the CommandSet.
This shorthand automatically tags our commands with self-diagnostic metadata.
Tip
For commands that shouldn't be included in release builds of the game you can instead use the shorthand CommandHidden().
Warning
- Do not instantiate commands using the
newkeyword. - Do not instantiate commands outside the
InstantiateCommands()method.
I have written the code for the echo command below...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | |
There is no real performative difference between the two examples. Choose the syntax you like.
Make sure to avoid naming collisions
The echo command is already occupied by the GlobalCommandSet.
Make sure to name your command something else, like my_echo!
4️⃣ Run the command!
That's it!
Now you just need to open up the developer console and type in your new command!
> my_echo Hello world!
Hello world!
Cheat protection is managed automatically. If we temporarily change isCheat parameter to true:
> my_echo Hello world!
my_echo is cheat protected!
> cheatmode 1
Set cheatmode to True
> my_echo Hello world!
Hello world!
🧩 The Command shorthand properties
In the above example we used a custom shorthand provided by the CommandSet API.
This shorthand comes in 2 flavors of parameters: Documented and Quick.
Out of the two, the framework will nudge you to use the documented version.
Note
You can turn off warnings for undocumented commands by enabling:
Project settings [General] > Fractal Pike > Pike Console > Supress Documentation Warnings
The API-Reference contains more information about the Command shorthands.
📄 Documenting the echo command
By applying the information above, we can now document our echo command, like so:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | |
Adding documentation to your commands may feel tedious, but it helps immensely with QA testing, runtime experience and remembering what stuff does 6 months from now.
ℹ️ Godot Lifecycle methods inside a CommandSet Node
The CommandSet Node uses _EnterTree, _Ready and _ExitTree for internal functioning,
thus if you need to access the lifecycle methods within a CommandSet you
override the API-provided wrapper methods instead:
OnEnterTreeOnReadyOnExitTree
The wrapper also contains a method for when cheatmode is edited.
This can be used to force-disable stuff like noclip.
OnCheatModeChanged
Here is that code added to our previous example...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | |
📦 Execution responses
All commands must return a response after execution.
The command response builds on the generic Resonse<T> struct containing a Status and a Message.
The Statement Executor will log any response where the Message is not empty.
Commands denied for being cheat protected are handled automatically.
// This will print to the console.
return new Response<ExecutionResponseStatus> (
ExecutionResponseStatus.InvalidArgs,
"Yo, those arguments are whack!"
);
// This will fail silently
return new Response<ExecutionResponseStatus> (
ExecutionResponseStatus.InvalidArgs,
null
);
To see available responses, check out ExecutionResponseStatus.