diff options
Diffstat (limited to 'patch-remap/mache-vineflower/net/minecraft/world/level/material/FlowingFluid.java.patch')
-rw-r--r-- | patch-remap/mache-vineflower/net/minecraft/world/level/material/FlowingFluid.java.patch | 718 |
1 files changed, 718 insertions, 0 deletions
diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/material/FlowingFluid.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/material/FlowingFluid.java.patch new file mode 100644 index 0000000000..74b87828a0 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/material/FlowingFluid.java.patch @@ -0,0 +1,718 @@ +--- a/net/minecraft/world/level/material/FlowingFluid.java ++++ b/net/minecraft/world/level/material/FlowingFluid.java +@@ -7,11 +7,13 @@ + import it.unimi.dsi.fastutil.shorts.Short2BooleanOpenHashMap; + import it.unimi.dsi.fastutil.shorts.Short2ObjectMap; + import it.unimi.dsi.fastutil.shorts.Short2ObjectOpenHashMap; ++import java.util.Iterator; + import java.util.Map; + import java.util.Map.Entry; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.tags.BlockTags; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; +@@ -21,7 +23,7 @@ + import net.minecraft.world.level.block.DoorBlock; + import net.minecraft.world.level.block.IceBlock; + import net.minecraft.world.level.block.LiquidBlockContainer; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; +@@ -29,73 +31,94 @@ + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.block.BlockFace; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.block.data.CraftBlockData; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.block.BlockFromToEvent; ++import org.bukkit.event.block.FluidLevelChangeEvent; ++// CraftBukkit end + + public abstract class FlowingFluid extends Fluid { ++ + public static final BooleanProperty FALLING = BlockStateProperties.FALLING; + public static final IntegerProperty LEVEL = BlockStateProperties.LEVEL_FLOWING; + private static final int CACHE_SIZE = 200; + private static final ThreadLocal<Object2ByteLinkedOpenHashMap<Block.BlockStatePairKey>> OCCLUSION_CACHE = ThreadLocal.withInitial(() -> { +- Object2ByteLinkedOpenHashMap<Block.BlockStatePairKey> map = new Object2ByteLinkedOpenHashMap<Block.BlockStatePairKey>(200) { +- @Override +- protected void rehash(int newSize) { +- } ++ Object2ByteLinkedOpenHashMap<Block.BlockStatePairKey> object2bytelinkedopenhashmap = new Object2ByteLinkedOpenHashMap<Block.BlockStatePairKey>(200) { ++ protected void rehash(int i) {} + }; +- map.defaultReturnValue((byte)127); +- return map; ++ ++ object2bytelinkedopenhashmap.defaultReturnValue((byte) 127); ++ return object2bytelinkedopenhashmap; + }); + private final Map<FluidState, VoxelShape> shapes = Maps.newIdentityHashMap(); + ++ public FlowingFluid() {} ++ + @Override + protected void createFluidStateDefinition(StateDefinition.Builder<Fluid, FluidState> builder) { +- builder.add(FALLING); ++ builder.add(FlowingFluid.FALLING); + } + + @Override + public Vec3 getFlow(BlockGetter blockReader, BlockPos pos, FluidState fluidState) { +- double d = 0.0; +- double d1 = 0.0; +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); ++ double d0 = 0.0D; ++ double d1 = 0.0D; ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + +- for (Direction direction : Direction.Plane.HORIZONTAL) { +- mutableBlockPos.setWithOffset(pos, direction); +- FluidState fluidState1 = blockReader.getFluidState(mutableBlockPos); +- if (this.affectsFlow(fluidState1)) { +- float ownHeight = fluidState1.getOwnHeight(); +- float f = 0.0F; +- if (ownHeight == 0.0F) { +- if (!blockReader.getBlockState(mutableBlockPos).blocksMotion()) { +- BlockPos blockPos = mutableBlockPos.below(); +- FluidState fluidState2 = blockReader.getFluidState(blockPos); +- if (this.affectsFlow(fluidState2)) { +- ownHeight = fluidState2.getOwnHeight(); +- if (ownHeight > 0.0F) { +- f = fluidState.getOwnHeight() - (ownHeight - 0.8888889F); ++ while (iterator.hasNext()) { ++ Direction enumdirection = (Direction) iterator.next(); ++ ++ blockposition_mutableblockposition.setWithOffset(pos, enumdirection); ++ FluidState fluid1 = blockReader.getFluidState(blockposition_mutableblockposition); ++ ++ if (this.affectsFlow(fluid1)) { ++ float f = fluid1.getOwnHeight(); ++ float f1 = 0.0F; ++ ++ if (f == 0.0F) { ++ if (!blockReader.getBlockState(blockposition_mutableblockposition).blocksMotion()) { ++ BlockPos blockposition1 = blockposition_mutableblockposition.below(); ++ FluidState fluid2 = blockReader.getFluidState(blockposition1); ++ ++ if (this.affectsFlow(fluid2)) { ++ f = fluid2.getOwnHeight(); ++ if (f > 0.0F) { ++ f1 = fluidState.getOwnHeight() - (f - 0.8888889F); + } + } + } +- } else if (ownHeight > 0.0F) { +- f = fluidState.getOwnHeight() - ownHeight; ++ } else if (f > 0.0F) { ++ f1 = fluidState.getOwnHeight() - f; + } + +- if (f != 0.0F) { +- d += (double)((float)direction.getStepX() * f); +- d1 += (double)((float)direction.getStepZ() * f); ++ if (f1 != 0.0F) { ++ d0 += (double) ((float) enumdirection.getStepX() * f1); ++ d1 += (double) ((float) enumdirection.getStepZ() * f1); + } + } + } + +- Vec3 vec3 = new Vec3(d, 0.0, d1); +- if (fluidState.getValue(FALLING)) { +- for (Direction direction1 : Direction.Plane.HORIZONTAL) { +- mutableBlockPos.setWithOffset(pos, direction1); +- if (this.isSolidFace(blockReader, mutableBlockPos, direction1) || this.isSolidFace(blockReader, mutableBlockPos.above(), direction1)) { +- vec3 = vec3.normalize().add(0.0, -6.0, 0.0); ++ Vec3 vec3d = new Vec3(d0, 0.0D, d1); ++ ++ if ((Boolean) fluidState.getValue(FlowingFluid.FALLING)) { ++ Iterator iterator1 = Direction.Plane.HORIZONTAL.iterator(); ++ ++ while (iterator1.hasNext()) { ++ Direction enumdirection1 = (Direction) iterator1.next(); ++ ++ blockposition_mutableblockposition.setWithOffset(pos, enumdirection1); ++ if (this.isSolidFace(blockReader, blockposition_mutableblockposition, enumdirection1) || this.isSolidFace(blockReader, blockposition_mutableblockposition.above(), enumdirection1)) { ++ vec3d = vec3d.normalize().add(0.0D, -6.0D, 0.0D); + break; + } + } + } + +- return vec3.normalize(); ++ return vec3d.normalize(); + } + + private boolean affectsFlow(FluidState state) { +@@ -103,116 +126,149 @@ + } + + protected boolean isSolidFace(BlockGetter level, BlockPos neighborPos, Direction side) { +- BlockState blockState = level.getBlockState(neighborPos); +- FluidState fluidState = level.getFluidState(neighborPos); +- return !fluidState.getType().isSame(this) +- && (side == Direction.UP || !(blockState.getBlock() instanceof IceBlock) && blockState.isFaceSturdy(level, neighborPos, side)); ++ IBlockData iblockdata = level.getBlockState(neighborPos); ++ FluidState fluid = level.getFluidState(neighborPos); ++ ++ return fluid.getType().isSame(this) ? false : (side == Direction.UP ? true : (iblockdata.getBlock() instanceof IceBlock ? false : iblockdata.isFaceSturdy(level, neighborPos, side))); + } + + protected void spread(Level level, BlockPos pos, FluidState state) { + if (!state.isEmpty()) { +- BlockState blockState = level.getBlockState(pos); +- BlockPos blockPos = pos.below(); +- BlockState blockState1 = level.getBlockState(blockPos); +- FluidState newLiquid = this.getNewLiquid(level, blockPos, blockState1); +- if (this.canSpreadTo(level, pos, blockState, Direction.DOWN, blockPos, blockState1, level.getFluidState(blockPos), newLiquid.getType())) { +- this.spreadTo(level, blockPos, blockState1, Direction.DOWN, newLiquid); ++ IBlockData iblockdata = level.getBlockState(pos); ++ BlockPos blockposition1 = pos.below(); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ FluidState fluid1 = this.getNewLiquid(level, blockposition1, iblockdata1); ++ ++ if (this.canSpreadTo(level, pos, iblockdata, Direction.DOWN, blockposition1, iblockdata1, level.getFluidState(blockposition1), fluid1.getType())) { ++ // CraftBukkit start ++ org.bukkit.block.Block source = CraftBlock.at(level, pos); ++ BlockFromToEvent event = new BlockFromToEvent(source, BlockFace.DOWN); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ this.spreadTo(level, blockposition1, iblockdata1, Direction.DOWN, fluid1); + if (this.sourceNeighborCount(level, pos) >= 3) { +- this.spreadToSides(level, pos, state, blockState); ++ this.spreadToSides(level, pos, state, iblockdata); + } +- } else if (state.isSource() || !this.isWaterHole(level, newLiquid.getType(), pos, blockState, blockPos, blockState1)) { +- this.spreadToSides(level, pos, state, blockState); ++ } else if (state.isSource() || !this.isWaterHole(level, fluid1.getType(), pos, iblockdata, blockposition1, iblockdata1)) { ++ this.spreadToSides(level, pos, state, iblockdata); + } ++ + } + } + +- private void spreadToSides(Level level, BlockPos pos, FluidState fluidState, BlockState blockState) { ++ private void spreadToSides(Level level, BlockPos pos, FluidState fluidState, IBlockData blockState) { + int i = fluidState.getAmount() - this.getDropOff(level); +- if (fluidState.getValue(FALLING)) { ++ ++ if ((Boolean) fluidState.getValue(FlowingFluid.FALLING)) { + i = 7; + } + + if (i > 0) { +- Map<Direction, FluidState> spread = this.getSpread(level, pos, blockState); ++ Map<Direction, FluidState> map = this.getSpread(level, pos, blockState); ++ Iterator iterator = map.entrySet().iterator(); + +- for (Entry<Direction, FluidState> entry : spread.entrySet()) { +- Direction direction = entry.getKey(); +- FluidState fluidState1 = entry.getValue(); +- BlockPos blockPos = pos.relative(direction); +- BlockState blockState1 = level.getBlockState(blockPos); +- if (this.canSpreadTo(level, pos, blockState, direction, blockPos, blockState1, level.getFluidState(blockPos), fluidState1.getType())) { +- this.spreadTo(level, blockPos, blockState1, direction, fluidState1); ++ while (iterator.hasNext()) { ++ Entry<Direction, FluidState> entry = (Entry) iterator.next(); ++ Direction enumdirection = (Direction) entry.getKey(); ++ FluidState fluid1 = (FluidState) entry.getValue(); ++ BlockPos blockposition1 = pos.relative(enumdirection); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ ++ if (this.canSpreadTo(level, pos, blockState, enumdirection, blockposition1, iblockdata1, level.getFluidState(blockposition1), fluid1.getType())) { ++ // CraftBukkit start ++ org.bukkit.block.Block source = CraftBlock.at(level, pos); ++ BlockFromToEvent event = new BlockFromToEvent(source, org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(enumdirection)); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end ++ this.spreadTo(level, blockposition1, iblockdata1, enumdirection, fluid1); + } + } ++ + } + } + +- protected FluidState getNewLiquid(Level level, BlockPos pos, BlockState blockState) { ++ protected FluidState getNewLiquid(Level level, BlockPos pos, IBlockData blockState) { + int i = 0; +- int i1 = 0; ++ int j = 0; ++ Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + +- for (Direction direction : Direction.Plane.HORIZONTAL) { +- BlockPos blockPos = pos.relative(direction); +- BlockState blockState1 = level.getBlockState(blockPos); +- FluidState fluidState = blockState1.getFluidState(); +- if (fluidState.getType().isSame(this) && this.canPassThroughWall(direction, level, pos, blockState, blockPos, blockState1)) { +- if (fluidState.isSource()) { +- i1++; ++ while (iterator.hasNext()) { ++ Direction enumdirection = (Direction) iterator.next(); ++ BlockPos blockposition1 = pos.relative(enumdirection); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ FluidState fluid = iblockdata1.getFluidState(); ++ ++ if (fluid.getType().isSame(this) && this.canPassThroughWall(enumdirection, level, pos, blockState, blockposition1, iblockdata1)) { ++ if (fluid.isSource()) { ++ ++j; + } + +- i = Math.max(i, fluidState.getAmount()); ++ i = Math.max(i, fluid.getAmount()); + } + } + +- if (this.canConvertToSource(level) && i1 >= 2) { +- BlockState blockState2 = level.getBlockState(pos.below()); +- FluidState fluidState1 = blockState2.getFluidState(); +- if (blockState2.isSolid() || this.isSourceBlockOfThisType(fluidState1)) { ++ if (this.canConvertToSource(level) && j >= 2) { ++ IBlockData iblockdata2 = level.getBlockState(pos.below()); ++ FluidState fluid1 = iblockdata2.getFluidState(); ++ ++ if (iblockdata2.isSolid() || this.isSourceBlockOfThisType(fluid1)) { + return this.getSource(false); + } + } + +- BlockPos blockPos1 = pos.above(); +- BlockState blockState3 = level.getBlockState(blockPos1); +- FluidState fluidState2 = blockState3.getFluidState(); +- if (!fluidState2.isEmpty() +- && fluidState2.getType().isSame(this) +- && this.canPassThroughWall(Direction.UP, level, pos, blockState, blockPos1, blockState3)) { ++ BlockPos blockposition2 = pos.above(); ++ IBlockData iblockdata3 = level.getBlockState(blockposition2); ++ FluidState fluid2 = iblockdata3.getFluidState(); ++ ++ if (!fluid2.isEmpty() && fluid2.getType().isSame(this) && this.canPassThroughWall(Direction.UP, level, pos, blockState, blockposition2, iblockdata3)) { + return this.getFlowing(8, true); + } else { +- int i2 = i - this.getDropOff(level); +- return i2 <= 0 ? Fluids.EMPTY.defaultFluidState() : this.getFlowing(i2, false); ++ int k = i - this.getDropOff(level); ++ ++ return k <= 0 ? Fluids.EMPTY.defaultFluidState() : this.getFlowing(k, false); + } + } + +- private boolean canPassThroughWall(Direction direction, BlockGetter level, BlockPos pos, BlockState state, BlockPos spreadPos, BlockState spreadState) { +- Object2ByteLinkedOpenHashMap<Block.BlockStatePairKey> map; ++ private boolean canPassThroughWall(Direction direction, BlockGetter level, BlockPos pos, IBlockData state, BlockPos spreadPos, IBlockData spreadState) { ++ Object2ByteLinkedOpenHashMap object2bytelinkedopenhashmap; ++ + if (!state.getBlock().hasDynamicShape() && !spreadState.getBlock().hasDynamicShape()) { +- map = OCCLUSION_CACHE.get(); ++ object2bytelinkedopenhashmap = (Object2ByteLinkedOpenHashMap) FlowingFluid.OCCLUSION_CACHE.get(); + } else { +- map = null; ++ object2bytelinkedopenhashmap = null; + } + +- Block.BlockStatePairKey blockStatePairKey; +- if (map != null) { +- blockStatePairKey = new Block.BlockStatePairKey(state, spreadState, direction); +- byte andMoveToFirst = map.getAndMoveToFirst(blockStatePairKey); +- if (andMoveToFirst != 127) { +- return andMoveToFirst != 0; ++ Block.BlockStatePairKey block_a; ++ ++ if (object2bytelinkedopenhashmap != null) { ++ block_a = new Block.BlockStatePairKey(state, spreadState, direction); ++ byte b0 = object2bytelinkedopenhashmap.getAndMoveToFirst(block_a); ++ ++ if (b0 != 127) { ++ return b0 != 0; + } + } else { +- blockStatePairKey = null; ++ block_a = null; + } + +- VoxelShape collisionShape = state.getCollisionShape(level, pos); +- VoxelShape collisionShape1 = spreadState.getCollisionShape(level, spreadPos); +- boolean flag = !Shapes.mergedFaceOccludes(collisionShape, collisionShape1, direction); +- if (map != null) { +- if (map.size() == 200) { +- map.removeLastByte(); ++ VoxelShape voxelshape = state.getCollisionShape(level, pos); ++ VoxelShape voxelshape1 = spreadState.getCollisionShape(level, spreadPos); ++ boolean flag = !Shapes.mergedFaceOccludes(voxelshape, voxelshape1, direction); ++ ++ if (object2bytelinkedopenhashmap != null) { ++ if (object2bytelinkedopenhashmap.size() == 200) { ++ object2bytelinkedopenhashmap.removeLastByte(); + } + +- map.putAndMoveToFirst(blockStatePairKey, (byte)(flag ? 1 : 0)); ++ object2bytelinkedopenhashmap.putAndMoveToFirst(block_a, (byte) (flag ? 1 : 0)); + } + + return flag; +@@ -221,20 +277,20 @@ + public abstract Fluid getFlowing(); + + public FluidState getFlowing(int level, boolean falling) { +- return this.getFlowing().defaultFluidState().setValue(LEVEL, Integer.valueOf(level)).setValue(FALLING, Boolean.valueOf(falling)); ++ return (FluidState) ((FluidState) this.getFlowing().defaultFluidState().setValue(FlowingFluid.LEVEL, level)).setValue(FlowingFluid.FALLING, falling); + } + + public abstract Fluid getSource(); + + public FluidState getSource(boolean falling) { +- return this.getSource().defaultFluidState().setValue(FALLING, Boolean.valueOf(falling)); ++ return (FluidState) this.getSource().defaultFluidState().setValue(FlowingFluid.FALLING, falling); + } + + protected abstract boolean canConvertToSource(Level level); + +- protected void spreadTo(LevelAccessor level, BlockPos pos, BlockState blockState, Direction direction, FluidState fluidState) { ++ protected void spreadTo(LevelAccessor level, BlockPos pos, IBlockData blockState, Direction direction, FluidState fluidState) { + if (blockState.getBlock() instanceof LiquidBlockContainer) { +- ((LiquidBlockContainer)blockState.getBlock()).placeLiquid(level, pos, blockState, fluidState); ++ ((LiquidBlockContainer) blockState.getBlock()).placeLiquid(level, pos, blockState, fluidState); + } else { + if (!blockState.isAir()) { + this.beforeDestroyingBlock(level, pos, blockState); +@@ -242,74 +298,68 @@ + + level.setBlock(pos, fluidState.createLegacyBlock(), 3); + } ++ + } + +- protected abstract void beforeDestroyingBlock(LevelAccessor level, BlockPos pos, BlockState state); ++ protected abstract void beforeDestroyingBlock(LevelAccessor level, BlockPos pos, IBlockData state); + + private static short getCacheKey(BlockPos sourcePos, BlockPos spreadPos) { + int i = spreadPos.getX() - sourcePos.getX(); +- int i1 = spreadPos.getZ() - sourcePos.getZ(); +- return (short)((i + 128 & 0xFF) << 8 | i1 + 128 & 0xFF); ++ int j = spreadPos.getZ() - sourcePos.getZ(); ++ ++ return (short) ((i + 128 & 255) << 8 | j + 128 & 255); + } + +- protected int getSlopeDistance( +- LevelReader level, +- BlockPos spreadPos, +- int distance, +- Direction direction, +- BlockState currentSpreadState, +- BlockPos sourcePos, +- Short2ObjectMap<Pair<BlockState, FluidState>> stateCache, +- Short2BooleanMap waterHoleCache +- ) { +- int i = 1000; ++ protected int getSlopeDistance(LevelReader level, BlockPos spreadPos, int distance, Direction direction, IBlockData currentSpreadState, BlockPos sourcePos, Short2ObjectMap<Pair<IBlockData, FluidState>> stateCache, Short2BooleanMap waterHoleCache) { ++ int j = 1000; ++ Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + +- for (Direction direction1 : Direction.Plane.HORIZONTAL) { +- if (direction1 != direction) { +- BlockPos blockPos = spreadPos.relative(direction1); +- short cacheKey = getCacheKey(sourcePos, blockPos); +- Pair<BlockState, FluidState> pair = stateCache.computeIfAbsent(cacheKey, key -> { +- BlockState blockState1 = level.getBlockState(blockPos); +- return Pair.of(blockState1, blockState1.getFluidState()); ++ while (iterator.hasNext()) { ++ Direction enumdirection1 = (Direction) iterator.next(); ++ ++ if (enumdirection1 != direction) { ++ BlockPos blockposition2 = spreadPos.relative(enumdirection1); ++ short short0 = getCacheKey(sourcePos, blockposition2); ++ Pair<IBlockData, FluidState> pair = (Pair) stateCache.computeIfAbsent(short0, (short1) -> { ++ IBlockData iblockdata1 = level.getBlockState(blockposition2); ++ ++ return Pair.of(iblockdata1, iblockdata1.getFluidState()); + }); +- BlockState blockState = pair.getFirst(); +- FluidState fluidState = pair.getSecond(); +- if (this.canPassThrough(level, this.getFlowing(), spreadPos, currentSpreadState, direction1, blockPos, blockState, fluidState)) { +- boolean flag = waterHoleCache.computeIfAbsent(cacheKey, key -> { +- BlockPos blockPos1 = blockPos.below(); +- BlockState blockState1 = level.getBlockState(blockPos1); +- return this.isWaterHole(level, this.getFlowing(), blockPos, blockState, blockPos1, blockState1); ++ IBlockData iblockdata1 = (IBlockData) pair.getFirst(); ++ FluidState fluid = (FluidState) pair.getSecond(); ++ ++ if (this.canPassThrough(level, this.getFlowing(), spreadPos, currentSpreadState, enumdirection1, blockposition2, iblockdata1, fluid)) { ++ boolean flag = waterHoleCache.computeIfAbsent(short0, (short1) -> { ++ BlockPos blockposition3 = blockposition2.below(); ++ IBlockData iblockdata2 = level.getBlockState(blockposition3); ++ ++ return this.isWaterHole(level, this.getFlowing(), blockposition2, iblockdata1, blockposition3, iblockdata2); + }); ++ + if (flag) { + return distance; + } + + if (distance < this.getSlopeFindDistance(level)) { +- int slopeDistance = this.getSlopeDistance( +- level, blockPos, distance + 1, direction1.getOpposite(), blockState, sourcePos, stateCache, waterHoleCache +- ); +- if (slopeDistance < i) { +- i = slopeDistance; ++ int k = this.getSlopeDistance(level, blockposition2, distance + 1, enumdirection1.getOpposite(), iblockdata1, sourcePos, stateCache, waterHoleCache); ++ ++ if (k < j) { ++ j = k; + } + } + } + } + } + +- return i; ++ return j; + } + +- private boolean isWaterHole(BlockGetter level, Fluid fluid, BlockPos pos, BlockState state, BlockPos spreadPos, BlockState spreadState) { +- return this.canPassThroughWall(Direction.DOWN, level, pos, state, spreadPos, spreadState) +- && (spreadState.getFluidState().getType().isSame(this) || this.canHoldFluid(level, spreadPos, spreadState, fluid)); ++ private boolean isWaterHole(BlockGetter level, Fluid fluid, BlockPos pos, IBlockData state, BlockPos spreadPos, IBlockData spreadState) { ++ return !this.canPassThroughWall(Direction.DOWN, level, pos, state, spreadPos, spreadState) ? false : (spreadState.getFluidState().getType().isSame(this) ? true : this.canHoldFluid(level, spreadPos, spreadState, fluid)); + } + +- private boolean canPassThrough( +- BlockGetter level, Fluid fluid, BlockPos pos, BlockState state, Direction direction, BlockPos spreadPos, BlockState spreadState, FluidState fluidState +- ) { +- return !this.isSourceBlockOfThisType(fluidState) +- && this.canPassThroughWall(direction, level, pos, state, spreadPos, spreadState) +- && this.canHoldFluid(level, spreadPos, spreadState, fluid); ++ private boolean canPassThrough(BlockGetter level, Fluid fluid, BlockPos pos, IBlockData state, Direction direction, BlockPos spreadPos, IBlockData spreadState, FluidState fluidState) { ++ return !this.isSourceBlockOfThisType(fluidState) && this.canPassThroughWall(direction, level, pos, state, spreadPos, spreadState) && this.canHoldFluid(level, spreadPos, spreadState, fluid); + } + + private boolean isSourceBlockOfThisType(FluidState state) { +@@ -320,54 +370,63 @@ + + private int sourceNeighborCount(LevelReader level, BlockPos pos) { + int i = 0; ++ Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + +- for (Direction direction : Direction.Plane.HORIZONTAL) { +- BlockPos blockPos = pos.relative(direction); +- FluidState fluidState = level.getFluidState(blockPos); +- if (this.isSourceBlockOfThisType(fluidState)) { +- i++; ++ while (iterator.hasNext()) { ++ Direction enumdirection = (Direction) iterator.next(); ++ BlockPos blockposition1 = pos.relative(enumdirection); ++ FluidState fluid = level.getFluidState(blockposition1); ++ ++ if (this.isSourceBlockOfThisType(fluid)) { ++ ++i; + } + } + + return i; + } + +- protected Map<Direction, FluidState> getSpread(Level level, BlockPos pos, BlockState state) { ++ protected Map<Direction, FluidState> getSpread(Level level, BlockPos pos, IBlockData state) { + int i = 1000; + Map<Direction, FluidState> map = Maps.newEnumMap(Direction.class); +- Short2ObjectMap<Pair<BlockState, FluidState>> map1 = new Short2ObjectOpenHashMap<>(); +- Short2BooleanMap map2 = new Short2BooleanOpenHashMap(); ++ Short2ObjectMap<Pair<IBlockData, FluidState>> short2objectmap = new Short2ObjectOpenHashMap(); ++ Short2BooleanOpenHashMap short2booleanopenhashmap = new Short2BooleanOpenHashMap(); ++ Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + +- for (Direction direction : Direction.Plane.HORIZONTAL) { +- BlockPos blockPos = pos.relative(direction); +- short cacheKey = getCacheKey(pos, blockPos); +- Pair<BlockState, FluidState> pair = map1.computeIfAbsent(cacheKey, key -> { +- BlockState blockState1 = level.getBlockState(blockPos); +- return Pair.of(blockState1, blockState1.getFluidState()); ++ while (iterator.hasNext()) { ++ Direction enumdirection = (Direction) iterator.next(); ++ BlockPos blockposition1 = pos.relative(enumdirection); ++ short short0 = getCacheKey(pos, blockposition1); ++ Pair<IBlockData, FluidState> pair = (Pair) short2objectmap.computeIfAbsent(short0, (short1) -> { ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ ++ return Pair.of(iblockdata1, iblockdata1.getFluidState()); + }); +- BlockState blockState = pair.getFirst(); +- FluidState fluidState = pair.getSecond(); +- FluidState newLiquid = this.getNewLiquid(level, blockPos, blockState); +- if (this.canPassThrough(level, newLiquid.getType(), pos, state, direction, blockPos, blockState, fluidState)) { +- BlockPos blockPos1 = blockPos.below(); +- boolean flag = map2.computeIfAbsent(cacheKey, key -> { +- BlockState blockState1 = level.getBlockState(blockPos1); +- return this.isWaterHole(level, this.getFlowing(), blockPos, blockState, blockPos1, blockState1); ++ IBlockData iblockdata1 = (IBlockData) pair.getFirst(); ++ FluidState fluid = (FluidState) pair.getSecond(); ++ FluidState fluid1 = this.getNewLiquid(level, blockposition1, iblockdata1); ++ ++ if (this.canPassThrough(level, fluid1.getType(), pos, state, enumdirection, blockposition1, iblockdata1, fluid)) { ++ BlockPos blockposition2 = blockposition1.below(); ++ boolean flag = short2booleanopenhashmap.computeIfAbsent(short0, (short1) -> { ++ IBlockData iblockdata2 = level.getBlockState(blockposition2); ++ ++ return this.isWaterHole(level, this.getFlowing(), blockposition1, iblockdata1, blockposition2, iblockdata2); + }); +- int i1; ++ int j; ++ + if (flag) { +- i1 = 0; ++ j = 0; + } else { +- i1 = this.getSlopeDistance(level, blockPos, 1, direction.getOpposite(), blockState, pos, map1, map2); ++ j = this.getSlopeDistance(level, blockposition1, 1, enumdirection.getOpposite(), iblockdata1, pos, short2objectmap, short2booleanopenhashmap); + } + +- if (i1 < i) { ++ if (j < i) { + map.clear(); + } + +- if (i1 <= i) { +- map.put(direction, newLiquid); +- i = i1; ++ if (j <= i) { ++ map.put(enumdirection, fluid1); ++ i = j; + } + } + } +@@ -375,35 +434,20 @@ + return map; + } + +- private boolean canHoldFluid(BlockGetter level, BlockPos pos, BlockState state, Fluid fluid) { ++ private boolean canHoldFluid(BlockGetter level, BlockPos pos, IBlockData state, Fluid fluid) { + Block block = state.getBlock(); +- return block instanceof LiquidBlockContainer liquidBlockContainer +- ? liquidBlockContainer.canPlaceLiquid(null, level, pos, state, fluid) +- : !(block instanceof DoorBlock) +- && !state.is(BlockTags.SIGNS) +- && !state.is(Blocks.LADDER) +- && !state.is(Blocks.SUGAR_CANE) +- && !state.is(Blocks.BUBBLE_COLUMN) +- && !state.is(Blocks.NETHER_PORTAL) +- && !state.is(Blocks.END_PORTAL) +- && !state.is(Blocks.END_GATEWAY) +- && !state.is(Blocks.STRUCTURE_VOID) +- && !state.blocksMotion(); ++ ++ if (block instanceof LiquidBlockContainer) { ++ LiquidBlockContainer ifluidcontainer = (LiquidBlockContainer) block; ++ ++ return ifluidcontainer.canPlaceLiquid((Player) null, level, pos, state, fluid); ++ } else { ++ return !(block instanceof DoorBlock) && !state.is(BlockTags.SIGNS) && !state.is(Blocks.LADDER) && !state.is(Blocks.SUGAR_CANE) && !state.is(Blocks.BUBBLE_COLUMN) ? (!state.is(Blocks.NETHER_PORTAL) && !state.is(Blocks.END_PORTAL) && !state.is(Blocks.END_GATEWAY) && !state.is(Blocks.STRUCTURE_VOID) ? !state.blocksMotion() : false) : false; ++ } + } + +- protected boolean canSpreadTo( +- BlockGetter level, +- BlockPos fromPos, +- BlockState fromBlockState, +- Direction direction, +- BlockPos toPos, +- BlockState toBlockState, +- FluidState toFluidState, +- Fluid fluid +- ) { +- return toFluidState.canBeReplacedWith(level, toPos, fluid, direction) +- && this.canPassThroughWall(direction, level, fromPos, fromBlockState, toPos, toBlockState) +- && this.canHoldFluid(level, toPos, toBlockState, fluid); ++ protected boolean canSpreadTo(BlockGetter level, BlockPos fromPos, IBlockData fromBlockState, Direction direction, BlockPos toPos, IBlockData toBlockState, FluidState toFluidState, Fluid fluid) { ++ return toFluidState.canBeReplacedWith(level, toPos, fluid, direction) && this.canPassThroughWall(direction, level, fromPos, fromBlockState, toPos, toBlockState) && this.canHoldFluid(level, toPos, toBlockState, fluid); + } + + protected abstract int getDropOff(LevelReader level); +@@ -415,17 +459,30 @@ + @Override + public void tick(Level level, BlockPos pos, FluidState state) { + if (!state.isSource()) { +- FluidState newLiquid = this.getNewLiquid(level, pos, level.getBlockState(pos)); +- int spreadDelay = this.getSpreadDelay(level, pos, state, newLiquid); +- if (newLiquid.isEmpty()) { +- state = newLiquid; +- level.setBlock(pos, Blocks.AIR.defaultBlockState(), 3); +- } else if (!newLiquid.equals(state)) { +- state = newLiquid; +- BlockState blockState = newLiquid.createLegacyBlock(); +- level.setBlock(pos, blockState, 2); +- level.scheduleTick(pos, newLiquid.getType(), spreadDelay); +- level.updateNeighborsAt(pos, blockState.getBlock()); ++ FluidState fluid1 = this.getNewLiquid(level, pos, level.getBlockState(pos)); ++ int i = this.getSpreadDelay(level, pos, state, fluid1); ++ ++ if (fluid1.isEmpty()) { ++ state = fluid1; ++ // CraftBukkit start ++ FluidLevelChangeEvent event = CraftEventFactory.callFluidLevelChangeEvent(level, pos, Blocks.AIR.defaultBlockState()); ++ if (event.isCancelled()) { ++ return; ++ } ++ level.setBlock(pos, ((CraftBlockData) event.getNewData()).getState(), 3); ++ // CraftBukkit end ++ } else if (!fluid1.equals(state)) { ++ state = fluid1; ++ IBlockData iblockdata = fluid1.createLegacyBlock(); ++ // CraftBukkit start ++ FluidLevelChangeEvent event = CraftEventFactory.callFluidLevelChangeEvent(level, pos, iblockdata); ++ if (event.isCancelled()) { ++ return; ++ } ++ level.setBlock(pos, ((CraftBlockData) event.getNewData()).getState(), 2); ++ // CraftBukkit end ++ level.scheduleTick(pos, fluid1.getType(), i); ++ level.updateNeighborsAt(pos, iblockdata.getBlock()); + } + } + +@@ -433,7 +490,7 @@ + } + + protected static int getLegacyLevel(FluidState state) { +- return state.isSource() ? 0 : 8 - Math.min(state.getAmount(), 8) + (state.getValue(FALLING) ? 8 : 0); ++ return state.isSource() ? 0 : 8 - Math.min(state.getAmount(), 8) + ((Boolean) state.getValue(FlowingFluid.FALLING) ? 8 : 0); + } + + private static boolean hasSameAbove(FluidState fluidState, BlockGetter level, BlockPos pos) { +@@ -447,7 +504,7 @@ + + @Override + public float getOwnHeight(FluidState state) { +- return (float)state.getAmount() / 9.0F; ++ return (float) state.getAmount() / 9.0F; + } + + @Override +@@ -455,8 +512,8 @@ + + @Override + public VoxelShape getShape(FluidState state, BlockGetter level, BlockPos pos) { +- return state.getAmount() == 9 && hasSameAbove(state, level, pos) +- ? Shapes.block() +- : this.shapes.computeIfAbsent(state, stateKey -> Shapes.box(0.0, 0.0, 0.0, 1.0, (double)stateKey.getHeight(level, pos), 1.0)); ++ return state.getAmount() == 9 && hasSameAbove(state, level, pos) ? Shapes.block() : (VoxelShape) this.shapes.computeIfAbsent(state, (fluid1) -> { ++ return Shapes.box(0.0D, 0.0D, 0.0D, 1.0D, (double) fluid1.getHeight(level, pos), 1.0D); ++ }); + } + } |