-
Notifications
You must be signed in to change notification settings - Fork 2
Extensibility of the EntityTypeContainer system
The EntityTypeContainer
class (and its builders) are designed to be extended and added to. You can also extend EntityRegistrarHandler
to include shorthand for new EntityTypeContainer
subclasses. IMDLib natively includes an extended EntityTypeContainer
!
Example in Better Animals Plus
Because of the complicated generic typing nature of builders and wrappers, I created a way to properly chain said extensions infinitely. Here is a chart of the inheritance that I made.
Essentially, you make a chain of abstract versions of your container's builder, then define an implementation with the proper built definitions, such that generic type chain is intact and getImplementation()
does not return the parent class' type.
I'll stop with the gibberish now and give you some concrete examples.
This is the class that will be used in the end, your extension of EntityTypeContainer
.
In this example, I will be using EntityTypeContainerExample
. It will require that the entity extends ExampleEntity
.
public class EntityTypeContainerExample<T extends ExampleEntity> extends EntityTypeContainer<T> {
protected int customValue;
private EntityTypeContainerExample(ExampleEntityTypeDefinition<T> def) {
this.customValue = def.getCustomValue();
}
public int getCustomValue() {
return customValue;
}
}
This class will simply retrieve a custom value from the builder and expose it via a method, but you can imagine the possibilities with this system, for example overriding the custom configuration methods to add a configuration field based on this value.
Now, there is an undefined ExampleEntityTypeDefinition
. I created these interfaces so that the constructor's argument list would be of manageable size due to the sheer amount of data to pass in.
This class will simply accept a builder and expose fields on the builder.
public class ExampleEntityTypeDefinition<T extends ExampleEntity> extends EntityTypeDefinition<T> {
AbstractEntityBuilderExample<T, ?, ?> builder;
public ExampleEntityTypeDefinition(AbstractEntityBuilderExample<T, ?, ?> builder) {
super(builder);
this.builder = builder;
}
public int getCustomValue() {
return builder.customValue;
}
}
As a side note, I like to put all of these classes as protected or public static inner classes of the main EntityTypeContainer, so as not to clutter the filesystem.
Now, we need to define the abstract builder. This will hold all of the extended logic for the container.
public abstract class AbstractEntityBuilderExample<T extends ExampleEntity, C extends EntityTypeContainerExample<T>, B extends AbstractEntityBuilderExample<T, C, B>> extends AbstractEntityBuilder<T, C, B> {
protected int customValue;
protected AbstractEntityBuilderExample(Class<T> entityClass, EntityType.IFactory<T> factory, String entityNameIn, Supplier<AttributeModifierMap.MutableAttribute> attributeMap, String modid) {
super(entityClass, factory, entityNameIn, attributeMap, modid);
}
public B customValue(int customValue) {
this.customValue = customValue;
return getImplementation();
}
}
Finally, we define the implementation of this abstract builder.
public class EntityTypeContainerExampleBuilder<T extends ExampleEntity> extends AbstractEntityBuilderExample<T, EntityTypeContainerExample<T>, EntityTypeContainerExampleBuilder<T>> {
protected EntityTypeContainerExampleBuilder(Class<T> entityClass, EntityType.IFactory<T> factory, String entityNameIn, Supplier<AttributeModifierMap.MutableAttribute> attributeMap, String modid) {
super(entityClass, factory, entityNameIn, attributeMap, modid);
}
@Override
public EntityTypeContainerExample<T> rawBuild() {
return new EntityTypeContainerExample<>(new ExampleEntityTypeDefinition<>(this));
}
@Override
public EntityTypeContainerExampleBuilder<T> getImplementation() {
return this;
}
public static <T extends ExampleEntity> EntityTypeContainerExampleBuilder<T> create(Class<T> entityClass, EntityType.IFactory<T> factory, String entityNameIn, Supplier<AttributeModifierMap.MutableAttribute> attributeMap, String modid) {
return new EntityTypeContainerExampleBuilder<>(entityClass, factory, entityNameIn, attributeMap, modid);
}
}
Now, you can get a builder via the create
method on the EntityTypeContainerExampleBuilder
class.