Пример #1
0
        public override void OnUpdate(World world, int x, int y, int z)
        {
            // Get all kinds of required data
            var type = world.GetBlockType(x, y, z);
            var groundtype = world.GetBlockType(x, y - 1, z);
            var metaData = world.GetBlockData(x, y, z);
            var height = GetHeight(metaData);
            var isFalling = IsFalling(metaData);
            var onWater = groundtype == SourceType || groundtype == FlowingType;

            // Still water drains and has some restriction the way it can flow:
            // 1) It can't flow on top of water tiles
            // 2) It can't spread if it is falling
            if (type == FlowingType) {
                // Not falling tiles adjust their size depending on their neighbors' height
                if (!isFalling) {
                    var maxNHeight = FindMaxNHeight(world, x, y, z);
                    if (maxNHeight >= height) { // this block is higher than our highest neighbor and needs to shrink
                        // If this already is the smallest block, disappear, otherwise shrink by 1
                        if (height == MaxHeight)
                            world.SetBlockType(x, y, z, (int)BlockType.Air);
                        else {
                            world.SetBlockData(x, y, z, height + 1);
                            ActivateNeighbors(world, x, y, z);
                            ActivateBlock(world, x, y, z);
                        }
                        return;
                    } else if (height != maxNHeight + 1) { // this block needs to grow
                        // Never grow higher than the max height
                        world.SetBlockData(x, y, z, Math.Min(MaxHeight, maxNHeight + 1));
                        ActivateNeighbors(world, x, y, z);
                        ActivateBlock(world, x, y, z);
                    }
                } else {
                    // Falling water shrinks if there is no water block above it
                    var aboveType = world.GetBlockType(x, y + 1, z);
                    if (aboveType != FlowingType && aboveType != SourceType) {
                        // Falling water shrinks faster than normal tiles
                        if (height >= MaxHeight)
                            world.SetBlockType(x, y, z, (int)BlockType.Air);
                        else {
                            world.SetBlockData(x, y, z, MaxHeight);
                            ActivateNeighbors(world, x, y, z);
                            ActivateBlock(world, x, y, z);
                        }
                        return;
                    }
                }

                // Flowing water doesn't spread on top of water
                if (onWater)
                    return;
            }

            // Set height of all following tiles and abort if this tile is already the smallest
            height++;
            if (height > MaxHeight)
                return;
            // Source blocks also spread on top of water
            bool flowDown = DoFlow(world, x, y - 1, z, 8);
            if (!flowDown || (onWater && type == SourceType)) {
                // Try flowing towards the nearest drop in 4 tiles radius
                if (!FlowRadius(world, x, y, z, 1, height))
                    if (!FlowRadius(world, x, y, z, 2, height))
                        if (!FlowRadius(world, x, y, z, 3, height))
                            if (!FlowRadius(world, x, y, z, 4, height)) {
                                // No nearby drop down, flow in all directions
                                DoFlow(world, x - 1, y, z, height);
                                DoFlow(world, x + 1, y, z, height);
                                DoFlow(world, x, y, z - 1, height);
                                DoFlow(world, x, y, z + 1, height);
                            }
                return;
            }

            if (flowDown && y == 0)
                return;
            // Schedule new update for this block if we flowed once (down or sideways)
            ActivateBlock(world, x, y, z);
        }