Stripping instances

- Remove #removeNow and #getWorldPosition from Instance
- Add #distanceSquared for use in update limiting
- Refactor DistanceUpdateLimiter to directly accept distance squared
- Remove proper name from backend
- Misc. cleanup
  - ifs without braces
  - some method names
This commit is contained in:
Jozufozu 2023-04-04 17:17:06 -07:00
parent 632240abf0
commit 7326bdd3c2
21 changed files with 103 additions and 120 deletions

View file

@ -115,7 +115,7 @@ public class Flywheel {
VanillaInstances.init(); VanillaInstances.init();
CrashReportCallables.registerCrashCallable("Flywheel Backend", BackendManager::getBackendDescriptor); CrashReportCallables.registerCrashCallable("Flywheel Backend", BackendManager::getBackendNameForCrashReport);
// https://github.com/Jozufozu/Flywheel/issues/69 // https://github.com/Jozufozu/Flywheel/issues/69
// Weird issue with accessor loading. // Weird issue with accessor loading.

View file

@ -11,15 +11,24 @@ import net.minecraft.network.chat.Component;
public interface Backend { public interface Backend {
static IdRegistry<Backend> REGISTRY = IdRegistryImpl.create(); static IdRegistry<Backend> REGISTRY = IdRegistryImpl.create();
// TODO: remove and use ID instead? Currently this is only used for the crash log string. /**
String getProperName(); * Get a message to display to the user when the engine is enabled.
*/
Component getEngineMessage(); Component engineMessage();
/**
* Create a new engine instance.
*/
Engine createEngine(); Engine createEngine();
/**
* Get a fallback backend in case this backend is not supported.
*/
Backend findFallback(); Backend findFallback();
/**
* Check if this backend is supported.
*/
boolean isSupported(); boolean isSupported();
@Nullable Pipeline pipelineShader(); @Nullable Pipeline pipelineShader();

View file

@ -16,8 +16,8 @@ public final class BackendManager {
/** /**
* Get a string describing the current backend. * Get a string describing the current backend.
*/ */
public static String getBackendDescriptor() { public static String getBackendNameForCrashReport() {
return BackendManagerImpl.getBackendDescriptor(); return BackendManagerImpl.getBackendNameForCrashReport();
} }
public static boolean isOn() { public static boolean isOn() {

View file

@ -2,13 +2,10 @@ package com.jozufozu.flywheel.api.instance;
import org.joml.FrustumIntersection; import org.joml.FrustumIntersection;
import net.minecraft.core.BlockPos;
/** /**
* A general interface providing information about any type of thing that could use Flywheel's instanced rendering. * A general interface providing information about any type of thing that could use Flywheel's instanced rendering.
*/ */
public interface Instance { public interface Instance {
BlockPos getWorldPosition();
/** /**
* Initialize parts here. * Initialize parts here.
@ -39,17 +36,25 @@ public interface Instance {
/** /**
* Check this instance against a frustum.<p> * Check this instance against a frustum.<p>
* An implementor may choose to return a constant to skip the frustum check. * An implementor may choose to return a constant to skip the frustum check.
*
* @param frustum A frustum intersection tester for the current frame. * @param frustum A frustum intersection tester for the current frame.
* @return {@code true} if this instance should be considered for updates. * @return {@code true} if this instance should be considered for updates.
*/ */
boolean checkFrustum(FrustumIntersection frustum); boolean checkFrustum(FrustumIntersection frustum);
/**
* Calculate the distance squared between this instance and the given <em>world</em> position.
*
* @param x The x coordinate.
* @param y The y coordinate.
* @param z The z coordinate.
* @return The distance squared between this instance and the given position.
*/
double distanceSquared(double x, double y, double z);
/** /**
* Free any acquired resources. * Free any acquired resources.
*/ */
void delete(); void delete();
// TODO
@Deprecated
void removeNow();
} }

View file

@ -65,7 +65,7 @@ public class EffectInstanceManager extends InstanceManager<Effect> {
this.tickableInstances.removeAll(instances); this.tickableInstances.removeAll(instances);
this.dynamicInstances.removeAll(instances); this.dynamicInstances.removeAll(instances);
for (Instance instance : instances) { for (Instance instance : instances) {
instance.removeNow(); instance.delete();
} }
} }

View file

@ -21,8 +21,6 @@ import com.jozufozu.flywheel.backend.instancing.ratelimit.NonLimiter;
import com.jozufozu.flywheel.backend.instancing.storage.Storage; import com.jozufozu.flywheel.backend.instancing.storage.Storage;
import com.jozufozu.flywheel.config.FlwConfig; import com.jozufozu.flywheel.config.FlwConfig;
import net.minecraft.core.BlockPos;
public abstract class InstanceManager<T> { public abstract class InstanceManager<T> {
private final Set<T> queuedAdditions = new HashSet<>(64); private final Set<T> queuedAdditions = new HashSet<>(64);
private final Set<T> queuedUpdates = new HashSet<>(64); private final Set<T> queuedUpdates = new HashSet<>(64);
@ -144,7 +142,7 @@ public abstract class InstanceManager<T> {
public void delete() { public void delete() {
for (Instance instance : getStorage().getAllInstances()) { for (Instance instance : getStorage().getAllInstances()) {
instance.removeNow(); instance.delete();
} }
} }
@ -191,28 +189,19 @@ public abstract class InstanceManager<T> {
tickLimiter.tick(); tickLimiter.tick();
processQueuedUpdates(); processQueuedUpdates();
// integer camera pos as a micro-optimization
int cX = (int) cameraX;
int cY = (int) cameraY;
int cZ = (int) cameraZ;
var instances = getStorage().getInstancesForTicking(); var instances = getStorage().getInstancesForTicking();
distributeWork(executor, instances, instance -> tickInstance(instance, cX, cY, cZ)); distributeWork(executor, instances, instance -> tickInstance(instance, cameraX, cameraY, cameraZ));
} }
protected void tickInstance(TickableInstance instance, int cX, int cY, int cZ) { protected void tickInstance(TickableInstance instance, double cX, double cY, double cZ) {
if (!instance.decreaseTickRateWithDistance()) { if (!instance.decreaseTickRateWithDistance()) {
instance.tick(); instance.tick();
return; return;
} }
BlockPos pos = instance.getWorldPosition(); var dsq = instance.distanceSquared(cX, cY, cZ);
int dX = pos.getX() - cX; if (!tickLimiter.shouldUpdate(dsq)) {
int dY = pos.getY() - cY;
int dZ = pos.getZ() - cZ;
if (!tickLimiter.shouldUpdate(dX, dY, dZ)) {
return; return;
} }
@ -223,11 +212,11 @@ public abstract class InstanceManager<T> {
frameLimiter.tick(); frameLimiter.tick();
processQueuedAdditions(); processQueuedAdditions();
// integer camera pos var cameraPos = context.camera()
BlockPos cameraIntPos = context.camera().getBlockPosition(); .getPosition();
int cX = cameraIntPos.getX(); double cX = cameraPos.x;
int cY = cameraIntPos.getY(); double cY = cameraPos.y;
int cZ = cameraIntPos.getZ(); double cZ = cameraPos.z;
FrustumIntersection culler = context.culler(); FrustumIntersection culler = context.culler();
var instances = getStorage().getInstancesForUpdate(); var instances = getStorage().getInstancesForUpdate();
@ -251,18 +240,13 @@ public abstract class InstanceManager<T> {
} }
} }
protected void updateInstance(DynamicInstance instance, FrustumIntersection frustum, int cX, int cY, int cZ) { protected void updateInstance(DynamicInstance instance, FrustumIntersection frustum, double cX, double cY, double cZ) {
if (!instance.decreaseFramerateWithDistance()) { if (!instance.decreaseFramerateWithDistance()) {
instance.beginFrame(); instance.beginFrame();
return; return;
} }
BlockPos worldPos = instance.getWorldPosition(); if (!frameLimiter.shouldUpdate(instance.distanceSquared(cX, cY, cZ))) {
int dX = worldPos.getX() - cX;
int dY = worldPos.getY() - cY;
int dZ = worldPos.getZ() - cZ;
if (!frameLimiter.shouldUpdate(dX, dY, dZ)) {
return; return;
} }

View file

@ -14,12 +14,12 @@ public class BandedPrimeLimiter implements DistanceUpdateLimiter {
} }
@Override @Override
public boolean shouldUpdate(int dX, int dY, int dZ) { public boolean shouldUpdate(double distanceSquared) {
return (tickCount % getUpdateDivisor(dX, dY, dZ)) == 0; return (tickCount % getUpdateDivisor(distanceSquared)) == 0;
} }
protected int getUpdateDivisor(int dX, int dY, int dZ) { protected int getUpdateDivisor(double distanceSquared) {
int dSq = dX * dX + dY * dY + dZ * dZ; int dSq = Mth.ceil(distanceSquared);
int i = (dSq / 2048); int i = (dSq / 2048);

View file

@ -11,10 +11,9 @@ public interface DistanceUpdateLimiter {
/** /**
* Check to see if an object at the given position relative to the camera should be updated. * Check to see if an object at the given position relative to the camera should be updated.
* @param dX The X distance from the camera. *
* @param dY The Y distance from the camera. * @param distanceSquared
* @param dZ The Z distance from the camera.
* @return {@code true} if the object should be updated, {@code false} otherwise. * @return {@code true} if the object should be updated, {@code false} otherwise.
*/ */
boolean shouldUpdate(int dX, int dY, int dZ); boolean shouldUpdate(double distanceSquared);
} }

View file

@ -6,7 +6,7 @@ public class NonLimiter implements DistanceUpdateLimiter {
} }
@Override @Override
public boolean shouldUpdate(int dX, int dY, int dZ) { public boolean shouldUpdate(double distanceSquared) {
return true; return true;
} }
} }

View file

@ -46,7 +46,6 @@ public abstract class One2OneStorage<T> extends AbstractStorage<T> {
instance.delete(); instance.delete();
dynamicInstances.remove(instance); dynamicInstances.remove(instance);
tickableInstances.remove(instance); tickableInstances.remove(instance);
instance.removeNow();
} }
@Override @Override

View file

@ -53,7 +53,7 @@ public class FlwCommands {
return 0; return 0;
} }
Component message = backend.getEngineMessage(); Component message = backend.engineMessage();
player.displayClientMessage(message, false); player.displayClientMessage(message, false);
} }
return Command.SINGLE_SUCCESS; return Command.SINGLE_SUCCESS;
@ -65,7 +65,7 @@ public class FlwCommands {
Backend backend = context.getArgument("id", Backend.class); Backend backend = context.getArgument("id", Backend.class);
value.set(Backend.REGISTRY.getIdOrThrow(backend).toString()); value.set(Backend.REGISTRY.getIdOrThrow(backend).toString());
Component message = backend.getEngineMessage(); Component message = backend.engineMessage();
player.displayClientMessage(message, false); player.displayClientMessage(message, false);
BackendUtil.reloadWorldRenderers(); BackendUtil.reloadWorldRenderers();

View file

@ -18,8 +18,15 @@ public final class BackendManagerImpl {
return backend; return backend;
} }
public static String getBackendDescriptor() { public static String getBackendNameForCrashReport() {
return backend == null ? "Uninitialized" : backend.getProperName(); if (backend == null) {
return "Uninitialized";
}
var backendId = Backend.REGISTRY.getId(backend);
if (backendId == null) {
return "Unregistered";
}
return backendId.toString();
} }
public static boolean isOn() { public static boolean isOn() {

View file

@ -15,7 +15,6 @@ import net.minecraft.network.chat.TextComponent;
public class Backends { public class Backends {
public static final Backend OFF = SimpleBackend.builder() public static final Backend OFF = SimpleBackend.builder()
.properName("Off")
.engineMessage(new TextComponent("Disabled Flywheel").withStyle(ChatFormatting.RED)) .engineMessage(new TextComponent("Disabled Flywheel").withStyle(ChatFormatting.RED))
.engineSupplier(() -> { .engineSupplier(() -> {
throw new IllegalStateException("Cannot create engine when backend is off."); throw new IllegalStateException("Cannot create engine when backend is off.");
@ -28,7 +27,6 @@ public class Backends {
* Use a thread pool to buffer instances in parallel on the CPU. * Use a thread pool to buffer instances in parallel on the CPU.
*/ */
public static final Backend BATCHING = SimpleBackend.builder() public static final Backend BATCHING = SimpleBackend.builder()
.properName("Parallel Batching")
.engineMessage(new TextComponent("Using Batching Engine").withStyle(ChatFormatting.GREEN)) .engineMessage(new TextComponent("Using Batching Engine").withStyle(ChatFormatting.GREEN))
.engineSupplier(BatchingEngine::new) .engineSupplier(BatchingEngine::new)
.fallback(() -> Backends.OFF) .fallback(() -> Backends.OFF)
@ -39,7 +37,6 @@ public class Backends {
* Use GPU instancing to render everything. * Use GPU instancing to render everything.
*/ */
public static final Backend INSTANCING = SimpleBackend.builder() public static final Backend INSTANCING = SimpleBackend.builder()
.properName("GL33 Instanced Arrays")
.engineMessage(new TextComponent("Using Instancing Engine").withStyle(ChatFormatting.GREEN)) .engineMessage(new TextComponent("Using Instancing Engine").withStyle(ChatFormatting.GREEN))
.engineSupplier(() -> new InstancingEngine(Contexts.WORLD, 100 * 100)) .engineSupplier(() -> new InstancingEngine(Contexts.WORLD, 100 * 100))
.fallback(() -> Backends.BATCHING) .fallback(() -> Backends.BATCHING)
@ -52,7 +49,6 @@ public class Backends {
* Use Compute shaders to cull instances. * Use Compute shaders to cull instances.
*/ */
public static final Backend INDIRECT = SimpleBackend.builder() public static final Backend INDIRECT = SimpleBackend.builder()
.properName("GL46 Compute Culling")
.engineMessage(new TextComponent("Using Indirect Engine").withStyle(ChatFormatting.GREEN)) .engineMessage(new TextComponent("Using Indirect Engine").withStyle(ChatFormatting.GREEN))
.engineSupplier(() -> new IndirectEngine(Contexts.WORLD, 100 * 100)) .engineSupplier(() -> new IndirectEngine(Contexts.WORLD, 100 * 100))
.fallback(() -> Backends.INSTANCING) .fallback(() -> Backends.INSTANCING)

View file

@ -13,15 +13,13 @@ import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
public class SimpleBackend implements Backend { public class SimpleBackend implements Backend {
private final String properName;
private final Component engineMessage; private final Component engineMessage;
private final Supplier<Engine> engineSupplier; private final Supplier<Engine> engineSupplier;
private final Supplier<Backend> fallback; private final Supplier<Backend> fallback;
private final BooleanSupplier isSupported; private final BooleanSupplier isSupported;
private final Pipeline pipelineShader; private final Pipeline pipelineShader;
public SimpleBackend(String properName, Component engineMessage, Supplier<Engine> engineSupplier, Supplier<Backend> fallback, BooleanSupplier isSupported, @Nullable Pipeline pipelineShader) { public SimpleBackend(Component engineMessage, Supplier<Engine> engineSupplier, Supplier<Backend> fallback, BooleanSupplier isSupported, @Nullable Pipeline pipelineShader) {
this.properName = properName;
this.engineMessage = engineMessage; this.engineMessage = engineMessage;
this.engineSupplier = engineSupplier; this.engineSupplier = engineSupplier;
this.fallback = fallback; this.fallback = fallback;
@ -34,12 +32,7 @@ public class SimpleBackend implements Backend {
} }
@Override @Override
public String getProperName() { public Component engineMessage() {
return properName;
}
@Override
public Component getEngineMessage() {
return engineMessage; return engineMessage;
} }
@ -69,18 +62,12 @@ public class SimpleBackend implements Backend {
} }
public static class Builder { public static class Builder {
private String properName;
private Component engineMessage; private Component engineMessage;
private Supplier<Engine> engineSupplier; private Supplier<Engine> engineSupplier;
private Supplier<Backend> fallback; private Supplier<Backend> fallback;
private BooleanSupplier isSupported; private BooleanSupplier isSupported;
private Pipeline pipelineShader; private Pipeline pipelineShader;
public Builder properName(String properName) {
this.properName = properName;
return this;
}
public Builder engineMessage(Component engineMessage) { public Builder engineMessage(Component engineMessage) {
this.engineMessage = engineMessage; this.engineMessage = engineMessage;
return this; return this;
@ -107,7 +94,7 @@ public class SimpleBackend implements Backend {
} }
public Backend register(ResourceLocation id) { public Backend register(ResourceLocation id) {
return Backend.REGISTRY.registerAndGet(id, new SimpleBackend(properName, engineMessage, engineSupplier, fallback, isSupported, pipelineShader)); return Backend.REGISTRY.registerAndGet(id, new SimpleBackend(engineMessage, engineSupplier, fallback, isSupported, pipelineShader));
} }
} }
} }

View file

@ -63,7 +63,7 @@ public abstract class AbstractBlockEntityInstance<T extends BlockEntity> extends
/** /**
* Just before {@link #update()} would be called, {@code shouldReset()} is checked. * Just before {@link #update()} would be called, {@code shouldReset()} is checked.
* If this function returns {@code true}, then this instance will be {@link #remove removed}, * If this function returns {@code true}, then this instance will be {@link #delete removed},
* and another instance will be constructed to replace it. This allows for more sane resource * and another instance will be constructed to replace it. This allows for more sane resource
* acquisition compared to trying to update everything within the lifetime of an instance. * acquisition compared to trying to update everything within the lifetime of an instance.
* *
@ -85,11 +85,6 @@ public abstract class AbstractBlockEntityInstance<T extends BlockEntity> extends
return pos.subtract(instancerManager.getOriginCoordinate()); return pos.subtract(instancerManager.getOriginCoordinate());
} }
@Override
public BlockPos getWorldPosition() {
return pos;
}
@Override @Override
public ImmutableBox getVolume() { public ImmutableBox getVolume() {
return MutableBox.from(pos); return MutableBox.from(pos);
@ -99,4 +94,9 @@ public abstract class AbstractBlockEntityInstance<T extends BlockEntity> extends
public boolean checkFrustum(FrustumIntersection frustum) { public boolean checkFrustum(FrustumIntersection frustum) {
return frustum.testAab(pos.getX(), pos.getY(), pos.getZ(), pos.getX() + 1, pos.getY() + 1, pos.getZ() + 1); return frustum.testAab(pos.getX(), pos.getY(), pos.getZ(), pos.getX() + 1, pos.getY() + 1, pos.getZ() + 1);
} }
@Override
public double distanceSquared(double x, double y, double z) {
return pos.distToCenterSqr(x, y, z);
}
} }

View file

@ -11,7 +11,6 @@ import com.jozufozu.flywheel.lib.box.MutableBox;
import com.jozufozu.flywheel.lib.light.TickingLightListener; import com.jozufozu.flywheel.lib.light.TickingLightListener;
import com.mojang.math.Vector3f; import com.mojang.math.Vector3f;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Vec3i; import net.minecraft.core.Vec3i;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
@ -88,20 +87,17 @@ public abstract class AbstractEntityInstance<E extends Entity> extends AbstractI
Vec3i origin = instancerManager.getOriginCoordinate(); Vec3i origin = instancerManager.getOriginCoordinate();
return new Vector3f( return new Vector3f(
(float) (Mth.lerp(partialTicks, entity.xOld, pos.x) - origin.getX()), (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.yOld, pos.y) - origin.getY()), (float) (Mth.lerp(partialTicks, entity.zOld, pos.z) - origin.getZ()));
(float) (Mth.lerp(partialTicks, entity.zOld, pos.z) - origin.getZ())
);
}
@Override
public BlockPos getWorldPosition() {
return entity.blockPosition();
} }
@Override @Override
public boolean checkFrustum(FrustumIntersection frustum) { public boolean checkFrustum(FrustumIntersection frustum) {
AABB aabb = entity.getBoundingBox(); AABB aabb = entity.getBoundingBox();
return frustum.testAab((float) aabb.minX, (float) aabb.minY, (float) aabb.minZ, return frustum.testAab((float) aabb.minX, (float) aabb.minY, (float) aabb.minZ, (float) aabb.maxX, (float) aabb.maxY, (float) aabb.maxZ);
(float) aabb.maxX, (float) aabb.maxY, (float) aabb.maxZ); }
@Override
public double distanceSquared(double x, double y, double z) {
return entity.distanceToSqr(x, y, z);
} }
} }

View file

@ -86,8 +86,4 @@ public abstract class AbstractInstance implements Instance, LightListener {
.setSkyLight(sky)); .setSkyLight(sky));
} }
@Override
public final void removeNow() {
LightUpdater.get(level).removeListener(this);
}
} }

View file

@ -41,15 +41,18 @@ public class BellInstance extends AbstractBlockEntityInstance<BellBlockEntity> i
@Override @Override
public void beginFrame() { public void beginFrame() {
float ringTime = (float)blockEntity.ticks + AnimationTickHolder.getPartialTicks(); float ringTime = (float) blockEntity.ticks + AnimationTickHolder.getPartialTicks();
if (ringTime == lastRingTime) return; if (ringTime == lastRingTime) {
return;
}
lastRingTime = ringTime; lastRingTime = ringTime;
if (blockEntity.shaking) { if (blockEntity.shaking) {
float angle = Mth.sin(ringTime / (float) Math.PI) / (4.0F + ringTime / 3.0F); float angle = Mth.sin(ringTime / (float) Math.PI) / (4.0F + ringTime / 3.0F);
Vector3f ringAxis = blockEntity.clickDirection.getCounterClockWise().step(); Vector3f ringAxis = blockEntity.clickDirection.getCounterClockWise()
.step();
bell.setRotation(ringAxis.rotation(angle)); bell.setRotation(ringAxis.rotation(angle));
} else { } else {
@ -59,7 +62,7 @@ public class BellInstance extends AbstractBlockEntityInstance<BellBlockEntity> i
@Override @Override
public void updateLight() { public void updateLight() {
relight(getWorldPosition(), bell); relight(pos, bell);
} }
@Override @Override

View file

@ -71,11 +71,9 @@ public class ChestInstance<T extends BlockEntity & LidBlockEntity> extends Abstr
body.setRotation(baseRotation); body.setRotation(baseRotation);
DoubleBlockCombiner.NeighborCombineResult<? extends ChestBlockEntity> wrapper = chestBlock.combine(blockState, level, getWorldPosition(), true); DoubleBlockCombiner.NeighborCombineResult<? extends ChestBlockEntity> wrapper = chestBlock.combine(blockState, level, pos, true);
this.lidProgress = wrapper.apply(ChestBlock.opennessCombiner(blockEntity)); this.lidProgress = wrapper.apply(ChestBlock.opennessCombiner(blockEntity));
} else { } else {
baseRotation = Quaternion.ONE; baseRotation = Quaternion.ONE;
lidProgress = $ -> 0f; lidProgress = $ -> 0f;
@ -86,7 +84,9 @@ public class ChestInstance<T extends BlockEntity & LidBlockEntity> extends Abstr
public void beginFrame() { public void beginFrame() {
float progress = lidProgress.get(AnimationTickHolder.getPartialTicks()); float progress = lidProgress.get(AnimationTickHolder.getPartialTicks());
if (lastProgress == progress) return; if (lastProgress == progress) {
return;
}
lastProgress = progress; lastProgress = progress;
@ -108,7 +108,7 @@ public class ChestInstance<T extends BlockEntity & LidBlockEntity> extends Abstr
@Override @Override
public void updateLight() { public void updateLight() {
relight(getWorldPosition(), body, lid); relight(pos, body, lid);
} }
@Override @Override
@ -123,13 +123,11 @@ public class ChestInstance<T extends BlockEntity & LidBlockEntity> extends Abstr
} }
private OrientedPart baseInstance() { private OrientedPart baseInstance() {
return instancerManager.getInstancer(StructTypes.ORIENTED, BASE.apply(chestType, sprite), RenderStage.AFTER_BLOCK_ENTITIES) return instancerManager.getInstancer(StructTypes.ORIENTED, BASE.apply(chestType, sprite), RenderStage.AFTER_BLOCK_ENTITIES)
.createInstance(); .createInstance();
} }
private TransformedPart lidInstance() { private TransformedPart lidInstance() {
return instancerManager.getInstancer(StructTypes.TRANSFORMED, LID.apply(chestType, sprite), RenderStage.AFTER_BLOCK_ENTITIES) return instancerManager.getInstancer(StructTypes.TRANSFORMED, LID.apply(chestType, sprite), RenderStage.AFTER_BLOCK_ENTITIES)
.createInstance(); .createInstance();
} }

View file

@ -59,7 +59,7 @@ public class MinecartInstance<T extends AbstractMinecart> extends AbstractEntity
contents.delete(); contents.delete();
contents = getContents(); contents = getContents();
if (contents != null) { if (contents != null) {
relight(getWorldPosition(), contents); relight(entity.blockPosition(), contents);
} }
} }
} }
@ -143,16 +143,19 @@ public class MinecartInstance<T extends AbstractMinecart> extends AbstractEntity
@Override @Override
public void updateLight() { public void updateLight() {
if (contents == null) if (contents == null) {
relight(getWorldPosition(), body); relight(entity.blockPosition(), body);
else } else {
relight(getWorldPosition(), body, contents); relight(entity.blockPosition(), body, contents);
}
} }
@Override @Override
protected void _delete() { protected void _delete() {
body.delete(); body.delete();
if (contents != null) contents.delete(); if (contents != null) {
contents.delete();
}
} }
private TransformedPart getContents() { private TransformedPart getContents() {
@ -165,8 +168,9 @@ public class MinecartInstance<T extends AbstractMinecart> extends AbstractEntity
} }
active = true; active = true;
if (shape == RenderShape.INVISIBLE) if (shape == RenderShape.INVISIBLE) {
return null; return null;
}
return instancerManager.getInstancer(StructTypes.TRANSFORMED, Models.block(blockState), RenderStage.AFTER_ENTITIES) return instancerManager.getInstancer(StructTypes.TRANSFORMED, Models.block(blockState), RenderStage.AFTER_ENTITIES)
.createInstance(); .createInstance();

View file

@ -256,11 +256,6 @@ public class ExampleEffect implements Effect {
.setSkyLight(15); .setSkyLight(15);
} }
@Override
public BlockPos getWorldPosition() {
return blockPos;
}
@Override @Override
protected void _delete() { protected void _delete() {
instance.delete(); instance.delete();
@ -304,5 +299,10 @@ public class ExampleEffect implements Effect {
public boolean checkFrustum(FrustumIntersection frustum) { public boolean checkFrustum(FrustumIntersection frustum) {
return true; return true;
} }
@Override
public double distanceSquared(double x, double y, double z) {
return 0;
}
} }
} }