이번에는 저번 onCommand 를 활용해 챗컬러 플러그인을 만들어보도록 하겠습니다.
제가 만들 챗컬러 플러그인은 "/chatColor [색깔]" 을 통해 채팅을 색깔을 변경시키는 플러그인 입니다.
그러면 플러그인의 설계부터 들어가도록 하겠습니다.
"/chatColor [색깔]" 라는 명령어를 입력할 시에
채팅의 색을 입력한 [색깔] 로 변경하는
플러그인 입니다.
이번에도 Eclipse 를 통해 maven 프로젝트를 만들어보도록 하겠습니다.
이번에는 폴더 구조를 분리하며 제작해보도록 하겠습니다.
현재 알고 있는 내용으로는 main 클래스, 리스너 클래스, 커맨드 클래스 위의 세 가지 클래스로 분리시킬 수 있다고 배웠습니다.
그러면 우선 가장 먼저 "/chatColor [색깔]" 라는 명령어를 입력할 시에 를 구현하기 위해
chatColor 라는 커맨드를 plugin.yml 에 등록해보도록 하겠습니다.
플러그인으로 제작해서 등록 시
chatColor 라는 명령어가 등록된 것을 확인할 수 있었습니다.
구성하기 전에 어떤 기능들이 있으면 좋을지 고려해봅시다.
/chatcolor help - 챗컬러의 사용법에 대해 알려줍니다.
/chatcolor list - 챗컬러에서 셋팅할 수 있는 컬러를 알려줍니다.
/chatcolor <컬러> - 챗컬러를 통해 유저의 채팅 색을 변경합니다.
위와 같은 명령어가 있으면 좋을 것 같습니다.
우선 예외 케이스를 먼저 고려해보도록 하겠습니다.
명령어가 chatcolor 가 아닐 경우와 명령어릐 형태가 위의 형태와 다를 경우
false 를 리턴하면서 명령어를 실행시키지 않도록 합니다.
chatColor 플러그인의 경우 ChatColor Class 를 활용할 것입니다.
ChatColor (Spigot-API 1.21.1-R0.1-SNAPSHOT API) (spigotmc.org)
ChatColor (Spigot-API 1.21.1-R0.1-SNAPSHOT API)
All Implemented Interfaces: Serializable, Comparable , Constable All supported color values for chat Nested Class Summary Enum Constant Summary Enum Constants Field Summary Fields static final char The special character which prefixes all chat colour codes
hub.spigotmc.org
/chatcolor help - 챗컬러의 사용법에 대해 알려줍니다.
우선 위 명령어를 먼저 제작해보도록 하겠습니다.
명령어의 형태가 /chatcolor help 일 경우
args[0] 에는 help 라는 값이 들어가게 됩니다.
해당 케이스에는 플레이어에게 사용법에 대한 메세지를 전달합니다.
/chatcolor list - 챗컬러에서 셋팅할 수 있는 컬러를 알려줍니다.
다음은 설정할 수 있는 컬러의 리스트를 알려주도록 합니다.
저희가 제작할 플러그인은 ChatColor 라는 Class 를 기반으로 하기 때문에
ChatColor 에 정의된 색이 아닐 경우에는 사용할 수 없기 때문입입니다.
ChatColor 의 값들을 향상된 for 문을 통해 하나씩 추출해서
유저에게 어떤 컬러가 있는지 알려줍니다.
isColor 를 통해 색인지 확인하는 이유는 ChatColor.values() 의 값 내에 BOLD 와 같은 색이 아닌 것들이 존재하기 때문에 걸러줍니다.
/chatcolor <컬러> - 챗컬러를 통해 유저의 채팅 색을 변경합니다.
마지막은 유저의 채팅 색을 변경해주는 작업을 해보도록 하겠습니다.
우선 입력된 내용이 색에 대한 내용이 맞는지 판단해야 합니다.
입력된 값이 ChatColor.values() for 문 내에서 일치하는 이름이 있다면
selectedChatColor 의 값을 color 값으로 변경하는 코드입니다.
더 이상의 불필요한 for 문은 돌 필요가 없기 때문에, 일치하는 것이 하나라도 있다면 for 문을 중지합니다.
만약 유효한 입력이 들어와 selectedChatColor 에 값이 들어갔다면, 더 이상 null 이 아닐 겁니다.
하지만, null 일 경우에는 유저에게 유효하지 않다는 정보를 알려주고
유효한 사용법을 알려주는 명령어인 /chatcolor help 를 이용해달라고 해줍니다.
유효한 값이 있다면 plugin 의 setChatColor 라는 메서드를 실행시키고
파라미터로는 player 의 UUID 와 지정한 컬러를 전달합니다.
현재의 구조는 main Class 가 존재하고, Listener 와 Command 가 main Class 에 연결되어 있는 구조입니다.
유저가 어떤 채팅 컬러를 가지고 있는지 ? 에 대한 정보는 main Class 에서 관리를 해야 하고
Command 는 main Class 의 정보를 변경하고
Listener 는 main Class 의 정보를 가져와 채팅의 색을 변경하는 작업을 해줘야 합니다.
가장 위 생성자 코드에 main Class 를 받아오는 코드를 작성해 줍니다.
생성자는 클래스를 통해 인스턴스를 생성할 때 한 번만 호출되는 코드 입니다.
이렇게 onCommand 메서드를 가지고 있는 ChatColorPluginCommand 클래스는 제작을 마쳤습니다.
package com.tistory.beingb.com.command;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import com.tistory.beingb.main.ChatColorPlugin;
public class ChatColorPluginCommand implements CommandExecutor {
ChatColorPlugin plugin;
public ChatColorPluginCommand(ChatColorPlugin chatColorPlugin) {
// TODO Auto-generated constructor stub
plugin = chatColorPlugin;
}
@Override
public boolean onCommand(CommandSender sender, Command command, String commandElias, String[] args) {
// 명령어가 chatColor 가 아닐 경우
if (!command.getName().equalsIgnoreCase("chatcolor"))
return false;
// 명령어의 형태가 /chatColor [색깔]이 아닌 경우
if (args.length != 1)
return false;
if (args[0].equals("help")) {
sender.sendMessage("/chatcolor list - 입력할 수 있는 컬러를 보여줍니다.");
sender.sendMessage("/chatcolor [color] - 채팅의 컬러를 변경합니다.");
return true;
}
// 명령어의 형태가 /chatColor list 일 경우
if (args[0].equals("list")) {
for (ChatColor color : ChatColor.values()) {
if (color.isColor()) {
sender.sendMessage(color + "입력할 수 있는 컬러는 " + color.name() + " " + "입니다.");
}
}
return true;
}
String inputColor = args[0];
ChatColor selectedChatColor = null;
for (ChatColor color : ChatColor.values()) {
if (color.isColor()) {
if (color.name().equalsIgnoreCase(inputColor)) {
selectedChatColor = color;
break;
}
}
}
// 유효하지 않은 색상 입력의 경우
if (selectedChatColor == null) {
sender.sendMessage("유효하지 않은 색상 입력입니다.");
sender.sendMessage("/chatcolor help 명령어를 통해 사용법을 확인해보세요.");
} else {
Player player = (Player) sender;
plugin.setChatColor(player.getUniqueId(), selectedChatColor);
}
return true;
}
}
그러면 위 Command 클래스를 main Class 에 등록해보도록 하겠습니다.
main Class 에서는 UUID 를 key 로 하고 ChatColor 인스턴스를 value 로 하는 HashMap 이라는 자료구조를 활용할 것입니다.
W3Schools.com
W3Schools offers free online tutorials, references and exercises in all the major languages of the web. Covering popular subjects like HTML, CSS, JavaScript, Python, SQL, Java, and many, many more.
www.w3schools.com
getter 함수와 setter 함수를 만들어 줌으로써
Command 클래스 에서는 setter 함수를 사용할 수 있도록 하고
Listener 클래스 에서는 getter 함수를 사용할 수 있도록 할 예정입니다.
onEnable 영역에
Command 클래스를 등록해 줌으로써 명령어를 활성화시켜 줍니다.
해당 생성자에 main Class 를 전달해줘야 하기에 파라미터로 this 를 넘김으로써 메인 클래스를 넘겨줍니다.
package com.tistory.beingb.main;
import java.util.HashMap;
import java.util.UUID;
import org.bukkit.ChatColor;
import org.bukkit.plugin.java.JavaPlugin;
import com.tistory.beingb.com.command.ChatColorPluginCommand;
public class ChatColorPlugin extends JavaPlugin {
HashMap<UUID, ChatColor> chatColorMap = new HashMap<>();
public ChatColor getChatColor(UUID uuid) {
return chatColorMap.get(uuid);
}
public void setChatColor(UUID uuid, ChatColor chatColor) {
chatColorMap.put(uuid, chatColor);
}
@Override
public void onDisable() {
// TODO Auto-generated method stub
super.onDisable();
}
@Override
public void onEnable() {
// TODO Auto-generated method stub
super.onEnable();
this.getCommand("chatcolor").setExecutor(new ChatColorPluginCommand(this));
}
@Override
public void onLoad() {
// TODO Auto-generated method stub
super.onLoad();
}
}
위 작업까지 마쳤다면 유저의 채팅 색깔을 변경할 수는 없지만, 그 외의 명령어는 정상적으로 작동할 것입니다.
그러면 이제 채팅의 색을 입력한 [색깔] 로 변경하는 작업을 해줘야 하는데요.
채팅을 입력했을 때 작동하는 이벤트 이기 때문에 spigot player chat event 로 검색해보도록 하겠습니다.
PlayerChatEvent (Spigot-API 1.21.1-R0.1-SNAPSHOT API) (spigotmc.org)
PlayerChatEvent (Spigot-API 1.21.1-R0.1-SNAPSHOT API)
All Implemented Interfaces: Cancellable Deprecated. Holds information for player chat and commands Nested Class Summary Field Summary Constructor Summary Constructors Method Summary All MethodsStatic MethodsInstance MethodsConcrete MethodsDeprecated Method
hub.spigotmc.org
검색결과로 SpigotMC 로 연결되는 PlayerChatEvent 가 등장합니다.
해당 사이트에 들어가 보니 더이상 위 이벤트는 사용되지 않고 대신해서 AsyncPlayerChatEvent 를 활용할 수 있다고 합니다.
AsyncPlayerChatEvent (Spigot-API 1.21.1-R0.1-SNAPSHOT API) (spigotmc.org)
AsyncPlayerChatEvent (Spigot-API 1.21.1-R0.1-SNAPSHOT API)
All Implemented Interfaces: Cancellable Direct Known Subclasses: AsyncPlayerChatPreviewEvent This event will sometimes fire synchronously, depending on how it was triggered. The constructor provides a boolean to indicate if the event was fired synchronousl
hub.spigotmc.org
그러면 위 이벤트를 통해서 Listener 를 구성해보도록 하겠습니다.
ChatColorPluginListener 의 경우에도 main Class 에서 getChatColor 메서드를 실행해야 하므로
생성자를 통해 main Class 를 전달받습니다.
onChat 이라는 이벤트 핸들러를 제작하고
plugin 즉, main Class 의 getChatColor 메서드를 활용해 ChatColor 를 가져오도록 합니다.
event 의 setMessage 를 통해 입력된 메세지를 컬러를 덮어서 다시 유저에게 보내주도록 합니다.
package com.tistory.beingb.com.listener;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import com.tistory.beingb.main.ChatColorPlugin;
public class ChatColorPluginListener implements Listener {
ChatColorPlugin plugin;
public ChatColorPluginListener(ChatColorPlugin chatColorPlugin) {
// TODO Auto-generated constructor stub
plugin = chatColorPlugin;
}
@EventHandler
public void onChat(AsyncPlayerChatEvent event) {
Player player = event.getPlayer();
String message = event.getMessage();
ChatColor selectedChatColor = plugin.getChatColor(player.getUniqueId());
if (selectedChatColor != null) {
event.setMessage(selectedChatColor + message);
}
}
}
마지막으로 onEnable 에 Listener 를 등록해줍니다.
생성자에서 메인 클래스를 활용하기 위해, this 를 파라미터로 넣어줍니다.
package com.tistory.beingb.main;
import java.util.HashMap;
import java.util.UUID;
import org.bukkit.ChatColor;
import org.bukkit.plugin.java.JavaPlugin;
import com.tistory.beingb.com.command.ChatColorPluginCommand;
import com.tistory.beingb.com.listener.ChatColorPluginListener;
public class ChatColorPlugin extends JavaPlugin {
HashMap<UUID, ChatColor> chatColorMap = new HashMap<>();
public ChatColor getChatColor(UUID uuid) {
return chatColorMap.get(uuid);
}
public void setChatColor(UUID uuid, ChatColor chatColor) {
chatColorMap.put(uuid, chatColor);
}
@Override
public void onDisable() {
// TODO Auto-generated method stub
super.onDisable();
}
@Override
public void onEnable() {
// TODO Auto-generated method stub
super.onEnable();
this.getCommand("chatcolor").setExecutor(new ChatColorPluginCommand(this));
this.getServer().getPluginManager().registerEvents(new ChatColorPluginListener(this), this);
}
@Override
public void onLoad() {
// TODO Auto-generated method stub
super.onLoad();
}
}
실제 플러그인이 제대로 작동하는지 테스트해보도록 하겠습니다.
/chatcolor help 명령어 입력 시 챗컬러 플러그인의 사용 방법에 대해 알려주고 있습니다.
/chatcolor list 명령어 입력 시 챗컬러 플러그인에서 사용할 수 있는 색깔들에 대해 알려주고 있습니다.
purple 은 Chatcolor 에서 제공해주는 컬러가 아닌 것을 list 명령어를 통해 알 수 있었는데요.
/chatcolor purple 로 유효하지 않은 색상을 입력하면 유저에게 알려주고 사용법을 사용할 수 있도록 유도합니다.
채팅의 색을 GREEN 으로 설정해보도록 하겠습니다.
정상적으로 채팅의 색이 GREEN 으로 변경된 것을 확인할 수 있었습니다.
이런 플러그인 내에서 HashMap 을 활용하는 방법은 서버가 실행되고 있는 순간이 상태의 라이프 사이클 입니다.
즉, 서버가 종료하게 되면 저장된 내용이 날라가 버리는데요.
이런 데이터가 날라가는 것을 방지하기 위해서는 데이터베이스를 활용해 저장하는 방법을 사용할 수 있습니다.
해당 방법은 추후 필요할 때 알아보도록 하겠습니다.
이번에는 파일의 분리와 HashMap 이라는 자료구조의 사용이라는 나름 어려운 주제에 대해 실습을 진행해보았는데요.
아무래도 Java 라는 언어를 기반으로 하다 보니, 언어에 대한 지식이 필요해 보입니다.
현재는 검색이 매우 잘 활성화 되어 있기 때문에
처음부터 잘 만들어야 겠다는 생각보다는 비효율적인 코드를 효율적인 코드로 변경해나가는 과정을 거쳐나가면 좋을 것 같습니다.
그러면서 이게 왜 효율적이고 이게 왜 비효율적일까에 대해 배우는 것이 더 좋은 플러그인을 만드는 방법이라 생각합니다.
이걸로 챗컬러 플러그인 제작을 마치도록 하겠습니다.
'마인크래프트' 카테고리의 다른 글
11. 마인크래프트 플러그인 개발 - 커스텀 아이템 플러그인 개발 (1) | 2024.08.31 |
---|---|
10. 마인크래프트 플러그인 개발 - 작물 성장 체크 플러그인 개발 (0) | 2024.08.25 |
7. 마인크래프트 플러그인 개발 - 데미지 디스플레이 플러그인 개발 (0) | 2024.08.16 |
6. 마인크래프트 플러그인 개발 - Listener 활용 (0) | 2024.08.16 |
5. 마인크래프트 플러그인 개발 - Listener (0) | 2024.08.15 |