banner
libxcnya.so

libxcnya.so

Nothing...
telegram
twitter
github
email

File IO に基づく Bukkit マップバックアップおよび復元技術とは?

前景需要#

最近 Minecraft サーバープラグイン開発を研究していて、サーバー再起動時にマップをリセットする必要があるシーンがありました。
探してみたところ、満足のいく既存のプラグインは見当たらなかったので、自分で作ることにしました。

探索#

最初は直接Slime World Managerを使おうと思ったのですが、リポジトリを見たら

このリポジトリは 2025 年 4 月 21 日にオーナーによってアーカイブされました。現在は読み取り専用です。

うーん、でもちょうどその派生フォークを見つけました。
https://github.com/InfernalSuite/AdvancedSlimePaper

とても役に立ちそうですが、そのプラグイン版は私のサーバー(Paper 1.20.4 + Java 24)をあまり好まないようです。
とにかくクラスが見つからないとエラーが出ます。

でも、彼らは Paper を魔改造するためのブランチを立ち上げたようで、私はあまり好きではありません。
仕方がないので、直接土方法を使うことにしました。

実現#

私たちは Bukkit API がonEnableonDisableを提供していることを知っています。
最初はonEnableの時にバックアップと復元を一気に行おうと思ったのですが、Bukkit のプラグインの読み込みはワールドの後に行われます。
さらに、Bukkit API を通じてデフォルトのワールド(つまりworldworld_netherworld_end)を直接アンロードすることはできません。

通常のBukkit.unloadWorld(Bukkit.getWorld("world"), false);ではアンロードできません。エラーが出ない場合でも(実際には無視されます)。
したがって、onEnableの時に復元することはできません。

では、より良い位置はないのでしょうか?賢いあなたなら思いついたはずです。それはonDisableの場所です。
ですので、onEnableの時にマップをバックアップし、毎回onDisableの時にコピーし戻すことができます。

大体以下のようになります。

    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;
            }
        });
    }

そしてonDisableの場所で呼び出すだけです。
え?ワールドがロードされた後にsession.lockがロックされてコピーできない?それならスキップすればいいじゃないですか!

     @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;
     }

これでこのロジックを書くことができるようになったので、さっそくプラグインを書いてみてください!

注意事項#

この方法はサーバーをきちんとシャットダウンしない人には優しくありません(つまりCtrl+C/stopを使わない人)。
そのため、onDisableをトリガーできず、復元イベントを発生させることができません(ただし、心配しないでください。次回正常にシャットダウンすれば復元できます)。

copyWorldを呼び出す際は、個人的には同期を保つべきだと思います(Bukkit は同期的にプラグインをアンロードするのですから、レースコンディションを心配する必要はありません)。
アーカイブが非常に大きいサーバーでは、完全にバックアップ / 復元が完了するまでに数十秒かかることがあります(したがって、あなたのハードディスクの IO が試されることになります!)。

もちろん、以上は最悪の解決策ですが、最も効果的でもあります。

END#

ホイールはすでに作成しましたので、君子協定に従って自由にスキッドしてください。
https://github.com/NyaStudio/MapBackup

この記事は Mix Space によって xLog に同期更新されています。
元のリンクは https://blog.xcnya.cn/posts/technology/128.html


読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。