Documentation Index Fetch the complete documentation index at: https://mintlify.com/toxicity188/BetterModel/llms.txt
Use this file to discover all available pages before exploring further.
This guide walks you through creating your first entity-based model with BetterModel.
Overview
Entity models are 3D models attached to Minecraft entities. They follow the entity’s position, rotation, and can respond to entity events like damage.
Prerequisites
Prepare Your Model
Create a BlockBench model and export it as .bbmodel format. Place it in BetterModel/models/ directory.
Add Plugin Dependency
Add BetterModel API to your build.gradle or pom.xml: repositories {
mavenCentral()
}
dependencies {
compileOnly("io.github.toxicity188:bettermodel-bukkit-api:2.2.0")
}
Basic Implementation
Creating an Entity Model
Here’s how to spawn a basic entity model:
import kr.toxicity.model.api.BetterModel;
import kr.toxicity.model.api.entity.BaseEntity;
import kr.toxicity.model.api.tracker.EntityTracker;
import org.bukkit.entity.Zombie;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntitySpawnEvent;
public class BasicModelListener implements Listener {
@ EventHandler
public void onEntitySpawn ( EntitySpawnEvent event ) {
if ( ! ( event . getEntity () instanceof Zombie zombie)) return ;
// Get the model renderer
BetterModel . model ( "demon_knight" ). ifPresent (renderer -> {
// Create entity tracker
EntityTracker tracker = renderer . create (
BaseEntity . of (zombie)
);
// Model is now attached and will render automatically
});
}
}
Getting or Creating Models
Use getOrCreate() to avoid creating duplicate models:
// Gets existing tracker or creates new one
EntityTracker tracker = BetterModel . model ( "demon_knight" )
. map (renderer -> renderer . getOrCreate ( BaseEntity . of (entity)))
. orElse ( null );
Playing Animations
Basic Animation
// Play the "walk" animation
tracker . animate ( "walk" );
// Play with custom settings
tracker . animate ( "attack" , AnimationModifier . builder ()
. start ( 5 ) // 5 tick fade-in
. end ( 5 ) // 5 tick fade-out
. speed ( 1.5F ) // 1.5x speed
. build ()
);
Stop Animation
// Stop specific animation
tracker . stopAnimation ( "walk" );
// Stop all animations on filtered bones
tracker . stopAnimation (bone -> bone . name (). value (). contains ( "arm" ), "attack" );
Updating Model Properties
Change Colors and Effects
import kr.toxicity.model.api.tracker.TrackerUpdateAction;
// Apply red tint (RGB)
tracker . update ( TrackerUpdateAction . tint ( 0xFF0000 ));
// Enable glow effect
tracker . update ( TrackerUpdateAction . glow ( true ));
// Set custom brightness (block light, sky light)
tracker . update ( TrackerUpdateAction . brightness ( 15 , 15 ));
// Composite multiple updates
tracker . update ( TrackerUpdateAction . composite (
TrackerUpdateAction . glow ( true ),
TrackerUpdateAction . glowColor ( 0x00FF00 ),
TrackerUpdateAction . enchant ( true )
));
Managing Model Lifecycle
Closing and Cleanup
// Close and remove model (calls despawn packets)
tracker . close ();
// Just despawn without closing
tracker . despawn ();
// Check if tracker is closed
if ( tracker . isClosed ()) {
// Handle closed tracker
}
Handle Close Events
tracker . handleCloseEvent ((t, reason) -> {
switch (reason) {
case REMOVE -> System . out . println ( "Model manually removed" );
case DESPAWN -> System . out . println ( "Entity despawned" );
case PLUGIN_DISABLE -> System . out . println ( "Plugin disabled" );
}
});
Player Visibility Control
import org.bukkit.entity.Player;
// Hide model from specific player
tracker . hide (player);
// Show model to specific player
tracker . show (player);
// Check if hidden
if ( tracker . isHide (player)) {
tracker . show (player);
}
Best Practices
Always use getOrCreate() instead of create() to prevent duplicate trackers
Store tracker references in a map keyed by entity UUID for easy retrieval
Close trackers when entities are removed to prevent memory leaks
Use Optional to safely handle cases where models don’t exist
Creating multiple trackers for the same entity can cause visual glitches
Always check if a model exists before trying to create a tracker
Trackers are not automatically removed when entities die - handle cleanup manually
Complete Example
Java - Complete System
Kotlin - Complete System
import kr.toxicity.model.api.BetterModel;
import kr.toxicity.model.api.entity.BaseEntity;
import kr.toxicity.model.api.tracker.EntityTracker;
import kr.toxicity.model.api.tracker.TrackerUpdateAction;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity. * ;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
public class ModelSystem implements Listener {
private final Map < UUID , EntityTracker > trackers = new ConcurrentHashMap <>();
@ EventHandler
public void onSpawn ( EntitySpawnEvent event ) {
if ( ! ( event . getEntity () instanceof LivingEntity entity)) return ;
BetterModel . model ( "demon_knight" ). ifPresent (renderer -> {
EntityTracker tracker = renderer . getOrCreate ( BaseEntity . of (entity));
trackers . put ( entity . getUniqueId (), tracker);
// Start idle animation
tracker . animate ( "idle" );
});
}
@ EventHandler
public void onDamage ( EntityDamageEvent event ) {
EntityTracker tracker = trackers . get ( event . getEntity (). getUniqueId ());
if (tracker == null ) return ;
// Play damage animation and apply red tint
tracker . animate ( "damage" );
tracker . damageTint (); // Built-in damage tint effect
}
@ EventHandler
public void onDeath ( EntityDeathEvent event ) {
EntityTracker tracker = trackers . remove ( event . getEntity (). getUniqueId ());
if (tracker == null ) return ;
// Play death animation, then close after 2 seconds
tracker . animate ( "death" );
tracker . location (). taskLater ( 40 , tracker :: close);
}
}
Next Steps
Animated NPC Create interactive NPCs with custom animations
Custom Events Learn about hitbox interactions and custom events
Conditional Animations Implement state-based animation systems
API Reference Explore the complete API documentation