본문 바로가기
마인크래프트/플러그인 제작 강좌(자바)

[자바로 마크 Paper 플러그인 만들기]3. 유저 데이터 관리하기(2) - 명령어 만들기

by Zepelown 2024. 1. 16.

*본 강의는 1.20.2 Paper 기준으로 제작되었습니다*

 

이전 강의

[자바로 마크 Paper 플러그인 만들기]2. 유저 데이터 관리하기(1) - 이벤트 처리 (tistory.com)

 

[자바로 마크 Paper 플러그인 만들기]2. 유저 데이터 관리하기(1) - 이벤트 처리

*본 강의는 1.20.2 Paper 기준으로 제작되었습니다* 이전 강의 [자바로 마크 Paper 플러그인 만들기]1. 기본 세팅하기 (tistory.com) [자바로 마크 Paper 플러그인 만들기]1. 기본 세팅하기 안녕하세요. 이전

zepelown.tistory.com

 

참고하면 좋은 강의

[인텔리제이로 마크 플러그인 개발하기]5. 나만의 명령어 만들기 (give, help 명령어 만들어보기) (tistory.com)

 

[인텔리제이로 마크 플러그인 개발하기]5. 나만의 명령어 만들기 (give, help 명령어 만들어보기)

*이 글은 Spigot 1.19.2 버전을 기준으로 하여 제작되었습니다. 이전화 https://zepelown.tistory.com/41 [인텔리제이로 마크 플러그인 개발하기]4. 나만의 아이템 제작하기 (ItemStack, ItemMeta에 관하여) *이 글은

zepelown.tistory.com

 


미리 보는 결과물 

그림1. 인게임 내에서 명령어 "uinfo" 입력 시 모습

 

그림 2. 플레이어 입퇴장 시 기록 남기는 모습


개요

이전 강의에서 이어서 진행합니다.

 

이벤트 처리가 끝났으니

 

명령어를 만들어 결과를 확인해 봅시다.

 

만들 명령어는 /uinfo로 이 명령어를 친 사용자의 정보를 화면에 뿌려주는 기능이 있습니다.


기능 구현 단계

그림 3. 컨트롤러 패키지 구조

 

기본적인 베이스는 이전 1강에서 만들었습니다.

 

이어서 UserInfoCommand 클래스를 만들어줍시다.

 

controller.UserInfoCommand

package org.blog.paperedu.user.management.controller.commands;

import org.blog.paperedu.user.management.entity.User;
import org.blog.paperedu.user.management.service.UserManager;
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 UserInfoCommand implements CommandExecutor {

    private final UserManager userManager;

    public UserInfoCommand(UserManager userManager){
        this.userManager = userManager;
    }

    @Override
    public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
                             @NotNull String[] args) {
        if (!(sender instanceof Player)){
            sender.sendMessage("플레이어만 입력이 가능합니다.");
            return false;
        }

        Player player = (Player) sender;
        User playerData = userManager.getUserData(player);

        player.sendMessage("----------------------------");
        player.sendMessage(String.format("이름 : %s", playerData.getDisplayName()));
        player.sendMessage(String.format("직업 : %s", playerData.getJob()));
        player.sendMessage(String.format("랭크 : %s", playerData.getRank()));
        player.sendMessage(String.format("칭호 : %s", playerData.getPrefix()));
        player.sendMessage(String.format("소지 금액 : %s", playerData.getMoney()));
        player.sendMessage("----------------------------");


        playerData.setMoney(playerData.getMoney() + 10L);

        return false;
    }
}

 

사용자가 명령어를 입력했을 때 어떤 행동을 진행하는지를 나타내는 곳입니다.

 

우린 이 명령어를 사용할 때 플레이어에게 자신의 정보를 알려주고 싶습니다.

 

그렇기 때문에, 플레이어의 정보를 가지고 있는 UserManager의 인스턴스가 필요합니다.

 

그걸 생성자로 받아옵니다.

 

그림 4. CommandExecutor를 확장하는 UserInfoCommand 클래스

PaperAPI에서 커맨드를 만들기 위해선 CommandExecutor 인터페이스를 Implements 합니다.

 

그렇게 사용하는 메소드가 바로 onCommand()입니다.

 

    @Override
    public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
                             @NotNull String[] args) {
        if (!(sender instanceof Player)){
            sender.sendMessage("플레이어만 입력이 가능합니다.");
            return false;
        }

        Player player = (Player) sender;
        User playerData = userManager.getUserData(player);

        player.sendMessage("----------------------------");
        player.sendMessage(String.format("이름 : %s", playerData.getDisplayName()));
        player.sendMessage(String.format("직업 : %s", playerData.getJob()));
        player.sendMessage(String.format("랭크 : %s", playerData.getRank()));
        player.sendMessage(String.format("칭호 : %s", playerData.getPrefix()));
        player.sendMessage(String.format("소지 금액 : %s", playerData.getMoney()));
        player.sendMessage("----------------------------");


        playerData.setMoney(playerData.getMoney() + 10L);

        return false;
    }

파라미터가 좀 많습니다.

 

하지만 그렇게 어렵지 않습니다.

 

다음의 표로 정리해 드리겠습니다.

파라미터 의미
sender 명령어를 친 대상으로
콘솔일 수도 있고 플레이어일 수도 있습니다.
command 말 그대로 실행된 명령어 인스턴스를 말하는 것으로
서버 인스턴스 단에서 처리할 수 있는 메소드들을
사용할 수 있습니다.
(명령어 등록, 취소, 펄미션 설정 등)
label 명령어의 별명이라고 생각하면 됩니다.
예를 들어, test라는 명령어의 label이 test2라고 하면
/test와 /test2는 같은 명령을 수행합니다.
args 명령어의 파라미터라고 생각하시면 됩니다.
예를 들어, /go home and sleep 이라고 한다면
home, and, sleep은 args 배열에 넣어져 있고,
각각의 인덱스는 0,1,2 입니다.

 

원래 코드로 돌아와서

 

onCommand 메소드 내의

그림 5. sender 검증

위 조건문은 sender의 객체 타입을 확인합니다.

 

이걸 왜 해야 하냐면 콘솔에서 명령어를 입력 시에는 누구의 정보를 확인할지 알 수 없기 때문입니다.

(현재 만들고 있는 명령어는 /uinfo 가 끝이기 때문)

 

다음으로 넘어가서

그림 6. 플레이어의 정보를 실질적으로 보여주는 부분

 

1강에서 잠깐 설명한 MVC 패턴에서 View를 사실 담당하고 있는 코드입니다.

 

플레이어의 정보를 보여주죠.

 

View까지 하려다가 이 부분은 좀 심화된 내용이 많기 때문에 

 

차후 강의에서 다루도록 하겠습니다.

(TMI로, 마크 서버에서 한번쯤은 보셨던 글자를 클릭한다거나 효과를 넣는 그런 겁니다 ㅎㅎ)

 

잠깐 딴 길로 샜지만 특별한 건 없고 UserManager로부터 플레이어의 데이터를 가져와서

 

하나씩 표시해 줍니다.

 

그리고 값 변경 테스트를 위해 마지막에 플레이어의 돈을 10원 올렸습니다.


 

명령어의 기능 구현은 끝났습니다.

 

이제 명령어를 등록해야 합니다.

 

어디서 해야 할까요??

 

UserManagementController에서 해야 한다고 설명드렸었죠?

 

 

controller.UserManagementController

package org.blog.paperedu.user.management.controller;

import org.blog.paperedu.PaperEdu;
import org.blog.paperedu.user.management.service.UserManager;
import org.blog.paperedu.user.management.controller.commands.UserInfoCommand;

public class UserManagementController {

    private static UserManager userManager;

    private final PaperEdu serverInstance;

    private UserConnectionController userConnectionController;

    public UserManagementController() {
        this.userManager = new UserManager();
        this.serverInstance = PaperEdu.getServerInstance();

        this.userConnectionController = new UserConnectionController(userManager);

        registerCommands();
        registerEvents();
    }


    private void registerEvents() {
        serverInstance.getServer().getPluginManager().registerEvents(userConnectionController, serverInstance);
    }

    private void registerCommands() {
        serverInstance.getServer().getPluginCommand("uinfo").setExecutor(new UserInfoCommand(userManager));
    }
}

 

추가된 건 registerCommands() 메소드입니다.

 

이때까지 자연스레 그런 의문이 드셨을 겁니다.

 

"uinfo"를 어디서 설정하는지에 대해서 말입니다.

 

바로 여기서 명령어를 등록할 때 합니다.

 

또한, 명령어 인스턴스를 생성할 때 UserManager 인스턴스도 넘겨줍니다.

 

이벤트 등록과 다르게 이렇게 해도 등록이 끝난 게 아닙니다.

 

plugin.yml을 건드려야 합니다.

그림 6. plugin.yml 예시

plugin.yml

name: PaperEdu
version: '${version}'
main: org.blog.paperedu.PaperEdu
api-version: '1.20'
commands:
  uinfo:
   description: display player data

plugin.yml은 플러그인에 대한 정보를 담고 있는 중요한 파일입니다.

 

이게 없으면 플러그인이 작동하지 않습니다.

 

명령어는 여기에 명령어의 정보를 명세해야 정상적으로 작동합니다.

 

위에 대한 설명은 다음 표를 봐주세요.

속성 의미
name 플러그인 이름
version 플러그인 버전
(마인크래프트 버전 아님)
main 메인 클래스의 위치
(onEnable(), onDisable() 메소드가 있는 곳)
api-version 마인크래프트 버전
commands.uinfo 추가한 커맨드의 이름
description /help 쳤을 때 나오는 커맨드의 설명

 

description은 마음대로 적어주셔도 됩니다.

 

/ (참고) 다양한 plugin.yml 설정 /

더보기

Plugin.yml | SpigotMC - High Performance Minecraft

 

Plugin.yml | SpigotMC - High Performance Minecraft

 

www.spigotmc.org

 

아까 잠깐 나온 onCommand 메소드 설명 때 나온 label 기억하시나요?

 

그걸 하는 설정하는 곳이 plugin.yml 입니다.

 

commands:
  thelp:
    description: help command
    aliases:
      - thelp2

 

위와 같이 작성해 주시면 됩니다.

 

또는

commands:
  thelp:
    description: help command
    aliases:[foobar, fubar]

이렇게 하셔도 됩니다. 

 

저렇게 되면 aliases 에 적은 것 또한 명령어가 됩니다.


결과

그림 7. 결과

 


 

만약 원하는 상대에 대한 정보까지 보려면 어떻게 해야 할까요?

 

한번 도전해 보세요.

 

힌트는 파라미터 부분에 있습니다.

 

다음 강의 시작 부분에서 부록으로 코드 예시를 올려드리겠습니다.

 

댓글