2016年6月19日日曜日

ゼロから始めるマインクラフトのサーバー構築の話

突然なのですが、最近いまさらながらマインクラフトに大ハマリしておりまして。きっかけは友人のマルチプレイサーバーでプレイしたことだったのですが、やっぱり皆で遊ぶゲームは面白いなと再確認している次第です。マインクラフトはリリース直後、βが取れたぐらいに遊んで面倒でやめてしまったのですが、近頃はFeed The Beastと呼ばれるオールインワンのランチャーアプリが登場しており、こいつがMODの導入や管理も全て一発でやってくれるため面倒やストレスが一切なく楽しめます。

で、しばらく遊んでいたのですが、友人が他のゲームにハマってしまったためマインクラフトのサーバーを立てなくなってしまいました。そこで私のほうで自分でマインクラフトのサーバーを立ててやろうと思い立ちまして早速今週末チャレンジしてみました。

ちなみに私インフラに関しては大の苦手で、サーバーをゼロから構築するのは初めてだったりします。大昔新卒の頃にSIerの仕事でちょっと触ったりとか、その後の仕事でちょっと触ったりとかした程度。アプリケーションなら分かるんですけど(´・_・`)

前置きはこのぐらいにして早速やってみましょう。

ホスティングサービスを選定

パッと思いつくところだとさくらVPSとAWSが有名ですが、今回は友人のおすすめでConoHaというVPSホスティングサービスを選んでみました。ほとんどさくらVPSと大差ないように見えたのですが、ConoHaのほうがさくらVPSと違い初期費用がかからないらしいです。新しいもの好きですしせっかくなのでConoHaを選択。

サーバーのスペック等は以下のようにしました。CentOS 7.2に3コア2GBメモリで月1750円。マインクラフトのサーバであればこのぐらいの性能で大丈夫なはず。


とりあえずサーバーを起動してsshまで

構築したらすぐにインスタンスが起動します。ConoHaでは自動的に固定Public IPが1インスタンスに割り当てられるようで、この点固定IPを用意したりするのが何かと面倒なAWSに比べて楽でした。管理画面もすっきりまとまっていて使いやすく好印象です。キーペアもその場で同時にすぐ作成してくれて手間がかかりません。

生成したキーペアをローカルの ./ssh 以下に保存して ./ssh/config を適当に設定してログイン。root@を付け忘れてssh接続要求に失敗するみたいなよくあるお約束のミスをしましたが、特に問題なくログインできました。

ログインに成功したのを確認してから手持ちのドメイン (akisute.com) のサブドメインを用意してDNSを設定してやります。疎通して問題なし。

nginxを立てる

サーバーの情報などをウェブに公開したいので、nginxを利用してstatic htmlファイルをホスティングできるようにします。nginxのCentOS 7.2に対するインストール自体はこちらのページに従えばすぐにできます。
http://nginx.org/en/linux_packages.html
後は以下のビギナーズガイドに従って設定を行えば良いのですが、基本的には最初から全て必要そうな設定は用意されているので、/usr/share/nginx/html以下のindex.htmlを適当に編集してやるだけでオッケーです。
http://nginx.org/en/docs/beginners_guide.html

firewalldを設定する

しかしながらnginxを立ち上げただけでは外からアクセスしてもつながりません。これはCentOS(に限らないですが、ほとんどのLinuxのディストリビューションについて)は何らかのファイアウォールがデフォルトで入っているためです。一般的にはiptablesが使用されているのですが、CentOS 7ではiptablesではなくfirewalldというやつが使われているらしいので、そちらを設定することにしました。
http://urashita.com/archives/963
http://www.unix-power.net/centos7/firewalld.html

httpサービスをpublicゾーンの設定に追加するだけで簡単に外からアクセスできるようになります。iptablesより簡単でいいですね。

Javaをインストールする

マインクラフトはJavaで動作するので最新版のJavaが必要です。Javaには大きくOpenJDKとOracle Javaがありますが、個人的にはOracle Javaのほうが速そうなのでそちらを使うことにしました。以下のページで紹介されているとおりにすれば簡単にインストールできるかと思います。
https://www.digitalocean.com/community/tutorials/how-to-install-java-on-centos-and-fedora

minecraft-serverを立てる

いよいよ本題のminecraft-serverです。これについてはFTBのmodpackであればFTBのクライアントからDownload Serverボタンを押すだけでzip形式で最初から用意されたサーバーセットアップ一式がダウンロードできますので、ダウンロードURLをコピーしておいてサーバー側からwgetして取得しunzipするだけで準備完了です。
http://www.feed-the-beast.com/servers

unzipして展開した中身のServerStart.batをServerStart.shにして中身を適当に書き換えてやり(主にJVMの起動オプションからヒープに割り当てる量を調整するなど)実行すれば簡単にサーバが立ち上がります。ただし普通に立ち上げるとシェルを専有されてしまうので、screenなど経由でServerStart.shを実行するようにすればいいでしょう。
http://www.minecraftforum.net/forums/support/server-support/server-administration/1897274-how-to-use-screen-on-your-linux-minecraft-server

あとはサーバーコマンドで自分をopにでも追加しておけば良いと思います。起動したサーバーのコマンドラインから /op 自分の名前 とコマンドを実行すればopを付与できます。その他必要に応じてminecraft-serverの設定ファイルを操作したりgameruleを調整すれば良いと思います。

最後に先ほど設定したfirewalldにminecraftサービスを追加して、外からアクセスできるようにすればおしまいです。minecraftはhttpと違ってデフォルトでサービスが用意されていないので、自分でサービスを追加する必要があります。サービスの追加は/etc/firewalld/servicesにxml設定ファイルを追加すればよいです。サンプル代わりにデフォルトのサービスのxml設定ファイルが/usr/lib/firewalld/services以下に配置されているので適当なものをコピーして改造して使えばよいです。minecraftはtcp/udpの25565がデフォルトポートなのでここを開くように設定してfirewalldを再起動すれば外から繋がるようになるかと思います。

その他の設定

ログローテーションを設定しておかないとディスクがログで溢れて死ぬかと思ったんですが、最初からnginxについてはログローテーションが設定されているため気にしなくてOKです。minecraft-serverについてはどうなるかわかりませんので、必要に応じてlogrotateを設定して対応したほうが良いと思います。
https://genchan.net/server/4907

まとめ

いろいろ調べながらで時間がかかりましたが、3時間ほどでゼロ知識の状態からでもマインクラフトのマルチプレイサーバーを立てることができました。現在のところ無事快適に遊べています\(^o^)/

こういう自分の趣味嗜好のために技術を勉強すると非常に捗るのでオススメですね。みなさんもゲームを楽しみながら技術を勉強して一石二鳥になりませんか\(^o^)/


2016年1月7日木曜日

Asset Catalog を使用しているときは [UIImage imageNamed:] が遅くなることがある

タイトルのとおりですが、本日発見してひどくパフォーマンスに影響が出たため注意喚起を兼ねて共有いたします。

最近のiOSプロジェクトは全て画像をxcassetsすなわちAsset Catalog経由で管理することが多いかと思いますが、このAsset Catalogを使用している際に[UIImage imageNamed:]経由で画像を取得するとiOS 8以前とは異なり大変画像の取得が遅くなることがあるようです。

詳細はこちら。
https://forums.developer.apple.com/thread/17888

実際に私の環境では目に見えて遅くなりました。Instruments経由で計測したところ最大で10倍ほど差が出ているように見えました。iOS 9.1以降は修正されているとのことですが、それでも[UIImage imageNamed:inBundle:compatibleWithTraitCollection:]を使用したほうがパフォーマンスへの悪影響が少ないとの情報があります。実際Instruments上でもTrait Collectionを検索するのに無駄なパワーを使っているように見えたのでパフォーマンスがタイトな箇所では自分で非同期ロードするなりキャッシュするなりして補ってあげたほうが良い気がします。

こちらからは以上です。

2015年12月17日木曜日

Xcode 7.2 の LLDB で Swiftのデバッグをするコツ

現在のXcode 7.2でSwiftを使ったiOSアプリのデバッグをするときのコツみたいなものをまとめました。将来的にはより良くなる可能性はあります。というか良くなってほしいです(´・_・`)

■LLDBはbreakした地点によって挙動が変わる

まずハマりどころがこれですが、現在のLLDBはbreakした地点で実行されていたコードがSwiftのコードかC言語系のコードかによってモードが変わります。
// Objective-C mode
(lldb) po [someObject property]

// Swift mode
(lldb) e someObject.property
Objective-Cモードの時にSwiftっぽい呼び出しをしたり、その逆をしてもまともにLLDBは動作しません。なので現在自分がどちらのモードのLLDBにいるのかを判断するのがキモになります。

ハマりどころとして、例えば実行中におもむろに停止ボタンを押してみるとか、debug viewボタンを押してみると、全部のコードがSwiftで書かれているアプリにも関わらずいきなりLLDBがObjective-Cモードで起動します。これはbreakされるのがシステムのC言語で書かれた領域だからです。

ちなみに現在のモードがどちらかを判断する方法は無いような気がします。気合と慣れで判断してください。オープンソースになりましたし、そのうち改善されると思います\(^o^)/

■SwiftモードのLLDBでprint object (po) したい

SwiftモードのLLDBのpoはかなり微妙な実装になっているので、SwiftモードでLLDBを使う場合にはpoの代わりにexprすなわちeを使うことをオススメいたします。
(lldb) e someObject
参照: http://stackoverflow.com/questions/28016227/when-debugging-swift-code-can-i-get-a-typed-reference-to-an-object-given-just-i

なんかこちらの記事ですとe -O -d run --で実行するといいよって書いてますけど何が違うのかはよくわかってません。個人的には普通のeでだいたい問題なかったです。

■SwiftモードのLLDBでポインタアドレスからオブジェクトを起こしたい

Objective-Cであれば
po 0x123456789012beef
で終わりなんですが、SwiftモードのLLDBはそこまで面倒を見てくれません。そこでunsafeBitCast()関数が便利に使えます。
(lldb) e let $v = unsafeBitCast(0x123456789012beef, MyView.self)
(lldb) e $v
これではかどりますね。