Homes
Named /home teleports that follow you across the network, with a warmup you can't cheese out of a fight.
On this page 7 sections
Homes let a player save named spots in the world and teleport back to them later. Stand where you want, run /sethome base, and /home base brings you back from anywhere. It’s the kind of feature every server has, so the interesting part isn’t that it exists, it’s the details: the teleport makes you stand still for a moment so you can’t bail out of a fight, your homes live in the shared database so they’re there whichever server you log into, and the chooser works the same whether you’re on Java or on Bedrock through Geyser.
I wrote it as a FyreUtils module, so it’s fully self-contained and drops onto any server running the plugin.
Setting one, and getting back
- Set one with
/sethome <name>. It saves your exact position and facing. No name given? It’s just calledhome. - Go back with
/home <name>. You stand still for a few seconds (the warmup), then you’re there. - No name?
/homeand/homesboth open the chooser, either an inventory menu or a clickable chat list, your pick. - Delete one with
/delhome <name>. - Your cap depends on your rank. Everyone starts with one home. Ranks raise the limit through permissions.
Home names are lowercase letters, numbers and underscores, up to 32 characters. Tab-completion suggests the homes you already own.
The commands
| Command | What it does |
|---|---|
/sethome [name] | Save your position as a home |
/home [name] | Teleport to a home, or open the chooser |
/homes | Open the chooser |
/delhome <name> | Delete a home |
/homes display menu|chat | Switch your chooser between a GUI and a text list |
Every command has an e-prefixed alias (ehome, esethome, edelhome, ehomes) so anyone with Essentials muscle memory, or a server moving off Essentials, doesn’t have to relearn anything.
Admin tooling sits behind /internal homes: list, teleport to, or delete another player’s homes (online or offline), and import homes from an old plugin.
The warmup
When you run /home, you don’t teleport instantly. You have to stand still for a few seconds first (three by default), with a countdown on your action bar. The countdown cancels the moment you:
- move a full block horizontally,
- fall or climb more than about two blocks,
- take any damage, or
- get combat-tagged.
The whole point is that a home teleport shouldn’t be an escape button. If someone’s swinging at you, you can’t just /home out of it. Ranks can be granted a bypass to skip the warmup entirely, and it can be turned off server-wide by setting it to zero.
Limits and edge cases
- Homes are per-player and shared across servers on the same database. Set one on the survival server, it’s waiting for you on the next.
- Names are
a-z,0-9and_, up to 32 characters. - Everyone starts with one home. Ranks raise the cap.
- Some worlds are off-limits. You can’t set a home in a blocked world, and an existing home in one gets dropped the next time your homes load.
- You can’t teleport home while combat-tagged, and getting tagged mid-warmup cancels it (needs PvPManager; it just skips the check if that isn’t installed).
- You choose how the chooser looks with
/homes display menuor/homes display chat.
Why players want it
- Getting around without wasting time. The bread and butter: hop between your base, your farm, and spawn.
- Not dying to the walk back. Bank a home before a risky trip so a death doesn’t cost you the trek out again.
- Selling ranks. More home slots is a clean, non-pay-to-win perk to hang on a rank ladder.
- A soft landing when switching plugins. The importer and the Essentials-style aliases mean players barely notice the change.
Architecture
Every module stands on its own
Homes is a single FyreModule. It brings its own config, language file, database schema, commands and PlaceholderAPI values, and it’s handed everything it needs (database, scheduler, Bedrock form support) when it’s enabled. It can be turned on or off without touching any other part of FyreUtils. That boundary is what keeps a plugin this size from turning into a tangle.
The database never touches the game thread
Every read and write goes through a DAO that runs on its own dedicated background thread and hands back a CompletableFuture. The game threads never block on SQL. In front of that sits an in-memory cache: a player’s homes load when they join and are dropped when they leave, so the common paths (opening the menu, teleporting) are just a map lookup with no database round-trip at all. Writes are write-through: the cache updates immediately and the database catches up in the background.
It’s also built for Folia, where there’s no single main thread. Teleports and sounds are dispatched onto the region thread that actually owns the player, and the teleport itself is async, so nothing stalls a region tick.
Homes follow you across servers
The storage layer is deliberately backend-agnostic. The same code runs on SQLite for a single server or MariaDB for a network, and the only thing that changes between them is the exact upsert syntax (ON CONFLICT versus ON DUPLICATE KEY), which the DAO picks based on the configured storage type. Point a fleet of servers at one MariaDB and everyone’s homes come with them.
I kept this honest rather than clever: homes load when you join a server, not through a live cross-server sync. A player is really only ever playing on one server at a time, so loading on join covers it without paying for a pub/sub invalidation channel and the headache of merging edits made in two places at once.
The schema versions itself
The tables aren’t created with a single blind CREATE TABLE. Homes declares a target schema version and a list of migrations, and on startup the plugin applies whatever steps are missing to get there. Version one created the homes table; version two added the display-preference table. Adding a column or a table later is just another numbered step, and every server catches up to the current version on its own the next time it boots.
Limits ride on permissions, not a config map
A player’s home cap is read straight off their permissions: the highest fyreutils.homes.max.<n> node they’ve been granted wins, falling back to the configured default when they have none. That means the cap plugs directly into LuckPerms and rank inheritance without FyreUtils needing to know a single thing about what ranks exist. A donor rank that inherits a lower one automatically keeps the bigger number.
One chooser, Java and Bedrock alike
Java players get a paginated inventory menu built with triumph-gui; Bedrock players (through Geyser) get a native form instead. Both are built from the same config file, and, more importantly, both route their clicks through the exact same teleportToHome path that /home <name> uses. So the warmup, the combat check, the sounds and the messages can never drift apart between “typed the command,” “clicked the menu,” and “tapped the Bedrock form.” The menu’s whole layout (materials, slots, lore, even the Bedrock button text) lives in a hot-reloadable YAML file, and any text pulled from a home name is escaped before it’s rendered so a clever name can’t inject formatting.
Coming from another plugin
Servers rarely start fresh, so there’s a migration path in from ModernHome. /internal homes migrate reads its database (MySQL or SQLite), and does the fiddly work of making that data actually fit: it de-duplicates home names per player (two homes both called “home” become home and home2), sanitizes them to the allowed character set, and re-centers the old integer block coordinates by half a block so players land on the middle of the block instead of clipping a corner. The whole import runs as one batched transaction, and online players get their homes reloaded the moment it finishes.
Trade-offs
- Cache-on-join instead of live sync. Set a home on one server during a session and it won’t appear on another server you’re simultaneously logged into until you rejoin it. In practice nobody plays two servers at once, and this bought a much simpler, race-free storage layer.
- The warmup is strict. It cancels on any damage, including a stray bit of fall damage or a friendly hit. That’s the price of it being a reliable anti-escape mechanism; a warmup you can tank a hit through isn’t really a warmup.
- One DAO thread. All homes database work is serialized onto a single thread. It trades raw parallelism for dead-simple ordering (a delete can never race a save for the same player), which is the right call for something as write-light as homes. If it ever got hot, it’s an isolated piece to swap.
- Permission-number limits over a group map. Reading the cap off permission nodes is less discoverable than a plain
rank: limitlist in a config, but it means the whole thing composes with permission inheritance for free and never has to be kept in sync with the server’s rank setup.