Mineuniverse
Log in Register
Mods

Mirage Sync

A fabirc minecraft mod for incremental dimension sync between main and mirror Minecraft servers via persistent TCP connection.
by MRNOBODY_ZST
Download Claim this project
27 downloads
0 likes
Updated Jul 6, 2026
0 hypes
Automation Server Utility Utility & QoL

Mirage

A Minecraft Fabric mod for incremental, real-time dimension region synchronization between a main server and one or more mirror servers.

Minecraft Fabric Java License Build

中文说明


Features

Incremental Sync SHA-256 delta comparison transfers only changed .mca region files
Netty TCP Persistent long-lived connection with automatic reconnection on the mirror side
Atomic File Replace Write-to-temp-then-move ensures zero file corruption during sync
Chunk-Level Precision Sync individual chunks via /mirage sync chunk / /mirage pull chunk
Multi-Dimension Supports any registered Minecraft dimension (overworld, nether, end, custom)
Online Sync Players are temporarily kicked only on the target mirror; main server stays online
Auto-Sync Optional scheduled background sync on the mirror side (configurable interval)
Cooldown Guard Built-in cooldown between syncs prevents accidental thundering-herd on servers

Architecture

flowchart LR
    subgraph Main["Main Server"]
        MS[ServerLevel world]
        RH[RegionHasher SHA-256]
        SS[MirageSyncServer<br/>Netty TCP :25566]
        SM[MainServerTask broadcasts hashes]
    end

    subgraph Mirror["Mirror Server"]
        MR[ServerLevel world]
        DC[DeltaComparator diff]
        FT[FileTransferManager atomic move]
        SC[MirageSyncClient TCP client]
        MA[MirrorApplyTask applies changes]
    end

    MS -->|"flush save"| RH
    RH -->|"hash map"| SS
    SS -.->|"HASH_LIST_RESP"| SC
    SC -->|"FILE_SYNC_START"| DC
    DC -->|"file list"| SS
    SS -.->|"FILE_CHUNK"| SC
    SC -->|"write temp mca"| FT
    FT -->|"atomic move"| MR
    MA -->|"kick players"| MR
    MA -->|"clear cache"| MR

Sync sequence (mirror-initiated pull):

sequenceDiagram
    participant M as Mirror Server
    participant S as Main Server

    M->>S: HANDSHAKE (authToken)
    S-->>M: OK

    M->>S: HASH_LIST_REQ
    S->>S: flush world, save chunks
    S->>S: compute SHA-256 for all .mca files
    S-->>M: HASH_LIST_RESP (dimension + hash map)

    M->>M: diff with local hashes
    alt no differences
        M-->>S: SYNC_DONE (no changes)
    else files differ
        M->>S: FILE_SYNC_START (list of changed files)
        loop each file
            S-->>M: FILE_CHUNK (512 KB segments, base64)
        end
        S-->>M: SYNC_DONE
    end

    M->>M: kick all players in dimension
    M->>M: force-save + disable saving
    M->>M: force-unload all chunks + clear region cache
    M->>M: atomic-move temp files → region dir
    M->>M: clear region cache again
    M->>M: re-enable world saving
    M->>M: sync complete

Requirements

Component Version
Minecraft 1.21.11
Fabric Loader ≥ 0.18.4
Fabric API 0.141.3+1.21.11
Java ≥ 21

Installation

  1. Build the mod
   ./gradlew build

The output jar is at build/libs/mirage-<version>.jar.

  1. Install on both main and mirror servers

    • Place the jar into each server's mods/ folder.
    • Both servers must run the same Minecraft version (1.21.11).
  2. First launch

    • Start the server once. config/mirage.json is auto-generated.
    • Stop the server and edit the config (see below).
    • Restart the server.

Configuration

Config file: config/mirage.json, created on first launch.

Main server

{
  "mode": "main",
  "syncCooldownSeconds": 30,
  "mainServer": {
    "port": 25566,
    "authToken": "replace-with-a-secure-random-string"
  }
}

Mirror server

{
  "mode": "mirror",
  "syncCooldownSeconds": 30,
  "mirrorServer": {
    "mainIp": "main-server-ip-or-hostname",
    "mainPort": 25566,
    "authToken": "replace-with-a-secure-random-string",
    "targetDimensions": [
      "minecraft:overworld"
    ],
    "autoSyncEnabled": false,
    "autoSyncIntervalMinutes": 30
  }
}

Configuration fields

Field Default Description
mode main Server role: main or mirror
syncCooldownSeconds 30 Minimum seconds between two sync operations
mainServer.port 25566 TCP port for sync listeners (main only)
mainServer.authToken change-me Must match the mirror's token exactly
mirrorServer.mainIp 127.0.0.1 Main server IP or hostname
mirrorServer.mainPort 25566 Main server sync port
mirrorServer.authToken change-me Must match the main server's token exactly
mirrorServer.targetDimensions [minecraft:overworld] Dimensions to sync on pull
mirrorServer.autoSyncEnabled false Enable automatic scheduled sync
mirrorServer.autoSyncIntervalMinutes 30 Interval between automatic syncs (minutes)

Warning: authToken must be identical on both servers — connections are rejected otherwise. Change the default value change-me to a secure random string before use.

Note: Changes to network settings (port, mainIp, mainPort) require a server restart.


Commands

All admin-level commands require permission level OPERATORS.

Main server commands

Command Description
/mirage sync <dimension> Compute and broadcast the hash list for one dimension to all connected mirrors
/mirage sync all Broadcast hash lists for all registered dimensions
/mirage sync chunk <dimension> <x> <z> Broadcast a single chunk by block coordinates
/mirage status Show mode, connected mirror count, sync state
/mirage reload Reload config/mirage.json from disk

Mirror server commands

Command Description
/mirage pull <dimension> Pull one dimension from the main server
/mirage pull all Pull all dimensions listed in targetDimensions
/mirage pull chunk <dimension> <x> <z> Pull a single chunk by block coordinates
/mirage status Show mode, connection state, sync state
/mirage reload Reload config/mirage.json from disk

Note: Players in the target dimension on the mirror server will be kicked during sync.


Project Structure

src/main/java/xyz/tofumc/
├── Mirage.java                         # Mod entrypoint, lifecycle
└── mirage/
    ├── command/
    │   └── MirageCommand.java          # /mirage command tree (brigadier)
    ├── config/
    │   ├── ConfigManager.java           # JSON config read/write
    │   └── MirageConfig.java            # Config POJO with defaults
    ├── hash/
    │   ├── RegionHasher.java            # SHA-256 all .mca files in a dimension
    │   ├── DeltaComparator.java         # Hash diff → files to download/delete
    │   └── FileTransferManager.java     # Chunked write + atomic move
    ├── network/
    │   ├── protocol/
    │   │   ├── MessageType.java        # Enum: HANDSHAKE, HASH_LIST_REQ, ...
    │   │   ├── MirageProtocol.java     # Binary encode/decode (ByteBuf codec)
    │   │   ├── MessagePayloads.java     # Record-based payload definitions
    │   │   └── MirageFrameDecoder.java # 4-byte big-endian length framing
    │   ├── server/
    │   │   ├── MirageSyncServer.java   # Netty NIO server, broadcast helper
    │   │   └── ServerHandler.java      # Server-side channel inbound handler
    │   └── client/
    │       ├── MirageSyncClient.java   # Netty TCP client, auto-reconnect
    │       └── ClientHandler.java      # Client-side channel inbound handler
    ├── sync/
    │   ├── SyncState.java              # Sync-in-progress flag + cooldown timer
    │   ├── MainServerTask.java         # Hash computation + broadcast
    │   ├── MirrorApplyTask.java        # Receive + apply files / in-memory chunk patch
    │   └── ScheduledSyncTask.java      # Auto-sync scheduling (mirror side)
    ├── util/
    │   ├── HashUtil.java               # SHA-256 digest wrapper
    │   ├── DimensionPathUtil.java      # Dimension ID → region/directory path
    │   ├── RegionFileUtil.java         # .mca filename, chunk offset, NBT I/O
    │   └── SyncLogger.java             # namespaced log helper
    └── world/
        ├── WorldSafetyManager.java     # kick players, force-save, save on/off
        └── ChunkUnloader.java          # unload chunks + clear region cache

Build & Release

Build locally

./gradlew build

Artifact: build/libs/mirage-<version>.jar

The version is read from gradle.properties (mod_version, currently 1.2.0).

CI/CD

Workflow Trigger Action
build.yml Push to any branch / PR ./gradlew build → upload artifact
release.yml Push tag v* Bump mod_version in gradle.properties./gradlew build → publish GitHub Release

Contributing

Bug reports and feature requests are welcome. Please open an issue before submitting a pull request.

Development setup

git clone https://github.com/MRNOBODY-ZST/Mirage.git
cd Mirage
./gradlew build   # verify it compiles

FAQ

Q: Can I run multiple mirrors? Yes. The main server is a TCP server — any number of mirrors can connect simultaneously. Each mirror operates independently.

Q: Does this mod act as a BungeeCord/Velocity proxy? No. Mirage only synchronizes world region files (.mca). It does not proxy player connections or chat. It is a world synchronization tool, not a proxy.

Q: What happens to players during sync? On the mirror server, players in the syncing dimension are kicked with a message and may reconnect immediately (the world is fully saved and consistent). The main server continues to operate normally — players are not affected.

Q: What if the sync is interrupted (e.g. network cut)? File transfer uses atomic temp-file-then-move. If interrupted mid-transfer, the mirror's world remains in its previous consistent state. No corruption occurs. Simply run /mirage pull <dimension> again after reconnecting.

Q: Does Fabric API need to be installed separately? Fabric API is declared as a dependency in fabric.mod.json with * version, meaning it is required. Install it alongside Mirage in the mods/ folder.


License

MIT License — see LICENSE.


Mirage — TofuMC · Minecraft 1.21.11 · Fabric

mirage-1.2.0.jar
MC Fabric, Server, 1.21.11
Release 2026-04-11 Get

You Might Also Like

APTweaks: Items (11.x Classic)
Item clustering (fallen blocks, experience orbs, ...) and garbage cleanup.
9,884,514
VanillaDeathChest (Fabric)
Places containers when players die that contain their items.
994,762
Styled Nicknames
Simple, but configurable nicknaming mod allowing your server's players (and admins) to change their nickname with full formatting support
989,499
Tiquality
Make server lag the problem of the source player.
99,489
Blame (Fabric)
Those gosh darn crashlogs not saying which worldgen feature is crashing!
99,012
Weathering with You
Forecast Minecraft weather with a radar or a hat!
98,579