Entities
How to define, register, and spawn custom entities and mobs in PowerNukkitX.
PowerNukkitX supports registering custom entities. Like blocks and items, custom entities require clients to download a resource pack containing their textures, models/geometries, and client-side entity definitions.
Registering a Custom Entity
Entities are registered in your plugin's onLoad() method. After registering, you must rebuild the entity tag registry:
import org.powernukkitx.registry.RegisterException;
import org.powernukkitx.registry.Registries;
@Override
public void onLoad() {
try {
Registries.ENTITY.registerCustomEntity(this, MyPig.class);
// Rebuild the NBT tags so the server registers the custom entity type
Registries.ENTITY.rebuildTag();
} catch (RegisterException e) {
throw new RuntimeException(e);
}
}Defining the Entity
Custom entities extend org.powernukkitx.entity.Entity and implement org.powernukkitx.entity.custom.CustomEntity. You must define getIdentifier(), getOriginalName(), and return a static CustomEntityDefinition method:
import org.powernukkitx.entity.Entity;
import org.powernukkitx.entity.custom.CustomEntity;
import org.powernukkitx.entity.custom.CustomEntityDefinition;
import org.powernukkitx.level.format.IChunk;
import org.powernukkitx.nbt.tag.CompoundTag;
import org.jetbrains.annotations.NotNull;
public class MyPig extends Entity implements CustomEntity {
public static final String IDENTIFIER = "powernukkitx:boar";
public MyPig(IChunk chunk, CompoundTag nbt) {
super(chunk, nbt);
}
@Override
public @NotNull String getIdentifier() {
return IDENTIFIER;
}
@Override
public String getOriginalName() {
return "boar";
}
// This method returns the client-facing definition properties of the entity
public static CustomEntityDefinition definition() {
return CustomEntityDefinition.simpleBuilder(IDENTIFIER)
.eid(IDENTIFIER)
.hasSpawnEgg(true) // Generates a creative inventory spawn egg
.isSummonable(true) // Allows spawning via /summon command
.originalName("Feral Boar")
.health(20) // Maximum health points
.attack(3) // Melee attack damage
.movement(0.2f) // Speed modifier
.typeFamily("mob", "pig") // Entity classification family
.collisionBox(0.9f, 0.9f) // Width and height collision boundaries
.knockbackResistance(0.2f)
.isPersistent(true) // Keeps the mob loaded at distance
.build();
}
}Rideable Entities (Mounts)
PowerNukkitX supports defining entities that players or other mobs can ride (such as horses, custom vehicles, or dragons) using the Bedrock minecraft:rideable component.
To configure a rideable entity, specify the RideableComponent in your CustomEntityDefinition builder. You can define details like seat coordinates and camera offsets:
package org.example.entity;
import org.powernukkitx.entity.Entity;
import org.powernukkitx.entity.custom.CustomEntity;
import org.powernukkitx.entity.custom.CustomEntityDefinition;
import org.powernukkitx.entity.components.RideableComponent;
import org.powernukkitx.level.format.IChunk;
import org.powernukkitx.math.Vector3f;
import org.powernukkitx.nbt.tag.CompoundTag;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.Set;
public class RideableBoar extends Entity implements CustomEntity {
public static final String IDENTIFIER = "powernukkitx:rideable_boar";
public RideableBoar(IChunk chunk, CompoundTag nbt) {
super(chunk, nbt);
}
@Override
public @NotNull String getIdentifier() {
return IDENTIFIER;
}
@Override
public String getOriginalName() {
return "rideable_boar";
}
public static CustomEntityDefinition definition() {
// Define seat positions relative to the entity pivot point (X, Y, Z coordinates)
List<RideableComponent.Seat> seats = List.of(
new RideableComponent.Seat(
1, // Minimum rider count
1, // Maximum rider count
new Vector3f(0f, 1.2f, -0.2f), // Physical coordinate offset of the seat
null, // Lock rider rotation (null to allow rotation)
null, // Rotate rider by degrees (null for default)
3.0f, // Third-person camera distance/radius multiplier
null // Camera smoothing
)
);
// Build the rideable component
RideableComponent rideable = new RideableComponent(
0, // Controlling seat index
true, // Crouching players skip mounting interaction
RideableComponent.DismountMode.DEFAULT,
Set.of("player"), // Entity families allowed to ride
"action.interact.ride", // Localization text string shown to Bedrock players
0f, // Passenger max width boundary (0 for unlimited)
false, // Pull in nearby entities automatically
true, // Riders can interact with chests/world while riding
1, // Seat count
seats // Seat configurations
);
return CustomEntityDefinition.simpleBuilder(IDENTIFIER)
.eid(IDENTIFIER)
.hasSpawnEgg(true)
.isSummonable(true)
.originalName("Rideable Boar")
.health(30)
.collisionBox(0.9f, 0.9f)
.rideable(rideable) // Bind the rideable component
.build();
}
}Spawning Custom Entities
Once registered, custom entities can be spawned:
- Via the
/summoncommand (if.isSummonable(true)was set in the definition). - Via the spawn egg in the Creative inventory (if
.hasSpawnEgg(true)). - Programmatically via the API.
Here is an example command executor spawning the custom entity at a player's location:
import org.powernukkitx.Player;
import org.powernukkitx.command.Command;
import org.powernukkitx.command.CommandSender;
import org.powernukkitx.entity.Entity;
import org.powernukkitx.nbt.tag.CompoundTag;
@Override
public boolean execute(CommandSender sender, String label, String[] args) {
if (sender instanceof Player player) {
// Construct default NBT tags for coordinates
CompoundTag nbt = Entity.getDefaultNBT(player.getPosition());
// Create the entity
RideableBoar boar = new RideableBoar(player.getChunk(), nbt);
// Spawn for everyone
boar.spawnToAll();
player.sendMessage("Spawned a rideable boar!");
return true;
}
return false;
}