반응형
SMALL

이전 강의

https://syntaxack.tistory.com/entry/%EB%A7%88%EC%9D%B8%ED%81%AC%EB%9E%98%ED%94%84%ED%8A%B8%ED%94%8C%EB%9F%AC%EA%B7%B8%EC%9D%B81%EA%B0%95

 

마인크래프트 플러그인 강좌 1강 - 첫 플러그인 만들기

이전 강의https://syntaxack.tistory.com/entry/%EB%A7%88%EC%9D%B8%ED%81%AC%EB%9E%98%ED%94%84%ED%8A%B8%ED%94%8C%EB%9F%AC%EA%B7%B8%EC%9D%B80%EA%B0%95 마인크래프트 플러그인 강좌 0강 - 준비하기마인크래프트 플러그인이란?마인크

syntaxack.tistory.com

아직 1강을 보지 않으신 분들은 보고 오시기 바랍니다!

 

커스텀 커맨드

마인크래프트에서 제공하지 않는 기능들을 플러그인을 통해 직접 만들 수 있습니다! 새로운 명령어를 만들어서 기능을 만들어봅시다.

① 새로운 Java Class 만들기

 

 

 

 

사진에서처럼 패키지를 우클릭하고 New Java Class를 선택해주세요.

 

 

 

 

 

 

 

그럼 이렇게 될 것입니다.

 

 

 

 

자 이제 준비가 되었습니다.

② 코드 작성하기

1. CommandExecutor 구현

package com.example.myplugin;

import org.bukkit.command.CommandExecutor;

public class MyCommandExecutor implements CommandExecutor {

}

우리가 1강에서 했던 것과는 다른 점이 있습니다. 여기서는 implements CommandExecutor을 사용했다는 점입니다. extends와 implements는 비슷해보이지만 약간 다른 기능을 합니다. 간단하게 말하면 extends는 상속받은 메서드를 그대로 사용하거나 오버라이딩이 가능하고, implements에서는 인터페이스의 모든 메서드를 직접 구현해야 합니다.

 

2. onCommand 메서드 구현하기

package org.blog.pluginExample;

import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;

public class MyCommand implements CommandExecutor {

    @Override
    public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
        return false;
    }
}

onCommand의 파라미터(인자 값)에는 Command Sender, Command, label, args 이렇게 구성됩니다. 그리고 앞에 붙는 @NotNull은 인자 값이 Null(값 없음)이 될 수 없음을 나타냅니다.

[Command Sender] : 명령어 실행 주체(플레이어, 콘솔 등)

[Command] : 실행된 명령어 객체

[label] : 실제 사용된 명령어 또는 별칭

[args] : 명령어 뒤에 입력된 매개변수

예시) /myCommand [args1] [args2] 이 명령어를 플레이어가 입력하면 Command Sender은 플레이어가 되고, Command는 이 명령어가 실행하는 내용, label은 /뒤에 붙는 myCommand, args는 args1, args2 에 해당합니다.

onCommand의 반환값이 boolean(논리: 참/거짓)인 이유는 명령어 처리 결과를 bukkit 서버에 전달하기 위해서입니다. boolean 반환값이 true인 경우 명령어가 성공적으로 처리되었음을 서버에 전달합니다. false가 반환되면 plugin.yml에 정의된 사용법이 자동으로 출력됩니다. plugin.yml은 마지막에 작성하기 때문에 그 때 알려드리도록 하겠습니다.

 

3. onCommand 함수 내용 작성하기

이제 명령어를 만들어보도록 하겠습니다. 플레이어가 명령어를 입력하면 "플러그인 작동"이라는 메시지가 출력되도록 하겠습니다. 만약에 콘솔에서 명령어를 입력 시 플레이어가 입력하라는 메시지도 작성해보겠습니다.

package org.blog.pluginExample;

import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;

public class MyCommand implements CommandExecutor {

    @Override
    public boolean onCommand(@NotNull CommandSender sender, Command cmd, @NotNull String label, String[] args) {
        if(cmd.getName().equalsIgnoreCase("test")) {
            if(sender instanceof Player) {
                sender.sendMessage("플러그인 작동");
                return false;
            }
            sender.sendMessage("========================" + "\r  \n"
                    + "                콘솔창에서 입력되었습니다." + "\r\n"
                    + "                플레이어가 치시기 바랍니다." + "\r\n"
                    + "                 ========================");
            return false;
        }

        return true;
    }

}

 

 

 

 

 

만약에 코드에서 빨간색으로 나오면 import를 해주어야 합니다. 따라서 빨간색으로 표시된 부분에 마우스를 올리시면 import class 라는 파란색 메시지가 뜰 것입니다. 그것을 눌러주시면 import 될 것입니다.

 

<코드 설명>

1. public boolean onCommand(@NotNull CommandSender sender, Command cmd, @NotNull String label, String[] args)

onCommand는 명령어의 실행을 처리하는 메서드고 boolean 값은 명령어 처리 여부를 나타냅니다.

sender은 명령어를 실행한 객체를 나타내고(플레이어 또는 콘솔, 커맨드 블록이 되겠죠?)cmd는 실행된 명령어 객체입니다. 명령어 이름이나 매개변수 등을 확인할 수 있습니다.label은 명령어가 실제로 사용된 이름입니다. 예를 들어 /test 명령어를 사용했으면 label은 test입니다.args는 명령어와 함께 전달 된 추가 인자들이 배열로 제공됩니다. 예를 들어서 플레이어1이 플레이어2에게 무엇을 주도록 하고 싶으면 예를 들어서 "/giveto 플레이어1 플레이어2" 라고 할 수 있겠죠?

 

2. if(cmd.getName().equalsIgnoreCase("test")) {

명령어 이름을 대소문자 구분 없이 비교하여 test 명령어가 실행된 경우에만 if문 안의 코드를 실행하게 합니다. 예를 들어서 /test, /TEST를 입력하면 둘 다 실행됩니다.

 

3. if(sender instanceof Player) {

이 명령어는 sender가 Player 객체인지 확인합니다. instanceof 연산자는 객체가 특정 클래스나 인터페이스의 인스턴스인지 확인하는 방법입니다. sender(명령어를 실행한 주체)가 플레이어인 경우 if 문 안의 코드를 실행합니다.

 

4. sender.sendMessage("플러그인 작동");

이 코드는 명령어를 실행한 객체(sender)에게 메세지를 보냅니다. 플레이어가 명령어를 실행하면 플레이어에게 "플러그인 작동"이라는 메세지를 출력합니다.

 

5. return false;

아까 onCommand의 boolean 값이 false가 되면 사용법 메세지가 출력된다고 했죠? 이것을 확인해보기 위해 return false를 한 것입니다.

 

6. sender.sendMessage("========================" + "\r \n" + " 콘솔창에서 입력되었습니다." + "\r\n" + " 플레이어가 치시기 바랍니다." + "\r\n" + " ========================");

이 부분은 콘솔에서 명령어가 입력되었을 때 출력하도록 만든 코드입니다. 이 부분은 나중에 직접 확인해보도록 하겠습니다. 형식은 위에서 플레이어에게 출력되는 메시지 형식과 같습니다.

 

③ plugin.yml 작성하기

plugin.yml은 플러그인의 메타데이터와 기본 설정을 정의하기 위해 사용하는 파일입니다. 이 파일은 플러그인이 로드 될 때 서버가 플러그인에 대한 정보를 읽고 관리할 수 있도록 도와줍니다. 플러그인의 정보, 명령어 등록, 플러그인 의존성 설정, 기타 설정 등을 할 수 있습니다. 우리는 새로운 명령어를 만들었기 때문에 새로운 명령어 등록을 해보겠습니다.

 

 

 

 

파일에서 plugin.yml로 들어가세요.

 

 

 

 

기본적으로 플러그인의 정보가 적혀있을 것입니다. 이는 Minecraft Development Plugin에서 이미 작성해놓았기 때문에 저희가 1강에서 plugin.yml 파일을 작성할 필요가 없었던 것입니다.

이제 여기에 새로운 명령어를 등록해보겠습니다.

description항목 아래에 적어주도록 하겠습니다.

commands:
  test:
    description: "플러그인의 작동 여부를 알려줍니다."
    usage: /test

 

 

 

 

이렇게 말입니다.

④ PluginExample 클래스와 MyCommand 클래스 연결하기

자 이제 다 끝났습니다. 마지막으로 MyCommand에서 정의한 test라는 명령어를 main 파일인 PluginExample 클래스에 정의해 주어야 합니다. 따라서 아래와 같이 코드를 작성해줍니다.

package org.blog.pluginExample;

import org.bukkit.plugin.java.JavaPlugin;

import java.util.Objects;

public final class PluginExample extends JavaPlugin {

    @Override
    public void onEnable() {
        // Plugin startup logic
        getLogger().info("플러그인이 활성화되었습니다.");
        Objects.requireNonNull(this.getCommand("test")).setExecutor(new MyCommand());
    }

    @Override
    public void onDisable() {
        // Plugin shutdown logic
        getLogger().info("플러그인이 비활성화되었습니다.");
    }
}
Objects.requireNonNull(this.getCommand("test")).setExecutor(new MyCommand());

이 코드를 onEnable 영역에 작성해줍니다. 

 

코드를 설명해보자면, "test"라는 이름의 명령어에 대해 MyCommand 클래스를 명령어 실행 처리기로 설정하는 것입니다.

<코드 설명>

1. this.getCommand("test"):

이 코드는 현재 플러그인에서 "test"라는 이름을 가진 명령어를 가져옵니다. 이 명령어는 plugin.yml 파일에서 정의된 명령어 중 하나여야 합니다. 예를 들어서 plugin.yml에 아래와 같이 명령어가 정의되어 있어야 합니다.

commands:
  test:
    description: "Test command"

 

2. Objects.requireNonNull(this.getCommand("test")):

getCommand 메서드는 "test" 명령어를 찾을 수 있으면 해당 명령어 객체를 반환하고, 명령어가 존재하지 않으면 null을 반환합니다. Objects.requireNonNull은 null이 반환될 경우 NullPointerException을 던집니다. 이는 "test" 명령어가 plugin.yml에 정의되지 않았거나, 명령어가 올바르게 로드되지 않을 때 발생합니다.

3. .setExecutor(new MyCommand()):

setExecutor() 메서드는 명령어가 실행되었을 때 호출할 실행 처리기(executor)을 설정합니다. MyCommand()는 CommandExecutor 인터페이스를 구현한 클래스여야 합니다. new MyCommand()는 MyCommand 클래스의 새 인스턴스를 생성하여 그 인스턴스를 "test" 명령어의 실행 처리기로 설정하는 것입니다. 즉 "test" 명령어가 호출되면 MyCommand 클래스의 메서드가 실행됩니다.

4. 이 코드를 onEnable()에 작성하는 이유:

onEnable은 플러그인이 서버에 로드될 때 호출되는 메서드입니다. 이 메서드는 플러그인이 활성화 될 때 필요한 초기 설정이나 객체들을 설정하는 데 사용됩니다.

 

⑤ jar 파일 빌드하기

이 부분은 1강을 보고 오시면 jar 파일을 어떻게 빌드하는지 확인 하실 수 있습니다.

 

⑥ 플러그인이 잘 적용되었는지 확인하고 명령어 테스트하기

server.bat을 실행시키시고 마인크래프트를 실행해주세요.

그 다음 첫번째로 마인크래프트에서 /test 명령어를 입력해보세요.

 

 

 

 

잘 작동되는 모습을 확인할 수 있습니다.

 

다음으로는 서버 콘솔에서 명령어를 입력해보세요.

 

 

 

 

정상적으로 작동되는 것을 확인할 수 있습니다. 위에서 설명했듯이 플러그인 usage가 출력되는 것을 확인할 수 있습니다. 아까 return false를 하였기 때문입니다.

 

마무리

오늘은 커스텀 명령어를 구현해보았습니다. 마인크래프트 플러그인 개발은 관련 문서를 보시면 더 공부하실 수 있습니다. 궁금하신 것이 있으시면 댓글 달아주시고, 성심성의껏 답변해드리겠습니다! 좋아요 한 번씩 눌러주세요!

반응형
LIST