الإحداثيات السالبة تفسد حسابات التشنكات في مكانين، لا في مكان واحد
القسمة التي تحذف الكسور تضع الكتلة -1 في التشنك 0 بدلاً من -1، وعلامة % العادية تعطي إزاحة داخل التشنك قدرها -1 بدلاً من 15. كلاهما خاطئ، وكلاهما يبدو صحيحًا حتى تتجه غرب نقطة الظهور.
كل عملية حسابية للتشنكات (chunk) تكون بسيطة في الربع الموجب وخاطئة في الأرباع الثلاثة الأخرى. هناك بالضبط مكانان يحدث فيهما الخطأ، وهما مستقلان عن بعضهما البعض، وكلاهما ينتج إجابات تبدو معقولة.
العمليتان
chunk = floor(block / 16) not trunc(block / 16)
offset = ((block % 16) + 16) % 16 not block % 16
إحداثيات المنطقة (Region) هي نفس الزوج، بمستوى أعلى، مع 32 بدلاً من 16:
region = floor(chunk / 32) -> r.<x>.<z>.mca
regionOff = ((chunk % 32) + 32) % 32
لذا، المنطقة الواحدة هي 32 × 32 تشنك، أي 512 × 512 كتلة.
أين يكمن الخطأ في كل منهما
القسمة. معظم اللغات تحذف الكسور باتجاه الصفر، بينما floor تقرب باتجاه اللامحدودية (Infinity) السالبة. تتفقان في الأعداد الموجبة وتختلفان في كل عدد سالب ليس مضاعفًا دقيقًا:
- الكتلة
−1←floor(−1/16) = −1✓، لكنtrunc(−1/16) = 0✗
الكتلة -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 ✗ |
أربع قيم، أربع إجابات خاطئة، لا شيء منها خارج النطاق بما يكفي ليبدو معطلًا بشكل واضح. المنطقة -3 تمتد من التشنكات -96 إلى -65، والتشنك -81 يقع على بعد 15 من بدايته - وهذا بالضبط ما يعيده الباقي المصحح.
تحويل نذر (Nether) يفقد البيانات في اتجاه واحد
التحويل من العالم العلوي (Overworld) إلى نذر يقسم على 8، ويقرب إلى الأسفل أيضًا:
netherX = floor(overworldX / 8)
العودة تضرب في 8. هذه ليست رحلة ذهاب وعودة. floor يتجاهل الباقي، لذا العودة تهبط بك على مضاعف للعدد 8:
- العالم العلوي
1000← نذر125← العودة إلى1000✓ - العالم العلوي
1007← نذر125← العودة إلى1000✗ — سبع كتل أقل
الخطأ يتراوح من 0 إلى 7 كتل لكل محور، لذا يصل إلى 7 على X و 7 على Z في نفس الوقت. هذا هو السبب الرئيسي وراء ضرورة تدوين إحداثيات نذر لربط البوابات بدقة بدلاً من إعادة اشتقاقها: بمجرد أن تقسم، لا يمكن استعادة موقع العالم العلوي الذي جاءت منه.
بالنسبة لمركز نذر، نادرًا ما يهم هذا - 7 كتل تقع ضمن نصف قطر التقاط البوابة نفسها. أما لربط بوابتين يجب ألا تسرق إحداهما حركة الأخرى، فهذا يهم كثيرًا.
الإحداثيات السالبة في العالم العلوي تجعل الأمر أسوأ بالطريقة المعتادة: العالم العلوي −1 يعطي نذر floor(−1/8) = −1، بينما الحذف يعطي 0 ويرسلك إلى الجانب الخاطئ من المحور.