Uploaded image for project: 'Minecraft: Java Edition'
  1. Minecraft: Java Edition
  2. MC-87565

Conversion to integers in packets causes loss of information in entities and results in desychronisation of the server and client

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Resolved
    • Resolution: Fixed
    • Affects Version/s: Minecraft 1.8.8, Minecraft 15w35c, Minecraft 15w36c, Minecraft 15w49b
    • Fix Version/s: Minecraft 1.11.2
    • Labels:
      None
    • Environment:

      Linux 3.19.0-26-generic (Ubuntu 15.04, 64 bit)
      Oracle Java 1.8.0_60 (64 bit)

    • Confirmation Status:
      Plausible

      Description

      Many of the packets concerning the communication about entities between server and client store integers with a conversion factor instead of the exact real numbers.
      This causes a variety of issues in (to my knowledge) all versions of Minecraft up to now.
      Examples of the implications are:

      1) It is impossible to specify the position of an entity using commands to any precision better than 1/32 of a block.
      This can be seen for instance after:

      /summon Giant 0 64.00 0 {NoAI:1}
      /summon Giant 0 64.02 0 {NoAI:1}
      

      Both Giants will appear to be in the same position. However, a third Giant summoned at:

      /summon Giant 0 64.04 0 {NoAI:1}
      

      will appear to hover 1/32 of a block higher than the other two giants.

      2) This is probably also the most common cause for MC-4. This can easily be reproduced with the following commands:

      /setblock 1 80 1 stone
      /summon Item 0.9 81 0.9 {Item:{id:1,Count:1}}
      

      For the client, the summoned item will visually appear to fall off the block. It then appears to teleport back to the top of the block every other second, only to start falling again.
      The reason for this is that the sever knows that the item is at the given coordinates (0.9, 81, 0.9). The item cannot fall down from there as the item's hitbox touches the stone block. In mathematical terms this is: 0.9 + 0.125 > 1.0, where 0.125 is half the width of the item's hitbox.

      Now the client only knows what the server tells it via packets. However, the packets are created in the following manner:

      /* pseudo java code */
      packetOut.posX = (int)MathHelper.floor_double(entity.posX * 32.0D);
      packetOut.posY = (int)MathHelper.floor_double(entity.posY * 32.0D);
      packetOut.posZ = (int)MathHelper.floor_double(entity.posZ * 32.0D);
      

      The information is then recovered from the packet by the client with:

      /* pseudo java code */
      double posX = (double)packetIn.getPosX() / 32.0D;
      double posY = (double)packetIn.getPosY() / 32.0D;
      double posZ = (double)packetIn.getPosZ() / 32.0D;
      

      Thus, the client can only know about the position of the item (and any other entity) to a precision of 1/32 of a block.
      So the client thinks the item is at (floor(0.9 * 32), 81, floor(0.9 * 32)) = (0.875, 81, 0.875). At this position the item can fall down, as the item's hitbox does just about not touch the stone block. In mathematical terms, 0.875 + 0.125 ≯ 1.0. As a result, the item appears to fall down for the client while the server keeps it on top of the block (i.e. MC-4).

      But it is not just the position of entities that is affected. Entity rotations are only stored to the nearest 1/256 of a full rotation (~1.41°). Also velocities are stored to the nearest 1/8000 block per tick. Furthermore, fixing this bug would allow map makers to use high precision entity manipulation to get rid of the Z-Fighting effect in their creations, by choosing small differences in positions.

      Possible Fix

      As a test I wrote a mod to mostly fix this issue by changing the variable types in the entity packets (see below for a list) from ints to doubles/floates and got rid of all occurences of multiplication/division factors involved. This means that rather than storing some discrete data, the packets contain the exact values used in the rest of the game code. As a result MC-4 seemed to be fixed as I could no longer reproduce it, and I was able to get rid of Z-fighting effects by teleporting/summoning entities to very slightly different coordinates.

      I changed the following classes in my fix-mod (I only made it for 1.8.0 and single player, using MCP):

      NetHandlerPlayClient.java
      Entity.java
      EntityTrackerEntry.java
      S0EPacketSpawnObject.java
      S2CPacketSpawnGlobalEntity.java
      S0CPacketSpawnPlayer.java
      S18PacketEntityTeleport.java
      S0FPacketSpawnMob.java
      S14PacketEntity.java
      

      I noticed that in NetHandlerPlayClient.java the code that processes the S11PacketSpawnExperienceOrb packets (around line 456) does not have the '/ 32.0D' conversion (which I removed everywhere else by writing this mod). This is a bug that seems to be described by MC-11601.

        Attachments

        1. 2015-08-28_21.02.14.png
          2015-08-28_21.02.14.png
          250 kB
        2. 2015-08-28_21.02.56.png
          2015-08-28_21.02.56.png
          227 kB
        3. 2015-08-28_21.04.07.png
          2015-08-28_21.04.07.png
          260 kB
        4. 2015-08-28_21.04.22.png
          2015-08-28_21.04.22.png
          192 kB

          Issue Links

            Activity

              People

              • Assignee:
                Unassigned
                Reporter:
                Cubitect Cubitect
              • Votes:
                27 Vote for this issue
                Watchers:
                17 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved:
                  CHK: