ProtocolLib

ProtocolLib마인크래프트 서버와 클라이언트 간의 패킷 통신을 제어할 수 있게 해주는 핵심 라이브러리 플러그인이다. 다른 플러그인들이 패킷을 가로채거나 수정할 수 있도록 API를 제공하며, 많은 고급 플러그인들의 필수 의존성이다.

개념

ProtocolLib는 마인크래프트의 네트워크 프로토콜 레이어에서 작동한다. 서버와 클라이언트 간에 주고받는 모든 데이터(패킷)를 모니터링하고 수정할 수 있어, 바닐라 마인크래프트의 한계를 뛰어넘는 기능 구현이 가능하다.

주요 기능

패킷 제어

  • 패킷 가로채기 (Intercept)
  • 패킷 수정 (Modify)
  • 패킷 취소 (Cancel)
  • 커스텀 패킷 전송

호환성 시스템

  • 버전 간 호환성 레이어 제공
  • 자동 패킷 ID 매핑
  • NMS(Net.Minecraft.Server) 코드 추상화
  • 다중 프로토콜 버전 지원

성능 최적화

  • 비동기 패킷 처리
  • 효율적인 리플렉션 캐싱
  • 메모리 풀링 시스템

명령어

명령어 설명 권한
/protocol version ProtocolLib 버전 확인 protocol.admin
/protocol timings 패킷 처리 성능 측정 protocol.admin
/protocol listeners 등록된 패킷 리스너 목록 protocol.admin
/protocol dump <플레이어> 플레이어의 패킷 덤프 protocol.admin
/packet monitor <패킷타입> 특정 패킷 모니터링 protocol.admin
/packet send <플레이어> <패킷> 테스트 패킷 전송 protocol.admin

설정

# config.yml 주요 설정
global:
  # 디버그 모드
  debug: false
  
  # 상세 오류 로깅
  detailed_error: false
  
  # 자동 업데이트
  auto_updater: true
  auto_download: false
  
  # 메트릭스 수집
  metrics: true
  
  # 백그라운드 컴파일러
  background_compiler: true
  
  # 패킷 로깅
  log_packet_count: false
  
  # 히스토리 크기
  history_size: 10

# 성능 설정
performance:
  # 비동기 처리
  async_manager_threads: 1
  
  # 패킷 큐 크기
  packet_queue_size: 1024
  
  # 타임아웃 설정
  timeout_ms: 10000

의존 플러그인 예시

ProtocolLib를 필요로 하는 주요 플러그인들:

  • LibsDisguises: 고급 변장 시스템
  • Citizens: NPC 생성 및 관리
  • PacketListenerAPI: 패킷 이벤트 처리
  • NoCheatPlus: 안티치트 시스템
  • HolographicDisplays: 홀로그램 표시
  • PlayerParticles: 플레이어 파티클 효과
  • TabList: 탭 리스트 커스터마이징

개발자를 위한 API

패킷 리스너 등록

// 패킷 리스너 예제
ProtocolManager manager = ProtocolLibrary.getProtocolManager();

manager.addPacketListener(new PacketAdapter(plugin, 
    ListenerPriority.NORMAL, 
    PacketType.Play.Client.CHAT) {
    
    @Override
    public void onPacketReceiving(PacketEvent event) {
        if (event.getPacketType() == PacketType.Play.Client.CHAT) {
            String message = event.getPacket().getStrings().read(0);
            // 채팅 메시지 처리
        }
    }
});

커스텀 패킷 전송

// 타이틀 패킷 전송 예제
PacketContainer packet = manager.createPacket(PacketType.Play.Server.TITLE);
packet.getTitleActions().write(0, TitleAction.TITLE);
packet.getChatComponents().write(0, 
    WrappedChatComponent.fromText("Welcome!"));

manager.sendServerPacket(player, packet);

패킷 타입

주요 패킷 카테고리

# 서버 → 클라이언트
Play.Server:
  - ENTITY_METADATA: 엔티티 메타데이터
  - PLAYER_INFO: 플레이어 정보
  - WORLD_PARTICLES: 파티클 효과
  - BLOCK_CHANGE: 블록 변경
  - CHAT: 채팅 메시지

# 클라이언트 → 서버  
Play.Client:
  - USE_ENTITY: 엔티티 상호작용
  - BLOCK_DIG: 블록 파괴
  - BLOCK_PLACE: 블록 설치
  - HELD_ITEM_SLOT: 핫바 슬롯 변경
  - POSITION: 플레이어 위치

고급 기능

패킷 필터링

// 조건부 패킷 필터링
manager.addPacketListener(new PacketAdapter(plugin,
    ListenerPriority.HIGH,
    PacketType.Play.Server.ENTITY_VELOCITY) {
    
    @Override
    public void onPacketSending(PacketEvent event) {
        Player player = event.getPlayer();
        
        // 특정 조건에서 패킷 취소
        if (player.hasPermission("antikb.bypass")) {
            event.setCancelled(true);
        }
    }
});

비동기 패킷 처리

// 비동기 리스너
AsyncListenerHandler handler = new AsyncListenerHandler(plugin) {
    @Override
    public void onPacketReceiving(AsyncMarker async, PacketEvent event) {
        // 무거운 작업 수행
        async.incrementProcessingDelay();
        
        // 작업 완료 후
        async.decrementProcessingDelay();
    }
};

manager.getAsynchronousManager().registerAsyncHandler(handler);

성능 모니터링

# 패킷 통계 확인
/protocol timings

# 출력 예시:
Packet Statistics:
- ENTITY_METADATA: 15,234 packets/s
- POSITION: 8,521 packets/s
- BLOCK_CHANGE: 3,102 packets/s

Listener Performance:
- MyPlugin: 0.5ms avg
- AnotherPlugin: 1.2ms avg

문제 해결

일반적인 오류

  • ClassNotFoundException: ProtocolLib 버전과 서버 버전 불일치
  • 패킷 오류: 잘못된 패킷 구조나 타입 사용
  • 메모리 누수: 리스너 미해제로 인한 문제

디버깅 방법

# 디버그 모드 활성화
debug: true

# 특정 패킷 추적
/packet monitor ENTITY_METADATA

# 패킷 덤프
/protocol dump PlayerName

보안 고려사항

  • 패킷 조작은 서버 보안에 영향을 줄 수 있음
  • 신뢰할 수 있는 플러그인만 사용 권장
  • 정기적인 업데이트 필수
  • 의심스러운 패킷 패턴 모니터링

버전 호환성

  • 마인크래프트 1.8 - 1.21 지원
  • 각 마인크래프트 버전별 전용 ProtocolLib 버전 존재
  • 하위 호환성 유지를 위한 레거시 API 제공

개발 팁

  • 패킷 리스너는 최소한으로 유지
  • 무거운 작업은 비동기로 처리
  • 불필요한 패킷 생성 자제
  • 리스너 등록 해제 확실히 수행[1]

각주

  1. 메모리 누수 방지를 위해 플러그인 비활성화 시 반드시 해제