171 lines
6.3 KiB
Java
171 lines
6.3 KiB
Java
package net.minecraft.world.level.lighting;
|
|
|
|
import it.unimi.dsi.fastutil.longs.Long2ByteMap;
|
|
import it.unimi.dsi.fastutil.longs.Long2ByteOpenHashMap;
|
|
import it.unimi.dsi.fastutil.longs.LongArrayList;
|
|
import it.unimi.dsi.fastutil.longs.LongList;
|
|
import java.util.function.LongPredicate;
|
|
import net.minecraft.util.Mth;
|
|
|
|
public abstract class DynamicGraphMinFixedPoint {
|
|
public static final long SOURCE = Long.MAX_VALUE;
|
|
private static final int NO_COMPUTED_LEVEL = 255;
|
|
protected final int levelCount;
|
|
private final LeveledPriorityQueue priorityQueue;
|
|
private final Long2ByteMap computedLevels;
|
|
private volatile boolean hasWork;
|
|
|
|
protected DynamicGraphMinFixedPoint(int p_75543_, int p_75544_, final int p_75545_) {
|
|
if (p_75543_ >= 254) {
|
|
throw new IllegalArgumentException("Level count must be < 254.");
|
|
} else {
|
|
this.levelCount = p_75543_;
|
|
this.priorityQueue = new LeveledPriorityQueue(p_75543_, p_75544_);
|
|
this.computedLevels = new Long2ByteOpenHashMap(p_75545_, 0.5F) {
|
|
@Override
|
|
protected void rehash(int p_75611_) {
|
|
if (p_75611_ > p_75545_) {
|
|
super.rehash(p_75611_);
|
|
}
|
|
}
|
|
};
|
|
this.computedLevels.defaultReturnValue((byte)-1);
|
|
}
|
|
}
|
|
|
|
protected void removeFromQueue(long p_75601_) {
|
|
int i = this.computedLevels.remove(p_75601_) & 255;
|
|
if (i != 255) {
|
|
int j = this.getLevel(p_75601_);
|
|
int k = this.calculatePriority(j, i);
|
|
this.priorityQueue.dequeue(p_75601_, k, this.levelCount);
|
|
this.hasWork = !this.priorityQueue.isEmpty();
|
|
}
|
|
}
|
|
|
|
public void removeIf(LongPredicate p_75582_) {
|
|
LongList longlist = new LongArrayList();
|
|
this.computedLevels.keySet().forEach((long p_75586_) -> {
|
|
if (p_75582_.test(p_75586_)) {
|
|
longlist.add(p_75586_);
|
|
}
|
|
});
|
|
longlist.forEach((java.util.function.LongConsumer)this::removeFromQueue);
|
|
}
|
|
|
|
private int calculatePriority(int p_278256_, int p_278328_) {
|
|
return Math.min(Math.min(p_278256_, p_278328_), this.levelCount - 1);
|
|
}
|
|
|
|
protected void checkNode(long p_75602_) {
|
|
this.checkEdge(p_75602_, p_75602_, this.levelCount - 1, false);
|
|
}
|
|
|
|
protected void checkEdge(long p_75577_, long p_75578_, int p_75579_, boolean p_75580_) {
|
|
this.checkEdge(p_75577_, p_75578_, p_75579_, this.getLevel(p_75578_), this.computedLevels.get(p_75578_) & 255, p_75580_);
|
|
this.hasWork = !this.priorityQueue.isEmpty();
|
|
}
|
|
|
|
private void checkEdge(long p_75570_, long p_75571_, int p_75572_, int p_75573_, int p_75574_, boolean p_75575_) {
|
|
if (!this.isSource(p_75571_)) {
|
|
p_75572_ = Mth.clamp(p_75572_, 0, this.levelCount - 1);
|
|
p_75573_ = Mth.clamp(p_75573_, 0, this.levelCount - 1);
|
|
boolean flag = p_75574_ == 255;
|
|
if (flag) {
|
|
p_75574_ = p_75573_;
|
|
}
|
|
|
|
int i;
|
|
if (p_75575_) {
|
|
i = Math.min(p_75574_, p_75572_);
|
|
} else {
|
|
i = Mth.clamp(this.getComputedLevel(p_75571_, p_75570_, p_75572_), 0, this.levelCount - 1);
|
|
}
|
|
|
|
int j = this.calculatePriority(p_75573_, p_75574_);
|
|
if (p_75573_ != i) {
|
|
int k = this.calculatePriority(p_75573_, i);
|
|
if (j != k && !flag) {
|
|
this.priorityQueue.dequeue(p_75571_, j, k);
|
|
}
|
|
|
|
this.priorityQueue.enqueue(p_75571_, k);
|
|
this.computedLevels.put(p_75571_, (byte)i);
|
|
} else if (!flag) {
|
|
this.priorityQueue.dequeue(p_75571_, j, this.levelCount);
|
|
this.computedLevels.remove(p_75571_);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected final void checkNeighbor(long p_75594_, long p_75595_, int p_75596_, boolean p_75597_) {
|
|
int i = this.computedLevels.get(p_75595_) & 255;
|
|
int j = Mth.clamp(this.computeLevelFromNeighbor(p_75594_, p_75595_, p_75596_), 0, this.levelCount - 1);
|
|
if (p_75597_) {
|
|
this.checkEdge(p_75594_, p_75595_, j, this.getLevel(p_75595_), i, p_75597_);
|
|
} else {
|
|
boolean flag = i == 255;
|
|
int k;
|
|
if (flag) {
|
|
k = Mth.clamp(this.getLevel(p_75595_), 0, this.levelCount - 1);
|
|
} else {
|
|
k = i;
|
|
}
|
|
|
|
if (j == k) {
|
|
this.checkEdge(p_75594_, p_75595_, this.levelCount - 1, flag ? k : this.getLevel(p_75595_), i, p_75597_);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected final boolean hasWork() {
|
|
return this.hasWork;
|
|
}
|
|
|
|
protected final int runUpdates(int p_75589_) {
|
|
if (this.priorityQueue.isEmpty()) {
|
|
return p_75589_;
|
|
} else {
|
|
while (!this.priorityQueue.isEmpty() && p_75589_ > 0) {
|
|
p_75589_--;
|
|
long i = this.priorityQueue.removeFirstLong();
|
|
int j = Mth.clamp(this.getLevel(i), 0, this.levelCount - 1);
|
|
int k = this.computedLevels.remove(i) & 255;
|
|
if (k < j) {
|
|
this.setLevel(i, k);
|
|
this.checkNeighborsAfterUpdate(i, k, true);
|
|
} else if (k > j) {
|
|
this.setLevel(i, this.levelCount - 1);
|
|
if (k != this.levelCount - 1) {
|
|
this.priorityQueue.enqueue(i, this.calculatePriority(this.levelCount - 1, k));
|
|
this.computedLevels.put(i, (byte)k);
|
|
}
|
|
|
|
this.checkNeighborsAfterUpdate(i, j, false);
|
|
}
|
|
}
|
|
|
|
this.hasWork = !this.priorityQueue.isEmpty();
|
|
return p_75589_;
|
|
}
|
|
}
|
|
|
|
public int getQueueSize() {
|
|
return this.computedLevels.size();
|
|
}
|
|
|
|
protected boolean isSource(long p_75551_) {
|
|
return p_75551_ == Long.MAX_VALUE;
|
|
}
|
|
|
|
protected abstract int getComputedLevel(long p_75566_, long p_75567_, int p_75568_);
|
|
|
|
protected abstract void checkNeighborsAfterUpdate(long p_75563_, int p_75564_, boolean p_75565_);
|
|
|
|
protected abstract int getLevel(long p_75599_);
|
|
|
|
protected abstract void setLevel(long p_75552_, int p_75553_);
|
|
|
|
protected abstract int computeLevelFromNeighbor(long p_75590_, long p_75591_, int p_75592_);
|
|
}
|