たくのろじぃのメモ部屋

プログラミング関係や数学、物理学などの内容を備忘録として残すブログ。

Microsoft Learn で C# 入門

Microsoft Learn では C# や Azure などの開発者向けコンテンツからデータサイエンスなどの研究者向けのコンテンツまで数多く揃っています。

無料で始められるので、これから「プログラミング(C#)を勉強したい」という人にもおすすめです。アカウントを登録しておくと、経験値を得られたりトロフィーをもらえたりして達成感を感じられます。特に、学生の方は学校のメールアドレスで登録しておくといいことが...?(学生向けコンテンツが増える?)

ここで紹介するものは、初心者にとって最初で最後の難関である 環境構築が必要ない のですぐにプログラムを書くことができます。

1. C# の最初のステップ

まずは C#の最初のステップ です。

f:id:takunology:20201014144810p:plain

このラーニングパス(学習コース)では C#の書き方、変数、文字列、計算、メソッド(関数)、配列とforeach構文、条件分岐、コーディングスタイルを学習できます。特に前提知識は必要ないので、全くプログラミングをしたことがない人はぜひぜひ。ただ、所々専門用語があるので、分からない部分は調べる必要があると思います。

2. C# でアプリケーションにロジックを追加する

最初のステップの後は C# でアプリケーションにロジックを追加する がオススメです。

f:id:takunology:20201014150551p:plain

前提条件に最初のステップの内容が含まれているので、もう少し C# について触れてみたい人はぜひ。

このラーニングパスでは ブール式(論理式)、変数のスコープとコードブロック、クラス・メソッド・名前空間、switch構文、反復処理 (for, while) が学習できます。

3. C# でデータを処理する

ここまでで、C#の書き方にも慣れてくるころだと思います。簡単なアルゴリズム(データ処理)をやってみたい人は C# でデータを処理する をやってみましょう。

f:id:takunology:20201014151045p:plain

このラーニングパスでは データと型、型変換、ヘルパーメソッド、配列操作、文字列補間、文字列操作が学習できます。

やってみた感想

ラーニングパスをクリアするとトロフィーがもらえます。

f:id:takunology:20201014152550p:plain

自分は前からC#に触れていたので半日もかからず終わってしまいましたが、結構内容は盛りだくさんでした。特に、データ処理の文字列操作は初めて経験したものがあったので、いい勉強になったと思います。この3つだけでも基礎は結構固まるという印象です。今回紹介した3つのラーニングパスではこれだけのことを扱っています。

  • 変数と型
  • 算術演算子
  • 文字の出力
  • 条件分岐 (if-else, switch)
  • 配列
  • 配列操作 (要素の削除、追加)
  • データ整列(昇順、降順)
  • 反復処理 (for, foreach, while, do-while, continue, break)
  • コーディングスタイル
  • ブール式
  • 論理演算子
  • コメントアウト(とその意味)
  • 名前空間・クラス・メソッド
  • 型変換 (キャスト, TryParse() メソッド)
  • 文字列操作 (補間、置換、検索)

もし、「これからプログラミングやってみたい」と思った人がいれば Progate でも学習できますが、ある程度進んだところで有料になるので Microsoft Learn ならば無料で一通り習得できます。

統合版 Minecraft で LANサーバを立てる

Java版のサーバの立て方は何回か記事にしていますが、今回は統合版 (Windows 10版) Minecraft のサーバを立てます。

1. bedrock版サーバのダウンロード

このサイトからサーバを立てるための Zip ファイルをダウンロードします。

f:id:takunology:20201004020121j:plain

ダウンロードしたら展開します。

f:id:takunology:20201004020337p:plain

bedrock_server.exe を開きます。初回起動では警告やら何やらが出てきますが、全て許可して開いてください。無事に起動できるとコマンドプロンプトが立ちあがります。

f:id:takunology:20201004040344p:plain

これでサーバが立てられました。

2. サーバをつくる

イクラを起動して、遊ぶ から サーバ タブを開き、サーバを追加 をクリックします。

f:id:takunology:20201004021513j:plain

コマンドプロンプトに表示されたサーバのポート番号と、サーバを立てたいPCのIPアドレスを入力して保存します。

f:id:takunology:20201004040428p:plain

保存したサーバを確認して、電波のマークが表示されていれば完了です。

f:id:takunology:20201004021700p:plain

【C#】JSON ファイルを書きだす

去年、C#JSONの読み込み(デシリアライズ)をやりました。

blog.takunology.jp

今回は書き出し(シリアライズ)をやります。と言っても、シンプルなJSONファイル(例えばオブジェクトや配列が1つの階層のもの)はいろんなサイトに載っているので、このブログでは多重構造になっているものを扱います。

書き出したいデータ

統合版マインクラフトのWebSocket通信で使用するJSONファイルを書き出してみます。

{
    "body": {
        "commandLine": "time set 0",
        "origin": {
            "type": "player"
        },
        "version": "1"
    },
    "header": {
        "messagePurpose": "commandRequest",
        "messageType": "commandRequest",
        "requestId": "e608eba7-13cb-48f9-b8d5-139088cc7cd8",
        "version": "1"
    }
}

これの面倒なところは body オブジェクトの中に origin オブジェクトが入っている点です。この二重構造になっているものをどうやって書き出すかがポイントです。

1. データコントラクト属性クラス

まずは書き出したいデータに対応するクラスを作ります。その際に、データコントラクト属性を付けます。クラス名は SampleData としています。オブジェクトの中にオブジェクトが入るような構造をしている場合は、クラスのクラス(おそらくネスト?)を作っていきます。例えば Body クラスには Origin クラスでネストしたプロパティが含まれています。

各プロパティにはデータメンバ属性を付けて、JSONに書き出す際の Key とします。Name プロパティを指定することで Key の名前を変更できます。

namespace JsonSerializeSample
{
    [DataContract]
    public class SampleData
    {
        [DataMember(Name = "body")]
        public Body Body { get; set; }
        [DataMember(Name = "header")]
        public Header Header { get; set; }
    }

    [DataContract]
    public class Origin
    {
        [DataMember(Name = "type")]
        public string type { get; set; }
    }

    [DataContract]
    public class Body
    {
        [DataMember(Name = "origin")]
        public Origin Origin { get; set; }

        [DataMember(Name = "commandLine")]
        public string commandLine { get; set; }

        [DataMember(Name = "version")]
        public string version { get; set; }
    }

    [DataContract]
    public class Header
    {
        [DataMember(Name = "requestId")]
        public string requestId { get; set; }

        [DataMember(Name = "messagePurpose")]
        public string messagePurpose { get; set; }

        [DataMember(Name = "version")]
        public string version { get; set; }

        [DataMember(Name = "messageType")]
        public string messageType { get; set; }
    }
}

2. シリアライズ

定義したプロパティを初期化した後、シリアライズをするためのインスタンスを生成します。また、メモリストリームでファイルの順次書き出しを行えるようにします。シリアライズインスタンスにて WriteObject メソッドを呼び出して、引数にメモリストリーム(順次書き出し)と初期化したデータを入れます。

Body クラスの中に Origin クラス(内部クラス)が宣言されているのがポイントです。これで二重構造にできます。

using System;
using System.IO;
using System.Runtime.Serialization.Json;
using System.Text;

namespace JsonSerializeSample
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Json serialize.");
            Serialize();
        }

        static void Serialize()
        {
            var sampleData = new SampleData()
            {
                Body = new Body()
                {
                    Origin = new Origin() { type = "player" },
                    commandLine = "time set 0",
                    version = "1"
                },

                Header = new Header()
                {
                    requestId = "e608eba7-13cb-48f9-b8d5-139088cc7cd8",
                    messagePurpose = "commandRequest",
                    version = "1",
                    messageType = "commandRequest"
                }
            };

            var serializer = new DataContractJsonSerializer(typeof(SampleData));
            var ms = new MemoryStream();
            serializer.WriteObject(ms, sampleData);
            Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
        }
    }
}

3. 実行結果

画像では改行されずに出力されていますが、JSON形式で書き出せています。 生のデータでは少しわかりにくいので、整形ツールなどを使うと見やすくなります。

f:id:takunology:20201009143019p:plain

参考

今回作ったコードを置いておきます。動かしたい人は .NET Core 3.1 以上で動かしてください。

github.com

Xamarin アプリから Minecraft にコマンドを投げよう

以前、マイクラ自動化でC#からRCON経由でマイクラのコマンドを投げられることを確認しました。同じC#ならばプラットフォームが異なってもできるのでは?というノリでXamarinアプリを作ってみたら意外といけました。

www.youtube.com

youtube では Androidエミュレータ で動かしていますが、この記事ではいろんな環境で試したいと思います。

1. 全体図

ざっと全体図です。

f:id:takunology:20201004002720p:plain

イクラサーバをPC上に立てて、実機と同じネットワークアドレスに所属させます。ホスト部をPCに指定してコマンドを送信すれば、スマホ (Xamarin) からコマンドを送信できるので遠隔操作ができるようになります。エミュレータの場合はPC上で動いているので直接ホストのIPを指定して接続する形になります。

2. プロジェクトの作成

Visual Studio にて Xamarin.Forms を選択します。

f:id:takunology:20201003035841p:plain

テンプレートは空白で大丈夫です。開発対象は自分のやりたい環境を選択してください。

f:id:takunology:20201003040146p:plain

起動までに少し時間がかかります。

3. 画面デザイン(XAML)

適当にデザインを書いていきます。初めてやる人はファイルが結構あって混乱すると思いますが、プロジェクト名直下にある MainPage.xaml (画像の青い部分) を選択します。

f:id:takunology:20201003040439p:plain

必要なパラメータはIPアドレスとコマンドなので、この2つは Entry コントロールとして配置します。あとはログを受け取るためのラベルなどを貼っていきます。

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XamarinMC.MainPage">

    <StackLayout>
        <Frame BackgroundColor="#2196F3" Padding="24" CornerRadius="0">
            <Label Text="Minecraft with Xamarin" HorizontalTextAlignment="Center" TextColor="White" FontSize="20"/>
        </Frame>
        <Label Margin="20, 0" Text="Your IP address" FontSize="18"/>
        <Entry Margin="20, 0" x:Name="your_ip" FontSize="16"/>
        <Label Margin="20, 0" Text="Command here" FontSize="18"/>
        <Entry Margin="20, 0" x:Name="command" FontSize="16"/>
        <Button Margin="20, 0" Text="send" Clicked="Button_Clicked"/>
        <Label Margin="20, 10" Text="Server log here." FontSize="12" x:Name="Loglabel"/>
    </StackLayout>

</ContentPage>

4. CoreRCON の導入

タブから プロジェクト の中にある Nuget パッケージの管理 を開きます。

f:id:takunology:20201003040932j:plain

参照 タブをクリックして、検索欄に CoreRCON と入力すると先頭に出てくると思います。

f:id:takunology:20201003041401j:plain

これを選択し、バージョンを 5.0.0 にして インストール をクリック してください。(3.0.0 でやってみましたが上手くいきませんでした。)

ソリューションエクスプローラ―の 依存関係 / パッケージ の中に CoreRCON 5.0.0 が入っていれば導入完了です。

f:id:takunology:20201003041620p:plain

5. コードビハインド (C#)

Mainpage.xaml の三角ボタンをクリックすると、MainPage.xaml.cs という C#ソースコードが入っているので開きます。 クラスは分けますが同一ファイル内にまとめて書いてしまいます。クラス名やメソッド名はお任せします。

using CoreRCON;
using System;
using System.Net;
using System.Threading.Tasks;
using Xamarin.Forms;

namespace XamarinForMinecraft
{
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
        }

        private async void Button_Clicked (object sender, EventArgs e)
        {
            MinecraftCommand mc = new MinecraftCommand();
           
            await mc.Execute(your_ip.Text, command.Text);

            Loglabel.Text = $"{System.DateTime.Now} \n {mc.logMessage}";
        }

    }

    public partial class MinecraftCommand
    {
        public string logMessage;

        public async Task Execute(string ipAddress, string mcCommand)
        {
            await CommandSend(ipAddress, mcCommand);
        }

        private async Task CommandSend(string ipAddress, string mcCommand)
        {
            try
            {
                var serveraddress = IPAddress.Parse(ipAddress); //IPアドレスとして扱うための変換
                var serverpass = "minecraft"; //RCONでログインするためのパスワード
                ushort port = 25575; //サーバのポート番号

                var rcon = new RCON(serveraddress, port, serverpass);
                await rcon.ConnectAsync(); //接続
                var result = await rcon.SendCommandAsync(mcCommand);

                logMessage = result;
            }
            catch (Exception ex)
            {
                logMessage = ex.Message;
            }
        }
    }
}

6. 様々なデバイスで試してみよう

イクラにコマンドを送信するには RCON 接続許可をしたマイクラサーバの設定が必要なので忘れずに行ってください。 参考までに。

blog.takunology.jp

6.1 Pixel 2 (Android 9.0)

f:id:takunology:20201004002311p:plain

6.2 iPhone11 (iOS14.0)

f:id:takunology:20201004001701p:plain

6.3 UWP (Windows 10)

f:id:takunology:20201003062506p:plain

7. おわりに

Xamarinを使って様々なデバイスからコマンドを送信できました。実機でもやってみましたが、それほど遅延は感じませんでした。

これをきっかけにマイクラも1つの学習ツールとして普及できればと思います。

Xamarin でマイクラ自動化できそう

CoreRCON を使えば C#言語でマイクラにコマンドを送信できます。ということは、プラットフォームに関係なく C# さえ扱えればスマホからもコマンド送信ができるのでは?と思いました。

結果として、Xamarinで作ったアプリでもRCON経由でマイクラにコマンドを送信できました。詳細はまた別の記事に書きたいと思います。

www.youtube.com