-
-
Notifications
You must be signed in to change notification settings - Fork 38
API example
toxicity188 edited this page Dec 4, 2025
·
41 revisions

To use BetterModel's API, you have to know about BM's architecture.
- Raw data - raw data of model file (like .bbmodel)
- Blueprint - converted data to Minecraft's model file
- Renderer - A renderer of blueprint (model, limb) -> Creates render pipeline (a tree of model bone)
- Tracker - A tracker of renderer (entity, dummy) -> Schedules render pipeline and sync with world or entity.
I published BM's API at these repositories.
repositories {
mavenCentral()
}
dependencies {
compileOnly("io.github.toxicity188:bettermodel:VERSION")
}repositories {
maven("https://maven.pkg.github.com/toxicity188/BetterModel") {
credentials {
username = YOUR_GITHUB_USERNAME
password = YOUR_GITHUB_TOKEN
}
}
}
dependencies {
compileOnly("io.github.toxicity188:bettermodel:VERSION-SNAPSHOT")
}You can always see my test plugin at here.
You can also follow my MythicMobs support to refer how BM's API is work.
BetterModel.model("demon_knight"); //A model file in BetterModel/models (for general model with saving)
BetterModel.limb("steve"); //A model file in BetterModel/players (for player model with no saveing)
BetterModel.modelOrNull("demon_knight"); //general model or null
BetterModel.limbOrNull("steve"); //player model or nullYou can apply some model to specific entity or player.
EntityTracker tracker = BetterModel.model("demon_knight")
.map(r -> r.getOrCreate(entity)) //Gets or creates entity tracker by this renderer to some entity.
.orElse(null);EntityTracker tracker = BetterModel.model("demon_knight")
.map(r -> r.create(entity, TrackerModifier.DEFAULT, t -> t.update(TrackerUpdateAction.tint(0x0026FF)))) //Creates entity tracker with pre-spawn task.
.orElse(null);Also, you can create some model to dummy.
DummyTracker tracker = BetterModel.model("demon_knight")
.map(r -> r.create(location)) //Creates some dummy tracker to this location.
.orElse(null);
DummyTracker skinTracker = BetterModel.limb("steve")
.map(r -> r.create(location, ModelProfile.of(player))) //Creates some dummy tracker to this location and player's skin profile.
.orElse(null);BetterModel.registry(uuid); //Gets optional registry from some uuid
BetterModel.registry(entity); //Gets optional registry from some entity if entity has model data.if (entity instanceof HitBox hitbox) {
Entity source = hitbox.source(); //Gets source entity
EntityTrackerRegistry source = hitbox.registry().orElse(null); //Gets source entity's registry
}BetterModel.registry(entity) //Gets tracker registry.
.map(reg -> reg.tracker("model")) //Gets tracker by it's name
.ifPresent(tracker -> tracker.animate("animation_name", AnimationModifier.DEFAULT_WITH_PLAY_ONCE, () -> {
//Do stuff when this animation is being removed.
});
});RenderedBone bone = BetterModel.registry(entity) //Gets tracker registry.
.map(reg -> reg.tracker("model")) //Gets tracker by it's name
.map(tracker -> tracker.bone("bone_name")) //Searches bone by it's raw name.
.orElse(null);Vector3f wpos = BetterModel.registry(entity) //Gets tracker registry.
.map(reg -> reg.tracker("model")) //Gets tracker by it's name
.map(tracker -> tracker.bone("bone_name")) //Searches bone by it's raw name.
.map(HitBoxSource::hitBoxPosition) //Gets bone's world relative position.
.orElse(null);
if (wpos == null) return;
Location finalLocation = entity.getLocation().add(wpos.x, wpos.y, wpos.z) //Final bone's world position = base entity's location + bone's positionRunningAnimation runningAnimation = BetterModel.registry(entity) //Gets tracker registry.
.map(reg -> reg.tracker("model")) //Gets tracker by it's name
.map(tracker -> tracker.bone("bone_name")) //Searches bone by it's raw name.
.map(RenderedBone::runningAnimation) //Gets running animation.
.orElse(null);BetterModel.registry(entity) //Gets tracker registry.
.map(reg -> reg.tracker("model")) //Gets tracker by it's name
.ifPresent(tracker -> {
boolean hideSuccess = tracker.hide(player); //Hide
boolean showSuccess = tracker.show(player); //Show
});BetterModel.limb("steve") //Gets model first
.flatMap(r -> r.animation("roll")) //Flat map to optional animation
.map(BlueprintAnimation::length) //Gets animation's length second
.orElse(0F) //Null value@EventHandler
public void spawn(CreateTrackerEvent event) {
event.tracker().getPipeline().viewFilter(player -> !player.isAfk()) //Prevents sending animation packet when player is AFK
}BetterModel.registry(entity) //Gets tracker registry.
.map(reg -> reg.tracker("model")) //Gets tracker by it's name
.ifPresent(Tracker::close);BetterModel.registry(entity).ifPresent(EntityTrackerRegistry::close);BetterModel.model("demon_knight")
.map(r -> r.create(entity, TrackerModifier.DEFAULT, t -> {
t.update(TrackerUpdateAction.tint(rgb)); //Tint
t.update(TrackerUpdateAction.enchant(true), bone -> true); //Enchant with predicate
}))
.ifPresent(tracker -> tracker.update(TrackerUpdateAction.composite( //Composite
TrackerUpdateAction.brightness(15, 15) //Brightness
TrackerUpdateAction.billboard(Display.Billboard.CENTER) //Billboard
)));
}//Creates animation modifier
AnimationModifier modifier = AnimationModifier.builder()
.player(player) //Sets target player
.type(AnimationIterator.Type.PLAY_ONCE)
.build()
BetterModel.registry(entity) //Gets tracker registry.
.map(reg -> reg.tracker("model")) //Gets tracker by it's name
.ifPresent(tracker -> tracker.animate("animation_name", modifier));