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.
Overview
The RenderPipeline class represents the rendering pipeline for a specific model instance. It manages the hierarchy of rendered bones, handles player visibility and packet bundling, and coordinates animation updates and inverse kinematics (IK) solving.
Constructor
public RenderPipeline(
@NotNull ModelRenderer parent,
@NotNull RenderSource<?> source,
@NotNull RenderedBone[] bones
)
Creates a new render pipeline instance.
Parameters:
parent - The parent model renderer
source - The source of the rendering (entity or location)
bones - The array of root bones
Core Properties
getParent
public ModelRenderer getParent()
Returns the parent ModelRenderer that created this pipeline.
getSource
public RenderSource<?> getSource()
Returns the RenderSource providing location and context data.
getRotation
public ModelRotation getRotation()
Returns the current rotation state of the model.
name
public @NotNull String name()
Returns the name of the parent model renderer.
Bone Management
bones
public @NotNull @Unmodifiable Collection<RenderedBone> bones()
Returns an unmodifiable collection of all bones in the pipeline.
boneOf
public @Nullable RenderedBone boneOf(@NotNull BoneName name)
Retrieves a specific bone by its name.
Parameters:
name - The bone name to search for
Returns: The rendered bone, or null if not found
stream
public @NotNull Stream<RenderedBone> stream()
Returns a sequential stream of all flattened bones.
hitboxes
public @NotNull Stream<HitBox> hitboxes()
Returns a stream of all hitboxes associated with the model.
Example:
RenderPipeline pipeline = tracker.pipeline();
// Access specific bone
RenderedBone headBone = pipeline.boneOf(BoneName.of("head"));
if (headBone != null) {
headBone.scale(1.5f);
}
// Iterate all bones
pipeline.bones().forEach(bone -> {
System.out.println("Bone: " + bone.name());
});
// Work with hitboxes
pipeline.hitboxes().forEach(hitbox -> {
hitbox.setInteractive(true);
});
Animation & Updates
tick
public boolean tick(@NotNull PacketBundler bundler)
public boolean tick(@NotNull UUID uuid, @NotNull PacketBundler bundler)
Ticks the model, updating animations and inverse kinematics.
Parameters:
bundler - The packet bundler for sending updates
uuid - (Optional) Player UUID for per-player animations
Returns: true if any updates occurred
runningAnimation
public @Nullable RunningAnimation runningAnimation()
Retrieves the currently running animation, if any.
rotate
public boolean rotate(@NotNull ModelRotation rotation, @NotNull PacketBundler bundler)
Rotates the model to a new orientation.
Parameters:
rotation - The new rotation
bundler - The packet bundler to use
Returns: true if the rotation changed, false otherwise
Example:
PacketBundler bundler = pipeline.createBundler();
// Tick the pipeline
if (pipeline.tick(bundler)) {
// Send updates to players
pipeline.allPlayer().forEach(bundler::send);
}
// Rotate model
ModelRotation rotation = ModelRotation.of(0, 90, 0);
pipeline.rotate(rotation, bundler);
// Check current animation
RunningAnimation anim = pipeline.runningAnimation();
if (anim != null) {
System.out.println("Playing: " + anim.name());
}
Bone Modifiers
addRotationModifier
public boolean addRotationModifier(
@NotNull BonePredicate predicate,
@NotNull Function<Quaternionf, Quaternionf> mapper
)
Adds a rotation modifier to bones matching the predicate.
Parameters:
predicate - The predicate to select bones
mapper - The rotation mapping function
Returns: true if any bones were modified
addPositionModifier
public boolean addPositionModifier(
@NotNull BonePredicate predicate,
@NotNull Function<Vector3f, Vector3f> mapper
)
Adds a position modifier to bones matching the predicate.
Parameters:
predicate - The predicate to select bones
mapper - The position mapping function
Returns: true if any bones were modified
defaultPosition
public void defaultPosition(@NotNull Function<Vector3f, Vector3f> movement)
Sets the default position modifier for all bones.
scale
public void scale(@NotNull FloatSupplier scale)
Scales the entire model.
Example:
// Scale the entire model
pipeline.scale(() -> 1.5f);
// Move all bones up by 1 block
pipeline.defaultPosition(pos -> pos.add(0, 1, 0));
// Rotate head bones to look at player
pipeline.addRotationModifier(
BonePredicate.name("head"),
rotation -> rotation.rotateY((float) Math.toRadians(45))
);
// Offset arm positions
pipeline.addPositionModifier(
BonePredicate.name("arm_right"),
pos -> pos.add(0.5f, 0, 0)
);
Player Visibility
isSpawned
public boolean isSpawned(@NotNull UUID uuid)
Checks if the model is spawned for a specific player.
playerCount
Returns the number of players currently viewing the model.
allPlayer
public @NotNull Stream<PlatformPlayer> allPlayer()
Returns a stream of all players viewing the model.
viewedPlayer
public @NotNull Stream<PlatformPlayer> viewedPlayer()
Returns a stream of players who pass the view filter.
nonHidePlayer
public @NotNull Stream<PlatformPlayer> nonHidePlayer()
Returns a stream of players who are not hidden and pass the view filter.
Example:
// Check if spawned for specific player
if (pipeline.isSpawned(player.uuid())) {
System.out.println("Model visible to player");
}
// Count viewers
int viewerCount = pipeline.playerCount();
// Send message to all viewers
pipeline.allPlayer().forEach(p -> {
p.sendMessage("Model updated!");
});
Hide/Show
hide
public boolean hide(@NotNull PlatformPlayer player)
Hides the model from a specific player.
Returns: true if the player was successfully hidden
show
public boolean show(@NotNull PlatformPlayer player)
Shows the model to a specific player (if previously hidden).
Returns: true if the player was successfully shown
isHide
public boolean isHide(@NotNull PlatformPlayer player)
Checks if the model is hidden from a specific player.
Example:
// Hide from specific player
pipeline.hide(player);
// Check visibility
if (pipeline.isHide(player)) {
// Show again
pipeline.show(player);
}
Filters & Handlers
viewFilter
public void viewFilter(@NotNull Predicate<PlatformPlayer> filter)
Adds a filter to restrict which players can view the model.
hideFilter
public void hideFilter(@NotNull Predicate<PlatformPlayer> filter)
Adds a filter to determine if a player should be hidden from the model.
Packet Handlers
public void spawnPacketHandler(@NotNull Consumer<PacketBundler> handler)
public void despawnPacketHandler(@NotNull Consumer<PacketBundler> handler)
public void hidePacketHandler(@NotNull Consumer<PacketBundler> handler)
public void showPacketHandler(@NotNull Consumer<PacketBundler> handler)
Adds handlers for various packet events.
Example:
// Only show to players in adventure mode
pipeline.viewFilter(player ->
player.gameMode() == GameMode.ADVENTURE
);
// Hide from vanished players
pipeline.hideFilter(player -> player.isVanished());
// Add spawn packet handler
pipeline.spawnPacketHandler(bundler -> {
System.out.println("Model spawned!");
});
Packet Bundling
createBundler
public @NotNull PacketBundler createBundler()
Creates a packet bundler for this pipeline.
createParallelBundler
public @NotNull PacketBundler createParallelBundler()
Creates a parallel packet bundler based on configuration.
channel
public @Nullable PlayerChannelHandler channel(@NotNull UUID uuid)
Retrieves the channel handler for a specific player.
Example:
// Create bundler for updates
PacketBundler bundler = pipeline.createBundler();
pipeline.tick(bundler);
// Send to all players
pipeline.allPlayer().forEach(bundler::send);
// Use parallel bundler for better performance
PacketBundler parallel = pipeline.createParallelBundler();
Tree Operations
matchTree
public boolean matchTree(@NotNull Predicate<RenderedBone> predicate)
public boolean matchTree(
@NotNull BonePredicate predicate,
BiPredicate<RenderedBone, BonePredicate> mapper
)
Applies operations to bones matching a predicate.
matchAnimation
public boolean matchAnimation(
@NotNull BiPredicate<RenderedBone, AnimationOverrideState> mapper
)
Applies a mapper to bones matching an animation predicate.
firstNotNull
public <T> @Nullable T firstNotNull(@NotNull Function<RenderedBone, T> mapper)
Finds the first non-null result of applying a mapper to all bones.
Example:
// Find first bone with hitbox
HitBox hitbox = pipeline.firstNotNull(RenderedBone::getHitBox);
// Apply operation to all leg bones
pipeline.matchTree(
BonePredicate.name("leg"),
(bone, pred) -> {
bone.scale(1.2f);
return true;
}
);
Lifecycle
despawn
Despawns the model for all players and clears internal state.
Example:
// Clean up when done
pipeline.despawn();
Event Handling
eventDispatcher
public @NotNull BoneEventDispatcher eventDispatcher()
Returns the bone event dispatcher for this pipeline.
Iteration
The RenderPipeline implements Iterable<RenderedBone>, allowing direct iteration:
for (RenderedBone bone : pipeline) {
System.out.println("Bone: " + bone.name());
}
// Or with forEach
pipeline.forEach(bone -> {
bone.setVisible(true);
});
Complete Example
// Get pipeline from tracker
EntityTracker tracker = renderer.create(entity);
RenderPipeline pipeline = tracker.pipeline();
// Configure visibility
pipeline.viewFilter(p -> p.world().equals(entity.world()));
pipeline.hideFilter(p -> p.isInvisible());
// Add packet handlers
pipeline.spawnPacketHandler(b -> {
System.out.println("Model spawned for players");
});
// Modify bones
pipeline.scale(() -> 1.5f);
pipeline.addRotationModifier(
BonePredicate.name("head"),
rot -> rot.rotateY((float) Math.toRadians(headYaw))
);
// Update loop
BukkitRunnable task = new BukkitRunnable() {
@Override
public void run() {
PacketBundler bundler = pipeline.createBundler();
if (pipeline.tick(bundler)) {
pipeline.nonHidePlayer().forEach(bundler::send);
}
// Check if animation finished
RunningAnimation anim = pipeline.runningAnimation();
if (anim == null) {
// Start idle animation
tracker.play("idle");
}
}
};
task.runTaskTimer(plugin, 0L, 1L);
// Cleanup when done
task.cancel();
pipeline.despawn();
See Also