Skip to content

feat(boats): integrate controlled boat physics and rendering - #590

Merged
zardoy merged 16 commits into
zardoy:nextfrom
sandexzx:feat/boat-physics-1.17.1
Aug 1, 2026
Merged

zardoy merged 16 commits into
zardoy:nextfrom
sandexzx:feat/boat-physics-1.17.1

Conversation

@sandexzx

@sandexzx sandexzx commented Jul 12, 2026 •

Copy link
Copy Markdown
Collaborator

Integrate controlled vehicle physics and rendering

Context

This PR connects the Mineflayer vehicle simulation to the renderer and enables
mounted vehicle interaction in the browser client.

It is the integration layer for the related physics, Mineflayer, and renderer
PRs, covering boats, horses, and minecarts.

Implementation

Vehicle interaction

  • Allow mouse interaction with vehicle entities so players can mount and control
    vehicles (boats and horses; minecarts are server-driven).
  • Enable interaction and controls while mounted.

Renderer hints

  • Mark the player's current vehicle as the local vehicle.
  • Forward a passenger layout per vehicle type (boat / minecart / horse)
    and the passenger IDs so the renderer can seat riders.
  • Boats:
    • forward authoritative local boat status from Mineflayer;
    • derive water-patch visibility for local boats from physics status and for
      remote boats from world blocks;
    • hide the patch for submerged boats, flowing-water cover, land, waterlogged
      solid blocks, and unloaded world data.
  • Horses: request a vertical camera lock while the player is actively
    controlling the horse.
  • Minecarts: forward riding state and select a server-driven camera movement
    mode (server-vehicle), keeping the local-player mode otherwise.
  • Forward the resulting hints with renderer entity updates.

Passenger rendering

  • Stabilize mounted-player rendering.
  • Add a rider movement-animation state (mounted/riding) so seated players are
    animated consistently.

Diagnostics

  • Expose BOAT_PHYS_DEBUG to browser builds for live controlled-boat
    diagnostics.

Build correctness

  • Declare glob and ws as direct dependencies because client scripts import
    them directly.
  • Migrate scripts/build.js to the glob@10 globSync API.

Previously these packages were available only through incidental pnpm transitive
hoisting. Changing the dependency graph for local file: development exposed
that undeclared dependency.

Testing

  • src/boatRenderHints.test.ts — 20 passing tests.
  • src/cameraMovementMode.test.ts — 2 passing tests.
  • src/entityMovementAnimation.test.ts — 7 passing tests.
  • Coverage includes:
    • every local BoatStatus;
    • source and flowing water; submerged and on-land boats; waterlogged blocks;
      unloaded world data; local versus remote vehicle hints;
    • boat / minecart / horse passenger layouts and horse camera lock;
    • minecart server-vehicle camera mode;
    • rider movement-animation states.
  • Full Minecraft 1.17.1 browser validation covered:
    • mounting and controls (boat and horse);
    • sustained acceleration; input press and release;
    • third-person alignment; server corrections;
    • boat water masking;
    • minecart riding.

Version support

The client itself has no version gate; it forwards whatever the physics,
Mineflayer, and renderer layers support and was validated on Minecraft 1.17.1.
The 1.17.1 limit for locally controlled boats and horses comes from Mineflayer
(vehicle control protocol and boat physics model); minecart riding is
server-authoritative and version-neutral.

Dependencies

This PR should merge after the following PRs are merged and released or otherwise
made available to the client:

Merge order

  1. mineflayer-physics-utils
  2. mineflayer and minecraft-renderer
  3. minecraft-web-client

sandexzx added 4 commits July 12, 2026 11:33
Allow right-click interaction with vehicle entities so players can mount
and control boats through the web client.
Inline BOAT_PHYS_DEBUG into browser builds so controlled-boat diagnostics can be enabled during live testing.
Mark the controlled vehicle and derive water-mask visibility before forwarding entity updates. Cover local status, remote water sampling, and unloaded-world behavior.
Build and data scripts imported glob and ws through transitive pnpm hoisting, so local file links could change whether those packages resolved. Declare both directly and migrate the build helper to the glob v10 globSync API.
@coderabbitai

coderabbitai Bot commented Jul 12, 2026 •

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds boat, minecart, and horse render hints, passenger refresh handling, minecart-specific camera movement modes, centralized movement animation selection with horse riding support, build glob updates, a debug environment value, dependencies, and explicit mouse vehicle interaction behavior.

Changes

Vehicle rendering

Layer / File(s) Summary
Vehicle render-hint logic
src/boatRenderHints.ts
Computes boat water visibility, passenger data, and vehicle-specific hints for boats, rideable minecarts, and horses.
Entity render-hint integration
src/appViewer.ts
Includes render hints in entity events and queues vehicle refreshes when passengers attach or detach.
Vehicle render-hint tests
src/boatRenderHints.test.ts
Tests boat water visibility, passenger behavior, minecart layouts, horse layouts, detach behavior, and vehicle name recognition.

Vehicle camera modes

Layer / File(s) Summary
Camera movement mode selection
src/cameraMovementMode.ts, src/cameraMovementMode.test.ts
Selects server-vehicle for rideable minecarts and local-player otherwise.
Camera update wiring
src/index.ts, src/mineflayer/playerState.ts
Passes movement modes to camera updates and handles regular versus forced movement events.

Movement animation resolution

Layer / File(s) Summary
Movement animation resolver
src/entityMovementAnimation.ts, src/entities.ts
Centralizes animation selection using mounted, horse-mounted, crouched, and horizontal velocity state.
Movement animation tests
src/entityMovementAnimation.test.ts
Tests mounted, horse-riding, walking, sprinting, crouched, and stationary animation states.

Build and interaction updates

Layer / File(s) Summary
Build glob and environment configuration
package.json, rsbuild.config.ts, scripts/build.js
Adds glob and ws, injects BOAT_PHYS_DEBUG, and uses globSync for build file discovery.
Mouse vehicle interaction setting
src/mineflayer/plugins/mouse.ts
Explicitly sets preventVehicleInteraction to false.

Estimated code review effort: 3 (Moderate) | ~30 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Bot
  participant WorldRenderer
  participant getCameraMovementMode
  participant Backend
  Bot->>WorldRenderer: Emit move or forcedMove
  WorldRenderer->>getCameraMovementMode: Inspect current vehicle
  getCameraMovementMode-->>WorldRenderer: Return movementMode
  WorldRenderer->>Backend: updateCamera with movementMode
Loading

Possibly related PRs

Suggested labels: Review effort 3/5

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and matches the PR’s main theme: integrating controlled boat physics with rendering.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot 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.

🧹 Nitpick comments (2)
src/boatRenderHints.test.ts (1)

29-40: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

ESLint: | 0 and == null in test helpers.

Static analysis flags | 0 (prefer Math.trunc) on line 32 and == null (prefer strict equality) on line 36. These are minor and don't affect test correctness, but would fail a strict lint gate.

♻️ Proposed fixes
 function makeWorld (blocks: Record<string, number | StubBlock | null>) {
   return {
     getBlock (pos: Vec3) {
-      const key = `${pos.x | 0},${pos.y | 0},${pos.z | 0}`
+      const key = `${Math.trunc(pos.x)},${Math.trunc(pos.y)},${Math.trunc(pos.z)}`
       const entry = blocks[key]
       if (entry === null) return null
       if (typeof entry === 'object') return entry
-      if (entry == null) return makeBlock(airId)
+      if (entry === null || entry === undefined) return makeBlock(airId)
       return makeBlock(entry)
     },
   }
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/boatRenderHints.test.ts` around lines 29 - 40, Update the
makeWorld.getBlock helper to replace bitwise | 0 coordinate coercion with
Math.trunc and replace the loose == null check with an explicit strict
null/undefined check, preserving the existing block lookup behavior.

Source: Linters/SAST tools

src/boatRenderHints.ts (1)

37-42: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

ESLint: simplify nullish checks and unnecessary ternary.

Static analysis flags multiple == null comparisons (no-eq-null, eqeqeq) and an unnecessary ternary on line 90. The == null checks are intentional for nullish (null | undefined) detection, but the project's ESLint config requires strict equality. The ternary on line 90 is a clear simplification.

♻️ Proposed fixes
 // Line 40: use explicit nullish check
-  if (ids.flowingWaterId != null && block.type === ids.flowingWaterId) return true
+  if (ids.flowingWaterId !== undefined && ids.flowingWaterId !== null && block.type === ids.flowingWaterId) return true

 // Line 90: simplify ternary
-  return foundSource ? true : false
+  return foundSource

 // Lines 77, 106, 127, 130: use strict null checks
-        if (block == null) return null
+        if (block === null || block === undefined) return null

Also applies to: 77-77, 90-90, 106-106, 127-127, 130-130

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/boatRenderHints.ts` around lines 37 - 42, Replace all nullish comparisons
in the affected code, including the ids.flowingWaterId check in isWaterBlock,
with explicit strict checks for null and undefined while preserving nullish
behavior. Simplify the unnecessary ternary at line 90 to its direct equivalent,
and apply the same ESLint-compliant changes at the other flagged locations.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/boatRenderHints.test.ts`:
- Around line 29-40: Update the makeWorld.getBlock helper to replace bitwise | 0
coordinate coercion with Math.trunc and replace the loose == null check with an
explicit strict null/undefined check, preserving the existing block lookup
behavior.

In `@src/boatRenderHints.ts`:
- Around line 37-42: Replace all nullish comparisons in the affected code,
including the ids.flowingWaterId check in isWaterBlock, with explicit strict
checks for null and undefined while preserving nullish behavior. Simplify the
unnecessary ternary at line 90 to its direct equivalent, and apply the same
ESLint-compliant changes at the other flagged locations.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a76ae778-3ec5-466a-bd40-5efe354190ba

📥 Commits

Reviewing files that changed from the base of the PR and between 6032dcc and 0326f30.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (7)
  • package.json
  • rsbuild.config.ts
  • scripts/build.js
  • src/appViewer.ts
  • src/boatRenderHints.test.ts
  • src/boatRenderHints.ts
  • src/mineflayer/plugins/mouse.ts

sandexzx added 3 commits July 12, 2026 22:37
Include boat passenger IDs in entity render hints and refresh
affected vehicles when remote passengers attach or detach.
Forward ordered minecart passenger data while keeping boat-specific
local prediction hints separate.

Select server-vehicle camera smoothing while mounted and apply forced
position corrections immediately.
Suppress walking and running animations while a player is mounted so
vehicle movement is not interpreted as player locomotion.

Mark locally ridden minecarts for camera-synced rendering and correct
flowing-water source classification.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/entityMovementAnimation.test.ts (1)

48-54: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add test for unmounted idle and crouched-at-sprint-speed.

Two paths are untested:

  1. Unmounted, not crouched, zero velocity → return 'idle' (line 25 of entityMovementAnimation.ts). Current idle tests only exercise the mounted early return (line 13).
  2. Crouched at sprinting speed → should return 'crouchWalking', confirming crouch suppresses sprinting animation.
🧪 Suggested additional tests
 test('unmounted stationary crouch uses crouch', () => {
   expect(getEntityMovementAnimation({
     isMounted: false,
     isCrouched: true,
     horizontalVelocity: { x: 0, z: 0 },
   })).toBe('crouch')
 })
+
+test('unmounted stationary uses idle', () => {
+  expect(getEntityMovementAnimation({
+    isMounted: false,
+    isCrouched: false,
+    horizontalVelocity: { x: 0, z: 0 },
+  })).toBe('idle')
+})
+
+test('crouched at sprinting speed uses crouchWalking not running', () => {
+  expect(getEntityMovementAnimation({
+    isMounted: false,
+    isCrouched: true,
+    horizontalVelocity: sprintingVelocity,
+  })).toBe('crouchWalking')
+})
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/entityMovementAnimation.test.ts` around lines 48 - 54, Add tests in the
entity movement animation test suite covering unmounted, non-crouched entities
with zero horizontal velocity expecting “idle”, and crouched entities moving at
sprint speed expecting “crouchWalking”.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/entities.ts`:
- Line 78: Update the isMounted expression in the entity mapping to avoid the
forbidden loose null comparison while preserving its current true/false behavior
for both null and undefined vehicle values, using an explicit
null-and-undefined-safe check.

---

Nitpick comments:
In `@src/entityMovementAnimation.test.ts`:
- Around line 48-54: Add tests in the entity movement animation test suite
covering unmounted, non-crouched entities with zero horizontal velocity
expecting “idle”, and crouched entities moving at sprint speed expecting
“crouchWalking”.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 57be005e-fd0b-48ca-8568-434f8c06f0f2

📥 Commits

Reviewing files that changed from the base of the PR and between 5c4d162 and cec6934.

📒 Files selected for processing (5)
  • src/boatRenderHints.test.ts
  • src/boatRenderHints.ts
  • src/entities.ts
  • src/entityMovementAnimation.test.ts
  • src/entityMovementAnimation.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/boatRenderHints.test.ts
  • src/boatRenderHints.ts

Comment thread src/entities.ts Outdated
sandexzx and others added 9 commits July 13, 2026 12:13
Expose horse passenger layout and local-vehicle hints for supported
rideable horse variants.

Keep the local horse camera client-authoritative and use the riding
animation for mounted players.
Pass an explicit horse-only vertical camera lock hint while local horse physics is active.
- Drive local animations from bot velocity instead of tracker lifecycle.
- Apply riding to every mounted vehicle and refresh on mount, dismount, and respawn.
- Sanitize velocity, avoid duplicate local processing, and cache only delivered animations.
- Add regression coverage for local and remote animation pipelines.
Add paddle state to boat render hints for local and remote entities.

Use local physics state without waiting for a metadata roundtrip and
resolve remote paddle flags from named metadata or the 1.17.1 raw
indices. Reset paddles for empty boats and malformed metadata.
Expose render hint so the renderer can predict horse model yaw from
camera without affecting boat or minecart passengers.
@zardoy
zardoy merged commit b6a2fa0 into zardoy:next Aug 1, 2026
2 of 3 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