API example - toxicity188/BetterModel GitHub Wiki
Architecture
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.
Repository
I published BM's API at these repositories.
Release
repositories {
mavenCentral()
}
dependencies {
compileOnly("io.github.toxicity188:bettermodel:VERSION")
}
Snapshot
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")
}
API Tester plugin
You can always see my test plugin at here.
You can also follow my MythicMobs support to refer how BM's API is work.
General API usage
Gets some model or limb
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 null
Creates model
You 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);
Gets entity tracker's registry
BetterModel.registry(uuid); //Gets optional registry from some uuid
BetterModel.registry(entity); //Gets optional registry from some entity if entity has model data.
Checks some entity is hitbox entity
if (entity instanceof HitBox hitbox) {
Entity source = hitbox.source(); //Gets source entity
EntityTrackerRegistry source = hitbox.registry().orElse(null); //Gets source entity's registry
}
Runs animation
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.
});
});
Gets bone
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);
Gets bone's world position
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 position
Gets bone's currently played animation
RunningAnimation 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);
Hide/Show some model tracker
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
});
Gets animation's length
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
Add view/spawn/hide filter
@EventHandler
public void spawn(CreateTrackerEvent event) {
event.tracker().getPipeline().viewFilter(player -> !player.isAfk()) //Prevents sending animation packet when player is AFK
}
Removes some tracker
BetterModel.registry(entity) //Gets tracker registry.
.map(reg -> reg.tracker("model")) //Gets tracker by it's name
.ifPresent(Tracker::close);
Removes all tracker of some entity
BetterModel.registry(entity).ifPresent(EntityTrackerRegistry::close);
Update some tracker's display data
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
)));
}
Animate animation per specific player
//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));