Requirements#
Recently, I have been researching Minecraft server plugin development, and there is a scenario that requires resetting the map when the server restarts.
After searching around, it seems that there aren't any satisfactory existing plugins, 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 a derived fork of it
https://github.com/InfernalSuite/AdvancedSlimePaper
It looks very useful, but its plugin version seems to not like my server (Paper 1.20.4 + Java 24)
Anyway, it reported missing classes.
However, it seems they have created a branch to heavily modify Paper, which I am not very fond of.
There was no other way, so I resorted to 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's plugin loading occurs 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 (in fact, it gets ignored).
So we cannot restore in onEnable
.
Is there a better place? I believe you clever ones have thought of it, which is in onDisable
.
So we can back up the map in onEnable
and copy it back during each onDisable
.
It looks something like this:
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 cannot 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;
}
Then you already know how to write this logic, go ahead and write a plugin!
Notes#
This method is not friendly for those who do not properly shut down their servers (referring to those who do not use Ctrl+C
or /stop
).
Because that way, onDisable
cannot be triggered, so the restoration 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 have 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