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@OverridevoidonEnable() {
PacketEntitiesAPISettingssettings = newPacketEntitiesAPISettings();
PaperPacketEntitiesPlatformplatform = newPaperPacketEntitiesPlatform(this, settings);
PacketEntities.init(platform);
// other logic...
}for spawning a player entity
Locationloc = /*...*/;
UUIDuuid = UUID.randomUUID();
ProtocolEntityentity = ProtocolEntity.builder()
.entityType(EntityTypes.PLAYER)
.extensions(extensions -> extensions
.extension(newPlayerExtension(
newUserProfile(uuid, "notch"),
GameMode.CREATIVE,
67,
true,
Component.text("Notch", NamedTextColor.GREEN)
))
.extension(newTickExtension())
.extension(newTickVelocityExtension())
)
.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(newVector3d(1, 1, 1))
.version(PacketEvents.getAPI().getServerManager().getVersion())
.buildAndSpawn(ProtocolWorld.of(loc.getWorld().getName()), loc);from packet
WrapperPlayServerEntityMetadatametadataPacket = /*...*/;
ProtocolEntityMetametadata = newProtocolEntityMeta(/*...*/); // provided you know the entity type of the packet's datametadata.setDataFromPacket(metadataPacket);to packet
ProtocolEntityMetametadata = /*...*/;
intentityId = /*...*/;
ServerVersionversion = PacketEvents.getAPI().getServerManager().getVersion();
WrapperPlayServerEntityMetadatametadataPacket = metadata.createPacket(entityId, version);During this project, EntityLib was used as a base to start development from, though PacketEntities was built from scratch.