Les coordonnées négatives faussent les calculs de chunks à deux endroits, pas un seul
La division par troncature place le bloc −1 dans le chunk 0 au lieu de −1, et un simple % donne un décalage intra-chunk de −1 au lieu de 15. Les deux sont faux, et les deux semblent corrects jusqu'à ce que vous alliez à l'ouest du point d'apparition.
Chaque calcul de chunk est trivial dans le quadrant positif et faux dans les trois autres. Il y a exactement deux endroits où cela ne va pas, ils sont indépendants l'un de l'autre, et les deux produisent des réponses qui semblent plausibles.
Les deux opérations
chunk = floor(block / 16) not trunc(block / 16)
offset = ((block % 16) + 16) % 16 not block % 16
Les coordonnées de région sont la même paire, un niveau au-dessus, avec 32 au lieu de 16 :
region = floor(chunk / 32) -> r.<x>.<z>.mca
regionOff = ((chunk % 32) + 32) % 32
Ainsi, une région est de 32 × 32 chunks, ce qui représente 512 × 512 blocs.
Où chacun pose problème
Division. La plupart des langages tronquent vers zéro, et floor arrondit vers l'Infinité négative. Ils sont d'accord pour les positifs et en désaccord pour chaque négatif qui n'est pas un multiple exact :
- bloc
−1→floor(−1/16) = −1✓, maistrunc(−1/16) = 0✗
Le bloc −1 est un bloc à l'ouest de l'origine et appartient au chunk −1. La troncature le place dans le chunk 0, à côté du bloc +1. Chaque index de chunk négatif est un de trop.
Reste. En JavaScript, Java, C et la plupart des autres, % conserve le signe de l'opérande gauche :
- bloc
−1→ décalage correct15, mais−1 % 16 = −1✗
Un décalage de −1 n'est pas du tout une position à l'intérieur d'un chunk de 16 de large. L'indexation d'un tableau de blocs avec cela provoque soit une erreur, soit lit silencieusement la mauvaise cellule.
Un exemple détaillé
Bloc −1290 sur un axe :
| étape | correct | naïf |
|---|---|---|
| chunk | floor(−1290/16) = −81 | trunc = −80 ✗ |
| décalage dans le chunk | 6 | −1290 % 16 = −10 ✗ |
| région | floor(−81/32) = −3 | trunc = −2 ✗ |
| décalage dans la région | 15 | −81 % 32 = −17 ✗ |
Quatre valeurs, quatre mauvaises réponses, aucune d'entre elles n'étant suffisamment hors de portée pour paraître manifestement fausse. La région −3 s'étend des chunks −96 à −65, et le chunk −81 se situe à 15 de son début — ce qui est exactement ce que le reste corrigé renvoie.
La conversion du Nether est avec perte dans une direction
De l'Overworld au Nether, on divise par 8, et on arrondit également à l'Infinité négative :
netherX = floor(overworldX / 8)
Le retour multiplie par 8. Ce n'est pas un aller-retour. floor jette le reste, donc le retour vous fait atterrir sur un multiple de 8 :
- Overworld
1000→ Nether125→ retour à1000✓ - Overworld
1007→ Nether125→ retour à1000✗ — sept blocs de moins
L'erreur est de 0 à 7 blocs par axe, donc jusqu'à 7 sur X et 7 sur Z à la fois. C'est la raison pour laquelle le lien précis des portails nécessite que la coordonnée du Nether soit notée plutôt que redérivée : une fois que vous avez divisé, la position de l'Overworld d'où elle provient n'est plus récupérable.
Pour un hub du Nether, cela importe rarement — 7 blocs sont à l'intérieur du rayon de capture d'un portail. Pour relier deux portails qui ne doivent pas se voler mutuellement leur trafic, cela importe beaucoup.
Les coordonnées négatives de l'Overworld aggravent la situation de la manière habituelle : Overworld −1 donne Nether floor(−1/8) = −1, tandis que la troncature donne 0 et vous envoie du mauvais côté de l'axe.