[Java] Spigot plugin development --Register the command as a vanilla command

Overview

-Normally, the command to be registered in plugin.yml is registered as a vanilla command.

Target audience

・ The environment for plug-in development is in place.

environment

・ Windows 10 --1909 -Eclipse IDE Version: 2020-06 (4.16.0) ・ Minecraft 1.16.1 ・ Spigot 1.16.1

Caution

This uses the command engine brigadier added from Minecraft 1.13, so it may not be possible with versions below 1.13.

Command to create

-This time, we will safely create a command to "make the player fly". -Command syntax /fly <player> allow

Source code and description

・ First, let's create a class.

FlyCommand.java


package com.hamusuke.qiita.command;

import java.util.Collection;

import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;

import net.minecraft.server.v1_16_R1.ArgumentEntity;
import net.minecraft.server.v1_16_R1.ChatMessage;
import net.minecraft.server.v1_16_R1.CommandListenerWrapper;
import net.minecraft.server.v1_16_R1.EntityPlayer;

public class FlyCommand {
	public static void register(CommandDispatcher<CommandListenerWrapper> dispatcher) {
		LiteralArgumentBuilder<CommandListenerWrapper> literalArgumentBuilder = net.minecraft.server.v1_16_R1.CommandDispatcher.a("fly").requires((permission) -> {
			return permission.hasPermission(2);
		}).then(net.minecraft.server.v1_16_R1.CommandDispatcher.a("target", ArgumentEntity.d()).then(net.minecraft.server.v1_16_R1.CommandDispatcher.a("allow").executes((commandcontext) -> {
			return execute(commandcontext.getSource(), ArgumentEntity.f(commandcontext, "target"));
		})));

		dispatcher.register(literalArgumentBuilder);
	}

	private static int execute(CommandListenerWrapper commandListenerWrapper, Collection<EntityPlayer> players) {
		for(EntityPlayer entityPlayer : players) {
			entityPlayer.abilities.canFly = true;
			entityPlayer.updateAbilities();
		}

		if(players.size() == 1) {
			commandListenerWrapper.sendMessage(new ChatMessage("%Made s flyable", new Object[] {players.iterator().next().getScoreboardDisplayName()}), true);
		}else {
			commandListenerWrapper.sendMessage(new ChatMessage("%Made s players flyable", new Object[] {players.size()}), true);
		}

		return players.size();
	}
}

public static void register(CommandDispatcher<CommandListenerWrapper> dispatcher) {

-Create a method for command registration. · CommandDispatcher is for com.mojang.brigadier.CommandDispatcher

LiteralArgumentBuilder<CommandListenerWrapper> literalArgumentBuilder = net.minecraft.server.v1_16_R1.CommandDispatcher.a("fly").requires((permission) -> {
	return permission.hasPermission(2);
}).then(net.minecraft.server.v1_16_R1.CommandDispatcher.a("target", ArgumentEntity.d()).then(net.minecraft.server.v1_16_R1.CommandDispatcher.a("allow").executes((commandcontext) -> {
	return execute(commandcontext.getSource(), ArgumentEntity.f(commandcontext, "target"));
})));

Net.minecraft.server.v1_16_R1.CommandDispatcher.a ("fly ") This is the / fly part.

Requires ((permission)-> { return permission.hasPermission(2); }); Specifies the privilege level at which the command can be executed. If you specify 2, only players with administrator privileges can execute it.

Then (net.minecraft.server.v1_16_R1.CommandDispatcher.a ("target", ArgumentEntity.d ()). then (net.minecraft.server.v1_16_R1.CommandDispatcher.a ("allow")) The syntax after / fly ʻArgumentEntity.d ()` is used when you want to specify only the player. If you specify an entity such as @e, you will get an error like this. Untitled.jpg

executes((commandcontext) -> {
    return execute(commandcontext.getSource(), ArgumentEntity.f(commandcontext, "target"));
})

-/ Fly Describes the processing when allow is executed. -You can get CommandListenerWrapper withgetSource (). -You can get Collection <EntityPlayer> with ʻArgumentEntity.f (commandcontext," target ")`.

dispatcher.register(literalArgumentBuilder);

-The command syntax is registered.

for(EntityPlayer entityPlayer : players) {
    entityPlayer.abilities.canFly = true;
    entityPlayer.updateAbilities();
}

-You can fly with ʻentityPlayer.abilities.canFly = true. • ʻentityPlayer.updateAbilities () sends to the server that the player's abilities(entityPlayer.abilities)have changed. Be sure to include this when you make changes.

if(players.size() == 1) {
    commandListenerWrapper.sendMessage(new ChatMessage("%Made s flyable", new Object[] {players.iterator().next().getScoreboardDisplayName()}), true);
}else {
    commandListenerWrapper.sendMessage(new ChatMessage("%Made s players flyable", new Object[] {players.size()}), true);
}

· CommandListenerWrapper.sendMessage () sends a message to the command sender. -If you use getScoreboardDisplayName (), the information will be displayed when you move the cursor like this. Untitled 1.jpg -If true is specified, it will be sent to other players and server logs. -If false is specified, only the command sender will be sent.

Main.java


package com.hamusuke.qiita;

import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_16_R1.CraftServer;
import org.bukkit.plugin.java.JavaPlugin;

import com.hamusuke.qiita.command.FlyCommand;
import com.mojang.brigadier.CommandDispatcher;

import net.minecraft.server.v1_16_R1.CommandListenerWrapper;
import net.minecraft.server.v1_16_R1.DedicatedServer;

public class Main extends JavaPlugin {
	@Override
	public void onEnable() {
		DedicatedServer dedicatedServer = ((CraftServer)Bukkit.getServer()).getServer();
		CommandDispatcher<CommandListenerWrapper> dispatcher = dedicatedServer.vanillaCommandDispatcher.a();
		
  		FlyCommand.register(dispatcher);
  		getLogger().info("registered fly command");
	}
}

-OnEnable () is called when the plug-in is loaded, so register the command here.

Try putting it on the server

無題3.jpg I have registered firmly. 無題2.jpg You can fly.

Since it is registered as a vanilla command, it will be / minecraft: fly. (minecraft: can be omitted)

Good point

-Functions like a vanilla command. -It is not necessary to describe it in plugin.yml. -It is not necessary to create a class for tab completion.

bad place

-The code tends to be long. (Difficult to see)

At the end

Thank you for reading the article. This is the first time I've written an article, so it may have been difficult to understand.

Recommended Posts

[Java] Spigot plugin development --Register the command as a vanilla command
Register as a package on PyPI
Notice the completion of a time-consuming command