banner
libxcnya.so

libxcnya.so

Nothing...
telegram
twitter
github
email

A Bukkit map backup and restoration technology based on File IO?

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


Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.