turgenev’s blog (original) (raw)
ラマはチェストを装着してインベントリを持たせることができる動物mobです。リードで引っ張られた別のラマに付いていく習性があるので、大量にアイテムを輸送したいときに便利…かもしれません。
この記事ではラマを繁殖させて強い個体を選別する方法を解説します。
ラマの繁殖のしくみ
ラマのもつパラメータは以下の通りです。
- 色…白、灰、クリーム、茶の4種類で、どちらかの親のものをランダムで引き継ぐ。白と灰はやや見分けづらい。
- 体力…15-30で、親の値の平均からランダムに変動する
- 強さ…1-5で、これを3倍したものがインベントリの枠の数になる。親2頭のうち大きい方の値のみによって制約され、その値以下になることがほとんどだが、まれにその値より1つ大きくなる。例えば親の強さが1と3なら、大きい方が3なので、ほとんどは1-3になる(割合としては全て約1/3ずつ)が、1%の確率で4になる。親の強さが3と3でも同じ。自然スポーンについては、ほとんどが1-3(約1/3ずつ)で、稀に4や5がいる。
- 速さ、ジャンプ…内部的に存在するようだが、挙動には影響しない
これに加えて、ラマには行商人のラマという亜種があります。これらはほとんど通常のラマと同様に振る舞いますが、以下のような特徴があります。
- 親が2頭とも行商人のラマである場合は、子供の見た目も行商人ラマになる(=青いカーペットを装着した状態で生まれる)
- 上記のようにして繁殖で生まれた行商人ラマであっても、飼い慣らさないでしばらく(正確に測定していないものの、通常の行商人と同じ40分=大人になってから20分)経つとデスポーンする。
これをもとに厳選の仕方を考えます。
厳選の方法
ゴールとしては、希望の見た目(色、および行商人ラマかどうか)とできるだけ高い体力とサイズ15のインベントリを持つラマを自由に生産できるようになるところまで行けば十分でしょう。
色については、同じ色を2体ずつ揃えればよさそうです。行商人ラマについては、親がどちらも行商人ラマでないと行商人ラマが産まれないため、行商人ラマだけで厳選を行ってから必要に応じて通常のラマをそこから産むということにします。体力についてはひたすら30を目指すのみですが、目視だと若干分かりづらい(2HP単位でしかわからない)ので、抵抗がなければHorseStatsVanilla(※fork元は1.21非対応)というmodを入れて確認しながらやるのをおすすめします。強さに関しては、大きい方の値のみが影響するという重要な特徴があるので、まずはとにかく1体でも強さ5のものを手に入れるのが重要になってきます。
つまり、厳選のフェーズを大きく2つに分けると、①まず1体でも強さ5の行商人ラマを手に入れる②強さ5の各色の行商人ラマを作る③強さ5の各色の通常ラマを作る という感じになります。それと並行して体力も上げていくという感じです。
これをまとめて戦略を立てると以下の通りになります。
- (小麦生産所を立てて干し草の俵を量産できるようにする。)
- 行商人ラマを全色揃える。
- 最低1匹、強さ3の行商人ラマを見つける(上記と被っていてもよい)。
- 超ラッキーなら行商人ラマで強さ4とか5のやつがいるかもしれないので、それを確保する。行商人のスポーンは遅いので、4や5がスポーンするのを待つのは非効率。3は約1/3の確率で出るので、待ったほうが早い。
- 行商人ラマ同士を繁殖させていく。このとき、親のうち片方は強さが最大のものになるようにする。
- このため、強さに応じてカーペットを付けておくとよい。
- 数が増えすぎてきたら、場所もとるし負荷もかかるので、一部のラマは殺すことになる。この際、強さや体力の値が低いものを殺す。
- このため、カーペットの色は体力よっても変えたほうがいい。筆者は、体力を3段階に分けて(基準は適当で、途中で変えたりしてもいい)、強さ2なら体力が高い順に「青、青緑、水色」強さ3なら体力が高い順に「緑、薄緑、白」、強さ4なら体力が高い順に「赤、オレンジ、黄色」のように分けていた。
- 強さ4のものが産まれたら、次は5を目指す。このタイミングで、強さ3以下のものは(体力が少ないものを中心に)だいぶ間引きしてもいいかも。
- そのうちめでたく強さ5の行商人ラマが産まれる(①が完了)
- こんどはこれを各色の行商人ラマと交配させる。すると1/10くらいの確率で、今までいなかった色の強さ5のラマが誕生する。そのうち全色揃う。(②が完了)
- 同色の普通のラマと交配させて、普通のラマについても各色で強さ5のものを作る。
- 各色、行商人ラマと通常ラマについて、「強さ5で体力が高いラマ」と「強さによらず体力が高いラマ」をペアにする。完成。
①の部分については、最初から強さ5のものがいればそれで完了、4がいれば5が出るまでに平均133.33…回の繁殖、3しかいなければ4が出るまでに平均100回とそこからさらに5が出るまでに平均133.33…回、という感じになります。4が出るまでと5が出るまでにそれぞれ壁があるということです。
先の見えない①に比べると、②③はそこまで大変ではありません。
前述の通り行商人ラマはしばらくすると消えてしまうので他の作業をしたり放置したりしながらだとあまりうまくいかないかもしれません。。
ラマの殺処分の設備
ラマの厳選で厄介なのは、ラマが中立mobであるということです。プレイヤーが反撃されるだけならまだいいのですが、ツバが他のラマに当たると今度はラマ同士で敵対してしまいます。密集して飼っている場合、これは簡単に全員を巻き込んだ大規模な同士討ちに発展します。最終的には4ブロックあたり1体くらいの密度でしか生き残らず酷いことになるので、攻撃せずに処理できるのが理想的です。
おすすめは以下のような設備を繁殖場所の上に作ることです。
ラマ殺処分施設
ちょっと見づらいかもしれません。地面から2マスあけて不燃フェンスゲート(看板でも可)を設置し、その上に溶岩を置きます。周りもフェンスゲートで囲っておきます。溶岩の上はガラス(などの燃えないブロック)を置きます。そこから1マスあけてネザーレンガフェンスを置いておきます(燃えないため)。
殺したいラマはリードにつないで上のネザーレンガフェンスにつなぎます。そうするとリードで地面から浮かんで溶岩に突っ込んで燃えるので死にます。リードと革はたまに消えますが大抵はちゃんとドロップします。
溶岩がこの高さなら飼い慣らすときにプレイヤーの頭が突っ込むこともありません。
なお、万が一誤ってラマの同士討ちに発展しそうなときは、とりあえず強さが最大のラマを1匹連れて逃げましょう。1匹でも残っていれば、損害はそこまで大きくありません。
Linux Mint 22が先月リリースされたので21.3からのアップグレードを行った。
アップグレードは問題なく完了したが、再起動してみるとgrubが壊れているっぽく、grubの画面が出るべきところで勝手に再起動されてbios画面が出てきてしまう。linux mint 22 bios loopで調べたら
https://forums.linuxmint.com/viewtopic.php?t=425504
これが出てきた。21.3 → 22で何か変更があった模様で、--no-uefi-secure-bootを付けてインストールするといいらしい。
もし事前にわかっていれば、22へのアップグレード完了時に(再起動する前に)以下のようなコマンドだけを打てばいいはず。
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=GRUB --no-uefi-secure-boot
ただし/boot/efiにはEFIシステムパーティションがマウントされているものとする。
しかし実際には事前にわからない場合のほうが多いので、Live CDからchrootして作業する。
だいたい以下のような感じでいいはず。(/dev/sdXY
はLinuxのルートパーティション、/dev/sdZW
はefiシステムパーティション)
sudo mount /dev/sdXY /mnt
sudo mount /dev/sdZW /mnt/boot/efi
sudo mount --bind /dev /mnt/dev
sudo mount --bind /proc /mnt/proc
sudo mount --bind /sys /mnt/sys
sudo chroot /mnt
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=MY-GRUB --no-uefi-secure-boot
update-grub
--bootloader-id
の文字列がXXXの場合、efiシステムパーティションの/EFI/XXXに関連ファイルが置かれる。なのでこれを利用するエントリをefibootmgr
で追加する(コマンド例: efibootmgr -c -L MyEntry -d /dev/sdZW -l '\EFI\MY-GRUB\grubx64.efi'
)。しかし実際にはefibootmgr
で既存のエントリが見ているディレクトリ(Linux Mintなら"ubuntu"だと思う)を調べてそれを指定すれば上書きしてくれそう(未検証)。ブートローダーのファイル名がshimx64.efiではなくgrubx64.efiになると思うので自分でエントリを追加する必要がありそう。
あとちなみにBIOSでSecure Bootをオフにする必要はなかった(有効のままで問題なく起動した)。オフにして起動したときにはNVIDIAがロードされなかったのでnvidia-dkms-470を再インストールしたりした。
全然細かい仕様はわかっていないのですが予想とちょっと違う挙動があったので一応体験談として記録しておきます。
Deutschlandticketというのはドイツ国鉄(Deutsche Bahn, 略称DB)の普通・快速列車(S/U/RB/REまでは可、IC/ICEは不可)およびバス・路面電車に使えるフリーパスで、1ヶ月あたり49ユーロという、5日間くらいでも(特に手間賃込みだと)割と簡単に元が取れる価格が設定されています。日本語では49ユーロチケットと呼ばれることのほうが多いようです。また、1ヶ月あたりといっても任意の日付で始めることはできず、月をまたいで1週間使う場合は2ヶ月分払わなければいけません。
購入・キャンセルが若干難しく、まずDB公式で買う場合には現地の銀行口座が必要、という問題があります。ただし実際には、各地域での運行を担当する運輸連合(Verkehrsverbund)を通して買うことができ、さらに運輸連合によってはクレジットカードでの購入ができます。日本語圏ではRheinbahnというアプリが良く知られているようで、筆者もこれを利用しました。こちらの日本語記事ではRMV goというのが紹介されています。
Deutschlandticketは月ごとの**サブスクリプションなので、購入後何もしないと勝手にそのまま契約が更新されてしまいます。従ってキャンセルをする必要があるのですがこれが2つ目の難関で、多くのサイトで警告されている通り、使いたい最後の月の10日までにキャンセルする必要があります。つまり8月まで使って9月は使わないのであれば、8/10までにキャンセルする必要があります。仮に8/20-8/30の間だけ使うのであっても、8/10までにチケットを購入してキャンセルまで済ませておく**必要があります。
これを踏まえて筆者の体験を説明します。
筆者は7/5-8/17の期間でDeutschlandticketを使いたかったため、まず7月の最初のほうにRheinbahnで購入しました。これは特に問題ありませんでした。ちなみに支払いにはPaypalを使いました。その後、7/15になって、7月の後半のみドイツに滞在する人(筆者と同じくドイツの銀行口座なし)にDeutschlandticketの買い方について聞かれました。彼はその時点でまだ買っていなかったため即座にキャンセルしても2ヶ月分払わなければいけないことを説明しましたが、それでもOKというのでRheinbahnを紹介しました。で、自分としてももう7/10は過ぎていて8月までは使うことになっているはずなので今日のうちにキャンセルをしてしまおうと思って操作しました。すると、キャンセル前の確認画面で、「今日キャンセルした場合、チケットは7/30まで有効になります」というような表示が出ました。…え?7/31まで?それができるのは7/10までだったはず…。しかし勢いでそのままキャンセルしてみました。するとチケット情報のところでもちゃんと有効期限は7/31までに設定されました。
Rheinbahnのアプリや公式サイトのどこを読んでも、10日までにキャンセルする必要があると書いてあります。しかし現に15日のキャンセルでもその月までで終了できているように見えます。とはいえ、システム的にやはりうまくいっていなくて8月分の料金を請求されてしまう可能性は依然として残っています。自分は8月もDeutschlandticketを使いたいので、それを新たに購入しなければならず、加えてシステム上キャンセルできていなかった分まで払わなければいけないとすれば二重請求されてしまうことになります。一応Rheinbahnに問い合わせてみましたが何も返ってきていません。
そんなこんなでこの件が心のどこかに引っかかったまま過ごしていたのですが、幸い8月になっても二重請求が発生することはありませんでした。さらに、筆者が買い方をアドバイスした彼(7/15以降に解約)も1ヶ月分しか請求されていなかったとのことです。つまり、結果としては15日になっても依然としてその月まででのキャンセルが可能だったことになります。
これをきっかけに英語情報も含めて調べてみると、このページや、そこからリンクされているこのページにたどり着きました。特に後者のほうにはサブスクリプションとは関係ない有益情報(適用される列車に関してなど)があるのでおすすめなんですが、特にこの記事と関連して注目したいところは、moplaというアプリでは月末の24時間前までキャンセルが可能らしいというところです。なお、このmoplaというアプリは日本国内からは使えないようです(VPNなどを使えばできると思われます)。また今まで挙げたもの以外ではハンブルクとミュンヘンの運輸連合のアプリ(それぞれhvvとmvvで検索)も使えるようです(これらは日本国内OKで、少なくとも書いてある限りではRheinbahnと同様に10日までしかキャンセルできないようです)。
24時間前までにキャンセルできるアプリが存在するということはDeutschlandTicketのシステム自体が10日までのキャンセルしか受け付けないように設計されていることはないので、15日時点で月末でのキャンセルが依然として可能だったとしてもそこまで不思議ではないのかなと思いました。
ちなみに、メモしておくのを忘れてしまったのですが、月末近くにキャンセルしたら一旦料金取られたけど後で勝手に返金されたというような情報を見たような気もするので、意外と緩いのかもしれません。
特に伝えておきたい要点をまとめると以下のようになります。
- (少なくともRheinbahnに関しては、)DeutschlandTicketのキャンセルはその月の10日までと書いてあるが、それよりさらに前だからといって前月の15日などにキャンセルしようとすると面倒なことになる可能性があるので、その月の頭~その月の10日までの期間にキャンセル操作を行うのが安全かもしれない。いずれにしろ、キャンセル時の表示をよく読むこと。
- もし10日までにキャンセルするのを忘れていた・できなかったとしても、月内まででのキャンセルが依然として可能かもしれないので、やってみる価値はある。
- 慣れているなら、VPNなど経由でmoplaアプリを使ってみるのも手かもしれない。
特に、実際に何日までならキャンセル可能なのか(15日ならいいけど25日ならダメ、など)とか、Rheinbahn以外のアプリではどうなのかとか、moplaはVPN使えばちゃんと使えるのかとか、そのへんは未検証なので誰か機会があれば続報書いてみていただけると誰かの助けになると思います。
以上です。
GCCとかmakeを使ってC/C++のプロジェクトをビルドするときの各種オプションや変数をいつも忘れてしまうのでまとめました。
基本
GCCによる実行ファイルの作成は大きく分けるとコンパイル→リンクの2段階があります。
まず、コンパイル時に必要になるのがヘッダです。#include <stdio.h>のstdio.hみたいなやつです。
ヘッダの探索にはデフォルトで**/usr/include**などが使われます。一覧は、例えばCのコンパイラ(cc)であれば
echo '#include <stdio.h>' | cc -v -x c -E - > /dev/null
などと打つと確認できます。手元のLinux Mintではこうなりました。
/usr/lib/gcc/x86_64-linux-gnu/11/include
/usr/local/include
/usr/include/x86_64-linux-gnu
/usr/include
コンパイル時に***.hとか***.hppが見つからないと言われたときは、lib***-devみたいな名前のパッケージを入れると大抵解決します。
次に、リンク時に必要になるのがライブラリです。正確にはリンクの中にも実行ファイル作成時の静的リンクと実行時の動的リンクの2種類があります。
静的リンクライブラリはLinuxだと***.a、Windowsだと***.libです。動的リンクライブラリはLinuxだと***.so、Windowsだと***.dlです。
ライブラリの探索にはデフォルトで**/usr/lib**などが使われます。一覧はさっきのコマンドのLIBRARY_PATH=というところで確認できます。手元ではこうなりました。
LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../:/lib/:/usr/lib/
長い…
ちなみに、 cc -print-search-dirsというコマンドの出力にもlibraries: =という項目がありますが、ここから重複や存在しないフォルダを取り除いたものが上記のLIBRARY_PATHになるらしい(出典)のでLIBRARY_PATHのほうが便利そうです。
コンパイル時や実行時に***.aとか***.soが見つからないと言われたときは、lib***みたいな名前のパッケージを入れるか、上記フォルダを探してそれっぽいのがあればlib***.so -> lib***.so.2.1みたいな感じでシンボリックリンクを作るかすると大抵解決します。
GCC用のオプション・変数
ヘッダ探索・ライブラリ探索の時に、上記のデフォルト値に加えて、自分で指定したフォルダも見てほしいという場合があります。
まずヘッダ探索時は、-I/my/include
のように-I
オプションでフォルダを追加できます。複数追加したければ複数回-I
オプションを書きます。さらに、以下の環境変数が読み込まれます。
- CPATH…CおよびC++のヘッダ探索が行われるパスの一覧
- C_INCLUDE_PATH…Cのヘッダ探索が行われるパスの一覧
- CPLUS_INCLUDE_PATH…C++のヘッダ探索が行われるパスの一覧
実際にはCPATHはあまり使われず、あとの2つが使われていることが多いような気がします。優先順位(探索の順番)としては、-I
>環境変数>デフォルト値となります。
次はリンク関連です。まず、コマンドラインオプションとしては、-L/my/lib
のように-L
でフォルダを追加できます。さらに、以下の環境変数が使われます。
- LIBRARY_PATH…静的リンク 時のライブラリ探索が行われるパスの一覧
- LD_LIBRARY_PATH…静的リンク時(LIBRARY_PATHと同様)、及び実行時に動的ライブラリ(共有ライブラリ)の探索が行われるパスの一覧
LD_LIBRARY_PATHは、実行時にも影響するので、.profileなんかに下手に書いておくとlsでさえ実行できなくなったりします。注意してください。また、ビルド時に使うことはありませんが、LD_LIBRARY_PATHよりさらに優先度の高い(早く読み込まれる)LD_PRELOADという変数もあり、こちらはフォルダではなく共有ライブラリファイルのパスを直接指定します。既存の実行ファイルの動作を無理やり変更したいときなどに使われます。
これらのオプション・変数の起源はGCC(コマンドはgccやg++)だと思いますが、後発のClang(コマンドはclangやclang++)も概ねGCCと互換性があるので同様に使うことができます。
また、gccには無関係ですが重要な変数として以下を挙げておきます。
- PKG_CONFIG_PATH…pkg-configによる.pcファイルの探索時に使われるパス
pkg-configは、ライブラリ探索を抽象化したインターフェースみたいなもので、/usr/libとかに直接ライブラリファイルを置かなくても、ライブラリファイルの場所を書いた.pcファイルを/usr/lib/pkgconfigとかにおいておけば、それに従ってライブラリを探してくれるというものです。configureスクリプトを使うようなプロジェクトとかでよく使われていると思います。
make用の変数
これらはGNU makeで使われる変数です。○○FLAGSという名前で、これがgccなどの各コマンドに対してオプションとして渡されます。
- CFLAGS…Cコンパイラに渡すオプション。
- CXXFLAGS…C++コンパイラに渡すオプション。
- CPPFLAGS…C/C++のプリプロセッサ(PreProcessor)に渡すオプション。名前が紛らわしいが、「C++に関するオプション」ではない。
- LDFLAGS…リンカ(ld)に渡すオプション。
#includeもプリプロセッサ命令の一種ですから、-I
はCPPFLAGSに追加します。-L
はLDFLAGSに追加します。CFLAGS/CXXFLAGSは、よく使うところだと最適化オプション(-O*)、警告(-W*)、デバッグ(-g*)あたりかと思います。
ちなみに、オプションではなく実行ファイル名を指定する変数としては、Cコンパイラを指定するCC、C++コンパイラを指定するCXX、Cプリプロセッサを指定するCPP(←これはほぼ使わなさそう)などがあるのでついでに覚えてしまいましょう。
これらの変数は、①Makefile内②makeのコマンドラインオプション③環境変数という3つの方法で指定できますが、**コマンドラインオプションの優先度が最も高く**、Makefile内に何を書いたとしてもコマンドラインオプションでの指定内容に上書きされます。環境変数は最も優先度が低く、Makefile内での各変数の初期値として設定されるので、Makefile内で書き換えることができます。
応用例1: root権限がないところで色々なソフトウェアをビルドしたい
共用のsshサーバーなど、root権限を持っていないところでもC/C++のソフトウェアをコンパイルしたい場合があります。
この場合、~/.myrootのようなフォルダを作っておいて、環境変数は以下のように設定します。
export C_INCLUDE_PATH="$HOME/.myroot/include:$HOME/.myroot/usr/include:$C_INCLUDE_PATH"
export CPLUS_INCLUDE_PATH="$HOME/.myroot/include:$HOME/.myroot/usr/include:$CPLUS_INCLUDE_PATH"
export LIBRARY_PATH="$HOME/.myroot/lib:$HOME/.myroot/usr/lib:$LIBRARY_PATH"
export PKG_CONFIG_PATH="$HOME/.myroot/lib/pkgconfig:$HOME/.myroot/usr/lib/pkgconfig:$PKG_CONFIG_PATH"
これはあくまで最低限の例です。実際にはx86_64-linux-gnuとかも指定する必要があるかもしれません。
その上で、aptとかrpmみたいなパッケージをインストール(rootが必要)ではなくダウンロードだけしてきて、~/.myrootをの中に展開します。すると上記の変数で指定されたフォルダに必要なファイルが入るのでビルドできるようになります。
また、aptやrpmでなく、configureスクリプトを用いてビルドするタイプのライブラリであれば、./configure --prefix=$HOME/.myrootのようにprefixに.myrootを指定すると、そこをルートのようにしてインストールが行われます。
応用例2: BSD系などでclangを使う
BSD系(Mac含む?)では、GNU界隈に由来する(?)ライブラリを入れると/usr/local以下に入ることがありますが、clangがここを見る設定になっていないことがあります。そこで以下のようにしておくと解決します。
export CPLUS_INCLUDE_PATH=/usr/local/include:$CPLUS_INCLUDE_PATH
export C_INCLUDE_PATH=/usr/local/include:$C_INCLUDE_PATH
export LIBRARY_PATH=/usr/local/lib:$LIBRARY_PATH
余談: ユーザー環境変数の設定方法
環境変数を常時設定するには、~/.profileに書きます。~/.bash_profileや~/.bashrcを使うと書いてある記事もありますが、これらはあくまでbashだけが使う設定ファイルなので、~/.profileに書くのが最も正当です。~/.bash_profileでは~/.profileと~/.bashrcの読み込みのみを行います。
詳しくは以下の記事をご覧ください。
Bash: .bashrcと.bash_profileの違いを今度こそ理解する|TechRacho by BPS株式会社
bash の初期化ファイル .profile, .bashrc, .bash_profile の使い分けと管理方針 - A Memorandum
自宅サーバーとしてヘッドレスで動かしているLinux Mintで、ソフトウェアのアップデートなどはxrdp経由でやっているのですが、ミラーサーバーの選択などに使う「ソフトウェアソース」(mintsources)が起動しません。
CUIで直接pkexec mintsources(スタートメニューのコマンドそのまま)を入れてみると、
Error executing command as another user: Not authorized
This incident has been reported.
などと言われます。
調べてみたら、以下のものがでてきました。
mintsources fails to open: Not authorized - Linux Mint Forums
これによると、/usr/share/polkit-1/actions/com.linuxmint.mintsources.policyを編集して、<allow_any>no</allow_any>を<allow_any>auth_admin</allow_any>に変更すると動くらしいです。動きました。
あるいは、ireport - "No protocol specified" when running a sudo/su app on Ubuntu Linux - Stack Overflowのように、xhost si:localuser:rootやxhost +を(非特権ユーザーで)実行してからsudoをつけて目的のコマンドを実行することでも解決するようです。手元では、xed(エディタ)などの場合はこちらしか使えませんでした(policyのほうはそもそも関連するファイルが見当たらない)。こっちのほうが正当かもしれないです。あと、終わったらxhost -si:localuser:rootやxhost -とかで変更を元に戻すといいっぽいです。
あとついでに、xrdpをsystemctlから再起動すると、タイミングによっては(例えば既にxrdp経由で接続中だと)以前のセッションが残ってしまい、そのせいでログイン後に画面が真っ黒でマウスポインタだけ見えるみたいな状態になってしまうことがあります。このときはssh経由とかでps -ef | grep xrdpをして、自分が実行している/usr/lib/xorg/Xorgのプロセスをすべてkillすると、ちゃんと入れるようになります。
概要
特定アプリケーションのTCP・UDP通信を透過的なSocks5プロキシ経由にする方法(Windows・Linux・Androidなど) - turgenev’s blogの外伝という感じで、BSD系のOSに触ってみるついでにredsocksを動かしてみました。(※NetBSDでは動かず)わからないところは適宜↑を読んでください。
普段使いする予定はなく実機に入れるのは面倒だったのでVirtualboxで試しました。
ちなみに、全て「そのPC自体から出ていく通信」(の一部)に透過プロキシを適用するものです。ルーターのような外部からのパケットへの設定はしていません。が、むしろそちらのほうが簡単だと思うので、たぶんこの記事の通りやればできます。
変更後のソースコードはGitHub - ge9/redsocks: transparent redirector of any TCP/UDP connection to proxyにあげてあります。全てDISABLE_SHADOWSOCKS=trueでmake(コマンドはgmakeですが)しています。TCP/UDP両方で動作確認しています。IPv6は確認していません(&多分このままでは動かない)。
FreeBSD
BSD系の中では一番メジャーで、pfSenseの元にもなっています。インストールはそこまで詰まることなくいけました。バージョンは14.0です。
各種パッケージはpkg install gitとかで入るようです。
外部インターフェイスにもともと(Virtualbox側のDHCPにより)10.0.2.15/24が割り当てられていたので10.0.2.25を追加しました。
ifconfig em0 alias 10.0.2.25 netmask 0xffffff00
ここから出ていくパケットに透過プロキシを適用します。テスト用コマンドはいつものstunserverの--localaddr 10.0.2.25です。本当に便利です。
ファイアウォールはipfwを使います。ipfilter(ipf)とは別物です。
上記のifconfigとまとめると以下のようになります。
kldload ipfw
fwcmd=ipfw
ifconfig em0 alias 10.0.2.25 netmask 0xffffff00
$fwcmd add 100 allow all from any to any via lo0
$fwcmd add 500 fwd 127.0.0.1,22222 tcp from 10.0.2.25 to any
$fwcmd add 600 fwd 127.0.0.1,22222 udp from 10.0.2.25 to any
$fwcmd add 700 allow ip from any to any
redsocksではredirector=genericとします。これでとりあえず動くと思います。
ソースコードで修正した点としては、なんかsizeofのあたりでうまくいってなさそうなのをちょっと直したのと、bound_udp_getのbindのところでエラーが出るのを無視したらいけました。
また、FreeBSDには、OpenBSD由来であるpfもあります。結果的に動きませんでしたが一応載せます。/etc/pf.confは以下のようにします。
rdr pass on lo0 proto {tcp, udp} from 10.0.2.25 -> 127.0.0.1 port 22222
pass out quick route-to lo0 from 10.0.2.25
pass
これでちゃんとredsocksにパケットは届くのですが、宛先が本来の宛先ではなく127.0.0.1:22222として取得されてしまっていて正しく動きません。これに関してはOpenBSDのところで述べます。
ipfilterのほうも一応やってみましたがうまくいきませんでした。ipfilterにおいてはNATはipnatというものを使って行うようで、こちらにはrdrという構文がありましたが、普通のDNAT(1.1.1.1:80に来たやつは192.168.1.1:80に流すとか)しかできそうになく、透過プロキシとして動作させる方法は不明です。redsocks自体にはredirector=ipfという設定があるので、何か方法があるような気もするのですが…。
pfSense
有名なFreeBSD派生とのことでpfSenseも使ってみました。
インストール時にインターネットに接続する必要があって、DHCPでやるのですがうまくいかないことがあるので何回かリトライすると通ります。
シェルまで戻ってしまっても、インストーラの起動はpfSense-installerコマンドでいけそうです。
インストール後もまたネットワークのところでちゃんと選んでるのに無限ループ?みたいになってイライラします。enter押すんじゃなくてem0とかちゃんとインターフェイス名入れると通ったりします。また、再起動後も確率的にDHCPが失敗します(というか再起動じゃなくて完全に電源オフ→起動しないとダメ?)。うまくいっていても使用中にいきなり切れたりもします。なんなんですかね。VirtualBoxの問題な気もしますが、普通のFreeBSDでは特に問題ありませんでした。
Using Software from FreeBSD | pfSense Documentationに書いてある通り、そのままだとセキュリティ上の理由でFreeBSD由来のパッケージは無効になっていますが、有効にするとpkg installで入れられるようになります。
clangが見つからないのでgccを入れました。(g++も入っています)
が、sys/types.hが無いとかで各種ソフトウェアのコンパイルはなんか難しそうです。幸いFreeBSD派生であり基本的にはバイナリレベルで互換性があるのでそちらからバイナリを持ってきました。
あとはFreeBSDと全く同様にipfwでやってみたら、なぜかUDPしか動きませんでした。本当に全く同じように設定しているはずなんですが…TCPのほうはそもそも透過プロキシに届いていません。UDPのルールと干渉している雰囲気もないです。原因不明。
pf/ipfは未調査ですがおそらくFreeBSDと同じ状況と思われます。
OpenBSD
NetBSDのforkで、FreeBSDよりはいくぶんマイナーかと思います。堅牢らしいです。
バージョンは7.5です。まずインストールでちょっと詰まりました。パッケージが全部入っててインターネットがなくてもインストールできるCD版のisoを落としたはずなのですが結局CD(cd0)ではなくインターネット(http)にしたらインストールが成功しました。ミラーはrepo.jing.rocksを使いました。追記: cd0のエラーは多分OpenBSD 7.3 on VirtualBox 7: ゲスト OS インストールに失敗 - 原因は I/O APIC 有効化 | OpenBSD Solutions ブログこれかな?再起動したらうまくいったこともありました。感覚的には、ホスト側マシンのメモリ・CPU使用率に余裕があるほうが成功しやすい気がします。
各種パッケージはpkg_add gitとかで入れます。
まず、em0に10.0.2.25を追加するため、/etc/hostname.em0(もともとinet autoconfとだけ書いてある)にalias 10.0.2.25 netmask 255.255.255.0みたいなことを追記し、sh /etc/netstartをしました。
さて、OpenBSDではpfを使います。/etc/pf.confは以下のようにします。
pass # establish keep-state
pass in quick proto {tcp, udp} from 10.0.2.25 to ! 10.0.2.25 divert-to 127.0.0.1 port 22222
pass out quick proto {tcp, udp} from 10.0.2.25 route-to lo0
本当に最低限で、セキュリティ皆無なので注意。透過プロキシの都合上、デフォルトでよくあるset skip on lo0をそのままにしているとたぶんうまくいかないです。to ! のところで10.0.2.25に向かうものだけ除外していますが、これがないとせっかく返ってきた応答パケットがまた透過プロキシに入ってしまうような感じになったので付けました。
pf.confのmanページのdivert-toのところを読むとIP_RECVDSTADDRがなんだかんだとかいろいろ書いてあって、これがカギです。実際、OpenBSD対応にあたっての変更点はこれらに関するものが主です。あとはccコマンドの-ldlが使えないらしいので無効にするのと、リンク時にlibevent関連の関数を見つけられてないようだったのでln -s /usr/local/lib/libevent_core.a /usr/local/lib/libevent.aをしました。あとはFreeBSD向けの変更をそのまま適用してやる感じです。
'Re: pf: difference between rdr-to and divert-to' - MARCにそれっぽいことが書いてありますが、(すくなくともこの記事のやり方だと)divert-toのかわりにrdr-toを使うと元の送り先アドレスが取得できず(最初から127.0.0.1:22222に送られたかのようになってしまう)、うまくいきません。FreeBSDのrdrの挙動もこれが理由です。FreeBSDでは、divert-toは(構文として存在はするものの全く別の動作であり実質的には)使えません。
(すくなくともこの記事のやり方だと)redirector=genericではなくredirector=pfにすると、TCP通信に関しては動きませんでした。ただredsocks側のソースをちゃんと変えれば動きそうな雰囲気はします。
NetBSD
OpenBSDのfork元ですが、ただでさえマイナーなBSD系の中でも近年はほとんど利用者がおらず、OSとしてはかなり厳しい状況のようです。
一応やってみました。バージョンは10.0です。
こっちはCDからでちゃんとインストールできました。
起動すると、まずそもそもIPアドレスが割り当たっていませんでしたがdhcpcd wm0でいけました。
pkg_addでgitを入れたいのですがエラーが出ます。どうやらPKG_PATH変数を設定しないといけないようです。日本のミラーにしてみます。ftpだとだめでhttpだといけました。
export PKG_PATH="http://ftp.allbsd.org/pkgsrc/packages/NetBSD/amd64/10.0/All/"
ところが、衝突もしてないのにdependencyを自動で入れてくれません。仕方ないので足りないと言われたものを入れていったら一応できましたが…さすがに不便です。
で、IP_RECVDSTPORTが定義されていないというエラーで詰まりました。NetBSDのpf.confを見ると、そもそもdivertがありません。なんか無理っぽい雰囲気がしたのとさすがに需要がなさすぎるのでここでやめました。pf.confも書いていません。
まとめ
過疎っていて先行きは怪しそうですがBSD系にちょっと触ることができてよかったです。
概要
マイクラの終盤、つまりエリトラを入手して以降のゲームプレイでもそれほど便利な方法が確立されていなかったタスクとしてmobの移動があります。
短距離ならエサ誘導やリード+徒歩(あるいはウマ)などもありますが、長距離だと手間がかかります。ネザー経由でトロッコや氷ボート通路で輸送する方法もありますが、準備が大変です。実はネザー岩盤上をウマで走るという方法がありますが、これは半分チートのようなもの(岩盤上に行けてしまうのはバグ扱い)なので考えないことにします。
ところで、なんと1.21のPre-release 1から、Java版でもボートにリードが付けられるようになりました。リードが直接付けられない敵mobやパンダや村人でもボートに載せればリードで引っ張れます。ボートは段差を超えられないという難点がありますが、もしリードを付けたままエリトラで飛ぶことができれば自由に移動できます。
そこで、この記事では、エリトラとリードを使ってmob(ボートも入りますがまとめてmobと呼ぶことにします)を空輸する方法を紹介します。なお、Java Editionのみ想定します(ボート以外のmobについては1.20以前でも問題なく使えます)。後述しますが統合版では筆者が試した限りそれほどうまくいかないようです。
方法
もちろん基本的にはリードでmobをつないだまま空を飛ぶというだけです。それが言うほど簡単ではないのでコツを紹介しようという感じです。
リードは基本的に以下のような性質を持っていると思います。
・長さが一定以上になると切れる。
・つないでいるmobに与えられる力に上限がある。つまり、mobを一気に加速・減速させることができない。
逆に言えば、プレイヤー・mobともに同じ速度で同じ方向に移動し続ける限りは、どれだけ速度が速くてもリードが切れることはありません。
試しに、高いところでmobをリードにつないでから花火を使わずに滑空して降りてみましょう。高度が下がるにつれてだんだんと速度は増しますが、リードは切れることなく、無事にmobを運べるはずです。F5で三人称視点にするとリードが見えるのでわかりやすいです。
このとき、高速で滑空中にすばやく向きを(どの方向にでも)変えると、急激な速度変化による強い力(加速度)がmobに伝わらずリードは切れてしまいます。エリトラ空輸の最重要事項は、急激な方向転換をしないことです。あるいは、上を向いて速度をかなり落としてからであれば方向転換は安全です。
(一応、非常にラグの少ない環境ではそこまで気にせず飛行してもリードが切れない場合もあるようです。そのような環境でプレイしている方はこの記事を読む必要はないかもしれません。)
高いところから滑空するだけなので一定の距離しか進めないため、長距離移動をしようと思ったら毎回足場を建てる必要があります。ちなみに足場は、足場ブロック(scaffolding)ではなく、ねじれツタ(ネザーの青いほうのツタ)をつかうのが断然おすすめです。骨粉1つで何ブロックか伸びますし、ツタが足りなくなっても増やせますし、骨粉は骨ブロックにすれば大量に持ち運べます。
花火での加速
とはいえ花火無しの滑空だけだと、そこまで便利とも言えません。何よりわざわざ紹介する意味がありません。実は、エリトラでmobを空輸しながら花火を使用して飛び続けることも可能です。しかしこれは慣れが必要です。
花火というのは使用した瞬間からいきなり最高速度になるので、静止あるいは低速飛行の状態からいきなり花火を使うとリードが切れてしまいます。
ではどうするかというと、まず滑空中のときは、下を向いてある程度の高速度域に達してから花火を使用することでリードが切れるのを防ぐことができます。一旦加速が成功してしまえば、あとは花火が効いている間の数秒間にゆっくりと上を向くことで高度を稼ぐことができます。ただ、毎回下を向いて花火を使って上を向いてと繰り返していると下向きに花火を使う割合が多くなって無駄が増えます。なので、花火を使う際は連続して何度か花火を使って、上を向きながらしばらく高速度域を維持するのがいいと思います。
具体的には、
地面が見えてきたら下を向いて加速し、花火を使用→ゆっくりと上を向きつつ速度が落ちないように何度か花火を追加→再び地面が見えなくなったら加速を停止して、滑空に入る
という感じです。
次に地面からの離陸ですが、これは結構難しいです。どうやるかというと、加速度を軽減するためにジグザグに発進します。最初は水平方向を向いて発進し、0.2秒くらいの間隔で視線方向を左右に90度-180度ほど変えながらゆっくりと上を向きます。せっかく飛び立ってもあまり高度が稼げず安定飛行に移れない場合もあるので、平地や少し高い丘あたりから始めるといいと思います。失敗してもボートがあれば落下ダメージを避けられるのはありがたいところです。
搭乗・騎乗したプレイヤーの輸送
mobを運べるなら、プレイヤーが搭乗したボートや騎乗したmobを運べばプレイヤーも運べるのでは?というのが思いつきます。
結論からいうと可能ですが、面白いことに、mob(ボート)をプレイヤーが操作できない状態にしておく必要があります。つまりサドルを付けていないウマや、ニンジン付きの棒を持っていないときのブタや、(そもそも操作ができない)ラマや、プレイヤーが騎乗したブタが乗ったボートなどであれば可能です。これは飛ばなくても平地でも試せるのですが、プレイヤーが操作できる状態の動物だとリードの動きにほとんど追従しなくなります。飛んでいる途中で操作できる状態にする(サドルを付けるとかニンジン付きの棒を持つとか)と、その瞬間にリードが外れます。
ボートやラクダを使えばプレイヤーを2人まで運べます。ラクダは大きいのでボートに乗りませんが、子供のラクダをボートに乗せた状態で成長させると乗ったままなので、4人まで運べると思います。
また、騎乗しているプレイヤーがさらにリードをもって別のmobを引っ張って数珠繋ぎにすればもっとたくさん運べて面白いのでは?というのも思いつきますが、これは割と不安定です。最後の動画の通り、リードで引っ張られるmobは上下にランダムに動くので、そのせいで余計な加速度が後ろのmobに伝わって切れやすくなります。特に発進時が危険です。これに加えて、リードで吊るされているmobは吊るしている側より低い高度をとるので、エリトラで飛んでいるプレイヤーはその分余計に高度を確保しなければなりません。
あと、ラグに関しては、飛行しているプレイヤーだけでなく騎乗しているプレイヤーの通信環境も影響するので注意が必要です。
その他注意点
急激な方向転換ができないため、目の前にいきなり高山が出現した場合などは越えるのが難しくなります。ボートに乗せているならリードが切れても基本的には安全ですが、粉雪がありそうな場合などは、安全運転にしたほうがいいでしょう。
高山を避けるにはあらかじめ高高度を確保しておく方法もあります。この際、霧があったり新月の夜だったりすると方向感覚がつかみづらくなりますが、F3+Gでチャンク境界を表示すると非常に飛びやすくなります。F3を使うことに抵抗がないならこれもおすすめです。
また、ラグが大きくプレイヤーの位置が途中で戻されたりするような状況だとそのときにリードが切れやすくなります。劣悪なプレイ環境では残念ながらこのテクニックは使えません。一応、表示チャンクを削るなどしてラグを改善できる可能性はあります。あとは、そこそこのスペックのサーバーであってもチャンクの新規生成時はかなり負荷が大きくなります。できるだけチャンクが既に生成されている場所を飛ぶように心がけ、未生成エリアではジグザグに方向転換をして速度を落とすなどした方がいいと思います。
ちなみに統合版でも試してみましたが、手元の環境では同じようにやるとリードが切れてしまいました。動作原理がちょっと違うような気がします。
動画
実際にやってみて動画を撮ってみました。
1.21のボート+リード+エリトラ飛行の様子
mobでもボートでもプレイヤーが操作できる状態だとリードで動かすのが難しいので動物を挟むとうまくいく
急加速を避けるために下向き加速しておいてから花火を使うのがコツ
滑空時も高速度域での方向転換はNG
最後に切れたのはチャンク生成ラグのため pic.twitter.com/pWoQPdIhmA— ツルゲーネフ (@e9g) 2024年5月30日
地面からの発進、後ろ側のプレイヤー視点 pic.twitter.com/3IoCch00uR
地面からの発進の例 pic.twitter.com/g0gflYSETg
— ツルゲーネフ (@e9g) 2024年5月30日
まとめ
以上のように、ちゃんと気を付ければ、マイクラでmobを空輸することは可能です。