Skip to content

Commit

Permalink
Document new CommandAPI#unregister behavior
Browse files Browse the repository at this point in the history
  • Loading branch information
willkroboth committed Aug 11, 2023
1 parent 200ba45 commit 8826219
Show file tree
Hide file tree
Showing 6 changed files with 484 additions and 65 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scoreboard.DisplaySlot;
import org.bukkit.scoreboard.Objective;
import org.bukkit.scoreboard.Scoreboard;
Expand Down Expand Up @@ -1393,19 +1394,118 @@ void commandRegistration() {
})
.register();
/* ANCHOR_END: commandRegistration1 */
}

/* ANCHOR: commandRegistration2 */
// Unregister the gamemode command from the server (by force)
CommandAPI.unregister("gamemode", true);
class CommandUnregistration {
class UnregistrationBukkit extends JavaPlugin {
/* ANCHOR: commandUnregistrationBukkit */
@Override
public void onLoad() {
CommandAPIBukkit.unregister("version", true, true);
}
/* ANCHOR_END: commandUnregistrationBukkit */
}

// Register our new /gamemode, with survival, creative, adventure and spectator
new CommandAPICommand("gamemode")
.withArguments(new MultiLiteralArgument("gamemodes", "survival", "creative", "adventure", "spectator"))
.executes((sender, args) -> {
// Implementation of our /gamemode command
})
.register();
/* ANCHOR_END: commandRegistration2 */
class UnregistrationVanilla extends JavaPlugin {
/* ANCHOR: commandUnregistrationVanilla */
@Override
public void onEnable() {
CommandAPI.unregister("gamemode");
}
/* ANCHOR_END: commandUnregistrationVanilla */
}

class UnregistrationReplaceVanilla extends JavaPlugin {
/* ANCHOR: commandUnregistrationReplaceVanilla */
@Override
public void onEnable() {
CommandAPI.unregister("gamemode");

// Register our new /gamemode, with survival, creative, adventure and spectator
new CommandAPICommand("gamemode")
.withArguments(new MultiLiteralArgument("gamemodes", "survival", "creative", "adventure", "spectator"))
.executes((sender, args) -> {
// Implementation of our /gamemode command
})
.register();
}
/* ANCHOR_END: commandUnregistrationReplaceVanilla */
}

class UnregistrationPlugin extends JavaPlugin {
/* ANCHOR: commandUnregistrationPlugin */
@Override
public void onEnable() {
CommandAPIBukkit.unregister("luckperms:luckperms", false, true);
}
/* ANCHOR_END: commandUnregistrationPlugin */
}

class UnregistrationCommandAPI extends JavaPlugin {
/* ANCHOR: commandUnregistrationCommandAPI */
@Override
public void onEnable() {
CommandAPI.unregister("break");
}
/* ANCHOR_END: commandUnregistrationCommandAPI */
}

class UnregistrationBukkitHelp extends JavaPlugin {
/* ANCHOR: commandUnregistrationBukkitHelp */
@Override
public void onEnable() {
new BukkitRunnable() {
@Override
public void run() {
CommandAPIBukkit.unregister("help", false, true);
}
}.runTaskLater(this, 0);
}
/* ANCHOR_END: commandUnregistrationBukkitHelp */
}

class UnregistrationOnlyVanillaNamespace extends JavaPlugin {
/* ANCHOR: commandUnregistrationOnlyVanillaNamespace */
@Override
public void onEnable() {
new BukkitRunnable() {
@Override
public void run() {
CommandAPI.unregister("minecraft:gamemode");
}
}.runTaskLater(this, 0);
}
/* ANCHOR_END: commandUnregistrationOnlyVanillaNamespace */
}

class UnregistrationDealyedVanillaBad extends JavaPlugin {
/* ANCHOR: commandUnregistrationDealyedVanillaBad */
// NOT RECOMMENDED
@Override
public void onEnable() {
new BukkitRunnable() {
@Override
public void run() {
CommandAPI.unregister("gamemode");
}
}.runTaskLater(this, 0);
}
/* ANCHOR_END: commandUnregistrationDealyedVanillaBad */
}

class UnregistrationDealyedVanillaBetter extends JavaPlugin {
/* ANCHOR: commandUnregistrationDealyedVanillaBetter */
@Override
public void onEnable() {
new BukkitRunnable() {
@Override
public void run() {
CommandAPI.unregister("gamemode", true);
}
}.runTaskLater(this, 0);
}
/* ANCHOR_END: commandUnregistrationDealyedVanillaBetter */
}
}

class commandTrees extends JavaPlugin {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import org.bukkit.metadata.FixedMetadataValue
import org.bukkit.plugin.java.JavaPlugin
import org.bukkit.potion.PotionEffect
import org.bukkit.potion.PotionEffectType
import org.bukkit.scheduler.BukkitRunnable
import org.bukkit.scoreboard.DisplaySlot
import org.bukkit.scoreboard.Objective
import org.bukkit.scoreboard.Team
Expand Down Expand Up @@ -1309,19 +1310,105 @@ CommandAPICommand("broadcastmsg")
})
.register()
/* ANCHOR_END: commandRegistration1 */
}

/* ANCHOR: commandRegistration2 */
// Unregister the gamemode command from the server (by force)
CommandAPI.unregister("gamemode", true)
class CommandUnregistration {
class UnregistrationBukkit : JavaPlugin() {
/* ANCHOR: commandUnregistrationBukkit */
override fun onLoad() {
CommandAPIBukkit.unregister("version", false, true)
}
/* ANCHOR_END: commandUnregistrationBukkit */
}

// Register our new /gamemode, with survival, creative, adventure and spectator
CommandAPICommand("gamemode")
.withArguments(MultiLiteralArgument("gamemodes", "survival", "creative", "adventure", "spectator"))
.executes(CommandExecutor { sender, args ->
// Implementation of our /gamemode command
})
.register()
/* ANCHOR_END: commandRegistration2 */
class UnregistrationVanilla : JavaPlugin() {
/* ANCHOR: commandUnregistrationVanilla */
override fun onEnable() {
CommandAPI.unregister("gamemode")
}
/* ANCHOR_END: commandUnregistrationVanilla */
}

class UnregistrationReplaceVanilla : JavaPlugin() {
/* ANCHOR: commandUnregistrationReplaceVanilla */
override fun onEnable() {
CommandAPI.unregister("gamemode");

// Register our new /gamemode, with survival, creative, adventure and spectator
CommandAPICommand("gamemode")
.withArguments(MultiLiteralArgument("gamemodes", "survival", "creative", "adventure", "spectator"))
.executes(CommandExecutor { sender, args ->
// Implementation of our /gamemode command
})
.register()
}
/* ANCHOR_END: commandUnregistrationReplaceVanilla */
}

class UnregistrationPlugin : JavaPlugin() {
/* ANCHOR: commandUnregistrationPlugin */
override fun onEnable() {
CommandAPIBukkit.unregister("luckperms:luckperms", false, true)
}
/* ANCHOR_END: commandUnregistrationPlugin */
}

class UnregistrationCommandAPI : JavaPlugin() {
/* ANCHOR: commandUnregistrationCommandAPI */
override fun onEnable() {
CommandAPI.unregister("break")
}
/* ANCHOR_END: commandUnregistrationCommandAPI */
}

class UnregistrationBukkitHelp : JavaPlugin() {
/* ANCHOR: commandUnregistrationBukkitHelp */
override fun onEnable() {
object : BukkitRunnable() {
override fun run() {
CommandAPIBukkit.unregister("help", false, true)
}
}.runTaskLater(this, 0)
}
/* ANCHOR_END: commandUnregistrationBukkitHelp */
}

class UnregistrationOnlyVanillaNamespace : JavaPlugin() {
/* ANCHOR: commandUnregistrationOnlyVanillaNamespace */
override fun onEnable() {
object : BukkitRunnable() {
override fun run() {
CommandAPI.unregister("minecraft:gamemode")
}
}.runTaskLater(this, 0)
}
/* ANCHOR_END: commandUnregistrationOnlyVanillaNamespace */
}

class UnregistrationDealyedVanillaBad : JavaPlugin() {
/* ANCHOR: commandUnregistrationDealyedVanillaBad */
// NOT RECOMMENDED
override fun onEnable() {
object : BukkitRunnable() {
override fun run() {
CommandAPI.unregister("gamemode")
}
}.runTaskLater(this, 0)
}
/* ANCHOR_END: commandUnregistrationDealyedVanillaBad */
}

class UnregistrationDealyedVanillaBetter : JavaPlugin() {
/* ANCHOR: commandUnregistrationDealyedVanillaBetter */
override fun onEnable() {
object : BukkitRunnable() {
override fun run() {
CommandAPI.unregister("gamemode", true)
}
}.runTaskLater(this, 0)
}
/* ANCHOR_END: commandUnregistrationDealyedVanillaBetter */
}
}

class commandTrees : JavaPlugin() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ void testOnEnableRegisterAndUnregisterCommand() {
// You would expect namespace to succeed since it is in the CommandMap
// However, running that command simply tells the Brig dispatcher to run the original command
// The command was removed from the Brig dispacter, so it doesn't actually know how to do that
// I'm going to say this is not a bug, just an example why you should be careful when unregistering commands
// This behavior is documented at the bottom of the docs page for Command unregistration
// As a result, this test doesn't actually pass
// // Namespace command should still work
// assertStoresResult(runCommandsPlayer, "minecraft:command argument", results, "argument");
Expand Down
1 change: 1 addition & 0 deletions docssrc/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
# Creating Commands

- [Command registration](./commandregistration.md)
- [Command unregistration](./commandunregistration.md)
- [Command executors](./commandexecutors.md)
- [Normal command executors](./normalexecutors.md)
- [Proxied commandsenders](./proxysender.md)
Expand Down
43 changes: 1 addition & 42 deletions docssrc/src/commandregistration.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,49 +179,8 @@ Registers the command.
It is recommended to register commands in either the `onLoad()` or `onEnable()` method. With the CommandAPI, depending on whether you use `onLoad()` or `onEnable()` to load your commands depends on whether your plugin is used with Minecraft's functions:

| When to load | What to do |
| ------------------- | -------------------------------------------------------------------------------------------------------------- |
|---------------------|----------------------------------------------------------------------------------------------------------------|
| `onLoad()` method | Register commands to be used in Minecraft functions ([see the Function section for more info](functions.html)) |
| `onEnable()` method | Register regular commands |

The CommandAPI does support registering commands outside of these methods while the server is running. Commands registered after the server is done loading _should_ work the same as commands registered in `onEnable`.

-----

## Command unregistration

The CommandAPI has support to unregister commands completely from Minecraft's command list. This includes Minecraft built in commands!

<div class="warning">

**Developer's Note:**

Command unregistration, although powerful, is not recommended! It is the CommandAPI's most "dangerous" feature as it can cause unexpected side effects, such as command blocks executing commands you wouldn't expect them to. In almost every case, I'd recommend just creating a new command instead of unregistering one to replace it.

For instance, instead of unregistering `/gamemode`, you could register a command `/gm` or `/changegamemode`.

</div>

| Method | Result |
| -------------------------------------------------- | ------------------------------------------------------------ |
| `CommandAPI.unregister(String cmd)` | Unregisters a command from the game |
| `CommandAPI.unregister(String cmd, boolean force)` | Attempts to unregister a command from the game by force. This includes `/minecraft:cmd`, `/bukkit:cmd` and `/spigot:cmd` commands as well. |

<div class="example">

### Example - Replacing Minecraft's `/gamemode` command

To replace a command, we can first unregister it and then register our implementation of that command.

<div class="multi-pre">

```java,Java
{{#include ../../commandapi-documentation-code/src/main/java/dev/jorel/commandapi/examples/java/Examples.java:commandRegistration2}}
```

```kotlin,Kotlin
{{#include ../../commandapi-documentation-code/src/main/kotlin/dev/jorel/commandapi/examples/kotlin/Examples.kt:commandRegistration2}}
```

</div>

</div>
Loading

0 comments on commit 8826219

Please sign in to comment.