Minecraft 1.7.10, Minecraft 14w28a, Minecraft 14w28b, Minecraft 14w29a, Minecraft 14w29b, Minecraft 14w30c, Minecraft 14w31a, Minecraft 14w32a, Minecraft 14w32b, Minecraft 14w32d, Minecraft 14w33a, Minecraft 14w33b, Minecraft 14w33c, Minecraft 14w34c, Minecraft 14w34d, Minecraft 1.8-pre1, Minecraft 1.8-pre2, Minecraft 1.8-pre3, Minecraft 1.8, Minecraft 1.12.2, Minecraft 18w02a
When a pixel in a map has a tie between multiple MapColors, the colour of the pixel can be inconsistent over restarts of Minecraft.
The problem is showcased in this image:
This is the same map over multiple restarts of Minecraft, stitched together. The world was not changed between each of these pictures being taken.
Notice how in the grey square, the colour of the pixels are different. Also notice the grey pixels in the brown square.
All these pixels have a 2:2 block ratio (although it should also happen when you have any other draw, such as four different blocks, or more complex ties with bigger map scales).
Notice also how even pixels with the same proportions of blocks but different configurations are not always the same colour at the same time (e.g. the brown line the in grey square, in the bottom right image).
- Download my test world map test flat.zip and copy it to your save folder
- Make sure you are near the grey square (you should spawn nearby) and hold map #1 in your hand to update the map.
- Take the map out of your hand (so it does not immediately render when you restart), close the world and completely quit out of Minecraft.
- Run the Minecraft launcher, relaunch Minecraft and open the test world
- The map should be in an item frame nearby, look at it and wait till the map has finished loading in.
- Watching the map closely, scroll over to the map in your hotbar to update it. You may see some of the pixels change colour.
- Repeat by restarting Minecraft again. You might not have seen a change first time, and you can see lots of variations by repeating the process.
I believe this bug is caused by the use of a HashMultiset to count the MapColors in each pixel. This works just fine when there is a clear winner when counting MapColors. However, when there is a tie, which MapColor wins is somewhat chaotic. This is due to Multisets.copyHighestCountFirst breaking ties by the iteration order of the multiset passed, and HashMultiset having an unspecified and generally chaotic iteration order.
I'm only an amateur programmer, but I do have some suggestions on how this bug could be fixed:
- Use a TreeMultiset in place of the HashMultiset. Allows you to specify the sorting order of the multiset. A simple Comparator could be written to sort the MapColors by index so that lower indices take precedence in a tie. However, it may be a bit slow.
- Use a LinkedHashMultiset in place of the HashMultiset. The iteration order is decided according to when the first occurrence of the element was added. Ties would be broken by which MapColor was added first, i.e. the MapColor that has the block with the lowest x and z coordinates would win. This might be a bit faster than a TreeMultiset.
- Write in manual tie-breaking. Check the multiset for a tie, and if there is one iterate over the tied MapColors and choose a winner somehow e.g. the one with the lowest index.
I found this bug while trying to make a map rendering script. If one of the developers fixes this bug, could they please leave a comment explaining how they did so? That would help me make the script accurate for future versions of Minecraft. Thanks!