BIG-BUG!!!!!!!! firstgid corruption when editing multiple maps sharing tilesets
Describe the bug
Our designer encountered firstgid corruption when working with two maps that share some common tilesets.
Actual Behavior: After saving Season_1_miniMap, the firstgid values for shared tilesets are overwritten and become inconsistent with their original values.
File Evidence:
Normal Season_1_miniMap (before corruption):
<tileset firstgid="264" source="../tilesets/s1/easy_water/s1_easy_water.tsx"/>
<tileset firstgid="288" source="../meta_tilesets/collision_check/collision_check.tsx"/>
<tileset firstgid="290" source="../tilesets/s1/one_tree/s1_2x2sk.tsx"/>
<tileset firstgid="294" source="../tilesets/s1/xzddb/s1_xzddb.tsx"/>
<tileset firstgid="298" source="../tilesets/s1/xzddb/s1_xzddb_c.tsx"/>
<tileset firstgid="314" source="../tilesets/s1/map_anim_objs/map_anim_objs_tileset.tsx"/>
Normal Season_1:
<tileset firstgid="270" source="../tilesets/s1/easy_water/s1_easy_water.tsx"/>
<tileset firstgid="408" source="../tilesets/s1/xzddb/s1_xzddb.tsx"/>
<tileset firstgid="412" source="../tilesets/s1/xzddb/s1_xzddb_c.tsx"/>
<tileset firstgid="428" source="../tilesets/s1/one_tree/s1_2x2sk.tsx"/>
<tileset firstgid="432" source="../tilesets/s1/db_2/s1_db.tsx"/>
Corrupted Season_1_miniMap (after saving):
<tileset firstgid="264" source="../tilesets/s1/easy_water/s1_easy_water.tsx"/>
<tileset firstgid="402" source="../meta_tilesets/collision_check/collision_check.tsx"/>
<tileset firstgid="404" source="../tilesets/s1/one_tree/s1_2x2sk.tsx"/>
<tileset firstgid="408" source="../tilesets/s1/xzddb/s1_xzddb.tsx"/>
<tileset firstgid="412" source="../tilesets/s1/xzddb/s1_xzddb_c.tsx"/>
<tileset firstgid="428" source="../tilesets/s1/map_anim_objs/map_anim_objs_tileset.tsx"/>
Suspected Cause: We suspect that Tiled might be treating tileset objects as globally shared instances, and the firstgid assignment logic might be using a global context instead of being map-specific.
Steps to reproduce
- Open and edit
Season_1.tmx - Then open and edit
Season_1_miniMap.tmx - Save
Season_1_miniMap.tmx - The firstgid values for shared tilesets become corrupted
Expected behavior
Each map should maintain its own firstgid assignments for tilesets, even when they reference the same source tileset files.
OS version
Windows 10
Tiled version
1.11.2
In case of corruption, Tiled should not be able to load your maps with tile references intact. It's hard to tell whether there is any corruption by just looking at the firstgids saved to the TMX file, they look fine to me even if they have changed between loading and saving.
We suspect that Tiled might be treating tileset objects as globally shared instances, and the firstgid assignment logic might be using a global context instead of being map-specific.
Actually firstgids are only assigned upon saving and used to resolve tile references during loading. While tilesets are shared between maps in memory, they have no firstgid attribute there. So firstgid assignment is map-specific.
Since firstgids are not remembered after loading, it is possible for them to be different after saving. This usually happens because a tileset has grown in size, in which case it is necessary to avoid ambiguous tile references. The process of resolving tile references is documented here.
Thank you for the response. I found that I missed some details in the case I provided, so I've updated it. This issue has caused significant trouble in actual editing. The key problem lies in: the same file produces completely different firstgid results due to different operation sequences.
When I edit and save Season_1_miniMap alone, the firstgid remains normal; but following the steps I described (editing Season_1 first, then Season_1_miniMap), the firstgid undergoes large-scale erroneous shifts.
This inconsistency is particularly fatal in team collaboration: any unintended operation by a team member could lead to a full rearrangement of firstgid, thereby triggering large-scale file changes. This not only undermines the stability of version management but also makes merge conflicts almost impossible to resolve.
I understand the logic of firstgid being reallocated upon loading, but when two maps share the same tileset source file, their firstgid should logically remain independent and stable. The current behavior clearly has a logical flaw.
Can you please re-examine the collaborative impact of this issue? It has caused real and serious disruption to our workflow.
Is it a corruption? I don't think Tiled's gids are necessarily meant to be stable
Is it a corruption? I don't think Tiled's gids are necessarily meant to be stable
I feel the same way, and it's very common to use the same tileset in two maps, but this can lead to gid not growing normally and being inconsistent with intuition. This is the most fatal issue. Currently, the only way to edit is to only open one map at a time. Painful.
@AILHC Could you provide the necessary files to reproduce this problem?
Even your edited report still talks about "corrupted" files, but again as long as Tiled can still read the file, any other tool should be able to do the same and the file can't really be considered corrupted. I understand it may change in a way that causes you trouble, but so far I'm not sure what's causing it. It should help if I was able to follow the steps to reproduce.
If you can't post your files publicly you could email them to me, share them in private on Discord, or you could adjust your reproduction steps to not rely on your files.
@AILHC Could you provide the necessary files to reproduce this problem?
Even your edited report still talks about "corrupted" files, but again as long as Tiled can still read the file, any other tool should be able to do the same and the file can't really be considered corrupted. I understand it may change in a way that causes you trouble, but so far I'm not sure what's causing it. It should help if I was able to follow the steps to reproduce.
If you can't post your files publicly you could email them to me, share them in private on Discord, or you could adjust your reproduction steps to not rely on your files.
Wait, let's see if we can make a reproducible file. If not, I'll send you the original file again.
First, the gid of the object reference is wrong (id="1" gid="200"), then the tileset reference order is wrong (1->23->120->96)
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.10" tiledversion="1.11.2" orientation="isometric" renderorder="right-down" width="100" height="100" tilewidth="256" tileheight="140" infinite="0" nextlayerid="7" nextobjectid="2">
<tileset firstgid="1" source="../tilesets/trees/trees.tsx"/>
<tileset firstgid="23" source="../tilesets/decoration_tiles/decoration_tiles.tsx"/>
<tileset firstgid="120" source="../tilesets/small_decs/small_desc.tsx"/>
<tileset firstgid="96" source="../tilesets/s1_easy_water/s1_easy_water.tsx"/>
<group id="2" name="metaLayers">
<objectgroup id="6" name="Object Layer 1">
<object id="1" gid="200" x="6857.71" y="8060.29" width="73" height="77"/>
</objectgroup>
</group>
<group id="3" name="surfaceLayers"/>
</map>
Saved
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.10" tiledversion="1.11.2" orientation="isometric" renderorder="right-down" width="100" height="100" tilewidth="256" tileheight="140" infinite="0" nextlayerid="7" nextobjectid="2">
<tileset firstgid="1" source="../tilesets/trees/trees.tsx"/>
<tileset firstgid="23" source="../tilesets/decoration_tiles/decoration_tiles.tsx"/>
<tileset firstgid="96" source="../tilesets/small_decs/small_desc.tsx"/>
<tileset firstgid="363" source="../tilesets/s1_easy_water/s1_easy_water.tsx"/>
<group id="2" name="metaLayers">
<objectgroup id="6" name="Object Layer 1">
<object id="1" gid="176" x="6857.71" y="8060.29" width="73" height="77"/>
</objectgroup>
</group>
<group id="3" name="surfaceLayers"/>
</map>
It feels like the tileset detected an incorrect order, or the firstgid is wrong (this might occur when modifying the tileset), and when regenerating this firstgid and order, it considered the object's reference to the gid
Mutual Influence Between Maps
When opening a Season_1 map with a wrong firstgid, then opening a Season_1_mini map with a correct firstgid
Saving a map with a correct firstgid will also become scrambled, with the scrambled starting id, it feels like the wrong gid reference in the Season_1 map is the starting point
Reproducible
- Example of a single map failing: Open
Season_1(before_save).tmxand save - Example of reproducing the effect between two maps: Open
Season_1(with_miss_gid_obj).tmx, do not manipulate or save the map, then openSeason_1_mini(no_proplem).tmx
@bjorn Sorry for making you wait
Reproduction 1 is a case of the tileset having been expanded since the map was last saved. When you open and save Season_1(before_save).tmx, we can see this change happening:
--- a/season_1_map_files/Season_1(before_save).tmx
+++ b/season_1_map_files/Season_1(before_save).tmx
@@ -3,10 +3,10 @@
<tileset firstgid="1" source="../tilesets/trees/trees.tsx"/>
<tileset firstgid="23" source="../tilesets/small_decs/small_desc.tsx"/>
<tileset firstgid="35" source="../tilesets/s1_easy_water/s1_easy_water.tsx"/>
- <tileset firstgid="50" source="../tilesets/decoration_tiles/decoration_tiles.tsx"/>
+ <tileset firstgid="59" source="../tilesets/decoration_tiles/decoration_tiles.tsx"/>
<group id="2" name="metaLayers">
<objectgroup id="6" name="对象层 1">
- <object id="1" gid="600" x="6857.71" y="8060.29" width="73" height="77"/>
+ <object id="1" gid="609" x="6857.71" y="8060.29" width="73" height="77"/>
</objectgroup>
</group>
<group id="3" name="surfaceLayers"/>
That's because the tileset s1_easy_water.tsx has tiles going up to ID 23. Likely the tileset was smaller when the map was saved the last time. But now, because you might have used any of the new tiles, including ID 23, which will have global tile ID 35 + 23 = 58, Tiled shifts the first global ID for decoration_tiles.tsx to 59. That also affects the gid of the tile object, because it being 600 implies it was part of this last tileset.
About reproduction 2, here we also somehow ended up with map file that has a broken tile reference. Tiled does its best to keep such references valid. While loading a map, when a broken reference is found, this causes a small but usually not important change to the affected tileset (in GidMapper::gidToCell):
// Adjust the next tile ID, in order to preserve tile references
// even to tilesets that failed to load.
tileset->setNextTileId(std::max(tileset->nextTileId(), tileId + 1));
As the comment says, this is to make sure that when saving the map, this broken reference is anyway interpreted as a reference to said tileset, even if other tilesets appear after that tileset.
This does have the potential of affecting other maps when they are saved. However, not in a way that should break them. All that should happen is that the firstgids of some of their tilesets might increase. This is what we see happening when saving Season_1_mini(no_proplem).tmx, where Tiled increases the firstgid of the small_desc.tsx tileset from 234 to 703.
That this is not corruption though. The file will still open fine in Tiled and should still work fine in any Tiled loader that correctly resolves global tile IDs.