# Auth-Limbo [![Build](https://github.com/s8n-ru/auth-limbo/actions/workflows/build.yml/badge.svg)](https://github.com/s8n-ru/auth-limbo/actions/workflows/build.yml) [![License: AGPL--3.0](https://img.shields.io/badge/license-AGPL--3.0-lightgrey.svg)](LICENSE) [![Paper](https://img.shields.io/badge/Paper-1.21.11%2B-lightgrey.svg)](https://papermc.io/) [![Java](https://img.shields.io/badge/Java-21%2B-lightgrey.svg)](https://adoptium.net/) A small Paper plugin I wrote because AuthMe's post-login teleport kept dumping my players at world spawn instead of where they last were. Tried every config flag, removed Multiverse, tried forks. Nothing fixed it. So this does. Two jobs: hosts a void `auth_limbo` world (so I could stop running Multiverse-Core for one world I never visited) and replaces AuthMe's broken post-login teleport with one that actually works. --- ## The problem Friend logs in, types `/login`, AuthMe is supposed to teleport them back to where they were. They land at world spawn instead. Every time. Spent a day chasing this. Disabled Multiverse-Core. Disabled GrimAC. Disabled UnexpectedSpawn. Disabled Essentials. Even ran with just AuthMe loaded and the bug stayed. Eventually traced it to [PaperMC/Paper#4085](https://github.com/PaperMC/Paper/issues/4085) โ€” `Player#teleportAsync` resolves before the destination chunk loads, Paper's safety logic snaps the player to the nearest loaded chunk, and that chunk is world spawn. AuthMe's `teleportOnLogin` flow walks right into it. Filed a mental bug report against AuthMe, decided writing my own listener was faster than waiting on a fork. --- ## What it does Two things and that's it. 1. **Void `auth_limbo` world.** A custom `ChunkGenerator` produces empty chunks. A 5x5 barrier platform sits under spawn so unauth players don't fall forever. No daylight cycle, no weather, no mob spawning, no PvP. AuthMe uses it as the pre-auth limbo. No Multiverse-Core needed. 2. **Authoritative restore-teleport.** A `LoginEvent` listener at `MONITOR` priority fires *after* AuthMe's broken teleport, reads the saved quit-location straight out of `plugins/AuthMe/authme.db`, pins the destination chunk with `Chunk#addPluginChunkTicket`, then chains `World#getChunkAtAsyncUrgently` into an authoritative `Player#teleportAsync`. Same pattern [PaperLib's `AsyncTeleportPaper`](https://github.com/PaperMC/PaperLib) uses, just narrower. That's the whole surface area. No password handling, no permissions beyond admin commands, no register flow, no chat formatting. AuthMe owns all of that. --- ## Install 1. Download `AuthLimbo-1.0.0.jar` from the [Releases page](https://github.com/s8n-ru/auth-limbo/releases). 2. Drop it in your `plugins/` directory. 3. Restart the server. Don't `/reload` โ€” it'll break things. Just restart. AuthMe-ReReloaded is a **hard dependency**. The plugin refuses to load without it. For the `itzg/minecraft-server` Docker image, see [`docs/installation.md`](docs/installation.md) for the `PLUGINS:` environment-variable form. --- ## Configuration Defaults work. `plugins/AuthLimbo/config.yml` is created on first start. If you want to tweak: ```yaml limbo: world: auth_limbo # Bukkit world name spawn-x: 0.5 spawn-y: 128.0 spawn-z: 0.5 build-platform: true # 5x5 barrier under spawn platform-y: 127 authme: db-path: plugins/AuthMe/authme.db teleport-delay-ticks: 10 # ticks to wait after LoginEvent preload-chunks: true # forceload chunk before teleport debug: false # verbose logging ``` Full reference in [`docs/configuration.md`](docs/configuration.md). --- ## Commands | Command | Permission | Effect | |----------------------------|---------------------|-----------------------------------------------------| | `/authlimbo reload` | `authlimbo.admin` | Reload `config.yml`. | | `/authlimbo tp ` | `authlimbo.admin` | Manually teleport a player to their saved location. | Aliases: `/alimbo`. --- ## What I tested | Component | Status | Notes | |-----------------------------------|----------|----------------------------------------| | Paper 1.21.11 | Yes | Primary target. | | Purpur 1.21.11 | Yes | Same Paper API surface. | | Folia | Unknown | Untested. Login event threading may differ. | | AuthMe-ReReloaded (HaHaWTH b49) | Yes | Verified on production. | | AuthMe-ReReloaded other 5.x forks | Untested | Schema is the same, should work. | | Multiverse-Core | Untested | Not required. Possible teleport-intercept conflict โ€” see [`docs/compatibility.md`](docs/compatibility.md). | --- ## Build from source ```bash mvn clean package ``` Shaded jar lands at `target/AuthLimbo-1.0.0.jar`. Java 21, Maven 3.9. Standard. The `lib/AuthMe-5.6.0-FORK-Universal.jar` is referenced as a `system`-scope dep so the build doesn't need any private repo credentials. --- ## Why not just use Multiverse-Core for the void world? Multiverse-Core does a dozen things. I needed one void world. Also Multiverse intercepts teleports for portals and respawn, which is the exact contention I was running from. This plugin is ~400 lines and only manages the one world AuthMe needs. If you already run Multiverse for legit reasons, ignore the limbo manager and just use the teleport fix. --- ## License AGPL-3.0. See [`LICENSE`](LICENSE). If you run a modified version of this plugin on a Minecraft server that players connect to over the network, AGPLv3 ยง13 requires you to offer the modified source to those players. Unmodified use carries no obligation beyond GPLv3 (no source-sharing required). --- ## Author Built by [s8n-ru](https://github.com/s8n-ru). If this fixes your headache too, cool. If not, file an issue, I'll look.