Component System and Minecraft

We have now a name conflict,
Did you mean cs.Entity or mc.Entity.

But.

NO

Nothing should extend a cs.Entity (or an cs.Entity?)
A cs.Entity is only a UUID

@Zidane
Maybe rename cs.Entity to ComponentEntity

Two

Notes:
General Blocks are not planned to be part of the Component System for performance reason, with some exceptions:

Ok, so that means ā€œEntityā€ really just is a name or uuid, and can be anything (a mob, a player, a world, a chest, a named item, a book item) depending on the attached components?

I understand that handling every block in a world as an entity doesnā€™t work (one object for every block), but it could be a hybrid system:

//returns a fresh Entity instance (just an uuid, you can store it in the minecraft save, nbt...)
Entity blockEntity = world.getBlockEntity(int x, int y, int z) 

//creates the material component when you ask for it
blockEntity.get("material",MaterialComponent.class).getID() 
// ---> "minecraft:chest"

//add a custom metadata component
blockEntity.add("owner",new CustomOwnerComponent(ownerPlayer))

1 Like

An Entity is a UUID.
What an entity is depends on the Components.
A name nornally depends on the component set ā€¦
Maybe take a look at my tutorial:

That is actually the plan. There wonā€™t be metadata classes, instead you will be able to attach components to everything. Book items? Just attach the pages and stuff. Snow blocks? Just add the layers component. If I got that correctly that is.

I too thought that it originally was only meant to be for entities, but @Zidane plans to do it that way - and I quite like the idea :wink:

2 Likes

I read that. The name ā€œentityā€ is just misleading. You should define what an entity can be depending on components. A mob, a book, a block, a world, a custom type.

There will be metadata components. You can just make your own class that implements Component, and stores custom data, or not?

Will custom/removed component changes persist across server restarts and whatnot? Or will it be dependent on plugins to keep track of entity UUID and re add/remove components when the server starts back up.

In regards to custom components, how will the component system know how to react to custom data? Say I have a RPG stat component with various stats and modifiers. How do I tell the ComponentSystem to take those values into account when manipulating health, damage, and such.

Earlier in the thread, I was talking about making a EntityBuilder, rather than use factories to create entities. Taking into account comments so far, I think something like the following Gist should give an idea as to what I meant:

Iā€™ve only written this quickly, so it might have a couple of syntatic errors in it (I havenā€™t got my IDE to hand yet). However, it should show the basics of how someone might create an entity itself - and how you could validate such a created entity.

Remember, such a builder is a template of an entity that could be created - so could also be used to create multiple copies. Weā€™d have to be careful to clone the components though, otherwise we might actually share one reference to a component to multiple entities.

Based on what has been said so far, you could create a creeper using this builder in the following way (this is not necessarily how components work/will work, just making a point):

HealthComponent comp = new HealthComponent();
comp.setHealth(10);
Entity e = EntityBuilder.forEntity("minecraft:creeper").with(comp).build();

The with method would replace the previous health component (if it exists), and the build method could do all of the required attaching to various classes. You could potentially use a fluent interface for entities themselves, but in that case, validation would need to be done during modification.

I must stress that this is not a completed builder system, Iā€™ve only written it to the extent where it should give you an idea on my thoughts on entity creation. Itā€™s main advantage would be to ensure that an entity would be created correctly, and wonā€™t create an entity that is missing vital components (thatā€™s what the validator is for - and the validator can be shared amongst multiple entities).

Regardless of whether what Iā€™ve said is useful or not, Iā€™d hope having such a entity system should hopefully make it much easier to work with entities - looking forward to see what comes out of the work!

An cs.entity can by everything ā€¦ a block, a zombie, a particle, a player

Components have no logic, Componets are only data container (maybe if that your defintion of metadata) ā€¦
But metadata normally groups data ā€¦ but you need no metadata (like a string for zombies), because the set of components (the aspects) are enough metadata ā€¦

You need to implement a CustomManager (init, load, addd Entites and Components) and CustomSystem (process all, here the actions happen)

I see this as a feature :wink:
.

One thing I donā€™t understand is which class stores the components that belong to an entity?

Why are the methods for adding, removing and getting components in the entity class?
I think they should be in the ComponentManager class, and the ones in the Entity class should just be convenience methods, right?

Iā€™m asking because the getter method is missing in ComponentManager:

<C extends Component> C getComponent(H holder, ComponentKey<C> key);

That is a good question. For that you would need to extend or replace the damage systems that are in effect. Most likely in sponge there will be only 1 damage system that will handle all the normal incoming damage(e.g. hits, lava, fire ticks, etc). To apply your own calculations, you would override that damage system so it would take your rpg stats into account.

Why not write your own system?
But, yes ā€¦
How can we inject existing systems?

You cann access it over the system (manager store it):
https://github.com/SpongePowered/SpongeAPI/blob/component-system/src/main/java/org/spongepowered/api/component/ComponentSystem.java#L78
ComponentSystem

Collection<H> getAll();

Iā€™m sorry, but the system does not store the components. It just works with them. The ComponentManager or the ComponentHolder (not quite sure yet) stores the instances.

Thatā€™s not right, ā€œHā€ refers to ā€œholderā€, itā€™s just a collection of entities, not components.

I think it should be the Manager, as it makes it easier to handle saving and loading of component instances.

What about this?

Well, for now the plan is that we just provide the API - it depends on the implementation how to store the data directly.

If you want to create a custom mod that adds a few new components you might want to think about how to store them. Since we probably wont have a meta-data system, but a component-based system I am sure that thereā€™ll be an implementation (like NBT) that can add new data to entities.

In the end it really just comes down to you; Whether itā€™ll be a text-file, just fields or something else.

Just a question(s)ā€¦
Lets say i want to add mana for each player.

  • i start by creating a mana component

    interface Mana extends Component {
    public static ComponentKey key = new blahā€¦
    double getMax(); double getCurrent();
    void setMax(double d); void setCurrent(double d);
    }

then i will need to create ComponentManager for my mana thing

class ManaComponentManager implements ComponentManager <Mana> {
          <overrided methods>
}

when player joins the server ill call method

componentManager.addComponent(H holder, Mana.key,<object which implements mana interface>);

where holder is the player object

if i want to handle all mana changes ā€œmanuallyā€ (eg.: on command) then my componentsystem must return always false in method boolean shouldProcess(), but if i will want to create for example manaregen then my best friend is going to be method void process(H holder, float dt); which is called on every game tick?

which class will hold an instance of my componentmanager and componentsystem.
am i guessing right that componentsystem must be registered into some kind of tickhandler in minecraft. And how about concurrency. Is it going to be threadsafe access/add/remove components from another thread?

(im bad at writting pseudocode :/)

No! You make a component manager for entity types, not one every component.

Use the component manager already linked with the player:

Entity playerEntity = server.getPlayer("Notch");

ComponentManager<Entity> componentManager = playerEntity.getComponentManager();

componentManager.addSystem(new ManaSystem(), ManaSystem.class);

componentManager.addComponent(playerEntity, new ManaComponent());
//or instead of that:
playerEntity.addComponent(new ManaComponent());

I have pushed another big change to the spec (Iā€™m sorry FAQ writers, truly!).

Iā€™ll quickly break down some concepts (much more indepth doc coming soon), bottom up

GameObject - Any object in an engine. Minecrat is our engine and we are focusing on Entities (with Blocks and Items to follow)

Component - Simply a data holder. Plugin devs extend this to add their own attributes to a GameObject

ComponentSystem - An object whose job is to take a filter of Components and compile together a list of GameObjects that fit this filter. Only these objects get processed byā€¦

ComponentManager - An object whose job is to register ComponentSystems as well as track which Components are on which GameObjects. Typically a World or Game has a ComponentManager and they pass off GameObjects to be processed to the system (if they meet the filter)

From a plugin developerā€™s prespective, you will get in the habit of making Components, attaching them to Entities/etc (myEntity.addComponent(myComponent)) and creating a system to do something with those Entities/etc if they have your Component. You can manually process your system or let Minecraft do it each game loop (from the ComponentManager in World).

You can even get much more intricate and define your own ComponentManager for your own custom game objects! By default, weā€™ll give your classic Entity, Block, and Item their own ComponentManagers per World but if you add your own object to the game (dunno what it would be), the API lets you control the ENTIRE process.

Last but not least, the latest spec allows you to attach multiple of the same Component (such as Inventory) with your extended versions! In example, a Player would have an Inventory for their typical Player inventory and one for an Enderchest version.

2 Likes

Couldnā€™t this also be a method of implement something like this:

EDIT for clarification:
I am thinking about unity/engine like scripting functionality

1 Like