soiz1's picture
Upload folder using huggingface_hub
d46f4a3 verified
package net.minecraft.world.ticks;
import it.unimi.dsi.fastutil.longs.Long2LongMap;
import it.unimi.dsi.fastutil.longs.Long2LongMaps;
import it.unimi.dsi.fastutil.longs.Long2LongOpenHashMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.longs.Long2LongMap.Entry;
import it.unimi.dsi.fastutil.objects.ObjectIterator;
import it.unimi.dsi.fastutil.objects.ObjectOpenCustomHashSet;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.LongSummaryStatistics;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.LongPredicate;
import java.util.function.Predicate;
import net.minecraft.Util;
import net.minecraft.core.BlockPos;
import net.minecraft.core.SectionPos;
import net.minecraft.core.Vec3i;
import net.minecraft.util.profiling.Profiler;
import net.minecraft.util.profiling.ProfilerFiller;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.levelgen.structure.BoundingBox;
public class LevelTicks<T> implements LevelTickAccess<T> {
private static final Comparator<LevelChunkTicks<?>> CONTAINER_DRAIN_ORDER = (p_193246_, p_193247_) -> ScheduledTick.INTRA_TICK_DRAIN_ORDER
.compare(p_193246_.peek(), p_193247_.peek());
private final LongPredicate tickCheck;
private final Long2ObjectMap<LevelChunkTicks<T>> allContainers = new Long2ObjectOpenHashMap<>();
private final Long2LongMap nextTickForContainer = Util.make(new Long2LongOpenHashMap(), p_193262_ -> p_193262_.defaultReturnValue(Long.MAX_VALUE));
private final Queue<LevelChunkTicks<T>> containersToTick = new PriorityQueue<>(CONTAINER_DRAIN_ORDER);
private final Queue<ScheduledTick<T>> toRunThisTick = new ArrayDeque<>();
private final List<ScheduledTick<T>> alreadyRunThisTick = new ArrayList<>();
private final Set<ScheduledTick<?>> toRunThisTickSet = new ObjectOpenCustomHashSet<>(ScheduledTick.UNIQUE_TICK_HASH);
private final BiConsumer<LevelChunkTicks<T>, ScheduledTick<T>> chunkScheduleUpdater = (p_193249_, p_193250_) -> {
if (p_193250_.equals(p_193249_.peek())) {
this.updateContainerScheduling(p_193250_);
}
};
public LevelTicks(LongPredicate p_193211_) {
this.tickCheck = p_193211_;
}
public void addContainer(ChunkPos p_193232_, LevelChunkTicks<T> p_193233_) {
long i = p_193232_.toLong();
this.allContainers.put(i, p_193233_);
ScheduledTick<T> scheduledtick = p_193233_.peek();
if (scheduledtick != null) {
this.nextTickForContainer.put(i, scheduledtick.triggerTick());
}
p_193233_.setOnTickAdded(this.chunkScheduleUpdater);
}
public void removeContainer(ChunkPos p_193230_) {
long i = p_193230_.toLong();
LevelChunkTicks<T> levelchunkticks = this.allContainers.remove(i);
this.nextTickForContainer.remove(i);
if (levelchunkticks != null) {
levelchunkticks.setOnTickAdded(null);
}
}
@Override
public void schedule(ScheduledTick<T> p_193252_) {
long i = ChunkPos.asLong(p_193252_.pos());
LevelChunkTicks<T> levelchunkticks = this.allContainers.get(i);
if (levelchunkticks == null) {
Util.logAndPauseIfInIde("Trying to schedule tick in not loaded position " + p_193252_.pos());
} else {
levelchunkticks.schedule(p_193252_);
}
}
public void tick(long p_193226_, int p_193227_, BiConsumer<BlockPos, T> p_193228_) {
ProfilerFiller profilerfiller = Profiler.get();
profilerfiller.push("collect");
this.collectTicks(p_193226_, p_193227_, profilerfiller);
profilerfiller.popPush("run");
profilerfiller.incrementCounter("ticksToRun", this.toRunThisTick.size());
this.runCollectedTicks(p_193228_);
profilerfiller.popPush("cleanup");
this.cleanupAfterTick();
profilerfiller.pop();
}
private void collectTicks(long p_193222_, int p_193223_, ProfilerFiller p_193224_) {
this.sortContainersToTick(p_193222_);
p_193224_.incrementCounter("containersToTick", this.containersToTick.size());
this.drainContainers(p_193222_, p_193223_);
this.rescheduleLeftoverContainers();
}
private void sortContainersToTick(long p_193217_) {
ObjectIterator<Entry> objectiterator = Long2LongMaps.fastIterator(this.nextTickForContainer);
while (objectiterator.hasNext()) {
Entry entry = objectiterator.next();
long i = entry.getLongKey();
long j = entry.getLongValue();
if (j <= p_193217_) {
LevelChunkTicks<T> levelchunkticks = this.allContainers.get(i);
if (levelchunkticks == null) {
objectiterator.remove();
} else {
ScheduledTick<T> scheduledtick = levelchunkticks.peek();
if (scheduledtick == null) {
objectiterator.remove();
} else if (scheduledtick.triggerTick() > p_193217_) {
entry.setValue(scheduledtick.triggerTick());
} else if (this.tickCheck.test(i)) {
objectiterator.remove();
this.containersToTick.add(levelchunkticks);
}
}
}
}
}
private void drainContainers(long p_193219_, int p_193220_) {
LevelChunkTicks<T> levelchunkticks;
while (this.canScheduleMoreTicks(p_193220_) && (levelchunkticks = this.containersToTick.poll()) != null) {
ScheduledTick<T> scheduledtick = levelchunkticks.poll();
this.scheduleForThisTick(scheduledtick);
this.drainFromCurrentContainer(this.containersToTick, levelchunkticks, p_193219_, p_193220_);
ScheduledTick<T> scheduledtick1 = levelchunkticks.peek();
if (scheduledtick1 != null) {
if (scheduledtick1.triggerTick() <= p_193219_ && this.canScheduleMoreTicks(p_193220_)) {
this.containersToTick.add(levelchunkticks);
} else {
this.updateContainerScheduling(scheduledtick1);
}
}
}
}
private void rescheduleLeftoverContainers() {
for (LevelChunkTicks<T> levelchunkticks : this.containersToTick) {
this.updateContainerScheduling(levelchunkticks.peek());
}
}
private void updateContainerScheduling(ScheduledTick<T> p_193280_) {
this.nextTickForContainer.put(ChunkPos.asLong(p_193280_.pos()), p_193280_.triggerTick());
}
private void drainFromCurrentContainer(Queue<LevelChunkTicks<T>> p_193268_, LevelChunkTicks<T> p_193269_, long p_193270_, int p_193271_) {
if (this.canScheduleMoreTicks(p_193271_)) {
LevelChunkTicks<T> levelchunkticks = p_193268_.peek();
ScheduledTick<T> scheduledtick = levelchunkticks != null ? levelchunkticks.peek() : null;
while (this.canScheduleMoreTicks(p_193271_)) {
ScheduledTick<T> scheduledtick1 = p_193269_.peek();
if (scheduledtick1 == null
|| scheduledtick1.triggerTick() > p_193270_
|| scheduledtick != null && ScheduledTick.INTRA_TICK_DRAIN_ORDER.compare(scheduledtick1, scheduledtick) > 0) {
break;
}
p_193269_.poll();
this.scheduleForThisTick(scheduledtick1);
}
}
}
private void scheduleForThisTick(ScheduledTick<T> p_193286_) {
this.toRunThisTick.add(p_193286_);
}
private boolean canScheduleMoreTicks(int p_193215_) {
return this.toRunThisTick.size() < p_193215_;
}
private void runCollectedTicks(BiConsumer<BlockPos, T> p_193273_) {
while (!this.toRunThisTick.isEmpty()) {
ScheduledTick<T> scheduledtick = this.toRunThisTick.poll();
if (!this.toRunThisTickSet.isEmpty()) {
this.toRunThisTickSet.remove(scheduledtick);
}
this.alreadyRunThisTick.add(scheduledtick);
p_193273_.accept(scheduledtick.pos(), scheduledtick.type());
}
}
private void cleanupAfterTick() {
this.toRunThisTick.clear();
this.containersToTick.clear();
this.alreadyRunThisTick.clear();
this.toRunThisTickSet.clear();
}
@Override
public boolean hasScheduledTick(BlockPos p_193254_, T p_193255_) {
LevelChunkTicks<T> levelchunkticks = this.allContainers.get(ChunkPos.asLong(p_193254_));
return levelchunkticks != null && levelchunkticks.hasScheduledTick(p_193254_, p_193255_);
}
@Override
public boolean willTickThisTick(BlockPos p_193282_, T p_193283_) {
this.calculateTickSetIfNeeded();
return this.toRunThisTickSet.contains(ScheduledTick.probe(p_193283_, p_193282_));
}
private void calculateTickSetIfNeeded() {
if (this.toRunThisTickSet.isEmpty() && !this.toRunThisTick.isEmpty()) {
this.toRunThisTickSet.addAll(this.toRunThisTick);
}
}
private void forContainersInArea(BoundingBox p_193237_, LevelTicks.PosAndContainerConsumer<T> p_193238_) {
int i = SectionPos.posToSectionCoord((double)p_193237_.minX());
int j = SectionPos.posToSectionCoord((double)p_193237_.minZ());
int k = SectionPos.posToSectionCoord((double)p_193237_.maxX());
int l = SectionPos.posToSectionCoord((double)p_193237_.maxZ());
for (int i1 = i; i1 <= k; i1++) {
for (int j1 = j; j1 <= l; j1++) {
long k1 = ChunkPos.asLong(i1, j1);
LevelChunkTicks<T> levelchunkticks = this.allContainers.get(k1);
if (levelchunkticks != null) {
p_193238_.accept(k1, levelchunkticks);
}
}
}
}
public void clearArea(BoundingBox p_193235_) {
Predicate<ScheduledTick<T>> predicate = p_193241_ -> p_193235_.isInside(p_193241_.pos());
this.forContainersInArea(p_193235_, (p_193276_, p_193277_) -> {
ScheduledTick<T> scheduledtick = p_193277_.peek();
p_193277_.removeIf(predicate);
ScheduledTick<T> scheduledtick1 = p_193277_.peek();
if (scheduledtick1 != scheduledtick) {
if (scheduledtick1 != null) {
this.updateContainerScheduling(scheduledtick1);
} else {
this.nextTickForContainer.remove(p_193276_);
}
}
});
this.alreadyRunThisTick.removeIf(predicate);
this.toRunThisTick.removeIf(predicate);
}
public void copyArea(BoundingBox p_193243_, Vec3i p_193244_) {
this.copyAreaFrom(this, p_193243_, p_193244_);
}
public void copyAreaFrom(LevelTicks<T> p_265554_, BoundingBox p_265172_, Vec3i p_265318_) {
List<ScheduledTick<T>> list = new ArrayList<>();
Predicate<ScheduledTick<T>> predicate = p_200922_ -> p_265172_.isInside(p_200922_.pos());
p_265554_.alreadyRunThisTick.stream().filter(predicate).forEach(list::add);
p_265554_.toRunThisTick.stream().filter(predicate).forEach(list::add);
p_265554_.forContainersInArea(p_265172_, (p_200931_, p_200932_) -> p_200932_.getAll().filter(predicate).forEach(list::add));
LongSummaryStatistics longsummarystatistics = list.stream().mapToLong(ScheduledTick::subTickOrder).summaryStatistics();
long i = longsummarystatistics.getMin();
long j = longsummarystatistics.getMax();
list.forEach(
p_193260_ -> this.schedule(
new ScheduledTick<>(
p_193260_.type(),
p_193260_.pos().offset(p_265318_),
p_193260_.triggerTick(),
p_193260_.priority(),
p_193260_.subTickOrder() - i + j + 1L
)
)
);
}
@Override
public int count() {
return this.allContainers.values().stream().mapToInt(TickAccess::count).sum();
}
@FunctionalInterface
interface PosAndContainerConsumer<T> {
void accept(long p_193289_, LevelChunkTicks<T> p_193290_);
}
}