There has been a lot of confusion and wasted time regarding the topics of Blocks, Voxels and Locations, so I’m making this post to clear it all up, or at least try to.
Blocks
Blocks in Minecraft aren’t Blocks in Bukkit. In Minecraft, Blocks are singletons used to define the logic of all blocks of a type. For example, defining whether or not a block burns. These are not bound to any location and the same instance is used for all logic calls.
In Bukkit, a Block is simply a Material and a Location. The Material refers to the logic and is a singleton (much like the Minecraft Blocks), and the Location provides the position in the world. You can have many Blocks of the same type and even of the same Location.
Sponge adopts the Minecraft way of defining Blocks for ease of implementation.
Locations and Vectors
Location in Bukkit is mostly just a fancy name for a Vector3d, which is a 3 component vector with double precision floating point numbers for numerical storage. Bukkit Locations do add pitch and yaw information, which actually makes it a simplified Transform, but these should be separate, since they aren’t alway needed. Sponge will use Vector3d as a replacement for Location, as well as Vector3i. Entities and other objects that require decimal precision for their position will use Vector3d, while objects that only need integer coordinates (such as Voxel that will be explained bellow) will use Vector3i. Sponge also adds classes for Vector2i, Vector2f, Vector2d and Vector3f. The number suffix is the dimension of the vector, while the letter suffix is the numerical storage type (int, float or double).
Voxels
To replace the Bukkit concept of Block, Sponge introduces Voxels, which are in essence the same thing as Bukkit Blocks. A Voxel is the smallest unit of a Minecraft world. They have a reference to the Block singleton that defines the logic, and a Vector3i that gives them a Location. These are simply there for convenience and are created on demand. They are not by themselves responsible for any logic at a their location.
Access interfaces
An access interface is a common interface for objects that allow access to other objects of a shared type in similar ways. For example, a World and a Chunk give you access to a Voxel at a location and a list of all Entities they contain. For abstraction purposes, we can regroup World and Chunk under interfaces for these accesses. They’re right now two major access interfaces: VoxelVolume and EntityUniverse.
VoxelVolume
A VoxelVolume is, as the name suggests, a Volume that contains Voxels. It can be bounded or unbounded. World is an example of an unbounded VoxelVolume, while Chunk is a bounded VoxelVolume. A Voxel is also a VoxelVolume. This might sound like a weird idea, since a Voxel is just a single Voxel, but, it’s actually the unit VoxelVolume, and including it under the interface can be very useful for abstracting certain algorithms. For example, if we have an algorithm that counts Voxels of a given Block type in a VoxelVolume, both Chunk and Voxel should be valid inputs, as both contain materials that can be counted (even if it’s just one). Another way to support this reasoning that a list with 1 item is still a list, and so a VoxelVolume with 1 Voxel is still a VoxelVolume. Other objects will be added that implement the interface, to provide bounded Views of unbounded Volumes, Buffers and thread-safe world editing. These will be detailed in another post.
EntityUniverse
Basically, anything that can return a list of entities should be an EntityUniverse. The terms simply means a universe in which entities can be found. World is a good example of such a thing. The term Universe was favoured over Volume since it’s formless and doesn’t actually suggest any formal concept of space.
Sumary
-
Bukkit Material = Sponge Block = Minecraft Block
-
Bukkit Block = Sponge Voxel
-
Bukkit Location = Sponge Vector{2/3}{i/f/d} = Minecraft Vector (in 1.8)
-
VoxelVolume = volume of Voxels
-
EntityUniverse = container of entities