# VoxelWorld

VoxelWorld is a Java/LWJGL voxel MMO prototype with a desktop client and a
headless authoritative multiplayer server.

See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for the current code map and extension notes.

## Local development

```sh
./dev play --args=--offline
```

To host the public multiplayer session, run:

```sh
./dev server
```

That command ensures the dedicated Docker Tailscale Funnel is ready before it
starts Java. The first run prints a Tailscale sign-in URL; approve this Mac once
and rerun the command. After that, the persistent Funnel publishes the game
with TLS on public port `443` and the read-only health endpoint with HTTPS on
public port `8443`. It connects outbound, so changing ISP/router addresses and
CGNAT do not require router port forwarding or a dynamic-DNS updater.

On macOS, `./dev server` also opens the Voxel Slop menu-bar controller. Its
light is green only when the public health endpoint is reachable and red when
the server is offline or only reachable locally. The menu provides Server On,
Server Off, detailed status, manual refresh, and the server log. Reopen it with
`./dev tray`; the equivalent terminal commands are `./dev server-on`,
`./dev server-off`, and `./dev server-status`. Quitting the tray leaves a
running server alone.

Run `./dev play` in another terminal for a direct client on this Mac. Use
`./dev server-local` for a loopback-only server, `./dev funnel-status` to
inspect the public routes, or `./dev funnel-off` to disable them. The first
account in a new server database is `admin` / `admin`; read the security
warning and connection details in
[docs/MULTIPLAYER.md](docs/MULTIPLAYER.md).

Build the current-host client, Windows x64 ZIP and setup executable, and
platform-independent server ZIP with:

```sh
./dev package
```

On this Apple Silicon Mac, refresh both public player downloads and verify the
website in one command:

```sh
./dev release-site
```

That command rebuilds the macOS Apple Silicon archive plus the Windows x64
installer and portable ZIP, copies the public artifacts into VoxelSlopSite,
regenerates sizes and SHA-256 checksums, then runs the site build and tests. See
[docs/RELEASING.md](docs/RELEASING.md) for the release checklist.

Public clients open with `play.projectslop.xyz` selected. They discover its
service endpoint through DNS SRV, require that result to match the hostname
pinned into the release (`vs.tailf3317e.ts.net`), and verify TLS before sending
login or gameplay data. The pin has an explicit Gradle/environment override for
a future planned endpoint migration; ordinary builds need no extra setting.
The Gradle `run` task is deliberately separate: plain `./dev play` continues
to use the local direct connection at `127.0.0.1:25565`.

Controls:

- `W`, `A`, `S`, `D`: move
- Mouse: look
- `Left Shift`: sprint
- `Left Control`: crouch while walking; fly down while fly mode is enabled
- `Space`: jump when walking
- Mouse wheel: select hotbar slot
- `T`: open persistent server chat; slash commands share the same input
- `E`: open inventory
- `Enter`: fast-forward the one-time opening wizard dialogue
- `F`: toggle fly mode
- `Q`: throw one item from the selected hotbar slot
- `Space` / `Left Control`: fly up/down when fly mode is enabled
- Left mouse: hold to break the targeted block
- Right mouse: place the selected hotbar block, fill an empty bucket from a
  still water source, or pour a water bucket against the targeted block face
- `Esc`: release or recapture the mouse

Crouching lowers the camera, prevents walking off ledges, halves walking speed, and reduces jump strength.

Inventory:

- Left click picks up, places, merges, or swaps full stacks.
- Right click picks up half a stack or places one item.
- The personal 2x2 grid supports basic recipes. A workbench opens 3x3 crafting,
  including one bucket from three iron ingots arranged in a V.
- Empty buckets stack to 16. Filled water buckets occupy one slot, collect only
  source water, and place a new source that flows on the normal water cadence.
- Broken blocks drop as small world items, then pull toward the player and enter inventory when close.

Commands:

- `/fly`: administrators toggle server-authoritative fly mode. Hunger pauses
  and disappears while flying, and flying administrators may remove
  spawn-protected blocks; placement remains warded and the shared starter
  chest cannot be removed.
- `/day` and `/night`: administrators change the shared server clock.
- `/perf`: toggle the local performance overlay.

Chat messages are attributed, persisted, and broadcast by the authenticated
server. Regular players see chat controls when pressing `T`; administrator
command suggestions are shown only to administrators.

Multiplayer protocol v12 keeps inventory and survival state authoritative per
account while sharing the outside world's drops, arrows, PvP, mobs, time,
weather, and persistent campfires. The crater boss is a private per-account
instance: its boss progress, terrain, water, and drops persist separately, and
players disappear from the shared world with a smoke transition while inside.
Remote players and creatures preserve stable identities and render from a
three-tick interpolation buffer on the authoritative server timeline, with
short bounded extrapolation instead of packet-time snapping. Local movement
remains immediate, while numbered correction epochs invalidate every stale pose
already in flight so delayed acknowledgements cannot pull the camera backward.
Client network reads and writes are bounded and coalesced off the render thread.
Gameplay overlays and cutscenes keep physical movement advancing, while a
midair reconnect resolves to safe support with authoritative fall damage. The
server still decides movement acceptance, impacts, damage, and despawn.

The `dev` helper prefers the Homebrew JDK 25 install on macOS without changing your global shell Java version.

Smoke capture:

```sh
./dev run -PsmokeFrames=8 -PautoStartWorld=true -PcaptureFrame=build/captures/smoke.png
```

For a deterministic opening-wizard capture, wait for all visible chunks before
starting the smoke frame clock:

```sh
./dev run -PautoStartWorld=true -PsmokeWaitForVisibleChunks=true \
  -PsmokeFrames=70 -PcaptureFrameAt=35 \
  -PcaptureFrame=build/captures/wizard-loaded.png --args=--offline
```

Chunk generation speed baseline:

```sh
./dev chunkGenerationSpeedTest
```

This headless probe measures the CPU terrain and water mesh work used by chunk
workers and writes `build/reports/chunk-generation-speed.json`. See
[docs/CHUNK_GENERATION_SPEED_TEST.md](docs/CHUNK_GENERATION_SPEED_TEST.md) for
the protocol, options, current baseline, and comparison rules.

The staged optimization and authoritative-server direction are documented in
[docs/CHUNK_PIPELINE_PLAN.md](docs/CHUNK_PIPELINE_PLAN.md).
