PacketEntities is a high-performance, developer library designed to abstract Minecraft's protocol-level entity system. Built on top of PacketEvents, it allows you to easily create, control, and manipulate packet-based entities without the overhead of heavy server-side entities.
Whether you are targeting backend game servers or proxy-side systems, PacketEntities handles the heavy lifting of version-agnostic metadata/object data, spawn packets, and entity tracking seamlessly across Minecraft 1.9.4 through the latest versions.
First, ensure you have PacketEvents shaded or installed on your platform. Then, add PacketEntities to your build system and relocate it to avoid conflicts with other plugins:
plugins {
id("java")
id("com.gradleup.shadow") version "9.1.0"
}
repositories {
// TODO (not published anywhere yet, probably going to use jitpack?)
}
dependencies {
implementation("dev.threeadd.packetentities:spigot:1.0-SNAPSHOT")
}
tasks {
shadowJar {
archiveFileName = project.name + "-" + project.version + ".jar"
relocate("dev.threeadd.packetentities.", "dev.threeadd.packetentitiestest.packetentities.")
}
}TODO
Choose a platform (The example uses paper, but other platforms have similar setups)
// in YourPlugin.java
@Override
void onEnable() {
PacketEntitiesAPISettings settings = new PacketEntitiesAPISettings();
PaperPacketEntitiesPlatform platform = new PaperPacketEntitiesPlatform(this, settings);
PacketEntities.init(platform);
// other logic...
}for spawning a player entity
Location loc = /*...*/;
UUID uuid = UUID.randomUUID();
ProtocolEntity entity = ProtocolEntity.builder()
.entityType(EntityTypes.PLAYER)
.extensions(extensions -> extensions
.extension(new PlayerExtension(
new UserProfile(uuid, "notch"),
GameMode.CREATIVE,
67,
true,
Component.text("Notch", NamedTextColor.GREEN)
))
.extension(new TickExtension())
.extension(new TickVelocityExtension())
)
.viewers(viewers -> viewers
.viewers(Bukkit.getOnlinePlayers().stream().map(Player::getUniqueId).toList())
)
.meta(meta -> {
meta.get(EntityMetaFields.Player.SHARED_FLAGS).setGlowing(true);
meta.set(EntityMetaFields.Player.SCORE, 200);
meta.set(EntityMetaFields.Player.POSE, EntityPose.SITTING);
})
.uuid(uuid)
.velocity(new Vector3d(1, 1, 1))
.version(PacketEvents.getAPI().getServerManager().getVersion())
.buildAndSpawn(ProtocolWorld.of(loc.getWorld().getName()), loc);from packet
WrapperPlayServerEntityMetadata metadataPacket = /*...*/;
ProtocolEntityMeta metadata = new ProtocolEntityMeta(/*...*/); // provided you know the entity type of the packet's data
metadata.setDataFromPacket(metadataPacket);to packet
ProtocolEntityMeta metadata = /*...*/;
int entityId = /*...*/;
ServerVersion version = PacketEvents.getAPI().getServerManager().getVersion();
WrapperPlayServerEntityMetadata metadataPacket = metadata.createPacket(entityId, version);During this project, EntityLib was used as a base to start development from, though PacketEntities was built from scratch.