ECS System in Minecraft

Helight
4 min readSep 8, 2021

When I recently stumbled upon Geary, an Entity Component System (ECS) for Minecraft, I just had to try writing my own version of it. ECS is a software architectural pattern mostly used in games that heavily relies on data-oriented-design and composition over inheritance, which practically means using independent component and systems to compose an entity.

The Entities

For representing the Entity I choose an UInt64 called ULong in Kotlin. I implemented two systems for generating the ids., one being similar to twitter Snowflakes which ensures uniqueness across multiple instances as well as an incremental id generator storing it’s current state in the file system. The entity itself doesn’t hold any data or behavior as you might have already guessed by it being just an number, so that leads us to

The Components

A component consists of an id, also represented by an ULong which in my system is by default derived from the class name of the corresponding class, as well as possible data associated with it. The components of an entity are defining the properties and behavior of any entity since they are the only part able to (or at least meant to) hold any data in the system

The Systems

Systems run continuously on a predefined combination of components, called a component group. They are the part of the system which performs actions, calculations and so on. For example a PhysicsSystem acting upon any PhysicsComponent.

ECS requires extensive usages of array iterations in order to access or change any date requiring us optimize the iteration algorithm to make it resource effective. To achieve this I choose Archetype Storage. An archetype is basically just a collection of entities having the same types of components as well as their data.

data class Archetype(
val group: ComponentGroup, /* TreeSet<ComponentID> */
val ids: MutableList<EntityId>,
val data: MutableList<MutableList<ComponentData>> /* Any */
)

A simple implementation of an archetype could look like this. Here both the entity and the corresponding data have to be stored at the same index in both the ids and the data list or in other terms in the same row. The order of the component data also has to conform to the oder of the component ids in the tree set. Notice that we just have to store the component group once since the all entities in this archetype have the same component composition therefore sharing an equal data structure. This should also make it easier to store this in memory, though I’m not exactly sure how this applies to the JVM, I’ll have to do a bit more research on that.

Since the order of the items is really important in the archetype storage and we are planning on running this in an multithreaded environment, we have to think about race conditions, et cetera. That’s why I choose to use Java’s ReetrantReadWriteLocks to make the archetype thread safe at the cost of a bit of speed, although I plan on switching to locks compatible with kotlinx.coroutines.

Finally we just have to make the archetype storage ‘store’ the archetypes and move entities and components between them based on their current composition. Now, if we want to get all entities which have the component PhysicsComponent, we just have to search for archetypes where the group contains the id of PhysicsComponent resulting in reduced iteration time per query since we can almost completely skip non matching groups entirely.

Tags

Some ECS implementations include tags which are stored in the entity id. I explicitly choose not to implement such a feature since I like to have more unique ids as a tradeoff. Despite this I implemented something tag like as non data holding components, so component which hold no data and can be used as tags while still being usable in any component context.

That was the first part of the blog series I will post to this project, in the next one, I will address serialization and persistence and my event system in a later part.

Note:
This is one of my first blog articles. If you find any errors or have advice to give, feel free to contact me here or via helightdev@gmail.com

Sources and further reading:

--

--