이번에는 플러그인의 꽃이라고 할 수 있는 Event Listner 이라는 것에 대해 알아보도록 하겠습니다.
저번 4편 까지의 내용으로 기본적인 플러그인을 구성하는 방법에 대해 배웠을 것입니다.
4편은 모든 플러그인을 개발할 때 가장 기본적인 틀을 만드는 역할을 한다고 생각하면 되겠습니다.
지난번 보았던 Plugin Tutorial WIKI 에서 Listeners 부분을 집중적으로 알아보도록 하겠습니다.
우선 링크를 타고 들어가기에 앞서 Listeners 가 무엇인지 설명해주고 있는데요.
이벤트에 대한 응답으로 메서드를 호출하는 클래스 라고 합니다.
이 이벤트란 2편에서 설명한 것처럼 마인크래프트가 서버로 보내는 신호를 의미합니다.
서버가 이러한 신호에 응답할 때 메서드라는 것을 호출하게 되고, 응답이 플러그인에 따라 수정되어
마인크래프트에 전달된다고 이해하면 될 것 같습니다.
이 리스너 라는 것은 org.bukkit.event.Listener 이라는 것을 implement 한다고 합니다.
이 implement 라는 개념은 JAVA 의 개념이고 우선은 extend 처럼 해당 내용을 상속해 사용한다고 생각하면 편할 것 같습니다.
그러면 링크를 타고 들어가 더 자세히 알아보도록 하겠습니다.
Event API Reference - Official BukkitWiki (fandom.com)
Event API Reference
Welcome to Bukkit's Event API reference page. Events are how the CraftBukkit server tells your plugin that something has happened in the world. Bukkit defines many events, in multiple categories; e.g. player actions (player logged in, player clicked a bloc
bukkit.fandom.com
가장 먼저 Events 가 무엇인지에 대해 소개하고 있는데요.
Events 는 CraftBukkit 서버가 플러그인에게 마인크래프트 세상에서 무슨 일이 일어났는지를 알려주는 것이라고 합니다.
우리는 CraftBukkit 으로 만든 서버를 사용하지 않고, Spigot 서버를 사용하고 있으니 대체해서 이해하면 될 것 같습니다.
Bukkit 에는 많은 이벤트들이 정의되어 있다고 합니다. 플레이어 액션, 블럭 이벤트, 엔티티 이벤트, 월드 이벤트 등 마인크래프트에서 일어날 수 있는 대부분의 일들이 신호 즉, 이벤트가 되고 서버를 거쳐 플러그인까지 도달한다고 이해하면 될 것 같습니다.
이번 튜토리얼은 PlayerLoginEvent 를 활용해 볼 것 같습니다.
PlayerLoginEvent 는 이름으로만 봤을 때는 플레이어가 로그인 했을 때의 이벤트를 의미하는 것 같습니다.
우선 실습을 하기 앞서 해당 튜토리얼을 먼저 읽어가며 이런 식으로 흘러가며 제작할 수 있겠구나 라는 것을 이해해보도록 하겠습니다.
우선 가장 먼저 Setting up the Method 입니다.
플러그인에서 event call 을 다루기 위해서는 메서드라는 것을 만들 필요가 있다고 합니다.
추후 제대로 설명하겠지만, 우선 이 메서드란게 무엇인지에 대해 알아보도록 하겠습니다.
메서드는 다른 이름으로 함수 또는 프로시저 라는 이름으로 많이 불립니다.
함수에 대해 처음 배우게 된다면 아래와 같은 그림을 종종 볼 때가 있는데요.
함수는 INPUT 즉, 입력이 들어가면 내부의 작업을 해 OUTPUT 즉, 결과를 내는 것을 의미합니다.
위의 onLogin 메서드는 PlayerLoginEvent 를 INPUT 으로 받고, 그것에 대한 결과값을 OUTPUT 으로 내는 작업을 해야 한다는 것을 의미합니다.
아래 설명을 보면 Bukkit 에서 PlayerLoginEvent 가 실행되면 위의 함수가 실행된다고 하는 것 같습니다.
우리는 이것을 annotate 할 필요가 있다고 하는데요. EventHandlers 라는 annotate 를 해야한다는 의미인 것 같습니다.
메서드의 윗 부분에 @EventHandler 라는 것이 적혀있는데 이것이 EventHandler 라는 것을 annotate 한 것 같습니다.
다음 내용을 보면 @EventHandler 가 무엇인지를 이야기해주는 것 같습니다.
"@EventHandler" 클래스는 Annotation 이라고 하고, 메서드의 윗 부분에 적혀야 한다고 합니다.
위와 같이 priority 라는 값을 통해 이벤트의 우선순위를 정해줄 수 있는 것 같습니다.
위에 작성한 onLogin 메서드의 경우에는 아무런 우선순위 즉, priority 값이 붙어 있지 않기에 NORMAL 이라는 기본적인 값이 설정되는 것 같습니다.
해당 링크에 들어가기 이전에 이 리스너 라는 것은 org.bukkit.event.Listener 이라는 것을 implement 해야 한다고 이야기 드렸는데요.
이 메서드라는 것은 Class 라는 상자에 들어있는 것들이라고 생각하면 편할 것 같습니다.
위의 튜토리얼에서 작성한 onLogin 메서드의 경우에도 MyPlayerListener 이라는 클래스 안에 들어있는 메서드인데요.
이 클래스는 event hnadling 메서드를 포함하려면 Listner 이라는 것을 implement 해야 한다고 합니다.
main 플러그인의 class 도 이벤트 리스너가 될 수 있다고 합니다.
다음은 EventHandler Parameters 에 대한 설명은 우선 건너뛰고
Registering Events 에 대해 먼저 알아보도록 하겠습니다.
EventHandler 를 포함하고 있는 클래스의 메서드들을 등록하기 위해서는 Listener 라는 것이 implement 되야 한다고 합니다.
그리고 PluginManager 라는 것에 등록하기 위해서는 plugin 과 listener 라는 것을 제공해줘야 한다고 합니다.
getServer().getPluginMaanger() 라는 것을 통해 PluginMaanger 를 가져올 수 있고
registerEvents 를 통해 이벤트를 등록할 수 있는데, 인자로 Listener 와 Plugin 을 주고 있습니다.
그 다음은 다시 한 번 EventListener 를 제작하는 예시를 보여주고 있습니다.
LoginListener 라는 Class 를 만들고 Listener 라는 것을 implements 해줬습니다.
그리고, 내부에는 두 개의 normalLogin 과 highLogin 이라는 메서드가 존재하고
두 개의 EventHandler annotation 은 NORMAL 과 HIGH 로 지정되어 있습니다.
그리고 메서드들의 INPUT 으로는 PlayerLoginEvent 라는 값을 넣어주고 있습니다.
플러그인을 등록하는 방법 중 하나로는
registerEvents 의 listener 인자에 위에서 제작한 LoginListener 라는 것을 넣어줄 수가 있는 것 같습니다.
우리가 만든 Class 는 실체가 없는 설계도라고 생각하면 편합니다.
Class 라는 설계도에 따라 실체를 만들기 위해서는 new 라는 것을 통해 실체를 만들어 줘야 하는데요.
listener 인자에 들어간 new LoginListener() 도 LoginListener 이라는 설계도에 따라, 실체를 만드는 것입니다.
위의 예시처럼 main class 내에 EventHandler 가 들어가 있는 케이스의 경우에는 두 개의 값 모두 this 라는 값으로 LoginPlugin 라는 메인 클래스를 바라보도록 만들어서 이벤트를 등록할 수 있습니다.
튜토리얼에서는 이렇게 내가 만들 플러그인에 이벤트 핸들러 라는 것을 등록하는 것에 대해 알려줬는데요.
이번에는 위 튜토리얼을 토대로 서버에 유저가 접속했을 때 서버의 로그를 남기는 플러그인을 개발해보도록 하겠습니다.
플러그인은 신호를 던지고 결과값을 돌려주는 것이라 말해줬습니다.
우리는 앞으로 플러그인을 만들 때 무엇을 만들것인지에 대한 분석을 한 후에 플러그인을 제작하는 플로우로 작업을 해보겠습니다.
우리가 만들 플러그인은
서버에 유저가 접속했을 때
서버의 로그를 남기는
플러그인 입니다.
우리는 튜토리얼을 진행하며 PlayerLoginEvent 와 getLogger 에 대해 알아보았던 적이 있습니다.
이런 정보를 토대로 플러그인을 제작해보도록 하겠습니다.
저번에 제작해두었던 TestPlugin 프로젝트 위에서 작업을 해주도록 하겠습니다.
package com.tistory.beingb.testplugin;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.plugin.java.JavaPlugin;
public final class TestPlugin extends JavaPlugin implements Listener {
@Override
public void onEnable() {
getLogger().info("onEnable has been invoked!");
}
@Override
public void onDisable() {
getLogger().info("onDisable has been invoked!");
}
@Override
public void onLoad() {
getLogger().info("onLoad has been invoked!");
}
}
우선 가장 먼저 EventHandler 를 제작하기 위해 implements Listener 를 붙여 줍니다.
이 Listener 는 위에서 설명한 것과 같이 org.bukkit.event.Listener 라는 곳에서 import 할 수 있습니다.
그 다음 실제 작동할 이벤트인 PlayerLoginEvent 를 붙여보도록 하겠습니다.
package com.tistory.beingb.testplugin;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.plugin.java.JavaPlugin;
public final class TestPlugin extends JavaPlugin implements Listener {
@Override
public void onEnable() {
getLogger().info("onEnable has been invoked!");
}
@Override
public void onDisable() {
getLogger().info("onDisable has been invoked!");
}
@Override
public void onLoad() {
getLogger().info("onLoad has been invoked!");
}
@EventHandler
public void onLogin(PlayerLoginEvent event) {
}
}
튜토리얼의 예시와 같이 onLogin 이라는 메서드를 제작했고
EventHandler 라는 annotaition 을 붙여줬고
PlayerLoginEvent 라는 인자를 메서드의 INPUT 으로 주었습니다.
그러면 마찬가지로 getLogger 라는 것을 통해 플레이어가 접속했을 때의 로깅을 추가해보도록 하겠습니다.
@EventHandler
public void onLogin(PlayerLoginEvent event) {
getLogger().info("플레이어가 입장했습니다.");
}
만약 플레이어가 성공적으로 서버에 Login 했다면 서버의 로그에 "플레이어가 입장했습니다." 라는 문구가 등장하게 될 것입니다.
package com.tistory.beingb.testplugin;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.plugin.java.JavaPlugin;
public final class TestPlugin extends JavaPlugin implements Listener {
@Override
public void onEnable() {
getLogger().info("onEnable has been invoked!");
getServer().getPluginManager().registerEvents(this, this);
}
@Override
public void onDisable() {
getLogger().info("onDisable has been invoked!");
}
@Override
public void onLoad() {
getLogger().info("onLoad has been invoked!");
}
@EventHandler
public void onLogin(PlayerLoginEvent event) {
getLogger().info("플레이어가 입장했습니다.");
}
}
그리고 만든 이벤트 핸들러를 플러그인 매니저에 등록해주는 작업을 해줘야 하는데요.
플러그인 매니저에 등록해주는 과정은 서버가 준비가 됐을 때 해주는 것이 좋기 때문에
onEnable 에 registerEvents 를 통해 리스너와 플러그인을 등록해줍니다.
extends JavaPlugin 을 해준 것이 main Class 를 의미하고 플러그인을 의미합니다.
implements Listener 을 해준 것이 Listener 를 의미합니다.
registerEvents 의 첫 번재 인자에는 Listener 두 번째 인자는 Plugin 이 들어간다고 설명했습니다.
이번에는 TestPlugin 이라는 클래스가 main Class 도 되고 Listener 도 되기 때문에, 나 자신을 가리키는 this 라는 값을 넣어 줍니다.
pom.xml 과 plugin.yml 을 4편에서 했던 것 처럼 버전을 올리고 JAR 파일을 제작해보도록 하겠습니다.
maven install 을 통해 TestPlugin-0.0.2-SNAPSHOT.jar 이라는 플러그인 파일이 만들어졌습니다.
해당 파일을 SPIGOT 서버의 plugins 폴더에 넣고 실행해보도록 하겠습니다.
서버를 가동했을 때 TsetPlugin 이라는 저희가 만든 플러그인이 정상적으로 탑재되고
onEnable 이라는 메서드가 정상적으로 호출되어, onEnable() 메서드 안에있는 getLogger 도 정상적으로 호출된 것을 확인할 수 있습니다.
그러면 PlayerLoginEvent 가 있는 onLogin 메서드가 정상적으로 작동하는지 서버에 접속해보도록 하겠습니다.
플레이어 접속 시 우리가 onLogin 메서드에 작성한 getLogger 로직이 정상적으로 작동했고
서버에 자체적으로 작성해주는 로그도 함께 작성되는 것을 확인했습니다.
'마인크래프트' 카테고리의 다른 글
7. 마인크래프트 플러그인 개발 - 데미지 디스플레이 플러그인 개발 (0) | 2024.08.16 |
---|---|
6. 마인크래프트 플러그인 개발 - Listener 활용 (0) | 2024.08.16 |
4. 마인크래프트 플러그인 개발 - 기초 플러그인 개발 (0) | 2024.08.15 |
3. 마인크래프트 플러그인 개발 - 커스텀 서버 제작 및 이클립스 설치 (0) | 2024.08.14 |
2. 마인크래프트 플러그인 개발 - 플러그인이란 ? (0) | 2024.08.13 |