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.
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.
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.
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
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;
}
}
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”
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
There is no way of adding Components to Entities (in releation with 1.?)
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?
TypeComponent should be removed (or renamed to ModelComponent, RenderComponent, ViewLikeComponent).
Developer can to easliy abuse it, e.g. to find all Zombies.