セーブポイント

特にジャンルの決まってない雑記です。

サバイバルで岩盤をアイテムとして入手するテクについての理解 Pt.1 [Minecraft 1.12]

本当は解説記事として出したかったものなのですが、理論があまりにも自分にとって難解だったので、現時点での理解をまとめたメモです。
Minecraft 1.12における話であることに注意

はじめに

先日、以下の動画を見つけたのですが、謎の技術すぎた(当社比)ので色々調べました。が、元情報が英語ゆえあまり理解できていないので、このようにバラバラに記事にしていくことにしました。


www.youtube.com

この記事は、上の動画と以下の動画から得たざっくりした情報に加えて、自分のために補足した情報を記載しています。英語が出来る方なら、一次情報を当たった方が良いと思います。

ところで、ここまで読むとこの記事のタイトルと中身が若干一致してない?と思うかもしれません。タイトルからの内容の想像の容易さ・キャッチーさを優先してこのようなタイトルにしてしまったのですが、実際は後に説明する技術によって岩盤のみならずワールド上に存在すらしないブロックを入手できます。この点は申し訳ありません。

キーワード

  • Population Supression
  • Update Suppression
  • Instant Tile Tick / Instant Falling
  • Blockstate Corruption
  • マルチスレッド

岩盤についての前提知識

さて、あなたはMinecraftの岩盤というブロックについてどれくらい知っていますか?

minecraft.fandom.com基本的な情報については上記のMinecraft Wikiの通りで、サバイバルモードにおいては採掘不可能であるブロックのうちの1つです。ただし、これは破壊も不可能ということではないというのは皆さんが知っている通りで、バージョンごとに様々なバグが存在してサバイバルでも岩盤を破壊することができます。ですが、このようなバグを用いて岩盤を破壊しても、破壊した岩盤ブロックをアイテムとして入手することはできません。では、どうすれば岩盤をアイテム化できるでしょうか。岩盤についてもう少し詳しく見ていきましょう。

ソースコード中では岩盤は以下のようにゲームに登録されています。

registerBlock(7, "bedrock", (new BlockEmptyDrops(Material.ROCK)).setBlockUnbreakable().setResistance(6000000.0F).setSoundType(SoundType.STONE).setUnlocalizedName("bedrock").disableStats().setCreativeTab(CreativeTabs.BUILDING_BLOCKS));

色々な属性が付加されていますが、注目すべきはsetBlockUnbreakableメソッドです。メソッドの定義を辿ると、以下のように記述されています。

setBlockUnbreakable

Minecraftのブロックは、それぞれ様々な硬さ(=採掘にかかる時間)を持ちます。これを設定するのが、Block#setHardnessです。で、上のコードに従うと岩盤の硬さは-1ということになります。「-1ってなんだよ」と思うかもしれませんが、マイクラ内では硬さが負の値であると採掘不可能という扱いになります*1。もし硬さが正の巨大な実数であれば理論上時間さえかければ破壊可能ですが、そうはなっていません。

ただ、なんらかの方法で岩盤が採掘できたとしても、岩盤をアイテムとして入手することはできません。これが岩盤アイテム化を難しくしている要因の1つです。先ほど岩盤の登録に用いられていたBlockEmptyDropsというクラスを見てみます。

public class BlockEmptyDrops extends Block
{
    public BlockEmptyDrops(Material materialIn)
    {
        super(materialIn);
    }

    /**
     * Returns the quantity of items to drop on block destruction.
     */
    public int quantityDropped(Random random)
    {
        return 0;
    }

    /**
     * Get the Item that this Block should drop when harvested.
     */
    public Item getItemDropped(IBlockState state, Random rand, int fortune)
    {
        return Items.AIR;
    }
}

上記のコードのように岩盤は採掘された際に何もアイテムをドロップしないようにハードコードされているため、真っ当に岩盤を採掘しても何も得られません。

ただし、実は岩盤を採掘したときに岩盤をアイテムとしてドロップさせることができる手法が存在します。それが、ツルハシにシルクタッチのエンチャントを付けることです。シルクタッチは上述したような設定を無視してブロックをドロップさせることができます*2

以上の内容は以下の動画においても解説されているので、動画で確認したい方は参考にしてください。

www.youtube.com

考えるべきこと

さて、シルクタッチのツルハシで岩盤を採掘すればいいということは分かったものの、じゃあどうやって岩盤を採掘するのという話です。実際は硬さ-1のブロックなわけですから、当然正攻法ではどうしようもありません。どうにかして、ゲームにシルクタッチ付きのツルハシで岩盤を採掘したと誤認させる必要があります。

考えられる解決策

プレイヤーがワールド上のブロックを左クリックしたときに発火する処理について見てみます。

PlayerInteractionManager#onBlockClicked

posはプレイヤーが左クリックしたブロックの座標、sideはクリックした面です。

1つ目のifブロック内でブロックが左クリックされたときの処理の呼び出し、および採掘スピードfの計算を行っています。2つ目のifブロックは、ブロックがInstant mining可能であるかの判定をしています。

ここがよくまだ分かっていないんですが、ブロックがInstant mining可能であるとき、ブロックが採掘されてからドロップされるまでの間にブロックをすり替えることが可能です。岩盤のアイテム化は、この特性を用いて行います。

実際にどうやってブロックをすり替えるかですが、上述したコード内を見ると2択で、燃えているブロックを消火する処理(195行目)をトリガーにするか、ブロックを左クリックしたこと(201行目)をトリガーにするかです。で、後者で今のところ上手くいった例は無いようで*3、参考にした動画では消火の処理を利用していました。

次回

思っていたよりも1つの記事が長くなってしまったので、ここで分割します。次回は、実際に消火の処理をトリガーにどうやって岩盤を採掘するかについて見ていきます。岩盤のアイテム化技術について解説が終わったら、Falling Block Swapに手をつけたいです。

*1:ちなみに、ツールの採掘速度を負の値にすると何も掘れないツールになります

*2:例外があり、FullCubeでないエンドポータルフレームなどのブロックはシルクタッチを利用しても入手できません

*3:レッドストーン鉱石を利用しようと考えていたようですが、レッドストーン鉱石をInstant mining可能にするには効率強化8が必要です