📂
BukkitプラグインでNBTデータをファイル保存する
プラグインを作っている最中にクリックイベントなどがついた本を保存しなければならない機会があり、NBT データごと保存するのに手こずったので備忘録。
注意事項
この記事に記載されている内容を実行し、発生したいかなる問題について執筆者は一切責任を負いません。自己責任でお願いします。
環境
- Minecraft 1.12.2(後述するリフレクションを使用する方法であれば 1.16.5 等でも使用可能)
- CraftBukkit version: Git-Spigot-642f6d2-ab13683
- APIVersion: 1.12.2-R0.1-SNAPSHOT
CraftBukkit が Maven に追加できる場合
Maven への詳しい説明はしませんが、CraftBukkit を何かしらの手段で Maven に追加できる場合はこの方法が楽です。(Spigot)
セーブ
保存は簡単。
- まず、
org.bukkit.inventory.ItemStackからnet.minecraft.server.v1_12_R1.ItemStackに変換する必要があるので、org.bukkit.craftbukkit.v1_12_R1.inventory.CraftItemStackのasNMSCopyメソッドを使う。 - 取得した ItemStack から、
net.minecraft.server.v1_12_R1.NBTTagCompoundを得るためにnmsItem.getTag()を使う。 - 取得した
NBTTagCompoundをtoString()する。 -
toString()で取得できた String が NBT タグ情報。適当に保存する。
保存は YamlConfiguration(FileConfiguration) で保存するなり、FileWriter を使って保存してもよし。
なお、ここで取得した NBT タグ情報は /give のデータタグと同じなので、1.12.2 なら /give @p <item> 1 0 <NBTタグ> で give できる。
ItemStack item = player.getInventory().getItemInMainHand(); // ここでは例としてプレイヤーのメインハンドのアイテムを取得。
net.minecraft.server.v1_12_R1.ItemStack nmsItem = CraftItemStack.asNMSCopy(item); // 1
NBTTagCompound nbttag = nmsItem.getTag(); // 2
String tag = nbttag.toString(); // 3
save(tag); // 4
ロード
- セーブの 4 で保存したものをロードする。
YamlConfiguration.loadConfigurationとかFileReaderとか。 - ロードした NBT タグを保持させる
net.minecraft.server.v1_12_R1.ItemStackを作る。getByIdなのでアイテムの数値 ID を使う。(記入済みの本なら387など) -
MojangsonParserを使って NBT タグをパースする。net.minecraft.server.v1_12_R1.NBTBaseが返る。 - 2 で作った
ItemStackに NBT タグを設定する。この際NBTTagCompoundにキャストする。 -
net.minecraft.server.v1_12_R1.ItemStackからorg.bukkit.inventory.ItemStackに変換するためにorg.bukkit.craftbukkit.v1_12_R1.inventory.CraftItemStackのasBukkitCopyメソッドを使う。
String tag = load(); // 1
net.minecraft.server.v1_12_R1.ItemStack nmsItem = new net.minecraft.server.v1_12_R1.ItemStack(Item.getById(1)); // 2
NBTBase nbtbase = MojangsonParser.parse(tag); // 3
nmsItem.setTag((NBTTagCompound) nbtbase); // 4
ItemStack item = CraftItemStack.asBukkitCopy(nmsItem); // 5
CraftBukkit が Maven に追加できない場合
CraftBukkit を Maven に追加できない場合(複数人開発で BuildTools を強制できないなど)の場合はリフレクションを使って頑張るしかありません。
以下は、私が作った ItemStack から NBT タグを取得できるようにしたライブラリコードの Gist リンクです。
これをプロジェクトに追加し、 NMSManager.getNBT(ItemStack) を実行すれば String で NBT タグの文字列が返ってきます。
Discussion