Expand description

Here’s the deal.

Blocks are always 4 bytes. The first byte is the [BlockKind]. For filled blocks, the remaining 3 sprites are the block colour. For unfilled sprites (air, water, etc.) the remaining 3 bytes correspond to sprite data. That’s not a lot to work with! As a result, we’re pulling every rabbit out of the bit-twiddling hat to squash as much information as possible into those 3 bytes.

Fundamentally, sprites are composed of one or more elements: the SpriteKind, which tells us what the sprite is, and a list of attributes that define extra properties that the sprite has. Some examples of attributes might include:

  • the orientation of the sprite (with respect to the volume it sits within)
  • whether the sprite has snow cover on it
  • a ‘variation seed’ that allows frontends to pseudorandomly customise the appearance of the sprite in a manner that’s consistent across clients
  • Whether doors are open, closed, or permanently locked
  • The stage of growth of a plant
  • The kind of plant that sits in pots/planters/vessels
  • The colour of the sprite
  • The material of the sprite

Category

The first of the three bytes is the sprite ‘category’. As much as possible, we should try to have the properties of each sprite within a category be consistent with others in the category, to improve performance.

Since a single byte is not enough to disambiguate the SpriteKind (we have more than 256 kinds, so there’s not enough space), the category also corresponds to a ‘kind mask’: a bitmask that, when applied to the first two of the three bytes gives us the SpriteKind.

Modules

Structs

Enums

Traits

Functions