File size: 4,839 Bytes
d46f4a3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package net.minecraft.world.level;

import com.google.common.collect.AbstractIterator;
import java.util.function.BiFunction;
import javax.annotation.Nullable;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Cursor3D;
import net.minecraft.core.SectionPos;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.shapes.BooleanOp;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;

public class BlockCollisions<T> extends AbstractIterator<T> {
    private final AABB box;
    private final CollisionContext context;
    private final Cursor3D cursor;
    private final BlockPos.MutableBlockPos pos;
    private final VoxelShape entityShape;
    private final CollisionGetter collisionGetter;
    private final boolean onlySuffocatingBlocks;
    @Nullable
    private BlockGetter cachedBlockGetter;
    private long cachedBlockGetterPos;
    private final BiFunction<BlockPos.MutableBlockPos, VoxelShape, T> resultProvider;

    public BlockCollisions(
        CollisionGetter p_286817_, @Nullable Entity p_286246_, AABB p_286624_, boolean p_286354_, BiFunction<BlockPos.MutableBlockPos, VoxelShape, T> p_286303_
    ) {
        this(p_286817_, p_286246_ == null ? CollisionContext.empty() : CollisionContext.of(p_286246_), p_286624_, p_286354_, p_286303_);
    }

    public BlockCollisions(
        CollisionGetter p_367210_, CollisionContext p_366924_, AABB p_365384_, boolean p_365770_, BiFunction<BlockPos.MutableBlockPos, VoxelShape, T> p_361273_
    ) {
        this.context = p_366924_;
        this.pos = new BlockPos.MutableBlockPos();
        this.entityShape = Shapes.create(p_365384_);
        this.collisionGetter = p_367210_;
        this.box = p_365384_;
        this.onlySuffocatingBlocks = p_365770_;
        this.resultProvider = p_361273_;
        int i = Mth.floor(p_365384_.minX - 1.0E-7) - 1;
        int j = Mth.floor(p_365384_.maxX + 1.0E-7) + 1;
        int k = Mth.floor(p_365384_.minY - 1.0E-7) - 1;
        int l = Mth.floor(p_365384_.maxY + 1.0E-7) + 1;
        int i1 = Mth.floor(p_365384_.minZ - 1.0E-7) - 1;
        int j1 = Mth.floor(p_365384_.maxZ + 1.0E-7) + 1;
        this.cursor = new Cursor3D(i, k, i1, j, l, j1);
    }

    @Nullable
    private BlockGetter getChunk(int p_186412_, int p_186413_) {
        int i = SectionPos.blockToSectionCoord(p_186412_);
        int j = SectionPos.blockToSectionCoord(p_186413_);
        long k = ChunkPos.asLong(i, j);
        if (this.cachedBlockGetter != null && this.cachedBlockGetterPos == k) {
            return this.cachedBlockGetter;
        } else {
            BlockGetter blockgetter = this.collisionGetter.getChunkForCollisions(i, j);
            this.cachedBlockGetter = blockgetter;
            this.cachedBlockGetterPos = k;
            return blockgetter;
        }
    }

    @Override
    protected T computeNext() {
        while (this.cursor.advance()) {
            int i = this.cursor.nextX();
            int j = this.cursor.nextY();
            int k = this.cursor.nextZ();
            int l = this.cursor.getNextType();
            if (l != 3) {
                BlockGetter blockgetter = this.getChunk(i, k);
                if (blockgetter != null) {
                    this.pos.set(i, j, k);
                    BlockState blockstate = blockgetter.getBlockState(this.pos);
                    if ((!this.onlySuffocatingBlocks || blockstate.isSuffocating(blockgetter, this.pos))
                        && (l != 1 || blockstate.hasLargeCollisionShape())
                        && (l != 2 || blockstate.is(Blocks.MOVING_PISTON))) {
                        VoxelShape voxelshape = this.context.getCollisionShape(blockstate, this.collisionGetter, this.pos);
                        if (voxelshape == Shapes.block()) {
                            if (this.box.intersects((double)i, (double)j, (double)k, (double)i + 1.0, (double)j + 1.0, (double)k + 1.0)) {
                                return this.resultProvider.apply(this.pos, voxelshape.move((double)i, (double)j, (double)k));
                            }
                        } else {
                            VoxelShape voxelshape1 = voxelshape.move((double)i, (double)j, (double)k);
                            if (!voxelshape1.isEmpty() && Shapes.joinIsNotEmpty(voxelshape1, this.entityShape, BooleanOp.AND)) {
                                return this.resultProvider.apply(this.pos, voxelshape1);
                            }
                        }
                    }
                }
            }
        }

        return this.endOfData();
    }
}