Advertisement
theosib

MC-2025 fix description

May 24th, 2018
324
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.21 KB | None | 0 0
  1. *The following describes a fix for MC-2025 that directly addresses the rounding errors that are the underlying cause.*
  2.  
  3. As mentioned previously, the underlying cause of MC-2025 is IEEE floating point artifacts, affecting the max and min faces of an entity's axis-aligned bounding box (AABB). The bug is most obvious when it cause entities to glitch through blocks (often being killed in the process, making this arguably a data loss bug). But it is *actually* caused by the way {{net.minecraft.util.math.AxisAlignedBB}} computes applies translations in its {{offset}} methods.
  4.  
  5. Put concisely, the difference between maxX and minX does not necessarily remain constant when adding the same value to both. This especially likely to happen in Minecraft due to the use of fractional values that cannot be represented exactly in floating point, such as the width of 0.6 used for villagers and other mobs. That 0.6 is actually stored in a 32-bit float, so the actual value used is closer to 0.60000002384185791015625. Normal IEEE rounding rules can result in this kind of drift at any time, but drift becomes more likely at power-of-two boundaries (where min and max face exponents are different).
  6.  
  7. Example
  8.  
  9. Consider an entity with Xmin=1.8 and width of 0.6. Xmin is stored as a double, off by about +4.441E-17. The width is a float, so it ends up being closer to 0.6000000238418577. Adding those gives us Xmax=2.4000000238418577 and center posX=2.1000000119209288. At this point, Xmin and Xmax average to 2.1000000119209288, so we're okay. Now let's add the following sequence of numbers to both Xmin and Xmax:
  10.  
  11. +0.01562500000000011 +0.015625000000000114 +0.01562500000000011 +0.015625000000000114 +0.01562500000000011 +0.015625000000000114 +0.01562500000000011 +0.015625000000000114 +0.01562500000000011 +0.015625000000000114 +0.01562500000000011 +0.015625000000000114 +0.015625000000000003 +0.015625000000000222
  12.  
  13. This results in Xmin=2.0187500000000034, Xmax=2.6187500238418577, width=0.6000000238418544, and if we calculate the center posX, we get 2.3187500119209306. The problem is that the width is now 3.552713678800501E-15 smaller than it should be.
  14.  
  15. Next, we're going to one last time shove the entity up against a wall at X=2.0, giving us:
  16. Xmin=2.0, Xmax=2.6000000238418544, width=0.6000000238418544, and computed center posX=2.300000011920927.
  17.  
  18. The chunk unloads, saving the entity X position at 2.300000011920927. When the chunk reloads, the AABB is reconstructed by adding and subtracting 0.30000001192093 from the center posX. This results in Xmin=1.9999999999999982and Xmax=2.600000023841856, where Xmin intersects the wall by -1.7763568394002505E-15.
  19.  
  20. Minecraft now considers the entity to be "inside" the wall, and another mob bumping into it will easily push it all the way inside the wall, suffering a gruesome death by suffocation.
  21.  
  22. Solution
  23.  
  24. The way I solved this was to pass width information to a new offset method on AxisAlignedBB. Based on the direction of movement, this method can tell which face might be getting pushed up against a boundary. For instance, if the delta-X is negative, it MIGHT mean that Xmin has met a boundary (while Xmax most likely has not). Therefore, the translation requested is applied to Xmin (in this case), but Xmax is computed by adding Xmin+width/2 to get the center X, and then adding width/2 again. This guarantees that when Xmin and Xmax are averaged, this centerX is what will be computed. More importantly, it guarantees that if width/2 is subtracted from this center X, these very same values for Xmin and Xmax will be reconstructed.
  25.  
  26. In other words, I added a new offset method that always corrects for drift in AABB size, and that makes it possible to convert back and forth between position and AABB losslessly. This way, when the center position is reloaded from the NBT data, the AABB calculated will not intersect with boundaries and will not glitch into them.
  27.  
  28. Code
  29.  
  30. The code and diffs are currently located here:
  31. https://www.dropbox.com/sh/p8p4cdjmt2jrqm5/AAARSbXvkcgeBfrH8_ZIQSDRa?dl=0
  32.  
  33. For MC-2025, only AxisAlignedBB.java and Entity.java are relevant. Entity.java has additional changes that are part of a fix for MC-4. All changes are clearly marked for which bug fix they are part of.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement