Minecraft 1.13 以降に追加された data
コマンドを用いると、チェストの中身を取得することができます。今回は /data get block <チェストの座標> Items
というコマンドを用いて、チェスト内のアイテムを取得してみます。
目標
Blazor アプリで任意の座標に設置されたチェストの中身(アイテム)を取得して、表として表示する!
実行環境
- Windows 10
- .NET Core 5.0.100
- Visual Studio 2019 Version 16.8.2
- Minecraft 1.16.3 (バニラ版, RCON許可済みサーバ)
- CoreRCON 5.0.0 (NuGet)
1. Blazor アプリの作成
プロジェクト作成と基本的な書き方はこちらを参照してください。CoreRCONの導入方法もここに書いています。
まずはチェストアイテムを表示するためのページを作成します。ソリューションエクスプローラ―の Pages
フォルダで右クリックして 追加
から 新しい Razor コンポーネント
を追加してください。名前は自由に決めてください。自分は ChestItemsView.razor
としました。できたら中身をこのように書いてください。はてなブログの都合上、ソースコードは区別していますが、同じファイル内に続けて記述してください。
@page "/ChestItems" <h1>ChestItems</h1> <p>チェストアイテムの中身を取得します。</p> <div class="mt-3"> <button type="button" class="btn btn-outline-primary" @onclick="GetItem">アイテムの取得</button> </div> <p> <div class="border" style="padding:10px;"> @ItemData </div> </p>
@code{ private string ItemData { get; set; } static IPAddress ipaddress = IPAddress.Parse("127.0.0.1"); static ushort port = 25575; static string password = "minecraft"; static RCON rcon = new RCON(ipaddress, port, password); private string command = $"/data get block <チェストの座標> Items"; private async Task GetItem() { await rcon.ConnectAsync(); var result = await rcon.SendCommandAsync(command); ItemData = result; } }
チェストの座標は皆さんの環境に合わせて変更してください。
2. メニューの追加と実行
次はこのページにアクセスするためのメニューを追記します。ソリューションエクスプローラ―内の Shared
フォルダに入っている NavMenu.razor
を開いてください。開くと色々書いてありますが、次のように追記してください。
<li class="nav-item px-3"> <NavLink class="nav-link" href="/ChestItems" Match="NavLinkMatch.All"> <span class="oi oi-box" aria-hidden="true"></span> ChestItems </NavLink> </li>
出来たら実行してみましょう。Minecraftサーバを起動後、アイテムを入れたチェストを用意し、アプリから「アイテムの取得」をクリックしてみてください。
スゴイ文字列で表示されると思います。これをマインクラフト上でも同じように実行してみて、同じデータが取得できていればOKです。
3. 不要な文字の除去
このままでは文字が大量で分かりにくいので、正規表現や分割などを使って扱いやすいような形にします。 上記の結果を見てみると、Json のようにみえますが、残念ながら Json ではなく JavaScript のオブジェクトです。これをデシリアライズすれば解決なのですが、さらに残念なことにライブラリがない(見つからなかった)ので、自力で何とかします。
まずはアイテムデータを管理するためのクラス ChestItems.cs
を Data
ディレクトリに作成し、次のように記述します。
public class ChestItems { public string ItemID { get; set; } public string ItemCount { get; set; } public string ItemSlot { get; set; } }
上から順にアイテム名(ID)、アイテムの数量、アイテムスロット(何番目にあるか)を保持しておくためのプロパティです。
次は Data
ディレクトリに ChestItemsDataService.cs
を作成し、この中で文字データの整理をしていきます。また、整理したデータを配列に格納し、表に出力するためのメソッドも作ります。少し複雑になりますが、仕方ありません。
public class ChestItemsDataService { public ChestItems[] Itemlist { get; set; } public void Extraction(string data) { data = data.Substring(data.IndexOf("[")); // [ 以降のデータを得る data = Regex.Replace(data, @"[\[{\]\s]", ""); // [, ], { 記号を削除 string[] split_data = data.Split("},"); // }, 記号で分割 Itemlist = new ChestItems[split_data.Length]; for (int i = 0; i < split_data.Length; i++) { Itemlist[i] = new ChestItems(); string[] str = split_data[i].Split(","); for (int j = 0; j < str.Length; j++) { if (str[j].Contains("Slot:")) { Itemlist[i].ItemSlot = Regex.Replace(str[j], "[^0-9]", ""); } else if (str[j].Contains("id:")) { str[j] = Regex.Replace(str[j], @"[^a-zA-Z:]", ""); Itemlist[i].ItemID = str[j].Substring(str[j].IndexOf("minecraft")); } else if (str[j].Contains("Count:")) { Itemlist[i].ItemCount = Regex.Replace(str[j], "[^0-9]", ""); } } } } public Task<ChestItems[]> AsyncExtraction() { return Task.FromResult(Enumerable.Range(0, Itemlist.Length).Select(index => new ChestItems { ItemCount = Itemlist[index].ItemCount, ItemID = Itemlist[index].ItemID, ItemSlot = Itemlist[index].ItemSlot }).ToArray()); } }
これで不要な文字の除去ができました。あとはこのデータを View (ChestItemsView.razor
) で受け取って表示するだけです。
4. 表にして出力する
このまま foreach
で回して表示しても見づらいだけなので、表にしてみます。ソースコードは分かれていますが、続けて書いてください。ChestItemsView.razor
をこのように書き換えます。
@page "/ChestItems" @using Data @inject ChestItemsDataService ItemData <h1>ChestItems</h1> <p>チェストの中身を取得します。</p> <div class="mt-3"> <button type="button" class="btn btn-outline-primary" @onclick="GetItem">アイテムの取得</button> </div> @if (chestFound == false) { <div class="alert alert-danger mt-3" role="alert"> チェストが見つかりませんでした。<br/> チェストの座標が正しいか、または Minecraft サーバの状態を確かめてください。 </div> } @if (items == null) { <div class="mt-3"> <table class="table"> <thead> <tr> <th>スロット</th> <th>アイテム名</th> <th>数量</th> </tr> </thead> </table> </div> } else { <div class="mt-3"> <table class="table"> <thead> <tr> <th>スロット</th> <th>アイテム名</th> <th>数量</th> </tr> </thead> <tbody> @foreach (var item in items) { <tr> <td>@item.ItemSlot</td> <td>@item.ItemID</td> <td>@item.ItemCount</td> </tr> } </tbody> </table> </div> }
@code{ static IPAddress ipaddress = IPAddress.Parse("127.0.0.1"); static ushort port = 25575; static string password = "minecraft"; static RCON rcon = new RCON(ipaddress, port, password); private string command = $"/data get block <ブロックの座標> Items"; private ChestItems[] items; private bool chestFound = true; private async Task GetItem() { await rcon.ConnectAsync(); var result = await rcon.SendCommandAsync(command); if (result.Contains("not")) { chestFound = false; return; } else chestFound = true; ItemData.Extraction(result); items = await ItemData.AsyncExtraction(); } }
これで View 側の記述もできました。これで完成に見えますが、まだ動きません。@inject
で導入したクラスは何もしないと「サービス」として認識しません。なので、次はサービスの登録を行います。
5. サービスの登録
ソリューションエクスプローラ―の中に Startup.cs
というファイルがあるので開いてください。中身を見てみると、ConfigureServices
というメソッドが記述されています。この中に、先ほど作った ChestItemsDataService
を登録します。
//なんかいっぱいかいてある public void ConfigureServices(IServiceCollection services) { services.AddRazorPages(); services.AddServerSideBlazor(); services.AddSingleton<WeatherForecastService>(); services.AddSingleton<ChestItemsDataService>(); } //なんかいっぱいかいてある
これで準備は整いました!あとは実行してみましょう。
6. 実行例
まずは最初のページです。アイテムを取得していない状態では items
の要素は null
になっているので、表示されていません。
正しくチェストの座標を指定し、「アイテムの取得」をクリックしてみると表示されます。ちなみに、チェストが空の場合は何も表示されません。
チェストの座標が正しくない、Minecraft サーバに接続できない等々でアイテムが取得できない場合は chestFound
フラグ が false
になるので、警告が表示されます。
あとは実際に動かしている様子を見ると分かりやすいかもしれません。
【Minecraft】Blazorアプリからチェストのアイテムを取得する
感想とか
今回は結構苦戦しました。Blazorって極めたらスゴイとは思いますが、こんな変な使い方をしている人はあまりいないと思います(笑)。本当に趣味で書いているので、このコーディングは微妙かもしれません。もっといい書き方があるはずですが、そこは時間を掛けながら模索していきたいですね。
Blazor 使えると楽しいですよ~
宣伝
Minecraft でプログラミング (C#) してみませんか? Minecraft with Code では、Minecraft と C# 言語などを組み合わせた面白いコンテンツを製作中です。整地作業や鉱石探しに苦労している人は、ぜひ自動化してみましょう!
ソースコード
今回作ったソースコードです。参考にどうぞ。
参考サイト
参考にしたサイトです。ありがとうございます。