Skip to content

Conversation

codingcat2468
Copy link
Contributor

@codingcat2468 codingcat2468 commented Jun 10, 2025

We've been using Typewriter on our (in-development) server for a while now and really love the plugin, but while using it, we've come across some minor issues or missing features that we needed. Most of those have been implemented in this PR, and we've been using them on the server for a few days now.

Here's a detailed list of the changes made:

  • The PlayerRespawnEventEntry does not trigger at all if the player doesn't have a respawn point (such as a bed / respawn anchor), so I added a NONE respawn location type that covers this case
  • The Invisible NBT tag can't be applied to "fake" armor stand entities (which would hide the wood frame of the armor stand, but not the worn armor), this can now be achieved using InvisibleData
  • We wanted to show the worldborder increasing in size in one of the cinematics on our server, which is why I added a new WorldborderCinematicEntry. A segment of that cinematic will resize the worldborder client-side for a given amount of time, and return it to the previous size when the segment ends.
  • We've been using "in cinematic" facts to hide certain NPCs when the player is in a cinematic, but there has been scenarios where the NPC needs to be visible until some point in the cinematic and only then disappear. I've added beforeFrame and afterFrame parameters to the fact, which can be used to narrow down the frame range in a cinematic.

Summary by CodeRabbit

  • New Features

    • Introduced cinematic world border animations, allowing smooth resizing effects during cinematic sequences.
    • Added support for managing and applying invisibility to armor stand entities.
    • Added a utility to access the current temporal frame for players.
    • Enhanced respawn event handling with a new "NONE" respawn location type.
    • Added a new cinematic fact entry to detect player presence within specific cinematic frame sections.
  • Improvements

    • Extended cinematic fact entries to support optional frame range filtering for more precise conditions.

Copy link
Contributor

coderabbitai bot commented Jun 10, 2025

Walkthrough

The TemporalInteraction class now exposes its frame property publicly with an added Player.currentTemporalFrame() extension. A new cinematic entry animates the Minecraft world border during cinematics. The RespawnLocationType enum includes a NONE value with updated event handling. Armor stand invisibility is managed via new entity data and property classes, integrated into property application. A new fact entry reports player presence in cinematic frame sections. A comment typo was fixed.

Changes

File(s) / Group Change Summary
engine/engine-paper/.../TemporalInteraction.kt Made frame property public; added Player.currentTemporalFrame() extension function.
extensions/BasicExtension/.../WorldborderCinematicEntry.kt Added WorldborderCinematicEntry, WorldborderSegment, and WorldborderCinematicAction for world border animations.
extensions/BasicExtension/.../PlayerRespawnEventEntry.kt Added NONE to RespawnLocationType enum; updated event logic to handle new type.
extensions/BasicExtension/.../InCinematicFactEntry.kt Corrected comment typo; no functional changes.
extensions/EntityExtension/.../InvisibleData.kt Added InvisibleData, InvisibleProperty, and applyInvisibleData() for armor stand invisibility.
extensions/EntityExtension/.../ArmorStandEntity.kt Updated applyProperty to handle InvisibleProperty using applyInvisibleData().
extensions/BasicExtension/.../CinematicSectionFactEntry.kt Added CinematicSectionFactEntry to report player presence in cinematic frame sections with optional cinematic filter.

Sequence Diagram(s)

sequenceDiagram
    participant Player
    participant CinematicSystem
    participant WorldBorder
    participant PacketSender

    Player->>CinematicSystem: Start cinematic with WorldborderCinematicEntry
    CinematicSystem->>WorldBorder: Determine segment (start/end frames, sizes)
    CinematicSystem->>PacketSender: Send world border size/lerp packets
    PacketSender->>Player: Animate border transition
    CinematicSystem->>PacketSender: On segment end, reset or fade back border
    PacketSender->>Player: Final border state update
Loading
sequenceDiagram
    participant Player
    participant FactEntry
    participant CinematicSystem

    Player->>FactEntry: Query CinematicSectionFactEntry
    FactEntry->>CinematicSystem: Get current cinematic and frame
    CinematicSystem-->>FactEntry: Return frame info
    FactEntry->>Player: Return value for matching frame range or default
Loading
sequenceDiagram
    participant WrapperEntity
    participant ArmorStandEntity
    participant InvisibleData

    WrapperEntity->>ArmorStandEntity: applyProperty(property)
    ArmorStandEntity->>InvisibleData: applyInvisibleData(entity, property)
    InvisibleData->>WrapperEntity: Set invisibility meta
Loading

Poem

Borders shift and frames align,
Cinematics dance in smooth design.
Armor stands now hide away,
Facts reveal where players stay.
Enums grow and code expands,
A rabbit hops with joyful hands!
🐇🎬✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2b5f7ec and 4c1b3d2.

📒 Files selected for processing (1)
  • extensions/BasicExtension/src/main/kotlin/com/typewritermc/basic/entries/fact/CinematicSectionFactEntry.kt (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • extensions/BasicExtension/src/main/kotlin/com/typewritermc/basic/entries/fact/CinematicSectionFactEntry.kt
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate Unit Tests
  • Create PR with Unit Tests
  • Commit Unit Tests in branch develop
  • Post Copyable Unit Tests in Comment

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai auto-generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
extensions/BasicExtension/src/main/kotlin/com/typewritermc/basic/entries/cinematic/WorldborderCinematicEntry.kt (1)

75-77: Consider improving type safety for polymorphic packet handling.

The current code assigns different packet types to the same variable, which could lead to type confusion. Consider making the packet creation and sending more explicit.

-        val packet = if (!segment.fadeBack) WrapperPlayServerWorldBorderSize(borderSize())
-        else WrapperPlayWorldBorderLerpSize(segment.newSize, borderSize(), segment.transitionTime.toMillis())
-        player.sendPacket(packet)
+        if (!segment.fadeBack) {
+            val packet = WrapperPlayServerWorldBorderSize(borderSize())
+            player.sendPacket(packet)
+        } else {
+            val packet = WrapperPlayWorldBorderLerpSize(segment.newSize, borderSize(), segment.transitionTime.toMillis())
+            player.sendPacket(packet)
+        }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d78f0d8 and 7b6ade6.

📒 Files selected for processing (6)
  • engine/engine-paper/src/main/kotlin/com/typewritermc/engine/paper/entry/temporal/TemporalInteraction.kt (2 hunks)
  • extensions/BasicExtension/src/main/kotlin/com/typewritermc/basic/entries/cinematic/WorldborderCinematicEntry.kt (1 hunks)
  • extensions/BasicExtension/src/main/kotlin/com/typewritermc/basic/entries/event/PlayerRespawnEventEntry.kt (2 hunks)
  • extensions/BasicExtension/src/main/kotlin/com/typewritermc/basic/entries/fact/InCinematicFactEntry.kt (2 hunks)
  • extensions/EntityExtension/src/main/kotlin/com/typewritermc/entity/entries/data/minecraft/living/armorstand/InvisibleData.kt (1 hunks)
  • extensions/EntityExtension/src/main/kotlin/com/typewritermc/entity/entries/entity/minecraft/ArmorStandEntity.kt (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
extensions/EntityExtension/src/main/kotlin/com/typewritermc/entity/entries/entity/minecraft/ArmorStandEntity.kt (1)
extensions/EntityExtension/src/main/kotlin/com/typewritermc/entity/entries/data/minecraft/living/armorstand/InvisibleData.kt (1)
  • applyInvisibleData (33-38)
extensions/EntityExtension/src/main/kotlin/com/typewritermc/entity/entries/data/minecraft/living/armorstand/InvisibleData.kt (1)
engine/engine-paper/src/main/kotlin/com/typewritermc/engine/paper/command/dsl/TypewriterDsl.kt (1)
  • error (21-23)
🔇 Additional comments (12)
extensions/EntityExtension/src/main/kotlin/com/typewritermc/entity/entries/data/minecraft/living/armorstand/InvisibleData.kt (3)

1-15: LGTM!

The package declaration and imports are well-organized and appropriate for the armor stand invisibility functionality.


16-27: Well-structured entity data implementation.

The InvisibleData class follows the established patterns for entity data entries with proper annotations, type safety, and builder pattern implementation.


29-31: Clean property implementation.

The InvisibleProperty data class and companion object follow the established patterns for entity properties with appropriate default values.

extensions/EntityExtension/src/main/kotlin/com/typewritermc/entity/entries/entity/minecraft/ArmorStandEntity.kt (1)

63-63: Proper integration pattern for the new property type.

The addition of InvisibleProperty handling follows the established pattern used by other armor stand properties. However, note that the applyInvisibleData function currently has an error handling issue that needs to be fixed.

extensions/BasicExtension/src/main/kotlin/com/typewritermc/basic/entries/event/PlayerRespawnEventEntry.kt (2)

42-42: LGTM: Clean enum extension for handling respawn without designated location.

The addition of NONE enum value appropriately addresses the use case where players don't have a bed or respawn anchor.


64-64: LGTM: Correct logic for NONE respawn location type.

The condition !event.isBedSpawn && !event.isAnchorSpawn properly identifies respawn events that don't involve a bed or anchor, which aligns with the NONE semantics.

engine/engine-paper/src/main/kotlin/com/typewritermc/engine/paper/entry/temporal/TemporalInteraction.kt (2)

38-38: LGTM: Appropriate visibility change to support frame querying.

Making the frame property public enables external components to access the current frame, which is required for the frame range filtering functionality in InCinematicFactEntry.


141-141: LGTM: Clean extension function for frame access.

The currentTemporalFrame() extension provides a convenient and null-safe way to access the current frame of a player's active temporal interaction.

extensions/BasicExtension/src/main/kotlin/com/typewritermc/basic/entries/fact/InCinematicFactEntry.kt (1)

41-42: LGTM: Well-documented optional frame range parameters.

The addition of beforeFrame and afterFrame parameters with clear documentation enhances the cinematic fact filtering capabilities.

extensions/BasicExtension/src/main/kotlin/com/typewritermc/basic/entries/cinematic/WorldborderCinematicEntry.kt (3)

19-28: Excellent documentation and clear use case explanation.

The entry documentation clearly explains the client-side nature of the animation and provides a practical use case example.


44-51: Well-designed segment structure with appropriate defaults.

The WorldborderSegment data class provides a comprehensive set of parameters with sensible defaults for world border animation control.


60-66: LGTM: Correct implementation of border size lerping.

The startSegment method properly handles the transition from old size (or current border size if not specified) to the new size using the lerp packet.

@gabber235
Copy link
Owner

Thanks for this PR, it's great to see other people help out with Typewriter!

Next time I would prefer you make 4 separate PRs for each feature because now we have multiple conversations next to each other.
For now it's fine.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
extensions/BasicExtension/src/main/kotlin/com/typewritermc/basic/entries/fact/CinematicSectionFactEntry.kt (1)

52-58: Shadowing the default property hurts readability.

Inside readSinglePlayer a local val default = … hides the constructor property of the same name; readers have to check scopes twice.
Pick a distinct name (e.g. fallbackValue) or reuse the property directly.

-        val default = default.orElse(0)
+        val fallback = default.orElse(0)-        if (!inCinematic) return FactData(default)
+        if (!inCinematic) return FactData(fallback)-        return FactData(output ?: default)
+        return FactData(output ?: fallback)
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7b6ade6 and 2b5f7ec.

📒 Files selected for processing (3)
  • extensions/BasicExtension/src/main/kotlin/com/typewritermc/basic/entries/fact/CinematicSectionFactEntry.kt (1 hunks)
  • extensions/BasicExtension/src/main/kotlin/com/typewritermc/basic/entries/fact/InCinematicFactEntry.kt (1 hunks)
  • extensions/EntityExtension/src/main/kotlin/com/typewritermc/entity/entries/data/minecraft/living/armorstand/InvisibleData.kt (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • extensions/BasicExtension/src/main/kotlin/com/typewritermc/basic/entries/fact/InCinematicFactEntry.kt
🚧 Files skipped from review as they are similar to previous changes (1)
  • extensions/EntityExtension/src/main/kotlin/com/typewritermc/entity/entries/data/minecraft/living/armorstand/InvisibleData.kt
🧰 Additional context used
🧬 Code Graph Analysis (1)
extensions/BasicExtension/src/main/kotlin/com/typewritermc/basic/entries/fact/CinematicSectionFactEntry.kt (1)
engine/engine-core/src/main/kotlin/com/typewritermc/core/entries/EntryReference.kt (1)
  • emptyRef (6-6)

@codingcat2468 codingcat2468 requested a review from gabber235 June 11, 2025 16:38
Copy link
Owner

@gabber235 gabber235 left a comment

Choose a reason for hiding this comment

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

Thanks for these changes! I think these are all great contributions to Typewriter

@gabber235 gabber235 merged commit 7a61d6a into gabber235:develop Jun 12, 2025
2 checks passed
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