Skip to content

Injecting an entity

After completing the project setup, creating a bootstrapper and writing your entity class, you’re ready to register your entity injection in your bootstrapper’s bootstrap() function. This is done using:

Bestium.getInjector().register(Supplier<EntityInjection>)

The Supplier provides an EntityInjection instance. Since this registration happens very early in server startup (before Bukkit or CraftBukkit are initialized) you can’t create the EntityInjection immediately. The Supplier is only resolved once the internals are ready.

An EntityInjection is created using:

EntityInjection.builder(...).build()

You must provide five required parameters:

A unique entity key, use your plugin namespace and a unique entity name:

Key.key("my_plugin", "capybara")

The entity class you’ve created:

Capybara::class.java

A factory constructing the entity from an EntityType and a Level, usually the constructor reference of your entity:

::Capybara

A function that converts our NMS entity into a Bukkit type. This is usually the constructor of a CraftBukkkit entity wrapper class and depends on the base abstract class you extended:

Base Bestium classCraftBukkit wrapper class
AbstractFishCraftFish
AbstractGolemCraftGolem
AbstractSchoolingFishPaperSchoolableFish
AbstractVillagerCraftAbstractVillager
AgeableMobCraftAgeable
AgeableWaterCreaturemissing, use CraftAgeable
AmbientCreatureCraftAmbient
AnimalCraftAnimals
EntityCraftEntity
LivingEntityCraftLivingEntity
MobCraftMob
MonsterCraftMonster
PathfinderMobCraftCreature
ShoulderRidingEntitymissing, use CraftTameableAnimal
TamableAnimalCraftTameableAnimal
WaterAnimalCraftWaterMob

Our capybara extends Animal, so we reference the constructor of CraftAnimals:

::CraftAnimals

A backing entity type. This is a very important parameter, before you choose you may want to read a little about how Bestium works internally.

Bestium uses backing type as the “disguise for your entity” that is actually sent to the client over the network protocol. If you choose an incompatible (too distant) backing type, it can lead to the client throwing a “Network Protocol Error” and disconnecting.

For example, if your entity directly extends Animal a good backing type might be EntityType.PIG or EntityType.COW.

You must never mix living and non-living entities. If you select a non-living backing entity type for your living entity (or vice versa), disconnect issues are pretty much guaranteed.

Once you’ve provided the required parameters, you can continue chaining configuration methods to further customize your entity. For the full list of options, see the EntityInjection.Builder Javadoc.
Below is a selection of the most important configuration methods you’ll likely want to use:

You must call this for living entities!

Defines the default entity attributes, you should call the static attributes method created earlier.

.setDefaultAttributes(Capybara.createDefaultAttributes())

Defaults to: no default attributes

Sets the category this mob belongs to, this defines whether the mob is friendly or hostile, how many instances there can be per chunk, whether it persists in world or how far from the player it despawns.

Mob categoryDescriptionMax per chunkFriendlyPersistentDespawn distance
MONSTERmonsters like Zombies or Skeletons70falsefalse128
CREATUREfriendly mobs like Sheep or Villagers10truetrue128
AMBIENTambient surface creatures like Bats15truefalse128
AXOLOTLSaxolotls5truefalse128
WATER_CREATUREfriendly water mobs like Dolphins and Squids5truefalse128
UNDERGROUND_WATER_CREATUREfriendly water mobs underground like Glow Squids5truefalse128
WATER_AMBIENTambient water creatures like Cods and Salmon20truefalse64
MISCentities that don’t naturally spawn like Boats, TNT or Projectiles-truetrue128

Our capybara is a friendly mob, so we use CREATURE:

.setMobCategory(MobCategory.CREATURE)

Defaults to: MobCategory.MISC

Sets the display name for this entity for the provided locale.

For example, here’s how you might define localized names for a capybara:

.setDisplayName(Locale.US, Component.text("Capybara"))
.setDisplayName(Locale.FRANCE, Component.text("Capybara"))
.setDisplayName(Locale.GERMANY, Component.text("Wasserschwein"))
.setDisplayName(Locale.ITALY, Component.text("Capibara"))
.setDisplayName(Locale.JAPAN, Component.text("カピバラ"))
.setDisplayName(Locale.KOREA, Component.text("카피바라"))
.setDisplayName(Locale.CHINA, Component.text("水豚"))
.setDisplayName(Locale.of("cs", "CZ"), Component.text("Kapybara"))

You can also set multiple display names at once using setDisplayNames(Map<Locale, Component>).

If you don’t care about localization, you can use the shorthand setDisplayName(Component) which sets the name for the default Locale.US.

If no display name is set, the entity will appear using its translation key (e.g., entity.my_plugin.capybara) in most places.

Sets a type customizer for the entity type being created. This allows you to modify the underlying EntityType.Builder before it is built and registered for injection.

You can use this to customize properties like whether the entity can be summoned with /summon, whether it’s fire immune, and more:

.setTypeCustomizer { builder ->
builder.noSummon()
builder.fireImmune()
}

Defaults to: no customizer

Additional configuration related to entity variants is available, but it is documented separately on the Variants API page.

If you want to configure natural biome spawning for your entities, refer to the dedicated Biome API documentation.