Component System and Minecraft

I (and others in the development channel) have been stewing with the idea of managing Entities with components. Anyone who has ever worked with a modern game engine will have experience with this in some way or another. The premise is given your basic Entity, you add or “attach” objects or components to give the Entity functionality. It intrinsically means that all entities are fundamentally the same and only components make them unique from another.

Obviously code speaks better than words, here is an example of an Entity/Component relationship:

API Goodness:

interface Component<T extends ComponentHolder> {
    T getHolder();
}

interface ComponentHolder<T extends Component> {
    T add(Class<T> clazz);

    @Nullable
    T get(Class<T> clazz);
     
    Collection<T> getAll();
}

interface EntityComponent extends Component<Entity> {
    Metadata getData();    
}

interface Entity extends ComponentHolder<EntityComponent> {

}

interface Health extends EntityComponent {
    double getHealth();
    void setHealth(double health);
}

Minor implementation stuffs:

// Might be its own class, might be on Minecraft's EntityLiving?
class HealthComponent implements Health {        
    // If its own class, can have a way to set this
    Entity entity;

    @Override
    public Entity getHolder() {
        return entity;
    }

    @Override
    public Metadata getData() {
        return entity.getData();
    }

    @Override
    public double getHealth() {
        // If data doesn't exist, return a fallback
        getData().get("health", 50.5);
    }

    @Override
    public void setHealth() {
        getData().set("health", 50.5);
    }
}

Phew, that is just basic stuff (and certaintly has room for improvement). The biggest change in this system is we move away from this:

interface Entity {
}

interface EntityLiving extends Entity {
}

…which is a top down design. Have the “parts” that make up Minecraft’s Enderman or Creeper separated into their own segments makes extending them a breeze. Even better, it makes adding new entities very easy in the future (if/when we support client-side content).

As with all structures, there are cons. In this case, it comes down to incompatibility with existing code. We’ve gotten hints from Mojang at the prospect of Minecraft converting to a component structure but obviously we have no ETAs nor a guarantee. At the same point, staying the course with a top-down design means that should Minecraft switch to components, its an API-break.

So, weighing all the factors…what is everyone’s thoughts on the matter? This decision needs to be made soon-ish before we are at the point where we break plugins “correcting” this.

Components or not?

15 Likes

What exactly is the Metadata object supposed to be? I don’t want to latch on to details of an example but that seems pretty central to your design.

I should have touched on it

Its basically a mapping of some identifier + some value

For instance, health is really some value arbitrarily changed. I would key it to “health” and save the value with it.

I am welcome to suggestions on handling and storing this data.

What would be the plan for adding these to MC entities?

The core [Sponge]Entity would have a reference to the MC entity and then each component would pass calls to the MC entity?

In theory, if MC went down the same route, there would be a SpongeEntity with a collection of components referencing a MC entity with a collection of components.

I think the plan was to monkey patch implementations of the Sponge interfaces onto the actual MC entity objects so we’d be storing the components directly in them. Since all the components would be interfaces in Sponge if MC had any that matched we could just drop theirs in directly. If not we’d have wrappers (and perhaps deprecate them and move to MCs component setup) which would be alright.

1 Like

A Component is only a data container:
http://t-machine.org/index.php/2007/11/11/entity-systems-are-the-future-of-mmog-development-part-2/

As my understanding the ES-System interact with the MC entity :wink:

I really like this idea, and it would also be super cool to extend this component system for the AI. AI behaviors could be regarded as just components on special entities, and it would allow for mix-and-match AI with custom mobs.

I’ve always wanted a component system for development in minecraft… It’s a dream come true!

I’d love that. give a bat the creeper explosive ability and make them hostile. oh and add a moo just for the kicks.
But this could be extended to some sort of npc system allowing for adding custom pathing behaviors and such like the citizens plugin did.

The AI, based on my code skimming, appears to be a component system already. There’s an AI for all sorts of small tasks, instead of just one AI for an entity. I actually saw that when I was interested in improving the dog pathfinding, although I never got too far into it.

Hm… I haven’t looked over the MC source, but if it’s already a component system, that makes it all the easier for Sponge to wrap the native component system with its own. I’m going to get to work on putting this in the API.

@gratimax
Before you start,
there are many discussions on closed PR’s and open PR’s …
Also there are some Entities PR’s that are not inclused yet:
SpongeApiOverview by IDragonfire - Google Sheets

Maybe wait on a respone from a core dev :wink:

Ohmygod. A decent AI system.

That’s fantastic

The point is that HealthComponent is an implementation of Health. The actual interface would be present in SpongeAPI, and the implementation would be present in Sponge. However, from a plugin’s point of view, they are dealing with a Health component, regardless of implementation.

Design Pattern - EntitySystem:

http://t-machine.org/index.php/2007/09/03/entity-systems-are-the-future-of-mmog-development-part-1/

A HealthComponent is a DataContainer that:

  1. is a label, that the entity has Health
  2. store data for the system

A System, e.g. HealthSystem managing, execute, processing stuff.
@Zidane Is that right?

Would there be any use to giving names to components when added to component holders, so that component access would just be a cast, something like (Health) entity.get("health")? One would then dynamically add a component with entity.set("health", myHealthComponent) I imagine that it wouldn’t be useful to put multiple components doing the same thing, so the holder would get ‘slots’ for the different components. First off this would prevent unnecessary iteration and make component access easier, and it would also restrict behavior to a well-defined and constrained set of names.

There could also be some sense of nesting, where child components would be able to get their parent components. E.g. for each entity there would be an "ai" name, and components that modify that would go under, like "ai.hide" or "ai.attack".

I’ll agree with this if us plugin devs are allowed to make custom components and attach them to whatever objects we want. I’m thinking fly component, player controller movement component, etc on a block = instant airplane. :slight_smile:

@Amaranth brought up a good point about Artemis (read about it here) and I think I can revise Components to not contain any logic (just data driven accessors). We can also extend this system to Blocks/Items…

API:

interface Block extends ComponentHolder<BlockComponent> {
    String getID();
}

interface BlockComponent extends Component<Block> {
}

interface Book extends BlockComponent {
    String getTitle();
}

We also need the Systems concept @IDragonfire brought up. I’ll keep conceptualizing this tonight and start pushing code to a branch.

2 Likes

I recommend this article again:
http://t-machine.org/index.php/2007/11/11/entity-systems-are-the-future-of-mmog-development-part-2/

I try to explain it from my point of view as short and simple as possible (for details wait on @Zidane code)

A EntitySystem has three elements:

  1. Entities
  2. Components
  3. Systems

An Entity is a unique Unit in a game.
It can be EVERYTHING (The zombie in front of your house, a bow, the grass, the lightparticle, …)
An Entity has only a UUID and Components.

Each Component has also a label and component data for each entity.
(e.g. base health, current health, …)

A System, e.g. CombatSystem grab the Components, e.g. HealhtComponent, DamageComponent, … from the entities and calculate the damage, set the new health …

Entities and Components have NO logic.

The system is very powerful, e.g. everything can do anything :smiley:

Overview:

I would love to see Vehicles like Trains in working order with this Component System.