dominion-ecs-java icon indicating copy to clipboard operation
dominion-ecs-java copied to clipboard

Insanely fast ECS (Entity Component System) for Java

|) () |\/| | |\| | () |\|

Java CI with Maven CodeQL

Dominion is an Entity Component System library for Java.

Entity Component System (ECS) architecture promotes data-oriented programming. It’s all about data (components) and first-class functions (systems) that operate on data.

This means that, unlike OOP, data and operations are not encapsulated together in objects, which are called entities in ECS.

Entities model the business objects of the user application, and the entity promotes "composition over inheritance" by grouping a dynamic list of components to define its specific features.

Systems usually operate on components sequentially and can be very fast if data are stored in cache-friendly ways. Systems are decoupled from each other and each system knows only about the data it operates on. This strongly promotes high concurrency, running systems in parallel whenever they can independently operate on the data.

ECS architecture is particularly suitable (but not limited to) if you have to manage many objects in your application. In addition, application code tends to be more reusable and easier to extend with new functionality thanks to the components' composition and subsequent addition of new systems.

Dominion Features

  • πŸš€ FAST > Dominion is not only an insanely fast ECS implemented in Java, it can also be in the same league as ECS for C, C++, and Rust - see benchmarks .
  • 🀏 TINY > Just a high-performance and high-concurrency Java library with a minimal footprint and no dependencies. So you can easily integrate the Dominion core library into your game engine or framework or use it directly for your game or application without warring about the dependency hell.
  • β˜•οΈ SIMPLE > Dominion promotes a clean, minimal and self-explanatory API that is simple by design. A few readme pages will provide complete usage documentation.
  • πŸ’ͺ with SUPPORT > Join the Discord! The server will support users and announce the availability of the new version.

Quick Start

In your local environment you must have already installed a Java 17 (or newer) and Maven.

Add the following dependency declaration in your project pom.xml:


<project>
    <!-- ... -->

    <dependencies>
        <dependency>
            <groupId>dev.dominion.ecs</groupId>
            <artifactId>dominion-ecs-engine</artifactId>
            <version>0.7.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

    <repositories>
        <repository>
            <id>central-snapshot</id>
            <url>https://s01.oss.sonatype.org/content/repositories/snapshots</url>
            <releases>
                <enabled>false</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
    </repositories>
</project>

Check out the Dominion API documentation as a reference to get started implementing your first app.

About Performance

Designing a high-performance and high-concurrency Java library is ~~a piece of cake~~ quite a challenge as the execution speed of Java code could be affected in many ways. Dominion mitigates Java's performance pitfalls by taking a few actions:

  • not just using the standard library: the Java standard library implements data structures and algorithms designed without making any assumption about the data as they are general purpose. Dominion implements some custom data structures and algorithms to increase performances and fill the gap with ECS frameworks written in system languages.
  • reducing garbage collection activities: GC could affect overall performances as its activities run concurrently with user code and without direct control. To reduce GC activities significantly, Dominion implements a very efficient pooling system to reuse objects living in a heap and creates off-heap data structures whenever possible.
  • mastering concurrency: an ECS library must be not only fast but able to scale running on a multicore CPU. Otherwise, it makes little sense today. Writing a highly concurrent library in Java requires non-blocking concurrency as much as possible and leveraging the best available lock implementation as the fast StampedLock.
  • using Java 17: only by upgrading to the Java 17 you will get a performance boost for free: Java 17 is about 8-9% faster than Java 11.
  • adding a blazing-fast logging layer: by implementing a thin logging layer over the standard System.Logger (Platform Logging API and Service - JEP 264), Dominion achieves a half nanosecond logging level check with next to no performance impact and does not require a specific dependency on the logging implementation of your choice.

Ok, enough blah blah blah..

Here is an example:

public class HelloDominion {

    public static void main(String[] args) {
        // creates your world
        Dominion hello = Dominion.create();

        // creates an entity with components
        hello.createEntity(
                "my-entity",
                new Position(0, 0),
                new Velocity(1, 1)
        );

        // creates a system
        Runnable system = () -> {
            //finds entities
            hello.findEntitiesWith(Position.class, Velocity.class)
                    // stream the results
                    .stream().forEach(result -> {
                        Position position = result.comp1();
                        Velocity velocity = result.comp2();
                        position.x += velocity.x;
                        position.y += velocity.y;
                        System.out.printf("Entity %s moved with %s to %s\n",
                                result.entity().getName(), velocity, position);
                    });
        };

        // creates a scheduler
        Scheduler scheduler = hello.createScheduler();
        // schedules the system
        scheduler.schedule(system);
        // starts 3 ticks per second
        scheduler.tickAtFixedRate(3);
    }

    // component types can be both classes and records

    static class Position {
        double x, y;

        public Position(double x, double y) {/*...*/}

        @Override
        public String toString() {/*...*/}
    }

    record Velocity(double x, double y) {
    }
}

Dominion Examples Page

Dominion comes with some documented sample apps to help adopt the solution, like the HelloDominion sample above.

The DarkEntities sample app has also been added, it could inspire a turn-based rogue-like game running on a terminal window:

Here the Dominion Examples page with all the documented code.

Dominion Release Cycle

Phase Description Distribution Git tag
Preview Features are under heavy development and often have changing requirements and scope. github-zip only none
Early Access (EA) Features are documented and ready for testing with a wider audience. maven SNAPSHOT release-EA-#
Release Candidate (RC) Features have been tested through one or more early access cycles with no known showstopper-class bugs. maven RC release-RC#
Stable Release Features have passed all verifications / tests. Stable releases are ready for production use maven RELEASE release

Dominion is officially in Early Access.

Join the Discord for further updates!

Credits

Java Profiler

Support Dominion

If you want to support Dominion project, consider giving it a Star ⭐️