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

[인텔리제이로 마크 플러그인 개발하기]7. 나만의 인벤토리 GUI 만들기 2편 (인벤토리와 관련된 이벤트 처리하기)

by Zepelown 2022. 10. 10.

*이 글은 Spigot 1.19.2 버전을 기준으로 하여 제작되었습니다.

 

지난 화

https://zepelown.tistory.com/44

 

[인텔리제이로 마크 플러그인 개발하기]6. 나만의 인벤토리 GUI 만들기 1편 (기본적인 인벤토리 작

*이 글은 Spigot 1.19.2 버전을 기준으로 하여 제작되었습니다. 지난 화 https://zepelown.tistory.com/43 [인텔리제이로 마크 플러그인 개발하기]5. 나만의 명령어 만들기 (give, help 명령어 만들어보기) *이 글.

zepelown.tistory.com


 

이전 화에서 유저가 인벤토리의 아이템을 마음대로 가져갈 수 있었습니다.

 

이 문제를 해결하기 위해 InventoryClickEvent 를 사용할 겁니다.

https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/event/inventory/InventoryClickEvent.html

 

InventoryClickEvent (Spigot-API 1.19.2-R0.1-SNAPSHOT API)

All Implemented Interfaces: Cancellable Direct Known Subclasses: CraftItemEvent, InventoryCreativeEvent, SmithItemEvent This event is called when a player clicks in an inventory. Because InventoryClickEvent occurs within a modification of the Inventory, no

hub.spigotmc.org

 

InvClickEvent.java

package io.github.zepelown.testplugin.event;

import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;

public class InvClickEvent implements Listener {

    @EventHandler
    public void onClick(InventoryClickEvent e){
        if(e.getClickedInventory() == null)
            return;
        if(ChatColor.stripColor(e.getView().getTitle()).equalsIgnoreCase("TESTGUI")){
            e.setCancelled(true);
            Player player = (Player) e.getWhoClicked();
            player.sendMessage("인벤토리 클릭이 취소되었습니다.");
        }
    }
}

 

TestPlugin.java

package io.github.zepelown.testplugin;


import io.github.zepelown.testplugin.commands.GiveDia;
import io.github.zepelown.testplugin.commands.Help;
import io.github.zepelown.testplugin.commands.OpenInv;
import io.github.zepelown.testplugin.event.BreakEvent;
import io.github.zepelown.testplugin.event.InvClickEvent;
import org.bukkit.plugin.java.JavaPlugin;

public final class TestPlugin extends JavaPlugin {

    @Override
    public void onEnable() {
        // Plugin startup logic
        getLogger().info("플러그인 활성화");
        getServer().getPluginManager().registerEvents(new BreakEvent(), this);
        getServer().getPluginManager().registerEvents(new InvClickEvent(), this);
        getServer().getPluginCommand("thelp").setExecutor(new Help());
        getServer().getPluginCommand("tgivedia").setExecutor(new GiveDia());
        getServer().getPluginCommand("topeninv").setExecutor(new OpenInv());
    }

    @Override
    public void onDisable() {
        // Plugin shutdown logic
        getLogger().info("플러그인 비활성화");
    }
}

 

이전 강좌에서 BlockBreakEvent를 사용한 것과 비슷한 맥락입니다.

 

먼저 onClick 매서드 내 첫 줄은 어떤 플레이어가 인벤토리를 클릭했을 때 그 값이 null, 즉 마크 내 기본 인벤토리 일 경우

 

이벤트를 즉시 종료하게 합니다.

 

쉽게 말해 창고나 플레이어 인벤토리일 경우 종료 시키는 겁니다.

 

저희는 새로 만든 TestGUI만 통과 시킬 것이기 때문에 필요가 없습니다.

 

if(ChatColor.stripColor(e.getView().getTitle()).equalsIgnoreCase("TESTGUI")){
    e.setCancelled(true);
    Player player = (Player) e.getWhoClicked();
    player.sendMessage("인벤토리 클릭이 취소되었습니다.");
}

조금 복잡해 보이실 수도 있습니다만 쉽습니다.

 

조건문은 만약 인벤토리 클릭 이벤트가 발생했을 경우 그 인벤토리의 이름(타이틀)의 색깔을 지우고

 

"TESTGUI"와 소문자 대문자 구분 없이 일치하는지를 확인하는 겁니다.

 

여기서 만약 인벤토리 이름에 색깔을 부여했다면 값이 같다고 리턴하지 않기 때문에

 

색깔을 지워주셔야합니다.

 

그리고 e.setCancelled(true)를 통해 그 클릭 이벤트를 취소하고

 

인벤토리를 누른 플레이어의 정보를 가져와 메시지를 전달하는 겁니다.

 

잠깐 나오는 회복 포션은 조만간 다룰 예정입니다 ㅎㅎ

이대로 실행하면 위와 같이 작동합니다.

 


간단한 gui도 구현했으니 기능을 추가해보고 꾸며보겠습니다.

 

먼저 다이아를 눌렀을 때 그 다이아를 유저에 주는 걸 추가해보겠습니다.

 

InvClickEvent.java

package io.github.zepelown.testplugin.event;

import io.github.zepelown.testplugin.ItemManager;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;

public class InvClickEvent implements Listener {

    @EventHandler
    public void onClick(InventoryClickEvent e){
        if(e.getClickedInventory() == null)
            return;
        if(ChatColor.stripColor(e.getView().getTitle()).equalsIgnoreCase("TESTGUI")){
            e.setCancelled(true);
            if(e.getCurrentItem() == null)
                return;
            else if(e.getCurrentItem().isSimilar(ItemManager.dia)){
                Player player = (Player) e.getWhoClicked();
                player.getInventory().addItem(ItemManager.dia);
                player.sendMessage("다이아가 지급되었습니다.");
                player.closeInventory();
            }
        }
    }
}

e.getCurrentItem 을 통해 클릭한 아이템의 정보가 null 즉, 빈칸을 선택한 경우는 함수를 종료시키고

 

누른 아이템의 ItemStack이 ItemManager의 dia와 유사할 때 (이름, 설명 등을 비교)

 

플레이어에게 dia를 주고 메시지를 전달 후 인벤토리를 닫습니다.

 

추가로 인벤토리를 조금 꾸며봤습니다.

 

ItemManager.java

public static final ItemStack guiGrayGlassPane = buildItem(Material.GRAY_STAINED_GLASS_PANE, 1, ChatColor.GRAY + "빈칸","아이템 설명을 잘 읽어보세요");

아이템을 새로 만들고

 

TestGUI.java

package io.github.zepelown.testplugin.inventory;

import io.github.zepelown.testplugin.ItemManager;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;



public class TestGUI implements InventoryHolder {
    private final Inventory inv;

    private void initItemSetting() {
        for(int i = 0; i < 9; i++){
            if(i==4)
                inv.setItem(i,ItemManager.dia);
            else
                inv.setItem(i,ItemManager.guiGrayGlassPane);
        }
    }

    public TestGUI() {
        this.inv = Bukkit.createInventory(null,9,"TESTGUI");
        initItemSetting();
    }

    public void open(Player player){
        player.openInventory(inv);
    }



    @Override
    public Inventory getInventory() {
        return inv;
    }
}

인벤토리를 수정했습니다.

 

빌드해보겠습니다!

 

 

댓글