Requirements#
Recently, I've been researching Minecraft server plugin development, and there's a scenario where I need to reset the map when the server restarts.
After searching around, it seems there aren't any existing plugins that meet my needs, so I decided to write one myself.
Exploration#
At first, I wanted to use Slime World Manager
directly, but upon checking the repository
This repository was archived by the owner on Apr 21, 2025. It is now read-only.
Uh oh, but I happened to see one of its derivative forks
https://github.com/InfernalSuite/AdvancedSlimePaper
It looks very useful, but its plugin version doesn't seem to like my server (Paper 1.20.4 + Java 24)
It just reports missing classes.
However, it seems they have created a branch to heavily modify Paper, which I'm not a fan of.
No choice but to use a more manual method.
Implementation#
We all know that the Bukkit API provides onEnable
and onDisable
.
Originally, I thought about backing up and restoring everything directly in onEnable
, but Bukkit loads plugins after the world.
Moreover, we cannot directly unload the default worlds (i.e., world
, world_nether
, world_end
) through the Bukkit API.
Using the normal Bukkit.unloadWorld(Bukkit.getWorld("world"), false);
cannot unload it, even if it doesn't throw an error (it is actually ignored).
So we cannot restore in onEnable
.
Is there a better place? I'm sure you clever folks have thought of it, and that is in onDisable
.
So we can back up the map in onEnable
and copy it back during each onDisable
.
Roughly as follows:
private void copyWorld(Path source, Path target) throws IOException {
Files.walkFileTree(source, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
Path targetDir = target.resolve(source.relativize(dir));
Files.createDirectories(targetDir);
return FileVisitResult.CONTINUE;
}
});
}
Then just call it in onDisable
.
Hey, you ask me if the session.lock
is locked after the world is loaded and can't be copied? Can't we just skip it?
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
if (!file.getFileName().toString().endsWith(".lock")) {
Files.copy(file, target.resolve(source.relativize(file)), StandardCopyOption.REPLACE_EXISTING);
}
return FileVisitResult.CONTINUE;
}
And now you already know how to write this logic, go ahead and write a plugin!
Notes#
This method is not friendly for those who don't properly shut down their servers (referring to those who don't use Ctrl+C
or /stop
).
Because that way, onDisable
cannot be triggered, so the restore event cannot be triggered (but don't worry, you can restore it next time you shut down properly).
I personally believe that calling copyWorld
should be synchronous (isn't Bukkit synchronously unloading plugins? So there shouldn't be a race condition).
For servers with excessively large archives, it may take several tens of seconds to completely back up/restore (so it will test your hard disk IO!).
Of course, the above is just the worst solution, but it is also the most effective.
END#
I've already built the wheel, feel free to skid under the gentleman's agreement.
https://github.com/NyaStudio/MapBackup
This article is synchronized and updated by Mix Space to xLog.
The original link is https://blog.xcnya.cn/posts/technology/128.html