mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-01-18 17:07:52 +01:00
Update light updates
- ... to address the nullpointer with create pulleys - LightListeners track their own levels - Remove BasicProvider and LightProvider - Rename MovingListener to better match functionality - Remove ListenerStatus in favor of a boolean - Instances keep track of their removal status and properly report it via LightListener#isListenerInvalid - Bump version - 0.6.4
This commit is contained in:
parent
f058b37b13
commit
055802160f
14 changed files with 112 additions and 147 deletions
|
@ -2,7 +2,7 @@ org.gradle.jvmargs = -Xmx3G
|
||||||
org.gradle.daemon = false
|
org.gradle.daemon = false
|
||||||
|
|
||||||
# mod version info
|
# mod version info
|
||||||
mod_version = 0.6.3
|
mod_version = 0.6.4
|
||||||
mc_update_version = 1.18
|
mc_update_version = 1.18
|
||||||
minecraft_version = 1.18.2
|
minecraft_version = 1.18.2
|
||||||
forge_version = 40.0.15
|
forge_version = 40.0.15
|
||||||
|
|
|
@ -10,8 +10,6 @@ import com.jozufozu.flywheel.api.instance.TickableInstance;
|
||||||
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstanceManager;
|
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstanceManager;
|
||||||
import com.jozufozu.flywheel.core.materials.FlatLit;
|
import com.jozufozu.flywheel.core.materials.FlatLit;
|
||||||
import com.jozufozu.flywheel.light.LightListener;
|
import com.jozufozu.flywheel.light.LightListener;
|
||||||
import com.jozufozu.flywheel.light.LightProvider;
|
|
||||||
import com.jozufozu.flywheel.light.ListenerStatus;
|
|
||||||
import com.jozufozu.flywheel.util.box.ImmutableBox;
|
import com.jozufozu.flywheel.util.box.ImmutableBox;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
@ -26,6 +24,7 @@ public abstract class AbstractInstance implements Instance, LightListener {
|
||||||
|
|
||||||
protected final MaterialManager materialManager;
|
protected final MaterialManager materialManager;
|
||||||
public final Level world;
|
public final Level world;
|
||||||
|
protected boolean removed = false;
|
||||||
|
|
||||||
public AbstractInstance(MaterialManager materialManager, Level world) {
|
public AbstractInstance(MaterialManager materialManager, Level world) {
|
||||||
this.materialManager = materialManager;
|
this.materialManager = materialManager;
|
||||||
|
@ -39,10 +38,19 @@ public abstract class AbstractInstance implements Instance, LightListener {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final void removeAndMark() {
|
||||||
|
if (removed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
remove();
|
||||||
|
removed = true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Free any acquired resources.
|
* Free any acquired resources.
|
||||||
*/
|
*/
|
||||||
public abstract void remove();
|
protected abstract void remove();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update instance data here. Good for when data doesn't change very often and when animations are GPU based.
|
* Update instance data here. Good for when data doesn't change very often and when animations are GPU based.
|
||||||
|
@ -78,12 +86,12 @@ public abstract class AbstractInstance implements Instance, LightListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ListenerStatus status() {
|
public boolean isListenerInvalid() {
|
||||||
return ListenerStatus.OKAY;
|
return removed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLightUpdate(LightProvider world, LightLayer type, ImmutableBox changed) {
|
public void onLightUpdate(LightLayer type, ImmutableBox changed) {
|
||||||
updateLight();
|
updateLight();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,4 +111,5 @@ public abstract class AbstractInstance implements Instance, LightListener {
|
||||||
models.forEach(model -> model.setBlockLight(block)
|
models.forEach(model -> model.setBlockLight(block)
|
||||||
.setSkyLight(sky));
|
.setSkyLight(sky));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -260,7 +260,7 @@ public abstract class InstanceManager<T> implements InstancingEngine.OriginShift
|
||||||
}
|
}
|
||||||
|
|
||||||
public void invalidate() {
|
public void invalidate() {
|
||||||
instances.values().forEach(AbstractInstance::remove);
|
instances.values().forEach(AbstractInstance::removeAndMark);
|
||||||
instances.clear();
|
instances.clear();
|
||||||
dynamicInstances.clear();
|
dynamicInstances.clear();
|
||||||
tickableInstances.clear();
|
tickableInstances.clear();
|
||||||
|
@ -314,7 +314,7 @@ public abstract class InstanceManager<T> implements InstancingEngine.OriginShift
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void removeInternal(T obj, AbstractInstance instance) {
|
protected void removeInternal(T obj, AbstractInstance instance) {
|
||||||
instance.remove();
|
instance.removeAndMark();
|
||||||
instances.remove(obj);
|
instances.remove(obj);
|
||||||
dynamicInstances.remove(obj);
|
dynamicInstances.remove(obj);
|
||||||
tickableInstances.remove(obj);
|
tickableInstances.remove(obj);
|
||||||
|
|
|
@ -6,8 +6,7 @@ import com.jozufozu.flywheel.api.instance.TickableInstance;
|
||||||
import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
|
import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
|
||||||
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstanceManager;
|
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstanceManager;
|
||||||
import com.jozufozu.flywheel.light.LightListener;
|
import com.jozufozu.flywheel.light.LightListener;
|
||||||
import com.jozufozu.flywheel.light.LightProvider;
|
import com.jozufozu.flywheel.light.TickingLightListener;
|
||||||
import com.jozufozu.flywheel.light.MovingListener;
|
|
||||||
import com.jozufozu.flywheel.util.box.GridAlignedBB;
|
import com.jozufozu.flywheel.util.box.GridAlignedBB;
|
||||||
import com.mojang.math.Vector3f;
|
import com.mojang.math.Vector3f;
|
||||||
|
|
||||||
|
@ -34,7 +33,7 @@ import net.minecraft.world.phys.Vec3;
|
||||||
*
|
*
|
||||||
* @param <E> The type of {@link Entity} your class is an instance of.
|
* @param <E> The type of {@link Entity} your class is an instance of.
|
||||||
*/
|
*/
|
||||||
public abstract class EntityInstance<E extends Entity> extends AbstractInstance implements LightListener, MovingListener {
|
public abstract class EntityInstance<E extends Entity> extends AbstractInstance implements LightListener, TickingLightListener {
|
||||||
|
|
||||||
protected final E entity;
|
protected final E entity;
|
||||||
protected final GridAlignedBB bounds;
|
protected final GridAlignedBB bounds;
|
||||||
|
@ -51,7 +50,7 @@ public abstract class EntityInstance<E extends Entity> extends AbstractInstance
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean update(LightProvider provider) {
|
public boolean tickLightListener() {
|
||||||
AABB boundsNow = entity.getBoundingBox();
|
AABB boundsNow = entity.getBoundingBox();
|
||||||
|
|
||||||
if (bounds.sameAs(boundsNow)) return false;
|
if (bounds.sameAs(boundsNow)) return false;
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
package com.jozufozu.flywheel.light;
|
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
|
||||||
import net.minecraft.world.level.BlockAndTintGetter;
|
|
||||||
import net.minecraft.world.level.LightLayer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wraps a world and minimally lowers the interface.
|
|
||||||
*/
|
|
||||||
public class BasicProvider implements LightProvider {
|
|
||||||
|
|
||||||
private final BlockAndTintGetter reader;
|
|
||||||
private final BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos();
|
|
||||||
|
|
||||||
public BasicProvider(BlockAndTintGetter reader) {
|
|
||||||
this.reader = reader;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getLight(LightLayer type, int x, int y, int z) {
|
|
||||||
return reader.getBrightness(type, pos.set(x, y, z));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -26,6 +26,7 @@ import com.jozufozu.flywheel.backend.gl.GlTextureUnit;
|
||||||
import com.jozufozu.flywheel.util.box.GridAlignedBB;
|
import com.jozufozu.flywheel.util.box.GridAlignedBB;
|
||||||
import com.jozufozu.flywheel.util.box.ImmutableBox;
|
import com.jozufozu.flywheel.util.box.ImmutableBox;
|
||||||
|
|
||||||
|
import net.minecraft.world.level.BlockAndTintGetter;
|
||||||
import net.minecraft.world.level.LightLayer;
|
import net.minecraft.world.level.LightLayer;
|
||||||
|
|
||||||
public class GPULightVolume extends LightVolume {
|
public class GPULightVolume extends LightVolume {
|
||||||
|
@ -36,8 +37,8 @@ public class GPULightVolume extends LightVolume {
|
||||||
private final GlTextureUnit textureUnit = GlTextureUnit.T4;
|
private final GlTextureUnit textureUnit = GlTextureUnit.T4;
|
||||||
protected boolean bufferDirty;
|
protected boolean bufferDirty;
|
||||||
|
|
||||||
public GPULightVolume(ImmutableBox sampleVolume) {
|
public GPULightVolume(BlockAndTintGetter level, ImmutableBox sampleVolume) {
|
||||||
super(sampleVolume);
|
super(level, sampleVolume);
|
||||||
this.sampleVolume.assign(sampleVolume);
|
this.sampleVolume.assign(sampleVolume);
|
||||||
|
|
||||||
glTexture = new GlTexture(GL_TEXTURE_3D);
|
glTexture = new GlTexture(GL_TEXTURE_3D);
|
||||||
|
@ -110,38 +111,24 @@ public class GPULightVolume extends LightVolume {
|
||||||
glTexture.delete();
|
glTexture.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void move(LightProvider world, ImmutableBox newSampleVolume) {
|
public void move(BlockAndTintGetter level, ImmutableBox newSampleVolume) {
|
||||||
if (lightData == null) return;
|
if (lightData == null) return;
|
||||||
|
|
||||||
if (box.contains(newSampleVolume)) {
|
if (box.contains(newSampleVolume)) {
|
||||||
sampleVolume.assign(newSampleVolume);
|
sampleVolume.assign(newSampleVolume);
|
||||||
initialize(world);
|
initialize();
|
||||||
} else {
|
} else {
|
||||||
super.move(world, newSampleVolume);
|
super.move(level, newSampleVolume);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onLightUpdate(LightProvider world, LightLayer type, ImmutableBox changedVolume) {
|
|
||||||
super.onLightUpdate(world, type, changedVolume);
|
|
||||||
bufferDirty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onLightPacket(LightProvider world, int chunkX, int chunkZ) {
|
|
||||||
super.onLightPacket(world, chunkX, chunkZ);
|
|
||||||
bufferDirty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Completely (re)populate this volume with block and sky lighting data.
|
|
||||||
* This is expensive and should be avoided.
|
|
||||||
*/
|
|
||||||
public void initialize(LightProvider world) {
|
|
||||||
super.initialize(world);
|
|
||||||
bufferDirty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ImmutableBox getVolume() {
|
public ImmutableBox getVolume() {
|
||||||
return sampleVolume;
|
return sampleVolume;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void markDirty() {
|
||||||
|
this.bufferDirty = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,26 +5,37 @@ import com.jozufozu.flywheel.util.box.ImmutableBox;
|
||||||
|
|
||||||
import net.minecraft.world.level.LightLayer;
|
import net.minecraft.world.level.LightLayer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementors of this interface may choose to subscribe to light updates by calling
|
||||||
|
* {@link LightUpdater#addListener(LightListener)}.<p>
|
||||||
|
*
|
||||||
|
* It is the responsibility of the implementor to keep a reference to the level an object is contained in.
|
||||||
|
*/
|
||||||
public interface LightListener {
|
public interface LightListener {
|
||||||
|
|
||||||
ImmutableBox getVolume();
|
ImmutableBox getVolume();
|
||||||
|
|
||||||
ListenerStatus status();
|
/**
|
||||||
|
* Check the status of the light listener.
|
||||||
|
* @return {@code true} if the listener is invalid/removed/deleted,
|
||||||
|
* and should no longer receive updates.
|
||||||
|
*/
|
||||||
|
boolean isListenerInvalid();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when a light updates in a chunk the implementor cares about.
|
* Called when a light updates in a chunk the implementor cares about.
|
||||||
*/
|
*/
|
||||||
void onLightUpdate(LightProvider world, LightLayer type, ImmutableBox changed);
|
void onLightUpdate(LightLayer type, ImmutableBox changed);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the server sends light data to the client.
|
* Called when the server sends light data to the client.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
default void onLightPacket(LightProvider world, int chunkX, int chunkZ) {
|
default void onLightPacket(int chunkX, int chunkZ) {
|
||||||
GridAlignedBB changedVolume = GridAlignedBB.from(chunkX, chunkZ);
|
GridAlignedBB changedVolume = GridAlignedBB.from(chunkX, chunkZ);
|
||||||
|
|
||||||
onLightUpdate(world, LightLayer.BLOCK, changedVolume);
|
onLightUpdate(LightLayer.BLOCK, changedVolume);
|
||||||
|
|
||||||
onLightUpdate(world, LightLayer.SKY, changedVolume);
|
onLightUpdate(LightLayer.SKY, changedVolume);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
package com.jozufozu.flywheel.light;
|
|
||||||
|
|
||||||
import net.minecraft.client.renderer.LightTexture;
|
|
||||||
import net.minecraft.world.level.LightLayer;
|
|
||||||
|
|
||||||
public interface LightProvider {
|
|
||||||
int getLight(LightLayer type, int x, int y, int z);
|
|
||||||
|
|
||||||
default int getPackedLight(int x, int y, int z) {
|
|
||||||
return LightTexture.pack(getLight(LightLayer.BLOCK, x, y, z), getLight(LightLayer.SKY, x, y, z));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -39,19 +39,15 @@ public class LightUpdater {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final LightProvider provider;
|
private final LevelAccessor level;
|
||||||
|
|
||||||
private final WeakHashSet<MovingListener> movingListeners = new WeakHashSet<>();
|
private final WeakHashSet<TickingLightListener> tickingLightListeners = new WeakHashSet<>();
|
||||||
private final WeakContainmentMultiMap<LightListener> sections = new WeakContainmentMultiMap<>();
|
private final WeakContainmentMultiMap<LightListener> sections = new WeakContainmentMultiMap<>();
|
||||||
private final WeakContainmentMultiMap<LightListener> chunks = new WeakContainmentMultiMap<>();
|
private final WeakContainmentMultiMap<LightListener> chunks = new WeakContainmentMultiMap<>();
|
||||||
|
|
||||||
public LightUpdater(LevelAccessor world) {
|
public LightUpdater(LevelAccessor level) {
|
||||||
taskEngine = Backend.getTaskEngine();
|
taskEngine = Backend.getTaskEngine();
|
||||||
provider = new BasicProvider(world);
|
this.level = level;
|
||||||
}
|
|
||||||
|
|
||||||
public LightProvider getProvider() {
|
|
||||||
return provider;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void tick() {
|
public void tick() {
|
||||||
|
@ -60,9 +56,9 @@ public class LightUpdater {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tickSerial() {
|
private void tickSerial() {
|
||||||
for (MovingListener movingListener : movingListeners) {
|
for (TickingLightListener tickingLightListener : tickingLightListeners) {
|
||||||
if (movingListener.update(provider)) {
|
if (tickingLightListener.tickLightListener()) {
|
||||||
addListener(movingListener);
|
addListener(tickingLightListener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,8 +67,8 @@ public class LightUpdater {
|
||||||
Queue<LightListener> listeners = new ConcurrentLinkedQueue<>();
|
Queue<LightListener> listeners = new ConcurrentLinkedQueue<>();
|
||||||
|
|
||||||
taskEngine.group("LightUpdater")
|
taskEngine.group("LightUpdater")
|
||||||
.addTasks(movingListeners.stream(), listener -> {
|
.addTasks(tickingLightListeners.stream(), listener -> {
|
||||||
if (listener.update(provider)) {
|
if (listener.tickLightListener()) {
|
||||||
listeners.add(listener);
|
listeners.add(listener);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -86,8 +82,8 @@ public class LightUpdater {
|
||||||
* @param listener The object that wants to receive light update notifications.
|
* @param listener The object that wants to receive light update notifications.
|
||||||
*/
|
*/
|
||||||
public void addListener(LightListener listener) {
|
public void addListener(LightListener listener) {
|
||||||
if (listener instanceof MovingListener)
|
if (listener instanceof TickingLightListener)
|
||||||
movingListeners.add(((MovingListener) listener));
|
tickingLightListeners.add(((TickingLightListener) listener));
|
||||||
|
|
||||||
ImmutableBox box = listener.getVolume();
|
ImmutableBox box = listener.getVolume();
|
||||||
|
|
||||||
|
@ -130,12 +126,12 @@ public class LightUpdater {
|
||||||
|
|
||||||
if (set == null || set.isEmpty()) return;
|
if (set == null || set.isEmpty()) return;
|
||||||
|
|
||||||
set.removeIf(l -> l.status().shouldRemove());
|
set.removeIf(LightListener::isListenerInvalid);
|
||||||
|
|
||||||
ImmutableBox chunkBox = GridAlignedBB.from(SectionPos.of(sectionPos));
|
ImmutableBox chunkBox = GridAlignedBB.from(SectionPos.of(sectionPos));
|
||||||
|
|
||||||
for (LightListener listener : set) {
|
for (LightListener listener : set) {
|
||||||
listener.onLightUpdate(provider, type, chunkBox);
|
listener.onLightUpdate(type, chunkBox);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,10 +147,10 @@ public class LightUpdater {
|
||||||
|
|
||||||
if (set == null || set.isEmpty()) return;
|
if (set == null || set.isEmpty()) return;
|
||||||
|
|
||||||
set.removeIf(l -> l.status().shouldRemove());
|
set.removeIf(LightListener::isListenerInvalid);
|
||||||
|
|
||||||
for (LightListener listener : set) {
|
for (LightListener listener : set) {
|
||||||
listener.onLightPacket(provider, chunkX, chunkZ);
|
listener.onLightPacket(chunkX, chunkZ);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,14 +8,17 @@ import com.jozufozu.flywheel.util.box.GridAlignedBB;
|
||||||
import com.jozufozu.flywheel.util.box.ImmutableBox;
|
import com.jozufozu.flywheel.util.box.ImmutableBox;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.world.level.BlockAndTintGetter;
|
||||||
import net.minecraft.world.level.LightLayer;
|
import net.minecraft.world.level.LightLayer;
|
||||||
|
|
||||||
public class LightVolume implements ImmutableBox, LightListener {
|
public class LightVolume implements ImmutableBox, LightListener {
|
||||||
|
|
||||||
|
protected final BlockAndTintGetter level;
|
||||||
protected final GridAlignedBB box = new GridAlignedBB();
|
protected final GridAlignedBB box = new GridAlignedBB();
|
||||||
protected ByteBuffer lightData;
|
protected ByteBuffer lightData;
|
||||||
|
|
||||||
public LightVolume(ImmutableBox sampleVolume) {
|
public LightVolume(BlockAndTintGetter level, ImmutableBox sampleVolume) {
|
||||||
|
this.level = level;
|
||||||
this.setBox(sampleVolume);
|
this.setBox(sampleVolume);
|
||||||
|
|
||||||
this.lightData = MemoryUtil.memAlloc(this.box.volume() * 2);
|
this.lightData = MemoryUtil.memAlloc(this.box.volume() * 2);
|
||||||
|
@ -57,7 +60,7 @@ public class LightVolume implements ImmutableBox, LightListener {
|
||||||
return box.getMaxZ();
|
return box.getMaxZ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void move(LightProvider world, ImmutableBox newSampleVolume) {
|
public void move(BlockAndTintGetter level, ImmutableBox newSampleVolume) {
|
||||||
if (lightData == null) return;
|
if (lightData == null) return;
|
||||||
|
|
||||||
setBox(newSampleVolume);
|
setBox(newSampleVolume);
|
||||||
|
@ -65,51 +68,43 @@ public class LightVolume implements ImmutableBox, LightListener {
|
||||||
if (neededCapacity > lightData.capacity()) {
|
if (neededCapacity > lightData.capacity()) {
|
||||||
lightData = MemoryUtil.memRealloc(lightData, neededCapacity);
|
lightData = MemoryUtil.memRealloc(lightData, neededCapacity);
|
||||||
}
|
}
|
||||||
initialize(world);
|
initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLightUpdate(LightProvider world, LightLayer type, ImmutableBox changedVolume) {
|
public void onLightUpdate(LightLayer type, ImmutableBox changedVolume) {
|
||||||
if (lightData == null) return;
|
if (lightData == null) return;
|
||||||
|
|
||||||
GridAlignedBB vol = changedVolume.copy();
|
GridAlignedBB vol = changedVolume.copy();
|
||||||
if (!vol.intersects(getVolume())) return;
|
if (!vol.intersects(getVolume())) return;
|
||||||
vol.intersectAssign(getVolume()); // compute the region contained by us that has dirty lighting data.
|
vol.intersectAssign(getVolume()); // compute the region contained by us that has dirty lighting data.
|
||||||
|
|
||||||
if (type == LightLayer.BLOCK) copyBlock(world, vol);
|
if (type == LightLayer.BLOCK) copyBlock(vol);
|
||||||
else if (type == LightLayer.SKY) copySky(world, vol);
|
else if (type == LightLayer.SKY) copySky(vol);
|
||||||
|
markDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLightPacket(LightProvider world, int chunkX, int chunkZ) {
|
public void onLightPacket(int chunkX, int chunkZ) {
|
||||||
if (lightData == null) return;
|
if (lightData == null) return;
|
||||||
|
|
||||||
GridAlignedBB changedVolume = GridAlignedBB.from(chunkX, chunkZ);
|
GridAlignedBB changedVolume = GridAlignedBB.from(chunkX, chunkZ);
|
||||||
if (!changedVolume.intersects(getVolume())) return;
|
if (!changedVolume.intersects(getVolume())) return;
|
||||||
changedVolume.intersectAssign(getVolume()); // compute the region contained by us that has dirty lighting data.
|
changedVolume.intersectAssign(getVolume()); // compute the region contained by us that has dirty lighting data.
|
||||||
|
|
||||||
copyLight(world, changedVolume);
|
copyLight(changedVolume);
|
||||||
|
markDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Completely (re)populate this volume with block and sky lighting data.
|
* Completely (re)populate this volume with block and sky lighting data.
|
||||||
* This is expensive and should be avoided.
|
* This is expensive and should be avoided.
|
||||||
*/
|
*/
|
||||||
public void initialize(LightProvider world) {
|
public void initialize() {
|
||||||
if (lightData == null) return;
|
if (lightData == null) return;
|
||||||
|
|
||||||
// the volume is indexed based on the greater bounding box
|
copyLight(getVolume());
|
||||||
int shiftX = box.getMinX();
|
markDirty();
|
||||||
int shiftY = box.getMinY();
|
|
||||||
int shiftZ = box.getMinZ();
|
|
||||||
|
|
||||||
// ... but we only iterate over the (potentially) smaller sample volume
|
|
||||||
getVolume().forEachContained((x, y, z) -> {
|
|
||||||
int blockLight = world.getLight(LightLayer.BLOCK, x, y, z);
|
|
||||||
int skyLight = world.getLight(LightLayer.SKY, x, y, z);
|
|
||||||
|
|
||||||
writeLight(x - shiftX, y - shiftY, z - shiftZ, blockLight, skyLight);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -117,13 +112,15 @@ public class LightVolume implements ImmutableBox, LightListener {
|
||||||
*
|
*
|
||||||
* @param worldVolume the region in the world to copy data from.
|
* @param worldVolume the region in the world to copy data from.
|
||||||
*/
|
*/
|
||||||
public void copyBlock(LightProvider world, ImmutableBox worldVolume) {
|
public void copyBlock(ImmutableBox worldVolume) {
|
||||||
|
var pos = new BlockPos.MutableBlockPos();
|
||||||
|
|
||||||
int xShift = box.getMinX();
|
int xShift = box.getMinX();
|
||||||
int yShift = box.getMinY();
|
int yShift = box.getMinY();
|
||||||
int zShift = box.getMinZ();
|
int zShift = box.getMinZ();
|
||||||
|
|
||||||
worldVolume.forEachContained((x, y, z) -> {
|
worldVolume.forEachContained((x, y, z) -> {
|
||||||
int light = world.getLight(LightLayer.BLOCK, x, y, z);
|
int light = this.level.getBrightness(LightLayer.BLOCK, pos.set(x, y, z));
|
||||||
|
|
||||||
writeBlock(x - xShift, y - yShift, z - zShift, light);
|
writeBlock(x - xShift, y - yShift, z - zShift, light);
|
||||||
});
|
});
|
||||||
|
@ -134,13 +131,15 @@ public class LightVolume implements ImmutableBox, LightListener {
|
||||||
*
|
*
|
||||||
* @param worldVolume the region in the world to copy data from.
|
* @param worldVolume the region in the world to copy data from.
|
||||||
*/
|
*/
|
||||||
public void copySky(LightProvider world, ImmutableBox worldVolume) {
|
public void copySky(ImmutableBox worldVolume) {
|
||||||
|
var pos = new BlockPos.MutableBlockPos();
|
||||||
|
|
||||||
int xShift = box.getMinX();
|
int xShift = box.getMinX();
|
||||||
int yShift = box.getMinY();
|
int yShift = box.getMinY();
|
||||||
int zShift = box.getMinZ();
|
int zShift = box.getMinZ();
|
||||||
|
|
||||||
worldVolume.forEachContained((x, y, z) -> {
|
worldVolume.forEachContained((x, y, z) -> {
|
||||||
int light = world.getLight(LightLayer.SKY, x, y, z);
|
int light = this.level.getBrightness(LightLayer.SKY, pos.set(x, y, z));
|
||||||
|
|
||||||
writeSky(x - xShift, y - yShift, z - zShift, light);
|
writeSky(x - xShift, y - yShift, z - zShift, light);
|
||||||
});
|
});
|
||||||
|
@ -151,7 +150,7 @@ public class LightVolume implements ImmutableBox, LightListener {
|
||||||
*
|
*
|
||||||
* @param worldVolume the region in the world to copy data from.
|
* @param worldVolume the region in the world to copy data from.
|
||||||
*/
|
*/
|
||||||
public void copyLight(LightProvider world, ImmutableBox worldVolume) {
|
public void copyLight(ImmutableBox worldVolume) {
|
||||||
BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos();
|
BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos();
|
||||||
|
|
||||||
int xShift = box.getMinX();
|
int xShift = box.getMinX();
|
||||||
|
@ -161,8 +160,8 @@ public class LightVolume implements ImmutableBox, LightListener {
|
||||||
worldVolume.forEachContained((x, y, z) -> {
|
worldVolume.forEachContained((x, y, z) -> {
|
||||||
pos.set(x, y, z);
|
pos.set(x, y, z);
|
||||||
|
|
||||||
int block = world.getLight(LightLayer.BLOCK, x, y, z);
|
int block = this.level.getBrightness(LightLayer.BLOCK, pos);
|
||||||
int sky = world.getLight(LightLayer.SKY, x, y, z);
|
int sky = this.level.getBrightness(LightLayer.SKY, pos);
|
||||||
|
|
||||||
writeLight(x - xShift, y - yShift, z - zShift, block, sky);
|
writeLight(x - xShift, y - yShift, z - zShift, block, sky);
|
||||||
});
|
});
|
||||||
|
@ -173,6 +172,10 @@ public class LightVolume implements ImmutableBox, LightListener {
|
||||||
lightData = null;
|
lightData = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void markDirty() {
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
|
||||||
protected void writeLight(int x, int y, int z, int block, int sky) {
|
protected void writeLight(int x, int y, int z, int block, int sky) {
|
||||||
byte b = (byte) ((block & 0xF) << 4);
|
byte b = (byte) ((block & 0xF) << 4);
|
||||||
byte s = (byte) ((sky & 0xF) << 4);
|
byte s = (byte) ((sky & 0xF) << 4);
|
||||||
|
@ -211,8 +214,8 @@ public class LightVolume implements ImmutableBox, LightListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ListenerStatus status() {
|
public boolean isListenerInvalid() {
|
||||||
return ListenerStatus.OKAY;
|
return lightData == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
package com.jozufozu.flywheel.light;
|
|
||||||
|
|
||||||
public enum ListenerStatus {
|
|
||||||
OKAY,
|
|
||||||
REMOVE,
|
|
||||||
UPDATE,
|
|
||||||
;
|
|
||||||
|
|
||||||
public boolean isOk() {
|
|
||||||
return this == OKAY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean shouldRemove() {
|
|
||||||
return this == REMOVE;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
package com.jozufozu.flywheel.light;
|
|
||||||
|
|
||||||
public interface MovingListener extends LightListener {
|
|
||||||
boolean update(LightProvider provider);
|
|
||||||
}
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
package com.jozufozu.flywheel.light;
|
||||||
|
|
||||||
|
public interface TickingLightListener extends LightListener {
|
||||||
|
/**
|
||||||
|
* Called every tick for active listeners.
|
||||||
|
* @return {@code true} if the listener changed.
|
||||||
|
*/
|
||||||
|
boolean tickLightListener();
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
|
||||||
|
@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault
|
||||||
|
package com.jozufozu.flywheel.light;
|
||||||
|
|
||||||
|
import javax.annotation.ParametersAreNonnullByDefault;
|
||||||
|
|
||||||
|
import net.minecraft.MethodsReturnNonnullByDefault;
|
Loading…
Reference in a new issue