godotengine / godotengine/godot
Unexpected behaviour for alternative tile IDs greater than 4095 at runtime
- Dominant language
- C++
- Stars
- 117k
- Forks
- 26.8k
- PR merge metrics
- PR metrics pending
Description
### Tested versions
Tested in 4.5.1-stable and on master (4.6-dev; as of pull request #112063)
### System information
Ubuntu 24.04.3
### Issue description
Trying to create a TileSetAtlasSource alternative tile ([create_alternative_tile](https://docs.godotengine.org/en/stable/classes/class_tilesetatlassource.html#class-tilesetatlassource-method-create-alternative-tile)) with `alternative_id_override` greater than 4095 silently fails. No error is thrown and the ID returned is equal to the parameter, instead of `-1` as it should be according to the documentation.
When trying to access the alternative tile of the ID, the functions I have tested ([TileSetAtlasSource.get_tile_data](https://docs.godotengine.org/en/stable/classes/class_tilesetatlassource.html#class-tilesetatlassource-method-get-tile-data), [TileMapLayer.set_cell](https://docs.godotengine.org/en/stable/classes/class_tilemaplayer.html#class-tilemaplayer-method-set-cell)) instead appear to use the ID `alternative_tile % 4096`. This also happens silently, although it does print this adjusted ID in error messages. (For example `TileSetAtlasSource has no alternative with id 1 for tile coords (0, 0)` if the actual ID is 4097)
### Steps to reproduce
1. Add a TileMapLayer whose TileSet has a TileSetAtlasSource with at least one tile.
2. At runtime, create two alternative tiles for the same tile, one with ID 1 and the other with ID 4097.
3. Now, accessing the two alternative tiles, both are associated with the same TileData object because `4097 % 4096 = 1`. This does not happen with two different IDs that are both less than 4096.
If you use ID 2 instead of 1, accessing tile 4097 will produce an error because there is no alternative tile *with the ID 1*.
### Minimal reproduction project (MRP)
[MRP zip archive](https://github.com/user-attachments/files/23217160/mrp.zip) (last edited in 4.6)
Contributor guide
Research direction
Start with TileSetAtlasSource.create_alternative_tile and the alternative-tile lookup paths used by TileSetAtlasSource.get_tile_data and TileMapLayer.set_cell. Reproduce the MRP with IDs 1 and 4097, then trace how the ID is stored, returned, and reported. Done means IDs greater than 4095 are handled consistently or rejected with the documented -1 result, with regression coverage for both cases.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- game-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100