mapsyncer-paper: server side of MapSyncer for Xaero's World Map, discovery-limited

Paper 26.2 plugin speaking the stock MapSyncer client mod's protocol.
Renders Xaero region zips from the world's region files, but only for chunks
players have actually been sent (PlayerChunkLoadEvent), seeded once from
InhabitedTime. Shared or per-player visibility, background render cycle,
per-player streaming with hash/timestamp skipping, Gitea Actions release
workflow.

Vendors the MCA parser and Xaero writer from upstream MapSyncer (GPL-3.0),
see NOTICE.md.

Claude-Session: https://claude.ai/code/session_011FePLXwBsCGLTzaSkk1Z6V
This commit is contained in:
2026-09-07 00:04:43 +03:00
commit 7fb3a82482
67 changed files with 10934 additions and 0 deletions
+86
View File
@@ -0,0 +1,86 @@
name: Build
run-name: ${{ gitea.actor }} is building mapsyncer-paper 🗺️
on:
push:
branches: [main]
tags: ['v*']
pull_request:
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Check out repository code
uses: actions/checkout@v4
- name: Set up JDK
uses: actions/setup-java@v4
with:
distribution: temurin
# Must be >= the `javaRelease` in gradle.properties (the class-file
# target that matches the Minecraft server's own JVM). Newer is fine:
# javac's --release pins the output regardless.
java-version: '25'
- name: Cache Gradle
uses: actions/cache@v4
with:
# The paperweight dev bundle is decompiled/remapped into
# ~/.gradle/caches/paperweight on first use; it is several minutes of
# work, so keep it between runs.
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts', 'gradle/wrapper/gradle-wrapper.properties', 'gradle.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Build and test
run: ./gradlew --no-daemon build
- name: Name the artifact
id: jar
run: |
set -euo pipefail
path="$(ls build/libs/mapsyncer-paper-*.jar | grep -vE -- '-(sources|thin)\.jar$' | head -1)"
echo "path=$path" >> "$GITHUB_OUTPUT"
echo "name=$(basename "$path")" >> "$GITHUB_OUTPUT"
ls -la build/libs/
- name: Upload the plugin jar
# v3, not v4, deliberately. v4 needs the artifact service v2, which only
# some runners in this fleet advertise; `runs-on: ubuntu-latest` can land
# on any of them, and v4 fails there with GHESNotSupportedError. v3 uses
# the older protocol, which every runner still serves.
uses: actions/upload-artifact@v3
with:
name: mapsyncer-paper
path: build/libs/mapsyncer-paper-*.jar
retention-days: 90
- name: Publish a release for a tag
if: startsWith(gitea.ref, 'refs/tags/v')
env:
# Injected by Gitea Actions for the running repository.
TOKEN: ${{ secrets.GITHUB_TOKEN }}
API: ${{ gitea.server_url }}/api/v1/repos/${{ gitea.repository }}
TAG: ${{ gitea.ref_name }}
JAR: ${{ steps.jar.outputs.path }}
JAR_NAME: ${{ steps.jar.outputs.name }}
run: |
set -euo pipefail
# Reuse the release if the tag was built before, so a re-run does not
# fail on "already exists".
id="$(curl -sS -H "Authorization: token $TOKEN" "$API/releases/tags/$TAG" \
| sed -n 's/.*"id":[[:space:]]*\([0-9]\+\).*/\1/p' | head -1 || true)"
if [ -z "$id" ]; then
id="$(curl -sS -X POST -H "Authorization: token $TOKEN" \
-H 'Content-Type: application/json' \
-d "{\"tag_name\":\"$TAG\",\"name\":\"$TAG\"}" "$API/releases" \
| sed -n 's/.*"id":[[:space:]]*\([0-9]\+\).*/\1/p' | head -1)"
fi
curl -sS -X POST -H "Authorization: token $TOKEN" \
-F "attachment=@$JAR" \
"$API/releases/$id/assets?name=$JAR_NAME" > /dev/null
echo "Attached $JAR_NAME to release $TAG"