It's-a me

- Lots of plumbing
- Storages/InstanceManagers directly reference the Engine
- Construct Instances with InstanceContext record
  - Stores InstancerProvider as well as Vec3i renderOrigin
- AbstractInstance stores renderOrigin
- InstancerProvider#getOriginCoordinate -> RenderDispatcher#renderOrigin
- Update some styling/documentation
- Inline InstancingControllerHelper create functions
- Use explicit functional interface instead of BiFunction in Controllers
This commit is contained in:
Jozufozu 2023-04-04 21:29:36 -07:00
parent b8effd31a4
commit e6248f502e
28 changed files with 164 additions and 159 deletions

View file

@ -5,6 +5,7 @@ import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.task.TaskExecutor;
import net.minecraft.client.Camera;
import net.minecraft.core.Vec3i;
public interface RenderDispatcher {
@ -15,9 +16,12 @@ public interface RenderDispatcher {
/**
* Maintain the integer origin coordinate to be within a certain distance from the camera in all directions,
* preventing floating point precision issues at high coordinates.
*
* @return {@code true} if the origin coordinate was changed, {@code false} otherwise.
*/
boolean maintainOriginCoordinate(Camera camera);
Vec3i renderOrigin();
void delete();
}

View file

@ -22,10 +22,9 @@ import com.jozufozu.flywheel.api.instancer.Instancer;
public interface TickableInstance extends Instance {
/**
* Called every tick, and after initialization.
* <br>
* <em>DISPATCHED IN PARALLEL</em>, don't attempt to mutate anything outside of this instance.
* <br>
* Called every tick, and after initialization.<p>
* <em>DISPATCHED IN PARALLEL</em>, don't attempt to mutate anything outside of this instance
* without proper synchronization.<p>
* {@link Instancer}/{@link InstancedPart} creation/acquisition is safe here.
*/
void tick();

View file

@ -1,7 +1,6 @@
package com.jozufozu.flywheel.api.instance.controller;
import com.jozufozu.flywheel.api.instance.BlockEntityInstance;
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
import net.minecraft.world.level.block.entity.BlockEntity;
@ -12,11 +11,12 @@ import net.minecraft.world.level.block.entity.BlockEntity;
public interface BlockEntityInstancingController<T extends BlockEntity> {
/**
* Given a block entity and an instancer manager, constructs an instance for the block entity.
* @param instancerManager The instancer manager to use.
*
* @param ctx Context for creating an Instance.
* @param blockEntity The block entity to construct an instance for.
* @return The instance.
*/
BlockEntityInstance<? super T> createInstance(InstancerProvider instancerManager, T blockEntity);
BlockEntityInstance<? super T> createInstance(InstanceContext ctx, T blockEntity);
/**
* Checks if the given block entity should not be rendered normally.

View file

@ -1,7 +1,6 @@
package com.jozufozu.flywheel.api.instance.controller;
import com.jozufozu.flywheel.api.instance.EntityInstance;
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
import net.minecraft.world.entity.Entity;
@ -12,11 +11,12 @@ import net.minecraft.world.entity.Entity;
public interface EntityInstancingController<T extends Entity> {
/**
* Given an entity and an instancer manager, constructs an instance for the entity.
* @param instancerManager The instancer manager to use.
*
* @param ctx Context for creating an Instance.
* @param entity The entity to construct an instance for.
* @return The instance.
*/
EntityInstance<? super T> createInstance(InstancerProvider instancerManager, T entity);
EntityInstance<? super T> createInstance(InstanceContext ctx, T entity);
/**
* Checks if the given entity should not render normally.

View file

@ -0,0 +1,16 @@
package com.jozufozu.flywheel.api.instance.controller;
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
import net.minecraft.core.Vec3i;
/**
* A context object passed on Instance creation.
*
* @param instancerProvider The {@link InstancerProvider} that the instance can use to get instancers to render models.
* @param renderOrigin The origin of the renderer as a world position.
* All models render as if this position is (0, 0, 0).
*/
public record InstanceContext(InstancerProvider instancerProvider, Vec3i renderOrigin) {
}

View file

@ -3,8 +3,8 @@ package com.jozufozu.flywheel.api.instance.effect;
import java.util.Collection;
import com.jozufozu.flywheel.api.instance.Instance;
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
import com.jozufozu.flywheel.api.instance.controller.InstanceContext;
public interface Effect {
Collection<Instance> createInstances(InstancerProvider instancerManager);
Collection<Instance> createInstances(InstanceContext ctx);
}

View file

@ -26,7 +26,6 @@ public interface Instancer<D extends InstancedPart> {
/**
* Copy a data from another Instancer to this.
*
* This has the effect of swapping out one model for another.
* @param inOther the data associated with a different model.
*/

View file

@ -4,8 +4,6 @@ import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.model.Model;
import com.jozufozu.flywheel.api.struct.StructType;
import net.minecraft.core.Vec3i;
public interface InstancerProvider {
/**
* Get an instancer for the given struct type, model, and render stage. Calling this method twice with the same arguments will return the same instancer.
@ -13,7 +11,4 @@ public interface InstancerProvider {
* @return An instancer for the given struct type, model, and render stage.
*/
<D extends InstancedPart> Instancer<D> getInstancer(StructType<D> type, Model model, RenderStage stage);
// TODO: this method does not belong in this interface
Vec3i getOriginCoordinate();
}

View file

@ -90,7 +90,7 @@ public class BatchingEngine implements Engine {
}
@Override
public Vec3i getOriginCoordinate() {
public Vec3i renderOrigin() {
return BlockPos.ZERO;
}

View file

@ -110,7 +110,7 @@ public class IndirectEngine implements Engine {
}
@Override
public Vec3i getOriginCoordinate() {
public Vec3i renderOrigin() {
return originCoordinate;
}

View file

@ -155,7 +155,7 @@ public class InstancingEngine implements Engine {
}
@Override
public Vec3i getOriginCoordinate() {
public Vec3i renderOrigin() {
return originCoordinate;
}

View file

@ -128,6 +128,6 @@ public class InstancedRenderDispatcher {
}
public static Vec3i getOriginCoordinate(ClientLevel level) {
return instanceWorlds.get(level).engine.getOriginCoordinate();
return instanceWorlds.get(level).engine.renderOrigin();
}
}

View file

@ -4,9 +4,11 @@ import java.util.List;
import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.backend.Engine;
import com.jozufozu.flywheel.api.instance.BlockEntityInstance;
import com.jozufozu.flywheel.api.instance.Instance;
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
import com.jozufozu.flywheel.api.instance.controller.InstanceContext;
import com.jozufozu.flywheel.api.instance.controller.InstancingControllerRegistry;
import com.jozufozu.flywheel.backend.BackendUtil;
import com.jozufozu.flywheel.backend.instancing.storage.One2OneStorage;
import com.jozufozu.flywheel.backend.instancing.storage.Storage;
@ -22,8 +24,8 @@ import net.minecraft.world.level.block.entity.BlockEntity;
public class BlockEntityInstanceManager extends InstanceManager<BlockEntity> {
private final BlockEntityStorage storage;
public BlockEntityInstanceManager(InstancerProvider instancerManager) {
storage = new BlockEntityStorage(instancerManager);
public BlockEntityInstanceManager(Engine engine) {
storage = new BlockEntityStorage(engine);
}
@Override
@ -72,21 +74,24 @@ public class BlockEntityInstanceManager extends InstanceManager<BlockEntity> {
private static class BlockEntityStorage extends One2OneStorage<BlockEntity> {
private final Long2ObjectMap<BlockEntityInstance<?>> posLookup = new Long2ObjectOpenHashMap<>();
public BlockEntityStorage(InstancerProvider instancerManager) {
super(instancerManager);
public BlockEntityStorage(Engine engine) {
super(engine);
}
@Override
@Nullable
protected Instance createRaw(BlockEntity obj) {
BlockEntityInstance<?> instance = InstancingControllerHelper.createInstance(instancerManager, obj);
if (instance != null) {
BlockPos blockPos = obj.getBlockPos();
posLookup.put(blockPos.asLong(), instance);
var controller = InstancingControllerRegistry.getController(InstancingControllerHelper.getType(obj));
if (controller == null) {
return null;
}
return instance;
var out = controller.createInstance(new InstanceContext(engine, engine.renderOrigin()), obj);
BlockPos blockPos = obj.getBlockPos();
posLookup.put(blockPos.asLong(), out);
return out;
}
@Override

View file

@ -4,17 +4,18 @@ import java.util.ArrayList;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.jozufozu.flywheel.api.backend.Engine;
import com.jozufozu.flywheel.api.instance.Instance;
import com.jozufozu.flywheel.api.instance.controller.InstanceContext;
import com.jozufozu.flywheel.api.instance.effect.Effect;
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
import com.jozufozu.flywheel.backend.instancing.storage.AbstractStorage;
import com.jozufozu.flywheel.backend.instancing.storage.Storage;
public class EffectInstanceManager extends InstanceManager<Effect> {
private final EffectStorage<Effect> storage;
public EffectInstanceManager(InstancerProvider instancerManager) {
storage = new EffectStorage<>(instancerManager);
public EffectInstanceManager(Engine engine) {
storage = new EffectStorage<>(engine);
}
@Override
@ -30,8 +31,8 @@ public class EffectInstanceManager extends InstanceManager<Effect> {
private static class EffectStorage<T extends Effect> extends AbstractStorage<T> {
private final Multimap<T, Instance> instances;
public EffectStorage(InstancerProvider manager) {
super(manager);
public EffectStorage(Engine engine) {
super(engine);
this.instances = HashMultimap.create();
}
@ -100,7 +101,7 @@ public class EffectInstanceManager extends InstanceManager<Effect> {
}
private void create(T obj) {
var instances = obj.createInstances(instancerManager);
var instances = obj.createInstances(new InstanceContext(engine, engine.renderOrigin()));
this.instances.putAll(obj, instances);

View file

@ -2,8 +2,10 @@ package com.jozufozu.flywheel.backend.instancing.manager;
import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.backend.Engine;
import com.jozufozu.flywheel.api.instance.Instance;
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
import com.jozufozu.flywheel.api.instance.controller.InstanceContext;
import com.jozufozu.flywheel.api.instance.controller.InstancingControllerRegistry;
import com.jozufozu.flywheel.backend.BackendUtil;
import com.jozufozu.flywheel.backend.instancing.storage.One2OneStorage;
import com.jozufozu.flywheel.backend.instancing.storage.Storage;
@ -15,8 +17,8 @@ import net.minecraft.world.level.Level;
public class EntityInstanceManager extends InstanceManager<Entity> {
private final EntityStorage storage;
public EntityInstanceManager(InstancerProvider instancerManager) {
storage = new EntityStorage(instancerManager);
public EntityInstanceManager(Engine engine) {
storage = new EntityStorage(engine);
}
@Override
@ -40,14 +42,18 @@ public class EntityInstanceManager extends InstanceManager<Entity> {
}
private static class EntityStorage extends One2OneStorage<Entity> {
public EntityStorage(InstancerProvider instancerManager) {
super(instancerManager);
public EntityStorage(Engine engine) {
super(engine);
}
@Override
@Nullable
protected Instance createRaw(Entity obj) {
return InstancingControllerHelper.createInstance(instancerManager, obj);
var controller = InstancingControllerRegistry.getController(InstancingControllerHelper.getType(obj));
if (controller == null) {
return null;
}
return controller.createInstance(new InstanceContext(engine, engine.renderOrigin()), obj);
}
}
}

View file

@ -3,18 +3,18 @@ package com.jozufozu.flywheel.backend.instancing.storage;
import java.util.ArrayList;
import java.util.List;
import com.jozufozu.flywheel.api.backend.Engine;
import com.jozufozu.flywheel.api.instance.DynamicInstance;
import com.jozufozu.flywheel.api.instance.Instance;
import com.jozufozu.flywheel.api.instance.TickableInstance;
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
public abstract class AbstractStorage<T> implements Storage<T> {
protected final InstancerProvider instancerManager;
protected final Engine engine;
protected final List<TickableInstance> tickableInstances = new ArrayList<>();
protected final List<DynamicInstance> dynamicInstances = new ArrayList<>();
protected AbstractStorage(InstancerProvider instancerManager) {
this.instancerManager = instancerManager;
protected AbstractStorage(Engine engine) {
this.engine = engine;
}
@Override

View file

@ -5,14 +5,14 @@ import java.util.Map;
import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.backend.Engine;
import com.jozufozu.flywheel.api.instance.Instance;
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
public abstract class One2OneStorage<T> extends AbstractStorage<T> {
private final Map<T, Instance> instances;
public One2OneStorage(InstancerProvider instancerManager) {
super(instancerManager);
public One2OneStorage(Engine engine) {
super(engine);
this.instances = new HashMap<>();
}

View file

@ -8,8 +8,8 @@ import org.joml.FrustumIntersection;
import com.jozufozu.flywheel.api.instance.BlockEntityInstance;
import com.jozufozu.flywheel.api.instance.DynamicInstance;
import com.jozufozu.flywheel.api.instance.TickableInstance;
import com.jozufozu.flywheel.api.instance.controller.InstanceContext;
import com.jozufozu.flywheel.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
import com.jozufozu.flywheel.backend.instancing.manager.BlockEntityInstanceManager;
import com.jozufozu.flywheel.lib.box.ImmutableBox;
import com.jozufozu.flywheel.lib.box.MutableBox;
@ -42,12 +42,12 @@ public abstract class AbstractBlockEntityInstance<T extends BlockEntity> extends
protected final BlockPos instancePos;
protected final BlockState blockState;
public AbstractBlockEntityInstance(InstancerProvider instancerManager, T blockEntity) {
super(instancerManager, blockEntity.getLevel());
public AbstractBlockEntityInstance(InstanceContext ctx, T blockEntity) {
super(ctx, blockEntity.getLevel());
this.blockEntity = blockEntity;
this.pos = blockEntity.getBlockPos();
this.blockState = blockEntity.getBlockState();
this.instancePos = pos.subtract(instancerManager.getOriginCoordinate());
this.instancePos = pos.subtract(renderOrigin);
}
@Override
@ -82,7 +82,7 @@ public abstract class AbstractBlockEntityInstance<T extends BlockEntity> extends
* represents should be rendered at to appear in the correct location.
*/
public BlockPos getInstancePosition() {
return pos.subtract(instancerManager.getOriginCoordinate());
return pos.subtract(renderOrigin);
}
@Override

View file

@ -5,13 +5,12 @@ import org.joml.FrustumIntersection;
import com.jozufozu.flywheel.api.instance.DynamicInstance;
import com.jozufozu.flywheel.api.instance.EntityInstance;
import com.jozufozu.flywheel.api.instance.TickableInstance;
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
import com.jozufozu.flywheel.api.instance.controller.InstanceContext;
import com.jozufozu.flywheel.backend.instancing.manager.BlockEntityInstanceManager;
import com.jozufozu.flywheel.lib.box.MutableBox;
import com.jozufozu.flywheel.lib.light.TickingLightListener;
import com.mojang.math.Vector3f;
import net.minecraft.core.Vec3i;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.block.entity.BlockEntity;
@ -38,8 +37,8 @@ public abstract class AbstractEntityInstance<E extends Entity> extends AbstractI
protected final E entity;
protected final MutableBox bounds;
public AbstractEntityInstance(InstancerProvider instancerManager, E entity) {
super(instancerManager, entity.level);
public AbstractEntityInstance(InstanceContext ctx, E entity) {
super(ctx, entity.level);
this.entity = entity;
bounds = MutableBox.from(entity.getBoundingBox());
}
@ -53,7 +52,9 @@ public abstract class AbstractEntityInstance<E extends Entity> extends AbstractI
public boolean tickLightListener() {
AABB boundsNow = entity.getBoundingBox();
if (bounds.sameAs(boundsNow)) return false;
if (bounds.sameAs(boundsNow)) {
return false;
}
bounds.assign(boundsNow);
@ -71,8 +72,7 @@ public abstract class AbstractEntityInstance<E extends Entity> extends AbstractI
*/
public Vector3f getInstancePosition() {
Vec3 pos = entity.position();
Vec3i origin = instancerManager.getOriginCoordinate();
return new Vector3f((float) (pos.x - origin.getX()), (float) (pos.y - origin.getY()), (float) (pos.z - origin.getZ()));
return new Vector3f((float) (pos.x - renderOrigin.getX()), (float) (pos.y - renderOrigin.getY()), (float) (pos.z - renderOrigin.getZ()));
}
/**
@ -84,10 +84,7 @@ public abstract class AbstractEntityInstance<E extends Entity> extends AbstractI
*/
public Vector3f getInstancePosition(float partialTicks) {
Vec3 pos = entity.position();
Vec3i origin = instancerManager.getOriginCoordinate();
return new Vector3f(
(float) (Mth.lerp(partialTicks, entity.xOld, pos.x) - origin.getX()),
(float) (Mth.lerp(partialTicks, entity.yOld, pos.y) - origin.getY()), (float) (Mth.lerp(partialTicks, entity.zOld, pos.z) - origin.getZ()));
return new Vector3f((float) (Mth.lerp(partialTicks, entity.xOld, pos.x) - renderOrigin.getX()), (float) (Mth.lerp(partialTicks, entity.yOld, pos.y) - renderOrigin.getY()), (float) (Mth.lerp(partialTicks, entity.zOld, pos.z) - renderOrigin.getZ()));
}
@Override

View file

@ -4,6 +4,7 @@ import java.util.Arrays;
import java.util.stream.Stream;
import com.jozufozu.flywheel.api.instance.Instance;
import com.jozufozu.flywheel.api.instance.controller.InstanceContext;
import com.jozufozu.flywheel.api.instancer.FlatLit;
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
import com.jozufozu.flywheel.lib.light.LightListener;
@ -11,23 +12,28 @@ import com.jozufozu.flywheel.lib.light.LightUpdater;
import net.minecraft.core.BlockPos;
import net.minecraft.core.SectionPos;
import net.minecraft.core.Vec3i;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LightLayer;
public abstract class AbstractInstance implements Instance, LightListener {
protected final InstancerProvider instancerManager;
public final Level level;
public final Vec3i renderOrigin;
protected final InstancerProvider instancerManager;
protected boolean deleted = false;
public AbstractInstance(InstancerProvider instancerManager, Level level) {
this.instancerManager = instancerManager;
public AbstractInstance(InstanceContext ctx, Level level) {
this.instancerManager = ctx.instancerProvider();
this.renderOrigin = ctx.renderOrigin();
this.level = level;
}
@Override
public void init() {
updateLight();
LightUpdater.get(level).addListener(this);
LightUpdater.get(level)
.addListener(this);
}
@Override

View file

@ -1,13 +1,8 @@
package com.jozufozu.flywheel.lib.instance;
import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.instance.BlockEntityInstance;
import com.jozufozu.flywheel.api.instance.EntityInstance;
import com.jozufozu.flywheel.api.instance.controller.BlockEntityInstancingController;
import com.jozufozu.flywheel.api.instance.controller.EntityInstancingController;
import com.jozufozu.flywheel.api.instance.controller.InstancingControllerRegistry;
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
@ -35,38 +30,6 @@ public final class InstancingControllerHelper {
return InstancingControllerRegistry.getController(type) != null;
}
/**
* Creates an instance for the given block entity, if possible.
* @param instancerManager The instancer manager to use.
* @param blockEntity The block entity to create an instance of.
* @param <T> 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 <T extends BlockEntity> BlockEntityInstance<? super T> createInstance(InstancerProvider instancerManager, T blockEntity) {
BlockEntityInstancingController<? super T> controller = InstancingControllerRegistry.getController(getType(blockEntity));
if (controller == null) {
return null;
}
return controller.createInstance(instancerManager, blockEntity);
}
/**
* Creates an instance for the given entity, if possible.
* @param instancerManager The instancer manager to use.
* @param entity The entity to create an instance of.
* @param <T> The type of the entity.
* @return An instance of the entity, or {@code null} if the entity cannot be instanced.
*/
@Nullable
public static <T extends Entity> EntityInstance<? super T> createInstance(InstancerProvider instancerManager, T entity) {
EntityInstancingController<? super T> controller = InstancingControllerRegistry.getController(getType(entity));
if (controller == null) {
return null;
}
return controller.createInstance(instancerManager, entity);
}
/**
* Checks if the given block entity is instanced and should not be rendered normally.
* @param blockEntity The block entity to check.

View file

@ -1,29 +1,30 @@
package com.jozufozu.flywheel.lib.instance;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Predicate;
import org.jetbrains.annotations.NotNull;
import com.jozufozu.flywheel.api.instance.BlockEntityInstance;
import com.jozufozu.flywheel.api.instance.controller.BlockEntityInstancingController;
import com.jozufozu.flywheel.api.instance.controller.InstanceContext;
import com.jozufozu.flywheel.api.instance.controller.InstancingControllerRegistry;
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
public class SimpleBlockEntityInstancingController<T extends BlockEntity> implements BlockEntityInstancingController<T> {
protected BiFunction<InstancerProvider, T, BlockEntityInstance<? super T>> instanceFactory;
protected Factory<T> instanceFactory;
protected Predicate<T> skipRender;
public SimpleBlockEntityInstancingController(BiFunction<InstancerProvider, T, BlockEntityInstance<? super T>> instanceFactory, Predicate<T> skipRender) {
public SimpleBlockEntityInstancingController(Factory<T> instanceFactory, Predicate<T> skipRender) {
this.instanceFactory = instanceFactory;
this.skipRender = skipRender;
}
@Override
public BlockEntityInstance<? super T> createInstance(InstancerProvider instancerManager, T blockEntity) {
return instanceFactory.apply(instancerManager, blockEntity);
public BlockEntityInstance<? super T> createInstance(InstanceContext ctx, T blockEntity) {
return instanceFactory.create(ctx, blockEntity);
}
@Override
@ -33,21 +34,28 @@ public class SimpleBlockEntityInstancingController<T extends BlockEntity> implem
/**
* Get an object to configure the instancing controller for the given block entity type.
*
* @param type The block entity type to configure.
* @param <T> The type of the block entity.
* @param <T> The type of the block entity.
* @return The configuration object.
*/
public static <T extends BlockEntity> BlockEntityConfig<T> configure(BlockEntityType<T> type) {
return new BlockEntityConfig<>(type);
}
@FunctionalInterface
public interface Factory<T extends BlockEntity> {
@NotNull BlockEntityInstance<? super T> create(InstanceContext ctx, T blockEntity);
}
/**
* An object to configure the instancing controller for a block entity.
*
* @param <T> The type of the block entity.
*/
public static class BlockEntityConfig<T extends BlockEntity> {
protected BlockEntityType<T> type;
protected BiFunction<InstancerProvider, T, BlockEntityInstance<? super T>> instanceFactory;
protected Factory<T> instanceFactory;
protected Predicate<T> skipRender;
public BlockEntityConfig(BlockEntityType<T> type) {
@ -56,10 +64,11 @@ public class SimpleBlockEntityInstancingController<T extends BlockEntity> implem
/**
* Sets the instance factory for the block entity.
*
* @param instanceFactory The instance factory.
* @return {@code this}
*/
public BlockEntityConfig<T> factory(BiFunction<InstancerProvider, T, BlockEntityInstance<? super T>> instanceFactory) {
public BlockEntityConfig<T> factory(Factory<T> instanceFactory) {
this.instanceFactory = instanceFactory;
return this;
}

View file

@ -1,29 +1,30 @@
package com.jozufozu.flywheel.lib.instance;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Predicate;
import org.jetbrains.annotations.NotNull;
import com.jozufozu.flywheel.api.instance.EntityInstance;
import com.jozufozu.flywheel.api.instance.controller.EntityInstancingController;
import com.jozufozu.flywheel.api.instance.controller.InstanceContext;
import com.jozufozu.flywheel.api.instance.controller.InstancingControllerRegistry;
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
public class SimpleEntityInstancingController<T extends Entity> implements EntityInstancingController<T> {
protected BiFunction<InstancerProvider, T, EntityInstance<? super T>> instanceFactory;
protected Factory<T> instanceFactory;
protected Predicate<T> skipRender;
public SimpleEntityInstancingController(BiFunction<InstancerProvider, T, EntityInstance<? super T>> instanceFactory, Predicate<T> skipRender) {
public SimpleEntityInstancingController(Factory<T> instanceFactory, Predicate<T> skipRender) {
this.instanceFactory = instanceFactory;
this.skipRender = skipRender;
}
@Override
public EntityInstance<? super T> createInstance(InstancerProvider instancerManager, T entity) {
return instanceFactory.apply(instancerManager, entity);
public EntityInstance<? super T> createInstance(InstanceContext ctx, T entity) {
return instanceFactory.create(ctx, entity);
}
@Override
@ -33,21 +34,28 @@ public class SimpleEntityInstancingController<T extends Entity> implements Entit
/**
* Get an object to configure the instancing controller for the given entity type.
*
* @param type The entity type to configure.
* @param <T> The type of the entity.
* @param <T> The type of the entity.
* @return The configuration object.
*/
public static <T extends Entity> EntityConfig<T> configure(EntityType<T> type) {
return new EntityConfig<>(type);
}
@FunctionalInterface
public interface Factory<T extends Entity> {
@NotNull EntityInstance<? super T> create(InstanceContext ctx, T entity);
}
/**
* An object to configure the instancing controller for an entity.
*
* @param <T> The type of the entity.
*/
public static class EntityConfig<T extends Entity> {
protected EntityType<T> type;
protected BiFunction<InstancerProvider, T, EntityInstance<? super T>> instanceFactory;
protected Factory<T> instanceFactory;
protected Predicate<T> skipRender;
public EntityConfig(EntityType<T> type) {
@ -56,10 +64,11 @@ public class SimpleEntityInstancingController<T extends Entity> implements Entit
/**
* Sets the instance factory for the entity.
*
* @param instanceFactory The instance factory.
* @return {@code this}
*/
public EntityConfig<T> factory(BiFunction<InstancerProvider, T, EntityInstance<? super T>> instanceFactory) {
public EntityConfig<T> factory(Factory<T> instanceFactory) {
this.instanceFactory = instanceFactory;
return this;
}

View file

@ -7,8 +7,8 @@ import org.jetbrains.annotations.NotNull;
import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.instance.DynamicInstance;
import com.jozufozu.flywheel.api.instance.controller.InstanceContext;
import com.jozufozu.flywheel.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
import com.jozufozu.flywheel.lib.instance.AbstractBlockEntityInstance;
import com.jozufozu.flywheel.lib.material.Materials;
import com.jozufozu.flywheel.lib.model.SimpleLazyModel;
@ -31,11 +31,10 @@ public class BellInstance extends AbstractBlockEntityInstance<BellBlockEntity> i
private float lastRingTime = Float.NaN;
public BellInstance(InstancerProvider instancerManager, BellBlockEntity blockEntity) {
super(instancerManager, blockEntity);
public BellInstance(InstanceContext ctx, BellBlockEntity blockEntity) {
super(ctx, blockEntity);
bell = createBellInstance()
.setPivot(0.5f, 0.75f, 0.5f)
bell = createBellInstance().setPivot(0.5f, 0.75f, 0.5f)
.setPosition(getInstancePosition());
}

View file

@ -9,8 +9,8 @@ import org.jetbrains.annotations.NotNull;
import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.instance.DynamicInstance;
import com.jozufozu.flywheel.api.instance.controller.InstanceContext;
import com.jozufozu.flywheel.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
import com.jozufozu.flywheel.lib.instance.AbstractBlockEntityInstance;
import com.jozufozu.flywheel.lib.material.Materials;
import com.jozufozu.flywheel.lib.model.SimpleLazyModel;
@ -51,16 +51,16 @@ public class ChestInstance<T extends BlockEntity & LidBlockEntity> extends Abstr
private float lastProgress = Float.NaN;
public ChestInstance(InstancerProvider instancerManager, T blockEntity) {
super(instancerManager, blockEntity);
public ChestInstance(InstanceContext ctx, T blockEntity) {
super(ctx, blockEntity);
Block block = blockState.getBlock();
chestType = blockState.hasProperty(ChestBlock.TYPE) ? blockState.getValue(ChestBlock.TYPE) : ChestType.SINGLE;
sprite = Sheets.chooseMaterial(blockEntity, chestType, isChristmas()).sprite();
sprite = Sheets.chooseMaterial(blockEntity, chestType, isChristmas())
.sprite();
body = baseInstance()
.setPosition(getInstancePosition());
body = baseInstance().setPosition(getInstancePosition());
lid = lidInstance();
if (block instanceof AbstractChestBlock<?> chestBlock) {

View file

@ -5,7 +5,7 @@ import org.jetbrains.annotations.NotNull;
import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.instance.DynamicInstance;
import com.jozufozu.flywheel.api.instance.TickableInstance;
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
import com.jozufozu.flywheel.api.instance.controller.InstanceContext;
import com.jozufozu.flywheel.api.model.Mesh;
import com.jozufozu.flywheel.lib.instance.AbstractEntityInstance;
import com.jozufozu.flywheel.lib.material.Materials;
@ -19,7 +19,6 @@ import com.jozufozu.flywheel.util.AnimationTickHolder;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Vector3f;
import net.minecraft.core.Vec3i;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.vehicle.AbstractMinecart;
import net.minecraft.world.level.block.RenderShape;
@ -37,8 +36,8 @@ public class MinecartInstance<T extends AbstractMinecart> extends AbstractEntity
private BlockState blockState;
private boolean active;
public MinecartInstance(InstancerProvider instancerManager, T entity) {
super(instancerManager, entity);
public MinecartInstance(InstanceContext ctx, T entity) {
super(ctx, entity);
body = getBody();
blockState = entity.getDisplayBlockState();
@ -75,11 +74,7 @@ public class MinecartInstance<T extends AbstractMinecart> extends AbstractEntity
stack.setIdentity();
float pt = AnimationTickHolder.getPartialTicks();
Vec3i originCoordinate = instancerManager.getOriginCoordinate();
tstack.translate(
Mth.lerp(pt, entity.xOld, entity.getX()) - originCoordinate.getX(),
Mth.lerp(pt, entity.yOld, entity.getY()) - originCoordinate.getY(),
Mth.lerp(pt, entity.zOld, entity.getZ()) - originCoordinate.getZ());
tstack.translate(Mth.lerp(pt, entity.xOld, entity.getX()) - renderOrigin.getX(), Mth.lerp(pt, entity.yOld, entity.getY()) - renderOrigin.getY(), Mth.lerp(pt, entity.zOld, entity.getZ()) - renderOrigin.getZ());
float yaw = Mth.lerp(pt, entity.yRotO, entity.getYRot());

View file

@ -6,8 +6,8 @@ import java.util.function.Function;
import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.instance.DynamicInstance;
import com.jozufozu.flywheel.api.instance.controller.InstanceContext;
import com.jozufozu.flywheel.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
import com.jozufozu.flywheel.lib.instance.AbstractBlockEntityInstance;
import com.jozufozu.flywheel.lib.material.Materials;
import com.jozufozu.flywheel.lib.model.SimpleLazyModel;
@ -41,14 +41,15 @@ public class ShulkerBoxInstance extends AbstractBlockEntityInstance<ShulkerBoxBl
private float lastProgress = Float.NaN;
public ShulkerBoxInstance(InstancerProvider instancerManager, ShulkerBoxBlockEntity blockEntity) {
super(instancerManager, blockEntity);
public ShulkerBoxInstance(InstanceContext ctx, ShulkerBoxBlockEntity blockEntity) {
super(ctx, blockEntity);
DyeColor color = blockEntity.getColor();
if (color == null) {
texture = Sheets.DEFAULT_SHULKER_TEXTURE_LOCATION.sprite();
} else {
texture = Sheets.SHULKER_TEXTURE_LOCATION.get(color.getId()).sprite();
texture = Sheets.SHULKER_TEXTURE_LOCATION.get(color.getId())
.sprite();
}
Quaternion rotation = getDirection().getRotation();

View file

@ -11,9 +11,10 @@ import org.joml.Vector3f;
import com.jozufozu.flywheel.api.event.ReloadRenderersEvent;
import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.instance.DynamicInstance;
import com.jozufozu.flywheel.api.instance.Instance;
import com.jozufozu.flywheel.api.instance.TickableInstance;
import com.jozufozu.flywheel.api.instance.controller.InstanceContext;
import com.jozufozu.flywheel.api.instance.effect.Effect;
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.lib.box.ImmutableBox;
import com.jozufozu.flywheel.lib.box.MutableBox;
@ -59,7 +60,7 @@ public class ExampleEffect implements Effect {
private final BlockPos blockPos;
private final ImmutableBox volume;
private final List<Instance> effects;
private final List<BoidInstance> effects;
private final List<Boid> boids;
@ -109,7 +110,7 @@ public class ExampleEffect implements Effect {
}
@Override
public Collection<com.jozufozu.flywheel.api.instance.Instance> createInstances(InstancerProvider instancerManager) {
public Collection<Instance> createInstances(InstanceContext ctx) {
effects.clear();
boids.clear();
for (int i = 0; i < INSTANCE_COUNT; i++) {
@ -119,7 +120,7 @@ public class ExampleEffect implements Effect {
Boid boid = new Boid(x, y, z);
boids.add(boid);
effects.add(new Instance(instancerManager, level, boid));
effects.add(new BoidInstance(ctx, level, boid));
}
return Collections.unmodifiableList(effects);
}
@ -237,13 +238,13 @@ public class ExampleEffect implements Effect {
}
}
public class Instance extends AbstractInstance implements DynamicInstance, TickableInstance {
public class BoidInstance extends AbstractInstance implements DynamicInstance, TickableInstance {
private final Boid self;
TransformedPart instance;
public Instance(InstancerProvider instancerManager, Level level, Boid self) {
super(instancerManager, level);
public BoidInstance(InstanceContext ctx, Level level, Boid self) {
super(ctx, level);
this.self = self;
}
@ -280,7 +281,7 @@ public class ExampleEffect implements Effect {
var z = Mth.lerp(partialTicks, self.lastPosition.z, self.position.z);
instance.loadIdentity()
.translateBack(instancerManager.getOriginCoordinate())
.translateBack(renderOrigin)
.translate(x, y, z)
.scale(RENDER_SCALE);
}