Skip to content

feat: parité Paper/PacketEvents et prise en charge de BlockData - #15

Open
el211 wants to merge 13 commits into
RedSavant:devfrom
el211:Dev3
Open

feat: parité Paper/PacketEvents et prise en charge de BlockData#15
el211 wants to merge 13 commits into
RedSavant:devfrom
el211:Dev3

Conversation

@el211

@el211 el211 commented Sep 11, 2026

Copy link
Copy Markdown

Résumé

Cette PR construit sur l'abstraction de backend introduite précédemment (PR #12) et vise deux objectifs :

  • Parité Paper / PacketEvents : un même réglage du builder produit un résultat aussi proche que possible sur les deux backends.
  • Prise en charge de BlockData : remplacement de la gestion limitée à Material par de vraies données de bloc Bukkit, en restant rétrocompatible.

L'architecture existante (DisplayHandle, PaperDisplayHandle, PacketDisplayHandle, Anchor, sélection de backend) n'est pas redessinée.

Parité Paper / PacketEvents

Le builder construit désormais un seul BlockDisplayState (données de bloc, transformation, billboard, luminosité, portée de vue, rayon et intensité d'ombre) transmis aux deux backends :

  • Paper l'applique à l'entité via PaperDisplayHandle.applyTo(entity, state).
  • PacketEvents le conserve et l'encode dans les métadonnées.

Le codec envoyait auparavant uniquement la transformation et l'état de bloc. Il émet maintenant aussi :

Propriété Index métadonnée
Billboard 15 (byte)
Luminosité 16 (int compacté)
Portée de vue 17 (float)
Rayon d'ombre 18 (float)
Intensité d'ombre 19 (float)

Les propriétés non configurées ne sont pas envoyées, ce qui préserve le comportement vanilla par défaut. Tous les index de métadonnées restent centralisés dans le codec.

Prise en charge de BlockData

  • Ajout de .block(BlockData) en plus de .block(Material) (raccourci converti en createBlockData()).
  • L'état logique du bloc est stocké sous forme de BlockData (copie défensive via clone()).
  • DisplayHandle expose block(BlockData) et blockData().
  • DisplayCrate.block(...) permet de changer l'état de bloc à l'exécution : une mise à jour de métadonnées est envoyée aux observateurs, sans respawn.
  • L'identifiant d'état de bloc est dérivé du BlockData stocké via SpigotConversionUtil.

Exemple :

BlockData stairs = Bukkit.createBlockData("minecraft:oak_stairs[facing=east]");

DisplayCrate crate = BDApi.get().displays().create()
        .backend(DisplayBackend.PACKET_EVENTS)
        .at(location)
        .block(stairs)
        .spawn();

Isolation

Les imports PacketEvents restent isolés dans la couche packet. Les classes cœur (display, builder, internal, DisplayCrate) n'importent aucune classe PacketEvents. Le fonctionnement Paper seul reste possible sans PacketEvents.

Tests

  • Mapping des billboards (4 modes) et compactage de la luminosité (0/0, 15/15, valeurs distinctes).
  • Parité des propriétés entre backends : ce que Paper applique correspond à ce que PacketEvents conserve.
  • État BlockData : préservation de l'état, mise à jour à l'exécution sans respawn, nouvel observateur recevant l'état complet, non-observateur ignoré.
  • Adaptation des tests existants au nouveau constructeur basé sur l'état.

./gradlew test : succès. ./gradlew build : succès. L'artefact publié n'embarque ni PacketEvents, ni JUnit, ni Mockito.

Vérifications en jeu recommandées

Un serveur Paper 1.21 est nécessaire (avec PacketEvents pour les commandes paquets) :

/bdtest blockdata
/bdtest parity
/bdtest packet

blockdata affiche des escaliers de chêne orientés nord et est. parity place une version Paper et une version PacketEvents côte à côte avec une configuration identique.

Portée

Aucune fonctionnalité de PR ultérieure n'est incluse (pas de tracking de distance, persistance, autres types d'affichage, ni système de dirty-state).

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved critical API-compatibility and PacketEvents metadata issues remain, along with moderate state and test-coverage issues.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds shared BlockData display state, Paper/PacketEvents parity, runtime updates, tests, demo commands, and documentation.

Changes:

  • Adds BlockData builder and runtime APIs.
  • Encodes additional visual properties for PacketEvents.
  • Updates backend, parity, state, and integration tests.
File summaries
File Summary Review notes
test-plugin/src/main/resources/plugin.yml Updates demo command help.
test-plugin/src/main/java/fr/redsavant/Main.java Adds BlockData and parity demonstrations.
src/test/java/fr/redsavant/bdapi/support/DisplayStates.java Adds test state utilities.
src/test/java/fr/redsavant/bdapi/packet/PacketDisplayMetadataCodecTest.java Tests billboard and brightness mappings. Moderate (1 vote): Lacks encode-level coverage for new indices, types, omission, and BlockData conversion.
src/test/java/fr/redsavant/bdapi/display/PacketDisplayHandleTest.java Adapts packet backend tests.
src/test/java/fr/redsavant/bdapi/display/BlockDataStateTest.java Tests BlockData state and runtime updates.
src/test/java/fr/redsavant/bdapi/display/BackendParityTest.java Verifies backend property parity.
src/test/java/fr/redsavant/bdapi/BackendSelectionTest.java Adapts backend selection tests.
src/test/java/fr/redsavant/bdapi/AnimationBackendTest.java Adapts animation backend coverage.
src/main/java/fr/redsavant/bdapi/packet/PacketDisplayMetadataCodec.java Encodes display metadata. Critical (2 votes): Brightness requires OPTIONAL_INT, not INT, to avoid invalid PacketEvents metadata.
src/main/java/fr/redsavant/bdapi/DisplayCrate.java Exposes runtime block-state operations.
src/main/java/fr/redsavant/bdapi/display/PaperDisplayHandle.java Applies shared state to Paper entities.
src/main/java/fr/redsavant/bdapi/display/PacketDisplayHandle.java Tracks and updates packet display state. Critical (2 votes): Replaces the public legacy constructor without a compatibility overload or explicit breaking-change documentation. Moderate (1 vote): Exposes live mutable state that can leave viewers stale. Moderate (1 vote): Uses pattern matching instead of exact BlockData equality for update suppression.
src/main/java/fr/redsavant/bdapi/display/DisplayHandle.java Adds BlockData operations. Critical (3 votes): Removes the public block(Material) overload despite the claimed backward compatibility.
src/main/java/fr/redsavant/bdapi/display/BlockDisplayState.java Stores defensive block and display state.
src/main/java/fr/redsavant/bdapi/builder/BlockDisplayBuilder.java Builds shared display state.
README.md Documents BlockData and backend parity.
Review details

Suppressed comments (3)

src/main/java/fr/redsavant/bdapi/display/PacketDisplayHandle.java:36

  • This public accessor returns the live mutable BlockDisplayState, while metadata is sent only by PacketDisplayHandle.block() and transformation(). A caller can therefore mutate handle.state().blockData(...) or .transformation(...) directly, leaving current viewers stale while future encodes use the new state; expose an immutable snapshot or keep state mutation internal and route changes through the handle.
    public BlockDisplayState state() {
        return state;

src/main/java/fr/redsavant/bdapi/display/PacketDisplayHandle.java:93

  • BlockData.matches is pattern matching rather than exact state equality, so a target with omitted properties can match the current data even when the requested block state differs in those properties. This suppresses the metadata update and leaves viewers showing the old state; use exact equality (or a canonical full-state comparison) for the no-op check.
        if (removed || target.matches(state.blockData())) {

src/main/java/fr/redsavant/bdapi/packet/PacketDisplayMetadataCodec.java:66

  • The new protocol path is not covered end-to-end: PacketDisplayMetadataCodecTest exercises only billboardId and packBrightness, but never calls encode to verify the new metadata indices, types, optional-field omission, or BlockData conversion. A wrong entry in this list would pass the suite and make PacketEvents clients render defaults; add an encode-level test for a full and a default state.
        data.add(new EntityData<>(BILLBOARD, EntityDataTypes.BYTE, billboardId(state.billboard())));
        if (state.hasBrightness()) {
            data.add(new EntityData<>(BRIGHTNESS, EntityDataTypes.INT, packBrightness(state.brightness())));
        }
        if (state.hasViewRange()) {
            data.add(new EntityData<>(VIEW_RANGE, EntityDataTypes.FLOAT, state.viewRange()));
        }
        if (state.hasShadowRadius()) {
            data.add(new EntityData<>(SHADOW_RADIUS, EntityDataTypes.FLOAT, state.shadowRadius()));
        }
        if (state.hasShadowStrength()) {
            data.add(new EntityData<>(SHADOW_STRENGTH, EntityDataTypes.FLOAT, state.shadowStrength()));
        }
        data.add(new EntityData<>(BLOCK_STATE, EntityDataTypes.BLOCK_STATE, blockStateId(state)));
  • Files reviewed: 17/17 changed files
  • Comments generated: 3
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/main/java/fr/redsavant/bdapi/display/DisplayHandle.java
Comment thread src/main/java/fr/redsavant/bdapi/display/PacketDisplayHandle.java
@RedSavant RedSavant added the Improving Improve a feature label Sep 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Improving Improve a feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants