Automatically backup the
worldfolder to cloud storage and sync from cloud every 3 days.
- Daily Backup: Every day at 3:00 AM, saves the world, zips it, and uploads to an Anyshare cloud drive.
- Periodic Sync: Every 3 days at 3:15 AM, downloads the latest cloud backup and swaps the world folder (requires server restart).
- Manual Commands: Trigger backup or sync on demand via in-game chat or MCDR console.
- State Persistence: Remembers last backup/sync dates across restarts via a JSON state file.
| File | Path | Purpose |
|---|---|---|
| Plugin | plugins/auto_world_sync.py |
This plugin |
| CLI tool | anyshare_cli.py (MCDR root) |
Anyshare cloud drive CLI |
| State file | config/auto_world_sync_state.json |
Last backup/sync dates |
| Temp dir | temp/ |
Temporary zip downloads |
All settings are at the top of auto_world_sync.py:
# Cloud share link (USTB Anyshare)
ANYSHARE_LINK = 'https://yunpan.ustb.edu.cn/link/AAE9BD48FD7D7F4716869B4CA17A1A1CC4'
# Remote subfolder (empty = root of share link)
REMOTE_SUBDIR = ''
# Backup schedule (24h format)
BACKUP_HOUR = 3 # 3:00 AM
BACKUP_MINUTE = 0
# Sync interval (days)
SYNC_INTERVAL_DAYS = 3
# Sync schedule (15 min after backup to ensure backup is done)
SYNC_HOUR = 3 # 3:15 AM
SYNC_MINUTE = 15
# Seconds to wait after save-all for disk writes
SAVE_WAIT_SECONDS = 10Type these in the MCDR console or in-game chat:
| Command | Action |
|---|---|
!!backup |
Trigger a backup immediately (save-all, zip, upload) |
!!sync |
Trigger a sync immediately (download latest, restart, swap world) |
!!syncinfo |
Show current status: last backup date, last sync date, schedule |
Warning:
!!syncwill restart the server. Make sure no players are online.
3:00 AM
|
+--> server.execute('save-all') # tell MC server to save world
+--> sleep 10s # wait for disk writes
+--> zip world/ -> world_backup_YYYYMMDD.zip
+--> upload zip to cloud (anyshare_cli.py upload)
+--> delete local temp zip
3:15 AM (every 3 days)
|
+--> anyshare_cli.py list # list cloud files
+--> find latest by timestamp # parse YYYY-MM-DD_HH-MM-SS from filename
+--> anyshare_cli.py download # download to temp/
+--> set _pending_restore = True
+--> server.restart() # restart MC server
|
v
on_server_stop event triggers:
+--> rename world/ -> world_old_YYYYMMDD_HHMMSS # keep old world as backup
+--> extract zip -> server/ # new world replaces old
+--> MCDR auto-restarts server # new world is live
- MCDReforged >= 2.0.0 (tested with v2.15.7)
- Python 3 with
requestslibrary (MCDR's bundled Python already has it) - anyshare_cli.py in the MCDR root directory (AnyshareCLI from LYOfficial/AnyshareCLI)
The plugin supports two backup filename formats:
| Source | Format | Example | Sort Key |
|---|---|---|---|
| This plugin | world_backup_YYYYMMDD.zip |
world_backup_20260810.zip |
20260810000000 |
| External tools | world_YYYY-MM-DD_HH-MM-SS.zip |
world_2026-08-09_20-42-57.zip |
20260809204257 |
Files are sorted by the full timestamp (date + time) to correctly identify the newest backup, even when multiple backups exist on the same day.
config/auto_world_sync_state.json:
{
"last_backup_date": "20260810",
"last_sync_date": "20260810"
}last_backup_date: Prevents duplicate backups on the same day.last_sync_date: Used to calculate when 3 days have passed for the next sync.- On first run,
last_sync_dateis initialized to today but no download is performed (avoids immediate restart on first launch).
This was a bug in anyshare_cli.py where the get_download_url() function discarded the Authorization and x-amz-date headers from the auth response. Fixed by parsing headers from authrequest[2:] and passing them to the download request.
If multiple backups exist on the same day, the old _extract_date() function only compared by date (YYYYMMDD), picking the first file of the day instead of the actual latest. Fixed by using _extract_sort_key() which extracts the full timestamp (YYYYMMDDHHMMSS).
AnyshareCLI prints errors to stdout (via print()), not stderr. The plugin now logs both result.stdout and result.stderr on failure.
Commands must be registered via the official MCDR command API (Literal + server.register_command()), not just on_user_info event handlers. Unregistered !! commands pass through to the Minecraft server, which doesn't understand them.
| Version | Changes |
|---|---|
| 1.0.0 | Initial: daily backup, 3-day sync, Unicode-escaped strings |
| 1.1.0 | Upload to root (no subdir), support dashed date format, add manual commands |
| 1.2.0 | Use MCDR command registration API (Literal) instead of on_user_info |
| 1.3.0 | Fix download 403 (auth headers), fix date sorting (full timestamp), fix error logging (stdout) |