TShock/TShock — pull request #494 by Scavenger3 (2013-07-06 16:36:25+00:00)
Title: Check for invalid place style.

I'm not sure if this is the best fix so I'm happy to add more commits if you'd like it done differently...

The Tile packet has a style byte that defines what kind of sub-tile should be placed...
For example: torches all have the same tile id just with a different frameX and frameY value. The style parameter is used instead of sending the actual frame values. So a normal Torch = 0, Blue Torch = 1, Red Torch = 2, Green Torch = 3 etc...

For tiles that have different sub-tiles, the frame value gets calculated by multipling this style value by the texture's height.[1]

When rendering a tile, the frame value is used to get the location of the tile's sprite in the tile's spritesheet. However if the frame is outside the spritesheet no exception will be thrown and just a default purple texture will be rendered.

When you can right click on a tile (e.g. destroy a torch, open a chest), the tile's item texture gets rendered next to the cursor. So we need to get the tile's item id from it's tile id and frame value. This is where a problem occurs (or some bad code), The frame value is devided by the texture's height to get back the style value, and because sub-tiles (more or less) have item id's that increment we can just add the first item id to the style value.[2]

But then what happens if our style value was too big in the first place?, well if the first item id plus the style value is still a valid item, then it renders that item. Otherwise the client looks for an index in the item textures array that is out of range, and crashes.

Ok, not such a big deal beacuse the player has to be within placement/breaking range, and then has to hover their cursor over the tile in order to crash. But what if this tile is then broken? well again we need to convert the tile id back into an item id & drop it. But we use the same conversion method. So surely when the item is dropped something will check to make sure it's it has a valid id?.. Well, it dropped from a tile, not a player, and oops everyone who tries to render the dropped item crashes.

So the way I've fixed this is to prevent these tiles with bad style values from being placed in the first place.

---
[1] reference with torches: https://github.com/Deathmax/TerrariaAPI-Server/blob/master/Terraria/WorldGen.cs#L13313
[2] reference with torches: https://github.com/Deathmax/TerrariaAPI-Server/blob/master/Terraria/Player.cs#L3454