負の座標がチャンク計算を2箇所で狂わせる
切り捨て除算により、ブロック-1がチャンク-1ではなくチャンク0に配置され、単純な%演算ではチャンク内オフセットが15ではなく-1になります。どちらも間違っており、スポーン地点の西に行くまでは正しく見えます。
すべてのチャンク計算は、正の象限では些細なことですが、他の3つの象限では間違っています。間違っている箇所は正確に2つあり、それぞれ独立しており、どちらももっともらしい結果を生成します。
2つの操作
chunk = floor(block / 16) not trunc(block / 16)
offset = ((block % 16) + 16) % 16 not block % 16
リージョン座標は、16の代わりに32を使用する、1レベル上の同じペアです。
region = floor(chunk / 32) -> r.<x>.<z>.mca
regionOff = ((chunk % 32) + 32) % 32
したがって、1つのリージョンは32 × 32チャンク、つまり512 × 512ブロックです。
それぞれの問題点
除算。 ほとんどの言語はゼロに向かって切り捨てますが、floorは負の無限大に向かって丸めます。これらは正の値では一致しますが、正確な倍数ではないすべての負の値では一致しません。
- ブロック
−1→floor(−1/16) = −1✓、しかしtrunc(−1/16) = 0✗
ブロック-1は原点の西1ブロックにあり、チャンク-1に属します。切り捨てにより、ブロック+1と同様にチャンク0に配置されます。すべての負のチャンクインデックスは1つ高くなります。
剰余。 JavaScript、Java、C、およびその他のほとんどの言語では、%は左オペランドの符号を保持します。
- ブロック
−1→ 正しいオフセット15、しかし−1 % 16 = −1✗
オフセット-1は、16幅のチャンク内の位置ではありません。これを使用してブロック配列をインデックス付けすると、エラーが発生するか、誤ったセルがサイレントに読み取られます。
具体例
ある軸上のブロック -1290:
| ステップ | 正しい値 | 素朴な値 |
|---|---|---|
| チャンク | floor(−1290/16) = -81 | trunc = -80 ✗ |
| チャンク内のオフセット | 6 | −1290 % 16 = -10 ✗ |
| リージョン | floor(−81/32) = -3 | trunc = -2 ✗ |
| リージョン内のオフセット | 15 | −81 % 32 = -17 ✗ |
4つの値、4つの間違った答え、どれも明らかに壊れているとわかるほど範囲外ではありません。リージョン-3はチャンク-96から-65にまたがり、チャンク-81はその開始から15番目に位置します。これは、修正された剰余が返す値とまったく同じです。
ネザー変換は一方向で情報が失われる
オーバーワールドからネザーへの変換は8で除算し、さらに切り捨てます。
netherX = floor(overworldX / 8)
戻る場合は8を掛けます。これは往復ではありません。floorは剰余を破棄するため、戻ると8の倍数の位置に着地します。
- オーバーワールド
1000→ ネザー125→ 戻って1000✓ - オーバーワールド
1007→ ネザー125→ 戻って1000✗ — 7ブロック不足
エラーは軸ごとに0から7ブロックなので、XとZで同時に最大7ブロックになります。これが、正確なポータルリンクにネザー座標を再導出するのではなく書き留める必要がある理由のすべてです。一度除算すると、それが由来するオーバーワールドの位置は回復できなくなります。
ネザーハブの場合、これはめったに問題になりません。7ブロックはポータル自身の捕捉半径内です。互いのトラフィックを奪ってはならない2つのポータルをリンクする場合、これは非常に重要です。
負のオーバーワールド座標は、おなじみの方法でさらに悪化させます。オーバーワールド −1はネザー floor(−1/8) = −1を与えますが、切り捨ては 0を与え、軸の反対側に送ります。