Compy's Blog
660 words
3 minutes
[Minecraft] ProtocolLib 패킷 받기
2025-02-06

ProtocolLib은 뭘까?#

ProtocolLib은 Bukkit에서 처리되는 이벤트나 다른 기능에서 제공되지 않거나, 별로 좋지 않은 기능들을 직접 구현할 수 있게 해주는 강력한 플러그인입니다. 정확히는 마인크래프트 서버, 클라이언트 끼리의 패킷을 읽고 보낼 수 있게 편리한 기능을 제공하는 플러그인이죠!

플러그인으로 좀 세부적인 것을 만들고 싶다면 거의 필수적으로 사용되는 플러그인인데요!! 그래서 한번 튜토리얼을 만들어 볼까 합니다.

먼저 ProtocolLib(이하 ‘프립’) 은 플러그인에서 종속성 설정을 해줘야합니다. 이 설정은 여기를 참고해주세요!

시작!#

Packet

사전적 의미는 ‘네트워크를 통해 전송되는 형식화된 데이터 덩어리’

사용자 데이터는 ‘페이로드(payload)‘로 알려져 있습니다. 제어정보는 페이로드를 전달하기 위한 정보

프로토콜립에서 제공하는 패킷 타입은 여기서서 볼 수 있어요!

이번에는 바로 실습을 진행해 보겠습니다.

원래 딱 보면 이해되는 것들이 더 많으니까요

    public ProtocolLibListener(){
        protocolManager = ProtocolLibrary.getProtocolManager();

        register();
    }

    public void register() {
        protocolManager.addPacketListener(new PacketAdapter(BlogPlugin.plugin, ListenerPriority.NORMAL,
                PacketType.Play.Client.USE_ENTITY) {
            @Override
            public void onPacketReceiving(PacketEvent event) {
                PacketContainer packet = event.getPacket();
                Player player = event.getPlayer();
                StructureModifier<Integer> integers = packet.getIntegers();
                if (integers != null && integers.size() > 0) {
                    int entityId = integers.read(0);

                        Bukkit.getScheduler().runTask(BlogPlugin.plugin, ()-> {
                            Entity entity = getEntityById(entityId, player.getWorld());
                            if(entity == null) return;
                            Location loc = entity.getLocation();
                            loc.setY(loc.getY() + 10);
                            entity.teleport(loc);
                        });
                }
            }
        });
    }

이렇게 작성하면 버킷에 프로토콜립의 이벤트 리스너가 등록된겁니다. 굉장히 간단하죠?

지금 아래 코드에서 좀 잘 봐야할 것은 뭐냐 runTask랑 packet.getIntegers() 정도가 되겠네요

둘 다 안전하게 처리하기 위해서 사용되는 것들이고요. 이를 통해서 오류 안 터지고 예외 처리도 되고 따로 핸들링도 가능해집니다. 제가 try, catch문을 별로 좋아하는 편은 아니여서 최대한 안 쓰려고 합니다.

    private Entity getEntityById(int id, World world){
        return world.getEntities().stream().filter(entity -> entity.getEntityId() == id).findFirst().orElse(null);
    }

이렇게 해서 아이디를 알면 그 월드에 존재하는 엔티티들을 전부 돌면서 하나를 받아올 수 있게 되겠죠

    public static BlogPlugin plugin;
    @Override
    public void onEnable() {
        plugin = this;
        new ProtocolLibListener();
    }

main도 별거 없습니다. 그냥 실행만 시켜주는 거에요!


구현 영상
[Minecraft] ProtocolLib 패킷 받기
https://compy07.github.io/Blog/posts/development/bukkit/util/protocollib/listenpacket/
Author
뒹굴뒹굴 이정훈 공부방
Published at
2025-02-06