Build / build (push) Successful in 3m6s
Build against the 26.3 dev bundle (26.3.build.151-beta; no stable build
exists yet).
26.3 rewrote the block palette in region files: a default-state block is a
bare string, any other state is {id, properties}, and a list mixing both
wraps the strings as {"": name}. The parser cast every entry to a
compound with Name/Properties, so every chunk saved by 26.3 threw
ClassCastException and the whole region failed to render. Both formats are
read now (a region holds a mix until every chunk is re-saved), and a chunk
that fails to parse is skipped instead of aborting the region.
98 lines
4.0 KiB
Markdown
98 lines
4.0 KiB
Markdown
# mapsyncer-paper
|
|
|
|
The server half of [MapSyncer for Xaero's World Map](https://github.com/RuoChennn/MapSyncer-for-XaeroWorldmap),
|
|
as a Paper plugin — with one twist: the map players receive is built from
|
|
**what players have actually discovered**, not from every chunk the server has
|
|
ever generated.
|
|
|
|
Players run the stock MapSyncer client mod (Fabric or NeoForge, same Minecraft
|
|
version as the server) next to Xaero's World Map. The plugin speaks the mod's
|
|
wire protocol byte for byte, so nothing on the client needs patching.
|
|
|
|
## What it does
|
|
|
|
1. **Tracks discovery.** Every chunk the server sends to a player is recorded
|
|
for that player (`PlayerChunkLoadEvent`). That is exactly the set Xaero's
|
|
client maps on its own, so the server's picture of a region is always a
|
|
superset of the player's — which matters, because the client mod overwrites
|
|
region files wholesale.
|
|
2. **Seeds history once.** On first start the plugin scans each world's region
|
|
files and marks chunks with `InhabitedTime > 0` as discovered. Pre-generated
|
|
terrain (Chunky, distant-terrain LOD generation) has `InhabitedTime = 0` and
|
|
stays hidden until somebody walks there.
|
|
3. **Renders on demand.** A region is converted from its `.mca` file into a
|
|
Xaero region zip only for the discovered chunks; everything else becomes a
|
|
"no data" tile. Re-rendering happens when the region file changes or the
|
|
discovery mask grows.
|
|
4. **Streams to the mod.** On join the client gets a hello, polls
|
|
periodically, and receives whatever changed since it last asked, hash- and
|
|
timestamp-checked per region layer.
|
|
|
|
Two visibility modes (`config.yml`):
|
|
|
|
| `visibility` | Player receives |
|
|
| --- | --- |
|
|
| `shared` (default) | the union of everyone's discoveries |
|
|
| `own` | only what they discovered themselves, plus the seeded history |
|
|
|
|
## Requirements
|
|
|
|
- Paper 26.3 on Java 25 (the build compiles against Paper's Mojang-mapped
|
|
internals via paperweight; other versions need a rebuild).
|
|
- Clients: Xaero's World Map 1.40.11+ and the MapSyncer client mod for the
|
|
same Minecraft version.
|
|
- Xaero's **Multiplayer world map** setting should be *Single*. The client mod
|
|
writes into the newest `mw$…` folder; Xaero's "world spawn" mode uses folders
|
|
without the `$` and would never see the synced files.
|
|
|
|
## Install
|
|
|
|
Drop the jar from the latest release into `plugins/`, start the server, read
|
|
the generated `plugins/MapSyncer/config.yml`. The first start scans every
|
|
tracked world once (a few minutes for a multi-gigabyte world, in the
|
|
background); nothing is served until the first render cycle after that.
|
|
|
|
Dimension folders on the client follow Xaero's own naming: vanilla keys map to
|
|
`null`, `DIM-1`, `DIM1`; anything else, including Multiverse worlds, to
|
|
`namespace$path` (e.g. `minecraft$survival`).
|
|
|
|
## Commands
|
|
|
|
```
|
|
/mapsync status counters: discovery, cache, syncs, clients with the mod
|
|
/mapsync worlds per-world mapping, layers, region directory
|
|
/mapsync render [force] run a render cycle now; force drops the cache first
|
|
/mapsync seed <world|all> re-run the InhabitedTime scan
|
|
/mapsync player <name> what one player has discovered
|
|
/mapsync reload re-read config.yml
|
|
```
|
|
|
|
Permission `mapsyncer.admin` (default: op).
|
|
|
|
## Data
|
|
|
|
Everything lives under `plugins/MapSyncer/`:
|
|
|
|
```
|
|
discovery/<world>.bin discovery bitmaps (per region: union, seeded, per player)
|
|
cache/<scope>/<dim>/[caves/<L>/]<x>_<z>.zip rendered regions; scope = shared or a player UUID
|
|
cache/<scope>/index.tsv timestamps, CRC32s, content stamps
|
|
```
|
|
|
|
Deleting `cache/` is always safe (it is rebuilt). Deleting `discovery/` loses
|
|
who-discovered-what; the next start re-seeds from `InhabitedTime`.
|
|
|
|
## Building
|
|
|
|
```
|
|
./gradlew build # runs the unit tests; jar in build/libs/mapsyncer-paper-<version>.jar
|
|
```
|
|
|
|
CI (`.gitea/workflows/build.yml`) builds on every push and attaches the jar to
|
|
a release for every `v*` tag.
|
|
|
|
## Licence
|
|
|
|
GPL-3.0. The Xaero region writer and MCA parser are vendored from MapSyncer
|
|
(GPL-3.0); see `NOTICE.md` for the exact provenance and the local changes.
|