Moving light updates

- Better system for moving objects that want to receive light updates
 - LightProvider interface to better abstract light lookups
 - All light listeners use GridAlignedBBs
 - More utility in GridAlignedBB
This commit is contained in:
Jozufozu 2021-09-04 16:40:41 -07:00
parent b0aba2d24a
commit e826b31a99
5 changed files with 52 additions and 60 deletions

View file

@ -1,40 +1,35 @@
package com.simibubi.create.content.contraptions.components.structureMovement; package com.simibubi.create.content.contraptions.components.structureMovement;
import com.jozufozu.flywheel.light.*; import com.jozufozu.flywheel.light.*;
import com.simibubi.create.content.contraptions.components.structureMovement.render.RenderedContraption;
import net.minecraft.world.IBlockDisplayReader;
import net.minecraft.world.LightType; import net.minecraft.world.LightType;
public abstract class ContraptionLighter<C extends Contraption> implements ILightUpdateListener { public abstract class ContraptionLighter<C extends Contraption> implements ILightUpdateListener {
protected final C contraption; protected final C contraption;
public final LightVolume lightVolume; public final LightVolume lightVolume;
protected final LightUpdater lightUpdater;
protected GridAlignedBB bounds; protected GridAlignedBB bounds;
protected boolean scheduleRebuild; protected boolean scheduleRebuild;
protected ContraptionLighter(C contraption) { protected ContraptionLighter(C contraption) {
this.contraption = contraption; this.contraption = contraption;
lightUpdater = LightUpdater.get(contraption.entity.level);
bounds = getContraptionBounds(); bounds = getContraptionBounds();
lightVolume = new LightVolume(contraptionBoundsToVolume(bounds.copy())); lightVolume = new LightVolume(contraptionBoundsToVolume(bounds.copy()));
lightVolume.initialize(contraption.entity.level); lightVolume.initialize(contraption.entity.level);
scheduleRebuild = true; scheduleRebuild = true;
startListening(); lightUpdater.addListener(this);
}
public void tick(RenderedContraption owner) { lightVolume.initialize(this.contraption.entity.level);
if (scheduleRebuild) { }
lightVolume.initialize(owner.contraption.entity.level);
scheduleRebuild = false;
}
}
public abstract GridAlignedBB getContraptionBounds(); public abstract GridAlignedBB getContraptionBounds();
@Override @Override
public ListenerStatus status() { public ListenerStatus status() {
@ -42,12 +37,12 @@ public abstract class ContraptionLighter<C extends Contraption> implements ILigh
} }
@Override @Override
public void onLightUpdate(IBlockDisplayReader world, LightType type, GridAlignedBB changed) { public void onLightUpdate(LightProvider world, LightType type, GridAlignedBB changed) {
lightVolume.notifyLightUpdate(world, type, changed); lightVolume.notifyLightUpdate(world, type, changed);
} }
@Override @Override
public void onLightPacket(IBlockDisplayReader world, int chunkX, int chunkZ) { public void onLightPacket(LightProvider world, int chunkX, int chunkZ) {
lightVolume.notifyLightPacket(world, chunkX, chunkZ); lightVolume.notifyLightPacket(world, chunkX, chunkZ);
} }
@ -59,12 +54,8 @@ public abstract class ContraptionLighter<C extends Contraption> implements ILigh
return bounds; return bounds;
} }
public GridAlignedBB getBounds() { @Override
public GridAlignedBB getVolume() {
return bounds; return bounds;
} }
@Override
public Volume.Box getVolume() {
return new Volume.Box(getBounds());
}
} }

View file

@ -1,27 +1,35 @@
package com.simibubi.create.content.contraptions.components.structureMovement; package com.simibubi.create.content.contraptions.components.structureMovement;
import com.jozufozu.flywheel.light.GridAlignedBB; import com.jozufozu.flywheel.light.GridAlignedBB;
import com.jozufozu.flywheel.light.IMovingListener;
import com.jozufozu.flywheel.light.LightProvider;
import com.jozufozu.flywheel.light.LightUpdater;
import com.simibubi.create.content.contraptions.components.structureMovement.render.RenderedContraption; import com.simibubi.create.content.contraptions.components.structureMovement.render.RenderedContraption;
import com.simibubi.create.foundation.config.AllConfigs;
public class NonStationaryLighter<C extends Contraption> extends ContraptionLighter<C> { public class NonStationaryLighter<C extends Contraption> extends ContraptionLighter<C> implements IMovingListener {
public NonStationaryLighter(C contraption) { public NonStationaryLighter(C contraption) {
super(contraption); super(contraption);
} }
@Override @Override
public void tick(RenderedContraption owner) { public boolean update(LightProvider provider) {
super.tick(owner); if (getVolume().volume() > AllConfigs.CLIENT.maxContraptionLightVolume.get())
GridAlignedBB contraptionBounds = getContraptionBounds(); return false;
if (!contraptionBounds.sameAs(bounds)) { GridAlignedBB contraptionBounds = getContraptionBounds();
lightVolume.move(contraption.entity.level, contraptionBoundsToVolume(contraptionBounds));
bounds = contraptionBounds;
startListening(); if (bounds.sameAs(contraptionBounds)) {
} return false;
} }
@Override bounds.assign(contraptionBounds);
lightVolume.move(contraption.entity.level, contraptionBoundsToVolume(bounds));
return true;
}
@Override
public GridAlignedBB getContraptionBounds() { public GridAlignedBB getContraptionBounds() {
GridAlignedBB bb = GridAlignedBB.from(contraption.bounds); GridAlignedBB bb = GridAlignedBB.from(contraption.bounds);

View file

@ -9,8 +9,10 @@ import com.jozufozu.flywheel.core.instancing.ConditionalInstance;
import com.jozufozu.flywheel.core.instancing.GroupInstance; import com.jozufozu.flywheel.core.instancing.GroupInstance;
import com.jozufozu.flywheel.core.instancing.SelectInstance; import com.jozufozu.flywheel.core.instancing.SelectInstance;
import com.jozufozu.flywheel.core.materials.OrientedData; import com.jozufozu.flywheel.core.materials.OrientedData;
import com.jozufozu.flywheel.light.BasicProvider;
import com.jozufozu.flywheel.light.GridAlignedBB; import com.jozufozu.flywheel.light.GridAlignedBB;
import com.jozufozu.flywheel.light.LightUpdater; import com.jozufozu.flywheel.light.IMovingListener;
import com.jozufozu.flywheel.light.LightProvider;
import com.jozufozu.flywheel.light.ListenerStatus; import com.jozufozu.flywheel.light.ListenerStatus;
import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.relays.encased.ShaftInstance; import com.simibubi.create.content.contraptions.relays.encased.ShaftInstance;
@ -143,7 +145,7 @@ public abstract class AbstractPulleyInstance extends ShaftInstance implements ID
bLight = Arrays.copyOf(bLight, length + 1); bLight = Arrays.copyOf(bLight, length + 1);
sLight = Arrays.copyOf(sLight, length + 1); sLight = Arrays.copyOf(sLight, length + 1);
initLight(world, volume); initLight(BasicProvider.get(world), volume);
needsUpdate = true; needsUpdate = true;
} }
@ -176,25 +178,21 @@ public abstract class AbstractPulleyInstance extends ShaftInstance implements ID
} }
boolean needsUpdate; boolean needsUpdate;
@Override
public ListenerStatus status() {
return needsUpdate ? ListenerStatus.UPDATE : super.status();
}
@Override @Override
public void onLightUpdate(IBlockDisplayReader world, LightType type, GridAlignedBB changed) { public void onLightUpdate(LightProvider world, LightType type, GridAlignedBB changed) {
changed.intersectAssign(volume); changed.intersectAssign(volume);
initLight(world, changed); initLight(world, changed);
} }
private void initLight(IBlockDisplayReader world, GridAlignedBB changed) { private void initLight(LightProvider world, GridAlignedBB changed) {
int top = this.pos.getY(); int top = this.pos.getY();
BlockPos.Mutable pos = new BlockPos.Mutable(); BlockPos.Mutable pos = new BlockPos.Mutable();
changed.forEachContained((x, y, z) -> { changed.forEachContained((x, y, z) -> {
pos.set(x, y, z); pos.set(x, y, z);
byte block = (byte) world.getBrightness(LightType.BLOCK, pos); byte block = (byte) world.getLight(LightType.BLOCK, x, y, z);
byte sky = (byte) world.getBrightness(LightType.SKY, pos); byte sky = (byte) world.getLight(LightType.SKY, x, y, z);
int i = top - y; int i = top - y;

View file

@ -28,10 +28,6 @@ public class FlwContraptionManager extends ContraptionRenderManager<RenderedCont
super.tick(); super.tick();
for (RenderedContraption contraption : visible) { for (RenderedContraption contraption : visible) {
ContraptionLighter<?> lighter = contraption.getLighter();
if (lighter.getBounds().volume() < AllConfigs.CLIENT.maxContraptionLightVolume.get())
lighter.tick(contraption);
contraption.kinetics.tick(); contraption.kinetics.tick();
} }
} }

View file

@ -15,9 +15,9 @@ import java.util.function.Function;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.light.GridAlignedBB; import com.jozufozu.flywheel.light.GridAlignedBB;
import com.jozufozu.flywheel.light.ILightUpdateListener; import com.jozufozu.flywheel.light.ILightUpdateListener;
import com.jozufozu.flywheel.light.LightProvider;
import com.jozufozu.flywheel.light.LightUpdater; import com.jozufozu.flywheel.light.LightUpdater;
import com.jozufozu.flywheel.light.ListenerStatus; import com.jozufozu.flywheel.light.ListenerStatus;
import com.jozufozu.flywheel.light.Volume;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.base.IRotate; import com.simibubi.create.content.contraptions.base.IRotate;
import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntity;
@ -50,7 +50,6 @@ import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.vector.Vector3d; import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.util.math.vector.Vector3i; import net.minecraft.util.math.vector.Vector3i;
import net.minecraft.world.IBlockDisplayReader;
import net.minecraft.world.LightType; import net.minecraft.world.LightType;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.model.data.IModelData; import net.minecraftforge.client.model.data.IModelData;
@ -119,7 +118,7 @@ public class BeltTileEntity extends KineticTileEntity implements ILightUpdateLis
if (light == null && level.isClientSide) { if (light == null && level.isClientSide) {
initializeLight(); initializeLight();
LightUpdater.getInstance() LightUpdater.get(level)
.addListener(this); .addListener(this);
} }
@ -525,7 +524,7 @@ public class BeltTileEntity extends KineticTileEntity implements ILightUpdateLis
return getController().equals(((BeltTileEntity) target).getController()) ? 1 : 0; return getController().equals(((BeltTileEntity) target).getController()) ? 1 : 0;
return 0; return 0;
} }
public void invalidateItemHandler() { public void invalidateItemHandler() {
itemHandler.invalidate(); itemHandler.invalidate();
} }
@ -537,14 +536,14 @@ public class BeltTileEntity extends KineticTileEntity implements ILightUpdateLis
BlockState state = getBlockState(); BlockState state = getBlockState();
return state != null && state.hasProperty(BeltBlock.PART) && state.getValue(BeltBlock.PART) == BeltPart.START; return state != null && state.hasProperty(BeltBlock.PART) && state.getValue(BeltBlock.PART) == BeltPart.START;
} }
@Override @Override
public Volume.Box getVolume() { public GridAlignedBB getVolume() {
BlockPos endPos = BeltHelper.getPositionForOffset(this, beltLength - 1); BlockPos endPos = BeltHelper.getPositionForOffset(this, beltLength - 1);
GridAlignedBB bb = GridAlignedBB.from(worldPosition, endPos); GridAlignedBB bb = GridAlignedBB.from(worldPosition, endPos);
bb.fixMinMax(); bb.fixMinMax();
return new Volume.Box(bb); return bb;
} }
@Override @Override
@ -553,10 +552,10 @@ public class BeltTileEntity extends KineticTileEntity implements ILightUpdateLis
} }
@Override @Override
public void onLightUpdate(IBlockDisplayReader world, LightType type, GridAlignedBB changed) { public void onLightUpdate(LightProvider world, LightType type, GridAlignedBB changed) {
Volume.Box beltVolume = getVolume(); GridAlignedBB beltVolume = getVolume();
if (beltVolume.box.intersects(changed)) { if (beltVolume.intersects(changed)) {
if (type == LightType.BLOCK) if (type == LightType.BLOCK)
updateBlockLight(); updateBlockLight();