Skip to content

Prevent client-side noteblock stack flicker - #9

Open
pxlarified wants to merge 2 commits into
1.220.0from
3ece8cd6-0a62-4f43-b7e6-06db0431fefd
Open

Prevent client-side noteblock stack flicker#9
pxlarified wants to merge 2 commits into
1.220.0from
3ece8cd6-0a62-4f43-b7e6-06db0431fefd

Conversation

@pxlarified

@pxlarified pxlarified commented Sep 4, 2026

Copy link
Copy Markdown
Member

Summary

Prevents custom note-block models from briefly rendering as vanilla note blocks when a vertically adjacent block is broken or placed.

The change covers both affected paths:

  • breaking an Oraxen FULL block between other custom note blocks;
  • breaking or placing vanilla blocks, including normal note blocks, immediately above or below a custom note block.

Root cause

The authoritative server block states remain correct. The flash is produced by client-side block-state processing and packet timing:

  1. The client predicts a block break or placement before the server finishes handling it.
  2. A vertical neighbor change runs the vanilla note-block shape update locally.
  3. That update recomputes the note-block instrument from its surroundings.
  4. The temporary instrument state can select the vanilla harp resource-pack fallback instead of the custom model.
  5. The model becomes correct again when the block-change sequence is acknowledged and the unchanged server state is applied.

A valid server update for a vanilla block can cause the same local neighbor recomputation even without a server-side note-block state change. Physics cancellation alone therefore cannot reliably solve the rendering problem.

Changes

Custom block breaking

  • Detect custom note blocks immediately above or below the mined Oraxen FULL block.
  • Route vulnerable stack breaks through BreakerSystem, including versions that normally use the BLOCK_BREAK_SPEED attribute path.
  • Temporarily prevent client-side break completion using invisible, client-only mining effects.
  • Preserve the configured tool and hardness timing by advancing the equivalent vanilla progress server-side.
  • Restore the real client potion-effect view on completion, abort, cancellation, replacement, or game-mode changes.

Adjacent vanilla block breaking

  • Handle vanilla blocks and normal note blocks adjacent to custom note blocks after other block-damage handlers have run.
  • Leave custom blocks and registered custom-hardness modifiers on their existing breaking paths.
  • Keep the break server-authoritative while displaying normal crack progress.
  • Complete the operation through Player#breakBlock so vanilla drops, tool damage, block events, and protection listeners remain intact.
  • Replay the unchanged custom note-block states immediately after the target removal update so observers receive the target and correction packets in the required order.

Adjacent vanilla block placement

  • Route affected placements through the existing server-side block-state correction path.
  • Preserve directional state, waterlogging, multi-block placement behavior, placement events, item consumption, and cancellation handling.
  • Replay the authoritative placed-block state and the unchanged custom neighbor states before settling client prediction.

Packet handling

  • Record the sequence, position, and operation type of incoming block placement and start-destroy packets.
  • Match acknowledgements to the exact Bukkit operation rather than acknowledging an unrelated or newer prediction.
  • Send the acknowledgement only after authoritative target and neighbor states have been queued.
  • Remove tracked entries when the normal server acknowledgement is sent, when the connection closes, and when the bounded per-connection queue is trimmed.

Folia and compatibility

  • Retain region-owned block operations.
  • Schedule viewer updates and client-effect restoration through entity schedulers where required.
  • Keep guarded server-version implementations in both Java 21 and Java 25 modules.
  • Leave the acknowledgement API as a safe no-op when a guarded implementation is unavailable.
  • Preserve the legacy breaking and placement-correction fallbacks for older supported versions.

Tests

NoteBlockClientPredictionTest covers:

  • a custom block inside a vertical custom note-block stack selecting server-authoritative breaking;
  • an isolated custom block retaining native attribute-driven breaking;
  • replaying the unchanged custom neighbor state after a vanilla block change;
  • client-only mining suppression without mutating server potion effects;
  • restoration of the real potion effects after breaking.

Validation performed:

./gradlew clean test
./gradlew test

Both runs completed successfully, including compilation and tests for the Java 21 and Java 25 server modules.

Behavioral impact

Server-side custom note-block data and physics behavior are unchanged. The fix changes only how vulnerable client predictions are completed and when unchanged authoritative neighbor states are replayed. Unrelated vanilla blocks, isolated custom blocks, and custom blocks owned by other hardness mechanics keep their existing paths.

Keep vulnerable vertical custom noteblock breaks server-authoritative while preserving configured mining timing. Suppress client prediction with temporary client-only effects and restore the player's real effects after completion or abort. Add regression coverage for stacked FULL blocks and effect restoration.
Keep vanilla block breaking next to custom note blocks server-authoritative and replay the unchanged custom states after the target update. Track and acknowledge matching placement and break prediction sequences while preserving vanilla placement state and item consumption.
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.

1 participant