Update light updates

- Remove NetworkLightUpdateMixin and associated code
- Do not defer level renderer reload when changing backend
- Remove RenderWork
- Reset DrawBuffer on free
- Move CoordinateConsumer inside ImmutableBox
- Rename GridAlignedBB -> MutableBox
- Rename LightListener#isListenerInvalid -> #isInvalid
- Move package light -> lib.light
- Move package util.box -> lib.box
This commit is contained in:
PepperCode1 2023-04-01 11:01:24 -07:00
parent 806e861edc
commit 59773125b2
28 changed files with 131 additions and 260 deletions

View file

@ -20,7 +20,6 @@ import com.jozufozu.flywheel.lib.model.PartialModel;
import com.jozufozu.flywheel.lib.pipeline.Pipelines;
import com.jozufozu.flywheel.lib.struct.StructTypes;
import com.jozufozu.flywheel.lib.util.QuadConverter;
import com.jozufozu.flywheel.lib.util.RenderWork;
import com.jozufozu.flywheel.lib.util.ShadersModHandler;
import com.jozufozu.flywheel.mixin.PausedPartialTickAccessor;
import com.jozufozu.flywheel.vanilla.VanillaInstances;
@ -97,8 +96,6 @@ public class Flywheel {
forgeEventBus.addListener(ForgeEvents::unloadWorld);
forgeEventBus.addListener(ForgeEvents::tickLight);
forgeEventBus.addListener(EventPriority.LOWEST, RenderWork::onRenderLevelLast);
modEventBus.addListener(PartialModel::onModelRegistry);
modEventBus.addListener(PartialModel::onModelBake);

View file

@ -9,7 +9,6 @@ import com.jozufozu.flywheel.api.backend.BackendType;
import com.jozufozu.flywheel.backend.task.ParallelTaskExecutor;
import com.jozufozu.flywheel.config.FlwConfig;
import com.jozufozu.flywheel.lib.backend.BackendTypes;
import com.jozufozu.flywheel.lib.util.RenderWork;
import com.mojang.logging.LogUtils;
import net.minecraft.client.Minecraft;
@ -86,7 +85,7 @@ public class Backend {
}
public static void reloadWorldRenderers() {
RenderWork.enqueue(Minecraft.getInstance().levelRenderer::allChanged);
Minecraft.getInstance().levelRenderer.allChanged();
}
private static BackendType chooseEngine() {

View file

@ -127,6 +127,8 @@ public class DrawBuffer {
}
public void free() {
reset();
if (memory == null) {
return;
}

View file

@ -9,10 +9,10 @@ import com.jozufozu.flywheel.api.instance.TickableInstance;
import com.jozufozu.flywheel.api.instancer.FlatLit;
import com.jozufozu.flywheel.api.instancer.InstancerManager;
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstanceManager;
import com.jozufozu.flywheel.light.LightListener;
import com.jozufozu.flywheel.util.box.ImmutableBox;
import com.jozufozu.flywheel.lib.light.LightListener;
import net.minecraft.core.BlockPos;
import net.minecraft.core.SectionPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LightLayer;
@ -86,7 +86,7 @@ public abstract class AbstractInstance implements Instance, LightListener {
}
@Override
public boolean isListenerInvalid() {
public boolean isInvalid() {
return removed;
}
@ -96,7 +96,7 @@ public abstract class AbstractInstance implements Instance, LightListener {
}
@Override
public void onLightUpdate(LightLayer type, ImmutableBox changed) {
public void onLightUpdate(LightLayer type, SectionPos pos) {
updateLight();
}

View file

@ -19,7 +19,7 @@ import com.jozufozu.flywheel.backend.instancing.ratelimit.DistanceUpdateLimiter;
import com.jozufozu.flywheel.backend.instancing.ratelimit.NonLimiter;
import com.jozufozu.flywheel.backend.instancing.storage.Storage;
import com.jozufozu.flywheel.config.FlwConfig;
import com.jozufozu.flywheel.light.LightUpdater;
import com.jozufozu.flywheel.lib.light.LightUpdater;
import net.minecraft.core.BlockPos;

View file

@ -10,8 +10,8 @@ import com.jozufozu.flywheel.api.instance.TickableInstance;
import com.jozufozu.flywheel.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.instancer.InstancerManager;
import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
import com.jozufozu.flywheel.util.box.GridAlignedBB;
import com.jozufozu.flywheel.util.box.ImmutableBox;
import com.jozufozu.flywheel.lib.box.ImmutableBox;
import com.jozufozu.flywheel.lib.box.MutableBox;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.entity.BlockEntity;
@ -90,7 +90,7 @@ public abstract class BlockEntityInstance<T extends BlockEntity> extends Abstrac
@Override
public ImmutableBox getVolume() {
return GridAlignedBB.from(pos);
return MutableBox.from(pos);
}
@Override

View file

@ -9,7 +9,7 @@ import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
import com.jozufozu.flywheel.backend.instancing.InstanceManager;
import com.jozufozu.flywheel.backend.instancing.storage.AbstractStorage;
import com.jozufozu.flywheel.backend.instancing.storage.Storage;
import com.jozufozu.flywheel.light.LightUpdater;
import com.jozufozu.flywheel.lib.light.LightUpdater;
public class EffectInstanceManager extends InstanceManager<Effect> {

View file

@ -7,9 +7,9 @@ import com.jozufozu.flywheel.api.instance.TickableInstance;
import com.jozufozu.flywheel.api.instancer.InstancerManager;
import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstanceManager;
import com.jozufozu.flywheel.light.LightListener;
import com.jozufozu.flywheel.light.TickingLightListener;
import com.jozufozu.flywheel.util.box.GridAlignedBB;
import com.jozufozu.flywheel.lib.box.MutableBox;
import com.jozufozu.flywheel.lib.light.LightListener;
import com.jozufozu.flywheel.lib.light.TickingLightListener;
import com.mojang.math.Vector3f;
import net.minecraft.core.BlockPos;
@ -38,16 +38,16 @@ import net.minecraft.world.phys.Vec3;
public abstract class EntityInstance<E extends Entity> extends AbstractInstance implements LightListener, TickingLightListener {
protected final E entity;
protected final GridAlignedBB bounds;
protected final MutableBox bounds;
public EntityInstance(InstancerManager instancerManager, E entity) {
super(instancerManager, entity.level);
this.entity = entity;
bounds = GridAlignedBB.from(entity.getBoundingBox());
bounds = MutableBox.from(entity.getBoundingBox());
}
@Override
public GridAlignedBB getVolume() {
public MutableBox getVolume() {
return bounds;
}

View file

@ -7,7 +7,7 @@ import com.jozufozu.flywheel.api.instance.DynamicInstance;
import com.jozufozu.flywheel.api.instance.TickableInstance;
import com.jozufozu.flywheel.api.instancer.InstancerManager;
import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
import com.jozufozu.flywheel.light.LightUpdater;
import com.jozufozu.flywheel.lib.light.LightUpdater;
public abstract class AbstractStorage<T> implements Storage<T> {
protected final List<TickableInstance> tickableInstances;

View file

@ -7,7 +7,7 @@ import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.instancer.InstancerManager;
import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
import com.jozufozu.flywheel.light.LightUpdater;
import com.jozufozu.flywheel.lib.light.LightUpdater;
public abstract class One2OneStorage<T> extends AbstractStorage<T> {
private final Map<T, AbstractInstance> instances;

View file

@ -5,8 +5,8 @@ import java.util.ArrayList;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.lib.light.LightUpdater;
import com.jozufozu.flywheel.lib.memory.FlwMemoryTracker;
import com.jozufozu.flywheel.light.LightUpdater;
import com.jozufozu.flywheel.util.StringUtil;
import com.jozufozu.flywheel.util.WorldAttached;

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.util.box;
package com.jozufozu.flywheel.lib.box;
import static com.jozufozu.flywheel.util.RenderMath.isPowerOf2;
@ -65,14 +65,14 @@ public interface ImmutableBox {
return isPowerOf2(volume());
}
default GridAlignedBB intersect(ImmutableBox other) {
default MutableBox intersect(ImmutableBox other) {
int minX = Math.max(this.getMinX(), other.getMinX());
int minY = Math.max(this.getMinY(), other.getMinY());
int minZ = Math.max(this.getMinZ(), other.getMinZ());
int maxX = Math.min(this.getMaxX(), other.getMaxX());
int maxY = Math.min(this.getMaxY(), other.getMaxY());
int maxZ = Math.min(this.getMaxZ(), other.getMaxZ());
return new GridAlignedBB(minX, minY, minZ, maxX, maxY, maxZ);
return new MutableBox(minX, minY, minZ, maxX, maxY, maxZ);
}
default ImmutableBox union(ImmutableBox other) {
@ -82,7 +82,7 @@ public interface ImmutableBox {
int maxX = Math.max(this.getMaxX(), other.getMaxX());
int maxY = Math.max(this.getMaxY(), other.getMaxY());
int maxZ = Math.max(this.getMaxZ(), other.getMaxZ());
return new GridAlignedBB(minX, minY, minZ, maxX, maxY, maxZ);
return new MutableBox(minX, minY, minZ, maxX, maxY, maxZ);
}
@ -108,7 +108,7 @@ public interface ImmutableBox {
&& other.getMaxZ() <= this.getMaxZ();
}
default boolean isContainedBy(GridAlignedBB other) {
default boolean isContainedBy(MutableBox other) {
return other.contains(this);
}
@ -132,7 +132,12 @@ public interface ImmutableBox {
return new AABB(getMinX(), getMinY(), getMinZ(), getMaxX(), getMaxY(), getMaxZ());
}
default GridAlignedBB copy() {
return new GridAlignedBB(getMinX(), getMinY(), getMinZ(), getMaxX(), getMaxY(), getMaxZ());
default MutableBox copy() {
return new MutableBox(getMinX(), getMinY(), getMinZ(), getMaxX(), getMaxY(), getMaxZ());
}
@FunctionalInterface
interface CoordinateConsumer {
void consume(int x, int y, int z);
}
}

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.util.box;
package com.jozufozu.flywheel.lib.box;
import java.util.Collection;
@ -10,7 +10,7 @@ import net.minecraft.core.SectionPos;
import net.minecraft.core.Vec3i;
import net.minecraft.world.phys.AABB;
public class GridAlignedBB implements ImmutableBox {
public class MutableBox implements ImmutableBox {
private int minX;
private int minY;
private int minZ;
@ -18,11 +18,11 @@ public class GridAlignedBB implements ImmutableBox {
private int maxY;
private int maxZ;
public GridAlignedBB() {
public MutableBox() {
}
public GridAlignedBB(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) {
public MutableBox(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) {
this.minX = minX;
this.minY = minY;
this.minZ = minZ;
@ -31,41 +31,41 @@ public class GridAlignedBB implements ImmutableBox {
this.maxZ = maxZ;
}
public static GridAlignedBB ofRadius(int radius) {
return new GridAlignedBB(-radius, -radius, -radius, radius + 1, radius + 1, radius + 1);
public static MutableBox ofRadius(int radius) {
return new MutableBox(-radius, -radius, -radius, radius + 1, radius + 1, radius + 1);
}
public static GridAlignedBB from(AABB aabb) {
public static MutableBox from(AABB aabb) {
int minX = (int) Math.floor(aabb.minX);
int minY = (int) Math.floor(aabb.minY);
int minZ = (int) Math.floor(aabb.minZ);
int maxX = (int) Math.ceil(aabb.maxX);
int maxY = (int) Math.ceil(aabb.maxY);
int maxZ = (int) Math.ceil(aabb.maxZ);
return new GridAlignedBB(minX, minY, minZ, maxX, maxY, maxZ);
return new MutableBox(minX, minY, minZ, maxX, maxY, maxZ);
}
public static GridAlignedBB from(SectionPos pos) {
return new GridAlignedBB(pos.minBlockX(), pos.minBlockY(), pos.minBlockZ(), pos.maxBlockX() + 1, pos.maxBlockY() + 1, pos.maxBlockZ() + 1);
public static MutableBox from(SectionPos pos) {
return new MutableBox(pos.minBlockX(), pos.minBlockY(), pos.minBlockZ(), pos.maxBlockX() + 1, pos.maxBlockY() + 1, pos.maxBlockZ() + 1);
}
public static GridAlignedBB from(BlockPos start, BlockPos end) {
return new GridAlignedBB(start.getX(), start.getY(), start.getZ(), end.getX() + 1, end.getY() + 1, end.getZ() + 1);
public static MutableBox from(BlockPos start, BlockPos end) {
return new MutableBox(start.getX(), start.getY(), start.getZ(), end.getX() + 1, end.getY() + 1, end.getZ() + 1);
}
public static GridAlignedBB from(BlockPos pos) {
return new GridAlignedBB(pos.getX(), pos.getY(), pos.getZ(), pos.getX() + 1, pos.getY() + 1, pos.getZ() + 1);
public static MutableBox from(BlockPos pos) {
return new MutableBox(pos.getX(), pos.getY(), pos.getZ(), pos.getX() + 1, pos.getY() + 1, pos.getZ() + 1);
}
public static GridAlignedBB from(int sectionX, int sectionZ) {
public static MutableBox from(int sectionX, int sectionZ) {
int startX = sectionX << 4;
int startZ = sectionZ << 4;
return new GridAlignedBB(startX, 0, startZ, startX + 16, 256, startZ + 16);
return new MutableBox(startX, 0, startZ, startX + 16, 256, startZ + 16);
}
public static ImmutableBox containingAll(Collection<BlockPos> positions) {
if (positions.isEmpty()) {
return new GridAlignedBB();
return new MutableBox();
}
int minX = Integer.MAX_VALUE;
int minY = Integer.MAX_VALUE;
@ -81,7 +81,7 @@ public class GridAlignedBB implements ImmutableBox {
maxY = Math.max(maxY, pos.getY());
maxZ = Math.max(maxZ, pos.getZ());
}
return new GridAlignedBB(minX, minY, minZ, maxX, maxY, maxZ);
return new MutableBox(minX, minY, minZ, maxX, maxY, maxZ);
}
public void fixMinMax() {
@ -277,37 +277,37 @@ public class GridAlignedBB implements ImmutableBox {
return maxZ;
}
public GridAlignedBB setMinX(int minX) {
public MutableBox setMinX(int minX) {
this.minX = minX;
return this;
}
public GridAlignedBB setMinY(int minY) {
public MutableBox setMinY(int minY) {
this.minY = minY;
return this;
}
public GridAlignedBB setMinZ(int minZ) {
public MutableBox setMinZ(int minZ) {
this.minZ = minZ;
return this;
}
public GridAlignedBB setMaxX(int maxX) {
public MutableBox setMaxX(int maxX) {
this.maxX = maxX;
return this;
}
public GridAlignedBB setMaxY(int maxY) {
public MutableBox setMaxY(int maxY) {
this.maxY = maxY;
return this;
}
public GridAlignedBB setMaxZ(int maxZ) {
public MutableBox setMaxZ(int maxZ) {
this.maxZ = maxZ;
return this;
}
public GridAlignedBB assign(BlockPos start, BlockPos end) {
public MutableBox assign(BlockPos start, BlockPos end) {
minX = start.getX();
minY = start.getY();
minZ = start.getZ();
@ -317,22 +317,22 @@ public class GridAlignedBB implements ImmutableBox {
return this;
}
public GridAlignedBB setMax(Vec3i v) {
public MutableBox setMax(Vec3i v) {
return setMax(v.getX(), v.getY(), v.getZ());
}
public GridAlignedBB setMin(Vec3i v) {
public MutableBox setMin(Vec3i v) {
return setMin(v.getX(), v.getY(), v.getZ());
}
public GridAlignedBB setMax(int x, int y, int z) {
public MutableBox setMax(int x, int y, int z) {
maxX = x;
maxY = y;
maxZ = z;
return this;
}
public GridAlignedBB setMin(int x, int y, int z) {
public MutableBox setMin(int x, int y, int z) {
minX = x;
minY = y;
minZ = z;
@ -376,14 +376,14 @@ public class GridAlignedBB implements ImmutableBox {
}
@Override
public GridAlignedBB intersect(ImmutableBox other) {
public MutableBox intersect(ImmutableBox other) {
int minX = Math.max(this.minX, other.getMinX());
int minY = Math.max(this.minY, other.getMinY());
int minZ = Math.max(this.minZ, other.getMinZ());
int maxX = Math.min(this.maxX, other.getMaxX());
int maxY = Math.min(this.maxY, other.getMaxY());
int maxZ = Math.min(this.maxZ, other.getMaxZ());
return new GridAlignedBB(minX, minY, minZ, maxX, maxY, maxZ);
return new MutableBox(minX, minY, minZ, maxX, maxY, maxZ);
}
@Override
@ -394,7 +394,7 @@ public class GridAlignedBB implements ImmutableBox {
int maxX = Math.max(this.maxX, other.getMaxX());
int maxY = Math.max(this.maxY, other.getMaxY());
int maxZ = Math.max(this.maxZ, other.getMaxZ());
return new GridAlignedBB(minX, minY, minZ, maxX, maxY, maxZ);
return new MutableBox(minX, minY, minZ, maxX, maxY, maxZ);
}
@Override
@ -426,8 +426,8 @@ public class GridAlignedBB implements ImmutableBox {
}
@Override
public GridAlignedBB copy() {
return new GridAlignedBB(minX, minY, minZ, maxX, maxY, maxZ);
public MutableBox copy() {
return new MutableBox(minX, minY, minZ, maxX, maxY, maxZ);
}
@Override

View file

@ -1,9 +1,10 @@
package com.jozufozu.flywheel.light;
package com.jozufozu.flywheel.lib.light;
import java.util.stream.Stream;
import com.jozufozu.flywheel.util.box.ImmutableBox;
import com.jozufozu.flywheel.lib.box.ImmutableBox;
import net.minecraft.core.SectionPos;
import net.minecraft.world.level.LightLayer;
public class DummyLightUpdater extends LightUpdater {
@ -29,12 +30,7 @@ public class DummyLightUpdater extends LightUpdater {
}
@Override
public void onLightUpdate(LightLayer type, long sectionPos) {
// noop
}
@Override
public void onLightPacket(int chunkX, int chunkZ) {
public void onLightUpdate(LightLayer type, SectionPos pos) {
// noop
}

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.light;
package com.jozufozu.flywheel.lib.light;
import static org.lwjgl.opengl.GL11.GL_LINEAR;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_MAG_FILTER;
@ -23,14 +23,14 @@ import org.lwjgl.opengl.GL30;
import com.jozufozu.flywheel.gl.GlTexture;
import com.jozufozu.flywheel.gl.GlTextureUnit;
import com.jozufozu.flywheel.util.box.GridAlignedBB;
import com.jozufozu.flywheel.util.box.ImmutableBox;
import com.jozufozu.flywheel.lib.box.ImmutableBox;
import com.jozufozu.flywheel.lib.box.MutableBox;
import net.minecraft.world.level.BlockAndTintGetter;
public class GPULightVolume extends LightVolume {
protected final GridAlignedBB sampleVolume = new GridAlignedBB();
protected final MutableBox sampleVolume = new MutableBox();
private final GlTexture glTexture;
private final GlTextureUnit textureUnit = GlTextureUnit.T4;

View file

@ -1,8 +1,8 @@
package com.jozufozu.flywheel.light;
package com.jozufozu.flywheel.lib.light;
import com.jozufozu.flywheel.util.box.GridAlignedBB;
import com.jozufozu.flywheel.util.box.ImmutableBox;
import com.jozufozu.flywheel.lib.box.ImmutableBox;
import net.minecraft.core.SectionPos;
import net.minecraft.world.level.LightLayer;
/**
@ -20,22 +20,10 @@ public interface LightListener {
* @return {@code true} if the listener is invalid/removed/deleted,
* and should no longer receive updates.
*/
boolean isListenerInvalid();
boolean isInvalid();
/**
* Called when a light updates in a chunk the implementor cares about.
*/
void onLightUpdate(LightLayer type, ImmutableBox changed);
/**
* Called when the server sends light data to the client.
*
*/
default void onLightPacket(int chunkX, int chunkZ) {
GridAlignedBB changedVolume = GridAlignedBB.from(chunkX, chunkZ);
onLightUpdate(LightLayer.BLOCK, changedVolume);
onLightUpdate(LightLayer.SKY, changedVolume);
}
void onLightUpdate(LightLayer type, SectionPos pos);
}

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.light;
package com.jozufozu.flywheel.lib.light;
/**
* Utility class for bit-twiddling light.

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.light;
package com.jozufozu.flywheel.lib.light;
import net.minecraft.client.Minecraft;
import net.minecraft.world.level.LevelAccessor;

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.light;
package com.jozufozu.flywheel.lib.light;
import java.util.Queue;
import java.util.Set;
@ -6,15 +6,12 @@ import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.stream.Stream;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.task.ParallelTaskExecutor;
import com.jozufozu.flywheel.backend.task.WorkGroup;
import com.jozufozu.flywheel.lib.box.ImmutableBox;
import com.jozufozu.flywheel.util.FlwUtil;
import com.jozufozu.flywheel.util.WorldAttached;
import com.jozufozu.flywheel.util.box.GridAlignedBB;
import com.jozufozu.flywheel.util.box.ImmutableBox;
import it.unimi.dsi.fastutil.longs.LongSet;
import net.minecraft.core.BlockPos;
import net.minecraft.core.SectionPos;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LightLayer;
@ -28,7 +25,11 @@ import net.minecraft.world.level.LightLayer;
public class LightUpdater {
private static final WorldAttached<LightUpdater> LEVELS = new WorldAttached<>(LightUpdater::new);
private final ParallelTaskExecutor taskExecutor;
private final LevelAccessor level;
private final WeakContainmentMultiMap<LightListener> listenersBySection = new WeakContainmentMultiMap<>();
private final Set<TickingLightListener> tickingListeners = FlwUtil.createWeakHashSet();
public static LightUpdater get(LevelAccessor level) {
if (LightUpdated.receivesLightUpdates(level)) {
@ -40,14 +41,7 @@ public class LightUpdater {
}
}
private final LevelAccessor level;
private final Set<TickingLightListener> tickingLightListeners = FlwUtil.createWeakHashSet();
private final WeakContainmentMultiMap<LightListener> sections = new WeakContainmentMultiMap<>();
private final WeakContainmentMultiMap<LightListener> chunks = new WeakContainmentMultiMap<>();
public LightUpdater(LevelAccessor level) {
taskExecutor = Backend.getTaskExecutor();
this.level = level;
}
@ -57,7 +51,7 @@ public class LightUpdater {
}
private void tickSerial() {
for (TickingLightListener tickingLightListener : tickingLightListeners) {
for (TickingLightListener tickingLightListener : tickingListeners) {
if (tickingLightListener.tickLightListener()) {
addListener(tickingLightListener);
}
@ -68,13 +62,13 @@ public class LightUpdater {
Queue<LightListener> listeners = new ConcurrentLinkedQueue<>();
WorkGroup.builder()
.addTasks(tickingLightListeners.stream(), listener -> {
.addTasks(tickingListeners.stream(), listener -> {
if (listener.tickLightListener()) {
listeners.add(listener);
}
})
.onComplete(() -> listeners.forEach(this::addListener))
.execute(taskExecutor);
.execute(Backend.getTaskExecutor());
}
/**
@ -84,12 +78,11 @@ public class LightUpdater {
*/
public void addListener(LightListener listener) {
if (listener instanceof TickingLightListener)
tickingLightListeners.add(((TickingLightListener) listener));
tickingListeners.add(((TickingLightListener) listener));
ImmutableBox box = listener.getVolume();
LongSet sections = this.sections.getAndResetContainment(listener);
LongSet chunks = this.chunks.getAndResetContainment(listener);
LongSet sections = this.listenersBySection.getAndResetContainment(listener);
int minX = SectionPos.blockToSectionCoord(box.getMinX());
int minY = SectionPos.blockToSectionCoord(box.getMinY());
@ -99,75 +92,42 @@ public class LightUpdater {
int maxZ = SectionPos.blockToSectionCoord(box.getMaxZ());
for (int x = minX; x <= maxX; x++) {
for (int z = minZ; z <= maxZ; z++) {
for (int y = minY; y <= maxY; y++) {
for (int y = minY; y <= maxY; y++) {
for (int z = minZ; z <= maxZ; z++) {
long sectionPos = SectionPos.asLong(x, y, z);
this.sections.put(sectionPos, listener);
this.listenersBySection.put(sectionPos, listener);
sections.add(sectionPos);
}
long chunkPos = SectionPos.asLong(x, 0, z);
this.chunks.put(chunkPos, listener);
chunks.add(chunkPos);
}
}
}
public void removeListener(LightListener listener) {
this.sections.remove(listener);
this.chunks.remove(listener);
this.listenersBySection.remove(listener);
}
/**
* Dispatch light updates to all registered {@link LightListener}s.
* @param type The type of light that changed.
* @param sectionPos A long representing the section position where light changed.
* @param type The type of light that changed.
* @param pos The section position where light changed.
*/
public void onLightUpdate(LightLayer type, long sectionPos) {
Set<LightListener> set = sections.get(sectionPos);
public void onLightUpdate(LightLayer type, SectionPos pos) {
Set<LightListener> listeners = listenersBySection.get(pos.asLong());
if (set == null || set.isEmpty()) return;
if (listeners == null || listeners.isEmpty()) return;
set.removeIf(LightListener::isListenerInvalid);
listeners.removeIf(LightListener::isInvalid);
ImmutableBox chunkBox = GridAlignedBB.from(SectionPos.of(sectionPos));
for (LightListener listener : set) {
listener.onLightUpdate(type, chunkBox);
for (LightListener listener : listeners) {
listener.onLightUpdate(type, pos);
}
}
/**
* Dispatch light updates to all registered {@link LightListener}s
* when the server sends lighting data for an entire chunk.
*
*/
public void onLightPacket(int chunkX, int chunkZ) {
long chunkPos = SectionPos.asLong(chunkX, 0, chunkZ);
Set<LightListener> set = chunks.get(chunkPos);
if (set == null || set.isEmpty()) return;
set.removeIf(LightListener::isListenerInvalid);
for (LightListener listener : set) {
listener.onLightPacket(chunkX, chunkZ);
}
}
public static long blockToSection(BlockPos pos) {
return SectionPos.asLong(pos.getX(), pos.getY(), pos.getZ());
}
public static long sectionToChunk(long sectionPos) {
return sectionPos & 0xFFFFFFFFFFF_00000L;
}
public Stream<ImmutableBox> getAllBoxes() {
return chunks.stream().map(LightListener::getVolume);
return listenersBySection.stream().map(LightListener::getVolume);
}
public boolean isEmpty() {
return chunks.isEmpty();
return listenersBySection.isEmpty();
}
}

View file

@ -1,19 +1,20 @@
package com.jozufozu.flywheel.light;
package com.jozufozu.flywheel.lib.light;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.lib.box.ImmutableBox;
import com.jozufozu.flywheel.lib.box.MutableBox;
import com.jozufozu.flywheel.lib.memory.MemoryBlock;
import com.jozufozu.flywheel.util.box.GridAlignedBB;
import com.jozufozu.flywheel.util.box.ImmutableBox;
import net.minecraft.core.BlockPos;
import net.minecraft.core.SectionPos;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.LightLayer;
public class LightVolume implements ImmutableBox, LightListener {
protected final BlockAndTintGetter level;
protected final GridAlignedBB box = new GridAlignedBB();
protected final MutableBox box = new MutableBox();
protected MemoryBlock lightData;
public LightVolume(BlockAndTintGetter level, ImmutableBox sampleVolume) {
@ -59,7 +60,7 @@ public class LightVolume implements ImmutableBox, LightListener {
}
@Override
public boolean isListenerInvalid() {
public boolean isInvalid() {
return lightData == null;
}
@ -207,10 +208,10 @@ public class LightVolume implements ImmutableBox, LightListener {
}
@Override
public void onLightUpdate(LightLayer type, ImmutableBox changedVolume) {
public void onLightUpdate(LightLayer type, SectionPos pos) {
if (lightData == null) return;
GridAlignedBB vol = changedVolume.copy();
MutableBox vol = MutableBox.from(pos);
if (!vol.intersects(getVolume())) return;
vol.intersectAssign(getVolume()); // compute the region contained by us that has dirty lighting data.
@ -219,16 +220,4 @@ public class LightVolume implements ImmutableBox, LightListener {
markDirty();
}
@Override
public void onLightPacket(int chunkX, int chunkZ) {
if (lightData == null) return;
GridAlignedBB changedVolume = GridAlignedBB.from(chunkX, chunkZ);
if (!changedVolume.intersects(getVolume())) return;
changedVolume.intersectAssign(getVolume()); // compute the region contained by us that has dirty lighting data.
copyLight(changedVolume);
markDirty();
}
}

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.light;
package com.jozufozu.flywheel.lib.light;
public interface TickingLightListener extends LightListener {
/**

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.light;
package com.jozufozu.flywheel.lib.light;
import java.util.AbstractCollection;
import java.util.Iterator;
@ -24,7 +24,7 @@ public class WeakContainmentMultiMap<T> extends AbstractCollection<T> {
}
/**
* This is a confusing function, but it maintains the internal state of the chunk/section maps.
* This is a confusing function, but it maintains the internal state of the section maps.
*
* <p>
* First, uses the reverse lookup map to remove listener from all sets in the lookup map.<br>
@ -32,7 +32,7 @@ public class WeakContainmentMultiMap<T> extends AbstractCollection<T> {
* </p>
*
* @param listener The listener to clean up.
* @return An empty set that should be populated with the chunks/sections the listener is contained in.
* @return An empty set that should be populated with the sections the listener is contained in.
*/
public LongSet getAndResetContainment(T listener) {
LongSet containmentSet = reverse.computeIfAbsent(listener, $ -> new LongRBTreeSet());

View file

@ -1,24 +0,0 @@
package com.jozufozu.flywheel.lib.util;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import net.minecraftforge.client.event.RenderLevelLastEvent;
public class RenderWork {
private static final Queue<Runnable> RUNS = new ConcurrentLinkedQueue<>();
public static void onRenderLevelLast(RenderLevelLastEvent event) {
while (!RUNS.isEmpty()) {
RUNS.remove()
.run();
}
}
/**
* Queue work to be executed at the end of a frame
*/
public static void enqueue(Runnable run) {
RUNS.add(run);
}
}

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.mixin.light;
package com.jozufozu.flywheel.mixin;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
@ -7,7 +7,7 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.jozufozu.flywheel.light.LightUpdater;
import com.jozufozu.flywheel.lib.light.LightUpdater;
import net.minecraft.client.multiplayer.ClientChunkCache;
import net.minecraft.client.multiplayer.ClientLevel;
@ -22,14 +22,12 @@ public abstract class LightUpdateMixin extends ChunkSource {
ClientLevel level;
/**
* JUSTIFICATION: This method is called after a lighting tick once per subchunk where a
* lighting change occurred that tick. On the client, Minecraft uses this method to inform
* the rendering system that it needs to redraw a chunk. It does all that work asynchronously,
* and we should too.
* JUSTIFICATION: This method is called after lighting updates are finished processing
* per section where a lighting change occurred that frame. On the client, Minecraft
* uses this method to inform the rendering system that it needs to redraw a chunk.
*/
@Inject(at = @At("HEAD"), method = "onLightUpdate")
@Inject(method = "onLightUpdate(Lnet/minecraft/world/level/LightLayer;Lnet/minecraft/core/SectionPos;)V", at = @At("HEAD"))
private void flywheel$onLightUpdate(LightLayer type, SectionPos pos, CallbackInfo ci) {
LightUpdater.get(level)
.onLightUpdate(type, pos.asLong());
LightUpdater.get(level).onLightUpdate(type, pos);
}
}

View file

@ -1,32 +0,0 @@
package com.jozufozu.flywheel.mixin.light;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.jozufozu.flywheel.lib.util.RenderWork;
import com.jozufozu.flywheel.light.LightUpdater;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.multiplayer.ClientPacketListener;
import net.minecraft.network.protocol.game.ClientboundLightUpdatePacket;
@Mixin(ClientPacketListener.class)
public class NetworkLightUpdateMixin {
@Inject(at = @At("TAIL"), method = "handleLightUpdatePacket")
private void flywheel$onLightPacket(ClientboundLightUpdatePacket packet, CallbackInfo ci) {
RenderWork.enqueue(() -> {
ClientLevel level = Minecraft.getInstance().level;
if (level == null) return;
int chunkX = packet.getX();
int chunkZ = packet.getZ();
LightUpdater.get(level)
.onLightPacket(chunkX, chunkZ);
});
}
}

View file

@ -1,6 +0,0 @@
package com.jozufozu.flywheel.util.box;
@FunctionalInterface
public interface CoordinateConsumer {
void consume(int x, int y, int z);
}

View file

@ -16,12 +16,12 @@ import com.jozufozu.flywheel.api.instancer.InstancerManager;
import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.backend.instancing.effect.Effect;
import com.jozufozu.flywheel.lib.box.ImmutableBox;
import com.jozufozu.flywheel.lib.box.MutableBox;
import com.jozufozu.flywheel.lib.model.Models;
import com.jozufozu.flywheel.lib.struct.StructTypes;
import com.jozufozu.flywheel.lib.struct.TransformedPart;
import com.jozufozu.flywheel.util.AnimationTickHolder;
import com.jozufozu.flywheel.util.box.GridAlignedBB;
import com.jozufozu.flywheel.util.box.ImmutableBox;
import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos;
@ -67,7 +67,7 @@ public class ExampleEffect implements Effect {
this.level = level;
this.targetPoint = targetPoint;
this.blockPos = new BlockPos(targetPoint.x, targetPoint.y, targetPoint.z);
this.volume = GridAlignedBB.from(this.blockPos);
this.volume = MutableBox.from(this.blockPos);
this.effects = new ArrayList<>(INSTANCE_COUNT);
this.boids = new ArrayList<>(INSTANCE_COUNT);
}

View file

@ -15,6 +15,7 @@
"GlStateManagerMixin",
"LevelRendererAccessor",
"LevelRendererMixin",
"LightUpdateMixin",
"PausedPartialTickAccessor",
"RenderTypeMixin",
"VertexFormatMixin",
@ -22,8 +23,6 @@
"instancemanage.InstanceAddMixin",
"instancemanage.InstanceRemoveMixin",
"instancemanage.InstanceUpdateMixin",
"light.LightUpdateMixin",
"light.NetworkLightUpdateMixin",
"matrix.Matrix3fAccessor",
"matrix.Matrix4fAccessor",
"matrix.PoseStackMixin"