Skip to content

fix: animation, GeckoLib and display tools - #73

Merged
jasonjgardner merged 12 commits into
jasonjgardner:mainfrom
heide-oficial:fix/animation-and-geckolib
Oct 1, 2026
Merged

jasonjgardner merged 12 commits into
jasonjgardner:mainfrom
heide-oficial:fix/animation-and-geckolib

Conversation

@heide-oficial

@heide-oficial heide-oficial commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Fixes for animation, GeckoLib and display tools, found while auditing 1.9.3 with Blockbench 5.2.1, the GeckoLib plugin 4.2.5 and GeckoLib 5.5.7. One commit per issue:

  • Export writes: export_model and the GeckoLib model, animation and display exports overwrote any file without asking, and relative paths resolved against Blockbench's working directory. They now share one writer: the path must be absolute and local, and an existing file is only replaced with overwrite: true (default false). The tools are marked destructive. Network (UNC) and device paths are refused, because writing to them makes Windows connect to the named host with the user's credentials.
  • GeckoLib validator: it failed models for a missing modid or identifier, which GeckoLib 5.5.7 does not need (the game uses geometry.unknown).
    • Those, and bone names that differ only in case, are now warnings; exact duplicate bone names stay errors.
    • Lowercase easing names, none and catmullrom are accepted, and easing arguments may be numbers or Molang strings.
  • Keyframe timing, interpolation and easing:
    • Keys created by the tools were rounded to the 1/24 s grid on export (0.05 became 0.0417). The animation snapping is now fitted to the keyframe times inside the same undo edit, so Redo restores it.
    • Editing only a keyframe's values reset its interpolation to linear; it is now kept unless one is passed.
    • Copy and paste keeps GeckoLib easing and easing arguments.
  • animation_graph_editor:
    • It ignored the axis, wrote scalar handles into Blockbench's per-axis arrays, skipped the validations it described and could leave an unsafe Undo entry.
    • It now validates first, converts curves into native per-axis handles from each segment's duration and value change, and runs in one reversible edit.
    • In GeckoLib models it refuses step curves, because the GeckoLib plugin's render_frame handler switches step keys back to linear on every frame. It also refuses Bezier curves, which GeckoLib 5.5 loads as linear.
    • Smoothing clears GeckoLib easings in the same edit; the plugin otherwise dropped them silently on the next frame.
  • Batch reverse, smooth and bake:
    • Reverse (and a negative scale) only moved times, so GeckoLib easings stayed on the wrong keys. It now follows the native Reverse Keyframes action, including the GeckoLib plugin's easing shift and the pre/post and Bezier handle swaps.
    • Smooth and bake clear the easings they replace, and report it.
  • geckolib_reverse_keyframe_easing: with the GeckoLib plugin loaded, the native reverse already shifts easings, so running this tool afterwards shifted them twice. This is documentation only: a previous shift cannot be detected, so the description now says when to use the tool.
  • Export format: geometry and animations were always written as two-space JSON.stringify, so re-exported files never matched native ones. They now go through Blockbench's autoStringify, with the user's indentation and minify settings and numbers rounded to five decimals. The display export keeps the two-space JSON the GeckoLib plugin itself writes.
  • Display parent: the display export writes the plugin's builtin/entity parent, which Minecraft Java 1.21.4 and later no longer have; the game reports a missing model. The default stays, so files keep matching the plugin's own export and older versions keep working. The result now warns about it, and a new parent option writes another parent or none.
  • set_display_transform: it accepted values the game silently changes. Translation is clamped to ±80 and scale to ±4 (checked as exported, with the mirror sign), pivots are not read, and there is no embedded slot. Values stay as given, like Blockbench keeps them, but Java projects get warnings.
  • bone_rigging:
    • An unknown parent moved the bone to the root while reporting success. Parents now resolve by UUID or unique name, in create too; cycles and ambiguity are errors.
    • Mirror only negated the copy's pivot. It now duplicates the bone and flips the copy like Blockbench's Flip action.
    • One shared Undo snapshot lost deleted cubes, copies, names and pivots, and deleting a bone lost its keyframes in every animation. Each action now records what it changes, including those animations, in one reversible edit.
  • create_animation name: the animation. prefix was added silently, and twice to a name that already had it. The parameter now documents the prefix, and a name that already starts with it is kept.

Behaviour changes to be aware of:

  • animation_graph_editor refuses input it used to accept silently.
    • Single-axis linear, stepped and smooth requests are refused.
    • Ranges and keys are validated.
    • GeckoLib projects refuse stepped and Bezier curves.
    • Its ease presets now produce the CSS cubic-bezier curves, and it may unlink Bezier handles.
  • Batch reverse and negative scale also swap pre/post values and Bezier handles.
  • Mirrored bones get Blockbench's names (left↔right, or a unique copy name) instead of a _mirrored suffix.
  • GeckoLib geometry and animation exports follow the user's JSON settings (tabs by default).
  • The export tools need absolute local paths, and overwrite: true to replace a file.
  • geckolib_export_display has a new parent option; it and set_display_transform return warnings.

Not included:

  • manage_keyframes still accepts step and Bezier interpolation in GeckoLib projects.
  • Time scaling does not scale Bezier handle times.
  • set_display_transform still calls Undo.initEdit/finishEdit directly.

Testing:

  • bun test: 1,232 pass, 0 fail (main: 1,184). bunx tsc --noEmit shows the same errors as main (none new). bun run build and bun run docs:build pass.
  • Live, with all the related PRs loaded together in Blockbench 5.2.1 and the GeckoLib plugin 4.2.5 on Windows 11.
    • These failed in the audit of 1.9.3 and pass now:
      • Overwrite refusal.
      • 0.05 s keys kept on export.
      • Interpolation kept on edit.
      • Easing kept on copy/paste.
      • Stepped on one axis refused.
      • Unknown parent refused.
      • Display parent warning.
      • Validator warnings instead of errors.
      • The animation. prefix documented.
    • Added later and passing:
      • No double prefix.
      • Bone delete + Undo restores the bone's keyframes, and Redo removes them again.
  • Upstream's test:animation:live passes all 46 checks against the same build. It caught a regression in an earlier version of this branch (the snapping fit ran outside the undo edit), which is fixed here.

Related PRs from the same audit: #70 (HTTP server, settings and file inputs), #71 (views and captures), #72 (modeling tools), #74 (paint and textures), #75 (headless server), #69 (loopback bind). All of them merge together without conflicts (checked).

🤖 Generated with Claude Code

heide-oficial and others added 12 commits September 30, 2026 22:11
export_model and the GeckoLib model, animation and display exports share one writer: the path must be absolute and an existing file is only replaced with overwrite: true (default false). The tools are marked destructive.

Network (UNC) and device paths are refused too: writing to them makes Windows connect to the named host with the user's credentials.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Missing modid or identifier and bone names that differ only in case are warnings; exact duplicate bone names stay errors. Lowercase easing names, none and catmullrom are accepted, and easing arguments may be numbers or Molang strings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Fit the animation snapping to the keyframe times after creating or editing keys, so exports keep 0.05 s instead of rounding to 1/24 s.
- Editing a keyframe keeps its interpolation unless one is passed; creation still defaults to linear.
- Copy and paste keeps GeckoLib easing and easing arguments.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The tool ignored the axis, wrote scalar handles into Blockbench's per-axis handle arrays, skipped every check its description promised and could leave a half-applied Undo entry. It now validates the range, keys, axis and format before Undo, converts normalized curves into native per-axis handles from each segment's duration and value change (the ease presets are the CSS cubic-bezier curves), and applies everything in one reversible animation edit.

Behaviour change: requests the old code accepted are now errors: key-wide modes on one axis, one-axis curves on keys that are not Bezier yet, fewer than two keys, Molang or pre/post keys, smooth or Bezier curves on quaternion rotation, and stepped or Bezier curves in GeckoLib models. In GeckoLib the plugin's render_frame handler (renderFrameCallback, plugin 4.2.5) switches every step key shown in the timeline back to linear on each frame, so the step shape is lost; and GeckoLib 5.5 reads no Bezier handles and loads the exported "bezier" easing as linear, so a curve only reaches the game as baked linear samples. Handles that no longer mirror each other are unlinked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…smooth or bake keys

Reverse (and a negative scale factor) only moved times, so GeckoLib easings stayed on the wrong keys, and smooth and bake left easings that GeckoLib then dropped or applied twice. Reverse now follows the native Reverse Keyframes action including the GeckoLib plugin's easing shift; smooth and bake clear the easings they replace inside the same undoable edit and report it. The easing helpers live in animation/shared.ts for the other animation tools.

Behaviour change: reverse and negative scale factors now also swap pre/post values and Bezier handles, as the native action does, and batch results end with a period and may carry notes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…asing-aware reversal

With the GeckoLib plugin loaded, Blockbench's Reverse Keyframes action already reverses and shifts easings, and batch_keyframe_operations reverse now does too, so running this tool afterwards shifted them twice. Whether easings were already adjusted cannot be detected, so the description now says exactly when to use the tool and that a second call is not an inverse, which a test pins down.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… own exports

The export tools always wrote two-space JSON.stringify output, while Blockbench exports geometry and animations through autoStringify, so re-exported files never matched native ones. Geometry and animations now use autoStringify when Blockbench provides it; the display export keeps the two-space JSON the GeckoLib plugin itself writes.

Behaviour change: geometry and animation export text now follows the user's JSON settings (indentation, tabs by default, minify and final newline) and autoStringify's five-decimal rounding.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ltin/entity

The display export always wrote the plugin's builtin/entity parent, which Minecraft Java 1.21.4 removed: on 1.21.4 and later the game reports a missing model and the file inherits nothing from it, while GeckoLib item models on 1.21.3 and older still need that parent. The default stays builtin/entity so files keep matching the plugin's own export, but the result now warns about it and a new parent option writes another parent, or none.

Behaviour change: geckolib_export_display gains the parent option (compile mode only; passing it in dialog mode is an error) and a warnings field.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
set_display_transform accepted values the game silently changes: Minecraft Java's item model loader clamps translation to ±80 (5 blocks) and scale to ±4, reads no rotation or scale pivots, and has no embedded display context. Values stay as given, like Blockbench keeps them, but the result now lists warnings for Java projects and the parameters document the limits. Scale is checked as Blockbench exports it, with mirrored axes negative, so [-6, 1, 2] is reported as clamped to [-4, 1, 2].

Behaviour change: the set_display_transform result gains a warnings array (empty for bedrock_block projects).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…do completely

An unknown parent silently moved the bone to the root while reporting success, mirror only negated the copy's pivot, and one shared Undo snapshot without the touched groups, elements and animations lost deleted cubes, copies, names, pivots and keyframes. Parents now resolve by UUID or unique name (cycles and names several bones share are errors, also for create), mirror duplicates the bone and flips the copy like Blockbench's Flip action, and each action records what it changes in one reversible edit. Deleting a bone also snapshots every animation that animates the deleted subtree, since Group.remove deletes those animators; runUndoableAnimationEdit gains finish aspects so Redo removes them again.

Behaviour change: unknown or ambiguous parents are errors; a mirrored copy gets Blockbench's names (left/right swapped when free, otherwise a unique duplicate name such as left_arm2) instead of a _mirrored suffix; delete reports how many child bones and elements it removed. The docs now say that create with ik_enabled records two history entries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Smoothing in the graph editor left GeckoLib easings on catmullrom keys, which the GeckoLib plugin's render_frame handler then dropped on the next frame, outside the edit. Like batch_keyframe_operations smooth, it now clears them in the same undoable edit and reports it in the result.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
create_animation always prepended animation. without saying so, which turned animation.walk into animation.animation.walk. The prefix is now added only when the name lacks it, as Bedrock and GeckoLib animation files expect, and the name parameter documents it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 59 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 2 included reviews currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Repository: jasonjgardner/blockbench-mcp-plugin/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 5624a909-5ae8-454d-8c39-bc72e2cae15f

📥 Commits

Reviewing files that changed from the base of the PR and between 6295e20 and ae49562.

📒 Files selected for processing (31)
  • lib/animation-undo.test.ts
  • lib/animation-undo.ts
  • lib/export-file.test.ts
  • lib/export-file.ts
  • lib/geckolib-display.ts
  • lib/geckolib-easing.ts
  • lib/geckolib-validate.test.ts
  • lib/geckolib-validate.ts
  • lib/geckolib.test.ts
  • lib/geckolib.ts
  • lib/zodObjects.ts
  • server/tools/animation/batch.ts
  • server/tools/animation/copy-paste.ts
  • server/tools/animation/create.ts
  • server/tools/animation/curves.ts
  • server/tools/animation/docs.ts
  • server/tools/animation/keyframes.ts
  • server/tools/animation/rigging.ts
  • server/tools/animation/schemas.ts
  • server/tools/animation/shared.ts
  • server/tools/display.test.ts
  • server/tools/display.ts
  • server/tools/export.ts
  • server/tools/geckolib.test.ts
  • server/tools/geckolib.ts
  • server/tools/geckolib/docs.ts
  • server/tools/geckolib/schemas.ts
  • tests/animation-batch.test.ts
  • tests/animation-graph-editor.test.ts
  • tests/animation-tools.test.ts
  • tests/bone-rigging.test.ts
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@jasonjgardner
jasonjgardner merged commit b0c1efc into jasonjgardner:main Oct 1, 2026
1 check passed
jasonjgardner added a commit that referenced this pull request Oct 1, 2026
lib/export-file.ts (#73) repeated the absolute-path check of
lib/local-files.ts (#70) without its reserved device names, so COM1.json
or nul.json could block Blockbench or report a write that never happened.
Export paths now share isAbsoluteLocalPath, and messages strip control
characters with displayPath.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jasonjgardner jasonjgardner mentioned this pull request Oct 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants