Search in sources :

Example 1 with ChunkSection

use of cn.nukkit.level.format.ChunkSection in project Nukkit by Nukkit.

the class Level method tickChunks.

private void tickChunks() {
    if (this.chunksPerTicks <= 0 || this.loaders.isEmpty()) {
        this.chunkTickList.clear();
        return;
    }
    int chunksPerLoader = Math.min(200, Math.max(1, (int) (((double) (this.chunksPerTicks - this.loaders.size()) / this.loaders.size() + 0.5))));
    int randRange = 3 + chunksPerLoader / 30;
    randRange = randRange > this.chunkTickRadius ? this.chunkTickRadius : randRange;
    ThreadLocalRandom random = ThreadLocalRandom.current();
    if (!this.loaders.isEmpty()) {
        for (ChunkLoader loader : this.loaders.values()) {
            int chunkX = (int) loader.getX() >> 4;
            int chunkZ = (int) loader.getZ() >> 4;
            long index = Level.chunkHash(chunkX, chunkZ);
            int existingLoaders = Math.max(0, this.chunkTickList.getOrDefault(index, 0));
            this.chunkTickList.put(index, (Integer) (existingLoaders + 1));
            for (int chunk = 0; chunk < chunksPerLoader; ++chunk) {
                int dx = random.nextInt(2 * randRange) - randRange;
                int dz = random.nextInt(2 * randRange) - randRange;
                long hash = Level.chunkHash(dx + chunkX, dz + chunkZ);
                if (!this.chunkTickList.containsKey(hash) && provider.isChunkLoaded(hash)) {
                    this.chunkTickList.put(hash, (Integer) (-1));
                }
            }
        }
    }
    int blockTest = 0;
    if (!chunkTickList.isEmpty()) {
        ObjectIterator<Long2ObjectMap.Entry<Integer>> iter = chunkTickList.long2ObjectEntrySet().fastIterator();
        while (iter.hasNext()) {
            Long2ObjectMap.Entry<Integer> entry = iter.next();
            long index = entry.getLongKey();
            if (!areNeighboringChunksLoaded(index)) {
                iter.remove();
                continue;
            }
            int loaders = entry.getValue();
            int chunkX = getHashX(index);
            int chunkZ = getHashZ(index);
            FullChunk chunk;
            if ((chunk = this.getChunk(chunkX, chunkZ, false)) == null) {
                iter.remove();
                continue;
            } else if (loaders <= 0) {
                iter.remove();
            }
            for (Entity entity : chunk.getEntities().values()) {
                entity.scheduleUpdate();
            }
            int tickSpeed = 3;
            if (tickSpeed > 0) {
                if (this.useSections) {
                    for (ChunkSection section : ((Chunk) chunk).getSections()) {
                        if (!(section instanceof EmptyChunkSection)) {
                            int Y = section.getY();
                            this.updateLCG = this.updateLCG * 3 + 1013904223;
                            int k = this.updateLCG >> 2;
                            for (int i = 0; i < tickSpeed; ++i, k >>= 10) {
                                int x = k & 0x0f;
                                int y = k >> 8 & 0x0f;
                                int z = k >> 16 & 0x0f;
                                int fullId = section.getFullBlock(x, y, z);
                                int blockId = fullId >> 4;
                                if (randomTickBlocks[blockId]) {
                                    Block block = Block.get(fullId, this, chunkX * 16 + x, (Y << 4) + y, chunkZ * 16 + z);
                                    block.onUpdate(BLOCK_UPDATE_RANDOM);
                                }
                            }
                        }
                    }
                } else {
                    for (int Y = 0; Y < 8 && (Y < 3 || blockTest != 0); ++Y) {
                        blockTest = 0;
                        this.updateLCG = this.updateLCG * 3 + 1013904223;
                        int k = this.updateLCG >> 2;
                        for (int i = 0; i < tickSpeed; ++i, k >>= 10) {
                            int x = k & 0x0f;
                            int y = k >> 8 & 0x0f;
                            int z = k >> 16 & 0x0f;
                            int fullId = chunk.getFullBlock(x, y + (Y << 4), z);
                            int blockId = fullId >> 4;
                            blockTest |= fullId;
                            if (this.randomTickBlocks[blockId]) {
                                Block block = Block.get(fullId, this, x, y + (Y << 4), z);
                                block.onUpdate(BLOCK_UPDATE_RANDOM);
                            }
                        }
                    }
                }
            }
        }
    }
    if (this.clearChunksOnTick) {
        this.chunkTickList.clear();
    }
}
Also used : BlockEntity(cn.nukkit.blockentity.BlockEntity) Entity(cn.nukkit.entity.Entity) Long2ObjectMap(it.unimi.dsi.fastutil.longs.Long2ObjectMap) Chunk(cn.nukkit.level.format.Chunk) BaseFullChunk(cn.nukkit.level.format.generic.BaseFullChunk) FullChunk(cn.nukkit.level.format.FullChunk) EmptyChunkSection(cn.nukkit.level.format.generic.EmptyChunkSection) BaseFullChunk(cn.nukkit.level.format.generic.BaseFullChunk) FullChunk(cn.nukkit.level.format.FullChunk) ThreadLocalRandom(java.util.concurrent.ThreadLocalRandom) ItemBlock(cn.nukkit.item.ItemBlock) Block(cn.nukkit.block.Block) EmptyChunkSection(cn.nukkit.level.format.generic.EmptyChunkSection) ChunkSection(cn.nukkit.level.format.ChunkSection)

Aggregations

Block (cn.nukkit.block.Block)1 BlockEntity (cn.nukkit.blockentity.BlockEntity)1 Entity (cn.nukkit.entity.Entity)1 ItemBlock (cn.nukkit.item.ItemBlock)1 Chunk (cn.nukkit.level.format.Chunk)1 ChunkSection (cn.nukkit.level.format.ChunkSection)1 FullChunk (cn.nukkit.level.format.FullChunk)1 BaseFullChunk (cn.nukkit.level.format.generic.BaseFullChunk)1 EmptyChunkSection (cn.nukkit.level.format.generic.EmptyChunkSection)1 Long2ObjectMap (it.unimi.dsi.fastutil.longs.Long2ObjectMap)1 ThreadLocalRandom (java.util.concurrent.ThreadLocalRandom)1