Mojira Archive
MC-106690

Servers sends SPacketMaps packets even if the map data did not change

The following is based on a decompiled version of Minecraft 1.10 using MCP 9.30.

The bug

Currently the server sends a SPacketMaps packet to update a filled_map if the blocks the map displays changed or every 5 ticks for players and every 50 ticks for maps in item frames. The latter updates are however not necessary if changing the markers on the map would mark the map data as dirty as well.

Possible solution (example)

net.minecraft.world.storage.MapData.updateDecorations(int, World, String, double, double, double)
private void updateDecorations(int type, World worldIn, String entityIdentifier, double worldX, double worldZ, double rotation)
{
    int i = 1 << this.scale;
    float f = (float)(worldX - (double)this.xCenter) / (float)i;
    float f1 = (float)(worldZ - (double)this.zCenter) / (float)i;
    byte b0 = (byte)((int)((double)(f * 2.0F) + 0.5D));
    byte b1 = (byte)((int)((double)(f1 * 2.0F) + 0.5D));
    int j = 63;
    byte b2;

    if (f >= -63.0F && f1 >= -63.0F && f <= 63.0F && f1 <= 63.0F)
    {
        rotation = rotation + (rotation < 0.0D ? -8.0D : 8.0D);
        b2 = (byte)((int)(rotation * 16.0D / 360.0D));

        if (this.dimension < 0)
        {
            int k = (int)(worldIn.getWorldInfo().getWorldTime() / 10L);
            b2 = (byte)(k * k * 34187121 + k * 121 >> 15 & 15);
        }
    }
    else
    {
        if (Math.abs(f) >= 320.0F || Math.abs(f1) >= 320.0F)
        {
            this.mapDecorations.remove(entityIdentifier);
            // Added this
            for (MapData.MapInfo mapdata$mapinfo : this.playersArrayList)
            {
                mapdata$mapinfo.isDirty = true;
            }
            // Change end
            return;
        }

        type = 6;
        b2 = 0;

        if (f <= -63.0F)
        {
            b0 = -128;
        }

        if (f1 <= -63.0F)
        {
            b1 = -128;
        }

        if (f >= 63.0F)
        {
            b0 = 127;
        }

        if (f1 >= 63.0F)
        {
            b1 = 127;
        }
    }

    // Changed this
    //this.mapDecorations.put(entityIdentifier, new Vec4b((byte)type, b0, b1, b2));
    
    Vec4b newVec4b = new Vec4b((byte)type, b0, b1, b2);
    if (this.mapDecorations.containsKey(entityIdentifier)) {
        Vec4b oldVec4b = this.mapDecorations.get(entityIdentifier);
        if (oldVec4b.equals(newVec4b)) {
            return;
        }
    }
    this.mapDecorations.put(entityIdentifier, newVec4b);
    
    for (MapData.MapInfo mapdata$mapinfo : this.playersArrayList)
    {
        mapdata$mapinfo.isDirty = true;
    }
    // Change end
}
net.minecraft.world.storage.MapData.MapInfo.getPacket(ItemStack)
public Packet<?> getPacket(ItemStack stack)
{
    if (this.isDirty)
    {
        this.isDirty = false;
        return new SPacketMaps(stack.getMetadata(), MapData.this.scale, MapData.this.trackingPosition, MapData.this.mapDecorations.values(), MapData.this.colors, this.minX, this.minY, this.maxX + 1 - this.minX, this.maxY + 1 - this.minY);
    }
    else
    {
        // Replaced this
        //return this.tick++ % 5 == 0 ? new SPacketMaps(stack.getMetadata(), MapData.this.scale, MapData.this.trackingPosition, MapData.this.mapDecorations.values(), MapData.this.colors, 0, 0, 0, 0) : null;
        return null;
    }
}

Fixed

Marcono1234

2016-08-31, 09:43 PM

2021-05-27, 03:15 PM

2021-05-27, 03:15 PM

5

5

Confirmed

(Unassigned)

filled_map, map, packet, server

Minecraft 1.10.2, 20w07a

20w46a