package pokefenn.totemic.util;

import java.util.Comparator;
import java.util.stream.Stream;

import javax.annotation.Nullable;

import net.minecraft.core.BlockPos;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityTicker;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.material.Fluids;

public final class TileUtil {
    //Same method as in BaseEntityBlock, but made public
    @SuppressWarnings("unchecked")
    public static <E extends BlockEntity, A extends BlockEntity> BlockEntityTicker<A> createTickerHelper(BlockEntityType<A> serverType, BlockEntityType<E> clientType, BlockEntityTicker<? super E> ticker) {
        return clientType == serverType ? (BlockEntityTicker<A>)ticker : null;
    }

    public static <T extends BlockEntity> Stream<T> getTileEntitiesInRange(@Nullable BlockEntityType<T> type, Level world, BlockPos pos, int range) {
        return getTileEntitiesIn(type, world, pos.offset(-range, -range, -range), pos.offset(range, range, range));
    }

    @SuppressWarnings("unchecked")
    public static <T extends BlockEntity> Stream<T> getTileEntitiesIn(@Nullable BlockEntityType<T> type, Level world, BlockPos start, BlockPos end) {
        return (Stream<T>) ChunkPos.rangeClosed(new ChunkPos(start), new ChunkPos(end))
                .filter(chunkPos -> world.hasChunk(chunkPos.x, chunkPos.z))
                .map(chunkPos -> world.getChunk(chunkPos.x, chunkPos.z))
                .flatMap(chunk -> chunk.getBlockEntities().values().stream())
                .filter(tile ->
                           (type == null || tile.getType() == type)
                        && !tile.isRemoved()
                        && tile.getBlockPos().compareTo(start) >= 0
                        && tile.getBlockPos().compareTo(end) <= 0);
    }

    public static Comparator<BlockEntity> compareCenterDistanceTo(double x, double y, double z) {
        return Comparator.comparing((BlockEntity t) -> t.getBlockPos().distToCenterSqr(x, y, z));
    }

    public static boolean placedInWater(BlockPlaceContext context) {
        return context.getLevel().getFluidState(context.getClickedPos()).getType() == Fluids.WATER;
    }

    public static void scheduleWaterloggedTick(BlockState state, BlockPos currentPos, LevelAccessor level) {
        if(state.getValue(BlockStateProperties.WATERLOGGED))
            level.scheduleTick(currentPos, Fluids.WATER, Fluids.WATER.getTickDelay(level));
    }
}

@@ -154,24 +154,57 @@
 e.BlockPos;%0A
+import net.minecraft.core.Vec3i;%0A
 import net.m
@@ -2105,32 +2105,47 @@
              && 
+isWithinBounds(
 tile.getBlockPos
@@ -2150,96 +2150,324 @@
 os()
-.compareTo(start) %3E= 0%0A                        && tile.getBlockPos().compareTo(end) %3C= 0
+, start, end));%0A    %7D%0A%0A    public static boolean isWithinBounds(Vec3i test, Vec3i start, Vec3i end) %7B%0A        return start.getX() %3C= test.getX() && test.getX() %3C= end.getX()%0A            && start.getY() %3C= test.getY() && test.getY() %3C= end.getY()%0A            && start.getZ() %3C= test.getZ() && test.getZ() %3C= end.getZ(
 );%0A 

Fix wrong way of comparing BlockPos