はじめに
この記事では、プラグイン導入における
ユーザーのデータ管理の手段を考察していきます。
PocketMine-MP(以下PMMP)利用者に向けた記事です。
ちなみに今回書く例は、
API4.0.0以降のPMMPでは使用できないのでご注意ください。
4.0.0でも恐らく書き方を変えれば(恐らく)使えますので
(気が向いたら)API4.0.0向けも書こうと思います。
私はSteadfast2を推します。
目的の説明
タイトルの player.datとは、
players/{プレイヤー名}.dat
を指すこととします。
PMMPを触ったことがある方ならわかると思いますが、
プレイヤーデータを保存しているファイルとなります。
一般的には リスポーン地点, ログアウト時の座標, インベントリ, 体力...等
を保存しています。
ではここでプラグインの話に移ります。
あなたのプラグインでは、データはどのように管理しているでしょう。
恐らくほとんどは、plugin_data/プラグイン名/○○.yml
や.json
, .db
等で保存し、
管理をしていることだと思います。
レガシーを有効にしてるのであればplugins/プラグイン名/○○
にありますね。
では、タイトル通り、player.datにプラグインのデータをぶち込み、
データ管理をすることと、その考察をしていきます。
書き方
先程さらっと player.datに保存することについて触れましたが、
どんな感じなコードになるのか分からない方もいると思います。
簡単な例を使って書いてみます。
例1:プレイヤーに数字のデータを付けてみる
よくプラグインの保存で使われるyaml形式だと
MyDeacy: 53
のようになります。
こういう保存ファイルはよく見ると思います。
で、player.datに保存する方法はこちら。
//$playerはPlayerオブジェクトとする
$nbt = $player->namedtag;
$nbt->setTag(new CompoundTag("Sample",
[
new IntTag("num", 53)
]
));
一つ一つ解説していきます。
$player->namedtag
で プレイヤーに紐づけられているNBTデータを取得します。
ここではplayer.datの中身が入っています。
$nbt->setTag(new CompoundTag("Sample"
先ほど取得したNBTデータの中には gamemode や health などの項目があります。
目的の説明で述べたようなものが入っています。
そこに、Sample という項目を作成します。
フォルダを作成するイメージです。
[new IntTag("num", 53)]
Int型のデータを入れます。
"num" と書いてあるのはキーです。
Configからデータを読むとき、get("num")
とするイメージです。
このデータは、player.datが保存されるとき
勝手に書き込まれます。
また、CompoundTagの中身は配列で複数入れることができます。
次の例で簡単に解説します。
例2:複数のデータを入れてみる
先程はInt型の1つのデータのみでしたが、前述の通り
配列で複数データを入れることができます。
そして、データ型ごとにTagがあり、
様々な型のデータを扱うことができます。
詳しくは
https://github.com/pmmp/NBT/tree/master/src/tag
では例
$nbt->setTag(new CompoundTag("Sample",
[
new IntTag("num", 53),
new StringTag("brain", "odabutsu")
]
));
このように配列で複数入れることができます。
簡単ですね。
例3:取得する
いくら保存方法が分かっても取得する方法が分からないと
意味がありません。
getter/setterの概念に慣れている方ならなんとなくわかりますよね。
例えば例2のデータを取得するとなるとこのようになります。
$nbt = $player->namedtag->getCompoundTag("Sample");
$num = $nbt->getInt("num");
$brain = $nbt->getString("brain");
簡単ですね。
例1,2が分かればなんてことないと思います。
よって解説は省きます。
メリットとデメリットについて
まず、この手段を用いる利点としては、プレイヤーデータに直接紐づけられるので
ファイルが多く生成されたり、
一つのファイルにプレイヤーごとのデータが大量に入ることが少なくなり、
見かけ上 楽になることです。
いつものプレイヤーデータのセーブに少し+αされるのみなので
IOの非同期云々を考慮する必要が(そこまで)出てくることはないです。
Playerオブジェクトさえあれば 簡単にデータを取ることができ、
プラグインでの利用としては扱いやすいのではないかなと思います。
デメリットは、プレイヤー個別にデータを持つことになるので
集計などでデータをリスト化することが困難になるのが不利な部分だと思います。
また、例を見てもらった通り、データを編集するたびにインスタンスを生成しています。
滅多にないとは思いますが一度に扱うデータが極端に膨大になりすぎると
処理が適切に追えるようになるのか 少し心配な面もあります。
まとめるとこんな感じ
メリット
・プレイヤーオブジェクトがあれば直接データを取得、編集ができ便利
・複数のプラグインで同時に使えるので 上手く使うとファイルが大量に生成されることがなくなる
・保存はPMMPの処理が勝手に行ってくれるため配慮は最小限で済む
デメリット
・データのリスト化が困難
・超膨大なデータを扱うときの配慮が必要
・オフラインプレイヤーへの配慮も必要
これ以上にもメリットデメリット双方挙げられますが
代表的なのはこんなものだと思います。
私がたどり着いた結論
**"リスト化する必要のなく、頻繁に読み書きを行わないデータ"**ならば
player.datへの保存を採用する機会は十分にあるのではないかなと考えます。
リスト化すると便利な所持金やレベルのようなデータに関しては
素直にJSON, SQLite等を使うべきですね。
ということをおよそ1か月前に考え、
サンプルとしてログインプラグインを作りました。
宜しければ評価をお願いします。
https://github.com/MyDeacy/PMLogin
おわりに
拙い文章でしたが最後まで読んでいただきありがとうございます。
結論で述べた通り、デメリットはあるもののきちんとした使用価値を見出せました。
このような使い方も悪くはないと思います。
あなたはどうお考えでしょうか。