Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ApolloPlayerTransfer

A Velocity-CTD plugin that automatically transfers legacy Lunar Client players to a fallback proxy when the proxy shuts down, using the Apollo Transfer module.

Why?

Velocity-CTD already evacuates players when a proxy shuts down, but only clients on 1.20.5+ understand the vanilla transfer packet. Everyone on an older protocol (< 1.20.5) is simply disconnected instead of being moved.

ApolloPlayerTransfer fills that gap: for legacy players running Lunar Client, it uses Apollo to redirect them to the exact same fallback proxy Velocity-CTD would have chosen, so a proxy restart no longer drops your legacy players.

Player Handled by
1.20.5+ (any client) Velocity-CTD native transfer packet
< 1.20.5 on Lunar Client ApolloPlayerTransfer (this plugin)
< 1.20.5 not on Lunar Velocity-CTD (disconnected, no transfer is possible)

How it works

  1. The plugin listens for ProxyPreShutdownEvent, which fires before Velocity-CTD disconnects its players.
  2. It asks Velocity-CTD itself for the fallback proxy (VelocityServer#getProxyAddressToUse()), so the destination is resolved with the same logic as the native transfer: your dynamic-proxy-filter (FIRST_FOUND / MOST_EMPTY / LEAST_EMPTY / NONE), self-exclusion via proxy-id, and Redis-based player counts.
  3. For every connected player that is on a legacy protocol and running Lunar Client, it sends an Apollo transfer to that proxy.

The plugin has no configuration file of its own, everything is read from your existing velocity.toml ([proxy-addresses], dynamic-proxy-filter, [redis] proxy-id).

Requirements

  • Velocity-CTD (the fallback selection relies on CTD's [proxy-addresses] machinery, plain Velocity is not supported).
  • Apollo-Velocity installed on the proxy, with the Transfer module enabled.
  • A multi-proxy setup (typically with Redis, required for the MOST_EMPTY / LEAST_EMPTY filters and cross-proxy player counts).
  • Java 21+.

Installation

  1. Drop both plugins into your proxy's plugins/ folder:
    • Apollo-Velocity (download)
    • ApolloPlayerTransfer-x.y.z.jar (from Releases or built from source)
  2. Make sure the Transfer module is enabled in Apollo's configuration.
  3. Configure [proxy-addresses] and dynamic-proxy-filter in your velocity.toml (this is standard Velocity-CTD setup, the plugin just reads it).
  4. Restart the proxy.

Recommended setup for a seamless experience

These two steps are not required for the transfer to happen, but they make it invisible to the player. Both are Velocity-CTD / DNS configuration, no plugin settings involved.

1. Skip the Lunar Client confirmation popup (DNS)

By default, Lunar Client shows a "you are being transferred" confirmation screen. You can auto-accept transfers between your own domains by adding a mc_transfer_accept_from TXT record on your root domain. Lunar queries the target's domain and its parents, so a single record on the apex covers all subdomains:

example.com   TXT   mc_transfer_accept_from=*.example.com,example.com

The client checks the address it is currently connected to against this whitelist; if it matches, the transfer is accepted with no prompt. See the Apollo Transfer docs for details.

Tip: the plugin sends a bare hostname (the default port 25565 is omitted) so Lunar performs its DNS lookup on a clean domain name rather than a host:port string.

2. Avoid "already connected to a remote proxy!" (Velocity-CTD)

When a transferred player reconnects to the fallback proxy faster than the old proxy can release its Redis session, Velocity-CTD rejects the login. Enable session displacement so the fallback proxy kicks the stale session instead of refusing the new one:

kick-existing-players = true
kick-existing-players-check-ip = true

kick-existing-players-check-ip = true restricts displacement to reconnections from the same IP, which is exactly the transfer scenario, safe, and it prevents UUID-spoofing abuse. Apply this on every proxy in the network.

Building

mvn clean package

The jar is produced in target/. The build uses the Lunar Client Maven repository (https://repo.lunarclient.dev) for the apollo-api dependency (provided scope).

Notes & limitations

  • Graceful shutdowns only. Transfers happen on ProxyPreShutdownEvent. A hard crash or power loss runs no code, so those players cannot be transferred by any plugin.
  • MOST_EMPTY / LEAST_EMPTY require Redis. Without it, Velocity-CTD returns no fallback and no transfer occurs, this mirrors CTD's own behavior.
  • Legacy Lunar players only. Modern clients are already handled natively by Velocity-CTD; non-Lunar legacy clients cannot be transferred at all.
  • Relies on a Velocity-CTD internal. The fallback is resolved via reflection on getProxyAddressToUse(). If a future CTD version renames it, the plugin logs a clear warning and performs no transfer (fail-safe) until updated.

License

Licensed under the GNU General Public License v3.0 — see LICENSE.txt.

You are free to use, modify, and fork this plugin, provided any redistributed version stays open source under the same license and keeps the original copyright notice. The ApolloPlayerTransfer name is not covered by the license: please rename your fork if you distribute a modified build.

About

Velocity-CTD plugin that transfers legacy (<1.20.5) Lunar Client players to a fallback proxy on shutdown using Apollo.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages