Negative Koordinaten stören Chunk-Berechnungen an zwei Stellen, nicht nur an einer
Die abschneidende Division platziert Block −1 in Chunk 0 statt −1, und ein einfaches % ergibt einen In-Chunk-Offset von −1 statt 15. Beides ist falsch und sieht erst richtig aus, bis man westlich des Spawns geht.
Jede Chunk-Berechnung ist im positiven Quadranten trivial und in den anderen drei falsch. Es gibt genau zwei Stellen, an denen sie falsch läuft, sie sind unabhängig voneinander, und beide liefern plausible Ergebnisse.
Die beiden Operationen
chunk = floor(block / 16) not trunc(block / 16)
offset = ((block % 16) + 16) % 16 not block % 16
Region-Koordinaten sind dasselbe Paar, eine Ebene höher, mit 32 statt 16:
region = floor(chunk / 32) -> r.<x>.<z>.mca
regionOff = ((chunk % 32) + 32) % 32
Eine Region ist also 32 × 32 Chunks, was 512 × 512 Blöcken entspricht.
Wo jede zuschlägt
Division. Die meisten Sprachen schneiden in Richtung Null ab, und floor rundet in Richtung negativer Unendlichkeit (negative Infinity). Sie stimmen für positive Zahlen überein und weichen für jede negative Zahl ab, die kein exaktes Vielfaches ist:
- Block
−1→floor(−1/16) = −1✓, abertrunc(−1/16) = 0✗
Block −1 ist ein Block westlich des Ursprungs und gehört zu Chunk −1. Das Abschneiden platziert ihn in Chunk 0, zusammen mit Block +1. Jeder negative Chunk-Index ist um eins zu hoch.
Restwert. In JavaScript, Java, C und den meisten anderen Sprachen behält % das Vorzeichen des linken Operanden bei:
- Block
−1→ korrekter Offset15, aber−1 % 16 = −1✗
Ein Offset von −1 ist überhaupt keine Position innerhalb eines 16 Blöcke breiten Chunks. Das Indizieren eines Block-Arrays damit führt entweder zu einem Fehler oder liest stillschweigend die falsche Zelle.
Ein ausgearbeitetes Beispiel
Block −1290 auf einer Achse:
| Schritt | Korrekt | Naiv |
|---|---|---|
| Chunk | floor(−1290/16) = −81 | trunc = −80 ✗ |
| Offset im Chunk | 6 | −1290 % 16 = −10 ✗ |
| Region | floor(−81/32) = −3 | trunc = −2 ✗ |
| Offset in der Region | 15 | −81 % 32 = −17 ✗ |
Vier Werte, vier falsche Antworten, keine davon so weit außerhalb des Bereichs, dass sie offensichtlich fehlerhaft aussieht. Region −3 erstreckt sich über die Chunks −96 bis −65, und Chunk −81 liegt 15 vom Anfang entfernt – was genau dem korrigierten Restwert entspricht.
Die Nether-Konvertierung ist in eine Richtung verlustbehaftet
Die Umrechnung von der Oberwelt in den Nether teilt durch 8 und rundet ebenfalls ab:
netherX = floor(overworldX / 8)
Zurück multipliziert man mit 8. Das ist kein Rundtrip. floor verwirft den Rest, sodass die Rückkehr auf einem Vielfachen von 8 landet:
- Oberwelt
1000→ Nether125→ zurück zu1000✓ - Oberwelt
1007→ Nether125→ zurück zu1000✗ — sieben Blöcke zu kurz
Der Fehler beträgt 0 bis 7 Blöcke pro Achse, also bis zu 7 auf X und 7 auf Z gleichzeitig. Das ist der ganze Grund, warum eine präzise Portalverknüpfung die Nether-Koordinate aufgeschrieben haben muss, anstatt sie neu abzuleiten: Sobald man geteilt hat, ist die Oberweltposition, von der sie stammte, nicht mehr wiederherstellbar.
Für einen Nether-Hub spielt dies selten eine Rolle – 7 Blöcke liegen innerhalb des Erfassungsradius eines Portals. Für die Verknüpfung zweier Portale, die sich nicht gegenseitig den Verkehr stehlen dürfen, ist es jedoch von großer Bedeutung.
Negative Oberwelt-Koordinaten verschlimmern die Situation auf die bekannte Weise: Oberwelt −1 ergibt Nether floor(−1/8) = −1, während das Abschneiden 0 ergibt und Sie auf die falsche Seite der Achse schickt.