02.005.Flower position - MCJE-Tech-Community/Datapack-WIki GitHub Wiki

🌹 花や竹の位置計算

 基本的にどのブロックも、当たり判定が場所によって変わるなんて事はありませんが、花や竹だけは一見ランダムに当たり判定の位置が変化します。ただワールドを変えて置いたりするとわかるように、これらの設置位置はx座標とz座標だけで決まっているため、頑張れば計算することができます。あまり使い道はない上級者向けですが、ブロックの当たり判定をコマンドで取得したい時何かに使えるかもしれません。こちらはファイルの配布もしています。


▲花や竹の位置はコマンドで計算できる!

アルゴリズム

 intsucさんの解析によると、花や竹の位置の計算プログラムは以下のようになっているみたいです。

public final class Main {
   public static void main(String[] args) {
       final var x = Integer.parseInt(args[0]);
       final var z = Integer.parseInt(args[1]);
       System.out.println(getOffset(x, z));
   }

   private static Offset getOffset(final int x, final int z) {
       final var seed = getSeed(x, z);
       final var maxHorizontalOffset = 0.25f;
       final var offsetX = clamp(((double) ((float) (seed & 15L) / 15.0F) - 0.5) * 0.5, -maxHorizontalOffset, maxHorizontalOffset);
       final var offsetZ = clamp(((double) ((float) (seed >> 8 & 15L) / 15.0F) - 0.5) * 0.5, -maxHorizontalOffset, maxHorizontalOffset);
       return new Offset(offsetX, offsetZ);
   }

   private static long getSeed(final int x, final int z) {
       var seed = (x * 3129871L) ^ (long) z * 116129781L;
       seed = seed * seed * 42317861L + seed * 11L;
       return seed >> 16;
   }

   private static double clamp(final double value, final double min, final double max) {
       return value < min ? min : Math.min(value, max);
   }

   private record Offset(double x, double z) {
   }
}

まずxzを元にseedを計算し、そのseedを弄り回して最終的な座標を計算しているようです。 使っている演算は 足し算、掛け算、ビットシフト、論理和、排他的論理和(XOR)の5種類だけなので、複雑そうですが再現可能です。おそらく疑似乱数生成のアルゴリズムの関係で、全部の演算が数が増加する方向にしか変化しないようになっていたり、下の方のビットしか最終的に使わなかったりと意外とスコアボードで再現が可能な作りになっています。排他的論理和の計算には、オーバーフロー式のビット判定を使っています。
ちなみにLはlong型、FはFloat型を意味した文字です。

流れとしては

  1. x * 3129871Lz * 116129781L を計算
  2. x * 3129871Lz * 116129781L との排他的論理和(XOR)を計算してseedとする
  3. seed = seed * seed * 42317861L + seed * 11L を計算
  4. seedを16桁右にビットシフトする
  5. seed & 15Lseed >> 8 & 15Lを計算する(seedの1~4ビット目と9~12ビット目を取り出す操作)
  6. x = (((seed & 15L) / 15.0F) - 0.5) * 0.5z = (((seed >> 8 & 15L) / 15.0F) - 0.5)を計算する 最終的に小数点の値になるが、スコアボードあ小数点を扱えないので、割り算する前に桁を増やしておく
  7. xzがそれぞれ-0.25~0.25の範囲内かどうか確認する 範囲外なら-0.250.25に丸める
  8. xzがそれぞれ1ブロック内における座標になる

以下コマンド(配布している方と同じ内容)

### 実行点の位置の花/竹等の位置を計算する

## 実行点の座標を取得
    # マーカー召喚
    execute unless entity 4fe002bb-0-0-0-1 run summon item_display ~ ~ ~ {UUID:[I;1340080827,0,0,1],item:{id:"glass",Count:1b},transformation:[0.375f,0f,0f,0f, 0f,0.625f,0f,0.3125f, 0f,0f,0.375f,0f, 0f,0f,0f,1f,]}
    execute align xyz run tp 4fe002bb-0-0-0-1 ~0.5 ~ ~0.5
    # 座標をストレージに保存
    data modify storage _ pos set from entity 4fe002bb-0-0-0-1 Pos

## シードの計算
# 最終的に下位28bit以内しか見ないのでオーバーフローしてても気にしない
    # x * 3129871L ついでに16も掛ける(後の排他的論理和の計算のため)
    execute store result score #x _ run data get storage _ pos[0]
    scoreboard players set _ _ 50077936
    scoreboard players operation #x _ *= _ _
    # (long)z * 116129781L ついでに16も掛ける
    execute store result score #z _ run data get storage _ pos[2]
    scoreboard players set _ _ 1858076496
    scoreboard players operation #z _ *= _ _
    # x ^ z 排他的論理和
        # スコア初期化
        scoreboard players set #seed _ 0
        scoreboard players set _ _ 4
        # 2bit分ずつずらしながら確認
        execute if score #x _ matches ..-1 if score #z _ matches 0.. run scoreboard players add #seed _ 134217728
        execute if score #z _ matches ..-1 if score #x _ matches 0.. run scoreboard players add #seed _ 134217728
        execute if score #x _ matches -1073741824.. unless score #x _ matches 0..1073741823 unless score #z _ matches -1073741824..-1 unless score #z _ matches 1073741824.. run scoreboard players add #seed _ 67108864
        execute if score #z _ matches -1073741824.. unless score #z _ matches 0..1073741823 unless score #x _ matches -1073741824..-1 unless score #x _ matches 1073741824.. run scoreboard players add #seed _ 67108864
        scoreboard players operation #x _ *= _ _
        scoreboard players operation #z _ *= _ _
        execute if score #x _ matches ..-1 if score #z _ matches 0.. run scoreboard players add #seed _ 33554432
        execute if score #z _ matches ..-1 if score #x _ matches 0.. run scoreboard players add #seed _ 33554432
        execute if score #x _ matches -1073741824.. unless score #x _ matches 0..1073741823 unless score #z _ matches -1073741824..-1 unless score #z _ matches 1073741824.. run scoreboard players add #seed _ 16777216
        execute if score #z _ matches -1073741824.. unless score #z _ matches 0..1073741823 unless score #x _ matches -1073741824..-1 unless score #x _ matches 1073741824.. run scoreboard players add #seed _ 16777216
        scoreboard players operation #x _ *= _ _
        scoreboard players operation #z _ *= _ _
        execute if score #x _ matches ..-1 if score #z _ matches 0.. run scoreboard players add #seed _ 8388608
        execute if score #z _ matches ..-1 if score #x _ matches 0.. run scoreboard players add #seed _ 8388608
        execute if score #x _ matches -1073741824.. unless score #x _ matches 0..1073741823 unless score #z _ matches -1073741824..-1 unless score #z _ matches 1073741824.. run scoreboard players add #seed _ 4194304
        execute if score #z _ matches -1073741824.. unless score #z _ matches 0..1073741823 unless score #x _ matches -1073741824..-1 unless score #x _ matches 1073741824.. run scoreboard players add #seed _ 4194304
        scoreboard players operation #x _ *= _ _
        scoreboard players operation #z _ *= _ _
        execute if score #x _ matches ..-1 if score #z _ matches 0.. run scoreboard players add #seed _ 2097152
        execute if score #z _ matches ..-1 if score #x _ matches 0.. run scoreboard players add #seed _ 2097152
        execute if score #x _ matches -1073741824.. unless score #x _ matches 0..1073741823 unless score #z _ matches -1073741824..-1 unless score #z _ matches 1073741824.. run scoreboard players add #seed _ 1048576
        execute if score #z _ matches -1073741824.. unless score #z _ matches 0..1073741823 unless score #x _ matches -1073741824..-1 unless score #x _ matches 1073741824.. run scoreboard players add #seed _ 1048576
        scoreboard players operation #x _ *= _ _
        scoreboard players operation #z _ *= _ _
        execute if score #x _ matches ..-1 if score #z _ matches 0.. run scoreboard players add #seed _ 524288
        execute if score #z _ matches ..-1 if score #x _ matches 0.. run scoreboard players add #seed _ 524288
        execute if score #x _ matches -1073741824.. unless score #x _ matches 0..1073741823 unless score #z _ matches -1073741824..-1 unless score #z _ matches 1073741824.. run scoreboard players add #seed _ 262144
        execute if score #z _ matches -1073741824.. unless score #z _ matches 0..1073741823 unless score #x _ matches -1073741824..-1 unless score #x _ matches 1073741824.. run scoreboard players add #seed _ 262144
        scoreboard players operation #x _ *= _ _
        scoreboard players operation #z _ *= _ _
        execute if score #x _ matches ..-1 if score #z _ matches 0.. run scoreboard players add #seed _ 131072
        execute if score #z _ matches ..-1 if score #x _ matches 0.. run scoreboard players add #seed _ 131072
        execute if score #x _ matches -1073741824.. unless score #x _ matches 0..1073741823 unless score #z _ matches -1073741824..-1 unless score #z _ matches 1073741824.. run scoreboard players add #seed _ 65536
        execute if score #z _ matches -1073741824.. unless score #z _ matches 0..1073741823 unless score #x _ matches -1073741824..-1 unless score #x _ matches 1073741824.. run scoreboard players add #seed _ 65536
        scoreboard players operation #x _ *= _ _
        scoreboard players operation #z _ *= _ _
        execute if score #x _ matches ..-1 if score #z _ matches 0.. run scoreboard players add #seed _ 32768
        execute if score #z _ matches ..-1 if score #x _ matches 0.. run scoreboard players add #seed _ 32768
        execute if score #x _ matches -1073741824.. unless score #x _ matches 0..1073741823 unless score #z _ matches -1073741824..-1 unless score #z _ matches 1073741824.. run scoreboard players add #seed _ 16384
        execute if score #z _ matches -1073741824.. unless score #z _ matches 0..1073741823 unless score #x _ matches -1073741824..-1 unless score #x _ matches 1073741824.. run scoreboard players add #seed _ 16384
        scoreboard players operation #x _ *= _ _
        scoreboard players operation #z _ *= _ _
        execute if score #x _ matches ..-1 if score #z _ matches 0.. run scoreboard players add #seed _ 8192
        execute if score #z _ matches ..-1 if score #x _ matches 0.. run scoreboard players add #seed _ 8192
        execute if score #x _ matches -1073741824.. unless score #x _ matches 0..1073741823 unless score #z _ matches -1073741824..-1 unless score #z _ matches 1073741824.. run scoreboard players add #seed _ 4096
        execute if score #z _ matches -1073741824.. unless score #z _ matches 0..1073741823 unless score #x _ matches -1073741824..-1 unless score #x _ matches 1073741824.. run scoreboard players add #seed _ 4096
        scoreboard players operation #x _ *= _ _
        scoreboard players operation #z _ *= _ _
        execute if score #x _ matches ..-1 if score #z _ matches 0.. run scoreboard players add #seed _ 2048
        execute if score #z _ matches ..-1 if score #x _ matches 0.. run scoreboard players add #seed _ 2048
        execute if score #x _ matches -1073741824.. unless score #x _ matches 0..1073741823 unless score #z _ matches -1073741824..-1 unless score #z _ matches 1073741824.. run scoreboard players add #seed _ 1024
        execute if score #z _ matches -1073741824.. unless score #z _ matches 0..1073741823 unless score #x _ matches -1073741824..-1 unless score #x _ matches 1073741824.. run scoreboard players add #seed _ 1024
        scoreboard players operation #x _ *= _ _
        scoreboard players operation #z _ *= _ _
        execute if score #x _ matches ..-1 if score #z _ matches 0.. run scoreboard players add #seed _ 512
        execute if score #z _ matches ..-1 if score #x _ matches 0.. run scoreboard players add #seed _ 512
        execute if score #x _ matches -1073741824.. unless score #x _ matches 0..1073741823 unless score #z _ matches -1073741824..-1 unless score #z _ matches 1073741824.. run scoreboard players add #seed _ 256
        execute if score #z _ matches -1073741824.. unless score #z _ matches 0..1073741823 unless score #x _ matches -1073741824..-1 unless score #x _ matches 1073741824.. run scoreboard players add #seed _ 256
        scoreboard players operation #x _ *= _ _
        scoreboard players operation #z _ *= _ _
        execute if score #x _ matches ..-1 if score #z _ matches 0.. run scoreboard players add #seed _ 128
        execute if score #z _ matches ..-1 if score #x _ matches 0.. run scoreboard players add #seed _ 128
        execute if score #x _ matches -1073741824.. unless score #x _ matches 0..1073741823 unless score #z _ matches -1073741824..-1 unless score #z _ matches 1073741824.. run scoreboard players add #seed _ 64
        execute if score #z _ matches -1073741824.. unless score #z _ matches 0..1073741823 unless score #x _ matches -1073741824..-1 unless score #x _ matches 1073741824.. run scoreboard players add #seed _ 64
        scoreboard players operation #x _ *= _ _
        scoreboard players operation #z _ *= _ _
        execute if score #x _ matches ..-1 if score #z _ matches 0.. run scoreboard players add #seed _ 32
        execute if score #z _ matches ..-1 if score #x _ matches 0.. run scoreboard players add #seed _ 32
        execute if score #x _ matches -1073741824.. unless score #x _ matches 0..1073741823 unless score #z _ matches -1073741824..-1 unless score #z _ matches 1073741824.. run scoreboard players add #seed _ 16
        execute if score #z _ matches -1073741824.. unless score #z _ matches 0..1073741823 unless score #x _ matches -1073741824..-1 unless score #x _ matches 1073741824.. run scoreboard players add #seed _ 16
        scoreboard players operation #x _ *= _ _
        scoreboard players operation #z _ *= _ _
        execute if score #x _ matches ..-1 if score #z _ matches 0.. run scoreboard players add #seed _ 8
        execute if score #z _ matches ..-1 if score #x _ matches 0.. run scoreboard players add #seed _ 8
        execute if score #x _ matches -1073741824.. unless score #x _ matches 0..1073741823 unless score #z _ matches -1073741824..-1 unless score #z _ matches 1073741824.. run scoreboard players add #seed _ 4
        execute if score #z _ matches -1073741824.. unless score #z _ matches 0..1073741823 unless score #x _ matches -1073741824..-1 unless score #x _ matches 1073741824.. run scoreboard players add #seed _ 4
        scoreboard players operation #x _ *= _ _
        scoreboard players operation #z _ *= _ _
        execute if score #x _ matches ..-1 if score #z _ matches 0.. run scoreboard players add #seed _ 2
        execute if score #z _ matches ..-1 if score #x _ matches 0.. run scoreboard players add #seed _ 2
        execute if score #x _ matches -1073741824.. unless score #x _ matches 0..1073741823 unless score #z _ matches -1073741824..-1 unless score #z _ matches 1073741824.. run scoreboard players add #seed _ 1
        execute if score #z _ matches -1073741824.. unless score #z _ matches 0..1073741823 unless score #x _ matches -1073741824..-1 unless score #x _ matches 1073741824.. run scoreboard players add #seed _ 1
    # seed = seed * seed * 42317861L + seed * 11L の計算
    scoreboard players operation #x _ = #seed _
    scoreboard players operation #seed _ *= #seed _
    scoreboard players set _ _ 42317861
    scoreboard players operation #seed _ *= _ _
    scoreboard players set _ _ 11
    scoreboard players operation #x _ *= _ _
    execute store result score #x _ store result score #z _ run scoreboard players operation #seed _ += #x _

## オフセットの計算
    #seed >> 16, seed & 15L, seed >> 8 & 15L の計算
        # 下を切る
        scoreboard players set _ _ 65536
        scoreboard players operation #x _ /= _ _
        scoreboard players set _ _ 16777216
        scoreboard players operation #z _ /= _ _
        # 上を切る
        scoreboard players set _ _ 16
        scoreboard players operation #x _ %= _ _
        scoreboard players operation #z _ %= _ _
        # 少数計算の為に桁を増やす
        scoreboard players set _ _ 10000
        scoreboard players operation #x _ *= _ _
        scoreboard players operation #z _ *= _ _
    # /15.0F
    scoreboard players set _ _ 3
    scoreboard players operation #x _ /= _ _
    scoreboard players operation #z _ /= _ _
    # -0.5F
    scoreboard players remove #x _ 25000
    scoreboard players remove #z _ 25000

## 出力
    # 座標を計算
        data modify storage _ pos set value [0f,0.3125f,0f]
        #x
        execute store result storage _ pos[0] float 0.00001 run scoreboard players get #x _
        #z
        execute store result storage _ pos[2] float 0.00001 run scoreboard players get #z _
    #title @s actionbar {"translate":"(%s,%s)","with":[{"nbt":"pos[0]","storage":"_"},{"nbt":"pos[2]","storage":"_"}]}
    # 反映
    data modify entity 4fe002bb-0-0-0-1 transformation.translation set from storage _ pos
    # スコアホルダーの削除
    scoreboard players reset #x
    scoreboard players reset #z
    scoreboard players reset #seed
⚠️ **GitHub.com Fallback** ⚠️