Component System and Minecraft

Quick question. Is the component system just various control points to control entities and other things? Or will we be able to extend some class to create our own with methods to override and manipulate the component holder or to just store data on to it.

I saw someone mention a system like Unity’s and I thought it would be a nice way to manipulate individual entities rather than making wrapper classes and listeners for everything.

The Component-System is an new approach:
http://t-machine.org/index.php/2007/11/11/entity-systems-are-the-future-of-mmog-development-part-2/

It is an NON oop approach.
You do not extend an Entity Class like in the past, because entites have no logic.

You use Components to label Entities and manage it with your own Systems/Managers.

They are talking about implementing ECS, which is not the same as unity’s system.

The main difference is that in ECS all the “component logic” is done in systems, whereas with unity it is on the component itself. Components in ECS are just data containers on which systems operate.

So yes, you will be able to create and add new components to entities and use systems to control them.

I understand the entity has no logic in this system, what I want to know is if we will be able to create our own components and add functionality or remove another component to remove it.

This of course would only happen to a single entity unless you listened for all or looped through all and made the change.

you ninja answered my question before I even asked it XD

But can I remove another component?

Yes this is the plan. You should be able to create new components and systems and attach them to any existing and / or custom entity.

Components can be added and removed.

Quick x-post: Discussion: Components, TypeComponents for Entities by jacklin213 · Pull Request #132 · SpongePowered/SpongeAPI · GitHub

@Zidane: “Is My Entity an Enderman”?

Thats true, and a few people (including @IDragonfire and myself) talked about this in IRC earlier today.

An entity is only defined by its components. But since they are very dynamic you cannot say “hey everybody with a health component is a hostile entity”. I think that was the reason for you to introduce the TypeComponent (correct me if I’m wrong).

Since the entity CLASS should be final (makes no sense to have an interface for it) and the components that extend the base entitycomponent as well (Once again, I would vote for them being classes as well, since they only store values, and have nothing to do with the logic), there should be at least a RenderComponent, ModelComponent or a TypeComponent that define the type or the way to render the entity.

The type could be an integer, although I wouldn’t really vote for that, since we want to be as dynamic as possible, right? Using an identifier-string once again would solve this problem.

Performance wise … Well, if you would have to check each tick a bunch of strings instead of class hierarchy you definitely would loose some FPS. So what to do? We could either create components for each mob type (would work, but is kind of ugly), or solve the “too-much-checks” problem by using the hashcode of the string and saving it in an integer (or something like that), which would reduce the lookup time by quite something (I’m guessing).

Something like that could be looking like the following:

public final class TypeComponent implements EntityComponent {
  private final int typeHash;
  private final String typeString;

  public TypeComponent(String typeString) {
    this.typeString = typeString;
    this.typeHash = typeString.hashCode();
  }

  public String getType() {
    return typeString;
  }

  public boolean isType(String other) {
    return typeHash == (other == null ? 0 : other.hashCode());
  }
}

There is almost no need to store the exact monster type as a component. Systems should not use it, and in the case you do need a specific entity type(for what purpose I would have no idea) you could have a simple NameComponent/TypeComponent which stores the name of the entity. There is no need to optimize this, because it should (almost) never be used. I could see it used by plugin developers that don’t understand the ECS structure well, but it should be discouraged.

In an ECS you never want to ask “is this entity a specific type”. Instead you will want to ask “Does this entity have this aspect” and aspects are represented by components.

For the rendering/model type sent to the client you would have a different component. And you should never use that component to see what kind of entity it is. It should only be used to tell the client what to render.

the components that extend the base entitycomponent as well (Once again, I would vote for them being classes as well, since they only store values, and have nothing to do with the logic)

I would argue against that. How it is stored can be an important implementation detail. e.g. with the RenderComponent it makes sense to store the internal value as an int or enum that is used for the package sent to the client, but for the API it makes no sense to expose it like that. You would want to expose it as a string and convert it to the int/enum value when it is set. The render system would use the int/enum value instead of converting it every time it is needed.

My suggestions: remove entity component, remove componentholder, remove enderman and add a NmsComponent
TypeComponent is enough.

@Falkreon and I started a document for the system and interactions:

Regarding the first topic of your post: Yes, thats true. I just tried to explain how it could be done for those who really do want to know it. I guess, you’re right when it is so “unimportant” that we do not need to think about that kind of performance optimization.

Regarding the second topic: Hmm, true. I guess I just assumed that it would always be an integer, my bad :wink:

Fair enough, I actually agree. Bear in mind I’m thinking about all those people used to Bukkit because this will easily trip them up if ECS is a new concept to them. This is an easy solution that makes both camps happy…

interface ModelComponent extends Component {
    String getModel();        
}

public enum VanillaModel extends ModelComponent {
    ENDERMAN(0, "enderman")

    private final int id;
    private final String identifier;

    public VanillaModel(int id, String identifier) {
        this.id = id;
        this.identifier = identifier;
    }
    
    @Override
    public String getModel() {
        return identifier;
    }
}
5 Likes

Yes. That seems like a suitable solution.

Yes that seems like a good solution, however I would also add namespacing to this. What if two mods add the same kind of mob but have different renderers (birds, snakes, …)? Vanilla could use “minecraft” as it uses that for the blocks already, so an enderman could be “minecraft:enderman” :wink:

Already had that thought and agreed.

If you want to see an example of this kind of thing in C#, I wrote a simple one a few years ago:

Isn’t that exactly what you tried to avoid? Discussion: Components, TypeComponents for Entities by jacklin213 · Pull Request #132 · SpongePowered/SpongeAPI · GitHub

Has the idea of using a marker interface or type components been discarded?

The Vanilla model can be an enum because nobody should be able to extend or change it. If they want to create their own models, they can just implement the ModelComponent on their own :wink:

1 Like

well done :smiley:

Some questions/comments:

  1. ComponentHolder still exists in ComponentManager
  2. There is no way of adding Components to Entities (in releation with 1.?)
  3. Why ComponentSystem and ComponentManager have a generic type <H>? Should be <H extends Component> but, why should Systems, Managers process only one Component? And why H, for Holder?

Current class diagram:

I wrote a little Tutorial:

Thanks to @Zerot for his help.

TypeComponent should be removed (or renamed to ModelComponent, RenderComponent, ViewLikeComponent).
Developer can to easliy abuse it, e.g. to find all Zombies.

I think this could replace the limited Bukkit Metadata System.

Components for any Game Object!

ComponentManager<Entity>
ComponentManager<Block>
ComponentManager<World>

Just one important question: Should Block and World extend Entity?