diff --git a/src/main/java/com/jozufozu/flywheel/api/Instancer.java b/src/main/java/com/jozufozu/flywheel/api/Instancer.java index 8ea0c3f70..5b6ac1cb4 100644 --- a/src/main/java/com/jozufozu/flywheel/api/Instancer.java +++ b/src/main/java/com/jozufozu/flywheel/api/Instancer.java @@ -50,4 +50,14 @@ public interface Instancer { *

*/ void notifyRemoval(); + + /** + * Populate arr with new instances of this model. + * @param arr An array to fill. + */ + default void createInstances(D[] arr) { + for (int i = 0; i < arr.length; i++) { + arr[i] = createInstance(); + } + } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderRegistry.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderRegistry.java index 87f43a90e..1946dabdb 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderRegistry.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderRegistry.java @@ -21,89 +21,177 @@ import net.minecraft.world.entity.EntityType; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; +/** + * A utility class for registering and retrieving {@code InstancingController}s. + */ +@SuppressWarnings("unchecked") public class InstancedRenderRegistry { + /** + * Checks if the given block entity type can be instanced. + * @param type The block entity type to check. + * @param The type of the block entity. + * @return {@code true} if the block entity type can be instanced. + */ public static boolean canInstance(BlockEntityType type) { - return getBlockEntityController(type) != null; + return getController(type) != null; } + /** + * Checks if the given entity type can be instanced. + * @param type The entity type to check. + * @param The type of the entity. + * @return {@code true} if the entity type can be instanced. + */ public static boolean canInstance(EntityType type) { - return getEntityController(type) != null; + return getController(type) != null; } + /** + * Creates an instance for the given block entity, if possible. + * @param materialManager The material manager to use. + * @param blockEntity The block entity to create an instance of. + * @param The type of the block entity. + * @return An instance of the block entity, or {@code null} if the block entity cannot be instanced. + */ @Nullable public static BlockEntityInstance createInstance(MaterialManager materialManager, T blockEntity) { - BlockEntityInstancingController controller = getBlockEntityController(getType(blockEntity)); + BlockEntityInstancingController controller = getController(getType(blockEntity)); if (controller == null) { return null; } return controller.createInstance(materialManager, blockEntity); } + /** + * Creates an instance for the given entity, if possible. + * @param materialManager The material manager to use. + * @param entity The entity to create an instance of. + * @param The type of the entity. + * @return An instance of the entity, or {@code null} if the entity cannot be instanced. + */ @Nullable public static EntityInstance createInstance(MaterialManager materialManager, T entity) { - EntityInstancingController controller = getEntityController(getType(entity)); + EntityInstancingController controller = getController(getType(entity)); if (controller == null) { return null; } return controller.createInstance(materialManager, entity); } + /** + * Checks if the given block entity is instanced and should not be rendered normally. + * @param blockEntity The block entity to check. + * @param The type of the block entity. + * @return {@code true} if the block entity is instanced and should not be rendered normally. + */ public static boolean shouldSkipRender(T blockEntity) { - BlockEntityInstancingController controller = getBlockEntityController(getType(blockEntity)); + BlockEntityInstancingController controller = getController(getType(blockEntity)); if (controller == null) { return false; } return controller.shouldSkipRender(blockEntity); } + /** + * Checks if the given entity is instanced and should not be rendered normally. + * @param entity The entity to check. + * @param The type of the entity. + * @return {@code true} if the entity is instanced and should not be rendered normally. + */ public static boolean shouldSkipRender(T entity) { - EntityInstancingController controller = getEntityController(getType(entity)); + EntityInstancingController controller = getController(getType(entity)); if (controller == null) { return false; } return controller.shouldSkipRender(entity); } + /** + * Get an object to configure the instancing controller for the given block entity type. + * @param type The block entity type to configure. + * @param The type of the block entity. + * @return The configuration object. + */ public static BlockEntityConfig configure(BlockEntityType type) { return new BlockEntityConfig<>(type); } + /** + * Get an object to configure the instancing controller for the given entity type. + * @param type The entity type to configure. + * @param The type of the entity. + * @return The configuration object. + */ public static EntityConfig configure(EntityType type) { return new EntityConfig<>(type); } - @SuppressWarnings("unchecked") + /** + * Gets the instancing controller for the given block entity type, if one exists. + * @param type The block entity type to get the instancing controller for. + * @param The type of the block entity. + * @return The instancing controller for the given block entity type, or {@code null} if none exists. + */ @Nullable - public static BlockEntityInstancingController getBlockEntityController(BlockEntityType type) { + public static BlockEntityInstancingController getController(BlockEntityType type) { return ((BlockEntityTypeExtension) type).flywheel$getInstancingController(); } - @SuppressWarnings("unchecked") - public static void setBlockEntityController(BlockEntityType type, BlockEntityInstancingController instancingController) { - ((BlockEntityTypeExtension) type).flywheel$setInstancingController(instancingController); - } - - @SuppressWarnings("unchecked") + /** + * Gets the instancing controller for the given entity type, if one exists. + * @param type The entity type to get the instancing controller for. + * @param The type of the entity. + * @return The instancing controller for the given entity type, or {@code null} if none exists. + */ @Nullable - public static EntityInstancingController getEntityController(EntityType type) { + public static EntityInstancingController getController(EntityType type) { return ((EntityTypeExtension) type).flywheel$getInstancingController(); } - @SuppressWarnings("unchecked") - public static void setEntityController(EntityType type, EntityInstancingController instancingController) { + /** + * Sets the instancing controller for the given block entity type. + * @param type The block entity type to set the instancing controller for. + * @param instancingController The instancing controller to set. + * @param The type of the block entity. + */ + public static void setController(BlockEntityType type, BlockEntityInstancingController instancingController) { + ((BlockEntityTypeExtension) type).flywheel$setInstancingController(instancingController); + } + + /** + * Sets the instancing controller for the given entity type. + * @param type The entity type to set the instancing controller for. + * @param instancingController The instancing controller to set. + * @param The type of the entity. + */ + public static void setController(EntityType type, EntityInstancingController instancingController) { ((EntityTypeExtension) type).flywheel$setInstancingController(instancingController); } - @SuppressWarnings("unchecked") + /** + * Gets the type of the given block entity. + * @param blockEntity The block entity to get the type of. + * @param The type of the block entity. + * @return The {@link BlockEntityType} associated with the given block entity. + */ public static BlockEntityType getType(T blockEntity) { return (BlockEntityType) blockEntity.getType(); } - @SuppressWarnings("unchecked") + /** + * Gets the type of the given entity. + * @param entity The entity to get the type of. + * @param The type of the entity. + * @return The {@link EntityType} associated with the given entity. + */ public static EntityType getType(T entity) { return (EntityType) entity.getType(); } + /** + * An object to configure the instancing controller for a block entity. + * @param The type of the block entity. + */ public static class BlockEntityConfig { protected BlockEntityType type; protected BiFunction> instanceFactory; @@ -113,32 +201,54 @@ public class InstancedRenderRegistry { this.type = type; } + /** + * Sets the instance factory for the block entity. + * @param instanceFactory The instance factory. + * @return {@code this} + */ public BlockEntityConfig factory(BiFunction> instanceFactory) { this.instanceFactory = instanceFactory; return this; } + /** + * Sets a predicate to determine whether to skip rendering a block entity. + * @param skipRender The predicate. + * @return {@code this} + */ public BlockEntityConfig skipRender(Predicate skipRender) { this.skipRender = skipRender; return this; } + /** + * Sets a predicate to always skip rendering for block entities of this type. + * @return {@code this} + */ public BlockEntityConfig alwaysSkipRender() { this.skipRender = be -> true; return this; } + /** + * Constructs the block entity instancing controller, and sets it for the block entity type. + * @return The block entity instancing controller. + */ public SimpleBlockEntityInstancingController apply() { Objects.requireNonNull(instanceFactory, "Instance factory cannot be null!"); if (skipRender == null) { skipRender = be -> false; } SimpleBlockEntityInstancingController controller = new SimpleBlockEntityInstancingController<>(instanceFactory, skipRender); - setBlockEntityController(type, controller); + setController(type, controller); return controller; } } + /** + * An object to configure the instancing controller for an entity. + * @param The type of the entity. + */ public static class EntityConfig { protected EntityType type; protected BiFunction> instanceFactory; @@ -148,28 +258,46 @@ public class InstancedRenderRegistry { this.type = type; } + /** + * Sets the instance factory for the entity. + * @param instanceFactory The instance factory. + * @return {@code this} + */ public EntityConfig factory(BiFunction> instanceFactory) { this.instanceFactory = instanceFactory; return this; } + /** + * Sets a predicate to determine whether to skip rendering an entity. + * @param skipRender The predicate. + * @return {@code this} + */ public EntityConfig skipRender(Predicate skipRender) { this.skipRender = skipRender; return this; } + /** + * Sets a predicate to always skip rendering for entities of this type. + * @return {@code this} + */ public EntityConfig alwaysSkipRender() { this.skipRender = entity -> true; return this; } + /** + * Constructs the entity instancing controller, and sets it for the entity type. + * @return The entity instancing controller. + */ public SimpleEntityInstancingController apply() { Objects.requireNonNull(instanceFactory, "Instance factory cannot be null!"); if (skipRender == null) { skipRender = entity -> false; } SimpleEntityInstancingController controller = new SimpleEntityInstancingController<>(instanceFactory, skipRender); - setEntityController(type, controller); + setController(type, controller); return controller; } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/blockentity/BlockEntityInstancingController.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/blockentity/BlockEntityInstancingController.java index d2af7e459..23bf0b318 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/blockentity/BlockEntityInstancingController.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/blockentity/BlockEntityInstancingController.java @@ -4,8 +4,23 @@ import com.jozufozu.flywheel.api.MaterialManager; import net.minecraft.world.level.block.entity.BlockEntity; +/** + * An instancing controller that will be keyed to a block entity type. + * @param The type of block entity this controller is for. + */ public interface BlockEntityInstancingController { + /** + * Given a block entity and a material manager, constructs an instance for the block entity. + * @param materialManager The material manager to use. + * @param blockEntity The block entity to construct an instance for. + * @return The instance. + */ BlockEntityInstance createInstance(MaterialManager materialManager, T blockEntity); + /** + * Checks if the given block entity should not be rendered normally. + * @param blockEntity The block entity to check. + * @return {@code true} if the block entity should not be rendered normally, {@code false} if it should. + */ boolean shouldSkipRender(T blockEntity); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/blockentity/BlockEntityTypeExtension.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/blockentity/BlockEntityTypeExtension.java index e21f03334..3ac1bbb7e 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/blockentity/BlockEntityTypeExtension.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/blockentity/BlockEntityTypeExtension.java @@ -1,9 +1,12 @@ package com.jozufozu.flywheel.backend.instancing.blockentity; +import javax.annotation.Nullable; + import net.minecraft.world.level.block.entity.BlockEntity; public interface BlockEntityTypeExtension { + @Nullable BlockEntityInstancingController flywheel$getInstancingController(); - void flywheel$setInstancingController(BlockEntityInstancingController instancingController); + void flywheel$setInstancingController(@Nullable BlockEntityInstancingController instancingController); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstancingController.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstancingController.java index c835ca59e..740800f6b 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstancingController.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstancingController.java @@ -4,8 +4,23 @@ import com.jozufozu.flywheel.api.MaterialManager; import net.minecraft.world.entity.Entity; +/** + * An instancing controller that will be keyed to an entity type. + * @param The entity type. + */ public interface EntityInstancingController { + /** + * Given an entity and a material manager, constructs an instance for the entity. + * @param materialManager The material manager to use. + * @param entity The entity to construct an instance for. + * @return The instance. + */ EntityInstance createInstance(MaterialManager materialManager, T entity); + /** + * Checks if the given entity should not render normally. + * @param entity The entity to check. + * @return {@code true} if the entity should not render normally, {@code false} if it should. + */ boolean shouldSkipRender(T entity); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityTypeExtension.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityTypeExtension.java index cede41bbe..b01918acd 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityTypeExtension.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityTypeExtension.java @@ -1,9 +1,12 @@ package com.jozufozu.flywheel.backend.instancing.entity; +import javax.annotation.Nullable; + import net.minecraft.world.entity.Entity; public interface EntityTypeExtension { + @Nullable EntityInstancingController flywheel$getInstancingController(); - void flywheel$setInstancingController(EntityInstancingController instancingController); + void flywheel$setInstancingController(@Nullable EntityInstancingController instancingController); } diff --git a/src/main/java/com/jozufozu/flywheel/mixin/BlockEntityTypeMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/BlockEntityTypeMixin.java index c9f086957..ba5b86e18 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/BlockEntityTypeMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/BlockEntityTypeMixin.java @@ -1,5 +1,7 @@ package com.jozufozu.flywheel.mixin; +import javax.annotation.Nullable; + import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -15,12 +17,13 @@ public class BlockEntityTypeMixin implements BlockEntityT private BlockEntityInstancingController flywheel$instancingController; @Override + @Nullable public BlockEntityInstancingController flywheel$getInstancingController() { return flywheel$instancingController; } @Override - public void flywheel$setInstancingController(BlockEntityInstancingController instancingController) { + public void flywheel$setInstancingController(@Nullable BlockEntityInstancingController instancingController) { this.flywheel$instancingController = instancingController; } } diff --git a/src/main/java/com/jozufozu/flywheel/mixin/EntityTypeMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/EntityTypeMixin.java index 828232c4a..fdd14c9d2 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/EntityTypeMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/EntityTypeMixin.java @@ -1,5 +1,7 @@ package com.jozufozu.flywheel.mixin; +import javax.annotation.Nullable; + import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -15,12 +17,13 @@ public class EntityTypeMixin implements EntityTypeExtension private EntityInstancingController flywheel$instancingController; @Override + @Nullable public EntityInstancingController flywheel$getInstancingController() { return flywheel$instancingController; } @Override - public void flywheel$setInstancingController(EntityInstancingController instancingController) { + public void flywheel$setInstancingController(@Nullable EntityInstancingController instancingController) { this.flywheel$instancingController = instancingController; } }