Skip to content
블로그로 돌아가기
Java code showing ProtocolLib packet listener implementation for Minecraft server plugins

ProtocolLib: Building Advanced Minecraft Server Plugins in 2026

ice
ice
@ice
Updated
133 조회수
TL;DR:ProtocolLib is a Java library that provides a safe event API for monitoring and modifying Minecraft server packets. It abstracts away obfuscated code and stays stable across Minecraft updates, making it essential for building advanced server plugins.
🐙 Open-source Minecraft project

dmulloy2/ProtocolLib

Provides read and write access to the Minecraft protocol with Bukkit.

⭐ 1,285 stars💻 Java📜 GPL-2.0
View on GitHub ↗

Ever tried to build a Minecraft server plugin that does something the standard Bukkit API won't let you do? Yeah, that's where most developers hit a wall. You either reverse-engineer obfuscated Minecraft code (which breaks every update), hook into internal CraftBukkit classes (and pray no other plugin does the same thing), or you just give up. ProtocolLib is the project that exists specifically so you don't have to.

What This Project Solves

ProtocolLib is a Java library that gives you clean, safe access to the Minecraft network protocol. Instead of wrestling with obfuscated bytecode or dodgy reflection hacks, you get a proper event API that lets you listen to, modify, or cancel packets sent between the server and clients. Think of it like Bukkit events, but for the protocol layer.

The big win: you don't reference CraftBukkit at all. No version-specific imports that break in 1.21. No fragile assumptions about internal class structures. Just packet listeners that stay stable across updates.


Real Minecraft Use Cases

Chat filtering and moderation is the most obvious application. Listen for client-side chat packets, read the message content through ProtocolLib's API, and cancel the packet if the player tries something you've blocked. The message never even reaches the server. Clean, simple, and it works every single update.

Custom network features are where things get interesting. You could build invisible particle effects, modify player appearance without skin changes, or send data to the server that the vanilla protocol doesn't officially support. A dueling system with custom visuals? A voting interface that responds to player movement packets? These are the kinds of things ProtocolLib makes possible.

But the real reason most people reach for it's plugin compatibility. When multiple plugins hook the same internal classes, everything gets messy. Plugins crash. Data corrupts silently. ProtocolLib centralizes packet handling so different plugins can actually coexist without stepping on each other's toes. That's not glamorous, but it's what keeps servers running smoothly.


Installation and Setup

If you're building a Bukkit plugin, the setup is straightforward. Add the dependency to your build file first.

For Maven:

xml
<dependencies>
 <dependency>
 <groupId>net.dmulloy2</groupId>
 <artifactId>ProtocolLib</artifactId>
 <version>5.4.0</version>
 <scope>provided</scope>
 </dependency>
</dependencies>

Note that version 5.4.0 requires Java 17 or higher, so make sure your build environment is up to date. If you're on an older server, grab an earlier release instead.

Gradle users should add it like this:

gradle
repositories {
 mavenCentral()
}

dependencies {
 compileOnly 'net.dmulloy2:ProtocolLib:5.4.0'
}

Next, add ProtocolLib as a dependency in your plugin.yml:

yml
depend: [ ProtocolLib ]

This tells the server that your plugin won't start unless ProtocolLib loads first. Critical for avoiding null pointer exceptions on startup. Then grab a reference to the ProtocolManager in your plugin's onLoad() method:

java
private ProtocolManager protocolManager;

public void onLoad() {
 protocolManager = ProtocolLibrary.getProtocolManager();
}

That's it. You're ready to start listening for packets.


How Packet Listeners Work

The simplest listener just disables something. Say you want to mute all sound effects server-wide:

java
protocolManager.addPacketListener(new PacketAdapter(
 this,
 ListenerPriority.NORMAL,
 PacketType.Play.Server.NAMED_SOUND_EFFECT
) {
 @Override
 public void onPacketSending(PacketEvent event) {
 event.setCancelled(true);
 }
});

Most of the complexity is right there. You create a PacketAdapter, specify which packet type you're listening for, override the callback, and modify the event.

Where it gets useful is reading and changing packet content. Here's a global chat filter:

java
protocolManager.addPacketListener(new PacketAdapter(
 this,
 ListenerPriority.NORMAL,
 PacketType.Play.Client.CHAT
) {
 @Override
 public void onPacketReceiving(PacketEvent event) {
 PacketContainer packet = event.getPacket();
 String message = packet.getStrings().read(0);

 if (message.contains("badword")) {
 event.setCancelled(true);
 }
 }
});

The getPacket() call gives you the packet data. You read fields by type (strings, integers, bytes) using their index. No field names, just positions. It's abstract at first, but it means you're never dependent on Minecraft's internal naming, which changes constantly with obfuscation.

You can modify packets too. Packet data is mutable, so you can write new values before they're sent. Listener priority matters as well - if multiple plugins listen to the same packet type, LOWEST runs first, HIGHEST runs last, letting you control execution order.


Key Features That Make This Worth Using

The abstraction layer is the main thing. Instead of dealing with obfuscated NMS (net.minecraft.server) classes, ProtocolLib wraps everything into typed accessors. Want to read player position? It's just packet.getDoubles().read(0), not hunting through a maze of getter methods on some internal class that probably renamed itself last snapshot.

Version compatibility is huge. ProtocolLib maintains packet definitions for every major Minecraft release. When you update your server from 1.20 to 1.21.4, your ProtocolLib code just works. The library handles protocol changes internally. You don't recompile anything.

Packet injection is another solid feature. You can create packets from scratch and send them to players:

java
PacketContainer packet = protocolManager.createPacket(PacketType.Play.Server.NAMED_SOUND_EFFECT);
// populate fields...
protocolManager.sendServerPacket(player, packet);

That's clean compared to trying to instantiate NMS packet classes directly. And again, it survives updates without modification.

The library also includes helper classes like WrappedChatComponent, ChunkData, and PlayerInfoData - basically anything tricky to construct gets wrapped with convenient builders. The recent 5.4.0 release fixed initialization issues for versions 1.20.4 through 1.21.5, so they're actively maintained.


What Trips New Users Up

The index-based field access takes getting used to. You look up the packet wiki to figure out which index corresponds to which field. For common packets it's documented, but if you're dealing with something custom or very recent, you're on your own. That's the tradeoff for not being tied to internal class names.

Thread safety matters. Minecraft runs packet handling on the network thread, and your listener code runs there too. If you do anything heavy, schedule it on the main server thread via Bukkit.getScheduler(). Blocking your packet listener stalls the entire network pipeline.

Version mismatches will destroy you. If you compile against ProtocolLib 5.4.0 but the server has 5.3.0 installed, you get runtime class not found errors. Match versions exactly. Don't rely on features from newer releases unless you specify a minimum version in your plugin.yml.

Debugging is harder than regular code because everything is listener-based. If a packet isn't behaving right, add logging at each step. Verify your listener is being called. Check that field indices match what you expect. The protocol wiki is your friend here.


Alternatives and When to Consider Them

PacketEvents exists as another option, though it's newer and less battle-tested. If you're building something that needs deep protocol access with modern tooling and don't mind being on slightly less stable ground, PacketEvents might appeal to you. But ProtocolLib is the established choice - 1285 GitHub stars, actively maintained, and the latest release supports Minecraft 1.21.4 through 1.21.8.

Some developers just work directly with NMS for highly specialized use cases. That's usually a mistake because you're signing up for maintenance work every Minecraft release. ProtocolLib handles that for you.

If you need to explore what players can do with your server, check out our Minecraft Skin Creator and Minecraft Block Search tools.

dmulloy2/ProtocolLib - GPL-2.0, ★1285

Frequently Asked Questions

Is ProtocolLib free and open source?
Yes, ProtocolLib is licensed under GPL-2.0 and freely available on GitHub. You can download the jar from the releases page or add it as a Maven/Gradle dependency from Maven Central. No licensing fees or proprietary restrictions.
What Minecraft versions does ProtocolLib support?
ProtocolLib 5.4.0 supports Minecraft 1.21.4 through 1.21.8. Earlier releases support older versions back to 1.8. Check the GitHub releases page to find the version compatible with your server. The library maintains packet definitions for every major release.
Will my ProtocolLib plugins break when Minecraft updates?
Usually no. ProtocolLib abstracts packet changes so your code stays stable across updates. However, major Minecraft version jumps (1.20 to 1.21) may occasionally require adjustments. The maintainers update packet definitions quickly after new releases.
Can I use ProtocolLib on a Paper or Spigot server?
Yes. ProtocolLib works on any Bukkit-compatible server including Paper, Spigot, and Purpur. Add it as a dependency in your plugin.yml and install the ProtocolLib jar on your server. It'll load before your plugin starts.
What's the difference between ProtocolLib and direct NMS access?
ProtocolLib provides a stable, version-independent API while NMS requires you to reference obfuscated Minecraft internals directly. NMS code breaks every update and becomes unreadable. ProtocolLib handles those details for you, making plugins maintainable long-term.