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


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