Building a Custom Command System
Create a chat-based command system for your realm with custom commands, permissions, and help.
Why Custom Commands?
It's a more simple way to add custom commands rather than registering a ton of /commands. A command system lets you build your own: !tp, !home, !shop, etc. By intercepting chat messages that start with !, you can parse them and execute custom logic.
The basic pattern: listen to chat, check if it's a command, parse arguments, execute logic.
Basic Command Parser
The foundation: catch chat messages starting with ! and route them to handlers:
world.beforeEvents.chatSend.subscribe((event) => {
const message = event.message;
if (!message.startsWith("!")) return;
event.cancel = true;
const parts = message.slice(1).split(" ");
const command = parts[0];
const args = parts.slice(1);
handleCommand(event.sender, command, args);
});
function handleCommand(player, command, args) {
switch (command) {
case "help":
showHelp(player);
break;
case "teleport":
teleportCommand(player, args);
break;
case "give":
giveCommand(player, args);
break;
default:
player.sendMessage("§cUnknown command");
}
}
Permission Checks
Not all players should be able to run all commands. Teleporting admins might want to restrict who can use certain features. This function checks if a player has permission:
const admins = ["admin_uuid_1", "admin_uuid_2"];
function hasPermission(player, permission) {
if (admins.includes(player.id)) return true;
switch (permission) {
case "admin":
return admins.includes(player.id);
case "mod":
return admins.includes(player.id); // Could expand this
default:
return true;
}
}
function teleportCommand(player, args) {
if (!hasPermission(player, "admin")) {
player.sendMessage("§cYou don't have permission for this command");
return;
}
if (args.length < 3) {
player.sendMessage("§cUsage: /tp <x> <y> <z>");
return;
}
const [x, y, z] = args.map(Number);
player.teleport({ x, y, z });
}
Command with Cooldown
Commands can be abused - players might spam teleport or spam gifts. A cooldown prevents this by forcing users to wait between uses:
const cooldowns = new Map();
function teleportCommand(player, args) {
const now = Date.now();
const cooldownTime = 5000; // 5 seconds
if (cooldowns.has(player.id)) {
const lastUse = cooldowns.get(player.id);
const remaining = Math.ceil((cooldownTime - (now - lastUse)) / 1000);
if (now - lastUse < cooldownTime) {
player.sendMessage(`§cPlease wait ${remaining}s`);
return;
}
}
cooldowns.set(player.id, now);
player.sendMessage("§aCommand executed!");
}
Help System
const commands = {
help: { description: "Show this help message" },
teleport: { description: "Teleport to coordinates", usage: "/tp <x> <y> <z>" },
give: { description: "Give items to players", usage: "/give <player> <item>" }
};
function showHelp(player) {
player.sendMessage("§6=== Commands ===");
Object.entries(commands).forEach(([cmd, info]) => {
player.sendMessage(`§e!${cmd}§r - ${info.description}`);
if (info.usage) {
player.sendMessage(` §7${info.usage}`);
}
});
}
Best Practices
- Always validate arguments
- Provide clear error messages
- Use permission systems for admin commands
- Implement cooldowns to prevent spam
- Log important command executions