Las coordenadas negativas rompen las matemáticas de los chunks en dos lugares, no en uno
La división por truncamiento coloca el bloque −1 en el chunk 0 en lugar de −1, y un simple % da un desplazamiento dentro del chunk de −1 en lugar de 15. Ambos están mal, y ambos parecen correctos hasta que vas al oeste del punto de aparición.
Cada cálculo de chunk es trivial en el cuadrante positivo y erróneo en los otros tres. Hay exactamente dos lugares donde falla, son independientes entre sí y ambos producen respuestas que parecen plausibles.
Las dos operaciones
chunk = floor(block / 16) not trunc(block / 16)
offset = ((block % 16) + 16) % 16 not block % 16
Las coordenadas de región son el mismo par, un nivel más arriba, con 32 en lugar de 16:
region = floor(chunk / 32) -> r.<x>.<z>.mca
regionOff = ((chunk % 32) + 32) % 32
Así, una región es de 32 × 32 chunks, lo que equivale a 512 × 512 bloques.
Dónde muerde cada una
División. La mayoría de los lenguajes truncan hacia cero, y floor redondea hacia el infinito negativo. Coinciden para los positivos y discrepan para cada negativo que no es un múltiplo exacto:
- bloque
−1→floor(−1/16) = −1✓, perotrunc(−1/16) = 0✗
El bloque −1 está un bloque al oeste del origen y pertenece al chunk −1. El truncamiento lo coloca en el chunk 0, junto al bloque +1. Cada índice de chunk negativo resulta ser uno demasiado alto.
Resto. En JavaScript, Java, C y la mayoría de los demás, % mantiene el signo del operando izquierdo:
- bloque
−1→ desplazamiento correcto15, pero−1 % 16 = −1✗
Un desplazamiento de −1 no es una posición dentro de un chunk de 16 de ancho en absoluto. Indexar un array de bloques con él o bien lanza un error o lee silenciosamente la celda incorrecta.
Un ejemplo práctico
Bloque −1290 en un eje:
| paso | correcto | ingenuo |
|---|---|---|
| chunk | floor(−1290/16) = −81 | trunc = −80 ✗ |
| desplazamiento en el chunk | 6 | −1290 % 16 = −10 ✗ |
| región | floor(−81/32) = −3 | trunc = −2 ✗ |
| desplazamiento en la región | 15 | −81 % 32 = −17 ✗ |
Cuatro valores, cuatro respuestas incorrectas, ninguna de ellas lo suficientemente fuera de rango como para parecer obviamente rota. La región −3 abarca los chunks −96 a −65, y el chunk −81 se encuentra a 15 de su inicio, que es exactamente lo que devuelve el resto corregido.
La conversión del Nether es con pérdida en una dirección
Del Overworld al Nether se divide por 8, y también se redondea hacia abajo (floor):
netherX = floor(overworldX / 8)
Volviendo se multiplica por 8. Eso no es un viaje de ida y vuelta. floor descarta el resto, por lo que al regresar aterrizas en un múltiplo de 8:
- Overworld
1000→ El Nether125→ de vuelta a1000✓ - Overworld
1007→ El Nether125→ de vuelta a1000✗ — siete bloques menos
El error es de 0 a 7 bloques por eje, así que hasta 7 en X y 7 en Z a la vez. Esa es la razón principal por la que la vinculación precisa de portales necesita que la coordenada del Nether se anote en lugar de volver a derivarse: una vez que has dividido, la posición del Overworld de la que provino ya no se puede recuperar.
Para un centro del Nether, esto rara vez importa — 7 bloques están dentro del radio de captura de un portal. Para vincular dos portales que no deben robarse el tráfico entre sí, importa mucho.
Las coordenadas negativas del Overworld lo empeoran de la manera familiar: Overworld −1 da El Nether floor(−1/8) = −1, mientras que el truncamiento da 0 y te envía al lado incorrecto del eje.