
이번 글에서는 명령어에 대해 다루고, 명령어를 꾸미는 법에 대해 알아보려고한다.
이 글에서 다룰 명령어는 두가지 종류이다.
- argument가 없는 명령어
- argument가 있는 명령어
전자는 “/돈”을 입력하면 잔액을 출력하는 것처럼 단순한 명령어를 말하고 후자는 /수표 1000 처럼 1000이나 100000처럼 동적으로 데이터가 변경되는 명령어를 말한다.
argument가 없는 명령어
먼저 “돈” 명령어부터 만들어보자

command 패키지를 만들고 BillProviderCommand와 MyMoneyCommand를 만들어 주었다. 전자는 수표를 지급하는 명령어를 작성할 것이고 후자는 내 돈을 보여줄 명령어이다.
MyMoneyCommand 클래스부터 작성해보자
public MyMoneyCommand(CommandDispatcher<CommandSourceStack> dispatcher) {
dispatcher.register(Commands.literal("돈").executes((command) -> {
return execute(command.getSource());
}));
}
클래스에 위와같은 메서드를 추가해주었다.
dipatcher에 명령어를 등록해주었다. Commands.literal("돈").executes
안에는 “/돈”을 입력 했을때 , 어떤 기능이 수행될지 코드를 작성한다. 나는 excute라는 메서드를 만들어 따로 작성해주었다.
private int execute(CommandSourceStack source) throws CommandSyntaxException {
if (source.getEntity() instanceof ServerPlayer player) {
String playerName = player.getName().getString();
Integer MONEY = new PlayerData().getMoney(player);
if (MONEY != null) {
source.sendSuccess(() -> Component.literal(playerName + "님의 돈: " + MONEY + "원")
.setStyle(Style.EMPTY.withColor(ChatFormatting.GREEN) // 빨간색
.withBold(true) // 굵게
.withItalic(true)), false);
}
} else {
source.sendFailure(Component.literal("이 명령어는 플레이어만 사용할 수 있습니다!"));
}
return Command.SINGLE_SUCCESS;
}
위 코드는 명령어를 입력했을 때, 어떤 기능을 할 지를 작성한 코드이다.
playerName 은 플레이어의 아이디를 가져오고, MONEY 는 저번 글에서 만든 데이터 공급자이다.
그리고 명령에 대한 응답을 전송하는 부분에는 sendFailure과 sendSuccess 외에도 두가지가 더 있는데 다음 표를 살펴보자
메서드 |
목적 |
메시지 출력 대상 |
특성 |
sendSuccess() |
명령어 실행 성공 시 출력 |
명령어 실행한 플레이어 |
- Supplier<Component> 로 메시지를 지연 생성- 운영자들에게도 메시지를 브로드캐스트 가능 (broadcastToOps ) |
sendFailure() |
명령어 실행 실패 시 출력 |
명령어 실행한 플레이어 |
- Component 객체로 즉시 메시지를 전달- 실패 메시지 출력 |
sendSystemMessage() |
시스템 관련 메시지 출력 |
서버의 관리자/콘솔 |
- 서버 관련 시스템 메시지를 출력- 관리자가 볼 수 있는 메시지로 사용 |
sendChatMessage() |
모든 플레이어에게 채팅 형식 메시지 전송 |
모든 플레이어 |
- 모든 플레이어에게 메시지를 전달- 채팅 형식으로 출력 |
/돈 을 입력했을 때, 잔액은 그 유저에게만 보이면 되므로, sendSuccess
를 사용하자.
source.sendSuccess(() -> Component.literal(playerName + "님의 돈: " + MONEY + "원")
.setStyle(Style.EMPTY.withColor(ChatFormatting.GREEN) // 초록색
.withBold(true) // 굵게
.withItalic(true)), false);
위 코드는 답변을 전송하는 것인데, setStyle로 답변의 색깔이나 굵기, 기울기를 정할 수도 있다. 위 코드는 색깔을 초록색으로, 굵고 기울어진 메세지를 전송하는 코드이다.
이렇게 코드를 작성했다면, 명령어도 등록해주어야 한다.
@EventBusSubscriber(modid = MODID, bus = EventBusSubscriber.Bus.GAME)
public static class ServerModEvents {
@SubscribeEvent
public static void onRegisterCommands(RegisterCommandsEvent event) {
CommandDispatcher<CommandSourceStack> dispatcher = event.getDispatcher();
new MyMoneyCommand(dispatcher);
LOGGER.info("[MyMod] SUCCESS: Commands registered");
}
}
프로젝트에서 메인메서드가 실행되는 클래스에 위와같은 코드를 작성하여 명령어를 등록해준다.
그 후 runClient를 실행하여 잘 작동이 되나 확인해보자.


위와 같이 초기 값인 100000원이 잘 나온다.
argument가 있는 명령어
이제 “/수표 10000”처럼 특정 argument가 있는 명령어를 제작해보자.
이 명령어의 기능은 일정한 금액의 수표를 발급하는 것이다.
“BillProviderCommand” 클래스에 다음과 같은 소스를 작성하자.
public class BillProviderCommand {
public BillProviderCommand(CommandDispatcher<CommandSourceStack> dispatcher) {
dispatcher.register(Commands.literal("수표")
.then(Commands.argument("amount", IntegerArgumentType.integer()) // 'amount'는 액수 입력 받기
.executes((command) -> {
int amount = IntegerArgumentType.getInteger(command, "amount"); // 액수 얻기
return execute(command.getSource(),amount);
})));
}
private int execute(CommandSourceStack source,Integer amount) throws CommandSyntaxException {
if (source.getEntity() instanceof ServerPlayer player) {
PlayerData playerData = new PlayerData();
int MONEY = playerData.getMoney(player);
} else {
source.sendFailure(Component.literal("이 명령어는 플레이어만 사용할 수 있습니다!"));
}
return Command.SINGLE_SUCCESS;
}
}
Command.argument부분에 argument의 이름과 타입을 정해준다. /수표 는 숫자값을 받으므로 Integer로 정했다. 그리고 명령어 실행 부분인 excute에는 금액인 amount를 매개변수로 받는다.
if (MONEY >= amount) {
source.sendSuccess(() -> Component.literal("수표 " + amount + "원이 발급되었습니다. 현재 잔액: " + (MONEY - amount) +"원")
setStyle(Style.EMPTY.withColor(ChatFormatting.GREEN)
.withBold(true) // 굵게
.withItalic(true)), false);
playerData.addMoney(player, -1*amount);
ItemStack BILL = new ItemStack(ModItems.BILL_ITEM.get());
player.addItem(BILL);
}else{
source.sendSuccess(() -> Component.literal("잔액이 부족합니다. 현재 잔액: " + MONEY +"원")
.setStyle(Style.EMPTY.withColor(ChatFormatting.RED)), false);
}
위 부분은 수표를 지급하는 코드이다. 만약 현재 잔액이 수표액수보다 많다면 지급을 허용하고 유저의 인벤토리에 아이템을 넣어준다. 하지만 부족하면 지급을 거절한다.
전체코드는 다음과 같다.
public class BillProviderCommand {
public BillProviderCommand(CommandDispatcher<CommandSourceStack> dispatcher) {
dispatcher.register(Commands.literal("수표")
.then(Commands.argument("amount", IntegerArgumentType.integer()) // 'amount'는 액수 입력 받기
.executes((command) -> {
int amount = IntegerArgumentType.getInteger(command, "amount"); // 액수 얻기
return execute(command.getSource(),amount);
})));
}
private int execute(CommandSourceStack source,Integer amount) throws CommandSyntaxException {
if (source.getEntity() instanceof ServerPlayer player) {
PlayerData playerData = new PlayerData();
int MONEY = playerData.getMoney(player);
if (MONEY >= amount) {
source.sendSuccess(() -> Component.literal("수표 " + amount + "원이 발급되었습니다. 현재 잔액: " + (MONEY - amount) +"원")
.setStyle(Style.EMPTY.withColor(ChatFormatting.GREEN)
.withBold(true) // 굵게
.withItalic(true)), false);
playerData.addMoney(player, -1*amount);
ItemStack BILL = new ItemStack(ModItems.BILL_ITEM.get());
BILL.set(BillDataComponent.VALUE,amount);
player.addItem(BILL);
}else{
source.sendSuccess(() -> Component.literal("잔액이 부족합니다. 현재 잔액: " + MONEY +"원")
.setStyle(Style.EMPTY.withColor(ChatFormatting.RED)), false);
}
} else {
source.sendFailure(Component.literal("이 명령어는 플레이어만 사용할 수 있습니다!"));
}
return Command.SINGLE_SUCCESS;
}
}
이것도 argument가 없는 명령어에서 한 것처럼 메인 클래스에 등록한 후 테스트해보자
위와 같이 잘 된다.