Skip to Content
MoripaFishing

WorldLifecycle

MoripaFishing-Integration-WorldLifecycle

Core (MoripaFishing) に依存する公式 Integration。以下の機能を提供します。

  • 環境の適用 (EnvironmentApplier): Core が決めた時刻・ゲームルール ADVANCE_TIME・ワールドボーダー・スポーン地点を Bukkit ワールドへ適用
  • ワールドの作成・アンロード (BukkitWorldLifecycle): ジェネレーター定義を使った釣りワールドの作成と、削除時のアンロード
  • プレイヤーの 参加時テレポート: 参加したプレイヤーを釣りワールドのスポーン地点へ移動

Core 自体は Bukkit ワールドへ一切書き込みません。本 Integration と Weather を 導入しない限り、ワールドの時刻・ゲームルール・スポーン・ボーダーは変更されません。 仕組みの全体像は Integration とは を参照してください。

導入

  1. plugins/ に Core とリリースの MoripaFishing-world-lifecycle-<version>.jar を配置する (プラグイン名は MoripaFishing-Integration-WorldLifecycle)。

  2. サーバーを起動する。本 Integration は Core に必須依存しているため (paper-plugin.yml の server("MoripaFishing", Load.BEFORE, required = true))、Core の後にロードされます。 Core が無いと本 Integration は起動しません。

  3. 起動時に次のログが出ます。

    [MoripaFishing-Integration-WorldLifecycle] MoripaFishing-Integration-WorldLifecycle enabled (generators: [normal, terra, void]).

有効化時に WorldLifecycle と WorldStateApplier を ServicesManager に登録します。 登録は本 Integration の無効化時に自動で解除されます。

環境の適用

EnvironmentApplier は Core から届く WorldState のうち、次の項目だけを適用します。

項目適用内容
doDaylightCycleゲームルール ADVANCE_TIME に毎回書き込む
timenull でなければワールド時刻に設定する。null なら時刻に触れない
bordernull でなければワールドボーダーの中心とサイズを設定する。null ならボーダーに触れない
spawnワールドのスポーン地点がブロック座標または向き (yaw) で異なる場合だけ設定する (Paper はスポーンをブロック単位で保持するため)

時刻の計算 (実時刻同期・固定時刻) とゲームルールの値は Core が決めます。詳細は 気候の設定 を参照してください。 ボーダーを他のプラグインで管理したい場合は、ワールド設定の world.border を null にします (ワールド設定)。

ワールドの作成とアンロード

BukkitWorldLifecycle は Core の WorldLifecycle SPI を実装します。

  • createWorld(worldKey, generatorId): ジェネレーター定義から WorldCreator を組み立てて Bukkit.createWorld を呼びます。 同じキーのワールドが既にある場合やジェネレーター ID が不明な場合は何もせず false を返します。
  • unloadWorld(worldKey): ワールドを保存せずにアンロードします。未ロードの場合やアンロードに失敗した場合 (プレイヤーが残っているなど) は false を返します。
  • getGeneratorIds(): 読み込んだジェネレーター ID の一覧を返します。

Core は次の場面でこれらを呼びます。

  • サーバー起動後 (ServerLoadEvent): 定義済みで未ロードの管理ワールドを、ワールド設定の world.generator で作成する (外部ワールドは作成しない)
  • /mf world create <id> <generator>: 新しい釣りワールドを定義して作成する。補完候補は getGeneratorIds() から供給される
  • /mf world delete <world>: ロード済みの釣りワールドをアンロードしてから定義を削除する

ジェネレーター定義

ジェネレーター定義は本 Integration の内部形式で、plugins/MoripaFishing-Integration-WorldLifecycle/generator/ に置きます。 初回起動時に同梱の terra.json / void.json / normal.json が書き出されます。

generator/terra.json
{
  "id": "terra",
  "generator": "Terra:OVERWORLD",
  "type": null,
  "biomeProvider": null,
  "generatorSetting": null
}
generator/void.json
{
  "id": "void",
  "generator": null,
  "type": "FLAT",
  "biomeProvider": null,
  "generatorSetting": "{\"layers\": [{\"block\": \"air\", \"height\": 1}], \"biome\":\"plains\"}"
}

normal.json は id を除く全フィールドが null で、Bukkit の既定生成にそのまま任せる定義です。

フィールド型説明
idstringジェネレーター ID。ワールド設定の world.generator から参照される
generatorstring?WorldCreator.generator() に渡される文字列 (プラグイン名
)
typestring?WorldType 名 (NORMAL / FLAT / LARGE_BIOMES / AMPLIFIED)
biomeProviderstring?全座標に同じバイオームを返す固定バイオーム名 (例: minecraft:plains)
generatorSettingstring?ジェネレーター設定文字列

ディレクトリ内の JSON ファイルはすべて読み込まれるため、任意の JSON を置くだけでジェネレーターを追加できます。 不正なファイルは警告を出して読み飛ばします。詳細は ジェネレーター設定 を参照してください。

参加時テレポート

プレイヤーがサーバーに参加した際、釣りワールドのスポーン地点へ自動でテレポートします。

テレポート先は参加のたびに決めます。管理ワールドでは Core の公開 API から取得したワールド設定の world.spawn、外部ワールド では Bukkit ワールドのスポーン地点を使います。

設定は plugins/MoripaFishing-Integration-WorldLifecycle/join-teleport.yml に置きます (初回起動時に既定値が書き出されます)。

join-teleport.yml
enabled: true
worldId: null
onlyFirstJoin: false
フィールド型説明
enabledboolean参加時テレポート機能の有効/無効 (デフォルト: true)
worldIdstring?テレポート先の釣りワールドID。null の場合は Core のデフォルトワールドを使用
onlyFirstJoinbooleantrue の場合、サーバーに初めて参加したプレイヤーにのみテレポートを行う (デフォルト: false)

テレポートの直前に AnglerJoinTeleportEvent が発火します。 キャンセルするとテレポートは行われず、setDestination で移動先を差し替えられます。

設定どおりに動かない場合は、次の条件に当てはまっていないか確認してください。

  • worldId が未定義の場合は何もしません (設定ミスの典型例)
  • 対象の Bukkit ワールドがロードされていない場合も何もしません
  • join-teleport.yml の読み込みに失敗した場合は警告を出して既定値で続行します
  • enabled が false の場合はリスナー自体を登録しません

独自の WorldStateApplier を書く

本 Integration と同じ仕組みで、Core が決めた状態を独自の方法で適用できます。 WorldStateApplier は登録された全件が呼ばれるため、公式 Integration と併用できます。

class DaylightOnlyApplier : WorldStateApplier {
    override fun apply(state: WorldState) {
        // メインスレッドで呼ばれる。未ロードのワールドは無視する
        val world = Bukkit.getWorld(state.worldKey) ?: return
        world.setGameRule(GameRules.ADVANCE_TIME, state.doDaylightCycle)
        // null は「変更しない」
        state.time?.let { world.time = it }
    }
}

class MyPlugin : JavaPlugin() {
    override fun onEnable() {
        server.servicesManager.register(
            WorldStateApplier::class.java,
            DaylightOnlyApplier(),
            this,
            ServicePriority.Normal,
        )
    }
}

依存の宣言・型の制約・WorldState の契約は Integration とは を参照してください。

On this page