mirror of
https://github.com/Winds-Studio/Leaf.git
synced 2025-12-25 18:09:17 +00:00
backport from dev/1.21.6
73ffcb09faoptimize mob spawning333373d204fix async mob spawning data race7c9f88e4f8[ci skip] cleanupbf9486f0f0remove hash lookup in optimize random tick915ac01cd3cleanupb90c1cd527fix playermobcaps commandfd34d9f626cleanup5d663b4d36optimize collectSpawningChunks (#382)
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
package org.dreeam.leaf.world;
|
||||
|
||||
import ca.spottedleaf.moonrise.common.list.ReferenceList;
|
||||
import com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent;
|
||||
import it.unimi.dsi.fastutil.longs.Long2LongOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.longs.LongArrayList;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class NatureSpawnChunkMap {
|
||||
/// breadth-first search
|
||||
///
|
||||
/// 0 4 12 28 48 80 112 148 196
|
||||
private static final long[][] TABLE_BFS = new long[][]{
|
||||
{0L},
|
||||
{0L, 4294967295L, -4294967296L, 4294967296L, 1L},
|
||||
{0L, -1L, 4294967295L, 8589934591L, -4294967296L, 4294967296L, -4294967295L, 1L, 4294967297L, 4294967294L, -8589934592L, 8589934592L, 2L},
|
||||
{0L, -1L, 4294967295L, 8589934591L, -4294967296L, 4294967296L, -4294967295L, 1L, 4294967297L, -4294967298L, -2L, 4294967294L, -4294967297L, -8589934592L, 8589934590L, 12884901886L, 12884901887L, 8589934592L, -8589934591L, 8589934593L, -8589934590L, -4294967294L, 2L, 4294967298L, 8589934594L, 4294967293L, -12884901888L, 12884901888L, 3L},
|
||||
{0L, -1L, 4294967295L, 8589934591L, -4294967296L, 4294967296L, -4294967295L, 1L, 4294967297L, -4294967298L, -2L, 4294967294L, -4294967297L, -8589934592L, 8589934590L, 12884901886L, 12884901887L, 8589934592L, -8589934591L, 8589934593L, -8589934590L, -4294967294L, 2L, 4294967298L, 8589934594L, -4294967299L, -3L, -8589934594L, -8589934593L, 4294967293L, 8589934589L, -12884901888L, -12884901887L, 12884901885L, 17179869182L, 17179869183L, 12884901888L, 12884901889L, -12884901886L, 12884901890L, -8589934589L, -4294967293L, 3L, 4294967299L, 8589934595L, 4294967292L, -17179869184L, 17179869184L, 4L},
|
||||
{0L, -1L, 4294967295L, 8589934591L, -4294967296L, 4294967296L, -4294967295L, 1L, 4294967297L, -4294967298L, -2L, 4294967294L, -4294967297L, -8589934592L, 8589934590L, 12884901886L, 12884901887L, 8589934592L, -8589934591L, 8589934593L, -8589934590L, -4294967294L, 2L, 4294967298L, 8589934594L, -8589934595L, -4294967299L, -3L, -8589934594L, -8589934593L, 4294967293L, 8589934589L, -12884901888L, -12884901887L, 12884901885L, 17179869181L, 17179869182L, 17179869183L, 12884901888L, 12884901889L, -12884901886L, 12884901890L, -12884901885L, -8589934589L, -4294967293L, 3L, 4294967299L, 8589934595L, 12884901891L, -8589934596L, -4294967300L, -12884901891L, -12884901890L, -4L, 4294967292L, -12884901889L, -17179869184L, 8589934588L, 12884901884L, -17179869183L, -17179869182L, 17179869180L, 21474836477L, 21474836478L, 21474836479L, 17179869184L, 17179869185L, 17179869186L, -17179869181L, 17179869187L, -12884901884L, -8589934588L, -4294967292L, 4L, 4294967300L, 8589934596L, 12884901892L, 4294967291L, -21474836480L, 21474836480L, 5L},
|
||||
{0L, -1L, 4294967295L, 8589934591L, -4294967296L, 4294967296L, -4294967295L, 1L, 4294967297L, -4294967298L, -2L, 4294967294L, -4294967297L, -8589934592L, 8589934590L, 12884901886L, 12884901887L, 8589934592L, -8589934591L, 8589934593L, -8589934590L, -4294967294L, 2L, 4294967298L, 8589934594L, -8589934595L, -4294967299L, -3L, -8589934594L, -8589934593L, 4294967293L, 8589934589L, -12884901888L, -12884901887L, 12884901885L, 17179869181L, 17179869182L, 17179869183L, 12884901888L, 12884901889L, -12884901886L, 12884901890L, -12884901885L, -8589934589L, -4294967293L, 3L, 4294967299L, 8589934595L, 12884901891L, -12884901892L, -8589934596L, -4294967300L, -12884901891L, -12884901890L, -4L, 4294967292L, -12884901889L, -17179869184L, 8589934588L, 12884901884L, -17179869183L, -17179869182L, 17179869180L, 21474836476L, 21474836477L, 21474836478L, 21474836479L, 17179869184L, 17179869185L, 17179869186L, -17179869181L, 17179869187L, -17179869180L, -12884901884L, -8589934588L, -4294967292L, 4L, 4294967300L, 8589934596L, 12884901892L, 17179869188L, -8589934597L, -17179869187L, -4294967301L, -5L, -17179869186L, -17179869185L, 4294967291L, 8589934587L, -21474836480L, -21474836479L, 12884901883L, 17179869179L, -21474836478L, -21474836477L, 25769803773L, 25769803774L, 25769803775L, 21474836480L, 21474836481L, 21474836482L, 21474836483L, -12884901883L, -8589934587L, -4294967291L, 5L, 4294967301L, 8589934597L, 12884901893L, 4294967290L, -25769803776L, 25769803776L, 6L},
|
||||
{0L, -1L, 4294967295L, 8589934591L, -4294967296L, 4294967296L, -4294967295L, 1L, 4294967297L, -4294967298L, -2L, 4294967294L, -4294967297L, -8589934592L, 8589934590L, 12884901886L, 12884901887L, 8589934592L, -8589934591L, 8589934593L, -8589934590L, -4294967294L, 2L, 4294967298L, 8589934594L, -8589934595L, -4294967299L, -3L, -8589934594L, -8589934593L, 4294967293L, 8589934589L, -12884901888L, -12884901887L, 12884901885L, 17179869181L, 17179869182L, 17179869183L, 12884901888L, 12884901889L, -12884901886L, 12884901890L, -12884901885L, -8589934589L, -4294967293L, 3L, 4294967299L, 8589934595L, 12884901891L, -12884901892L, -8589934596L, -4294967300L, -12884901891L, -12884901890L, -4L, 4294967292L, -12884901889L, -17179869184L, 8589934588L, 12884901884L, -17179869183L, -17179869182L, 17179869180L, 21474836476L, 21474836477L, 21474836478L, 21474836479L, 17179869184L, 17179869185L, 17179869186L, -17179869181L, 17179869187L, -17179869180L, -12884901884L, -8589934588L, -4294967292L, 4L, 4294967300L, 8589934596L, 12884901892L, 17179869188L, -12884901893L, -8589934597L, -17179869188L, -17179869187L, -4294967301L, -5L, -17179869186L, -17179869185L, 4294967291L, 8589934587L, -21474836480L, -21474836479L, 12884901883L, 17179869179L, -21474836478L, -21474836477L, 21474836475L, 25769803772L, 25769803773L, 25769803774L, 25769803775L, 21474836480L, 21474836481L, 21474836482L, 21474836483L, -21474836476L, 21474836484L, -17179869179L, -12884901883L, -8589934587L, -4294967291L, 5L, 4294967301L, 8589934597L, 12884901893L, 17179869189L, -8589934598L, -4294967302L, -21474836483L, -21474836482L, -6L, 4294967290L, -21474836481L, -25769803776L, 8589934586L, 12884901882L, -25769803775L, -25769803774L, 17179869178L, -25769803773L, 30064771069L, 30064771070L, 30064771071L, 25769803776L, 25769803777L, 25769803778L, 25769803779L, -12884901882L, -8589934586L, -4294967290L, 6L, 4294967302L, 8589934598L, 12884901894L, 4294967289L, -30064771072L, 30064771072L, 7L},
|
||||
{0L, -1L, 4294967295L, 8589934591L, -4294967296L, 4294967296L, -4294967295L, 1L, 4294967297L, -4294967298L, -2L, 4294967294L, -4294967297L, -8589934592L, 8589934590L, 12884901886L, 12884901887L, 8589934592L, -8589934591L, 8589934593L, -8589934590L, -4294967294L, 2L, 4294967298L, 8589934594L, -8589934595L, -4294967299L, -3L, -8589934594L, -8589934593L, 4294967293L, 8589934589L, -12884901888L, -12884901887L, 12884901885L, 17179869181L, 17179869182L, 17179869183L, 12884901888L, 12884901889L, -12884901886L, 12884901890L, -12884901885L, -8589934589L, -4294967293L, 3L, 4294967299L, 8589934595L, 12884901891L, -12884901892L, -8589934596L, -4294967300L, -12884901891L, -12884901890L, -4L, 4294967292L, -12884901889L, -17179869184L, 8589934588L, 12884901884L, -17179869183L, -17179869182L, 17179869180L, 21474836476L, 21474836477L, 21474836478L, 21474836479L, 17179869184L, 17179869185L, 17179869186L, -17179869181L, 17179869187L, -17179869180L, -12884901884L, -8589934588L, -4294967292L, 4L, 4294967300L, 8589934596L, 12884901892L, 17179869188L, -17179869189L, -12884901893L, -8589934597L, -17179869188L, -17179869187L, -4294967301L, -5L, -17179869186L, -17179869185L, 4294967291L, 8589934587L, -21474836480L, -21474836479L, 12884901883L, 17179869179L, -21474836478L, -21474836477L, 21474836475L, 25769803771L, 25769803772L, 25769803773L, 25769803774L, 25769803775L, 21474836480L, 21474836481L, 21474836482L, 21474836483L, -21474836476L, 21474836484L, -21474836475L, -17179869179L, -12884901883L, -8589934587L, -4294967291L, 5L, 4294967301L, 8589934597L, 12884901893L, 17179869189L, 21474836485L, -17179869190L, -12884901894L, -21474836485L, -21474836484L, -8589934598L, -4294967302L, -21474836483L, -21474836482L, -6L, 4294967290L, -21474836481L, -25769803776L, 8589934586L, 12884901882L, -25769803775L, -25769803774L, 17179869178L, 21474836474L, -25769803773L, -25769803772L, 25769803770L, 30064771067L, 30064771068L, 30064771069L, 30064771070L, 30064771071L, 25769803776L, 25769803777L, 25769803778L, 25769803779L, 25769803780L, -25769803771L, 25769803781L, -21474836474L, -17179869178L, -12884901882L, -8589934586L, -4294967290L, 6L, 4294967302L, 8589934598L, 12884901894L, 17179869190L, 21474836486L, -8589934599L, -25769803779L, -4294967303L, -7L, -25769803778L, -25769803777L, 4294967289L, 8589934585L, -30064771072L, -30064771071L, 12884901881L, 17179869177L, -30064771070L, -30064771069L, 34359738365L, 34359738366L, 34359738367L, 30064771072L, 30064771073L, 30064771074L, 30064771075L, -12884901881L, -8589934585L, -4294967289L, 7L, 4294967303L, 8589934599L, 12884901895L, 4294967288L, -34359738368L, 34359738368L, 8L}
|
||||
};
|
||||
private static final int MAX_RADIUS = 8;
|
||||
private static final int SIZE_RADIUS = 9;
|
||||
private static final int REGION_MASK = 15;
|
||||
private static final int REGION_SHIFT = 4;
|
||||
|
||||
private final LongArrayList[] centersByRadius;
|
||||
private final Long2LongOpenHashMap regionBitSets;
|
||||
|
||||
public NatureSpawnChunkMap() {
|
||||
this.centersByRadius = new LongArrayList[SIZE_RADIUS];
|
||||
for (int i = 0; i < SIZE_RADIUS; i++) {
|
||||
this.centersByRadius[i] = new LongArrayList();
|
||||
}
|
||||
this.regionBitSets = new Long2LongOpenHashMap();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
for (LongArrayList chunkPosition : this.centersByRadius) {
|
||||
chunkPosition.clear();
|
||||
}
|
||||
this.regionBitSets.clear();
|
||||
}
|
||||
|
||||
public void addPlayer(ServerPlayer player) {
|
||||
if (player.isSpectator()) {
|
||||
return;
|
||||
}
|
||||
PlayerNaturallySpawnCreaturesEvent event = player.playerNaturallySpawnedEvent;
|
||||
if (event == null || event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
int range = event.getSpawnRadius();
|
||||
if (range > MAX_RADIUS) {
|
||||
range = MAX_RADIUS;
|
||||
} else if (range < 0) {
|
||||
return;
|
||||
}
|
||||
this.centersByRadius[range].add(player.chunkPosition().longKey);
|
||||
}
|
||||
|
||||
public void build() {
|
||||
for (int index = 0; index < SIZE_RADIUS; index++) {
|
||||
buildBy(index);
|
||||
}
|
||||
}
|
||||
|
||||
private void buildBy(int index) {
|
||||
LongArrayList list = this.centersByRadius[index];
|
||||
int centersSize = deduplicate(list);
|
||||
if (centersSize == 0) {
|
||||
return;
|
||||
}
|
||||
long[] centersRaw = list.elements();
|
||||
long cachedKey = ChunkPos.asLong(ChunkPos.getX(centersRaw[0]) >> REGION_SHIFT, ChunkPos.getZ(centersRaw[0]) >> REGION_SHIFT);
|
||||
long cachedVal = this.regionBitSets.get(cachedKey);
|
||||
long[] offsets = TABLE_BFS[index];
|
||||
for (int i = 0; i < centersSize; i++) {
|
||||
long center = centersRaw[i];
|
||||
int cx = ChunkPos.getX(center);
|
||||
int cz = ChunkPos.getZ(center);
|
||||
|
||||
for (long packedOffset : offsets) {
|
||||
int dx = ChunkPos.getX(packedOffset);
|
||||
int dz = ChunkPos.getZ(packedOffset);
|
||||
int chunkX = cx + dx;
|
||||
int chunkZ = cz + dz;
|
||||
|
||||
int regionX = chunkX >> REGION_SHIFT;
|
||||
int regionZ = chunkZ >> REGION_SHIFT;
|
||||
long regionKey = ChunkPos.asLong(regionX, regionZ);
|
||||
|
||||
int localX = chunkX & REGION_MASK;
|
||||
int localZ = chunkZ & REGION_MASK;
|
||||
int bitIndex = (localZ << REGION_SHIFT) | localX;
|
||||
long bitMask = 1L << bitIndex;
|
||||
|
||||
if (regionKey != cachedKey) {
|
||||
this.regionBitSets.put(cachedKey, cachedVal);
|
||||
cachedKey = regionKey;
|
||||
cachedVal = this.regionBitSets.get(regionKey);
|
||||
}
|
||||
|
||||
cachedVal |= bitMask;
|
||||
}
|
||||
}
|
||||
|
||||
if (cachedVal != 0L) {
|
||||
this.regionBitSets.put(cachedKey, cachedVal);
|
||||
}
|
||||
}
|
||||
|
||||
private int deduplicate(LongArrayList list) {
|
||||
int n = list.size();
|
||||
if (n == 0) {
|
||||
return 0;
|
||||
}
|
||||
list.unstableSort(null);
|
||||
long[] centersRaw = list.elements();
|
||||
int size = 0;
|
||||
for (int i = 1; i < n; i++) {
|
||||
long current = centersRaw[i];
|
||||
long last = centersRaw[size];
|
||||
if (current != last) {
|
||||
size++;
|
||||
centersRaw[size] = current;
|
||||
}
|
||||
}
|
||||
return size + 1;
|
||||
}
|
||||
|
||||
public void collectSpawningChunks(ReferenceList<LevelChunk> chunks, List<LevelChunk> out) {
|
||||
LevelChunk[] raw = chunks.getRawDataUnchecked();
|
||||
for (int i = 0, length = chunks.size(); i < length; i++) {
|
||||
LevelChunk chunk = raw[i];
|
||||
if (contains(chunk.locX, chunk.locZ)) {
|
||||
out.add(chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean contains(int chunkX, int chunkZ) {
|
||||
int regionX = chunkX >> REGION_SHIFT;
|
||||
int regionZ = chunkZ >> REGION_SHIFT;
|
||||
long bitset = this.regionBitSets.get(ChunkPos.asLong(regionX, regionZ));
|
||||
return bitset != 0 && (bitset & (1L << (((chunkZ & REGION_MASK) << REGION_SHIFT) | (chunkX & REGION_MASK)))) != 0L;
|
||||
}
|
||||
}
|
||||
@@ -1,115 +1,162 @@
|
||||
package org.dreeam.leaf.world;
|
||||
|
||||
import ca.spottedleaf.moonrise.common.list.ReferenceList;
|
||||
import ca.spottedleaf.moonrise.common.list.ShortList;
|
||||
import it.unimi.dsi.fastutil.longs.LongArrayList;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.GameRules;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import net.minecraft.world.level.chunk.LevelChunkSection;
|
||||
import net.minecraft.world.level.levelgen.BitRandomSource;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
|
||||
import java.util.OptionalLong;
|
||||
|
||||
public final class RandomTickSystem {
|
||||
private static final long SCALE = 0x100000L;
|
||||
private static final long CHUNK_BLOCKS = 4096L;
|
||||
|
||||
/// reduce unnecessary sampling and block counting
|
||||
private static final long TICK_MASK = 0b11L;
|
||||
private static final long TICK_MUL = 4L;
|
||||
private static final long TICK_FILTER_MASK = 0b11L;
|
||||
private static final long CHUNK_BLOCKS = 4096L / 4L;
|
||||
private static final int BITS_STEP = 2;
|
||||
private static final int BITS_MAX = 60;
|
||||
|
||||
private final LongArrayList queue = new LongArrayList();
|
||||
private final LongArrayList samples = new LongArrayList();
|
||||
private final LongArrayList weights = new LongArrayList();
|
||||
private long weightsSum = 0L;
|
||||
|
||||
private int bits = 60;
|
||||
private long cacheRandom = 0L;
|
||||
|
||||
public void tick(ServerLevel world) {
|
||||
if (weights.isEmpty() || samples.isEmpty()) {
|
||||
queue.clear();
|
||||
samples.clear();
|
||||
weights.clear();
|
||||
|
||||
final BitRandomSource random = world.simpleRandom;
|
||||
final ReferenceList<LevelChunk> entityTickingChunks = world.moonrise$getEntityTickingChunks();
|
||||
final int randomTickSpeed = world.getGameRules().getInt(GameRules.RULE_RANDOMTICKING);
|
||||
final LevelChunk[] raw = entityTickingChunks.getRawDataUnchecked();
|
||||
final int size = entityTickingChunks.size();
|
||||
final boolean disableIceAndSnow = world.paperConfig().environment.disableIceAndSnow;
|
||||
if (randomTickSpeed <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
final var random = world.simpleRandom;
|
||||
final long chosen;
|
||||
if (((weightsSum % SCALE) >= boundedNextLong(random, SCALE))) {
|
||||
chosen = weightsSum / SCALE + 1L;
|
||||
} else {
|
||||
chosen = weightsSum / SCALE;
|
||||
if (!disableIceAndSnow) {
|
||||
iceSnow(world, size, randomTickSpeed, random, raw);
|
||||
}
|
||||
final long weightsSum = collectTickingChunks(size, random, raw, randomTickSpeed);
|
||||
if (samples.isEmpty() || weightsSum == 0L) {
|
||||
return;
|
||||
}
|
||||
sampling(random, weightsSum);
|
||||
|
||||
final long[] q = queue.elements();
|
||||
final int minY = ca.spottedleaf.moonrise.common.util.WorldUtil.getMinSection(world) << 4;
|
||||
for (int k = 0, len = queue.size(); k < len; ++k) {
|
||||
final long packed = q[k];
|
||||
final LevelChunk chunk = raw[(int) (packed >>> 16)];
|
||||
tickBlock(world, chunk, (int) (packed & 0xFFFF), random, minY);
|
||||
}
|
||||
}
|
||||
|
||||
private void sampling(BitRandomSource random, long weightsSum) {
|
||||
final long chosen = ((weightsSum % SCALE) >= boundedNextLong(random, SCALE))
|
||||
? (weightsSum / SCALE + 1L)
|
||||
: (weightsSum / SCALE);
|
||||
if (chosen == 0L) {
|
||||
return;
|
||||
}
|
||||
|
||||
final long[] w = weights.elements();
|
||||
final long[] s = samples.elements();
|
||||
long accumulated = w[0];
|
||||
final long spoke = weightsSum / chosen;
|
||||
if (spoke == 0L) {
|
||||
return;
|
||||
}
|
||||
if (spoke == 0L) return;
|
||||
|
||||
final long[] weightsRaw = weights.elements();
|
||||
final long[] samplesRaw = samples.elements();
|
||||
|
||||
long accumulated = weightsRaw[0];
|
||||
long current = boundedNextLong(random, spoke);
|
||||
int i = 0;
|
||||
while (current < weightsSum) {
|
||||
while (accumulated < current) {
|
||||
i += 1;
|
||||
accumulated += weightsRaw[i];
|
||||
i++;
|
||||
accumulated += w[i];
|
||||
}
|
||||
queue.add(samplesRaw[i]);
|
||||
queue.add(s[i]);
|
||||
current += spoke;
|
||||
}
|
||||
while (queue.size() < chosen) {
|
||||
queue.add(samplesRaw[i]);
|
||||
}
|
||||
|
||||
long[] queueRaw = queue.elements();
|
||||
int j = 0;
|
||||
int k;
|
||||
for (k = queue.size() - 3; j < k; j += 4) {
|
||||
final long packed1 = queueRaw[j];
|
||||
final long packed2 = queueRaw[j + 1];
|
||||
final long packed3 = queueRaw[j + 2];
|
||||
final long packed4 = queueRaw[j + 3];
|
||||
final LevelChunk chunk1 = getChunk(world, packed1);
|
||||
final LevelChunk chunk2 = packed1 != packed2 ? getChunk(world, packed2) : chunk1;
|
||||
final LevelChunk chunk3 = packed2 != packed3 ? getChunk(world, packed3) : chunk2;
|
||||
final LevelChunk chunk4 = packed3 != packed4 ? getChunk(world, packed4) : chunk3;
|
||||
if (chunk1 != null) tickBlock(world, chunk1, random);
|
||||
if (chunk2 != null) tickBlock(world, chunk2, random);
|
||||
if (chunk3 != null) tickBlock(world, chunk3, random);
|
||||
if (chunk4 != null) tickBlock(world, chunk4, random);
|
||||
}
|
||||
for (k = queue.size(); j < k; j++) {
|
||||
final LevelChunk chunk = getChunk(world, queueRaw[j]);
|
||||
if (chunk != null) tickBlock(world, chunk, random);
|
||||
}
|
||||
|
||||
weightsSum = 0L;
|
||||
queue.clear();
|
||||
weights.clear();
|
||||
samples.clear();
|
||||
}
|
||||
|
||||
private static LevelChunk getChunk(ServerLevel world, long packed) {
|
||||
return world.chunkSource.getChunkAtIfLoadedImmediately((int) packed, (int) (packed >> 32));
|
||||
private long collectTickingChunks(int size, BitRandomSource random, LevelChunk[] raw, long randomTickSpeed) {
|
||||
int bits = 0;
|
||||
long cacheRandom = random.nextLong();
|
||||
long weightsSum = 0L;
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (bits != BITS_MAX) {
|
||||
bits += BITS_STEP;
|
||||
} else {
|
||||
bits = 0;
|
||||
cacheRandom = random.nextLong();
|
||||
}
|
||||
if ((cacheRandom & (TICK_FILTER_MASK << bits)) != 0L) {
|
||||
continue;
|
||||
}
|
||||
final LevelChunk chunk = raw[i];
|
||||
if (chunk.leaf$tickingBlocksDirty) {
|
||||
populateChunkTickingCount(chunk);
|
||||
}
|
||||
int[] data = chunk.leaf$tickingCount;
|
||||
for (int packed : data) {
|
||||
int count = packed >>> 16;
|
||||
int idx = packed & 0xFFFF;
|
||||
samples.add((((long) i) << 16 | idx));
|
||||
long weight = (randomTickSpeed * count * SCALE) / CHUNK_BLOCKS;
|
||||
weights.add(weight);
|
||||
weightsSum += weight;
|
||||
}
|
||||
}
|
||||
return weightsSum;
|
||||
}
|
||||
|
||||
private static void tickBlock(ServerLevel world, LevelChunk chunk, RandomSource random) {
|
||||
int count = chunk.leaf$tickingBlocksCount();
|
||||
if (count == 0) {
|
||||
return;
|
||||
private static void populateChunkTickingCount(LevelChunk chunk) {
|
||||
chunk.leaf$tickingBlocksDirty = false;
|
||||
int sum = 0;
|
||||
for (LevelChunkSection section : chunk.getSections()) {
|
||||
sum += (section.moonrise$getTickingBlockList().size() == 0) ? 0 : 1;
|
||||
}
|
||||
OptionalLong optionalPos = chunk.leaf$getTickingPos(random.nextInt(count));
|
||||
if (optionalPos.isEmpty()) {
|
||||
return;
|
||||
|
||||
if (chunk.leaf$tickingCount.length != sum) {
|
||||
chunk.leaf$tickingCount = new int[sum];
|
||||
}
|
||||
BlockPos pos = BlockPos.of(optionalPos.getAsLong());
|
||||
BlockState state = chunk.getBlockStateFinal(pos.getX(), pos.getY(), pos.getZ());
|
||||
|
||||
int k = 0;
|
||||
LevelChunkSection[] sections = chunk.getSections();
|
||||
for (int j = 0; j < sections.length; j++) {
|
||||
ShortList list = sections[j].moonrise$getTickingBlockList();
|
||||
int n = list.size();
|
||||
if (n != 0) {
|
||||
chunk.leaf$tickingCount[k++] = (n << 16) | (j & 0xFFFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void iceSnow(ServerLevel world, int size, int randomTickSpeed, BitRandomSource random, LevelChunk[] raw) {
|
||||
int currentIceAndSnowTick = random.nextInt(48 * 16);
|
||||
for (int i = 0; i < size; i++) {
|
||||
currentIceAndSnowTick -= randomTickSpeed;
|
||||
if (currentIceAndSnowTick <= 0) {
|
||||
currentIceAndSnowTick = random.nextInt(48 * 16);
|
||||
LevelChunk chunk = raw[i];
|
||||
ChunkPos pos = chunk.getPos();
|
||||
world.tickPrecipitation(world.getBlockRandomPos(pos.getMinBlockX(), 0, pos.getMinBlockZ(), 15));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void tickBlock(ServerLevel world, LevelChunk chunk, int sectionIdx, BitRandomSource random, int minSection) {
|
||||
LevelChunkSection section = chunk.getSection(sectionIdx);
|
||||
ShortList list = section.moonrise$getTickingBlockList();
|
||||
int size = list.size();
|
||||
if (size == 0) return;
|
||||
short location = list.getRaw(boundedNextInt(random, size));
|
||||
BlockState state = section.states.get(location);
|
||||
final BlockPos pos = new BlockPos((location & 15) | (chunk.locX << 4), (location >>> 8) | (minSection + (sectionIdx << 4)), ((location >>> 4) & 15) | (chunk.locZ << 4));
|
||||
state.randomTick(world, pos, random);
|
||||
|
||||
final boolean doubleTickFluids = !ca.spottedleaf.moonrise.common.PlatformHooks.get().configFixMC224294();
|
||||
@@ -121,43 +168,13 @@ public final class RandomTickSystem {
|
||||
}
|
||||
}
|
||||
|
||||
public void tickChunk(
|
||||
RandomSource random,
|
||||
LevelChunk chunk,
|
||||
long tickSpeed
|
||||
) {
|
||||
if (this.bits == BITS_MAX) {
|
||||
this.bits = 0;
|
||||
this.cacheRandom = random.nextLong();
|
||||
} else {
|
||||
this.bits += BITS_STEP;
|
||||
}
|
||||
if ((this.cacheRandom & (TICK_MASK << bits)) == 0L) {
|
||||
long count = chunk.leaf$tickingBlocksCount();
|
||||
if (count != 0L) {
|
||||
long weight = (TICK_MUL * tickSpeed * count * SCALE) / CHUNK_BLOCKS;
|
||||
samples.add(chunk.getPos().longKey);
|
||||
weights.add(weight);
|
||||
weightsSum += weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param rng a random number generator to be used as a
|
||||
* source of pseudorandom {@code long} values
|
||||
* @param bound the upper bound (exclusive); must be greater than zero
|
||||
*
|
||||
* @return a pseudorandomly chosen {@code long} value
|
||||
*
|
||||
* @see java.util.random.RandomGenerator#nextLong(long) nextLong(bound)
|
||||
*/
|
||||
public static long boundedNextLong(RandomSource rng, long bound) {
|
||||
final long m = bound - 1;
|
||||
private static long boundedNextLong(BitRandomSource rng, long bound) {
|
||||
final long m = bound - 1L;
|
||||
long r = rng.nextLong();
|
||||
if ((bound & m) == 0L) {
|
||||
r &= m;
|
||||
} else {
|
||||
//noinspection StatementWithEmptyBody
|
||||
for (long u = r >>> 1;
|
||||
u + m - (r = u % bound) < 0L;
|
||||
u = rng.nextLong() >>> 1)
|
||||
@@ -165,4 +182,19 @@ public final class RandomTickSystem {
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
private static int boundedNextInt(BitRandomSource rng, int bound) {
|
||||
final int m = bound - 1;
|
||||
int r = rng.nextInt();
|
||||
if ((bound & m) == 0) {
|
||||
r &= m;
|
||||
} else {
|
||||
//noinspection StatementWithEmptyBody
|
||||
for (int u = r >>> 1;
|
||||
u + m - (r = u % bound) < 0;
|
||||
u = rng.nextInt() >>> 1)
|
||||
;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user