Code/net/minecraft/world/level/lighting/DynamicGraphMinFixedPoint.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_);
}