Source: https://oliviercouthaud.com/resetworld · Status: Shipped · 2026 · Tags: Java, Paper, Minecraft # ResetWorld A Minecraft server plugin for shared hardcore: when anyone dies, everyone is wiped and the whole map is put back from a template. ## The problem I built this for friends. We were going to run hardcore challenges on a shared server, and the tedious part is the reset after each run. Hardcore Minecraft gives you one life, and on a server I wanted that life shared, so a single death ends the run for everyone. Doing that by hand means stopping the server, deleting the world folders, copying a fresh map back and clearing every player's inventory, XP and advancements, every time. I wanted a custom map rather than a random seed, so the plugin keeps a template of it and restores that. It got used for a Hardcore Shared Health Skyblock challenge that ran for roughly three days. That ended when everyone went into the End and the dragon's breath hit the confined spawn platform, damaging all of us at once. Everyone died in under half a second, and everyone rage-quit afterwards. The plugin ignores a second death during the countdown, so a pile of deaths at once only starts one reset. ## How it works It's a Paper plugin in Java 21, about 690 lines of Java and config. Four classes: ResetWorldPlugin starts everything, HardcoreManager owns the worlds, the run counter and the reset cycle, HardcoreListener handles the game events, and ResetCommand is the /resetworld command, which is op only. **What is Paper?** Paper is a widely used Minecraft server program, a faster fork of Spigot. A plugin is a Java jar you drop into the server's plugins/ folder. It can hook into events such as a player dying, joining or walking through a portal, and it can load, unload and create worlds. The plugin keeps three worlds, hardcore, hardcore_nether and hardcore_the_end, and treats the server's normal world as the lobby. At startup it refuses to run if the hardcore world has the same name as the lobby, or if there is no template. If the hardcore folder already exists, the current run carries on across server restarts, and the template is only copied when there is nothing there. Figure: Diagram. The reset cycle as HardcoreManager runs it. A death in the hardcore worlds, or an op running /resetworld, starts it. Everything except the delete and copy step runs on the server's main thread. Click through one reset below. Pick a step in the diagram or from the buttons, or use Back and Next. ### One reset, step by step - **Death.** Someone dies in one of the three hardcore worlds. The plugin takes the vanilla death message and broadcasts it in red, followed by how long the run lasted and when the reset will happen. Everyone else who is alive in those worlds is switched to spectator. The player who died is respawned straight away, so nobody sits at the death screen. A death in the lobby does nothing, and a second death during the countdown doesn't start a second reset. - **Countdown.** Ten seconds by default, set by countdown-seconds in the config. Once a second everybody gets a title that reads "World resetting" with "in N..." underneath. It's a plain timer on the main thread. - **Wipe and unload.** Everyone alive in the hardcore worlds is wiped and teleported to the lobby in adventure mode. Then the end, the nether and the overworld are unloaded, in that order. If any of them refuses, it tries again a second later, up to five times, and then stops and tells the ops. - **Delete and copy.** The only step off the main thread. The three world folders are deleted, each delete tried up to ten times, 500 ms apart. Then the template is copied in without uid.dat and session.lock, with the nether and end data split into their own folders. - **New run.** The run counter goes up and is saved to data.yml with the start time. The three worlds are loaded with difficulty set to hard and the hardcore flag on. Every online player who is alive is wiped again, put in survival at the map's spawn, and the server says "Run #N has started. Don't die." **Why does the copying run off the main thread?** The server does all its game logic on one main thread, in ticks of 50 ms, twenty a second. If that thread spends a few seconds copying a big map, every player freezes for those seconds. So the slow disk work goes to a separate thread, and the plugin only comes back to the main thread to load the worlds and move people once the files are in place. Some details exist because the obvious version would break. Players who were offline during a reset carry the run number in their saved data, and on join a mismatch means they get wiped too. Someone who logged out on the death screen is respawned when they come back. Anyone who joins mid-reset is sent to the lobby. And a wipe clears more than the inventory: the ender chest, the item on the cursor, XP, effects, health and hunger, fire and freeze, the bed spawn, the phantom timer, and every advancement. Figure: Diagram. Where a player is during one reset. A player in the run is wiped twice: once when they are moved out, once when they come back in. The three worlds also have to be built from the template. A singleplayer save keeps its nether and end inside the same folder, in DIM-1 and DIM1, while Paper uses separate world folders, so the plugin splits them on the way in. If you give it separate templates/world_nether and templates/world_the_end folders, those win. If there are none, the nether and end are generated fresh from the overworld's seed. **What are DIM-1 and DIM1, and why skip uid.dat?** In a singleplayer save the overworld sits in the main folder and the nether and end are subfolders called DIM-1 and DIM1. A server wants each one as its own world, so the copy step puts them in hardcore_nether/DIM-1 and hardcore_the_end/DIM1. Each world folder also has a uid.dat holding its unique ID. Copying it every run would give every run the same world ID, so it's left out and the server makes a new one, along with session.lock. Figure: Diagram. Where the template ends up. The lobby is whatever level-name is set to in server.properties, so it's best to keep it small. ## Portals A hardcore overworld that sent its portals to the lobby's nether would be no good, so portals are rerouted by hand. Going into the nether, X and Z are divided by 8; coming out, they are multiplied by 8. If you stand in a portal at X 800, Z -240 in the hardcore overworld, you arrive near X 100, Z -30 in the hardcore nether, and the game looks for an existing portal within 16 blocks of that spot before it builds a new one. Coming back the other way it looks within 128. ### Where does a portal send you Try your own numbers: enter the X and Z you are standing at when you step into the portal. Height is clamped to the world's limits. The end works differently. Going into the end always puts you on a platform at X 100.5, Y 49, Z 0.5, and the plugin rebuilds the 5x5 obsidian square vanilla makes there, with air cleared above it. Leaving the end sends you to your bed if it is in a hardcore world, and to the map spawn if not. The respawn handler does the same if you jump into the end exit portal with no bed set, where vanilla would have sent you to the lobby. world-name: hardcore countdown-seconds: 10 ## What I ran into Windows can keep region files open for a moment after a world is unloaded, so a delete straight after unloading can be refused. That's why the delete tries up to ten times, 500 ms apart. Unloading can also refuse, which is why that retries five times, a second apart. After that it stops, tells the ops in chat to run /resetworld again, and leaves everyone in the lobby. If the delete or copy does not complete after the hardcore worlds have already been unloaded, nothing loads them again until an op runs the command or the server is restarted. A player who logs in during that gap gets an error instead of a friendly message, because joining does not yet handle a missing world. Handling that state, and adding automated tests, are the natural next pieces. ## What's next The plugin is shipped and did its job for the challenge. Possible additions: a per-run statistics file, since today it keeps only the run number and start time and nothing remembers how long past runs lasted or what killed everyone; a setting for difficulty, which is forced to hard; and handling for the missing-world state above. A template with no nether or end gets a freshly generated one. - **Stack**: Java 21, Paper API 1.21.11, Maven - **Size**: About 690 lines of Java and config - **Status**: Shipped - **Code**: Not public