Skip to content

Repository files navigation

PacketAPI

Modern, versioned access to the Minecraft protocol through direct NMS (CraftPlayer.getHandle(), ServerPlayer.connection.send). Menu/container packets live in PacketUxUi; sign input lives in SignGUI. Optional Netty intercept uses an instance-scoped injection path that refuses to silently overwrite another PacketAPI copy.

Codacy Badge

What it is

  • Per-version paperweight adapters (1.16 → 26.2) sharing one NMS implementation when the packet layout does not break
  • Typed PacketWrap around raw net.minecraft.network.protocol.Packet handles
  • Packet domains, cases, and exemptions so PacketAPI does not fight companion libraries (SignGUI, PacketUxUi)
  • PacketSendEvent / PacketReceiveEvent plus NMS player events (NmsPlayerJoinEvent, NmsSwingEvent, …)
  • Expanded facades: packets, players, connections, metadata, protocol, classifier, cases
  • Folia / Paper / Canvas region-safe schedulers
  • Ownership-aware PacketListenerBus.ensureInjected (single inject entry point) that detects foreign shaded copies via pipeline markers and backs off instead of hijacking
  • No duplication of PacketUxUi window click / open / set-slot / cursor / book packets

Add the dependency

Latest release: 1.0.2 — hosted on Reposilite.

Maven (pom.xml):

<repositories>
    <repository>
        <id>mastersmp-releases</id>
        <url>http://repo.mastersmp.net/releases</url>
    </repository>
</repositories>

<dependencies>
    <dependency>
        <groupId>net.opmasterleo</groupId>
        <artifactId>PacketAPI</artifactId>
        <version>1.0.2</version>
    </dependency>
</dependencies>

Gradle (Groovy) (build.gradle):

repositories {
    maven {
        name = "mastersmp-releases"
        url = uri("http://repo.mastersmp.net/releases")
        isAllowInsecureProtocol = true
    }
}

dependencies {
    implementation("net.opmasterleo:PacketAPI:1.0.2")
}

Gradle (Kotlin DSL) (build.gradle.kts):

repositories {
    maven {
        name = "mastersmp-releases"
        url = uri("http://repo.mastersmp.net/releases")
        isAllowInsecureProtocol = true
    }
}

dependencies {
    implementation("net.opmasterleo:PacketAPI:1.0.2")
}

Send a packet

import net.opmasterleo.packet.PacketAPI;
import net.opmasterleo.packet.PacketAPIConfig;
import net.opmasterleo.packet.event.PacketReceiveEvent;
import net.opmasterleo.packet.event.PacketSendEvent;
import net.opmasterleo.packet.packet.OwnedPacketPolicy;
import net.opmasterleo.packet.packet.PacketExemption;
import net.opmasterleo.packet.packet.PacketExemptions;
import net.kyori.adventure.text.Component;

PacketAPI api = PacketAPI.bootstrap(plugin, PacketAPIConfig.builder()
        .autoInjectOnJoin(true)
        .registerExemption(PacketExemption.builder("MyMenus")
                .domains(net.opmasterleo.packet.packet.PacketDomain.UI_CONTAINER)
                .nameContains("OpenScreen")
                .build())
        .build());

api.packets().setHealth(player, 20f, 20, 5f);
api.packets().keepAlive(player, System.currentTimeMillis());

api.cases().when(packet, view -> {
    if (view.isUiOwned()) return;
    if (view.isEntityLifecycle()) { /* ... */ }
});

@EventHandler
public void onReceive(PacketReceiveEvent event) {
    if (event.getDomain() == net.opmasterleo.packet.packet.PacketDomain.UI_SIGN) {
        return; // SignGUI owns this path
    }
}

Built-in exemptions (disable with respectExemptionsOnSend(false)):

  • PacketExemptions.SIGN_GUI — sign editor packets
  • PacketExemptions.PACKET_UX_UI — menus, containers, slots, books, cursors

Listen without touching Netty:

import net.opmasterleo.packet.event.PacketSendEvent;
import net.opmasterleo.packet.event.NmsPlayerJoinEvent;

@EventHandler
public void onPacket(PacketSendEvent event) {
    if (event.getPacketName().contains("SetHealth")) {
        event.setCancelled(true);
    }
}

@EventHandler
public void onJoin(NmsPlayerJoinEvent event) {
    Object serverPlayer = event.getPlayerHandle();
}

Optional Netty filters (single entry point — never call low-level inject helpers):

api.listeners().addOutbound(player, (viewer, packet) -> OutboundPacketResult.keep());
// Conflict / ownership probe for status/debug:
InjectionProbe.Result probe = api.detectInjectionConflicts(player);
String status = api.injectionStatus(player);

Build / publish

./gradlew shadowJar
./gradlew publish          # Reposilite releases
./gradlew publishSnapshot  # Reposilite snapshots

About

Modern access to the Minecraft protocol

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages