Search in sources :

Example 6 with ChunkSection

use of net.minecraft.world.chunk.ChunkSection in project lithium-fabric by CaffeineMC.

the class LandPathNodeMakerMixin method getNodeTypeFromNeighbors.

/**
 * @reason Use optimized implementation which avoids scanning blocks for dangers where possible
 * @author JellySquid
 */
@Overwrite
public static PathNodeType getNodeTypeFromNeighbors(BlockView world, BlockPos.Mutable pos, PathNodeType type) {
    int x = pos.getX();
    int y = pos.getY();
    int z = pos.getZ();
    ChunkSection section = null;
    // reads to just one chunk and avoid hits against the server chunk manager.
    if (world instanceof CollisionView && WorldHelper.areNeighborsWithinSameChunk(pos)) {
        // if the cached chunk section was initialized will early-exit.
        if (!world.isOutOfHeightLimit(y)) {
            // This cast is always safe and is necessary to obtain direct references to chunk sections.
            Chunk chunk = (Chunk) ((CollisionView) world).getChunkAsView(Pos.ChunkCoord.fromBlockCoord(x), Pos.ChunkCoord.fromBlockCoord(z));
            // An empty chunk or section will never pose any danger sources, which will be caught later.
            if (chunk != null) {
                section = chunk.getSectionArray()[Pos.SectionYIndex.fromBlockCoord(world, y)];
            }
        }
        // against this chunk section will always fail, allowing us to fast-exit.
        if (section == null || PathNodeCache.isSectionSafeAsNeighbor(section)) {
            return type;
        }
    }
    int xStart = x - 1;
    int yStart = y - 1;
    int zStart = z - 1;
    int xEnd = x + 1;
    int yEnd = y + 1;
    int zEnd = z + 1;
    // Vanilla iteration order is XYZ
    for (int adjX = xStart; adjX <= xEnd; adjX++) {
        for (int adjY = yStart; adjY <= yEnd; adjY++) {
            for (int adjZ = zStart; adjZ <= zEnd; adjZ++) {
                // Skip the vertical column of the origin block
                if (adjX == x && adjZ == z) {
                    continue;
                }
                BlockState state;
                // retrieval by calling upon the cached chunk directly.
                if (section != null) {
                    state = section.getBlockState(adjX & 15, adjY & 15, adjZ & 15);
                } else {
                    state = world.getBlockState(pos.set(adjX, adjY, adjZ));
                }
                // Ensure that the block isn't air first to avoid expensive hash table accesses
                if (state.isAir()) {
                    continue;
                }
                PathNodeType neighborType = PathNodeCache.getNeighborPathNodeType(state);
                if (neighborType != PathNodeType.OPEN) {
                    return neighborType;
                }
            }
        }
    }
    return type;
}
Also used : BlockState(net.minecraft.block.BlockState) CollisionView(net.minecraft.world.CollisionView) PathNodeType(net.minecraft.entity.ai.pathing.PathNodeType) Chunk(net.minecraft.world.chunk.Chunk) ChunkSection(net.minecraft.world.chunk.ChunkSection) Overwrite(org.spongepowered.asm.mixin.Overwrite)

Example 7 with ChunkSection

use of net.minecraft.world.chunk.ChunkSection in project lithium-fabric by CaffeineMC.

the class EntityMixin method tryShortcutFluidPushing.

@Inject(method = "updateMovementInFluid(Lnet/minecraft/tag/TagKey;D)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;isPushedByFluids()Z", shift = At.Shift.BEFORE), cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD)
public void tryShortcutFluidPushing(TagKey<Fluid> tag, double speed, CallbackInfoReturnable<Boolean> cir, Box box, int x1, int x2, int y1, int y2, int z1, int z2, double zero) {
    TrackedBlockStatePredicate blockStateFlag;
    if (tag == FluidTags.WATER) {
        blockStateFlag = BlockStateFlags.WATER;
    } else if (tag == FluidTags.LAVA) {
        blockStateFlag = BlockStateFlags.LAVA;
    } else {
        return;
    }
    int chunkX1 = x1 >> 4;
    int chunkZ1 = z1 >> 4;
    int chunkX2 = ((x2 - 1) >> 4);
    int chunkZ2 = ((z2 - 1) >> 4);
    int chunkYIndex1 = Math.max(Pos.SectionYIndex.fromBlockCoord(this.world, y1), Pos.SectionYIndex.getMinYSectionIndex(this.world));
    int chunkYIndex2 = Math.min(Pos.SectionYIndex.fromBlockCoord(this.world, y2 - 1), Pos.SectionYIndex.getMaxYSectionIndexInclusive(this.world));
    for (int chunkX = chunkX1; chunkX <= chunkX2; chunkX++) {
        for (int chunkZ = chunkZ1; chunkZ <= chunkZ2; chunkZ++) {
            Chunk chunk = this.world.getChunk(chunkX, chunkZ);
            for (int chunkYIndex = chunkYIndex1; chunkYIndex <= chunkYIndex2; chunkYIndex++) {
                ChunkSection section = chunk.getSectionArray()[chunkYIndex];
                if (((BlockCountingSection) section).anyMatch(blockStateFlag)) {
                    // fluid found, cannot skip code
                    return;
                }
            }
        }
    }
    // side effects of not finding a fluid:
    this.fluidHeight.put(tag, 0.0);
    cir.setReturnValue(false);
}
Also used : TrackedBlockStatePredicate(me.jellysquid.mods.lithium.common.block.TrackedBlockStatePredicate) Chunk(net.minecraft.world.chunk.Chunk) ChunkSection(net.minecraft.world.chunk.ChunkSection) BlockCountingSection(me.jellysquid.mods.lithium.common.block.BlockCountingSection) Inject(org.spongepowered.asm.mixin.injection.Inject)

Example 8 with ChunkSection

use of net.minecraft.world.chunk.ChunkSection in project lithium-fabric by CaffeineMC.

the class WorldMixin method getBlockState.

/**
 * @reason Reduce method size to help the JVM inline, Avoid excess height limit checks
 * @author 2No2Name
 */
@Overwrite
public BlockState getBlockState(BlockPos pos) {
    WorldChunk worldChunk = this.getChunk(ChunkSectionPos.getSectionCoord(pos.getX()), ChunkSectionPos.getSectionCoord(pos.getZ()));
    ChunkSection[] sections = worldChunk.getSectionArray();
    int x = pos.getX();
    int y = pos.getY();
    int z = pos.getZ();
    int chunkY = this.getSectionIndex(y);
    if (chunkY < 0 || chunkY >= sections.length) {
        return OUTSIDE_WORLD_BLOCK;
    }
    ChunkSection section = sections[chunkY];
    if (section == null || section.isEmpty()) {
        return INSIDE_WORLD_DEFAULT_BLOCK;
    }
    return section.getBlockState(x & 15, y & 15, z & 15);
// This code path is slower than with the extra world height limit check. Tradeoff in favor of the default path.
}
Also used : WorldChunk(net.minecraft.world.chunk.WorldChunk) ChunkSection(net.minecraft.world.chunk.ChunkSection) Overwrite(org.spongepowered.asm.mixin.Overwrite)

Example 9 with ChunkSection

use of net.minecraft.world.chunk.ChunkSection in project lithium-fabric by CaffeineMC.

the class ExplosionMixin method traverseBlock.

/**
 * Called for every step made by a ray being cast by an explosion.
 *
 * @param strength The strength of the ray during this step
 * @param blockX   The x-coordinate of the block the ray is inside of
 * @param blockY   The y-coordinate of the block the ray is inside of
 * @param blockZ   The z-coordinate of the block the ray is inside of
 * @return The resistance of the current block space to the ray
 */
private float traverseBlock(float strength, int blockX, int blockY, int blockZ, LongOpenHashSet touched) {
    BlockPos pos = this.cachedPos.set(blockX, blockY, blockZ);
    // Early-exit if the y-coordinate is out of bounds.
    if (this.world.isOutOfHeightLimit(blockY)) {
        Optional<Float> blastResistance = this.behavior.getBlastResistance((Explosion) (Object) this, this.world, pos, Blocks.AIR.getDefaultState(), Fluids.EMPTY.getDefaultState());
        // noinspection OptionalIsPresent
        if (blastResistance.isPresent()) {
            return (blastResistance.get() + 0.3F) * 0.3F;
        }
        return 0.0F;
    }
    int chunkX = Pos.ChunkCoord.fromBlockCoord(blockX);
    int chunkZ = Pos.ChunkCoord.fromBlockCoord(blockZ);
    // Avoid calling into the chunk manager as much as possible through managing chunks locally
    if (this.prevChunkX != chunkX || this.prevChunkZ != chunkZ) {
        this.prevChunk = this.world.getChunk(chunkX, chunkZ);
        this.prevChunkX = chunkX;
        this.prevChunkZ = chunkZ;
    }
    final Chunk chunk = this.prevChunk;
    BlockState blockState = Blocks.AIR.getDefaultState();
    float totalResistance = 0.0F;
    Optional<Float> blastResistance;
    labelGetBlastResistance: {
        // If the chunk is missing or out of bounds, assume that it is air
        if (chunk != null) {
            // We operate directly on chunk sections to avoid interacting with BlockPos and to squeeze out as much
            // performance as possible here
            ChunkSection section = chunk.getSectionArray()[Pos.SectionYIndex.fromBlockCoord(chunk, blockY)];
            // If the section doesn't exist or it's empty, assume that the block is air
            if (section != null && !section.isEmpty()) {
                // Retrieve the block state from the chunk section directly to avoid associated overhead
                blockState = section.getBlockState(blockX & 15, blockY & 15, blockZ & 15);
                // If the block state is air, it cannot have fluid or any kind of resistance, so just leave
                if (blockState.getBlock() != Blocks.AIR) {
                    // Rather than query the fluid state from the container as we just did with the block state, we can
                    // simply ask the block state we retrieved what fluid it has. This is exactly what the call would
                    // do anyways, except that it would have to retrieve the block state a second time, adding overhead.
                    FluidState fluidState = blockState.getFluidState();
                    // Get the explosion resistance like vanilla
                    blastResistance = this.behavior.getBlastResistance((Explosion) (Object) this, this.world, pos, blockState, fluidState);
                    break labelGetBlastResistance;
                }
            }
        }
        blastResistance = this.behavior.getBlastResistance((Explosion) (Object) this, this.world, pos, Blocks.AIR.getDefaultState(), Fluids.EMPTY.getDefaultState());
    }
    // Calculate how much this block will resist an explosion's ray
    if (blastResistance.isPresent()) {
        totalResistance = (blastResistance.get() + 0.3F) * 0.3F;
    }
    // Check if this ray is still strong enough to break blocks, and if so, add this position to the set
    // of positions to destroy
    float reducedStrength = strength - totalResistance;
    if (reducedStrength > 0.0F && (this.explodeAirBlocks || !blockState.isAir())) {
        if (this.behavior.canDestroyBlock((Explosion) (Object) this, this.world, pos, blockState, reducedStrength)) {
            touched.add(pos.asLong());
        }
    }
    return totalResistance;
}
Also used : BlockState(net.minecraft.block.BlockState) Explosion(net.minecraft.world.explosion.Explosion) BlockPos(net.minecraft.util.math.BlockPos) Chunk(net.minecraft.world.chunk.Chunk) ChunkSection(net.minecraft.world.chunk.ChunkSection) FluidState(net.minecraft.fluid.FluidState)

Example 10 with ChunkSection

use of net.minecraft.world.chunk.ChunkSection in project Spelunker by Leximon.

the class PlayerEntityMixin method moveEndInject.

@Inject(method = "tick", at = @At("HEAD"))
private void moveEndInject(CallbackInfo ci) {
    if (!hasStatusEffect(SpelunkerMod.STATUS_EFFECT_SPELUNKER)) {
        if (!spelunkerEffectChunks.isEmpty())
            spelunkerEffectChunks.clear();
        forceOreChunkUpdate = true;
        return;
    }
    if (SpelunkerConfig.serverValidating && world.isClient())
        return;
    int cx = ChunkSectionPos.getSectionCoord(getX());
    int cy = ChunkSectionPos.getSectionCoord(getY());
    int cz = ChunkSectionPos.getSectionCoord(getZ());
    // update if player crosses chunk border
    if (cx != lastCx || cy != lastCy || cz != lastCz || forceOreChunkUpdate) {
        forceOreChunkUpdate = false;
        HashMap<Vec3i, ChunkSection> newChunks = SpelunkerEffectManager.getSurroundingChunkSections(world, getPos());
        // calc difference and find ores
        HashSet<Vec3i> remove = new HashSet<>();
        spelunkerEffectChunks.removeIf(p -> {
            if (!newChunks.containsKey(p)) {
                remove.add(p);
                return true;
            }
            return false;
        });
        ArrayList<ChunkOres> add = new ArrayList<>();
        for (Map.Entry<Vec3i, ChunkSection> section : newChunks.entrySet()) {
            Vec3i pos = section.getKey();
            if (!spelunkerEffectChunks.contains(pos)) {
                add.add(SpelunkerEffectManager.findOresInChunk(world, pos));
                spelunkerEffectChunks.add(pos);
            }
        }
        // handle new and removed chunk sections
        if (world.isClient()) {
            SpelunkerModClient.spelunkerEffectRenderer.updateChunks(world, remove, add);
        } else if (SpelunkerConfig.serverValidating) {
            PacketByteBuf buf = SpelunkerEffectManager.writePacket(world, true, remove, add);
            ServerPlayNetworking.send((ServerPlayerEntity) (Object) this, SpelunkerMod.PACKET_ORE_CHUNKS, buf);
        }
    }
    lastCx = cx;
    lastCy = cy;
    lastCz = cz;
}
Also used : Vec3i(net.minecraft.util.math.Vec3i) ChunkOres(de.leximon.spelunker.core.ChunkOres) ArrayList(java.util.ArrayList) ServerPlayerEntity(net.minecraft.server.network.ServerPlayerEntity) PacketByteBuf(net.minecraft.network.PacketByteBuf) ChunkSection(net.minecraft.world.chunk.ChunkSection) HashMap(java.util.HashMap) Map(java.util.Map) HashSet(java.util.HashSet) Inject(org.spongepowered.asm.mixin.injection.Inject)

Aggregations

ChunkSection (net.minecraft.world.chunk.ChunkSection)36 Chunk (net.minecraft.world.chunk.Chunk)11 BlockState (net.minecraft.block.BlockState)10 BlockPos (net.minecraft.util.math.BlockPos)8 Overwrite (org.spongepowered.asm.mixin.Overwrite)8 WorldChunk (net.minecraft.world.chunk.WorldChunk)5 Inject (org.spongepowered.asm.mixin.injection.Inject)5 TileEntity (net.minecraft.tileentity.TileEntity)3 BiomeContainer (net.minecraft.world.biome.BiomeContainer)3 ArrayList (java.util.ArrayList)2 Block (net.minecraft.block.Block)2 ITileEntityProvider (net.minecraft.block.ITileEntityProvider)2 PathNodeType (net.minecraft.entity.ai.pathing.PathNodeType)2 FluidState (net.minecraft.fluid.FluidState)2 CompoundNBT (net.minecraft.nbt.CompoundNBT)2 NBTUtil (net.minecraft.nbt.NBTUtil)2 ServerPlayerEntity (net.minecraft.server.network.ServerPlayerEntity)2 ChunkPos (net.minecraft.util.math.ChunkPos)2 PalettedContainer (net.minecraft.util.palette.PalettedContainer)2 CollisionView (net.minecraft.world.CollisionView)2