-
Notifications
You must be signed in to change notification settings - Fork 11
Prefabs
We want to be able to reuse certain components across different entities, and we often want to have specific entity types that we make instances out of.
Prefabs are a common word for these instantiable entity types, but the implementations vary widely. The following will be an outline of what our current system will look like after a small rewrite. At the end, I will start adding links to other solutions to this problem and discuss limitations of our current system.
Mobzy often extends some NMS classes such as FlyingEntity, Monster, etc... to override some behaviour to fit our ECS more (ex when the server requests for a mob to play a sound, Mobzy overrides that and goes through a Sounds
component).
However, we can't rely on this because we're trying to avoid inheritance! As explained in Linking Minecraft and Geary entities, we don't actually need to get into NMS to make a geary entity if we don't wish to override anything, so we know our prefab system must be separated from the NMS inheritance hierarchy.
We store our prefabs in config files. These contain Static, instance, and persisting components, which can be added to a geary entity.
Static components in our prefabs get created when we first deserialize the prefab, and one instance is added as a component for all instances of the prefab. We don't want to persist these components on entities because we know it makes sense for all entities made from this prefab to share them. Storing them on each entity writes unnecessary data, slows down serialization, and forces us to make migrations if we ever make updates.
With this in mind, the current solution is for entities to store a reference to a prefab. A component stores this reference as a string corresponding to prefab config's name. When the entity loads, we look for the this prefab component and apply components from the prefab as instructed.
Currently we have specific prefab implementations for Looty items and Mobzy mobs so we can instantiate entities from the prefab. However, this means we can't use prefabs to just apply components onto existing bukkit entities.
Luckily, we could move all the information we need for spawning into one property that uses polymorphic serialization to define how a prefab gets instantiated. Then we get the option to either apply a prefab to an existing entity or instantiate a new one with it!
An analogy I like for prefabs is Kotlin's singleton objects. Defining a prefab in a config allows us to assign it a name and reference it later, just as defining a singleton allows us to reference it by name later.
Kotlin also lets us create anonymous objects which don't have a name. Hence, the idea of anonymous prefabs. We could allow defining prefabs either by reference or by just defining a new prefab in the same config. For instance, say we want to shoot a projectile that poisons the player on hit. We could either make a new prefab for this projectile in a separate file, or we could create an anonymous prefab in the same config.
If we don't wish to persist a reference to this prefab, this becomes trivial to do. This feels like a reasonable limitation to have, as the alternative means somehow getting a name to reference this anonymous prefab by.
- Will fill this in as we get more stuff!