Le coordinate negative rompono la matematica dei chunk in due punti, non uno
La divisione con troncamento inserisce il blocco −1 nel chunk 0 invece di −1, e un semplice % restituisce un offset interno al chunk di −1 invece di 15. Entrambi sono errati ed entrambi sembrano corretti finché non vai a ovest dello spawn.
Ogni calcolo dei chunk è banale nel quadrante positivo ed errato negli altri tre. Ci sono esattamente due punti in cui fallisce, sono indipendenti l'uno dall'altro ed entrambi producono risultati che sembrano plausibili.
Le due operazioni
chunk = floor(block / 16) not trunc(block / 16)
offset = ((block % 16) + 16) % 16 not block % 16
Le coordinate della regione sono la stessa coppia, un livello sopra, con 32 invece di 16:
region = floor(chunk / 32) -> r.<x>.<z>.mca
regionOff = ((chunk % 32) + 32) % 32
Quindi una regione è di 32 × 32 chunk, ovvero 512 × 512 blocchi.
Dove colpisce ciascuna
Divisione. La maggior parte dei linguaggi tronca verso lo zero, e floor rounds toward negative infinity. They agree for positives and disagree for every negative that is not an exact multiple:
- blocco
−1→floor(−1/16) = −1✓, buttrunc(−1/16) = 0✗
Il blocco −1 si trova un blocco a ovest dell'origine e appartiene al chunk −1. Il troncamento lo inserisce nel chunk 0, insieme al blocco +1. Ogni indice di chunk negativo risulta più alto di uno.
Resto. In JavaScript, Java, C e nella maggior parte degli altri, % keeps the sign of the left operand:
- blocco
−1→ correct offset15, but−1 % 16 = −1✗
Un offset di −1 non è affatto una posizione all'interno di un chunk largo 16. Indicizzare un array di blocchi con questo valore genera un errore o legge silenziosamente la cella sbagliata.
Un esempio pratico
Blocco −1290 su un asse:
| passaggio | corretto | ingenuo |
|---|---|---|
| chunk | floor(−1290/16) = −81 | trunc = −80 ✗ |
| offset nel chunk | 6 | −1290 % 16 = −10 ✗ |
| regione | floor(−81/32) = −3 | trunc = −2 ✗ |
| offset nella regione | 15 | −81 % 32 = −17 ✗ |
Quattro valori, quattro risposte errate, nessuna delle quali abbastanza fuori intervallo da sembrare chiaramente sbagliata. La regione −3 copre i chunk da −96 a −65 e il chunk −81 si trova a 15 dal suo inizio, che è esattamente ciò che restituisce il resto corretto.
La conversione del Nether ha perdite in una direzione
Dal Sopramondo al Nether divide per 8 e arrotonda per difetto:
netherX = floor(overworldX / 8)
Tornando indietro si moltiplica per 8. Questo non è un viaggio di andata e ritorno. floor throws away the remainder, so returning lands you on a multiple of 8:
- Sopramondo
1000→ Nether125→ back to1000✓ - Sopramondo
1007→ Nether125→ back to1000✗ — seven blocks short
L'errore è compreso tra 0 e 7 blocchi per asse, quindi fino a 7 su X e 7 su Z contemporaneamente. Questo è l'unico motivo per cui il collegamento preciso dei portali richiede di annotare le coordinate del Nether anziché ricalcolarle: una volta diviso, la posizione di origine nel Sopramondo non è più recuperabile.
Per un hub del Nether questo ha raramente importanza: 7 blocchi rientrano nel raggio di cattura del portale stesso. Per collegare due portali che non devono interferire a vicenda con il rispettivo traffico, ha un'enorme importanza.
Le coordinate negative del Sopramondo peggiorano le cose nel solito modo: Sopramondo −1 gives Nether floor(−1/8) = −1, while truncation gives 0 and sends you to the wrong side of the axis.