banner
libxcnya.so

libxcnya.so

Nothing...
telegram
twitter
github
email

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

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


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