Files
Emil c7e86663d8
MVP checks / mvp (push) Waiting to run
Expand voxel gameplay, lighting, full-height streaming and world imports
Add shared Rust/WASM physics, worker meshing and diagnostics, 64-chunk full-height streaming, atlas texture support, and baseline world import. Document the current implementation and include the supplied in-game lobby screenshot.
2026-09-17 02:10:53 +03:00

9.4 KiB

Player physics

Shacraft uses one Rust player-movement implementation on the authoritative server and in the browser through WebAssembly. It targets the movement of Minecraft Java 26.2, with measured reference cases from the original executable. The measurements establish specific numerical agreements; they do not establish complete Minecraft compatibility.

Playing

  • WASD / arrow keys: walk; Ctrl + forward: sprint.
  • Space: jump, swim upward, or ascend while flying.
  • Shift: crouch and avoid walking off edges; descend in water or flight.
  • Double-tap Space / F: toggle flight when the server permits it. Creative worlds permit flight; ordinary players in other world modes cannot enable it.
  • F3: inspect the active physics mode, pose, unacknowledged input count, and the latest position correction.

Walking accelerates and retains momentum. Ground friction, air control, the sprint jump impulse, held-jump cooldown, gravity and drag all operate on fixed 50 ms ticks. Crouching changes the collision box and eye height. A player who cannot stand or crouch fits into the swimming-sized crawling pose when possible.

Collision handling uses the catalog's block-state boxes, resolves vertical movement before horizontal movement, and chooses step heights from obstacle surfaces. Slabs, stairs, ceilings, corners and sneak-edge support participate in the same solver. Scaffolding and powder snow have additional player-dependent collision rules.

The solver also handles ice variants, slime and bed bounces, honey slowing and wall sliding, soul sand, climbable blocks, cobwebs, berry bushes, powder snow, water, lava, waterlogged cells, bubble columns, swimming and creative flight. Water/lava behavior includes acceleration, drag, buoyancy inputs, fluid levels and currents derived from the provided nearby block states.

PhysicsSettings exposes movement and flight speed, step height, launch-pad jump overrides, leather boots and coefficients for speed, slowness, jump boost, levitation, slow falling, Dolphin's Grace and Depth Strider. These are solver inputs for server integrations; their presence does not add an inventory, equipment or potion gameplay system. apply_impulse accepts an external velocity change for future combat, explosions or scripted launch effects.

Shared simulation and networking

The implementation is in crates/shacraft-physics. Positions use blocks and velocities use blocks per tick. Angles are radians; Shacraft yaw zero faces negative Z. Reference tests convert Minecraft's positive Z convention explicitly.

The server supplies authoritative nearby block states, shape boxes and settings. The browser runs the same compiled solver immediately for local input. Each server motion update includes a sequence acknowledgement, tick and motion epoch. The client restores the acknowledged state and replays pending inputs. Teleports and world changes reset prediction; render smoothing affects the displayed position without feeding a smoothed position back into physics.

client/player-physics.js samples the swept collision neighborhood, keeps a bounded input history and interpolates display frames between fixed simulation ticks. It suspends prediction when that neighborhood extends into unknown chunks instead of treating missing data as air. A failed or incompatible WebAssembly load falls back to server movement. Server support is negotiated with movement_prediction_v1 so older clients can continue using authoritative updates.

Reference evidence

scripts/physics_reference.java runs against the pinned official 26.2 server executable already used for catalog extraction. It does not start a Minecraft server. Registry initialization is real; player and world constructors are bypassed for an isolated measurement harness. Only factual measurements and the independently authored harness are stored in the repository.

The committed java26.2.json contains:

  • Friction, speed, jump and bounce factors for 16 surfaces; default player attributes; five pose dimensions; water/lava heights for all 16 level values.
  • Thirteen trajectories from original Player.travel, jumpFromGround and Entity.collideWithShapes calls: walking, sprinting, jumping, ice movement, water, lava and creative flight.
  • Eight original Entity.collide measurements, including low-ceiling steps, thin steps, descending into a step and choosing the lowest useful step.
  • Separate original collision restitution, honey slide, slime step, bubble column and current-application measurements.

The trajectory harness supplies inputs, small-velocity threshold preparation, the measured sprint attribute modifier, constant medium/depth and flat-plane position/collision bookkeeping. It deliberately does not claim to execute the entire original game tick. Callback samples measure the callbacks separately, not their complete automatic dispatch in a running world. The water sprint kernel keeps the swimming pose disabled to isolate water travel.

Some details differ from older Minecraft physics descriptions: the sprint attribute modifier is the float-derived 0.30000001192092896, the player's horizontal small-velocity threshold applies to the vector's squared length, bed restitution is 0.75, and bounce velocity includes the fraction of motion completed before collision. The measured standing jump reaches 1.2522033402537238 blocks above its starting position.

Native trajectory tests compare position and velocity on every tested tick with an absolute tolerance of 2e-6. They exercise twelve of the thirteen kernels: the artificial constant shallow-lava depth is excluded because an integrated world changes immersion as the player falls. Water sprint comparison stops when input is released, because the integrated controller ends sprinting while the isolated kernel keeps its sprint flag set. Separate step cases use 1e-7, and restitution, honey and bubble callback tests use 1e-12.

Browser tests execute the shipped WebAssembly through the actual JavaScript ABI, compare the eight air/ground/flight reference trajectories with 2e-6 tolerance, and exercise replay under delayed acknowledgements. Additional tests cover movement, collision, fluids, body poses, prediction resets, missing chunks and input ordering. These tolerances describe the tested cases, not an error bound for every possible world, angle or interaction.

The HTTP/WebSocket integration check starts a real release server on an isolated port with a temporary database and loads the WebAssembly it serves. It compares consecutive authoritative states against the same consumed command in the browser solver with 1e-10 tolerance. It also checks burst acknowledgements, duplicate commands, crouching, jumping, flight permissions, reset epochs, continuous movement across chunk boundaries, and a client without prediction support. Only explicit world changes may produce full snapshots during that check. The report records both binary hashes and the largest observed error.

Building and verification

After changing the Rust solver, rebuild the browser artifact before opening the game or running browser physics tests:

rustup target add wasm32-unknown-unknown
bash scripts/build_physics.sh
cargo test -p shacraft-physics
cd client
npm test

The complete workspace checks remain cargo test --workspace, cargo fmt --all -- --check and cargo clippy --workspace --all-targets -- -D warnings from the repository root.

Run the isolated real-network check from the repository root after rebuilding both the native server and browser module:

cargo build -p shacraft-server --release
bash scripts/build_physics.sh
node scripts/check_player_physics.mjs \
  --port 4013 \
  --binary target/release/shacraft-server \
  --output artifacts/physics/network-report.json

The harness refuses a port already serving HTTP and does not use the running demo server or its database.

To reproduce measurements with an existing Java 25 JDK and the catalog cache:

python3 scripts/measure_physics.py \
  --java /path/to/java25/bin/java \
  --output crates/shacraft-physics/tests/fixtures/java26.2.json

If the cache is absent, prepare it using the catalog generation instructions before running the probe. The measurement runner verifies the pinned official bundle hash and verifies that the extracted executable matches that bundle. The fixture records the source URL, source and executable hashes, Java version, probe hash and reproduction command. Runtime binaries, diagnostic bytecode output and logs remain in ignored artifacts/.

Remaining scope

This change implements player locomotion, not Minecraft's complete simulation. It does not add fluid spreading or scheduled fluid/block updates, pistons and moving block machinery, boats/minecarts, entity pushing, an elytra model, or the full combat/damage/knockback system. The external impulse API is a building block for those systems rather than their implementation.

Collision accuracy also depends on the catalog's measured boxes and on the states supplied by the server. Additional entity-dependent shapes, moving obstacles, complete fluid flow rules, every status-effect interaction and arbitrary input-angle trajectories need further reference cases. The browser and server share the same numerical implementation, but prediction can still be corrected when world edits or authoritative settings arrive after an input.